<?xml version="1.0" encoding="ISO-8859-1"?>
<rss version="2.0">
	<channel>
		<docs>http://blogs.law.harvard.edu/tech/</docs>
		<description>RSS-Feed from https://potassium.1338.at/</description>
		<link>https://potassium.1338.at/</link>
		<title>Potassiums Weblog - One step ahead of the average nerd - Kategorie: PHP-Entwicklung</title>
		<ttl>30</ttl>
		
<item>
	<title><![CDATA[Synchronize Android Calendar without Google Calendar with iCal-Files using SabreDav a CalDav server [update]]]></title>
	<description><![CDATA[I was searching for solutions for using my existing iCal-calendars from Lightning/Sunbird with my new HTC Desire WITHOUT using the Google-calender (respectively without sending them your private data).<br />
<br />
To create the calendars on the Adroid I couldn't find any other way then, just to create them at your Google-Account, sync them and afterwards disable the calendar-syncing at your Android-Phone.<br />
<br />
Now you have to install yourself a CalDav-Server. The simplest server I found, for configuring and installing was <a href="http://code.google.com/p/sabredav/" target='_blank'>SabreDav</a>. Just get a <a href="http://www.apachefriends.org/en/xampp.html" target='_blank'>XAMPP</a> running on your machine and installing SabreDav. <br />
<br />
Since there is no out-of-the-box possibility to import your iCal-files in the new CalDav server I wrote myself a little script, that does that for me. I know the code is messy and very imperformant, but it works and that is all it counts for me, at the moment.<br />
<br />
<fieldset><legend>Code</legend><br />
<?php<br />
/* iCal-import script for SabreDav CalDav Server<br />
 * Coder: Daniel Bomze - daniel.bomze {att} gmx {dottt} net<br />
 * Last changes: 04.01.2011<br />
 * Please let me know if you find bugs, failures or just have code-improvements<br />
 */<br />
<br />
//the user in which the calendars should be created, the have to exists and start with 'pricipals/'<br />
$principalUser = "principals/admin";<br />
<br />
// settings<br />
date_default_timezone_set('Europe/Berlin');<br />
<br />
// If you want to run the SabreDAV server in a custom location (using mod_rewrite for instance)<br />
// You can override the baseUri here.<br />
// $baseUri = '/';<br />
<br />
/* Database */<br />
$pdo = new PDO('sqlite:data/db.sqlite');<br />
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);<br />
<br />
//Mapping PHP errors to exceptions<br />
function exception_error_handler($errno, $errstr, $errfile, $errline ) {<br />
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);<br />
}<br />
set_error_handler("exception_error_handler");<br />
<br />
// Files we need<br />
require_once 'lib/Sabre/autoload.php';<br />
<br />
// The object tree needs in turn to be passed to the server class<br />
$server = new Sabre_CalDAV_Server($pdo);<br />
<br />
if (isset($baseUri))<br />
    $server->setBaseUri($baseUri);<br />
