<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>theCurity</title>
	<atom:link href="http://www.theCurity.de/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.theCurity.de</link>
	<description>Tipps und Tricks für sicherere Programmierung</description>
	<lastBuildDate>Fri, 25 Apr 2008 13:40:44 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Alternative zu URL Parametern</title>
		<link>http://www.theCurity.de/2008/04/25/alternative-zu-url-parametern/</link>
		<comments>http://www.theCurity.de/2008/04/25/alternative-zu-url-parametern/#comments</comments>
		<pubDate>Fri, 25 Apr 2008 13:39:58 +0000</pubDate>
		<dc:creator>kai</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Parameter]]></category>

		<guid isPermaLink="false">http://www.theCurity.de/?p=90</guid>
		<description><![CDATA[Wem Argumente an der URL nicht SEO freundlich genug sind:
/abc.php?key=value
der kann eine Variante in dieser Art vorbauen:
if(isset($_SERVER['PATH_INFO'])) {
$ap = explode(&#8216;/&#8217;, $_SERVER['PATH_INFO']); // in key/value pairs zerlegen
array_shift($ap);
while(count($ap) &#62;= 2) {
$key = array_shift($ap);
$value = array_shift($ap);
$_GET[$key] = $value;
} // while
} // if PATH_INFO
Dann geht die gleiche URL zusätzlich auch als
/abc.php/key/value
Sieht gleich viel hübscher aus. Vorsicht allerdings bei relativen [...]]]></description>
			<content:encoded><![CDATA[<p>Wem Argumente an der URL nicht SEO freundlich genug sind:</p>
<blockquote><p>/abc.php?key=value</p></blockquote>
<p>der kann eine Variante in dieser Art vorbauen:</p>
<blockquote><p>if(isset($_SERVER['PATH_INFO'])) {<br />
$ap = explode(&#8216;/&#8217;, $_SERVER['PATH_INFO']); // in key/value pairs zerlegen<br />
array_shift($ap);</p>
<p>while(count($ap) &gt;= 2) {<br />
$key = array_shift($ap);<br />
$value = array_shift($ap);<br />
$_GET[$key] = $value;<br />
} // while<br />
} // if PATH_INFO</p></blockquote>
<p>Dann geht die gleiche URL zusätzlich auch als</p>
<blockquote><p>/abc.php/key/value</p></blockquote>
<p>Sieht gleich viel hübscher aus. Vorsicht allerdings bei relativen Links innerhalb der Seite! Die müssen daraufhin alle Absolut zur Wurzel angegeben werden.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.theCurity.de/2008/04/25/alternative-zu-url-parametern/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Umlaute Zweilerlei</title>
		<link>http://www.theCurity.de/2008/04/23/umlaute-zweilerlei/</link>
		<comments>http://www.theCurity.de/2008/04/23/umlaute-zweilerlei/#comments</comments>
		<pubDate>Wed, 23 Apr 2008 09:29:53 +0000</pubDate>
		<dc:creator>kai</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[umlaute]]></category>

		<guid isPermaLink="false">http://www.theCurity.de/?p=89</guid>
		<description><![CDATA[Baim Auslesen von EXIF-Informationen kann man auf beliebige Kodierungen von Umlauten stoßen. Die drei meisten Fälle sind so abgefangen:
if(isset($ea['ImageDescription'])) {
$caption = $ea['ImageDescription'];
$encoding = mb_detect_encoding($caption, &#8216;ASCII, UTF-8, ISO-8859-1&#8242;);
if(&#8216;UTF-8&#8242; == $encoding)
$caption = utf8_decode($caption);
}
Damit werden ISO und UTF Umlaute gleich dargestellt.
]]></description>
			<content:encoded><![CDATA[<p>Baim Auslesen von EXIF-Informationen kann man auf beliebige Kodierungen von Umlauten stoßen. Die drei meisten Fälle sind so abgefangen:</p>
<blockquote><p>if(isset($ea['ImageDescription'])) {<br />
$caption = $ea['ImageDescription'];<br />
$encoding = mb_detect_encoding($caption, &#8216;ASCII, UTF-8, ISO-8859-1&#8242;);<br />
if(&#8216;UTF-8&#8242; == $encoding)<br />
$caption = utf8_decode($caption);<br />
}</p></blockquote>
<p>Damit werden ISO und UTF Umlaute gleich dargestellt.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.theCurity.de/2008/04/23/umlaute-zweilerlei/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>binäre Dateien und readfile</title>
		<link>http://www.theCurity.de/2008/03/31/binare-dateien-und-readfile/</link>
		<comments>http://www.theCurity.de/2008/03/31/binare-dateien-und-readfile/#comments</comments>
		<pubDate>Mon, 31 Mar 2008 11:13:49 +0000</pubDate>
		<dc:creator>kai</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[PDF]]></category>

		<guid isPermaLink="false">http://www.theCurity.de/2008/03/31/binare-dateien-und-readfile/</guid>
		<description><![CDATA[Wer sich immer wieder über PDF Dateien ärgert, die angeblich defekt vom PHP erzeugt wurden, auf dem Server abgelegt jedoch intakt sind: readfile wandelt anscheinen NULL Bytes in Blanks um im Datenstrom. Ein Parameter für binäres Verhalten ist der aktuellen Doku erst mal nicht zu entnehmen. Daher geht es erst mal nur so:
$pdf = file_get_contents($tmppdf,FILE_BINARY);
echo [...]]]></description>
			<content:encoded><![CDATA[<p>Wer sich immer wieder über PDF Dateien ärgert, die angeblich defekt vom PHP erzeugt wurden, auf dem Server abgelegt jedoch intakt sind: readfile wandelt anscheinen NULL Bytes in Blanks um im Datenstrom. Ein Parameter für binäres Verhalten ist der aktuellen Doku erst mal nicht zu entnehmen. Daher geht es erst mal nur so:</p>
<blockquote><p>$pdf = file_get_contents($tmppdf,FILE_BINARY);<br />
echo $pdf;</p></blockquote>
<p>Wenn die Datei aber größer ist, kann die $pdf Variable zu viel Speicher brauchen. Dann muß leider eine eigene Schleife her:</p>
<blockquote><p>$file = fopen($tmppdf, &#8216;rb&#8217;);<br />
while(!feof($file)) {<br />
echo fread($file, 2048);<br />
}<br />
fclose($file);</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.theCurity.de/2008/03/31/binare-dateien-und-readfile/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cachen verboten</title>
		<link>http://www.theCurity.de/2008/03/27/cachen-verboten/</link>
		<comments>http://www.theCurity.de/2008/03/27/cachen-verboten/#comments</comments>
		<pubDate>Thu, 27 Mar 2008 10:28:31 +0000</pubDate>
		<dc:creator>kai</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Cache]]></category>

		<guid isPermaLink="false">http://www.theCurity.de/2008/03/27/cachen-verboten/</guid>
		<description><![CDATA[Soweit scheint dieses Stück Code genau das zu machen was es soll. Eine Datei wird generiert und landet immer frisch auf dem Tisch:
    header(&#8216;Content-Type: image/png&#8217;);
header(&#8216;Content-Disposition: attachment; filename=&#8221;flyer.png&#8221;&#8216;);
header(&#8216;Content-Transfer-Encoding: binary&#8217;);
header(&#8216;Content-Length: &#8216; . filesize($tmpfile));
header(&#8216;Cache-Control: no-store, no-cache, must-revalidate, proxy-revalidate, private&#8217;); // HTTP/1.1
header(&#8216;Cache-Control: pre-check=0, post-check=0, max-age=0&#8242;, false);
header(&#8216;Last-Modified: &#8216;.gmdate(&#8216;D, d M Y H:i:s&#8217;) . &#8216; GMT&#8217;);
header(&#8216;Expires: &#8216; . gmdate(&#8216;D, d M [...]]]></description>
			<content:encoded><![CDATA[<p>Soweit scheint dieses Stück Code genau das zu machen was es soll. Eine Datei wird generiert und landet immer frisch auf dem Tisch:</p>
<blockquote><p>    header(&#8216;Content-Type: image/png&#8217;);<br />
header(&#8216;Content-Disposition: attachment; filename=&#8221;flyer.png&#8221;&#8216;);<br />
header(&#8216;Content-Transfer-Encoding: binary&#8217;);<br />
header(&#8216;Content-Length: &#8216; . filesize($tmpfile));<br />
header(&#8216;Cache-Control: no-store, no-cache, must-revalidate, proxy-revalidate, private&#8217;); // HTTP/1.1<br />
header(&#8216;Cache-Control: pre-check=0, post-check=0, max-age=0&#8242;, false);<br />
header(&#8216;Last-Modified: &#8216;.gmdate(&#8216;D, d M Y H:i:s&#8217;) . &#8216; GMT&#8217;);<br />
header(&#8216;Expires: &#8216; . gmdate(&#8216;D, d M Y H:i:s&#8217;) . &#8216; GMT&#8217;);<br />
header(&#8216;Pragma: no-cache&#8217;);<br />
header(&#8216;ETag: &#8216; . session_id() . &#8216;_&#8217; . time());</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.theCurity.de/2008/03/27/cachen-verboten/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Administration via URL</title>
		<link>http://www.theCurity.de/2008/03/10/administration-via-url/</link>
		<comments>http://www.theCurity.de/2008/03/10/administration-via-url/#comments</comments>
		<pubDate>Mon, 10 Mar 2008 09:34:24 +0000</pubDate>
		<dc:creator>kai</dc:creator>
				<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://www.theCurity.de/2008/03/10/administration-via-url/</guid>
		<description><![CDATA[Kleine Ursache, große Wirkung:
Ein kleines Script auf dem Server soll einmalig an die User eine eMail schreiben. Man ruft es im Browser auf, es versendet, schreibt noch brav ein wenig Logging auf den Schirm und ist fertig. Toll!
Leider: Im Browser war ein Alexa-Plugin installiert (die google Toolbar wäre wohl der gleiche Fall), dadurch lernt eine [...]]]></description>
			<content:encoded><![CDATA[<p>Kleine Ursache, große Wirkung:</p>
<p>Ein kleines Script auf dem Server soll einmalig an die User eine eMail schreiben. Man ruft es im Browser auf, es versendet, schreibt noch brav ein wenig Logging auf den Schirm und ist fertig. Toll!</p>
<p>Leider: Im Browser war ein Alexa-Plugin installiert (die google Toolbar wäre wohl der gleiche Fall), dadurch lernt eine Suchmaschine diesen Link und besucht ihn Tage später wieder.</p>
<p>Resultat: Die Mails werden erneut verschickt und die Ausgabe gelangt auch noch in die Trefferliste einer Suchmaschine.</p>
<p>Lösung:</p>
<ul>
<li>Nie eine Aktion schon im GET anstoßen, sondern lieber eine Vorseite bauen, die einen POST erzeugt.</li>
<li>Administration mit Kennwort schützen</li>
<li>Administration nur aus dem Büro-IP-Nummernkreis erlauben</li>
<li>Logging Ausgaben im Detail lokal auf der Platte speichern und nicht im Browser zeigen</li>
<li>Aktion und Ergebnisausgabe mit getrennten URLs, also stilles Script mit Weiterleitung auf das Ergebnis</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.theCurity.de/2008/03/10/administration-via-url/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Selbsttest</title>
		<link>http://www.theCurity.de/2007/11/08/selbsttest/</link>
		<comments>http://www.theCurity.de/2007/11/08/selbsttest/#comments</comments>
		<pubDate>Thu, 08 Nov 2007 09:56:00 +0000</pubDate>
		<dc:creator>kai</dc:creator>
				<category><![CDATA[C]]></category>

		<guid isPermaLink="false">http://www.theCurity.de/2007/11/08/selbsttest/</guid>
		<description><![CDATA[Für das sichere Gefühl nach dem Compilieren:
make test
Sollte man, wenn es schon vorhanden ist, immer ausführen! Gerade bei z.B. MySQL ist es beruhigend zu sehen, daß die meisten Features dadurch entweder als passed bestanden werden oder halt bei skipped einfach nicht zutreffen, aber wenigstens ist kein failed dabei.
Nur schade, daß MySQL nicht gerade hilfreiche Meldungen [...]]]></description>
			<content:encoded><![CDATA[<p>Für das sichere Gefühl nach dem Compilieren:</p>
<blockquote><p><strong>make test</strong></p></blockquote>
<p>Sollte man, wenn es schon vorhanden ist, immer ausführen! Gerade bei z.B. MySQL ist es beruhigend zu sehen, daß die meisten Features dadurch entweder als <strong>passed</strong> bestanden werden oder halt bei <strong>skipped</strong> einfach nicht zutreffen, aber wenigstens ist kein <strong>failed</strong> dabei.</p>
<p>Nur schade, daß MySQL nicht gerade hilfreiche Meldungen liefert, wenn man als root den Test starten wollte. Erst in den Tiefen der Logfiles wird dann erwähnt, daß es als root einfach nicht läuft. Im Frontend kommt nur was von gestorbenen Prozessen. Also besser als mysql User testen, dann geht es.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.theCurity.de/2007/11/08/selbsttest/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reload sichere Formulare</title>
		<link>http://www.theCurity.de/2007/10/18/reload-sichere-formulare/</link>
		<comments>http://www.theCurity.de/2007/10/18/reload-sichere-formulare/#comments</comments>
		<pubDate>Thu, 18 Oct 2007 11:19:16 +0000</pubDate>
		<dc:creator>kai</dc:creator>
				<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://www.theCurity.de/2007/10/18/reload-sichere-formulare/</guid>
		<description><![CDATA[Ein beliebter Fehler ist, einen Reload einer Webseite nicht im Workflow einzuplanen. Am besten pflegeleicht wird es, wenn man Aktion und Reaktion auf verschiedene URLs und Dateien verteilt. Als Beispiel mal ein Kontaktformular:

kontakt.php
kontakt_do.php
kontakt_done.php
kontakt_err.php

Hier wird die Aufgabeverteilung wie folgt gestreut:

Darstellen des Formulars ohne Interaktion mit einem Backend wie Mailer oder Datenbank,
Empfang der Formulardaten via POST im [...]]]></description>
			<content:encoded><![CDATA[<p>Ein beliebter Fehler ist, einen Reload einer Webseite nicht im Workflow einzuplanen. Am besten pflegeleicht wird es, wenn man Aktion und Reaktion auf verschiedene URLs und Dateien verteilt. Als Beispiel mal ein Kontaktformular:</p>
<ol>
<li>kontakt.php</li>
<li>kontakt_do.php</li>
<li>kontakt_done.php</li>
<li>kontakt_err.php</li>
</ol>
<p>Hier wird die Aufgabeverteilung wie folgt gestreut:</p>
<ol>
<li>Darstellen des Formulars ohne Interaktion mit einem Backend wie Mailer oder Datenbank,</li>
<li>Empfang der Formulardaten via POST im <strong>do</strong> Script, Verarbeitung und Prüfung, sowie Absenden oder Speichern des Kontaktwunsches. Danach eine Weiterleitung an diese Ergebnisseiten:</li>
<li>Im Erfolgsfall wird die Seite <strong>done</strong> aufgerufen. Wer hier ein reload macht, stößt keine neue Aktion mehr an.</li>
<li>Im Fehlerfall (auch der ist vorzusehen) kann auf die <strong>err</strong> Seite gesprungen werden. Auch hier wird ein Reload die fehlgeschlagene Aktion nicht neu ausführen.</li>
</ol>
<p>So ist es übersichtlich und läuft  hier ohne Probleme auch bei hoher Last und unerzogenen Usern.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.theCurity.de/2007/10/18/reload-sichere-formulare/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Vergleich mit Konstanten</title>
		<link>http://www.theCurity.de/2007/10/16/vergleich-mit-konstanten/</link>
		<comments>http://www.theCurity.de/2007/10/16/vergleich-mit-konstanten/#comments</comments>
		<pubDate>Tue, 16 Oct 2007 06:35:09 +0000</pubDate>
		<dc:creator>kai</dc:creator>
				<category><![CDATA[Allgemein]]></category>

		<guid isPermaLink="false">http://tc.kaikretschmann.de/?p=82</guid>
		<description><![CDATA[Immer die Konstante links der Komparators halten, falls man mal aus Versehen eine Zuweisung draus macht.
if 13 == Pech then
]]></description>
			<content:encoded><![CDATA[<p>Immer die Konstante links der Komparators halten, falls man mal aus Versehen eine Zuweisung draus macht.</p>
<blockquote><p>if 13 == Pech then</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.theCurity.de/2007/10/16/vergleich-mit-konstanten/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Prepared Statements</title>
		<link>http://www.theCurity.de/2007/10/16/prepared-statements/</link>
		<comments>http://www.theCurity.de/2007/10/16/prepared-statements/#comments</comments>
		<pubDate>Tue, 16 Oct 2007 06:34:31 +0000</pubDate>
		<dc:creator>kai</dc:creator>
				<category><![CDATA[Allgemein]]></category>

		<guid isPermaLink="false">http://tc.kaikretschmann.de/?p=81</guid>
		<description><![CDATA[Wenn möglich alle extern gelieferten Parameter via Prepared Statements einbinden. SQL Injection wird so unwarscheinlicher.
]]></description>
			<content:encoded><![CDATA[<p>Wenn möglich alle extern gelieferten Parameter via Prepared Statements einbinden. SQL Injection wird so unwarscheinlicher.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.theCurity.de/2007/10/16/prepared-statements/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Datenbank Zugriffsrechte</title>
		<link>http://www.theCurity.de/2007/10/16/datenbank-zugriffsrechte/</link>
		<comments>http://www.theCurity.de/2007/10/16/datenbank-zugriffsrechte/#comments</comments>
		<pubDate>Tue, 16 Oct 2007 06:34:12 +0000</pubDate>
		<dc:creator>kai</dc:creator>
				<category><![CDATA[Allgemein]]></category>

		<guid isPermaLink="false">http://tc.kaikretschmann.de/?p=80</guid>
		<description><![CDATA[Der Datenbankbenutzer mit dem das Backend an eine DB sich anmeldet braucht nur minimale Rechte wie INSERT, UPDATE, SELECT und ggf. DELETE zu besitzen. Er braucht keine CREATE, FILE oder DROP Rechte!
]]></description>
			<content:encoded><![CDATA[<p>Der Datenbankbenutzer mit dem das Backend an eine DB sich anmeldet braucht nur minimale Rechte wie INSERT, UPDATE, SELECT und ggf. DELETE zu besitzen. Er braucht keine CREATE, FILE oder DROP Rechte!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.theCurity.de/2007/10/16/datenbank-zugriffsrechte/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
