问:
SSL handshake failure after ClientHello in Ubuntu 20.04 and Debian 10 (works in Ubuntu 18.04 and Debian 9)
I have been trying to use Oracle Cloud Email Delivery Service. Once configured it provides SMTP credentials which you can use to send email from approved senders.

I am stuck with few interesting scenarios.
It works in Ubuntu 18.04 but fails in docker container(running Debian 10) running on same machine.

I was testing handshake with openssl s_client

```<code>echo QUIT | openssl s_client -starttls smtp -crlf -connect smtp.email.ap-mumbai-1.oci.oraclecloud.com:587
</code>```

This command works fine in Ubuntu 18.04 but fails with handshake failure in docker container running Debian 10

Output from Docker Container

```<code>root@06369bfe7c16:/var/www/html# echo QUIT | openssl s_client -starttls smtp -crlf -connect smtp.email.ap-mumbai-1.oci.oraclecloud.com:587
CONNECTED(00000003)
140491098481792:error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure:../ssl/record/rec_layer_s3.c:1544:SSL alert number 40
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 199 bytes and written 367 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
root@06369bfe7c16:/var/www/html#
</code>```

I tried to check openssl versions in both.

18.04 is having openssl version OpenSSL 1.1.1  11 Sep 2018

Docker container is having openssl version OpenSSL 1.1.1d  10 Sep 2019

Can it be something related to versions?

I tried to debug more via Wireshark to see how ClientHello messages are sent -

ClientHello from Ubuntu 18.04 ( which returns in success)

```<code>TLSv1.2 Record Layer: Handshake Protocol: Client Hello
    Content Type: Handshake (22)
    Version: TLS 1.0 (0x0301)
    Length: 339
    Handshake Protocol: Client Hello
        Handshake Type: Client Hello (1)
        Length: 335
        Version: TLS 1.2 (0x0303)
        Random: e595f987b8d92387f7114d9dee4df7bc3f00b5b082ba0ec8…
        Session ID Length: 32
        Session ID: 74c873d7894514a047e0763cd14c01fb19a4f238cb9085f2…
        Cipher Suites Length: 62
        Cipher Suites (31 suites)
            Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302)
            Cipher Suite: TLS_CHACHA20_POLY1305_SHA256 (0x1303)
            Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x009f)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca9)
            Cipher Suite: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca8)
            Cipher Suite: TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xccaa)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x009e)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (0xc024)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (0x006b)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (0xc023)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (0x0067)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033)
            Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
            Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
            Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA256 (0x003d)
            Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA256 (0x003c)
            Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
            Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
            Cipher Suite: TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff)
        Compression Methods Length: 1
        Compression Methods (1 method)
            Compression Method: null (0)
        Extensions Length: 200
        Extension: server_name (len=47)
            Type: server_name (0)
            Length: 47
            Server Name Indication extension
        Extension: ec_point_formats (len=4)
            Type: ec_point_formats (11)
            Length: 4
            EC point formats Length: 3
            Elliptic curves point formats (3)
                EC point format: uncompressed (0)
                EC point format: ansiX962_compressed_prime (1)
                EC point format: ansiX962_compressed_char2 (2)
        Extension: supported_groups (len=12)
            Type: supported_groups (10)
            Length: 12
            Supported Groups List Length: 10
            Supported Groups (5 groups)
        Extension: session_ticket (len=0)
            Type: session_ticket (35)
            Length: 0
            Data (0 bytes)
        Extension: encrypt_then_mac (len=0)
            Type: encrypt_then_mac (22)
            Length: 0
        Extension: extended_master_secret (len=0)
            Type: extended_master_secret (23)
            Length: 0
        Extension: signature_algorithms (len=48)
            Type: signature_algorithms (13)
            Length: 48
            Signature Hash Algorithms Length: 46
            Signature Hash Algorithms (23 algorithms)
                Signature Algorithm: ecdsa_secp256r1_sha256 (0x0403)
                Signature Algorithm: ecdsa_secp384r1_sha384 (0x0503)
                Signature Algorithm: ecdsa_secp521r1_sha512 (0x0603)
                Signature Algorithm: ed25519 (0x0807)
                Signature Algorithm: ed448 (0x0808)
                Signature Algorithm: rsa_pss_pss_sha256 (0x0809)
                Signature Algorithm: rsa_pss_pss_sha384 (0x080a)
                Signature Algorithm: rsa_pss_pss_sha512 (0x080b)
                Signature Algorithm: rsa_pss_rsae_sha256 (0x0804)
                Signature Algorithm: rsa_pss_rsae_sha384 (0x0805)
                Signature Algorithm: rsa_pss_rsae_sha512 (0x0806)
                Signature Algorithm: rsa_pkcs1_sha256 (0x0401)
                Signature Algorithm: rsa_pkcs1_sha384 (0x0501)
                Signature Algorithm: rsa_pkcs1_sha512 (0x0601)
                Signature Algorithm: SHA224 ECDSA (0x0303)
                Signature Algorithm: ecdsa_sha1 (0x0203)
                Signature Algorithm: SHA224 RSA (0x0301)
                Signature Algorithm: rsa_pkcs1_sha1 (0x0201)
                Signature Algorithm: SHA224 DSA (0x0302)
                Signature Algorithm: SHA1 DSA (0x0202)
                Signature Algorithm: SHA256 DSA (0x0402)
                Signature Algorithm: SHA384 DSA (0x0502)
                Signature Algorithm: SHA512 DSA (0x0602)
        Extension: supported_versions (len=9)
            Type: supported_versions (43)
            Length: 9
            Supported Versions length: 8
            Supported Version: TLS 1.3 (0x0304)
            Supported Version: TLS 1.2 (0x0303)
            Supported Version: TLS 1.1 (0x0302)
            Supported Version: TLS 1.0 (0x0301)
        Extension: psk_key_exchange_modes (len=2)
            Type: psk_key_exchange_modes (45)
            Length: 2
            PSK Key Exchange Modes Length: 1
            PSK Key Exchange Mode: PSK with (EC)DHE key establishment (psk_dhe_ke) (1)
        Extension: key_share (len=38)
            Type: key_share (51)
            Length: 38
            Key Share extension
</code>```

ClientHello message from Docker Container (which results in handshake failure SSL alert number 40)

```<code>TLSv1.2 Record Layer: Handshake Protocol: Client Hello
    Content Type: Handshake (22)
    Version: TLS 1.0 (0x0301)
    Length: 234
    Handshake Protocol: Client Hello
        Handshake Type: Client Hello (1)
        Length: 230
        Version: TLS 1.2 (0x0303)
        Random: 20375888f578157f3989533cc8d2c6e5b1db2795dba56ff2…
        Session ID Length: 0
        Cipher Suites Length: 56
        Cipher Suites (28 suites)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x009f)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca9)
            Cipher Suite: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca8)
            Cipher Suite: TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xccaa)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x009e)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (0xc024)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (0x006b)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (0xc023)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (0x0067)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033)
            Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
            Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
            Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA256 (0x003d)
            Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA256 (0x003c)
            Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
            Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
            Cipher Suite: TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff)
        Compression Methods Length: 1
        Compression Methods (1 method)
            Compression Method: null (0)
        Extensions Length: 133
        Extension: server_name (len=47)
            Type: server_name (0)
            Length: 47
            Server Name Indication extension
        Extension: ec_point_formats (len=4)
            Type: ec_point_formats (11)
            Length: 4
            EC point formats Length: 3
            Elliptic curves point formats (3)
                EC point format: uncompressed (0)
                EC point format: ansiX962_compressed_prime (1)
                EC point format: ansiX962_compressed_char2 (2)
        Extension: supported_groups (len=12)
            Type: supported_groups (10)
            Length: 12
            Supported Groups List Length: 10
            Supported Groups (5 groups)
        Extension: session_ticket (len=0)
            Type: session_ticket (35)
            Length: 0
            Data (0 bytes)
        Extension: encrypt_then_mac (len=0)
            Type: encrypt_then_mac (22)
            Length: 0
        Extension: extended_master_secret (len=0)
            Type: extended_master_secret (23)
            Length: 0
        Extension: signature_algorithms (len=42)
            Type: signature_algorithms (13)
            Length: 42
            Signature Hash Algorithms Length: 40
            Signature Hash Algorithms (20 algorithms)
                Signature Algorithm: ecdsa_secp256r1_sha256 (0x0403)
                Signature Algorithm: ecdsa_secp384r1_sha384 (0x0503)
                Signature Algorithm: ecdsa_secp521r1_sha512 (0x0603)
                Signature Algorithm: ed25519 (0x0807)
                Signature Algorithm: ed448 (0x0808)
                Signature Algorithm: rsa_pss_pss_sha256 (0x0809)
                Signature Algorithm: rsa_pss_pss_sha384 (0x080a)
                Signature Algorithm: rsa_pss_pss_sha512 (0x080b)
                Signature Algorithm: rsa_pss_rsae_sha256 (0x0804)
                Signature Algorithm: rsa_pss_rsae_sha384 (0x0805)
                Signature Algorithm: rsa_pss_rsae_sha512 (0x0806)
                Signature Algorithm: rsa_pkcs1_sha256 (0x0401)
                Signature Algorithm: rsa_pkcs1_sha384 (0x0501)
                Signature Algorithm: rsa_pkcs1_sha512 (0x0601)
                Signature Algorithm: SHA224 ECDSA (0x0303)
                Signature Algorithm: SHA224 RSA (0x0301)
                Signature Algorithm: SHA224 DSA (0x0302)
                Signature Algorithm: SHA256 DSA (0x0402)
                Signature Algorithm: SHA384 DSA (0x0502)
                Signature Algorithm: SHA512 DSA (0x0602)

</code>```

