<?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>feisley &#187; Coding</title>
	<atom:link href="http://feisley.com/category/coding/feed/" rel="self" type="application/rss+xml" />
	<link>http://feisley.com</link>
	<description>programming with a side of life</description>
	<lastBuildDate>Thu, 15 Apr 2010 07:33:58 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Blackberry eScreen Keygen</title>
		<link>http://feisley.com/2009/09/26/blackberry-escreen-keygen/</link>
		<comments>http://feisley.com/2009/09/26/blackberry-escreen-keygen/#comments</comments>
		<pubDate>Sat, 26 Sep 2009 23:19:35 +0000</pubDate>
		<dc:creator>Jacob Feisley</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[BlackBerry]]></category>
		<category><![CDATA[eScreen]]></category>
		<category><![CDATA[reverse engineering]]></category>

		<guid isPermaLink="false">http://feisley.com/?p=3548</guid>
		<description><![CDATA[As an avid BlackBerry user I always love to see what new things I can make it do.  One of the more interesting parts is the Engineering Screen or &#8220;eScreen&#8221; within the OS. However you need a special key to unlock it.
RIM has the keygen published on their website but you need a password to [...]]]></description>
			<content:encoded><![CDATA[<p>As an avid BlackBerry user I always love to see what new things I can make it do.  One of the more interesting parts is the Engineering Screen or &#8220;eScreen&#8221; within the OS. However you need a special key to unlock it.</p>
<p>RIM has the keygen published on their website but you need a password to get to it (Perhaps it is for partners only?) You can see the site here: <a href="https://www.blackberry.com/EngineeringScreens/">https://www.blackberry.com/EngineeringScreens/</a></p>
<p>Earlier this year a few websites published their own keygen to compute the unlock code. Much to my dismay, however, none of them decided to share exactly how they did this. With that, I decided to discover the unlock code myself and publish the results. <span id="more-3548"></span></p>
<p>The unlock code is actually a simple HMAC digest with a SHA1 variant. The trick is knowing what data to throw at the algorithm to produce the proper unlock code. The data used includes:</p>
<ol>
<li>The BlackBerry device PIN</li>
<li>The application version (including parentheses if provided)</li>
<li>The current uptime of the device in seconds</li>
<li>The unlock duration</li>
<li>The secret sauce</li>
</ol>
<p>The relevant data needed was found by inspecting &#8220;net.rim.device.internal.EScreens.EngScreenSecurity&#8221;, however, I will not go into the details of that here. Once I found the unlock duration codes and the secret key, it was just a matter of putting them into a standard HMAC hash function and out came the unlock code.</p>
<p>In order to use an unlock code, you simply visit the &#8220;Help Me!&#8221; screen by pressing alt+shift+H on your BlackBerry device to get the necessary information, generate a code, and then type it directly into the Help Me screen. No characters will be echoed, but if you enter it correctly, the screen with change over to the &#8220;Engineering Screen&#8221; main page. Do note it is possible to make some changes in the &#8220;eScreen&#8221; that could cause your phone to operate improperly or even break completely so do proceed with changing values at your own risk.</p>
<p>Now I wont point fingers at the various people that have already discovered how this is done but refused to share the code or details with anyone. They are what prompted me to undertake this project in the first place. With that, I give you the Python source code to my basic unlock code keygen:</p>
<p><br class="spacer_" /></p>

<div class="wp_syntax"><div 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;">import</span> <span style="color: #dc143c;">hmac</span>
<span style="color: #ff7700;font-weight:bold;">import</span> hashlib
&nbsp;
pin = <span style="color: #483d8b;">'ffaa0000'</span>            <span style="color: #808080; font-style: italic;"># Device PIN                [XXXXXXXX]</span>
app = <span style="color: #483d8b;">'4.6.0.100 (233)'</span>     <span style="color: #808080; font-style: italic;"># OS Application version    [n.n.n.n (n)]</span>
uptime = <span style="color: #483d8b;">'12345'</span>            <span style="color: #808080; font-style: italic;"># Uptime in seconds             </span>
duration = <span style="color: #ff4500;">30</span>               <span style="color: #808080; font-style: italic;"># Duration for key to last  [1, 3, 6, 15, or 30]</span>
&nbsp;
lifetime = <span style="color: black;">&#123;</span>
 <span style="color: #ff4500;">1</span>: <span style="color: #483d8b;">&quot;&quot;</span>,
 <span style="color: #ff4500;">3</span>: <span style="color: #483d8b;">&quot;Hello my baby, hello my honey, hello my rag time gal&quot;</span>,
 <span style="color: #ff4500;">7</span>: <span style="color: #483d8b;">&quot;He was a boy, and she was a girl, can I make it any more obvious?&quot;</span>,
 <span style="color: #ff4500;">15</span>: <span style="color: #483d8b;">&quot;So am I, still waiting, for this world to stop hating?&quot;</span>,
 <span style="color: #ff4500;">30</span>: <span style="color: #483d8b;">&quot;I love myself today, not like yesterday. I'm cool, I'm calm, I'm gonna be okay&quot;</span>
<span style="color: black;">&#125;</span>
&nbsp;
secret = <span style="color: #483d8b;">'Up the time stream without a TARDIS'</span>
&nbsp;
data = pin + app + uptime + lifetime<span style="color: black;">&#91;</span>duration<span style="color: black;">&#93;</span>
<span style="color: #008000;">hash</span> = <span style="color: #dc143c;">hmac</span>.<span style="color: #dc143c;">new</span><span style="color: black;">&#40;</span>secret, data, digestmod = hashlib.<span style="color: black;">sha1</span><span style="color: black;">&#41;</span>
key = <span style="color: #008000;">hash</span>.<span style="color: black;">hexdigest</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span>:<span style="color: #ff4500;">8</span><span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> key</pre></div></div>

<p>Weighing in at only 25 lines, this shows how simple the algorithm actually is if one only knows how to put it together. If you want a packaged online tool, then by all means check out the other published keygens, but if you are curious how the codes actually are generated (like I was) feel free to take, use, and share this code at your will.</p>
]]></content:encoded>
			<wfw:commentRss>http://feisley.com/2009/09/26/blackberry-escreen-keygen/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Add a Little Privacy to Google Latitude</title>
		<link>http://feisley.com/2009/08/04/add-a-little-privacy-to-google-latitude/</link>
		<comments>http://feisley.com/2009/08/04/add-a-little-privacy-to-google-latitude/#comments</comments>
		<pubDate>Tue, 04 Aug 2009 12:52:32 +0000</pubDate>
		<dc:creator>Jacob Feisley</dc:creator>
				<category><![CDATA[Google]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[LBS]]></category>
		<category><![CDATA[privacy]]></category>

		<guid isPermaLink="false">http://feisley.com/?p=3496</guid>
		<description><![CDATA[This title must sound very ironic given that the whole purpose of Google Latitude is to reduce privacy. I am not saying this is a bad thing, just that telling people where you are right now is less private than not telling them.
Recently, Google took the reduction of privacy a little further by allowing you [...]]]></description>
			<content:encoded><![CDATA[<p>This title must sound very ironic given that the whole purpose of Google Latitude is to reduce privacy. I am not saying this is a bad thing, just that telling people where you are right now is less private than not telling them.</p>
<p>Recently, Google took the reduction of privacy a little further by allowing you to setup a web site badge for Latitude. Up until this point, you could only share your location with select friends, however, now you can share it with the whole world via your website, blog, etc. I do use this, so you can spy on <a href="http://feisley.com/contact/location">my location</a> if you wish.</p>
<p><span id="more-3496"></span></p>
<p>But to the privacy elements shall we&#8230; When you generate a badge, Google gives you a snippet of HTML code that looks like this:</p>
<p><br class="spacer_" /></p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">&lt;!-- Google Public Location Badge --&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;iframe</span> <span style="color: #000066;">src</span>=<span style="color: #ff0000;">&quot;http://www.google.com/latitude/apps/badge/api?user=1234567890&amp;type=iframe&amp;maptype=roadmap&quot;</span> <span style="color: #000066;">width</span>=<span style="color: #ff0000;">&quot;180&quot;</span> <span style="color: #000066;">frameborder</span>=<span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #000066;">height</span>=<span style="color: #ff0000;">&quot;300&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/iframe<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #808080; font-style: italic;">&lt;!-- To disable location sharing, you *must* visit http://www.google.com/latitude/apps/badge and disable the Google Public Location badge. Removing this code snippet is not enough! --&gt;</span></pre></div></div>

<p>This works fine as is if you place it on your site, however, that number there (1234567890) is actually your API &#8220;username&#8221; and given inspecting this from your site, any user could simply place your position on their site or access the API by other programmatic methods. Notice Google&#8217;s warning that to disable it, you have to disable the badge globally via their site, but what if you just don&#8217;t want some people using your badge or plan to put it on a password protected area of your site&#8230; This is where a little privacy can help.</p>
<p>What I did for my site is use some PHP code to add a layer of abstraction to the Google Latitude API. It requests the content server side and displays it without ever revealing my Latitude user id. I then include my own PHP page within an iframe just as i would have the Google snippet and that&#8217;s it. Here is the simple PHP code to do this:</p>
<p><br class="spacer_" /></p>
<p><strong>location.php</strong></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000088;">$url</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;http://www.google.com/latitude/apps/badge/api?user=1234567890&amp;type=iframe&amp;maptype=roadmap&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$content</span> <span style="color: #339933;">=</span> <span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">print</span> <span style="color: #000088;">$content</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>The resulting PHP page will generate a map that fills the entire browser. Then simply add an iframe that references that PHP script and your desired width and height and boom, no one can inspect your user id and you have added a little privacy back to Google Latitude.</p>
<p><br class="spacer_" /></p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;iframe</span> <span style="color: #000066;">src</span>=<span style="color: #ff0000;">&quot;location.php&quot;</span> <span style="color: #000066;">width</span>=<span style="color: #ff0000;">&quot;650&quot;</span> <span style="color: #000066;">frameborder</span>=<span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #000066;">height</span>=<span style="color: #ff0000;">&quot;480&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/iframe<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>P.S. For the advanced users out there you can also do some creative things with the &#8220;$content&#8221; object within PHP such as inject your own CSS or even remove elements of the badge that you don&#8217;t want on your site since Google gives very limited customization to this.</p>
]]></content:encoded>
			<wfw:commentRss>http://feisley.com/2009/08/04/add-a-little-privacy-to-google-latitude/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Voice and Asterisk</title>
		<link>http://feisley.com/2009/07/29/google-voice-and-asterisk/</link>
		<comments>http://feisley.com/2009/07/29/google-voice-and-asterisk/#comments</comments>
		<pubDate>Wed, 29 Jul 2009 17:27:56 +0000</pubDate>
		<dc:creator>Jacob Feisley</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[asterisk]]></category>
		<category><![CDATA[Gizmo5]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[SIP]]></category>
		<category><![CDATA[voip]]></category>

		<guid isPermaLink="false">http://feisley.com/?p=3436</guid>
		<description><![CDATA[Many months back Paul Marks and I looked into how to integrate Google Voice and Asterisk. Inbound calling was simple as you direct your Google Voice account to a Gizmo5 number and Asterisk integrates with the open SIP standard that Gizmo5 uses.
However, our task was to be able to make outbound calls without the need [...]]]></description>
			<content:encoded><![CDATA[<p>Many months back <a href="http://pmarks.net">Paul Marks</a> and I looked into how to integrate Google Voice and Asterisk. Inbound calling was simple as you direct your Google Voice account to a Gizmo5 number and Asterisk integrates with the open SIP standard that Gizmo5 uses.</p>
<p>However, our task was to be able to make outbound calls without the need to use the web interface to place the call. What essentially had to happen is when you dialed a number on your SIP phone, Asterisk would have to talk to the Google Voice site and handle the call setup for you.</p>
<p><span id="more-3436"></span></p>
<p><strong>***UPDATE***: I worked with Ward Mundy of <a href="http://nerdvittles.com/">Nerd Vittles</a> who put togeather a complete solution for both Asterisk 1.4 and 1.6. Additionally we are now using<a href="http://code.google.com/p/pygooglevoice/"> pyGoogleVoice</a> which is a more complete library than Paul&#8217;s script below. For the full write up, check out: <a href="http://nerdvittles.com/?p=635">http://nerdvittles.com/?p=635</a></strong></p>
<p>Paul then created a Python AGI (Asterisk Gateway Interface) script. It integrates into your dial plan and allows for the call to be made. The logic flow is as follows:</p>
<ol>
<li>You pick up your SIP phone and make a call.</li>
<li>Asterisk receives your call and the google-voice-dialout.agi script is called.</li>
<li>The script contacts Google Voice and initiates a call based on the number passed to asterisk.</li>
<li>Google Voice then dials your Gizmo5 number which rings into Asterisk.</li>
<li>Asterisk identifies this call by its caller id and the script binds your outbound call and the incoming call from Google</li>
<li>Google proceeds to call out to your destination.</li>
<li>Call is connected!</li>
</ol>
<p>Now a few caveats to this approach. As Paul&#8217;s script is essentially<span style="text-decoration: line-through;"> screen scraping</span> using unpublished API&#8217;s to the Google Voice application, any changes made to their web API could break this script. (As he notes in the script comments) At any rate, at the time of writing it works and the script is available for download here, <a href="http://feisley.com/wp-content/uploads/2009/07/google-voice-dialout.agi">google-voice-dialout.agi</a>, or shown below for reference.</p>
<p>When I get some more time, I will post details how to integrate this into an Asterisk dialplan and other features.</p>
<p><br class="spacer_" /></p>

<div class="wp_syntax"><div 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: #808080; font-style: italic;"># google-voice-dialout.agi</span>
<span style="color: #808080; font-style: italic;"># Paul Marks (http://pmarks.net)</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># This is an Asterisk 1.6 script to place outgoing calls through Google Voice.</span>
<span style="color: #808080; font-style: italic;"># It will automatically sign into the web interface, and submit a click2call</span>
<span style="color: #808080; font-style: italic;"># request through your registered Gizmo number.  Asterisk can then answer</span>
<span style="color: #808080; font-style: italic;"># the incoming call, and Bridge() it into your original outgoing call.</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># I deduced the click2call sequence by using the &quot;Live HTTP Headers&quot; Firefox</span>
<span style="color: #808080; font-style: italic;"># plugin.  If the website changes too much, this script will probably stop</span>
<span style="color: #808080; font-style: italic;"># working, so don't use it for anything too important.</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># This assumes you've already configured Asterisk to receive Gizmo calls.</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># This rule will redirect outbound calls to this script:</span>
<span style="color: #808080; font-style: italic;">#   exten =&gt; _1NXXNXXXXXX,1,AGI(google-voice-dialout.agi)</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># This rule will connect the inbound GV/Gizmo calls:</span>
<span style="color: #808080; font-style: italic;">#   exten =&gt; s/6502650000,1,Bridge(${DB_DELETE(gv_dialout/channel)}, p)</span>
<span style="color: #808080; font-style: italic;">#              ^-- Put your 10-digit Google Voice number here.</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># To test this script from the command line without Asterisk, type the</span>
<span style="color: #808080; font-style: italic;"># following.  Be sure to type a few linefeeds at the end:</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;">#   $ ./google-voice-dialout.agi</span>
<span style="color: #808080; font-style: italic;">#   agi_channel:</span>
<span style="color: #808080; font-style: italic;">#   agi_dnid: 18004664411</span>
<span style="color: #808080; font-style: italic;">#</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Put your Google login and Gizmo number here:</span>
USERNAME = <span style="color: #483d8b;">&quot;username@gmail.com&quot;</span>
PASSWORD = <span style="color: #483d8b;">&quot;password&quot;</span>
GIZMO_NUMBER = <span style="color: #483d8b;">&quot;17475555555&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">httplib</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">urllib</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">time</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Error<span style="color: black;">&#40;</span><span style="color: #008000;">Exception</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> ReadAgiEnvironment<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    env = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
        line = <span style="color: #dc143c;">sys</span>.<span style="color: black;">stdin</span>.<span style="color: #dc143c;">readline</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">strip</span><span style="color: black;">&#40;</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> line:
            <span style="color: #ff7700;font-weight:bold;">break</span>
        key, data = line.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">':'</span><span style="color: black;">&#41;</span>
        env<span style="color: black;">&#91;</span>key.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span> = data.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> env
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> SendAgi<span style="color: black;">&#40;</span><span style="color: #dc143c;">cmd</span><span style="color: black;">&#41;</span>:
    <span style="color: #dc143c;">sys</span>.<span style="color: black;">stdout</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;%s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #dc143c;">cmd</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">sys</span>.<span style="color: black;">stdout</span>.<span style="color: black;">flush</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">sys</span>.<span style="color: black;">stdin</span>.<span style="color: #dc143c;">readline</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> SimpleCookieJar<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    cookie_re = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">&quot;(?i)set-cookie: (<span style="color: #000099; font-weight: bold;">\w</span>+)=([^;]+).*&quot;</span><span style="color: black;">&#41;</span>
    <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><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">cookies</span> = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> addCookies<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, response<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">for</span> header <span style="color: #ff7700;font-weight:bold;">in</span> response.<span style="color: black;">msg</span>.<span style="color: black;">headers</span>:
            m = <span style="color: #008000;">self</span>.<span style="color: black;">cookie_re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span>header<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> m:
                <span style="color: #ff7700;font-weight:bold;">continue</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">cookies</span><span style="color: black;">&#91;</span>m.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span> = m.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> get<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;; &quot;</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;%s=%s&quot;</span> <span style="color: #66cc66;">%</span> kv <span style="color: #ff7700;font-weight:bold;">for</span> kv <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">self</span>.<span style="color: black;">cookies</span>.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> GVClickToCall<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    USER_AGENT = <span style="color: #483d8b;">&quot;google-voice-dialout.agi/1.1&quot;</span>
&nbsp;
    <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>, username, password, via, dial<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">username</span> = username
        <span style="color: #008000;">self</span>.<span style="color: black;">password</span> = password
        <span style="color: #008000;">self</span>.<span style="color: black;">via</span> = via
        <span style="color: #008000;">self</span>.<span style="color: black;">dial</span> = dial
        <span style="color: #008000;">self</span>.<span style="color: black;">cj</span> = SimpleCookieJar<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">h</span> = <span style="color: #dc143c;">httplib</span>.<span style="color: black;">HTTPSConnection</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;www.google.com&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">login</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">placeCall</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">logout</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> login<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span>sys.<span style="color: black;">stderr</span>, <span style="color: #483d8b;">&quot;Logging in.&quot;</span>
        postdata = <span style="color: #dc143c;">urllib</span>.<span style="color: black;">urlencode</span><span style="color: black;">&#40;</span><span style="color: black;">&#123;</span> <span style="color: #483d8b;">&quot;Email&quot;</span>: <span style="color: #008000;">self</span>.<span style="color: black;">username</span>,
                                      <span style="color: #483d8b;">&quot;Passwd&quot;</span>: <span style="color: #008000;">self</span>.<span style="color: black;">password</span> <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">doRequest</span><span style="color: black;">&#40;</span>
            method=<span style="color: #483d8b;">&quot;POST&quot;</span>, url=<span style="color: #483d8b;">&quot;/accounts/ServiceLoginAuth&quot;</span>,
            body=postdata,
            headers=<span style="color: black;">&#123;</span> <span style="color: #483d8b;">&quot;Content-Type&quot;</span>: <span style="color: #483d8b;">&quot;application/x-www-form-urlencoded&quot;</span> <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Start at https://www.google.com/voice, and collect cookies as we</span>
        <span style="color: #808080; font-style: italic;"># follow all the redirects.</span>
        PREFIX = <span style="color: #483d8b;">&quot;https://www.google.com/&quot;</span>
        location = <span style="color: #483d8b;">&quot;/voice&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>:
            response, html = <span style="color: #008000;">self</span>.<span style="color: black;">doRequest</span><span style="color: black;">&#40;</span>
                method=<span style="color: #483d8b;">&quot;GET&quot;</span>, url=location,
                headers=<span style="color: black;">&#123;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
&nbsp;
            location = response.<span style="color: black;">getheader</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;location&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> location:
                <span style="color: #808080; font-style: italic;"># No more redirects, yay!</span>
                <span style="color: #ff7700;font-weight:bold;">break</span>
&nbsp;
            <span style="color: #808080; font-style: italic;"># All redirects should fall within the same domain.</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> location.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span>PREFIX<span style="color: black;">&#41;</span>:
                <span style="color: #ff7700;font-weight:bold;">raise</span> Error<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Unexpected redirect: %s&quot;</span> <span style="color: #66cc66;">%</span> location<span style="color: black;">&#41;</span>
            location = location<span style="color: black;">&#91;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span>PREFIX<span style="color: black;">&#41;</span>-<span style="color: #ff4500;">1</span>:<span style="color: black;">&#93;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Scrape magic _rnr_se value from the HTML.</span>
        m = <span style="color: #dc143c;">re</span>.<span style="color: black;">search</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'name=&quot;_rnr_se&quot; type=&quot;hidden&quot; value=&quot;([^&quot;]+)&quot;'</span>, html<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> m:
            <span style="color: #ff7700;font-weight:bold;">raise</span> Error<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Can't find _rnr_se.  Not logged in?&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">magic_rnr_se</span> = m.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> placeCall<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span>sys.<span style="color: black;">stderr</span>, <span style="color: #483d8b;">&quot;Calling %s via %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">dial</span>, <span style="color: #008000;">self</span>.<span style="color: black;">via</span><span style="color: black;">&#41;</span>
        postdata = <span style="color: #dc143c;">urllib</span>.<span style="color: black;">urlencode</span><span style="color: black;">&#40;</span><span style="color: black;">&#123;</span> <span style="color: #483d8b;">&quot;outgoingNumber&quot;</span>: <span style="color: #008000;">self</span>.<span style="color: black;">dial</span>,
                                      <span style="color: #483d8b;">&quot;forwardingNumber&quot;</span>: <span style="color: #008000;">self</span>.<span style="color: black;">via</span>,
                                      <span style="color: #483d8b;">&quot;_rnr_se&quot;</span>: <span style="color: #008000;">self</span>.<span style="color: black;">magic_rnr_se</span> <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
        response, http = <span style="color: #008000;">self</span>.<span style="color: black;">doRequest</span><span style="color: black;">&#40;</span>
            method=<span style="color: #483d8b;">&quot;POST&quot;</span>, url=<span style="color: #483d8b;">&quot;/voice/call/connect&quot;</span>,
            body=postdata,
            headers=<span style="color: black;">&#123;</span> <span style="color: #483d8b;">&quot;Content-Type&quot;</span>: <span style="color: #483d8b;">&quot;application/x-www-form-urlencoded&quot;</span> <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span>sys.<span style="color: black;">stderr</span>, <span style="color: #483d8b;">&quot;Dial response:&quot;</span>, http
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> logout<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">doRequest</span><span style="color: black;">&#40;</span>
            method=<span style="color: #483d8b;">&quot;GET&quot;</span>, url=<span style="color: #483d8b;">&quot;/accounts/Logout&quot;</span>,
            headers=<span style="color: black;">&#123;</span> <span style="color: #483d8b;">&quot;Connection&quot;</span>: <span style="color: #483d8b;">&quot;close&quot;</span> <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span>sys.<span style="color: black;">stderr</span>, <span style="color: #483d8b;">&quot;Logged out.&quot;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> doRequest<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, headers, <span style="color: #66cc66;">**</span>kw<span style="color: black;">&#41;</span>:
        headers<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;User-agent&quot;</span><span style="color: black;">&#93;</span> = <span style="color: #008000;">self</span>.<span style="color: black;">USER_AGENT</span>
        headers<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;Cookie&quot;</span><span style="color: black;">&#93;</span> = <span style="color: #008000;">self</span>.<span style="color: black;">cj</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">h</span>.<span style="color: black;">request</span><span style="color: black;">&#40;</span>headers=headers, <span style="color: #66cc66;">**</span>kw<span style="color: black;">&#41;</span>
        response = <span style="color: #008000;">self</span>.<span style="color: black;">h</span>.<span style="color: black;">getresponse</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">cj</span>.<span style="color: black;">addCookies</span><span style="color: black;">&#40;</span>response<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> response, response.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    env = ReadAgiEnvironment<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span>sys.<span style="color: black;">stderr</span>, env
&nbsp;
    agi_channel = env<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;agi_channel&quot;</span><span style="color: black;">&#93;</span>
    agi_dnid = env<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;agi_dnid&quot;</span><span style="color: black;">&#93;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Write the channel ID to Asterisk's database, so it can be accessed</span>
    <span style="color: #808080; font-style: italic;"># by the incoming call when it arrives.</span>
    SendAgi<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;database put gv_dialout channel %s&quot;</span> <span style="color: #66cc66;">%</span> agi_channel<span style="color: black;">&#41;</span>
&nbsp;
    SendAgi<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;answer&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        GVClickToCall<span style="color: black;">&#40;</span>username=USERNAME, password=PASSWORD,
                      dial=agi_dnid, via=GIZMO_NUMBER<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Asterisk should patch in the incoming call while we're asleep.</span>
        <span style="color: #dc143c;">time</span>.<span style="color: black;">sleep</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">finally</span>:
        SendAgi<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;hangup&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://feisley.com/2009/07/29/google-voice-and-asterisk/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Kindle Books, without the Kindle&#8230;</title>
		<link>http://feisley.com/2009/03/05/kindle-books-without-the-kindle/</link>
		<comments>http://feisley.com/2009/03/05/kindle-books-without-the-kindle/#comments</comments>
		<pubDate>Thu, 05 Mar 2009 14:47:20 +0000</pubDate>
		<dc:creator>Jacob Feisley</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[drm]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[iPod]]></category>
		<category><![CDATA[kindle]]></category>
		<category><![CDATA[mobipocket]]></category>

		<guid isPermaLink="false">http://feisley.com/?p=2375</guid>
		<description><![CDATA[As everyone is well aware, Amazon has one of the largest eBook libraries available for sale. The only caveat to this was that you had to purchase their $350 Kindle / Kindle 2 Reader before you could take advantage of these books. All that has changed now with the release of the iPod/iPhone app for [...]]]></description>
			<content:encoded><![CDATA[<p>As everyone is well aware, Amazon has one of the largest eBook libraries available for sale. The only caveat to this was that you had to purchase their $350 Kindle / Kindle 2 Reader before you could take advantage of these books. All that has changed now with the release of the iPod/iPhone app for Kindle books. Now you can register your iPod or iPhone with Amazon and purchase Kindle books for it. But there is more&#8230; You can also manage to extract the purchased books from the iPod / iPhone and take off the DRM so you can use your book on any of your other readers.</p>
<p><span id="more-2375"></span></p>
<p><em>DISCLAIMER: Stripping DRM from eBooks treads heavily on the DMCA. Any instructions here should be considered to be for educational purposes only. Therefore you are responsible for how you use this information.</em></p>
<p>Here were the steps I followed to free my books from my iPod:</p>
<p><strong>Step 1</strong></p>
<p>First you need an iPod or iPhone. I find it is easiest and most cross-platform to use a jailbroken device as that makes this process all the easier.</p>
<p><strong>Step 2</strong></p>
<p>Install the Kindle app from the App Store</p>
<p><strong>Step 3</strong></p>
<p>When you open the app for the first time, you will be prompted for your Amazon.com username and password. Once you enter this your device will be registered and you can purchase books from the Amazon Kindle Book Store.</p>
<p><strong>Step 4</strong></p>
<p><em><strong>UPDATE</strong>: A</em><em>mazon has taken the &#8220;security by obscurity&#8221; route and removed the UUID from the website. You can still find it easily by connecting your iPod/iPhone to iTunes and when you see the Serial Number, click on the word &#8220;Serial Number&#8221; and it will change to &#8220;Identifier&#8221; this is the string you are looking for. Here is a picture for clarity.</em></p>
<p><strong><img class="alignnone size-full wp-image-2391" title="ipod-serial-uuid" src="http://feisley.com/wp-content/uploads/2009/03/ipod-serial-uuid.png" alt="ipod-serial-uuid" width="530" height="296" /><br />
 </strong></p>
<p><strong>Step 5</strong></p>
<p>Purchase your favorite book from the Store ;-) Your purchase will be automatically downloaded by the app once you are connected to the internet.</p>
<p><strong>Step 6</strong></p>
<p>This is the tricky part. Now that you have the books purchased and on your iPod/iPhone you will need to get them off. There are two routes here. A few folks over at <a href="http://mobileread.com">MobileRead.com</a> mentioned that you can use the <a href="http://supercrazyawesome.com/">iPhone Backup Extractor</a>, however, at this time it is only for Mac OS X.</p>
<p><em><strong>UPDATE</strong></em><em>: fugislider informed me there is also a <a href="http://www.reincubate.com/labs/iphone-backup-extractor-how-extract-files-iphone-backup-windows/">iPhone Backup Extractor version for Windows and Linux</a> you can use as well if you don&#8217;t want to jailbreak your device.</em></p>
<p>The better solution in my opinion is to use a jailbroken phone and copy the books direct from the device using SCP or similar mechanism. I wont go into the details of how to jailbreak or SCP files as that is covered by several other articles&#8230;</p>
<p>The eBooks are stored as .prc files which are DRM&#8217;d MobiPocket format. (Same as the Kindle, no surprises there) You can find all of them in this folder on the iPod / iPhone:</p>
<p><br class="spacer_" /></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="" style="font-family:monospace;">/var/mobile/Applications/<span class="br0">&#123;</span>Appplication UUID<span class="br0">&#125;</span>/Documents/eBooks</pre></td></tr></table></div>

<p>There are also some .mbp files in the directory, which seem to be unneeded for extracting the books. Also note they have some crazy names that don&#8217;t appear to correlate to their actual title, so you will have to rely on software such as <a href="http://calibre.kovidgoyal.net/">Calibre</a> to read the headers and tell you what files you have.</p>
<p><strong>Step 7</strong></p>
<p>Well, there is no longer a Step 7. Sorry.</p>
<p>On March 11, I received notice from Amazon.com to remove the instructions relating to removal of the DRM from the books. I left the first 6 steps intact since they do not relate to breaking any portion of the DRM and are in full compliance with the DMCA. If you want to remove the DRM from these books you will have to find instructions elsewhere.</p>
<p><strong>The End!</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://feisley.com/2009/03/05/kindle-books-without-the-kindle/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Trac &#8211; Part 2</title>
		<link>http://feisley.com/2009/03/02/trac-part-2/</link>
		<comments>http://feisley.com/2009/03/02/trac-part-2/#comments</comments>
		<pubDate>Mon, 02 Mar 2009 15:08:50 +0000</pubDate>
		<dc:creator>Jacob Feisley</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Trac]]></category>

		<guid isPermaLink="false">http://feisley.com/?p=2347</guid>
		<description><![CDATA[In Part 1 I mentioned that I had recently selected Trac as my project management tool of choice. It is fairly feature complete for my needs and where a core feature is lacking, there is usually a plugin to facilitate it.
In this part I will describe how I setup this system. I had specific goals [...]]]></description>
			<content:encoded><![CDATA[<p>In Part 1 I mentioned that I had recently selected Trac as my project management tool of choice. It is fairly feature complete for my needs and where a core feature is lacking, there is usually a plugin to facilitate it.</p>
<p>In this part I will describe how I setup this system. I had specific goals in mind so this may need to be adapted for your needs. Additionally I will briefly cover the Subversion setup that was required to make this work.</p>
<h3><span id="more-2347"></span></h3>
<h2>Goals</h2>
<ol>
<li>Multiple Trac projects needed to be hosted</li>
<li>Seamless integration to the Subversion server</li>
<li>Simple adding of new projects without the need for configuration changes</li>
<li>Single Sign On (SSO) for all projects (see #5)</li>
<li>Centralized authentication for all projects (one account is all you need)</li>
<li>Per project authorization / permissions</li>
</ol>
<h2>Requirements / Supplies</h2>
<ol>
<li>Ubuntu Server 8.04.1 LTS</li>
<li>Subversion 1.5</li>
<li>Python 2.5</li>
<li>Setuptools (for Python)</li>
<li>Trac 0.11.3</li>
<li>Apache 2
<ol>
<li>mod_wsgi</li>
<li>mod_dav</li>
</ol>
</li>
</ol>
<h2>Preliminary Notes<br />
</h2>
<p>In order to attain the goals I mentioned before, I determined the easiest way to proceed was to use subdomains for the &#8220;sections&#8221; and then subdirectories for the projects. For example:</p>
<p><strong>http://dev.mydomain.com/&lt;project1&gt;   <br />
http://dev.mydomain.com/&lt;project2&gt; </strong></p>
<p>and</p>
<p><strong>http://svn.mydomain.com/&lt;project1&gt;   <br />
http://svn.mydomain.com/&lt;project2&gt; </strong></p>
<p>Additionally, it is important to note that I will be applying authentication at the root of each subdomain (thus there is no anonymous access to the Trac instances. If this is not what you want, it is possible to modify your Apache configuration to allow anonymous access.</p>
<p>When I am referring to configuration names and paths, I will use <em> </em> to represent any generic project name for which you may have a Trac and Subversion instance.</p>
<h2>Procedure</h2>
<p>First of all we will need to prepare space on the server for the Trac instances as well as the Subversion repository. These can really be anywhere but for my server I chose the following:</p>
<p>Subversion Repositories: <strong>/var/repos/<em> </em></strong><br />
 Trac Instances: <strong>/var/trac/<em> </em></strong></p>
<p><br class="spacer_" /></p>
<p>Next we will setup the Apache2 server for the Subversion server. I will assume you are familiar with making a new VirtualHost within Apache and will just go over the snippet for the Subversion handler.</p>
<p><br class="spacer_" /></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="text" style="font-family:monospace;">&lt;Location /&gt;
    AuthType Basic
    AuthName &quot;My Subversion Server&quot;
    AuthUserFile /var/trac/htpasswd
    Require valid-user
&nbsp;
    DAV svn
    SVNParentPath /var/repos/
    SVNListParentPath on
    AuthzSVNAccessFile /etc/apache2/subversion.authz
&lt;/Location&gt;</pre></td></tr></table></div>

<p>The first section deals with enforcing authentication. Notice that it points to <em>/var/trac/htpasswd</em> which will be the global password file for all Trac instances and Subversion.</p>
<p>Also, I used the SVNParentPath to point to /var/repos so that it will automatically map any repository under that path without having to change the VirtualHost.</p>
<p>Notice also the AuthzSVNAccessFile. This is the permissions file for the Subversion server. If you specify this, then you can grant read and write permissions to the repository on a user by user basis. <em>NOTE: If you choose to omit this, then anyone that is in your htpasswd file will be able to write to the repository. </em>For the sake of consistance I placed the global authz file in /var/apache2/</p>
<p>Here is an example &#8220;subversion.authz&#8221; file:</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
</pre></td><td class="code"><pre class="" style="font-family:monospace;"># Groups
<span class="br0">&#91;</span>groups<span class="br0">&#93;</span>
admin = myusername
&nbsp;
# Global permissions <span class="br0">&#40;</span> &quot;* = &quot;  means default is no access<span class="br0">&#41;</span>
<span class="br0">&#91;</span>/<span class="br0">&#93;</span>
* =
@admin = rw
&nbsp;
# Permissions for &lt;project1&gt;
<span class="br0">&#91;</span>&lt;project1&gt;:/<span class="br0">&#93;</span>
&nbsp;
# Permissions for &lt;project2&gt;
<span class="br0">&#91;</span>&lt;project2&gt;:/<span class="br0">&#93;</span>
user1 = rw
user2 = r</pre></td></tr></table></div>

<p>So, now that we have the Subversion hosting working via apache, we will setup the Trac instance. Start by making sure you have the latest version of Trac installed. At the time of writing this was Trac 0.11.3:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">easy_install Trac</pre></div></div>

<p>Next, you will need the following WSGI handler code to dispatch requests to the Trac server.<br class="spacer_" /></p>
<p>Create a file &#8220;trac.wsgi&#8221; in /var/www/wsgi/</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> trac.<span style="color: black;">web</span>.<span style="color: black;">main</span>
&nbsp;
application = trac.<span style="color: black;">web</span>.<span style="color: black;">main</span>.<span style="color: black;">dispatch_request</span></pre></td></tr></table></div>

<p>After we have this file, we will add the following code to the VirdualHost for trac.mydomain.com:</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
</pre></td><td class="code"><pre class="" style="font-family:monospace;">WSGIScriptAlias / /var/www/wsgi/trac.wsgi
&nbsp;
&lt;Location /&gt;
    WSGIApplicationGroup %<span class="br0">&#123;</span>GLOBAL<span class="br0">&#125;</span>
    Order deny,allow
    Allow from all
&nbsp;
    SetEnv trac.env_parent_dir /var/trac
&nbsp;
    AuthType Basic
    AuthName &quot;My Trac Server&quot;
    AuthUserFile /var/trac/htpasswd
    Require valid-user
&lt;/Location&gt;</pre></td></tr></table></div>

<p>Once you have added that restart the web server and you should have the Trac site enabled.</p>
<p><br class="spacer_" /></p>
<p>Now we will make a new project called &#8220;TestProject&#8221;. The following commands will do that:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>repos
&nbsp;
<span style="color: #c20cb9; font-weight: bold;">mkdir</span> TestProject
<span style="color: #c20cb9; font-weight: bold;">svnadmin</span> create TestProject
&nbsp;
<span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>trac
<span style="color: #c20cb9; font-weight: bold;">mkdir</span> TestProject
trac-admin TestProject initenv
&nbsp;
<span style="color: #c20cb9; font-weight: bold;">chown</span> www-data:www-data <span style="color: #660033;">-R</span> <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>repos
<span style="color: #c20cb9; font-weight: bold;">chown</span> www-data:www-data <span style="color: #660033;">-R</span> <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>trac</pre></td></tr></table></div>

<p>This will create the Subversion repository as well as initialize the Trac instance.  Note the last two lines where we set the owner of the Subversion and Trac instances to &#8220;www-data&#8221; this is so that the Apache process owns the files and manages all permissions to them.</p>
<h2>Next Steps</h2>
<p>The next steps will be to configure your Trac instances. The config for each instance will be located at &#8220;/var/trac/&lt;project&gt;/config/trac.ini&#8221;. If you used the SVN authz file as I did, there is a place in the config file to specify this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="" style="font-family:monospace;"><span class="br0">&#91;</span>trac<span class="br0">&#93;</span>
authz_file = /etc/apache2/subversion.authz
authz_module_name = &lt;project&gt;
# Where &lt;project&gt; is the repository name.</pre></td></tr></table></div>

<p>This configuratuion will ensure that even if someone has trac browser access, they still must have svn autorization otherwise the browser will display a permission denied error.</p>
<h2>The End!</h2>
<p>I hope you found this useful. If you have any comments or find any errors in my tutorial, please leave me a comment so that I may answer you or fix the issue.</p>
]]></content:encoded>
			<wfw:commentRss>http://feisley.com/2009/03/02/trac-part-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PyAMF 0.4</title>
		<link>http://feisley.com/2009/01/05/pyamf-04/</link>
		<comments>http://feisley.com/2009/01/05/pyamf-04/#comments</comments>
		<pubDate>Tue, 06 Jan 2009 04:56:28 +0000</pubDate>
		<dc:creator>Jacob Feisley</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[PyAMF]]></category>

		<guid isPermaLink="false">http://feisley.com/?p=2211</guid>
		<description><![CDATA[Well almost&#8230;
We just release PyAMF 0.4-RC2 yesterday! While it is not quite the final version, this is a huge step for the project and includes a ton of updates and features.
Some highlighted features include:

cPyAMF &#8211; An implementation of PyAMF serialization that results in tremendous speedups.
SQLAlchemy Adapter &#8211; Adapter for the popular Python Database ORM.
Improved Google [...]]]></description>
			<content:encoded><![CDATA[<p>Well almost&#8230;</p>
<p>We just release PyAMF 0.4-RC2 yesterday! While it is not quite the final version, this is a huge step for the project and includes a ton of updates and features.</p>
<p>Some highlighted features include:</p>
<ul>
<li>cPyAMF &#8211; An implementation of PyAMF serialization that results in tremendous speedups.</li>
<li>SQLAlchemy Adapter &#8211; Adapter for the popular Python Database ORM.</li>
<li>Improved Google AppEngine Adapter &#8211; makes deploying Flex/Flash apps on Google&#8217;s new service even easier.</li>
</ul>
<p>You can see our official announcement on the <a href="http://blog.pyamf.org/archives/pyamf-04rc2-released">PyAMF Blog</a>.</p>
<p>Currently PyAMF 0.4 is in the Release Candidate stage so we are testing and getting feedback. The release candidate and final version (when it is ready) are available for download <a href="http://pyamf.org/wiki/Download#Download">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://feisley.com/2009/01/05/pyamf-04/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Site Updates (continued)</title>
		<link>http://feisley.com/2008/12/21/site-updates-continued/</link>
		<comments>http://feisley.com/2008/12/21/site-updates-continued/#comments</comments>
		<pubDate>Sun, 21 Dec 2008 07:24:45 +0000</pubDate>
		<dc:creator>Jacob Feisley</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[website]]></category>

		<guid isPermaLink="false">http://feisley.com/?p=2061</guid>
		<description><![CDATA[As I was in the coding mood from my changes last night to my website/blog, I took the next logical step and completely overhauled the entire theme. After heavily modifying a theme I think I have the general look I am wanting.
Some of the notable changes include:

Grouped categories into logical groups.
Better search with context provided [...]]]></description>
			<content:encoded><![CDATA[<p>As I was in the coding mood from my changes last night to my website/blog, I took the next logical step and completely overhauled the entire theme. After heavily modifying a theme I think I have the general look I am wanting.</p>
<p>Some of the notable changes include:</p>
<ul>
<li>Grouped categories into logical groups.</li>
<li>Better search with context provided along with titles.</li>
<li>New logo based on old site logo + favicon (with a touch of red)</li>
<li>A few other interesting features that I may take advantage of in the near future</li>
</ul>
<p>Everything should be in place, if anyone notices some stray PHP code or CSS trying to escape, please let me know so I can put it in its place.</p>
]]></content:encoded>
			<wfw:commentRss>http://feisley.com/2008/12/21/site-updates-continued/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google App Engine</title>
		<link>http://feisley.com/2008/04/08/google-app-engine/</link>
		<comments>http://feisley.com/2008/04/08/google-app-engine/#comments</comments>
		<pubDate>Wed, 09 Apr 2008 03:41:19 +0000</pubDate>
		<dc:creator>Jacob Feisley</dc:creator>
				<category><![CDATA[Google]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[App Engine]]></category>
		<category><![CDATA[PyAMF]]></category>

		<guid isPermaLink="false">http://feisley.com/?p=32</guid>
		<description><![CDATA[
Last night, Google launched App Engine which allows developers to create web applications and publish them on Google&#8217;s infrastructure. The exciting part of the App Engine in my eyes is that the language you use to develop on it is Python. Google provides many API&#8217;s to interface the Python programming language with the various services [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone size-thumbnail wp-image-33" title="Google App Engine" src="http://feisley.com/wp-content/uploads/2008/04/app-engine-150x150.png" alt="" width="150" height="150" /></p>
<p>Last night, Google launched <a href="http://appengine.google.com">App Engine</a> which allows developers to create web applications and publish them on Google&#8217;s infrastructure. The exciting part of the App Engine in my eyes is that the language you use to develop on it is Python. Google provides many API&#8217;s to interface the Python programming language with the various services they offer. You can authenticate via Google accounts, use Bigtable to store data, and use Google Aps to bind your application to your own domain. They opened the initial &#8220;Preview Release&#8221; to the first 10,000 developers to sign up. From the looks of it, those 10,000 spots filled up within the first few hours of the launch.</p>
<p>I was fortunate to be one of the first to sign up and got my account last night. I created a basic hello world application to test and overall the system seems very easy to use. My demo is at <a href="http://labs.appspot.com">http://labs.appspot.com</a>.</p>
<p>I also created an account for the <a href="http://pyamf.org">PyAMF</a> project and we were able to get a PyAMF echo server running on App Engine. It is currently located at: <a href="http://ae.pyamf.org">http://ae.pyamf.org</a> We are continuing to work with it today and tomorrow to write up some examples and a How-to to get people started quickly. We will continue to add more examples to the site as time progresses and we get everything documented.</p>
]]></content:encoded>
			<wfw:commentRss>http://feisley.com/2008/04/08/google-app-engine/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Hydra Preview</title>
		<link>http://feisley.com/2008/04/01/hydra-preview/</link>
		<comments>http://feisley.com/2008/04/01/hydra-preview/#comments</comments>
		<pubDate>Tue, 01 Apr 2008 19:06:34 +0000</pubDate>
		<dc:creator>Jacob Feisley</dc:creator>
				<category><![CDATA[Flex]]></category>
		<category><![CDATA[Hydra Labs]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Hydra]]></category>
		<category><![CDATA[PyAMF]]></category>
		<category><![CDATA[RIA]]></category>
		<category><![CDATA[Twisted]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://feisley.com/?p=29</guid>
		<description><![CDATA[With the public announcement of Hydra EMS being announced any day now, I thought I would give those of you that have been following its development a sneak preview of the UI and some of the new features we have added recently.

The most noticeable addition to Hydra recently has been the addition of the Flex [...]]]></description>
			<content:encoded><![CDATA[<p>With the public announcement of Hydra EMS being announced any day now, I thought I would give those of you that have been following its development a sneak preview of the UI and some of the new features we have added recently.</p>
<p><span id="more-29"></span></p>
<p>The most noticeable addition to Hydra recently has been the addition of the Flex UI. <a href="http://www.adobe.com/go/flex">Flex</a> is an open source Flash framework from Adobe that allows for rapid development of Rich Internet Applications (RIAs). Behind the Flex UI is the powerful <a href="http://twistedmatrix.com">Twisted</a> framework that powers the data back end. Communication between Flex and Twisted is handled by the <a href="http://pyamf.org/">PyAMF</a> library. PyAMF is an implementation of Adobe&#8217;s Action Message Format (AMF) for Python. This library allows for data to be exchanged in a binary form which is many times faster than the traditional XML mechanism.</p>
<p>Enough talk, lets get to the show! Here is a shot of the CPE LiveGrid module from Hydra. LiveGrid handles adding, searching, modifying, and deleting of CPE&#8217;s and assets withing the system. This module was originally based on an XML API, however, after changing to PyAMF speeds over doubled when running:</p>
<p><a href="http://feisley.com/wp-content/uploads/2008/04/live_grid.png"><img class="alignnone size-full wp-image-30" title="CPE LiveGrid" src="http://feisley.com/wp-content/uploads/2008/04/live_grid.png" alt="Hydra CPE LiveGrid" width="500" height="276" /></a></p>
<p>The second example here is of the CPE LiveDiag module. This allows for real time graphing and analysis of a CPE&#8217;s performance in the network and will allow network administrators to make faster diagnostics when problems occur. This module was also a port from its original XML interface to the PyAMF library:</p>
<p><a href="http://feisley.com/wp-content/uploads/2008/04/live_diag.png"><img class="alignnone size-full wp-image-31" title="CPE LiveDiag" src="http://feisley.com/wp-content/uploads/2008/04/live_diag.png" alt="Hydra CPE LiveGrid" width="500" height="276" /></a></p>
<p>These are just a few of the new interfaces coming in the release of Hydra EMS.</p>
]]></content:encoded>
			<wfw:commentRss>http://feisley.com/2008/04/01/hydra-preview/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web File Listings</title>
		<link>http://feisley.com/2008/03/28/web-file-listings/</link>
		<comments>http://feisley.com/2008/03/28/web-file-listings/#comments</comments>
		<pubDate>Sat, 29 Mar 2008 01:22:37 +0000</pubDate>
		<dc:creator>Jacob Feisley</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[template]]></category>
		<category><![CDATA[theme]]></category>

		<guid isPermaLink="false">http://feisley.com/?p=17</guid>
		<description><![CDATA[I finally made my web file listings integrate with my web site theme. Normally web file directories look pretty very ugly and this certainly was an improvement. Apache has built-in support for header and footer files to be wrapped around the file listing. You can even wrap PHP or other scripting languages around it if [...]]]></description>
			<content:encoded><![CDATA[<p>I finally made my web file listings integrate with my web site theme. Normally web file directories look <span style="text-decoration: line-through;">pretty</span> very ugly and this certainly was an improvement. Apache has built-in support for header and footer files to be wrapped around the file listing. You can even wrap PHP or other scripting languages around it if you configure Apache properly. I chose to use PHP as it can easily pull in template changes from the main site.</p>
<p><span id="more-17"></span></p>
<p>The first step is to make a template directory under your site root for the template. Then add your PHP files to the directory and make the following .htaccess file:</p>
<p>source/theme/apache/.htaccess</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="text" style="font-family:monospace;">AddType text/html .php
AddHandler application/x-httpd-php .php
Options -indexes</pre></td></tr></table></div>

<p><br class="spacer_" /></p>
<p>The AddHandler statement tells Apache to process the PHP files when used as a template.</p>
<p>Next I added the Directory Indexing statements to the main .htaccess file under the root of the site:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="text" style="font-family:monospace;">Options +Indexes
IndexOptions +FancyIndexing +SuppressDescription +SuppressHTMLPreamble +XHTML
IndexOptions +FoldersFirst +IgnoreCase +NameWidth=*
HeaderName /source/theme/apache/header.php
ReadmeName /source/theme/apache/footer.php</pre></td></tr></table></div>

<p>And it works! You can see it in action at <a href="http://feisley.com/python/">http://feisley.com/python/</a></p>
<p><br class="spacer_" /></p>
<p><br class="spacer_" /></p>
]]></content:encoded>
			<wfw:commentRss>http://feisley.com/2008/03/28/web-file-listings/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

