Toolchain für Webentwickler

Vorwort: Ich arbeite in Düsseldorf bei der “menadwork GmbH” als Webentwickler und vor einigen Monaten habe ich mein Betriebssystem auf Linux (Debian) umgestellt, daher musste ich meine Toolchain / Programmierumgebung neu einrichten. Vorweg kann ich schon mal verraten, dass man sehr gut und effizient damit arbeiten kann. Nur drei, vier Programme (IE, Photoshop, Outlook, MS Office) musste ich per VIrtualBox (Win7) virtualisieren. 

 

Im folgenden wird eine Toolchain / Programmierumgebung für Webprojekte (PHP, HTML, CSS, Sass, JavaScript) eingerichtet. Diese Anleitung werden ich im parallel für Windows und Linux beschreiben.

 

1.) git - git-scm.com

Als erstes Installieren / Konfigurieren wir “git” zur Versionskontrolle und um Quellcode von github.com laden zu können. Auch wenn du mit wenigen Leuten oder alleine an einem Projekt arbeitest ist der Einsatz von “git” sehr empfehlenswert. Da man so auch noch nach Wochen / Monaten nachvollziehen kann, warum man welche Änderung gemacht hat und diese zudem ganz einfach rückgängig machen kann.  

 

1.1) Installation:

1.1.1) Linux (Debian / Ubuntu)

sudo apt-get install git

 

1.1.2) Windows
http://msysgit.github.io/

 

Tipp:

- nutze von Anfang an die git-bash!

- bei der Installation wird nach “PATH” gefragt, hier sollte der zweite Punkt ausgewählt werden, da man ansonsten nur mit der git-bash arbeiten kann

git in der Windows-CMD

git für Windows

- Aktiviere “quick-edit-mode” in den Einstellungen der git-bash (nach der Installation), so dass man schnell kopieren und einfügen kann

- Windows-Laufwerke (Partitionen) sind direkt unter “/” aufgehangen -> z.b. cd /d/xampp/

- “vim ~/.vimrc” -> Konfiguration für “vim” 

z.B.: 

:syntax enable
:set tabstop=2
:set shiftwidth=2
:set expandtab

 

1.2) Konfiguration

 

1.2.1) “line ending” 

Es wird wahrscheinlich zu Probleme (Änderung in jeder Zeile der gespeicherten Datei) bei der Zusammenarbeit von “git unter Windows” & “git unter Linux (Mac)” geben, da diese ein anderes “line ending” haben (\n bzw. \r\n). - http://git-scm.com/book/ch7-1.html#Formatting-and-Whitespace

 

# Windows - Diese wandelt “LF” (\n) in “CRLF” (\r\n) Endungen um, wenn der Befehl “git pull” ausgeführt wird und wandelt dies beim “git commit” wieder zurück  

git config --global core.autocrlf true

 

# Linux (Mac) – Diese wandelt “CRLF” (\r\n) in “LF” (\n) Endungen um, wenn der Befehl “git commit” ausgeführt wird

git config --global core.autocrlf input

 

-> somit sind die Dateien auf dem Repository (z.B.: github oder gitlab) und in der lokalen git-history immer mit “LF” (\n) codiert.

 

1.2.2) “push” 

git config --global push.default simple

 

-> der Befehl “git push” schiebt nur commits von der aktuellen “branch” zum Repository (branch mit dem selben Namen)

 

1.2.3) “user”

Teile “git” mit wer du bist:

git config --global user.name DEIN_NAME
git config --global user.email DEINE_MAIL@ADRESSE

 

1.2.4) “alias”

Wie in der Linux-Bash (~/.bashrc), kann man auch für git “aliases” (~/.gitconfig) vergeben:

git config --global alias.last 'log -1 HEAD'
git config --global alias.unstage 'reset HEAD --'
git config --global alias.hard 'reset --hard'
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.cam commit -a -m

 

1.2.5) “color”

git config --global color.diff auto
git config --global color.ui auto
git config --global color.status auto
git config --global color.branch auto

 

2.) Webserver + PHP

Als Webserver installieren wir uns lokal den “Apache”-Webserver, da diese bei vielen Web-Projekten später auch im Live-System zum Einsatz kommt und wir bereits lokal Dinge wie “.htaccess“-Umleitungen etc. testen kann.  

 

2.1) Installation:

2.1.1) Linux (Debian / Ubuntu)

sudo apt-get install apache2 libapache2-mod-php5 php5-mysql php5-curl php5-gd php5-intl php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-ming php5-ps php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl php5-apcu php5-xdebug

 

Achtung: “php5-xdebug” sollte man nur auf seiner lokalen PC installieren!!! 

 

2.1.2) Windows

http://www.apachefriends.org/de/index.html

 

2.2) Konfiguration

Wenn man unter Linux bzw. Mac arbeitet, sollte man den Webserver bzw. PHP so konfigurieren, dass die entsprechenden PHP-Skript-Prozesse mit dem User des Webs laufen. Dies kann man z.B. via suphp oder via php-fpm bewerkstelligen. (Quick & Dirty: die Skripte mit dem eigenen User laufen lassen und das htdocs-Verzeichnis in das eigene Home-Verzeichnis legen)

Unter Windows braucht man sich an dieser Stelle noch keine Gedanken über User-Rechte machen, jedoch spätestens wenn man das Projekte zum ersten mal auf dem Server deployed muss man diesen Schritt auf dem Server wiederholen.

 

Tipp: hier findet man viele Anleitungen für die Installation von Linux-Servern -> http://www.howtoforge.de/

 

2.2.1) xDebug -> http://xdebug.org

