RSA Encryption between JavaScript and PHP (bidirectional)

Auf der Suche nach einer Möglichkeit, Daten zwischen JavaScript und PHP mittels RSA (PublicKey und PrivateKey) zu verschlüsseln und entschlüsseln trifft man auf viele Libraries, Demos, Beispiele und GitHub Repos.
Egal welche ich getestet habe, es war keine zufrieden stellende Lösung dabei.
Entweder funktionieren diese schlichtweg nicht (mehr) oder es ist eine unidirektionale Lösung, jedoch keine bidirektionale.

JsPhpRSa

Continue reading “RSA Encryption between JavaScript and PHP (bidirectional)” »

Visual Studio Code / Hide .map & .js when developing in TypeScript

Nutzt man den Editor Visual Studio Code um beispielsweise Angular2 Anwendungen zu entwickeln, könnten die generierten .js bzw. .js.map Dateien pro .ts Datei die Übersicht im Projekt nehmen.
Dank der genialen Möglichkeit in den Settings des Editors (JSON) auch Bedingungen anzugeben, ist beispielsweise folgende Einstellung in den UserSettings möglich:

    "files.exclude": {
        "**/*.map": true,
        "**/*.js": {"when": "$(basename).ts"}
    }

Damit werden die .js Dateien nur ausgeblendet, wenn es eine gleichnamige .ts Datei gibt. Sonst wäre diese Einstellung wohl zu weitreichend.

SSH Two-factor mit Publickey und ohne Passwort (google-authenticator)

Im Internet finden sich viele Anleitungen um den SSH Zugang mittels einer Two-factor Komponente (z.B. dem google-authenticator) zu sichern.
Bei fast allen Anleitungen wird jedoch von der Kombination aus Passwort und Two-factor Code ausgegangen. Wird dabei der Publickey des Clients auf dem Server unter den authorized_keys abgelegt, wird die Two-factor Authentifizierung komplett umgegangen, da PubkeyAuthentication alles andere aufhebt.

In dieser Anleitung wird beschrieben, wie der SSH Dienst konfiguriert werden muss, damit eine Kombination aus Publickey und Two-factor Token ausgewertet wird.

Continue reading “SSH Two-factor mit Publickey und ohne Passwort (google-authenticator)” »

KMS-Host-based Activation Troubleshooting

Bei der Verwendung eines KMS Host kann es unter Umständen zu seltsamen Phänomenen kommen. Evtl. hat der Sysadmin den KMS Server umgezogen oder den DNS Server migriert oder vielleicht sogar den notwendigen DNS SRV Record vergessen. Um all diesen Ursachen auf “die schliche” zu kommen, können folgende Befehle verwendet werden:

Ein häufig auftretender Fehler wird mit dem Error-Code “0xC004F035″ quittiert. Dieser Error Code bedeutet soviel wie “Der KMS Host kann nicht kontaktiert werden”
Continue reading “KMS-Host-based Activation Troubleshooting” »

Quick Setup: PHP7 + Nginx + PHP-FPM

Der Release von PHP 7.0 rückt immer näher! Mittlerweile sind wir beim fünften Release Candidate angekommen, den wir in diesem Quick Setup zusammen mit Nginx, Fast_cgi und PHP-FPM installieren werden. Zusätzlich sind in der späteren Nginx Site Config noch ein paar TYPO3 Flow 3.x spezifische Redirect Rules definiert, damit das TYPO3 Flow Framework funktioniert… Diese zusätzlichen Zeilen sind markiert und können getrost weggelassen werden falls nicht mit TYPO3 Flow gearbeitet wird.

In diesem Quick Setup Tutorial:
– Nginx 1.9.5 Mainline
– PHP7.0 RC5 von dotdeb
– PHP7-FPM sowie Fast_CGI
– Debian 8 Jessie OS

Continue reading “Quick Setup: PHP7 + Nginx + PHP-FPM” »

TYPO3 Flow CronJob Scheduler

