问:
Nodemailer: Greeting never received
When trying to send email within Node using Nodemailer (https://github.com/nodemailer/nodemailer), the call to the sendMail of the Nodemailer transporter is raising the error Greeting never received when using in conjunction with an Ethereal test email account.

I have tried using both a "callback approach" and also an "async/await" approach, but the same error is thrown in both scenarios. Both examples are pretty much straight from the working examples in the Nodemailer documentation. Maybe I'm missing something simple? :)

Here is the "callback approach" code that is producing the error:

```<code>it('can send email with a dynamic test account', done => {
    nodemailer.createTestAccount((err, account) => {
        const transporter = nodemailer.createTransport({
            host: 'smtp.ethereal.email',
            port: 587,
            auth: {
                user: account.user, // generated ethereal user
                pass: account.pass // generated ethereal password
            }
        });

        const mailOptions = {
            from: '"Fred Foo " <foo@example.com>', // sender address
            to: 'bar@example.com, baz@example.com', // list of receivers
            subject: 'Hello ✔', // Subject line
            text: 'Hello world?', // plain text body
            html: '<b>Hello world?</b>' // html body
        };

        // send mail with defined transport object
        transporter.sendMail(mailOptions, (error, info) => {
            if (error) {
                return console.log(error);
            }
            console.log('Message sent: %s', info.messageId);
            console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info));
            // Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321@example.com>
            // Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou...

            done();
        });
    });
}).timeout(10000);
</code>```

And here is the stacktrace of the error:

```<code>{ Error: Greeting never received
    at SMTPConnection._formatError (/Users/<username>/projects/personal/learning-tests/javascript/nodemailer/node_modules/nodemailer/lib/smtp-connection/index.js:606:19)
    at SMTPConnection._onError (/Users/<username>/projects/personal/learning-tests/javascript/nodemailer/node_modules/nodemailer/lib/smtp-connection/index.js:579:20)
    at Timeout._greetingTimeout.setTimeout (/Users/<username>/projects/personal/learning-tests/javascript/nodemailer/node_modules/nodemailer/lib/smtp-connection/index.js:520:22)
    at ontimeout (timers.js:498:11)
    at tryOnTimeout (timers.js:323:5)
    at Timer.listOnTimeout (timers.js:290:5) code: 'ETIMEDOUT', command: 'CONN' }
</code>```

And some additional info:

node version: 8.11.2

nodemailer version: 4.6.4

operating system: OSX version 10.12.6

答:
Check your internet connection probably its down .
below is an example with Etheral Email with typescript</p>

```<code>import * as nodemailer from "nodemailer";

export const sendEmail = async (recipient: string, url: string, linkText: string) => {
  nodemailer.createTestAccount((err, account) => {
    if (err) {
      console.log(err);
    }
    const transporter = nodemailer.createTransport({
      host: account.smtp.host,
      port: account.smtp.port,
      secure: account.smtp.secure,
      auth: {
        user: account.user,
        pass: account.pass
      }
    });

    const message = {
      from: "Sender Name <sender@example.com>",
      to: `Recipient <${recipient}>`,
      subject: "Nodemailer is unicode friendly ✔",
      text: "Hello to myself!",
      html: `
        <html>
        <body>
        <p>Testing sparkpost API</p>
        <a href="${url}">${linkText}</a>
        </body>
        </html>`
    };

    transporter.sendMail(message, (err, info) => {
      if (err) {
        console.log("Error occurred. " + err.message);
      }

      console.log("Message sent: %s", info.messageId);
      // Preview only available when sending through an Ethereal account
      console.log("Preview URL: %s", nodemailer.getTestMessageUrl(info));
    });
  });
};
</code>```

Title: Nodemailer: Greeting never received

Body:
When trying to send email within Node using Nodemailer (https://github.com/nodemailer/nodemailer), the call to the sendMail of the Nodemailer transporter is raising the error Greeting never received when using in conjunction with an Ethereal test email account.

I have tried using both a "callback approach" and also an "async/await" approach, but the same error is thrown in both scenarios. Both examples are pretty much straight from the working examples in the Nodemailer documentation. Maybe I'm missing something simple? :)

Here is the "callback approach" code that is producing the error:

it('can send email with a dynamic test account', done => {
    nodemailer.createTestAccount((err, account) => {
        const transporter = nodemailer.createTransport({
            host: 'smtp.ethereal.email',
            port: 587,
            auth: {
                user: account.user, // generated ethereal user
                pass: account.pass // generated ethereal password
            }
        });

        const mailOptions = {
            from: '"Fred Foo " <foo@example.com>', // sender address
            to: 'bar@example.com, baz@example.com', // list of receivers
            subject: 'Hello ✔', // Subject line
            text: 'Hello world?', // plain text body
            html: 'Hello world?' // html body
        };

        // send mail with defined transport object
        transporter.sendMail(mailOptions, (error, info) => {
            if (error) {
                return console.log(error);
            }
            console.log('Message sent: %s', info.messageId);
            console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info));
            // Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321@example.com>
            // Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou...

            done();
        });
    });
}).timeout(10000);

And here is the stacktrace of the error:

{ Error: Greeting never received
    at SMTPConnection._formatError (/Users/<username>/projects/personal/learning-tests/javascript/nodemailer/node_modules/nodemailer/lib/smtp-connection/index.js:606:19)
    at SMTPConnection._onError (/Users/<username>/projects/personal/learning-tests/javascript/nodemailer/node_modules/nodemailer/lib/smtp-connection/index.js:579:20)
    at Timeout._greetingTimeout.setTimeout (/Users/<username>/projects/personal/learning-tests/javascript/nodemailer/node_modules/nodemailer/lib/smtp-connection/index.js:520:22)
    at ontimeout (timers.js:498:11)
    at tryOnTimeout (timers.js:323:5)
    at Timer.listOnTimeout (timers.js:290:5) code: 'ETIMEDOUT', command: 'CONN' }

And some additional info:

node version: 8.11.2

nodemailer version: 4.6.4

operating system: OSX version 10.12.6

Body:
Check your internet connection probably its down .
below is an example with Etheral Email with typescript

import * as nodemailer from "nodemailer";

export const sendEmail = async (recipient: string, url: string, linkText: string) => {
  nodemailer.createTestAccount((err, account) => {
    if (err) {
      console.log(err);
    }
    const transporter = nodemailer.createTransport({
      host: account.smtp.host,
      port: account.smtp.port,
      secure: account.smtp.secure,
      auth: {
        user: account.user,
        pass: account.pass
      }
    });

    const message = {
      from: "Sender Name <sender@example.com>",
      to: `Recipient <${recipient}>`,
      subject: "Nodemailer is unicode friendly ✔",
      text: "Hello to myself!",
      html: `
        <html>
        <body>
        <p>Testing sparkpost API</p>
        <a href="${url}">${linkText}</a>
        </body>
        </html>`
    };

    transporter.sendMail(message, (err, info) => {
      if (err) {
        console.log("Error occurred. " + err.message);
      }

      console.log("Message sent: %s", info.messageId);
      // Preview only available when sending through an Ethereal account
      console.log("Preview URL: %s", nodemailer.getTestMessageUrl(info));
    });
  });
};


来源: stackexchange

问:
.htaccess rule to remove from URL if present?
We are having a problem with one of our websites, sometimes we see a long url that is not related to any real page on our site. For example the URL should be

```<code>https://example.com/browse
</code>```

But one time in a hundred we get this

```<code>https://example.com/index.php/module/action/param1/static/PFBC/js/jquery/rss/signup/static/js/jquery/templates/themes/love/img/icon/asset/css/legal/user/album/tipocorneo/me/browse
</code>```

Its not always the same URL it changes from time to time but my question is this... Is there a rewrite rule we could use that simply removes the extra part of the URL if its present?