Unter Windows (XAMPP) ist xDebug bereits vorinstalliert und muss nur noch in der “php.ini”-Datei aktiviert werden. Unter Linux befinden sich die Konfigurationen für PHP-Erweiterungen unter “/etc/php5/config.d/”.

z.B.: für Windows, wenn xampp unter “D:\xampp\” installiert ist

[XDebug]
;zend_extension = /path/to/xdebug.so
zend_extension = "D:\xampp\php\ext\php_xdebug.dll"
;xdebug.profiler_append = 0
;xdebug.profiler_enable = 1
xdebug.profiler_enable_trigger = 1
xdebug.profiler_output_dir = "D:\xampp\tmp"
xdebug.profiler_output_name = "cachegrind.out.%t-%s"
xdebug.remote_enable = 1
xdebug.remote_handler = "dbgp"
xdebug.remote_host = "127.0.0.1"
xdebug.trace_output_dir = "D:\xampp\tmp"
xdebug.remote_port=9000

 

 Info: http://wiki.netbeans.org/HowToConfigureXDebug#How_to_configure_XDebug

 

2.3) erster Test mit PHP

php -v

#MYSQL
php -r 'var_dump(function_exists("mysql_query"));'
php -r 'var_dump(function_exists("mysqli_query"));'

#JSON
php -r 'var_dump(function_exists("json_encode"));'

#BCMATH
php -r 'var_dump(function_exists("bcmod"));'

#MAIL
php -r 'var_dump(function_exists("mail"));'

#GD-LIB
php -r 'var_dump(function_exists("imagejpeg"));'

#SESSION
php -r 'var_dump(function_exists("session_start"));'

#SSH
php -r 'var_dump(function_exists("ssh2_connect"));'

#ZIP
php -r 'var_dump(function_exists("zip_open"));'

#GZIP
php -r 'var_dump(function_exists("gzopen"));'

#HASH
php -r 'var_dump(function_exists("hash_hmac"));'

#MCRYPT
php -r 'var_dump(function_exists("mcrypt_module_open"));'

#XML
php -r 'var_dump(function_exists("DomDocument"));'

#CURL
php -r 'var_dump(function_exists("curl_init"));'

#APC
php -r 'var_dump(function_exists("apc_store"));'

 

 2.4) PHPUnit installieren

pear config-set auto_discover 1
pear install --alldeps pear.phpunit.de/PHPUnit
pear install --alldeps phpunit/PHPUnit_SkeletonGenerator

 

3.) Netbeans (HTML5 & PHP) || PhpStorm (kostenpflichtig) || Sublime Text

Als nächsten großen Schritt werden wir uns nun eine IDE installieren hier würde ich für größere PHP-Projekte “Netbeans” bzw. “PhpStorm” empfehlen, obwohl “Sublime Text” auch seine Stärken hat und jeder der das Programm noch nicht ausprobiert hat, sollte es einmal testen!!!

 

3.1) Konfiguration

3.1.1) Netbeans

3.1.1.1) PHPUnit

Unter den Tools -> Options -> PHP -> PHPUnit-> kann man automatisch nach dem bereits installiertem PHPUnit und dem Skeleton-Generator suchen lassen und anschließend aus jeder PHP-Klasse ein PHPUnit-Template erstellen lassen. 

php_skeleton php_skeleton_confignetbeans_php_unit_beispiel

3.1.1.2) xDebug

Auch dieses Tool müssen wir einmal konfigurieren unter Tools -> Options -> PHP -> Debugging

netbeans_debug_xdebug netbeans_debug_xdebug_action

 

Tipp: Wir können unser PHP-Projekt nun nicht nur Debuggen, sondern auch Profilen. Indem wir den Parameter “XDEBUG_PROFILE=1″ per GET oder POST übermitteln und den Output anschließend z.B.: via  KCachegrind visualisieren lassen.

kcachegrind1

 

4.) “composer” - getcomposer.org

composer ist ein Manager für externe Bibliotheken (libs) und dessen Abhängigkeiten in PHP-Projekten.

 

4.1) Installation

4.1.1) Linux

curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin

 

4.1.2) Windows
https://getcomposer.org/Composer-Setup.exe

 

4.2) Repository -> https://packagist.org/

Auf der Webseite Packagist.org findet man alle Projekte, welche man ohne weitere Anpassungen in seinem Projekt verwenden kann und man kann seine eigenen Projekte einstellen (oder auch eigene Repositories verwenden, falls man diese nicht öffentlich machen will). z.B.: mein Profil -> packagist.org/users/voku/

4.3) Konfiguration

Man lege eine Datei mit dem Namen “composer.json” an und sucht sich seine zu installieren Bibliotheken aus, anschließend ein “composer install –optimize-autoloader” bzw. “composer update” und schon kann man die Bibliotheken verwenden (include von “vendor/composer/autoload.php” nicht vergessen).

 

5.) Ruby && Node.js

Bower ist auch ein Manager für externe Bibliotheken, jedoch auf JavaScript, jQuery, SASS, LESS, CSS etc. (A package manager for the web) ausgerichtet. Für die Installation muss man auch Ruby und Node.js installieren, jedoch benötigen noch andere wichtige Tools in unserer Toolchain diese Programme, daher folgt nun zuerst die kurze Installation unter Linux und die etwas ausführlichere für Windows. :P

 

5.1) Installation

5.1.1) Linux (Debian / Ubuntu)

sudo aptitude install ruby-full build-essential nodejs

 

5.1.2) Windows

Downlaod & Installation von Ruby & Node.js:

http://rubyinstaller.org/ + “DevKit”
http://nodejs.org/download/

 