Fast jede Web Anwendung benötigt früher oder später einen oder mehrere CronJobs. Während sich eine geringe Anzahl an CronJobs noch verhältnismäßig gut verwalten lässt, wird es umso komplexerer desto mehr CronJobs eingesetzt werden müssen. Kommt hinzu, dass diese mit verschiedenen Timings ausgeführt werden müssen, hilft oft nur noch ein Scheduler.

CronJobs innerhalb eines Frameworks wie TYPO3 Flow scheinen im ersten Moment nicht ganz einfach, denn wie soll dieser gezielt ausgeführt (inkl. dem gesamten Initialisierungsprozess des Frameworks) werden, ohne dabei einen HTTP Request zu simulieren, welcher ggfs. sogar eine Authentifizierung erfordert?

Dank der CommandControllers des TYPO3 Flow Frameworks können wir die Aufgaben eines CronJobs in einen Service auslagern und von einem CommandController (ReadTheDocs: Custom Commands) auf der Shell ausführen lassen.

Hierzu würde man den CronJob (bspw. durch Eintragung in die crontab) einfach den entsprechenden Command ausführen lassen:

* * * * * /var/www/flow myCommandController:myCommand

Der Scheduler

Kommen wir zurück zum Thema komplexere CronJobs mit unterschiedlichen Timings… Dies würde mit Hilfe der Crontab zu einer komplizierten Angelegenheit führen, welche sich darüber hinaus nicht schön warten lassen würde. (Je nach Hoster hätten wir auch gar keinen Zugriff auf diese Datei sondern müssten uns mit einem mehr oder weniger komfortablen WebInterface zufrieden geben).

Für unseren Scheduler innerhalb von TYPO3 Flow verwenden wir das Scheduler Package von TreeAgency (GitHub ttreeagency/Scheduler) welches die Aufgabe eines CronJob Schedulers herrvoragend übernimmt.

Nach der Installation des Packages werden die einzelnen CronJobs in einzelne Klassen aufgeteilt, welche alle das Interface \Ttree\Scheduler\Task\TaskInterface implementieren und mit einer eigens aus dem Package stammenden Annotation @Scheduler\Schedule(expression=”* * * * *”) getimed werden.

Anschließend sollte nur noch ein jede Minute laufender CronJob auf den entsprechenden Scheduler CommandController des Packages gesetzt werden.
Alle weiteren Wartungen/Timings an den CronJobs können nun bequem bei der Implementierung der Klassen vorgenommen werden.

* * * * * /var/www/flow task:run

Für weitere Informationen und Anleitung befolgt bitte das Readme des Entwicklers auf GitHub (ttreeagency/Scheduler)

TYPO3 Flow Render View Template from Database

In einem kürzlichen Anwendungsfall benötigte ich in einem Projekt die Möglichkeit, das View Template dynamisch aus der Datenbank anstatt aus dem Resource/Private/Template Verzeichnis aus einer HTML View zu laden. Dies könnte zum Beispiel dann sinnvoll sein, wenn ein Backend/Admin Benutzer (wie in meinem Fall) in der Lage sein soll den View Code zu editieren.

Ein klassischer Anwendungsfall könnte das Editieren eines kleinen Partials bzw. dem Inhalt eines HTML Newsletter sein.
Leider bietet TYPO3 Flow von Hause aus keine Möglichkeit, den View Code dynamisch zu injecten anstatt aus einer HTML Datei zu laden.

Eine Möglichkeit soll dieser Artikel mit Hilfe einer eigenen View Klasse aufzeigen:

Die View Klasse

Wir erstellen in unserem Package eine eigene View Klasse. Dazu ist es wichtig, dass die Datei innerhalb einer Ordnerstruktur Classes/Vendor/Package/View/MyController/MyActionName.php angelegt wird.
Zur Erklärung: Die View Klasse muss den Namen der Controller Action tragen, in welcher sie automatisch verwendet werden soll. Damit das Funktioniert muss die View Klasse zusätzlich in einem Ordner mit dem Namen des entsprechenden Controllers abgelegt werden. Daraus ergibt sich die Verzeichnisstruktur View/MyController/MyActionName.php