This is ServerHello message from Ubuntu 18.04

```<code>TLSv1.2 Record Layer: Handshake Protocol: Multiple Handshake Messages
    Content Type: Handshake (22)
    Version: TLS 1.2 (0x0303)
    Length: 4345
    Handshake Protocol: Server Hello
        Handshake Type: Server Hello (2)
        Length: 81
        Version: TLS 1.2 (0x0303)
        Random: 5ecea16938ffb32685dee0d46241ab4533820a178f3766e6…
        Session ID Length: 32
        Session ID: 5ecea169972b4c49269218eb6d64fbdeedb76539703d48e5…
        Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
        Compression Method: null (0)
        Extensions Length: 9
        Extension: renegotiation_info (len=1)
        Extension: extended_master_secret (len=0)
    Handshake Protocol: Certificate
    Handshake Protocol: Server Key Exchange
        Handshake Type: Server Key Exchange (12)
        Length: 329
        EC Diffie-Hellman Server Params
            Curve Type: named_curve (0x03)
            Named Curve: secp256r1 (0x0017)
            Pubkey Length: 65
            Pubkey: 048f81fb0fcd06c8f1d50620af144965cae3dd3804df3454…
            Signature Algorithm: rsa_pkcs1_sha256 (0x0401)
            Signature Length: 256
            Signature: 76bf06d1a887440d01be65938a92094510ae52e031463d58…
    Handshake Protocol: Server Hello Done
</code>```

Server seems to use CipherSuite TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 which happens to be present in Docker Container ClientHello as well.

So What I am missing in this case. I am new to SSL debugging.

If Ciphersuites are matching what could be different so that servers returns handshake failure?

Please provide me directions what can I investigate next.

I have uploaded wireshark captures at https://gofile.io/d/ERJXNe

There is one capture from docker container running Debian-9,(openssl 1.1.0l) which results in handshake success.

Update:
I tried to use openssl s_client in latest Ubuntu 20.04 VM, it fails with handshake failure.

答:
This is one of the issues described in this github comment by David Benjamin:

https://github.com/openssl/openssl/issues/11438#issuecomment-606927855

Basically it is a buggy server. Even though it is perfectly capable of signing signatures using a SHA-2 hash, it will fail if SHA-1 is not in the list of supported signature algorithm hashes supported by the client.

To test this I first tried this:

```<code>$ openssl s_client -starttls smtp -crlf -connect smtp.email.ap-mumbai-1.oci.oraclecloud.com:587 -no_tls1_3 -trace -sigalgs "RSA+SHA256"
</code>```

I received the handshake failure alert that you got. I then retried the same command, but added an additional SHA1 based sigalg:

```<code>$ openssl s_client -starttls smtp -crlf -connect smtp.email.ap-mumbai-1.oci.oraclecloud.com:587 -no_tls1_3 -trace -sigalgs "RSA+SHA256:RSA+SHA1"
</code>```

This second connection succeeds.

You will notice in your traces that your docker contained based version of OpenSSL is not sending any SHA1 based signature algorithms. To work around the problem you need to additionally configure these.

Body:
I have been trying to use Oracle Cloud Email Delivery Service. Once configured it provides SMTP credentials which you can use to send email from approved senders.

I am stuck with few interesting scenarios.
It works in Ubuntu 18.04 but fails in docker container(running Debian 10) running on same machine.

I was testing handshake with openssl s_client

echo QUIT | openssl s_client -starttls smtp -crlf -connect smtp.email.ap-mumbai-1.oci.oraclecloud.com:587

This command works fine in Ubuntu 18.04 but fails with handshake failure in docker container running Debian 10

Output from Docker Container

root@06369bfe7c16:/var/www/html# echo QUIT | openssl s_client -starttls smtp -crlf -connect smtp.email.ap-mumbai-1.oci.oraclecloud.com:587
CONNECTED(00000003)
140491098481792:error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure:../ssl/record/rec_layer_s3.c:1544:SSL alert number 40
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 199 bytes and written 367 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
root@06369bfe7c16:/var/www/html#

I tried to check openssl versions in both.

18.04 is having openssl version OpenSSL 1.1.1  11 Sep 2018

Docker container is having openssl version OpenSSL 1.1.1d  10 Sep 2019

Can it be something related to versions?

I tried to debug more via Wireshark to see how ClientHello messages are sent -

ClientHello from Ubuntu 18.04 ( which returns in success)

TLSv1.2 Record Layer: Handshake Protocol: Client Hello
    Content Type: Handshake (22)
    Version: TLS 1.0 (0x0301)
    Length: 339
    Handshake Protocol: Client Hello
        Handshake Type: Client Hello (1)
        Length: 335
        Version: TLS 1.2 (0x0303)
        Random: e595f987b8d92387f7114d9dee4df7bc3f00b5b082ba0ec8…
        Session ID Length: 32
        Session ID: 74c873d7894514a047e0763cd14c01fb19a4f238cb9085f2…
        Cipher Suites Length: 62
        Cipher Suites (31 suites)
            Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302)
            Cipher Suite: TLS_CHACHA20_POLY1305_SHA256 (0x1303)
            Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x009f)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca9)
            Cipher Suite: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca8)
            Cipher Suite: TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xccaa)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x009e)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (0xc024)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (0x006b)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (0xc023)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (0x0067)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033)
            Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
            Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
            Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA256 (0x003d)
            Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA256 (0x003c)
            Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
            Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
            Cipher Suite: TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff)
        Compression Methods Length: 1
        Compression Methods (1 method)
            Compression Method: null (0)
        Extensions Length: 200
        Extension: server_name (len=47)
            Type: server_name (0)
            Length: 47
            Server Name Indication extension
        Extension: ec_point_formats (len=4)
            Type: ec_point_formats (11)
            Length: 4
            EC point formats Length: 3
            Elliptic curves point formats (3)
                EC point format: uncompressed (0)
                EC point format: ansiX962_compressed_prime (1)
                EC point format: ansiX962_compressed_char2 (2)
        Extension: supported_groups (len=12)
            Type: supported_groups (10)
            Length: 12
            Supported Groups List Length: 10
            Supported Groups (5 groups)
        Extension: session_ticket (len=0)
            Type: session_ticket (35)
            Length: 0
            Data (0 bytes)
        Extension: encrypt_then_mac (len=0)
            Type: encrypt_then_mac (22)
            Length: 0
        Extension: extended_master_secret (len=0)
            Type: extended_master_secret (23)
            Length: 0
        Extension: signature_algorithms (len=48)
            Type: signature_algorithms (13)
            Length: 48
            Signature Hash Algorithms Length: 46
            Signature Hash Algorithms (23 algorithms)
                Signature Algorithm: ecdsa_secp256r1_sha256 (0x0403)
                Signature Algorithm: ecdsa_secp384r1_sha384 (0x0503)
                Signature Algorithm: ecdsa_secp521r1_sha512 (0x0603)
                Signature Algorithm: ed25519 (0x0807)
                Signature Algorithm: ed448 (0x0808)
                Signature Algorithm: rsa_pss_pss_sha256 (0x0809)
                Signature Algorithm: rsa_pss_pss_sha384 (0x080a)
                Signature Algorithm: rsa_pss_pss_sha512 (0x080b)
                Signature Algorithm: rsa_pss_rsae_sha256 (0x0804)
                Signature Algorithm: rsa_pss_rsae_sha384 (0x0805)
                Signature Algorithm: rsa_pss_rsae_sha512 (0x0806)
                Signature Algorithm: rsa_pkcs1_sha256 (0x0401)
                Signature Algorithm: rsa_pkcs1_sha384 (0x0501)
                Signature Algorithm: rsa_pkcs1_sha512 (0x0601)
                Signature Algorithm: SHA224 ECDSA (0x0303)
                Signature Algorithm: ecdsa_sha1 (0x0203)
                Signature Algorithm: SHA224 RSA (0x0301)
                Signature Algorithm: rsa_pkcs1_sha1 (0x0201)
                Signature Algorithm: SHA224 DSA (0x0302)
                Signature Algorithm: SHA1 DSA (0x0202)
                Signature Algorithm: SHA256 DSA (0x0402)
                Signature Algorithm: SHA384 DSA (0x0502)
                Signature Algorithm: SHA512 DSA (0x0602)
        Extension: supported_versions (len=9)
            Type: supported_versions (43)
            Length: 9
            Supported Versions length: 8
            Supported Version: TLS 1.3 (0x0304)
            Supported Version: TLS 1.2 (0x0303)
            Supported Version: TLS 1.1 (0x0302)
            Supported Version: TLS 1.0 (0x0301)
        Extension: psk_key_exchange_modes (len=2)
            Type: psk_key_exchange_modes (45)
            Length: 2
            PSK Key Exchange Modes Length: 1
            PSK Key Exchange Mode: PSK with (EC)DHE key establishment (psk_dhe_ke) (1)
        Extension: key_share (len=38)
            Type: key_share (51)
            Length: 38
            Key Share extension

ClientHello message from Docker Container (which results in handshake failure SSL alert number 40)