Nachdem wir Ruby Installiert haben müssen wir noch das “DevKit” für Ruby herunterladen und in das Verzeichnis in welchem du Ruby installiert hat in das Unterverzeichnis “\DevKit” entpacken. – z.B.: “D:\xampp\Ruby200-x64\DevKit” und dann folgenden Befehl auf der Kommandozeile (ggf. muss man ruby noch zum PATH hinzufügen oder Windows mal wieder neu-starten)

 

ruby dk.rb init

 

Anschließend müssen wir die Datei “dk.rb” noch wie folgt anpassen:

# This configuration file contains the absolute path locations of all
# installed Rubies to be enhanced to work with the DevKit. This config
# file is generated by the 'ruby dk.rb init' step and may be modified
# before running the 'ruby dk.rb install' step. To include any installed
# Rubies that were not automagically discovered, simply add a line below
# the triple hyphens with the absolute path to the Ruby root directory.
#
# Example:
#
# ---
# - C:/ruby19trunk
# - C:/ruby192dev
#
---
- D:/xampp/Ruby200-x64

 

 … und können die Installation mit folgenden Befehlen abschließen:

ruby dk.rb review
ruby dk.rb install

 

6.) Bower” – bower.io

Zurück zu Bower, nachdem wir nun Ruby && Node.js installiert haben, können wir nun weiter Tools sehe einfach über die Kommandozeile via npm installieren lassen.

 

6.1) Installation

npm install -g bower

 

6.2) Repository -> http://bower.io/search/

 

6.3) Konfiguration

Auch Bower hat eine Konfigurationsdatei “bower.json”, in welcher man die entsprechenden Abhängigkeiten eintragen kann.

 

Tipp: Video anschauen -> https://egghead.io/lessons/bower-introduction-and-setup

 

7.) “Sass” – sass-lang.com

Sass ist ein Preprocessor für CSS, so dass man Variablen, Schleifen, Funktionen etc. in CSS nutzten kann. Große Projekte wie z.B.: Bootstrap bieten Ihren Quellcode als scss-Version an. Der Code-Style unterscheidet sich nur minimal von “normalem” CSS, wobei hier normal in Anführungszeichen stehen, da man die verschiedenen CSS-Selektoren nicht zwingend verschachteln muss. Man kann auch einfach seine bestehende CSS-Datei in eine SCSS-Datei umbenennen und per “sass” kompilieren oder eine bestehen CSS-Datei (z.B.: test.css) per “sass-convert” Konvertieren.

sass-convert -F css -T scss css/test.css scss/test.scss

 

7.1) Installation

gem install sass

 

 7.2) Links

Basics: http://sass-lang.com/guide

Playground: http://sassmeister.com/

HowTos: http://thesassway.com/

 

7.3) Video

 

 8.) “compass” - compass-style.org

 compass ist ein Framework, welches auf sass aufbaut und dieses um CSS3-Funktionen und z.B. automatisches erstellen und aktualisieren von CSS-Sprites bietet.

 

8.1) Installation

gem install compass

 

Tipp: wenn man noch Browser unterstützen muss, welche keine Transparenzen via CSS (opacity) können, dann sollte man sich mal “compass-rgbapng” anschauen. Damit werden automatisch Fallback-Bilder (png’s) in der entsprechenden Farbe / Transparenz erstellt und im CSS eingebaut. 

 

8.2) Konfiguration

Wir starten indem wir folgende Datei anlegen -> “config.rb”

# Require any additional compass plugins here.
#require "rgbapng"

#add_import_path "vendor/bower/foundation/scss/"
#add_import_path "vendor/bower/normalize-scss/"

# Set this to the root of your project when deployed:
http_path = "/"
css_dir = "css"
sass_dir = "scss"
images_dir = "images"
javascripts_dir = "js"

# You can select your preferred output style here (can be overridden via the command line):
# output_style = :expanded or :nested or :compact or :compressed
output_style = :expanded

# To enable relative paths to assets via compass helper functions. Uncomment:
# relative_assets = true

# To disable debugging comments that display the original location of your selectors. Uncomment:
# line_comments = false
line_comments = true

# If you prefer the indented syntax, you might want to regenerate this
# project again passing --syntax sass, or you can uncomment this:
# preferred_syntax = :sass
# and then run:
# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass

  

8.3) HowTo

Nachdem wir die Konfiguration angelegt und ggf. angepasst haben, wird mit dem folgendem Befehl automatisch (bei Änderungen) die entsprechende scss-Datei in eine css-Datei kompeliert.

compass watch

 compass_watch

 

9.) “auto-prefixer” – github.com/ai/autoprefixer-rails

Anstatt die entsprechenden CSS3-Funktionen von compass zu verwernden, erscheint es mir einfacher und Sinnvoller entsprechende Vendor-Prefixes automatisch zu erstellen und genau das macht dieses Tool! Man kann es entweder selber aufrufen, in compass oder via “grunt” (dazu kommen wir gleich) integrieren.

 

9.1) Installation

gem install autoprefixer-rails

 

9.2.1) HowTo: Grunt + autoprefixer

(Auch wenn ich noch gar nicht zu grunt geschrieben habe, zeige ich schon mal wie, man dies nutzten kann.)

Als erstes wird das Plugin “grunt-autoprefixer” installiert und dann folgender Task in der Datei “Gruntfile.js” angelegt:

    autoprefixer: {
      options: {
        browsers: ['last 4 version']
      },
      multiple_files: {
        expand: true,
        flatten: true,
        src: 'css/*.css',
        dest: 'css/'
      }
    },

 

9.2.2) HowTo: compass + autoprefixer

