<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">

	<title type="text" xml:lang="en" />
	
 	<link type="text" href="http://jfoucher.com" rel="alternate" />
	<updated>Fri Jun 14 13:34:53 +0200 2013</updated>
	<id>http://jfoucher.com</id>
	<author>
		<name>Jonathan Foucher</name>
	</author>
	<rights>Copyright (c) 2004-2011,Jonathan Foucher; Some rights reserved.</rights>

	
	<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/GeekyNuggets" /><feedburner:info uri="geekynuggets" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="license" type="text/html" href="http://creativecommons.org/licenses/by-nc-nd/3.0/" /><feedburner:emailServiceId>GeekyNuggets</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><entry>
		<title>How I built running shoes for my whole family in one sunday afternoon (Huarache sandals)</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/QeBztCui_zs/building-and-using-minimalist-running-shoes.html" />
		<updated>Sun May 26 21:17:07 +0200 2013</updated>
		<id>http://jfoucher.com/2013/05/building-and-using-minimalist-running-shoes</id>
		<content type="html">&lt;p&gt;Some time ago, &lt;a href="http://diegosantamarta.com"&gt;Diego Santamarta&lt;/a&gt; casually mentioned that the shoes he was wearing were not regular flip flops, but rather some kind of sandal which I had never heard about. "Oh ok" was my less than enthusiastic answer. In the meantime, and even before, I had been reading about barefoot running, even though I had never run more than a few hundred meters without panting uncontrollably. Yes, 15 years smoking does take it's toll. After two years tobacco free, I feel I'm only now starting to recover.&lt;/p&gt;

&lt;p&gt;Anyway, I had dismissed barefoot running as something that I would love to do&amp;nbsp;&amp;mdash;&amp;nbsp;and probably the only way that I would ever run for pleasure&amp;nbsp;&amp;mdash;&amp;nbsp;but that seemed very uncomfortable bordering on dangerous. Two days ago, that same Diego Santamarta posts to facebook a link about those sandals as used by barefoot runners to protect their feet on difficult terrain.&lt;/p&gt;

&lt;h3&gt;Documentation and materials&lt;/h3&gt;

&lt;p&gt;I almost immediately started &lt;a href="http://bit.ly/10znWIx"&gt;reading about them&lt;/a&gt;, watching &lt;a href="http://bit.ly/10WcB48%20or%20[instructables](http://bit.ly/10zo22R"&gt;youtube videos&lt;/a&gt; explaining how to build them. I had an old tire in the growing "to throw away" pile which I never get around to bringing to the recycling center, so that was the main part of the material sorted. I also have some polypropylene cord (the blue one used to tie straw bales and some black one) which could be used as laces. As will be seen later this is not comfortable nor durable so I used some more elaborate string for the laces.&lt;/p&gt;

&lt;p&gt;Trace your foot on paper and locate the holes as indicated in one of these guides.&lt;/p&gt;

&lt;h3&gt;Cutting the sole&lt;/h3&gt;

&lt;p&gt;Now the real work begins. We will need to hack at that tire, and it truly is tiresome work. I had some tin snips on hand which I thought would be perfect for  the job. They are in fact totally useless. I did the job with a hacksaw to cut through the metal ring where the tire meets the wheel, and then one of my trusty &lt;a href="https://en.wikipedia.org/wiki/Opinel"&gt;Opinels&lt;/a&gt; to cut through the reinforced rubber outwall. If the knife is kept sharp, this is actually fairly easy work.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Cutting the tire" src="/uploads/2013/05/cutting-tire.jpg" width="800" style="max-width: 100%;margin:0 auto;"/&gt;&lt;/p&gt;

&lt;p&gt;I cut some rough pieces from the outerwall, one from each side of the tire to match the curvature of the outerwall to the natural curve of each foot.&lt;/p&gt;

&lt;p&gt;You then trace the outline of your paper pattern on the pieces you just cut, enabling you to have perfect tire soles for your huarache sandals.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Matching sole to template" src="/uploads/2013/05/cutting-soles.jpg" width="800" style="max-width: 100%;margin:0 auto;"/&gt;&lt;/p&gt;

&lt;p&gt;I then used a small drill bit, around 5mm to drill the holes.&lt;/p&gt;

&lt;h3&gt;Putting the laces in places&lt;/h3&gt;

&lt;p&gt;The are many lacing systems that can be used, the one I used seemed simple enough, and can be slipped on and off easily.&lt;/p&gt;

&lt;p&gt;To pull the string through the holes, I used a piece of bent wire as a threader, and pliers to pull on it if need be. A &lt;a href="http://en.wikipedia.org/wiki/Figure-eight_knot"&gt;figure of 8 knot&lt;/a&gt; locks the string in the toe hole. the string then goes throught the outer hole, around the heel, through the inner whole, and ties around the front part of the lace&lt;/p&gt;

&lt;p&gt;&lt;img alt="Threading the cord" src="/uploads/2013/05/threading-cord.jpg" width="800" style="max-width: 100%;margin:0 auto;"/&gt;&lt;/p&gt;

&lt;p&gt;Here is the result: my son's sandals. He complained that they were not very comfortable though, so I changed the cord (which was too thin) and used a thicker braided one I had around, which is much more comfortable.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Huarache running sandal complete" src="/uploads/2013/05/huarache-running-sandal-kid.jpg" width="800" style="max-width: 100%;margin:0 auto;"/&gt;&lt;/p&gt;

&lt;p&gt;Once everyone had their sandals ready, I decided to go for a short run to try them out&lt;/p&gt;

&lt;h3&gt;Running&lt;/h3&gt;

&lt;p&gt;Please keep in mind that I was a heavy smoker for many years, have &lt;em&gt;never&lt;/em&gt; run unless obligated to, and never more than a few hundred meters.&lt;/p&gt;

&lt;p&gt;The first segment was downhill, and I had to readjust the shoes almost immediately, for the only time in the entire run.&lt;/p&gt;

&lt;p&gt;When I arrived at the first uphill segment I got out of breath quickly and decide to alternate running and fast walking for the rest of the outing. That worked out pretty good, and the running actually felt easier and easier. The shoes are superb. They are pretty comfortable, provide just the right amount of protection to avoid having to look out for every little piece of gravel and can be used to cross streams without fear of them becoming slippery.&lt;/p&gt;

&lt;p&gt;My calves started hurting at around the ten minute mark, I think from landing on the front portion of the feet. It only got worse from then on, and now I can barely walk, it feels like I have a continuous cramp in these muscles. The feet are in perfect condition though, I just feel that they have had a good workout.&lt;/p&gt;

&lt;p&gt;Can't wait to go out tomorrow for more!&lt;/p&gt;
&lt;a href="http://jfoucher.com/2013/05/building-and-using-minimalist-running-shoes.html"&gt;How I built running shoes for my whole family in one sunday afternoon (Huarache sandals)&lt;/a&gt; is a post by Jonathan Foucher at &lt;a
href="http://jfoucher.com"&gt;Geeky Nuggets&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=QeBztCui_zs:pRNoLhA1S7E:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=QeBztCui_zs:pRNoLhA1S7E:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=QeBztCui_zs:pRNoLhA1S7E:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/QeBztCui_zs" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2013/05/building-and-using-minimalist-running-shoes.html</feedburner:origLink></entry>
	
	<entry>
		<title>Installing PHP, Apache2 and nginx for faster websites</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/aJlBdjVeT8I/installing-apache-php-and-nginx-for-faster-websites.html" />
		<updated>Mon Apr 23 08:17:07 +0200 2012</updated>
		<id>http://jfoucher.com/2012/04/installing-apache-php-and-nginx-for-faster-websites</id>
		<content type="html">&lt;p&gt;My contract with my previous shared hosting contractor is coming to a close, and as they seem to have all but abandoned their business, I decided it was time to move away. I looked at using Amazon's EC2, but ultimately decided to go with Bhost, with which I'm fairly happy so far. To get some decent performance out of it, I planned to use Nginx as my web server&lt;/p&gt;

&lt;h3&gt;Keep using Apache as usual&lt;/h3&gt;

&lt;p&gt;All my websites are configured to work with apache, sometimes using fairly advanced rewrite rules, and a fair proportion of wordpress sites. So to save myself a ton of work I decided to just use Nginx as a proxy to apache and not reconfigure each site to use Nginx's rewrite rules.&lt;/p&gt;

&lt;h3&gt;Install required software&lt;/h3&gt;

&lt;p&gt;I'm using Ubuntu, but the steps below should be fairly easy to adapt to your distribution of choice. To install everything from scratch, just run &lt;code&gt;sudo apt-get install php5 apache2 mysql-server php5-mysql nginx&lt;/code&gt;. This installs mysql, Apache, PHP and Nginx&lt;/p&gt;

&lt;h3&gt;Configure Apache and Nginx&lt;/h3&gt;

&lt;p&gt;I created one bash script that creates the necessary virtual hosts files for Apache and Nginx, by taking a template a doing a search/replace with sed. Here is the apache virtual host template that goes into &lt;code&gt;/etc/apache2/sites-available&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="apache"&gt;&lt;span class="nt"&gt;&amp;lt;VirtualHost&lt;/span&gt; &lt;span class="s"&gt;*:8080&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nb"&gt;ServerAdmin&lt;/span&gt; webmaster@localhost
        &lt;span class="nb"&gt;ServerName&lt;/span&gt; template
        &lt;span class="nb"&gt;ServerAlias&lt;/span&gt; template www.template cdn.template cdn2.template
        &lt;span class="nb"&gt;DocumentRoot&lt;/span&gt; &lt;span class="sx"&gt;/var/www/template&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Directory&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nb"&gt;Options&lt;/span&gt; FollowSymLinks
                &lt;span class="nb"&gt;AllowOverride&lt;/span&gt; &lt;span class="k"&gt;None&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/Directory&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Directory&lt;/span&gt; &lt;span class="s"&gt;/var/www/template/&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nb"&gt;Options&lt;/span&gt; Indexes FollowSymLinks MultiViews
                &lt;span class="nb"&gt;AllowOverride&lt;/span&gt; &lt;span class="k"&gt;All&lt;/span&gt;
                &lt;span class="nb"&gt;Order&lt;/span&gt; allow,deny
                &lt;span class="nb"&gt;allow&lt;/span&gt; from &lt;span class="k"&gt;all&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/Directory&amp;gt;&lt;/span&gt;

        &lt;span class="nb"&gt;ScriptAlias&lt;/span&gt; &lt;span class="sx"&gt;/cgi-bin/&lt;/span&gt; &lt;span class="sx"&gt;/usr/lib/cgi-bin/&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Directory&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;/usr/lib/cgi-bin&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nb"&gt;AllowOverride&lt;/span&gt; &lt;span class="k"&gt;None&lt;/span&gt;
                &lt;span class="nb"&gt;Options&lt;/span&gt; +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                &lt;span class="nb"&gt;Order&lt;/span&gt; allow,deny
                &lt;span class="nb"&gt;Allow&lt;/span&gt; from &lt;span class="k"&gt;all&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/Directory&amp;gt;&lt;/span&gt;

        &lt;span class="nb"&gt;ErrorLog&lt;/span&gt; ${APACHE_LOG_DIR}/error.log

        &lt;span class="c"&gt;# Possible values include: debug, info, notice, warn, error, crit,&lt;/span&gt;
        &lt;span class="c"&gt;# alert, emerg.&lt;/span&gt;
        &lt;span class="nb"&gt;LogLevel&lt;/span&gt; &lt;span class="k"&gt;warn&lt;/span&gt;

        &lt;span class="nb"&gt;CustomLog&lt;/span&gt; ${APACHE_LOG_DIR}/access.log combined

    &lt;span class="nb"&gt;Alias&lt;/span&gt; &lt;span class="sx"&gt;/doc/&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/usr/share/doc/&amp;quot;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Directory&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;/usr/share/doc/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nb"&gt;Options&lt;/span&gt; Indexes MultiViews FollowSymLinks
        &lt;span class="nb"&gt;AllowOverride&lt;/span&gt; &lt;span class="k"&gt;None&lt;/span&gt;
        &lt;span class="nb"&gt;Order&lt;/span&gt; deny,allow
        &lt;span class="nb"&gt;Deny&lt;/span&gt; from &lt;span class="k"&gt;all&lt;/span&gt;
        &lt;span class="nb"&gt;Allow&lt;/span&gt; from &lt;span class="m"&gt;127.0.0.0/255&lt;/span&gt;.0.0.0 ::1/128
    &lt;span class="nt"&gt;&amp;lt;/Directory&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/VirtualHost&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You'll notice that Apache listens on port 8080. You need to change the port from 80 to 8080 in &lt;code&gt;/etc/apache2/ports.conf&lt;/code&gt; as well, this is what mine looks like after the change :&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="apache"&gt;&lt;span class="nb"&gt;NameVirtualHost&lt;/span&gt; *:8080
&lt;span class="nb"&gt;Listen&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;IfModule&lt;/span&gt; &lt;span class="s"&gt;mod_ssl.c&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;# If you add NameVirtualHost *:443 here, you will also have to change&lt;/span&gt;
    &lt;span class="c"&gt;# the VirtualHost statement in /etc/apache2/sites-available/default-ssl&lt;/span&gt;
    &lt;span class="c"&gt;# to &amp;lt;VirtualHost *:443&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;# Server Name Indication for SSL named virtual hosts is currently not&lt;/span&gt;
    &lt;span class="c"&gt;# supported by MSIE on Windows XP.&lt;/span&gt;
    &lt;span class="nb"&gt;Listen&lt;/span&gt; &lt;span class="m"&gt;443&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/IfModule&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;IfModule&lt;/span&gt; &lt;span class="s"&gt;mod_gnutls.c&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nb"&gt;Listen&lt;/span&gt; &lt;span class="m"&gt;443&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/IfModule&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Next up is the template for the default nginx site, which is much simpler and goes in &lt;code&gt;/etc/nginx/sites-available&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="nginx"&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;access_log&lt;/span&gt; &lt;span class="s"&gt;/var/log/nginx.access.log&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;error_log&lt;/span&gt; &lt;span class="s"&gt;/var/log/nginx.error.log&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="s"&gt;/var/www/template&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;index&lt;/span&gt; &lt;span class="s"&gt;index.php&lt;/span&gt; &lt;span class="s"&gt;index.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;template&lt;/span&gt; &lt;span class="s"&gt;*.template&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:8080&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;/\.(ht|git)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kn"&gt;deny&lt;/span&gt; &lt;span class="s"&gt;all&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;All that does is proxy everything to apache on localhost, port 8080&lt;/p&gt;