```<code>RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>
    Options +FollowSymLinks

</IfModule>

<IfModule mod_php5.c>
    php_flag allow_url_include Off
    php_flag expose_php Off
</IfModule>

### Security and Spam ###

# Protect the repository directory
<IfModule mod_rewrite.c>
    RewriteRule "(^|/)\.git" - [F,L]
</IfModule>

ServerSignature Off

# Deny access to all CGI, Perl, Python, Bash, SQL, Template, INI configuration, cache, log, temporary and text files
<FilesMatch "\.(cgi|pl|py|sh|bash|sql|tpl|ini|cache|log|tmp|txt)$">
    <IfModule mod_authz_core.c>
        Require all denied
    </IfModule>
</FilesMatch>

# Leave open the humans.txt and robots.txt file
<FilesMatch "humans\.txt|robots\.txt">
    <IfModule mod_authz_core.c>
        Require all granted
    </IfModule>
</FilesMatch>

# Deny access for "composer.json"
<FilesMatch "composer\.json|sample\.htaccess">
    <IfModule mod_authz_core.c>
        Require all denied
    </IfModule>
</FilesMatch>

# Prevent .htaccess/.htpasswd from being downloaded
<Files ~ "^\.ht">
    <IfModule mod_authz_core.c>
        Require all denied
    </IfModule>
</Files>

<Limit GET POST PUT DELETE HEAD>
    <IfModule mod_authz_core.c>
        <RequireAll>
            Require all granted
            Require not env bad_bot
        </RequireAll>
    </IfModule>
</Limit>

ErrorDocument 400 /error/http/index?code=400
ErrorDocument 401 /error/http/index?code=401
ErrorDocument 402 /error/http/index?code=402
ErrorDocument 403 /error/http/index?code=403
ErrorDocument 404 /error
ErrorDocument 405 /error/http/index?code=405
ErrorDocument 500 /error/http/index?code=500
ErrorDocument 501 /error/http/index?code=501
ErrorDocument 502 /error/http/index?code=502
ErrorDocument 504 /error/http/index?code=504
ErrorDocument 505 /error/http/index?code=505

# URL Rewrite
<IfModule mod_rewrite.c>
    <IfModule mod_env.c>
        # Tell PHP that the mod_rewrite module is ENABLED.
        SetEnv HTTP_MOD_REWRITE On
    </IfModule>

    # Uncomment the following only if HTTPS is enabled. HSTS header increases security of your website & SEO
    # <IfModule mod_headers.c>
    # Header set Strict-Transport-Security "max-age=31536000; preload" env=HTTPS
    # </IfModule>

    # Remove www subdomain in the URL
    # RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
    # RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

    # Force the URL to be https (only if you have an SSL certificate). May not be necessary if HSTS is enabled
    # RewriteCond %{SERVER_PORT} 80
    # RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d

    RewriteRule ^(.*)$ index.php?$1 [L,QSA]

    # Start Bad Bot Prvention
    RewriteCond %{HTTP_USER_AGENT} ^BackWeb [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Bandit [OR]
    RewriteCond %{HTTP_USER_AGENT} ^BatchFTP [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Buddy [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Collector [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Copier [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Download\Wonder [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Downloader [OR]
    RewriteCond %{HTTP_USER_AGENT} ^LinkWalker [OR]
    RewriteCond %{HTTP_USER_AGENT} ^BlackWidow [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Bot\ mailto:craftbot@yahoo.com [OR]
    RewriteCond %{HTTP_USER_AGENT} ^ChinaClaw [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Custo [OR]
    RewriteCond %{HTTP_USER_AGENT} ^DISCo [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Download\ Demon [OR]
    RewriteCond %{HTTP_USER_AGENT} ^eCatch [OR]
    RewriteCond %{HTTP_USER_AGENT} ^EirGrabber [OR]
    RewriteCond %{HTTP_USER_AGENT} ^EmailSiphon [OR]
    RewriteCond %{HTTP_USER_AGENT} ^EmailWolf [OR]
    RewriteCond %{HTTP_USER_AGENT} ^EmailCollector [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Crescent [OR]
    RewriteCond %{HTTP_USER_AGENT} ^CherryPicker [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Express\ WebPictures [OR]
    RewriteCond %{HTTP_USER_AGENT} ^ExtractorPro [OR]
    RewriteCond %{HTTP_USER_AGENT} ^EyeNetIE [OR]
    RewriteCond %{HTTP_USER_AGENT} ^FlashGet [OR]
    RewriteCond %{HTTP_USER_AGENT} ^GetRight [OR]
    RewriteCond %{HTTP_USER_AGENT} ^GetWeb! [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Go!Zilla [OR]
    RewriteCond %{HTTP_USER_AGENT} ^gotit [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Go-Ahead-Got-It [OR]
    RewriteCond %{HTTP_USER_AGENT} ^GrabNet [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Grafula [OR]
    RewriteCond %{HTTP_USER_AGENT} ^HMView [OR]
    RewriteCond %{HTTP_USER_AGENT} HTTrack [NC,OR]
    RewriteCond %{HTTP_USER_AGENT} ^Image\ Stripper [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Image\ Sucker [OR]
    RewriteCond %{HTTP_USER_AGENT} Indy\ Library [NC,OR]
    RewriteCond %{HTTP_USER_AGENT} ^InterGET [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Internet\ Ninja [OR]
    RewriteCond %{HTTP_USER_AGENT} ^JetCar [OR]
    RewriteCond %{HTTP_USER_AGENT} ^JOC\ Web\ Spider [OR]
    RewriteCond %{HTTP_USER_AGENT} ^larbin [OR]
    RewriteCond %{HTTP_USER_AGENT} ^libghttp [OR]
    RewriteCond %{HTTP_USER_AGENT} ^LeechFTP [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Mass\ Downloader [OR]
    RewriteCond %{HTTP_USER_AGENT} ^MIDown\ tool [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Mister\ PiX [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Navroad [OR]
    RewriteCond %{HTTP_USER_AGENT} ^NearSite [OR]
    RewriteCond %{HTTP_USER_AGENT} ^NetAnts [OR]
    RewriteCond %{HTTP_USER_AGENT} ^NetSpider [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Net\ Vampire [OR]
    RewriteCond %{HTTP_USER_AGENT} ^NetZIP [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Octopus [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Offline\ Explorer [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Offline\ Navigator [OR]
    RewriteCond %{HTTP_USER_AGENT} ^PageGrabber [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Papa\ Foto [OR]
    RewriteCond %{HTTP_USER_AGENT} ^pavuk [OR]
    RewriteCond %{HTTP_USER_AGENT} ^pcBrowser [OR]
    RewriteCond %{HTTP_USER_AGENT} libwww-perl.* [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Pockey [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Pump [OR]
    RewriteCond %{HTTP_USER_AGENT} ^RealDownload [OR]
    RewriteCond %{HTTP_USER_AGENT} ^ReGet [OR]
    RewriteCond %{HTTP_USER_AGENT} ^SiteSnagger [OR]
    RewriteCond %{HTTP_USER_AGENT} ^SmartDownload [OR]
    RewriteCond %{HTTP_USER_AGENT} ^SuperBot [OR]
    RewriteCond %{HTTP_USER_AGENT} ^SuperHTTP [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Surfbot [OR]
    RewriteCond %{HTTP_USER_AGENT} ^tAkeOut [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Teleport\ Pro [OR]
    RewriteCond %{HTTP_USER_AGENT} ^VoidEYE [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Web\ Image\ Collector [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Web\ Sucker [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebAuto [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebCopier [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebFetch [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebGo\ IS [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebLeacher [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebReaper [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebSauger [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Website\ eXtractor [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Website\ Quester [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebStripper [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebWhacker [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebZIP [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Wget [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Widow [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WWWOFFLE [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Xaldon\ WebSpider [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Zeus
    RewriteRule ^.* - [F,L]
    # End Bad Bot Prevention
</IfModule>

# Modify Headers
<IfModule mod_headers.c>
    # Cache files
    <FilesMatch "\.(jpe?g|png|gif|ico|webp|swf|mp3|mp4|flv|webm|pdf)$">
        Header set Cache-Control "public"
        Header set Expires "Mon, 20 Apr 2060 20:00:00 GMT"
        Header unset Last-Modified
    </FilesMatch>

    # Cache JavaScript & CSS
    <FilesMatch "\.(js|css)$">
        Header set Cache-Control "public"
        Header set Expires "Mon, 20 Apr 2060 20:00:00 GMT"
        Header unset Last-Modified
    </FilesMatch>
</IfModule>

# Compress files
<IfModule mod_deflate.c>
    # Insert filter
    SetOutputFilter DEFLATE
    <IfModule mod_setenvif.c>
        # Netscape 4.x has some problems...
        BrowserMatch ^Mozilla/4 gzip-only-text/html
        # Netscape 4.06-4.08 have some more problems
        BrowserMatch ^Mozilla/4\.0[678] no-gzip
        # MSIE masquerades as Netscape, but it is fine
        BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
        # Don't compress images/archives/music/video/etc
        SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
        SetEnvIfNoCase Request_URI \.(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
        SetEnvIfNoCase Request_URI \.(?:avi|mov|mp3|mp4|rm|flv|swf|mp?g)$ no-gzip dont-vary
    </IfModule>
    <IfModule mod_headers.c>
        # Make sure proxies don't deliver the wrong content
        Header append Vary User-Agent env=!dont-vary
    </IfModule>
</IfModule>

# Enable Expirations
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "access plus 1 month"
    # expire images/css/js/swf files after a month in the client's cache
    ExpiresByType text/css "access plus 31 days"
    ExpiresByType text/javascript "access plus 31 days"
    ExpiresByType application/javascript "access plus 31 days"
    ExpiresByType application/x-javascript "access plus 31 days"
    ExpiresByType application/x-gzip "access plus 31 days"
    ExpiresByType image/gif "access plus 31 days"
    ExpiresByType image/jpeg "access plus 31 days"
    ExpiresByType image/png "access plus 31 days"
    ExpiresByType application/x-shockwave-flash "access plus 31 days"
    ExpiresByType image/vnd.microsoft.icon "access plus 31 days"
    ExpiresByType image/x-icon "access plus 1 year"
</IfModule>

# For the videos extensions
#AddType video/ogg .ogg
AddType video/webm .webm
AddType video/mp4 .mp4
AddType application/rss+xml .xml
</code>```

答:
To redirect /index.php/foo/bar/baz/something to /something then you can do something like the following at the very top of your .htaccess file:

```<code>RewriteRule ^index\.php/[\w/]+/([\w]+)$ https://%{HTTP_HOST}/$1 [R=302,L]
</code>```

The shorthand character class \w matches word characters (a-z, A-Z, 0-9 and _) so matches the example URL given.

This redirect also canonicalises the scheme, so place this directive before the HTTP to HTTPS redirect to avoid a 2nd redirect when requesting HTTP.

However, a URL of this nature does suggest a missconfiguration in your site/application. Although, it could also be a malicious request (although the non-spam-like content in the URL does not really suggest that).

You should check the Referer in your server's access log for these requests, which should give you a clue as to their origin.

ContentLicense: CC BY-SA 4.0

Body:
We are having a problem with one of our websites, sometimes we see a long url that is not related to any real page on our site. For example the URL should be

https://example.com/browse

But one time in a hundred we get this

https://example.com/index.php/module/action/param1/static/PFBC/js/jquery/rss/signup/static/js/jquery/templates/themes/love/img/icon/asset/css/legal/user/album/tipocorneo/me/browse

Its not always the same URL it changes from time to time but my question is this... Is there a rewrite rule we could use that simply removes the extra part of the URL if its present?

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>
    Options +FollowSymLinks

</IfModule>

<IfModule mod_php5.c>
    php_flag allow_url_include Off
    php_flag expose_php Off
</IfModule>

### Security and Spam ###

# Protect the repository directory
<IfModule mod_rewrite.c>
    RewriteRule "(^|/)\.git" - [F,L]
</IfModule>

ServerSignature Off

# Deny access to all CGI, Perl, Python, Bash, SQL, Template, INI configuration, cache, log, temporary and text files
<FilesMatch "\.(cgi|pl|py|sh|bash|sql|tpl|ini|cache|log|tmp|txt)$">
    <IfModule mod_authz_core.c>
        Require all denied
    </IfModule>
</FilesMatch>

# Leave open the humans.txt and robots.txt file
<FilesMatch "humans\.txt|robots\.txt">
    <IfModule mod_authz_core.c>
        Require all granted
    </IfModule>
</FilesMatch>

# Deny access for "composer.json"
<FilesMatch "composer\.json|sample\.htaccess">
    <IfModule mod_authz_core.c>
        Require all denied
    </IfModule>
</FilesMatch>

# Prevent .htaccess/.htpasswd from being downloaded
<Files ~ "^\.ht">
    <IfModule mod_authz_core.c>
        Require all denied
    </IfModule>
</Files>

<Limit GET POST PUT DELETE HEAD>
    <IfModule mod_authz_core.c>
        <RequireAll>
            Require all granted
            Require not env bad_bot
        </RequireAll>
    </IfModule>
</Limit>

ErrorDocument 400 /error/http/index?code=400
ErrorDocument 401 /error/http/index?code=401
ErrorDocument 402 /error/http/index?code=402
ErrorDocument 403 /error/http/index?code=403
ErrorDocument 404 /error
ErrorDocument 405 /error/http/index?code=405
ErrorDocument 500 /error/http/index?code=500
ErrorDocument 501 /error/http/index?code=501
ErrorDocument 502 /error/http/index?code=502
ErrorDocument 504 /error/http/index?code=504
ErrorDocument 505 /error/http/index?code=505