Folgendes in die compass-Konfiguration “config.rb” einfügen:

  require 'autoprefixer-rails'

  on_stylesheet_saved do |file|
    css = File.read(file)
    File.open(file, 'w') do |io|
      io << AutoprefixerRails.process(css)
    end
  end

 

10.) “Grunt” – gruntjs.com

Grunt ist ein Task-Runner, dass heißt das Programme automatisch z.B. nach dem Speichern einer Datei ausgeführt werden können. Falls jemand das Tool noch nicht im Einsatz hat -> einfach mal Testen!!! Erst dieses Tool verknüpft alle hier vorgestellten Tools zu einer “Toolchain”. Und man ist nur noch einen Schritt davon entfernt automatisierte Tests im Browser, Live-Reload im Brower etc. zu nutzen.

 

10.1) Installation

npm install -g grunt-cli
npm install -g grunt-init

 

10.2) HowTo: Init

Entweder man legt sich selber ein entsprechendes “Gruntfile.js” (Konfiguration) und “package.json”- Datei an oder man nutzt den Befehl:

grunt-init TEMPLATE_NAME

 

10.3) Video

 

Wie im Video erklärt wird, kann man gunt, nachdem man dies einstellt hat, mit dem Befehl “grunt watch” auf Änderungen von beliebigen Dateien, beliebige Tasks ausführen lasse. In meinem Fall lasse ich z.B. bei Änderungen von “*.scss”-Dateien diese via compass in CSS compilieren, anschließend per “autoprefixer” überarbeiten, minifizieren und zum Schluss wird automatisch ein reload von dem entsprechendem Brower-Tab durchgeführt. :)

 

10.4) Plugins -http://gruntjs.com/plugins

Nachdem man ein Plugin in der Datei “package.json” eingetragen hat, kann man diese über diesen Befehl installieren: 

npm install

 

Tipp: Mit dem Plugin “matchdep” muss man die entsprechenden Plugins nicht noch in der Datei “Gruntfile.js” registrieren. 

 

PS: hier noch mein aktuelles Gruntfile + package 

 

Viel Spaß beim programmieren!!! :)

Testing PHP-Projekte von github via Travis CI

Um seine PHP-Projekte einfach mit verschiedenen PHP-Versionen zu testen, kann man z.B. “Travis CI” verwenden, dazu hier ein kleines Beispiel:

 

1.) Projekt bei github.com anlegen 

 

2.) PHP-Unit Test erstellen: z.B.: URLifyTest.php && phpunit.xml && bootstrap.php

 

$ phpunit --bootstrap bootstrap.php  URLifyTest.php
PHPUnit 4.0.4 by Sebastian Bergmann.

.....

Time: 161 ms, Memory: 3.75Mb

OK (5 tests, 23 assertions)

 

3.) Travis-Konfiguration anlegen -> “.travis.yml

 

language: php

php:
  - 5.3
  - 5.4
  - 5.5
  - 5.6

before_script:
  - composer self-update
  - composer install --no-interaction --prefer-source --dev

script:
  - phpunit --coverage-text --verbose

 

4.) Projekt bei Travis CI anlegen (https://travis-ci.org/) und schon beim nächsten “git push” wird das Projekt automatisch getestet …

 

Travis CI

Travis CI

 

 

php – die nächsten Mittwoche berechnen

“Mittwoche” klingt irgendwie falsch … ;)

for ($i = 0; $i < = 4; $i++) {
	if ($i == 0) {
		$next_wednesday[$i] = date("Y-m-d", strtotime("next Wednesday"));
	}
	else {
		$next_wednesday[$i] = date("Y-m-d", strtotime("next Wednesday", strtotime($next_wednesday[($i-1)])));
	}
}

// DEBUG
print_r($next_wednesday);

php – Regular Expression Schnipsel – Escaping “/”

Hier ein kleines Beispiel wie man die Lesbarkeit von RegEx durch den Delimiter  “#” verbessern kann … ;)

$zeichenkette = "suckup.de Informationen / test, lall / Linux / lall123";
#$suchmuster = "/^[^\/]*\/[^\/]*\/[^\/]*\/[^\/]/";
$suchmuster = "#^[^/]*/[^/]*/[^/]*/[^/]#";
preg_match($suchmuster, $zeichenkette, $treffer);
print_r($treffer);

 

Ausgabe:

Array ( [0] => suckup.de Informationen / test, lall / Linux / )

UTF-8 Byte Order Mark (BOM) in php-Dateien …

for Linux (shell):

 

BOM aus allen PHP-Dateien entfernen:

find . -type f -iname "*.php" -exec sed -i '1s/^\xEF\xBB\xBF//' {} \;

 

PHP-Dateien mit BOM anzeigen:

find . -type f -iname "*.php" -exec grep -l $'\xEF\xBB\xBF' {} \;

 

mehr Infos:

sed – suckup.de/linux/streameditor-sed

find – suckup.de/linux/find-linux

Byte Order Mark – http://de.wikipedia.org/wiki/Byte_Order_Mark

php – Regular Expression Schnipsel – Links aus -Tags

Habe zu dem Thema (“Reguläre Ausdrücke”) bereits ausführlicher geschrieben -> http://suckup.de/howto/php-howto/php-sicherheit-erhoehen-teil-2/ <- daher folgt hier einfach ein Beispiel, welches man sicherlich noch optimieren kann … :)

<?php
$lall =' lall lall123
<a style="gfsedfd;" href="http://test1.de">test
<a style="gfsedfd;" href="test2.php" target="_blank>test</a> dsadsa
<a style="gfsedfd;" href="http://test3.de" target="_blank>test</a>
dsads
';