Da wir innerhalb des View Template Codes in der Lage sein wollen Fluid Code zu rendern, müssen wir unsere eigene View Klasse von \TYPO3\Fluid\View\TemplateView ableiten.
Im Großen und Ganzen besteht der gesamte Code unserer eigenen View Klasse aus den wichtigsten Methoden der abgeleiteten Basis Klasse mit ein paar wenigen aber tiefgreifenden Eingriffen in den Code

class MyActionName extends \TYPO3\Fluid\View\TemplateView {

    /**
     * @var string
     */
    protected $xmlTemplateCode = "";

    /**
     * @param $xmlTemplateCode
     */
    public function setXmlTemplateCode($xmlTemplateCode) {
        $this->xmlTemplateCode = $xmlTemplateCode;
    }

    /**
     * Resolve the template path and filename for the given action. If $actionName
     * is NULL, looks into the current request.
     *
     * @param string $actionName Name of the action. If NULL, will be taken from request.
     * @throws Exception\InvalidTemplateResourceException
     * @throws \TYPO3\Fluid\View\Exception\InvalidTemplateResourceException
     * @return string Full path to template
     */
    protected function getTemplateSource($actionName = NULL) {
        // This is the modified Part
        if ($this->xmlTemplateCode != "") {
            return $this->xmlTemplateCode;
        }

        // This can be deleted
        $templatePathAndFilename = $this->getTemplatePathAndFilename($actionName);
        $templateSource = Files::getFileContents($templatePathAndFilename, FILE_TEXT);
        if ($templateSource === FALSE) {
            throw new Exception\InvalidTemplateResourceException('"' . $templatePathAndFilename . '" is not a valid template resource URI.', 1257246929);
        }

        return $templateSource;
    }


    /**
     * Original Render Code with a little adjustment!!!!!
     * isCompilable is always set to FALSE
     * This enables to load a different Fluid Template on each request without cache
     *
     *
     * Loads the template source and render the template.
     * If "layoutName" is set in a PostParseFacet callback, it will render the file with the given layout.
     *
     * @param string $actionName If set, the view of the specified action will be rendered instead. Default is the action specified in the Request object
     * @return string Rendered Template
     * @api
     */
    public function render($actionName = NULL) {
        $this->baseRenderingContext->setControllerContext($this->controllerContext);
        $this->templateParser->setConfiguration($this->buildParserConfiguration());

        $templateIdentifier = $this->getTemplateIdentifier($actionName);
        if ($this->templateCompiler->has($templateIdentifier)) {
            $parsedTemplate = $this->templateCompiler->get($templateIdentifier);
        } else {
            $parsedTemplate = $this->templateParser->parse($this->getTemplateSource($actionName));

            // Set isCompilable to FALSE
            $parsedTemplate->setCompilable(false);

            if ($parsedTemplate->isCompilable()) {
                $this->templateCompiler->store($templateIdentifier, $parsedTemplate);
            }
        }

        if ($parsedTemplate->hasLayout()) {
            $layoutName = $parsedTemplate->getLayoutName($this->baseRenderingContext);
            $layoutIdentifier = $this->getLayoutIdentifier($layoutName);
            if ($this->templateCompiler->has($layoutIdentifier)) {
                $parsedLayout = $this->templateCompiler->get($layoutIdentifier);
            } else {
                $parsedLayout = $this->templateParser->parse($this->getLayoutSource($layoutName));
                if ($parsedLayout->isCompilable()) {
                    $this->templateCompiler->store($layoutIdentifier, $parsedLayout);
                }
            }
            $this->startRendering(self::RENDERING_LAYOUT, $parsedTemplate, $this->baseRenderingContext);
            $output = $parsedLayout->render($this->baseRenderingContext);
            $this->stopRendering();
        } else {
            $this->startRendering(self::RENDERING_TEMPLATE, $parsedTemplate, $this->baseRenderingContext);
            $output = $parsedTemplate->render($this->baseRenderingContext);
            $this->stopRendering();
        }

        return $output;
    }
}

