<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>GrenadePod &#187; IT Technology</title>
	<atom:link href="http://www.grenadepod.com/category/it-technology/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.grenadepod.com</link>
	<description>Dispersing the Seeds</description>
	<lastBuildDate>Mon, 22 Feb 2010 20:30:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=abc</generator>
		<item>
		<title>Building python 2.6.4 RPM for CentOS 5.4</title>
		<link>http://www.grenadepod.com/2009/12/26/building-python-2-6-4-rpm-for-centos-5-4/</link>
		<comments>http://www.grenadepod.com/2009/12/26/building-python-2-6-4-rpm-for-centos-5-4/#comments</comments>
		<pubDate>Sat, 26 Dec 2009 10:37:25 +0000</pubDate>
		<dc:creator>pulegium</dc:creator>
				<category><![CDATA[IT Technology]]></category>
		<category><![CDATA[System administration]]></category>
		<category><![CDATA[CentOS]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.grenadepod.com/?p=655</guid>
		<description><![CDATA[CentOS is an enterprise linux distribution. And as such, it doesn&#8217;t really like anything new, unless it is a security patch. So it mostly contains older packages that are proven to be stable and secure. Any security patches and changes are backported to the older packages. This is all right for majority of the tools, [...]


Related posts:<ol><li><a href='http://www.grenadepod.com/2009/12/21/sorting-out-yum-repositories-on-centos-5-4/' rel='bookmark' title='Permanent Link: Sorting out YUM repositories on CentOS 5.4'>Sorting out YUM repositories on CentOS 5.4</a></li>
<li><a href='http://www.grenadepod.com/2009/11/23/use-ssh-to-upgrade-wordpress-plugins-automatically/' rel='bookmark' title='Permanent Link: Use SSH to upgrade WordPress plugins automatically'>Use SSH to upgrade WordPress plugins automatically</a></li>
<li><a href='http://www.grenadepod.com/2009/12/03/building-and-running-google-chrome-os-on-virtualbox/' rel='bookmark' title='Permanent Link: Building and running Google Chrome OS on VirtualBox'>Building and running Google Chrome OS on VirtualBox</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p id="top" />CentOS is an enterprise linux distribution. And as such, it doesn&#8217;t really like anything new, unless it is a security patch. So it mostly contains older packages that are proven to be stable and secure. Any security patches and changes are backported to the older packages. This is all right for majority of the tools, but some really needs upgrading. Python is a very good example. Python release, which is included in CentOS 5.4 is a rather old 2.4 branch. If you&#8217;re serious about python development, you really want to have 2.6. Unfortunately there is no CentOS RPM available. So here&#8217;s how to build your own.</p>
<p>First, you need to install RPM devtools:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;"># yum install rpmdevtools</pre></div></div>

<p>Then setup your local RPM build tree:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">$ rpmdev-setuptree</pre></div></div>

<p>This will create RPM build tree (~/rpmbuild/) in your home directory. Just a reminder &#8211; never, ever, under any circumstances, build RPMs as root user. Just a reminder. Obviously, you knew that already, right?</p>
<p>You also want to get and install additional header files and libraries, such as TCL/TK, expat, sqlite, etc, that are used to build some Python components:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;"># yum install tk-devel tcl-devel expat-devel db4-devel gdbm-devel sqlite-devel</pre></div></div>

<p>Now we&#8217;re ready to start building an RPM. Get the RPM spec file from source build tree and copy it to your rpmbuild/SPECS directory, also copy the tarball to your build directory:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">$ wget http://www.python.org/ftp/python/2.6.4/Python-2.6.4.tar.bz2
$ tar jxf Python-2.6.4.tar.bz2
$ cp Python-2.6.4/Misc/RPM/python-2.6.spec ~/rpmbuild/SPECS/
$ cp Python-2.6.4.tar.bz2 ~/rpmbuild/SOURCES/</pre></div></div>

<p>This spec file is slightly broken and if you try building an RPM with it, it most likely is going to fail. So you need to patch it. The <a href="http://bugs.python.org/issue5063" target="_blank">proposed patch</a> has been submitted to python bug tracking system in the days of 2.6.1 release, but hasn&#8217;t yet been implemented. This patch doesn&#8217;t seem to work with 2.6.4 release and needs changing as well.</p>
<p>I have modified original 2.6.1 patch file slightly so that it can be used to build 2.6.4 Python RPM. You <a href="http://www.grenadepod.com/wp-content/uploads/python-2.6.4.spec.diff">download it</a> and apply to the original .spec:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">$ cd ~/rpmbuild/SPECS/
$ wget http://www.grenadepod.com/wp-content/uploads/python-2.6.4.spec.diff
$ patch python-2.6.spec python-2.6.4.spec.diff</pre></div></div>

<p>You should be OK to build the RPM now, but it&#8217;ll most likely fail with minor rpath-check errors, such as:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">ERROR   0001: file '/usr/lib/python2.6/lib-dynload/_bsddb.so' contains a standard rpath '/usr/lib' in [/usr/lib]
ERROR   0001: file '/usr/lib/python2.6/lib-dynload/_sqlite3.so' contains a standard rpath '/usr/lib' in [/usr/lib]</pre></div></div>

<p>Which indicates that some components are using hardcoded library paths. It&#8217;s not a big issue and can be ignored. Run build command as this:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">$ QA_RPATHS=$[ 0x0001|0x0010 ] rpmbuild -ba python-2.6.spec</pre></div></div>

<p>It should now build without any issues and the result is a set of python RPMs:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">$ QA_RPATHS=$[ 0x0001|0x0010 ] rpmbuild -ba python-2.6.spec
...
Wrote: /home/pulegium/rpmbuild/SRPMS/python2.6-2.6.4-1gpod.src.rpm
Wrote: /home/pulegium/rpmbuild/RPMS/i386/python2.6-2.6.4-1gpod.i386.rpm
Wrote: /home/pulegium/rpmbuild/RPMS/i386/python2.6-devel-2.6.4-1gpod.i386.rpm
Wrote: /home/pulegium/rpmbuild/RPMS/i386/python2.6-tkinter-2.6.4-1gpod.i386.rpm
Wrote: /home/pulegium/rpmbuild/RPMS/i386/python2.6-tools-2.6.4-1gpod.i386.rpm
Wrote: /home/pulegium/rpmbuild/RPMS/i386/python2.6-debuginfo-2.6.4-1gpod.i386.rpm
...
$</pre></div></div>

<p>This is it&#8230; You now have python RPMs that you can install on your CentOS 5.x server.</p>
<p>I&#8217;m planning to create my little own repository, where I&#8217;ll put this (and other) packages. For now, you can download <a href="http://www.grenadepod.com/wp-content/uploads/python2.6-2.6.4-1gpod.src.rpm">python 2.6.4 source RPM</a> if you want to change something in the spec file and rebuild it yourself.</p>


<p>Related posts:<ol><li><a href='http://www.grenadepod.com/2009/12/21/sorting-out-yum-repositories-on-centos-5-4/' rel='bookmark' title='Permanent Link: Sorting out YUM repositories on CentOS 5.4'>Sorting out YUM repositories on CentOS 5.4</a></li>
<li><a href='http://www.grenadepod.com/2009/11/23/use-ssh-to-upgrade-wordpress-plugins-automatically/' rel='bookmark' title='Permanent Link: Use SSH to upgrade WordPress plugins automatically'>Use SSH to upgrade WordPress plugins automatically</a></li>
<li><a href='http://www.grenadepod.com/2009/12/03/building-and-running-google-chrome-os-on-virtualbox/' rel='bookmark' title='Permanent Link: Building and running Google Chrome OS on VirtualBox'>Building and running Google Chrome OS on VirtualBox</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.grenadepod.com/2009/12/26/building-python-2-6-4-rpm-for-centos-5-4/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Sorting out YUM repositories on CentOS 5.4</title>
		<link>http://www.grenadepod.com/2009/12/21/sorting-out-yum-repositories-on-centos-5-4/</link>
		<comments>http://www.grenadepod.com/2009/12/21/sorting-out-yum-repositories-on-centos-5-4/#comments</comments>
		<pubDate>Mon, 21 Dec 2009 19:01:45 +0000</pubDate>
		<dc:creator>pulegium</dc:creator>
				<category><![CDATA[IT Technology]]></category>
		<category><![CDATA[System administration]]></category>
		<category><![CDATA[CentOS]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[system administration]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.grenadepod.com/?p=647</guid>
		<description><![CDATA[&#8230; or any other CentOS 5.X flavour for that matter. By default, freshly installed CentOS 5.X has the following Yum repositories enabled: addons CentOS-5 - Addons base CentOS-5 - Base extras CentOS-5 - Extras updates CentOS-5 - Updates These are all defined in /etc/yum.repos.d/CentOS-Base.repo configuration file. Repositories enabled by default provide you with the core [...]


Related posts:<ol><li><a href='http://www.grenadepod.com/2009/12/26/building-python-2-6-4-rpm-for-centos-5-4/' rel='bookmark' title='Permanent Link: Building python 2.6.4 RPM for CentOS 5.4'>Building python 2.6.4 RPM for CentOS 5.4</a></li>
<li><a href='http://www.grenadepod.com/2009/12/03/building-and-running-google-chrome-os-on-virtualbox/' rel='bookmark' title='Permanent Link: Building and running Google Chrome OS on VirtualBox'>Building and running Google Chrome OS on VirtualBox</a></li>
<li><a href='http://www.grenadepod.com/2009/11/23/use-ssh-to-upgrade-wordpress-plugins-automatically/' rel='bookmark' title='Permanent Link: Use SSH to upgrade WordPress plugins automatically'>Use SSH to upgrade WordPress plugins automatically</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p id="top" />&#8230; or any other CentOS 5.X flavour for that matter.</p>
<p>By default, freshly installed CentOS 5.X has the following Yum repositories enabled:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">addons                                             CentOS-5 - Addons
base                                               CentOS-5 - Base
extras                                             CentOS-5 - Extras
updates                                            CentOS-5 - Updates</pre></div></div>

<p>These are all defined in <em>/etc/yum.repos.d/CentOS-Base.repo</em> configuration file. Repositories enabled by default provide you with the core CentOS packages and updates for them. So you must have them enabled if you want your updates to work correctly. It is also important that these repositories take precedence over other repositories that you are going to use.</p>
<p>I will show later how to use Yum priorities package, just note that these are going to be priority one repositories</p>
<h3>Enable standard CentOS repositories</h3>
<p>There are two useful repositories defined in the configuration, but not enabled:</p>
<ul>
<li><strong>CentOS Plus</strong>. Packages in this repository contains upgraded versions of the software. If you enable this repository, after applying updates/upgrades your system will no longer be of the original version you have installed. Fear not though, all packages are tested by CentOS team and will no cause any issues. So unless you have really good reason to keep you installation at the same version level I&#8217;d recommend enabling this repository.</li>
<li><strong>Contrib</strong>. Packages supplied and maintained by CentOS users. These packages are not inspected by CentOS team, but they are not attempt to replace/modify core CentOS package set, so normally this repository should not cause any issues. Beware that some packages are not following mainstream CentOS very closely. I normally don&#8217;t have this enabled.</li>
</ul>
<p>These two repositories are going to get priority two setting. If you wish to enable them, edit default <em>/etc/yum.repos.d/CentOS-Base.repo</em> Yum repository configuration file and remove (or rather comment out) &#8220;<em>enabled=0</em>&#8221; line.</p>
<h3>Install and enable EPEL repository</h3>
<p>I must mention, that in this article I&#8217;m mostly talking about CentOS installation that is used for server environment. Therefore I&#8217;m not really interested in repositories that provide packages such as DVD or other multimedia decoders and players.</p>
<p>One of the most useful repositories for your server environment is <a href="http://fedoraproject.org/wiki/EPEL" target="_blank">EPEL repository</a> &#8211; Extra Packages for Enterprise Linux. This repository is maintained by Fedora project, and every effort is made to keep this repository as least  intrusive as possible, so in theory enabling and using this repository should not break or otherwise cause issues to your CentOS installation.</p>
<p>First of all, you need to install EPEL repository configuration files:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">[root@centos54 ~]# rpm -ihv http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-3.noarch.rpm
Retrieving http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-3.noarch.rpm
warning: /var/tmp/rpm-xfer.RT5AzP: Header V3 DSA signature: NOKEY, key ID 217521f6
Preparing...                ########################################### [100%]
   1:epel-release           ########################################### [100%]
[root@centos54 ~]#</pre></div></div>

<p>This provides you with two configuration files: base and testing. Don&#8217;t worry about testing one and leave it disabled.</p>
<p>Main configuration comes with three sections:</p>
<ul>
<li><strong>Base packages</strong>. This is enabled by default.</li>
<li><strong>Debug packages</strong>. Disabled, and no need to enable unless you want to use debug packages.</li>
<li><strong>Source packages</strong>. Disabled. Enable only if you want to be able to install source RPMs from EPEL. Useful if you want to rebuild them to your specific needs. I&#8217;d recommend to leave it disabled and enable on yum command line only when you really need to install source RPMs.</li>
</ul>
<p>These should be getting priority 3 setting.</p>
<h3>Set priorities for Yum repositories</h3>
<p>So if you enabled repositories from the previous section and installed EPEL repository configuration, here&#8217;s what you should see in you repositories list:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">addons                             CentOS-5 - Addons
base                               CentOS-5 - Base
centosplus                         CentOS-5 - Plus
epel                               Extra Packages for Enterprise Linux 5 - i386
extras                             CentOS-5 - Extras
updates                            CentOS-5 - Updates</pre></div></div>

<p>Now I need to set priorities for each repository. Install Yum priorities package:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;"># yum install yum-priorities</pre></div></div>

<p>Make sure new plugin is enabled:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">[root@centos54 ~]# cat /etc/yum/pluginconf.d/priorities.conf
[main]
enabled = 1
[root@centos54 ~]#</pre></div></div>

<p>Now you can set priorities for each repository. It&#8217;s done by adding &#8220;priority=X&#8221; for each repository section in repository configuration files. Here&#8217;s what I ended up with:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">[base]
...
priority=1
&nbsp;
[updates]
...
priority=1
&nbsp;
[addons]
...
priority=1
&nbsp;
[extras]
...
priority=1
&nbsp;
[centosplus]
...
priority=2
&nbsp;
[contrib]
...
priority=2
&nbsp;
[epel]
...
priority=3</pre></div></div>

<p>Now you should be good to do upgrades and install packages as you see fit for your system.</p>


<p>Related posts:<ol><li><a href='http://www.grenadepod.com/2009/12/26/building-python-2-6-4-rpm-for-centos-5-4/' rel='bookmark' title='Permanent Link: Building python 2.6.4 RPM for CentOS 5.4'>Building python 2.6.4 RPM for CentOS 5.4</a></li>
<li><a href='http://www.grenadepod.com/2009/12/03/building-and-running-google-chrome-os-on-virtualbox/' rel='bookmark' title='Permanent Link: Building and running Google Chrome OS on VirtualBox'>Building and running Google Chrome OS on VirtualBox</a></li>
<li><a href='http://www.grenadepod.com/2009/11/23/use-ssh-to-upgrade-wordpress-plugins-automatically/' rel='bookmark' title='Permanent Link: Use SSH to upgrade WordPress plugins automatically'>Use SSH to upgrade WordPress plugins automatically</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.grenadepod.com/2009/12/21/sorting-out-yum-repositories-on-centos-5-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python web crawler</title>
		<link>http://www.grenadepod.com/2009/12/13/python-web-crawler/</link>
		<comments>http://www.grenadepod.com/2009/12/13/python-web-crawler/#comments</comments>
		<pubDate>Sun, 13 Dec 2009 20:57:51 +0000</pubDate>
		<dc:creator>pulegium</dc:creator>
				<category><![CDATA[IT Technology]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.grenadepod.com/?p=633</guid>
		<description><![CDATA[For one of my (upcoming) projects I needed to write a simple webcrawler. Just as I always do, I searched Google (obviously), but couldn&#8217;t find anything simple enough. Or good enough for me for that matter. So spent an hr or so writing most simplistic webcrawler myself. Application logic is extremely simple: Retrieve specified page [...]


Related posts:<ol><li><a href='http://www.grenadepod.com/2009/11/10/changing-menu-order/' rel='bookmark' title='Permanent Link: Changing menu order'>Changing menu order</a></li>
<li><a href='http://www.grenadepod.com/2009/11/04/top-level-menu-in-arras-theme/' rel='bookmark' title='Permanent Link: Top level menu in Arras theme'>Top level menu in Arras theme</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p id="top" />For one of my (upcoming) projects I needed to write a simple webcrawler. Just as I always do, I searched Google (obviously), but couldn&#8217;t find anything simple enough. Or good enough for me for that matter. So spent an hr or so writing most simplistic webcrawler myself.</p>
<p>Application logic is extremely simple:</p>
<ul>
<li>Retrieve specified page</li>
<li>If cannot retrieve, try another from stored in the DB</li>
<li>Store all found URLs (&lt;a href&gt;) in the DB</li>
<li>Return one (and remove from DB)</li>
</ul>
<p>I store all pages in memory, but for more serious crawling, consider storing data on a physical file, that way it&#8217;ll be more memory efficient. Considering the size of the internets, even if you store only URL strings you will not last for very long&#8230;</p>
<p>Anyway, happy crawling! (and let me know if there are any issues, so far it worked fine for me)</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> BeautifulSoup <span style="color: #ff7700;font-weight:bold;">import</span> BeautifulSoup
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">urllib2</span>, <span style="color: #dc143c;">random</span>, <span style="color: #dc143c;">re</span>, sqlite3, <span style="color: #dc143c;">logging</span>
&nbsp;
DATABASE   = <span style="color: #483d8b;">':memory:'</span>
LOG_LEVEL  = <span style="color: #dc143c;">logging</span>.<span style="color: black;">INFO</span>
ABS_URL_RE = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'(?P&lt;url&gt;https?://.+?/)'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> WebCrawler:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, logging_level=LOG_LEVEL, database=DATABASE<span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">basicConfig</span><span style="color: black;">&#40;</span>level=logging_level<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">conn</span> = sqlite3.<span style="color: black;">connect</span><span style="color: black;">&#40;</span>database<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">conn</span>.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'create table url_stack (url text)'</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">conn</span>.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'create table url_visited (url text)'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _form_url<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, url, link<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> link<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span>:<span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'http'</span>:
            ret_url = link
        <span style="color: #ff7700;font-weight:bold;">elif</span> link<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'/'</span>:
            m = ABS_URL_RE.<span style="color: black;">search</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>
            ret_url = <span style="color: #483d8b;">&quot;%s%s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>m.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'url'</span><span style="color: black;">&#41;</span>, link<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            ret_url = <span style="color: #483d8b;">&quot;%s%s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>url, link<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> ret_url
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _pop_from_db<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Retrieving one URL from the DB...&quot;</span><span style="color: black;">&#41;</span>
        res = <span style="color: #008000;">self</span>.<span style="color: black;">conn</span>.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'select url from url_stack limit 1'</span><span style="color: black;">&#41;</span>.<span style="color: black;">fetchone</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Query result: %s&quot;</span>, res<span style="color: black;">&#41;</span>
        url = res<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">conn</span>.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;delete from url_stack where url = ?&quot;</span>, <span style="color: black;">&#40;</span>url,<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> url
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _push_to_db<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, url<span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Inserting record into DB...&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Check if it hasn't been visited yet&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">self</span>.<span style="color: black;">conn</span>.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'select url from url_visited where url=?'</span>, <span style="color: black;">&#40;</span>url,<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">fetchone</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
            <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;URL not found in list of visited URLs, inserting&quot;</span><span style="color: black;">&#41;</span>
            <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;URL to insert: %s&quot;</span> <span style="color: #66cc66;">%</span> url<span style="color: black;">&#41;</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">conn</span>.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'insert into url_stack values (?)'</span>, <span style="color: black;">&#40;</span>url,<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">conn</span>.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'insert into url_visited values (?)'</span>, <span style="color: black;">&#40;</span>url,<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;URL has already been visited or added for processing, skipping&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> crawl<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, url<span style="color: black;">&#41;</span>:
        work_url = url
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Work URL: %s&quot;</span> <span style="color: #66cc66;">%</span> work_url<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
            <span style="color: #ff7700;font-weight:bold;">try</span>:
                <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Trying to open and parse the URL...&quot;</span><span style="color: black;">&#41;</span>
                page = <span style="color: #dc143c;">urllib2</span>.<span style="color: black;">urlopen</span><span style="color: black;">&#40;</span>work_url<span style="color: black;">&#41;</span>
                soup = BeautifulSoup<span style="color: black;">&#40;</span>page<span style="color: black;">&#41;</span>
                <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Parsed successfuly&quot;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">except</span>:
                <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Failed to parse, attempting to get next URL from DB&quot;</span><span style="color: black;">&#41;</span>
                work_url = <span style="color: #008000;">self</span>._pop_from_db<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
                <span style="color: #ff7700;font-weight:bold;">continue</span>
            links = soup<span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: black;">&#41;</span>
            <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Found total of %d links (&lt;a href=...&gt;)&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>links<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">for</span> link <span style="color: #ff7700;font-weight:bold;">in</span> soup<span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: black;">&#41;</span>:
                <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Processing link object: %s&quot;</span> <span style="color: #66cc66;">%</span> link<span style="color: black;">&#41;</span>
                <span style="color: #ff7700;font-weight:bold;">try</span>:
                    <span style="color: #ff7700;font-weight:bold;">if</span> link<span style="color: black;">&#91;</span><span style="color: #483d8b;">'href'</span><span style="color: black;">&#93;</span> <span style="color: #66cc66;">!</span>= <span style="color: #483d8b;">''</span>:
                        <span style="color: #008000;">self</span>._push_to_db<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>._form_url<span style="color: black;">&#40;</span>work_url, link<span style="color: black;">&#91;</span><span style="color: #483d8b;">'href'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
                <span style="color: #ff7700;font-weight:bold;">except</span>:
                    <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;An exception has occured, this may be ok (href attribute may be missing)&quot;</span><span style="color: black;">&#41;</span>
                    <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;  ... but can also indicate error in insert code&quot;</span><span style="color: black;">&#41;</span>
            <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Finished adding URLs&quot;</span><span style="color: black;">&#41;</span>
            <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Getting a new URL for processing from DB&quot;</span><span style="color: black;">&#41;</span>
            work_url = <span style="color: #008000;">self</span>._pop_from_db<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #dc143c;">logging</span>.<span style="color: black;">info</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Found URL: %s&quot;</span> <span style="color: #66cc66;">%</span> work_url<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">yield</span> work_url
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    wc = WebCrawler<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> url <span style="color: #ff7700;font-weight:bold;">in</span> wc.<span style="color: black;">crawl</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://www.google.com/'</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span></pre></td></tr></table></div>

<p>As you can see it&#8217;s very easy to use. Effectively it is an infinite generator (well, depending what you pass as initial URL). It&#8217;s then up to you what you&#8217;re going to do with the resulting URL&#8230;</p>
<p>One thing to bear in mind when you use it: this crawler pays absolutely no attention to the domain it&#8217;s searching. It just blindly collects links, selects one and follows it. So depending on the site link relative location it may stay for a while on a site, or may just wonder away quite quickly.</p>
<p>I wanted to have something that does not stick around for long on one site, so this suits me well, if you want to have something more pedantic, you may want to modify the code, so that it leaves current domain only when it has visited all pages and there are no new pages within the domain to analyse.</p>


<p>Related posts:<ol><li><a href='http://www.grenadepod.com/2009/11/10/changing-menu-order/' rel='bookmark' title='Permanent Link: Changing menu order'>Changing menu order</a></li>
<li><a href='http://www.grenadepod.com/2009/11/04/top-level-menu-in-arras-theme/' rel='bookmark' title='Permanent Link: Top level menu in Arras theme'>Top level menu in Arras theme</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.grenadepod.com/2009/12/13/python-web-crawler/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building and running Google Chrome OS on VirtualBox</title>
		<link>http://www.grenadepod.com/2009/12/03/building-and-running-google-chrome-os-on-virtualbox/</link>
		<comments>http://www.grenadepod.com/2009/12/03/building-and-running-google-chrome-os-on-virtualbox/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 18:49:22 +0000</pubDate>
		<dc:creator>pulegium</dc:creator>
				<category><![CDATA[IT Technology]]></category>
		<category><![CDATA[System administration]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[system administration]]></category>

		<guid isPermaLink="false">http://www.grenadepod.com/?p=548</guid>
		<description><![CDATA[This is (sort of) hot topic on the internets at the moment. Google released their Linux based Chrome OS to the public. It&#8217;s still in beta and under development, but you can try it now. There are lots of manuals such as this one, that instruct how to run already built image using Sun VirtualBox. [...]


Related posts:<ol><li><a href='http://www.grenadepod.com/2009/12/21/sorting-out-yum-repositories-on-centos-5-4/' rel='bookmark' title='Permanent Link: Sorting out YUM repositories on CentOS 5.4'>Sorting out YUM repositories on CentOS 5.4</a></li>
<li><a href='http://www.grenadepod.com/2009/12/26/building-python-2-6-4-rpm-for-centos-5-4/' rel='bookmark' title='Permanent Link: Building python 2.6.4 RPM for CentOS 5.4'>Building python 2.6.4 RPM for CentOS 5.4</a></li>
<li><a href='http://www.grenadepod.com/2009/11/05/the-most-unusual-photocameras/' rel='bookmark' title='Permanent Link: The most unusual photocameras'>The most unusual photocameras</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p id="top" />This is (sort of) hot topic on the internets at the moment. Google released their Linux based <a href="http://www.chromium.org/chromium-os" target="_blank">Chrome OS</a> to the public. It&#8217;s still in beta and under development, but you can try it now. There are lots of manuals such as <a href="http://chromeos-blog.com/tutorial-chrome-os-virtualbox/" target="_blank">this one</a>, that instruct how to run already built image using Sun VirtualBox. But this is not fun, because:</p>
<ul>
<li>Insecure. Who knows who&#8217;s built the image and if they aren&#8217;t sending your Google login data to themselves when you login</li>
<li>You&#8217;re stuck with that particular release. As I said, it&#8217;s in development, so new features and bug fixes get introduced on a daily basis</li>
</ul>
<p>So I&#8217;ll show you how to (relatively) quickly build your very own Google Chrome OS. This instruction tells how to build Chromium OS with pre-built Chromium web browser. You will also need Sun <a href="http://www.virtualbox.org/" target="_blank">VirtualBox</a>.</p>
<p>In a nutshell:</p>
<ul>
<li>Install Ubuntu as a VirtualBox VM</li>
<li>Download ChromeOS sources</li>
<li>Build ChromeOS</li>
<li>Create VMWare image</li>
<li>Boot it in VirtualBox</li>
<li>Enjoy</li>
</ul>
<p>For the latest build release numbers check <a href="http://sites.google.com/a/chromium.org/dev/chromium-os/building-chromium-os/build-instructions" target="_blank">Chromium OS build page</a>.</p>
<h3>Preparation</h3>
<p><strong><em>Install Ubuntu</em></strong></p>
<p>Do the standard installation, as you would normally do. I selected all defaults, and allocated 20GB single partition for the installation and assigned 512MB RAM.</p>
<p><strong><em>Get OS source</em></strong></p>
<p>Download/unpack <a href="http://build.chromium.org/buildbot/archives/chromiumos-0.4.22.8.tar.gz" target="_blank">http://build.chromium.org/buildbot/archives/chromiumos-0.4.22.8.tar.gz</a> to <em>/home/user/chromiumos/</em></p>
<p><strong>NOTE!</strong> It seems that Google have removed OS tarballs and you now have to use <a href="http://sites.google.com/a/chromium.org/dev/chromium-os/building-chromium-os/getting-the-chromium-os-source-code" target="_blank">these instructions</a> to get the source code.</p>
<p><strong><em>Install some additional packages required to build ChromiumOS</em></strong></p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">$ sudo apt-get install subversion pkg-config python perl g++ g++-multilib \
bison flex gperf libnss3-dev libgtk2.0-dev libnspr4-0d libasound2-dev \
libnspr4-dev msttcorefonts libgconf2-dev libcairo2-dev libdbus-1-dev
$ sudo apt-get install wdiff lighttpd php5-cgi sun-java6-fonts</pre></div></div>

<h3>OS build</h3>
<p><strong><em>Building local repository</em></strong></p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">cd ~/chromiumos/src/scripts
./make_local_repo.sh</pre></div></div>

<p>Watch the output carefully and make sure it hasn&#8217;t failed with some errors!</p>
<p>Google says if the script fails, remove repo directory and call the script again. It hasn&#8217;t failed for me, so if you&#8217;ve done everything as per above you should be fine. I don&#8217;t really understand why calling the same script might make any difference…</p>
<p>This step is quite lengthy, so you might want to make yourself some coffee or tea. Or just take a short walk if the weather is good.</p>
<p><strong><em>Create build environment</em></strong></p>
<p>Another totally automated step. Just run</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">./make_chroot.sh</pre></div></div>

<p>Which creates chroot&#8217;ed build environment for you. This uses all packages you downloaded in the previous step. There are adoption how to pull required packages from the remote repositories (Google and official Ubuntu), but I advise to take an easy way and download all packages first and build locally.</p>
<p><strong><em>Get Chromium binary</em></strong></p>
<p>make the following directory:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">mkdir -p ~/chromiumos/src/build/x86/local_assets</pre></div></div>

<p>And download chromium package from Google:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">wget -O ~/chromiumos/src/build/x86/local_assets/chrome-chromeos.zip \
http://build.chromium.org/buildbot/archives/chromium-chromiumos-r32516.zip</pre></div></div>

<p><strong><em>Building OS</em></strong></p>
<p>First you need to enter you chroot&#8217;ed build environment. Use the following command:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">./enter_chroot.sh</pre></div></div>

<p>I also recommend generating password for shared user, so that you can sudo from the terminal:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">./set_shared_user_password.sh</pre></div></div>

<p>And finally build all packages:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">./build_all.sh</pre></div></div>

<p>At this point, go and make some more tea or coffee. Which I wouldn&#8217;t recommend, though. Simply because you will have trouble getting asleep. Because sleeping is the most sane thing you might want to do at this moment. Building OS packages takes ages!…</p>
<p>But seriously, it&#8217;s not that bad, it took about an hour and a half on my Ubuntu VM to build it.</p>
<p><strong>Make VM image and boot it in VirtualBox</strong></p>
<p><strong><em>Build bootable image</em></strong></p>
<p>Once all packages have been built, you need to create OS image to boot from. Image build process creates two artefacts:<br />
- Master boot record (mbr.image)<br />
- Root FileSystem (rootfs.image)</p>
<pre style="font: normal normal normal 12px/18px Consolas, Monaco, 'Courier New', Courier, monospace;" lang="shell">./build_image.sh</pre>
<p>Once the image files have been creates, the script will tell you where to find them. It is going to be in ~/chromiumos/src/build/images//</p>
<p>Here&#8217;s what you will have once the image build is done:</p>
<pre style="font: normal normal normal 12px/18px Consolas, Monaco, 'Courier New', Courier, monospace;" lang="shell">pulegium@ubuntu:~/chromiumos/src/build/images/999.999.33509.212332-a1$ ls -lh
total 729M
-rw-r--r--  1 pulegium 5000  512 2009-12-01 21:34 mbr.image
-rw-r--r--  1 root     root  40K 2009-12-01 21:31 package_list_installed.txt
-rw-r--r--  1 root     root  40K 2009-12-01 21:34 package_list_pruned.txt
drwxr-xr-x 22 root     root 4.0K 2009-12-01 21:29 rootfs
-rw-r--r--  1 pulegium 5000 950M 2009-12-01 21:23 rootfs.image</pre>
<div>Exit Chroot environment and run <em>image_to_vmware.sh</em> script which will create you a VM image. The script will tell you where the image is stored. Copy it to your VirtualBox machine. Mine was called <em>ide.vmdk<span style="font-style: normal;">.</span></em></div>
<div><strong><em>Attach image as VirtualBox VM disk</em></strong></div>
<div>Best to show where to click&#8230; So fire up VirtualBox and start creating new VM.</div>
<div>
<dl id="attachment_555" class="wp-caption aligncenter" style="width: 310px;">
<dt class="wp-caption-dt"><img class="size-medium wp-image-555" title="ChromeOS-1" src="http://www.grenadepod.com/wp-content/uploads/2009/12/ChromeOS-1-300x261.png" alt="Creating New VM for Chrome OS" width="300" height="261" /></dt>
<dd class="wp-caption-dd">Creating New VM for Chrome OS</dd>
</dl>
</div>
<div>Then when prompted tell that you are going to use your own disk image.</div>
<div>
<div id="attachment_556" class="wp-caption aligncenter" style="width: 310px"><img class="size-medium wp-image-556" title="ChromeOS-2" src="http://www.grenadepod.com/wp-content/uploads/2009/12/ChromeOS-2-300x261.png" alt="Tell VirtualBox to use existing image" width="300" height="261" /><p class="wp-caption-text">Tell VirtualBox to use existing image</p></div>
</div>
<div>Add new image&#8230;</div>
<div>
<div id="attachment_557" class="wp-caption aligncenter" style="width: 310px"><img class="size-medium wp-image-557" title="ChromeOS-3" src="http://www.grenadepod.com/wp-content/uploads/2009/12/ChromeOS-3-300x267.png" alt="Add new image" width="300" height="267" /><p class="wp-caption-text">Add new image</p></div>
</div>
<div>And voila!</div>
<div>
<div id="attachment_558" class="wp-caption aligncenter" style="width: 310px"><img class="size-medium wp-image-558" title="ChromeOS-4" src="http://www.grenadepod.com/wp-content/uploads/2009/12/ChromeOS-4-300x267.png" alt="Image added" width="300" height="267" /><p class="wp-caption-text">Image added</p></div>
</div>
<div><strong><em>Enjoy Chrome OS</em></strong></div>
<div>This is it, you&#8217;re ready to explore the new flashy OS&#8230; Enjoy!</div>
<div>
<dl id="attachment_559" class="wp-caption aligncenter" style="width: 310px;">
<dt class="wp-caption-dt"><img class="size-medium wp-image-559" title="ChromeOS-5" src="http://www.grenadepod.com/wp-content/uploads/2009/12/ChromeOS-5-300x243.png" alt="Chrome OS login screen" width="300" height="243" /></dt>
<dd class="wp-caption-dd">Chrome OS login screen</dd>
</dl>
</div>
<div id="attachment_560" class="wp-caption aligncenter" style="width: 310px"><img class="size-medium wp-image-560 " title="ChromeOS-6" src="http://www.grenadepod.com/wp-content/uploads/2009/12/ChromeOS-6-300x245.png" alt="Selection of preinstalled application. All web based and ready to go. Make sure you have connection to the internet. Chrome OS bit dull and TBH useless without internet..." width="300" height="245" /><p class="wp-caption-text">Selection of preinstalled application. All web based and ready to go. Make sure you have connection to the internet. Chrome OS bit dull and TBH useless without internet...</p></div>
<div>
<div id="attachment_561" class="wp-caption aligncenter" style="width: 310px"><img class="size-medium wp-image-561" title="ChromeOS-7" src="http://www.grenadepod.com/wp-content/uploads/2009/12/ChromeOS-7-300x245.png" alt="In general I think Chrome OS looks OK'ish, but this menu smells of M$ Windows..." width="300" height="245" /><p class="wp-caption-text">In general I think Chrome OS looks OK&#39;ish, but this menu smells of M$ Windows...</p></div>
</div>


<p>Related posts:<ol><li><a href='http://www.grenadepod.com/2009/12/21/sorting-out-yum-repositories-on-centos-5-4/' rel='bookmark' title='Permanent Link: Sorting out YUM repositories on CentOS 5.4'>Sorting out YUM repositories on CentOS 5.4</a></li>
<li><a href='http://www.grenadepod.com/2009/12/26/building-python-2-6-4-rpm-for-centos-5-4/' rel='bookmark' title='Permanent Link: Building python 2.6.4 RPM for CentOS 5.4'>Building python 2.6.4 RPM for CentOS 5.4</a></li>
<li><a href='http://www.grenadepod.com/2009/11/05/the-most-unusual-photocameras/' rel='bookmark' title='Permanent Link: The most unusual photocameras'>The most unusual photocameras</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.grenadepod.com/2009/12/03/building-and-running-google-chrome-os-on-virtualbox/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Basic Apache security</title>
		<link>http://www.grenadepod.com/2009/11/25/basic-apache-security/</link>
		<comments>http://www.grenadepod.com/2009/11/25/basic-apache-security/#comments</comments>
		<pubDate>Wed, 25 Nov 2009 13:44:38 +0000</pubDate>
		<dc:creator>pulegium</dc:creator>
				<category><![CDATA[IT Technology]]></category>
		<category><![CDATA[System administration]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[system administration]]></category>

		<guid isPermaLink="false">http://www.grenadepod.com/?p=520</guid>
		<description><![CDATA[Below are just a few things to consider if you want to make your Apache installation more secure: Hide your identity Well, first of all you need to hide details about who you are, or rather what your webserver is. It is a good practice to always run on the latest security patch, but not [...]


Related posts:<ol><li><a href='http://www.grenadepod.com/2009/11/21/securing-wordpress/' rel='bookmark' title='Permanent Link: Securing WordPress'>Securing WordPress</a></li>
<li><a href='http://www.grenadepod.com/2009/11/22/using-openid-for-authentication-in-django/' rel='bookmark' title='Permanent Link: Using OpenID for authentication in Django'>Using OpenID for authentication in Django</a></li>
<li><a href='http://www.grenadepod.com/2009/11/23/use-ssh-to-upgrade-wordpress-plugins-automatically/' rel='bookmark' title='Permanent Link: Use SSH to upgrade WordPress plugins automatically'>Use SSH to upgrade WordPress plugins automatically</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p id="top" />Below are just a few things to consider if you want to make your Apache installation more secure:</p>
<h3>Hide your identity</h3>
<p>Well, first of all you need to hide details about who you are, or rather what your webserver is. It is a good practice to always run on the latest security patch, but not always feasible. So if you can&#8217;t upgrade in time, at least make attackers life harder by hiding details about your server:</p>
<pre>#
# ServerTokens
# This directive configures what you return as the Server HTTP response
# Header. The default is 'Full' which sends information about the OS-Type
# and compiled in modules.
# Set to one of:  Full | OS | Minor | Minimal | Major | Prod
# where Full conveys the most information, and Prod the least.
#
ServerTokens Prod

#
# Optionally add a line containing the server version and virtual host
# name to server-generated pages (internal error documents, FTP directory
# listings, mod_status and mod_info output etc., but not CGI generated
# documents or custom error documents).
# Set to "EMail" to also include a mailto: link to the ServerAdmin.
# Set to one of:  On | Off | EMail
#
ServerSignature Off</pre>
<h3>Allow only basic HTTP methods</h3>
<p>HTTP protocol defines GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE and CONNECT methods. Guess how many of those are actually used (intensively). Yup, only two. Most of the webservers would do just fine with only GET and POST methods. You might however find that you need more, so enable them as you see fit. In the example below I only allow two basic, commonly used methods:</p>
<pre>&lt;Location /&gt;
   &lt;LimitExcept GET POST&gt;
     Order allow,deny
     Deny from all
   &lt;/LimitExcept&gt;
 &lt;/Location&gt;</pre>
<h3>Disable old and insecure SSL</h3>
<p>Use only new protocols and only strong ciphers.</p>
<pre>SSLProtocol -ALL +SSLv3 +TLSv1
SSLCipherSuite ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM</pre>
<h3>Disable modules that you don&#8217;t need</h3>
<p>Again, this depends on your installation and what you&#8217;re actually using, but in most of the cases most of the modules that Apache loads by default are not needed. Search for LoadModule instruction and remove anything you don&#8217;t need. Good list to start:</p>
<ul>
<li>mod_imap</li>
<li>mod_include</li>
<li>mod_info</li>
<li>mod_userdir</li>
<li>mod_status</li>
<li>mod_cgi</li>
<li>mod_autoindex</li>
<li>mod_dav</li>
</ul>
<h3>Other settings</h3>
<p>Reduce timeout, which is 300 seconds by default. Meaning that the server waits for 5 minutes before it decides that the client is no longer there. Reduce it to something sensible, like 20-30 seconds to avoid potential DDoS attacks.</p>
<pre>Timeout 20</pre>
<p>Disable directory browsing for any directory that has no index file:</p>
<pre>Options -Indexes</pre>


<p>Related posts:<ol><li><a href='http://www.grenadepod.com/2009/11/21/securing-wordpress/' rel='bookmark' title='Permanent Link: Securing WordPress'>Securing WordPress</a></li>
<li><a href='http://www.grenadepod.com/2009/11/22/using-openid-for-authentication-in-django/' rel='bookmark' title='Permanent Link: Using OpenID for authentication in Django'>Using OpenID for authentication in Django</a></li>
<li><a href='http://www.grenadepod.com/2009/11/23/use-ssh-to-upgrade-wordpress-plugins-automatically/' rel='bookmark' title='Permanent Link: Use SSH to upgrade WordPress plugins automatically'>Use SSH to upgrade WordPress plugins automatically</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.grenadepod.com/2009/11/25/basic-apache-security/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Use SSH to upgrade WordPress plugins automatically</title>
		<link>http://www.grenadepod.com/2009/11/23/use-ssh-to-upgrade-wordpress-plugins-automatically/</link>
		<comments>http://www.grenadepod.com/2009/11/23/use-ssh-to-upgrade-wordpress-plugins-automatically/#comments</comments>
		<pubDate>Mon, 23 Nov 2009 12:23:46 +0000</pubDate>
		<dc:creator>pulegium</dc:creator>
				<category><![CDATA[IT Technology]]></category>
		<category><![CDATA[Publishing]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[system administration]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.grenadepod.com/?p=479</guid>
		<description><![CDATA[Here&#8217;s a quick summary on how to enable WordPress updates using SSH. For one or the other reason default FTP/SFTP method didn&#8217;t work for me, so I tried this, which seems to be working fine. Build and install SSH2 libraries Depending on your linux distribution you might need to use different method. On my Debian, [...]


Related posts:<ol><li><a href='http://www.grenadepod.com/2009/11/21/securing-wordpress/' rel='bookmark' title='Permanent Link: Securing WordPress'>Securing WordPress</a></li>
<li><a href='http://www.grenadepod.com/2009/12/26/building-python-2-6-4-rpm-for-centos-5-4/' rel='bookmark' title='Permanent Link: Building python 2.6.4 RPM for CentOS 5.4'>Building python 2.6.4 RPM for CentOS 5.4</a></li>
<li><a href='http://www.grenadepod.com/2009/12/03/building-and-running-google-chrome-os-on-virtualbox/' rel='bookmark' title='Permanent Link: Building and running Google Chrome OS on VirtualBox'>Building and running Google Chrome OS on VirtualBox</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p id="top" />Here&#8217;s a quick summary on how to enable WordPress updates using SSH. For one or the other reason default FTP/SFTP method didn&#8217;t work for me, so I tried this, which seems to be working fine.</p>
<h3>Build and install SSH2 libraries</h3>
<p>Depending on your linux distribution you might need to use different method. On my Debian, I had to use the following to install:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">#  wget http://downloads.sourceforge.net/project/libssh2/libssh2-1.2.1.tar.gz?use_mirror=kent
#  tar zxf libssh2-1.2.1.tar.gz
#  cd libssh2-1.2.1
#  ./configure
#  make
#  make install</pre></div></div>

<p>What&#8217;s important here is that I had to build libssh2 from sources manually. However I hate doing this, it was apparently the only way. Aptitude was only offering me an older (0.12) version of the library, which failed to build PHP ssh2 extension.</p>
<h3>Build and install PHP SSH2 extension</h3>
<p>Now again, for some reason simple command failed to work for me&#8230; So I had to specify beta channel to install PHP SSH2 extension. Fear not though, just try this</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">#  pecl install ssh2</pre></div></div>

<p>And if it doesn&#8217;t work, then do this</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">#  pecl install channel://pecl.php.net/ssh2-0.11.0</pre></div></div>

<p>Simple, isn&#8217;t it?</p>
<h3>Generate SSH public and private keys</h3>
<p>You need to generate both public and private keys that are going to be used to connect to your server (even if it is the same server your connecting from!). Go to your home directory:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">$ cd .ssh
$ ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/user/.ssh/id_rsa.
Your public key has been saved in /home/user/.ssh/id_rsa.pub.
The key fingerprint is:
fe:3b:5d:94:53:1e:d3:9f:87:45:73:ab:8d:9f:d7:cc user@server
$ cp id_rsa.pub authorized_keys</pre></div></div>

<p>Private key is used to decrypt the data, whereas public key is used by the remote host to encrypt the data. You also need to create authorized_keys file, so that server knows your key is trusted and allows you to login without using actual user account password.</p>
<p>There is one annoying bit though. Apache user needs to be able to read both private and public keys. Normally they are kept secure in user&#8217;s .ssh/ directory, which is readable by user only, and allowing all to see it, is not a particularly good idea. So I had to copy both files to /etc/wordpress/ and make them readable to www-data group:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">#  cd /etc
#  mkdir wordpress
#  cp /home/user/.ssh/id_rsa* wordpress/
#  chgrp www-data wordpress/*
#  chmod 640 wordpress/*</pre></div></div>

<h3>Configure WordPress to use public keys automatically</h3>
<p>Add the following lines to your wp-config.php file, so you&#8217;re not asked any passwords or server names during the upgrade:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'FTP_PUBKEY'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'/etc/wordpress/id_rsa.pub'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'FTP_PRIKEY'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'/etc/wordpress/id_rsa'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'FTP_USER'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'user'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'FTP_PASS'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'FTP_HOST'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'localhost:22'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>



<p>Related posts:<ol><li><a href='http://www.grenadepod.com/2009/11/21/securing-wordpress/' rel='bookmark' title='Permanent Link: Securing WordPress'>Securing WordPress</a></li>
<li><a href='http://www.grenadepod.com/2009/12/26/building-python-2-6-4-rpm-for-centos-5-4/' rel='bookmark' title='Permanent Link: Building python 2.6.4 RPM for CentOS 5.4'>Building python 2.6.4 RPM for CentOS 5.4</a></li>
<li><a href='http://www.grenadepod.com/2009/12/03/building-and-running-google-chrome-os-on-virtualbox/' rel='bookmark' title='Permanent Link: Building and running Google Chrome OS on VirtualBox'>Building and running Google Chrome OS on VirtualBox</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.grenadepod.com/2009/11/23/use-ssh-to-upgrade-wordpress-plugins-automatically/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using OpenID for authentication in Django</title>
		<link>http://www.grenadepod.com/2009/11/22/using-openid-for-authentication-in-django/</link>
		<comments>http://www.grenadepod.com/2009/11/22/using-openid-for-authentication-in-django/#comments</comments>
		<pubDate>Sun, 22 Nov 2009 18:03:51 +0000</pubDate>
		<dc:creator>pulegium</dc:creator>
				<category><![CDATA[IT Technology]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[openid]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.grenadepod.com/?p=446</guid>
		<description><![CDATA[Tired of memorising login details for million different websites? Wanted to download or check somethning, but been prompted to created a user account on some random website? We&#8217;ve all been in this situation. And for me personally, I would steer away from the site that forces me to register just to see some part of [...]


Related posts:<ol><li><a href='http://www.grenadepod.com/2009/12/13/python-web-crawler/' rel='bookmark' title='Permanent Link: Python web crawler'>Python web crawler</a></li>
<li><a href='http://www.grenadepod.com/2009/11/09/how-to-use-generic-views-in-django/' rel='bookmark' title='Permanent Link: How to use generic views in Django'>How to use generic views in Django</a></li>
<li><a href='http://www.grenadepod.com/2009/12/03/building-and-running-google-chrome-os-on-virtualbox/' rel='bookmark' title='Permanent Link: Building and running Google Chrome OS on VirtualBox'>Building and running Google Chrome OS on VirtualBox</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p id="top" />Tired of memorising login details for million different websites? Wanted to download or check somethning, but been prompted to created a user account on some random website?</p>
<p>We&#8217;ve all been in this situation. And for me personally, I would steer away from the site that forces me to register just to see some part of forum or similar. Mostly this is because I don&#8217;t want to provide my details and follow lengthy registration process.</p>
<p>I don&#8217;t mind to have an account (even though I forget about the website next day), but the whole process of typing in all the stuff, deciphering captcha images, logging in to my email account just to confirm registration, etc, etc. Why don&#8217;t they use OpenId? These days if you have Yahoo or Gmail account (and just who doesn&#8217;t?) you can use them to login to all websites that support OpenId.</p>
<p>In a nutshell, OpenId is a decentralised authentication standard. User (U) who has an OpenId account with a trusted company (C) wants to login to a website (W). W prompts with a login screen. U enters his/her OpenId URL (no personal information here provided at all). W then redirects to C login screen, where U is prompted to allow access to some parts of the information (usually it&#8217;s username only, sometimes email). If U is happy to provide this information, he then clicks login button and information is passed back to W. In this scenario, W will never get any personal information about U without explicit permission. And U benefits from having only one login that works for all websites.</p>
<p>Below is a simple diagram that shows how authentication is done when using OpenId to login to the websites:</p>
<div id="attachment_476" class="wp-caption aligncenter" style="width: 476px"><img class="size-full wp-image-476" title="OID identification" src="http://www.grenadepod.com/wp-content/uploads/2009/11/OID-identification.jpg" alt="Authentication with OpenID flow" width="466" height="317" /><p class="wp-caption-text">Authentication with OpenID flow</p></div>
<p>Unfortunately Django does not have native support for OpenId, and their website recommends using <a href="http://bitbucket.org/benoitc/django-authopenid/wiki/Home" target="_blank">django-authopenid</a> library to perform authentication and login using OpenId.</p>
<h3>Install required libraries</h3>
<p>You need to install <a href="http://openidenabled.com/python-openid/" target="_blank">python-openid</a> library first. Installation is a breeze, however there seems to be some issues with internal version number in the package, but let&#8217;s assume it&#8217;s all fine:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;"># easy_install python-openid
Searching for python-openid
Reading http://pypi.python.org/simple/python-openid/
Reading http://openidenabled.com/python-openid/
Reading http://www.openidenabled.com/openid/libraries/python/
Best match: python-openid 2.2.4
Downloading http://openidenabled.com/files/python-openid/packages/python-openid-2.2.4.zip
Processing python-openid-2.2.4.zip
Running python-openid-2.2.4/setup.py -q bdist_egg --dist-dir /tmp/easy_install-Xyxx61/python-openid-2.2.4/egg-dist-tmp-oexXVf
zip_safe flag not set; analyzing archive contents...
Adding python-openid 2.2.4 to easy-install.pth file
&nbsp;
Installed /usr/lib/python2.5/site-packages/python_openid-2.2.4-py2.5.egg
Processing dependencies for python-openid
Finished processing dependencies for python-openid
# python
Python 2.5.1 (r251:54863, Jul 31 2008, 23:17:43)
[GCC 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)] on linux2
Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.
&amp;gt;&amp;gt;&amp;gt; openid.__version__
'2.2.1'
&amp;gt;&amp;gt;&amp;gt; openid.__path__
['/usr/lib/python2.5/site-packages/python_openid-2.2.4-py2.5.egg/openid']
&amp;gt;&amp;gt;&amp;gt; openid.version_info
(2, 2, 1)
&amp;gt;&amp;gt;&amp;gt;</pre></div></div>

<p>Then install django-authopenid. Installation seems to spit out some errors, but I guess these can be ignored as they don&#8217;t seem to cause any issues:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;"># easy_install django-authopenid
Searching for django-authopenid
Reading http://pypi.python.org/simple/django-authopenid/
Reading http://hg.e-engura.org/django-authopenid/
Reading http://code.google.com/p/django-authopenid/
Best match: django-authopenid 1.0.1
Downloading http://pypi.python.org/packages/source/d/django-authopenid/django-authopenid-1.0.1.tar.gz#md5=93d44b4ce40de55bed36c9ed292adb49
Processing django-authopenid-1.0.1.tar.gz
Running django-authopenid-1.0.1/setup.py -q bdist_egg --dist-dir /tmp/easy_install-UtVC7d/django-authopenid-1.0.1/egg-dist-tmp-oWjnYf
warning: no files found matching 'CHANGES.MD'
Sorry: TypeError: ('compile() expected string without null bytes',)
...
Adding django-authopenid 1.0.1 to easy-install.pth file
&nbsp;
Installed /usr/lib/python2.5/site-packages/django_authopenid-1.0.1-py2.5.egg
Processing dependencies for django-authopenid
Finished processing dependencies for django-authopenid</pre></div></div>

<h3>Prepare Django application environment</h3>
<p>There are several things you&#8217;d need to do:</p>
<ol>
<li>Create directory for application files</li>
<p>I will use /var/app/application/ in this example</p>
<li>Create directory for static content such as JS, CSS, HTML and images</li>
<p>I will use /var/www/application/ in this example</p>
<li>If you are using Apache web server add Virtual host definition and specify where web root is and when to pass control to mod_python module (note that all requests that do not start with /static/ will be passed to Django):</li>
<pre>    ServerName test.example.com
    DocumentRoot /var/www/application/
    ErrorLog /var/log/apache2/application-error.log
    CustomLog /var/log/apache2/application-access.log combined
    SetHandler mod_python
    PythonHandler django.core.handlers.modpython
    PythonPath sys.path+['/var/app/']
    SetEnv DJANGO_SETTINGS_MODULE application.settings
    SetEnv PYTHON_EGG_CACHE /tmp
    &lt;Location "/static/"&gt;
        SetHandler None
    &lt;/Location&gt;</pre>
<li>Also create database and configure appropriately in settings.py.</li>
<li>Enable administration application for Django</li>
</ol>
<h3 style="font-size: 1.17em;">Enable OpenID support</h3>
<p>These were the basic steps to get your Django environment set-up, now let&#8217;s enable OpenID module:</p>
<ol>
<li>In settings.py add OpenID middleware, application and also tell Django where to find templates</li>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">MIDDLEWARE_CLASSES = <span style="color: black;">&#40;</span>
    ...
    <span style="color: #483d8b;">'django_authopenid.middleware.OpenIDMiddleware'</span>,
<span style="color: black;">&#41;</span>
INSTALLED_APPS = <span style="color: black;">&#40;</span>
    ...
    <span style="color: #483d8b;">'django_authopenid'</span>,
    <span style="color: #483d8b;">'registration'</span>,
<span style="color: black;">&#41;</span>
LOGIN_URL = <span style="color: #483d8b;">&quot;/account/signin/&quot;</span>
TEMPLATE_DIRS = <span style="color: black;">&#40;</span>
    ...
    <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span>__file__<span style="color: black;">&#41;</span>, <span style="color: #483d8b;">'templates'</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#41;</span></pre></div></div>

<li>In urls.py just include urls from django_authopenid package:</li>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">urlpatterns = patterns<span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>,
    ...
    <span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^account/'</span>, include<span style="color: black;">&#40;</span><span style="color: #483d8b;">'django_authopenid.urls'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>,
<span style="color: black;">&#41;</span></pre></div></div>

<li>Add the following context processors list (majority is what&#8217;s loaded by default anyway, you just need to add one line, but since it&#8217;s a tuple, you cannot modify it, so you must redefine it):

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">TEMPLATE_CONTEXT_PROCESSORS = <span style="color: black;">&#40;</span>
   <span style="color: #483d8b;">'django.core.context_processors.auth'</span>,
   <span style="color: #483d8b;">'django.core.context_processors.debug'</span>,
   <span style="color: #483d8b;">'django.core.context_processors.i18n'</span>,
   <span style="color: #483d8b;">'django.core.context_processors.media'</span>,
   <span style="color: #483d8b;">'django.core.context_processors.request'</span>,
   <span style="color: #483d8b;">'django_authopenid.context_processors.authopenid'</span>,
<span style="color: black;">&#41;</span></pre></div></div>

</li>
<li>Copy templates from the examples folder. Of course you&#8217;ll want them eventually to be fully integrated with your site, so that they match styles or even be incorporated in other pages, but for now, let&#8217;s just use the ones provided with the package. Location of the example templates obviously depends on your Linux distribution. On my Debian installation it was in /usr/lib/python2.5/site-packages/django_authopenid-1.0.1-py2.5.egg/example/templates. Copy examples/ directory to your Django application directory.</li>
</ol>
<h3>Test it</h3>
<p>Once you&#8217;re done, test it. Navigate to http:///account/signin/ and if you followed this manual you should see something like this:</p>
<div id="attachment_474" class="wp-caption aligncenter" style="width: 310px"><img class="size-medium wp-image-474" title="openid-login" src="http://www.grenadepod.com/wp-content/uploads/2009/11/openid-login-300x162.png" alt="Django authopenid login screen" width="300" height="162" /><p class="wp-caption-text">Django authopenid login screen</p></div>
<p>You may wonder what the login prompt on the left side is doing there. This is because Django authopenId logoc is to associate your OpenId account with local account and use standard Django &#8220;registration&#8221; middleware classes to handle all user management functions. If user does not exist &#8211; after you have selected your OpenID URL you will be asked to provide local username. You don&#8217;t need to memorise nor use it &#8211; it&#8217;s just to allow authopenId create association.</p>
<p>This may feel bit unintuitive, and I don&#8217;t particularly like this. I&#8217;m going to make some changes so that internal association is hidden from the end user and happens behind the scenes. This way my users are going to see only OpenId selector and login screen.</p>


<p>Related posts:<ol><li><a href='http://www.grenadepod.com/2009/12/13/python-web-crawler/' rel='bookmark' title='Permanent Link: Python web crawler'>Python web crawler</a></li>
<li><a href='http://www.grenadepod.com/2009/11/09/how-to-use-generic-views-in-django/' rel='bookmark' title='Permanent Link: How to use generic views in Django'>How to use generic views in Django</a></li>
<li><a href='http://www.grenadepod.com/2009/12/03/building-and-running-google-chrome-os-on-virtualbox/' rel='bookmark' title='Permanent Link: Building and running Google Chrome OS on VirtualBox'>Building and running Google Chrome OS on VirtualBox</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.grenadepod.com/2009/11/22/using-openid-for-authentication-in-django/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Securing WordPress</title>
		<link>http://www.grenadepod.com/2009/11/21/securing-wordpress/</link>
		<comments>http://www.grenadepod.com/2009/11/21/securing-wordpress/#comments</comments>
		<pubDate>Sat, 21 Nov 2009 10:15:08 +0000</pubDate>
		<dc:creator>pulegium</dc:creator>
				<category><![CDATA[IT Technology]]></category>
		<category><![CDATA[Publishing]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[system administration]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.grenadepod.com/?p=457</guid>
		<description><![CDATA[No matter how good developers are (and I trust WordPress developers are one of the best bunch out there) they are still humans and make mistakes. When it comes to a security, one doesn&#8217;t need to make mistakes or introduce bugs in the code to make software or application vulnerable to external attacks. Software development [...]


Related posts:<ol><li><a href='http://www.grenadepod.com/2009/11/23/use-ssh-to-upgrade-wordpress-plugins-automatically/' rel='bookmark' title='Permanent Link: Use SSH to upgrade WordPress plugins automatically'>Use SSH to upgrade WordPress plugins automatically</a></li>
<li><a href='http://www.grenadepod.com/2009/11/25/basic-apache-security/' rel='bookmark' title='Permanent Link: Basic Apache security'>Basic Apache security</a></li>
<li><a href='http://www.grenadepod.com/2009/11/06/essential-wordpress-plugins/' rel='bookmark' title='Permanent Link: Essential WordPress plugins'>Essential WordPress plugins</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p id="top" />No matter how good developers are (and I trust WordPress developers are one of the best bunch out there) they are still humans and make mistakes. When it comes to a security, one doesn&#8217;t need to make mistakes or introduce bugs in the code to make software or application vulnerable to external attacks.</p>
<p>Software development is really complex process and although  WordPress developers take security very seriously, you should also take extra measures to ensure safety and security of your blog/web site.</p>
<p>There are few simple steps to make your WordPress installation lot harder for attacker to compromise.</p>
<h3>WordPress software</h3>
<p>Always keep up to date. Flaws in security model are being identified and addressed immediately as soon as they are reported. So it&#8217;s important for you to always keep your WordPress installation up to date. It&#8217;s very easy to do now that WordPress has automatic update feature, where all you have to do is just to tell it to install the newer version of it.</p>
<h3>File permissions</h3>
<p>You need to make sure that webserver can modify only those files that it is allowed to. Do not rely on WordPress to enforce this, use file system permission model. All files in WordPress installation need to be owned and writeable to by the user that installed the system and not the user which is used to run webserver. Only exceprion to this is /wp-content/ directory, which contains uploaded contents.</p>
<blockquote><p>Make sure you perform all actions in whatever your WordPress installation directory is, and not outside of it!</p></blockquote>
<p>Let&#8217;s make all files owned by your user and set the group to web server group:</p>
<pre>
$ sudo chown -R myuser.www-data *
</pre>
<p>Then change all file permissions so that files can be written to by your user only, and read-only by other users:</p>
<pre>
$ find . -type d -exec chmod 755 {} \;
$ find . -type f -exec chmod 644 {} \;
</pre>
<p>Finally allow group write for wp-content/ directory, so that web server can do automatic updates for plugins and user content could be uploaded:</p>
<pre>
$ chmod -R g+w *
</pre>
<h3>Secure wp-admin access</h3>
<p>WordPress recommend using additional plugins and HTTP authentication to provide additional security to the administration pages, but I think this is not necessary if you implement the following two security measures: enforce SSL only traffic to /wp-admin/ and allow access only from certain IP addresses.</p>
<p>Make /wp-admin/ available on SSL connection only, so all traffic to and from (including passwords) is encrypted. This prevent attackers hijacking traffic and intercepting passwords and other sensitive data.</p>
<p>This may sound bit complicated, but bear with me, it&#8217;s not that scary as it may look like. So you will need two &lt;VirtualServer&gt; directives: one for normal web traffic and one for SSL.</p>
<p>In default HTTP definition, you then need to make a special case for /wp-admin/ URL, and enforce redirection to HTTPS, so whenever you try to access wp-admin/ using http:// you will be redirected to https:// instead. HTTPS VirtualHost on it turn has instructions to deny access from all, but only the IPs listed in the configuration:</p>
<pre>&lt;VirtualHost server_ip:80&gt;
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/virtual/www.example.com
    ErrorLog /var/log/apache2/www.example.com-error.log
    CustomLog /var/log/apache2/www.example.com-access.log combined
    &lt;Location /wp-admin/&gt;
        RewriteEngine on
        RewriteRule ^(.*)$ https://%{SERVER_NAME}/wp-admin/ [R=permanent,L]
    &lt;/Location&gt;
&lt;/VirtualHost&gt; 

&lt;VirtualHost server_ip:443&gt;
    ServerName example.com
    ServerAlias www.example.com
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/example.com.pem
    SSLCertificateKeyFile /etc/ssl/private/example.com.key
    DocumentRoot /var/www/virtual/www.example.com
    ErrorLog /var/log/apache2/www.example.com-error.log
    CustomLog /var/log/apache2/www.example.com-access.log combined
    &lt;Location /wp-admin&gt;
        Order deny,allow
        Deny from all
        Allow from trusted_ip_1
        Allow from trusted_ip_2
    &lt;/Location&gt;
&lt;/VirtualHost&gt;</pre>
<h3>Other security measures</h3>
<p>Install <a href="http://wordpress.org/extend/plugins/wp-security-scan/" target="_blank">WP Security scan plugin</a> which will provide a good overview of how your installation looks like from the security point of view.</p>
<p>Also remove advertising of the WordPress version that you are using. Add the following line to functions.php file, which you are using:</p>
<pre>
remove_action('wp_head', 'wp_generator');
</pre>
<p>And did I mention that you need to make regular backups?&#8230;</p>


<p>Related posts:<ol><li><a href='http://www.grenadepod.com/2009/11/23/use-ssh-to-upgrade-wordpress-plugins-automatically/' rel='bookmark' title='Permanent Link: Use SSH to upgrade WordPress plugins automatically'>Use SSH to upgrade WordPress plugins automatically</a></li>
<li><a href='http://www.grenadepod.com/2009/11/25/basic-apache-security/' rel='bookmark' title='Permanent Link: Basic Apache security'>Basic Apache security</a></li>
<li><a href='http://www.grenadepod.com/2009/11/06/essential-wordpress-plugins/' rel='bookmark' title='Permanent Link: Essential WordPress plugins'>Essential WordPress plugins</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.grenadepod.com/2009/11/21/securing-wordpress/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Developing my first WordPress plugin</title>
		<link>http://www.grenadepod.com/2009/11/18/developing-my-first-wordpress-plugin/</link>
		<comments>http://www.grenadepod.com/2009/11/18/developing-my-first-wordpress-plugin/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 14:28:54 +0000</pubDate>
		<dc:creator>pulegium</dc:creator>
				<category><![CDATA[IT Technology]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.grenadepod.com/?p=435</guid>
		<description><![CDATA[It&#8217;s only couple of weeks that I&#8217;m using WordPress (actively!) and it&#8217;s been quite some time I last used PHP. There was a time when I was really comfortable with PHP, but that&#8217;s been oh so long ago. I&#8217;m all in Python nowadays. No stupid endless  curly brackets, or semicolons and the nice indentation is [...]


Related posts:<ol><li><a href='http://www.grenadepod.com/2009/11/21/securing-wordpress/' rel='bookmark' title='Permanent Link: Securing WordPress'>Securing WordPress</a></li>
<li><a href='http://www.grenadepod.com/2009/11/06/essential-wordpress-plugins/' rel='bookmark' title='Permanent Link: Essential WordPress plugins'>Essential WordPress plugins</a></li>
<li><a href='http://www.grenadepod.com/2009/11/23/use-ssh-to-upgrade-wordpress-plugins-automatically/' rel='bookmark' title='Permanent Link: Use SSH to upgrade WordPress plugins automatically'>Use SSH to upgrade WordPress plugins automatically</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p id="top" />It&#8217;s only couple of weeks that I&#8217;m using WordPress (actively!) and it&#8217;s been quite some time I last used PHP. There was a time when I was really comfortable with PHP, but that&#8217;s been oh so long ago. I&#8217;m all in Python nowadays. No stupid endless  curly brackets, or semicolons and the nice indentation is enforced&#8230; Ok, ok, it&#8217;s just me ranting, because I spent nearly 30 mins trying to figure out what&#8217;s wrong with my code. It appeared to be a missing $ in front of my variable name. How lame could that be?&#8230;</p>
<p>Right, back to business. So I decided to write a WordPress plugin. There were few reasons I wanted to do that:</p>
<ul>
<li>See how difficult it is and what WordPress looks like under the hood</li>
<li>Since I&#8217;m using WP, which is a PHP shop I needed to remind myself how PHP looks like</li>
<li>Get some more publicity and bump up the Google rating (that&#8217;ll never hurt, will it?)</li>
</ul>
<p>So, I remembered seeing this neat trick of reversing, or flipping over text by replacing regular ASCII latin characters with Unicode ones that resemble a mirror image of the original ones. There are numerous websites out there on the wild internets that would swallow your piece of texts and then spit out same text, but flipped over.</p>
 p&#x01DDs&#x0279&#x01DD&#x028C&#x01DD&#x0279 u&#x01DD&#x01DDq s&#x0250&#x0265 &#x0287&#x0131 &#x0279&#x01DD&#x0287&#x025F&#x0250 &#x01DD&#x029E&#x0131&#x0283 &#x029Eoo&#x0283 p&#x0283no&#x028D &#x0287x&#x01DD&#x0287 &#x01DD&#x0265&#x0287 &#x028Do&#x0265 s&#x0131 &#x01DD&#x0279&#x01DDH
<p>As you can see it is still text information, no magic with images or anything like that. You can select, copy-paste, etc.</p>
<p>So, I thought, right, let&#8217;s see if there was someone smart who has created a plugin for WordPress that would do this. Not that I&#8217;m a big fan of flipped over text, but just to make sure that I&#8217;m not reinventing the wheel. At the end of the day, what&#8217;s the point in creating something that&#8217;s already been build. If such plugin existed, I would have had to think of something else. Lucky for me, no one has yet created anything like it.</p>
<p>So, simple idea, just what I need to warm up.</p>
<p>First things first, go and read <a href="http://codex.wordpress.org/Writing_a_Plugin" target="_blank">official manual</a> from WordPress about how to develop plugins. It&#8217;s a really good manual, and everyone developing a plugin must read it. Or read it if you feel you need more details in following my manual&#8230; <img src='http://www.grenadepod.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>All plugins go into /wp-content/plugins/ directory in your WordPress installation. Each plugin has it&#8217;s own directory, but this isn&#8217;t a strict requirement, but if you&#8217;re not creating a directory for your plugin, it must be just a single PHP file. I&#8217;d advise to create a directory for your plugin.</p>
<p>Right, this is how I saw me implementing this: user types in any text in the post (or page, or comment, or even excerpt) and encloses any text he/she wants to flip over in my new (made up) tags, just like that:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&amp;lt;upsidedown&amp;gt;your text&amp;lt;/upsidedown&amp;gt;</pre></div></div>

<p>Because WordPress does some clever validation of the text and only certain tags are allowed, I had to include this code in my plugin to declare my new tags as valid ones:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>CUSTOM_TAGS<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// allow new tag in the posts</span>
    <span style="color: #000088;">$allowedposttags</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'upsidedown'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">// ... and also in the comments</span>
    <span style="color: #000088;">$allowedtags</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'upsidedown'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Next thing is to register new filter function with WordPress. Hold on, what is this filter function? Filter function is a function that WordPress calls and passes contents of the post to it. Filter function can do anything it likes to the text and then spits is back to WordPress engine. WordPress will then pass the result to another filter, and so on and on until there are no more filter registered. Each filter get a priority flag assigned, and those with priority 0 will get executed before those that have priority 10. By default each filter gets priority 6 assigned to them.</p>
<p>Right, going back to my filters, let&#8217;s register them:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">add_filter<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'the_content'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'flip_text_upside_down_filter'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
add_filter<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'the_excerpt'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'flip_text_upside_down_filter'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
add_filter<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'comment_text'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'flip_text_upside_down_filter'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>As you can see, I register my filter with three types of content: post (or page), excerpt and comment.</p>
<p>Next thing is to define the filter function:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> flip_text_upside_down_filter<span style="color: #009900;">&#40;</span><span style="color: #000088;">$content</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #990000;">preg_replace_callback</span><span style="color: #009900;">&#40;</span>
        <span style="color: #0000ff;">'/\s*&amp;lt;upsidedown&amp;gt;(.*)&amp;lt;\/upsidedown&amp;gt;/siU'</span><span style="color: #339933;">,</span>
        <span style="color: #0000ff;">'convert_to_upsidedown_unicode'</span><span style="color: #339933;">,</span>
        <span style="color: #000088;">$content</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>WordPress is going to call it with a parameter that contains content text in it. I pass the contents to PHP function preg_replace_callback, which matches the regular expression (any text in between my tags) and calls another function with the contents of the regular expression match (hope that makes sense to you, if not, read the sentence again, repeat until you got it&#8230; <img src='http://www.grenadepod.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ).<br />
Finally, a function that actually does the conversion. Which is pretty simple &#8211; go through all characters and replace them with matching Unicode chars from the table. I&#8217;m not including the whole table here, you can download source code from WordPress plugins directory (in fact, if you install the plugin &#8211; you&#8217;ll have the sourcecode in your plugins/ directory):</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> convert_to_upsidedown_unicode<span style="color: #009900;">&#40;</span><span style="color: #000088;">$match</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// conversion table</span>
    <span style="color: #000088;">$flipTable</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
<span style="color: #339933;">...</span>
    <span style="color: #009900;">&#41;</span>
    <span style="color: #000088;">$origStr</span> <span style="color: #339933;">=</span> <span style="color: #990000;">strrev</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$match</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$newStr</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">' '</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> <span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$origStr</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$ch</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$origStr</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">array_key_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span> <span style="color: #000088;">$flipTable</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$newStr</span> <span style="color: #339933;">.=</span> <span style="color: #000088;">$flipTable</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$ch</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$newStr</span> <span style="color: #339933;">.=</span> <span style="color: #000088;">$ch</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$newStr</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>This is it. Well, ok nearly it. You still need to do the boring bit, ie put a formal header so WP recognises your plugin code (put this, replacing what&#8217;s necessary accordingly):</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">/*
Plugin Name: Upside Down Text
Plugin URI: http://www.grenadepod.com/projects/upside-down-text-plugin-for-wordpress/
Description: This plugin allows to &quot;flip&quot; any section of text upside down
Version: 1.1.0
Author: Grenadepod
Author URI: http://www.grenadepod.com
*/</span></pre></div></div>

<p>Now you can activate the plugin from your WP admin console, and start typing text that everyone struggles to read.</p>
<p>Sooner or later you&#8217;ll notice that the implementation is not ideal. When you switch over to visual editor (which I use most of the time) and then back to HTML editor, all &#8220;new&#8221; tags are gone. This is because the editor does not know about them and so it removes them. Solution was to type in text in Visual (if you prefer to use it) then switch to HTML and place tags where needed. Save without switching back, and publish.</p>
<p>This wasn&#8217;t really nice, and I wasn&#8217;t going to get lots of users with this approach. Some nice soul on WordPress forum suggested to have a look at <a href="http://codex.wordpress.org/Shortcode_API" target="_blank">Shortcode API</a>. This API allows plugin to register shortcode that looks like: [somethinghere]content[/somethinghere], and passes all content back to your function. And this would be immune to switching between editors issue.</p>
<p>So I decided to make a second release of the plugin, where shortcodes are supported alongside with tags. And in fact using shortcodes not only allows me to type them in directly in the Visual editor, but also coding is simpler, I don&#8217;t need to do any regexp magic.</p>
<p>Register my new shortcode:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">add_shortcode<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'upsidedown'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'flip_text_upside_down_shortcode'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>And define what function to call:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> flip_text_upside_down_shortcode<span style="color: #009900;">&#40;</span><span style="color: #000088;">$atts</span><span style="color: #339933;">,</span> <span style="color: #000088;">$content</span><span style="color: #339933;">=</span><span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> convert_to_upsidedown_unicode<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span> <span style="color: #000088;">$content</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>As you can see, I&#8217;m reusing same character conversion function, so the changes were minimal.</p>
<p>All seems to be working quite fine, at the end of the day, what can go wrong with only few lines of code?&#8230;</p>


<p>Related posts:<ol><li><a href='http://www.grenadepod.com/2009/11/21/securing-wordpress/' rel='bookmark' title='Permanent Link: Securing WordPress'>Securing WordPress</a></li>
<li><a href='http://www.grenadepod.com/2009/11/06/essential-wordpress-plugins/' rel='bookmark' title='Permanent Link: Essential WordPress plugins'>Essential WordPress plugins</a></li>
<li><a href='http://www.grenadepod.com/2009/11/23/use-ssh-to-upgrade-wordpress-plugins-automatically/' rel='bookmark' title='Permanent Link: Use SSH to upgrade WordPress plugins automatically'>Use SSH to upgrade WordPress plugins automatically</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.grenadepod.com/2009/11/18/developing-my-first-wordpress-plugin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Query data from Django site with jQuery</title>
		<link>http://www.grenadepod.com/2009/11/13/query-data-from-django-site-with-jquery/</link>
		<comments>http://www.grenadepod.com/2009/11/13/query-data-from-django-site-with-jquery/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 16:06:37 +0000</pubDate>
		<dc:creator>pulegium</dc:creator>
				<category><![CDATA[IT Technology]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.grenadepod.com/?p=331</guid>
		<description><![CDATA[Right, here&#8217;s what I needed to do: I have a list of IP addresses displayed on a web page and I want to show the status of every each of them. By &#8220;status&#8221; I mean just perform a simple ping and display OK next to the IP, or &#8216;no response&#8217; otherwise. Listing is a Django [...]


Related posts:<ol><li><a href='http://www.grenadepod.com/2009/11/09/how-to-use-generic-views-in-django/' rel='bookmark' title='Permanent Link: How to use generic views in Django'>How to use generic views in Django</a></li>
<li><a href='http://www.grenadepod.com/2009/11/18/developing-my-first-wordpress-plugin/' rel='bookmark' title='Permanent Link: Developing my first WordPress plugin'>Developing my first WordPress plugin</a></li>
<li><a href='http://www.grenadepod.com/2009/11/22/using-openid-for-authentication-in-django/' rel='bookmark' title='Permanent Link: Using OpenID for authentication in Django'>Using OpenID for authentication in Django</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p id="top" />Right, here&#8217;s what I needed to do: I have a list of IP addresses displayed on a web page and I want to show the status of every each of them. By &#8220;status&#8221; I mean just perform a simple ping and display OK next to the IP, or &#8216;no response&#8217; otherwise.</p>
<p>Listing is a Django application, so theoretically I could just go through the list of IPs, ping and add status to the list that gets passed to Django template. But nice it is not. It might take ages to query the whole list, and even if I spend time implementing multithreaded ping and ping them all concurrently it still going to take at leas couple of seconds to complete.</p>
<p>So obvious choice is to delay the ping action. I will serve the page with all IPs and other bits and pieces and then let my JavaScript to do the AJAX magic.</p>
<p>So, how do I do that?</p>
<p>Well, first I need a view that checks if the given IP responds to a ping and displays the result. To keep things simple, I&#8217;m going to return a string, which will be displayed on the list page:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> ping<span style="color: black;">&#40;</span>request, address=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> responding_to_ping<span style="color: black;">&#40;</span>address<span style="color: black;">&#41;</span>:
        msg = <span style="color: #483d8b;">&quot;Ping OK&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        msg = <span style="color: #483d8b;">&quot;No response&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> HttpResponse<span style="color: black;">&#40;</span>msg<span style="color: black;">&#41;</span></pre></div></div>

<p>I then need to add URL pattern, so I can call the view:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">    url<span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^ping/(?P&lt;address&gt;<span style="color: #000099; font-weight: bold;">\d</span>{1,3}<span style="color: #000099; font-weight: bold;">\.</span><span style="color: #000099; font-weight: bold;">\d</span>{1,3}<span style="color: #000099; font-weight: bold;">\.</span><span style="color: #000099; font-weight: bold;">\d</span>{1,3}<span style="color: #000099; font-weight: bold;">\.</span><span style="color: #000099; font-weight: bold;">\d</span>{1,3})/$'</span>, views.<span style="color: black;">ping</span><span style="color: black;">&#41;</span>,</pre></div></div>

<p>Good, so now I can navigate to http://<hostname>/ping/<ip_address>/ and it&#8217;ll come back with either &#8220;Ping OK&#8221; or &#8220;No response&#8221; message.<br />
Right, now let&#8217;s add some JavaScript magic that&#8217;ll query the server and update my web page with details.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">&lt;script type=&quot;text/javascript&quot; src=&quot;/static/js/jquery-1.3.2.min.js&quot;&gt;&lt;/script&gt;
<span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
    $<span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">ready</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;.address&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">each</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #003366; font-weight: bold;">var</span> curId <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'id'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            updateStatus<span style="color: #009900;">&#40;</span>curId<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">function</span> updateStatus<span style="color: #009900;">&#40;</span>attrId<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        address <span style="color: #339933;">=</span> attrId.<span style="color: #660066;">replace</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'ip_'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        address <span style="color: #339933;">=</span> address.<span style="color: #660066;">replace</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/_/g</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'.'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        $.<span style="color: #660066;">ajax</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
            url<span style="color: #339933;">:</span> <span style="color: #3366CC;">'/ping/'</span> <span style="color: #339933;">+</span> address<span style="color: #339933;">,</span>
            success<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>response<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#'</span> <span style="color: #339933;">+</span> attrId<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">html</span><span style="color: #009900;">&#40;</span>response<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span></pre></td></tr></table></div>

<p>So, what exactly is happening here?</p>
<ul>
<li><strong>Line 3:</strong> This waits for a document too load and call the callback function when ready to proceed, calback function defined in the lines below</li>
<li><strong>Lines 4-6:</strong>Goes through each element of the HTML document (my web page) that are of class &#8220;address&#8221;, extracts the element&#8217;s &#8216;id&#8217; attribute, and calls &#8216;updateStatus&#8217; function passing the &#8216;id&#8217; to it. So all elements that are going to be updated should look like: &lt;span class=&#8221;address&#8221; id=&#8221;ip_address&#8221; /&gt;</li>
<li><strong>Lines 11-12:</strong> All id&#8217;s are going to be in the following format: ip_1_2_3_4, so before I pass this to the URL, I need to strip the ip_ bit, and replace underscores with dots.</li>
<li><strong>Lines 13-17:</strong> This is where I perform AJAX call to the URL. The &#8216;success&#8217; bit is a call to the function that gets executed when the result is successfully retrieved. This function is pretty simple, it just replaces the contents of the tag with whatever it receives from the server</li>
</ul>
<p>And this is it, all that is left to do is list all IPs that need checking. Below is the raw HTML, but I trust you can be creative in writing a decent Django template to generate the page.</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;ul&gt;
    &lt;li&gt;192.168.0.1 [Status: &lt;span class=&quot;address&quot; id=&quot;ip_192_168_0_1&quot;&gt;Unknown&lt;/span&gt; ]&lt;/li&gt;
    &lt;li&gt;192.168.0.2 [Status: &lt;span class=&quot;address&quot; id=&quot;ip_192_168_0_2&quot;&gt;Unknown&lt;/span&gt; ]&lt;/li&gt;
    &lt;li&gt;192.168.0.3 [Status: &lt;span class=&quot;address&quot; id=&quot;ip_192_168_0_3&quot;&gt;Unknown&lt;/span&gt; ]&lt;/li&gt;
    ...
&lt;/ul&gt;</pre></div></div>



<p>Related posts:<ol><li><a href='http://www.grenadepod.com/2009/11/09/how-to-use-generic-views-in-django/' rel='bookmark' title='Permanent Link: How to use generic views in Django'>How to use generic views in Django</a></li>
<li><a href='http://www.grenadepod.com/2009/11/18/developing-my-first-wordpress-plugin/' rel='bookmark' title='Permanent Link: Developing my first WordPress plugin'>Developing my first WordPress plugin</a></li>
<li><a href='http://www.grenadepod.com/2009/11/22/using-openid-for-authentication-in-django/' rel='bookmark' title='Permanent Link: Using OpenID for authentication in Django'>Using OpenID for authentication in Django</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.grenadepod.com/2009/11/13/query-data-from-django-site-with-jquery/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