$lall = str_ireplace("\r", '', $lall);
$lall = str_ireplace("\n", '', $lall);
$lall = str_ireplace("\t", '', $lall);
preg_match_all('/<a [^>].*href="(.*)".*>/i', $lall, $lall_new);
$allLinks = explode("</a>", $lall_new[0][0]);
foreach ($allLinks as $key => $val) {
  $val = trim($val);
  if ($val != '') {
    $data =preg_replace('/.*<a [^>].*href\s*=\s*(["\'])(.*?)\1.*>.*/i',"$2",$val);
    echo $data . "\n";
  }
}
?>
php testtest.php

http://test1.de
test2.php
http://test3.de

PHP-Sicherheit erhöhen – Teil 2

Kein Programm ist 100% sicher, aber wir wollen es potenziellen Angreifern auch nicht zu leicht machen, daher folgen ein paar Grundlegende Regeln zur Sicherheit von PHP. Ich gehe hier davon aus, dass die installierte PHP-Version auf dem aktuellen Stand ist und somit weniger Angriffsfläche bietet. -> PHP-Sicherheit erhöhen – Teil 1

1.) “register_globals” sollten deaktiviert sein!!!

Falls diese Option aktiv ist, ist das Überschreiben lokaler Variablen via GET / POST möglich z.B.:

test.php:
———

<?php 
if (!isset($test))
{
  $test = 1;
}
echo 'Der Wert von test ist: '.$test;
?>

Browser:
——–
…/test.php?test=2

Ab PHP 4.2 ist diese Option (php.ini -> register_globals = Off) jedoch bereits standardmäßig auf “Off” gesetzt.

 

2.) “Type Casting” verwenden

Casting bedeutet so viel wie Umwandeln einer Variable in einen bestimmten Type z.B. wird aus “123z” -> “123″ wenn wir dies zu einer Ganzzahl (int) casten. z.B.

test.php:
———

<?php 
$zahl = (int)$_GET['zahl'];
?>

Browser:
——–
…/test.php?zahl=123z

php.net:
——–
Type Casting -> http://de2.php.net/manual/de/language.types.type-juggling.php

 

3.) Variablen prüfen

Allgemein kann man prüfen, ob die Variablen überhaupt vorhanden/gesetzt sind.

test.php:
———

<?php 
if (empty($_GET['zahl']) { [...]
if (!isset(($_GET['zahl']) { [...]
if (!$_GET['zahl']) { [...] // Warnung ("Notice") falls "error_reporting(E_ALL)" und die Variable nicht definiert wurde

php.net:
——–
empty() -> http://php.net/manual/de/function.empty.php
isset() -> http://php.net/manual/de/function.isset.php

 

4.) Variablen “Type” prüfen

test.php:
———

<?php 
if (gettype($_GET['zahl']) == "integer") { $zahl = $_GET['zahl']; }
else { $zahl = (int) $_GET['zahl']; }
?>

Alternative: if (is_int($_GET['zahl'])) { [...]

 

5.) “Ctype” Funktionen

Es gibt noch weitere php-Module z.B. “ctype” mit denen sich Variablen überprüfen lassen, ich will jedoch als nächstes einen allgemein gültigen Ansatz via “regulären Ausdrücken” zeigen.

php.net:
——–
http://de2.php.net/manual/de/ref.ctype.php
    
    

6.) Variablen prüfen / zuschneiden via “regulären Ausdrücke”

Reguläre Ausdrücke sind Muster, mit denen Zeichenketten beschrieben werden könnten!

Wer die Syntax noch nicht im Kopf hat sollte sich einmal “The Regex Coach” anschauen -> http://weitz.de/regex-coach/

The Regex Coach

The Regex Coach

 

Zusammenfassung:
—————-

[abc] -> a oder b oder c
[^abc] -> nicht a oder b oder c
[a-z] -> von a bis z -> alle Kleinbuchstaben
[A-Z] -> von A bis Z -> alle Großbuchstaben
[a-zA-Z] -> Buchstaben

[0-9] -> von 0 bis 9 -> Ziffern
\d -> von 0 bis 9 -> Ziffern
\D -> keine Ziffer

[a-zA-Z0-9_] -> Buchstaben, Ziffern, Unterstrich
\w -> Buchstaben, Ziffern, Unterstrich
\W -> keine Buchstaben, Ziffern, Unterstrich

[\r\n\t\f]] -> Wagenrücklauf, New Line, Tabulatur, Seitenwechsel -> Leerzeichen
\s -> Leerzeichen
\S -> keine Leerzeichen

\b -> Wortanfang bzw. Wortende z.B. “/\bWort\b/”
\B -> kein Wortanfang bzw. Wortende z.B. “/\BWort\B/”

. -> ein beliebiges Zeichen (Punkt)

x{m} -> “x” muss genau “m”-Mal vorkommen
x{m,} -> “x” muss min. “m”-Mal vorkommen (Ende offen)
x{,n} -> “x” darf max. “n”-Mal vorkommen (Anfang offen)
x{m,n} -> “x” muss zwischen “m”- und “n”-Mal vorkommen
x? -> “x” kann, muss aber nicht an dieser Stelle vorkommen => x{0,1}
x* -> “x” kann kein, ein oder mehrmals an dieser Stelle vorkommen => x{0,}
x+ -> “x” kann ein oder mehrmals an dieser Stelle vorkommen => x{1,}

^ -> markiert den Beginn einer Zeichenkette
$ -> markiert das Ende einer Zeichenkette

| -> Alternative z.B. “/ae|a/”

\ -> Maskierung (Escape-Zeichen) für z.B. einen Punkt “\.”

[] -> Zusammenfassung von Mustern

() -> Zusammenfassung von Mustern + selektieren und an PHP zurückgeben

 
6.1) ein Beispiel

test.php:
———

<?php 
if((!empty($_GET['Text'])) && (preg_match("/^(T|t)est(ing*){0,1}$/",$_GET['Text'])))
{
    $variable = "OK";
} else {
    $variable = "nicht OK";
}
echo 'Der Wert ist '.$variable;
?>

Browser:
——–
…/test.php?Text=Test -> OK -> (T|t)est
…/test.php?Text=test -> OK -> test(ing){0,1} = test(ing)?
…/test.php?Text=testing -> OK -> test(ing){0,1} = test(ing)?
…/test.php?testinggggg -> OK -> g*

 

6.2) noch ein Beispiel

Hier sind nur Zahlen zugelassen …

test.php:
———

<?php 
if((!empty($_GET['Text'])) && (preg_match("/^\d+([\.,]\d+)?$/",$_GET['Text'])))
{
    $variable = "OK";
} else {
    $variable = "nicht OK";
}
echo 'Der Wert ist '.$variable;
?>

Info:
—–
/^\d+([\.,]\d+)?$/ -> ist gleich -> /^[0-9]{1,}([\.,][0-9]{1,})?$/

Browser:
——–
…/test.php?Text=1 -> OK -> [0-9]{1,}
…/test.php?Text=123456789 -> OK -> [0-9]{1,}
…/test.php?Text=1.9 -> OK -> [0-9][\.,][0-9]
…/test.php?Text=123.789 -> OK -> [0-9]{1,}[\.,][0-9]{1,}
…/test.php?Text=123,789 -> OK -> [0-9]{1,}[\.,][0-9]{1,}

 

6.3) und noch ein Beispiel