Anwendung / Im Controller

Um nun innerhalb unseres Controllers bzw. genauer gesagt unserer myActionName Action den View Template Code dynamisch zu laden ist lediglich eine Zeile Code notwendig:

/**
 * MyActionName Action
 */
public function myActionName() {

    $myTemplateCode = "
….
"; // Load this from Database or WebService

    $this->view->setXmlTemplateCode($myTemplateCode); // This allows to set a XMLTemplate which is stored in Database
}

In meinem Beispiel arbeite ich mit XML Template Code welcher aus einer Datenbank injected wird, daher der Name der Methode setXmlTemplateCode.

TYPO3 Flow Model Revisions / Doctrine Versionable

Es gibt Anwendungsfälle, bei denen jede Änderung an einem oder mehrerer Models festgehalten bzw. archiviert werden sollte.

Dies ist mittels des Doctrine Behaviors “Versionable” relativ einfach und vor allem transparent umzusetzen (Doctrine Behaviors).

Mein Versuch war es, dies in TYPO3 Flow einzubauen. Jedoch scheiterte mein Versuch da ich kein umfassendes Doctrine Wissen hatte um dies einzubauen.

Nun möchte ich hier einen Alternativen Weg vorstellen, welcher sich einem Symfony2 Bundle von SimpleThings bedient (GitHub: simplethings/entityaudit).

Um dieses SymfonyBundle in TYPO3 Flow lauffähig und schön zu integrieren, werden wir im folgenden eine Bridge zwischen Flow und dem Symfony Bundle erstellen.

SimpleThings EntityAudit installieren

Die Installation des SimpleThings/EntityAudit Bundles in unserem Flow Framework gestaltet sich dank Composer als relativ einfach.
Wir führen den Composer Befehl einfach im Root Verzeichnis der TYPO3 Flow Anwendung aus:

composer require "simplethings/entity-audit-bundle"

Hiermit wird das Symfony Bundle im Packages/Library Verzeichnis abgelegt.

Um dieses Bundle von Flows Object Management auszuschließen, fügenden wir folgende Einstellung in unserer Settings.yaml hinzu:

TYPO3:
  Flow:
    object:
      excludeClasses:
        'simplethings.entityauditbundle': ['SimpleThings\\EntityAudit\\.*']

Flow AOP Bridge

Als nächstes bedienen wir uns dem mächtigen AOP Features von TYPO3 Flow um unser Symfony Bundle zu integrieren.
Dazu legen wir einen neuen AOP Aspect in unserem Package an:

buildEventManager())")
     * @param \TYPO3\Flow\Aop\JoinPointInterface $joinPoint
     * @return \Doctrine\Common\EventManager
     */
    public function registerSimpleThingsAuditManager(\TYPO3\Flow\Aop\JoinPointInterface $joinPoint) {
        $emInstance = $joinPoint->getAdviceChain()->proceed($joinPoint);

        // Hier festlegen, welche Entities versioniert werden sollen
        $auditEntitiesArray = array('Vendor\Package\Domain\Model\MyEntity');

        $entityAuditConf = new \SimpleThings\EntityAudit\AuditConfiguration();
        $entityAuditConf->setAuditedEntityClasses($auditEntitiesArray);

        $entityAuditManagerInstance = new \SimpleThings\EntityAudit\AuditManager($entityAuditConf);
        $entityAuuditManagerInstance->registerEvents($emInstance);
        
        return $emInstance;
    }
}
?>

Als nächstes führen wir ein

# Database aktualisieren (Audit Tables erstellen)
./flow doctrine:update

auf der Shell aus und prüfen anschließend unsere Datenbank Tabellen. Wenn alles funktioniert hat, sollte es nun passend zu unserer MyEntity Tabelle eine weitere MyEntity_audit Tabelle sowie eine revision Tabelle geben.

