<?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>2012-01-06T12:00:44+00:00</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>Implementing BrowserID identification on your website</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/kNEoOm5w3Jo/implementing-browserid-identification.html" />
		<updated>2011-12-25T13:05:13+00:00</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="nx"&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="nx"&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>2011-09-16T23:09:13+00:00</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>2011-08-17T23:09:13+00:00</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>2011-06-29T12:10:00+00:00</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>2011-04-11T12:10:51+00:00</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://cdn.jfoucher.com/uploads/2011/04/Screenshot.png"&gt;&lt;img class="size-medium wp-image-450" title="css minification for codeigniter" src="http://cdn.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>2011-04-03T19:42:49+00:00</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://cdn.jfoucher.com/uploads/2011/03/FlickHoldr1.png"&gt;&lt;img class="size-full wp-image-413" title="FlickHoldr" src="http://cdn.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>2011-02-13T22:33:33+00:00</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;amp;gt;output-&amp;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://cdn.jfoucher.com/uploads/2011/02/chart22.png"&gt;&lt;img class="aligncenter size-full wp-image-387" title="Codeigniter APC cache benchmark" src="http://cdn.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://cdn.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://cdn.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>2011-01-22T22:42:45+00:00</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="x"&gt;function email_error(){&lt;/span&gt;