&lt;p&gt;So, our virtual host templates are ready, and if you only have one or two sites you could copy the contents to a new file by hand and change the word &lt;code&gt;template&lt;/code&gt; for your actual domain name / folder, but as I had quite a few sites to convert, I created a small bash script that takes car of it for me, by just calling it with the hostname:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nv"&gt;CMDLN_ARGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;$@&amp;quot;&lt;/span&gt; &lt;span class="c"&gt;# Command line arguments for this script&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;CMDLN_ARGS

&lt;span class="c"&gt;# Run this script as root if not already.&lt;/span&gt;
chk_root &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

 &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; ! &lt;span class="k"&gt;$(&lt;/span&gt; id -u &lt;span class="k"&gt;)&lt;/span&gt; -eq 0 &lt;span class="o"&gt;]&lt;/span&gt;; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="k"&gt;   &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Please enter your password.&amp;quot;&lt;/span&gt;
   &lt;span class="nb"&gt;exec &lt;/span&gt;sudo su -c &lt;span class="s2"&gt;&amp;quot;${0} ${CMDLN_ARGS}&amp;quot;&lt;/span&gt; &lt;span class="c"&gt;# Call this prog as root&lt;/span&gt;
   &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;  &lt;span class="c"&gt;# since we&amp;#39;re &amp;#39;execing&amp;#39; above, we wont reach this exit&lt;/span&gt;
              &lt;span class="c"&gt;# unless something goes wrong.&lt;/span&gt;
 &lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
chk_root
cat /etc/apache2/sites-available/template | sed &lt;span class="s2"&gt;&amp;quot;s/template/$1/g&amp;quot;&lt;/span&gt; |cat &amp;gt; /etc/apache2/sites-available/&lt;span class="nv"&gt;$1&lt;/span&gt;
ln -s /etc/apache2/sites-available/&lt;span class="nv"&gt;$1&lt;/span&gt; /etc/apache2/sites-enabled/&lt;span class="nv"&gt;$1&lt;/span&gt;
cat /etc/nginx/sites-available/template | sed &lt;span class="s2"&gt;&amp;quot;s/template/$1/g&amp;quot;&lt;/span&gt; |cat &amp;gt; /etc/nginx/sites-available/&lt;span class="nv"&gt;$1&lt;/span&gt;
ln -s /etc/nginx/sites-available/&lt;span class="nv"&gt;$1&lt;/span&gt; /etc/nginx/sites-enabled/&lt;span class="nv"&gt;$1&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -d /var/www/&lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;;
&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="k"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;host directory exists&amp;quot;&lt;/span&gt;;
&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="k"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;creating directory&amp;quot;&lt;/span&gt;
  mkdir &lt;span class="s2"&gt;&amp;quot;/var/www/$1&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
chown -R www-data:www-data /var/www/&lt;span class="nv"&gt;$1&lt;/span&gt;

/etc/init.d/apache2 restart
/etc/init.d/nginx restart
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Put this say in your home folder and give it executable permission with &lt;code&gt;chmod 755 new_host&lt;/code&gt; or whatever you named the file.&lt;/p&gt;

&lt;p&gt;Then run it with &lt;code&gt;./new_host example.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will create a folder in &lt;code&gt;/var/www/example.com&lt;/code&gt;, copy the updated template virtual host configuration to the required location and restart apache and nginx.&lt;/p&gt;

&lt;p&gt;Now put some content in that folder and configure your mysql connection if neccesary&lt;/p&gt;

&lt;p&gt;You should now be able to browse to example.com and see your brand new site. Some quick benchmarking with ab gives roughly a tenfold increase in requests per second, depending on the configuration of the website itself&lt;/p&gt;

&lt;p&gt;These are some rough numbers for &lt;a href="http://6px.eu"&gt;Six Pixels&lt;/a&gt;, built with Kohana2 without any caching mechanism&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ab -c20 -n200 http://6px.eu:8080/&lt;/code&gt; is hitting Apache on port 8080&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code&gt;Server Hostname:        6px.eu
Server Port:            8080

Document Path:          /
Document Length:        12101 bytes