<br />
$backend = new Sabre_CalDAV_Backend_PDO($pdo);<br />
$calendars = $backend->getCalendarsForUser($principalUser);<br />
foreach($calendars as $calendar){<br />
	$calendars[$calendar["uri"]] = $calendar;<br />
}<br />
$dir_handle = opendir(".");<br />
$calendar_options = array("VEVENT","VTODO", "{DAV:}description" => "");<br />
$prepend_data = "BEGIN:VCALENDAR<br />
PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN<br />
VERSION:2.0<br />
";<br />
$append_data = "<br />
END:VCALENDAR<br />
";<br />
while($file = readdir($dir_handle)){<br />
	if(strrchr($file, ".") == ".ics"){<br />
		$calendar_uri = substr($file, 0, strrpos($file, "."));<br />
		$calendar_options["{DAV:}displayname"] = $calendar_uri;<br />
		if(!array_key_exists($calendar_uri, $calendars)){<br />
			$calendar_id = $backend->createCalendar($principalUser, $calendar_uri, $calendar_options);<br />
		}<br />
		else{<br />
			$calendar_id = $calendars[$calendar_uri]["id"];<br />
		}<br />
		$ics_file = file_get_contents($file);<br />
<br />
		$count_matches = preg_match_all("/(BEGIN\:VEVENT)+?(.*?)(END\:VEVENT)+?/is",$ics_file, $matches,PREG_SET_ORDER );<br />
		foreach($matches as $match){<br />
			$UID = trim(preg_replace("/(.*?)\sUID:(.*?)\n(.*)/ims", "$2", $match[0])).".ics";<br />
			$date = preg_replace("/(.*?)\sLAST-MODIFIED:(.*?)\s(.*)/ims", "$2", $match[0]);<br />
			$unixtimestamp = mktime(substr($date,9,2), substr($date,11,2), substr($date,13,2), substr($date,4,2), substr($date,6,2), substr($date,0,4));<br />
			$calendar_obj = $backend->getCalendarObject($calendar_id, $UID);<br />
			if($calendar_obj === FALSE){<br />
				$backend->createCalendarObject($calendar_id, $UID, $prepend_data.$match[0].$append_data);<br />
			}<br />
			else{<br />
				if($calendar_obj["lastmodified"] <= $unixtimestamp){<br />
					$backend->updateCalendarObject($calendar_id, $UID, $prepend_data.$match[0].$append_data);<br />
				}<br />
				else{<br />
					//entry in online-calender is newer than the one in ics-file, so do not update it<br />
				}<br />
			}<br />
			<br />
		}<br />
	}<br />
}<br />
echo "all files were imported";<br />
?><br />
<br />
<br />
</fieldset><br />
<br />
Just put this code in a file in the directory where your SabreDav-Server is located and put the .ics files in the same directory.<br />
<br />
<strong>You eventually need to increase the max_execution_time in the php.ini file</strong><br />
A value of 600 worked fine for me.<br />
<br />
If your iCal-files were imported to your CalDav serer you can synchronize the your Android phone with the server. To synchronize your Android calendar with your new CalDav-Server you will have to install this tiny app: <a href="http://de.androlib.com/android.application.com-hypermatix-app-calendarsync-txxF.aspx" target='_blank'>Calendar (CalDAV) Sync</a><br />
<br />
When configuring the app on your phone your URL to the calendar could look like this<br />
<br />
<fieldset><legend>Code</legend>http://192.168.0.1/dav/calendarserver.php/calendars/admin/Privat/</fieldset><br />
<br />
Also you can access the CalDav server via Lightning/Sunbird via:<br />
New calendar->On the network->select CalDav and enter the URL to your calender. Don't forget the trailing slash! For me the URL looked for example like this<br />
<fieldset><legend>Code</legend>http://192.168.0.1/dav/calendarserver.php/calendars/admin/Privat/</fieldset><br />
<br />
<strong>Explaination:</strong> <br />
<em>192.168.0.1</em> is the IP of the computer where der xampp is runing, <br />
<em>dav</em> is the directory where I installed my SabreDav server, <br />
<em>calendarserver.php</em> is the SabreDav calendar-server file. <br />
<em>calendars</em>, the virtual directory calandars is for accessing (who got it? ;-)) the calendars, <br />
<em>admin</em> is the principal/user and <br />
<em>Privat</em> is the name of the calandar as i created it. <br />
<em>Be sure to have the trailing slash at the end of the URL or this won't work properly.</em><br />
<br />
Tip: If you wan't to synchronize your phone from outside the LAN you have to use a <a href="http://de.wikipedia.org/wiki/Virtual_Private_Network" target='_blank'>VPN</a> or a public webserver.<br />
<br />
If you have questions feel free to contact me via comments, email or jabber.<br />
<br />
<strong>Update</strong>:<br />
Added the trim() function to the UID-detection, because if synchronizing without them, apache sometimes can't find the ics-files.<br />
]]></description>
	<guid>https://potassium.1338.at/index.php?id=1102#vPyX3u</guid>
	<link>https://potassium.1338.at/index.php?id=1102</link>
	<pubDate>Tue, 04 Jan 2011 14:36:00 +0100</pubDate>
	<author>potassium</author>
	<category><![CDATA[Programmieren, PHP-Entwicklung, HTC Desire, Android]]></category>
</item>
<item>
	<title><![CDATA[Apache CGI Version local Non Thread Safe Version VC6]]></title>
	<description><![CDATA[Just to remember the next time...]]></description>
	<guid>https://potassium.1338.at/index.php?id=1051#</guid>
	<link>https://potassium.1338.at/index.php?id=1051</link>
	<pubDate>Wed, 29 Sep 2010 21:09:00 +0200</pubDate>
	<author>potassium</author>
	<category><![CDATA[Programmieren, PHP-Entwicklung]]></category>
