shad's blog http://shad.cc Most recent posts at shad's blog posterous.com Fri, 04 Mar 2011 18:55:00 -0800 How to know all of your unfollowers on Twitter http://feedproxy.google.com/~r/shadsblog/~3/d4IJl2eUZjg/how-to-know-all-of-your-unfollowers-on-twitte http://shad.cc/how-to-know-all-of-your-unfollowers-on-twitte <p> <p>Here is my easy way to know who unfollows me on Twitter. Or more precisely, how to monitor the changes on your followers list.</p> <p /> <div>First of all, create a simple script named "twitter_changes.sh":</div> <p /> <div> <blockquote> <div>#!/bin/sh</div> <p /> <div>SCREEN_NAME="sam_alba"</div> <div>EMAIL="<a href="mailto:myemail@domain.com">myemail@domain.com</a>"</div> <p /> <div>( cd $(dirname $(readlink -f $0))</div> <div>mv latest.log previous.log</div> <div>curl -s -X GET "<a href="http://api.twitter.com/1/statuses/followers.xml?screen_name=${SCREEN_NAME}">http://api.twitter.com/1/statuses/followers.xml?screen_name=${SCREEN_NAME}</a>" | grep -E '^ &nbsp;&lt;(screen_name|name)&gt;' &gt; latest.log</div> <div>data=$(diff previous.log latest.log)</div> <div>if [ ! -z "$data" ] ; then</div> <div><span style=""> </span>echo "$data" | mail -s "[twitter] changes" -a "From: <a href="mailto:twitter@shad.cc">twitter@shad.cc</a>" $EMAIL</div> <div>fi</div> <div>)</div> </blockquote> </div> <div>Then, execute the script daily with a crontab:</div> <blockquote> <div># cd /etc/cron.daily ; ln -s /path/of/your/script twitter_changes</div> </blockquote> <p /> <div>That's it, every changes on your twitter account will be emailed to you every morning.</div> </p> <p><a href="http://shad.cc/how-to-know-all-of-your-unfollowers-on-twitte">Permalink</a> </p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=d4IJl2eUZjg:Ovo-kHM5Be8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=d4IJl2eUZjg:Ovo-kHM5Be8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=d4IJl2eUZjg:Ovo-kHM5Be8:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=d4IJl2eUZjg:Ovo-kHM5Be8:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=d4IJl2eUZjg:Ovo-kHM5Be8:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=d4IJl2eUZjg:Ovo-kHM5Be8:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=d4IJl2eUZjg:Ovo-kHM5Be8:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=I9og5sOYxJI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/shadsblog/~4/d4IJl2eUZjg" height="1" width="1"/> http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/1lrZtSWEfRex Samuel Alba shad42 Samuel Alba http://shad.cc/how-to-know-all-of-your-unfollowers-on-twitte Sun, 23 Jan 2011 08:15:00 -0800 Released CirruxCache 0.4.2 http://feedproxy.google.com/~r/shadsblog/~3/6kZJU-R9pBQ/released-cirruxcache-042 http://shad.cc/released-cirruxcache-042 <p> <p>I have just released a new minor version of <a href="http://code.google.com/p/cirruxcache/">CirruxCache</a>. This new version includes several bugfixes and third party library upgrades.</p> <p /> <div>Here is the change list of the 0.4.2:</div> <div> <ul> <li>Admin panel: upgraded jquery, jquery-ui et jquery-form to the latest versions.</li> <li>Store service: fixed file upload (which was not working anymore on appengine with billing mode enabled).</li> <li>Some code cleanup</li> </ul> <div>This update is not critical, I invite you to upgrade only if you are experiencing problems with the admin panel or the store service.</div> <p /> <div><em>Thanks to Doug Tung who shared me an appengine account with billing mode enabled, that was really helpful for debugging.</em></div> </div> </p> <p><a href="http://shad.cc/released-cirruxcache-042">Permalink</a> </p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=6kZJU-R9pBQ:uy9d5rkOQFs:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=6kZJU-R9pBQ:uy9d5rkOQFs:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=6kZJU-R9pBQ:uy9d5rkOQFs:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=6kZJU-R9pBQ:uy9d5rkOQFs:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=6kZJU-R9pBQ:uy9d5rkOQFs:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=6kZJU-R9pBQ:uy9d5rkOQFs:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=6kZJU-R9pBQ:uy9d5rkOQFs:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=I9og5sOYxJI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/shadsblog/~4/6kZJU-R9pBQ" height="1" width="1"/> http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/1lrZtSWEfRex Samuel Alba shad42 Samuel Alba http://shad.cc/released-cirruxcache-042 Tue, 26 Oct 2010 20:10:00 -0700 CirruxCache 0.4.1 is out! http://feedproxy.google.com/~r/shadsblog/~3/Y9AQzTBAZDc/cirruxcache-041-is-out http://shad.cc/cirruxcache-041-is-out <p> <p style="margin-top: 14px; margin-right: 0px; margin-bottom: 14px; margin-left: 0px; font-size: 13px; padding: 0px;">An easy way to use Google Appengine as a personal CDN! CirruxCache 0.4.1 is out, so let me show you a set of new cool features!</p> <p style="margin-top: 14px; margin-right: 0px; margin-bottom: 14px; margin-left: 0px; font-size: 13px; padding: 0px;"><a href="http://code.google.com/p/cirruxcache/" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 1px; border-left-width: 0px; border-color: initial; font-size: 13px; border-bottom-style: dotted; border-bottom-color: #000000; text-decoration: none; color: #000000; font-weight: 600; padding: 0px; margin: 0px;">CirruxCache</a>&nbsp;provides a software solution to dynamically cache HTTP objects on Google Appengine (using the Datastore and the Memcache services).</p> <p style="margin-top: 14px; margin-right: 0px; margin-bottom: 14px; margin-left: 0px; font-size: 13px; padding: 0px;">Since the last release, I received a lot of good comments and smart suggestions. Fortunately, Some of you increased the size of my todo-list and a bunch of nice ideas are still in the box.</p> <p style="margin-top: 14px; margin-right: 0px; margin-bottom: 14px; margin-left: 0px; font-size: 13px; padding: 0px;">Let&rsquo;s take a look at this release:</p> <ul> <li style="font-size: 13px; padding: 0px; margin: 0px;">Admin panel now includes a config helper (<a href="http://code.google.com/p/cirruxcache/wiki/AdminPanel" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 1px; border-left-width: 0px; border-color: initial; font-size: 13px; border-bottom-style: dotted; border-bottom-color: #000000; text-decoration: none; color: #000000; font-weight: 600; padding: 0px; margin: 0px;">find here screenshots and documentation</a>).</li> <li style="font-size: 13px; padding: 0px; margin: 0px;">Object flushing has been fixed in the admin panel, give it a try!</li> <li style="font-size: 13px; padding: 0px; margin: 0px;"><a href="http://code.google.com/p/cirruxcache/wiki/PoP" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 1px; border-left-width: 0px; border-color: initial; font-size: 13px; border-bottom-style: dotted; border-bottom-color: #000000; text-decoration: none; color: #000000; font-weight: 600; padding: 0px; margin: 0px;">The Cache service</a>&nbsp;now includes a &ldquo;Content Prefetching&rdquo; feature. When it is enabled, HTML pages are interpreted. All associated content are loaded in the cache before the user request them. So it speeds up the first page loading. It is experimental for the moment, but it works (it is enabled on this blog!).</li> <li style="font-size: 13px; padding: 0px; margin: 0px;"><a href="http://code.google.com/p/cirruxcache/wiki/Image" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 1px; border-left-width: 0px; border-color: initial; font-size: 13px; border-bottom-style: dotted; border-bottom-color: #000000; text-decoration: none; color: #000000; font-weight: 600; padding: 0px; margin: 0px;">A new Image service</a>&nbsp;enables you to delegate image transformation to CirruxCache. For example, you won&rsquo;t need to upload images previews or thumbnail on your website anymore, let CirruxCache generate them and cache them on the fly! (All images&nbsp;<a href="http://code.google.com/p/cirruxcache/wiki/AdminPanel" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 1px; border-left-width: 0px; border-color: initial; font-size: 13px; border-bottom-style: dotted; border-bottom-color: #000000; text-decoration: none; color: #000000; font-weight: 600; padding: 0px; margin: 0px;">on this page</a>&nbsp;are generated this way).</li> <li style="font-size: 13px; padding: 0px; margin: 0px;">Config has been simplified: you don&rsquo;t need to edit the main &ldquo;app.py&rdquo; file. It is located in a file named &ldquo;config.py&rdquo;. On top of that, all internal services (admin, cron, store) are now included by default, you can forget them! (<a href="http://code.google.com/p/cirruxcache/wiki/QuickInstall" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 1px; border-left-width: 0px; border-color: initial; font-size: 13px; border-bottom-style: dotted; border-bottom-color: #000000; text-decoration: none; color: #000000; font-weight: 600; padding: 0px; margin: 0px;">Install documentation page</a>&nbsp;has been updated).</li> <li style="font-size: 13px; padding: 0px; margin: 0px;">A lot of bugfixes which improved the caching mechanism.</li> </ul> <p style="margin-top: 14px; margin-right: 0px; margin-bottom: 14px; margin-left: 0px; font-size: 13px; padding: 0px;">I hope you will enjoy this new release, check it out&nbsp;<a href="http://code.google.com/p/cirruxcache/downloads/list" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 1px; border-left-width: 0px; border-color: initial; font-size: 13px; border-bottom-style: dotted; border-bottom-color: #000000; text-decoration: none; color: #000000; font-weight: 600; padding: 0px; margin: 0px;">on the download page</a>.</p> <p style="margin-top: 14px; margin-right: 0px; margin-bottom: 14px; margin-left: 0px; font-size: 13px; padding: 0px;">I would like to share with you the&nbsp;<a href="http://code.google.com/p/cirruxcache/wiki/Users" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 1px; border-left-width: 0px; border-color: initial; font-size: 13px; border-bottom-style: dotted; border-bottom-color: #000000; text-decoration: none; color: #000000; font-weight: 600; padding: 0px; margin: 0px;">Users page</a>, I try to list some of you using CirruxCache.&nbsp;<a href="http://code.google.com/p/cirruxcache/wiki/Users" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 1px; border-left-width: 0px; border-color: initial; font-size: 13px; border-bottom-style: dotted; border-bottom-color: #000000; text-decoration: none; color: #000000; font-weight: 600; padding: 0px; margin: 0px;">This page</a>does not have much success, please take a look!</p> <p style="margin-top: 14px; margin-right: 0px; margin-bottom: 14px; margin-left: 0px; font-size: 13px; padding: 0px;">Finally, I warmly encourage you to subscribe to&nbsp;<a href="http://groups.google.com/group/cirruxcache" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 1px; border-left-width: 0px; border-color: initial; font-size: 13px; border-bottom-style: dotted; border-bottom-color: #000000; text-decoration: none; color: #000000; font-weight: 600; padding: 0px; margin: 0px;">the CirruxCache group</a>, it is really cool to get help and to provide advices to other users.</p> <p style="margin-top: 14px; margin-right: 0px; margin-bottom: 14px; margin-left: 0px; font-size: 13px; padding: 0px;">Spread the word!</p> <p>&nbsp;</p> </p> <p><a href="http://shad.cc/cirruxcache-041-is-out">Permalink</a> </p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=Y9AQzTBAZDc:lJB0zIplJMc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=Y9AQzTBAZDc:lJB0zIplJMc:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=Y9AQzTBAZDc:lJB0zIplJMc:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=Y9AQzTBAZDc:lJB0zIplJMc:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=Y9AQzTBAZDc:lJB0zIplJMc:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=Y9AQzTBAZDc:lJB0zIplJMc:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=Y9AQzTBAZDc:lJB0zIplJMc:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=I9og5sOYxJI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/shadsblog/~4/Y9AQzTBAZDc" height="1" width="1"/> http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/1lrZtSWEfRex Samuel Alba shad42 Samuel Alba http://shad.cc/cirruxcache-041-is-out Sat, 16 Oct 2010 20:10:00 -0700 Google Appengine on Ubuntu Maverick - without Python 2.5 http://feedproxy.google.com/~r/shadsblog/~3/LUDxrLr5WXg/google-appengine-on-ubuntu-maverick-without-p http://shad.cc/google-appengine-on-ubuntu-maverick-without-p <p> <p><span style="font-family: Helvetica Neue, Helvetica, Arial, sans-serif; font-size: 13px; line-height: 22px;">&nbsp;</span>First of all, install the required ubuntu packages:</p> <p style="margin-top: 14px; margin-right: 0px; margin-bottom: 14px; margin-left: 0px; font-size: 13px; padding: 0px;">&nbsp;</p> <p style="margin-top: 14px; margin-right: 0px; margin-bottom: 14px; margin-left: 0px; font-size: 13px; padding: 0px;">&nbsp;$ sudo aptitude install libssl-dev libsqlite3-dev</p> <p style="margin-top: 14px; margin-right: 0px; margin-bottom: 14px; margin-left: 0px; font-size: 13px; padding: 0px;">Then, fetch python2.5 source tarball:</p> <p style="margin-top: 14px; margin-right: 0px; margin-bottom: 14px; margin-left: 0px; font-size: 13px; padding: 0px;">&nbsp;$ wget <a href="http://python.org/ftp/python/2.5/Python-2.5.tar.bz2">http://python.org/ftp/python/2.5/Python-2.5.tar.bz2</a><br />&nbsp;$ tar xjf Python-2.5.tar.bz2</p> <p style="margin-top: 14px; margin-right: 0px; margin-bottom: 14px; margin-left: 0px; font-size: 13px; padding: 0px;">Before compiling, we need to tweak the file Python-2.5/Modules/Setup.dist (line 207) as following:</p> <p style="margin-top: 14px; margin-right: 0px; margin-bottom: 14px; margin-left: 0px; font-size: 13px; padding: 0px;">&nbsp;_ssl _ssl.c \<br />&nbsp;-DUSE_SSL -I/usr/include/openssl \<br />&nbsp;-L/usr/lib -lssl -lcrypto</p> <p style="margin-top: 14px; margin-right: 0px; margin-bottom: 14px; margin-left: 0px; font-size: 13px; padding: 0px;">Compile and install:</p> <p style="margin-top: 14px; margin-right: 0px; margin-bottom: 14px; margin-left: 0px; font-size: 13px; padding: 0px;">&nbsp;$ mkdir /opt/python2.5<br />&nbsp;$ ./configure --prefix=/opt/python2.5<br />&nbsp;$ make $ sudo make install</p> <p style="margin-top: 14px; margin-right: 0px; margin-bottom: 14px; margin-left: 0px; font-size: 13px; padding: 0px;">Finally, after having deployed the appengine framework package, we need to modify shebangs:</p> <p style="margin-top: 14px; margin-right: 0px; margin-bottom: 14px; margin-left: 0px; font-size: 13px; padding: 0px;">&nbsp;$ cd /path/to/appengine<br />&nbsp;$ find . -name '*.py' -exec sed -i "s/#!\/usr\/bin\/env python/#!\/opt\/python2.5\/python/" {} \;<br />&nbsp;$ chmod -R 755 .</p> <p>&nbsp;</p> </p> <p><a href="http://shad.cc/google-appengine-on-ubuntu-maverick-without-p">Permalink</a> </p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=LUDxrLr5WXg:c4DtyHXY_qU:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=LUDxrLr5WXg:c4DtyHXY_qU:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=LUDxrLr5WXg:c4DtyHXY_qU:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=LUDxrLr5WXg:c4DtyHXY_qU:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=LUDxrLr5WXg:c4DtyHXY_qU:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=LUDxrLr5WXg:c4DtyHXY_qU:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=LUDxrLr5WXg:c4DtyHXY_qU:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=I9og5sOYxJI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/shadsblog/~4/LUDxrLr5WXg" height="1" width="1"/> http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/1lrZtSWEfRex Samuel Alba shad42 Samuel Alba http://shad.cc/google-appengine-on-ubuntu-maverick-without-p Sat, 07 Aug 2010 19:29:00 -0700 CirruxCache: Store API documentation http://feedproxy.google.com/~r/shadsblog/~3/ru6Kk943_A8/cirruxcache-store-api-documentation http://shad.cc/2010/08/07/cirruxcache-store-api-documentation <p> <p>I have just written <a href="http://code.google.com/p/cirruxcache/wiki/StoreAPI">some documentation about the Store WebService</a> of <a href="http://code.google.com/p/cirruxcache/">CirruxCache</a>. This little page will help you to upload big files on CirruxCache in the same way than the current admin panel does.</p> <p><a href="http://code.google.com/p/cirruxcache/wiki/StoreAPI" title="http://code.google.com/p/cirruxcache/wiki/StoreAPI">http://code.google.com/p/cirruxcache/wiki/StoreAPI</a></p> <p><a href="http://code.google.com/p/cirruxcache/wiki/StoreAPI" title="http://code.google.com/p/cirruxcache/wiki/StoreAPI"></a><em>Just to remember, the Store WebService has been developed to bypass the 1MB limitation of appengine. It is not possible to dynamically cache objects with a size greater than 1MB, in this case, you need to store explicitly such an object using this WebService. It uses the Blobstore service, so file size cannot exceed 2GB.</em></p> </p> <p><a href="http://shad.cc/2010/08/07/cirruxcache-store-api-documentation">Permalink</a> </p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=ru6Kk943_A8:7UwAH9hAahc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=ru6Kk943_A8:7UwAH9hAahc:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=ru6Kk943_A8:7UwAH9hAahc:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=ru6Kk943_A8:7UwAH9hAahc:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=ru6Kk943_A8:7UwAH9hAahc:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=ru6Kk943_A8:7UwAH9hAahc:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=ru6Kk943_A8:7UwAH9hAahc:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=I9og5sOYxJI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/shadsblog/~4/ru6Kk943_A8" height="1" width="1"/> http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/1lrZtSWEfRex Samuel Alba shad42 Samuel Alba http://shad.cc/2010/08/07/cirruxcache-store-api-documentation Wed, 21 Jul 2010 22:46:00 -0700 CirruxCache: Advanced configuration sample http://feedproxy.google.com/~r/shadsblog/~3/tMXzdVBjN4E/cirruxcache-advanced-configuration-sample http://shad.cc/2010/07/21/cirruxcache-advanced-configuration-sample <p> That's it! This whole blog is cached and directly delivered by <a href="http://code.google.com/p/cirruxcache/">CirruxCache</a> (only static files were cached before). My origin server is a tiny <a href="http://event.asus.com/eeepc/microsites/eeebox/en/index.html">eeebox</a> connected through my personal ISP. So this configuration is a good challenge to offload my tiny web server as much as possible. I think this is a good opportunity to show an example of a configuration which is a little bit more evolved. The point is, I cannot set the same cache TTL for the whole website, and actually, I want to cache several websites... <div class="CodeRay"> <div class="code"><pre># URL mapping urls = {} base = ( '/_admin/(.*)', 'Admin', '/_store/(.*)', 'Store', '/_cron/(.*)', 'Cron' ) urls['default'] = base + ( '(/debug/.*)', 'Debug', '/(.*)', 'Root' ) urls['www.shad.cc'] = base + ( '(/themes/.*)', 'Blog_Static', '(/plugins/.*)', 'Blog_Static', '(/admin/.*)', 'Blog_Forward', '(/.*)', 'Blog_Page' ) urls['www.zaphod.eu'] = base + ( '(/pub/.*)', 'Zaphod_Redirect', '(/.*)', 'Zaphod' ) # still supporting the old config urls['cdn.shad.cc'] = base + ( '/blog(/.*)', 'Blog_Static', '/(.*)', 'Root' ) urls['cdn.zaphod.eu'] = base + ( '(/admin/.*)', 'Zaphod', '/(.*)', 'Root' ) # POP definition # You can define and configure your Point Of Presence class Blog_Static(cache.Service): origin = 'http://orig.shad.cc' forceTTL = 2592000 # 1 month ignoreQueryString = True forwardPost = False allowFlushFrom = ['x.x.x.x'] class Blog_Page(cache.Service): origin = 'http://orig.shad.cc' forceTTL = 3600 # 1 hour ignoreQueryString = True forwardPost = True allowFlushFrom = ['x.x.x.x'] class Blog_Forward(forward.Service): origin = 'http://orig.shad.cc' class Zaphod(cache.Service): origin = 'http://orig.zaphod.eu' forceTTL = 2592000 # 1 month ignoreQueryString = True forwardPost = False allowFlushFrom = ['x.x.x.x'] class Zaphod_Redirect(redirect.Service): origin = 'http://zaphod.eu' # !POP I think this configuration is enough readable to avoid any explanation. However, do not hesitate to leave any comments.</pre></div> </div> Finally, I created <a href="http://groups.google.com/group/cirruxcache">a google groups</a> to centralize all help requests. So if you need help, go to <a href="http://groups.google.com/group/cirruxcache" title="http://groups.google.com/group/cirruxcache">http://groups.google.com/group/cirr...</a> or send an email to cirruxcache 'at' googlegroups 'dot' com. </p> <p><a href="http://shad.cc/2010/07/21/cirruxcache-advanced-configuration-sample">Permalink</a> </p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=tMXzdVBjN4E:yzQadPpb8OM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=tMXzdVBjN4E:yzQadPpb8OM:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=tMXzdVBjN4E:yzQadPpb8OM:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=tMXzdVBjN4E:yzQadPpb8OM:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=tMXzdVBjN4E:yzQadPpb8OM:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=tMXzdVBjN4E:yzQadPpb8OM:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=tMXzdVBjN4E:yzQadPpb8OM:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=I9og5sOYxJI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/shadsblog/~4/tMXzdVBjN4E" height="1" width="1"/> http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/1lrZtSWEfRex Samuel Alba shad42 Samuel Alba http://shad.cc/2010/07/21/cirruxcache-advanced-configuration-sample Sun, 18 Jul 2010 15:21:00 -0700 New release: CirruxCache 0.3.1 http://feedproxy.google.com/~r/shadsblog/~3/pDi5UFNI80A/new-release-cirruxcache-0-3-1 http://shad.cc/2010/07/18/new-release-cirruxcache-0-3-1 <p> <p>I am really glad to announce a new major release of <a href="http://code.google.com/p/cirruxcache/">CirruxCache</a>.<p /> This new release includes the following changes:</p> <ul> <li>A storage webservice: store big files (&lt;= 2GB) on the Blobstore in order to deliver them through CirruxCache. This feature is useful to bypass the 1MB limit on appengine.</li> <li>An admin panel that enables users to flush objects, manage big files and see some statistics about the resources used.</li> <li>Bugfixes</li> </ul> <p>It is really important to note there are few limitations on the panel admin:</p> <ul> <li>There is no error reporting on the flush panel (it only displays the number of objects trying to be flushed).</li> <li>Storage manager displays a "500 Internal Error" when uploading. It only happens when you don't have a billing account (the Blobstore is only available on billing accounts, refer to appengine).</li> </ul> <p>These two limitations will be improved in the next release, and there will be more informations in the statistics panel.<p /> The Storage WebService will be documented really soon, but you can access the admin panel through "http://your.cirruxcache.app/_admin/"<p /> I make the most of this opportunity to announce some changes on <a href="http://code.google.com/p/cirruxcache/">the project website</a>:</p> <ul> <li><a href="http://code.google.com/p/cirruxcache/wiki/Roadmap">Roadmap page</a></li> <li> <a href="http://code.google.com/p/cirruxcache/wiki/Users">Users list</a>: this page has just been started, so do not hesitate to notify me to add you.</li> </ul> <p>I hope you will enjoy this new release.</p> </p> <p><a href="http://shad.cc/2010/07/18/new-release-cirruxcache-0-3-1">Permalink</a> </p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=pDi5UFNI80A:zkb-pgrWNvA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=pDi5UFNI80A:zkb-pgrWNvA:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=pDi5UFNI80A:zkb-pgrWNvA:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=pDi5UFNI80A:zkb-pgrWNvA:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=pDi5UFNI80A:zkb-pgrWNvA:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=pDi5UFNI80A:zkb-pgrWNvA:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=pDi5UFNI80A:zkb-pgrWNvA:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=I9og5sOYxJI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/shadsblog/~4/pDi5UFNI80A" height="1" width="1"/> http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/1lrZtSWEfRex Samuel Alba shad42 Samuel Alba http://shad.cc/2010/07/18/new-release-cirruxcache-0-3-1 Wed, 19 May 2010 17:45:00 -0700 Minor release: CirruxCache 0.2.2 http://feedproxy.google.com/~r/shadsblog/~3/eLkqmBHTnJc/minor-release-cirruxcache-0-2-2 http://shad.cc/2010/05/19/minor-release-cirruxcache-0-2-2 <p> <p><a href="http://code.google.com/p/cirruxcache/">CirruxCache</a> 0.2.2 has just been released. It contains some bugfixes (thanks to Devattas to have reported errors on Datastore latency). Webpy has been updated to the last version.<p /> I have also updated the documentation, especially I brought more details on <a href="http://code.google.com/p/cirruxcache/wiki/PoP">Point of Presence configuration</a> and usage of <a href="http://code.google.com/p/cirruxcache/wiki/Cron">cron tasks for garbage collection</a>.<p /> Finally, some of the users reported me that there is a real problem with the cached object size limit (currently 1MB). I am working on the solution, I will take advantage of the new Blobstore service on AppEngine to store objects. Maybe I will keep the Datastore only for meta-data. This solution will raise the cache object limit to 50MB.<p /> Stay tuned :)</p> </p> <p><a href="http://shad.cc/2010/05/19/minor-release-cirruxcache-0-2-2">Permalink</a> </p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=eLkqmBHTnJc:bG8j5EUIN2E:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=eLkqmBHTnJc:bG8j5EUIN2E:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=eLkqmBHTnJc:bG8j5EUIN2E:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=eLkqmBHTnJc:bG8j5EUIN2E:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=eLkqmBHTnJc:bG8j5EUIN2E:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=eLkqmBHTnJc:bG8j5EUIN2E:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=eLkqmBHTnJc:bG8j5EUIN2E:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=I9og5sOYxJI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/shadsblog/~4/eLkqmBHTnJc" height="1" width="1"/> http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/1lrZtSWEfRex Samuel Alba shad42 Samuel Alba http://shad.cc/2010/05/19/minor-release-cirruxcache-0-2-2 Thu, 11 Mar 2010 17:20:00 -0800 CirruxCache 0.2.1 is released http://feedproxy.google.com/~r/shadsblog/~3/9RoXPpU02QI/cirruxcache-0-2-1-is-released http://shad.cc/2010/03/11/cirruxcache-0-2-1-is-released <p> <p>I have just released <a href="http://code.google.com/p/cirruxcache/">a new version (0.2.1) of CirruxCache</a>. To remember:<p /> <a href="http://code.google.com/p/cirruxcache/">CirruxCache</a> provides a software solution to dynamically cache HTTP objects on Google Appengine (using the Datastore and the Memcache services).</p> <p>This new version includes an interesting set of features:</p> <ul> <li>allow object flushing from restricted IP</li> <li>configure a PoP (Point of Presence) according to a virtual host</li> <li>several behaviors (cache, redirect, forward)</li> </ul> <p>In more details, the last feature is the ability to configure a point of presence to differ from a classical caching mechanism. For example, I may want to configure "/admin/*" on my website to be redirected on the origin without caching.<p /> Of course, this release includes several bugfixes, especially a fix on the "Expires" HTTP header which improves the caching performances.<p /> Do not hesitate to test this new version and to comment any bugs or any suggestions.</p> </p> <p><a href="http://shad.cc/2010/03/11/cirruxcache-0-2-1-is-released">Permalink</a> </p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=9RoXPpU02QI:_wVVLVVZZWI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=9RoXPpU02QI:_wVVLVVZZWI:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=9RoXPpU02QI:_wVVLVVZZWI:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=9RoXPpU02QI:_wVVLVVZZWI:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=9RoXPpU02QI:_wVVLVVZZWI:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=9RoXPpU02QI:_wVVLVVZZWI:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=9RoXPpU02QI:_wVVLVVZZWI:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=I9og5sOYxJI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/shadsblog/~4/9RoXPpU02QI" height="1" width="1"/> http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/1lrZtSWEfRex Samuel Alba shad42 Samuel Alba http://shad.cc/2010/03/11/cirruxcache-0-2-1-is-released Fri, 19 Feb 2010 18:11:00 -0800 Adding virtual host support to webpy http://feedproxy.google.com/~r/shadsblog/~3/XHnD83DY0FQ/adding-virtual-host-support-to-webpy http://shad.cc/2010/02/19/adding-virtual-host-support-to-webpy <p> <p><a href="http://webpy.org/">Webpy</a> is a tiny web framework. I use it a lot for my web-services applications. In general, I let my web server (<a href="http://www.lighttpd.net/">lighttpd</a>) to handle virtual hosting. But as you may know, I am working on a CDN solution on top of <a href="http://code.google.com/appengine/">Google App Engine</a>, named <a href="http://code.google.com/p/cirruxcache/">CirruxCache</a>. In that case, while I have absolutely no control on the server configuration, I need to handle virtual hosting from the code. Webpy maps urls by iterating through a <a href="http://docs.python.org/library/functions.html#tuple">tuple</a>. So my solution is quite simple: wrapping the tuple to override the <a href="http://docs.python.org/library/stdtypes.html#iterator-types">__iter__</a> function according to an environment variable (HTTP_HOST). Let's take this basic webpy example, without vhosting:</p> <div class="CodeRay"> <div class="code"><pre>import web urls = ('/(.*)', 'hello') class hello(object): def GET(self, name): if not name: name = 'World' return 'Hello, %s' % name if __name__ == &quot;__main__&quot;: app = web.application(urls, globals()) app.run() Let's add the VhostMapper class:</pre></div> </div> <div class="CodeRay"> <div class="code"><pre>import web urls = { 'default' : ('/(.*)', 'hello'), 'my-vhost.domain.tld' : ('/(.*)', 'helloVhost') } class hello(object): def GET(self, name): if not name: name = 'World' return 'Hello, %s !' % name class helloVhost(object): def GET(self, name): return 'Hello %s' % web.ctx.environ['HTTP_HOST'] class VhostMapper(object): def __iter__(self): url = urls['default'] if 'HTTP_HOST' in web.ctx.environ: vhost = web.ctx.environ['HTTP_HOST'] if vhost in urls: url = urls[vhost] return iter(url) if __name__ == &quot;__main__&quot;: app = web.application(VhostMapper(), globals()) app.run() Finally, you can use curl or wget to test your vhosts:</pre></div> </div> <div class="CodeRay"> <div class="code"><pre>$&gt; curl -H &quot;Host: my-vhost.domain.tld&quot; http://localhost:8080/</pre></div> </div> <p>It is not so early to announce that the next version of <a href="http://code.google.com/p/cirruxcache/">CirruxCache</a> will handle virtual hosting :) I am sure this simple hack can be easily reproduced to use virtual hosting in some other Rest frameworks.</p> </p> <p><a href="http://shad.cc/2010/02/19/adding-virtual-host-support-to-webpy">Permalink</a> </p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=XHnD83DY0FQ:myYwF9R0_i4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=XHnD83DY0FQ:myYwF9R0_i4:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=XHnD83DY0FQ:myYwF9R0_i4:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=XHnD83DY0FQ:myYwF9R0_i4:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=XHnD83DY0FQ:myYwF9R0_i4:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=XHnD83DY0FQ:myYwF9R0_i4:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=XHnD83DY0FQ:myYwF9R0_i4:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=I9og5sOYxJI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/shadsblog/~4/XHnD83DY0FQ" height="1" width="1"/> http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/1lrZtSWEfRex Samuel Alba shad42 Samuel Alba http://shad.cc/2010/02/19/adding-virtual-host-support-to-webpy Thu, 04 Feb 2010 12:53:00 -0800 Exploiter le SIP de sa Freebox http://feedproxy.google.com/~r/shadsblog/~3/eo9YC3Zf8VM/exploiter-le-sip-de-sa-freebox http://shad.cc/2010/02/04/exploiter-le-sip-de-sa-freebox <p> <p>J'ai commenc&eacute; &agrave; jouer r&eacute;cemment avec le compte <a href="http://fr.wikipedia.org/wiki/Session_Initiation_Protocol">SIP</a> de ma <a href="http://www.free.fr/">Freebox</a>.<p /> Le compte SIP se param&egrave;tre via <a href="http://subscribe.free.fr/login/">le panel de gestion de Free</a>, dans l'onglet T&eacute;l&eacute;phonie. Deux options sont possibles:</p> <ol> <li>Rediriger les appels vers la Freebox</li> <li>Rediriger les appels vers le serveur SIP</li> </ol> <p>Dans le deuxieme cas, il vous faudra un t&eacute;l&eacute;phone IP si voulez conserver un t&eacute;l&eacute;phone physique connect&eacute; &agrave; la Freebox. Pour ma part, ayant un t&eacute;l&eacute;phone analogique standard, je redirige les appels vers la Freebox. J'utilise donc le serveur SIP uniquement pour passer des appels, et non en recevoir.<p /> Il existe de <a href="http://en.wikipedia.org/wiki/List_of_SIP_software#SIP_clients">nombreux clients SIP</a>. J'utilise <a href="http://www.linphone.org/">Linphone</a> sur Linux que je trouve l&eacute;ger et stable.<p /> Un point interessant, le serveur SIP est accessible de l'exterieur, autrement dit, vous pouvez appeler en illimit&eacute;s sur des fixes en France et dans certains pays depuis n'importe o&ugrave; en utilisant votre compte SIP Freephonie.<p /> De plus, si vous &ecirc;tes l'heureux possesseur d'un iPhone (ou tout autre t&eacute;l&eacute;phone sur Symbian, Windows Mobile ou Android), il vous suffit d'installer un client SIP (j'utilise <a href="http://itunes.apple.com/app/isipsimple-simple-basic-sip/id347525679">iSipSimple</a> sur iPhone) et de solliciter votre forfait data illimit&eacute; (ou pas) pour passer vos appels vers les fixes tout en utilisant votre g&eacute;n&eacute;reux forfait Free.<p /> Attention aux appels vers les mobiles qui ne seraient pas avantageux.</p> </p> <p><a href="http://shad.cc/2010/02/04/exploiter-le-sip-de-sa-freebox">Permalink</a> </p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=eo9YC3Zf8VM:Agk4zQkqxzY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=eo9YC3Zf8VM:Agk4zQkqxzY:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=eo9YC3Zf8VM:Agk4zQkqxzY:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=eo9YC3Zf8VM:Agk4zQkqxzY:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=eo9YC3Zf8VM:Agk4zQkqxzY:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=eo9YC3Zf8VM:Agk4zQkqxzY:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=eo9YC3Zf8VM:Agk4zQkqxzY:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=I9og5sOYxJI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/shadsblog/~4/eo9YC3Zf8VM" height="1" width="1"/> http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/1lrZtSWEfRex Samuel Alba shad42 Samuel Alba http://shad.cc/2010/02/04/exploiter-le-sip-de-sa-freebox Wed, 06 Jan 2010 12:23:00 -0800 How to auto-update Chromium on Mac OS X, Linux and other http://feedproxy.google.com/~r/shadsblog/~3/qT_oR1clMbs/how-to-auto-update-chromium-on-mac-os-x-linux-and-other http://shad.cc/2010/01/06/how-to-auto-update-chromium-on-mac-os-x-linux-and-other <p> I want to try to use Chromium as my first web browser. But for the moment, Chromium suffers from a lack of package maintaining though it targets developers. On my Gentoo Linux, I let portage to handle my Chromium version. But I also use Mac OS X at work, so I have written a little shell script to auto update my Chromium.app. Put the content of this scripts wherever you want and make it executable ($&gt; chmod 755 chromium_update.sh). <div class="CodeRay"> <div class="code"><pre>#!/bin/sh # Chromium update script # - by shad &lt;shad@zaphod.eu&gt; # mac | linux | ... OS=mac LATEST=$(wget -q -O - http://build.chromium.org/buildbot/snapshots/chromium-rel-${OS}/LATEST) INSTALL_DIR=/Applications TMP=&quot;/tmp/update-chrome-$RANDOM&quot; ( mkdir $TMP ; cd $TMP echo Download... wget -q -O chrome.zip http://build.chromium.org/buildbot/snapshots/chromium-rel-${OS}/${LATEST}/chrome-${OS}.zip if [ $? -ne 0 ] ; then echo Cannot update. exit 1 fi echo Unzip... unzip -qq chrome.zip echo Copying... rm -rf &quot;${INSTALL_DIR}/Chromium.app&quot; mv chrome-$OS/Chromium.app &quot;$INSTALL_DIR&quot; ) rm -rf $TMP Then, set a crontab rule to choose the update interval ($&gt; crontab -e). Mine runs every day at 12:00.</pre></div> </div> <div class="CodeRay"> <div class="code"><pre># Run Chromium update script every day at 12:00 00 12 * * * /Users/shad/mbin/chromium_update.sh</pre></div> </div> I hope it will be useful for someone as much as for me. </p> <p><a href="http://shad.cc/2010/01/06/how-to-auto-update-chromium-on-mac-os-x-linux-and-other">Permalink</a> </p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=qT_oR1clMbs:vF0QddnuOWE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=qT_oR1clMbs:vF0QddnuOWE:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=qT_oR1clMbs:vF0QddnuOWE:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=qT_oR1clMbs:vF0QddnuOWE:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=qT_oR1clMbs:vF0QddnuOWE:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=qT_oR1clMbs:vF0QddnuOWE:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=qT_oR1clMbs:vF0QddnuOWE:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=I9og5sOYxJI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/shadsblog/~4/qT_oR1clMbs" height="1" width="1"/> http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/1lrZtSWEfRex Samuel Alba shad42 Samuel Alba http://shad.cc/2010/01/06/how-to-auto-update-chromium-on-mac-os-x-linux-and-other Fri, 30 Oct 2009 22:05:00 -0700 CirruxCache: speeds up your HTTP app using Google Appengine as a CDN http://feedproxy.google.com/~r/shadsblog/~3/zUKKWIIIG-Y/cirruxcache-speeds-up-your-http-app-using-google-appengine-as-a-cdn http://shad.cc/2009/10/30/cirruxcache-speeds-up-your-http-app-using-google-appengine-as-a-cdn <p> <p>It is a great moment, for the first time since I have started to work at <a href="http://www.zoomorama.com/">Zoomorama</a>, I have just released as open-source an important part of our server platform.<p /> <a href="/post/Speed-up-HTTP-delivering-using-Google-AppEngine">I previously explained</a> how to use Google AppEngine as a Content Delivery Network (CDN). CirruxCache project concretizes this idea. I released the first version based as the one we use in production.<p /> Here is the features it currently supports:</p> <ul> <li>honor Cache-Control</li> <li>cache TTL override</li> <li>several POP (Point Of Presence) configuration mapped on custom base-url</li> <li>ignore query string</li> <li>POST forwarding</li> <li>expired entries garbage collection</li> <li>extensibility</li> </ul> <p><br /> CirruxCache is not documented at the moment even if you would be able to use it after reading the comments in the app.py file. I'll document this app in the next few days, but if you need more documentation, don't hesitate to contact me.<p /> <a href="http://cirrux.org/cache/">The project website.</a></p> </p> <p><a href="http://shad.cc/2009/10/30/cirruxcache-speeds-up-your-http-app-using-google-appengine-as-a-cdn">Permalink</a> </p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=zUKKWIIIG-Y:ln3FiJqb8zE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=zUKKWIIIG-Y:ln3FiJqb8zE:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=zUKKWIIIG-Y:ln3FiJqb8zE:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=zUKKWIIIG-Y:ln3FiJqb8zE:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=zUKKWIIIG-Y:ln3FiJqb8zE:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=zUKKWIIIG-Y:ln3FiJqb8zE:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=zUKKWIIIG-Y:ln3FiJqb8zE:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=I9og5sOYxJI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/shadsblog/~4/zUKKWIIIG-Y" height="1" width="1"/> http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/1lrZtSWEfRex Samuel Alba shad42 Samuel Alba http://shad.cc/2009/10/30/cirruxcache-speeds-up-your-http-app-using-google-appengine-as-a-cdn Thu, 30 Jul 2009 15:16:00 -0700 Speed up HTTP delivering using Google AppEngine http://feedproxy.google.com/~r/shadsblog/~3/dC3OZtffA2M/peed-up-http-delivering-using-google-appengine http://shad.cc/2009/07/30/peed-up-http-delivering-using-google-appengine <p> <div class='p_embed p_image_embed'> <img alt="" src="https://www.google.com/accounts/ah/appengine.jpg" /> </div> Google AppEngine provides an high-level cloud service which means that your application will be distributed automatically on top of the Google platform. All of your code will depends on the AppEngine SDK, so it could be risky to develop complex application on it. I develop a webservice application for content delivering and content publishing at <a href="http://www.zoomorama.com/">Zoomorama</a>. We currently use Akamai CDN as a simple cache layer to improve data delivering accross the world. It is interesting for me to use AppEngine in the same way: without changing anything on my existing code base. I have found some posts on blogs dealing with this AppEngine usage, but they are not focused on dynamic HTTP caching like a real CDN. Principle is very simple, all HTTP requests on my AppEngine application will be copied to the AppEngine Datastore. Moreover data which are delivered through AppEngine are cached by AppEngine servers. The code below is a tiny proof of concept: <div class="CodeRay"> <div class="code"><pre># HTTP caching on Google App Engine # - by shad &lt;shad@zaphod.eu&gt; # import web # webpy 0.3x from google.appengine.ext import db from google.appengine.api import urlfetch origin = 'http://my.website.com' urls = ( '(/.*)', 'Root' ) class Cache(db.Model): data = db.BlobProperty(default=None) headers = db.ListProperty(str) class Root(object): def GET(self, request): cache = self.readCache(request) if cache is None: cache = self.writeCache(request) for h in cache.headers: print h return cache.data def readCache(self, key): cache = cache = Cache.get_by_key_name(key) if cache: return cache def writeCache(self, request): url = origin + request response = urlfetch.Fetch(url=url) if response.status_code != 200: raise web.NotFound() cache = Cache(key_name=request) cache.data = db.Blob(response.content) cache.headers = [] for k, v in response.headers.iteritems(): cache.headers.append('%s: %s' % (k, v)) cache.put() return cache if __name__ == '__main__' app = web.application(urls, globals()) app.cgirun() I use webpy to depends on the AppEngine SDK as less as possible.</pre></div> </div> I have almost finished the production version of this application. I am doing some performance tests. This application is closed source for now. But I am going to release the code source in few weeks. This version will include: <ul> <li>Fetch from Memcache (about 10 times faster).</li> <li>Headers forwarding.</li> <li>Read "Cache-Control" and "Expires" to define a TTL (rfc 2616).</li> <li>Multi origins (according to url mount points).</li> <li>Other small features (force TTL, ignore query string, etc...).</li> </ul> It is important to note that AppEngine does not keep running instances of your application (your CGI is distributed and it is executed on demand). So this application have to start very quickly (no configuration file, no dynamic generation, etc...). </p> <p><a href="http://shad.cc/2009/07/30/peed-up-http-delivering-using-google-appengine">Permalink</a> </p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=dC3OZtffA2M:UD2rxr5FBHQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=dC3OZtffA2M:UD2rxr5FBHQ:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=dC3OZtffA2M:UD2rxr5FBHQ:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=dC3OZtffA2M:UD2rxr5FBHQ:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=dC3OZtffA2M:UD2rxr5FBHQ:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=dC3OZtffA2M:UD2rxr5FBHQ:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=dC3OZtffA2M:UD2rxr5FBHQ:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=I9og5sOYxJI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/shadsblog/~4/dC3OZtffA2M" height="1" width="1"/> http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/1lrZtSWEfRex Samuel Alba shad42 Samuel Alba http://shad.cc/2009/07/30/peed-up-http-delivering-using-google-appengine Wed, 01 Jul 2009 19:20:00 -0700 Generates your C++ bindings easily with SWIG http://feedproxy.google.com/~r/shadsblog/~3/y6DHqaSyJL4/ake-your-c-bindings-easily-with-swig http://shad.cc/2009/07/01/ake-your-c-bindings-easily-with-swig <p> Today, I have to develop a client library. This client library aims to allow users to use my storage webservice app more easily. Mainly to avoid them to read my HTTP Rest API documentation. I want to target the most used languages, and of course, I don't want to develop the same library for each languages. The main reason is that my client library is a draft for the moment, and I want to make changes on the client API over the time. This library is very high level, so I take only the HTTP core class for the example: <div class="CodeRay"> <div class="code"><pre>#ifndef __HTTP_H__ #define __HTTP_H__ #include &lt;iostream&gt; #include &lt;fstream&gt; #include &lt;string&gt; #include &lt;map&gt; #include &lt;vector&gt; #include &lt;exception&gt; #include &lt;curl/curl.h&gt; namespace HTTP { class Error : public std::exception { private: std::string _message; public: Error(const std::string &amp;msg) : _message(&quot;HTTPError: &quot;) { _message.append(msg); } virtual const char* what() const throw() { return _message.c_str(); } virtual ~Error() throw() {} }; class Response { private: friend class Request; std::map&lt;std::string, std::string&gt; _headers; std::string _version; std::string _code; std::string _message; std::string _body; void _parseHeaderLine(const std::string &amp;headerData); Response() {} public: const std::map&lt;std::string, std::string&gt; &amp;getHeaders() const { return _headers; } const std::string &amp;getVersion() const { return _version; } const std::string &amp;getCode() const { return _code; } const std::string &amp;getMessage() const { return _message; } const std::string &amp;getBody() const { return _body; } friend std::ostream&amp; operator&lt;&lt;(std::ostream &amp;out, const Response &amp;resp) { std::map&lt;std::string, std::string&gt;::const_iterator it, ite = resp._headers.end(); for (it = resp._headers.begin(); it != ite; ++it) out &lt;&lt; it-&gt;first &lt;&lt; &quot;: &quot; &lt;&lt; it-&gt;second &lt;&lt; std::endl; return out; } }; class Request { private: std::string _host; unsigned int _port; CURL *_curl; struct curl_slist *_headerList; Response _response; std::ofstream _outFile; std::ifstream _inFile; std::string _credentials; std::vector&lt;char&gt; _buffer; void _request(const std::string &amp;uri); public: Request(const std::string &amp;host, const unsigned int port = 80); virtual ~Request(); virtual void setHeader(const std::string &amp;name, const std::string &amp;value); virtual void setCredentials(const std::string &amp;login, const std::string &amp;passwd); virtual void get(const std::string &amp;uri, const std::string &amp;outFile = &quot;&quot;); virtual void post(const std::string &amp;uri, const std::string &amp;data); virtual void postFile(const std::string &amp;uri, const std::string &amp;inFile); virtual void setVerbose(); virtual void setHost(const std::string &amp;host, const unsigned int port = 80); static size_t writeHeaderCallback(void *ptr, size_t size, size_t nmemb, void *stream); static size_t writeCallback(void *ptr, size_t size, size_t nmemb, void *stream); static size_t readCallback(void *ptr, size_t size, size_t nmemb, void *stream); virtual const Response &amp;getResponse() const { return _response; } }; } #endif /* !__HTTP_H__ */ SWIG uses interface files to parse and to generate bindings. IMHO, a good thing is to have an only one interface file to add language bindings much easier.</pre></div> </div> <a href="http://www.swig.org/Doc1.3/Introduction.html#Introduction_nn5">Here is some documentation on SWIG interface syntax.</a> First, here is my interface file (http.i): <div class="CodeRay"> <div class="code"><pre>%module http %include stl.i %include exception.i %exception { try { $function } catch (std::exception &amp;e) { SWIG_exception(SWIG_RuntimeError, e.what()); } catch (...) { SWIG_exception(SWIG_RuntimeError, &quot;Unknown exception&quot;); } } %include &quot;http.h&quot; %{ #include &quot;http.h&quot; %} All C++ code between %{ ... }% tags will be copied during generation. SWIG provides a lot of interface files. Some of them are language-dependant. So I have written a generic exception handler to use the same interface file for all targetted languages.</pre></div> </div> Finally, I just have to write a shell script to build each languages with the same http.i: <div class="CodeRay"> <div class="code"><pre>#!/bin/sh CFLAGS_python_Darwin=-I/usr/include/python2.5 LDFLAGS_python_Darwin=&quot;-dynamiclib -lpython2.5 -o _zws.so&quot; CFLAGS_java_Darwin=-I/System/Library/Frameworks/JavaVM.framework/Headers LDFLAGS_java_Darwin=&quot;-dynamiclib -o libzws.dylib&quot; CFLAGS_ruby_Darwin=-I/System/Library/Frameworks/Ruby.framework/Headers LDFLAGS_ruby_Darwin=&quot;-dynamiclib -lruby -o zws.bundle&quot; CFLAGS_php_Darwin=&quot;$(php-config --includes)&quot; LDFLAGS_php_Darwin=&quot;-bundle -o zws.so&quot; if [ $# -lt 1 ] ; then echo Usage $0 language exit 1 fi LANG=$1 ROOT=$(dirname $0) OSNAME=$(uname -s) ARCH=$(uname -p) # All the source files SRC=&quot;http.cpp&quot; ( DIR=${LANG}_${OSNAME}_${ARCH} rm -rf ${DIR}/* mkdir -p ${ROOT}/${DIR} cd ${ROOT}/${DIR} # This options will be always added to the compilation/linking CFLAGS+=&quot;-undefined suppress -flat_namespace&quot; LDFLAGS+=&quot;-lcurl&quot; CFLAGS+=&quot; $(eval echo \$CFLAGS_${LANG}_${OSNAME})&quot; LDFLAGS+=&quot; $(eval echo \$LDFLAGS_${LANG}_${OSNAME})&quot; swig -I./src -${LANG} -c++ -o wrapper.cpp -outdir . ./http.i g++ ${CFLAGS} ${SRC} wrapper.cpp ${LDFLAGS} ) Notes:</pre></div> </div> <ul> <li>./script.sh python to generate python bindings.</li> <li>Some of the code below has been modified for the example, the most important thing to understand is the way of use.</li> <li>I work on Mac OS X, so you just have to add (CFLAGS|LDFLAGS)_&lt;lang&gt;_&lt;os&gt; for other configs.</li> <li>It would be cleaner with a Makefile ;)</li> </ul> Cheers ! </p> <p><a href="http://shad.cc/2009/07/01/ake-your-c-bindings-easily-with-swig">Permalink</a> </p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=y6DHqaSyJL4:_7YJD9Wm8E8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=y6DHqaSyJL4:_7YJD9Wm8E8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=y6DHqaSyJL4:_7YJD9Wm8E8:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=y6DHqaSyJL4:_7YJD9Wm8E8:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=y6DHqaSyJL4:_7YJD9Wm8E8:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=y6DHqaSyJL4:_7YJD9Wm8E8:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=y6DHqaSyJL4:_7YJD9Wm8E8:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=I9og5sOYxJI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/shadsblog/~4/y6DHqaSyJL4" height="1" width="1"/> http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/1lrZtSWEfRex Samuel Alba shad42 Samuel Alba http://shad.cc/2009/07/01/ake-your-c-bindings-easily-with-swig Fri, 03 Apr 2009 15:16:00 -0700 How to handle SSL certificates smartly in Firefox http://feedproxy.google.com/~r/shadsblog/~3/nnLo0nJNXqI/how-to-smartly-manage-ssl-certificates-in-firefox http://shad.cc/2009/04/03/how-to-smartly-manage-ssl-certificates-in-firefox <p> <p>SSL certificates validation is often annoying. In most of cases, the certificate is not acceptable by Firefox because it is self-signed by the server. Some of personal blogs does not have their certificate signed by a known authority.<p /> I think Perspectives is a good solution for this problem, which does not concern only Firefox.<p /> According to perspectives website:<br /> Perspectives is a new approach to help clients securely identify Internet servers in order to avoid "man-in-the-middle" attacks. Perspectives is simple and cheap compared to existing approaches because it automatically builds a robust database of network identities using lightweight network probing by "network notaries" located in multiple vantage points across the Internet.<p /> Firefox extension: <a href="http://www.cs.cmu.edu/~perspectives/firefox.html">http://www.cs.cmu.edu/~perspectives/firefox.html</a></p> </p> <p><a href="http://shad.cc/2009/04/03/how-to-smartly-manage-ssl-certificates-in-firefox">Permalink</a> </p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=nnLo0nJNXqI:ZzKxCpzuLYA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=nnLo0nJNXqI:ZzKxCpzuLYA:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=nnLo0nJNXqI:ZzKxCpzuLYA:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=nnLo0nJNXqI:ZzKxCpzuLYA:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=nnLo0nJNXqI:ZzKxCpzuLYA:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=nnLo0nJNXqI:ZzKxCpzuLYA:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=nnLo0nJNXqI:ZzKxCpzuLYA:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=I9og5sOYxJI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/shadsblog/~4/nnLo0nJNXqI" height="1" width="1"/> http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/1lrZtSWEfRex Samuel Alba shad42 Samuel Alba http://shad.cc/2009/04/03/how-to-smartly-manage-ssl-certificates-in-firefox Sun, 18 Jan 2009 20:28:00 -0800 FreeBSD on the ASUS Eee Box using an USB flash drive http://feedproxy.google.com/~r/shadsblog/~3/fBEOObbARII/freebsd-on-the-asus-eee-box http://shad.cc/2009/01/18/freebsd-on-the-asus-eee-box <p> <p>I wanted my personal server to be closer to me. So I invested few days ago in the Asus Eee Box, thinking it is the best configuration for a light server at home.<p /> I moved this blog and all my services from my dedicated server to my new one.<p /> To setup FreeBSD on this kind of machine, you have two ways to do it:</p> <ul> <li><a href="http://www.freebsd.org/doc/en_US.ISO8859-1/articles/pxe/article.html">Install FreeBSD using a pxeboot image and a dhcp server.</a></li> <li>Install FreeBSD using a bootable USB flash drive.</li> </ul> <p><br /> Creating a bootable USB flash drive by using the original ISO image is a bit annoying if you haven't got a FreeBSD station yet. I have been using the <a href="http://sites.google.com/site/kengell/freebsd-boot-iso-on-usb">fbsd2img.sh script</a>,<p /> I share my USB flash drive image: <a href="http://zaphod.eu/pub/7.1-RELEASE-i386-bootonly.img">7.1-RELEASE-i386-bootonly.img</a>.<br /> To setup the USB flash drive, use "dd" (/dev/XXX is the device of your USB flash drive):</p> <div class="CodeRay"> <div class="code"><pre>dd if=7.1-RELEASE-i386-bootonly.img of=/dev/XXX bs=1m</pre></div> </div> <p><br /> <a href="http://zaphod.eu/pub/eeebox.jpg">Here is the result of the server hosting this blog</a> :)</p> </p> <p><a href="http://shad.cc/2009/01/18/freebsd-on-the-asus-eee-box">Permalink</a> </p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=fBEOObbARII:Ir5CpNEKrE0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=fBEOObbARII:Ir5CpNEKrE0:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=fBEOObbARII:Ir5CpNEKrE0:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=fBEOObbARII:Ir5CpNEKrE0:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=fBEOObbARII:Ir5CpNEKrE0:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=fBEOObbARII:Ir5CpNEKrE0:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=fBEOObbARII:Ir5CpNEKrE0:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=I9og5sOYxJI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/shadsblog/~4/fBEOObbARII" height="1" width="1"/> http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/1lrZtSWEfRex Samuel Alba shad42 Samuel Alba http://shad.cc/2009/01/18/freebsd-on-the-asus-eee-box Fri, 18 Jul 2008 11:04:00 -0700 Subversion repository corruption: something to try when svnadmin recover does not work. http://feedproxy.google.com/~r/shadsblog/~3/P8c_8jh_k7U/subversion-repository-corruption-something-to-try-when-svnadmin-recover-does-not-work http://shad.cc/2008/07/18/subversion-repository-corruption-something-to-try-when-svnadmin-recover-does-not-work <p> I had the wrong habit to keep my old projects in a subversion repository. It's not the good way of keeping code safe. svnadmin recover works when there is no corruption in your repository. If you have an old corrupted repository that you can't recover, you can first try a berkeley db recovery: <div class="CodeRay"> <div class="code"><pre>cd /var/svn/myrepos dbX.X_recover</pre></div> </div> X.X is the berkelay db version of the repository. If svnadmin recover and db_recover don't work, try the solution below, it worked for me. You have to know the database version: <div class="CodeRay"> <div class="code"><pre>REPOS_PATH=&quot;/var/svn/myrepos&quot; DB_VERSION=&quot;4.3&quot; cd ${REPOS_PATH}/db rm log.* __db.* mv changes changes.old mv copies copies.old mv nodes nodes.old mv representations representations.old mv revisions revisions.old mv strings strings.old mv transactions transactions.old mv uuids uuids.old mv lock-tokens lock-tokens.old mv locks locks.old db${DB_VERSION}_dump changes.old | db${DB_VERSION}_load changes db${DB_VERSION}_dump copies.old | db${DB_VERSION}_load copies db${DB_VERSION}_dump nodes.old | db${DB_VERSION}_load nodes db${DB_VERSION}_dump representations.old | db${DB_VERSION}_load representations db${DB_VERSION}_dump revisions.old | db${DB_VERSION}_load revisions db${DB_VERSION}_dump strings.old | db${DB_VERSION}_load strings db${DB_VERSION}_dump transactions.old | db${DB_VERSION}_load transactions db${DB_VERSION}_dump uuids.old | db${DB_VERSION}_load uuids db${DB_VERSION}_dump lock-tokens.old | db${DB_VERSION}_load lock-tokens db${DB_VERSION}_dump locks.old | db${DB_VERSION}_load locks svnadmin recover .. If binaries dbX.X_dump and dbX.X_load does not exist, you have to compile a old version of subversion with the berkeley database corresponding.</pre></div> </div> <em>Thanks to dmp.</em> Link: <a href="http://svn.haxx.se/users/archive-2005-07/0576.shtml">http://svn.haxx.se/users/archive-2005-07/0576.shtml</a> </p> <p><a href="http://shad.cc/2008/07/18/subversion-repository-corruption-something-to-try-when-svnadmin-recover-does-not-work">Permalink</a> </p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=P8c_8jh_k7U:AZlwlyeHnBo:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=P8c_8jh_k7U:AZlwlyeHnBo:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=P8c_8jh_k7U:AZlwlyeHnBo:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=P8c_8jh_k7U:AZlwlyeHnBo:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=P8c_8jh_k7U:AZlwlyeHnBo:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=P8c_8jh_k7U:AZlwlyeHnBo:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=P8c_8jh_k7U:AZlwlyeHnBo:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=I9og5sOYxJI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/shadsblog/~4/P8c_8jh_k7U" height="1" width="1"/> http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/1lrZtSWEfRex Samuel Alba shad42 Samuel Alba http://shad.cc/2008/07/18/subversion-repository-corruption-something-to-try-when-svnadmin-recover-does-not-work Thu, 17 Jul 2008 14:21:00 -0700 Gmail-Notify improvements and a modified behavior http://feedproxy.google.com/~r/shadsblog/~3/QrbIAyNrb2w/gmail-notify http://shad.cc/2008/07/17/gmail-notify <p> <a href="http://gmail-notify.sourceforge.net/">Gmail-notify</a> is a small program written in Python. I use it because it is light and it just do what I want. I am a regular user of the firefox extension <a href="https://addons.mozilla.org/en-US/firefox/addon/173">gmail-notifyer</a> and I was uncomfortable with the Gmail-notify behavior, so I wrote a little patch to make it more like I want. I also added the possibility to execute a command when a new message arrive. I use it to play a sound (aplay ~/sounds/mail.wav). I don't know your habits but maybe you could enjoy my modifications. Here is a small description: <ul> <li>A click on the event box close it.</li> <li>A click on tray icon open the mailbox.</li> <li>Mailbox is now open as HTTPS.</li> <li>A command can be executed when a new mail is received (like playing a sound).</li> </ul> To use my modifications, <a href="http://zaphod.eu/pub/gmail-notify-1.6.1.1.patch">download my patch</a>, and apply it to gmail-notify-1.6.1.1: <div class="CodeRay"> <div class="code"><pre>wget http://garr.dl.sourceforge.net/sourceforge/gmail-notify/gmail-notify-1.6.1.1.tar.gz wget http://zaphod.eu/pub/gmail-notify-1.6.1.1.patch tar zxvf gmail-notify-1.6.1.1.tar.gz (cd gmail-notify ; patch -p1 &lt; ../gmail-notify-1.6.1.1.patch) rm gmail-notify-1.6.1.1.tar.gz</pre></div> </div> Then run gmail-notify. <div class="CodeRay"> <div class="code"><pre>gmail-notify/notifier.py</pre></div> </div> </p> <p><a href="http://shad.cc/2008/07/17/gmail-notify">Permalink</a> </p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=QrbIAyNrb2w:LdxszAL-Emg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=QrbIAyNrb2w:LdxszAL-Emg:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=QrbIAyNrb2w:LdxszAL-Emg:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=QrbIAyNrb2w:LdxszAL-Emg:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=QrbIAyNrb2w:LdxszAL-Emg:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=QrbIAyNrb2w:LdxszAL-Emg:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=QrbIAyNrb2w:LdxszAL-Emg:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=I9og5sOYxJI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/shadsblog/~4/QrbIAyNrb2w" height="1" width="1"/> http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/1lrZtSWEfRex Samuel Alba shad42 Samuel Alba http://shad.cc/2008/07/17/gmail-notify Wed, 09 Jul 2008 00:01:00 -0700 Ushare on Gentoo Linux http://feedproxy.google.com/~r/shadsblog/~3/jziSxAOBcrA/ushare-on-gentoo http://shad.cc/2008/07/09/ushare-on-gentoo <p> Ushare is a UPnP media server on linux. I use it to browse media files from my Xbox. There is no official gentoo ebuild. Sunrise Gentoo overlay provides an ebuild for Ushare, it requires some modifications to be used. I noticed some problems: <ol> <li>Ushare daemon is configured to run as root. Without being paranoid, I don't want to entrust a root daemon which manipulate my precious media directory.</li> <li>Boot script in init.d directory is written for debian, so it does not work at all on Gentoo.</li> <li>Default configuration file contains some wrong variable names. So this configuration directives are ignored.</li> </ol> I rewrote the init.d script to work on Gentoo and to launch ushare daemon as nobody user. To sum up, Ushare can be deployed rapidly as follow: 1. Checkout Sunrise overlay with layman <div class="CodeRay"> <div class="code"><pre>emerge -v layman layman -a sunrise echo source /usr/portage/local/layman/make.conf &gt;&gt; /etc/make.conf echo media-video/ushare &gt;&gt; /etc/portage/package.keywords emerge -v ushare 2. Replace the Ushare boot script /etc/init.d/ushare by my script:</pre></div> </div> <div class="CodeRay"> <div class="code"><pre>#!/sbin/runscript #- by shad DAEMON=&quot;/usr/bin/ushare&quot; NAME=&quot;ushare&quot; CONFIGFILE=&quot;/etc/ushare.conf&quot; OPTS=&quot;-f $CONFIGFILE&quot; PIDFILE=&quot;/var/run/ushare.pid&quot; USER=&quot;nobody&quot; [ -x $DAEMON ] || exit 0 start() { ebegin &quot;Starting $NAME&quot; start-stop-daemon --start --quiet --background --pidfile $PIDFILE \ --make-pidfile --exec /bin/su -- --command &quot;$DAEMON $OPTS&quot; $USER eend $? } stop() { ebegin &quot;Stopping $NAME&quot; start-stop-daemon --stop --quiet --pidfile $PIDFILE eend $? } 3. The last thing to check is the name of configuration variables in /etc/ushare.conf. Make sure each variable starts with the &quot;USHARE_&quot; prefix.</pre></div> </div> Then, <div class="CodeRay"> <div class="code"><pre>/etc/init.d/ushare start</pre></div> </div> and watch your favorite movie on your Xbox 360 :) </p> <p><a href="http://shad.cc/2008/07/09/ushare-on-gentoo">Permalink</a> </p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=jziSxAOBcrA:6RgvVtVvreU:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=jziSxAOBcrA:6RgvVtVvreU:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=jziSxAOBcrA:6RgvVtVvreU:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=jziSxAOBcrA:6RgvVtVvreU:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/shadsblog?i=jziSxAOBcrA:6RgvVtVvreU:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=jziSxAOBcrA:6RgvVtVvreU:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/shadsblog?a=jziSxAOBcrA:6RgvVtVvreU:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/shadsblog?d=I9og5sOYxJI" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/shadsblog/~4/jziSxAOBcrA" height="1" width="1"/> http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/1lrZtSWEfRex Samuel Alba shad42 Samuel Alba http://shad.cc/2008/07/09/ushare-on-gentoo en-us