TLSv1.2 Record Layer: Handshake Protocol: Client Hello
    Content Type: Handshake (22)
    Version: TLS 1.0 (0x0301)
    Length: 234
    Handshake Protocol: Client Hello
        Handshake Type: Client Hello (1)
        Length: 230
        Version: TLS 1.2 (0x0303)
        Random: 20375888f578157f3989533cc8d2c6e5b1db2795dba56ff2…
        Session ID Length: 0
        Cipher Suites Length: 56
        Cipher Suites (28 suites)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x009f)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca9)
            Cipher Suite: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca8)
            Cipher Suite: TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xccaa)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x009e)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (0xc024)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (0x006b)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (0xc023)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (0x0067)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
            Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033)
            Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
            Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
            Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA256 (0x003d)
            Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA256 (0x003c)
            Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
            Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
            Cipher Suite: TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff)
        Compression Methods Length: 1
        Compression Methods (1 method)
            Compression Method: null (0)
        Extensions Length: 133
        Extension: server_name (len=47)
            Type: server_name (0)
            Length: 47
            Server Name Indication extension
        Extension: ec_point_formats (len=4)
            Type: ec_point_formats (11)
            Length: 4
            EC point formats Length: 3
            Elliptic curves point formats (3)
                EC point format: uncompressed (0)
                EC point format: ansiX962_compressed_prime (1)
                EC point format: ansiX962_compressed_char2 (2)
        Extension: supported_groups (len=12)
            Type: supported_groups (10)
            Length: 12
            Supported Groups List Length: 10
            Supported Groups (5 groups)
        Extension: session_ticket (len=0)
            Type: session_ticket (35)
            Length: 0
            Data (0 bytes)
        Extension: encrypt_then_mac (len=0)
            Type: encrypt_then_mac (22)
            Length: 0
        Extension: extended_master_secret (len=0)
            Type: extended_master_secret (23)
            Length: 0
        Extension: signature_algorithms (len=42)
            Type: signature_algorithms (13)
            Length: 42
            Signature Hash Algorithms Length: 40
            Signature Hash Algorithms (20 algorithms)
                Signature Algorithm: ecdsa_secp256r1_sha256 (0x0403)
                Signature Algorithm: ecdsa_secp384r1_sha384 (0x0503)
                Signature Algorithm: ecdsa_secp521r1_sha512 (0x0603)
                Signature Algorithm: ed25519 (0x0807)
                Signature Algorithm: ed448 (0x0808)
                Signature Algorithm: rsa_pss_pss_sha256 (0x0809)
                Signature Algorithm: rsa_pss_pss_sha384 (0x080a)
                Signature Algorithm: rsa_pss_pss_sha512 (0x080b)
                Signature Algorithm: rsa_pss_rsae_sha256 (0x0804)
                Signature Algorithm: rsa_pss_rsae_sha384 (0x0805)
                Signature Algorithm: rsa_pss_rsae_sha512 (0x0806)
                Signature Algorithm: rsa_pkcs1_sha256 (0x0401)
                Signature Algorithm: rsa_pkcs1_sha384 (0x0501)
                Signature Algorithm: rsa_pkcs1_sha512 (0x0601)
                Signature Algorithm: SHA224 ECDSA (0x0303)
                Signature Algorithm: SHA224 RSA (0x0301)
                Signature Algorithm: SHA224 DSA (0x0302)
                Signature Algorithm: SHA256 DSA (0x0402)
                Signature Algorithm: SHA384 DSA (0x0502)
                Signature Algorithm: SHA512 DSA (0x0602)

This is ServerHello message from Ubuntu 18.04

TLSv1.2 Record Layer: Handshake Protocol: Multiple Handshake Messages
    Content Type: Handshake (22)
    Version: TLS 1.2 (0x0303)
    Length: 4345
    Handshake Protocol: Server Hello
        Handshake Type: Server Hello (2)
        Length: 81
        Version: TLS 1.2 (0x0303)
        Random: 5ecea16938ffb32685dee0d46241ab4533820a178f3766e6…
        Session ID Length: 32
        Session ID: 5ecea169972b4c49269218eb6d64fbdeedb76539703d48e5…
        Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
        Compression Method: null (0)
        Extensions Length: 9
        Extension: renegotiation_info (len=1)
        Extension: extended_master_secret (len=0)
    Handshake Protocol: Certificate
    Handshake Protocol: Server Key Exchange
        Handshake Type: Server Key Exchange (12)
        Length: 329
        EC Diffie-Hellman Server Params
            Curve Type: named_curve (0x03)
            Named Curve: secp256r1 (0x0017)
            Pubkey Length: 65
            Pubkey: 048f81fb0fcd06c8f1d50620af144965cae3dd3804df3454…
            Signature Algorithm: rsa_pkcs1_sha256 (0x0401)
            Signature Length: 256
            Signature: 76bf06d1a887440d01be65938a92094510ae52e031463d58…
    Handshake Protocol: Server Hello Done

Server seems to use CipherSuite TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 which happens to be present in Docker Container ClientHello as well.

So What I am missing in this case. I am new to SSL debugging.

If Ciphersuites are matching what could be different so that servers returns handshake failure?

Please provide me directions what can I investigate next.

I have uploaded wireshark captures at https://gofile.io/d/ERJXNe

There is one capture from docker container running Debian-9,(openssl 1.1.0l) which results in handshake success.

Update:
I tried to use openssl s_client in latest Ubuntu 20.04 VM, it fails with handshake failure.

Body:
This is one of the issues described in this github comment by David Benjamin:

https://github.com/openssl/openssl/issues/11438#issuecomment-606927855

Basically it is a buggy server. Even though it is perfectly capable of signing signatures using a SHA-2 hash, it will fail if SHA-1 is not in the list of supported signature algorithm hashes supported by the client.

To test this I first tried this:

$ openssl s_client -starttls smtp -crlf -connect smtp.email.ap-mumbai-1.oci.oraclecloud.com:587 -no_tls1_3 -trace -sigalgs "RSA+SHA256"

I received the handshake failure alert that you got. I then retried the same command, but added an additional SHA1 based sigalg:

$ openssl s_client -starttls smtp -crlf -connect smtp.email.ap-mumbai-1.oci.oraclecloud.com:587 -no_tls1_3 -trace -sigalgs "RSA+SHA256:RSA+SHA1"

This second connection succeeds.

You will notice in your traces that your docker contained based version of OpenSSL is not sending any SHA1 based signature algorithms. To work around the problem you need to additionally configure these.


来源: stackexchange

问:
Geofence with multiple transitions Types set - Android
Im confused with the Android Geofence Api. So the method says .setTransitionTypes(int). However when ever I try to set my geofence to monitor both enter and exit of a particular geofence, it only monitors the transition type of the Transition that I set it to monitor.

Here is an Example of my code

```<code>public Geofence toGeofence() {
// Build a new Geofence object
return new Geofence.Builder()
        .setRequestId(getId())
        .setTransitionTypes(getTransitionType()) //Geofence.GEOFENCE_TRANSITION_ENTER
        .setTransitionTypes(getTransitionType2())// Geofence.GEOFENCE_TRANSITION_EXIT
        .setCircularRegion(
                getLatitude(), getLongitude(), getRadius())
        .setExpirationDuration(mExpirationDuration)
        .build();}
</code>```

This only monitors the last transition type set which is the exit transition, I have resorted to creating 2 geofences for the same area, one to monitor each transition but I feel like that isnt the way to go. Any help?

答:
For adding multiple geofence transition type you can use | for java and for kotlin you have to use or keyword between transition types. For more ref Create geofence objects from android developer doc

for Java

new Geofence.Builder().setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)

For Kotlin

Geofence.Builder().setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER or Geofence.GEOFENCE_TRANSITION_EXIT)

ContentLicense: CC BY-SA 3.0

Body:
Im confused with the Android Geofence Api. So the method says .setTransitionTypes(int). However when ever I try to set my geofence to monitor both enter and exit of a particular geofence, it only monitors the transition type of the Transition that I set it to monitor.

Here is an Example of my code

public Geofence toGeofence() {
// Build a new Geofence object
return new Geofence.Builder()
        .setRequestId(getId())
        .setTransitionTypes(getTransitionType()) //Geofence.GEOFENCE_TRANSITION_ENTER
        .setTransitionTypes(getTransitionType2())// Geofence.GEOFENCE_TRANSITION_EXIT
        .setCircularRegion(
                getLatitude(), getLongitude(), getRadius())
        .setExpirationDuration(mExpirationDuration)
        .build();}

This only monitors the last transition type set which is the exit transition, I have resorted to creating 2 geofences for the same area, one to monitor each transition but I feel like that isnt the way to go. Any help?

ContentLicense: CC BY-SA 4.0


问:
OpenCV Video capture using keyboard to start/stop
I have a running script capable of starting/stopping a video stream using 2 different keys;

Program runs and shows the live stream.

When ESC is hit, the program exits.

When SPACE is hit, the video stream is captured.

However, when a video is captured it stores all the stream from the beginning of script execution.

```<code>    import cv2
    import numpy as np

    capture = cv2.VideoCapture(1)
    codec = cv2.VideoWriter_fourcc(*'XVID')
    output = cv2.VideoWriter('CAPTURE.avi', codec, 30, (640, 480))

    while True:
        ret, frame_temp = capture.read()
        cv2.imshow('FRAME', frame_temp)
        key=cv2.waitKey(1)
        if key%256 == 27:
            break
        elif key%256 == 32:
            output.write(frame_temp)

    capture.release()
    output.release()
    cv2.destroyAllWindows()
</code>```

So, instead when the program runs I would like;

Program runs and shows the live stream.

Begin recording the stream when SPACE is hit and stop the recording when SPACE is hit once more.

Any suggestions would be much appreciated.

答:
This line while True: isn't exactly ideal for what you're trying to do. I would recommend you define a function to do the recording and have it recursively call itself if the user stops recording via the space key. The top of your script would still start the same:

```<code>import cv2
import numpy as np

capture = cv2.VideoCapture(1)
codec = cv2.VideoWriter_fourcc(*'XVID')
output = cv2.VideoWriter('CAPTURE.avi', codec, 30, (640, 480))
</code>```