&lt;span class="x"&gt;    global $wp_query;&lt;/span&gt;
&lt;span class="x"&gt;    $location=$_SERVER[&amp;#39;REQUEST_URI&amp;#39;];&lt;/span&gt;
&lt;span class="x"&gt;    if ($wp_query-&amp;amp;gt;is_404){&lt;/span&gt;
&lt;span class="x"&gt;        email_admin($location);&lt;/span&gt;
&lt;span class="x"&gt;    }&lt;/span&gt;
&lt;span class="x"&gt;}&lt;/span&gt;
&lt;span class="x"&gt;add_action(&amp;#39;get_header&amp;#39;, &amp;#39;email_error&amp;#39;);&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;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;get_header&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&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="x"&gt;function email_admin($location){&lt;/span&gt;
&lt;span class="x"&gt;    $name=get_option(&amp;#39;blogname&amp;#39;);&lt;/span&gt;
&lt;span class="x"&gt;    $email = get_option(&amp;#39;admin_email&amp;#39;);&lt;/span&gt;
&lt;span class="x"&gt;    $headers  = &amp;quot;MIME-Version: 1.0\r\n&amp;quot;;&lt;/span&gt;
&lt;span class="x"&gt;    $headers .= &amp;quot;Content-type: text/plain; charset=UTF-8\r\n&amp;quot;;&lt;/span&gt;
&lt;span class="x"&gt;    $headers .= &amp;#39;From: &amp;quot;&amp;#39; . $name . &amp;#39;&amp;quot; &amp;amp;lt;&amp;#39; .$email. &amp;quot;&amp;amp;gt;\r\n&amp;quot;;&lt;/span&gt;
&lt;span class="x"&gt;    $subject=&amp;#39;404 error in &amp;#39;.$name;&lt;/span&gt;
&lt;span class="x"&gt;    $body=&amp;#39;A 404 error occured at the following url: &amp;#39;.$_SERVER[&amp;#39;SERVER_NAME&amp;#39;].$location;&lt;/span&gt;
&lt;span class="x"&gt;    @mail($email,$subject,$body,$headers);&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;strong&gt;UPDATE&lt;/strong&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;/p&gt;

&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;br /&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;&amp;lt;br /&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;function email_error(){&amp;lt;br /&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    global $wp_query;&amp;lt;br /&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    $location=$_SERVER[&amp;#39;REQUEST_URI&amp;#39;];&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;&amp;lt;p&amp;gt;   if ($wp_query-&amp;gt;is_404){&amp;lt;br /&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;        email_admin($location);&amp;lt;br /&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    }&amp;lt;br /&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;}&amp;lt;br /&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;add_action(&amp;#39;get_header&amp;#39;, &amp;#39;email_error&amp;#39;);&amp;lt;br /&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;br /&gt;
This is the main part of the code, the one gets executed everytime the 
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;get_header&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&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;p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;&amp;lt;br /&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;function email_admin($location){&amp;lt;br /&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    $name=get_option(&amp;#39;blogname&amp;#39;);&amp;lt;br /&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    $email = get_option(&amp;#39;admin_email&amp;#39;);&amp;lt;br /&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    $headers  = &amp;quot;MIME-Version: 1.0\r\n&amp;quot;;&amp;lt;br /&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    $headers .= &amp;quot;Content-type: text/plain; charset=UTF-8\r\n&amp;quot;;&amp;lt;br /&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    $headers .= &amp;#39;From: &amp;quot;&amp;#39; . $name . &amp;#39;&amp;quot; &amp;lt;&amp;#39; .$email. &amp;quot;&amp;gt;\r\n&amp;quot;;&amp;lt;br /&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    $subject=&amp;#39;404 error in &amp;#39;.$name;&amp;lt;br /&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    $body=&amp;#39;A 404 error occured at the following url: &amp;#39;.$_SERVER[&amp;#39;SERVER_NAME&amp;#39;].$location;&amp;lt;br /&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    @mail($email,$subject,$body,$headers);&amp;lt;br /&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;}&amp;lt;br /&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;/p&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;Until approval by the wordpress.org guys, you can download it here: &lt;a href='http://cdn.jfoucher.com/uploads/2011/01/email-404.zip'&gt;Email 404 Wordpress plugin&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;&lt;/p&gt;&lt;/p&gt;

&lt;p&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>2011-01-14T21:06:17+00:00</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;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;LWin - &amp;#39; &amp;gt; e&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt; which writes �&lt;/p&gt;

&lt;p&gt;To choose the compose key, open&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;Preferences &amp;gt; Keyboard&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;,&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;Layouts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt; tab and click on&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;Options&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;. Open the&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;Compose key position&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&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;a href="http://cdn.jfoucher.com/uploads/2011/01/Screenshot-Keyboard-Layout-Options-1.png"&gt;&lt;img src="http://cdn.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;
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>2011-01-14T12:21:52+00:00</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://cdn.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://cdn.jfoucher.com/uploads/2011/01/skype-not-started.png"&gt;&lt;img src="http://cdn.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://cdn.jfoucher.com/uploads/2011/01/skype-indicator-menu.png"&gt;&lt;img src="http://cdn.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://cdn.jfoucher.com/uploads/2011/01/skype-indicator.png"&gt;&lt;img src="http://cdn.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>2011-01-12T14:06:02+00:00</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;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;~/Downloads
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&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;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/Downloads/linux-2.6.37
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt; and run&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;make gconfig
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt; if using Ubuntu or&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;make kconfig
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&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;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;/boot&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt; directory, with names like&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;config-2.6.35-24-generic&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt; Copy the latest one to your linux source directory. When the configuration editor is loaded, choose&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;File &amp;gt;&amp;gt; Load&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&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;p&gt;We'll try and better that a bit.&lt;/p&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;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;make localmodconfig
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&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;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;make all
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt; or&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;make -j4 all
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt; on multicore processors to run several processes in parallel, which will compile the kernel and the modules specified in the .config 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;blockquote&gt;
&lt;p class="line862"&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;p class="line874"&gt;Now you can compile the kernel and create the packages:&lt;/p&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;/blockquote&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>2010-05-19T14:45:10+00:00</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>2010-01-01T23:29:39+00:00</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>2009-12-14T16:59:32+00:00</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>2009-11-20T09:00:29+00:00</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://cdn.jfoucher.com/uploads/2009/11/Screenshot-1.png"&gt;&lt;img class="size-medium wp-image-172" title="Google Wave" src="http://cdn.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>
	
	<entry>
		<title>Cafepress SIGG bottles discount and coupon code !</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/LLLixi1NkqQ/cafepress-sigg-bottles-discount-coupon-code.html" />
		<updated>2009-07-27T19:13:36+00:00</updated>
		<id>http://jfoucher.com/2009/07/cafepress-sigg-bottles-discount-coupon-code</id>
		<content type="html">&lt;p&gt;You've probably seen that cafepress let's you&lt;a href="http://www.cafepress.com/designer/sigg/"&gt; customize your sigg bottle&lt;/a&gt;, and you also no doubt know that water bottles are bad for the &lt;a href="http://ecoquotidien.fr"&gt;environment&lt;/a&gt;, as only a small proportion are recycled, and many end up scattered around natural areas, not least of which, due to their rather &lt;em&gt;floating&lt;/em&gt; nature, our beaches. Sigg bottles are a durable, light and trendy alternative, and today we are going to &lt;em&gt;design our own&lt;/em&gt;, but not using &lt;a href="http://cafepress.com"&gt;cafepress'&lt;/a&gt; flash designer!&lt;/p&gt;

&lt;blockquote&gt;There is a better and cheaper way to get your custom sigg bottle.&lt;/blockquote&gt;


&lt;p&gt;No, because there is a &lt;em&gt;better and cheaper&lt;/em&gt; way to get your custom sigg bottle. Don't want to pay $28 for a bottle ? Don't worry, this solution will get you a three dollars discount per bottle, which added to our 5 dollars &lt;em&gt;cafepress coupon&lt;/em&gt; below, will get you a brand new, custom SIGG bottle for around 23 dollars! Of course, you'll have to buy three, because the coupon is only valid for purchases above $50, but these bottles are such great, eco-friendly gifts, that three of them is not nearly enough!&lt;/p&gt;

&lt;p&gt;Anyway, to get a cheaper custom sigg bottle, we need to &lt;em&gt;open a cafepress account&lt;/em&gt;, and set up a shop. Don't worry, it's completely free. First, click on "sign in" at the top of the home page in cafepress, then click continue once you reach the screen below.&lt;/p&gt;

&lt;div class="image-with-caption aligncenter" style="width:300px"&gt;&lt;div class="caption"&gt;Register at Cafepress&lt;/div&gt;&lt;a href="http://cdn.jfoucher.com/uploads/2009/07/cafepress1.jpg"&gt;&lt;img class="size-medium wp-image-151" title="Sign In" src="http://cdn.jfoucher.com/uploads/2009/07/cafepress1-300x159.jpg" alt="Register at Cafepress" width="300" height="159" /&gt;&lt;/a&gt;&lt;/div&gt;


&lt;p&gt;You arrive at the page shown below where you enter your registration information. Fill all the  fields in and then click on "Join now".&lt;/p&gt;

&lt;div class="image-with-caption aligncenter" style="width:300px"&gt;&lt;div class="caption"&gt;Enter your information&lt;/div&gt;&lt;a href="http://cdn.jfoucher.com/uploads/2009/07/cafepress2.jpg"&gt;&lt;img class="size-medium wp-image-152" title="Register" src="http://cdn.jfoucher.com/uploads/2009/07/cafepress2-300x168.jpg" alt="Enter your information" width="300" height="168" /&gt;&lt;/a&gt;&lt;/div&gt;


&lt;p&gt;Fill in more info and then click "Open your shop!"&lt;/p&gt;

&lt;div class="image-with-caption aligncenter" style="width:300px"&gt;&lt;div class="caption"&gt;Fill in More Info&lt;/div&gt;&lt;a href="http://cdn.jfoucher.com/uploads/2009/07/cafepress3.jpg"&gt;&lt;img class="size-medium wp-image-153" title="More Info" src="http://cdn.jfoucher.com/uploads/2009/07/cafepress3-300x124.jpg" alt="Fill in More Info" width="300" height="124" /&gt;&lt;/a&gt;&lt;/div&gt;


&lt;p&gt;You are now given a choice to open a basic or a premium shop.� For our purposes, a free basic shop is sufficient, so click on "Open a basic shop"&lt;/p&gt;

&lt;div class="image-with-caption aligncenter" style="width:300px"&gt;&lt;div class="caption"&gt;Choose shop type&lt;/div&gt;&lt;a href="http://cdn.jfoucher.com/uploads/2009/07/cafepress4.jpg"&gt;&lt;img class="size-medium wp-image-155" title="Shop type" src="http://cdn.jfoucher.com/uploads/2009/07/cafepress4-300x217.jpg" alt="Choose shop type" width="300" height="217" /&gt;&lt;/a&gt;&lt;/div&gt;


&lt;p&gt;Fill in some more details on the next page and click on "Submit", then click on "Build your shop once you reach the page below&lt;/p&gt;

&lt;div class="image-with-caption aligncenter" style="width:300px"&gt;&lt;div class="caption"&gt;Build your shop&lt;/div&gt;&lt;a href="http://cdn.jfoucher.com/uploads/2009/07/cafepress5.jpg"&gt;&lt;img class="size-medium wp-image-156" title="Build your shop" src="http://cdn.jfoucher.com/uploads/2009/07/cafepress5-300x179.jpg" alt="Build your shop" width="300" height="179" /&gt;&lt;/a&gt;&lt;/div&gt;


&lt;p&gt;I leave it as an exercise to the reader to insert a product, preferably a Sigg botlle into the shop. Once you reach the screen below, you can keep going.&lt;/p&gt;

&lt;div class="image-with-caption aligncenter" style="width:300px"&gt;&lt;div class="caption"&gt;Sigg bottle added to shop&lt;/div&gt;&lt;a href="http://cdn.jfoucher.com/uploads/2009/07/cafepress6.jpg"&gt;&lt;img class="size-medium wp-image-157" title="Sigg bottle added to shop" src="http://cdn.jfoucher.com/uploads/2009/07/cafepress6-300x211.jpg" alt="Sigg bottle added to shop" width="300" height="211" /&gt;&lt;/a&gt;&lt;/div&gt;


&lt;blockquote&gt;Draw your image using Gimp or Inkscape, or whatever software you are used to.&lt;/blockquote&gt;


&lt;p&gt;Great, you've added a Sigg bottle to your shop. The only slight problem is that it's completely white. We really need to do something about that! So, &lt;em&gt;is your image ready&lt;/em&gt;? No? Well let's go then. Cafepress provides a &lt;a href="http://www.cafepress.com/content/help/img/templates/280_H_F.jpg"&gt;template&lt;/a&gt; for the image on the Sigg bottles, and I suggest you follow it to get an image of the proper size. The only thing is that it's at 200 dpi, which seems a bit low for printing, so I suggest you scale it up to at least 300 DPI, or a pixel size of 975x1800. Here is &lt;a href="http://cdn.jfoucher.com/uploads/2009/07/280_H_R.png"&gt;my template at 600 DPI&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Draw your image using &lt;a href="http://gimp.org"&gt;Gimp&lt;/a&gt; or &lt;a href="http://inkscape.org"&gt;Inkscape&lt;/a&gt;, or whatever software you are used to, or just choose a photograph from your collection. The thing to keep in mind is that the shape of the template is the maximum size of your image, but it can be smaller...&lt;/p&gt;

&lt;p&gt;Ok, so now you have your image the way you like it, I suggest you &lt;em&gt;give it a try&lt;/em&gt; on the &lt;a href="http://www.cafepress.com/designer/sigg/"&gt;flash designer&lt;/a&gt;. When you are entirely satisfied, click on "edit" below the image of the bottle to get to the page shown on the screenshot below.&lt;/p&gt;

&lt;div class="image-with-caption aligncenter" style="width:300px"&gt;&lt;div class="caption"&gt;Add image&lt;/div&gt;&lt;a href="http://cdn.jfoucher.com/uploads/2009/07/cafepress7.jpg"&gt;&lt;img class="size-medium wp-image-161" title="Add image" src="http://cdn.jfoucher.com/uploads/2009/07/cafepress7-300x207.jpg" alt="Add image" width="300" height="207" /&gt;&lt;/a&gt;&lt;/div&gt;


&lt;p&gt;On the right hand side, click on the "select image" button, then on "Upload image", which brings you to a page where you can upload a number of images, choose and &lt;em&gt;upload your image&lt;/em&gt;. It takes a few steps, which I'm not going to detail here.&lt;/p&gt;

&lt;div class="image-with-caption aligncenter" style="width:300px"&gt;&lt;div class="caption"&gt;Image applied to bottle&lt;/div&gt;&lt;a href="http://cdn.jfoucher.com/uploads/2009/07/cafepress8.jpg"&gt;&lt;img class="size-medium wp-image-165" title="Image applied to bottle" src="http://cdn.jfoucher.com/uploads/2009/07/cafepress8-300x205.jpg" alt="Image applied to bottle" width="300" height="205" /&gt;&lt;/a&gt;&lt;/div&gt;


&lt;p&gt;Once you selected the image to apply to your bottle, you can tweak it's size, but if you used the template, it should fill all the space available, see screenshot above.&lt;/p&gt;

&lt;p&gt;Click next, and you can write a title, a description and choose a price for your item. Don't worry, you'll be able to buy it at the base price later, so &lt;em&gt;set any markup you like&lt;/em&gt;. I didn't touch anything, as it doesn't matter for our purposes. But feel free to change things if you want to sell your custom bottle later.&lt;/p&gt;

&lt;div class="image-with-caption aligncenter" style="width:300px"&gt;&lt;div class="caption"&gt;Change item details&lt;/div&gt;&lt;a href="http://cdn.jfoucher.com/uploads/2009/07/cafepress9.jpg"&gt;&lt;img class="size-medium wp-image-166" title="Change item details" src="http://cdn.jfoucher.com/uploads/2009/07/cafepress9-300x195.jpg" alt="Change item details" width="300" height="195" /&gt;&lt;/a&gt;&lt;/div&gt;


&lt;p&gt;Once you click "save and finish", &lt;em&gt;your custom Sigg bottle is created!&lt;/em&gt; You can now buy it at the base price by following these instructions : first, click on the "your shops" link at the top left of the page shown above, then on "buy" on the same line as your shop's name, and then "Click to buy from your own shop", after which you get to the product page for your custom bottle, which you can then buy following normal procedures.&lt;/p&gt;

&lt;div class="image-with-caption aligncenter" style="width:300px"&gt;&lt;div class="caption"&gt;Buy your custom Sigg bottle&lt;/div&gt;&lt;a href="http://cdn.jfoucher.com/uploads/2009/07/cafepress11.jpg"&gt;&lt;img class="size-medium wp-image-167" title="Buy your custom Sigg bottle" src="http://cdn.jfoucher.com/uploads/2009/07/cafepress11-300x129.jpg" alt="Buy your custom Sigg bottle" width="300" height="129" /&gt;&lt;/a&gt;&lt;/div&gt;


&lt;p&gt;When you get to the checkout form, fill in the following Cafepress coupon code: POPPYSNEEZE to get a further $5 discount, on purchases over $50.&lt;/p&gt;

&lt;blockquote&gt;
Cafepress coupon code: a further $5 discount&lt;/blockquote&gt;


&lt;p&gt;And that's it, your three brand new, custom, home made sigg bottles for &lt;strong&gt;$76.22&lt;/strong&gt; including shipping.&lt;/p&gt;

&lt;p&gt;A further tip if you want a different design on each bottle : as the free version of cafepress doesn't allow you to sell more than one product of each type in each shop, open several free shops with a different Sigg bottle in each!&lt;/p&gt;

&lt;p&gt;I hope you enjoy this post. If you decide to follow this tutorial, send a pic of your bottle in the comments.&lt;/p&gt;
&lt;a href="http://jfoucher.com/2009/07/cafepress-sigg-bottles-discount-coupon-code.html"&gt;Cafepress SIGG bottles discount and coupon code !&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=LLLixi1NkqQ:pyszeqMvvCk: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=LLLixi1NkqQ:pyszeqMvvCk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=LLLixi1NkqQ:pyszeqMvvCk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/LLLixi1NkqQ" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2009/07/cafepress-sigg-bottles-discount-coupon-code.html</feedburner:origLink></entry>
	
	<entry>
		<title>Access to MySQL import class</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/rl8EJYLXON0/access-to-mysql-import-class.html" />
		<updated>2009-07-18T07:57:25+00:00</updated>
		<id>http://jfoucher.com/2009/07/access-to-mysql-import-class</id>
		<content type="html">&lt;p&gt;In my latest project &lt;a href="http://tecknosfera.com"&gt;at work&lt;/a&gt; I need to import data from an acess database into mySQL to be able to create an online shop from that data. Instead of importing just the database of that particular client, I created a generic PHP class that can import any Access database to MySQL.&lt;/p&gt;

&lt;blockquote&gt;
Big databases must be imported by chunks.&lt;/blockquote&gt;


&lt;p&gt;Since Access databases can get so big, the import class has to do its job by chunks, to avoid memory limits. It also needs to reload itself when it detects it is close to the time limit, all of which it now does without any problems.
We can now import (hopefully) any Access database.&lt;/p&gt;
&lt;a href="http://jfoucher.com/2009/07/access-to-mysql-import-class.html"&gt;Access to MySQL import class&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=rl8EJYLXON0:PFY3LIn7k60: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=rl8EJYLXON0:PFY3LIn7k60:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=rl8EJYLXON0:PFY3LIn7k60:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/rl8EJYLXON0" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2009/07/access-to-mysql-import-class.html</feedburner:origLink></entry>
	
	<entry>
		<title>Ecoquotidien.fr</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/T083Yojq6Ts/ecoquotidien.html" />
		<updated>2009-07-10T08:18:11+00:00</updated>
		<id>http://jfoucher.com/2009/07/ecoquotidien</id>
		<content type="html">&lt;div class="image-with-caption alignleft" style="width:370px"&gt;&lt;div class="caption"&gt;Ecoquotidien&lt;/div&gt;&lt;a href="http://ecoquotidien.fr"&gt;&lt;img src="http://jfoucher.fr/wp-content/uploads/2009/07/ecoquotidien-370x231.jpg" alt="Ecoquotidien" title="Ecoquotidien" width="370" height="231" class="size-medium wp-image-157" /&gt;&lt;/a&gt;&lt;/div&gt;


&lt;p&gt;[lang_es]La ecologia al cotidiano. Que hacer para cuidar de nuestro planeta en nuestros hogares y jardines.&lt;/p&gt;

&lt;p&gt;Basado en &lt;a href="http://wordpress.org"&gt;Wordpress&lt;/a&gt;, este blog hace uso extensivo de &lt;a href="http://jquery.com"&gt;jQuery&lt;/a&gt; para dar vida a la p&amp;aacute;gina, con animaciones, contenido dyn&amp;aacute;mico, etc... Las nubes, por ejemplo, se mueven de manera aleatoria sobre la pantalla.
[/lang_es][lang_en]Daily ecology. What we can do to take care of our planet from our homes and gardens.&lt;/p&gt;

&lt;p&gt;Based in &lt;a href="http://wordpress.org"&gt;Wordpress&lt;/a&gt;, this blog makes extensive use of &lt;a href="http://jquery.com"&gt;jQuery&lt;/a&gt; to give life to the page, with animations, dynamic content, etc... The clouds, for example move around on the screen as if an imaginary electronic wind was blowing!
[/lang_en]&lt;/p&gt;
&lt;a href="http://jfoucher.com/2009/07/ecoquotidien.html"&gt;Ecoquotidien.fr&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=T083Yojq6Ts:99oqN8rkPxw: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=T083Yojq6Ts:99oqN8rkPxw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=T083Yojq6Ts:99oqN8rkPxw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/T083Yojq6Ts" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2009/07/ecoquotidien.html</feedburner:origLink></entry>
	
	<entry>
		<title>WP-Feedly theme available for download</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/9U2tYYOxdWM/wpfeedly-theme-download.html" />
		<updated>2009-06-27T09:19:32+00:00</updated>
		<id>http://jfoucher.com/2009/06/wpfeedly-theme-download</id>
		<content type="html">&lt;div class="image-with-caption aligncenter" style="width:300px"&gt;&lt;div class="caption"&gt;WP-Feedly Screenshot&lt;/div&gt;&lt;a href="http://cdn.jfoucher.com/uploads/2009/06/screenshot1.png"&gt;&lt;img class="size-full wp-image-138" title="WP-Feedly Screenshot" src="http://cdn.jfoucher.com/uploads/2009/06/screenshot1.png" alt="WP-Feedly Screenshot" width="300" height="255" /&gt;&lt;/a&gt;&lt;/div&gt;


&lt;p&gt;After some beta testing and subsequent bug squashing, WP-Feedly is ready for prime-time, and &lt;a href="/wp-feedly.zip"&gt;available for download&lt;/a&gt;.&lt;/p&gt;
&lt;a href="http://jfoucher.com/2009/06/wpfeedly-theme-download.html"&gt;WP-Feedly theme available for download&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=9U2tYYOxdWM:Jw4IfvYq5kY: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=9U2tYYOxdWM:Jw4IfvYq5kY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=9U2tYYOxdWM:Jw4IfvYq5kY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/9U2tYYOxdWM" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2009/06/wpfeedly-theme-download.html</feedburner:origLink></entry>
	
	<entry>
		<title>New portfolio theme: CleanFolio</title>
		<link href="http://feedproxy.google.com/~r/GeekyNuggets/~3/qPntYKy3rqA/portfolio-theme.html" />
		<updated>2009-06-26T22:17:07+00:00</updated>
		<id>http://jfoucher.com/2009/06/portfolio-theme</id>
		<content type="html">&lt;div class="image-with-caption aligncenter" style="width:300px"&gt;&lt;div class="caption"&gt;CleanFolio&lt;/div&gt;&lt;a href="http://cdn.jfoucher.com/uploads/2009/06/screenshot.png"&gt;&lt;img class="size-medium wp-image-130" title="CleanFolio" src="http://cdn.jfoucher.com/uploads/2009/06/screenshot-300x187.png" alt="CleanFolio" width="300" height="187" /&gt;&lt;/a&gt;&lt;/div&gt;


&lt;p&gt;I've been working on my profesionnal portfolio these days, and I'm thinking about releasing the theme. It's a very clean and white design, with a jQuery carousel to present my past work. You can see a demo on &lt;a href="http://jfoucher.fr"&gt;Jonathan Foucher's portfolio&lt;/a&gt;. So, should I release it? Do you like it?&lt;/p&gt;
&lt;a href="http://jfoucher.com/2009/06/portfolio-theme.html"&gt;New portfolio theme: CleanFolio&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=qPntYKy3rqA:WshscPIWksk: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=qPntYKy3rqA:WshscPIWksk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/GeekyNuggets?i=qPntYKy3rqA:WshscPIWksk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/GeekyNuggets/~4/qPntYKy3rqA" height="1" width="1"/&gt;</content>
	<feedburner:origLink>http://jfoucher.com/2009/06/portfolio-theme.html</feedburner:origLink></entry>
	
</feed>

