Recursively delete directories Gau Frette FTP adapter

To with FTP recursively delete files and directories adapter Gau Frette, you can apply following trick to avoid the error message:

ftp_rmdir(): Directory not empty.

1. just delete all files

2. then delete the lowest directories up to the top:

/**
 * @param Filesystem $fileSystem
 */
function deleteAllFilesInDirectory(Filesystem $fileSystem)
{
    // delete files first, than directories
    foreach ($fileSystem->keys() as $key) {
        if (!$fileSystem->isDirectory($key)) {
            $fileSystem->delete($key);
        }
    }
    $keys = $fileSystem->keys();
    usort($keys, function (string $a, string $b){
        $aCount = substr_count($a, '/');
        $bCount = substr_count($b, '/');
        return $bCount <=> $aCount;
    });
    foreach ($keys as $key) {
        $fileSystem->delete($key);
    }
}

AWS time zone adjust Amazon Linux 2 and RDS MySQL

In the logs and the database use the correct time stamp of the own time zone, must be

1. Configure the system time of the EC2 instance

sudo ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime

and in the file /etc/sysconfig/clock Enter the time zone:

sudo vi /etc/sysconfig/clock
ZONE="Europe/Berlin"

After a reboot of the instance must be:

sudo reboot

The adjustment can be checked with

date

Those more…

Symfony FosUser bundle to apply their own password policy

In the SonataAdmin with FosUser bundle your own rules to define module for the strength of the passwords, can you overwrite the validation.xml, by one in the folder src/application/Sonata/UserBundle/resources/config /. its own validation.XML creates:

<?xml version="1.0" ?>
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping
        http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">

    <class name="FOS\UserBundle\Model\User">

        <property name="plainPassword">
            <constraint name="NotBlank">
                <option name="message">fos_user.password.blank</option>
                <option name="groups">
                    <value>Registration</value>
                    <value>ResetPassword</value>
                    <value>ChangePassword</value>
                </option>
            </constraint>
            <constraint name="Length">
                <option name="min">8</option>
                <option name="max">50</option>
                <option name="minMessage">fos_user.password.short</option>
                <option name="groups">
                    <value>Registration</value>
                    <value>Profile</value>
                    <value>ResetPassword</value>
                    <value>ChangePassword</value>
                </option>
            </constraint>
            <constraint name="Regex">
                <option name="pattern">/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}$/</option>
                <option name="message">Das Passwort muss mindestens 8 Zeichen haben, eine Zahl, Groß und Kleinschreibung enthalten.</option>
                <option name="groups">
                    <value>Registration</value>
                    <value>Profile</value>
                    <value>ResetPassword</value>
                    <value>ChangePassword</value>
                </option>
            </constraint>
        </property>
    </class>
</constraint-mapping>

Create symfony brute-force guard for SonataAdmin

For the SonataAdmin bundle There is the possibility of Symofny guards own logic in the login process to incorporate, such as:

  • Defense against brute force attacks by a maximum number of login attempts

In the following example, I have configured a guard for the administration area, It will count, How many times a user incorrectly logged.

The UserManager must then contain the logic, to counting the number of logins for each user, and it formed. also to ban for a period of time. more…

letsencrypt AWS http challenge

I had the problem, that when renewing the Letsencrypt certificate via cronjob Amazon Linux 2

certbot renew --post-hook "systemctl reload httpd"  >> /var/log/certbot.log 2>&1

the SSL certificate was not renewed, but following error occurred:

Could not choose appropriate plugin: The manual plugin is not working; there may be problems with your existing configuration.
The error was: PluginError('An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.',)
Attempting to renew cert (foo.de) from /etc/letsencrypt/renewal/foo.conf produced an unexpected error: The manual plugin is not working; there may be problems with your existing configuration.
The error was: PluginError('An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.',). Skipping.

I then looked in configuration: /etc/letsencrypt/renewal/foo.conf&nbsp;and the Authentificator modified on Apache and the challenge of Authentificator on HTTP (through the Web server).

# Options used in the renewal process
[renewalparams]
account = xxx
server = https://acme-v02.api.letsencrypt.org/directory
authenticator = apache
installer = apache
pref_challs = http-01,

After that was the important Port 80 unlock the security group for authentication and another command

certbot renew

was the certificate was successfully renewed.

Cert is due for renewal, auto-renewing...
Plugins selected: Authenticator apache, Installer apache
Renewing an existing certificate
Performing the following challenges:
http-01 challenge for foo.de
Waiting for verification...
Cleaning up challenges

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
new certificate deployed with reload of apache server; fullchain is
/etc/letsencrypt/live/foo.de/fullchain.pem

Angular ngx-translate TranslateLoader ohne http Modul

Compatibility with old browsers, as the Firefox version <= 5 to reach, can you do that angular http Do not use module. The NGX-translate Modules bneötigt a loader, It loads the correct language via AJAX request. Also with the XMLHttpRequest and an Observalbe solve this can:

import {Injectable} from '@angular/core';
import {TranslateLoader} from '@ngx-translate/core';
import {Observable} from 'rxjs/Observable';

@Injectable()
export class LanguageLoader implements TranslateLoader {

  getTranslation(lang: string): Observable<any> {
    return Observable.create(function (observer) {
    let url = `./assets/i18n/${lang}.json?=` + new Date().getTime();
    let xhr = new XMLHttpRequest();

      xhr.onreadystatechange = function () {
        if (xhr.readyState == XMLHttpRequest.DONE || xhr.readyState == 4) {
              let response = JSON.parse(xhr.responseText);
              observer.next(response);
              observer.complete();
        }
      }
      xhr.open('GET', url, true);
      xhr.send(null);
    });
  }
}

In the app.module.TS can you then embed the loader as follows:

TranslateModule.forRoot({
  loader: {provide: TranslateLoader, useClass: LanguageLoader}
})

Execute PHP script as a Windows service

Under Windows, scripts can be, that's endless run with PHP using a service implemented.

This has the advantage of, that is the memory consumption with the time to infinity, with endless script versions and a recovery and restart functionality can be implemented, to keep the service over long periods of time running.

Furthermore, the service receives from the operating system events, if e.g.. a shutdown is, to be able to stop in time itself and not corrupt data to produce cancellation in a non-atomic operation.

To create a Windows service, you need the win32service PHP library.

You can here them Download and in the php.ini embed:

extension=php_win32service.dll

Create service more…