Next you would define your function, it starts by waiting (forever) for a key to be pressed. Once a key is pressed if it is escape (27) it exits the function and cleans up, if it is space (32) it sets a boolean flag that starts recording (while loop). If neither escape or space is pressed it calls itself and starts the process over. Inside the while loop it checks if a key is pressed if so it checks if it is escape (27) or space (32). If either it hit it either exits the function (escape) or haults recording by calling itself which starts the process all over again (space).

```<code>def wait_then_capture():
    key = cv2.waitKey(0)
    if key%256 == 27:
        return
    elif key%256 == 32:
        record = True
    else:
        wait_then_capture()
    while record == True:
        ret, frame_temp = capture.read()
        cv2.imshow('FRAME', frame_temp)
        key = cv2.waitKey(1)
        if key%256 == 27:
            return
        elif key%256 == 32:
            break
        output.write(frame)
    wait_then_capture()
</code>```

We then call our new function and end the script with the same cleanup you already have

```<code>wait_then_capture()

capture.release()
output.release()
cv2.destroyAllWindows()
</code>```

Your finished script would look like this

```<code>import cv2
import numpy as np

capture = cv2.VideoCapture(1)
codec = cv2.VideoWriter_fourcc(*'XVID')
output = cv2.VideoWriter('CAPTURE.avi', codec, 30, (640, 480))

def wait_then_capture():
    key = cv2.waitKey(0)
    if key%256 == 27:
        return
    elif key%256 == 32:
        record = True
    else:
        wait_then_capture()
    while record == True:
        ret, frame_temp = capture.read()
        cv2.imshow('FRAME', frame_temp)
        key = cv2.waitKey(1)
        if key%256 == 27:
            return
        elif key%256 == 32:
            break
        output.write(frame)
    wait_then_capture()

wait_then_capture()

capture.release()
output.release()
cv2.destroyAllWindows()
</code>```

Body:
I have a running script capable of starting/stopping a video stream using 2 different keys;

Program runs and shows the live stream.

When ESC is hit, the program exits.

When SPACE is hit, the video stream is captured.

However, when a video is captured it stores all the stream from the beginning of script execution.

    import cv2
    import numpy as np

    capture = cv2.VideoCapture(1)
    codec = cv2.VideoWriter_fourcc(*'XVID')
    output = cv2.VideoWriter('CAPTURE.avi', codec, 30, (640, 480))

    while True:
        ret, frame_temp = capture.read()
        cv2.imshow('FRAME', frame_temp)
        key=cv2.waitKey(1)
        if key%256 == 27:
            break
        elif key%256 == 32:
            output.write(frame_temp)

    capture.release()
    output.release()
    cv2.destroyAllWindows()

So, instead when the program runs I would like;

Program runs and shows the live stream.

Begin recording the stream when SPACE is hit and stop the recording when SPACE is hit once more.

Any suggestions would be much appreciated.

Body:
This line while True: isn't exactly ideal for what you're trying to do. I would recommend you define a function to do the recording and have it recursively call itself if the user stops recording via the space key. The top of your script would still start the same:

import cv2
import numpy as np

capture = cv2.VideoCapture(1)
codec = cv2.VideoWriter_fourcc(*'XVID')
output = cv2.VideoWriter('CAPTURE.avi', codec, 30, (640, 480))

Next you would define your function, it starts by waiting (forever) for a key to be pressed. Once a key is pressed if it is escape (27) it exits the function and cleans up, if it is space (32) it sets a boolean flag that starts recording (while loop). If neither escape or space is pressed it calls itself and starts the process over. Inside the while loop it checks if a key is pressed if so it checks if it is escape (27) or space (32). If either it hit it either exits the function (escape) or haults recording by calling itself which starts the process all over again (space).

def wait_then_capture():
    key = cv2.waitKey(0)
    if key%256 == 27:
        return
    elif key%256 == 32:
        record = True
    else:
        wait_then_capture()
    while record == True:
        ret, frame_temp = capture.read()
        cv2.imshow('FRAME', frame_temp)
        key = cv2.waitKey(1)
        if key%256 == 27:
            return
        elif key%256 == 32:
            break
        output.write(frame)
    wait_then_capture()

We then call our new function and end the script with the same cleanup you already have

wait_then_capture()

capture.release()
output.release()
cv2.destroyAllWindows()

Your finished script would look like this

import cv2
import numpy as np

capture = cv2.VideoCapture(1)
codec = cv2.VideoWriter_fourcc(*'XVID')
output = cv2.VideoWriter('CAPTURE.avi', codec, 30, (640, 480))

def wait_then_capture():
    key = cv2.waitKey(0)
    if key%256 == 27:
        return
    elif key%256 == 32:
        record = True
    else:
        wait_then_capture()
    while record == True:
        ret, frame_temp = capture.read()
        cv2.imshow('FRAME', frame_temp)
        key = cv2.waitKey(1)
        if key%256 == 27:
            return
        elif key%256 == 32:
            break
        output.write(frame)
    wait_then_capture()

wait_then_capture()

capture.release()
output.release()
cv2.destroyAllWindows()


问:
How to make Username Email case Insensitive in Symfony
What i need

Username : ABC@gmail.com  email address stored in db &  input  will be lowercase.

there is no canonical field  which has lower case email address stored.

The solution

```<code>     select * from view   where trim(lower(username))=trim(lower(input_username))
</code>```

I read Url  https://symfony.com/doc/current/security/user_provider.html

security.yml

```<code>providers:
    entity_provider:
        entity:
            class: App\Entity\User
</code>```

property: username

I have commented out property as i need to call loadUserByUsername in repository.

Service.yml

```<code>app.repository.user_repositry:
    class: Doctrine\ORM\EntityRepository
    autowire: false

    autoconfigure: true
    factory: ["@doctrine.orm.entity_manager", getRepository]
    arguments: []
    tags: ['doctrine.repository_service']
</code>```

Repository code

```<code>            class UserRepository extends EntityRepository implements UserLoaderInterface
            {

                public function loadUserByUsername($username)
                {

                    return $em->createQuery(
                            'SELECT u
                            FROM App\CORE\Entity\User u
                            WHERE LOWER(u.username) = :query'
                        )
                        //->where('LOWER(user.username) = :username')
                        ->setParameter('query', strtolower($username))
                        //->setParameter('query', $usernameOrEmail)
                        ->getQuery()
                        ->getOneOrNullResult();
                }
            }
</code>```

Problem occurs

```<code>  You must either make the "App\Entity\User" entity Doctrine Repository ("Doctrine\ORM\EntityRepository") implement "Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface" or set the "property" option in the corresponding entity provider configuration."

If i set Entity Abstract class then My app stops working

    namespace App\CORE\Entity;

   use Doctrine\ORM\Mapping as ORM;
   use Symfony\Component\Security\Core\User\UserInterface;
   use Doctrine\ORM\EntityRepository;
   use Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface;
   use Doctrine\ORM\Mapping\MappedSuperclass;

    /**
    * @ORM\Table(name="users")
   * @ORM\Entity
    */

   class User  implements UserInterface,\Serializable
</code>```

After fixing eror making enity abstract causing issues.

```<code>   //abstract class User extends EntityRepository implements UserLoaderInterface,UserInterface,\Serializable
</code>```

if i change enity to abstract my application not working.

any suggestion can i implement without making entity class abstract.

Refrence

https://symfony.com/doc/current/security/user_provider.html

How to do username case insensitive in login form?

答:
You can use FOSUser approach with canonical username and email

Add additional field && save the canonical value

Use canonical field to search user

```<code>public function findUserByUsername($username)
{
    return $this->findUserBy(['usernameCanonical' => $this->canonicalFieldsUpdater->canonicalizeUsername($username)]);
}
//------------

public function canonicalize($string)
{
    if (null === $string) {
        return;
    }

    $encoding = mb_detect_encoding($string);
    $result = $encoding
        ? mb_convert_case($string, MB_CASE_LOWER, $encoding)
        : mb_convert_case($string, MB_CASE_LOWER);

    return $result;
}
</code>```

Body:
What i need

Username : ABC@gmail.com  email address stored in db &  input  will be lowercase.

there is no canonical field  which has lower case email address stored.

The solution

     select * from view   where trim(lower(username))=trim(lower(input_username))

I read Url  https://symfony.com/doc/current/security/user_provider.html

security.yml

providers:
    entity_provider:
        entity:
            class: App\Entity\User

property: username

I have commented out property as i need to call loadUserByUsername in repository.

Service.yml

app.repository.user_repositry:
    class: Doctrine\ORM\EntityRepository
    autowire: false

    autoconfigure: true
    factory: ["@doctrine.orm.entity_manager", getRepository]
    arguments: []
    tags: ['doctrine.repository_service']

Repository code

            class UserRepository extends EntityRepository implements UserLoaderInterface
            {

                public function loadUserByUsername($username)
                {

                    return $em->createQuery(
                            'SELECT u
                            FROM App\CORE\Entity\User u
                            WHERE LOWER(u.username) = :query'
                        )
                        //->where('LOWER(user.username) = :username')
                        ->setParameter('query', strtolower($username))
                        //->setParameter('query', $usernameOrEmail)
                        ->getQuery()
                        ->getOneOrNullResult();
                }
            }

Problem occurs

  You must either make the "App\Entity\User" entity Doctrine Repository ("Doctrine\ORM\EntityRepository") implement "Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface" or set the "property" option in the corresponding entity provider configuration."