Hier schneiden wir einen Teil aus einen String aus und geben diesen aus …

test.php:
———

<?php 
$imagemap = "<map id=\"imgmap201111415460\" name=\"imgmap201111415460\"><area shape=\"rect\" alt=\"\" title=\"\" coords=\"151,58,221,148\" href=\"\" target=\"\" /></map>";

$imagemap_name = preg_replace(‘/^<map(.+)name=\”(.+)\”><area(.+)/i’, “$2″, $imagemap);

echo ‘Imagemap-Name: ‘.$imagemap_name;
?>

Ausgabe => Imagemap-Name: imgmap201111415460

Info:
—–
(.+) -> ist gleich -> (.{1,})

 

php.net:
——–
http://de3.php.net/manual/de/function.preg-replace.php

 

7.) Maskieren von Strings zur Nutzung in Datenbanken

Sobald Daten in einer Datenbank gespeichert werden, sollte man diese via “mysql_real_escape_string” bzw. “mysqli_real_escape_string” maskieren, so dass “SQL Injection Angriffe” verhindert werden.

 

php.net:
——–
http://php.net/manual/de/function.mysql-real-escape-string.php

 

8.) Ein-Weg-Verschlüsselung

Bei der Ein-Weg-Verschlüsselung wird nicht die original Eingabe, sondern ein Hash-Wert davon gespeichert z.B. md5

test.php:
———

<?php $passwort = 'mein_Pwd';
echo md5($passwort); ?>

Ausgabe: b4e28e9d7dbf6d41d6e609b3eb46fac4

Das Problem ist jedoch, dass man diese Verschlüsselung via “Brute-Force-Attacke” erraten bzw. in einer “bösen”-Datenbank ;) mit vielen Kombinationen aus md5-hash und original-Wert auslesen kann.
Daher kann man z.B. auch sha1() anstelle von md5() nutzen, was zwar den Zeitaufwand bei “Brute-Force-Attacke” erhöht, jedoch nicht die Schwachstellen der Ein-Weg-Verschlüsselung behebt.

 

php.net:
——–
http://de.php.net/manual/de/function.md5.php
http://de.php.net/manual/de/function.sha1.php

 

9.) Zwei-Wege-Verschlüsselung

Bei der Zwei-Wege-Verschlüsselung werden Daten über einen Schlüssel verschlüsselt, so dass diese auch wieder entschlüsselt werden können.

test.php:
———

<?php 
function encryptData($value){
$key = "top secret key";
$text = $value;
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$crypttext = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $text, MCRYPT_MODE_ECB, $iv);
return $crypttext;
}

function decryptData($value){
$key = “top secret key”;
$crypttext = $value;
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$decrypttext = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $crypttext, MCRYPT_MODE_ECB, $iv);
return trim($decrypttext);
}

$test = encryptData(“Dies ist ein TEST!!!”);

echo $test;
echo “<br><br>”;
echo decryptData($test);
?>

 

Algorithmus:
————
-> MCRYPT_BLOWFISH (blowfish)
-> MCRYPT_TRIPLEDES (tripledes)
-> MCRYPT_RJINDAEL_256 (rjindael-256)
-> MCRYPT_CAST_256 (cast-256)

 

Modus:
——
-> MCRYPT_MODE_ECB (electronic codebook): für kurze Zeichenketten
-> MCRYPT_MODE_CBC (cipher block chaining): zur Dateiverschlüsselung
-> MCRYPT_MODE_CFB (cipher feedback): für Byteströme, mit Verschlüsselung einzelner Bytes
-> [...]

 

php.net:
——–
http://php.net/manual/de/function.mcrypt-encrypt.php

 

Unter MySQL ist die “Zwei-Wege-Verschlüsselung” einfacher zu handhaben, es gibt nur zwei Alternativen

- AES (Advanced Encryption Standard)
- DES: TripleDES

z.B.:
AES_DECRYPT(verschluesselt,schluessel)
AES_ENCRYPT(text,schluessel)

 