Concurrency Level:      20
Time taken for tests:   282.679 seconds
Complete requests:      200
Failed requests:        0
Write errors:           0
Total transferred:      2486000 bytes
HTML transferred:       2420200 bytes
Requests per second:    0.71 [#/sec] (mean)
Time per request:       28267.940 [ms] (mean)
Time per request:       1413.397 [ms] (mean, across all concurrent requests)
Transfer rate:          8.59 [Kbytes/sec] received&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now with nginx &lt;code&gt;ab -c20 -n200 http://6px.eu/&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code&gt;Server Hostname:        6px.eu
Server Port:            80

Document Path:          /
Document Length:        12081 bytes

Concurrency Level:      20
Time taken for tests:   40.606 seconds
Complete requests:      200
Failed requests:        0
Write errors:           0
Total transferred:      2482000 bytes
HTML transferred:       2416200 bytes
Requests per second:    4.93 [#/sec] (mean)
Time per request:       4060.612 [ms] (mean)
Time per request:       203.031 [ms] (mean, across all concurrent requests)
Transfer rate:          59.69 [Kbytes/sec] received&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Update:&lt;/h3&gt;

&lt;p&gt;As rightly noted by &lt;a href="https://twitter.com/#!/arnaud_lb/status/196610128261296129"&gt;@arnaud_lb&lt;/a&gt; the benchmarks should give nearly the same results,
as nginx is waiting for Apache to return it's data before sending it along.
What happened in those benchmarks is that &lt;a href="http://cloudflare.com"&gt;cloudflare.com&lt;/a&gt; (highly recommended by the way) was caching some results and not others.&lt;/p&gt;

&lt;p&gt;When I tried on localhost, the results were effectively the same.
So the way to get better performance is to get nginx to cache the results from apache, by adding the following to your nginx virtual host definition :&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="nginx"&gt;                &lt;span class="k"&gt;proxy_cache&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="s"&gt;e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;proxy_cache_use_stale&lt;/span&gt; &lt;span class="s"&gt;error&lt;/span&gt; &lt;span class="s"&gt;timeout&lt;/span&gt; &lt;span class="s"&gt;invalid_header&lt;/span&gt; &lt;span class="s"&gt;updating&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;proxy_cache_key&lt;/span&gt; &lt;span class="nv"&gt;$scheme$host$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;proxy_cache_valid&lt;/span&gt;       &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="mi"&gt;302&lt;/span&gt; &lt;span class="mi"&gt;20m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;proxy_cache_valid&lt;/span&gt;       &lt;span class="mi"&gt;404&lt;/span&gt; &lt;span class="mi"&gt;1m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;proxy_cache_valid&lt;/span&gt;       &lt;span class="s"&gt;any&lt;/span&gt; &lt;span class="mi"&gt;15m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;where the &lt;code&gt;proxy_cache&lt;/code&gt; named &lt;code&gt;one&lt;/code&gt; is defined in nginx.conf as such :&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="nginx"&gt;&lt;span class="k"&gt;proxy_cache_path&lt;/span&gt; &lt;span class="s"&gt;/usr/local/nginx/proxy&lt;/span&gt; &lt;span class="s"&gt;levels=1:2&lt;/span&gt; &lt;span class="s"&gt;keys_zone=one:15m&lt;/span&gt; &lt;span class="s"&gt;inactive=7d&lt;/span&gt; &lt;span class="s"&gt;max_size=1000m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;proxy_cache_valid&lt;/code&gt; entries above define different cache times for various response codes&lt;/p&gt;

&lt;p&gt;And here are the real benchmarks :&lt;/p&gt;

&lt;h4&gt;Apache:&lt;/h4&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code&gt;Server Hostname:        direct.6px.eu
Server Port:            8080

Document Path:          /
Document Length:        11487 bytes

Concurrency Level:      10
Time taken for tests:   15.082 seconds
Complete requests:      200
Failed requests:        0
Write errors:           0
Total transferred:      2338600 bytes
HTML transferred:       2297400 bytes
Requests per second:    13.26 [#/sec] (mean)
Time per request:       754.075 [ms] (mean)
Time per request:       75.408 [ms] (mean, across all concurrent requests)
Transfer rate:          151.43 [Kbytes/sec] received&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;Nginx:&lt;/h4&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code&gt;Server Hostname:        direct.6px.eu
Server Port:            80

Document Path:          /
Document Length:        3031 bytes

Concurrency Level:      10
Time taken for tests:   0.027 seconds
Complete requests:      200
Failed requests:        0
Write errors:           0
Total transferred:      654600 bytes
HTML transferred:       606200 bytes
Requests per second:    7305.94 [#/sec] (mean)
Time per request:       1.369 [ms] (mean)
Time per request:       0.137 [ms] (mean, across all concurrent requests)
Transfer rate:          23351.88 [Kbytes/sec] received&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Just, wow...&lt;/p&gt;

&lt;p&gt;Careful though as this will wreak havoc on your sessions, at the minimum you can disable caching for logged-in users with&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="nginx"&gt;&lt;span class="k"&gt;proxy_cache_bypass&lt;/span&gt; &lt;span class="nv"&gt;$cookie_session&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;proxy_no_cache&lt;/span&gt; &lt;span class="nv"&gt;$cookie_session&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;where &lt;code&gt;session&lt;/code&gt; is the name of your cookie&lt;/p&gt;
&lt;a href="http://jfoucher.com/2012/04/installing-apache-php-and-nginx-for-faster-websites.html"&gt;Installing PHP, Apache2 and nginx for faster websites&lt;/a&gt; is a post by Jonathan Foucher at &lt;a
href="http://jfoucher.com"&gt;Geeky Nuggets&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=aJlBdjVeT8I:C0pD7yIVirk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=aJlBdjVeT8I:C0pD7yIVirk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=aJlBdjVeT8I:C0pD7yIVirk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/aJlBdjVeT8I" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2012/04/installing-apache-php-and-nginx-for-faster-websites.html</feedburner:origLink></entry>
	
	<entry>
		<title>Import contacts from Google by entering your email and password</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/Yl1BtpN-wm8/getting-your-users-gmail-contacts.html" />
		<updated>Sun Apr 15 09:17:07 +0200 2012</updated>
		<id>http://jfoucher.com/2012/04/getting-your-users-gmail-contacts</id>
		<content type="html">&lt;p&gt;What I wanted to do was something similar to what Dropbox does for their referral program: Allow the user to input their email and password, show them a list of their contacts and allow them to select who to invite. The invited contacts' emails would then be saved directly to database and an email sent to them.&lt;/p&gt;

&lt;p&gt;This is what google calls the &lt;a href="https://developers.google.com/accounts/docs/AuthForInstalledApps#Using"&gt;ClientLogin&lt;/a&gt; method of authentication. It allow your user to simply input their username and password and see a list of their contacts displayed, where they can select which ones to invite, in this case.&lt;/p&gt;

&lt;p&gt;The way to do that is pretty easy, first we have to make a POST request to google to get an authentification token for the subsequent authenticated requests. I chose to use the &lt;a href="https://github.com/kriswallsmith/Buzz"&gt;Buzz PHP library&lt;/a&gt; as my HTTP client. It makes everything easy and removes the necessity of countless &lt;code&gt;curl_set_opts()&lt;/code&gt;. Buzz requires PHP 5.3, but I'm using Symfony2 which also does, so that's not a problem, actually more of a boon as I find PHP5.3 code generally cleaner.&lt;/p&gt;

&lt;p&gt;I created a class &lt;code&gt;Importer&lt;/code&gt; with a protected variable &lt;code&gt;$browser&lt;/code&gt; which is the Buzz\Browser instance we'll be using to connect to google. Google returns the data in a line based format, so I used a little helper function to convert it to a PHP array:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;unserializeGoogleData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nv"&gt;$returns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;explode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;explode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;=&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nv"&gt;$returns&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$returns&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;So first we need to get the auth token from google:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;accountType&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;HOSTED_OR_GOOGLE&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;Email&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;email&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;Passwd&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;password&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;service&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;cp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;source&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;mention-web-1.0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;browser&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;https://www.google.com/accounts/ClientLogin&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nb"&gt;http_build_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nv"&gt;$returns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;unserializeGoogleData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Where &lt;code&gt;$data['email']&lt;/code&gt; and &lt;code&gt;$data['password']&lt;/code&gt; are the user's email and password, respectively.&lt;/p&gt;

&lt;p&gt;If everything went fine, the &lt;code&gt;$returns&lt;/code&gt; variable now contains an associative array with a key &lt;code&gt;Auth&lt;/code&gt;, so we can proceed with the next step, actually getting the contacts:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$returns&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Auth&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="nv"&gt;$feed_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;https://www.google.com/m8/feeds/contacts/&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;
            &lt;span class="nb"&gt;urlencode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;email&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;/full?alt=json&amp;amp;max-results=500&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


        &lt;span class="nv"&gt;$header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;&amp;#39;Authorization: GoogleLogin auth=&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$returns&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Auth&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;browser&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$feed_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$header&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


        &lt;span class="nv"&gt;$r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;json_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;//return $r;&lt;/span&gt;
        &lt;span class="nv"&gt;$results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;feed&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;entry&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;feed&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;entry&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])){&lt;/span&gt;
            &lt;span class="nv"&gt;$results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$el&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
                &lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$el&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;gd$email&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])){&lt;/span&gt;
                    &lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;email&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$el&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;gd$email&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;address&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$el&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;title&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;$t&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])){&lt;/span&gt;
                        &lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$el&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;title&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;$t&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;feed&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;entry&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$results&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If the user and password were incorrect, the &lt;code&gt;Auth&lt;/code&gt; key will not be present in the array, and so we simply return &lt;code&gt;false&lt;/code&gt;. It is recommended to see if Google requires the user to solve a catcha, in which case it should be displayed. But as that was not necessary in this case, it will be left as an exercise for the reader.
On the other hand, if everything was ok, the &lt;code&gt;$results&lt;/code&gt; array is now populated with the user's contacts, so the next step is to walk over the array extracting the data we need, in this case only the main email and the full name of the contact. We populate an array with the required data and simply return it for the caller to use.&lt;/p&gt;

&lt;p&gt;I hope this will be useful to someone, but please note that Google &lt;a href="https://developers.google.com/accounts/docs/AuthForInstalledApps"&gt;recommends&lt;/a&gt; you use OAuth for that kind of things.&lt;/p&gt;
&lt;a href="http://jfoucher.com/2012/04/getting-your-users-gmail-contacts.html"&gt;Import contacts from Google by entering your email and password&lt;/a&gt; is a post by Jonathan Foucher at &lt;a
href="http://jfoucher.com"&gt;Geeky Nuggets&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=Yl1BtpN-wm8:wbcbdcvZLzE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=Yl1BtpN-wm8:wbcbdcvZLzE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=Yl1BtpN-wm8:wbcbdcvZLzE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/Yl1BtpN-wm8" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2012/04/getting-your-users-gmail-contacts.html</feedburner:origLink></entry>
	
	<entry>
		<title>Git tips from stackoverflow</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/oAjS9GEnk5s/github-tricks-from-stackoverflow.html" />
		<updated>Mon Apr 09 00:00:00 +0200 2012</updated>
		<id>http://jfoucher.com/2012/04/github-tricks-from-stackoverflow</id>
		<content type="html">&lt;p&gt;Here are some pretty cool and very useful git tricks I learnt  by searching or reading stackoverflow.
Most of them are operations that should be pretty easy to do, and seem pointlessly complicated. The second one is an excellent example of both the flexibility and the lack of user friendliness of the git UI&lt;/p&gt;

&lt;h3&gt;Prevent a file from being commited, ever&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://stackoverflow.com/a/8485503/210824"&gt;Git: Never Commit Changed Files (But still keep original revisioned.)&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;git update-index --assume-unchanged &amp;lt;file&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;To make it commitable again run&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;git update-index --no-assume-unchanged &amp;lt;file&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Commits no yet pushed&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://stackoverflow.com/a/3338774/210824"&gt;Viewing Unpushed Git Commits&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to see all commits on all branches that aren't pushed yet, you might be looking for something like this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;git log --branches --not --remotes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And if you only want to see the most recent commit on each branch, and the branch names, this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;git log --branches --not --remotes --simplify-by-decoration --decorate --oneline
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;a href="http://jfoucher.com/2012/04/github-tricks-from-stackoverflow.html"&gt;Git tips from stackoverflow&lt;/a&gt; is a post by Jonathan Foucher at &lt;a
href="http://jfoucher.com"&gt;Geeky Nuggets&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=oAjS9GEnk5s:_BTtvfq16sA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=oAjS9GEnk5s:_BTtvfq16sA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=oAjS9GEnk5s:_BTtvfq16sA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/oAjS9GEnk5s" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2012/04/github-tricks-from-stackoverflow.html</feedburner:origLink></entry>
	
	<entry>
		<title>From Titanium to Adobe Air, or, Building Desktop Apps with Javascript</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/GPY7Ar_qDIM/from-titanium-to-air-building-desktop-apps-with-javascript.html" />
		<updated>Mon Feb 13 00:00:00 +0100 2012</updated>
		<id>http://jfoucher.com/2012/02/from-titanium-to-air-building-desktop-apps-with-javascript</id>
		<content type="html">&lt;p&gt;&lt;a href="http://vessenger.com"&gt;Vessenger&lt;/a&gt; is an app that allows closed groups such as
organizations, to chat and send documents to each other or to a central
repository. People can be divided in groups so that they can share status
updates or documents with just the required people. In some ways it is similar
to yammer, but was to be based primarily on a desktop app.&lt;/p&gt;

&lt;h3&gt;We decide to use Titanium&lt;/h3&gt;

&lt;p&gt;After some brainstorming with the company owner, we decided that we'd make the
app available cross platform, and at least for Mac OSX and Windows. I
personally use Linux, so I also wanted to make sure that it would work on Linux
as well.  Developping two or three native apps was not a viable option, so we
decided to use a framework that would allow us to use HTML and Javascript, such
as Titanium and Adobe Air. Titanium looked like it had great support from the
community, is Open source and actively developped, so we went with that.&lt;/p&gt;

&lt;p&gt;Developing in Titanium takes some getting used to, but is not much different to
building javascript heavy web applications. Initially, an index.html file is
loaded by Titanium, in which we load all the required javascript files. At
first I had everything in one big and quickly growing javascript file, which
although properly namespaced, was really giving me headaches just to move
around. So I split it up in several smaller files, by functionality, as I
should have done since the beginning.&lt;/p&gt;

&lt;p&gt;Working in Titanium can be frustrating at times, and although it works pretty
well, I had to spend a lot of time looking through the documentation. After
some time, I realized that the docs for Tianium are not easy to understand, not
particularly friendly and sometimes even incomplete.&lt;/p&gt;

&lt;p&gt;I started working on &lt;a href="http://vessenger.com"&gt;Vessenger&lt;/a&gt; by doing most of the UI,
the status message sending and retrieving, and getting a basic version of the
chat feature working for demo purposes. The status updates was the easiest one
to build, and I added the possibility to upload files within you status update.
They can be any type of files, with images showing a thumbnail when seen by
your colleagues. All the files live on &lt;a href="http://vessenger.com"&gt;Vessenger&lt;/a&gt;'s
servers, which makes it very easy to retrieve information at a later date, just
by looking at your (infinite) chat or status history.&lt;/p&gt;

&lt;h3&gt;Switching to Adobe Air&lt;/h3&gt;

&lt;p&gt;I then started working on the chat feature, which is where we noticed an issue
with the repeated server polling we were doing: as well as being suboptimal on
the server side, the was also a memory leak on the client side, which seemd to
be caused by Titanium not properly closing and/or releasing the connection
object, a problem compouded by the fact that Titanium has no method for
explicitely closing a remote connection. As I was connecting to the server
several times per second, the memory footprint of the application grew fairly
quickly. After a lot a frustration trying to make it right, we decided the
problem lay with Titanium and decided to switch to Adobe Air. Regretfully, the
latest Air version is not supported on Linux anymore, but it's possible to make
the app the app compatible with Air 2.6 to get it to run properly on linux.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;The memory used by the app could climb to 600Mb overnight...&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;The switch to Adobe air did not involve the complete rewrite I feared, as most
of the code is compatible and I had created some abstractions for things like
connecting to the API and storing data. Nevertheless, EncryptedLocalStorage is
great: very easy to use and has all the features needed. My only problem with
Adobe Air was the way it handled cookies: it basically did not, so I had to
create that from scratch, storing the cookies in EcryptedLocalStorage and
sending it explicitely with each and every request. In hindsight I should have
setup a dedicated server with node.js to talk to the API, and socket.io to talk
between the desktop app and the node server. I am actually implementing this
solution now for another project and I think it would be a perfect fit for
&lt;a href="http://vessenger.com"&gt;Vessenger&lt;/a&gt; as well.&lt;/p&gt;

&lt;h3&gt;Sort issues caused by Titanium&lt;/h3&gt;

&lt;p&gt;So by a combination of moving to Air and reducing the polling frequency for the
things that did not need to be refreshed so often, I managed to eliminate the
memory leak. Development could then continue as previously planned: I
integrated &lt;a href="http://vessenger.com/snaplr"&gt;Snaplr&lt;/a&gt; in the file upload dialogs,
allowing the user to easily take a screenshot, annotate it and upload it along
along with his message, to be seen instantly by the people he is chatting with.
For me this is one of the killer features of &lt;a href="http://vessenger.com"&gt;Vessenger&lt;/a&gt;&lt;/p&gt;
&lt;a href="http://jfoucher.com/2012/02/from-titanium-to-air-building-desktop-apps-with-javascript.html"&gt;From Titanium to Adobe Air, or, Building Desktop Apps with Javascript&lt;/a&gt; is a post by Jonathan Foucher at &lt;a
href="http://jfoucher.com"&gt;Geeky Nuggets&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=GPY7Ar_qDIM:4nRuM2OFElo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=GPY7Ar_qDIM:4nRuM2OFElo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=GPY7Ar_qDIM:4nRuM2OFElo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/GPY7Ar_qDIM" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2012/02/from-titanium-to-air-building-desktop-apps-with-javascript.html</feedburner:origLink></entry>
	
	<entry>
		<title>Implementing BrowserID identification on your website</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/kNEoOm5w3Jo/implementing-browserid-identification.html" />
		<updated>Sun Dec 25 14:05:13 +0100 2011</updated>
		<id>http://jfoucher.com/2011/12/implementing-browserid-identification</id>
		<content type="html">&lt;p&gt;BrowserID &lt;a href="http://identity.mozilla.com/post/7616727542/introducing-browserid-a-better-way-to-sign-in"&gt;was released a few months ago&lt;/a&gt; and is a new way to sign in to websites or web applications that doesn't require you to give your password each time you want to login. It doesn't even require you to register as such on each website. In that way, it is very similar to openId, but without the usability issues.&lt;/p&gt;

&lt;p&gt;For developpers, Mozilla set up a service that provides everything you need to let your users simply login without handling any of the dirty work yourself. &lt;a href="http://browserid.org"&gt;http://browserid.org&lt;/a&gt; is an identity provider that allows your users to create and manage their accounts across the web. One account for an infinite number of websites. Could this finally be our &lt;a href="http://www.codinghorror.com/blog/2010/11/your-internet-drivers-license.html"&gt;universal login mechanism&lt;/a&gt;?&lt;/p&gt;

&lt;h3&gt;&lt;a href="https://github.com/mozilla/browserid/wiki/How-to-Use-BrowserID-on-Your-Site"&gt;Implementing BrowserID&lt;/a&gt; on your site or app is easy&lt;/h3&gt;

&lt;h4&gt;Include the following javascript snippet in your page&lt;/h4&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;https://browserid.org/include.js&amp;quot;&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;Identify the user&lt;/h4&gt;

&lt;p&gt;When the user clicks on your "Login" button, a window pops up asking them to confirm that they want to login, or asking them to create a browserID account if they haven't done it yet. Once they decide that they want to login, they are redirected to your site, and the following function is called, with the assertion being passed to the callback if the login was successful&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="nx"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getVerifiedEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;assertion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;assertion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// This code will be invoked once the user has successfully&lt;/span&gt;
        &lt;span class="c1"&gt;// selected an email address they control to sign in with.&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// something went wrong!  the user isn&amp;#39;t logged in.&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If the assertion is there, the user authenticated successfully. now you must verify that the assertion really is authentic, and get the relevant data from it. You &lt;em&gt;could&lt;/em&gt; &lt;a href="https://wiki.mozilla.org/Identity/Verified_Email_Protocol/Latest"&gt;do it yourself&lt;/a&gt;, but if you don't have any special requirements, I recommend you just use the service provided by &lt;a href="http://browserid.org"&gt;http://browserid.org&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;Verify the assertion&lt;/h4&gt;

&lt;p&gt;To do so, and once you have the &lt;code&gt;assertion&lt;/code&gt;, you have to make a POST request to &lt;a href="http://browserid.org/verify"&gt;http://browserid.org/verify&lt;/a&gt;, with two parameters: the assertion and the audience, which is simply the hostname of your site. This has to be done from your server. For security reasons, it won't work if you do it as an ajax request from the user's browser. What I suggest is that you call a url on your server from the javascript callback which will be in charge of itself making the request to browserid.org. Do it as a POST request as that assertion is a &lt;em&gt;long&lt;/em&gt; string. This an example implementation for the &lt;a href="http://www.slimframework.com/"&gt;Slim framework&lt;/a&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/browserid&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="nv"&gt;$assertion&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;assertion&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;//get the POSTed assertion&lt;/span&gt;
        &lt;span class="nv"&gt;$post_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;assertion&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$assertion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;audience&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;SERVER&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;//SERVER is my site&amp;#39;s hostname&lt;/span&gt;
        &lt;span class="nv"&gt;$r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;https://browserid.org/verify&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$post_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;//This makes a post request to browserid.org&lt;/span&gt;
        &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;json_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;status&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;okay&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="nx"&gt;handle_users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;//This logs the user in if we have an account for that email address,&lt;/span&gt;
            &lt;span class="c1"&gt;//or creates it otherwise&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Could not log you in&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nv"&gt;$status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;message&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;$msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;status&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;$status&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;


    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This call to the browserID API returns some json_encoded stuff, for example something like this :&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;status&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;okay&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;email&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;lloyd@example.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;audience&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;https://mysite.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;expires&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1308859352261&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;issuer&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;browserid.org&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;Login or register&lt;/h4&gt;

&lt;p&gt;If you don't get anything, or the status is not okay, something failed. Otherwise, great, your user just asked to be logged in! (or registered)&lt;/p&gt;

&lt;p&gt;If the status was "okay", you then need to proceed to login your user (set session varibles, or whatever...) or register them (create an account in your database and then log them in)&lt;/p&gt;

&lt;p&gt;The data returned is very basic, but allows you to check whether that user already has an account or your site or not. You are then free to ask them for additional data, such as their name, date of birth, etc...&lt;/p&gt;

&lt;p&gt;And that's it! I'm really happy because now I can forget about email address verification, lost passwords and all the annoying stuff that having actual users imply. Let someone else do the hard work is what I say!! Especially when it integrates so well everywhere.&lt;/p&gt;

&lt;p&gt;Oh by the way, there's a &lt;a href="http://wordpress.org/extend/plugins/browserid/"&gt;Wordpress plugin&lt;/a&gt; for that&lt;/p&gt;
&lt;a href="http://jfoucher.com/2011/12/implementing-browserid-identification.html"&gt;Implementing BrowserID identification on your website&lt;/a&gt; is a post by Jonathan Foucher at &lt;a
href="http://jfoucher.com"&gt;Geeky Nuggets&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=kNEoOm5w3Jo:IdkvkBD4hgM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=kNEoOm5w3Jo:IdkvkBD4hgM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=kNEoOm5w3Jo:IdkvkBD4hgM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/kNEoOm5w3Jo" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2011/12/implementing-browserid-identification.html</feedburner:origLink></entry>
	
	<entry>
		<title>A 10 minute script to graph your server load</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/b1hs5X6V2ZA/a-10-minute-script-to-graph-your-server-load.html" />
		<updated>Sat Sep 17 01:09:13 +0200 2011</updated>
		<id>http://jfoucher.com/2011/09/a-10-minute-script-to-graph-your-server-load</id>
		<content type="html">&lt;p&gt;This is a quick and dirty PHP script that I whipped up in about 10 minutes, used to show the load averages on the server where it is uploaded.&lt;/p&gt;

&lt;p&gt;Here are the load curves for the server that hosts most of my websites at the moment. It is an overworked shared server, which explains why all the curves are through the roof...&lt;/p&gt;

&lt;iframe src="http://xiilo.com/uptime.php" width="650" height="450"&gt;&lt;/iframe&gt;


&lt;p&gt;The load is updated every minute with a crontab that calls this same script.&lt;/p&gt;

&lt;p&gt;The visualization is done using the Google chart API, which does require javascript but offers some great chart options, the "annotatedtimeline" being especially suitable to my purpose.&lt;/p&gt;

&lt;p&gt;&lt;a title="server load graph on github" href="https://github.com/jfoucher/Server-load-graph" target="_blank"&gt;Get the source on github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://jfoucher.com/projects/serverload.html"&gt;installation and project details&lt;/a&gt;&lt;/p&gt;
&lt;a href="http://jfoucher.com/2011/09/a-10-minute-script-to-graph-your-server-load.html"&gt;A 10 minute script to graph your server load&lt;/a&gt; is a post by Jonathan Foucher at &lt;a
href="http://jfoucher.com"&gt;Geeky Nuggets&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=b1hs5X6V2ZA:dFIQBHKYiJQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=b1hs5X6V2ZA:dFIQBHKYiJQ:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=b1hs5X6V2ZA:dFIQBHKYiJQ:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/b1hs5X6V2ZA" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2011/09/a-10-minute-script-to-graph-your-server-load.html</feedburner:origLink></entry>
	
	<entry>
		<title>Remote debugging with Xdebug and PhpStorm on Ubuntu</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/b7CR7oZNIF0/remote-debugging-with-xdebug-and-phpstorm-on-ubuntu.html" />
		<updated>Thu Aug 18 01:09:13 +0200 2011</updated>
		<id>http://jfoucher.com/2011/08/remote-debugging-with-xdebug-and-phpstorm-on-ubuntu</id>
		<content type="html">&lt;p&gt;Being able to debug your php application right from your IDE is something that you can't fully realise the power of, unless you've tried it. The advantages are immediately obvious: as soon as the connection from Xdebug is successful, you are blinded by variable inspection, code stepping, breakpoints, etc... Debugging heaven!
It took me... a few months to finally find the time figure out how to set up everything properly, so I hope this post can help someone, somewhere. But don't worry: it retrospect, it's not that difficult at all.&lt;/p&gt;

&lt;h3&gt;First things first : install xdebug&lt;/h3&gt;


&lt;p&gt;On Ubuntu and Debian, it couldn't be easier: just open a terminal and type&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;sudo apt-get install
php5-xdebug
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt; This will also install Apache and PHP if you don't have them already.&lt;/p&gt;

&lt;h3&gt;Setup Xdebug on server&lt;/h3&gt;


&lt;p&gt;Done? Right, so this created a config file in /etc/php5/conf.d called xdebug.ini, which is read by php and contains xdebug's configuration options. You'll need to open this file for editing as root, as we need to make a few changes in there. you can copy/paste the command below in the terminal, or do it your own way.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;gksu gedit /etc/apache2/conf.d/xdebug.ini
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Within this file, there will be a single line, referencing the xdebug zend extension, something like this (the path can vary slightly)&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ini"&gt;&lt;span class="na"&gt;zend_extension&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/lib/php5/20090626/xdebug.so&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This is what we're going to add:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ini"&gt;&lt;span class="na"&gt;xdebug.remote_enable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;On #this enables remote debugging&lt;/span&gt;
&lt;span class="na"&gt;xdebug.remote_host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;192.168.1.83 #change this IP adress for the one of the computer you are typing on&lt;/span&gt;
&lt;span class="na"&gt;xdebug.remote_port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;9000 #this is the default, leave it as is&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now we restart apache so that the new configuration is taken into account:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;sudo /etc/init.d/apache2 restart
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And we that we are &lt;strong&gt;done&lt;/strong&gt; on the server side of things&lt;/p&gt;

&lt;h3&gt;Prepare PhpStorm&lt;/h3&gt;


&lt;p&gt;Switch to the computer where PhpStorm is installed, and open your project. All you have to do is click on the "Accept debug connections" button, and activate Xdebug by using a browser extension. Here are four extensions to do this:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/58688"&gt;Firefox&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://chrome.google.com/extensions/detail/eadndfjplgieldjbigjakmdgkmoaaaoc"&gt;Chrome&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://benmatselby.posterous.com/xdebug-toggler-for-safari"&gt;Safari&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://addons.opera.com/addons/extensions/details/xdebug-launcher/?display=en"&gt;Opera&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Use your preferred extension to activate Xdebug for the page you're on. Go back to PhpStorm, and instruct it to listen to incoming debug connections by clicking on the "Listen PHP debug connections" button &lt;img class="alignnone" title="accept connection button" src="http://i.imgur.com/uMBOg.png" alt="" width="28" height="26" /&gt;&lt;/p&gt;

&lt;p&gt;Now all you have to is set a breakpoint and reload your page.&lt;/p&gt;

&lt;div class="image-with-caption aligncenter" style="width:319px"&gt;&lt;div class="caption"&gt;Setting a breakpoint in PhpStorm&lt;/div&gt;&lt;img title="Setting breakpoint" src="http://i.imgur.com/9AuKc.png" alt="Setting breakpoint" width="319" height="173" /&gt;&lt;/div&gt;


&lt;p&gt;A window will popup asking you if PhpStorm should accept the connection from Xdebug&lt;/p&gt;

&lt;div class="image-with-caption aligncenter" style="width:331px"&gt;&lt;div class="caption"&gt;Accepting connection from Xdebug on PhpStorm&lt;/div&gt;&lt;img title="Accepting connection from Xdebug" src="http://i.imgur.com/2fZKq.png" alt="Accepting connection from Xdebug" width="331" height="398" /&gt;&lt;/div&gt;


&lt;p&gt;Just click debug and happy bug squishing!&lt;/p&gt;
&lt;a href="http://jfoucher.com/2011/08/remote-debugging-with-xdebug-and-phpstorm-on-ubuntu.html"&gt;Remote debugging with Xdebug and PhpStorm on Ubuntu&lt;/a&gt; is a post by Jonathan Foucher at &lt;a
href="http://jfoucher.com"&gt;Geeky Nuggets&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=b7CR7oZNIF0:L-e8BnrTopo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=b7CR7oZNIF0:L-e8BnrTopo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=b7CR7oZNIF0:L-e8BnrTopo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/b7CR7oZNIF0" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2011/08/remote-debugging-with-xdebug-and-phpstorm-on-ubuntu.html</feedburner:origLink></entry>
	
	<entry>
		<title>A Phing task to update your Twitter status</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/Zj4UGtBvfgE/phing-task-to-update-twitter-status.html" />
		<updated>Wed Jun 29 14:10:00 +0200 2011</updated>
		<id>http://jfoucher.com/2011/06/phing-task-to-update-twitter-status</id>
		<content type="html">&lt;h3&gt;Phing and Twitter&lt;/h3&gt;


&lt;p&gt;I recently starting working with &lt;a title="PHP build and deployment tool" href="http://www.phing.info"&gt;phing&lt;/a&gt; to automate the build and deployement process for the web apps I'm building. I use it to compile my LESS files to CSS and minimize then, to compress and concatenate the javascript files, to optimize images using &lt;a href="http://www.smushit.com/"&gt;smushit&lt;/a&gt;, etc...&lt;/p&gt;

&lt;p&gt;I like to be able to comunicate exactly what I'm doing, and thankfully Phing has a built in task to email a message to a list of recipients, which is good, but slightly old school. I wanted something that would be able to integrate readily with twitter, i.e. update my status when a build was completed. I saw &lt;a href="http://codeinthehole.com/archives/14-Phing-task-to-update-Twitter-status.html"&gt;this post&lt;/a&gt;, which unfortunately uses Basic Auth. As you doubtless know, &lt;a href="http://dev.twitter.com/pages/basic_auth_shutdown"&gt;Twitter deprecated this form of authentication&lt;/a&gt;, and now asks all users to authenticate using &lt;a href="http://dev.twitter.com/pages/basic_to_oauth"&gt;OAuth&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Download twitterOAuth library&lt;/h3&gt;


&lt;p&gt;That meant I had to roll my own phing task... However, thanks to great work by cleverer people, doing it was quite simple. Using &lt;a href="http://abrah.am/"&gt;Abraham Williams'&lt;/a&gt; &lt;a href="https://github.com/abraham/twitteroauth"&gt;twitteroauth&lt;/a&gt; library means that the coding I'd have to do was greatly reduced. Awesome, because &lt;a href="http://www.codinghorror.com/blog/2005/08/how-to-be-lazy-dumb-and-successful.html"&gt;I aim to be lazy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The first step is to &lt;a href="https://github.com/abraham/twitteroauth/tarball/master"&gt;download the twitteroauth library&lt;/a&gt; from github. Extract it to a temporary folder and copy the subfolder&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;twitteroauth
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt; to the folder where your fing tasks are stored (on my system it is&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;/usr/share/php/phing/tasks/my/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;. Please note you might have to create the&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;my/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt; folder within&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;/usr/share/php/phing/tasks/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;. You will need root privileges for these steps.&lt;/p&gt;

&lt;h3&gt;Register application with Twitter&lt;/h3&gt;


&lt;p&gt;Secondly, you need to &lt;a href="https://dev.twitter.com/apps/new"&gt;register an application with twitter&lt;/a&gt;, as you will need a consumer key and consumer secret later on. Please &lt;a href="https://dev.twitter.com/apps/new"&gt;do so now&lt;/a&gt;, and come back once you have your app data available.&lt;/p&gt;

&lt;h3&gt;Create the custom phing task&lt;/h3&gt;


&lt;p&gt;Next up is creating the actual task PHP class. Create an empty file named TwitterUpdateTask.php&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;sudo touch /usr/share/php/phing/tasks/my/TwitterUpdateTask.php
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt; and open it for editing with your favorite editor. We'll use gedit :&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;gksu gedit /usr/share/php/phing/tasks/my/TwitterUpdateTask.php
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The code for this file is as shown below:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;require_once&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;phing/Task.php&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;require_once&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;phing/tasks/my/twitteroauth/twitteroauth.php&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;span class="cm"&gt;/* get the lines below from http://twittertokens.6px.eu/ */&lt;/span&gt;

&lt;span class="nb"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;CONSUMER_KEY&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Your Consumer Key Here&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;CONSUMER_SECRET&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Your Consumer Secret Here&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;OAUTH_TOKEN&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Your OAuth Token Here&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;OAUTH_TOKEN_SECRET&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Your Oauth Token Secret Here&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TwitterUpdateTask&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Task&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cm"&gt;/*&lt;/span&gt;
&lt;span class="cm"&gt;     * The setter for the status message&lt;/span&gt;
&lt;span class="cm"&gt;     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;setMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
        &lt;span class="cm"&gt;/* Connect to twitter */&lt;/span&gt;
        &lt;span class="nv"&gt;$connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;TwitterOAuth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CONSUMER_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CONSUMER_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OAUTH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OAUTH_TOKEN_SECRET&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="cm"&gt;/* Pass the status message as a parameter */&lt;/span&gt;
        &lt;span class="nv"&gt;$parameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;status&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="cm"&gt;/* Post the data to the API endpoint */&lt;/span&gt;
        &lt;span class="nv"&gt;$status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$connection&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;statuses/update&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$parameters&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$status&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)){&lt;/span&gt;
            &lt;span class="cm"&gt;/* if there is an error, fail the build */&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BuildException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$status&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="cm"&gt;/* if there is no error, show a success message */&lt;/span&gt;
            &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Status posted to twitter&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;




&lt;h3&gt;Get the OAuth token and secret&lt;/h3&gt;


&lt;p&gt;Don't close this file, we still need to add the authentication data to it. You can already place your consumer key and consumer secret in the apropriate&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;define()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt; calls (the first two lines), but if not, we'll do it now.&lt;/p&gt;

&lt;p&gt;Navigate to &lt;a href="http://twittertokens.6px.eu"&gt;http://twittertokens.6px.eu&lt;/a&gt;, put your consumer data and consumer secret in the apropriate fields and click on "Sign in with Twitter". A twitter page will open asking for your confirmation. Click "Sign in" and you are redirected to http://twittertokens.6px.eu/. You should see 4 lines of code appear, that look like this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;define(&amp;#39;CONSUMER_KEY&amp;#39;, &amp;#39;V1UsnZJrgfhgKJFoqsQ&amp;#39;);&lt;/span&gt;
&lt;span class="x"&gt;define(&amp;#39;CONSUMER_SECRET&amp;#39;, &amp;#39;UUazcBfXrWW1jcpiSU564hg654t1EMki8gzptQU&amp;#39;);&lt;/span&gt;
&lt;span class="x"&gt;define(&amp;#39;OAUTH_TOKEN&amp;#39;, &amp;#39;325454656-EuCudghg8tTYwKf9yjt5nhqr14i5egHJPeVRGVxQv&amp;#39;);&lt;/span&gt;
&lt;span class="x"&gt;define(&amp;#39;OAUTH_TOKEN_SECRET&amp;#39;, &amp;#39;gh6854hg6tyGEvGEiEi15XmUtOmDpaONM&amp;#39;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Copy this code to the corresponding spot in the TwitterUpdateTask.php file, overwriting what's already there.&lt;/p&gt;

&lt;p&gt;Please note though that I'm not making any claims as to how secure this is or whatever. I don't store any of your data anywhere, but if sending your application consumer token and secret worries you, find another way to get the Oauth tokens.&lt;/p&gt;

&lt;h3&gt;Create the build file&lt;/h3&gt;


&lt;p&gt;First, we define the custom task:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="xml"&gt;&lt;span class="nt"&gt;&amp;lt;taskdef&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;twitterupdate&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;classname=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;phing.tasks.my.TwitterUpdateTask&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Secondly, let's create a custom target that will send a tweet with the message we want.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="xml"&gt;    &lt;span class="nt"&gt;&amp;lt;target&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;tweet&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;twitterupdate&lt;/span&gt; &lt;span class="na"&gt;message=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${twitter.status}&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/target&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now we can call this task from another one, but we need to make that the twitter.status is set. Let's we have a "staging" target. Part of it could look like this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="xml"&gt;    &lt;span class="c"&gt;&amp;lt;!-- Set the timestamp to be used in the twitter update --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;tstamp&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;format&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;build.time&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;pattern=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%Y-%m-%d %H:%I&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/tstamp&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;twitter.status&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Staging build completed at ${build.time}&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;phingcall&lt;/span&gt; &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;tweet&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This will post the message to twitter, replacing the&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;${build.time}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt; token by the actual build and time.&lt;/p&gt;

&lt;p&gt;Do you use Phing for your webapp build and deployment? If so, please share any custom tasks you might have created.&lt;/p&gt;
&lt;a href="http://jfoucher.com/2011/06/phing-task-to-update-twitter-status.html"&gt;A Phing task to update your Twitter status&lt;/a&gt; is a post by Jonathan Foucher at &lt;a
href="http://jfoucher.com"&gt;Geeky Nuggets&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=Zj4UGtBvfgE:w3K4NaO22BA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=Zj4UGtBvfgE:w3K4NaO22BA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=Zj4UGtBvfgE:w3K4NaO22BA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/Zj4UGtBvfgE" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2011/06/phing-task-to-update-twitter-status.html</feedburner:origLink></entry>
	
	<entry>
		<title>CSS minification library for codeigniter</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/jFtd3P6Jubs/css-minification-library-for-codeigniter.html" />
		<updated>Mon Apr 11 14:10:51 +0200 2011</updated>
		<id>http://jfoucher.com/2011/04/css-minification-library-for-codeigniter</id>
		<content type="html">&lt;p&gt;For my latest project, I wanted to be able to easily minify CSS stylesheets, using the simplest syntax possible, ideally using a simple tag in the header, like&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;css&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/assets/css/fonts.css&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/assets/css/layout.css&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;After some searching, I found a css minification library for PHP, &lt;a href="https://code.google.com/p/minify/"&gt;minify&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It was very easy to modify it so that It could be used in our CodeIgniter applications like any other libraries.
All I did was wrap the main minification function in Codeigniter specific code.
I modelled the interaction on the image library, as I guess that's what most people are used to.&lt;/p&gt;

&lt;div class="image-with-caption aligncenter" style="width:300px"&gt;&lt;div class="caption"&gt;css minification library for codeigniter&lt;/div&gt;&lt;a href="http://jfoucher.com/uploads/2011/04/Screenshot.png"&gt;&lt;img class="size-medium wp-image-450" title="css minification for codeigniter" src="http://jfoucher.com/uploads/2011/04/Screenshot-300x162.png" alt="css minification for codeigniter" width="300" height="162" /&gt;&lt;/a&gt;&lt;/div&gt;




&lt;h3&gt;How to use&lt;/h3&gt;


&lt;p&gt;Using the library involves loading it, setting up an array with some configuration values, such as the source css file(s), the destination file (optional) or the time that the generated file should be cached, and finally initializing the library with the configuration array() .&lt;/p&gt;

&lt;p&gt;The following code, which should go in your controller, will look very familiar to Codeigniter users.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;load&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;css&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;//array of files to concatenate and minify&lt;/span&gt;
&lt;span class="nv"&gt;$config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;source_file&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/assets/css/layout.css&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/assets/css/fonts.css&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;//where to output the result&lt;/span&gt;
&lt;span class="nv"&gt;$config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dest_file&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/assets/css/css.min.css&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;//Cache time in hours&lt;/span&gt;
&lt;span class="nv"&gt;$config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cache_time&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;css&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;css&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;link&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Will output the following stylesheet tag:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/assets/css/css.min.css&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/css&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;screen&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;




&lt;h3&gt;Get It!&lt;/h3&gt;


&lt;p&gt;You can &lt;a href="https://github.com/jfoucher/codeigniter-css-library"&gt;get it from GitHub&lt;/a&gt;. Don't forget to fork it if you think you can make it better!&lt;/p&gt;

&lt;h3&gt;Finally&lt;/h3&gt;


&lt;p&gt;I'm not sure the way I've done it, using a&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;$config&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt; array and so on, is the best way. It might be a bit overkill for such a simple library. I'd love to hear your thoughts on the subject.&lt;/p&gt;
&lt;a href="http://jfoucher.com/2011/04/css-minification-library-for-codeigniter.html"&gt;CSS minification library for codeigniter&lt;/a&gt; is a post by Jonathan Foucher at &lt;a
href="http://jfoucher.com"&gt;Geeky Nuggets&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=jFtd3P6Jubs:b7fQmTsLPas:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=jFtd3P6Jubs:b7fQmTsLPas:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=jFtd3P6Jubs:b7fQmTsLPas:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/jFtd3P6Jubs" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2011/04/css-minification-library-for-codeigniter.html</feedburner:origLink></entry>
	
	<entry>
		<title>The making of flickholdr.com, an image placeholder generator</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/jYiC8dpnc3k/the-making-of-flickholdr-an-image-placeholder-generator.html" />
		<updated>Sun Apr 03 21:42:49 +0200 2011</updated>
		<id>http://jfoucher.com/2011/04/the-making-of-flickholdr-an-image-placeholder-generator</id>
		<content type="html">&lt;p&gt;There are a few services available to web designer and HTML coders to use dummy images in their html mockups or templates. The one I used to use is &lt;a href="http://dummyimage.com"&gt;dummyimage&lt;/a&gt; but it is somewhat limited in that the images are completely static: a flat color and some text. I needed the same kind of service, but with actual images or photographs rather than simple placeholders. Something like dynamically generated stock images.&lt;/p&gt;

&lt;h3&gt;The idea&lt;/h3&gt;

&lt;p&gt;And then the idea dawned on me: why not use &lt;a href="http://flickr.com"&gt;flickr&lt;/a&gt;'s &lt;a href="http://creativecommons.org/"&gt;creative commons&lt;/a&gt; licensed images? The quality is often very good, especially for "interesting" images, a lot of sizes are available, and users often use tags to classify their images, making it rather easy to get placeholder images about a particular subject.&lt;/p&gt;

&lt;div class="image-with-caption aligncenter" style="width:600px"&gt;&lt;div class="caption"&gt;flickholdr.com&lt;/div&gt;&lt;a href="http://jfoucher.com/uploads/2011/03/FlickHoldr1.png"&gt;&lt;img class="size-full wp-image-413" title="FlickHoldr" src="http://jfoucher.com/uploads/2011/03/FlickHoldr1.png" alt="screenshot of flickholdr.com" width="600" height="417" /&gt;&lt;/a&gt;&lt;/div&gt;


&lt;h3&gt;The execution&lt;/h3&gt;

&lt;p&gt;So I proceeded to develop a little webapp to do just that, using &lt;a href="http://codeigniter.com"&gt;codeigniter&lt;/a&gt;, my framework of choice for rapid application development&lt;/p&gt;

&lt;p&gt;I used Codeigniter 2.0 from bitbucket, as I think it is the most up-to-date code available at the moment.&lt;/p&gt;

&lt;p&gt;If the requested image already exists in the cache (i.e. it has already been requested) we simply echo that out, with proper headers, otherwise, we have to generate the image.&lt;/p&gt;

&lt;h3&gt;Getting images from flickr&lt;/h3&gt;

&lt;p&gt;Most of the code deals with pulling images from flickr, and then doing various to them before display. The code that pulls the image from flickr is located in a model called Flickr_model with three methods:&lt;/p&gt;

&lt;ol&gt;
    &lt;li&gt;A public method called 
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;search()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  that gets images using the &lt;a href="http://www.flickr.com/services/api/"&gt;flickr API&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;A private method called 
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;_get_sizes()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 that finds the sizes available for that particular image&lt;/li&gt;
    &lt;li&gt;Another private method 
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;_get_author()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 that gets the information for the image and returns the name of the author, to be displayed in the watermark&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;The&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;search()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt; method returns as soon as it finds an image of at least the required size.&lt;/p&gt;

&lt;p&gt;The controller private method&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;_get_image()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt; then takes charge of resizing, cropping and watermarking the image, using codeigniter's &lt;a title="Codeigniter image manipulation class manual" href="http://codeigniter.com/user_guide/libraries/image_lib.html"&gt;image manipulation library&lt;/a&gt; to keep things quick and simple. I just tweaked the watermarking method of that class to allow for semi-transparent watermarks.&lt;/p&gt;

&lt;p&gt;The controller then sends the image to the browser with the proper headers.&lt;/p&gt;

&lt;h3&gt;End of the story!&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: Flickholdr is now open sourced and the code is available on &lt;a href="https://github.com/jfoucher/flickholdr"&gt;github&lt;/a&gt;&lt;/p&gt;
&lt;a href="http://jfoucher.com/2011/04/the-making-of-flickholdr-an-image-placeholder-generator.html"&gt;The making of flickholdr.com, an image placeholder generator&lt;/a&gt; is a post by Jonathan Foucher at &lt;a
href="http://jfoucher.com"&gt;Geeky Nuggets&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=jYiC8dpnc3k:9DjjlRPI-Tc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=jYiC8dpnc3k:9DjjlRPI-Tc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=jYiC8dpnc3k:9DjjlRPI-Tc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/jYiC8dpnc3k" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2011/04/the-making-of-flickholdr-an-image-placeholder-generator.html</feedburner:origLink></entry>
	
	<entry>
		<title>Installing and running APC cache with CodeIgniter</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/syTVGWrEKRg/installing-running-apc-cache-codeigniter.html" />
		<updated>Sun Feb 13 23:33:33 +0100 2011</updated>
		<id>http://jfoucher.com/2011/02/installing-running-apc-cache-codeigniter</id>
		<content type="html">&lt;p&gt;Codeigniter 2 now includes an excellent cache driver, which makes it dead easy to use any one of the great available cache librairies such as &lt;a href="http://php.net/apc"&gt;APC&lt;/a&gt; o &lt;a href="http://www.memcached.org/"&gt;memcached&lt;/a&gt;. In this post I will focus on APC, it's installation on an &lt;a href="/?p=193"&gt;Ubuntu 10.04 server&lt;/a&gt;, and a few benchmarks to compare the various cache systems.  For my testing, I will use an Ubuntu Server installation, on a VirtualBox virtual machine with 256 Mb of RAM and a single processor. This enables me to test things until everything breaks, than just scrap that VM and start with a clean one. However, a description of this setup is a story for another day...&lt;/p&gt;

&lt;h3&gt;Installation&lt;/h3&gt;


&lt;p&gt;On Ubuntu, and on other debian based linuxes, you can install APC by typing&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;sudo apt-get install php-apc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt; on the command line. Of course, you will have to install Apache and php before that, but that is really easy:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;sudo apt-get install php5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt; will install &lt;a href="http://php.net"&gt;PHP&lt;/a&gt; and all needed dependencies, including &lt;a href="http://apache.org"&gt;apache&lt;/a&gt; So now that APC is installed, just restart apache&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;sudo /etc/init.d/apache2 restart
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt; and you're ready to go.  In codeigniter, you don't need to do anything special. Just turn the cache on by putting the following line somewhere in your controller:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;$this-&amp;gt;output-&amp;gt;cache(n);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt; Where 'n' is the number of minutes to cache that particular content.  The cache library is clever enough to pick the best cache driver from the four available ones (memcached, APC, file and dummy). Forget about the dummy driver: it doesn't do anything&lt;/p&gt;

&lt;h3&gt;Benchmarks&lt;/h3&gt;


&lt;p&gt;These are the results for 50 concurrent connections : For APC we get about 43 requests/s, with the file caching mecanism around 25, requests/s, and with no cache at all we are below 18 requests/s&lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;a href="http://jfoucher.com/uploads/2011/02/chart22.png"&gt;&lt;img class="aligncenter size-full wp-image-387" title="Codeigniter APC cache benchmark" src="http://jfoucher.com/uploads/2011/02/chart22.png" alt="APC: 43, File: 25, None: 18 " width="560" height="260" /&gt;&lt;/a&gt;&lt;/p&gt;


&lt;p style="text-align: left;"&gt;For low concurency (2) the improvement when using APC is similar: in this case the number of requests per second nearly doubled, from 19 to 47 between the case without any caching system and the APC case&lt;/p&gt;


&lt;p style="text-align: left;"&gt;&lt;a href="http://jfoucher.com/uploads/2011/02/chart2.png"&gt;&lt;img class="aligncenter size-full wp-image-383" title="Codeigniter cache benchmark: low concurency" src="http://jfoucher.com/uploads/2011/02/chart2.png" alt="APC: 46.37 rps, File: 27.23 rps, None: 18.99 rps" width="560" height="260" /&gt;&lt;/a&gt;&lt;/p&gt;


&lt;p style="text-align: left;"&gt;So just turning the default codeigniter cache on gives us a significant speed improvement, going all the way and installing APC can nearly double the speed of your application. Not too shabby I should think.&lt;/p&gt;


&lt;p style="text-align: left;"&gt;It is &lt;strong&gt;so&lt;/strong&gt; easy to take advantage of this caching mechasism on Codeigniter 2 that it would really be a pity not to do so!&lt;/p&gt;


&lt;p style="text-align: left;"&gt;The only caching library missing here is memcached. Have you tried any of these caching libraries with codeigniter 2?&lt;/p&gt;


&lt;p style="text-align: left;"&gt;&lt;/p&gt;


&lt;p&gt;
&lt;/p&gt;


&lt;p&gt;&lt;/p&gt;

&lt;a href="http://jfoucher.com/2011/02/installing-running-apc-cache-codeigniter.html"&gt;Installing and running APC cache with CodeIgniter&lt;/a&gt; is a post by Jonathan Foucher at &lt;a
href="http://jfoucher.com"&gt;Geeky Nuggets&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=syTVGWrEKRg:Vd1wluc74Gc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=syTVGWrEKRg:Vd1wluc74Gc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=syTVGWrEKRg:Vd1wluc74Gc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/syTVGWrEKRg" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2011/02/installing-running-apc-cache-codeigniter.html</feedburner:origLink></entry>
	
	<entry>
		<title>Wordpress 404 notification by email</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/f8Tg5tsdps8/wordpress-email-404-notification.html" />
		<updated>Sat Jan 22 23:42:45 +0100 2011</updated>
		<id>http://jfoucher.com/2011/01/wordpress-email-404-notification</id>
		<content type="html">&lt;p&gt;I couldn't find something that did just what I wanted and no more: send me an email when someone gets a 404 error on my blog. It seems pretty simple, and it really is. More than that actually. It's problably the simplest plugin I've ever written.&lt;/p&gt;

&lt;p&gt;Check it out:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;email_error&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="nv"&gt;$wp_query&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$location&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$_SERVER&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;REQUEST_URI&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$wp_query&lt;/span&gt;&lt;span class="o"&gt;-&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nx"&gt;is_404&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nx"&gt;email_admin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$location&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;get_header&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;email_error&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This is the main part of the code, the one gets executed everytime the &lt;code&gt;get_header&lt;/code&gt; hook is called. It basically just checks the $wp_query object to see if the current url gives a 404 error and then passes that url to the email_admin function&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;email_admin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$location&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;get_option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;blogname&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;get_option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;admin_email&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$headers&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;MIME-Version: 1.0&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$headers&lt;/span&gt; &lt;span class="o"&gt;.=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Content-type: text/plain; charset=UTF-8&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$headers&lt;/span&gt; &lt;span class="o"&gt;.=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;From: &amp;quot;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;quot; &amp;amp;lt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$subject&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;404 error in &amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;A 404 error occured at the following url: &amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$_SERVER&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;SERVER_NAME&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$location&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This function sets some headers for the email, such as the sender's name and email, and the subject of the message, and then sends the message. No error is shown if the message can't be sent, as this would be displayed on the page.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;UPDATE&lt;/em&gt;: Finally available on the &lt;a href="http://wordpress.org/extend/plugins/email-404/"&gt;wordpress plugin repository&lt;/a&gt;&lt;/p&gt;
&lt;a href="http://jfoucher.com/2011/01/wordpress-email-404-notification.html"&gt;Wordpress 404 notification by email&lt;/a&gt; is a post by Jonathan Foucher at &lt;a
href="http://jfoucher.com"&gt;Geeky Nuggets&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=f8Tg5tsdps8:XEwLg4mVhRM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=f8Tg5tsdps8:XEwLg4mVhRM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=f8Tg5tsdps8:XEwLg4mVhRM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/f8Tg5tsdps8" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2011/01/wordpress-email-404-notification.html</feedburner:origLink></entry>
	
	<entry>
		<title>Spanish characters on Qwerty keyboard for Ubuntu 10.10</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/oKdxbL8-Ck4/spanish-characters-on-qwerty-keyboard-for-ubuntu-10-10.html" />
		<updated>Fri Jan 14 22:06:17 +0100 2011</updated>
		<id>http://jfoucher.com/2011/01/spanish-characters-on-qwerty-keyboard-for-ubuntu-10-10</id>
		<content type="html">&lt;p&gt;Typing spanish characters on a standard QWERTY (or other) keyboard is near impossible. I have used the Character Palette panel applet to do so, but this method requires clicking on the letter you want, and then paste it where you want it. To much work for my tastes. Yes I'm lazy. I'm a programmer.&lt;/p&gt;

&lt;p&gt;So, an easier is using the compose key. This allows me to type that key and a single apostrophe followed by the letter e for example, and get a �. I mapped the compose key to the left Win key, so the sequience is &lt;code&gt;LWin - ' &amp;gt; e&lt;/code&gt; which writes é&lt;/p&gt;

&lt;p&gt;To choose the compose key, open &lt;code&gt;Preferences &amp;gt; Keyboard&lt;/code&gt;,  &lt;code&gt;Layouts&lt;/code&gt; tab and click on &lt;code&gt;Options&lt;/code&gt;. Open the &lt;code&gt;Compose key position&lt;/code&gt; submenu, and choose whichever one you like best. I think the Win key is a good choice as it's not used for anything much... Except remind us of our freedom...&lt;/p&gt;

&lt;p&gt;&lt;a href="http://jfoucher.com/uploads/2011/01/Screenshot-Keyboard-Layout-Options-1.png"&gt;
&lt;img src="http://jfoucher.com/uploads/2011/01/Screenshot-Keyboard-Layout-Options-1-300x218.png" alt="Keyboard Layout Options" title="Keyboard Layout Options" width="300" height="218" class="aligncenter size-medium wp-image-264" /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And yay! Writing Spanish is cool again!&lt;/p&gt;
&lt;a href="http://jfoucher.com/2011/01/spanish-characters-on-qwerty-keyboard-for-ubuntu-10-10.html"&gt;Spanish characters on Qwerty keyboard for Ubuntu 10.10&lt;/a&gt; is a post by Jonathan Foucher at &lt;a
href="http://jfoucher.com"&gt;Geeky Nuggets&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=oKdxbL8-Ck4:QgD9ep53H2g:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=oKdxbL8-Ck4:QgD9ep53H2g:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=oKdxbL8-Ck4:QgD9ep53H2g:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/oKdxbL8-Ck4" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2011/01/spanish-characters-on-qwerty-keyboard-for-ubuntu-10-10.html</feedburner:origLink></entry>
	
	<entry>
		<title>Python skype notifier for Ubuntu</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/_ZltPcr9WN4/python-skype-notifier-for-ubuntu.html" />
		<updated>Fri Jan 14 13:21:52 +0100 2011</updated>
		<id>http://jfoucher.com/2011/01/python-skype-notifier-for-ubuntu</id>
		<content type="html">&lt;p&gt;What's the best way to learn a new programming language ? Well, according to &lt;a href="http://programmers.stackexchange.com/q/3519/3984"&gt;this question&lt;/a&gt; the best (only ?) way to learn a new language is just to code in that language.&lt;/p&gt;

&lt;h3&gt;Why Python ?&lt;/h3&gt;


&lt;p&gt;Because it's &lt;a href="http://en.wikipedia.org/wiki/Python_(programming_language)#Name_and_neologisms"&gt;named after the Monty Python&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No, seriously, that's why :&lt;a href="http://xkcd.com/353/"&gt;&lt;img class="aligncenter size-medium wp-image-201" title="python" src="http://jfoucher.com/uploads/2011/01/python-264x300.png" alt="I wrote 20 short programs in Python yesterday.  It was wonderful.  Perl, I'm leaving you." width="264" height="300" /&gt;&lt;/a&gt;No, not this "that's why"! &lt;a href="http://programmers.stackexchange.com/questions/10675/ideal-programming-language-learning-sequence#answer-10748"&gt;That one&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are just starting out as a programmer, I cannot recommend &lt;a href="http://learnpythonthehardway.org/"&gt;Learn Python The Hard Way&lt;/a&gt; highly enough. It is an excellent introduction to the ideas and skills you will need as a programmer, starting from the very basics, like you've never seen a for loop in your life.
Actually the first 10 or so lessons do not include ANY control structures!&lt;/p&gt;

&lt;p&gt;If on the other hand you already have some coding experience, I recomend &lt;a href="http://diveintopython.org/"&gt;Dive Into Python&lt;/a&gt;.
Although it's no quite as hands on as Learn Python the Hard Way, it's a very good book, only covering the basics insofar as they are specific to python.&lt;/p&gt;

&lt;h3&gt;Why for &lt;a href="/2011/01/193-compile-custom-kernel-on-ubuntu-10-10.html"&gt;Ubuntu&lt;/a&gt;?&lt;/h3&gt;


&lt;p&gt;That's what I use. Simple as that. Also python and pygtk are included by default, making distribution much easier.&lt;/p&gt;

&lt;h3&gt;Why Skype?&lt;/h3&gt;


&lt;p&gt;Haven't found out yet. I started developping a backup application in pygtk and glade, a front end to rsync, but got sidetracked reading about the chnges to Ubuntu's &lt;a href="https://wiki.ubuntu.com/DesktopExperienceTeam/ApplicationIndicators"&gt;application notifier&lt;/a&gt;, ended up interested in the &lt;a href="https://wiki.ubuntu.com/MessagingMenu"&gt;messaging notifier&lt;/a&gt;, and decided to do something with that.&lt;/p&gt;

&lt;p&gt;Skype seemed like the obvious target, given that's it's the only communication application I use that lacks a messaging menu indicator. It does have a systray icon though, so my app is probably superfluous...&lt;/p&gt;

&lt;h3&gt;Anyway, to the coding!&lt;/h3&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="python"&gt;&lt;span class="c"&gt;#!/usr/bin/env python&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;indicate&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;gobject&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pynotify&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;gtk&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;hashlib&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Skype4Py&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;urllib&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The first line tell the host system to use python to interpret that file&lt;/p&gt;

&lt;p&gt;The next lines import the required python modules.&lt;/p&gt;

&lt;p&gt;Next, we have to define the main class and declare some variables:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="python"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;skypeIndicator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;notifShown&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;oldcount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This is the clas initialization function&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="python"&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Skype4Py&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Skype&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loadSkype&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="c"&gt;#create notification icon&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;indicate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicate_server_ref_default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;message.im&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_desktop_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/usr/share/applications/skype.desktop&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;server-display&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;server_display&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_indicators&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The first line creates the skype API instance, after which we call the loadSkype() function, which checks if skype is loaded and if not, starts it. We'll look at that function later on.
Next, we create the notification server instance, choose an icon, connect the function server_display to the server-display event (when the icon is clicked on) and finally run the create_indicators function that looks for skype messages and displays them accordingly.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="python"&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;loadSkype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsRunning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c"&gt;#&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Please open skype first&amp;quot;&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;noSkype&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Attach&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;Skype4Py&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ISkypeAPIError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Please open skype first&amp;quot;&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;noSkype&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This basically tries to start skype if it is not already started and calls noSkype() if it couldn't start it. noSype() shows a notification message to let the user know that they have to start Skype.
&lt;a href="http://jfoucher.com/uploads/2011/01/skype-not-started.png"&gt;&lt;img src="http://jfoucher.com/uploads/2011/01/skype-not-started.png" alt="Error shown if Skype is not running" title="skype-not-started" width="428" height="213" class="aligncenter size-full wp-image-256" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This next function is where the meat of the process takes place. Please read the inline comments to understand how it works, and ask for clarification by &lt;a href="#respond"&gt;posting a comment&lt;/a&gt;.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="python"&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_indicators&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Loads skype messages, displays them as notification bubbles and also shows them in the messaging menu&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

        &lt;span class="c"&gt;#initialize count dictionaries&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="c"&gt;#get unread messages from skype, set self.unread variable&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_messages&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c"&gt;#self.unread is a dictionary having the username of the sender as key and a list of messages as value&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unread&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

            &lt;span class="c"&gt;# Here we look at the first message from this user to set the messaging menu indicator&lt;/span&gt;
            &lt;span class="c"&gt;# we only want one indicator per user&lt;/span&gt;
            &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unread&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

            &lt;span class="c"&gt;#initialize message count for this user&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;oldcount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;oldcount&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;

            &lt;span class="c"&gt;# if this user doesn&amp;#39;t have his indicator yet&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c"&gt;# create indicator&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;indicate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Indicator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;creating indicator&amp;quot;&lt;/span&gt;

                &lt;span class="c"&gt;# Set indicator properties&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fullname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name_from_handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;subtype&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;im&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sender&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fullname&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;handle&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="c"&gt;#this gets the most user-friendly name available for this user&lt;/span&gt;
                &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_from_handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="c"&gt;# get an avatar for this user&lt;/span&gt;
                &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="c"&gt;# This will only work on windows&lt;/span&gt;
                    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;.jpg&amp;#39;&lt;/span&gt;
                    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SaveAvatarToFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;Skype4Py&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ISkypeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="c"&gt;# So on linux we use a generated monster ID. Fun but useless!&lt;/span&gt;
                    &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;md5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="c"&gt;#TODO find a way to get skype avatars on linux&lt;/span&gt;
                    &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urlretrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://friedcellcollective.net/monsterid/monster/&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;/64&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;.jpg&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;.jpg&amp;#39;&lt;/span&gt;

                &lt;span class="c"&gt;#convert the imge to a pixbuf&lt;/span&gt;
                &lt;span class="n"&gt;pixbuf&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;gtk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gdk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pixbuf_new_from_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="c"&gt;# for use in the indicator&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property_icon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;icon&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pixbuf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="c"&gt;# set the timestamp of the indicator (this is what makes the indicator display the time since the message was received&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property_time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;time&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Timestamp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="c"&gt;# when the user clicks on the indicator message, open the skype messaging window for this user&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user-display&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;display_msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                
            &lt;span class="n"&gt;msgbody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
            &lt;span class="c"&gt;#reverse list so latest message is at the bottom&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;eachmsg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unread&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;][::&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
                &lt;span class="c"&gt;# msgbody contains all the messages from that user so far&lt;/span&gt;
                &lt;span class="n"&gt;msgbody&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;eachmsg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;

            &lt;span class="c"&gt;# We set this person&amp;#39;s indicator body to the compound text&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;body&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msgbody&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c"&gt;# if there are more than one message from this user, we set the indicator count to be displayed in the messaging menu.&lt;/span&gt;
            &lt;span class="c"&gt;# Otherwise the time elapsed since receiving the message will be shown&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;count&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
            
            &lt;span class="c"&gt;# If a new message arrived since last time checked, mark notification as not shown&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;oldcount&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notifShown&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;

            &lt;span class="c"&gt;#If notification marked as not shown, show it&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notifShown&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;showNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fullname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msgbody&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="c"&gt;#mark notification as shown&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notifShown&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;

                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;draw-attention&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;notification shown for&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;

            &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt; messages from &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c"&gt;# Set oldcountt variable for next loop&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;oldcount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;
        &lt;span class="c"&gt;# Loop runs as long as true is returned&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;When a new messages arrives, this is what the messaging menu looks like
&lt;a href="http://jfoucher.com/uploads/2011/01/skype-indicator-menu.png"&gt;&lt;img src="http://jfoucher.com/uploads/2011/01/skype-indicator-menu.png" alt="Messaging menu open qith unread messages" title="skype-indicator-menu" width="376" height="256" class="aligncenter size-full wp-image-258" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The function that gets unread skype messages is as follows For each message, we add it to a list containg the messages from a particular user in the self.unread dictionary.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="python"&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_messages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;checking messages&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unread&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MissedMessages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;display_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromHandle&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unread&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unread&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
            
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unread&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unread&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The next two functions are in charge of getting the skype user username as well as the friendliest name available.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="python"&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;name_from_handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FullName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FullName&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DisplayName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DisplayName&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;user_from_handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Below is the generic function in charge of showing popup notifications.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="python"&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;showNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;takes a title and a message to display the email notification. Returns the&lt;/span&gt;
&lt;span class="sd"&gt;        created notification object&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;

        &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pynotify&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Notification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;notification-message-im&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;icon-name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getcwd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;/&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This is what it looks like with three new messages
&lt;a href="http://jfoucher.com/uploads/2011/01/skype-indicator.png"&gt;&lt;img src="http://jfoucher.com/uploads/2011/01/skype-indicator.png" alt="The Ubuntu skype indicator with three new messages" title="skype-indicator" width="428" height="232" class="aligncenter size-full wp-image-253" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next one shows the popup notification that skype is not loaded :&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="python"&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;noSkype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;Shows a notification if skype is not started&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
        &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Start Skype&amp;#39;&lt;/span&gt;
        &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Please start skype otherwise this won&lt;/span&gt;&lt;span class="se"&gt;\&amp;#39;&lt;/span&gt;&lt;span class="s"&gt;t work&amp;#39;&lt;/span&gt;
        &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;showNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;icon-name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;gtk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STOCK_DIALOG_WARNING&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And finally, the indicator events callbacks (what happens when we click on the skype indicator, or on a particular message&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="python"&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;display_msg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c"&gt;#hide this indicator&lt;/span&gt;
        &lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="c"&gt;#messaging menu goes back to normal&lt;/span&gt;
        &lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;draw-attention&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c"&gt;# open the skype chat window for this user&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenMessageDialog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;handle&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;At the end of the file, we start everything :&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="python"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;skypeind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;skypeIndicator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c"&gt;# Loop&lt;/span&gt;
    &lt;span class="n"&gt;gobject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout_add_seconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;skypeind&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_indicators&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;gtk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And finally, here is the complete source code :&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="python"&gt;&lt;span class="c"&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;#Copyright 2010 Jonathan Foucher&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;#Authors:&lt;/span&gt;
&lt;span class="c"&gt;#    Jonathan Foucher &amp;lt;jfoucher@6px.eu&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;#This program is free software: you can redistribute it and/or modify it &lt;/span&gt;
&lt;span class="c"&gt;#under the terms of either or both of the following licenses:&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;#1) the GNU Lesser General Public License version 3, as published by the &lt;/span&gt;
&lt;span class="c"&gt;#Free Software Foundation; and/or&lt;/span&gt;
&lt;span class="c"&gt;#2) the GNU Lesser General Public License version 2.1, as published by &lt;/span&gt;
&lt;span class="c"&gt;#the Free Software Foundation.&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;#This program is distributed in the hope that it will be useful, but &lt;/span&gt;
&lt;span class="c"&gt;#WITHOUT ANY WARRANTY; without even the implied warranties of &lt;/span&gt;
&lt;span class="c"&gt;#MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR &lt;/span&gt;
&lt;span class="c"&gt;#PURPOSE.  See the applicable version of the GNU Lesser General Public &lt;/span&gt;
&lt;span class="c"&gt;#License for more details.&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;#You should have received a copy of both the GNU Lesser General Public &lt;/span&gt;
&lt;span class="c"&gt;#License version 3 and version 2.1 along with this program.  If not, see &lt;/span&gt;
&lt;span class="c"&gt;#&amp;lt;http://www.gnu.org/licenses/&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;


&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;indicate&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;gobject&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pynotify&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;gtk&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;hashlib&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Skype4Py&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;urllib&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;skypeIndicator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;notifShown&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;oldcount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c"&gt;#self.no_skype()&lt;/span&gt;
        &lt;span class="c"&gt;#get skype control&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Skype4Py&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Skype&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loadSkype&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c"&gt;#create notification icon&lt;/span&gt;

        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;indicate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicate_server_ref_default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;message.im&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_desktop_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/usr/share/applications/skype.desktop&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;server-display&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;server_display&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c"&gt;#self.server.set_status (indicate.STATUS_ACTIVE)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c"&gt;#       for slot in dir(self.server):&lt;/span&gt;
&lt;span class="c"&gt;#           attr = getattr(self.server, slot)&lt;/span&gt;
&lt;span class="c"&gt;#           print attr&lt;/span&gt;

        &lt;span class="c"&gt;#self.unread={}&lt;/span&gt;
        &lt;span class="c"&gt;#self.indicator.set_property(&amp;#39;draw-attention&amp;#39;, &amp;#39;true&amp;#39;);&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_indicators&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="c"&gt;#pass&lt;/span&gt;
        &lt;span class="c"&gt;#indicator.connect(&amp;quot;user-display&amp;quot;, self.display_msg)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;loadSkype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsRunning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c"&gt;#&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Please open skype first&amp;quot;&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;noSkype&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;



        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Attach&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;Skype4Py&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ISkypeAPIError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Please open skype first&amp;quot;&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;noSkype&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c"&gt;#pass&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_indicators&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Loads skype messages, displays them as notification bubbles and also shows them in the messaging menu&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

        &lt;span class="c"&gt;#initialize count dictionaries&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="c"&gt;#get unread messages from skype, set self.unread variable&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_messages&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c"&gt;#self.unread is a dictionary having the username of the sender as key and a list of messages as value&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unread&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

            &lt;span class="c"&gt;# Here we look at the first message from this user to set the messaging menu indicator&lt;/span&gt;
            &lt;span class="c"&gt;# we only want one indicator per user&lt;/span&gt;
            &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unread&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

            &lt;span class="c"&gt;#initialize message count for this user&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;oldcount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;oldcount&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;

            &lt;span class="c"&gt;# if this user doesn&amp;#39;t have his indicator yet&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c"&gt;# create indicator&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;indicate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Indicator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;creating indicator&amp;quot;&lt;/span&gt;

                &lt;span class="c"&gt;# Set indicator properties&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fullname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name_from_handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;subtype&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;im&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sender&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fullname&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;handle&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="c"&gt;#this gets the most user-friendly name available for this user&lt;/span&gt;
                &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_from_handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="c"&gt;# get an avatar for this user&lt;/span&gt;
                &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="c"&gt;# This will only work on windows&lt;/span&gt;
                    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;.jpg&amp;#39;&lt;/span&gt;
                    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SaveAvatarToFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;Skype4Py&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ISkypeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="c"&gt;# So on linux we use a generated monster ID. Fun but useless!&lt;/span&gt;
                    &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;md5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="c"&gt;#TODO find a way to get skype avatars on linux&lt;/span&gt;
                    &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urlretrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://friedcellcollective.net/monsterid/monster/&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;/64&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;.jpg&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;.jpg&amp;#39;&lt;/span&gt;

                &lt;span class="c"&gt;#convert the imge to a pixbuf&lt;/span&gt;
                &lt;span class="n"&gt;pixbuf&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;gtk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gdk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pixbuf_new_from_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="c"&gt;# for use in the indicator&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property_icon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;icon&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pixbuf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="c"&gt;# set the timestamp of the indicator (this is what makes the indicator display the time since the message was received&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property_time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;time&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Timestamp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="c"&gt;# when the user clicks on the indicator message, open the skype messaging window for this user&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user-display&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;display_msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                
            &lt;span class="n"&gt;msgbody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
            &lt;span class="c"&gt;#reverse list so latest message is at the bottom&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;eachmsg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unread&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;][::&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
                &lt;span class="c"&gt;# msgbody contains all the messages from that user so far&lt;/span&gt;
                &lt;span class="n"&gt;msgbody&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;eachmsg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;

            &lt;span class="c"&gt;# We set this person&amp;#39;s indicator body to the compound text&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;body&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msgbody&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c"&gt;# if there are more than one message from this user, we set the indicator count to be displayed in the messaging menu.&lt;/span&gt;
            &lt;span class="c"&gt;# Otherwise the time elapsed since receiving the message will be shown&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;count&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
            
            &lt;span class="c"&gt;# If a new message arrived since last time checked, mark notification as not shown&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;oldcount&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notifShown&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;

            &lt;span class="c"&gt;#If notification marked as not shown, show it&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notifShown&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;showNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fullname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msgbody&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="c"&gt;#mark notification as shown&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notifShown&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;

                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;draw-attention&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;notification shown for&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;

            &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt; messages from &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c"&gt;# Set oldcountt variable for next loop&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;oldcount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;
        &lt;span class="c"&gt;# Loop runs as long as true is returned&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;


    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;name_from_handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FullName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FullName&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DisplayName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DisplayName&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;user_from_handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;showNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;takes a title and a message to display the email notification. Returns the&lt;/span&gt;
&lt;span class="sd"&gt;        created notification object&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;

        &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pynotify&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Notification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;notification-message-im&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;icon-name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getcwd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;/&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;noSkype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;Shows a notification if skype is not started&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
        &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Start Skype&amp;#39;&lt;/span&gt;
        &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Please start skype otherwise this won&lt;/span&gt;&lt;span class="se"&gt;\&amp;#39;&lt;/span&gt;&lt;span class="s"&gt;t work&amp;#39;&lt;/span&gt;
        &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;showNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;icon-name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;gtk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STOCK_DIALOG_WARNING&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_messages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;checking messages&amp;quot;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unread&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MissedMessages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;display_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromHandle&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unread&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unread&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
            
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unread&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unread&lt;/span&gt;



    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;server_display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c"&gt;#Show main Skype window&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Focus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;display_msg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c"&gt;#hide this indicator&lt;/span&gt;
        &lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="c"&gt;#messaging menu goes back to normal&lt;/span&gt;
        &lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;draw-attention&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c"&gt;# open the skype chat window for this user&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenMessageDialog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;handle&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;



&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="n"&gt;skypeind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;skypeIndicator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;# Loop&lt;/span&gt;
    &lt;span class="n"&gt;gobject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout_add_seconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;skypeind&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_indicators&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;gtk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Download the script, or fork it on the &lt;a href="https://github.com/jfoucher/ubuntu-skype-indicator"&gt;ubuntu-skype-indicator github repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;UPDATE: Before you run this script, you need to install its dependencies, python-indicate and skype4py
On ubuntu, it's as simple as running&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;sudo apt-get install python-skype python-indicate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;a href="http://jfoucher.com/2011/01/python-skype-notifier-for-ubuntu.html"&gt;Python skype notifier for Ubuntu&lt;/a&gt; is a post by Jonathan Foucher at &lt;a
href="http://jfoucher.com"&gt;Geeky Nuggets&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=_ZltPcr9WN4:dv7-TV4hS68:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=_ZltPcr9WN4:dv7-TV4hS68:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=_ZltPcr9WN4:dv7-TV4hS68:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/_ZltPcr9WN4" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2011/01/python-skype-notifier-for-ubuntu.html</feedburner:origLink></entry>
	
	<entry>
		<title>Compile custom kernel on Ubuntu 10.10</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/LEeObYUmD54/compile-custom-kernel-on-ubuntu-10-10.html" />
		<updated>Wed Jan 12 15:06:02 +0100 2011</updated>
		<id>http://jfoucher.com/2011/01/compile-custom-kernel-on-ubuntu-10-10</id>
		<content type="html">&lt;p&gt;First off, you want to grab the latest kernel source from &lt;a href="http://kernel.org/"&gt;http://kernel.org/&lt;/a&gt; and save it to a folder on your computer. I used my browser's default : &lt;code&gt;~/Downloads&lt;/code&gt;. Right click on the archive and select "extract here"&lt;/p&gt;

&lt;h3&gt;Configuration&lt;/h3&gt;


&lt;p&gt;Open a terminal, "cd" to your source directory, in my case &lt;code&gt;cd ~/Downloads/linux-2.6.37&lt;/code&gt; and run &lt;code&gt;make gconfig&lt;/code&gt; if using Ubuntu or &lt;code&gt;make kconfig&lt;/code&gt; if running Kubuntu. At that point, you'll need to know a fair bit about your system's hardware, to select only the options that are applicable. I like to reuse my current config as a starting point, so if you are using the default ubuntu kernel, the configuration used is stored in the &lt;code&gt;boot&lt;/code&gt; directory, with names like &lt;code&gt;config-2.6.35-24-generic&lt;/code&gt;&lt;/p&gt;

&lt;p&gt; Copy the latest one to your linux source directory. When the configuration editor is loaded, choose &lt;code&gt;File &amp;gt;&amp;gt; Load&lt;/code&gt; and select the file you just copied over. Now the Ubuntu default configuration is loaded. If you were to compile your kernel you would get the same kind of system you have now : functional but suboptimal.&lt;/p&gt;

&lt;h3&gt;We'll try and better that a bit.&lt;/h3&gt;

&lt;p&gt;The first submenu I open is Processor type and features. In there, I disable everything related to SMP and Paravirtualized guest support as I do not plan to run this as a VM guest. I choose the type of processor appropriate to my machine, in this case "new Xeon"&lt;/p&gt;

&lt;p&gt;You can use &lt;code&gt;make localmodconfig&lt;/code&gt; which will disable all the modules not currently loaded from your config file. Be careful though, because if there are devices and/of file systems you're not using at the moment, the drivers won't be added.&lt;/p&gt;

&lt;h3&gt;Compiling and instalation&lt;/h3&gt;

&lt;p&gt;Once you're happy with the configuration, save and close the editor, and run &lt;code&gt;make all&lt;/code&gt; or &lt;code&gt;make -j4 all&lt;/code&gt; on multicore processors to run several processes in parallel, which will compile the kernel and the modules specified in the &lt;code&gt;.config&lt;/code&gt; file&lt;/p&gt;

&lt;p&gt;That's the regular debian method, in which you have to run mkinitrd afterwards. I ended up doing it &lt;a href="https://help.ubuntu.com/community/Kernel/Compile"&gt;the ubuntu way&lt;/a&gt;, where you create .deb packages you can later install with your preferred package manager.&lt;/p&gt;

&lt;p&gt;If you re-used the existing configuration, note that Ubuntu kernels build with debugging information on, which makes the resulting kernel modules (*.ko files) much larger than they would otherwise be. To turn this off, go into the config's "Kernel hacking"&amp;lt;!-- ; then, under "Kernel debugging", --&amp;gt; and turn OFF "Compile the kernel with debug info".&lt;/p&gt;

&lt;h3&gt;Now you can compile the kernel and create the packages:&lt;/h3&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;make-kpkg clean &lt;span class="c"&gt;# only needed if you want to do a &amp;quot;clean&amp;quot; build&lt;/span&gt;
fakeroot make-kpkg --initrd --append-to-version&lt;span class="o"&gt;=&lt;/span&gt;-some-string-here kernel-image kernel-headers
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;




&lt;p style="text-align: center;"&gt;&lt;img class="aligncenter" src="http://media.tumblr.com/tumblr_let0e9SCP01qzbvjd.png" alt="" width="500" height="338" /&gt;&lt;/p&gt;


&lt;p&gt;Much easier...&lt;/p&gt;

&lt;h3&gt;Drivers&lt;/h3&gt;

&lt;p&gt;Of course, if you're using non-free drivers, you'll want to reinstall them. The first time I booted the new kernel, X did not start because it couldn't load the nvidia kernel module. Luckily, I had the latest driver around from a previous install, so installed straight away from the command line.&lt;/p&gt;

&lt;p&gt;You should now have a working Ubuntu install running your own custom kernel. Of course, you are responsible for upgradin kernel and binary drivers, as the updates from Ubuntu are not going to work any longer... Although I'm not so sure about that. I'll see in a while I guess.&lt;/p&gt;

&lt;h3&gt;Done!&lt;/h3&gt;

&lt;p&gt;Anyway, in my case this upgrade is really worth it because I get a functioning built-in microphone on my Vaio! Yay!&lt;/p&gt;

&lt;p&gt;So the moral is: don't be scared of trying a custom kernel, it really got much easier, and if you don't like it, going back is as easy as selecting another entry in grub...&lt;/p&gt;
&lt;a href="http://jfoucher.com/2011/01/compile-custom-kernel-on-ubuntu-10-10.html"&gt;Compile custom kernel on Ubuntu 10.10&lt;/a&gt; is a post by Jonathan Foucher at &lt;a
href="http://jfoucher.com"&gt;Geeky Nuggets&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=LEeObYUmD54:dzaLP4Ucfxc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=LEeObYUmD54:dzaLP4Ucfxc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=LEeObYUmD54:dzaLP4Ucfxc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/LEeObYUmD54" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2011/01/compile-custom-kernel-on-ubuntu-10-10.html</feedburner:origLink></entry>
	
	<entry>
		<title>New version of the auto-tag plugin released!</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/oOHpeOMYH-o/version-autotag-plugin-released.html" />
		<updated>Wed May 19 16:45:10 +0200 2010</updated>
		<id>http://jfoucher.com/2010/05/version-autotag-plugin-released</id>
		<content type="html">&lt;p&gt;&lt;a href="http://wordpress.org/extend/plugins/auto-tag/"&gt;Version 0.4 is here!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I know it's been a long time coming, but I just couldn't let you all down on that.&lt;/p&gt;

&lt;p&gt;Heavily refactored, lots of bug fixes, some nice improvements, I think you're going to like it.&lt;/p&gt;

&lt;p&gt;Let me know how it goes !&lt;/p&gt;
&lt;a href="http://jfoucher.com/2010/05/version-autotag-plugin-released.html"&gt;New version of the auto-tag plugin released!&lt;/a&gt; is a post by Jonathan Foucher at &lt;a
href="http://jfoucher.com"&gt;Geeky Nuggets&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=oOHpeOMYH-o:tF4zB-NaiP0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=oOHpeOMYH-o:tF4zB-NaiP0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=oOHpeOMYH-o:tF4zB-NaiP0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/oOHpeOMYH-o" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2010/05/version-autotag-plugin-released.html</feedburner:origLink></entry>
	
	<entry>
		<title>One app a month challenge</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/ID6mHe4enfc/one-app-a-month-challenge.html" />
		<updated>Sat Jan 02 00:29:39 +0100 2010</updated>
		<id>http://jfoucher.com/2010/01/one-app-a-month-challenge</id>
		<content type="html">&lt;p&gt;To keep learning and progressing in my line of work, you have to be &lt;strong&gt;learning new things&lt;/strong&gt; everyday. The evolution is so fast that if you don't go forward, you are effectively going backwards.&lt;/p&gt;

&lt;blockquote&gt;I need ideas of useful apps or libraries to include in this challenge.&lt;/blockquote&gt;


&lt;p&gt;So, my&lt;strong&gt; challenge for 2010&lt;/strong&gt; will be to build one web app &lt;strong&gt;every month&lt;/strong&gt;, and publish it here on the last day of each month. My schedule is pretty tight right now, so the apps will have to be rather quick to develop, but hopefuly it will help me learn new techniques and better coding practices. As they say, "practice makes perfect"...&lt;/p&gt;

&lt;p&gt;Whether I use a framework or not is entirely up to me, but I'd like to take this opportunity to try my hand at &lt;a href="http://www.kohanaphp.com/"&gt;Kohana&lt;/a&gt;. I've been using &lt;a href="http://codeigniter.com"&gt;CodeIgniter&lt;/a&gt; for nearly one year, and it seems like Kohana takes the CI spirit one step further.&lt;/p&gt;

&lt;p&gt;So, this is where I need your help : I need &lt;strong&gt;ideas of useful apps&lt;/strong&gt; or libraries to include in this challenge. The first one is going to be a &lt;strong&gt;url shortener&lt;/strong&gt;, developping the shortening and storing algorithms from scratch. I'm not sure whether I should do it as a standalone app, a standalone library, or a Kohana library...&lt;/p&gt;

&lt;p&gt;So, if you have any ideas about what I should develop, something you need, whatever, please comment below, thanks!&lt;/p&gt;

&lt;p&gt;EDIT: The result of the January Challenge is now live : &lt;a href="http://6px.eu/smallurl"&gt;The URL shortener&lt;/a&gt;&lt;/p&gt;
&lt;a href="http://jfoucher.com/2010/01/one-app-a-month-challenge.html"&gt;One app a month challenge&lt;/a&gt; is a post by Jonathan Foucher at &lt;a
href="http://jfoucher.com"&gt;Geeky Nuggets&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=ID6mHe4enfc:lg2nFdxsMYA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=ID6mHe4enfc:lg2nFdxsMYA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=ID6mHe4enfc:lg2nFdxsMYA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/ID6mHe4enfc" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2010/01/one-app-a-month-challenge.html</feedburner:origLink></entry>
	
	<entry>
		<title>BlueIce Plugin</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/75jSBrsIdHs/blueice-plugin.html" />
		<updated>Mon Dec 14 17:59:32 +0100 2009</updated>
		<id>http://jfoucher.com/2009/12/blueice-plugin</id>
		<content type="html">&lt;p&gt;I just created a very simple plugin for &lt;a title="The Anti-CMS" href="http://blueiceapp.com"&gt;BlueIce&lt;/a&gt;, the anti-CMS. It simply inserts a list containg links to all pages in the web site. The author published it on his &lt;a href="http://blueiceapp.com/docs/plugins"&gt;3rd party plugins&lt;/a&gt; page, and I highly recommend his anti-CMS for small, semi static sites.&lt;/p&gt;

&lt;p&gt;It includes a clever cache system, so your web site will be almost as fast as if it was pure static html. All pages are rendered using &lt;a href="http://daringfireball.net/projects/markdown/"&gt;Markdown&lt;/a&gt;, making for simple content editing, using a &lt;a href="http://geany.org/"&gt;text editor&lt;/a&gt; and an FTP client.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;UPDATE 2011:&lt;/em&gt;
Blue ice seems to be dead, and so so is this plugin, i guess...&lt;/p&gt;
&lt;a href="http://jfoucher.com/2009/12/blueice-plugin.html"&gt;BlueIce Plugin&lt;/a&gt; is a post by Jonathan Foucher at &lt;a
href="http://jfoucher.com"&gt;Geeky Nuggets&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=75jSBrsIdHs:AAnGNuqOU-Y:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=75jSBrsIdHs:AAnGNuqOU-Y:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=75jSBrsIdHs:AAnGNuqOU-Y:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/75jSBrsIdHs" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2009/12/blueice-plugin.html</feedburner:origLink></entry>
	
	<entry>
		<title>Why Google Wave is useless (with invites giveaway)</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/i2CpcEns-rA/google-wave-useless.html" />
		<updated>Fri Nov 20 10:00:29 +0100 2009</updated>
		<id>http://jfoucher.com/2009/11/google-wave-useless</id>
		<content type="html">&lt;div class="image-with-caption aligncenter" style="width:300px"&gt;&lt;div class="caption"&gt;Google Wave&lt;/div&gt;&lt;a href="http://jfoucher.com/uploads/2009/11/Screenshot-1.png"&gt;&lt;img class="size-medium wp-image-172" title="Google Wave" src="http://jfoucher.com/uploads/2009/11/Screenshot-1-300x158.png" alt="Google Wave" width="300" height="158" /&gt;&lt;/a&gt;&lt;/div&gt;


&lt;h3&gt;1. You need to have it open in your browser to appear online&lt;/h3&gt;


&lt;h3&gt;2. Nobody is ever online for that exact reason.&lt;/h3&gt;


&lt;h3&gt;3. All my contacts disappeared&lt;/h3&gt;


&lt;p&gt;For no apparent reason, none of my contacts are showing in wave right now... Kind of reduces the usability.&lt;/p&gt;

&lt;h3&gt;4. Too many ads in independently developped "gadgets"&lt;/h3&gt;


&lt;h3&gt;5. Counter intuitive interface.&lt;/h3&gt;


&lt;ul&gt;
    &lt;li&gt;"pinging" someone just opens a new wave with that contact : I could have done that myself... Do something more, like, I don't know, send an email&lt;/li&gt;
    &lt;li&gt;can't search trough a list to add contacts that are on wave&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;And now (oh the irony) to the Wave invite giveaway.&lt;/h3&gt;


&lt;p&gt;Very easy : leave a comment on this post with your real email address, and on Monday at 12 GMT I'll pick ten winners. (yes I have that many unused invites...)&lt;/p&gt;

&lt;p&gt;Have a good weekend&lt;/p&gt;
&lt;a href="http://jfoucher.com/2009/11/google-wave-useless.html"&gt;Why Google Wave is useless (with invites giveaway)&lt;/a&gt; is a post by Jonathan Foucher at &lt;a
href="http://jfoucher.com"&gt;Geeky Nuggets&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=i2CpcEns-rA:ucypBBp046k:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/GeekyNuggets?a=i2CpcEns-rA:ucypBBp046k:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=i2CpcEns-rA:ucypBBp046k:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/i2CpcEns-rA" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2009/11/google-wave-useless.html</feedburner:origLink></entry>
	
</feed>
