<?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; Projects</title>
	<atom:link href="http://feisley.com/category/projects/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>Thank You Kayako</title>
		<link>http://feisley.com/2009/12/21/thank-you-kayako/</link>
		<comments>http://feisley.com/2009/12/21/thank-you-kayako/#comments</comments>
		<pubDate>Mon, 21 Dec 2009 22:22:30 +0000</pubDate>
		<dc:creator>Jacob Feisley</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[dtella]]></category>
		<category><![CDATA[kayako]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[Purdue]]></category>

		<guid isPermaLink="false">http://feisley.com/?p=3558</guid>
		<description><![CDATA[I would like to thank Kayako for their generous open source license of SupportSuite for the Dtella project. We were running into trouble with users emailing one person for help and this will help having a larger group of people available to better support our new users.
I have used Kayako&#8217;s products commercially for years both [...]]]></description>
			<content:encoded><![CDATA[<p>I would like to thank <a href="http://kayako.com">Kayako</a> for their generous open source license of SupportSuite for the <a href="http://dtella.org">Dtella</a> project. We were running into trouble with users emailing one person for help and this will help having a larger group of people available to better support our new users.</p>
<p>I have used Kayako&#8217;s products commercially for years both at <a href="http://darkhorsenetworks.com">Dark Horse Networks</a> and <a href="http://hydralabs.com">Hydra Labs</a>, so it seems a excellent extension to our open source project as well.</p>
<p>Our new support desk is located at: <a href="http://support.dtella.org">http://support.dtella.org</a></p>
<p><br class="spacer_" /></p>
<p>Thanks Kayako!</p>
]]></content:encoded>
			<wfw:commentRss>http://feisley.com/2009/12/21/thank-you-kayako/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Free Time</title>
		<link>http://feisley.com/2009/12/19/free-time/</link>
		<comments>http://feisley.com/2009/12/19/free-time/#comments</comments>
		<pubDate>Sat, 19 Dec 2009 23:59:17 +0000</pubDate>
		<dc:creator>Jacob Feisley</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://feisley.com/?p=3563</guid>
		<description><![CDATA[If it seems like I have been MIA for the better part of 3 months and have been neglecting my site and other online projects, that would be correct. Recent projects at work have kept me very busy and I have had little time to tinker with my site and the various projects I usually [...]]]></description>
			<content:encoded><![CDATA[<p>If it seems like I have been MIA for the better part of 3 months and have been neglecting my site and other online projects, that would be correct. Recent projects at work have kept me very busy and I have had little time to tinker with my site and the various projects I usually work on.</p>
<p>Fortunately, I have a small break in the form of Christmas coming up. This will allow me to catch up on some much needed maintenance as well as possibly get into some new projects as well.</p>
<p>A list of potential areas to go into soon (to remind me when I forget) ((and in no particular order)):</p>
<ul>
<li>Buildbot</li>
<li>Flickr</li>
<li>Projects at Work (the unclassified ones, of course)</li>
<li>Dynamic DNS</li>
<li>Kindle</li>
<li>Integration</li>
<li>Anything else?</li>
</ul>
<p><br class="spacer_" /></p>
<p>Should be some interesting things coming soon&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://feisley.com/2009/12/19/free-time/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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>Broken LCD</title>
		<link>http://feisley.com/2009/08/12/broken-lcd/</link>
		<comments>http://feisley.com/2009/08/12/broken-lcd/#comments</comments>
		<pubDate>Thu, 13 Aug 2009 06:12:47 +0000</pubDate>
		<dc:creator>Jacob Feisley</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[broken]]></category>
		<category><![CDATA[LCD]]></category>
		<category><![CDATA[Samsung]]></category>

		<guid isPermaLink="false">http://feisley.com/?p=3524</guid>
		<description><![CDATA[My Samsung LCD of 5 years finally decided to call it quits. It didn&#8217;t so much quit as it began to flicker very quickly across the whole panel. Google indicated others seemed to have this problem and pointed to a pair of bad capacitors on the power supply. Time to tear it open&#8230;

At this point [...]]]></description>
			<content:encoded><![CDATA[<p>My Samsung LCD of 5 years finally decided to call it quits. It didn&#8217;t so much quit as it began to flicker very quickly across the whole panel. Google indicated others seemed to have this problem and pointed to a pair of bad capacitors on the power supply. Time to tear it open&#8230;</p>
<p><span id="more-3524"></span></p>
<p>At this point I have not had much time to tinker with the internals so for now I will simply post my pictures of the internals and leave digging for another day&#8230;</p>
<p>
<a href='http://feisley.com/2009/08/12/broken-lcd/img_3310/' title='IMG_3310'><img width="150" height="112" src="http://feisley.com/wp-content/uploads/2009/08/IMG_3310-150x112.jpg" class="attachment-thumbnail" alt="" title="IMG_3310" /></a>
<a href='http://feisley.com/2009/08/12/broken-lcd/img_3311/' title='IMG_3311'><img width="150" height="112" src="http://feisley.com/wp-content/uploads/2009/08/IMG_3311-150x112.jpg" class="attachment-thumbnail" alt="" title="IMG_3311" /></a>
<a href='http://feisley.com/2009/08/12/broken-lcd/img_3312/' title='IMG_3312'><img width="150" height="112" src="http://feisley.com/wp-content/uploads/2009/08/IMG_3312-150x112.jpg" class="attachment-thumbnail" alt="" title="IMG_3312" /></a>
<a href='http://feisley.com/2009/08/12/broken-lcd/img_3313/' title='IMG_3313'><img width="150" height="112" src="http://feisley.com/wp-content/uploads/2009/08/IMG_3313-150x112.jpg" class="attachment-thumbnail" alt="" title="IMG_3313" /></a>
<a href='http://feisley.com/2009/08/12/broken-lcd/img_3314/' title='IMG_3314'><img width="150" height="112" src="http://feisley.com/wp-content/uploads/2009/08/IMG_3314-150x112.jpg" class="attachment-thumbnail" alt="" title="IMG_3314" /></a>
<a href='http://feisley.com/2009/08/12/broken-lcd/img_3315/' title='IMG_3315'><img width="150" height="112" src="http://feisley.com/wp-content/uploads/2009/08/IMG_3315-150x112.jpg" class="attachment-thumbnail" alt="" title="IMG_3315" /></a>
<a href='http://feisley.com/2009/08/12/broken-lcd/img_3316/' title='IMG_3316'><img width="150" height="112" src="http://feisley.com/wp-content/uploads/2009/08/IMG_3316-150x112.jpg" class="attachment-thumbnail" alt="" title="IMG_3316" /></a>

]]></content:encoded>
			<wfw:commentRss>http://feisley.com/2009/08/12/broken-lcd/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>Wordpress Code Highlighting</title>
		<link>http://feisley.com/2009/02/13/wordpress-code-highlighting/</link>
		<comments>http://feisley.com/2009/02/13/wordpress-code-highlighting/#comments</comments>
		<pubDate>Fri, 13 Feb 2009 22:59:33 +0000</pubDate>
		<dc:creator>Jacob Feisley</dc:creator>
				<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[Coding]]></category>

		<guid isPermaLink="false">http://feisley.com/?p=2224</guid>
		<description><![CDATA[With as many people blogging on Wordpress that wish to show code snippets I would have thought some better solutions for syntax highlighting would have been available by now. Unfortunately support is limited to only a handful of 3rd party modules each of which having their own limitations or issues that must be overcome.

Here are [...]]]></description>
			<content:encoded><![CDATA[<p>With as many people blogging on Wordpress that wish to show code snippets I would have thought some better solutions for syntax highlighting would have been available by now. Unfortunately support is limited to only a handful of 3rd party modules each of which having their own limitations or issues that must be overcome.</p>
<p><span id="more-2224"></span></p>
<p>Here are the various solutions I tried along with my comments:</p>
<p><br class="spacer_" /></p>
<h3>WP-Syntax (<a href="http://wordpress.org/extend/plugins/wp-syntax/">http://wordpress.org/extend/plugins/wp-syntax/</a>)</h3>
<h3><img class="alignnone size-full wp-image-2261" title="wp_syntax" src="http://feisley.com/wp-content/uploads/2009/02/wp_syntax.png" alt="wp_syntax" width="350" height="175" /><br />
</h3>
<p>Pros:</p>
<ul>
<li>Simple to use with &lt;pre&gt; tags</li>
<li>Uses GeSHi for highlighting resulting in a wide variety of supported languages</li>
<li>Easy to copy code from the page without getting the formatting / line numbers with it</li>
</ul>
<p>Cons:</p>
<ul>
<li>Requires some minor tweaks to the CSS to get it to work (perhaps this is just my theme)</li>
</ul>
<p><br class="spacer_" /></p>
<h3>SyntaxHighlighter (<a href="http://wordpress.org/extend/plugins/syntaxhighlighter/">http://wordpress.org/extend/plugins/syntaxhighlighter/</a>)</h3>
<p><img class="alignnone size-full wp-image-2260" title="syntaxhighlighter" src="http://feisley.com/wp-content/uploads/2009/02/syntaxhighlighter.png" alt="syntaxhighlighter" width="350" height="178" /></p>
<p>Pros:</p>
<ul>
<li>The best layout of any of the plugins I tried</li>
<li>Plain and Print views for viewing the source</li>
</ul>
<p>Cons:</p>
<ul>
<li>A much more limited set of languages supported</li>
<li>Copying code from the plugin requires a special mode.</li>
</ul>
<p><br class="spacer_" /></p>
<h3>Conclusions</h3>
<p>After playing with both of these libraries and feeding them a variety of code snippets, I settled upon <strong>wp-syntax</strong>. While it did require a few modifications to the CSS to get the line numbers to match with the code, the wider variety of supported languages was the key feature for me. I also modified the CSS to match my theme for both the plugins, so out of the box they dont look quite like my pictures shown.</p>
]]></content:encoded>
			<wfw:commentRss>http://feisley.com/2009/02/13/wordpress-code-highlighting/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Trac &#8211; Part 1</title>
		<link>http://feisley.com/2009/02/01/trac-part-1/</link>
		<comments>http://feisley.com/2009/02/01/trac-part-1/#comments</comments>
		<pubDate>Sun, 01 Feb 2009 07:33:13 +0000</pubDate>
		<dc:creator>Jacob Feisley</dc:creator>
				<category><![CDATA[Hydra Labs]]></category>
		<category><![CDATA[Trac]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://feisley.com/?p=2255</guid>
		<description><![CDATA[
I recently decided to adopt Trac for my development for Hydra Labs, as well as for my personal and school projects. Trac is a Python powered development tool that includes a wiki, ticketing system, and source browser. Trac focuses on being very transparent and does not require a large process to begin using it. Additionally, [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone size-thumbnail wp-image-2256" title="trac_logo" src="http://feisley.com/wp-content/uploads/2009/02/trac_logo-150x42.png" alt="trac_logo" width="150" height="42" /></p>
<p>I recently decided to adopt <a href="http://trac.edgewall.org/">Trac</a> for my development for Hydra Labs, as well as for my personal and school projects. Trac is a Python powered development tool that includes a wiki, ticketing system, and source browser. Trac focuses on being very transparent and does not require a large process to begin using it. Additionally, it is extremely extendable using a vast array of plugins available from the <a href="http://trac-hacks.org/">Trac-Hacks</a> site.</p>
<p>My environment required a few moderate customizations because I wanted to have global authentication so that once I create an account to login to one of my projects, it would be valid for all the other ones. Also I needed to integrate authentication and authorization for the Subversion repository as well.</p>
<p>In Part 2 of this article, I will describe the complete setup process I went through to get this installed and customized to the needs of my projects.</p>
]]></content:encoded>
			<wfw:commentRss>http://feisley.com/2009/02/01/trac-part-1/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>
	</channel>
</rss>