dev.mysql.com:
————–
http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html

 

10.) SSL (Secure Socket Layer)

Da das HTTP-Protokoll Daten plain (unverschlüsselt) überträgt, ist eine SSL- bzw. HTTPS-Verschlüsselung immer dann sinnvoll, wenn sensible Daten übertragen werden. So können die Daten beim Transport über das Internet nicht von dritten mitgelesen (Sniffing) werden.

 

11.) Cross-Site-Scripting (XSS)

Es geht darum Code auszuführen, der von einer fremden Webseite, in die aktuelle Webseite eingeschleust wird. Es ist ein Oberbrgriff für unterschiedliche Arten (serverseitiges & clientseitiges Cross-Site-Scripting) von Angriffen.

 

wikipedia.org:
————–
http://de.wikipedia.org/wiki/Cross-Site-Scripting

 

11.1) Serverseitiges Cross-Site-Scripting

Hier wird der “böse” Code direkt auf dem Server der angegriffenen Webseite ausgeführt (z.B.: von PHP) …

… es folgt ein sehr schwerwiegender Programmierfehler, eine include & GET kombination, um serverseitiges XSS zu demonstrieren.

 

test.php:
———

<?php 
inculde($_GET['skript'];
// etc.
...
?>

Info: Clientseitiges Cross-Site-Scripting -> Hier wird der “böse” Code via Browser-Technologien (z.B. via JavaScript, ActiveX …) eingeschleust.

 

11.2) SQL Injection

 

wikipedia.org:
————–
http://de.wikipedia.org/wiki/SQL-Injection

 

Auch dies ist eine Art des serverseitiges Cross-Site-Scriptings und das Ziel des Angreifers ist die Datenbank.

 

test.php:
———

<?php 
[...]
$sql = "SELECT * FROM tabelle WHERE id=" . $id;
[...]
?>

Wenn die Variable die nun per GET, POST oder Cookie überschrieben werden kann, wird eine neue SQL-Query an die Datenbank gesendet. Dabei wird die Tatsache ausgenutzt, dass man mehrere SQL-Befehle mit
Simikolon getrennt, ausführen kann.

Gegenmaßnahmen:

-> Anführungsstriche verwenden

Anführungsstriche werden dazu verwendet um Variablen in SQL-Queries zu benutzen.

 

test.php:
———

[...] SELECT * FROM xyz WHERE id = '$Test' [...]

 

Ein Angreifer, der $Test verändert kann nicht aus den Anführungsstrichen ausbrechen, sloange $Test geparst wurde und alle ‘ mit \’ maskiert sind.
Es gibt jedoch noch weitere Möglichkeiten um sich vor solchen Angriffen zu schützen.

 

-> Keine Strings in numerischen Variablen zulassen

Die Funktion settype wandelt Variablen (var) in einen Integer (int) um:

 

test.php:
———

[...]
settype($Variable, 'integer');
[...]

 

php.net:
——–
settype -> http://www.php.net/manual/de/function.settype.php

 

-> Datenbankverbindungen mit eingeschränkten Rechten

Gehe sparsam mit der Rechtevergabe an die Web (User) um, so dass im Notfall nicht die komplette Datenbank (DROP DATABASE name) betroffen ist. ;)

 

-> Werte maskieren

Mit der Funktion mysql(i)_real_escape_string bietet PHP eine einfache Möglichkeit SQL-Befehle zu maskieren.

Hinweis: Neben dem Semikolon ist auch ein doppelter Bindestrich (Kommentar in MySQL) dazu geeignet SQL-Kommandos nach dem eingeschleusten Code abzubrechen.

 

Zusammenfassung: Wenn man generell Anführungszeichen in den SQL-Kommandos benutzt und Variablen immer maskiert, würde dies zirka wie folgt aussehen…

 

test.php:
———

[...] 
if (!isset($_GET['id'])) { $id = 0; }
else { $id = $_GET['id']; }

if (gettype($id) == “integer”) { $zahl = $id; }
else { $zahl = settype($id, ‘integer’); }

$sql = “SELECT * FROM tabelle
WHERE id=’” . mysqli_real_escape_string($zahl) . “‘
AND user=’test’
“;
[...]

Rewrite-Rules: Apache vs Nginx

Bei dem Apache Webserver wird das URL-Handling (Rewrite-Rules) via .htaccess gesteuert, sobald sich eine Datei mit diesem Namen in einem Verzeichnis befindet, werden die darin enthaltenen Befehle vom Apache umgesetzt. Da dieses Verfahren jedoch voraussetzt, dass alle Verzeichnisse zuvor auf eine solche Datei geprüft, diese anschließend eingelesen und verarbeitet werden muss, macht es Sinn wie z.B. beim Nginx Webserver diese in die Konfiguration des Webs aufzunehmen. Leider ist die Syntax und Logik dieser beiden Rewrite-Rules nicht kompatibel, daher folgt eine Einführung in dieses Thema … außerdem habe ich auf github.com/voku/ meine kompletten Konfigurationsdaten für Nginx + PHP + MySQL hochgeladen.

 

Erklärung: einfache Weiterleitung

 

Apa­che:

Redirect /altes_Verzeichnis/alte_Seite.html http://suckup.de/

 

Nginx: 

rewrite /altes_Verzeichnis/alte_Seite.html http://suckup.de/ last;

 

Falls “/altes_Verzeichnis/alte_Seite.html” hinter deiner Domain in der URL steht, wird die Anfrage auf die Domain “meine_domain.de” umgeleitet.

z.B. http://suckup.de/altes_Verzeichnis/alte_Seite.html

 

Erklärung: Domain Weiterleitung

 

Apa­che:

