<?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:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en" xml:base="http://nilvec.com/wp-atom.php">
	<title type="text">Nilvec</title>
	<subtitle type="text" />

	<updated>2012-01-15T10:41:35Z</updated>

	<link rel="alternate" type="text/html" href="http://nilvec.com" />
	<id>http://nilvec.com/feed/atom/</id>
	

	<generator uri="http://wordpress.org/" version="3.3.1">WordPress</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/nilvec" /><feedburner:info uri="nilvec" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
		<author>
			<name>ldx</name>
						<uri>http://nilvec.com</uri>
					</author>
		<title type="html"><![CDATA[Nginx and git via HTTP]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/nilvec/~3/wefK0ys-8qw/" />
		<id>http://nilvec.com/?p=555</id>
		<updated>2012-01-15T10:41:35Z</updated>
		<published>2012-01-15T10:13:44Z</published>
		<category scheme="http://nilvec.com" term="development" /><category scheme="http://nilvec.com" term="git" /><category scheme="http://nilvec.com" term="linux" /><category scheme="http://nilvec.com" term="nginx" />		<summary type="html"><![CDATA[Nginx is a high-performance HTTP server and proxy that has been gaining a lot of traction recently. It&#8217;s easy to set up, can handle a large number of clients with minimal resources, modular and supports SSL/TLS. Dynamic web content can &#8230; <a href="http://nilvec.com/nginx-and-git-via-http/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></summary>
		<content type="html" xml:base="http://nilvec.com/nginx-and-git-via-http/">&lt;!-- Start Shareaholic LikeButtonSetTop Automatic --&gt;&lt;!-- End Shareaholic LikeButtonSetTop Automatic --&gt;&lt;div class="shr-publisher-555"&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="http://nginx.org/"&gt;Nginx&lt;/a&gt;&lt;/strong&gt; is a high-performance HTTP server and proxy that has been gaining a lot of traction recently. It&amp;#8217;s easy to set up, can handle a large number of clients with minimal resources, modular and supports SSL/TLS. Dynamic web content can be served via FastCGI to Nginx.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Git&lt;/strong&gt; uses WebDAV for pushing via HTTP(S). Even though Nginx handles WebDAV requests, not all DAV commands are implemented in its &lt;a href="http://wiki.nginx.org/HttpDavModule"&gt;DAV module&lt;/a&gt;. Locking and PROPFIND are missing in particular, and since these commands are used by Git when pushing via HTTP, pushing to a plain Nginx server is not possible at the moment.&lt;/p&gt;
&lt;p&gt;One solution is to run Apache on a different port and proxy Git requests to it. However, Apache is such a resource hog that if a lightweight solution is desired it&amp;#8217;s out of question. Here comes &lt;strong&gt;&lt;a href="http://code.google.com/p/pywebdav/"&gt;PyWebDAV&lt;/a&gt;&lt;/strong&gt;, a standalone WebDAV server written in Python, into the picture.&lt;/p&gt;
&lt;p&gt;&lt;span id="more-555"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;PyWedDAV is available in both Ubuntu and Debian, so just install it via apt-get:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
$ sudo apt-get install python-webdav&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The actual binary for running the server will be at &lt;code&gt;/usr/bin/davserver&lt;/code&gt;. The packages have no init script, but it&amp;#8217;s easy to create one, or you can just shove it at the end of &lt;code&gt;/etc/rc.local&lt;/code&gt;:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
/usr/bin/sudo -u www-data /usr/bin/davserver -D /var/www/git -n -P 8008 -i 0 -J -d start&lt;br /&gt;
exit 0&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This will start &lt;code&gt;davserver&lt;/code&gt; on port 8008 running as user &lt;code&gt;www-data&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s now only a matter of making Nginx proxy git requests to PyWebDAV:&lt;/p&gt;
&lt;pre&gt;
server {

...

    location /git {
        proxy_pass       http://localhost:8008/;
        proxy_redirect   http://localhost:8008 http://git.mysite.com;
    }

}
&lt;/pre&gt;
&lt;p&gt;This assumes you store your git repositories under &lt;code&gt;/var/www/git&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However, trying to git push to this server reveals something is still not working as expected:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
$ git push&lt;br /&gt;
error: cannot lock existing info/refs&lt;br /&gt;
error: failed to push to 'http://git.mysite.com/git/foobar.git'&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Even though davserver returns 200 for a LOCK operation, Git checks that the lock timeout is indeed correct in the reply. PyWebDAV by default uses &amp;#8216;Seconds-Infinite&amp;#8217; for timeouts, but Git expects a numerical timeout value. This can be fixed in /usr/share/pyshared/DAV/locks.py, just change &amp;#8216;Infinite&amp;#8217; at its two occurences to some sane default value. Here&amp;#8217;s a diff to make it easier for the lazy:&lt;/p&gt;
&lt;pre&gt;
--- /usr/lib/python2.6/dist-packages/DAV/locks.py       2010-04-15 11:25:35.000000000 +0200
+++ locks.py    2012-01-15 11:05:18.406041553 +0100
@@ -169,7 +169,7 @@
                     token = tokenFinder(listitem)
                     if token and self._l_hasLock(token):
                         lock = self._l_getLock(token)
-                        timeout = self.headers.get('Timeout', 'Infinite')
+                        timeout = self.headers.get('Timeout', '3600')
                         lock.setTimeout(timeout) # automatically refreshes
                         found = 1

@@ -188,7 +188,7 @@
     """ Lock with support for exclusive write locks. Some code taken from
     webdav.LockItem from the Zope project. """

-    def __init__(self, uri, creator, lockowner, depth=0, timeout='Infinite',
+    def __init__(self, uri, creator, lockowner, depth=0, timeout='3600',
                     locktype='write', lockscope='exclusive', token=None, **kw):

         self.uri = uri
&lt;/pre&gt;
&lt;p&gt;Just save it as &lt;code&gt;locks.diff&lt;/code&gt;, apply the patch with &lt;code&gt;patch -p0 &lt; locks.diff&lt;/code&gt;, restart &lt;code&gt;davserver&lt;/code&gt; and now &lt;code&gt;git push&lt;/code&gt; should be working fine.&lt;/p&gt;
&lt;div class="shr-publisher-555"&gt;&lt;/div&gt;&lt;!-- Start Shareaholic LikeButtonSetBottom Automatic --&gt;&lt;!-- End Shareaholic LikeButtonSetBottom Automatic --&gt;&lt;img src="http://feeds.feedburner.com/~r/nilvec/~4/wefK0ys-8qw" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://nilvec.com/nginx-and-git-via-http/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://nilvec.com/nginx-and-git-via-http/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://nilvec.com/nginx-and-git-via-http/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>ldx</name>
						<uri>http://nilvec.com</uri>
					</author>
		<title type="html"><![CDATA[Python-iptables]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/nilvec/~3/LCwh4OIh6VQ/" />
		<id>http://nilvec.com/?p=519</id>
		<updated>2011-11-02T23:34:21Z</updated>
		<published>2011-11-02T23:20:49Z</published>
		<category scheme="http://nilvec.com" term="development" /><category scheme="http://nilvec.com" term="iptables" /><category scheme="http://nilvec.com" term="linux" /><category scheme="http://nilvec.com" term="python" />		<summary type="html"><![CDATA[Python-iptables is a Python project that provides bindings to the iptables C libraries in Linux. Interoperability with iptables is achieved using the iptables C libraries (libiptc, libxtables, and iptables extensions), not calling the iptables executable and parsing its output as &#8230; <a href="http://nilvec.com/python-iptables/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></summary>
		<content type="html" xml:base="http://nilvec.com/python-iptables/">&lt;!-- Start Shareaholic LikeButtonSetTop Automatic --&gt;&lt;!-- End Shareaholic LikeButtonSetTop Automatic --&gt;&lt;div class="shr-publisher-519"&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Python-iptables&lt;/strong&gt; is a Python project that provides bindings to the iptables C libraries in Linux. Interoperability with iptables is achieved using the iptables C libraries (libiptc, libxtables, and iptables extensions), not calling the iptables executable and parsing its output as most other iptables wrapper libraries do; this makes python-iptables faster and not prone to parsing errors, at the same time leveraging all available iptables match and target extensions without further work.  If you need further information on how iptables and netfilter work, &lt;a href="http://www.thegeekstuff.com/2011/01/iptables-fundamentals/" target="_blank"&gt;this&lt;/a&gt; is a great summary.&lt;/p&gt;
&lt;p&gt;&lt;span id="more-519"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Iptables is organized into a hierarchy: the basic building blocks are tables which contain chains, and chains consist of the actual rules that tell netfilter what to do with network packets. A rule contains at least one (possibly more) match(es) and a target. There are a few default tables and chains, but users can create further chains to organize their rules into blocks.  A rule can also jump into another chain (kind of like calling a subroutine).&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style="width: 540px; font-size: 100%; text-align: center;"&gt;&lt;img style="padding-bottom: 0.5em;" src="http://www.thegeekstuff.com/wp-content/uploads/2011/01/iptables-table-chain-rule-structure.png" alt="Tables, chains and rules (image from thegeekstuff.com)" width="width" height="height" /&gt;Tables, chains and rules (image from thegeekstuff.com)&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Python-iptables makes it very easy to programatically manipulate or alter chains and rules. E.g. to traverse all rules in the &lt;em&gt;INPUT&lt;/em&gt; chain in the &lt;em&gt;FILTER&lt;/em&gt; table:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; import iptc&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; table = iptc.TABLE_FILTER&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; inp = iptc.Chain(table, "INPUT")&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; for r in inp.rules:&lt;br /&gt;
... print r.src, "-&amp;gt;", r.dst, "L4:", r.protocol,&lt;br /&gt;
... for m in r.matches:&lt;br /&gt;
... print "match:", m.name,&lt;br /&gt;
... print "target:", r.target.name&lt;br /&gt;
...&lt;br /&gt;
192.168.1.0/255.255.255.0 -&amp;gt; 192.168.2.0/255.255.255.0 L4: udp match: udp target: ACCEPT&lt;br /&gt;
192.168.1.0/255.255.255.0 -&amp;gt; 192.168.2.0/255.255.255.0 L4: tcp match: tcp target: ACCEPT&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You are of course free to create new rules:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; import iptc&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; rule = iptc.Rule()&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; rule.dst = "192.168.100.1"&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; rule.protocol = "tcp"&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; rule.in_interface = "eth0"&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; match = iptc.Match(rule, "tcp")&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; match.dport = "8000"&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; rule.add_match(match)&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; target = iptc.Target(rule, "REDIRECT")&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; rule.target = target&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; chain = iptc.Chain(iptc.TABLE_NAT, "iptc_test_redirect")&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; iptc.TABLE_NAT.create_chain(chain)&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; target.reset()&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; target.to_ports = "1234-1235"&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; rule.target = target&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; chain.insert_rule(rule)&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; for r in chain.rules:&lt;br /&gt;
... print r.src, "-&amp;gt;", r.dst, "L4:", r.protocol,&lt;br /&gt;
... for m in r.matches:&lt;br /&gt;
... print "match:", m.name,&lt;br /&gt;
... print "target:", r.target.name&lt;br /&gt;
...&lt;br /&gt;
0.0.0.0/0.0.0.0 -&amp;gt; 192.168.100.1/255.255.255.255 L4: tcp match: tcp target: REDIRECT&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; chain.delete_rule(rule)&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; chain.flush()&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; chain.delete()&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This is equivalent to the following command line sequence:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;# iptables -t nat -N iptc_test_redirect&lt;br /&gt;
# iptables -t nat -A iptc_test_redirect -d 192.168.100.1 -i eth0 -p tcp --dport 8000 -j REDIRECT --to-ports 1234-1235&lt;br /&gt;
# iptables -t nat -F iptc_test_redirect&lt;br /&gt;
# iptables -t nat -X iptc_test_redirect&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You can find detailed API documentation and further examples &lt;a href="/stuff/python-iptables/docs/html/index.html" target="_blank"&gt;here&lt;/a&gt;.  The source code is available on &lt;a href="https://github.com/ldx/python-iptables" target="_blank"&gt;Github&lt;/a&gt;.&lt;/p&gt;
&lt;div class="shr-publisher-519"&gt;&lt;/div&gt;&lt;!-- Start Shareaholic LikeButtonSetBottom Automatic --&gt;&lt;!-- End Shareaholic LikeButtonSetBottom Automatic --&gt;&lt;img src="http://feeds.feedburner.com/~r/nilvec/~4/LCwh4OIh6VQ" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://nilvec.com/python-iptables/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://nilvec.com/python-iptables/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://nilvec.com/python-iptables/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>NexusGuy</name>
					</author>
		<title type="html"><![CDATA[New Android Market countries]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/nilvec/~3/IA1eI89wON4/" />
		<id>http://nilvec.com/?p=513</id>
		<updated>2011-11-02T23:37:03Z</updated>
		<published>2011-05-12T19:06:20Z</published>
		<category scheme="http://nilvec.com" term="android" />		<summary type="html"><![CDATA[On 11th May 2011 Google announced the availability of paid apps in 99 new countries. The list of countries where now you can purchase Android applications from the Market: Albania Algeria Angola Antigua and Barbuda Armenia Aruba Azerbaijan Bahamas Bahrain &#8230; <a href="http://nilvec.com/new-android-market-countries/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></summary>
		<content type="html" xml:base="http://nilvec.com/new-android-market-countries/">&lt;!-- Start Shareaholic LikeButtonSetTop Automatic --&gt;&lt;!-- End Shareaholic LikeButtonSetTop Automatic --&gt;&lt;div class="shr-publisher-513"&gt;&lt;/div&gt;&lt;p&gt;On 11th May 2011 Google announced the availability of paid apps in 99 new countries.&lt;/p&gt;
&lt;p&gt;&lt;span id="more-513"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The list of countries where now you can purchase Android applications from the Market:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Albania&lt;/li&gt;
&lt;li&gt;Algeria&lt;/li&gt;
&lt;li&gt;Angola&lt;/li&gt;
&lt;li&gt;Antigua and Barbuda&lt;/li&gt;
&lt;li&gt;Armenia&lt;/li&gt;
&lt;li&gt;Aruba&lt;/li&gt;
&lt;li&gt;Azerbaijan&lt;/li&gt;
&lt;li&gt;Bahamas&lt;/li&gt;
&lt;li&gt;Bahrain&lt;/li&gt;
&lt;li&gt;Bangladesh&lt;/li&gt;
&lt;li&gt;Belarus&lt;/li&gt;
&lt;li&gt;Belize&lt;/li&gt;
&lt;li&gt;Benin&lt;/li&gt;
&lt;li&gt;Bolivia&lt;/li&gt;
&lt;li&gt;Bosnia and Herzegovina&lt;/li&gt;
&lt;li&gt;Botswana&lt;/li&gt;
&lt;li&gt;Bulgaria&lt;/li&gt;
&lt;li&gt;Burkina Faso&lt;/li&gt;
&lt;li&gt;Cambodia&lt;/li&gt;
&lt;li&gt;Cameroon&lt;/li&gt;
&lt;li&gt;Cape Verde&lt;/li&gt;
&lt;li&gt;Chile&lt;/li&gt;
&lt;li&gt;Colombia&lt;/li&gt;
&lt;li&gt;Costa Rica&lt;/li&gt;
&lt;li&gt;Cote d&amp;#8217; Ivore&lt;/li&gt;
&lt;li&gt;Croatia&lt;/li&gt;
&lt;li&gt;Cyprus&lt;/li&gt;
&lt;li&gt;Dominican Republic&lt;/li&gt;
&lt;li&gt;Ecuador&lt;/li&gt;
&lt;li&gt;El Salvador&lt;/li&gt;
&lt;li&gt;Estonia&lt;/li&gt;
&lt;li&gt;Fiji&lt;/li&gt;
&lt;li&gt;Gabon&lt;/li&gt;
&lt;li&gt;Ghana&lt;/li&gt;
&lt;li&gt;Greece&lt;/li&gt;
&lt;li&gt;Guatemala&lt;/li&gt;
&lt;li&gt;Guinea-Bissau&lt;/li&gt;
&lt;li&gt;Haiti&lt;/li&gt;
&lt;li&gt;Honduras&lt;/li&gt;
&lt;li&gt;Hungary&lt;/li&gt;
&lt;li&gt;Iceland&lt;/li&gt;
&lt;li&gt;Indonesia&lt;/li&gt;
&lt;li&gt;Jamaica&lt;/li&gt;
&lt;li&gt;Jordan&lt;/li&gt;
&lt;li&gt;Kazakhstan&lt;/li&gt;
&lt;li&gt;Kenya&lt;/li&gt;
&lt;li&gt;Kuwait&lt;/li&gt;
&lt;li&gt;Kyrgyzstan&lt;/li&gt;
&lt;li&gt;Laos&lt;/li&gt;
&lt;li&gt;Latvia&lt;/li&gt;
&lt;li&gt;Lebanon&lt;/li&gt;
&lt;li&gt;Lithuania&lt;/li&gt;
&lt;li&gt;Luxembourg&lt;/li&gt;
&lt;li&gt;Macedonia&lt;/li&gt;
&lt;li&gt;Malaysia&lt;/li&gt;
&lt;li&gt;Mali&lt;/li&gt;
&lt;li&gt;Malta&lt;/li&gt;
&lt;li&gt;Mauritius&lt;/li&gt;
&lt;li&gt;Moldova&lt;/li&gt;
&lt;li&gt;Morocco&lt;/li&gt;
&lt;li&gt;Mozambique&lt;/li&gt;
&lt;li&gt;Namibia&lt;/li&gt;
&lt;li&gt;Nepal&lt;/li&gt;
&lt;li&gt;Netherlands Antilles&lt;/li&gt;
&lt;li&gt;Nicaragua&lt;/li&gt;
&lt;li&gt;Niger&lt;/li&gt;
&lt;li&gt;Nigeria&lt;/li&gt;
&lt;li&gt;Oman&lt;/li&gt;
&lt;li&gt;Pakistan&lt;/li&gt;
&lt;li&gt;Panama&lt;/li&gt;
&lt;li&gt;Papua New Guinea&lt;/li&gt;
&lt;li&gt;Paraguay&lt;/li&gt;
&lt;li&gt;Peru&lt;/li&gt;
&lt;li&gt;Philippines&lt;/li&gt;
&lt;li&gt;Qatar&lt;/li&gt;
&lt;li&gt;Romania&lt;/li&gt;
&lt;li&gt;Rwanda&lt;/li&gt;
&lt;li&gt;Senegal&lt;/li&gt;
&lt;li&gt;Serbia&lt;/li&gt;
&lt;li&gt;Slovakia&lt;/li&gt;
&lt;li&gt;Slovenia&lt;/li&gt;
&lt;li&gt;South Africa&lt;/li&gt;
&lt;li&gt;Sri Lanka&lt;/li&gt;
&lt;li&gt;Tajikistan&lt;/li&gt;
&lt;li&gt;Tanzania&lt;/li&gt;
&lt;li&gt;Thailand&lt;/li&gt;
&lt;li&gt;Togo&lt;/li&gt;
&lt;li&gt;Trinidad and Tobago&lt;/li&gt;
&lt;li&gt;Tunisia&lt;/li&gt;
&lt;li&gt;Turkmenistan&lt;/li&gt;
&lt;li&gt;Uganda&lt;/li&gt;
&lt;li&gt;Ukraine&lt;/li&gt;
&lt;li&gt;Uruguay&lt;/li&gt;
&lt;li&gt;Uzbekistan&lt;/li&gt;
&lt;li&gt;Venezuela&lt;/li&gt;
&lt;li&gt;Vietnam&lt;/li&gt;
&lt;li&gt;Yemen&lt;/li&gt;
&lt;li&gt;Zambia&lt;/li&gt;
&lt;li&gt;Zimbabwe&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="shr-publisher-513"&gt;&lt;/div&gt;&lt;!-- Start Shareaholic LikeButtonSetBottom Automatic --&gt;&lt;!-- End Shareaholic LikeButtonSetBottom Automatic --&gt;&lt;img src="http://feeds.feedburner.com/~r/nilvec/~4/IA1eI89wON4" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://nilvec.com/new-android-market-countries/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://nilvec.com/new-android-market-countries/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://nilvec.com/new-android-market-countries/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>NexusGuy</name>
					</author>
		<title type="html"><![CDATA[Android emoticons on Ubuntu with Empathy]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/nilvec/~3/JhpVaNpl0OM/" />
		<id>http://nilvec.com/?p=486</id>
		<updated>2011-02-17T11:45:52Z</updated>
		<published>2011-02-13T22:24:35Z</published>
		<category scheme="http://nilvec.com" term="android" />		<summary type="html"><![CDATA[The default Ubuntu IM client has now been Empathy for a while. Though it supports themes, replacing the stock emoticons (which come from Gnome), unlike in Pidgin, is not a straightforward process. Which is kind of embarrassing, since the default &#8230; <a href="http://nilvec.com/android-emoticons-on-ubuntu-with-empathy/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></summary>
		<content type="html" xml:base="http://nilvec.com/android-emoticons-on-ubuntu-with-empathy/">&lt;!-- Start Shareaholic LikeButtonSetTop Automatic --&gt;&lt;!-- End Shareaholic LikeButtonSetTop Automatic --&gt;&lt;div class="shr-publisher-486"&gt;&lt;/div&gt;&lt;p&gt;The default Ubuntu IM client has now been &lt;a href="http://live.gnome.org/Empathy"&gt;Empathy&lt;/a&gt; for a while.  Though it supports themes, replacing the stock emoticons (which come from Gnome), unlike in Pidgin, is not a straightforward process.  Which is kind of embarrassing, since the default smileys in Gnome are far from being pretty and eye-candy.&lt;/p&gt;
&lt;p&gt;Fortunately, you can override the system emoticons for your user: just create the proper directory structure under &lt;strong&gt;~/.local&lt;/strong&gt;, and applications will use the emoticons found under &lt;strong&gt;~/.local/share/icons/gnome/16&amp;#215;16/emotes&lt;/strong&gt;, where &lt;em&gt;16&amp;#215;16&lt;/em&gt; is the resolution they need.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://nilvec.com/wordpress/wp-content/uploads/2011/02/empathy.png"&gt;&lt;img src="http://nilvec.com/wordpress/wp-content/uploads/2011/02/empathy.png" alt="" title="empathy" width="474" height="358" class="aligncenter size-full wp-image-491" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To make it easy for Ubuntu users, we just packed the &lt;a href="http://nilvec.com/the-ultimate-android-smiley-list/"&gt;Android emoticons&lt;/a&gt; into a &lt;a href="http://nilvec.com/downloads/android-emoticons.tar.gz"&gt;ready to use package&lt;/a&gt;.  Once you downloaded it, untar the package into your home folder:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
$ cd ~&lt;br /&gt;
$ tar xvzf ~/Downloads/android-emoticons.tar.gz&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;It will create all the necessary folders under &lt;strong&gt;.local&lt;/strong&gt;, and place the smileys in different resolutions there.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://nilvec.com/wordpress/wp-content/uploads/2011/02/empathy_smileys.png"&gt;&lt;img src="http://nilvec.com/wordpress/wp-content/uploads/2011/02/empathy_smileys.png" alt="" title="empathy_smileys" width="474" height="358" class="aligncenter size-full wp-image-492" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="shr-publisher-486"&gt;&lt;/div&gt;&lt;!-- Start Shareaholic LikeButtonSetBottom Automatic --&gt;&lt;!-- End Shareaholic LikeButtonSetBottom Automatic --&gt;&lt;img src="http://feeds.feedburner.com/~r/nilvec/~4/JhpVaNpl0OM" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://nilvec.com/android-emoticons-on-ubuntu-with-empathy/#comments" thr:count="1" />
		<link rel="replies" type="application/atom+xml" href="http://nilvec.com/android-emoticons-on-ubuntu-with-empathy/feed/atom/" thr:count="1" />
		<thr:total>1</thr:total>
	<feedburner:origLink>http://nilvec.com/android-emoticons-on-ubuntu-with-empathy/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>ldx</name>
						<uri>http://nilvec.com</uri>
					</author>
		<title type="html"><![CDATA[Implementing SMTP or IMAP XOAUTH authentication in Java]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/nilvec/~3/9W_OS6CyPQ8/" />
		<id>http://nilvec.com/?p=466</id>
		<updated>2011-02-10T12:00:06Z</updated>
		<published>2011-02-09T21:54:38Z</published>
		<category scheme="http://nilvec.com" term="android" /><category scheme="http://nilvec.com" term="development" /><category scheme="http://nilvec.com" term="java" /><category scheme="http://nilvec.com" term="oauth" />		<summary type="html"><![CDATA[XOAUTH is a SASL authentication mechanism that can be used with the IMAP AUTHENTICATE and SMTP AUTH commands. It is based on OAuth, and uses the same OAuth parameters to authenticate against an SMTP or IMAP server. It is backed &#8230; <a href="http://nilvec.com/implementing-smtp-or-imap-xoauth-authentication-in-java/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></summary>
		<content type="html" xml:base="http://nilvec.com/implementing-smtp-or-imap-xoauth-authentication-in-java/">&lt;!-- Start Shareaholic LikeButtonSetTop Automatic --&gt;&lt;!-- End Shareaholic LikeButtonSetTop Automatic --&gt;&lt;div class="shr-publisher-466"&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;XOAUTH&lt;/strong&gt; is a SASL authentication mechanism that can be used with the IMAP AUTHENTICATE and SMTP AUTH commands.  It is based on &lt;a href="http://nilvec.com/implementing-client-side-oauth-on-android/"&gt;OAuth&lt;/a&gt;, and uses the same OAuth parameters to authenticate against an SMTP or IMAP server.  It is backed by Google, and you can use XOAUTH with Gmail SMTP or IMAP to authenticate without an username and its corresponding password.&lt;/p&gt;
&lt;p&gt;You need to go through the usual &lt;a href="http://nilvec.com/implementing-client-side-oauth-on-android/"&gt;&amp;#8220;OAuth dance&amp;#8221;&lt;/a&gt; to acquire an access token and its corresponding secret.  Once you have that, you can generate the OAuth signature the usual OAuth way, with the following parameters:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The HTTP method is &lt;strong&gt;GET&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;The URL has the following form: &lt;strong&gt;https://mail.google.com/mail/b/[user email address]/[protocol]/&lt;/strong&gt;, where protocol is either &lt;strong&gt;&amp;#8220;smtp&amp;#8221;&lt;/strong&gt; or &lt;strong&gt;&amp;#8220;imap&amp;#8221;&lt;/strong&gt; (without quotes) and&lt;/li&gt;
&lt;li&gt;All the usual &lt;strong&gt;OAuth parameters&lt;/strong&gt; except &amp;#8220;oauth_signature&amp;#8221;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The actual XOAUTH string will be constructed from the &lt;strong&gt;HTTP method&lt;/strong&gt;, the &lt;strong&gt;URL&lt;/strong&gt; as defined above and the &lt;strong&gt;OAuth parameters&lt;/strong&gt;, the three parts concatenated with space characters, and then base64-encoded.  You can find examples for it at Google&amp;#8217;s &lt;a href="http://code.google.com/apis/gmail/oauth/protocol.html"&gt;reference page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We can build the XOAUTH string in a straightforward way with &lt;a href="http://code.google.com/p/oauth-signpost/"&gt;signpost&lt;/a&gt; and our Android OAuth &lt;a href="http://nilvec.com/implementing-client-side-oauth-on-android/"&gt;helper class&lt;/a&gt; (if you&amp;#8217;d like to use it in plain Java, just remove the Log lines).  Since many people have asked for the source code of the class, here it goes the whole stuff as used in &lt;a href="https://market.android.com/details?id=com.nilvec.smsforwarder"&gt;SMSForwarder&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="brush: java; "&gt;

package com.nilvec.oauth;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.SortedSet;
import java.util.Map.Entry;

import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.util.Log;

import oauth.signpost.OAuth;
import oauth.signpost.OAuthConsumer;
import oauth.signpost.OAuthProvider;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import oauth.signpost.commonshttp.CommonsHttpOAuthProvider;
import oauth.signpost.commonshttp.HttpRequestAdapter;
import oauth.signpost.exception.OAuthCommunicationException;
import oauth.signpost.exception.OAuthExpectationFailedException;
import oauth.signpost.exception.OAuthMessageSignerException;
import oauth.signpost.exception.OAuthNotAuthorizedException;
import oauth.signpost.http.HttpParameters;
import oauth.signpost.signature.HmacSha1MessageSigner;
import oauth.signpost.signature.OAuthMessageSigner;

public class OAuthHelper {

    private static final String TAG = &amp;quot;OAuthHelper&amp;quot;;

    private OAuthConsumer mConsumer;
    private OAuthProvider mProvider;

    private String mCallbackUrl;

    public OAuthHelper(String consumerKey, String consumerSecret,
            String scope, String callbackUrl, String appname)
    throws UnsupportedEncodingException {
        String reqUrl;
        if (appname == null)
            reqUrl = OAuth.addQueryParameters(
                    &amp;quot;https://www.google.com/accounts/OAuthGetRequestToken&amp;quot;,
                    &amp;quot;scope&amp;quot;, scope);
        else
            reqUrl = OAuth.addQueryParameters(
                    &amp;quot;https://www.google.com/accounts/OAuthGetRequestToken&amp;quot;,
                    &amp;quot;scope&amp;quot;, scope, &amp;quot;xoauth_displayname&amp;quot;, appname);

        mConsumer = new CommonsHttpOAuthConsumer(consumerKey, consumerSecret);

        mProvider = new CommonsHttpOAuthProvider(reqUrl,
                &amp;quot;https://www.google.com/accounts/OAuthGetAccessToken&amp;quot;,
                &amp;quot;https://www.google.com/accounts/OAuthAuthorizeToken?hd=default&amp;quot;);
        mProvider.setOAuth10a(true);

        mCallbackUrl = (callbackUrl == null ? OAuth.OUT_OF_BAND : callbackUrl);
    }

    public String getRequestToken()
    throws OAuthMessageSignerException, OAuthNotAuthorizedException,
    OAuthExpectationFailedException, OAuthCommunicationException {
        String authUrl =
                mProvider.retrieveRequestToken(mConsumer, mCallbackUrl);
        return authUrl;
    }

    public String[] getAccessToken(String verifier)
    throws OAuthMessageSignerException, OAuthNotAuthorizedException,
    OAuthExpectationFailedException, OAuthCommunicationException {
        mProvider.retrieveAccessToken(mConsumer, verifier);
        return new String[] {
                mConsumer.getToken(), mConsumer.getTokenSecret()
        };
    }

    public String[] getToken() {
        return new String[] {
                mConsumer.getToken(), mConsumer.getTokenSecret()
        };
    }

    public void setToken(String token, String secret) {
        mConsumer.setTokenWithSecret(token, secret);
    }

    public String getUrlContent(String url)
    throws OAuthMessageSignerException, OAuthExpectationFailedException,
    OAuthCommunicationException, IOException {
        HttpGet request = new HttpGet(url);

        // sign the request
        mConsumer.sign(request);

        // send the request
        HttpClient httpClient = new DefaultHttpClient();
        HttpResponse response = httpClient.execute(request);

        // get content
        BufferedReader in = new BufferedReader(
                new InputStreamReader(response.getEntity().getContent()));
        StringBuffer sb = new StringBuffer(&amp;quot;&amp;quot;);
        String line = &amp;quot;&amp;quot;;
        String NL = System.getProperty(&amp;quot;line.separator&amp;quot;);
        while ((line = in.readLine()) != null)
            sb.append(line + NL);
        in.close();

        return sb.toString();
    }

    public String buildXOAuth(String email) {
        String url =
            String.format(&amp;quot;https://mail.google.com/mail/b/%s/smtp/&amp;quot;, email);
        HttpRequestAdapter request = new HttpRequestAdapter(new HttpGet(url));

        // Sign the request, the consumer will add any missing parameters
        try {
            mConsumer.sign(request);
        } catch (OAuthMessageSignerException e) {
            Log.e(TAG, &amp;quot;failed to sign xoauth http request &amp;quot; + e);
            return null;
        } catch (OAuthExpectationFailedException e) {
            Log.e(TAG, &amp;quot;failed to sign xoauth http request &amp;quot; + e);
            return null;
        } catch (OAuthCommunicationException e) {
            Log.e(TAG, &amp;quot;failed to sign xoauth http request &amp;quot; + e);
            return null;
        }
        HttpParameters params = mConsumer.getRequestParameters();

        // Since signpost doesn&amp;#039;t put the signature into params,
        // we&amp;#039;ve got to create it again.
        OAuthMessageSigner signer = new HmacSha1MessageSigner();
        signer.setConsumerSecret(mConsumer.getConsumerSecret());
        signer.setTokenSecret(mConsumer.getTokenSecret());
        String signature;
        try {
            signature = signer.sign(request, params);
        } catch (OAuthMessageSignerException e) {
            Log.e(TAG, &amp;quot;invalid oauth request or parameters &amp;quot; + e);
            return null;
        }
        params.put(OAuth.OAUTH_SIGNATURE, OAuth.percentEncode(signature));

        StringBuilder sb = new StringBuilder();
        sb.append(&amp;quot;GET &amp;quot;);
        sb.append(url);
        sb.append(&amp;quot; &amp;quot;);
        int i = 0;
        for (Entry&amp;lt;String, SortedSet&amp;lt;String&amp;gt;&amp;gt; entry : params.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue().first();

            int size = entry.getValue().size();
            if (size != 1)
                Log.d(TAG, &amp;quot;warning: &amp;quot; + key + &amp;quot; has &amp;quot; + size + &amp;quot; values&amp;quot;);

            if (i++ != 0)
                sb.append(&amp;quot;,&amp;quot;);
            sb.append(key);
            sb.append(&amp;quot;=\&amp;quot;&amp;quot;);
            sb.append(value);
            sb.append(&amp;quot;\&amp;quot;&amp;quot;);
        }
        Log.d(TAG, &amp;quot;xoauth encoding &amp;quot; + sb);

        Base64 base64 = new Base64();
        try {
            byte[] buf = base64.encode(sb.toString().getBytes(&amp;quot;utf-8&amp;quot;));
            return new String(buf, &amp;quot;utf-8&amp;quot;);
        } catch (UnsupportedEncodingException e) {
            Log.e(TAG, &amp;quot;invalid string &amp;quot; + sb);
        }

        return null;
    }

}
&lt;/pre&gt;
&lt;p&gt;Don&amp;#8217;t forget to provide feedback if you find this class or article useful.  Happy hacking!&lt;/p&gt;
&lt;div class="shr-publisher-466"&gt;&lt;/div&gt;&lt;!-- Start Shareaholic LikeButtonSetBottom Automatic --&gt;&lt;!-- End Shareaholic LikeButtonSetBottom Automatic --&gt;&lt;img src="http://feeds.feedburner.com/~r/nilvec/~4/9W_OS6CyPQ8" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://nilvec.com/implementing-smtp-or-imap-xoauth-authentication-in-java/#comments" thr:count="6" />
		<link rel="replies" type="application/atom+xml" href="http://nilvec.com/implementing-smtp-or-imap-xoauth-authentication-in-java/feed/atom/" thr:count="6" />
		<thr:total>6</thr:total>
	<feedburner:origLink>http://nilvec.com/implementing-smtp-or-imap-xoauth-authentication-in-java/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>ldx</name>
						<uri>http://nilvec.com</uri>
					</author>
		<title type="html"><![CDATA[Implementing client-side OAuth on Android]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/nilvec/~3/e3KVfzYLEHU/" />
		<id>http://nilvec.com/?p=408</id>
		<updated>2011-03-06T17:43:25Z</updated>
		<published>2011-02-04T18:29:39Z</published>
		<category scheme="http://nilvec.com" term="android" /><category scheme="http://nilvec.com" term="development" /><category scheme="http://nilvec.com" term="java" /><category scheme="http://nilvec.com" term="oauth" />		<summary type="html"><![CDATA[OAuth is becoming the de-facto protocol to allow access to your data and services without sharing user password. Effectively all the big names such as Twitter, Google, Yahoo or LinkedIn have already implemented it. There are quite a few libraries &#8230; <a href="http://nilvec.com/implementing-client-side-oauth-on-android/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></summary>
		<content type="html" xml:base="http://nilvec.com/implementing-client-side-oauth-on-android/">&lt;!-- Start Shareaholic LikeButtonSetTop Automatic --&gt;&lt;!-- End Shareaholic LikeButtonSetTop Automatic --&gt;&lt;div class="shr-publisher-408"&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="http://oauth.net/"&gt;OAuth&lt;/a&gt; is becoming the de-facto protocol to allow access to your data and services without sharing user password.  Effectively all the big names such as Twitter, Google, Yahoo or LinkedIn have already implemented it.  There are quite a few libraries and code samples in all the popular programming languages out there to implement OAuth in your desktop, mobile or web application as well.&lt;/p&gt;
&lt;p&gt;There are &lt;a href="http://donpark.org/blog/2009/01/24/android-client-side-oauth"&gt;guides&lt;/a&gt; for Android too, however most of them are not up to date, accurate or just difficult to comprehend if you are in a hurry.  Here we provide a few easy to follow steps with some explanation how it can be done in a straightforward way.&lt;/p&gt;
&lt;p&gt;First, a short summary how OAuth works.  It is based on cryptography, where&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;a token and a corresponding secret is acquired by a &lt;strong&gt;consumer&lt;/strong&gt; (a desktop or web application) from a &lt;strong&gt;provider&lt;/strong&gt; (a server in the cloud),
&lt;/li&gt;
&lt;li&gt;this token is authorized by the &lt;strong&gt;user&lt;/strong&gt; as valid and allowed to access their data and then
&lt;/li&gt;
&lt;li&gt;the token is upgraded, and this can then be used from then on until it is revoked by same user who authorized it.
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The token acquired in the first step is called a &lt;strong&gt;request token&lt;/strong&gt;, this is where you usually specify which service you would like to get access to; it is called &lt;strong&gt;scope&lt;/strong&gt;.  The second step is called &lt;strong&gt;authorization&lt;/strong&gt;, after which control can be passed back to the consumer application via a callback.  The final token that is received in the third step is called &lt;strong&gt;access token&lt;/strong&gt;.  This can be used for a long period of time, it won&amp;#8217;t expire (but, as mentioned, the user can revoke it any time).  It is basically a short string, with a corresponding secret string, and once the application acquired it, it can be used to sign HTTP requests, thus authenticating it for the provider.  All three steps have a corresponding URL at the provider, to where an HTTP request is sent to get the token or manipulate it.&lt;/p&gt;
&lt;p&gt;If you need further details, there&amp;#8217;s a good article with API reference at &lt;a href="http://code.google.com/apis/accounts/docs/OAuth_ref.html"&gt;code.google.com&lt;/a&gt;, and another very detailed overview with figures &lt;a href="http://blog.doityourselfandroid.com/2010/11/07/google-oauth-overview/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We will use the excellent &lt;a href="http://code.google.com/p/oauth-signpost/"&gt;signpost&lt;/a&gt; Java library to implement OAuth access to Gmail. Just &lt;a href="http://code.google.com/p/oauth-signpost/downloads/list"&gt;download&lt;/a&gt; at least the signpost-core and signpost-commonshttp4 jars, copy them to the lib/ folder inside your Android project, right click on the project, and under Properties/Java Build Path you can add them to the build path:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://nilvec.com/wordpress/wp-content/uploads/2011/02/oauth_build_path.png"&gt;&lt;img src="http://nilvec.com/wordpress/wp-content/uploads/2011/02/oauth_build_path.png" alt="Adding the signpost jars to the build path" title="oauth_build_path" width="401" class="alignnone size-full wp-image-411" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We will implement OAuth support via a helper class called &lt;strong&gt;OAuthHelper&lt;/strong&gt;.  The two single most important classes provided by signpost are &lt;strong&gt;OAuthConsumer&lt;/strong&gt;  and &lt;strong&gt;OAuthProvider&lt;/strong&gt;; before diving into actual communications, we set these up first:&lt;/p&gt;
&lt;pre class="brush: java; "&gt;

	private OAuthConsumer mConsumer;
	private OAuthProvider mProvider;

	private String mCallbackUrl;

	public OAuthHelper(String consumerKey, String consumerSecret,
			String scope, String callbackUrl)
	throws UnsupportedEncodingException {
		mConsumer = new CommonsHttpOAuthConsumer(consumerKey, consumerSecret);
		mProvider = new CommonsHttpOAuthProvider(
				&amp;quot;https://www.google.com/accounts/OAuthGetRequestToken?scope=&amp;quot;
				+ URLEncoder.encode(scope, &amp;quot;utf-8&amp;quot;),
				&amp;quot;https://www.google.com/accounts/OAuthGetAccessToken&amp;quot;,
				&amp;quot;https://www.google.com/accounts/OAuthAuthorizeToken?hd=default&amp;quot;);
		mProvider.setOAuth10a(true);
		mCallbackUrl = (callbackUrl == null ? OAuth.OUT_OF_BAND : callbackUrl);
	}
&lt;/pre&gt;
&lt;p&gt;The &lt;strong&gt;consumerKey&lt;/strong&gt; and &lt;strong&gt;consumerSecret&lt;/strong&gt; strings depend on your consumer application, you can use anonymous for both.  Later you might want to register your application at the provider (Google in this case), which will issue a key and secret for your app.  To access an user&amp;#8217;s Gmail inbox the scope is &lt;em&gt;&amp;#8220;https://mail.google.com/&amp;#8221;&lt;/em&gt;, the URLs for OAuth are in the constructor of the helper class.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;callbackUrl&lt;/strong&gt; variable can be used to pass an URL to the provider which will be called once your token is authorized.  On Android you can register a special URL scheme to your application, thus the browser will fire up an activity of your app once authorization has been done.  E.g. if you would like &lt;em&gt;MyActivity&lt;/em&gt; to be called put the following into your app manifest:&lt;/p&gt;
&lt;pre class="brush: xml; "&gt;

&amp;lt;activity android:name=&amp;quot;MyActivity&amp;quot;&amp;gt;
	&amp;lt;intent-filter&amp;gt;
        &amp;lt;action android:name=&amp;quot;android.intent.action.VIEW&amp;quot; /&amp;gt;
        &amp;lt;category android:name=&amp;quot;android.intent.category.DEFAULT&amp;quot; /&amp;gt;
        &amp;lt;category android:name=&amp;quot;android.intent.category.BROWSABLE&amp;quot; /&amp;gt;
        &amp;lt;data android:scheme=&amp;quot;my-activity&amp;quot;/&amp;gt;
	&amp;lt;/intent-filter&amp;gt;
&amp;lt;/activity&amp;gt;
&lt;/pre&gt;
&lt;p&gt;and pass &lt;em&gt;&amp;#8220;my-activity://mywebsite.com/&amp;#8221;&lt;/em&gt; as the callback URL.  This also has the side effect of identifying your application as &lt;em&gt;mywebsite.com&lt;/em&gt; at the provider (at least at Google).  Your application will get back a verifier code via the callback as a query parameter to the URL, where the query key is &lt;em&gt;&amp;#8220;verifier&amp;#8221;&lt;/em&gt;.  You will need this later.&lt;/p&gt;
&lt;p&gt;As a next step, retrieve the request token:&lt;/p&gt;
&lt;pre class="brush: java; "&gt;

	public String getRequestToken()
	throws OAuthMessageSignerException, OAuthNotAuthorizedException,
	OAuthExpectationFailedException, OAuthCommunicationException {
		String authUrl = mProvider.retrieveRequestToken(mConsumer, mCallbackUrl);
		return authUrl;
	}
&lt;/pre&gt;
&lt;p&gt;Once you got back the authentication URL from this method, just start up the browser with it:&lt;/p&gt;
&lt;pre class="brush: java; "&gt;

try {
	String uri = helper.getRequestToken();
	startActivity(new Intent(&amp;quot;android.intent.action.VIEW&amp;quot;, Uri.parse(uri)));
} catch (...) {
}
&lt;/pre&gt;
&lt;p&gt;In your &lt;em&gt;OnResume()&lt;/em&gt; method in &lt;em&gt;MyActivity&lt;/em&gt; you can catch the callback and retrieve the verifier, and upgrade your token with it:&lt;/p&gt;
&lt;pre class="brush: java; "&gt;

		String[] token = getVerifier();
		if (token != null)
			String accessToken[] = getAccessToken(token[1]);

...

	private String[] getVerifier() {
		// extract the token if it exists
		Uri uri = this.getIntent().getData();
		if (uri == null) {
			return null;
		}

		String token = uri.getQueryParameter(&amp;quot;oauth_token&amp;quot;);
		String verifier = uri.getQueryParameter(&amp;quot;oauth_verifier&amp;quot;);
		return new String[] { token, verifier };
	}
&lt;/pre&gt;
&lt;p&gt;In our helper class:&lt;/p&gt;
&lt;pre class="brush: java; "&gt;

	public String[] getAccessToken(String verifier)
	throws OAuthMessageSignerException, OAuthNotAuthorizedException,
	OAuthExpectationFailedException, OAuthCommunicationException {
		mProvider.retrieveAccessToken(mConsumer, verifier);
		return new String[] {
				mConsumer.getToken(), mConsumer.getTokenSecret()
		};
	}
&lt;/pre&gt;
&lt;p&gt;And that&amp;#8217;s it.  Just make sure you save the access token and its secret.  You can now use signpost to sign your HTTP queries e.g.&lt;/p&gt;
&lt;pre class="brush: java; "&gt;

	OAuthConsumer consumer = new CommonsHttpOAuthConsumer(accessToken[0], accessToken[1]);

	HttpGet request = new HttpGet(url);

       // sign the request
       consumer.sign(request);

       // send the request
       HttpClient httpClient = new DefaultHttpClient();
       HttpResponse response = httpClient.execute(request);
&lt;/pre&gt;
&lt;p&gt;Happy hacking!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update&lt;/em&gt;: fixed some typos in code snippets.&lt;/p&gt;
&lt;div class="shr-publisher-408"&gt;&lt;/div&gt;&lt;!-- Start Shareaholic LikeButtonSetBottom Automatic --&gt;&lt;!-- End Shareaholic LikeButtonSetBottom Automatic --&gt;&lt;img src="http://feeds.feedburner.com/~r/nilvec/~4/e3KVfzYLEHU" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://nilvec.com/implementing-client-side-oauth-on-android/#comments" thr:count="7" />
		<link rel="replies" type="application/atom+xml" href="http://nilvec.com/implementing-client-side-oauth-on-android/feed/atom/" thr:count="7" />
		<thr:total>7</thr:total>
	<feedburner:origLink>http://nilvec.com/implementing-client-side-oauth-on-android/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>ldx</name>
						<uri>http://nilvec.com</uri>
					</author>
		<title type="html"><![CDATA[How to use the latest 802.11 drivers and stack with Linux]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/nilvec/~3/M6bVYEdyg2U/" />
		<id>http://nilvec.com/?p=399</id>
		<updated>2011-01-24T23:12:37Z</updated>
		<published>2011-01-24T23:11:32Z</published>
		<category scheme="http://nilvec.com" term="80211" /><category scheme="http://nilvec.com" term="linux" /><category scheme="http://nilvec.com" term="wireless" />		<summary type="html"><![CDATA[There might be several reasons why the wireless drivers from your distro don&#8217;t fit the bill. You purchased a new wifi card which doesn&#8217;t have a driver in the kernel of your Linux system, or you would like to play &#8230; <a href="http://nilvec.com/how-to-use-the-latest-802-11-drivers-and-stack-with-linux/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></summary>
		<content type="html" xml:base="http://nilvec.com/how-to-use-the-latest-802-11-drivers-and-stack-with-linux/">&lt;!-- Start Shareaholic LikeButtonSetTop Automatic --&gt;&lt;!-- End Shareaholic LikeButtonSetTop Automatic --&gt;&lt;div class="shr-publisher-399"&gt;&lt;/div&gt;&lt;p&gt;There might be several reasons why the wireless drivers from your distro don&amp;#8217;t fit the bill. You purchased a new wifi card which doesn&amp;#8217;t have a driver in the kernel of your Linux system, or you would like to play with some cool new feature or just to make sure you have the latest and greatest, cutting edge 802.11 software.&lt;/p&gt;
&lt;p&gt;Thanks to the work of the Linux &lt;a href="http://wireless.kernel.org/"&gt;wireless developers&lt;/a&gt; it is now possible to do that without upgrading your kernel. Using a compatibility layer you can compile and install the latest drivers and the 802.11 stack, and use it with your current kernel (that is, if you have a relatively recent kernel &amp;#8212; if you have 2.6.24 or anything more recent, you&amp;#8217;re good to go).&lt;/p&gt;
&lt;p&gt;To use bleeding edge drivers, first make sure your kernel headers package is installed. Then fetch the necessary git trees:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
mkdir compat-wireless &amp;#038;&amp;#038; cd compat-wireless&lt;br /&gt;
git clone git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git&lt;br /&gt;
git clone git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/compat.git&lt;br /&gt;
git clone git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/compat-wireless-2.6.git&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;linux-next&lt;/strong&gt; git tree contains the code for the next kernel release, and 802.11 updates are pulled into it on a regular basis. The &lt;strong&gt;compat&lt;/strong&gt; and &lt;strong&gt;compat-wireless-2.6&lt;/strong&gt; trees implement the necessary compatibility layer, thus making it possible to use the wireless subsystem from &lt;strong&gt;linux-next&lt;/strong&gt; with your kernel. You can also use your git trees to follow development, and keep your wireless drivers up to date: just pull from the remote repositories when you&amp;#8217;d like to update. However, the &lt;strong&gt;linux-next&lt;/strong&gt; repository is rebased on a regular basis, so you may want to check out the daily tag instead of pulling.&lt;/p&gt;
&lt;p&gt;You can use the &lt;strong&gt;compat-wireless-2.6&lt;/strong&gt; directory to actually build the wireless subsystem:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
cd compat-wireless-2.6&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Specify where your newly fetched kernel tree and the compat tree are:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
export GIT_TREE=`pwd`/../linux-next/&lt;br /&gt;
export GIT_COMPAT_TREE=`pwd`/../compat/&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Then refresh &lt;strong&gt;compat-wireless-2.6&lt;/strong&gt; with the contents of your git trees:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
./scripts/admin-refresh.sh&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You can also select just a specific driver or group of drivers, e.g. if you only need the &lt;em&gt;ath5k&lt;/em&gt; driver:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
./scripts/driver-select ath5k&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And that&amp;#8217;s it, everything should be ready for the build.&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
make&lt;br /&gt;
sudo make install&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Your newly built modules will go into the &lt;em&gt;updates&lt;/em&gt; folder inside your kernel module directory. Reboot your box (or use the scripts supplied with &lt;strong&gt;compat-wireless-2.6&lt;/strong&gt; to reload any drivers).&lt;/p&gt;
&lt;div class="shr-publisher-399"&gt;&lt;/div&gt;&lt;!-- Start Shareaholic LikeButtonSetBottom Automatic --&gt;&lt;!-- End Shareaholic LikeButtonSetBottom Automatic --&gt;&lt;img src="http://feeds.feedburner.com/~r/nilvec/~4/M6bVYEdyg2U" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://nilvec.com/how-to-use-the-latest-802-11-drivers-and-stack-with-linux/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://nilvec.com/how-to-use-the-latest-802-11-drivers-and-stack-with-linux/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://nilvec.com/how-to-use-the-latest-802-11-drivers-and-stack-with-linux/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>NexusGuy</name>
					</author>
		<title type="html"><![CDATA[Nexus S details]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/nilvec/~3/tvucQA4varw/" />
		<id>http://nilvec.com/?p=379</id>
		<updated>2010-12-18T03:10:52Z</updated>
		<published>2010-12-18T02:38:31Z</published>
		<category scheme="http://nilvec.com" term="android" />		<summary type="html"><![CDATA[Is the Nexus S ugly? We don&#8217;t think so. The new Google Android phone Nexus S just arrived and looks like some amazing alien toy with a pitch black front. You can&#8217;t tell where the screen ends and where the phone &#8230; <a href="http://nilvec.com/nexus-s-details/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></summary>
		<content type="html" xml:base="http://nilvec.com/nexus-s-details/">&lt;!-- Start Shareaholic LikeButtonSetTop Automatic --&gt;&lt;!-- End Shareaholic LikeButtonSetTop Automatic --&gt;&lt;div class="shr-publisher-379"&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Is the Nexus S ugly? We don&amp;#8217;t think so.&lt;/strong&gt; &lt;span style="font-size: 11.6667px;"&gt;The new Google Android phone Nexus S just arrived and looks like some amazing alien toy with a pitch black front. You can&amp;#8217;t tell where the screen ends and where the phone starts. Check out these unboxing pictures below.&lt;/span&gt;&lt;/p&gt;
&lt;div class="wp-caption alignnone" style="width: 610px"&gt;&lt;img title="Google Nexus S box" src="http://lh4.ggpht.com/_mw_mnFA9-5g/TQwXh5fcXLI/AAAAAAAAE9g/-ArKXyHTcOw/google-nexus-s-box-1.jpg" alt="Google Nexus S box" width="600" height="480" /&gt;&lt;p class="wp-caption-text"&gt;Google Nexus S box&lt;/p&gt;&lt;/div&gt;
&lt;div class="wp-caption alignnone" style="width: 610px"&gt;&lt;img class=" " title="Google Nexus S box and phone" src="http://lh6.ggpht.com/_mw_mnFA9-5g/TQwXiVnEPWI/AAAAAAAAE9k/WQhMtOilEzg/s720/google-nexus-s-box-and-phone.jpg" alt="Google Nexus S box and phone" width="600" height="480" /&gt;&lt;p class="wp-caption-text"&gt;Google Nexus S box and phone&lt;/p&gt;&lt;/div&gt;
&lt;div class="wp-caption alignnone" style="width: 610px"&gt;&lt;img class=" " title="Nexus S box contents - battery, charger and chord" src="http://lh4.ggpht.com/_mw_mnFA9-5g/TQwXjA-fUJI/AAAAAAAAE9s/wLV9ubVb-Uo/s720/nexus-s-box-contents.jpg" alt="Nexus S box contents - battery, charger and chord" width="600" height="480" /&gt;&lt;p class="wp-caption-text"&gt;Nexus S box contents - battery, charger and chord&lt;/p&gt;&lt;/div&gt;
&lt;div class="wp-caption alignnone" style="width: 610px"&gt;&lt;img class=" " title="Nexus S box contents with phone" src="http://lh4.ggpht.com/_mw_mnFA9-5g/TQwX1V6a_lI/AAAAAAAAE94/LOd-z4nL3f4/s720/nexus-s-box-contents-with-phone.jpg" alt="Nexus S box contents with phone" width="600" height="480" /&gt;&lt;p class="wp-caption-text"&gt;Nexus S box contents with the pitch black phone&lt;/p&gt;&lt;/div&gt;
&lt;div class="wp-caption alignnone" style="width: 610px"&gt;&lt;img class=" " title="Nexus S, an alien looking phone" src="http://lh3.ggpht.com/_mw_mnFA9-5g/TQwX3XilIVI/AAAAAAAAE-I/4k0Mt5bt8IQ/s720/nexus-s-switched-off-pitch-black.jpg" alt="Nexus S, an alien looking phone" width="600" height="480" /&gt;&lt;p class="wp-caption-text"&gt;Nexus S, an alien looking phone&lt;/p&gt;&lt;/div&gt;
&lt;div class="wp-caption alignnone" style="width: 394px"&gt;&lt;img class=" " title="Nexus S start screen" src="http://lh6.ggpht.com/_mw_mnFA9-5g/TQwX3NKpMgI/AAAAAAAAE-E/HgsmIRBYobU/s512/nexus-s-start-screen.jpg" alt="Nexus S start screen" width="384" height="512" /&gt;&lt;p class="wp-caption-text"&gt;Nexus S welcome screen - say hello!&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Highlights:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;#8220;Gingerbread&amp;#8221; operating system, version 2.3.&lt;/li&gt;
&lt;li&gt;Keyboard is much better, you can forget Swype.&lt;/li&gt;
&lt;li&gt;2 cameras, including 1 in the front (for video chat).&lt;/li&gt;
&lt;li&gt;I prefer unmodified Android stock UI more than manufacturer overlay eg. HTC Sense UI.&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 11.6667px;"&gt;Near Field Communication ability (so it can become your wallet in the future).&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 11.6667px;"&gt; &lt;/span&gt;&lt;span style="font-size: 11.6667px;"&gt;16GB built-in memory  (OK, no way to add an SD card, but at this point everything I have is in the cloud anyway).&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 11.6667px;"&gt;4.0 inches, WVGA (800 x 480) touch screen.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 11.6667px;"&gt;Awesome, curved, super-black and alien looking gadget.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style="font-family: GillSans, Calibri, Trebuchet, Arial, sans-serif; line-height: 16px; font-size: 11.6667px;"&gt;We are complete Nexus drones, so we don&amp;#8217;t buy into all the mixed comments in other Android blogs. But we can be reasoned with &amp;#8211; what do you think?  &lt;img title="android grin" src="http://nilvec.com/wordpress/wp-content/uploads/2010/03/android-smile.png" alt="android grin" width="20" height="20" align="middle" /&gt; &lt;/span&gt;&lt;/p&gt;
&lt;div class="shr-publisher-379"&gt;&lt;/div&gt;&lt;!-- Start Shareaholic LikeButtonSetBottom Automatic --&gt;&lt;!-- End Shareaholic LikeButtonSetBottom Automatic --&gt;&lt;img src="http://feeds.feedburner.com/~r/nilvec/~4/tvucQA4varw" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://nilvec.com/nexus-s-details/#comments" thr:count="2" />
		<link rel="replies" type="application/atom+xml" href="http://nilvec.com/nexus-s-details/feed/atom/" thr:count="2" />
		<thr:total>2</thr:total>
	<feedburner:origLink>http://nilvec.com/nexus-s-details/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>ldx</name>
						<uri>http://nilvec.com</uri>
					</author>
		<title type="html"><![CDATA[Testing an Android image built from source]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/nilvec/~3/db4dBCvG4dc/" />
		<id>http://nilvec.com/?p=366</id>
		<updated>2010-11-10T17:02:47Z</updated>
		<published>2010-11-10T16:58:11Z</published>
		<category scheme="http://nilvec.com" term="android" /><category scheme="http://nilvec.com" term="development" />		<summary type="html"><![CDATA[So you just built a new android system from source and you would like to test it first in the emulator before flashing it onto your phone.  Or perhaps you would just like to know how the bleeding edge version &#8230; <a href="http://nilvec.com/testing-an-android-image-built-from-source/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></summary>
		<content type="html" xml:base="http://nilvec.com/testing-an-android-image-built-from-source/">&lt;!-- Start Shareaholic LikeButtonSetTop Automatic --&gt;&lt;!-- End Shareaholic LikeButtonSetTop Automatic --&gt;&lt;div class="shr-publisher-366"&gt;&lt;/div&gt;&lt;p&gt;So you just built a new android system &lt;a href="http://nilvec.com/building-cyanogen-from-source/"&gt;from source&lt;/a&gt; and you would like to test it first in the emulator before flashing it onto your phone.  Or perhaps you would just like to know how the bleeding edge version of android straight from the source repositories looks.  Fortunately, the emulator used by android SDK is flexible enough, so you can specify what image it should use for the data, system or the other partitions &amp;#8212; thus you can build your own flavor of android and test it in the emulator easily.&lt;/p&gt;
&lt;p&gt;Once you have checked out the android source tree via repo (either the &lt;a href="http://android.git.kernel.org/?p=platform/manifest.git;a=summary"&gt;official one&lt;/a&gt;, &lt;a href="https://github.com/CyanogenMod/android"&gt;cyanogenmod&lt;/a&gt; or some other mod which published its source via a manifest file) apply your changes if any (add a new component to the system, modify the framework etc).  Then just pick a build target (it can be for example full-eng, it will work with the emulator) and build it the &lt;a href="http://nilvec.com/building-cyanogen-from-source/"&gt;usual way&lt;/a&gt;.  By default the qemu-based emulator is also built, and it will be placed to&lt;strong&gt; out/host/linux-x86/bin/&lt;/strong&gt;.  When it&amp;#8217;s done the images will be in &lt;strong&gt;out/target/product/(your target device name)/&lt;/strong&gt;.  From now on I&amp;#8217;ll assume you picked the generic target.&lt;/p&gt;
&lt;p&gt;You will also likely need an SD card image that can mounted by the emulator.  The SDK contains a tool, &lt;strong&gt;mksdcard&lt;/strong&gt; with which it&amp;#8217;s simple enough to create one:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;$ mksdcard 1024M out/target/product/generic/sdcard.img&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;The SDK &lt;strong&gt;tools/&lt;/strong&gt; folder should be in your &lt;strong&gt;$PATH&lt;/strong&gt; for this to work.&lt;/p&gt;
&lt;p&gt;Now the only thing left is to fire up the emulator with your newly built images:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;$ ./out/host/linux-x86/bin/emulator \
-sysdir out/target/product/generic \
-kernel prebuilt/android-arm/kernel/kernel-qemu \
-data out/target/product/generic/userdata.img \
-sdcard out/target/product/generic/sdcard.img&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;That&amp;#8217;s all, the emulator should start up, and if you are lucky your new android hack will come to light and work.  You can use &lt;strong&gt;adb&lt;/strong&gt; to copy files to/from the emulator image, or just fire up a root shell in the emulator via &lt;strong&gt;adb shell&lt;/strong&gt; and take a look what is going on.&lt;/p&gt;
&lt;div class="shr-publisher-366"&gt;&lt;/div&gt;&lt;!-- Start Shareaholic LikeButtonSetBottom Automatic --&gt;&lt;!-- End Shareaholic LikeButtonSetBottom Automatic --&gt;&lt;img src="http://feeds.feedburner.com/~r/nilvec/~4/db4dBCvG4dc" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://nilvec.com/testing-an-android-image-built-from-source/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://nilvec.com/testing-an-android-image-built-from-source/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://nilvec.com/testing-an-android-image-built-from-source/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>ldx</name>
						<uri>http://nilvec.com</uri>
					</author>
		<title type="html"><![CDATA[IndentFinder vim plugin]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/nilvec/~3/TyieJM4RkUc/" />
		<id>http://nilvec.com/?p=346</id>
		<updated>2010-10-28T22:21:04Z</updated>
		<published>2010-10-21T21:40:36Z</published>
		<category scheme="http://nilvec.com" term="python" /><category scheme="http://nilvec.com" term="vim" />		<summary type="html"><![CDATA[This is a great little python script that finds out what indentation is used in your source files. The author also provides a vim plugin, which is a life saver for anyone working with others on software projects. It prevents &#8230; <a href="http://nilvec.com/indentfinder-vim-plugin/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></summary>
		<content type="html" xml:base="http://nilvec.com/indentfinder-vim-plugin/">&lt;!-- Start Shareaholic LikeButtonSetTop Automatic --&gt;&lt;!-- End Shareaholic LikeButtonSetTop Automatic --&gt;&lt;div class="shr-publisher-346"&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="http://www.freehackers.org/Indent_Finder"&gt;This&lt;/a&gt; is a great little python script that finds out what indentation is used in your source files. The author also provides a vim plugin, which is a life saver for anyone working with others on software projects.  It prevents the complete mess that is the result of team members using their own indentation settings on source code.  It analyses the text file, and provides reliable hints what indentation settings (tabs vs spaces, number of spaces etc) were used by the author.  There is &lt;a href="http://www.vim.org/scripts/script.php?script_id=3096"&gt;another plugin&lt;/a&gt; for the same purpose, which is basically the vimscript port of IndentFinder, but this latter is extremely slow, especially on large files (it seems vimscript was not really meant for parsing thousands of lines every time you open a file).&lt;/p&gt;
&lt;p&gt;What I did not really like about IndentFinder was the way it invokes the python interpreter (thus increasing startup time and leaving room for errors), even if python bindings are supported in vim.  One solution could have been simply to create a vim plugin from the python source, but then this would have meant increased maintenance efforts (copying changes from the python source to the vim plugin).  Another possibility was to generate the vim plugin via setup.py from the python source.&lt;/p&gt;
&lt;p&gt;First I added a new method to the main class in indent_finder.py:&lt;/p&gt;
&lt;pre&gt;--- a/indent_finder.py
+++ b/indent_finder.py
@@ -125,16 +125,21 @@ class IndentFinder:
         self.clear()^M
         f = open( fname )^M
         l = f.readline()^M
         while( l ):^M
             self.analyse_line( l )^M
             l = f.readline()^M
         f.close()^M
 ^M
+    def parse_buffer( self, buf ):^M
+        self.clear()^M
+        for l in buf:^M
+            self.analyse_line(l)^M
+^M
     def clear( self ):^M
         self.lines = {}^M
         for i in range(2,9): self.lines['space%d' % i] = 0^M
         for i in range(2,9): self.lines['mixed%d' % i] = 0^M
         self.lines['tab'] = 0^M
 ^M
         self.nb_processed_lines = 0^M
         self.nb_indent_hint = 0^M&lt;/pre&gt;
&lt;p&gt;It just makes it possible to call the parser with a buffer instead of a file name: vim opens the file and reads its contents into memory, thus it&amp;#8217;s easier to pass the buffer itself to IndentFinder.&lt;/p&gt;
&lt;p&gt;The second part is modifying setup.py to build the plugin from a fixed header, the python source and a fixed trailer.  It turned out distutils is flexible enough to do this easily: you can subset the build class and do your special stuff in it.  Easy:&lt;/p&gt;
&lt;pre&gt;#!/usr/bin/env python

from distutils.core import setup
from distutils.command.build import build
import os
import indent_finder

HEADER = """if exists('indent_finder') || !has('python')
	finish
endif
let indent_finder=1

python &amp;lt;&amp;lt; EOS
"""

TRAILER = """EOS

augroup indent
	au!
	au BufRead *.* :py import vim
	au BufRead *.* :py fi = IndentFinder()
	au BufRead *.* :py fi.parse_buffer(vim.current.buffer)
	au BufRead *.* :py vim.command(fi.vim_output())
augroup END
"""&lt;/pre&gt;
&lt;p&gt;These are our fixed header and trailer parts.  We just make sure python is supported in vim, and make IndentFinder parse the opened buffer.  The result from IndentFinder is an actual vim command that adjusts indentation settings.&lt;/p&gt;
&lt;pre&gt;class build_vimscript(build):
	vimscript = "indent_finder.vim"
	pyscript = "indent_finder.py"

	def run(self):
		build.run(self) # call superclass first

		if self.is_vimscript_outdated():
			self.update_vimscript()

	def is_vimscript_outdated(self):
		pyst = os.stat(self.pyscript)
		try:
			vimst = os.stat(self.vimscript)
		except OSError:
			return True
		else:
			if pyst.st_mtime &amp;gt; vimst.st_mtime:
				return True
		return False

	def update_vimscript(self):
		pyf = open(self.pyscript, "r")
		vimf = open(self.vimscript, "w")

		vimf.write(HEADER)
		for line in pyf:
			vimf.write(line)
		vimf.write(TRAILER)

		vimf.close()
		pyf.close()&lt;/pre&gt;
&lt;p&gt;Here we check that the vim plugin is older than the python source of IndentFinder.  If it is, then the plugin is rebuilt.  Calling the superclass in our run() method makes sure the other part of the build process is handled the usual way.&lt;/p&gt;
&lt;pre&gt;setup( 	name = "Indentation Finder",
		version = indent_finder.VERSION,
		description = "Finds of check the indentation used in programming source files",
		author = "Philippe Fremy",
		author_email = "phil at freehackers dot org",
		maintainer = "Philippe Fremy",
		maintainer_email = "phil at freehackers dot org",
		license = "BSD license",
		url="http://www.freehackers.org/Indent_Finder",
		py_modules = [ "indent_finder" ],
		cmdclass={"build": build_vimscript},
		)&lt;/pre&gt;
&lt;p&gt;Here we&amp;#8217;ve just added a new parameter to setup &lt;em&gt;cmdclass&lt;/em&gt; tells distutils to use our class for building the package.&lt;/p&gt;
&lt;p&gt;And that&amp;#8217;s it.  The .vim plugin is built and can be copied to&lt;br /&gt;
&lt;em&gt;~/.vim/plugin/&lt;/em&gt;.&lt;/p&gt;
&lt;div class="shr-publisher-346"&gt;&lt;/div&gt;&lt;!-- Start Shareaholic LikeButtonSetBottom Automatic --&gt;&lt;!-- End Shareaholic LikeButtonSetBottom Automatic --&gt;&lt;img src="http://feeds.feedburner.com/~r/nilvec/~4/TyieJM4RkUc" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://nilvec.com/indentfinder-vim-plugin/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://nilvec.com/indentfinder-vim-plugin/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://nilvec.com/indentfinder-vim-plugin/</feedburner:origLink></entry>
	</feed>

