<?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"
	>

<channel>
	<title>Bastiaans Blog</title>
	<atom:link href="http://blog.welmers.net/bastiaan/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.welmers.net/bastiaan</link>
	<description>Just another weblog about computers and nothing</description>
	<pubDate>Tue, 20 Dec 2011 12:24:00 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>Use a global PHP include for your site</title>
		<link>http://blog.welmers.net/bastiaan/2011/12/use-a-global-php-include-for-your-site.html</link>
		<comments>http://blog.welmers.net/bastiaan/2011/12/use-a-global-php-include-for-your-site.html#comments</comments>
		<pubDate>Tue, 20 Dec 2011 12:24:00 +0000</pubDate>
		<dc:creator>bastiaan</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[apache]]></category>

		<category><![CDATA[configuration]]></category>

		<category><![CDATA[fastcgi]]></category>

		<category><![CDATA[mod_php]]></category>

		<category><![CDATA[mod_rewrite]]></category>

		<category><![CDATA[php]]></category>

		<category><![CDATA[php_flag]]></category>

		<category><![CDATA[php_value]]></category>

		<guid isPermaLink="false">http://blog.welmers.net/bastiaan/?p=25</guid>
		<description><![CDATA[Recently I switched from mod_php to FastCGI for serving PHP websites. With all the advantages of being able to run all websites separatly, the drawback is that configuration options like php_value and php_flag in .htaccess or other Apache configurations do not work anymore. There are some hacks that can be loaded as a PHP Module [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I switched from mod_php to FastCGI for serving PHP websites. With all the advantages of being able to run all websites separatly, the drawback is that configuration options like php_value and php_flag in .htaccess or other Apache configurations do not work anymore. There are some hacks that can be loaded as a PHP Module so PHP itself will read .htaccess files, but none of them work quite well. So the other solution is to use ini_set() in a global PHP include file in the very beginning of the PHP application.</p>
<p>Zend Framework applications are quite easy as all request are forwarded to index.php handling all request, so all global settings like include_paths can be handled there. However, with some PHP websites it is quite hard to introduce a common global PHP include file for application that has no single PHP file the application starts with, and it depends on a include_path set with php_value. The solution is to use Apache mod_rewrite to redirect all php request to a single file, proxy.php, that sets the global settings, and runs the original PHP file requested. <span id="more-25"></span></p>
<p>Add the following mod_rewrite code to your Apache vhost file or in .htaccess in the document root:<br />
<code><br />
RewriteCond  %{REQUEST_FILENAME}     ^(.*)\.php$<br />
RewriteCond  %{REQUEST_FILENAME}     -f<br />
RewriteRule  ^(.+)$                  proxy.php?proxy_script=$1 [QSA]<br />
</code><br />
This will cause all request ending with .php to be redirected to /proxy.php?proxy_script=<em>original_file</em>.php<br />
In the proxy.php file we define following code to set the global settings and handle the original request:</p>
<pre name="code" class="php">

/* Declare global PHP stuff */

set_include_path(get_include_path() . PATH_SEPARATOR .
   &#039;/home/www/mysite/current/include&#039; . PATH_SEPARATOR .
   &#039;/home/www/mysite/current/localsettings&#039;
   );

//register globals ( EVILNESS!! &#039;m&#039; )
foreach($_REQUEST as $varname =&gt; $varvalue)
        $$varname = $varvalue;

/****************************/

$proxy_script = str_replace(&#039;..&#039;, &#039;.&#039;, $_REQUEST[&#039;proxy_script&#039;]);

$script = $_SERVER[&#039;DOCUMENT_ROOT&#039;] . &#039;/&#039; . $proxy_script;

if (is_readable($script) &amp;&amp; $proxy_script != &#039;proxy.php&#039;) {

   // set environment for the original request
   $_SERVER[&#039;SCRIPT_FILENAME&#039;] = $script;
   $_SERVER[&#039;PHP_SELF&#039;] = $_SERVER[&#039;SCRIPT_NAME&#039;] = &#039;/&#039; . $proxy_script;

   // run original request
   include($script);

} else {
   header(&quot;HTTP/1.1 404 Not Found&quot;);
   print &quot;&lt;h2&gt;404 not found&lt;/h2&gt;&quot;;
}
</pre>
<p>Now every request will be handled properly, while global environment can be set easily in the proxy.php file.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.welmers.net/bastiaan/2011/12/use-a-global-php-include-for-your-site.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Cache layer for slow PHP objects</title>
		<link>http://blog.welmers.net/bastiaan/2010/03/cache-layer-for-slow-php-object.html</link>
		<comments>http://blog.welmers.net/bastiaan/2010/03/cache-layer-for-slow-php-object.html#comments</comments>
		<pubDate>Wed, 17 Mar 2010 20:39:43 +0000</pubDate>
		<dc:creator>bastiaan</dc:creator>
		
		<category><![CDATA[English]]></category>

		<category><![CDATA[IT]]></category>

		<category><![CDATA[cache]]></category>

		<category><![CDATA[php]]></category>

		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://blog.welmers.net/bastiaan/?p=24</guid>
		<description><![CDATA[When I was measuring execution time in a new PHP application using Doctrine and Zend_Date, I discovered lots of time is consumed by the code. It will slow down the app really if you show 50 objects in a list on a page when every object uses 100ms to list the results. It&#8217;s hard to [...]]]></description>
			<content:encoded><![CDATA[<p>When I was measuring execution time in a new PHP application using Doctrine and Zend_Date, I discovered lots of time is consumed by the code. It will slow down the app really if you show 50 objects in a list on a page when every object uses 100ms to list the results. It&#8217;s hard to get that library code fast, it&#8217;s easier to write a cache class around the object.<br />
<span id="more-24"></span><br />
The problem with these objects is that it takes too much time to get the output from certain methods or properties.<br />
See for example</p>
<pre name="code" class="php">

$date = new Zend_Date(...);
....
print $date-&gt;toString();
</pre>
<p>The toString() method takes up lots of execution time. To &#8216;fix&#8217; that, instead of this we use a cache object that has the original object and forwards all calls from the cache object to the original object, and caches the output, so next time, it will be served from cache.</p>
<pre name="code" class="php">

$date = new Zend_Date(...);
....
$cachedDate = new Cache($date);
print $cachedDate-&gt;toString();
</pre>
<h3>Preserve object type</h3>
<p>Sometimes you want to use type hinting and other methods to force the right type of object to be used within your application. Therefore you can use interfaces so both the cache object and the date object roots from the same interface which describes the proper abilities:</p>
<pre name="code" class="php">

interface Interface_Date { public function toString(); }

class Date extends Zend_Date implements Interface_Date {}

class Cache_Date extends Cache implements Interface_Date
{
	public function toString()
	{
		return parent::__call(&#039;toString&#039;, array());
	}
}

function printDate(Interface_Date $date) { print $date-&gt;toString(); }

$date = new Date(...);
....
$cachedDate = new Cache($date);
// both work now using type hinting:
printDate($date);
printDate($cachedDate);
</pre>
<h3>Iterators</h3>
<p>The cache object is most usefull when using and looping through long lists of objects. Therefore a Cache_Iterator becomes handy. For maximum execution efficiency, it will keep all calls to all containing objects in one cache item and writes it to cache on destruction of the Cache_Iterator container object.</p>
<pre name="code" class="php">

/* for example */
$dates = $users-&gt;getBirthDates();
/* assume $dates is an iterator with slow Date objects in it */

$datesCached = Cache_Iterator($dates);

foreach($datesCached as $dateCached)
{
	// dateCached is now a Cache object proxying a Date object
	print $dateCached-&gt;toString();
}
</pre>
<p>Also here, type preserving can be done.</p>
<pre name="code" class="php">

/* extend Cache_Iterator and make it
   producing Cache_Date objects instead
   of Date objects when looping */
class Cache_Iterator_Date extends Cache_Iterator
	{ protected $_class = &quot;Cache_Date&quot;; }

$dates = $users-&gt;getBirthDates();

$datesCached = Cache_Iterator_Date($dates);

foreach($datesCached as $dateCached)
{
	// dateCached is now a Cache_Date object
	printDate($dateCached);
}
</pre>
<h3>Cache ID auto generated</h3>
<p>The cache ID is generated by a md5 sum of a serialized object. The serialisation does not take significant execution time and it will make sure that an updated object or iterator with objects will generate new cache instead of showing the old contents. It however also means this won&#8217;t be usefull if the object or object iterator changes all the time. In such cases, find another unique ID like the combination of get_class($object) and $object-&gt;count() (Iterator), or $object-&gt;id (single object).</p>
<h3>When does this cache method <em>not</em> help</h3>
<p>When the time consuming or load is not caused by object code execution, but for example, (inefficient) database queries, database overload or a problem before or after or somewhere else but showing contents of the object. (No shit&#8230;) You should analize time consumption in your (too slow) application quite carefully. It&#8217;s however quite easy, by using <code>print microtime();</code> between your statements.</p>
<h3>The classes</h3>
<p>The code can be downloaded at <a href="http://www.welmers.net/~bastiaan/php-cache.tar.gz">http://www.welmers.net/~bastiaan/php-cache.tar.gz</a></p>
<pre name="code" class="php">

/**
 * @author Bastiaan Welmers
 *
 * cache layer to an object
 */
class Cache
{
	/**
	 * holds object that needs to be cached
	 * @var object
	 */
	private $object;

	/**
	 * the Cache ID of the cache data in Zend_Cache
	 * @var string
	 */
	private $cacheId;

	/**
	 * The instance of Zend_Cache
	 * @var Zend_Cache
	 */
	private $cacheInstance;

	/**
	 * The cache data
	 * @var array
	 */
	private $cache;

	/**
	 * Keeps track of changes in cache data. If true, cache data needs to be saved on destruction
	 * @var boolean
	 */
	private $needSave = false;

	/**
	 * Set to false by constructor if data doesnt need to be saved on destruction. default true.
	 * @var boolean
	 */
	private $saveAtDestruct = true;

	/**
	 * construct cache object.
	 * @param object Object that needs to be cached
	 * @param object optional object (passed by instance) where to save data in, instead of
	 *               creating our own. if this variable is set, cache data wil not be saved by us
	 *               @see Cache_Iterator for this kind of use
	 */
	public function __construct($object, &amp;$cache = false)
	{
		$this-&gt;object = $object;
		if ($cache === false)
		{
			// cache variable passed, here we save the data in.

			// try to find an unique id of the object for saving
			if (isset($object-&gt;id))
				$this-&gt;cacheId = get_class($object) . $object-&gt;id;
			else
				$this-&gt;cacheId = get_class($object) . &#039;_&#039; . md5(serialize($object));

			// get cache instance from zend_registry. Here we use a Zend_Cache backend object.
			// Here you can set your own if not using Zend_Cache.
			// It must however implement save() and load().
			$this-&gt;cacheInstance = Zend_Registry::get(&#039;cache&#039;);

			// load data from cache if available
			$this-&gt;cache = $this-&gt;cacheInstance-&gt;load($this-&gt;cacheId);
			if (!is_array($this-&gt;cache))
				$this-&gt;cache = array();

		} else {
			// cache variable passed, here we save the data in.
			$this-&gt;cache =&amp; $cache;
			if (!is_array($this-&gt;cache))
				$this-&gt;cache = array();
			// don&#039;t save the data on destruction
			$this-&gt;saveAtDestruct = false;
		}
	}

	/**
	 * catch all calls to this object and transparently pass them
	 * to the object with caching in between.
	 * @param string method name
	 * @param array arguments of functions
	 * @return mixed result of call
	 */
	public function __call($method, array $args)
	{
		if (is_callable(array($this-&gt;object, $method)))
		{
			// make up an string ID
			$id = &quot;method_{$method}_&quot; . md5(serialize($args));
			if (!isset($this-&gt;cache[$id]))
			{ // not found in cache, do the actual call to our object

				$return = call_user_func_array(array($this-&gt;object, $method), $args);

				// if having a Date object, return a dedicated date cache object
				if ($return instanceof Date)
					$return = new Cache_Date($return, $this-&gt;cache[$id . &#039;_date&#039;]);

				// save our result in cache data array
				$this-&gt;cache[$id] = $return;
				// we need so save the cache at destruction
				$this-&gt;needSave = true;
			} else
				// found in cache, get data from cache
				$return = $this-&gt;cache[$id];

			return $return;

		} else
			throw new Cache_Exception(get_class($this-&gt;object) . &quot;::$method() is not callable&quot;);
	}

	/**
	 * catch all properties of this object and transparently get them
	 * from the object with caching in between.
	 * @param string property
	 * @return mixed result of underlaying object
	 */
	public function __get($property)
	{
		if (isset($this-&gt;object-&gt;$property))
		{
			$id = &quot;property_{$property}&quot;;
			if (!isset($this-&gt;cache[$id]))
			{ // not found in cache. request from our object
				$return = $this-&gt;object-&gt;$property;
				// save in cache data array
				$this-&gt;cache[$id] = $return;
				// we need so save the cache at destruction
				$this-&gt;needSave = true;
			} else
				// get our result from cache
				$return = $this-&gt;cache[$id];

			return $return;

		} else
			throw new Cache_Exception(get_class($this-&gt;object) . &quot;::$name is not set&quot;);
	}

	/**
	 * Checks if an item is set. We pass it to the
	 * the object directly.
	 * @param string property
	 * @return boolean true if set false if not
	 */
	public function __isset($property)
	{
		return isset($this-&gt;object-&gt;$property);
	}

	/**
	 * destructor for saving cache data to cache if neccessary, on
	 * end of object lifetime.
	 */
	public function __destruct()
	{

		if ($this-&gt;saveAtDestruct &amp;&amp; $this-&gt;needSave &amp;&amp; isset($this-&gt;cacheInstance))
			$this-&gt;cacheInstance-&gt;save($this-&gt;cache, $this-&gt;cacheId);

	}

	/**
	 * __toString magic function if this object is used as string.
	 * pass call to __call()
	 */
	public function __toString()
	{
		return $this-&gt;__call(&#039;__toString&#039;, array());
	}

}
</pre>
<pre name="code" class="php">

/**
 * @author Bastiaan Welmers
 *
 * cache layer to an iterator
 * @see Cache
 * @see Iterator
 */
class Cache_Iterator implements Iterator, Countable
{
	/**
	 * Cache object to be spawned by current()
	 * @var string
	 */
	protected $_class = &#039;Cache&#039;;

	/**
	 * holds Iterator object that needs to be cached
	 * @var Iterator
	 */
	private $object;

	/**
	 * The instance of Zend_Cache
	 * @var Zend_Cache
	 */
	private $cacheInstance;

	/**
	 * The cache data
	 * @var array
	 */
	private $cache;

	/**
	 * the Cache ID of the cache data in Zend_Cache
	 * @var string
	 */
	private $cacheId;

	/**
	 * construct cache object.
	 * @param Iterator Object that needs to be cached
	 */
	public function __construct(Iterator $object)
	{

		$this-&gt;object = $object;
		$this-&gt;cacheInstance = Zend_Registry::get(&#039;cache&#039;);
		$this-&gt;cacheId = get_class($object) . md5(serialize($object));
		$this-&gt;cache = $this-&gt;cacheInstance-&gt;load($this-&gt;cacheId);
		if (!is_array($this-&gt;cache))
			$this-&gt;cache = array();
	}

	/**
	 * Rewinds object.
	 * Passed directly.
	 */
	public function rewind()
	{
		$this-&gt;object-&gt;rewind();
	}

	/**
	 * Get current value, and cache it if it is an object
	 * @return mixed value
	 */
	public function current()
	{
		// get value
		$object = $this-&gt;object-&gt;current();
		if (is_object($object))
			// create cache layer object of object,
			// pass our cache data array to it so it can save
			// its data there
			$object = new $this-&gt;_class($object, $this-&gt;cache[$this-&gt;key()]);

		return $object;
	}

	/**
	 * Get key of current value
	 * Passed directly.
	 * @return int key
	 */
	public function key()
	{
		return $this-&gt;object-&gt;key();
	}

	/**
	 * Move to next value.
	 * Passed directly.
	 */
	public function next()
	{
		$this-&gt;object-&gt;next();
	}

	/**
	 * Is current object still valid?
	 * Passed directly.
	 * @return boolean valid or not
	 */
	public function valid()
	{
		return $this-&gt;object-&gt;valid();
	}

	/**
	 * For countable iterators, count the values
	 * Passed directly.
	 * @see Countable
	 * @return int amount of values
	 */
	public function count()
	{
		if ($this-&gt;object instanceof Countable)
			return $this-&gt;object-&gt;count();
		else
			throw new Cache_Exception(&#039;Object of class &#039; . get_class($object) . &#039; does not implement Countable&#039;);
	}

	/**
	 * Destructor which saves the cache data at the end of object life time
	 */
	public function __destruct()
	{
		$this-&gt;cacheInstance-&gt;save($this-&gt;cache, $this-&gt;cacheId);
	}

}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.welmers.net/bastiaan/2010/03/cache-layer-for-slow-php-object.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>kdevelop3 on opensuse 11.2</title>
		<link>http://blog.welmers.net/bastiaan/2009/11/kdevelop3-on-opensuse-11-2.html</link>
		<comments>http://blog.welmers.net/bastiaan/2009/11/kdevelop3-on-opensuse-11-2.html#comments</comments>
		<pubDate>Fri, 27 Nov 2009 21:54:24 +0000</pubDate>
		<dc:creator>bastiaan</dc:creator>
		
		<category><![CDATA[English]]></category>

		<category><![CDATA[IT]]></category>

		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[kde]]></category>

		<category><![CDATA[kdevelop]]></category>

		<category><![CDATA[OpenSUSE]]></category>

		<guid isPermaLink="false">http://blog.welmers.net/bastiaan/?p=23</guid>
		<description><![CDATA[I recently installed OpenSUSE 11.2 on my netbook. There&#8217;s a lot of great new features like KDE 4.3, much better kernel 2.6.31 support for Intel Graphics and the Atheros wifi, but also good things disappear from the distro like some good working old kde3 applications. KDevelop3 is still a favorite for my daily work. However [...]]]></description>
			<content:encoded><![CDATA[<p>I recently installed OpenSUSE 11.2 on my netbook. There&#8217;s a lot of great new features like KDE 4.3, much better kernel 2.6.31 support for Intel Graphics and the Atheros wifi, but also good things disappear from the distro like some good working old kde3 applications. KDevelop3 is still a favorite for my daily work. However kdevelop4 is there, it is still having bugs and lacking functionality and not in a final release. I still want to work with KDevelop3. Well, it&#8217;s quite easy to fix that.<br />
<span id="more-23"></span><br />
One could easily install the packages from an old repository found on:<br />
<a href="http://ftp.yandex.ru/opensuse/repositories/openSUSE:/11.2/standard/">http://ftp.yandex.ru/opensuse/repositories/openSUSE:/11.2/standard/</a><br />
<a href="http://www2.nl.freebsd.org/opensuse/repositories/openSUSE:/11.2/standard/x86_64/">http://www2.nl.freebsd.org/opensuse/repositories/openSUSE:/11.2/standard/x86_64/</a></p>
<p>Probably this is just the openesuse 11.1 repository, but I&#8217;m not sure, it could also be a prerelease of<br />
11.2. If the repositories disappear, I hve placed the files on<br />
<a href="http://www.welmers.net/~bastiaan/kdevelop3-opensuse11.2/">http://www.welmers.net/~bastiaan/kdevelop3-opensuse11.2/</a></p>
<p>Items like qt3, cvs, subversion, ruby, python, kdebase3, kdelibs3, kdelibs3-devel should be installed<br />
from the OpenSUSE 11.2 repository. After that, these additional packages are neccessary:</p>
<p>kdebase3-devel-3.5.10<br />
kdebindings3-3.5.10<br />
kdebindings3-ruby<br />
kdesdk3-3.5.10<br />
python-kde3-3.16<br />
python-qt-3.17<br />
<em>and at last:</em><br />
kdevelop3-3.5.3</p>
<p>Probably the binary package from <a href="http://www.kdevelop.org/index.html?filename=3.5/download.html">kdevelop.org</a> can be used too, but I didn&#8217;t try that yet.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.welmers.net/bastiaan/2009/11/kdevelop3-on-opensuse-11-2.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>T-Mobile HSPA met linux (OpenSUSE kppp)</title>
		<link>http://blog.welmers.net/bastiaan/2009/10/t-mobile-hspa-met-linux.html</link>
		<comments>http://blog.welmers.net/bastiaan/2009/10/t-mobile-hspa-met-linux.html#comments</comments>
		<pubDate>Sat, 03 Oct 2009 17:00:17 +0000</pubDate>
		<dc:creator>bastiaan</dc:creator>
		
		<category><![CDATA[IT]]></category>

		<category><![CDATA[nederlands]]></category>

		<category><![CDATA[gprs]]></category>

		<category><![CDATA[hspa]]></category>

		<category><![CDATA[kppp]]></category>

		<category><![CDATA[Linux]]></category>

		<category><![CDATA[OpenSUSE]]></category>

		<category><![CDATA[pppd]]></category>

		<category><![CDATA[t-mobile]]></category>

		<category><![CDATA[tmobile]]></category>

		<category><![CDATA[umts]]></category>

		<category><![CDATA[web'n'walk]]></category>

		<guid isPermaLink="false">http://blog.welmers.net/bastiaan/?p=22</guid>
		<description><![CDATA[Onlangs heb ik een T-Mobile data abonnement afgesloten, zodat ik ook onderweg nutteloze dingen op internet kan doen. Een USB stick met een modem is bijgeleverd die in de laptop geprikt kan worden.

De vraag is natuurlijk hoe dit werkend te krijgen onder Linux. Er zou een programma bij zitten die gebruikt kon worden, maar die [...]]]></description>
			<content:encoded><![CDATA[<p>Onlangs heb ik een T-Mobile data abonnement afgesloten, zodat ik ook onderweg nutteloze dingen op internet kan doen. Een USB stick met een modem is bijgeleverd die in de laptop geprikt kan worden.</p>
<p><img src="http://www.welmers.net/~bastiaan/tmobile/kl-sdc10580.jpg" alt="HSPA Modem HUAWEI E176" width="600" height="450" /></p>
<p>De vraag is natuurlijk hoe dit werkend te krijgen onder Linux. Er zou een programma bij zitten die gebruikt kon worden, maar die heb ik niet gevonden tot nog toe. Met pppd en de KDE gui kppp werkt het echter ook prima.</p>
<p><span id="more-22"></span></p>
<p>De bijgeleverde modem is de Huawei E176. Een aardige HSPA/UMTS modem met micro-sd card slot en externe antenneaansluiting.</p>
<p>Wanneer de stick in een linux computer geplugd wordt (opensuse 11.1 kernel, 2.6.27) dan verschijnt er een /dev/ttyUSB0 aparaat. Deze kan gebruikt worden als normale modem om verbinding te leggen.</p>
<p>Met kppp kan uiterst eenvoudig de modem gebruikt worden. Het volgende dient te worden ingesteld:</p>
<p>- te kiezen nummer: *99***1#<br />
<img src="http://www.welmers.net/~bastiaan/tmobile/screenshots/kiezen.png" alt="KPPP nummer instellen" width="404" height="451" /></p>
<p>- te kiezen modemaparaat: /dev/ttyUSB0<br />
<img src="http://www.welmers.net/~bastiaan/tmobile/screenshots/modem.png" alt="KPPP modem selecteren" /></p>
<p>- Kies als login/wachtwoord: web en web<br />
<img src="http://www.welmers.net/~bastiaan/tmobile/screenshots/kppp-login.png" alt="KPPP" /></p>
<p>Voordat je het modem kan gebruiken, moet je op het modem identificeren met de PIN code. Dit kan met het modemcommando AT+CPIN=pincode. In kppp kan via Instellen-&gt;Modems-&gt;Wijzigen-&gt;Modem-&gt;Terminal een terminal geopend worden.<br />
<a href="http://www.welmers.net/~bastiaan/tmobile/screenshots/pin.png"><img src="http://www.welmers.net/~bastiaan/tmobile/screenshots/pin.png" alt="KPPP terminal - pin invoeren" /></a><br />
Voer hier het commando in, de modem zal OK retourneren bij de juiste pincode en het modem zal contact maken met een netwerk en het lampje zal blauw gaan knipperen.</p>
<p>Vervolgens kan er verbinding gemaakt worden:<br />
<a href="http://www.welmers.net/~bastiaan/tmobile/screenshots/verbinden.png"><img src="http://www.welmers.net/~bastiaan/tmobile/screenshots/verbinden.png" alt="KPPP terminal - pin invoeren" /></a><br />
Na het ATDT dial commando zal een CONNECT verschijnen, of NO CARIER als er geen netwerkbereik is.</p>
<p>Met kppp is vervolgens te zien dat er verbonden is en er is een grafiek en een lijstje met gebruikte data. Handig om een beetje in de gaten te houden dat je niet te snel te veel gebruikt.<br />
<a href="http://www.welmers.net/~bastiaan/tmobile/screenshots/verbonden.png"><img src="http://www.welmers.net/~bastiaan/tmobile/screenshots/verbonden.png" alt="KPPP terminal - pin invoeren" /></a></p>
<p>Na het verbinden verschijnt er een ppp0 interface die met /sbin/ifconfig gezien kan worden met het IP dat je krijgt van T-Mobile. Tevens verschijnt er een default route, die naar 10.64.64.64 komt te staan. Ik kwam er achter dat /etc/resolv.conf niet wordt geupdate en dat er dus geen DNS servers bereikbaar zijn. Er staat echter een resolv.conf in /var/run/ppp_resolv.conf.ppp0 die met cp naar /etc/resolv.conf gekopieerd kan worden. Dan is de verbinding klaar voor gebruik.</p>
<p>TODO:<br />
- Het AT+CPIN commando automatiseren<br />
- Manieren vinden om meer met het modem te kunnen zoals sms versturen, statestieken op te vragen, beschikbare netwerken te bekijken en te kiezen&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.welmers.net/bastiaan/2009/10/t-mobile-hspa-met-linux.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Nieuwe conti grand-prix en gator-skin</title>
		<link>http://blog.welmers.net/bastiaan/2009/08/nieuwe-conti-grand-prix-en-gator-skin.html</link>
		<comments>http://blog.welmers.net/bastiaan/2009/08/nieuwe-conti-grand-prix-en-gator-skin.html#comments</comments>
		<pubDate>Wed, 26 Aug 2009 19:52:26 +0000</pubDate>
		<dc:creator>bastiaan</dc:creator>
		
		<category><![CDATA[Fietsen]]></category>

		<category><![CDATA[406]]></category>

		<category><![CDATA[559]]></category>

		<category><![CDATA[continental]]></category>

		<category><![CDATA[durano]]></category>

		<category><![CDATA[gatorskin]]></category>

		<category><![CDATA[grand]]></category>

		<category><![CDATA[grand-prix]]></category>

		<category><![CDATA[kojak]]></category>

		<category><![CDATA[prix]]></category>

		<category><![CDATA[swalbe]]></category>

		<guid isPermaLink="false">http://blog.welmers.net/bastiaan/?p=21</guid>
		<description><![CDATA[Vorige week een nieuw 28-559 (26&#8243; race) bandje gekocht: de Contintental GatorSkin. Volgens de reviews een compromis racebandje voor de lange afstand.

Direct op mijn Quest gemonteerd en een trainingsrondje Soesterberg-Austerlitz gereden en een retourtje Utrecht-Enschede (286km).

Dit vooral om de band in te rijden en eens te kijken of de band een beetje snel is. Resultaat: [...]]]></description>
			<content:encoded><![CDATA[<p>Vorige week een nieuw 28-559 (26&#8243; race) bandje gekocht: de Contintental GatorSkin. Volgens de reviews een compromis racebandje voor de lange afstand.</p>
<p><img src="http://www.welmers.net/~bastiaan/2009-08-26-banden/tn/sdc10539.med.jpg" alt="Conti GatorSkin 559 en GrandPrix 406" width="550" height="412" /></p>
<p>Direct op mijn Quest gemonteerd en <a href="http://www.google.com/maps?q=http://www.welmers.net/~bastiaan/tracks/utrecht_soesterberg_leusden_zeist_utrecht/20080501.kml">een trainingsrondje Soesterberg-Austerlitz</a> gereden en een retourtje <a href="http://www.google.com/maps?q=http://www.welmers.net/~bastiaan/routes/utrecht-boekelo.kml">Utrecht-Enschede</a> (286km).</p>
<p><span id="more-21"></span></p>
<p>Dit vooral om de band in te rijden en eens te kijken of de band een beetje snel is. Resultaat: de band is vrij snel maar een groot verschil met de Swalbe Kojak 50-559 (standaard achterband Quest) is niet echt voelbaar, behalve dat de band op 9 bar sneller dribbelt en oncomfortabeler loopt op klinkers.</p>
<p>Het doel zou zijn voor wedstrijden met de Quest op asfalt bij snelheden waarbij een dikke zware achterband mogelijk te veel luchtweerstand heeft en zwaarder accelereert. Bovendien zou de dunne Conti bij 9 bar toch lichter kunnen rollen dan een Swalbe Kojak 50-559 bij 5,5 bar (de max druk). Ik zou hiervoor eens rolweerstandtesten willen uitvoeren (wie weet een goede lokatie? verhoging van enkele meters en een perfect egaal uitrolparcours van middelmatig grof asfalt).</p>
<p>Andere mogelijke kandidaat voor gebruik is bij mijn Xlow achterwiel.</p>
<p>Vandaag heb ik de GatorSkin vervangen door een 25-559 Grand-Prix voor een trainingsrondje van 42km en ik vermoed dat de Grand-Prix toch lichter loopt dan de GatorSkin.</p>
<p><a href="http://www.welmers.net/~bastiaan/2009-08-26-banden/tn/sdc10537.jpg.html"><img src="http://www.welmers.net/~bastiaan/2009-08-26-banden/tn/sdc10537.med.jpg" alt="Oude Conti GrandPrix banden 559 en 406" width="550" height="412" /><br />
<em>Oude Conti GrandPrix banden 559 en 406</em></a></p>
<p>Verder heb ik ook een 2tal nieuwe Continental Grand-Prix banden gekocht. De nieuwe Grand-Prix banden zijn anders dan de oude. Voor het gevoel zachter rubber, andere wangen, en iets breder, en nog steeds behoorlijk soepel, misschien zelfs soepeler. Maximale aangegeven druk is verlaagd van 8,5 naar 8 bar. (in praktijk is 9 bar prima). Deze ga ik binnenkort monteren op de voorwielen van de Quest om te kijken hoe ze lopen. Ook een rolweerstandproef zou ik graag willen uitvoeren, tezamen met de nieuwe 406 racebanden van Swalbe, de Durano.</p>
<p><a href="http://www.welmers.net/~bastiaan/2009-08-26-banden/tn/sdc10535.jpg.html"><img src="http://www.welmers.net/~bastiaan/2009-08-26-banden/tn/sdc10535.med.jpg" alt="Nieuwe Conti GrandPrix 406 en GatorSkin 559" width="550" height="412" /><br />
<em>Nieuw Conti GrandPrix 406 en GatorSkin 559</em></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.welmers.net/bastiaan/2009/08/nieuwe-conti-grand-prix-en-gator-skin.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Tijdrit Nijeveen</title>
		<link>http://blog.welmers.net/bastiaan/2009/08/nijeveen.html</link>
		<comments>http://blog.welmers.net/bastiaan/2009/08/nijeveen.html#comments</comments>
		<pubDate>Sun, 02 Aug 2009 20:13:08 +0000</pubDate>
		<dc:creator>bastiaan</dc:creator>
		
		<category><![CDATA[Fietsen]]></category>

		<category><![CDATA[nederlands]]></category>

		<category><![CDATA[nijeveen]]></category>

		<category><![CDATA[quest]]></category>

		<category><![CDATA[tijdrit]]></category>

		<category><![CDATA[wedstrijd]]></category>

		<guid isPermaLink="false">http://blog.welmers.net/bastiaan/?p=20</guid>
		<description><![CDATA[Ik vertrek om 8:00 vanuit St Maartensbrug, zo&#8217;n 20km onder Den Helder. Ik heb nog zo&#8217;n 140km te gaan voor Nijeveen, waar ik om 13:00 wel wil zijn. De avond ervoor gezellig geBBQt met m&#8217;n collega&#8217;s, dus dat was een redelijk kort nachtje.
Ik geniet van het West-Friese landschap in de vroege morgen. Bij Medemblik voelde [...]]]></description>
			<content:encoded><![CDATA[<p>Ik vertrek om 8:00 vanuit St Maartensbrug, zo&#8217;n 20km onder Den Helder. Ik heb nog zo&#8217;n 140km te gaan voor Nijeveen, waar ik om 13:00 wel wil zijn. De avond ervoor gezellig geBBQt met m&#8217;n collega&#8217;s, dus dat was een redelijk kort nachtje.<br />
Ik geniet van het West-Friese landschap in de vroege morgen. Bij Medemblik voelde ik dat ik niet meer echt fit ben. Vroeg opstaan is bij mij dan ook een garantie op niet fit zijn. Rustig aan verder. Om 9:30 kom ik aan in Enkhuizen en daar bleek de pont Enkhuizen-Urk pas om 11:15 te vertrekken. Dat wordt dus fietsend over de dijk naar Lelystad.</p>
<p><a href="http://www.welmers.net/~bastiaan/nijeveen2009/tn/sdc10340.jpg.html"><img src="http://www.welmers.net/~bastiaan/nijeveen2009/tn/sdc10340.med.jpg" /></a></p>
<p><span id="more-20"></span></p>
<p>Met een vaartje van 37km/h rijd ik tegen de wind in. Het is opmerkelijk hoe het tegenvalt als je in het onderste stuk van de dijk nog een hele slinger naar buiten moet maken, terwijl je maar 1km van het vaste land bent waar je zijn moet. De brug bij de sluis gaat net open, en een hele rits 3masters gleed langzaam voorbij. Daarna is het oponthoud nog niet voorbij, bij Lelystad mag je eerst allemaal onoverzichterlijke woonwijken in voordat je weer op de dijk bent richting Ketelbrug. Dankzij <a href="http://www.google.nl/maps?q=http://www.welmers.net/~bastiaan/tracks/20090801.kml">de GPS</a> kom ik er redelijk vlot doorheen, maar relaxed is anders, er moet doorgereden worden om niet te laat te komen.</p>
<p>Bij Ens stop ik voor boodschappen. Het is warm en ik ben duf. Het nog maar zo&#8217;n 30km en dat moet lukken in anderhalf uur. Ondanks ander oponthoud met openstaande bruggen ben ik braaf om 13:00 in Nijeveen en schrijf ik me in. Ymte is er ook en gaat rijden met koepeltje om het baanrecord verder te verbeteren. Ook Guus gaat met koepel rijden. Verder veel andere bekenden. Ik zet de tent op en gooi mijn zooi en die van anderen erin, en doe een poging tot powernap.</p>
<p>Rond 14:30 kunnen de ligfietsen van start. Het is benauwd, maar niet echt superwarm. Toch niet ideaal. Op het laatste moment besluit ik zonder schuimdeksel te gaan rijden. Zodra ik van start ben rijd ik na de eerste bocht 56km/h. De spieren geven signalen, auw! auw! Niet doen! Duidelijk gaar gereden van de heenrit in het warme weer. Na de 2e bocht gaat de snelheid met moeite richting de 53. Ik passeer Paulus. De bochten snijd ik slecht aan en ik verlies teveel snelheid. Dit gaat niet lekker. Na 2 bochten gaat het steeds vervelender. Ik schiet niet op. Zal ik stoppen? Nee, als je wilt stoppen gaat het juist goed, met die gedachten ga ik weer wat harder. Zie ik daar in de verte wat wits, Guus die 1 minuut voor mij gestart is? Ik ga weer wat harder. Helaas, dat bleek een container te zijn op een boerenerf. Ik passeer Magnus Hübel en roep Schneller! Schneller! Mijn quest is leeg en dat ben ik niet gewend en ik mis bagage om mijn ellebogen goed in te leggen. Bij een van de scherpe bochten vlieg ik op 2 wielen de berm in. Gelukkig gaat het net goed en ik kan verder rijden. </p>
<p><a href="http://picasaweb.google.nl/mldries2/Nijeveen2009?feat=directlink#5365421072133813602"><img src="http://lh5.ggpht.com/_hJ9-NyIjbbI/SnXOCbLudWI/AAAAAAAADmo/q__MOWXF3iQ/s800/DSC03772.JPG" /><i>Foto: Marloes Dries</i></a></p>
<p>Ik passeer de start-finish met 53km/h, en gelukkig roepen mijn spieren steeds minder auw. Toch gaat het niet zo heel hard meer de 2e ronde, zo net 50 top. Verdorie! Normaal kan ik makkelijk 57 pieken als ik even een stuk tussen de auto&#8217;s meerrijd naar mijn werk. Op een recht stuk zie ik een tractor van een erf komen. Als dat maar goed gaat&#8230; Gelukkig gaat hij net op tijd aan de kant en ik bedank de chauffeur. In de verte&#8230; zie ik toch echt Guus rijden. Het laatste stukje doe ik een poging tot sprinten, wat niet gaat. Ik ben teleurgesteld. Van veel anderen hoor ik dat het ook niet zo geweldig ging. De quest van Stefan was bedekt met waterplanten en zwarte vlekken. Zijn rem had het begeven en hij was de sloot in gereden in de 1e ronde. Jammer, want hij was goed bezig. Ymte leek de enige te zijn waarbij het wel goed ging. De prijsuitrijking begint en ik slof er naar toe. Tot mijn verbazing blijk ik toch 2e te zijn geworden met ruim 48km/h. </p>
<p><a href="http://picasaweb.google.nl/mldries2/Nijeveen2009#5365424983167402466"><img src="http://lh5.ggpht.com/_hJ9-NyIjbbI/SnXRmE6zAeI/AAAAAAAADrA/YYkKXh39yPI/s576/DSC03840.JPG" /><br />
<i>Foto: Marloes Dries</i></a><br />
Volgens <a href="http://www.ligfiets.net/agenda/race.php?id=344">de resultaten</a> was ik net 2 seconden sneller dan Guus die met koepel reed en 3e werd. Ymte heeft het baanrecord verbeterd met 24:25 en reed gemiddeld ruim 53km/h. Pfoe, daar sta ik toch nog best ver vanaf, zelfs als het wel goed zou gaan. Nu ben ik eigenlijk ook 2e geworden bij gebrek aan echte concurentie want ik reed inderdaad zo&#8217;n 30 seconden trager op vorig jaar, toen met zwaarder lopende Quest 1 en meer tegenwind. Maar er is wel ruimte voor verbetering door betere voorbereiding, dat geeft weer een goed gevoel.</p>
<p>De 3&#215;26&#8243; quest van Theo bleek door z&#8217;n achterbrug te zijn gezakt. Gelukkig net na de wedstrijd. De schanieras blijkt te zijn gebroken, en met een stuk tak wordt de zaak op z&#8217;n plek gehouden. </p>
<p><a href="http://www.welmers.net/~bastiaan/nijeveen2009/tn/sdc10361.jpg.html"><img src="http://www.welmers.net/~bastiaan/nijeveen2009/tn/sdc10357.med.jpg" /></a></p>
<p>Rond 18:00 vertrekken we vanuit Nijeveen richting Zwolle met Stefan, Paulus, Guus en Niels. Niels heeft er zin in en we rijden 38km/h. Paulus wijst de weg tot en met Zwolle. Daarna gaan we verder en we gaan steeds harder, ondanks ruim 200km en een wedstrijd in de benen. Guus zegt gedag bij Harderwijk en Niels en ik scheuren met zo&#8217;n 45km/h langs Ermelo en Nijkerk (klote rotondes!) richting Amersfoort. Dat je voor de quest weinig vermogen nodig hebt om vlak rechtuit te rijden en ik toch wel moe ben blijkt bij Amersfoort als de snelheid terugzakt naar 15km/h op het hellinkje voor de Stichtse Rotonde.</p>
<p><a href="http://www.welmers.net/~bastiaan/nijeveen2009/tn/sdc10363.jpg.html"><img src="http://www.welmers.net/~bastiaan/nijeveen2009/tn/sdc10363.med.jpg" /></a></p>
<p>Vals plat langs Soesterberg nog even op volle snelheid en vlak voor De Bilt mag de snelheid eruit en het verzet op licht om het zuur uit de benen te trappelen en zo een hoop spierpijn later te vermijden. Rond 22:00 kom ik thuis met 310km op de teller. Een leuke dag al met al, en een lekkere terugrit met Niels.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.welmers.net/bastiaan/2009/08/nijeveen.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Opnieuw Avocet Fasgrip</title>
		<link>http://blog.welmers.net/bastiaan/2009/03/opnieuw-avocet-fasgrip.html</link>
		<comments>http://blog.welmers.net/bastiaan/2009/03/opnieuw-avocet-fasgrip.html#comments</comments>
		<pubDate>Sun, 29 Mar 2009 18:15:45 +0000</pubDate>
		<dc:creator>bastiaan</dc:creator>
		
		<category><![CDATA[Fietsen]]></category>

		<category><![CDATA[nederlands]]></category>

		<category><![CDATA[avocet]]></category>

		<category><![CDATA[fasgrip]]></category>

		<category><![CDATA[quest]]></category>

		<category><![CDATA[ritten]]></category>

		<guid isPermaLink="false">http://blog.welmers.net/bastiaan/?p=18</guid>
		<description><![CDATA[
Na een winter met voornamelijk Vredestein HPV banden gereden te hebben met de Quest, vond ik het tijd worden voor wat nieuws. Stiekem ook wel iets beters. De HPV&#8217;s scoren niet echt geweldig op het gebied van betrouwbaarheid en rolweerstand.

Zo&#8217;n 1,5 jaar geleden heb ik 3 Avocet FasGrip banden besteld. Vrij exclusieve banden die Harry [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.welmers.net/~bastiaan/avocet/"><img src="http://www.welmers.net/~bastiaan/avocet/tn/avocet.jpeg.jpg" alt="" /></a></p>
<p>Na een winter met voornamelijk <a href="http://www.velomobiel.nl/onderdelen/banden.php">Vredestein HPV banden</a> gereden te hebben met de Quest, vond ik het tijd worden voor wat nieuws. Stiekem ook wel iets beters. De HPV&#8217;s scoren niet echt geweldig op het gebied van betrouwbaarheid en rolweerstand.<br />
<span id="more-18"></span><br />
Zo&#8217;n 1,5 jaar geleden heb ik 3 <a href="http://www.ligfiets.net/accessoires/type.php3?id=454">Avocet FasGrip</a> banden besteld. Vrij exclusieve banden die Harry Lieben uit de VS heeft geimporteerd. De kosten waren ongeveer 30 euro per band. Op het moment worden ze niet meer gemaakt.<br />
Wim Schermer is <a href="http://wimschermer.blogspot.com/2007/10/5-banden-getest.html">vol lof</a> over deze banden. Zelf heb ik er minder goede ervaring mee. De rubbersoort is vrij hard, waardoor de grip tegenvalt, vooral bij nat wegdek. Op de voorwielen was bij nat wegdek in de bocht snel sprake van <a href="http://nl.wikipedia.org/wiki/Onderstuur_(auto)">onderstuur</a>, en bij gebruik als achterband ben je verassend vaak en lang aan het spinnen bij vlot aanzetten. Ook had ik het idee dat ze niet echt snel waren. Nu in april de zomer weer in aantocht is en er mogelijk lagerproblemen waren in de tijd dat ik met de avocets heb gereden, vond ik het tijd om ze er maar weer eens om te leggen en te kijken wat ik ervan vind.</p>
<p><a href="http://maps.google.com/maps?q=http://www.welmers.net/~bastiaan/tracks/20090322.kml"><img src="http://www.welmers.net/~bastiaan/tracks/20090322.png" alt="" /></a></p>
<p>Vorige week heb ik de quest met deze banden geprobeerd tijdens een rondje van 75km met lekker zonnig weer, o.a. op de lekdijk tussen Houten en Amerongen. Het groffe asfalt word soepeltjes overwonnen en de snelheden waren niet mis, zo&#8217;n 50km kruissnelheid en uitschieter naar 65 op een stukje de dijk af. De Amerongse Berg af piekte zelfs op 81,0km/h. (ja inderdaad, veel te onverantwoord hard voor een smal 60km/h bosweggetje <img src='http://blog.welmers.net/bastiaan/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> ) Tot nu toe kan ik er wel tevreden over zijn.</p>
<p>De Avocet zal ik alleen maar op op de voorwielen monteren. Op het achterwiel wil ik een band die meer grip heeft, om gevaarlijke situaties door <a href="http://nl.wikipedia.org/wiki/Overstuur">overstuur</a> te voorkomen.<br />
Ook hier wil ik een vrij dikke band, voor lage rolweerstand en voldoende comfort, en om ongelijkheid tussen voor en achter te voorkomen. Ik heb daarvoor de <a href="http://www.ligfiets.net/accessoires/type.php3?id=398">Perfect Moiree 47-406</a> besteld, waar vrij goede ervaring over te vinden zijn. Komende week komt ie naar verwachting binnen bij mijn lokale fietsenwinkel.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.welmers.net/bastiaan/2009/03/opnieuw-avocet-fasgrip.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Google via IPv6</title>
		<link>http://blog.welmers.net/bastiaan/2009/03/google-via-ipv6.html</link>
		<comments>http://blog.welmers.net/bastiaan/2009/03/google-via-ipv6.html#comments</comments>
		<pubDate>Sat, 28 Mar 2009 10:50:02 +0000</pubDate>
		<dc:creator>bastiaan</dc:creator>
		
		<category><![CDATA[English]]></category>

		<category><![CDATA[IT]]></category>

		<category><![CDATA[google]]></category>

		<category><![CDATA[ipv6]]></category>

		<category><![CDATA[network]]></category>

		<guid isPermaLink="false">http://blog.welmers.net/bastiaan/?p=17</guid>
		<description><![CDATA[After all the signs from the ICT business world about the lack of interrest in deploying IPv6 because it should be too difficult and wouldn&#8217;t worth the investment, yesterday I found an article (Dutch  techworld.nl, read more on Googles blog post) about the deployment of IPv6 at Google. They stress about the ease it [...]]]></description>
			<content:encoded><![CDATA[<p>After all the signs from the ICT business world about the lack of interrest in deploying IPv6 because it should be too difficult and wouldn&#8217;t worth the investment, yesterday I found an <a href="http://techworld.nl/article/6636/'ipv6-makkelijk-en-niet-duur'.html">article</a> (Dutch <a href="http://techworld.nl"> techworld.nl</a>, read more on <a href="http://googlepublicpolicy.blogspot.com/2009/03/why-next-generation-internet-protocol.html">Googles blog post</a>) about the deployment of IPv6 at Google. They stress about the ease it takes to implement it. Actually exactly the same I think about it. When I deployed IPv6 about 2 years ago on my own network with the <a href="http://www.sixxs.net/">SiXXS</a> and <a href="http://www.xs4all.nl/allediensten/experimenteel/IPv6.php">XS4All</a> IPv6 tunnel brokers, it took only a little effort, I even didn&#8217;t have to restart my old BSD machines that were used as network gateways to get the network connected via IPv6. <span id="more-17"></span></p>
<p>The advantages are really there: no annoying NAT issues and no limitations to real Internet IP adresses. Even if you use it only for yourself, there&#8217;s a advantage when connecting multiple local areay networks, for example an backup server in network 2 that is pushed from several machines in network 1.</p>
<p>For a geek like me it&#8217;s even cooler if other internet services not under my control can be used via IPv6. Actually that is the situation where we all want to go in the future. There are <a href="http://www.sixxs.net/wiki/IPv6_Enabled_Websites">already a few</a> and <a href="http://www.computable.nl/artikel/ict_topics/besturingssystemen/2773238/1277048/macgebruikers-zorgen-voor-toename-ipv6.html"> 2,5% of the Mac users seem to be IPv6 connected</a>. So now Google is entirely IPv6 enabled, however their DNS does not return any AAAA records. Following <a href="http://www.google.com/ipv6">http://www.google.com/ipv6</a> only DNS resolvers on a whitelist will receive AAAA records because else the AAAA records could jeapordize their service availability because of poorly connected or configured network environments.</p>
<p><img src="http://www.welmers.net/~bastiaan/ipv6_resolvers2.png" /></p>
<p>So how to get on the whitelist? There&#8217;s no need actually: XS4All has their <a href="http://groups.google.nl/group/xs4all.general/browse_thread/thread/e89ddc81598ee7ff?hl=nl#">IPv6 resolvers</a> already on the whitelist. By using the resolvers 2001:888:0:9::99 and 2001:888:0:6::66 in /etc/fresolv.conf instead of your probably ordinary IPv4 resolvers, you will get connected to google by IPv6.</p>
<pre>
bastiaan@stofzuiger:~&gt; host www.google.com
www.google.com is an alias for www.l.google.com.
www.l.google.com has address 74.125.77.103
www.l.google.com has address 74.125.77.104
www.l.google.com has address 74.125.77.99
www.l.google.com has address 74.125.77.147
www.l.google.com has IPv6 address 2001:4860:a005::68
</pre>
<p>w00t ! <img src='http://blog.welmers.net/bastiaan/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>Are there any disadvantages? Probably there are. Beside the practical problems if the IPv6 link is down, your Google services will not work too, there are some privacy related concerns.<br />
Because IPv6 adresses are auto generated from the MAC address, and every single device connects directly to the peer, the end site (Google here) can gather location related information much easier. How many computers are there in your network, what does there MAC address look like, etcetera.  <a href="http://www.enterprisenetworkingplanet.com/netsp/article.php/641481">Read more about this</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.welmers.net/bastiaan/2009/03/google-via-ipv6.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Improved memcache php classes</title>
		<link>http://blog.welmers.net/bastiaan/2009/01/improved-memcache-php-classes.html</link>
		<comments>http://blog.welmers.net/bastiaan/2009/01/improved-memcache-php-classes.html#comments</comments>
		<pubDate>Wed, 14 Jan 2009 19:30:01 +0000</pubDate>
		<dc:creator>bastiaan</dc:creator>
		
		<category><![CDATA[English]]></category>

		<category><![CDATA[IT]]></category>

		<category><![CDATA[memcache]]></category>

		<category><![CDATA[mysql]]></category>

		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.welmers.net/bastiaan/?p=16</guid>
		<description><![CDATA[Today I rewrote the previous mysql - memcache classes, mentioned in my previous post.
I wrote a clas with static methods (why should you need an object at all?) with logic. supporting an easy way store items in a PHP application. A second DB class extends this one, for an easy way of caching complicated queries.



/** [...]]]></description>
			<content:encoded><![CDATA[<p>Today I rewrote the previous mysql - memcache classes, mentioned in <a href="http://blog.welmers.net/bastiaan/2008/11/caching-mysql-queries-with-memcache-in-php.html">my previous post</a>.<br />
I wrote a clas with static methods (why should you need an object at all?) with logic. supporting an easy way store items in a PHP application. A second DB class extends this one, for an easy way of caching complicated queries.<br />
<span id="more-16"></span></p>
<pre name="code" class="php">

/** @author Bastiaan Welmers
  *
  * 2009-01-13
  *
  * Holds memcache instance for caching stuff
  */

class Welmers_Memcache
{
	/**
	 * memcached ID for the ID list
	 */

	const IDLIST = &#039;__idlist_RANDOMCHARS&#039;;

	/**
	 * Holds the memcache instance
	 */

	private static $_memcache;

	/**
	 * Holds the application key generated bij init()
	 * @see init()
	 */

	private static $_appKey;

	/**
	 * TTL of the objects in memcached in seconds
	 *
	 */

	public static $timeout = 1800;

	/**
	 * Get list of IDs
	 *
	 * @return array with queries as keys and unix timestamps as value
	 */

	public static function getIdList()
	{
		return self::get(self::IDLIST);
	}

	/**
	 * Get the queries that are cached in this object
	 * from memcache
	 *
	 * @param string unique ID to identify object
	 * @return mixed|bool object in cache, or false on error
	 */

	public static function get($id)
	{
		if (!self::$_memcache instanceof Memcache)
			self::init();

		return self::$_memcache-&gt;get(self::$_appKey . $id);

	}

	/**
	 * Store object into memcache
	 *
	 * @param string unique ID to identify object
	 * @param mixed object to store
	 * @return bool true on succes, false on failure
	 */

	public static function set($id, $value, $timeout = null)
	{
		if ($timeout == null)
			$timeout = self::$timeout;

		if (!self::$_memcache instanceof Memcache)
			self::init();

		if ($id != self::IDLIST)
		{ // save ID
			$idList = self::get(self::IDLIST);

			if (!is_array($idList))
				$idList = array();

			$idList[$id] = time() + $timeout;

			self::set(self::IDLIST, $idList, $timeout + 2);
		}

		return self::$_memcache-&gt;set(self::$_appKey . $id, $value, 0, $timeout);
	}

	/**
	 * expires (deletes) items from memcache
	 *
	 * @param string unique ID to identify object, ommit to flush entire cache (removes every stored object)
	 */

	public static function expire($id = null)
	{

		if (!self::$_memcache instanceof Memcache)
			self::init();

		$idList = self::get(self::IDLIST);

		if (!is_array($idList))
			$idList = array();

		if ($id == null)
		{ // remove all IDS
			foreach($idList as $expireId =&gt; $timeout)
			{
				self::$_memcache-&gt;delete($expireId);
			}
			$idList = array();
			self::set(self::IDLIST, $idList, self::$timeout);
		} else { //specific item
			if (isset($idList[$id]))
			{
				self::$_memcache-&gt;delete(self::$_appKey . $id);
				unset($idList[$id]);
				self::set(self::IDLIST, $idList, self::$timeout);
			}
		}
	}

	/**
	 * Initiates memcache.
	 *
	 * @param int $timeout TTL of every stored object, if ommitted, self::$timeout will be used, 1800 seconds.
	 */

	public static function init($timeout = null)
	{
		if ($timeout != null)
			self::$timeout = $timeout;

		self::$_memcache = new Memcache();
		self::$_memcache-&gt;connect(&#039;localhost&#039;, 11211) or die (&quot;Could not connect to memcache&quot;);
		self::$_appKey = md5(__FILE__);
	}
}
</pre>
<p>Example for using this class:</p>
<pre name="code" class="php">

function get_difficult_var()
{
      if (!$difficult_var = Welmers_Memcache::get(&#039;difficult_var&#039;))
      {
          // difficult logic to create difficult var
          Welmers_Memcache::set(&#039;difficult_var&#039;, $difficult_var, 3600 /*timeout*/);
      }
      return $difficult_var
}
</pre>
<p>To remove this var, use</p>
<pre name="code" class="php">

Welmers_Memcache::expire(&#039;difficult_var&#039;)
</pre>
<p>To expire everything inserted in this application:</p>
<pre name="code" class="php">

Welmers_Memcache::expire()
</pre>
<p>The next class is useable for complicated MySQL queries, and replaces mysql_query.</p>
<pre name="code" class="php">

/** @author Bastiaan Welmers
  *
  * 2009-01-13
  *
  * Cache mysql queries
  *
  */

class Welmers_Memcache_Db extends Welmers_Memcache
{
	/**
	 * IDPREFIX - salt prefix for memcached ID for queries
	 * should be random value
	 */

	const IDPREFIX = &#039;aasd79tpbo1234&#039;; 

	/**
	 * QUERIES_PREFIX - prefix for memcached ID storing cached queries
	 */

	const QUERIES_PREFIX = &#039;__queries&#039;;

	/**
	 * Get the queries that are cached in this object
	 *
	 * @return array with queries as keys
	 */

	public static function getQueries()
	{
		return self::get(self::IDPREFIX . self::QUERIES_PREFIX);
	}

	/**
	 * Get the queries that are cached in this object
	 *
	 * @return array with queries as keys
	 */

	private static function _saveQuery($sql)
	{
		$queries = self::get(self::IDPREFIX . self::QUERIES_PREFIX);
		if (!is_array($queries))
			$queries = array();
		$queries[$sql] = true;
		self::set(self::IDPREFIX . self::QUERIES_PREFIX, $queries, self::$timeout + 2);
	}

	/**
	 * Helper function for mysql_query and delete* functions
	 *
	 * @param string $sql SQL query
	 * @return string with ID for memcached for this query
	 */

	private static function _getQueryKey($sql)
	{
		return md5(self::IDPREFIX . $sql);
	}

	/**
	 * The cached version of the plain mysql_query funtion
	 * Returns multidimensional array with al return values.
	 *
	 * @param string $sql SQL query
	 * @param resource $linkIdentifier optional link identifier of the mysql connection
	 * @return array multidimensional array with all returned records
	 */

	public static function mysql_query($sql, $linkIdentifier = false)
	{

		if (!($cache = self::get(self::_getQueryKey($sql))))
		{
			$cache = array();
			$r = ($linkIdentifier !== false) ? mysql_query($sql, $linkIdentifier) : mysql_query($sql);
			if (is_resource($r) &amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp; (($rows = mysql_num_rows($r)) != 0))
			{
				for ($i=0; $i &lt; $rows; $i++) {
					$fields = mysql_num_fields($r);
					$row = mysql_fetch_array($r);
					for ($j = 0; $j  $true)
			{
				if (strpos($query, $searchItem) !== false)
				{
					self::expire(self::_getQueryKey($query));
					unset($queries[$query]);
				}
			}
		}

		self::set(self::IDPREFIX . self::QUERIES_PREFIX, $queries, self::$timeout + 2);

	}

	/**
	 * Deletes all queries that are cached with this application
	 * Only use this for a global flush functionality, i.e. not for
	 * every change of a particular table.
	 * (then use deleteMatching(&#039;tablename&#039;) instead)
	 *
	 */

	public function deleteAll()
	{
		$queries = self::get(self::IDPREFIX . self::QUERIES_PREFIX);
		if (!is_array($queries))
			$queries = array();

		foreach($queries as $query =&gt; $true)
		{
			self::expire(self::_getQueryKey($query));
			unset($queries[$query]);
		}

		self::set(self::IDPREFIX . self::QUERIES_PREFIX, $queries, self::$timeout + 2);

	}
}
</pre>
<p>Example of this use would be easy:</p>
<pre name="code" class="php">

// example query, quite complicated for mysql to calculate
$query = &quot;SELECT
   DATE_FORMAT(lb.datum, &#039;%Y&#039;) AS year,
   DATE_FORMAT(lb.datum, &#039;%d-%m-%Y&#039;) AS datum_formatted,
   DATE_FORMAT(lb2.datum, &#039;%d-%m-%Y&#039;) AS datum_tot_formatted,
lp.lidnummer, lp.bedrijfsnaam, lp.voornaam, lp.tussenvoegsel, lp.achternaam
FROM leden_betaalmethodearchief lb
LEFT JOIN leden_persoonlijk lp ON lp.lidnummer = lb.lidnummer
LEFT JOIN leden_betaalmethodearchief lb2 ON
       lb.lidnummer = lb2.lidnummer AND
       lb2.datum &gt; lb.datum AND
       lb2.betaalmethode != &#039;acceptgiro&#039;
WHERE lb.betaalmethode = &#039;acceptgiro&#039; ORDER BY lb.datum ASC
&quot;;
$result = Welmers_Memcache_Db::mysql_query($query);
// instead of $result = mysql_query($query)

foreach($result as $row) {
// instead of while ($row = mysql_fetch_assoc($result) {
     print $row[&#039;field&#039;];
     // &#8230;..
}
</pre>
<p>Have a lot of fun!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.welmers.net/bastiaan/2009/01/improved-memcache-php-classes.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Zend_Db and UTF-8</title>
		<link>http://blog.welmers.net/bastiaan/2008/12/zend_db-and-utf-8.html</link>
		<comments>http://blog.welmers.net/bastiaan/2008/12/zend_db-and-utf-8.html#comments</comments>
		<pubDate>Sun, 14 Dec 2008 11:14:08 +0000</pubDate>
		<dc:creator>bastiaan</dc:creator>
		
		<category><![CDATA[English]]></category>

		<category><![CDATA[IT]]></category>

		<category><![CDATA[encoding]]></category>

		<category><![CDATA[mysql]]></category>

		<category><![CDATA[pdo]]></category>

		<category><![CDATA[php]]></category>

		<category><![CDATA[utf-8]]></category>

		<category><![CDATA[zend]]></category>

		<category><![CDATA[zend_db]]></category>

		<guid isPermaLink="false">http://blog.welmers.net/bastiaan/?p=15</guid>
		<description><![CDATA[Today I discovered a problem with my PHP/MySQL application. SQL data coming from the Zend_Db logic has the wrong encoding.
Like IMO all modern applications should, my application only uses UTF-8 for displaying and handling all non-ASCII characters. To make the MySQL server understand that I talk UTF-8 to it, I always use the following immediately [...]]]></description>
			<content:encoded><![CDATA[<p>Today I discovered a problem with my PHP/MySQL application. SQL data coming from the Zend_Db logic has the wrong encoding.</p>
<p>Like IMO all modern applications should, my application only uses UTF-8 for displaying and handling all non-ASCII characters. To make the MySQL server understand that I talk UTF-8 to it, I always use the following immediately after connecting:<br />
<span id="more-15"></span></p>
<pre name="code" class="sql">

SET NAMES utf8;
SET CHARACTER SET utf8;
</pre>
<p>The PDO interface of PHP, that Zend_Db is using, doesn&#8217;t use this, resulting in wrong character encoding (probably, the default is still latin-9 or something)<br />
To solve this, you can extend the Zend_Db_Adapter_Pdo_Mysql class and use the extended class instead for setting up the connection in bootstrap.php:</p>
<pre name="code" class="php">

class DbAdapter_Pdo_Mysql extends Zend_Db_Adapter_Pdo_Mysql {

   protected function _connect() {
       // if we already have a PDO object, no need to re-connect.
       if ($this-&gt;_connection)
            return;

        parent::_connect();

        $this-&gt;query(&#039;SET NAMES utf8&#039;);
        $this-&gt;query(&#039;SET CHARACTER SET utf8&#039;);
    }
}
</pre>
<p>Now replace code like this in your bootstrap.ini:</p>
<pre name="code" class="php">

$dbAdapter = new Zend_Db_Adapter_Pdo_Mysql(array(
             &#039;host&#039; =&gt; &#039;localhost&#039;,
             &#039;username&#039; =&gt; $dbuser,
             &#039;password&#039; =&gt; $dbpass,
             &#039;dbname&#039; =&gt; $db
             ));

$registry-&gt;set(&#039;dbAdapter&#039;, $dbAdapter);

Zend_Db_Table_Abstract::setDefaultAdapter($dbAdapter);
</pre>
<p>by this:</p>
<pre name="code" class="php">

$dbAdapter = new DbAdapter_Pdo_Mysql(array(
             &#039;host&#039; =&gt; &#039;localhost&#039;,
             &#039;username&#039; =&gt; $dbuser,
             &#039;password&#039; =&gt; $dbpass,
             &#039;dbname&#039; =&gt; $db
             ));

$registry-&gt;set(&#039;dbAdapter&#039;, $dbAdapter);

Zend_Db_Table_Abstract::setDefaultAdapter($dbAdapter);
</pre>
<p>Wow, problem solved <img src='http://blog.welmers.net/bastiaan/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> That&#8217;s an easy character encoding problemen today <img src='http://blog.welmers.net/bastiaan/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.welmers.net/bastiaan/2008/12/zend_db-and-utf-8.html/feed</wfw:commentRss>
		</item>
	</channel>
</rss>