If i set Entity Abstract class then My app stops working

    namespace App\CORE\Entity;

   use Doctrine\ORM\Mapping as ORM;
   use Symfony\Component\Security\Core\User\UserInterface;
   use Doctrine\ORM\EntityRepository;
   use Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface;
   use Doctrine\ORM\Mapping\MappedSuperclass;

    /**
    * @ORM\Table(name="users")
   * @ORM\Entity
    */

   class User  implements UserInterface,\Serializable

After fixing eror making enity abstract causing issues.

   //abstract class User extends EntityRepository implements UserLoaderInterface,UserInterface,\Serializable

if i change enity to abstract my application not working.

any suggestion can i implement without making entity class abstract.

Refrence

https://symfony.com/doc/current/security/user_provider.html

How to do username case insensitive in login form?

Body:
You can use FOSUser approach with canonical username and email

Add additional field && save the canonical value

Use canonical field to search user

public function findUserByUsername($username)
{
    return $this->findUserBy(['usernameCanonical' => $this->canonicalFieldsUpdater->canonicalizeUsername($username)]);
}
//------------

public function canonicalize($string)
{
    if (null === $string) {
        return;
    }

    $encoding = mb_detect_encoding($string);
    $result = $encoding
        ? mb_convert_case($string, MB_CASE_LOWER, $encoding)
        : mb_convert_case($string, MB_CASE_LOWER);

    return $result;
}


问:
How do I run a shell script from rpm during the build process?
Basically I want my build process to do this:

Run a shell script that strips data from csv files and combines them into a single csv.

The resulting csv output from that script is then packaged in the rpm.

When rpm -install is run, the csv file (not the script) is placed in a specific location on the target machine.

I'm very new to RPM so I'm sorry if I've made a blunder with the code below, but it gives me several errors when trying to build or install.

I attempted to run a script from the sources directory

I'm a little confused on how the expected flow of rpm should work. In testing, I'm building and installing on the same machine, but in practice it will be on two machines.

When I run the code below, does it put a copy of my source files into the .rpm file?
I'm wondering why it doesn't work. (it says process.sh does not exist)

```<code>Name:       Test
Version:    1
Release:    1
Summary:    Test
License:    FIXME

%description
this is a test build

%prep
echo "BUILDROOT = $RPM_BUILD_ROOT"
mkdir -p -m777 $RPM_BUILD_ROOT/usr/local/bin/
cp /home/myuser/foo/util/* $RPM_BUILD_ROOT/usr/local/bin
cd $RPM_BUILD_ROOT/usr/local/bin/
./process.sh hosts.csv processed.csv
exit

%files
%attr(0777, root, root) /foo/processed.csv
</code>```

答:
You need to:

Set up the build tree for your user, e.g. run rpmdev-setuptree

Place the source files to SOURCES in the build tree

Declare some Source tags. It is crucial for a proper build. Because this is how you reference the files that make up your build, during the build.

E.g.

```<code>Source0: process.sh
Source1: util.tar.gz
</code>```

