<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:wfw="http://wellformedweb.org/CommentAPI/"
     >
  <channel>
    <title>Topdog.za.net</title>
    <link>http://www.topdog.za.net</link>
    <description>A bored sysadmin</description>
    <pubDate>Fri, 26 Feb 2016 10:06:56 GMT</pubDate>
    <generator>Blogofile</generator>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Book Review: Jumpstart NodeJS By Don Nguyen</title>
      <link>http://www.topdog.za.net/2014/02/21/book-review:-jumpstart-nodejs-by-don-nguyen</link>
      <pubDate>Fri, 21 Feb 2014 12:30:00 SAST</pubDate>
      <category><![CDATA[Book review]]></category>
      <guid isPermaLink="true">http://www.topdog.za.net/2014/02/21/book-review:-jumpstart-nodejs-by-don-nguyen</guid>
      <description>Book Review: Jumpstart NodeJS By Don Nguyen</description>
      <content:encoded><![CDATA[<p><strong>"Book Review: Jumpstart NodeJS By Don Nguyen"; Sitepoint</strong></p>
<p><img alt="Book Review: Jumpstart NodeJS By Don Nguyen;" src="/imgs/jump-start-nodejs.gif" /></p>
<p>This introduction to NodeJS is written in basic tutorial style. This enables
you to learn by doing and getting your feet wet.</p>
<p>It starts with an introduction to NodeJS and the surrounding ecosystem as
well as installing the required software.</p>
<p>The next chapters focus on building a sample application in NodeJS using
several of the current technics of application development such as MVC,
realtime web and NoSQL.</p>
<p>The final chapter covers the deployment options available to deploy NodeJS
applications.</p>
<p>All in all it is a good read and will enable you to get started. Unfortunately
only NoSQL persistence is covered, given that most applications still work
better with SQL databases that was a downside for me.</p>
<p>Product page <a href="http://shop.oreilly.com/product/9780987332103.do">http://shop.oreilly.com/product/9780987332103.do</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Book Review: Perl One-Liners - 130 Programs That Get Things Done By Peteris Krumins</title>
      <link>http://www.topdog.za.net/2013/12/31/book-review:-perl-one-liners---130-programs-that-get-things-done-by-peteris-krumins</link>
      <pubDate>Tue, 31 Dec 2013 12:30:00 SAST</pubDate>
      <category><![CDATA[Book review]]></category>
      <guid isPermaLink="true">http://www.topdog.za.net/2013/12/31/book-review:-perl-one-liners---130-programs-that-get-things-done-by-peteris-krumins</guid>
      <description>Book Review: Perl One-Liners - 130 Programs That Get Things Done By Peteris Krumins</description>
      <content:encoded><![CDATA[<p><strong>"Perl One-Liners - 130 Programs That Get Things Done By Peteris Krumins"; No Starch Press</strong></p>
<p><img alt="Perl One-Liners - 130 Programs That Get Things Done By Peteris Krumins;" src="/imgs/perl-one-liners.gif" /></p>
<p>Want to stock up on a bag of tricks and snippets to get your work done
quicker, this is the book for you. Either as a system admin or as a
developer you do yourself a great deal of good by reading and grasping
the one liners in this book.</p>
<p>Perl being specifically designed to process text is an invaluable tool
to Unix admins given that everything is a file on Unix.</p>
<p>The book provides 130 solid one lines which will enhance your arsenal
of snippets or get you on the road to creating one.</p>
<p>The one liners are broken down into seven sections: Spacing, Numbering,
Calculations, Arrays and Strings, Text conversion and Substitution,
Selective printing and deletion, Regular expressions. There are two
appendixes which over Perl's special variables and using the one liners
in a Windows world.</p>
<p>Many of these one liners are drop in replacements of the piped commands
with several Unix utilities that you have been using, which allows you
to use a single tool in place of several chained commands.</p>
<p>The presentation style is great as all the one liners are explained and
alternatives presented, in keeping with the Perl idiom <strong>"There is more
than one way to do it"</strong> </p>
<p>Well what are you waiting for go out and get your copy now.</p>
<p>Product page <a href="http://shop.oreilly.com/product/9781593275204.do">http://shop.oreilly.com/product/9781593275204.do</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Book Review: 21st Century C By Ben Klemens</title>
      <link>http://www.topdog.za.net/2013/09/13/book-review:-21st-century-c-by-ben-klemens</link>
      <pubDate>Fri, 13 Sep 2013 07:30:00 SAST</pubDate>
      <category><![CDATA[Book review]]></category>
      <guid isPermaLink="true">http://www.topdog.za.net/2013/09/13/book-review:-21st-century-c-by-ben-klemens</guid>
      <description>Book Review: 21st Century C By Ben Klemens</description>
      <content:encoded><![CDATA[<p><strong>"21st Century C By Ben Klemens"; O'Reilly Media</strong></p>
<p><img alt="21st Century C By Ben Klemens;" src="/imgs/21st-century-c.gif" /></p>
<p>This intermediate level book provides guidance on new methods of coding
in C as well as identifying the common pitfalls and providing workarounds
to them.</p>
<p>The book is split into two sections on dealing with the ecosystem around
C development and the second the language itself.</p>
<p>This is not a teach you how to write in C book, users are expected to have
a grasp of the language prior to starting out with this book.</p>
<p>The first section covers the development enviroment, issues such as building
as well as linking and packaging of software for wide distribution.</p>
<p>Also covered is version control in a short chapter, this is one of the very
well written parts of the book, the explanation of the Git version management
system in this short chapter puts to shame some of the larger dedicated books
on the market.</p>
<p>A short example of bridging other languages with C is provided in form of a
C based python module.</p>
<p>The second section deals with the new age thinking around using the C language.
And also provides insights in dealing with the know pitfalls of C such as
memory management as well as string handling.</p>
<p>Covered in the second section as well are pointers, OO, Structures as well as
libraries.</p>
<p>The downside for me was that section 2 should have been section 1 as it is
logical to deal with the language first then the ecosystem around it later.</p>
<p>All in all, if you have some C experience of passing knowledge this book will
help improve your pedigree. It is however not a book for the beginner.</p>
<p>Product page <a href="http://shop.oreilly.com/product/0636920025108.do">http://shop.oreilly.com/product/0636920025108.do</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Testing SSL client certificate authentication with curl</title>
      <link>http://www.topdog.za.net/2013/03/28/testing-ssl-client-certificate-authentication-with-curl</link>
      <pubDate>Thu, 28 Mar 2013 07:40:00 SAST</pubDate>
      <category><![CDATA[Sysadmin]]></category>
      <category><![CDATA[Tips]]></category>
      <category><![CDATA[Security]]></category>
      <guid isPermaLink="true">http://www.topdog.za.net/2013/03/28/testing-ssl-client-certificate-authentication-with-curl</guid>
      <description>Testing SSL client certificate authentication with curl</description>
      <content:encoded><![CDATA[<p>When using SSL client certificate authentication you may need to
test it using command line tools.</p>
<p>To do so run the following command:</p>
<pre><code>curl -v -s -k --key client.key --cert client.pem https://servername
</code></pre>
<p>Thats it.</p>]]></content:encoded>
    </item>
    <item>
      <title>Setup a OpenVPN server on Centos 6</title>
      <link>http://www.topdog.za.net/2013/02/02/setup-a-openvpn-server-on-centos-6</link>
      <pubDate>Sat, 02 Feb 2013 07:40:00 SAST</pubDate>
      <category><![CDATA[Sysadmin]]></category>
      <category><![CDATA[Tips]]></category>
      <category><![CDATA[Security]]></category>
      <category><![CDATA[Centos]]></category>
      <guid isPermaLink="true">http://www.topdog.za.net/2013/02/02/setup-a-openvpn-server-on-centos-6</guid>
      <description>Setup a OpenVPN server on Centos 6</description>
      <content:encoded><![CDATA[<h2>EPEL Repository</h2>
<p>OpenVPN 2 is available for Centos from the EPEL repository, so you
need to have EPEL enabled.</p>
<p>If you do not have EPEL enabled run:</p>
<pre><code>rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
</code></pre>
<h2>Installation</h2>
<p>To install OpenVPN run:</p>
<pre><code>yum install openvpn lzo -y
</code></pre>
<h2>Configuration</h2>
<p>Setup the SSL CA and keys:</p>
<pre><code>cp -r /usr/share/openvpn/easy-rsa/2.0 /etc/openvpn/open-rsa
</code></pre>
<p>Create and customize the <code>vars</code> file <code>/etc/openvpn/open-rsa/vars</code>,
Make sure you change the <code>KEY_</code> values to your own settings</p>
<div class="pygments_murphy"><pre><span class="nb">export </span><span class="nv">EASY_RSA</span><span class="o">=</span><span class="s2">&quot;`pwd`&quot;</span>
<span class="nb">export </span><span class="nv">OPENSSL</span><span class="o">=</span><span class="s2">&quot;openssl&quot;</span>
<span class="nb">export </span><span class="nv">PKCS11TOOL</span><span class="o">=</span><span class="s2">&quot;pkcs11-tool&quot;</span>
<span class="nb">export </span><span class="nv">GREP</span><span class="o">=</span><span class="s2">&quot;grep&quot;</span>
<span class="nb">export </span><span class="nv">KEY_CONFIG</span><span class="o">=</span><span class="sb">`</span><span class="nv">$EASY_RSA</span>/whichopensslcnf <span class="nv">$EASY_RSA</span><span class="sb">`</span>
<span class="nb">export </span><span class="nv">KEY_DIR</span><span class="o">=</span><span class="s2">&quot;/etc/openvpn/keys&quot;</span>
<span class="nb">echo </span>NOTE: If you run ./clean-all, I will be doing a rm -rf on <span class="nv">$KEY_DIR</span>
<span class="nb">export </span><span class="nv">PKCS11_MODULE_PATH</span><span class="o">=</span><span class="s2">&quot;dummy&quot;</span>
<span class="nb">export </span><span class="nv">PKCS11_PIN</span><span class="o">=</span><span class="s2">&quot;dummy&quot;</span>
<span class="nb">export </span><span class="nv">KEY_SIZE</span><span class="o">=</span>1024
<span class="nb">export </span><span class="nv">CA_EXPIRE</span><span class="o">=</span>3650
<span class="nb">export </span><span class="nv">KEY_EXPIRE</span><span class="o">=</span>3650
<span class="nb">export </span><span class="nv">KEY_COUNTRY</span><span class="o">=</span><span class="s2">&quot;ZA&quot;</span>
<span class="nb">export </span><span class="nv">KEY_PROVINCE</span><span class="o">=</span><span class="s2">&quot;Gauteng&quot;</span>
<span class="nb">export </span><span class="nv">KEY_CITY</span><span class="o">=</span><span class="s2">&quot;Johannesburg&quot;</span>
<span class="nb">export </span><span class="nv">KEY_ORG</span><span class="o">=</span><span class="s2">&quot;Topdog-software&quot;</span>
<span class="nb">export </span><span class="nv">KEY_EMAIL</span><span class="o">=</span><span class="s2">&quot;andrew@topdog.za.net&quot;</span>
<span class="nb">export </span><span class="nv">KEY_CN</span><span class="o">=</span><span class="s2">&quot;Topdog-software OpenVPN CA&quot;</span>
<span class="nb">export </span><span class="nv">KEY_NAME</span><span class="o">=</span><span class="s2">&quot;tdss&quot;</span>
<span class="nb">export </span><span class="nv">KEY_OU</span><span class="o">=</span><span class="s2">&quot;Topdog-software&quot;</span>
</pre></div>

<p>Create the keys directory:</p>
<pre><code>mkdir /etc/openvpn/keys
</code></pre>
<p>Create the CA:</p>
<pre><code>cd /etc/openvpn/open-rsa
source ./vars
./clean-all
./build-ca
</code></pre>
<p>Create the servers SSL certificate (replace <code>vpn.home.topdog-software.com</code> with
name of your server):</p>
<pre><code>./build-key-server vpn.home.topdog-software.com
</code></pre>
<p>Generate Diffie Hellman parameters:</p>
<pre><code>./build-dh
</code></pre>
<p>Create the leases file:</p>
<pre><code>touch /etc/openvpn/ipp.txt
</code></pre>
<p>Create the configuration file <code>/etc/openvpn/server.conf</code>:</p>
<div class="pygments_murphy"><pre>port 1194
proto udp
dev tun
ca keys/ca.crt
cert keys/vpn.home.topdog-software.com.crt
key keys/vpn.home.topdog-software.com.key
dh keys/dh1024.pem
cipher AES-128-CBC
server 10.0.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
client-config-dir ccd
keepalive 10 120
comp-lzo
persist-key
persist-tun
status /var/log/openvpn-status.log
verb 3
</pre></div>

<p>Create iptables rules to allow traffic through:</p>
<div class="pygments_murphy"><pre>*filter
..
..
-A INPUT -p udp -m state --state NEW -m udp --dport 1194 -j ACCEPT
-A FORWARD -i tun+ -o eth0 -j ACCEPT
-A FORWARD -i eth0 -o tun+ -j ACCEPT
</pre></div>

<p>Enable packet forwarding:</p>
<pre><code>echo 1 &gt; /proc/sys/net/ipv4/ip_forward
</code></pre>
<p>Make it permanent add the following to <code>/etc/sysctl.conf</code>:</p>
<div class="pygments_murphy"><pre>net.ipv4.ip_forward = 1
</pre></div>

<p>Your OpenVPN should be ready to go, start OpenVPN:</p>
<pre><code>service openvpn start
</code></pre>
<h2>Client configuration</h2>
<p>Each client requires a certificate &amp; key pairing, lets create one:</p>
<pre><code>./build-key client1.home.topdog-software.com
</code></pre>
<p>Copy the <code>client1.home.topdog-software.com.crt</code>, <code>ca.crt</code> and
<code>client1.home.topdog-software.com.key</code> files to the OpenVPN keys
directory on the client.</p>
<p>Create the client OpenVPN configuration <code>/etc/openvpn/server.conf</code>:</p>
<div class="pygments_murphy"><pre>remote vpn.home.topdog-software.com 1194
client 
remote-cert-tls server 
dev tun0 
proto udp
resolv-retry infinite 
nobind 
persist-key 
persist-tun 
float 
ca keys/ca.crt 
cert keys/client1.home.topdog-software.com.crt
key keys/client1.home.topdog-software.com.key
cipher AES-128-CBC
comp-lzo
status /var/log/openvpn-client.log
</pre></div>

<h2>Static addresses</h2>
<p>If you want some clients to get static addresses:</p>
<pre><code>mkdir /etc/openvpn/ccd
</code></pre>
<p>Create a client file for each of the clients you want to get a static
address in <code>/etc/openvpn/ccd</code> the file name should match the CN in
the client certificate.</p>
<div class="pygments_murphy"><pre>ifconfig-push 10.0.0.2 10.0.0.1
</pre></div>]]></content:encoded>
    </item>
    <item>
      <title>Centos 6 Bonded network interfaces</title>
      <link>http://www.topdog.za.net/2013/02/01/centos-6-bonded-network-interfaces</link>
      <pubDate>Fri, 01 Feb 2013 07:40:00 SAST</pubDate>
      <category><![CDATA[Sysadmin]]></category>
      <category><![CDATA[Tips]]></category>
      <category><![CDATA[Centos]]></category>
      <guid isPermaLink="true">http://www.topdog.za.net/2013/02/01/centos-6-bonded-network-interfaces</guid>
      <description>Centos 6 Bonded network interfaces</description>
      <content:encoded><![CDATA[<p>Bonding allows you to aggregate multiple ports, providing redundancy,
fault tolerance and load balancing.</p>
<p>There are various types of bonding available but i will show how to
bond in mode 1 which is active-backup. If your interested in the other
available types please refer to the
<a href="https://www.kernel.org/doc/Documentation/networking/bonding.txt">documentation</a>.</p>
<p>In this setup i have two connections to different switches in case one
fails the other takes over and services are not disrupted.</p>
<h2>Setup bonded interface</h2>
<p>Create a file in /etc/modprobe.d called bond.conf and add the following</p>
<div class="pygments_murphy"><pre><span class="nb">alias </span>bond0 bonding
</pre></div>

<p>Create the bonded interface file /etc/sysconfig/network-scripts/ifcfg-bond0
with the following contents</p>
<div class="pygments_murphy"><pre><span class="nv">DEVICE</span><span class="o">=</span>bond0
<span class="nv">IPADDR</span><span class="o">=</span>xxx.xxx.xxx.xxx
<span class="nv">NETMASK</span><span class="o">=</span>xxx.xxx.xxx.xxx
<span class="nv">ONBOOT</span><span class="o">=</span>yes
<span class="nv">BOOTPROTO</span><span class="o">=</span>none
<span class="nv">USERCTL</span><span class="o">=</span>no
<span class="nv">BONDING_OPTS</span><span class="o">=</span><span class="s2">&quot;bond0 miimon=80 mode=1&quot;</span>
</pre></div>

<p>Modify the interfaces you want to bond to look like:</p>
<div class="pygments_murphy"><pre><span class="nv">DEVICE</span><span class="o">=</span>ethX
<span class="nv">ONBOOT</span><span class="o">=</span>yes
<span class="nv">BOOTPROTO</span><span class="o">=</span>none
<span class="nv">USERCTL</span><span class="o">=</span>no
<span class="nv">MASTER</span><span class="o">=</span>bond0
<span class="nv">SLAVE</span><span class="o">=</span>yes
</pre></div>

<p>Restart networking for the changes to take effect:</p>
<pre><code>service network restart
</code></pre>
<h2>Checking the status</h2>
<p>You can check the status of the interface by running:</p>
<pre><code>cat /proc/net/bonding/bond0
</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Commandline OpenVPN client on Mac OSX with macports</title>
      <link>http://www.topdog.za.net/2013/01/31/commandline-openvpn-client-on-mac-osx-with-macports</link>
      <pubDate>Thu, 31 Jan 2013 07:40:00 SAST</pubDate>
      <category><![CDATA[Sysadmin]]></category>
      <category><![CDATA[Mac OS X]]></category>
      <category><![CDATA[Tips]]></category>
      <category><![CDATA[Security]]></category>
      <category><![CDATA[Unix]]></category>
      <guid isPermaLink="true">http://www.topdog.za.net/2013/01/31/commandline-openvpn-client-on-mac-osx-with-macports</guid>
      <description>Commandline OpenVPN client on Mac OSX with macports</description>
      <content:encoded><![CDATA[<p>Most people use TunnelBrick to setup OpenVPN client connections on Mac OSX,
i prefer using the command line.</p>
<p>To get OpenVPN up and running off the command line is a simple process. The
commands below need to be run as a privileged user if your root account is
not enabled use sudo to run the commands.</p>
<h2>Install OpenVPN</h2>
<p>To install OpenVPN 2 from macports run:</p>
<pre><code>port install openvpn2
</code></pre>
<h2>Install TunTap</h2>
<p>To install <a href="http://tuntaposx.sourceforge.net/">TunTap</a> from macports run:</p>
<pre><code>port install tuntaposx
</code></pre>
<p>Configure it to startup at boot:</p>
<pre><code>launchctl load -w /Library/LaunchDaemons/org.macports.tuntaposx.plist
</code></pre>
<p>You need <a href="http://tuntaposx.sourceforge.net/">TunTap</a> as it allows you
to create virtual interfaces using the supplied kernel extensions.
If you don't install TunTap you will get the error
<em>Cannot allocate TUN/TAP dev dynamically</em> when you try and make a
OpenVPN connection.</p>
<h2>Configuration</h2>
<p>Create a directory to hold your configuration and keys.</p>
<pre><code>mkdir /opt/local/etc/openvpn
</code></pre>
<p>Place your keys and configuration files in /opt/local/etc/openvpn/</p>
<p>A sample client configuration is provided below.</p>
<div class="pygments_murphy"><pre>client
dev tun
proto udp
remote vpn.home.topdog-software.com 1194
nobind
resolv-retry infinite
tls-client
ca /opt/local/etc/openvpn/ca.crt
cert /opt/local/etc/openvpn/client.crt
key /opt/local/etc/openvpn/client.key
ns-cert-type server
cipher BF-CBC
tls-cipher DHE-RSA-AES256-SHA
tls-remote vpn.home.topdog-software.com
tls-auth /opt/local/etc/openvpn/tls-auth.key 1
remote-cert-tls server
comp-lzo
persist-key
persist-tun
mute-replay-warnings
verb 3
mlock
</pre></div>

<h2>Connecting</h2>
<p>To connect simply run:</p>
<pre><code>openvpn2 --config /opt/local/etc/openvpn/openvpn.conf
</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Automating translation of software using the Microsoft Translator and Python</title>
      <link>http://www.topdog.za.net/2013/01/25/automating-translation-of-software-using-the-microsoft-translator-and-python</link>
      <pubDate>Fri, 25 Jan 2013 07:40:00 SAST</pubDate>
      <category><![CDATA[Sysadmin]]></category>
      <category><![CDATA[Tips]]></category>
      <category><![CDATA[Unix]]></category>
      <category><![CDATA[Linux]]></category>
      <guid isPermaLink="true">http://www.topdog.za.net/2013/01/25/automating-translation-of-software-using-the-microsoft-translator-and-python</guid>
      <description>Automating translation of software using the Microsoft Translator and Python</description>
      <content:encoded><![CDATA[<p>The <a href="http://msdn.microsoft.com/en-us/library/dd576287.aspx">Microsoft translator</a> provides an
API that you can use for automated translation. It currently supports about 39 languages.</p>
<p>True to the nature of open source i found that someone had already written
a <a href="https://github.com/openlabs/Microsoft-Translator-Python-API">python wrapper</a>
to the API. I extended the wrapper to use the <a href="http://docs.python-requests.org/en/latest/">requests</a>
and <a href="http://polib.readthedocs.org/en/latest/">pofile</a> packages.</p>
<p>My extended script is able to read gettext Portable Object <code>PO</code> source files and translate
the strings and write the translations back into <code>PO</code> files, here by automating the whole
translation process.</p>
<h2>Source</h2>
<div class="pygments_murphy"><pre><span class="c">#!/usr/bin/env python</span>
<span class="c"># -*- coding: utf-8 -*-</span>
<span class="c"># vim: ai ts=4 sts=4 et sw=4</span>

<span class="sd">&quot;&quot;&quot;Automatic translation using m$ translator</span>
<span class="sd">    :copyright: 2012 Andrew Colin Kissa</span>
<span class="sd">    :copyright: 2011 by Openlabs Technologies &amp; Consulting (P) Limited</span>
<span class="sd">    :license: BSD, see LICENSE for more details.</span>
<span class="sd">&quot;&quot;&quot;</span>

<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">re</span>
<span class="kn">import</span> <span class="nn">json</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="kn">import</span> <span class="nn">urllib</span>
<span class="kn">import</span> <span class="nn">logging</span>
<span class="kn">import</span> <span class="nn">datetime</span>

<span class="kn">import</span> <span class="nn">requests</span>

<span class="kn">from</span> <span class="nn">optparse</span> <span class="kn">import</span> <span class="n">OptionParser</span>

<span class="kn">from</span> <span class="nn">polib</span> <span class="kn">import</span> <span class="n">pofile</span>

<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;Translator&#39;</span><span class="p">,</span> <span class="s">&#39;TranslateApiException&#39;</span><span class="p">]</span>

<span class="k">class</span> <span class="nc">ArgumentException</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Argument&quot;&quot;&quot;</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">message</span> <span class="o">=</span> <span class="n">message</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;ArgumentException: &#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">)</span>
        <span class="nb">super</span><span class="p">(</span><span class="n">ArgumentException</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">message</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">ArgumentOutOfRangeException</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;ArgumentOutOfRange&quot;&quot;&quot;</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">message</span> <span class="o">=</span> <span class="n">message</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;ArgumentOutOfRangeException: &#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">)</span>
        <span class="nb">super</span><span class="p">(</span><span class="n">ArgumentOutOfRangeException</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">message</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">TranslateApiException</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;TranslateApi&quot;&quot;&quot;</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">message</span> <span class="o">=</span> <span class="n">message</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;TranslateApiException: &#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">)</span>
        <span class="nb">super</span><span class="p">(</span><span class="n">TranslateApiException</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">message</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">Translator</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Implements AJAX API for the Microsoft Translator service</span>
<span class="sd">    </span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">lang_url</span> <span class="o">=</span> <span class="s">&#39;http://api.microsofttranslator.com/V2/Ajax.svc/GetLanguagesForTranslate&#39;</span>
    <span class="n">oauth_url</span> <span class="o">=</span> <span class="s">&#39;https://datamarket.accesscontrol.windows.net/v2/OAuth2-13&#39;</span>
    <span class="n">translate_url</span> <span class="o">=</span> <span class="s">&quot;http://api.microsofttranslator.com/V2/Ajax.svc/Translate&quot;</span>
    <span class="n">translate_array_url</span> <span class="o">=</span> <span class="s">&quot;http://api.microsofttranslator.com/V2/Ajax.svc/TranslateArray&quot;</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">client_id</span><span class="p">,</span> <span class="n">client_secret</span><span class="p">,</span>
            <span class="n">scope</span><span class="o">=</span><span class="s">&quot;http://api.microsofttranslator.com&quot;</span><span class="p">,</span> <span class="n">debug</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>

<span class="sd">        :param client_id: The client ID that you specified when you registered</span>
<span class="sd">                          your application with Azure DataMarket.</span>
<span class="sd">        :param client_secret: The client secret value that you obtained when</span>
<span class="sd">                              you registered your application with Azure</span>
<span class="sd">                              DataMarket.</span>
<span class="sd">        :param scope: Defaults to http://api.microsofttranslator.com</span>
<span class="sd">        :param debug: If true, the logging level will be set to debug</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">client_id</span> <span class="o">=</span> <span class="n">client_id</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">client_secret</span> <span class="o">=</span> <span class="n">client_secret</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">scope</span> <span class="o">=</span> <span class="n">scope</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">grant_type</span> <span class="o">=</span> <span class="s">&quot;client_credentials&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">access_token</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">debug</span> <span class="o">=</span> <span class="n">debug</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s">&quot;microsofttranslator&quot;</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">session</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">langs</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">debug</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">setLevel</span><span class="p">(</span><span class="n">level</span><span class="o">=</span><span class="n">logging</span><span class="o">.</span><span class="n">DEBUG</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">create_session</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="s">&quot;create a requests session&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">session</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">session</span><span class="p">()</span>

    <span class="k">def</span> <span class="nf">get_access_token</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">force</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        .. note::</span>
<span class="sd">            The value of access token can be used for subsequent calls to the</span>
<span class="sd">            Microsoft Translator API. The access token expires after 10</span>
<span class="sd">            minutes. It is always better to check elapsed time between time at</span>
<span class="sd">            which token issued and current time. If elapsed time exceeds 10</span>
<span class="sd">            minute time period renew access token by following obtaining</span>
<span class="sd">            access token procedure.</span>

<span class="sd">        :return: The access token to be used with subsequent requests</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">args</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">urlencode</span><span class="p">({</span>
            <span class="s">&#39;client_id&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">client_id</span><span class="p">,</span>
            <span class="s">&#39;client_secret&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">client_secret</span><span class="p">,</span>
            <span class="s">&#39;scope&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">scope</span><span class="p">,</span>
            <span class="s">&#39;grant_type&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">grant_type</span>
        <span class="p">})</span>

        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span> <span class="ow">or</span> <span class="n">force</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">create_session</span><span class="p">()</span>

        <span class="n">response</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">post</span><span class="p">(</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">oauth_url</span><span class="p">,</span>
            <span class="n">data</span><span class="o">=</span><span class="n">args</span>
        <span class="p">)</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">access_token</span> <span class="o">=</span> <span class="n">response</span><span class="p">[</span><span class="s">&#39;access_token&#39;</span><span class="p">]</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">access_token</span>

    <span class="k">def</span> <span class="nf">call</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">params</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Calls the given url with the params urlencoded</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">access_token</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">get_access_token</span><span class="p">()</span>

        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">create_session</span><span class="p">()</span>

        <span class="n">headers</span> <span class="o">=</span> <span class="p">{</span><span class="s">&#39;Authorization&#39;</span><span class="p">:</span> <span class="s">&#39;Bearer </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">access_token</span><span class="p">}</span>
        <span class="n">translation_url</span> <span class="o">=</span> <span class="s">&#39;</span><span class="si">%s</span><span class="s">?</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">urllib</span><span class="o">.</span><span class="n">urlencode</span><span class="p">(</span><span class="n">params</span><span class="p">))</span>
        <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">translation_url</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">)</span>
        <span class="n">retval</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">content</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s">&quot;UTF-8-sig&quot;</span><span class="p">))</span>

        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">retval</span><span class="p">,</span> <span class="nb">basestring</span><span class="p">)</span> <span class="ow">and</span> \
                <span class="n">retval</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&quot;ArgumentOutOfRangeException&quot;</span><span class="p">):</span>
            <span class="k">raise</span> <span class="n">ArgumentOutOfRangeException</span><span class="p">(</span><span class="n">retval</span><span class="p">)</span>

        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">retval</span><span class="p">,</span> <span class="nb">basestring</span><span class="p">)</span> <span class="ow">and</span> \
                <span class="n">retval</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&quot;TranslateApiException&quot;</span><span class="p">):</span>
            <span class="k">raise</span> <span class="n">TranslateApiException</span><span class="p">(</span><span class="n">retval</span><span class="p">)</span>

        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">retval</span><span class="p">,</span> <span class="nb">basestring</span><span class="p">)</span> <span class="ow">and</span> \
                <span class="n">retval</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&quot;ArgumentException&quot;</span><span class="p">):</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">access_token</span> <span class="o">=</span> <span class="bp">None</span>
            <span class="k">raise</span> <span class="n">ArgumentException</span><span class="p">(</span><span class="n">retval</span><span class="p">)</span>

        <span class="k">return</span> <span class="n">retval</span>

    <span class="k">def</span> <span class="nf">languages</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Check languages supported&quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">create_session</span><span class="p">()</span>

        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">langs</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">langs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">lang_url</span><span class="p">,</span> <span class="p">{})</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">langs</span>

    <span class="k">def</span> <span class="nf">translate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">text</span><span class="p">,</span> <span class="n">to_lang</span><span class="p">,</span> <span class="n">from_lang</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span>
            <span class="n">content_type</span><span class="o">=</span><span class="s">&#39;text/plain&#39;</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Translates a text string from one language to another.</span>

<span class="sd">        :param text: A string representing the text to translate.</span>
<span class="sd">        :param to_lang: A string representing the language code to</span>
<span class="sd">            translate the text into.</span>
<span class="sd">        :param from_lang: A string representing the language code of the</span>
<span class="sd">            translation text. If left None the response will include the</span>
<span class="sd">            result of language auto-detection. (Default: None)</span>
<span class="sd">        :param content_type: The format of the text being translated.</span>
<span class="sd">            The supported formats are &quot;text/plain&quot; and &quot;text/html&quot;. Any HTML</span>
<span class="sd">            needs to be well-formed.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">params</span> <span class="o">=</span> <span class="p">{</span>
            <span class="s">&#39;text&#39;</span><span class="p">:</span> <span class="n">text</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s">&#39;utf8&#39;</span><span class="p">),</span>
            <span class="s">&#39;to&#39;</span><span class="p">:</span> <span class="n">to_lang</span><span class="p">,</span>
            <span class="s">&#39;contentType&#39;</span><span class="p">:</span> <span class="n">content_type</span><span class="p">,</span>
            <span class="s">&#39;category&#39;</span><span class="p">:</span> <span class="s">&#39;general&#39;</span><span class="p">,</span>
            <span class="p">}</span>
        <span class="k">if</span> <span class="n">from_lang</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
            <span class="n">params</span><span class="p">[</span><span class="s">&#39;from&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">from_lang</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">translate_url</span><span class="p">,</span> <span class="n">params</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">translate_array</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">texts</span><span class="p">,</span> <span class="n">to_lang</span><span class="p">,</span> <span class="n">from_lang</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Translates an array of text strings from one language to another.</span>

<span class="sd">        :param texts: A list containing texts for translation.</span>
<span class="sd">        :param to_lang: A string representing the language code to </span>
<span class="sd">            translate the text into.</span>
<span class="sd">        :param from_lang: A string representing the language code of the </span>
<span class="sd">            translation text. If left None the response will include the </span>
<span class="sd">            result of language auto-detection. (Default: None)</span>
<span class="sd">        :param options: A TranslateOptions element containing the values below. </span>
<span class="sd">            They are all optional and default to the most common settings.</span>

<span class="sd">                Category: A string containing the category (domain) of the </span>
<span class="sd">                    translation. Defaults to &quot;general&quot;.</span>
<span class="sd">                ContentType: The format of the text being translated. The </span>
<span class="sd">                    supported formats are &quot;text/plain&quot; and &quot;text/html&quot;. Any </span>
<span class="sd">                    HTML needs to be well-formed.</span>
<span class="sd">                Uri: A string containing the content location of this </span>
<span class="sd">                    translation.</span>
<span class="sd">                User: A string used to track the originator of the submission.</span>
<span class="sd">                State: User state to help correlate request and response. The </span>
<span class="sd">                    same contents will be returned in the response.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">options</span> <span class="o">=</span> <span class="p">{</span>
            <span class="s">&#39;Category&#39;</span><span class="p">:</span> <span class="s">&quot;general&quot;</span><span class="p">,</span>
            <span class="s">&#39;Contenttype&#39;</span><span class="p">:</span> <span class="s">&quot;text/plain&quot;</span><span class="p">,</span>
            <span class="s">&#39;Uri&#39;</span><span class="p">:</span> <span class="s">&#39;&#39;</span><span class="p">,</span>
            <span class="s">&#39;User&#39;</span><span class="p">:</span> <span class="s">&#39;default&#39;</span><span class="p">,</span>
            <span class="s">&#39;State&#39;</span><span class="p">:</span> <span class="s">&#39;&#39;</span>
            <span class="p">}</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">options</span><span class="p">)</span>
        <span class="n">params</span> <span class="o">=</span> <span class="p">{</span>
            <span class="s">&#39;texts&#39;</span><span class="p">:</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">texts</span><span class="p">),</span>
            <span class="s">&#39;to&#39;</span><span class="p">:</span> <span class="n">to_lang</span><span class="p">,</span>
            <span class="s">&#39;options&#39;</span><span class="p">:</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">options</span><span class="p">),</span>
            <span class="p">}</span>
        <span class="k">if</span> <span class="n">from_lang</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
            <span class="n">params</span><span class="p">[</span><span class="s">&#39;from&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">from_lang</span>

        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">translate_array_url</span><span class="p">,</span> <span class="n">params</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">format_date</span><span class="p">():</span>
    <span class="s">&quot;Return a date string in required format&quot;</span>
    <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s">&quot;%Y-%m-</span><span class="si">%d</span><span class="s"> %R+0200&quot;</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">ctime</span><span class="p">()))</span>

<span class="k">def</span> <span class="nf">first_pass</span><span class="p">(</span><span class="n">items</span><span class="p">,</span> <span class="n">thestring</span><span class="p">):</span>
    <span class="s">&quot;replace </span><span class="si">%(xxx)s</span><span class="s"> vars&quot;</span>
    <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">items</span><span class="p">:</span>
        <span class="n">thestring</span> <span class="o">=</span> <span class="n">thestring</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="s">&#39;|^^|&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">thestring</span>

<span class="k">def</span> <span class="nf">second_pass</span><span class="p">(</span><span class="n">items</span><span class="p">,</span> <span class="n">thestring</span><span class="p">):</span>
    <span class="s">&quot;replace </span><span class="si">%s</span><span class="s"> with actual </span><span class="si">%(xxx)s</span><span class="s">&quot;</span>
    <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">items</span><span class="p">:</span>
        <span class="n">thestring</span> <span class="o">=</span> <span class="n">thestring</span>\
                    <span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;|^^|&#39;</span><span class="p">,</span> <span class="n">item</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>\
                    <span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;| ^ ^ |&#39;</span><span class="p">,</span> <span class="n">item</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">thestring</span>

<span class="k">def</span> <span class="nf">getpofs</span><span class="p">(</span><span class="n">matched</span><span class="p">,</span> <span class="n">dirname</span><span class="p">,</span> <span class="n">files</span><span class="p">):</span>
    <span class="s">&quot;utility to get po files&quot;</span>
    <span class="n">matched</span><span class="o">.</span><span class="n">extend</span><span class="p">([</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">dirname</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
                    <span class="k">for</span> <span class="n">filename</span> <span class="ow">in</span> <span class="n">files</span>
                    <span class="k">if</span> <span class="n">filename</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s">&#39;.po&#39;</span><span class="p">)])</span>

<span class="k">def</span> <span class="nf">get_lang</span><span class="p">(</span><span class="n">dirname</span><span class="p">):</span>
    <span class="s">&quot;Get the language from directory name&quot;</span>
    <span class="k">return</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">basename</span><span class="p">(</span>
                <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span>
                    <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">dirname</span><span class="p">)</span>
                <span class="p">)</span>
            <span class="p">)</span>

<span class="k">def</span> <span class="nf">process</span><span class="p">(</span><span class="n">translator</span><span class="p">,</span> <span class="n">raw_entry</span><span class="p">,</span> <span class="n">language</span><span class="p">,</span> <span class="n">sentry</span><span class="p">,</span> <span class="n">regex</span><span class="p">):</span>
    <span class="s">&quot;Process and Translate the string&quot;</span>
    <span class="n">languages_bidi</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;he&quot;</span><span class="p">,</span> <span class="s">&quot;ar&quot;</span><span class="p">,</span> <span class="s">&quot;fa&quot;</span><span class="p">,</span> <span class="s">&quot;yi&quot;</span><span class="p">]</span>
    <span class="n">found</span> <span class="o">=</span> <span class="n">regex</span><span class="o">.</span><span class="n">findall</span><span class="p">(</span><span class="n">raw_entry</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">found</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">language</span> <span class="ow">in</span> <span class="n">languages_bidi</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">None</span>
        <span class="n">raw_entry</span> <span class="o">=</span> <span class="n">first_pass</span><span class="p">(</span><span class="n">found</span><span class="p">,</span> <span class="n">raw_entry</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span> <span class="o">&gt;=</span> <span class="n">sentry</span><span class="p">:</span>
        <span class="k">print</span> <span class="s">&quot;Renewing token&quot;</span>
        <span class="n">translator</span><span class="o">.</span><span class="n">get_access_token</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
        <span class="n">sentry</span> <span class="o">=</span> <span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span> <span class="o">+</span>
                <span class="n">datetime</span><span class="o">.</span><span class="n">timedelta</span><span class="p">(</span><span class="n">minutes</span><span class="o">=</span><span class="mi">8</span><span class="p">))</span>
    <span class="n">new_entry</span> <span class="o">=</span> <span class="n">translator</span><span class="o">.</span><span class="n">translate</span><span class="p">(</span><span class="n">raw_entry</span><span class="p">,</span> <span class="n">language</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">found</span><span class="p">:</span>
        <span class="n">new_entry</span> <span class="o">=</span> <span class="n">second_pass</span><span class="p">(</span><span class="n">found</span><span class="p">,</span> <span class="n">new_entry</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">new_entry</span>

<span class="k">def</span> <span class="nf">createps</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="n">client_id</span><span class="p">,</span> <span class="n">api_key</span><span class="p">,</span> <span class="n">meta</span><span class="p">,</span> <span class="n">default_lang</span><span class="p">):</span>
    <span class="s">&quot;update po file&quot;</span>
    <span class="n">do_save</span> <span class="o">=</span> <span class="bp">False</span>
    <span class="n">trans</span> <span class="o">=</span> <span class="n">Translator</span><span class="p">(</span><span class="n">client_id</span><span class="p">,</span> <span class="n">api_key</span><span class="p">)</span>
    <span class="k">print</span> <span class="s">&quot;Processing: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">filename</span>
    <span class="n">pobj</span> <span class="o">=</span> <span class="n">pofile</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
    <span class="n">lang</span> <span class="o">=</span> <span class="n">get_lang</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>

    <span class="k">if</span> <span class="p">(</span><span class="ow">not</span> <span class="n">lang</span> <span class="ow">in</span> <span class="n">trans</span><span class="o">.</span><span class="n">languages</span><span class="p">()</span> <span class="ow">or</span> <span class="n">lang</span> <span class="o">==</span> <span class="n">default_lang</span><span class="p">)</span> <span class="ow">and</span> <span class="n">lang</span> <span class="o">!=</span> <span class="s">&#39;zh&#39;</span><span class="p">:</span>
        <span class="k">print</span> <span class="s">&quot;Language: </span><span class="si">%s</span><span class="s"> not supported by API&quot;</span> <span class="o">%</span> <span class="n">lang</span>
        <span class="k">return</span>

    <span class="k">try</span><span class="p">:</span>
        <span class="n">match_re</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s">r&#39;((?:%\([^\W]{1,}\)(?:s|d))|(?:{{\w+}}))&#39;</span><span class="p">)</span>
        <span class="n">sentry</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span> <span class="o">+</span> <span class="n">datetime</span><span class="o">.</span><span class="n">timedelta</span><span class="p">(</span><span class="n">minutes</span><span class="o">=</span><span class="mi">8</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">lang</span> <span class="o">==</span> <span class="s">&#39;zh&#39;</span><span class="p">:</span>
            <span class="n">lang</span> <span class="o">=</span> <span class="s">&#39;zh-CHS&#39;</span>
        <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="n">pobj</span><span class="o">.</span><span class="n">untranslated_entries</span><span class="p">():</span>
            <span class="k">try</span><span class="p">:</span>
                <span class="n">msgstr</span> <span class="o">=</span> <span class="n">process</span><span class="p">(</span><span class="n">trans</span><span class="p">,</span> <span class="n">entry</span><span class="o">.</span><span class="n">msgid</span><span class="p">,</span> <span class="n">lang</span><span class="p">,</span> <span class="n">sentry</span><span class="p">,</span> <span class="n">match_re</span><span class="p">)</span>
                <span class="k">if</span> <span class="n">entry</span><span class="o">.</span><span class="n">msgid_plural</span><span class="p">:</span>
                    <span class="k">if</span> <span class="n">msgstr</span><span class="p">:</span>
                        <span class="n">entry</span><span class="o">.</span><span class="n">msgstr_plural</span><span class="p">[</span><span class="s">&#39;0&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">msgstr</span>
                    <span class="n">msgstr_plural</span> <span class="o">=</span> <span class="n">process</span><span class="p">(</span><span class="n">trans</span><span class="p">,</span> <span class="n">entry</span><span class="o">.</span><span class="n">msgid_plural</span><span class="p">,</span>
                                            <span class="n">lang</span><span class="p">,</span> <span class="n">sentry</span><span class="p">,</span> <span class="n">match_re</span><span class="p">)</span>
                    <span class="k">if</span> <span class="n">msgstr_plural</span><span class="p">:</span>
                        <span class="n">entry</span><span class="o">.</span><span class="n">msgstr_plural</span><span class="p">[</span><span class="s">&#39;1&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">msgstr_plural</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="k">if</span> <span class="n">msgstr</span><span class="p">:</span>
                        <span class="n">entry</span><span class="o">.</span><span class="n">msgstr</span> <span class="o">=</span> <span class="n">msgstr</span>
                <span class="n">do_save</span> <span class="o">=</span> <span class="bp">True</span>
            <span class="k">except</span> <span class="p">(</span><span class="n">TranslateApiException</span><span class="p">,</span> <span class="n">ArgumentOutOfRangeException</span><span class="p">),</span> <span class="n">ermsg</span><span class="p">:</span>
                <span class="k">print</span> <span class="s">&#39;Error occured: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="n">ermsg</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">do_save</span><span class="p">:</span>
            <span class="n">pobj</span><span class="o">.</span><span class="n">metadata</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">meta</span><span class="p">)</span>
            <span class="n">pobj</span><span class="o">.</span><span class="n">metadata</span><span class="p">[</span><span class="s">&#39;PO-Revision-Date&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">format_date</span><span class="p">()</span>
            <span class="n">pobj</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
    <span class="k">except</span> <span class="n">ArgumentException</span><span class="p">,</span> <span class="n">errstr</span><span class="p">:</span>
        <span class="k">print</span> <span class="s">&quot;Access Error: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="n">errstr</span><span class="p">)</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="c"># Run tings mon</span>

    <span class="n">CLIENT_ID</span> <span class="o">=</span> <span class="s">&#39;xxxxx&#39;</span>
    <span class="n">API_KEY</span> <span class="o">=</span> <span class="s">&#39;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&#39;</span>

    <span class="n">metadata</span> <span class="o">=</span> <span class="p">{</span>
        <span class="s">&#39;Report-Msgid-Bugs-To&#39;</span><span class="p">:</span> <span class="s">&#39;baruwa@lists.baruwa.org&#39;</span><span class="p">,</span>
        <span class="s">&#39;Last-Translator&#39;</span><span class="p">:</span> <span class="s">&#39;Andrew Colin Kissa &lt;andrew@topdog.za.net&gt;&#39;</span><span class="p">,</span>
        <span class="s">&#39;Generated-By&#39;</span><span class="p">:</span> <span class="s">&#39;auto-translate.py 0.0.1&#39;</span><span class="p">,</span>
        <span class="s">&#39;Language-Team&#39;</span><span class="p">:</span> <span class="s">&#39;Baruwa Project&#39;</span><span class="p">,</span>
    <span class="p">}</span>

    <span class="n">usage</span> <span class="o">=</span> <span class="s">&quot;usage: %prog directory&quot;</span>
    <span class="n">parser</span> <span class="o">=</span> <span class="n">OptionParser</span><span class="p">(</span><span class="n">usage</span><span class="p">)</span>
    <span class="n">parser</span><span class="o">.</span><span class="n">add_option</span><span class="p">(</span><span class="s">&#39;-s&#39;</span><span class="p">,</span> <span class="s">&#39;--source&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="s">&quot;source_lang&quot;</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="s">&quot;en&quot;</span><span class="p">)</span>
    <span class="n">opts</span><span class="p">,</span> <span class="n">arguments</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span>

    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">arguments</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">parser</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">&quot;Please specify the directory to process&quot;</span><span class="p">)</span>

    <span class="n">directory</span> <span class="o">=</span> <span class="n">arguments</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">directory</span><span class="p">):</span>
        <span class="n">parser</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">&quot;Directory: </span><span class="si">%s</span><span class="s"> does not exist&quot;</span> <span class="o">%</span> <span class="n">directory</span><span class="p">)</span>

    <span class="k">try</span><span class="p">:</span>        
        <span class="n">pofiles</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">walk</span><span class="p">(</span><span class="n">directory</span><span class="p">,</span> <span class="n">getpofs</span><span class="p">,</span> <span class="n">pofiles</span><span class="p">)</span>
        <span class="n">_</span> <span class="o">=</span> <span class="p">[</span><span class="n">createps</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">CLIENT_ID</span><span class="p">,</span> <span class="n">API_KEY</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span> <span class="n">opts</span><span class="o">.</span><span class="n">source_lang</span><span class="p">)</span>
            <span class="k">for</span> <span class="n">path</span> <span class="ow">in</span> <span class="n">pofiles</span><span class="p">]</span>
    <span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span>
        <span class="k">print</span> <span class="s">&quot;</span><span class="se">\n</span><span class="s">CTRL-C pressed, exiting&quot;</span>
</pre></div>

<h2>Usage</h2>
<p>You need to obtain an access token from the Azure Marketplace instructions can be
found <a href="http://msdn.microsoft.com/en-us/library/hh454950.aspx">here</a></p>
<p>Set the <code>CLIENT_ID</code> and <code>API_KEY</code> variables in the script to the values you
obtain from Azure DataMarket.</p>
<p>Then point the script to the directory containing the <code>PO</code> files you want to translate
and let it do its thing.</p>
<pre><code>/auto-translate.py &lt;directory&gt;
</code></pre>
<h2>Download</h2>
<p>You can download the script from <a href="https://github.com/akissa/auto-translate">github</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Boot into single user mode on various unixes</title>
      <link>http://www.topdog.za.net/2013/01/24/boot-into-single-user-mode-on-various-unixes</link>
      <pubDate>Thu, 24 Jan 2013 07:40:00 SAST</pubDate>
      <category><![CDATA[Sysadmin]]></category>
      <category><![CDATA[Tips]]></category>
      <category><![CDATA[Unix]]></category>
      <category><![CDATA[Linux]]></category>
      <guid isPermaLink="true">http://www.topdog.za.net/2013/01/24/boot-into-single-user-mode-on-various-unixes</guid>
      <description>Boot into single user mode on various unixes</description>
      <content:encoded><![CDATA[<h2>Linux/Grub</h2>
<p>Press <code>a</code> to append to the boot options then add <code>single</code></p>
<pre><code>grub append&gt; ro root=LABEL=/ single
</code></pre>
<h2>Solaris/OpenBoot PROM</h2>
<p>Press <code>L1+a</code> or <code>STOP+a</code> to enter OpenBoot PROM then type</p>
<pre><code>boot -s
</code></pre>
<h2>AIX</h2>
<p>Select <code>maintanance</code> mode from the boot menu or type <code>telinit S</code> on
a running machine</p>
<h2>HP-UX</h2>
<p>Interrupt the boot process when prompted and at the prompt type
<code>boot pri isl</code> to get the ISL prompt that allows you to boot into
single user mode. At the ISL prompt type</p>
<pre><code>ISL&gt; prompt: hpux -iS /stand/vmunix
</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>How to update man keywords database</title>
      <link>http://www.topdog.za.net/2013/01/16/how-to-update-man-keywords-database</link>
      <pubDate>Wed, 16 Jan 2013 07:40:00 SAST</pubDate>
      <category><![CDATA[Centos]]></category>
      <category><![CDATA[Ubuntu]]></category>
      <category><![CDATA[Sysadmin]]></category>
      <category><![CDATA[Unix]]></category>
      <category><![CDATA[RHEL]]></category>
      <category><![CDATA[Linux]]></category>
      <category><![CDATA[Tips]]></category>
      <guid isPermaLink="true">http://www.topdog.za.net/2013/01/16/how-to-update-man-keywords-database</guid>
      <description>How to update man keywords database</description>
      <content:encoded><![CDATA[<p>Man keywords database allow you to search for man pages using keywords,
the database needs to be updated when ever man pages are added or removed.</p>
<p>This is how you do it for various *nix types.</p>
<h2>Debian/Ubuntu/SUSE</h2>
<pre><code>mandb
</code></pre>
<h2>RHEL/CENTOS/SL/Fedora</h2>
<pre><code>makewhatis
</code></pre>
<h2>AIX/Solaris/HP-UX</h2>
<pre><code>catman -w
</code></pre>]]></content:encoded>
    </item>
  </channel>
</rss>
