<?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>Tyler Oderkirk&#039;s Blog &#187; Linux</title>
	<atom:link href="http://unsyncopated.com/blog/index.php/category/linux/feed/" rel="self" type="application/rss+xml" />
	<link>http://unsyncopated.com/blog</link>
	<description>&#34;Scared money don&#039;t[sic] make money&#34;</description>
	<lastBuildDate>Thu, 27 Jan 2011 05:02:58 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Sending data via cellular voice connections with Linux</title>
		<link>http://unsyncopated.com/blog/index.php/2009/11/19/sending-data-via-cellular-voice-connections-with-linux/</link>
		<comments>http://unsyncopated.com/blog/index.php/2009/11/19/sending-data-via-cellular-voice-connections-with-linux/#comments</comments>
		<pubDate>Thu, 19 Nov 2009 10:45:03 +0000</pubDate>
		<dc:creator>Tyler</dc:creator>
				<category><![CDATA[Flickr]]></category>
		<category><![CDATA[Footnotes]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Python programming]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Shell programming]]></category>
		<category><![CDATA[Syntax highlighter]]></category>
		<category><![CDATA[Table of Contents]]></category>

		<guid isPermaLink="false">http://unsyncopated.com/blog/index.php/2009/11/20/sending-data-via-cellular-voice-connections-with-linux/</guid>
		<description><![CDATA[&#8220;A5/1 [the encryption scheme used in most cellular voice calls] has operated unchanged for the last 21 years but it has now reached its cryptographic end-of-life, engulfed by the march of Moore&#8217;s Law. However, the operational end-of-life of A5/1 may still be decades away as there are approximately 2 billion GSM subscribers, commanding about 80% of [...]]]></description>
			<content:encoded><![CDATA[<div>
<p style="padding-left: 30px;">&#8220;A5/1 [the encryption scheme used in most cellular voice calls] has operated unchanged for the last 21 years but it has now reached its cryptographic end-of-life, engulfed by the march of Moore&#8217;s Law. However, the operational end-of-life of A5/1 may still be decades away as there are approximately 2 billion GSM subscribers, commanding about 80% of the global mobile market. This would be a tough product recall indeed. A5/1 is well-positioned to become the NT of the mobile crypto world, and I see the makings of a long tail of GSM vulnerability.&#8221; - <a href="http://ch.linkedin.com/pub/luke-o-connor/1/bb6/152">Dr. Luke O&#8217;Connor</a> at <a href="http://lukenotricks.blogspot.com/2009/09/another-crack-at-open-rainbow-tables.html">NoTricks: Another crack at open Rainbow Tables for A5/1</a></p>
<div class='toc wptoc'>
<h2>Contents</h2>
<ol class='toc-odd level-1'>
	<li>
		<a href="#Introduction">Introduction</a>
	</li>
	<li>
		<a href="#The_modem__Hardware_components">The modem / Hardware components</a>
	</li>
	<li>
		<a href="#Transmitting_audio_from_a_PC_to_a_cell_phone__Software_components">Transmitting audio from a PC to a cell phone / Software components</a>
	</li>
	<li>
		<a href="#Demonstration__OKCrypto_scripts">Demonstration / OKCrypto scripts</a>
	</li>
	<li>
		<a href="#Encryption">Encryption</a>
	</li>
	<li>
		<a href="#Further_work">Further work</a>
	</li>
	<li>
		<a href="#What_I_learned">What I learned</a>
	</li>
	<li>
		<a href="#Conclusion__Download">Conclusion / Download</a>
	</li>
	<li>
		<a href="#Further_reading">Further reading</a>
	</li>
</ol>
</ol>
</ol>
</div>
<div class='wptoc-end'>&nbsp;</div>
<span id="Introduction"><h3>Introduction</h3></span>
<p>The ability to intercept and decrypt GSM cell phone conversations is now well within the reach of hobbyists.<sup>1</sup><sup>2</sup></p>
<p>My friend Scott and I were discussing this sobering fact one night and we began wondering if any systems exist which provide end-to-end encryption for this insecure link.</p>
<p>Sure, there are plenty of solutions for people with access to cellular dataconnections, but what can voice call participants use to foil eavesdroppers?</p>
<p>We didn&#8217;t find any low-cost systems so we decided to create our own. OKCrypto is the Linux-based encrypting software modem that we&#8217;ve made. It consists of two components: the modem component and crypto component.</p>
<span id="The_modem__Hardware_components"><h3>The modem / Hardware components</h3></span>
<p>We needed the ability to send data before we could try sending  encrypteddata, so the first step was to design a simple software modem.</p>
<p>Rather than executing the modem code on the cell phones themselves, I decided to host the modem code on a the sender and receiver&#8217;s Linux systems. This design provides two benefits:</p>
<ol>
<li>The modem code and crypto code has access to the rich Linux API.</li>
<li>Sensitive code and data are isolated from the both the cell phone itself and from the cell infrastructure. We have clean separation between trusted (PC) and untrusted (cell) environments.</li>
</ol>
<p>Thus, the &#8220;real work&#8221; in OKCrypto is done on the PC &#8211; the cell phones simply allow the PCs to talk to each other. See figure 1 for an overview of the hardware involved in the system. 						<div class="flickr-gallery image right"><a href="http://www.flickr.com/photos/55502932@N00/4153181728"><img class="flickr small" title="Fig. 1 - Hardware components" alt="Fig. 1 - Hardware components" src="http://farm3.static.flickr.com/2534/4153181728_a0fe8e3a63_m.jpg" /></a></div>
					</p>
<p>Conceptually, the modem is similar to the analog Plain Old Telephone Service (POTS) modems from the Bad Old Days before broadband service became popular. Instead of an audio coupler, we&#8217;re using Bluetooth to connect our PC to our phone line. Instead of custom hardware, our modem is comprised of some glue scripts and the software packages they connect &#8211; all running on a Linux PC.</p>
<p>The modem doesn&#8217;t provide an asynchronous full-duplex communication link like traditional modems. This modem&#8217;s operation is simpler: The sender&#8217;s modem dials the number of, and subsequently transmits a pre-prepared chunk of data to, the recipient&#8217;s modem. It then hangs up.</p>
<p>The modem uses Dual-tone multi-frequency (DTMF) signaling to encode the data it transmits. I chose DTMF because I was familiar with it and because Debian provides a package for <a href="http://www.baycom.org/~tom/ham/linux/multimon.html">Multimon</a>. OKCrypto uses two utilities that Multimon provides:</p>
<ol>
<li>gen &#8211; a DTMF generation utility (digits-&gt;wav file)</li>
<li>multimon &#8211; a DTMF detection utility (wav file-&gt;digits)</li>
</ol>
<span id="Transmitting_audio_from_a_PC_to_a_cell_phone__Software_components"><h3>Transmitting audio from a PC to a cell phone / Software components</h3></span>
<p>I&#8217;d been working on a few Bluetooth security projects at the time, so the Hands-Free Profile (HFP)<sup>3</sup> came immediately to mind as a convenient way to transfer audio (and any data we&#8217;ve encoded in the audio) between a PC and a cell phone during a call.</p>
<p>-flickr size=&#8221;small&#8221; float=&#8221;right&#8221;-4153181752-/flickr-In most cases HFP is used to connect a a Bluetooth phone to a Bluetooth headset so that the headset can be used to make calls via the phone. See figure 2.</p>
<p>-flickr size=&#8221;small&#8221; float=&#8221;right&#8221;-4153181518-/flickr-In the PC world, HFP is typically used to connect a desktop computer to a bluetooth headset. See figure 3. In that configuration, the PC fulfills the first of two roles mandated by the HFP specification: the Audio Gateway (AG) role. The headset fulfills the hands-free (HF) role.</p>
						<div class="flickr-gallery image right"><a href="http://www.flickr.com/photos/55502932@N00/4152393267"><img class="flickr small" title="Fig. 4 - PC ~ Cell phone" alt="Fig. 4 - PC ~ Cell phone" src="http://farm3.static.flickr.com/2737/4152393267_95526e2aaf_m.jpg" /></a></div>
					For our purposes, we need the PC to appear to be a bluetooth headset to a cell phone &#8211; the PC must fulfill the HF role. See figure 4. This is similar to how call-handling in-vehicle GPS/stereo units work.</p>
<p>Support for the HF role in <a href="http://www.bluez.org/">bluez</a>, the Linux Bluetooth stack (pronounced &#8220;blue-zee&#8221;), is just now maturing<sup>4</sup> so I went searching for a userspace implementation of the HFP protocol stack.</p>
<p>One of the best, chan_mobile, is distributed as an add-on to the popular open-source private branch exchange (PBX) <a href="http://www.asterisk.org/">Asterisk</a> system. If you configure chan_mobile to use your cell phone, Asterisk can make both outbound calls and receive inbound calls with the phone.</p>
<p>Asterisk is the largest software component of the OKCrypto modem. It not only provides a reliable HFP HF role implementation which works with a wide array of modern phones (see above), but also many essential telephony operations:</p>
<ol>
<li>Recording audio during a call. OKCrypto uses Asterisk&#8217;s built-in voicemail capabilities.</li>
<li>Transmitting audio during a call.</li>
<li>Pausing for a given time period.</li>
<li>Logging phone call details.</li>
</ol>
<p>See figure 5 for an overview of the software components in the OKCrypto system. Note that the same software is used on both the sender and receiver&#8217;s PCs.						<div class="flickr-gallery image right"><a href="http://www.flickr.com/photos/55502932@N00/4153379126"><img class="flickr small" title="Fig. 5 - Software components" alt="Fig. 5 - Software components" src="http://farm3.static.flickr.com/2521/4153379126_22a0fbc569_m.jpg" /></a></div>
					
<span id="Demonstration__OKCrypto_scripts"><h3>Demonstration / OKCrypto scripts</h3></span>
<p>Let&#8217;s look at how we can use this modem to send a 16-byte binary file over a cellular voice connection.</p>
<p>First, the sender and recipient will need to perform some set-up steps:</p>
<ol>
<li>1. Acquire a Linux-supported computer and Bluetooth adapter. I found that using a virtual machine introduces latency that bluez/btusb cannot tolerate.</li>
<li>Acquire a HFP-capable cell phone.</li>
<li>Install Linux, <a href="http://sox.sourceforge.net/">SoX</a>, Python, multimon, Asterisk, the Asterisk &#8220;add-ons&#8221;, GPG, and the OKCrypto scripts.</li>
<li>Pair cell phone with computer. Grant HFP access.</li>
<li>Configure chan_mobile</li>
<li>Start Asterisk Next, the sender can issue this command at a shell to send the file &#8216;/tmp/foo&#8217; to the recipient at 585-555-3258.
<pre class="brush: bash;">$ ./bin_to_int_seq.py /tmp/foo | ./ast_send.sh 5855553258 [...]
$ cksum /tmp/foo 668417501 16 /tmp/foo</pre>
<p>She&#8217;ll notice her PC making a call with her phone, silently transmitting the data, and disconnecting. Behind the scenes, the OKCrypto scripts will&#8230;</li>
<li>Convert the bytes in /tmp/foo to a series of decimal digits.</li>
<li>Encode the digits as DTMF tones with gen from the multimon package. 1. Increase the pitch (time-independent) to prevent any intermediary systems (esp. Asterisk) from interpreting the tones.</li>
<li>Queue the final audio file for transmission by Asterisk.</li>
</ol>
<p>The recipient will hear his phone ring once before his PC answers the call, records the audio, and disconnects. When the call is complete, Asterisk will invoke one of the OKCrypto scripts to&#8230;</p>
<ol>
<li>Decrease the pitch to yield the original DTMF tones.</li>
<li>Decode the DTMF tones to a series of decimal digits.</li>
<li>Convert the digits to a series of bytes which is written to &#8216;/tmp/bar&#8217;.
<pre class="brush: bash;">$ tr -d '\n' &lt; /tmp/newest_vm.txt | ./int_seq_to_bin.py /tmp/bar [...]
$ cksum /tmp/bar 668417501 16 /tmp/bar</pre>
</li>
</ol>
<span id="Encryption"><h3>Encryption</h3></span>
<p>Now that we can reliably send data, let&#8217;s make sure that it&#8217;s encrypted first. This turns out to be one of the simplest components of the system &#8211; many good crypto APIs are available.</p>
<p>I use <a href="http://www.gnupg.org/">GnuPG</a>:</p>
<pre class="brush: bash;">$ gpg --symmetric --force-mdc --cipher-algo AES256 filetoencrypt </pre>
<p>The `&#8211;force-mdc` option provides integrity checking &#8211; useful for handling transmission errors. Consider these GPG options carefully and make sure they fit your requirements.</p>
<span id="Further_work"><h3>Further work</h3></span>
<p>Here are a few ideas we&#8217;re pursuing for the future of this project:</p>
<ul>
<li>Moving the modem code to the cell phone. This would simplify the setup but potentially risk security.</li>
<li>Improving modem error rate. Data is often erroneously duplicated during transmission.</li>
<li>Increasing the modem throughput. The current code averages a meager 10 bytes/second.</li>
<li>Hiding the data within a steganographic channel in a normal voice conversation.</li>
<li>Incorporating GPG into the OKCrypto scripts.</li>
<li>Packaging the system as a LiveCD/Live flash drive.</li>
<li>Implementing key exchange.</li>
<li>Building an embedded device dedicated to OKCrypto.</li>
</ul>
<span id="What_I_learned"><h3>What I learned</h3></span>
<p>I gained experience in the follow areas during the design, implementation. and testing:</p>
<ul>
<li>GSM, CDMA crypto. I suspect the cellular phone industry would make a great case study in protocol security by obscurity.</li>
<li>Cellular voice codecs used by large carriers. Trivia: your calls only require ~10kbps.<sup>5</sup></li>
<li>Bluetooth HFP specification and available implementations.</li>
<li>Debugging latency tolerances in virtual machine USB &#8220;passthrough&#8221; subsystems.</li>
<li>The <a href="http://www.twilio.com/">Twilio</a> telephony API. I used Twilio when I only had one cell phone to debug with.</li>
<li>Asterisk administration.</li>
</ul>
<span id="Conclusion__Download"><h3>Conclusion / Download</h3></span>
<p>I&#8217;ve described a method to securely transmit data over any of the widely-available cell voice networks. The implementation requires only commodity hardware, open-source software, and minimal setup.</p>
<p>Be aware that transmitting data by &#8220;automated means&#8221; may violate the terms of your cellular service contract. I disclaim all liability. This information is provided for educational purposes only.</p>
<p>You can download the OKCrypto system here: http://www.unsyncopated.com/corral/okcrypto_v0.1.tar.gz</p>
<p>It is licensed under the LGPL.</p>
<span id="Further_reading"><h3>Further reading</h3></span>
<ul>
<li>You&#8217;ll find lots of links to cell security architecture articles, Bluetooth HFP implementations, and Asterisk administration web pages on the wiki at <a href="http://www.unsyncopated.com/wiki/Crypto%20Phone/Stacked%20Linux-based%20CPhone%20Brainstorming">Crypto Phone/Stacked Linux-based CPhone Brainstorming</a></li>
</ul>
<p>Update 1/13/09 - Check out some technical notes on our recent progress with a faster and more reliable modem: <a href="https://www.unsyncopated.com/wiki/OKCrypto/Progress%20Report%20for%2001-09-2010">OKCrypto/Progress Report for 01-09-2010</a></p>
</div>
<ol class="footnotes">
<li id="footnote_0_317" class="footnote"><a href="http://spectrum.ieee.org/telecom/wireless/open-source-effort-to-hack-gsm">Open-Source Effort to Hack GSM</a> John Blau &#8211; IEEE Spectrum Magazine &#8211; December 2009 issue</li>
<li id="footnote_1_317" class="footnote"><a href="https://har2009.org/program/attachments/119_GSM.A51.Cracking.Nohl.pdf">Subverting the security base of GSM</a> Karsten Nohl &#8211; Hacking at Random &#8211; 8/15/2009</li>
<li id="footnote_2_317" class="footnote"><a href="http://www.bluetooth.com/Bluetooth/Technology/Works/HFP.htm">Bluetooth Hands-Free Profile (HFP) 1.5</a> &#8211; Bluetooth Special Interest Group &#8211; 11/25/2005</li>
<li id="footnote_3_317" class="footnote"><a href="https://bugs.maemo.org/show_bug.cgi?id=2754#c1">Comment #1 on Maemo bug #2754</a> &#8211; Johan Hedberg &#8211; 1/25/2009</li>
<li id="footnote_4_317" class="footnote"><a href="http://en.wikipedia.org/w/index.php?title=Adaptive_Multi-Rate_audio_codec&amp;oldid=327719647">Adaptive Multi-Rate audio codec</a> &#8211; Wikipedia &#8211; 11/24/2009</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://unsyncopated.com/blog/index.php/2009/11/19/sending-data-via-cellular-voice-connections-with-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Creating a local mirror of Ubuntu&#8217;s most popular packages</title>
		<link>http://unsyncopated.com/blog/index.php/2009/11/04/creating-a-local-mirror-of-ubuntus-most-popular-packages/</link>
		<comments>http://unsyncopated.com/blog/index.php/2009/11/04/creating-a-local-mirror-of-ubuntus-most-popular-packages/#comments</comments>
		<pubDate>Wed, 04 Nov 2009 22:25:55 +0000</pubDate>
		<dc:creator>Tyler</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Syntax highlighter]]></category>
		<category><![CDATA[Table of Contents]]></category>

		<guid isPermaLink="false">http://unsyncopated.com/blog/index.php/2009/11/04/creating-a-local-mirror-of-ubuntus-most-popular-packages/</guid>
		<description><![CDATA[The problem You want to create local mirrors of the apt repositories that you use but you don&#8217;t have enough hard drive space to mirror every package. Or maybe you have a slow link and you don&#8217;t want to spend time downloading packages that you&#8217;re unlikely to need. The solution Only mirror packages whose popularity [...]]]></description>
			<content:encoded><![CDATA[<span id="The_problem"><h3>The problem</h3></span>
<p>You want to create local mirrors of the apt repositories that you use but you don&#8217;t have enough hard drive space to mirror every package. Or maybe you have a slow link and you don&#8217;t want to spend time downloading packages that you&#8217;re unlikely to need.</p>
<span id="The_solution"><h3>The solution</h3></span>
<p>Only mirror packages whose popularity (as reported by popcon&#8217;s &#8220;installed&#8221; metric) matches a certain threshold.</p>
<span id="The_explanation"><h3>The explanation</h3></span>
<p>I&#8217;ve been hacking without a network connection recently and one of the biggest pain points is not having access to my distro&#8217;s software package repository.</p>
<p>For example, while writing some Python screen-scraping code last week I realized I didn&#8217;t have the Python library I wanted to parse some HTML with &#8211; <a href="http://www.crummy.com/software/BeautifulSoup/">Beautiful Soup</a>. Rather than postpone my work on the script until I found a weefee signal, it would have been nice to simply install the package from a local mirror of the repository.</p>
<p>I soon discovered two common tools that can be used to create a local mirror of a repository &#8211; Frans Pop&#8217;s <a href="http://alioth.debian.org/~fjp/log/posts.html">debmirror</a> and Dmitriy Khramtsov&#8217;s <a href="http://apt-mirror.sourceforge.net/">apt-mirror</a>.</p>
<p>I chose apt-mirror, skimmed <a href="http://popey.com/blog/2006/10/24/Creating_an_Ubuntu_repository_mirror_with_apt-mirror/">Alan Pope&#8217;s handy step-by-step guide</a> and kicked off the mirror script&#8230;</p>
<pre class="brush: bash;">
$ sudo -u apt-mirror apt-mirror

[...]
52.7 GiB will be downloaded into archive.
Downloading 75 archive files using 10 threads...
</pre>
<p>ACK! That&#8217;s a lot of gibibytes.</p>
<p>Eventually I&#8217;d like a complete mirror, but for now, I only want the packages I&#8217;m likely to need. <a href="http://www.frontier.com">My broadband connection</a> isn&#8217;t as &#8220;broad&#8221; as I would like.</p>
<p>The <a href="http://popcon.debian.org/">Debian Popularity Contest</a> (&#8220;popcon&#8221;) came to mind and sure enough, Ubuntu also provides <a href="http://popcon.ubuntu.com/by_inst">a flat text file</a> containing the names of all packages sorted by the frequency with which they&#8217;re installed by users.</p>
<p>I downloaded this file and hacked up the primary apt-mirror perl script to consult the file, only mirroring binary and source packages if they meet a chosen popularity threshold.</p>
<p>Here&#8217;s the meat from <a href="http://unsyncopated.com/corral/apt-mirror-0.4.5-1ubuntu2_popcon.patch">a patch that applies cleanly to apt-mirror version 0.4.5-1ubuntu2</a>:</p>
<pre class="brush: perl;">

sub should_process {
# print &quot;should_process()\n&quot;;
my $pkg_name = shift;
my $section_name = shift;
my @popular_pkgs = @{ $_[0] };

# if the pkg isn't in the 'game' section...
if($section_name !~ /game/){
my %is_popular;
for (@popular_pkgs) { $is_popular{$_} = 1 };

if( $is_popular{$pkg_name} ) {
# print &quot;processing popular pkg: &quot; . $pkg_name . &quot;\n&quot;;
return 1;
} else {
# print &quot;skipping unpopular pkg: &quot; . $pkg_name . &quot;\n&quot;;
return 0;
}
} else {
# print &quot;skipping game pkg: &quot; . $pkg_name . &quot;\n&quot;;
return 0;
}
}

# [...]

# open our popcon database
my $db_path = &quot;/home/tz/Desktop/by_inst&quot;;
open(FILE,$db_path) or die &quot;Can't open popcon db: $!&quot;;
my @data=; # beware record separator ($/) tweak below
close FILE;
my $num_comment_lines = 11;
my $threshold = 3000;
my $cur_line;
my @popular_pkgs;
# for each of the first $threshold lines, grab pkg name
foreach $cur_line (@data[$num_comment_lines .. ($num_comment_lines + $threshold)]) {
# print &quot;cur_line: $cur_line&quot;;
my @tokens = split / +/, $cur_line;
# print &quot;pkgname: &quot; . $tokens[1] . &quot;\n&quot;;
push( @popular_pkgs, $tokens[1] );
}

# [...]

if( should_process( $lines{&quot;Package:&quot;}, $lines{&quot;Section:&quot;},@popular_pkgs ) ) {
add_url_to_download($uri . &quot;/&quot; . $lines{&quot;Directory:&quot;} . &quot;/&quot; . $file[2], $file[1]);
}
</pre>
<p>Tweak the path to the flat file (`$db_path`) and the threshold (`$threshold`!) to suit your needs.<br />
<!-- echo "As you can see, I also modified the\nscript to skip games. Games tend to be\nlarge and there aren't many that I use\noften, except perhaps cowsay(1) :]" |cowsay -f gnu --></p>
<pre> ________________________________________
/ As you can see, I also modified the    \
| script to skip games. Games tend to be |
| large and there aren't many that I use |
\ often, except perhaps cowsay(1) :]     /
 ----------------------------------------
    \               ,-----._
  .  \         .  ,'        `-.__,------._
 //   \      __\\'                        `-.
((    _____-'___))                           |
 `:='/     (alf_/                            |
 `.=|      |='                               |
    |)   O |                                  \
    |      |                               /\  \
    |     /                          .    /  \  \
    |    .-..__            ___   .--' \  |\   \  |
   |o o  |     ``--.___.  /   `-'      \  \\   \ |
    `--''        '  .' / /             |  | |   | \
                 |  | / /              |  | |   mmm
                 |  ||  |              | /| |
                 ( .' \ \              || | |
                 | |   \ \            // / /
                 | |    \ \          || |_|
                /  |    |_/         /_|
               /__/</pre>
<span id="Future_improvements"><h3>Future improvements</h3></span>
<ul>
<li>Download popcon db file, rather than expect that it already exists on disk.</li>
<li>Read desired popularity threshold from mirror.list rather than using a hard-coded value.</li>
<li>Read desired sections as above.</li>
<li>Speed holes! My perl-fu is weak.</li>
</ul>
<span id="Tips"><h3>Tips</h3></span>
<ul>
<li>I found a faster mirror half-way through creating my local mirror. Renaming `/var/spool/apt-mirror/{mirror,skel}/${OLD_MIRROR` to `/var/spool/apt-mirror/{mirror,skel}/${NEW_MIRROR}` was sufficient.</li>
<li>If you try to install a package from your local mirror which doesn&#8217;t exist, you&#8217;ll get a 404 error &#8211; nothing catastrophic happens.</li>
<li>Beware <a href="http://sourceforge.net/projects/apt-mirror/forums/forum/197335/topic/1747995">permissions issues</a>. Avoid running apt-mirror as root rather than the prescribed `apt-mirror` user.</li>
<li>debmirror has a `&#8211;exclude-deb-section` option</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://unsyncopated.com/blog/index.php/2009/11/04/creating-a-local-mirror-of-ubuntus-most-popular-packages/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Downloading photos from Facebook with Linux</title>
		<link>http://unsyncopated.com/blog/index.php/2009/11/02/downloading-photos-from-facebook-with-linux/</link>
		<comments>http://unsyncopated.com/blog/index.php/2009/11/02/downloading-photos-from-facebook-with-linux/#comments</comments>
		<pubDate>Tue, 03 Nov 2009 02:37:49 +0000</pubDate>
		<dc:creator>Tyler</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Python programming]]></category>
		<category><![CDATA[Syntax highlighter]]></category>

		<guid isPermaLink="false">http://unsyncopated.com/blog/index.php/2009/11/03/downloading-photos-from-facebook-with-linux/</guid>
		<description><![CDATA[Tommy Murphy recently released photograbber, a simple Python/tkinter app that uses the Facebook API to&#8230; 1. Find all the photos that you&#8217;ve been tagged in and&#8230; 2. Download each photo to a chosen directory. It worked fine for me after I fixed a trivial tkinter bug. Right now I&#8217;m adapting photograbber to download entire albums [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://eat.ourbunny.com/">Tommy Murphy</a> recently released <a href="http://code.google.com/p/photograbber">photograbber</a>, a simple Python/tkinter app that uses the Facebook API to&#8230;</p>
<p>1. Find all the photos that you&#8217;ve been tagged in and&#8230;<br />
2. Download each photo to a chosen directory.</p>
<p>It worked fine for me after I <a href="http://code.google.com/p/photograbber/issues/detail?id=5">fixed a trivial tkinter bug</a>.</p>
<p>Right now I&#8217;m adapting photograbber to download entire albums for me. Here&#8217;s the crucial code that requests a collection of &#8220;photo&#8221; records using <a href="http://wiki.developers.facebook.com/index.php/FQL">Facebook Query Language</a> (FQL):</p>
<pre class="brush: python;">

photos = self.facebook.fql.query(&quot;SELECT pid, aid, src_big FROM &quot; \
&quot;photo WHERE pid IN (SELECT pid FROM photo_tag WHERE subject=&quot; + \
str(self.facebook.uid) + &quot;)&quot;)
</pre>
<p>Changing the query to&#8230;</p>
<pre class="brush: python;">

&quot;SELECT pid, aid, src_big FROM photo WHERE aid IN (SELECT aid &quot; \
&quot;FROM album WHERE owner IN (SELECT uid FROM user WHERE name=\&quot;&quot; + \
FriendName + &quot;\&quot;) AND name=\&quot;&quot; + AlbumName + &quot;\&quot;)&quot;
</pre>
<p>&#8230; did the trick. Caveat coder: the album IDs that you see in your browser while surfing Facebook <em>aren&#8217;t</em> the same IDs that you should use in your FQL queries. If you slip up, you might receive this misleading message: &#8220;FacebookError: Error 600: An unknown error occurred in FQLPhotoTable::get_ids_for_queries:  should never have a pid or aid without a uid&#8221;</p>
<p>Keep <a href="http://www.facebook.com/terms.php">Facebook&#8217;s terms of service</a> in mind when interacting with their site &#8211; you don&#8217;t want a &#8220;cease and desist&#8221; letter like <a href="http://www.vincentcheung.ca/blog/facedown/cease-and-desist/">Vincent Cheung received for his &#8220;FaceDown&#8221; application</a>.</p>
<p>If all else fails, you might have some luck with a PHP script called &#8220;FBCMD&#8221; as illustrated <a href="http://dieter.plaetinck.be/a_script_that_pulls_photos_from_facebook">here</a>. There&#8217;s also a .NET standalone app: <a href="http://rajitss.com/albumdownloader/index.php">The RajitSS Album Downloader</a>.</p>
<p>I&#8217;ll spare you my internet balkanization rant &#8211; Fred Vogelstein made the argument far better in the June issue of Wired: <a href="http://www.wired.com/techbiz/it/magazine/17-07/ff_facebookwall?currentPage=all">Great Wall of Facebook &#8211; The Social Network&#8217;s Plan to Dominate the Internet &#8211; and Keep Google Out</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://unsyncopated.com/blog/index.php/2009/11/02/downloading-photos-from-facebook-with-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Bash &#8220;edit-in-place&#8221; idiom</title>
		<link>http://unsyncopated.com/blog/index.php/2009/02/19/a-bash-edit-in-place-idiom/</link>
		<comments>http://unsyncopated.com/blog/index.php/2009/02/19/a-bash-edit-in-place-idiom/#comments</comments>
		<pubDate>Thu, 19 Feb 2009 12:48:43 +0000</pubDate>
		<dc:creator>Tyler</dc:creator>
				<category><![CDATA[Flickr]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Shell programming]]></category>

		<guid isPermaLink="false">http://unsyncopated.com/blog/index.php/2009/02/19/a-bash-edit-in-place-idiom/</guid>
		<description><![CDATA[I use a shell script called `stream.sh` to launch my music player and open a given internet radio station. I use it like this to tune to a local AM station: $ stream.sh 1370 I usually edit small scripts like that with `nano(1)`. Rather than type the entire path to the script when I need [...]]]></description>
			<content:encoded><![CDATA[<p>I use a shell script called `stream.sh` to launch my music player and open a given internet radio station. I use it like this to tune to a local AM station:</p>
<pre class="brush: bash;">

$ stream.sh 1370
</pre>
<p>I usually edit small scripts like that with `nano(1)`. Rather than type the entire path to the script when I need to edit it (`nano ~/prog/sh/stream.sh`) I just say `nano $(which stream.sh)` i.e. &#8220;edit whichever file is in the `$PATH` with that name&#8221;. 						<div class="flickr-gallery image right"><a href="http://www.flickr.com/photos/scoobyfoo/268948449"><img class="flickr small" title="Repairs" alt="Repairs" src="http://farm1.static.flickr.com/83/268948449_6204a3eae5_m.jpg" /></a></div>
					My shell (`zsh(1)`) performs tab-completion on the single argument to `which(1)` &#8211; here, &#8220;stream.sh&#8221;. So I&#8217;ve got &#8220;nano $(which stre_.s_)&#8221; where &#8220;_&#8221;s are tabs.</p>
<p>It&#8217;s actually a brain-saver with more verbose names, I promise `:]`.</p>
<span id="Blogged_to8230"><h3>Blogged to&#8230;</h3></span>
<p>&#8220;Step by Step&#8221; by Chronos on <a href="http://www.di.fm">di.fm</a>&#8216;s chillout station as recommended by <a href="http://www.mixstation.net/comment.php?dlid=2713&amp;ENGINEsessID=3c9d4fb2b462f91616237e2819581684">DJ JMULV</a></p>
<span id="See_also"><h3>See also</h3></span>
<ul>
<li><span style="font-size: 13.3333px;"><a href="http://www.google.com/search?q=&quot;Writing+Zsh+Completion+Functions&quot;">An article on Zsh(1) completion</a> from Linux Magazine</span></li>
<li><span style="font-size: 13.3333px;"><a href="http://michael-prokop.at/blog/2008/12/19/mikas-advent-calendar-day-19-zsh-completion/">mikas blog &#8211; Blog Archive &#8211; mika&#8217;s advent calendar &#8211; day 19: zsh completion</a></span></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://unsyncopated.com/blog/index.php/2009/02/19/a-bash-edit-in-place-idiom/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hats off to cdparanoia&#8217;s UI</title>
		<link>http://unsyncopated.com/blog/index.php/2008/10/02/hats-off-to-cdparanoias-ui/</link>
		<comments>http://unsyncopated.com/blog/index.php/2008/10/02/hats-off-to-cdparanoias-ui/#comments</comments>
		<pubDate>Fri, 03 Oct 2008 03:12:19 +0000</pubDate>
		<dc:creator>Tyler</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Music]]></category>

		<guid isPermaLink="false">http://unsyncopated.com/blog/index.php/2009/02/28/hats-off-to-cdparanoias-ui/</guid>
		<description><![CDATA[I recently decided to rip all of my music CDs to a more reliable medium: my hard drive. One of the software tools I&#8217;m using to do this is called cdparanoia. It&#8217;s a solid little app from the venerable Xiph.org multimedia project with an entertaining but informative console interface. An excerpt from `cdparanoia(1)`: OUTPUT SMILIES [...]]]></description>
			<content:encoded><![CDATA[<p>I recently decided to rip all of my music CDs to a more reliable medium: my hard drive.</p>
<p>One of the software tools I&#8217;m using to do this is called <a href="http://www.xiph.org/paranoia/">cdparanoia</a>. It&#8217;s a solid little app from the venerable <a href="http://www.xiph.org">Xiph.org multimedia project</a> with an entertaining but informative console interface. An excerpt from `cdparanoia(1)`:</p>
<pre style="padding-left: 30px;">OUTPUT SMILIES
:-)  Normal operation, low/no jitter
:-|  Normal operation, considerable jitter
:-/  Read drift
:-P  Unreported loss of streaming in atomic read operation
8-|  Finding read problems at same point during reread;
     hard to correct
:-0  SCSI/ATAPI transport error
:-(  Scratch detected
;-(  Gave up trying to perform a correction
8-X  Aborted read due to known, uncorrectable error
:^D  Finished extracting</pre>
<pre style="padding-left: 30px;">PROGRESS BAR SYMBOLS</pre>
<pre style="padding-left: 30px;">    No corrections needed
-   Jitter correction required
+   Unreported loss of streaming/other error in read
!   Errors  found  after stage 1 correction; the drive is
    making the same error through multiple re-reads, and
    cdparanoia is having trouble detecting them.
e   SCSI/ATAPI transport error (corrected)
V   Uncorrected error/skip</pre>
<p>The interface is a testament to the poor reliability of the little plastic discs. I&#8217;ve found, however, that I&#8217;d rather learn of a fatal scratch on some rare dub reggae disc from <em>it</em> rather than by a Zsh core dump message.</p>
<p>The UI also uses an interesting variation on the throbber/baton: <a href="http://www.google.com/codesearch/p?hl=en#JgMOjnoOaNs/cdparanoia-3.10+debian~pre0/main.c&amp;q=cdparanoia%20main.c&amp;l=510">main.c &#8211; cdparanoia-3.10+debian~pre0</a>.</p>
<p>Long live the console.</p>
]]></content:encoded>
			<wfw:commentRss>http://unsyncopated.com/blog/index.php/2008/10/02/hats-off-to-cdparanoias-ui/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Recalling a word from the current command line</title>
		<link>http://unsyncopated.com/blog/index.php/2007/04/22/recalling-a-word-from-the-current-command-line/</link>
		<comments>http://unsyncopated.com/blog/index.php/2007/04/22/recalling-a-word-from-the-current-command-line/#comments</comments>
		<pubDate>Sun, 22 Apr 2007 17:29:46 +0000</pubDate>
		<dc:creator>Tyler</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Shell programming]]></category>

		<guid isPermaLink="false">http://unsyncopated.com/blog/?p=668</guid>
		<description><![CDATA[I often find myself using a command like this to make a backup of a file: cp /etc/slop/gunk.conf /etc/slop/gunk.conf_before_v2_upgrade Since the first portion of the second argument is always the same as the first argument (the green text), it bugged me to have to do tab completion for it. Luckily, zsh and bash provide an [...]]]></description>
			<content:encoded><![CDATA[<p>I often find myself using a command like this to make a backup of a file:</p>
<blockquote>
<pre>cp <span style="color: #008000;">/etc/slop/gunk.conf</span> <span style="color: #008000;">/etc/slop/gunk.conf</span>_before_v2_upgrade</pre>
</blockquote>
<p>Since the first portion of the second argument is always the same as the first argument (the green text), it bugged me to have to do tab completion for it. Luckily, zsh and bash provide an event designator for the current command line (ie the one you&#8217;re currently typing). It is !# and it works just like the other events (eg !! is the previous command). See <a href="http://zsh.dotsrc.org/Doc/Release/zsh_13.html#SEC48">Zsh Documentation &#8211; History Expansion.</a> Bash&#8217;s syntax is very similar.</p>
<p>So now when I want to make a crude backup like above, I use something like this:</p>
<blockquote>
<pre>cp /etc/slop/gunk.conf !#:1_before_v2_upgrade</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://unsyncopated.com/blog/index.php/2007/04/22/recalling-a-word-from-the-current-command-line/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Intel Motherboarding</title>
		<link>http://unsyncopated.com/blog/index.php/2007/02/07/intel-motherboarding/</link>
		<comments>http://unsyncopated.com/blog/index.php/2007/02/07/intel-motherboarding/#comments</comments>
		<pubDate>Wed, 07 Feb 2007 19:10:38 +0000</pubDate>
		<dc:creator>Tyler</dc:creator>
				<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://unsyncopated.com/blog/?p=767</guid>
		<description><![CDATA[If you&#8217;re trying to install the Intel(R) Chipset Software Installation Utility (aka drivers) from a CD and you encounter a message like &#8220;usbehci.sys on (Unknown) is needed&#8221;, you may want to try installing Service Pack 2 if you&#8217;re on Windows XP. Worked for me. Speaking of Intel, kudos to them for having the best website [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re trying to install the Intel(R) Chipset Software Installation Utility (aka drivers) from a CD and you encounter a message like &#8220;usbehci.sys on (Unknown) is needed&#8221;, you may want to try installing Service Pack 2 if you&#8217;re on Windows XP. Worked for me.</p>
<p><span style="font-size: 13.3333px;">Speaking of Intel, kudos to them for having the <em>best</em> website of any motherboard manufacturer I&#8217;ve bought from. Their motherboard pages have</span></p>
<ul>
<li>High resolution pictures of the boards.</li>
<li><em>Detailed </em>specs for each available &#8220;configuration&#8221;.</li>
<li>BIOS updates (including old ones) in 4 different formats including bootable CDs.</li>
<li>3 effective ways to identify an Intel board (BIOS string, sticker label on board, part number)</li>
<li>Detailed information on where temperature sensors are located.</li>
</ul>
<p>They also support the Linux community by releasing <a href="http://intellinuxgraphics.org/">quality open-source graphics drivers</a>. Very, very nice.</p>
<p>If you want to install Ubuntu on a 965-based Intel board like the DQ965GF, I recommend the third Fiesty Fawn milestone, <a href="http://www.ubuntu.com/testing/herd3">Herd 3</a>. With Herd 3, you get the 2.6.20 kernel which supports <a href="http://kvm.qumranet.com/kvmwiki">KVM</a>, a loadable kernel module to support hardware virtualization (scoooore!).</p>
<p>Because the 965 chipset is new, there are still some kinks. At first the installer crapped out and left me with:</p>
<pre>BusyBox [ver] Built-in shell (ash)
Enter 'help' for a list of built-in commands.

/bin/sh: can't access tty; job control turned off</pre>
<p>Later on, I got garbled X graphics.</p>
<p>The solution to these problems was to add &#8220;vga=771 all-generic-ide pci=nommconf&#8221; to my kernel options line after booting to the install CD (hit F6 when the installer while you&#8217;ve got the &#8220;Start or install Ubuntu&#8221; menu item selected). Your final options line should read &#8220;file=/cdrom/preseed/ubuntu.seed boot=casper initrd=/casper/initrd.gz vga=771 all-generic-ide pci=nommconf quiet splash &#8211;&#8221;. I removed &#8220;quiet&#8221; and changed &#8220;splash&#8221; to &#8220;nosplash&#8221; also.</p>
<p>Windows XP Profession rebooted every time it tried to load &#8220;mup.sys&#8221; during bootup. The fix was to change the BIOS setting for Configure SATA As&#8221; (Advanced Tab -&gt; Drive Configuration) from &#8220;AHCI&#8221; to &#8220;IDE&#8221;. Note that this will nix any benefit you get from SATA.</p>
<p>Some of these links were helpful:</p>
<ul>
<li><span style="font-size: 13.3333px;"><a href="http://vip.asus.com/forum/view.aspx?board_id=1&amp;model=P5W+DH+Deluxe&amp;id=20060718094204123&amp;page=1&amp;SLanguage=en-us">Configure SATA as [Standard IDE] or [AHCI] ??? </a></span></li>
<li><span style="font-size: 13.3333px;"><a href="http://www.blindedbytech.com/2006/11/10/how-to-install-fedora-core-6-on-intel-dg965ss-motherboard/">How To: Install Fedora Core 6 On Intel DG965SS Motherboard</a></span></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://unsyncopated.com/blog/index.php/2007/02/07/intel-motherboarding/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Specifying environment variables in .lesskey</title>
		<link>http://unsyncopated.com/blog/index.php/2007/02/05/specifying-environment-variables-in-lesskey/</link>
		<comments>http://unsyncopated.com/blog/index.php/2007/02/05/specifying-environment-variables-in-lesskey/#comments</comments>
		<pubDate>Mon, 05 Feb 2007 13:32:51 +0000</pubDate>
		<dc:creator>Tyler</dc:creator>
				<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://unsyncopated.com/blog/index.php/2009/02/28/specifying-environment-variables-in-lesskey/</guid>
		<description><![CDATA[One day while I was fooling with my `less` pager settings, I came across a fancy prompt string posted to the darwinos-users mailing list: re: less modifications. I added it to my `.lesskey` file, yielding: #env LESS = -i --prompt="%f (%pb%, %lmth line, %L lines)$" After I executed `lesskey` to apply the new settings to [...]]]></description>
			<content:encoded><![CDATA[<p>One day while I was fooling with my `less` pager settings, I came across a fancy prompt string posted to the darwinos-users mailing list: <a href="http://lists.apple.com/archives/darwinos-users/2002/Dec/msg00109.html">re: less modifications</a>. I added it to my `.lesskey` file, yielding:</p>
<pre style="padding-left: 30px;">#env LESS = -i --prompt="%f (%pb%, %lmth line, %L lines)$"</pre>
<p><span style="font-size: 13.3333px;">After I executed `lesskey` to apply the new settings to `.less`, I started seeing error messages like these whenever I tried to use the pager:</span></p>
<ul>
<li><span style="font-size: 13.3333px;">`-&#8221; must be followed by 1 or 2 chars Missing filename (&#8220;less &#8211;help&#8221; for help)`</span></li>
<li><span style="font-size: 13.3333px;">`There is no -&#8217; option (&#8220;less &#8211;help&#8221; for help)`</span></li>
</ul>
<p>It turns out that the problem is with the quote characters. Unlike `bash`, you don&#8217;t have to worry about `lesskey` interpreting the `$` or `%` characters. Thus, you don&#8217;t need to &#8220;protect&#8221; them with quotes.</p>
<p>Removing the quotes fixed the problem and now `less` tells me where I&#8217;m at in the file in terms of percentage, line number, and total lines: `/etc/passwd (68 14th line, 33 lines)`</p>
]]></content:encoded>
			<wfw:commentRss>http://unsyncopated.com/blog/index.php/2007/02/05/specifying-environment-variables-in-lesskey/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