</item>
<item>
	<title><![CDATA[PHP: empty("0") != empty("00")]]></title>
	<description><![CDATA[Die PHP-Funktion <a href="http://at.php.net/manual/en/function.empty.php" target='_blank'>empty()</a> gibt Auskunft darüber, ob die angegebe Variable <em>leer</em> ist. Folgendes weiß das Manual dazu zu sagen<br />
<fieldset class="quotediv"><legend>Zitat</legend>Returns FALSE if var has a non-empty and non-zero value. <br />
<br />
The following things are considered to be empty: <br />
"" (an empty string)<br />
0 (0 as an integer)<br />
"0" (0 as a string)<br />
NULL<br />
FALSE<br />
array() (an empty array)<br />
var $var; (a variable declared, but without a value in a class)</fieldset><br />
<br />
Man sollte nun doch meinen, dass folgende beide Code-Snippets das gleiche Ergebnise erzeugen: nämlich <em>true</em>.<br />
<fieldset><legend>Code</legend><br />
<?php<br />
$var = "0";<br />
var_dump(empty($var));<br />
?><br />
</fieldset><br />
<fieldset><legend>Code</legend><br />
<?php<br />
$var = "00";<br />
var_dump(empty($var));<br />
?><br />
</fieldset><br />
Dem ist aber nicht so.<br />
Das erste snippet gibt folgendes wiede<br />
<fieldset class="quotediv"><legend>Zitat</legend>bool(true)</fieldset><br />
das zweite Snippet<br />
<fieldset class="quotediv"><legend>Zitat</legend>bool(false)</fieldset><br />
<br />
Um darauf zu kommen, habe ich gerade zwei Stunden meines Lebens verschwendet...Dankeschön!<br />
]]></description>
	<guid>https://potassium.1338.at/index.php?id=1033#</guid>
	<link>https://potassium.1338.at/index.php?id=1033</link>
	<pubDate>Thu, 19 Aug 2010 22:06:00 +0200</pubDate>
	<author>potassium</author>
	<category><![CDATA[Programmieren, PHP-Entwicklung]]></category>
</item>
<item>
	<title><![CDATA[Fix: serialize() und unserialize() fail with data containing single or double quotes [update]]]></title>
	<description><![CDATA[When serialize()ing an array containing the data of the last created blogpost there was no error at first.<br />
But if the data were fetched from the database and the script tried to unserialize() them the following error occured:<br />
<fieldset class="quotediv"><legend>Zitat</legend>Notice: unserialize() [function.unserialize]: Error at offset 51 of 66 bytes in somefile.php</fieldset><br />
So why is this?<br />
Lets say you have an array with 3 indizes containing 2 strings and one integer.<br />
<br />
<fieldset><legend>Code</legend>$somearray[0] = "test";<br />
$somearray[1] = "he hasn\'t eaten anything";<br />
$somearray[2] = 36;</fieldset><br />
As you can see the single quote in the second array-element is escaped by a backslash.<br />
If you now serialize the data you get the following string<br />
<fieldset><legend>Code</legend>a:3:{i:0;s:4:"test";i:1;s:25:"<font color="red">he hasn\'t eaten anything</font>";i:2;i:36;}<br />
</fieldset><br />
If this string is now written to the database the backslashes disappears and the field contains the following data:<br />
<fieldset><legend>Code</legend>a:3:{i:0;s:4:"test";i:1;s:25:"<font color="red">he hasn't eaten anything</font>";i:2;i:36;}<br />
</fieldset><br />
As the considerate reader might have discovered the length of the highlighted string was first 25 characters and is after inserting into the database 24 characters long. <br />
So if PHP tries to unserialize the string it thinks it has to read 25 characters but there are only 24. This throws the above error.<br />
<br />
So how can you circumvent this?<br />
<fieldset><legend>Code</legend>$somearray[0] = "test";<br />
$somearray[1] = "he hasn\'t eaten anything";<br />
$somearray[2] = 36;<br />
foreach($somearray as $key=>$value){<br />
$somearray[$key] = stripslashes($value);<br />
}<br />
$serialized_data = addslashes(serialize($somearray));</fieldset><br />
<br />
So the backslashes are removed before serializing the data and added afterwards to prevent database malfunctions or errors.]]></description>
	<guid>https://potassium.1338.at/index.php?id=862#</guid>
	<link>https://potassium.1338.at/index.php?id=862</link>
	<pubDate>Thu, 27 Aug 2009 22:33:00 +0200</pubDate>
	<author>potassium</author>
	<category><![CDATA[Software-Entwicklung, Programmieren, PHP-Entwicklung]]></category>