RewriteCond %{HTTP_HOST} ^voku-online.de$ [NC]
RewriteRule ^(.*)$ http://www.suckup.de/$1 [R=301,L]

 

%{HTTP_HOST} -> Hostname

 

Nginx: 

if ($host ~* voku-online.de) {
rewrite ^(.*)$ http://suckup.de$1 permanent;
}

 

Fall der Hostname “voku-online.de” ist, dann wird dieser zu “suckup.de” umgeschrieben und alles was hinter der ursprünglichen Hostnamen stand, wird hinter den neuen gesetzt. 

^ -> Anfang 

.* -> “.” ein beliebiges Zeichen, “*” Wiederholung => alle beliebigen Zeichen

( ) -> erstes Vorkommen der einfachen Klammern wird zur ersten Variable $1 … u.s.w.

$ -> Ende

z.B. http://voku-online.de/altes_Verzeichnis/alte_Seite.html

 

Erklärung: entferne doppelte “/”

 

Apa­che:

RewriteCond %{REQUEST_URI} ^(.*)//(.*)$
RewriteRule . %1/%2 [R=301,L]

 

 %{REQUEST_URI} -> URL ohne Parameter

 ( ) -> erstes Vorkommen der einfachen Klammern in der “RewriteCond”-Bedingung wird zur ersten Variable %1 … u.s.w.

 

Nginx: 
if ($request_uri ~* “\/\/”) {
rewrite ^(.*)$ $scheme://$host$1 permanent;
}

 

\/ -> Escapezeichen “\” vor “/”

$scheme -> http bzw. https

$host -> Hostname

permanent -> gibt den Statuscode 301 zurück

 

Erklärung: statische Dateien (.css/.js/.html) beschleunigen

 

Nginx:

## static files are served directly
location ~* \.(?:js|css|htm?|js\?ver.*|css\?ver.*)$ {
        set $betterForCache  0;

        if ($args ~* ver=(.*)$) {
                set $betterForCache  1;
        }
        if ($request_uri ~* “/wp-admin”) {
                set $betterForCache  0;
        }
        if ($betterForCache = 1) {
                rewrite ^(.*) $scheme://$host$uri? last;
        }

        gzip_static on;

        autoindex off;
        expires 1d;
        add_header Pragma public;
        # We bypass all delays in the post-check and pre-check parameters of Cache-Control. Both set to 0.
        add_header Pragma public;
        add_header Cache-Control “public, must-revalidate, proxy-revalidate, post-check=0, pre-check=0″;
        ## No need to bleed constant updates. Send the all shebang in one
        ## fell swoop.
        tcp_nodelay off;
        ## Set the OS file cache.
        open_file_cache max=3000 inactive=120s;
        open_file_cache_valid 45s;
        open_file_cache_min_uses 2;
        open_file_cache_errors off;
        break;
}

Verschachtelte if-Abfragen kann man einfach via Hilfsvariablen (z.B. $betterForCache) erstellen …

$uri -> URL ohne Parameter

z.B.: http://suckup.de/wp-content/themes/mystique/css/core.css?ver=3.3.2

 

weitere Infos:

- Nginx & HttpRewriteModule:  http://wiki.nginx.org/HttpRewriteModule

- Apache & mod_rewrite: http://httpd.apache.org/docs/current/mod/mod_rewrite.html

- Beispiel-Konfiguration (WordPress Multi: Nginx + PHP-FPM): https://github.com/voku/CONFIG–nginx—php-fpm—mysql

PHP-Sicherheit erhöhen – Teil 1

 Jeder Server welcher PHP-Skripte verarbeitet, sollte zumindest zwei Sicherheitsschlösser eingebaut haben, so dass man nicht jedem Tür & Tor öffnet. 

 

1.) suPHP oder suexec + fcgid

Wir sollten PHP-Skript nicht alle mit dem selben User-Berechtigungen (z.B. apache) laufen lassen, daher empfiehlt es sich auf kleinen Webservern suPHP und auf Webseiten mit mehr Traffic “Fast CGI” zu installieren. Alternativ kann man PHP mit “PHP-FPM” (FastCGI Process Manager) auch jeweils als eigenständigen Prozess laufen lassen. 

2.) Suhosin

Da einige PHP-Projekte nicht wirklich für Ihre Sicherheit bekannt sind, empfiehlt es sich zudem die “Suhosin” Erweiterung für PHP zu installieren. “Es wurde entworfen, um den Server und die Benutzer vor bekannten und unbekannten Fehlern in PHP-Anwendungen und im PHP-Kern zu schützen.” – Wiki

PS: auf der Webseite -> http://www.dotdeb.org <- findet man einfach zu installierende .deb-Pakete für Debian / Ubuntu in welchen die Suhosin-Erweiterung bereits integriert ist und liegt zudem als “php5-fpm” Version zur Verfügung. ;) 

 

mehr Sicherheit:

- Mod-Security und Apache

- Mod-Spamhaus und Apache

WordPress Sicherheit erhöhen

php.ini / php.net

- www.howtoforge.com | viele gute HowTo’s 

Monatsnamen / Wochentagsnamen in deutsch via PHP

“Gibt einen String zurück, der den angegebenen Formatierungs-Merkmalen entspricht. Dabei wird der gegebene Timestamp/ Zeitstempel oder – falls dieser fehlt – die momentane lokale Zeit benutzt. Der Monats- und Wochentagsname wird entsprechend des per setlocale() eingestellten Wertes gesetzt.” - php.net/manual/de/function.strftime.php

 

setlocale(LC_TIME, "de_DE");
echo strftime("%A"); // Wochentagsname
echo strftime("%B"); // Monatsname