Nun solltet ihr testen, ob bei einer Änderung von MyEntity auch gleichzeitig eine entsprechende Revision und ein Eintrag in der MyEntity_audit Tabelle angelegt wird.

Flow Annotation “Versionable”

Natürlich ist es unschön, die zu versionierenden Models innerhalb des Aspects im Array hardcoded einzutragen. Eine andere Möglichkeit könnte hier die Settings.yaml sein, in welcher die zu versionierenden Models eingetragen werden können.
Am saubersten halte ich jedoch die Möglichkeit, hierfür eine eigene TYPO3 Flow Annotation zu erstellen.

Hierzu legen wir eine neue Klasse mit dem Namen “AuditEntity” an und befüllen Sie mit dem Code für eine Annotation
Beispielnamespace: Vendor\Package\Audit\Annotations\AuditEntity

/**
 * @Annotation
 * @Target("CLASS")
 */
final class AuditEntity {
/** Nothing here, it's only a Marker Class */
}

Nun lassen sich innerhalb EntityAuditRegisterAspect mittels des TYPO3 Flow Reflection Services alle Models ermitteln, welche die neue Annotation tragen:

/**
 * @var \TYPO3\Flow\Reflection\ReflectionService
 * @Flow\Inject
 */
protected $reflectionService;

$annotatedModels = $this->reflectionService->getClassNamesByAnnotation('Vendor\Package\Audit\Annotations\AuditEntity');

Um sich die versionierten Models später nochmal auslesen lassen zu können, bringt das SimpleThings EntityAudit Bundle einen AuditReader mit GitHub: SimpleThings/EntityAudit AuditReader. Diesen können wir ebenfalls in unserem TYPO3 Flow Package verwenden.

TYPO3 Flow xDebug with DebugProxy

In PHP war das Debugging noch nie eine einfache Angelegenheit. Wenn der zu untersuchende Code auf einem entfernten Server lief, welcher sich hinter einer Firewall / NAT verbirgt, wurde es noch ein Stückchen komplizierter.

Wunderbar dass es mit TYPO3 Flow noch ein wenig komplexer wird, als es bereits sowieso schon ist. Der Grund liegt ganz einfach an der Tatsache, dass TYPO3 Flow für eure Services, Controller und anderen Klassen sogenannte Proxy Klassen generiert, welche dann zur Laufzeit ausgeführt werden.

Dies bedeutet, dass ein Breakpoint innerhalb der IDE im UserController auf der indexAction (z.B. Zeile 18) im später generierten und ausgeführten Proxy mit dem ungefähren Namen “UserController_Original” eine ganz andere Zeile ist. Das führt dazu dass z.B. PHPStorm bei einem Breakpoint entweder gar keine Reaktion zeigt oder das Debugging mit einer Fehlermeldung endet.

Lösung: DebugProxy

Ein DebugProxy schaltet sich zwischen eurer IDE und dem xDebug Protokoll und ist in der Lage, Zeilennummern und Dateipfade für TYPO3 Flow zu mappen.
Im besten Fall arbeitet der DebugProxy völlig transparent ohne das die IDE oder man selbst etwas davon mitbekommt.

Eines dieser DebugProxy Scripte war der debugproxy von sandstorm mitte 2012, welcher im April 2013 noch für TYPO3 Flow 2.0 angepasst wurde, mit den aktuellen Versionen jedoch nicht mehr zu funktionieren scheint.

https://github.com/sandstorm/debugproxy

Inzwischen gibt es jedoch vom User dfeyer auf GitHub einen neueren und deutlich schnelleren DebugProxy geschrieben in Googles Programmiersprache GO zum Download.

https://github.com/dfeyer/flow-debugproxy

Mein Setup (PHP 5.6, Debian 8, TYPO3 Flow 3.0)

Installation von GO und setzen der benötigten Go-Pfade

apt-get install golang
export $GOPATH=/usr/local/go
export $GOBIN=
export $GOROOT=/usr/lib/go

Setup des DebugProxy Scripts