The util.tar.gz can be the tarball for all the numerous CSV files (I assume there are too many, so it would be not feasible to have an individual Source entry for each of them.

Then:

in the %prep section you would extract %{SOURCE1}.

in the %build section you can combine them into a single file

in the %install section you would install the combined file

```<code>%prep
cp -p %{SOURCE0} .
tar zxvf %{SOURCE1}

# ...

%install
%{__mkdir} -p $RPM_BUILD_ROOT%{_datadir}/%{name}
%{__install} -m 644 -p processed.csv \
    $RPM_BUILD_ROOT%{_datadir}/%{name}/

%files
%{_datadir}/%{name}/processed.csv
</code>```

P.S. I know for a beginner it would sound a bit an unnecessary task to copy something to the SOURCES directory when you already have it elsewhere, but this is the way to go still.

Body:
Basically I want my build process to do this:

Run a shell script that strips data from csv files and combines them into a single csv.

The resulting csv output from that script is then packaged in the rpm.

When rpm -install is run, the csv file (not the script) is placed in a specific location on the target machine.

I'm very new to RPM so I'm sorry if I've made a blunder with the code below, but it gives me several errors when trying to build or install.

I attempted to run a script from the sources directory

I'm a little confused on how the expected flow of rpm should work. In testing, I'm building and installing on the same machine, but in practice it will be on two machines.

When I run the code below, does it put a copy of my source files into the .rpm file?
I'm wondering why it doesn't work. (it says process.sh does not exist)

Name:       Test
Version:    1
Release:    1
Summary:    Test
License:    FIXME

%description
this is a test build

%prep
echo "BUILDROOT = $RPM_BUILD_ROOT"
mkdir -p -m777 $RPM_BUILD_ROOT/usr/local/bin/
cp /home/myuser/foo/util/* $RPM_BUILD_ROOT/usr/local/bin
cd $RPM_BUILD_ROOT/usr/local/bin/
./process.sh hosts.csv processed.csv
exit

%files
%attr(0777, root, root) /foo/processed.csv

Body:
You need to:

Set up the build tree for your user, e.g. run rpmdev-setuptree

Place the source files to SOURCES in the build tree

Declare some Source tags. It is crucial for a proper build. Because this is how you reference the files that make up your build, during the build.

E.g.

Source0: process.sh
Source1: util.tar.gz

The util.tar.gz can be the tarball for all the numerous CSV files (I assume there are too many, so it would be not feasible to have an individual Source entry for each of them.

Then:

in the %prep section you would extract %{SOURCE1}.

in the %build section you can combine them into a single file

in the %install section you would install the combined file

%prep
cp -p %{SOURCE0} .
tar zxvf %{SOURCE1}

# ...

%install
%{__mkdir} -p $RPM_BUILD_ROOT%{_datadir}/%{name}
%{__install} -m 644 -p processed.csv \
    $RPM_BUILD_ROOT%{_datadir}/%{name}/

%files
%{_datadir}/%{name}/processed.csv

P.S. I know for a beginner it would sound a bit an unnecessary task to copy something to the SOURCES directory when you already have it elsewhere, but this is the way to go still.


问:
Python beautifulsoup loading more data
When you scroll through a web page it loads more data. How do you get bs4 to load all of these data? </p>

答: Beautiful soup is a parser which parses the data you feed it. For loading whole data from a dynamic webpage, you can use selenium like Selenium: Scroll to end of page in dynamically loading webpage </p>

Title: Python beautifulsoup loading more data


问:
Azure Search - Cost study of MergeOrUpload operation?
I've written two different functions to populate the same document but different attributes. One of the function updates A1,A2,A3 attributes of document X and other function updates A4,A5 attributes of same document X given the document id. They are using MergeOrUpload operation to update the document.

I'm trying to evaluate the cost of MergeOrUpload operation. How it works at the backend and does it read the entire document and then merge the new attribute values and push back the document to the index or what? How much cost-effective it is?

答:
It would be more efficient to include all attributes in a single call, rather than first creating the document with A1, A2 and A3, and then sending a mergeOrUpdate call to add A4, A5 and A6. In the backend, all index files are "read-only" to facilitate the distributed and concurrent nature of the service, so when you update a document, we actually need to do a copy of the original document which includes the newly updated attributes.

Your best bet to get accurate cost would be to do your own testing using your own data and usage pattern, however, its likely that you will discover creating the document with all the attributes is the most efficient approach.


问:
How can i make a code run automatically every 30 mins in shell script or PHP?
I have a code which I want to run every 30mins. Since it is not possible to do it manually over 30 days I wanted to make it an automated process. Please suggest me how to do it. I want to execute this command in Putty. </p>

```<code>--user root --host 10.0.2.140 --port 3306 --socket /var/lib/mysql/mysql.sock
</code>```

答:
Unix and derivatives use Cron Jobs

http://en.wikipedia.org/wiki/Cron

Windows uses scheduled tasks.

https://superuser.com/questions/85297/how-to-schedule-a-task-in-windows-7

Note that there are also some Cron clone implementations for windows available if you prefer.

Body:
I have a code which I want to run every 30mins. Since it is not possible to do it manually over 30 days I wanted to make it an automated process. Please suggest me how to do it. I want to execute this command in Putty.

--user root --host 10.0.2.140 --port 3306 --socket /var/lib/mysql/mysql.sock


问:
Access Control Origin Header error using Axios
I'm making an API call using Axios in a React Web app. However, I'm getting this error in Chrome:

XMLHttpRequest cannot load
https://example.restdb.io/rest/mock-data. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:8080' is therefore not allowed
access.
```
</blockquote>
<pre class="lang-js prettyprint-override"><code>{
    axios
      .get("https://example.restdb.io/rest/mock-data", {
        headers: {
          "x-apikey": "API_KEY",
        },
        responseType: "json",
      })
      .then((response) => {
        this.setState({ tableData: response.data });
      });
}
</code>```

I have also read several answers on Stack Overflow about the same issue, titled Access-Control-Allow-Origin but still couldn't figure out how to solve this. I don't want to use an extension in Chrome or use a temporary hack to solve this. Please suggest the standard way of solving the above issue.

After trying out few answers I have tried with this,

headers: {
  'x-apikey': '59a7ad19f5a9fa0808f11931',
  'Access-Control-Allow-Origin' : '*',
  'Access-Control-Allow-Methods':'GET,PUT,POST,DELETE,PATCH,OPTIONS',
},
```
<p>Now I get the error as,</p>
<blockquote>
<pre class="lang-none prettyprint-override"><code>Request header field Access-Control-Allow-Origin is not
allowed by Access-Control-Allow-Headers in preflight response
</code>```

答:
I had a similar problem when I tried to create the React Axios instance.

I resolved it using the below approach.

```<code>const instance = axios.create({
  baseURL: "https://jsonplaceholder.typicode.com/",
  withCredentials: false,
  headers: {
    'Access-Control-Allow-Origin' : '*',
    'Access-Control-Allow-Methods':'GET,PUT,POST,DELETE,PATCH,OPTIONS',
    }
});
</code>```

Body:
I'm making an API call using Axios in a React Web app. However, I'm getting this error in Chrome:

XMLHttpRequest cannot load
https://example.restdb.io/rest/mock-data. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:8080' is therefore not allowed
access.

{
    axios
      .get("https://example.restdb.io/rest/mock-data", {
        headers: {
          "x-apikey": "API_KEY",
        },
        responseType: "json",
      })
      .then((response) => {
        this.setState({ tableData: response.data });
      });
}

I have also read several answers on Stack Overflow about the same issue, titled Access-Control-Allow-Origin but still couldn't figure out how to solve this. I don't want to use an extension in Chrome or use a temporary hack to solve this. Please suggest the standard way of solving the above issue.

After trying out few answers I have tried with this,

headers: {
  'x-apikey': '59a7ad19f5a9fa0808f11931',
  'Access-Control-Allow-Origin' : '*',
  'Access-Control-Allow-Methods':'GET,PUT,POST,DELETE,PATCH,OPTIONS',
},

Now I get the error as,

Request header field Access-Control-Allow-Origin is not
allowed by Access-Control-Allow-Headers in preflight response

Body:
I had a similar problem when I tried to create the React Axios instance.

I resolved it using the below approach.

const instance = axios.create({
  baseURL: "https://jsonplaceholder.typicode.com/",
  withCredentials: false,
  headers: {
    'Access-Control-Allow-Origin' : '*',
    'Access-Control-Allow-Methods':'GET,PUT,POST,DELETE,PATCH,OPTIONS',
    }
});


问:
How to loop case statement in a whiptail

#!/bin/bash
function advancedMenu() {
    ADVSEL=$(whiptail --title "Advanced Menu" --fb --menu "Choose an option" 15 60 4 \
    "1" "Delete group" \
    "2" "Create login name" \
    "3" "Exit" 3>&1 1>&2 2>&3)
    case "$ADVSEL" in
    1)
    echo "Option 1"
    whiptail --title "Option 1" --msgbox "You chose group deleting. Exit status $?" 8 45
    bash ./script3;;
    2)
    echo "Option 2"
    whiptail --title "Option 1" --msgbox "You chose login name creating. Exit status $?" 8 45
    bash ./script;;
    3)
    echo "Option 3"
    whiptail --title "Option 1" --msgbox "You chose exit. Exit status $?" 8 45
    ;;
    esac
}

advancedMenu
```

<hr>

<p>I don't know how to loop my case statement. I have user friendly interface here. Someone chooses 1\2 or exit. 1 and 2 runs another scripts. So when 1 is clicked and scripted is finished, I need the main menu back until case 3 is clicked. I will be grateful for your help!</p>

<hr>

```#!/bin/bash
export NEWT_COLORS='
window=white,blue
border=white,green
textbox=white,green
button=black,white
'

{
    for ((i = 0 ; i <= 100 ; i += 1)); do
    sleep 1
    echo $i
    done

} | whiptail --gauge "Wait..." 6 60 0

touch 35_2.csv
while read line; do
IFS=","
set -- $line
group_name=$1
student_name=$2
student_name=`echo $student_name | tr -d '\r\n' `
login_name=`echo $student_name | sed 's/[b\`]//g;'`
login_name=`echo $login_name | sed 'y/Р°Р±РІРіРґРµС”Р·РёС–С—Р№РєР»РјРЅРѕРїСЂСЃС‚СѓС„С…СЊ/abvgdeeziiijklmnoprstufh_/'`
login_name=`echo $login_name | sed 's/ /_/g; s/С†/ts/g; s/Р¶/zh/g; s/С‡/ch/g; s/С€/sh/g; s/С‰/sh/g; s/СЋ/yu/g; s/СЏ/ya/;'`
echo "$group_name, $student_name, $login_name" >> 35_2.csv
done < 35_2.csv
```

Don't look at wrong encoding. Your decision seemed to be right. The first script runs then menu goes back. However, when I start the second script the menu does not go back. Attached the 2nd's script code.

答:
Simply put a while loop around it.

```<code>#!/bin/bash
function advancedMenu() {
    while :; do
        ADVSEL=$(whiptail --title "Advanced Menu" --fb --menu "Choose an option" 15 60 4 \

            "1" "Delete group" \
            "2" "Create login name" \
            "3" "Exit" 3>&1 1>&2 2>&3)
        case "$ADVSEL" in
        1)
            echo "Option 1"
            whiptail --title "Option 1" --msgbox "You chose group deleting. Exit status $?" 8 45
            bash ./script3;;
        2)
            echo "Option 2"
            whiptail --title "Option 1" --msgbox "You chose login name creating. Exit status $?" 8 45
            bash ./script;;
        3)
            echo "Option 3"
            whiptail --title "Option 1" --msgbox "You chose exit. Exit status $?" 8 45
            return
            ;;
        esac
    done
}
advancedMenu
</code>```

I'm not sure what you expect Exit status $? to show. $? is the exit status of the echo statement on the previous line, so it will almost always just be 0.

Body:
#!/bin/bash
function advancedMenu() {
    ADVSEL=$(whiptail --title "Advanced Menu" --fb --menu "Choose an option" 15 60 4 \
    "1" "Delete group" \
    "2" "Create login name" \
    "3" "Exit" 3>&1 1>&2 2>&3)
    case "$ADVSEL" in
    1)
    echo "Option 1"
    whiptail --title "Option 1" --msgbox "You chose group deleting. Exit status $?" 8 45
    bash ./script3;;
    2)
    echo "Option 2"
    whiptail --title "Option 1" --msgbox "You chose login name creating. Exit status $?" 8 45
    bash ./script;;
    3)
    echo "Option 3"
    whiptail --title "Option 1" --msgbox "You chose exit. Exit status $?" 8 45
    ;;
    esac
}

advancedMenu

I don't know how to loop my case statement. I have user friendly interface here. Someone chooses 1\2 or exit. 1 and 2 runs another scripts. So when 1 is clicked and scripted is finished, I need the main menu back until case 3 is clicked. I will be grateful for your help!

#!/bin/bash
export NEWT_COLORS='
window=white,blue
border=white,green
textbox=white,green
button=black,white
'

{
    for ((i = 0 ; i <= 100 ; i += 1)); do
    sleep 1
    echo $i
    done

} | whiptail --gauge "Wait..." 6 60 0

touch 35_2.csv
while read line; do
IFS=","
set -- $line
group_name=$1
student_name=$2
student_name=`echo $student_name | tr -d '\r\n' `
login_name=`echo $student_name | sed 's/[b\`]//g;'`
login_name=`echo $login_name | sed 'y/Р°Р±РІРіРґРµС”Р·РёС–С—Р№РєР»РјРЅРѕРїСЂСЃС‚СѓС„С…СЊ/abvgdeeziiijklmnoprstufh_/'`
login_name=`echo $login_name | sed 's/ /_/g; s/С†/ts/g; s/Р¶/zh/g; s/С‡/ch/g; s/С€/sh/g; s/С‰/sh/g; s/СЋ/yu/g; s/СЏ/ya/;'`
echo "$group_name, $student_name, $login_name" >> 35_2.csv
done < 35_2.csv

Don't look at wrong encoding. Your decision seemed to be right. The first script runs then menu goes back. However, when I start the second script the menu does not go back. Attached the 2nd's script code.

Body:
Simply put a while loop around it.

#!/bin/bash
function advancedMenu() {
    while :; do
        ADVSEL=$(whiptail --title "Advanced Menu" --fb --menu "Choose an option" 15 60 4 \

            "1" "Delete group" \
            "2" "Create login name" \
            "3" "Exit" 3>&1 1>&2 2>&3)
        case "$ADVSEL" in
        1)
            echo "Option 1"
            whiptail --title "Option 1" --msgbox "You chose group deleting. Exit status $?" 8 45
            bash ./script3;;
        2)
            echo "Option 2"
            whiptail --title "Option 1" --msgbox "You chose login name creating. Exit status $?" 8 45
            bash ./script;;
        3)
            echo "Option 3"
            whiptail --title "Option 1" --msgbox "You chose exit. Exit status $?" 8 45
            return
            ;;
        esac
    done
}
advancedMenu

I'm not sure what you expect Exit status $? to show. $? is the exit status of the echo statement on the previous line, so it will almost always just be 0.


问:
React Tabs onClick get index of selected Tab
I am new to React and I am trying to get the selected Tab and from a onClick event.

Below is my code along with output.

How would I implement the handleSelect function?

Here is my current code:

```<code>class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value : 0};
  }

  getState(){
    return this.state.value;
  }

  setState(state){
    this.state = state;
  }

  handleSelect(index){
    console.log('Selected tab: ' + index);
  }

  render() {
    let selectedIndex = this.getState();

    return (
      <header className="header">
        <AppBar title="App Bar" />

        <Tabs>
          <Tab label="Core Courses" onClick={this.handleSelect(0)} />
          <Tab label="Capstone Requirement" onClick={this.handleSelect(1)}/>
          <Tab label="Computer Science Electives" onClick={this.handleSelect(2)}/>
          <Tab label="Support Courses" onClick={this.handleSelect(3)} />
        </Tabs>

      </header>
    );
  }
}
</code>```

Here is the console log currently when rendered:

```<code>Selected tab: 0
Selected tab: 1
Selected tab: 2
Selected tab: 3
</code>```

答:
This is the way I think is more readable, using a functional component with useState hook and material ui Tabs and Tab components.

You can have access to the current selected child tab index
 as an argument passed to the function handler provided to the onChange prop of the Tabs component.

```<code>    `const Header = ()=>{
         const[currentIndex,setCurrentIndex]=React.useState(0)

         const handleChange = (event, currentSelectedIndex) =>
               {  setCurrentIndex(currentSelectedIndex) };

          return (
              <Tabs
               value={currentIndex}
               onChange={handleChange}
             >
                   <Tab label="Core Courses"/>
                   <Tab label="Capstone Requirement"/>
                   <Tab label="Computer Science Electives"/>
                   <Tab label="Support Courses" />
              </Tabs>
                                )
                          }`
</code>```

Body:
I am new to React and I am trying to get the selected Tab and from a onClick event.

Below is my code along with output.

How would I implement the handleSelect function?

Here is my current code:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value : 0};
  }

  getState(){
    return this.state.value;
  }

  setState(state){
    this.state = state;
  }

  handleSelect(index){
    console.log('Selected tab: ' + index);
  }

  render() {
    let selectedIndex = this.getState();

    return (

        <AppBar title="App Bar" />

        <Tabs>
          <Tab label="Core Courses" onClick={this.handleSelect(0)} />
          <Tab label="Capstone Requirement" onClick={this.handleSelect(1)}/>
          <Tab label="Computer Science Electives" onClick={this.handleSelect(2)}/>
          <Tab label="Support Courses" onClick={this.handleSelect(3)} />
        </Tabs>

    );
  }
}

Here is the console log currently when rendered:

Selected tab: 0
Selected tab: 1
Selected tab: 2
Selected tab: 3

Body:
This is the way I think is more readable, using a functional component with useState hook and material ui Tabs and Tab components.

You can have access to the current selected child tab index
 as an argument passed to the function handler provided to the onChange prop of the Tabs component.

    `const Header = ()=>{
         const[currentIndex,setCurrentIndex]=React.useState(0)

         const handleChange = (event, currentSelectedIndex) =>
               {  setCurrentIndex(currentSelectedIndex) };

          return (
              <Tabs
               value={currentIndex}
               onChange={handleChange}
             >
                   <Tab label="Core Courses"/>
                   <Tab label="Capstone Requirement"/>
                   <Tab label="Computer Science Electives"/>
                   <Tab label="Support Courses" />
              </Tabs>
                                )
                          }`


问:
MySQL - How do I relate a custom table bi-directionally with user and usermeta tables? - Wordpress
I am using Wordpress, PhpMyAdmin, MySQL.
I am also quite novice when it comes to SQL and databases, so bear with me.

I have a Custom Data Table (this is a master table of user information), which I want to relate bi-directionally with the wp_users and wp_usermeta tables - meaning if a user updates their profile (Users or Usermeta tables) then the Custom Data Table would automatically update without me needing to manually input their updated information.

Likewise, if I edit the Custom Data Table I want the related information in Users and Usermeta to automatically update.

I tried creating a rough diagram of what is in my head. Diagram of data handling

The current system is terrible and very difficult to maintain. Another issue is that there are many SQL reports that use the current Custom Data Table. I understand that the solution I am looking for most likely means creating a completely new table. That's ok.

```<code>       User
–––––––––––––––––––
| ID  | username  |
|–––––+–––––––––––|
| 376 | John      |
| 377 | Paul      |
| 378 | Ringo     |
–––––––––––––––––––

       Usermeta
–––––––––––––––––––––––––––––––––––––––––––––
| meta_id | user_id | meta_key | meta_value |
|–––––––––+–––––––––+––––––––––+––––––––––––|
| 8       | 1       | job      | Keys       |
| 102     | 2       | job      | Vocals     |
| 203     | 3       | job      | Drums      |
–––––––––––––––––––––––––––––––––––––––––––––

       Custom_Table
––––––––––––––––––––––––––––––––––––––
| ID | username  | job     | user_ID |
|––––+–––––––––––+–––––––––+–––––––––|
| 1  | John      | Keys    | 376     |
| 2  | Paul      | Vocals  | 377     |
| 3  | Ringo     | Drums   | 378     |
––––––––––––––––––––––––––––––––––––––
</code>```

Basically, this is what I have a query (except I have many more lines of the usermeta):

```<code>CREATE TABLE custom_table
    SELECT users.username,
    MAX(CASE WHEN meta_key = 'job' THEN meta_value ELSE NULL END) AS job,
    users.ID
    FROM wp_users as users, wp_usermeta as umeta
    WHERE umeta.user_id = users.ID
</code>```

This creates the table I want but if any of the tables are updated it is not 'synced' anywhere else. Is this possible? Would it be done by some sort of trigger (I am still unfamiliar with triggers)?

答:
Just use a view instead of a table. This gives you an always up-to-date perspective at your actual data, without any maintenance cost (and, for what it worth, without storage cost either).

```<code>create view custom_view as
select
    u.username,
    um.meta_value as job
    u.id as user_id
from wp_users as users u
left join wp_usermeta as umeta um on um.user_id = u.ID and um.meta_key = 'job'
</code>```

Note about your original query:

it is actually invalid SQL (it was missing a group by clause)

event if it had a group by clause, it would filter out users without a job (which might not be what you want)

do not use old-school, implicit joins; always use standard joins (with the on keyword and no comma in the from clause)

Since you are interested in only one meta key per user, the query can be rewritten as a simple join, without aggregation.

Body:
I am using Wordpress, PhpMyAdmin, MySQL.
I am also quite novice when it comes to SQL and databases, so bear with me.

I have a Custom Data Table (this is a master table of user information), which I want to relate bi-directionally with the wp_users and wp_usermeta tables - meaning if a user updates their profile (Users or Usermeta tables) then the Custom Data Table would automatically update without me needing to manually input their updated information.

Likewise, if I edit the Custom Data Table I want the related information in Users and Usermeta to automatically update.

I tried creating a rough diagram of what is in my head. Diagram of data handling

The current system is terrible and very difficult to maintain. Another issue is that there are many SQL reports that use the current Custom Data Table. I understand that the solution I am looking for most likely means creating a completely new table. That's ok.

       User
–––––––––––––––––––
| ID  | username  |
|–––––+–––––––––––|
| 376 | John      |
| 377 | Paul      |
| 378 | Ringo     |
–––––––––––––––––––

       Usermeta
–––––––––––––––––––––––––––––––––––––––––––––
| meta_id | user_id | meta_key | meta_value |
|–––––––––+–––––––––+––––––––––+––––––––––––|
| 8       | 1       | job      | Keys       |
| 102     | 2       | job      | Vocals     |
| 203     | 3       | job      | Drums      |
–––––––––––––––––––––––––––––––––––––––––––––

       Custom_Table
––––––––––––––––––––––––––––––––––––––
| ID | username  | job     | user_ID |
|––––+–––––––––––+–––––––––+–––––––––|
| 1  | John      | Keys    | 376     |
| 2  | Paul      | Vocals  | 377     |
| 3  | Ringo     | Drums   | 378     |
––––––––––––––––––––––––––––––––––––––

Basically, this is what I have a query (except I have many more lines of the usermeta):

CREATE TABLE custom_table
    SELECT users.username,
    MAX(CASE WHEN meta_key = 'job' THEN meta_value ELSE NULL END) AS job,
    users.ID
    FROM wp_users as users, wp_usermeta as umeta
    WHERE umeta.user_id = users.ID

This creates the table I want but if any of the tables are updated it is not 'synced' anywhere else. Is this possible? Would it be done by some sort of trigger (I am still unfamiliar with triggers)?

Body:
Just use a view instead of a table. This gives you an always up-to-date perspective at your actual data, without any maintenance cost (and, for what it worth, without storage cost either).

create view custom_view as
select
    u.username,
    um.meta_value as job
    u.id as user_id
from wp_users as users u
left join wp_usermeta as umeta um on um.user_id = u.ID and um.meta_key = 'job'

Note about your original query:

it is actually invalid SQL (it was missing a group by clause)

event if it had a group by clause, it would filter out users without a job (which might not be what you want)

do not use old-school, implicit joins; always use standard joins (with the on keyword and no comma in the from clause)

Since you are interested in only one meta key per user, the query can be rewritten as a simple join, without aggregation.


问:
Shouldn't this fail without the use of locking? Simple producer consumer
I have a queue, a list with producer threads and a list with consumer threads.

My code looks like this

```<code>    public class Runner
{
    List<Thread> Producers;
    List<Thread> Consumers;
    Queue<int> queue;
    Random random;

    public Runner()
    {
        Producers = new List<Thread>();
        Consumers = new List<Thread>();

        for (int i = 0; i < 2; i++)
        {
            Thread thread = new Thread(Produce);
            Producers.Add(thread);
        }

        for (int i = 0; i < 2; i++)
        {
            Thread thread = new Thread(Consume);
            Consumers.Add(thread);
        }

        queue = new Queue<int>();
        random = new Random();

        Producers.ForEach(( thread ) => { thread.Start(); });
        Consumers.ForEach(( thread ) => { thread.Start(); });
    }

    protected void Produce()
    {
        while (true)
        {
                int number = random.Next(0, 99);
                queue.Enqueue(number);
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId + " Produce: " + number);
        }
    }

    protected void Consume()
    {
        while (true)
        {
                if (queue.Any())
                {
                    int number = queue.Dequeue();
                    Console.WriteLine(Thread.CurrentThread.ManagedThreadId + " Consume: " + number);
                }
                else
                {
                    Console.WriteLine("No items to consume");
                }
        }
    }
}
</code>```

Shouldn't this fail miserable cause of the missing use of the lock keyword?
It failed once because it tried to dequeue when the queue was empty, using the lock keyword will fix that right?

If the lock keyword is not needed for the above code, when is it needed then?

Thank you in advance! =)

答: Yes this code will fail.  The queue needs to support multi-threading.  Use a ConcurrentQueue.  See http://msdn.microsoft.com/en-us/library/dd267265.aspx

Body:
I have a queue, a list with producer threads and a list with consumer threads.

My code looks like this

    public class Runner
{
    List<Thread> Producers;
    List<Thread> Consumers;
    Queue<int> queue;
    Random random;

    public Runner()
    {
        Producers = new List<Thread>();
        Consumers = new List<Thread>();

        for (int i = 0; i < 2; i++)
        {
            Thread thread = new Thread(Produce);
            Producers.Add(thread);
        }

        for (int i = 0; i < 2; i++)
        {
            Thread thread = new Thread(Consume);
            Consumers.Add(thread);
        }

        queue = new Queue<int>();
        random = new Random();

        Producers.ForEach(( thread ) => { thread.Start(); });
        Consumers.ForEach(( thread ) => { thread.Start(); });
    }

    protected void Produce()
    {
        while (true)
        {
                int number = random.Next(0, 99);
                queue.Enqueue(number);
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId + " Produce: " + number);
        }
    }

    protected void Consume()
    {
        while (true)
        {
                if (queue.Any())
                {
                    int number = queue.Dequeue();
                    Console.WriteLine(Thread.CurrentThread.ManagedThreadId + " Consume: " + number);
                }
                else
                {
                    Console.WriteLine("No items to consume");
                }
        }
    }
}

Shouldn't this fail miserable cause of the missing use of the lock keyword?
It failed once because it tried to dequeue when the queue was empty, using the lock keyword will fix that right?

If the lock keyword is not needed for the above code, when is it needed then?

Thank you in advance! =)


问:
How can I create a card using Stripe and Node,js
I'm using Stripe as a payment method in my project using Node.js. I'm following the docs to archive this.

What I need is to create a card with the following information: credit card number, person's name, expiration date and security code.

This is my code:

const createCard = (customer, cardInfo) => {
  return new Promise((resolve, reject) => {
    stripe.customers.createSource(
      customer,
      {
        source: {
          object: 'card',
          ...cardInfo
        }
      },
      (err, card) => {
        if (err) {
          debug('There was an error while creating a new card')
          reject(err)
        }
        debug(card)
        resolve(card)
      }
    )
  })
}
```

<p>The <code>cardInfo</code> object looks like this:</p>

```{
  "number": "4242424242424242",
  "exp_month": "11",
  "exp_year": "2021",
  "cvc": "123",
  "name": "My name"
}
```

This is what I get in the callback answer:

Sending credit card numbers directly to the Stripe API is generally unsafe. We suggest you use test tokens that map to the test card you are using, see https://stripe.com/docs/testing."

I'm using my develpment api key.

答:
You should be using Stripe.js and Elements (a client-side Javascript library) to tokenize cards on your webpage, and then using the tokens Stripe gives you, on your server-side Node.js code (to either charge them or save for future use).

https://stripe.com/docs/payments/accept-a-payment#web-collect-card-details

Passing card details directly to your server is highly not recommended as it has much higher PCI compliance burden on your integration.

Body:
I'm using Stripe as a payment method in my project using Node.js. I'm following the docs to archive this.

What I need is to create a card with the following information: credit card number, person's name, expiration date and security code.

This is my code:

const createCard = (customer, cardInfo) => {
  return new Promise((resolve, reject) => {
    stripe.customers.createSource(
      customer,
      {
        source: {
          object: 'card',
          ...cardInfo
        }
      },
      (err, card) => {
        if (err) {
          debug('There was an error while creating a new card')
          reject(err)
        }
        debug(card)
        resolve(card)
      }
    )
  })
}

The cardInfo object looks like this:

{
  "number": "4242424242424242",
  "exp_month": "11",
  "exp_year": "2021",
  "cvc": "123",
  "name": "My name"
}

This is what I get in the callback answer:

Sending credit card numbers directly to the Stripe API is generally unsafe. We suggest you use test tokens that map to the test card you are using, see https://stripe.com/docs/testing."

I'm using my develpment api key.


问:
Quanteda: How can I use square brackets with glob-style pattern matching using tokens_lookup?
I have two interrelated questions with respect to pattern matching in R using the package {quanteda} and the tokens_lookup() function with the default valuetype="glob" (see here and here).

Say I wanted to match a German word which can be spelt slightly differently depending on whether it is singular or plural: "Apfel" (EN: apple), "Äpfel" (EN: apples). For the plural, we thus use the umlaut "ä" instead of "a" at the beginning. So if I look up tokens, I want to make sure that whether or not I find fruits in a text does not depend on whether the word I'm lokking for is singular or plural. This is a very simple example and I'm aware that I might as well build a dictionary that features "äpfel*" and "apfel*", but my question is more generally about the use of special characters like square brackets.

So in essence, I thought I could simply go with sqaure brackets similarly to regex pattern matching: [aä]. More generally, I thought I could use things like [a-z] to match any single letter from a to z or [0-9] to match any single number between 0 and 9. In fact, that's what it says here. For some reason, none of that seems to work:

```<code>library(quanteda)

text <- c(d1 = "i like apples and apple pie",
          d2 = "ich mag äpfel und apfelkuchen")

dict_1 <- dictionary(list(fruits = c("[aä]pfel*")))      # EITHER "a" OR "ä"
dict_2 <- dictionary(list(fruits = c("[a-z]pfel*")))     # ANY LETTER

tokens(text) %>%
  tokens_lookup(dict_1, valuetype = "glob")

tokens(text) %>%
  tokens_lookup(dict_2, valuetype = "glob")
</code>```

1.) Is there a way to use square brackets at all in glob pattern matching?

2.) If so, would [a-z] also match umlauts (ä,ö,ü) or if not, how can we match characters like that?

答:
1) No, you cannot use brackets with glob pattern matching.  However, they work perfectly with regex pattern matching.

2) No, [a-z] will not match umlauts.

Here's how to do it, stripping away all from your question that is not necessary to answering the question.

library("quanteda")
## Package version: 2.0.1

text <- "Ich mag Äpfel und Apfelkuchen"

toks <- tokens(text)

dict_1 <- dictionary(list(fruits = c("[aä]pfel*")))
dict_2 <- dictionary(list(fruits = c("[a-z]pfel*")))

tokens_lookup(toks, dict_1, valuetype = "regex", exclusive = FALSE)
## Tokens consisting of 1 document.
## text1 :
## [1] "Ich"    "mag"    "FRUITS" "und"    "FRUITS"
tokens_lookup(toks, dict_2, valuetype = "regex", exclusive = FALSE)
## Tokens consisting of 1 document.
## text1 :
## [1] "Ich"    "mag"    "Äpfel"  "und"    "FRUITS"
```

Note: No need to import all of the tidyverse just to get %>%, as quanteda makes this available through re-export.

Body:
I have two interrelated questions with respect to pattern matching in R using the package {quanteda} and the tokens_lookup() function with the default valuetype="glob" (see here and here).

Say I wanted to match a German word which can be spelt slightly differently depending on whether it is singular or plural: "Apfel" (EN: apple), "Äpfel" (EN: apples). For the plural, we thus use the umlaut "ä" instead of "a" at the beginning. So if I look up tokens, I want to make sure that whether or not I find fruits in a text does not depend on whether the word I'm lokking for is singular or plural. This is a very simple example and I'm aware that I might as well build a dictionary that features "äpfel*" and "apfel*", but my question is more generally about the use of special characters like square brackets.

So in essence, I thought I could simply go with sqaure brackets similarly to regex pattern matching: [aä]. More generally, I thought I could use things like [a-z] to match any single letter from a to z or [0-9] to match any single number between 0 and 9. In fact, that's what it says here. For some reason, none of that seems to work:

library(quanteda)

text <- c(d1 = "i like apples and apple pie",
          d2 = "ich mag äpfel und apfelkuchen")

dict_1 <- dictionary(list(fruits = c("[aä]pfel*")))      # EITHER "a" OR "ä"
dict_2 <- dictionary(list(fruits = c("[a-z]pfel*")))     # ANY LETTER

tokens(text) %>%
  tokens_lookup(dict_1, valuetype = "glob")

tokens(text) %>%
  tokens_lookup(dict_2, valuetype = "glob")

1.) Is there a way to use square brackets at all in glob pattern matching?

2.) If so, would [a-z] also match umlauts (ä,ö,ü) or if not, how can we match characters like that?

Body:
1) No, you cannot use brackets with glob pattern matching.  However, they work perfectly with regex pattern matching.

2) No, [a-z] will not match umlauts.

Here's how to do it, stripping away all from your question that is not necessary to answering the question.

library("quanteda")
## Package version: 2.0.1

text <- "Ich mag Äpfel und Apfelkuchen"

toks <- tokens(text)

dict_1 <- dictionary(list(fruits = c("[aä]pfel*")))
dict_2 <- dictionary(list(fruits = c("[a-z]pfel*")))

tokens_lookup(toks, dict_1, valuetype = "regex", exclusive = FALSE)
## Tokens consisting of 1 document.
## text1 :
## [1] "Ich"    "mag"    "FRUITS" "und"    "FRUITS"
tokens_lookup(toks, dict_2, valuetype = "regex", exclusive = FALSE)
## Tokens consisting of 1 document.
## text1 :
## [1] "Ich"    "mag"    "Äpfel"  "und"    "FRUITS"

Note: No need to import all of the tidyverse just to get %>%, as quanteda makes this available through re-export.