</item>
<item>
	<title><![CDATA[PotaBlog 2.0 [update]]]></title>
	<description><![CDATA[Bwah, derzeit arbeite ich grad am Release 2.0 von PotaBlog. Da sich einige Dinge grundlegend verändern, ist es ein weitaus größerer Aufwand, als erwartet.<br />
<br />
Bin gerade 3 Stunden gesessen und hab nur Texte aus Templates in Variablen kopiert und diese Texte ins Englische übersetzt -_-<br />
<br />
Wünsche eine gute Nacht!]]></description>
	<guid>https://potassium.1338.at/index.php?id=772#</guid>
	<link>https://potassium.1338.at/index.php?id=772</link>
	<pubDate>Fri, 03 Apr 2009 03:55:00 +0200</pubDate>
	<author>potassium</author>
	<category><![CDATA[Software-Entwicklung, Weblog, Programmieren, PHP-Entwicklung]]></category>
</item>
<item>
	<title><![CDATA[Barcode Interleaved 2 of 5 selfmade [update]]]></title>
	<description><![CDATA[Da ich für ein Projekt Barcodes der Form <em>Interleaved 2 of 5</em> brauche und die Schriftarten dafür erst ab 139 $ zu bekommen sind hab ich beschlossen das mit PHP und GD-Library selbst zu lösen.<br />
<br />
Mit Hilfe von <a href="http://www.spatula.net/proc/barcode/i25.src" target='_blank'>Nick Johnsons</a> Site über Barcodes und spezifisch über I2O5 war es möglich das zu bekommen, was ich erreichen wollte:<br />
<br />
Die Zahl 0930000153 wird umgewandelt in<br />
<img alt='Picture' src='https://potassium.1338.at/upload/pictures/barcode_0930000153_23.02.2009.jpg' border='0' class='blogged_image' /><br />
<br />
Und sieht auch noch aus wie das Original, das ich nachzumachen versuchte.<br />
<br />
Gelöst hab ich es wie folgt:<br />
Die umzuwandelnde Zahl wird in 2 Zeichen lange Strings aufgespalten und diese in ein Array geschrieben. In einem anderen Array, dass 2 Indizes hat [0-9] und [0-4] steht jeweils drinnen ob es als ein breiter oder ein dünner Strich dargestellt werden soll - nach folgendem Schema.<br />
<fieldset><legend>Code</legend>0: nnwwn<br />
1: wnnnw<br />
2: nwnnw<br />
3: wwnnn<br />
4: nnwnw<br />
5: wnwnn<br />
6: nwwnn<br />
7: nnnww<br />
8: wnnwn<br />
9: nwnwn</fieldset><br />
Wobei n für narrow als dünn und w für wide also dick steht.<br />
Nun wird eine Schleife gestartet die von 0 bis 4 durchläuft und dabei wird der die erste Ziffer der 2 Ziffern die vorher in ein Array geschrieben wurden als Index genommen und die Schleifenzähler-Variable für den 2 Index. <br />
Dann wird je nach Inhalt des 2. Arrays entweder ein dünner Senkrechter Strich, ein dünner Abstand, ein dicker Strich oder ein dicker Abstand in das Bild geschrieben.<br />
Mit der 2. Zahl wird danach ebenso fortgefahren.<br />
<br />
<fieldset><legend>Code</legend>//create image<br />
$width = "300";<br />
	$height = "40";<br />
	$img = ImageCreatetruecolor($width, $height)  or die("Cannot Initialize new GD image stream");<br />
	if(!$img){<br />
		die("can't create picture");<br />
	}<br />
	$black = imagecolorallocate($img, 0, 0, 0); <br />
	$white = imagecolorallocate($img,255,255,255);<br />
	imagefill($img,0,0,$white);	<br />
	$data = str_split("0930000153",2);<br />
	global $pos;<br />
	$pos = 1;<br />
	//startpattern<br />
	nline();<br />
	nspace();<br />
	nline();<br />
	nspace();<br />
//eigentliche Daten<br />
	foreach($data as $data){<br />
		for($i=0;$i<=4;$i++){<br />
			call_user_func($digits[$data[0]][$i]."line");<br />
			call_user_func($digits[$data[1]][$i]."space");<br />
		}<br />
	}<br />
//endpattern<br />
	wline();<br />
	nspace();<br />
	nline();<br />
//show image<br />
	Header("Content-Type: image/png");<br />
	imagepng($img);<br />
	imagedestroy($img);<br />
	exit();</fieldset><br />
Wobei im Array $digits halt noch die o.g. Daten drinnenstehn.<br />
Hoffe alle Unklarheit ist beseitigt.<br />
<br />
]]></description>
	<guid>https://potassium.1338.at/index.php?id=756#</guid>
	<link>https://potassium.1338.at/index.php?id=756</link>
	<pubDate>Mon, 23 Feb 2009 18:41:00 +0100</pubDate>
	<author>potassium</author>
	<category><![CDATA[lost and found @ WWW, Programmieren, PHP-Entwicklung]]></category>