cd /usr/local/go/src
# GitHub Repo klonen
git clone https://github.com/dfeyer/flow-debugproxy.git
cd /usr/local/go/src/github.com/dfeyer/flow-debugproxy

# Go Dependencies & Build
go get
go build

Nun haben wir das flow-debugproxy Go Script bereit zur Ausführung:

/usr/local/go/bin/flow-debugproxy --xdebug 127.0.0.1:9000 --ide 127.0.0.1:9010 --vv

Remote Server / Firewall / NAT ?!

Eine der wohl einfachsten Lösungen dieses Problems ist ein SSH-Tunnel von eurem lokalen Rechner auf dem PHPStorm läuft zum entsprechenden Remote-Server.

SSH-Tunnel auf OS X öffnen

ssh user@host -p 22 -R9010:127.0.0.1:9010

Hier wird eine SSH Sitzung gestartet welche den lokalen Port 9010 auf den Remote-Server Port 9010 tunnelt.
Auf dem Remote-Server lauscht auf Port 9010 nun der (vorher gestartete) DebugProxy von dfeyer, welcher die Daten an xDebug (welcher an Port 9000 lauscht) weitergibt bzw. zuvor ein Path-Mapping vornimmt.

Weitere Informationen / Links

Flow DebugProxy Script von dfeyer: GitHub: dfeyer/flow-debugproxy
Altes DebugProxy Script von sandstorm: GitHub: sandstorm/debugproxy
Hilfreiches Gist: https://gist.github.com/michaelgerdemann/7a4e2f5315c19ff6f896

Edit:
Mittlerweile gibt es auch auf discuss.neos.io einen entsprechenden Beitrag zu dem Thema:
Neos.io: how-to-debug-a-flow-application-with-xdebug-and-phpstorm

Nachtrag: PHPStorm / xDebug / DebugProxy

Folgendes Setup auf einem MacBook mit MAMP (Free)

xDebug Einstellungen in der php.ini

[xdebug]
zend_extension="/Applications/MAMP/bin/php/php5.6.10/lib/php/extensions/no-debug-non-zts-20131226/xdebug.so" ; Achtung! Pfad muss angepasst werden!
xdebug.remote_autostart=1
xdebug.remote_enable=1
xdebug.remote_host=127.0.0.1
xdebug.remote_port=9000
xdebug.idekey=phpstorm-xdebug

flow-debugproxy starten
Nachdem der flow-debugproxy von dfeyer in Go kompiliert wurde, können wir diesen nun starten:
./flow-debugproxy –v (Pfad: /Users/…./go/bin)

PHPStorm Einstellungen

xdebug_phpstorm_1

xdebug_phpstorm_2

xdebug_phpstorm_3

xdebug_phpstorm_4

TYPO3 Extbase: Storage Pid im Repository ändern

Die Storage Pid wird normalerweise über das TypoScript festgelegt und gilt somit für das gesamte Repository der Extension.
Möchte man – aus welchen Gründen auch immer – in einer individuellen Repository Methode eine andere Storage Pid verwenden, lässt sich dies unter anderem mit der Typo3QuerySettings lösen:

/**
 * Returns only Advert Presets
 */
public function getAllPresets() {
    $customStoragePid = "15"; // <== Custom Storage Pid

    // Get the default Settings
    $querySettings = $this->objectManager->get('\\TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Typo3QuerySettings');
    $querySettings->setStoragePageIds(array($customStoragePid));
    $this->setDefaultQuerySettings($querySettings);

    // Now get all (only Presets)
    $queryResult = $this->findAll();
    return $queryResult;
}

Durch das Fortsetzen der Benutzung dieser Seite, stimmst du der Benutzung von Cookies zu. Weitere Informationen

Wir verwenden Cookies, um Inhalte und Anzeigen zu personalisieren, Funktionen für soziale Medien anbieten zu können und die Zugriffe auf unsere Website zu analysieren. Außerdem geben wir Informationen zu Ihrer Nutzung unserer Website an unsere Partner für soziale Medien, Werbung und Analysen weiter.

Schließen