# URL Rewrite
<IfModule mod_rewrite.c>
    <IfModule mod_env.c>
        # Tell PHP that the mod_rewrite module is ENABLED.
        SetEnv HTTP_MOD_REWRITE On
    </IfModule>

    # Uncomment the following only if HTTPS is enabled. HSTS header increases security of your website & SEO
    # <IfModule mod_headers.c>
    # Header set Strict-Transport-Security "max-age=31536000; preload" env=HTTPS
    # </IfModule>

    # Remove www subdomain in the URL
    # RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
    # RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

    # Force the URL to be https (only if you have an SSL certificate). May not be necessary if HSTS is enabled
    # RewriteCond %{SERVER_PORT} 80
    # RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d

    RewriteRule ^(.*)$ index.php?$1 [L,QSA]

    # Start Bad Bot Prvention
    RewriteCond %{HTTP_USER_AGENT} ^BackWeb [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Bandit [OR]
    RewriteCond %{HTTP_USER_AGENT} ^BatchFTP [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Buddy [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Collector [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Copier [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Download\Wonder [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Downloader [OR]
    RewriteCond %{HTTP_USER_AGENT} ^LinkWalker [OR]
    RewriteCond %{HTTP_USER_AGENT} ^BlackWidow [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Bot\ mailto:craftbot@yahoo.com [OR]
    RewriteCond %{HTTP_USER_AGENT} ^ChinaClaw [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Custo [OR]
    RewriteCond %{HTTP_USER_AGENT} ^DISCo [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Download\ Demon [OR]
    RewriteCond %{HTTP_USER_AGENT} ^eCatch [OR]
    RewriteCond %{HTTP_USER_AGENT} ^EirGrabber [OR]
    RewriteCond %{HTTP_USER_AGENT} ^EmailSiphon [OR]
    RewriteCond %{HTTP_USER_AGENT} ^EmailWolf [OR]
    RewriteCond %{HTTP_USER_AGENT} ^EmailCollector [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Crescent [OR]
    RewriteCond %{HTTP_USER_AGENT} ^CherryPicker [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Express\ WebPictures [OR]
    RewriteCond %{HTTP_USER_AGENT} ^ExtractorPro [OR]
    RewriteCond %{HTTP_USER_AGENT} ^EyeNetIE [OR]
    RewriteCond %{HTTP_USER_AGENT} ^FlashGet [OR]
    RewriteCond %{HTTP_USER_AGENT} ^GetRight [OR]
    RewriteCond %{HTTP_USER_AGENT} ^GetWeb! [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Go!Zilla [OR]
    RewriteCond %{HTTP_USER_AGENT} ^gotit [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Go-Ahead-Got-It [OR]
    RewriteCond %{HTTP_USER_AGENT} ^GrabNet [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Grafula [OR]
    RewriteCond %{HTTP_USER_AGENT} ^HMView [OR]
    RewriteCond %{HTTP_USER_AGENT} HTTrack [NC,OR]
    RewriteCond %{HTTP_USER_AGENT} ^Image\ Stripper [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Image\ Sucker [OR]
    RewriteCond %{HTTP_USER_AGENT} Indy\ Library [NC,OR]
    RewriteCond %{HTTP_USER_AGENT} ^InterGET [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Internet\ Ninja [OR]
    RewriteCond %{HTTP_USER_AGENT} ^JetCar [OR]
    RewriteCond %{HTTP_USER_AGENT} ^JOC\ Web\ Spider [OR]
    RewriteCond %{HTTP_USER_AGENT} ^larbin [OR]
    RewriteCond %{HTTP_USER_AGENT} ^libghttp [OR]
    RewriteCond %{HTTP_USER_AGENT} ^LeechFTP [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Mass\ Downloader [OR]
    RewriteCond %{HTTP_USER_AGENT} ^MIDown\ tool [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Mister\ PiX [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Navroad [OR]
    RewriteCond %{HTTP_USER_AGENT} ^NearSite [OR]
    RewriteCond %{HTTP_USER_AGENT} ^NetAnts [OR]
    RewriteCond %{HTTP_USER_AGENT} ^NetSpider [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Net\ Vampire [OR]
    RewriteCond %{HTTP_USER_AGENT} ^NetZIP [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Octopus [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Offline\ Explorer [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Offline\ Navigator [OR]
    RewriteCond %{HTTP_USER_AGENT} ^PageGrabber [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Papa\ Foto [OR]
    RewriteCond %{HTTP_USER_AGENT} ^pavuk [OR]
    RewriteCond %{HTTP_USER_AGENT} ^pcBrowser [OR]
    RewriteCond %{HTTP_USER_AGENT} libwww-perl.* [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Pockey [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Pump [OR]
    RewriteCond %{HTTP_USER_AGENT} ^RealDownload [OR]
    RewriteCond %{HTTP_USER_AGENT} ^ReGet [OR]
    RewriteCond %{HTTP_USER_AGENT} ^SiteSnagger [OR]
    RewriteCond %{HTTP_USER_AGENT} ^SmartDownload [OR]
    RewriteCond %{HTTP_USER_AGENT} ^SuperBot [OR]
    RewriteCond %{HTTP_USER_AGENT} ^SuperHTTP [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Surfbot [OR]
    RewriteCond %{HTTP_USER_AGENT} ^tAkeOut [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Teleport\ Pro [OR]
    RewriteCond %{HTTP_USER_AGENT} ^VoidEYE [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Web\ Image\ Collector [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Web\ Sucker [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebAuto [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebCopier [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebFetch [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebGo\ IS [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebLeacher [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebReaper [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebSauger [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Website\ eXtractor [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Website\ Quester [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebStripper [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebWhacker [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebZIP [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Wget [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Widow [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WWWOFFLE [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Xaldon\ WebSpider [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Zeus
    RewriteRule ^.* - [F,L]
    # End Bad Bot Prevention
</IfModule>

# Modify Headers
<IfModule mod_headers.c>
    # Cache files
    <FilesMatch "\.(jpe?g|png|gif|ico|webp|swf|mp3|mp4|flv|webm|pdf)$">
        Header set Cache-Control "public"
        Header set Expires "Mon, 20 Apr 2060 20:00:00 GMT"
        Header unset Last-Modified
    </FilesMatch>

    # Cache JavaScript & CSS
    <FilesMatch "\.(js|css)$">
        Header set Cache-Control "public"
        Header set Expires "Mon, 20 Apr 2060 20:00:00 GMT"
        Header unset Last-Modified
    </FilesMatch>
</IfModule>

# Compress files
<IfModule mod_deflate.c>
    # Insert filter
    SetOutputFilter DEFLATE
    <IfModule mod_setenvif.c>
        # Netscape 4.x has some problems...
        BrowserMatch ^Mozilla/4 gzip-only-text/html
        # Netscape 4.06-4.08 have some more problems
        BrowserMatch ^Mozilla/4\.0[678] no-gzip
        # MSIE masquerades as Netscape, but it is fine
        BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
        # Don't compress images/archives/music/video/etc
        SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
        SetEnvIfNoCase Request_URI \.(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
        SetEnvIfNoCase Request_URI \.(?:avi|mov|mp3|mp4|rm|flv|swf|mp?g)$ no-gzip dont-vary
    </IfModule>
    <IfModule mod_headers.c>
        # Make sure proxies don't deliver the wrong content
        Header append Vary User-Agent env=!dont-vary
    </IfModule>
</IfModule>

# Enable Expirations
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "access plus 1 month"
    # expire images/css/js/swf files after a month in the client's cache
    ExpiresByType text/css "access plus 31 days"
    ExpiresByType text/javascript "access plus 31 days"
    ExpiresByType application/javascript "access plus 31 days"
    ExpiresByType application/x-javascript "access plus 31 days"
    ExpiresByType application/x-gzip "access plus 31 days"
    ExpiresByType image/gif "access plus 31 days"
    ExpiresByType image/jpeg "access plus 31 days"
    ExpiresByType image/png "access plus 31 days"
    ExpiresByType application/x-shockwave-flash "access plus 31 days"
    ExpiresByType image/vnd.microsoft.icon "access plus 31 days"
    ExpiresByType image/x-icon "access plus 1 year"
</IfModule>

# For the videos extensions
#AddType video/ogg .ogg
AddType video/webm .webm
AddType video/mp4 .mp4
AddType application/rss+xml .xml

Body:
To redirect /index.php/foo/bar/baz/something to /something then you can do something like the following at the very top of your .htaccess file:

RewriteRule ^index\.php/[\w/]+/([\w]+)$ https://%{HTTP_HOST}/$1 [R=302,L]

The shorthand character class \w matches word characters (a-z, A-Z, 0-9 and _) so matches the example URL given.

This redirect also canonicalises the scheme, so place this directive before the HTTP to HTTPS redirect to avoid a 2nd redirect when requesting HTTP.

However, a URL of this nature does suggest a missconfiguration in your site/application. Although, it could also be a malicious request (although the non-spam-like content in the URL does not really suggest that).

You should check the Referer in your server's access log for these requests, which should give you a clue as to their origin.


问:
What is the difference between map() and switchMap() methods?
What is the difference between those 2 methods of the LiveData class? The official doc and tutorial are pretty vague on that. In the map() method the first parameter called source but in the switchMap() it called trigger. What's the rationale behind that?

答:
switchMap :
Let’s say we’re looking for the username Alice. The repository is creating a new instance of that User LiveData class and after that, we display the users. After some time we need to look for the username Bob there’s the repository creates a new instance of LiveData and our UI subscribes to that LiveData. So at this moment, our UI subscribes to two instances of LiveData because we never remove the previous one. So it means whenever our repository changes the user’s data it sends two times subscription. Now, how do we solve this problem…?

What we actually need is a mechanism that allows us to stop observing from the previous source whenever we want to observe a new one. In order to this, we would use switchMap. Under the hood, switchMap uses the MediatorLiveData that removes the initial source whenever the new source is added. In short, it does all the mechanism removing and adding a new Observer for us.

but map is static it used when you don't forced to get new live data every time

ContentLicense: CC BY-SA 3.0


问:
Cannot find Chrome binary when executing a selenium (testng) test in jenkins on windows 7
I have a basic login test with selenium and testng. When executed from eclipse, it works as expected and invoke Google Chrome. If executed from TESTNG command line, it works fine too.

This is my @Before:

```<code>@BeforeMethod
public void setUp() throws Exception {
 File file = new File("C:/Selenium-driver/chromedriver.exe");
 System.setProperty("webdriver.chrome.driver", file.getAbsolutePath());
 driver = new ChromeDriver();
 driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
 }
</code>```

However, if I execute the same test thru Jenkins it says:

```<code>Building in workspace C:\EclipsePortable\Data\workspace\GS_TESTNG
[G_TESTNG] $ cmd /c call C:\Windows\TEMP\hudson9049518275115936054.bat

C:\EclipsePortable\Data\workspace\G_TESTNG>_test_login_cmd.bat

C:\EclipsePortable\Data\workspace\G_TESTNG>cd C:\EclipsePortable\Data\workspace\G_TESTNG

C:\EclipsePortable\Data\workspace\G_TESTNG>java -cp C:\EclipsePortable\Data\workspace\G_TESTNG\lib\*;C:\EclipsePortable\Data\workspace\G_TESTNG\bin org.testng.TestNG testng.xml
...
... TestNG 6.9.9 by Cédric Beust (cedric@beust.com)
...

[TestNG] Running:
  C:\EclipsePortable\Data\workspace\G_TESTNG\testng.xml

Starting ChromeDriver 2.26.436362 (5476ec6bf7ccbada1734a0cdec7d570bb042aa30) on port 36257
Only local connections are allowed.
FAILED CONFIGURATION: @BeforeMethod setUp
org.openqa.selenium.WebDriverException: unknown error: cannot find Chrome binary
  (Driver info: chromedriver=2.26.436362 (5476ec6bf7ccbada1734a0cdec7d570bb042aa30),platform=Windows NT 6.1.7601 SP1 x86_64) (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 664 milliseconds
Build info: version: '2.51.0', revision: '1af067d', time: '2016-02-05 19:15:17'
System info: host: 'NMTLA12810', ip: '192.168.0.179', os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.8.0_102'
Driver info: org.openqa.selenium.chrome.ChromeDriver
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
        at java.lang.reflect.Constructor.newInstance(Unknown Source)
        at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:206)
        at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:158)
        at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:678)
        at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:249)
        at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:131)
        at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:144)
        at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:170)
        at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:159)
        at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:116)
        at com.test.TestA.setUp(TestA.java:33)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:85)
        at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:510)
        at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:211)
        at org.testng.internal.Invoker.invokeMethod(Invoker.java:585)
        at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:816)
        at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1124)
        at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
        at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:108)
        at org.testng.TestRunner.privateRun(TestRunner.java:774)
        at org.testng.TestRunner.run(TestRunner.java:624)
        at org.testng.SuiteRunner.runTest(SuiteRunner.java:359)
        at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:354)
        at org.testng.SuiteRunner.privateRun(SuiteRunner.java:312)
        at org.testng.SuiteRunner.run(SuiteRunner.java:261)
        at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
        at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
        at org.testng.TestNG.runSuitesSequentially(TestNG.java:1215)
        at org.testng.TestNG.runSuitesLocally(TestNG.java:1140)
        at org.testng.TestNG.run(TestNG.java:1048)
        at org.testng.TestNG.privateMain(TestNG.java:1355)
        at org.testng.TestNG.main(TestNG.java:1324)

SKIPPED CONFIGURATION: @AfterClass tearDown
SKIPPED: testGooglePageTitleInChrome

===============================================
    TestNG Test Group
    Tests run: 1, Failures: 0, Skips: 1
    Configuration Failures: 1, Skips: 1
===============================================

===============================================
Main Test Suite
Total tests run: 1, Failures: 0, Skips: 1
Configuration Failures: 1, Skips: 1
===============================================

[TestNG] Time taken by org.testng.reporters.JUnitReportReporter@7fbe847c: 16 ms
[TestNG] Time taken by org.testng.reporters.jq.Main@759ebb3d: 78 ms
[TestNG] Time taken by org.testng.reporters.SuiteHTMLReporter@ba8a1dc: 59 ms
[TestNG] Time taken by org.testng.reporters.XMLReporter@1c655221: 5 ms
[TestNG] Time taken by org.testng.reporters.EmailableReporter2@1edf1c96: 16 ms
[TestNG] Time taken by [FailedReporter passed=0 failed=0 skipped=0]: 0 ms
Build step 'Exécuter une ligne de commande batch Windows' marked build as failure
Finished: FAILURE
</code>```

答: Mac users, Please make sure that chromeBinary file is placed at bin folder and chrome if it is in downloads move it to application.</p>

Body:
I have a basic login test with selenium and testng. When executed from eclipse, it works as expected and invoke Google Chrome. If executed from TESTNG command line, it works fine too.

This is my @Before:

@BeforeMethod
public void setUp() throws Exception {
 File file = new File("C:/Selenium-driver/chromedriver.exe");
 System.setProperty("webdriver.chrome.driver", file.getAbsolutePath());
 driver = new ChromeDriver();
 driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
 }

However, if I execute the same test thru Jenkins it says:

Building in workspace C:\EclipsePortable\Data\workspace\GS_TESTNG
[G_TESTNG] $ cmd /c call C:\Windows\TEMP\hudson9049518275115936054.bat

C:\EclipsePortable\Data\workspace\G_TESTNG>_test_login_cmd.bat

C:\EclipsePortable\Data\workspace\G_TESTNG>cd C:\EclipsePortable\Data\workspace\G_TESTNG

C:\EclipsePortable\Data\workspace\G_TESTNG>java -cp C:\EclipsePortable\Data\workspace\G_TESTNG\lib\*;C:\EclipsePortable\Data\workspace\G_TESTNG\bin org.testng.TestNG testng.xml
...
... TestNG 6.9.9 by Cédric Beust (cedric@beust.com)
...

[TestNG] Running:
  C:\EclipsePortable\Data\workspace\G_TESTNG\testng.xml

Starting ChromeDriver 2.26.436362 (5476ec6bf7ccbada1734a0cdec7d570bb042aa30) on port 36257
Only local connections are allowed.
FAILED CONFIGURATION: @BeforeMethod setUp
org.openqa.selenium.WebDriverException: unknown error: cannot find Chrome binary
  (Driver info: chromedriver=2.26.436362 (5476ec6bf7ccbada1734a0cdec7d570bb042aa30),platform=Windows NT 6.1.7601 SP1 x86_64) (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 664 milliseconds
Build info: version: '2.51.0', revision: '1af067d', time: '2016-02-05 19:15:17'
System info: host: 'NMTLA12810', ip: '192.168.0.179', os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.8.0_102'
Driver info: org.openqa.selenium.chrome.ChromeDriver
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
        at java.lang.reflect.Constructor.newInstance(Unknown Source)
        at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:206)
        at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:158)
        at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:678)
        at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:249)
        at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:131)
        at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:144)
        at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:170)
        at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:159)
        at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:116)
        at com.test.TestA.setUp(TestA.java:33)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:85)
        at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:510)
        at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:211)
        at org.testng.internal.Invoker.invokeMethod(Invoker.java:585)
        at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:816)
        at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1124)
        at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
        at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:108)
        at org.testng.TestRunner.privateRun(TestRunner.java:774)
        at org.testng.TestRunner.run(TestRunner.java:624)
        at org.testng.SuiteRunner.runTest(SuiteRunner.java:359)
        at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:354)
        at org.testng.SuiteRunner.privateRun(SuiteRunner.java:312)
        at org.testng.SuiteRunner.run(SuiteRunner.java:261)
        at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
        at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
        at org.testng.TestNG.runSuitesSequentially(TestNG.java:1215)
        at org.testng.TestNG.runSuitesLocally(TestNG.java:1140)
        at org.testng.TestNG.run(TestNG.java:1048)
        at org.testng.TestNG.privateMain(TestNG.java:1355)
        at org.testng.TestNG.main(TestNG.java:1324)

SKIPPED CONFIGURATION: @AfterClass tearDown
SKIPPED: testGooglePageTitleInChrome

===============================================
    TestNG Test Group
    Tests run: 1, Failures: 0, Skips: 1
    Configuration Failures: 1, Skips: 1
===============================================

===============================================
Main Test Suite
Total tests run: 1, Failures: 0, Skips: 1
Configuration Failures: 1, Skips: 1
===============================================

[TestNG] Time taken by org.testng.reporters.JUnitReportReporter@7fbe847c: 16 ms
[TestNG] Time taken by org.testng.reporters.jq.Main@759ebb3d: 78 ms
[TestNG] Time taken by org.testng.reporters.SuiteHTMLReporter@ba8a1dc: 59 ms
[TestNG] Time taken by org.testng.reporters.XMLReporter@1c655221: 5 ms
[TestNG] Time taken by org.testng.reporters.EmailableReporter2@1edf1c96: 16 ms
[TestNG] Time taken by [FailedReporter passed=0 failed=0 skipped=0]: 0 ms
Build step 'Exécuter une ligne de commande batch Windows' marked build as failure
Finished: FAILURE


问:
help with NSDateFormater
I am trying to set the format for a given dateString but I am not able to get it working. Here is the code I am using:

[dateFormatter setDateFormat:@"yyyy-MM-dd hh:mm:ss"];

  date = [dateFormatter dateFromString:@"2011-05-08 18:31:42"];

but I keep getting (null) for the date,
Any help would be appreciated.

答:
hh should be HH. hh is for 12-hour time and HH is 24-hour time. Here's your code with the changes:

```<code>[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
date = [dateFormatter dateFromString:@"2011-05-08 18:31:42"];
</code>```

Title: help with NSDateFormater

Body:
hh should be HH. hh is for 12-hour time and HH is 24-hour time. Here's your code with the changes:

[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
date = [dateFormatter dateFromString:@"2011-05-08 18:31:42"];


问:
www.paypal.com/jp/cgi-bin/webscr? item_name encoding
I am working on a site that is trying pass a japanese item name to paypal through
this form

```<code><form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
          <input name="cmd" value="_xclick" type="hidden">

          <input name="item_name" value="フォトグラフィー基礎コース" type="hidden">
          <input name="amount" value="59000" type="hidden">
          <input name="currency_code" value="JPY" type="hidden">
          <input type="hidden" name="item_number" value="PHP001">
          <input name="no_note" value="0" type="hidden">
          <input type="hidden" name="lc" value="ja_JP">
          <input name="bn" value="PP-BuyNowBF:btn_buynowCC_LG.gif:NonHostedGuest" type="hidden">
          <input class="coursepayment" name="submit" value="今すぐ購入" alt="PayPal - The safer, easier way to pay online!" border="0" type="submit">
        </form>
</code>```

But the Item name comes out reading:
ãƒ•ã‚©ãƒˆã‚°ãƒ©ãƒ•ã‚£ãƒ¼åŸºç¤Žã‚³ãƒ¼ã‚¹
Is there a way to fix this?

答:
Another alternative is to set the default encoding accepted by the PayPal account (which as of today is still not utf-8 until you set it that way).

Check "More Options" under https://www.paypal.com/cgi-bin/customerprofileweb?cmd=_profile-language-encoding

Body:
I am working on a site that is trying pass a japanese item name to paypal through
this form

<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
          <input name="cmd" value="_xclick" type="hidden">

          <input name="item_name" value="フォトグラフィー基礎コース" type="hidden">
          <input name="amount" value="59000" type="hidden">
          <input name="currency_code" value="JPY" type="hidden">
          <input type="hidden" name="item_number" value="PHP001">
          <input name="no_note" value="0" type="hidden">
          <input type="hidden" name="lc" value="ja_JP">
          <input name="bn" value="PP-BuyNowBF:btn_buynowCC_LG.gif:NonHostedGuest" type="hidden">
          <input class="coursepayment" name="submit" value="今すぐ購入" alt="PayPal - The safer, easier way to pay online!" border="0" type="submit">
        </form>

But the Item name comes out reading:
ãƒ•ã‚©ãƒˆã‚°ãƒ©ãƒ•ã‚£ãƒ¼åŸºç¤Žã‚³ãƒ¼ã‚¹
Is there a way to fix this?


问:
How to show bottom sheet on map in flutter mobile application?
I see a lot of tutorials for implementing bottom sheet in my flutter application, but i am facing problem in implementing that, all of them showing bottom sheet after onPressed/onTap and i do not want that. I had implemented google map in my application but now i want to show persistent bottom sheet after i got response from API on map screen and color of that bottom sheet must be transparent so that map can be visible through bottom sheet.

Can you share some code that how can i show bottomsheet without onpressed on google map screen in flutter mobile application?

答:
you can use a stack widget and visibility widgets to show that.
here is some minimalist code
bool _isVisible=false;

```<code>//after you get a response  fro your api you set state of `_isVisible` to `true/!_isVisible.`
    Stack....

    Positioned(bottom:10,left:0
    child: Visibility(visible:!_isVisible,
     child Container(color:Colors.Transparent,
    child:Center(child:Text("your data here")))),
    ...
</code>```

Body:
you can use a stack widget and visibility widgets to show that.
here is some minimalist code
bool _isVisible=false;

//after you get a response  fro your api you set state of `_isVisible` to `true/!_isVisible.`
    Stack....

    Positioned(bottom:10,left:0
    child: Visibility(visible:!_isVisible,
     child Container(color:Colors.Transparent,
    child:Center(child:Text("your data here")))),
    ...


问:
Hamburger menu issue
I know this question might be asked a lot, but can someone help me with this one problem.

So the problem is that I'm trying to make a mobile hamburger menu and I want to make the onclick event happened when someone clicks on the icon.

```<code>function toggleMenuFunction() {
  let  getSidebar = document.querySelector(".sidebar");

    if(getSidebar.style.display === 'none'){
        getSidebar.style.display = 'block';
    }else if ( getSidebar.style.display === 'block'){
        getSidebar.style.display = 'none';
    }
}
</code>```

I tried doing it like this and it won't do anything. Please can any one help me?

答:
If you want to trigger a function when an element is clicked you need to write that too ;)

```<code>document.onload = () => document.querySelector(".sidebar").addEventListener("click",toggleMenuFunction);
</code>```

the document.onload makes sure the listener gets attached after the document has fully loaded. Note: You can only have one document.onloadassignment in your code. It is almost always a good idea to write a wrapper function for that purpose. As in:

```<code>document.onload = () => {
 document.querySelector(".sidebar")
   .addEventListener("click",toggleMenuFunction);
}
</code>```

Title: Hamburger menu issue

Body:
I know this question might be asked a lot, but can someone help me with this one problem.

So the problem is that I'm trying to make a mobile hamburger menu and I want to make the onclick event happened when someone clicks on the icon.

function toggleMenuFunction() {
  let  getSidebar = document.querySelector(".sidebar");

    if(getSidebar.style.display === 'none'){
        getSidebar.style.display = 'block';
    }else if ( getSidebar.style.display === 'block'){
        getSidebar.style.display = 'none';
    }
}

I tried doing it like this and it won't do anything. Please can any one help me?

Body:
If you want to trigger a function when an element is clicked you need to write that too ;)

document.onload = () => document.querySelector(".sidebar").addEventListener("click",toggleMenuFunction);

the document.onload makes sure the listener gets attached after the document has fully loaded. Note: You can only have one document.onloadassignment in your code. It is almost always a good idea to write a wrapper function for that purpose. As in:

document.onload = () => {
 document.querySelector(".sidebar")
   .addEventListener("click",toggleMenuFunction);
}


问:
Typescript complains when passing a possibly null (but not null) value to anonymous callback
When I have a property that initially begins as null, how can I pass this as an argument to an anonymous callback function that expects a non null value, without typescript complaining?

I can wrap my function call in an if statement to check for null, which stops typescript complaining at the function call level, but in the callback, typescript still complains.

Here's a snippet of the code. I allow some DatabaseState properties to be null, as this is how they are initialized.

```<code>//types.ts
export interface DatabaseState {
  db: PouchDB.Database | null;
  remoteDb: PouchDB.Database | null;
  dbReplication: PouchDB.Replication.Sync<{}> | null;
  dbSyncStatus: number;
  dbSyncInfo: string;
  dbSyncError: string;
}

//state typing - state: DatabaseState

//An action in database.ts
async startDatabaseSyncronisation({ state, commit, dispatch }) {
  var opts = { live: true, retry: true };

  if (state.remoteDb != null && state.db != null) {

    /* THE IF STATEMENT PREVENTS THE BELOW FUNCTION FROM CAUSING TYPESCRIPT TO COMPLAIN */

    await PouchDB.replicate(state.remoteDb, state.db, opts).on("complete",
      function(info) {

        /* WITHIN THE CALLBACK FUNCTION THOUGH, TYPESCRIPT COMPLAINS THAT state.remoteDb and state.db
        COULD BE NULL AND THE FUNCTION DOESN'T ACCEPT A NULL VALUE */

        let replication = PouchDB.sync(state.remoteDb, state.db, opts)
          .on("paused", function(err: {}) {
            dispatch("onSyncPaused", err);
          })
          .on("active", function() {
            dispatch("onSyncActive");
          })
          .on("denied", function(err: {}) {
            dispatch("onSyncError", err);
          })
          .on("error", function(err: {}) {
            dispatch("onSyncError", err);
          })
          .on("complete", function() {});
        commit(SET_DB_REPLICATION, replication);
      }
    );
  }
},
</code>```

How should I approach these kinds of typing checks?
Is there a more "Typescript-friendly" way of describing an initial value as unset?

The project uses Vue, with Vuex for state management.

答:
I would highly advise you always account for null. The concept of null was deemed to be a mistake and not protecting yourself against that value makes your code unsafe. But if you insist, there is an option you can turn off your tsconfig.json called strictNullChecks https://www.typescriptlang.org/docs/handbook/compiler-options.html

Should you even attempt a query if remoteDb or db isnull`? Isn't that just going to break your code in runtime?

EDIT:
The function will just never run if either value is null? If that's the case, replicate and sync are incorrectly typed by the library. An oversight by the package authors then.

There's no "good" way to account for a fundamental mistake from a 3rd party. Easiest way to document this, but still keep typing is to create a type with a variable name to declare the reasoning. Maybe someone else has a better idea, but I would do this:

type POUCH_BD_DATABASE_OR_NULL = PouchDB.Database

export interface DatabaseState {
  db: POUCH_BD_DATABASE_OR_NULL;
  remoteDb: POUCH_BD_DATABASE_OR_NULL;
  dbReplication: PouchDB.Replication.Sync<{}> | null;
  dbSyncStatus: number;
  dbSyncInfo: string;
  dbSyncError: string;
}
```

<p>EDIT2:
If you are doing validations on <code>state</code> <em>before</em> it is passed into <code>startDatabaseSyncronisation</code>, then your typing that you are using for <code>startDatabaseSyncronisation</code> is fundamentally incorrect and you can't directly share <code>interface DatabaseState</code> between the two functions. The best you can do is the create an <code>interface</code> of the shared elements in both and then <code>extend</code> in the two interfaces.</p>

<pre class="lang-js prettyprint-override"><code>interface DatabaseMetaData {
    dbSyncStatus: number;
    dbSyncInfo: string;
    dbSyncError: string;
}

// for the function where it might be null
export interface DatabaseState extends DatabaseMetaData{
    db: PouchDB.Database | null;
    remoteDb: PouchDB.Database | null;
    dbReplication: PouchDB.Replication.Sync<{}> | null;
}

// for startDatabaseSyncronisation
export interface DatabaseSyncState extends DatabaseMetaData{
    db: PouchDB.Database;
    remoteDb: PouchDB.Database;
    dbReplication: PouchDB.Replication.Sync<{}>;
}
</code>```

Body:
When I have a property that initially begins as null, how can I pass this as an argument to an anonymous callback function that expects a non null value, without typescript complaining?

I can wrap my function call in an if statement to check for null, which stops typescript complaining at the function call level, but in the callback, typescript still complains.

Here's a snippet of the code. I allow some DatabaseState properties to be null, as this is how they are initialized.

//types.ts
export interface DatabaseState {
  db: PouchDB.Database | null;
  remoteDb: PouchDB.Database | null;
  dbReplication: PouchDB.Replication.Sync<{}> | null;
  dbSyncStatus: number;
  dbSyncInfo: string;
  dbSyncError: string;
}

//state typing - state: DatabaseState

//An action in database.ts
async startDatabaseSyncronisation({ state, commit, dispatch }) {
  var opts = { live: true, retry: true };

  if (state.remoteDb != null && state.db != null) {

    /* THE IF STATEMENT PREVENTS THE BELOW FUNCTION FROM CAUSING TYPESCRIPT TO COMPLAIN */

    await PouchDB.replicate(state.remoteDb, state.db, opts).on("complete",
      function(info) {

        /* WITHIN THE CALLBACK FUNCTION THOUGH, TYPESCRIPT COMPLAINS THAT state.remoteDb and state.db
        COULD BE NULL AND THE FUNCTION DOESN'T ACCEPT A NULL VALUE */

        let replication = PouchDB.sync(state.remoteDb, state.db, opts)
          .on("paused", function(err: {}) {
            dispatch("onSyncPaused", err);
          })
          .on("active", function() {
            dispatch("onSyncActive");
          })
          .on("denied", function(err: {}) {
            dispatch("onSyncError", err);
          })
          .on("error", function(err: {}) {
            dispatch("onSyncError", err);
          })
          .on("complete", function() {});
        commit(SET_DB_REPLICATION, replication);
      }
    );
  }
},

How should I approach these kinds of typing checks?
Is there a more "Typescript-friendly" way of describing an initial value as unset?

The project uses Vue, with Vuex for state management.

Body:
I would highly advise you always account for null. The concept of null was deemed to be a mistake and not protecting yourself against that value makes your code unsafe. But if you insist, there is an option you can turn off your tsconfig.json called strictNullChecks https://www.typescriptlang.org/docs/handbook/compiler-options.html

Should you even attempt a query if remoteDb or db isnull`? Isn't that just going to break your code in runtime?

EDIT:
The function will just never run if either value is null? If that's the case, replicate and sync are incorrectly typed by the library. An oversight by the package authors then.

There's no "good" way to account for a fundamental mistake from a 3rd party. Easiest way to document this, but still keep typing is to create a type with a variable name to declare the reasoning. Maybe someone else has a better idea, but I would do this:

type POUCH_BD_DATABASE_OR_NULL = PouchDB.Database

export interface DatabaseState {
  db: POUCH_BD_DATABASE_OR_NULL;
  remoteDb: POUCH_BD_DATABASE_OR_NULL;
  dbReplication: PouchDB.Replication.Sync<{}> | null;
  dbSyncStatus: number;
  dbSyncInfo: string;
  dbSyncError: string;
}

EDIT2:
If you are doing validations on state before it is passed into startDatabaseSyncronisation, then your typing that you are using for startDatabaseSyncronisation is fundamentally incorrect and you can't directly share interface DatabaseState between the two functions. The best you can do is the create an interface of the shared elements in both and then extend in the two interfaces.

interface DatabaseMetaData {
    dbSyncStatus: number;
    dbSyncInfo: string;
    dbSyncError: string;
}

// for the function where it might be null
export interface DatabaseState extends DatabaseMetaData{
    db: PouchDB.Database | null;
    remoteDb: PouchDB.Database | null;
    dbReplication: PouchDB.Replication.Sync<{}> | null;
}

// for startDatabaseSyncronisation
export interface DatabaseSyncState extends DatabaseMetaData{
    db: PouchDB.Database;
    remoteDb: PouchDB.Database;
    dbReplication: PouchDB.Replication.Sync<{}>;
}


问:
How to get the first day of the current week and month?
I have the date of several events expressed in milliseconds[1], and I want to know which events are inside the current week and the current month, but I can't figure out how to obtain the first day (day/month/year) of the running week and convert it to milliseconds, the same for the first day of the month.

```<code>[1]Since January 1, 1970, 00:00:00 GMT
</code>```

答:
You can use the java.time package (since Java8 and late) to get start/end of day/week/month.

The util class example below:

```<code>import org.junit.Test;

import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;

public class DateUtil {
    private static final ZoneId DEFAULT_ZONE_ID = ZoneId.of("UTC");

    public static LocalDateTime startOfDay() {
        return LocalDateTime.now(DEFAULT_ZONE_ID).with(LocalTime.MIN);
    }

    public static LocalDateTime endOfDay() {
        return LocalDateTime.now(DEFAULT_ZONE_ID).with(LocalTime.MAX);
    }

    public static boolean belongsToCurrentDay(final LocalDateTime localDateTime) {
        return localDateTime.isAfter(startOfDay()) && localDateTime.isBefore(endOfDay());
    }

    //note that week starts with Monday
    public static LocalDateTime startOfWeek() {
        return LocalDateTime.now(DEFAULT_ZONE_ID)
                .with(LocalTime.MIN)
                .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
    }

    //note that week ends with Sunday
    public static LocalDateTime endOfWeek() {
        return LocalDateTime.now(DEFAULT_ZONE_ID)
                .with(LocalTime.MAX)
                .with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
    }

    public static boolean belongsToCurrentWeek(final LocalDateTime localDateTime) {
        return localDateTime.isAfter(startOfWeek()) && localDateTime.isBefore(endOfWeek());
    }

    public static LocalDateTime startOfMonth() {
        return LocalDateTime.now(DEFAULT_ZONE_ID)
                .with(LocalTime.MIN)
                .with(TemporalAdjusters.firstDayOfMonth());
    }

    public static LocalDateTime endOfMonth() {
        return LocalDateTime.now(DEFAULT_ZONE_ID)
                .with(LocalTime.MAX)
                .with(TemporalAdjusters.lastDayOfMonth());
    }

    public static boolean belongsToCurrentMonth(final LocalDateTime localDateTime) {
        return localDateTime.isAfter(startOfMonth()) && localDateTime.isBefore(endOfMonth());
    }

    public static long toMills(final LocalDateTime localDateTime) {
        return localDateTime.atZone(DEFAULT_ZONE_ID).toInstant().toEpochMilli();
    }

    public static Date toDate(final LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(DEFAULT_ZONE_ID).toInstant());
    }

    public static String toString(final LocalDateTime localDateTime) {
        return localDateTime.format(DateTimeFormatter.ISO_DATE_TIME);
    }

    @Test
    public void test() {
        //day
        final LocalDateTime now = LocalDateTime.now();
        System.out.println("Now: " + toString(now) + ", in mills: " + toMills(now));
        System.out.println("Start of day: " + toString(startOfDay()));
        System.out.println("End of day: " + toString(endOfDay()));
        System.out.println("Does '" + toString(now) + "' belong to the current day? > " + belongsToCurrentDay(now));
        final LocalDateTime yesterday = now.minusDays(1);
        System.out.println("Does '" + toString(yesterday) + "' belong to the current day? > " + belongsToCurrentDay(yesterday));
        final LocalDateTime tomorrow = now.plusDays(1);
        System.out.println("Does '" + toString(tomorrow) + "' belong to the current day? > " + belongsToCurrentDay(tomorrow));
        //week
        System.out.println("Start of week: " + toString(startOfWeek()));
        System.out.println("End of week: " + toString(endOfWeek()));
        System.out.println("Does '" + toString(now) + "' belong to the current week? > " + belongsToCurrentWeek(now));
        final LocalDateTime previousWeek = now.minusWeeks(1);
        System.out.println("Does '" + toString(previousWeek) + "' belong to the current week? > " + belongsToCurrentWeek(previousWeek));
        final LocalDateTime nextWeek = now.plusWeeks(1);
        System.out.println("Does '" + toString(nextWeek) + "' belong to the current week? > " + belongsToCurrentWeek(nextWeek));
        //month
        System.out.println("Start of month: " + toString(startOfMonth()));
        System.out.println("End of month: " + toString(endOfMonth()));
        System.out.println("Does '" + toString(now) + "' belong to the current month? > " + belongsToCurrentMonth(now));
        final LocalDateTime previousMonth = now.minusMonths(1);
        System.out.println("Does '" + toString(previousMonth) + "' belong to the current month? > " + belongsToCurrentMonth(previousMonth));
        final LocalDateTime nextMonth = now.plusMonths(1);
        System.out.println("Does '" + toString(nextMonth) + "' belong to the current month? > " + belongsToCurrentMonth(nextMonth));
    }
}
</code>```

Test output:

```<code>Now: 2020-02-16T22:12:49.957, in mills: 1581891169957
Start of day: 2020-02-16T00:00:00
End of day: 2020-02-16T23:59:59.999999999
Does '2020-02-16T22:12:49.957' belong to the current day? > true
Does '2020-02-15T22:12:49.957' belong to the current day? > false
Does '2020-02-17T22:12:49.957' belong to the current day? > false
Start of week: 2020-02-10T00:00:00
End of week: 2020-02-16T23:59:59.999999999
Does '2020-02-16T22:12:49.957' belong to the current week? > true
Does '2020-02-09T22:12:49.957' belong to the current week? > false
Does '2020-02-23T22:12:49.957' belong to the current week? > false
Start of month: 2020-02-01T00:00:00
End of month: 2020-02-29T23:59:59.999999999
Does '2020-02-16T22:12:49.957' belong to the current month? > true
Does '2020-01-16T22:12:49.957' belong to the current month? > false
Does '2020-03-16T22:12:49.957' belong to the current month? > false
</code>```

ContentLicense: CC BY-SA 2.5

Body:
I have the date of several events expressed in milliseconds[1], and I want to know which events are inside the current week and the current month, but I can't figure out how to obtain the first day (day/month/year) of the running week and convert it to milliseconds, the same for the first day of the month.

[1]Since January 1, 1970, 00:00:00 GMT

Body:
You can use the java.time package (since Java8 and late) to get start/end of day/week/month.

The util class example below:

import org.junit.Test;

import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;

public class DateUtil {
    private static final ZoneId DEFAULT_ZONE_ID = ZoneId.of("UTC");

    public static LocalDateTime startOfDay() {
        return LocalDateTime.now(DEFAULT_ZONE_ID).with(LocalTime.MIN);
    }

    public static LocalDateTime endOfDay() {
        return LocalDateTime.now(DEFAULT_ZONE_ID).with(LocalTime.MAX);
    }

    public static boolean belongsToCurrentDay(final LocalDateTime localDateTime) {
        return localDateTime.isAfter(startOfDay()) && localDateTime.isBefore(endOfDay());
    }

    //note that week starts with Monday
    public static LocalDateTime startOfWeek() {
        return LocalDateTime.now(DEFAULT_ZONE_ID)
                .with(LocalTime.MIN)
                .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
    }

    //note that week ends with Sunday
    public static LocalDateTime endOfWeek() {
        return LocalDateTime.now(DEFAULT_ZONE_ID)
                .with(LocalTime.MAX)
                .with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
    }

    public static boolean belongsToCurrentWeek(final LocalDateTime localDateTime) {
        return localDateTime.isAfter(startOfWeek()) && localDateTime.isBefore(endOfWeek());
    }

    public static LocalDateTime startOfMonth() {
        return LocalDateTime.now(DEFAULT_ZONE_ID)
                .with(LocalTime.MIN)
                .with(TemporalAdjusters.firstDayOfMonth());
    }

    public static LocalDateTime endOfMonth() {
        return LocalDateTime.now(DEFAULT_ZONE_ID)
                .with(LocalTime.MAX)
                .with(TemporalAdjusters.lastDayOfMonth());
    }

    public static boolean belongsToCurrentMonth(final LocalDateTime localDateTime) {
        return localDateTime.isAfter(startOfMonth()) && localDateTime.isBefore(endOfMonth());
    }

    public static long toMills(final LocalDateTime localDateTime) {
        return localDateTime.atZone(DEFAULT_ZONE_ID).toInstant().toEpochMilli();
    }

    public static Date toDate(final LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(DEFAULT_ZONE_ID).toInstant());
    }

    public static String toString(final LocalDateTime localDateTime) {
        return localDateTime.format(DateTimeFormatter.ISO_DATE_TIME);
    }

    @Test
    public void test() {
        //day
        final LocalDateTime now = LocalDateTime.now();
        System.out.println("Now: " + toString(now) + ", in mills: " + toMills(now));
        System.out.println("Start of day: " + toString(startOfDay()));
        System.out.println("End of day: " + toString(endOfDay()));
        System.out.println("Does '" + toString(now) + "' belong to the current day? > " + belongsToCurrentDay(now));
        final LocalDateTime yesterday = now.minusDays(1);
        System.out.println("Does '" + toString(yesterday) + "' belong to the current day? > " + belongsToCurrentDay(yesterday));
        final LocalDateTime tomorrow = now.plusDays(1);
        System.out.println("Does '" + toString(tomorrow) + "' belong to the current day? > " + belongsToCurrentDay(tomorrow));
        //week
        System.out.println("Start of week: " + toString(startOfWeek()));
        System.out.println("End of week: " + toString(endOfWeek()));
        System.out.println("Does '" + toString(now) + "' belong to the current week? > " + belongsToCurrentWeek(now));
        final LocalDateTime previousWeek = now.minusWeeks(1);
        System.out.println("Does '" + toString(previousWeek) + "' belong to the current week? > " + belongsToCurrentWeek(previousWeek));
        final LocalDateTime nextWeek = now.plusWeeks(1);
        System.out.println("Does '" + toString(nextWeek) + "' belong to the current week? > " + belongsToCurrentWeek(nextWeek));
        //month
        System.out.println("Start of month: " + toString(startOfMonth()));
        System.out.println("End of month: " + toString(endOfMonth()));
        System.out.println("Does '" + toString(now) + "' belong to the current month? > " + belongsToCurrentMonth(now));
        final LocalDateTime previousMonth = now.minusMonths(1);
        System.out.println("Does '" + toString(previousMonth) + "' belong to the current month? > " + belongsToCurrentMonth(previousMonth));
        final LocalDateTime nextMonth = now.plusMonths(1);
        System.out.println("Does '" + toString(nextMonth) + "' belong to the current month? > " + belongsToCurrentMonth(nextMonth));
    }
}

Test output:

Now: 2020-02-16T22:12:49.957, in mills: 1581891169957
Start of day: 2020-02-16T00:00:00
End of day: 2020-02-16T23:59:59.999999999
Does '2020-02-16T22:12:49.957' belong to the current day? > true
Does '2020-02-15T22:12:49.957' belong to the current day? > false
Does '2020-02-17T22:12:49.957' belong to the current day? > false
Start of week: 2020-02-10T00:00:00
End of week: 2020-02-16T23:59:59.999999999
Does '2020-02-16T22:12:49.957' belong to the current week? > true
Does '2020-02-09T22:12:49.957' belong to the current week? > false
Does '2020-02-23T22:12:49.957' belong to the current week? > false
Start of month: 2020-02-01T00:00:00
End of month: 2020-02-29T23:59:59.999999999
Does '2020-02-16T22:12:49.957' belong to the current month? > true
Does '2020-01-16T22:12:49.957' belong to the current month? > false
Does '2020-03-16T22:12:49.957' belong to the current month? > false


问:
read indefinite amount of integers and print on file
*this program read integers until one is negative then prints on a file a characteristic of each of them: how many integers it can be divided by. the problem is that it keeps asking for integers even when i inseert negative ones. please let me know if you can a way to fix this without changing too much of the code</p>

```<code>#include <stdio.h>
#include <stdlib.h>
int checkdiv(int *n);
int main(int argc, char * argv[]){
    int *p;
    int i, j;
    FILE *fp;
    int amount;
    i=0;
    p=NULL;

    if(fp = fopen("ris.txt", "w")){
        do{i++;
        p=realloc(p,sizeof(int)*i);
        scanf("%d", (p+i-1));
        amount=checkdiv(p+i-1);
        if(amount!= -1);
        fprintf(fp,"%d  %d\n", *(p+i-1),amount);
        }while(p+i-1>0);

    }else{
        printf("errore");
    }
    fclose(fp);
    free(p);
    return 0;
}
int checkdiv(int *n){
int i;
int amount=0;
for(i = 2;i < *n; i++){
    if(*n % i == 0){
        amount++;
    }
}
if(*n <= 0){
    amount= -1;
}
return amount;
}
</code>```

答:
Your problem is in:

```<code>}while(p+i-1>0);
</code>```

must be;

```<code>}while(*(p+i-1)>0);
</code>```

HTH

Body:
*this program read integers until one is negative then prints on a file a characteristic of each of them: how many integers it can be divided by. the problem is that it keeps asking for integers even when i inseert negative ones. please let me know if you can a way to fix this without changing too much of the code

#include <stdio.h>
#include <stdlib.h>
int checkdiv(int *n);
int main(int argc, char * argv[]){
    int *p;
    int i, j;
    FILE *fp;
    int amount;
    i=0;
    p=NULL;

    if(fp = fopen("ris.txt", "w")){
        do{i++;
        p=realloc(p,sizeof(int)*i);
        scanf("%d", (p+i-1));
        amount=checkdiv(p+i-1);
        if(amount!= -1);
        fprintf(fp,"%d  %d\n", *(p+i-1),amount);
        }while(p+i-1>0);

    }else{
        printf("errore");
    }
    fclose(fp);
    free(p);
    return 0;
}
int checkdiv(int *n){
int i;
int amount=0;
for(i = 2;i < *n; i++){
    if(*n % i == 0){
        amount++;
    }
}
if(*n <= 0){
    amount= -1;
}
return amount;
}

Body:
Your problem is in:

}while(p+i-1>0);

must be;

}while(*(p+i-1)>0);

HTH


问:
Spring Security with roles and permissions
I'm trying to set up role-based Security with permissions. I'm trying to do this together with  Spring-Security.

I don't want to set up ACL as it seems it's an overkill for my requirements.

I just want to have simple permissions and roles as described in this article.
Unfortunately the article does not describe how to implement the given solution.

Has someone already tried this and can point me in the right direction? Maybe there is another blog entry that describes the implementation?

Thank you very much.

答:
ACL was overkill for my requirements also.

I ended up creating a library similar to @Alexander's  to inject a GrantedAuthority list for Role->Permissions based on the role membership of a user.

For example, using a DB to hold the relationships -

```<code>@Autowired
RolePermissionsRepository repository;

public void setup(){
  String roleName = "ROLE_ADMIN";
  List<String> permissions = new ArrayList<String>();
  permissions.add("CREATE");
  permissions.add("READ");
  permissions.add("UPDATE");
  permissions.add("DELETE");
  repository.save(new RolePermissions(roleName, permissions));
}
</code>```

When an Authentication object is injected in the current security session, it will have the original roles/granted authorities.

This library provides 2 built-in integration points for Spring Security.
When the integration point is reached, the PermissionProvider is called to get the effective permissions for each role the user is a member of.

The distinct list of permissions are added as GrantedAuthority items in the Authentication object.

You can also implement a custom PermissionProvider to store the relationships in config for example.

A more complete explanation here - https://stackoverflow.com/a/60251931/1308685

And the source code is here -
https://github.com/savantly-net/spring-role-permissions

Body:
ACL was overkill for my requirements also.

I ended up creating a library similar to @Alexander's  to inject a GrantedAuthority list for Role->Permissions based on the role membership of a user.

For example, using a DB to hold the relationships -

@Autowired
RolePermissionsRepository repository;

public void setup(){
  String roleName = "ROLE_ADMIN";
  List<String> permissions = new ArrayList<String>();
  permissions.add("CREATE");
  permissions.add("READ");
  permissions.add("UPDATE");
  permissions.add("DELETE");
  repository.save(new RolePermissions(roleName, permissions));
}

When an Authentication object is injected in the current security session, it will have the original roles/granted authorities.

This library provides 2 built-in integration points for Spring Security.
When the integration point is reached, the PermissionProvider is called to get the effective permissions for each role the user is a member of.

The distinct list of permissions are added as GrantedAuthority items in the Authentication object.

You can also implement a custom PermissionProvider to store the relationships in config for example.

A more complete explanation here - https://stackoverflow.com/a/60251931/1308685

And the source code is here -
https://github.com/savantly-net/spring-role-permissions


问:
What characters do you send to a "Generic/Text Only" printer to print bolded and underlined characters?
I need to print a report for a project I'm working on. I'm already printing it, but some formatting is missing (bold, underline) that is used to emphasize and differentiate certain areas.

The printer is installed as "Generic/Text Only" (required by the client). I've been googling for a while now, and haven't found a way to send the right characters to make the text bolded and underlined from code.

How can I print bold and underline characters in a generic text only printer by code?

答:
Well, if it accepts Epson-like codes then print the bytes:

```<code>27, 45, 49  for underline on
27, 45, 48  for underline off
27, 69      for bold on
27, 70      for bold off
</code>```

Body:
Well, if it accepts Epson-like codes then print the bytes:

27, 45, 49  for underline on
27, 45, 48  for underline off
27, 69      for bold on
27, 70      for bold off


问:
Is there any difference between `xtratim` and overriding p3?
According to reference csound manual, one should use xtratim (or opcodes that implicitly use it e.g. madsr) when writing instruments that respond to MIDI since the duration of the key/note is not know in advance (for live performances).

However, I also noted in an external example that one can override p3 (the score note length) from within the instrument code. So, is there any difference between doing this and using xtratim?

答:
Yes, xtratim and -r opcodes that have a release segment will trigger that extra time for release when the note turns off.  p3 will only be the duration value for the "on" time.

For example, if you run the following:

```<code>instr S1
  p3 = 2
  asig = oscili(0.25, 440)
  asig *= linsegr(1, .1, 1, 4, 0)
  out(asig, asig)
endin
schedule("S1", 0, 0.1)
</code>```

The schedule call sets p3 to 0.1 seconds

The instrument redefines p3 to 2 seconds

The instrument runs for 2 seconds and has a 4 second release time afterwards due to the linsegr release value

In general, overriding p3 should be used with caution but is good for certain situations like ensuring a minimum amount of time is given to an instrument. Release time from xtratim or -r opcodes is probably more applicable to most use cases.

Body:
Yes, xtratim and -r opcodes that have a release segment will trigger that extra time for release when the note turns off.  p3 will only be the duration value for the "on" time.

For example, if you run the following:

instr S1
  p3 = 2
  asig = oscili(0.25, 440)
  asig *= linsegr(1, .1, 1, 4, 0)
  out(asig, asig)
endin
schedule("S1", 0, 0.1)

The schedule call sets p3 to 0.1 seconds

The instrument redefines p3 to 2 seconds

The instrument runs for 2 seconds and has a 4 second release time afterwards due to the linsegr release value

In general, overriding p3 should be used with caution but is good for certain situations like ensuring a minimum amount of time is given to an instrument. Release time from xtratim or -r opcodes is probably more applicable to most use cases.


问:
Laravel query join ManyToMany unique result
I have 3 tables : artists, albums and artist_albums.

I want get 1 result per album. For example, the album "What a Time to Be Alive" have 2 artists : "Drake" and "Future".
I would like a result in the following form :

```<code>id: 1,
name: "What a Time to Be Alive"
artists: [
    name: "Drake",
    name: "Future"
]
</code>```

Thanks for yous help

答: You'll want to set the Model up with a belongsToMany relationship, and eager load the results.</p>

Body:
I have 3 tables : artists, albums and artist_albums.

I want get 1 result per album. For example, the album "What a Time to Be Alive" have 2 artists : "Drake" and "Future".
I would like a result in the following form :

id: 1,
name: "What a Time to Be Alive"
artists: [
    name: "Drake",
    name: "Future"
]

Thanks for yous help


问:
Auto-reload browser when I save changes to html file, in Chrome?
I'm editing an HTML file in Vim and I want the browser to refresh whenever the file underneath changes.

Is there a plugin for Google Chrome that will listen for changes to the file and auto refresh the page every time I save a change to the file? I know there's XRefresh for Firefox but I could not get XRefresh to run at all.

How hard would it be to write a script to do this myself?

答:
Offline solution using R

This code will:

setup a local server using the given .html-file

return the server adress, so that you can watch it in a browser.

make the browser refresh everytime a change is saved to the .html-file.

```<code>install.packages("servr")
servr::httw(dir = "c:/users/username/desktop/")
</code>```

Similar solutions exist for python etc.

Body:
Offline solution using R

This code will:

setup a local server using the given .html-file

return the server adress, so that you can watch it in a browser.

make the browser refresh everytime a change is saved to the .html-file.

install.packages("servr")
servr::httw(dir = "c:/users/username/desktop/")

Similar solutions exist for python etc.


问:
Web parsing | How to get data that's generated by script
I want to parse site, and I want to get a data which is generated by script. To get this data I have to run next js script in chrome dev tools console

```<code>let key;

grecaptcha
  .execute(<SITE_KEY>, { action: 'pageview' })
  .then(function(e) {
    $.post('/recaptcha', {
      token: e,
      imprints: key
    }).done(function(i) {
      console.log(i);
    });
  });
</code>```

Problem is next, key it's a data-verify attribute in span (see screenshoot below)

I have python script that parse page and get all keys for all objects i need, but problem that when I run that script all keys are different with keys from page (because page reloaded probably, or different cookies). I need any ideas how to run this script properly. And let me know if you need any info to clarify smth.

答: Got it! I did it with Selenium WebDriver, it can execute javascript code in python via execute_script method.

Body:
I want to parse site, and I want to get a data which is generated by script. To get this data I have to run next js script in chrome dev tools console

let key;

grecaptcha
  .execute(<SITE_KEY>, { action: 'pageview' })
  .then(function(e) {
    $.post('/recaptcha', {
      token: e,
      imprints: key
    }).done(function(i) {
      console.log(i);
    });
  });

Problem is next, key it's a data-verify attribute in span (see screenshoot below)

I have python script that parse page and get all keys for all objects i need, but problem that when I run that script all keys are different with keys from page (because page reloaded probably, or different cookies). I need any ideas how to run this script properly. And let me know if you need any info to clarify smth.


问:
Can I add a whole Bootstrap only project to a new Angular one?
I've got a ready Bootstrap project (with good UI&UX) but I'm not sure if I can import it straightaway in my Angular one. I saw some tips to add bootstrap on the internet but there wasn't a guide how to import a whole ready one.</p>

答: Sure you can add. If the project is not using BS4 yet, then you have to install it, and can use the bs4 classes as you would use outside of an Angular app.</p>


问:
How to comment each change in files so they will be visible for git but hidden in actual files
When I develop a feature I usually need to change non-related files: utils, helpers. But not only those. There are cases when event some repository is not related to the feature but it just contains additional code to allow developing of the main feature.

Initially I just skipped this problem. But now I understand that it is difficult to understand why I changed some files if they are not related to the feature I committed. I need something like usual comments in files but they should be visible just for git: when I browse commit message/history I want to see why I did a specific change. I can not comment each change. The biggest problem is that my change could be not just adding code lines but removing. Nobody need to see comments for the absent lines.

My first idea is to commit changes with comments in files and then do another commit to remove comments. By it is like a workaround. I work in PhpStorm. And I always see git history there. I want to open a file from commit and see why I did some change. I would be very useful for me. Very useful. For me it give the same profit as I have from commit message.

I do not see other solutions. Maybe someone else had such problem.

I also assume that other git GUI programs could have such a feature.

答:
Well, why not using the git commit message for that?

You can add several lines to a commit message by putting many -m parameters:

```<code>git commit -m "My commit message (headline)" -m "Second line" -m "third line..."
</code>```

Or if you don't want to write this way, you can setup the editor and when you run git commit, it will open your editor to write your long commit message, so there you can explain everything you need, why you changed the files and so on.

To setup the editor, just run:

```<code>git config core.editor vim
</code>```

PS: I recommend looking how people write commit messages in great repositories, like the linux one (https://github.com/torvalds/linux). Look how descriptive are the messages there and be inspired :)

Body:
Well, why not using the git commit message for that?

You can add several lines to a commit message by putting many -m parameters:

git commit -m "My commit message (headline)" -m "Second line" -m "third line..."

Or if you don't want to write this way, you can setup the editor and when you run git commit, it will open your editor to write your long commit message, so there you can explain everything you need, why you changed the files and so on.

To setup the editor, just run:

git config core.editor vim

PS: I recommend looking how people write commit messages in great repositories, like the linux one (https://github.com/torvalds/linux). Look how descriptive are the messages there and be inspired :)


问:
How to implement CSS button animations into your website?
I stumbled across this website that lists CSS button animations. I have linked it --> https://buttonanimations.github.io/ I don't know if its just me but when I try to implement the animations into my website (Copy and paste) they just break. Is it on their end or mine, maybe they didn't input the animations correctly into the website. </p>

<p>(Currently using Safari) (I mean it should work right?)</p>

答:
The animations can be used by clicking on the animation on the page, copying the value:

```<code>.button_name:hover{ color: blue; -webkit-transform: scale(1.2); -ms-transform: scale(1.2); transform: scale(1.2); animation-duration: 1s; transition-duration: 1s; transition-property: 1s; }
.button_name { width: 300px; height: 45px; background-color: #cccccc; }
</code>```

and putting the code in a stylesheet or

<button class="hover_button">Test</button>

```

Body:
I stumbled across this website that lists CSS button animations. I have linked it --> https://buttonanimations.github.io/ I don't know if its just me but when I try to implement the animations into my website (Copy and paste) they just break. Is it on their end or mine, maybe they didn't input the animations correctly into the website.

(Currently using Safari) (I mean it should work right?)

Body:
The animations can be used by clicking on the animation on the page, copying the value:

.button_name:hover{ color: blue; -webkit-transform: scale(1.2); -ms-transform: scale(1.2); transform: scale(1.2); animation-duration: 1s; transition-duration: 1s; transition-property: 1s; }
.button_name { width: 300px; height: 45px; background-color: #cccccc; }

and putting the code in a stylesheet or <style> element.

Note that the .button_name selector should be replaced by the class(such as hover_button) that the element has when putting the code in a file or style element:

<button class="hover_button">Test</button>

.hover_button:hover{ color: blue; -webkit-transform: scale(1.2); -ms-transform: scale(1.2); transform: scale(1.2); animation-duration: 1s; transition-duration: 1s; transition-property: 1s; }
.hover_button { width: 300px; height: 45px; background-color: #cccccc; }

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
.hover_button:hover{ color: blue; -webkit-transform: scale(1.2); -ms-transform: scale(1.2); transform: scale(1.2); animation-duration: 1s; transition-duration: 1s; transition-property: 1s; }
.hover_button { width: 300px; height: 45px; background-color: #cccccc; }
    </style>
</head>
<body>
<button class="hover_button">Test</button>
</body>
</html>


问:
regex to extract lookbehind and lookahead from a regex pattern
I have an unusual application whereby I need to extract the content of lookbehind and lookahead portions of a regex pattern (using regex of course!). For example in the following pattern:

```<code>(?<=(?:c|d))123(?=(?:x|y))
</code>```

matches the first 123 in the following string:

```<code>abc123xyz123xyz
</code>```

What I need is to extract the following strings:

```<code>(?:c|d)
</code>```

and

```<code>(?:x|y)
</code>```

It is proving hard because I can't easily find the correct closing brackets as there could be other brackets as in the example.

Just wondering if anyone has had to do this before. Any thoughts welcome

答:
Based on the comments to the question, my understanding is that the asker Kaveh1000 is happy with Wiktor's solution; however it seems he's puzzled by one part of that solution

```<code>(\((?:[^()]++|(?1))*\))
</code>```

In this respect, I suggest to read Mastering Regular Expressions, 3rd Edition's, which dedicates a lot of words to this topic (and specifically to this very regex); I've just read it from there now, and in the following I try to convey my understanding:

it is a capturing group (…) to which we can refer if we need (and we do indeed in 4.2.);

it matches a pair of literal parethesis with something in between \(…\);

that something in between, (?:…)*, is the sequence of 0 or more (ordinary greedy) non-captured expressions;

each of those 0 or more repetions can be either

4.1. a sequence of 0 or more non-parenthesis, [^()]++,

4.2. or something, (?1), which matches the same regex we are matching now (point 1); this is the recursiveness of the regex.

Two notes:

The literal parenthesis appear in (this part of) the regex only through \( and \), which are ordered (opening first, then closing) and both have to match; this guarantees that this part of the regex will match balanced parethesis only.

++ is necessary because if the regex is ((something)+)* there are many ways to assign a number of repetions to + and *, and all of them have to be tried; ++ instead of + will match as much as possible, as it was alone in (something)+, and only then the * takes effect.

But what is ++ by itself? I mean, what is ++ beyond the reason why it's necessary in this regex? One easy way to isolate and clearly see the effect of ++ as compared to + is to compare how the regexes a+ab and a++ab behave with a line containing aaaaaab. The former will match the whole line, with a+ matching the first 5 as, and ab matching the last two characters; the latter will not match, as a++ matches as many as as possible without giving up in favour of the rest of the regex, thus matching all 6 a, without leaving any chance for ab to match after it and, eventually, leading to a match failure.

Body:
I have an unusual application whereby I need to extract the content of lookbehind and lookahead portions of a regex pattern (using regex of course!). For example in the following pattern:

(?<=(?:c|d))123(?=(?:x|y))

matches the first 123 in the following string:

abc123xyz123xyz

What I need is to extract the following strings:

(?:c|d)

and

(?:x|y)

It is proving hard because I can't easily find the correct closing brackets as there could be other brackets as in the example.

Just wondering if anyone has had to do this before. Any thoughts welcome

Body:
Based on the comments to the question, my understanding is that the asker Kaveh1000 is happy with Wiktor's solution; however it seems he's puzzled by one part of that solution

(\((?:[^()]++|(?1))*\))

In this respect, I suggest to read Mastering Regular Expressions, 3rd Edition's, which dedicates a lot of words to this topic (and specifically to this very regex); I've just read it from there now, and in the following I try to convey my understanding:

it is a capturing group (…) to which we can refer if we need (and we do indeed in 4.2.);

it matches a pair of literal parethesis with something in between \(…\);

that something in between, (?:…)*, is the sequence of 0 or more (ordinary greedy) non-captured expressions;

each of those 0 or more repetions can be either

4.1. a sequence of 0 or more non-parenthesis, [^()]++,

4.2. or something, (?1), which matches the same regex we are matching now (point 1); this is the recursiveness of the regex.

Two notes:

The literal parenthesis appear in (this part of) the regex only through \( and \), which are ordered (opening first, then closing) and both have to match; this guarantees that this part of the regex will match balanced parethesis only.

++ is necessary because if the regex is ((something)+)* there are many ways to assign a number of repetions to + and *, and all of them have to be tried; ++ instead of + will match as much as possible, as it was alone in (something)+, and only then the * takes effect.

But what is ++ by itself? I mean, what is ++ beyond the reason why it's necessary in this regex? One easy way to isolate and clearly see the effect of ++ as compared to + is to compare how the regexes a+ab and a++ab behave with a line containing aaaaaab. The former will match the whole line, with a+ matching the first 5 as, and ab matching the last two characters; the latter will not match, as a++ matches as many as as possible without giving up in favour of the rest of the regex, thus matching all 6 a, without leaving any chance for ab to match after it and, eventually, leading to a match failure.