</item>
<item>
	<title><![CDATA[Update auf V 1.70 [update]]]></title>
	<description><![CDATA[Da <a href="http://potablog.1338.at" target='_blank'>PotaBlog</a> nun in Version 1.70 released ist, sind Kommentare ab sofort auch wieder möglich.]]></description>
	<guid>https://potassium.1338.at/index.php?id=657#</guid>
	<link>https://potassium.1338.at/index.php?id=657</link>
	<pubDate>Fri, 26 Sep 2008 01:28:00 +0200</pubDate>
	<author>potassium</author>
	<category><![CDATA[Software-Entwicklung, Weblog, PHP-Entwicklung]]></category>
</item>
<item>
	<title><![CDATA[Verhindern, dass Cookies von Javascript gelesen werden mit PHP < 5.2 [update]]]></title>
	<description><![CDATA[Ab PHP Version 5.2 wurde die Funktion setcookie() erweitert um das Argument <em>[, bool $httponly ]</em><br />
Nun lautet die Funktion<br />
<fieldset><legend>Code</legend><br />
bool setcookie ( string $name [, string $value [, int $expire [, string $path [, string $domain [, bool $secure [, bool $httponly ]]]]]] )</fieldset><br />
httponly bewirkt, dass beim Senden des Cookies an den Browser ein httpOnly; mitgesendet wird, das bei neuen Browsern verhindert, dass das Cookie von Javascript oder anderen Clientseitigen Skriptsprachen gelesen wird.<br />
<br />
Es funktionert derzeit bei folgenden Browsern:<br />
<br />
Microsoft Internet Explorer 	6 (SP1)+ 	Yes<br />
Mozilla Firefox 	2.0.0.6 	Yes<br />
Netscape Navigator 	9.0b3 	Yes<br />
<strong>Opera 	9.23 	No</strong><br />
Opera 	9.50 	Yes<br />
<strong>Safari 	3.0 	No</strong><br />
Google's Chrome 	Beta (initial public release) 	Yes<br />
(Verhindert jeweils nur das lesen)<br />
<br />
Mehr dazu <a href="http://www.owasp.org/index.php/HTTPOnly" target='_blank'>hier</a>, <a href="http://www.codinghorror.com/blog/archives/001167.html" target='_blank'>hier</a> und <a href="http://www.jellyandcustard.com/2006/08/11/httponly-cookies-in-php/" target='_blank'>hier</a>.<br />
<br />
Was macht man aber nun, wenn man eine PHP-Version vor 5.2 benutzt und sich nicht selbst eine setcookie() Funktion basteln will bzw. die Header manuell senden?<br />
<br />
Ganz einfach: Man fügt an das die Variable $domain einfach <br />
<fieldset><legend>Code</legend>; httpOnly; </fieldset><br />
an.<br />
<br />
Das sieht dann zb so aus<br />
<fieldset><legend>Code</legend>setcookie("userid", $userid, (time() + 886400), "/", $_SERVER["SERVER_NAME"]."; httpOnly;", FALSE);</fieldset><br />
<br />
Der Browser erhällt dann folgenden Header<br />
<br />
<fieldset><legend>Code</legend>Set-Cookie: userid=5; expires=Wed, 01-Oct-2008 04:20:40 GMT; path=/; domain=localhost; httpOnly;</fieldset><br />
<br />
Was exakt der Ausgabe von der setcookie() Funktion in PHP ab Version 5.2 entspricht.<br />
Ein wenig Dirty aber es funktioniert :-)<br />
<br />
<br />
]]></description>
	<guid>https://potassium.1338.at/index.php?id=649#</guid>
	<link>https://potassium.1338.at/index.php?id=649</link>
	<pubDate>Sun, 21 Sep 2008 00:07:00 +0200</pubDate>
	<author>potassium</author>
	<category><![CDATA[lost and found @ WWW, Software-Entwicklung, Softwarereview, Weblog, PHP-Entwicklung]]></category>
</item>

	</channel>
</rss>
