<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5764775246593834691</id><updated>2011-11-27T17:16:32.294-08:00</updated><category term='ham'/><category term='pe file'/><category term='bash'/><category term='diablo'/><category term='python'/><category term='osx'/><category term='rich header'/><title type='text'>Trendy Stephen</title><subtitle type='html'>eh, what the hell?</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://trendystephen.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://trendystephen.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>stephen</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>16</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5764775246593834691.post-2728768113932771450</id><published>2011-09-25T21:30:00.001-07:00</published><updated>2011-09-25T21:39:55.078-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='osx'/><title type='text'>Save Flash Video under OS X (firefox)</title><content type='html'>&lt;div style="text-align: justify;"&gt;Once upon a time, in Linux, it was possible to copy the files being downloaded and played by the Flash plugin out of /tmp and to wherever for later viewing.  I was pretty sure this was possible under OS X.  And wouldn't you know it, it is.  But the files were harder to find.  They're stored somewhere under /private/var/folders.  I did this to locate them:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;find /private/var/folders/ -type f -exec file {} \; 2&gt;/dev/null | grep Macromedia &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;To figure out the top-level folder that contained them, a google query showed me this &lt;a href="http://hints.macworld.com/article.php?story=20080311022147414"&gt;thread&lt;/a&gt; which clued me in.  I don't know if someone pointed out the exact location later (tl;dr) but when I saw the bits about /private/var/folders I did a find in a terminal.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5764775246593834691-2728768113932771450?l=trendystephen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trendystephen.blogspot.com/feeds/2728768113932771450/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5764775246593834691&amp;postID=2728768113932771450' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/2728768113932771450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/2728768113932771450'/><link rel='alternate' type='text/html' href='http://trendystephen.blogspot.com/2011/09/save-flash-video-under-os-x-firefox.html' title='Save Flash Video under OS X (firefox)'/><author><name>stephen</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5764775246593834691.post-8486218961959631624</id><published>2011-09-24T06:50:00.000-07:00</published><updated>2011-09-24T07:00:17.498-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='osx'/><title type='text'>Removing Linux from OS X (to redo Bootcamp)</title><content type='html'>&lt;div style="text-align: justify;"&gt;I wanted to remove Linux and try Windows (for some steam games) on my MacBook Air, but I had a little trouble.  Using the Disk Utility (graphical program), I was only able to merge the existing JHFS+ file system with my Linux partition, but It wouldn't touch the swap.  You can't just launch Boot Camp at this point because it will see the multiple partitions and refuse to run.&lt;br /&gt;&lt;br /&gt;I tried to merge using the diskUtil command line, but it gave me the error: Merging partitions encountered error "Couldn't read partition map (-69876)".&lt;br /&gt;&lt;br /&gt;So, I erased the volume and replaced it with a HFS+ with journaling.  Then I launched the Disk Utility and it refused to let me merge them.  For posterity, this is the command I used to erase:&lt;br /&gt;diskutil eraseVolume JHFS+ new /dev/disk0s3&lt;br /&gt;&lt;br /&gt;The result is that I had two Journaled HFS+ partitions that still couldn't be merged, but once I erased the volume from within the Disk Utility, it let me grow the remaining partition to fill the space.  Boot Camp happily ran and created a new Windows Partition after that.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5764775246593834691-8486218961959631624?l=trendystephen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trendystephen.blogspot.com/feeds/8486218961959631624/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5764775246593834691&amp;postID=8486218961959631624' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/8486218961959631624'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/8486218961959631624'/><link rel='alternate' type='text/html' href='http://trendystephen.blogspot.com/2011/09/removing-linux-from-os-x-to-redo.html' title='Removing Linux from OS X (to redo Bootcamp)'/><author><name>stephen</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5764775246593834691.post-2932914899986710478</id><published>2011-07-25T22:14:00.001-07:00</published><updated>2011-07-26T14:23:00.785-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='diablo'/><category scheme='http://www.blogger.com/atom/ns#' term='osx'/><title type='text'>Fuck You, OS X!</title><content type='html'>&lt;div style="text-align: justify;"&gt;The joys of a commercial operating system!  I was happy to play Diablo 2 on my shiny new MacBook Air.  No, not one of the cool new-new MacBook Airs, the slightly older MacBook air that still has discreet graphics.  Anyway, I decided to finally bite the bullet and pay the $5 for the latest Xcode.  I was happy to discover that it's now free.  Then I noticed that it was free for Lion, only.  So I paid the $30 and upgraded.  Then I discovered that I couldn't play Diablo 2 anymore.  Then I discovered that I probably could have gotten the upgrade to Lion for free, through Apple, because I bought my system so close to the release date of Lion.&lt;br /&gt;&lt;br /&gt;Well, bitterness aside, I decided to grab wine for OS X and use that to launch a windows install of Diablo 2.  Then once that was working, I decided to package it up in a .app file so that I could at least pretend it was a native app.  After that, I discovered there's something called wineskin that will let you package stuff up into .app bundles.  Eh, whatever, I already made the damn script, put the right files in the right places, and through some guesswork figured out how to get it to all play nicely.  Then I tweaked my script so that it would search for any old wine installation within the bundle, in case I upgrade the version of wine it's using.  Then I tweaked the script a bit further to have it configure the 800x600 desktop so that the game would stop fucking up my graphics and displaying incorrectly in the process.  It was weird, the game would launch, it looked great, but the window was getting pushed off the screen, ever so slightly.  The emulated desktop fixed that.&lt;br /&gt;&lt;br /&gt;Since I had it configure wine, I decided to remove the stupid gecko prompt for HTML support in windows applications.  Maybe battle.net makes use of the HTML display, I don't know, the game certainly didn't need it for multi-player.&lt;br /&gt;&lt;br /&gt;Anyway, here's the bizarre stuff that I learned in the process of creating the .app.  I knew that .apps were folders, but I didn't know what the structure needed to look like, so I took a peek at Torchlight.  Nice and simple.  I mimicked the directory structure so that I had the following:&lt;pre&gt;Diablo2.app/Contents/MacOS&lt;br /&gt;Diablo2.app/Contents/MacOS/Info.plist&lt;br /&gt;Diablo2.app/Contents/MacOS/diablo2.icns  (stole from somewhere)&lt;br /&gt;Diablo2.app/Contents/MacOS/diablo2.sh    (script I wrote)&lt;br /&gt;Diablo2.app/Contents/Resources&lt;br /&gt;Diablo2.app/Contents/Resources/diablo2.icns -&gt;&lt;br /&gt; ../MacOS/diablo2.icns&lt;br /&gt;Diablo2.app/Contents/PkgInfo&lt;br /&gt;Diablo2.app/Contents/Info.plist -&gt; ./MacOS/Info.plist&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;When it was all said and done, I had the following additional items:&lt;pre&gt;Diablo2.app/Contents/MacOS/1.3.24     (wine distro)&lt;br /&gt;Diablo2.app/Contents/MacOS/Diablo II  (from windows)&lt;br /&gt;Diablo2.app/Contents/MacOS/prefix     (generated)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;[Edit: Here's where I got the icon set: http://www.iconeasy.com/icon/diablo-ii-icon/  No idea where they got it from, so I don't know that this is really proper attribution.]&lt;br /&gt;&lt;br /&gt;So, here's the cool part.  Parameter Expansion.  The diablo2.sh I created was modeled after the Steam.app steam.sh script.  And when I say modeled after, what I really mean is that I read the first executable line of the script and said, "What the hell is this?"&lt;br /&gt;&lt;br /&gt;Here's the line in question:&lt;br /&gt;&lt;code language="bash"&gt;STEAMROOT=$(cd "${0%/*}" &amp;&amp; echo $PWD)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I gathered that PWD was feeding the PWD to the variable STEAMROOT, so I figured the ${0%/*} must be doing something crazy to $0.  So the first thing I did was start issuing echo commands and trying things with different variables.  Now, I could see that the ${0%/*} was taking whatever the value of the variable was and chopping off the trailing file name but I didn't understand what sorcery was allowing this.  Turns out bash has some built-in awesomeness that I just didn't bother to notice in the 10 years or so that I've been using it.  I'm so so sorry for ignoring you, bash!  If you look at the man page for bash, it will explain (among other things) ${VAR%pattern}, ${VAR#pattern}, and ${VAR/pattern/substitute/}.  They work much like you can imagine.  The ${VAR%pattern) removes the pattern, starting its search from the right side of the value and searching towards the left, going for the least-greedy approach.  The ${VAR#pattern} similarly removes the pattern, but starting from the left.  The ${VAR/pattern/substitute} is something that I've needed ever since I started using Linux back in high school.  It's like a sed expression.  It replaces the specified pattern with the specified substition.  It's all so bloody awesome.&lt;br /&gt;&lt;br /&gt;Up until now, I had been doing this to get the directory part of a file name:&lt;br /&gt;&lt;code language="bash"&gt;DIR="`echo $FULLPATH| rev | cut -f1- -d/ | rev`"&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I just needed to do this:&lt;br /&gt;&lt;code language="bash"&gt;DIR="${FULLPATH%/*}"&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I cannot count the number of times that I've shelled out to imagemagick to process a directory and have done something foolish like this:&lt;br /&gt;&lt;code language="bash"&gt;for f in *.jpg ; do NEW_NAME="`echo $f | rev | cut -f2- -d'/' | rev`.png" convert "$f" "$NEW_NAME" ; done &lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And I could have just done this:&lt;br /&gt;&lt;code language="bash"&gt;for f in *.jpg ; do convert "${f}" "${f/\.jpg/.png}; done&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;So, getting back to the Diablo stuff.  I don't know why the steam.sh does the cd and pwd when it could just evaluate the variable, but whatever; maybe they use a side-effect later.  Here's my diablo2.sh file:&lt;br /&gt;&lt;iframe src="http://pastebin.com/embed_iframe.php?i=Hi0anga8" style="border:none;width:100%"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;On to the other package details...&lt;br /&gt;&lt;br /&gt;Info.plist, ties everything in the package together:&lt;br /&gt;&lt;iframe src="http://pastebin.com/embed_iframe.php?i=4VQii40M" style="border:none;width:100%"&gt;&lt;/iframe&gt;&lt;br /&gt;PkgInfo only contains this line:&lt;pre&gt;APPL????&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://pastebin.com/raw.php?i=ihRCXAFW"&gt;Here's&lt;/a&gt; a crazy script I threw together, simply invoke it and it will base64 decode the last line of it's content, reconstitute a tar.bz2 file, md5 it for integrity, and if all went well, it will extract a copy of my Diablo2.app folder, minus the wine and minus my Diablo 2 install folder.  Just get any one of the pre-built wine for OS X from here: http://wine.playonlinux.com/darwin-i386/ and extract it into the MacOS folder of the Diablo2.app.  Then, copy in your Diablo II from a windows install, and the script will locate all the pieces and launch.  Be prepared for sounds, because the script speaks its status messages.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5764775246593834691-2932914899986710478?l=trendystephen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trendystephen.blogspot.com/feeds/2932914899986710478/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5764775246593834691&amp;postID=2932914899986710478' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/2932914899986710478'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/2932914899986710478'/><link rel='alternate' type='text/html' href='http://trendystephen.blogspot.com/2011/07/fuck-you-os-x.html' title='Fuck You, OS X!'/><author><name>stephen</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5764775246593834691.post-7823804547107523310</id><published>2011-07-03T07:25:00.001-07:00</published><updated>2011-07-25T21:55:34.236-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='osx'/><title type='text'>OS X Right Click Menu Additions</title><content type='html'>&lt;div style="text-align: justify;"&gt;I'm sure this is documented somewhere, but I didn't find it while looking.  If you use the Automator to create a service that receives files or folders in any application, it will get added to the right click menu.  Now I can right click documents and choose to edit them with Vim.&lt;br /&gt;&lt;br /&gt;I noticed this while trying to add a hotkey to the service.  The hotkey didn't work, but then I noticed my edit option in the menu, so that's almost as good.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;So here's how I created a right-click option for Edit with Vim under Snow Leopard:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Launch Automator&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Choose The Service Template&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Change "Service receives selected" pulldown option from "text" to "files or folders."&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Drag "Run Shell Script" from the library into the current workflow&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Change the "Pass input" pulldown from "to stdin" to "as arguments"&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Delete the text from the edit box and enter the following:&lt;/li&gt;&lt;br /&gt;&lt;iframe src="http://pastebin.com/embed_iframe.php?i=XMzAGvSV" style="border:none;width:100%"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;li&gt;Save it as something concise, but descriptive, like: Edit with single Vim&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;This time I embedded everything for the command in the shell script of the service because I'll only ever need to call this from the gui.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Edit: Update: OS X Lion treats Applications like services.  If you create an Application with the Automator, it will likewise show up in your services menu.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5764775246593834691-7823804547107523310?l=trendystephen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trendystephen.blogspot.com/feeds/7823804547107523310/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5764775246593834691&amp;postID=7823804547107523310' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/7823804547107523310'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/7823804547107523310'/><link rel='alternate' type='text/html' href='http://trendystephen.blogspot.com/2011/07/os-x-right-click-menu-additions.html' title='OS X Right Click Menu Additions'/><author><name>stephen</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5764775246593834691.post-7892761458377829267</id><published>2011-07-02T20:12:00.000-07:00</published><updated>2011-07-26T14:34:32.006-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bash'/><category scheme='http://www.blogger.com/atom/ns#' term='osx'/><title type='text'>OS X DMG Creation from a Folder</title><content type='html'>&lt;div style="text-align: justify;"&gt;Edit: As of OS X Lion (10.7) Applications show up in your services menu, so you get a right click menu for free.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;The hdiutil command is awesome.  Amongst its many features is the ability to create a DMG file from a specified folder.  For some reason, there's no right click option for creating DMG files from folders.  Strangely enough, there is a right click compress option that will create a zip, but that's really not sufficient.  If you create a zip, you can't access individual files from it like you can a compressed DMG.&lt;br /&gt;&lt;br /&gt;Edit: For anyone who just wants the command and not fuss with the scripts, here's how you might create a zip compressed dmg file from a folder called Movies:&lt;br /&gt;&lt;pre&gt;hdiutil create -srcfolder Movies -volname Movies -fs HFS+ \&lt;br /&gt; -fsargs -c c=64,a=16,e=16 -format UDBZ ./Movies.dmg&lt;/pre&gt;&lt;br /&gt;Once again, I've used Automator to invoke a bash script.  Now I can drop folders on my app and generate a compressed, read-only DMG file.  I don't have lots of free space, so I use this for applications I've downloaded that come as a tar.gz/tar.bz/zip/whatever.&lt;br /&gt;&lt;br /&gt;I'd like to point out that while it is possible to embed all of the bash script content into the Automator "Run Shell Script" feature, but then I wouldn't be able to easily invoke it from the command line and I use the command line alot.&lt;br /&gt;&lt;br /&gt;Here's the content of my Automator "Run Shell Script" box (CreateDMGFromFolder.app):&lt;br /&gt;&lt;iframe src="http://pastebin.com/embed_iframe.php?i=1uWbSnbH" style="border:none;width:100%"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;Here's the content of my shell script (CreateDMGFromFolder):&lt;br /&gt;&lt;iframe src="http://pastebin.com/embed_iframe.php?i=3i3ZaUHT" style="border:none;width:100%"&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;Edit: I've updated the script in light of reading the bash man page.  Parameter Expansion is bad-ass.&lt;br /&gt;&lt;br /&gt;Here's the new shell script to replace the aforementioned (CreateDMGFromFolder):&lt;br /&gt;&lt;iframe src="http://pastebin.com/embed_iframe.php?i=eLXSAPQf" style="border:none;width:100%"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5764775246593834691-7892761458377829267?l=trendystephen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trendystephen.blogspot.com/feeds/7892761458377829267/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5764775246593834691&amp;postID=7892761458377829267' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/7892761458377829267'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/7892761458377829267'/><link rel='alternate' type='text/html' href='http://trendystephen.blogspot.com/2011/07/os-x-dmg-creation-from-folder.html' title='OS X DMG Creation from a Folder'/><author><name>stephen</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5764775246593834691.post-4695652786748107577</id><published>2011-07-01T20:39:00.000-07:00</published><updated>2011-07-25T22:11:36.408-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bash'/><category scheme='http://www.blogger.com/atom/ns#' term='osx'/><title type='text'>OS X Open With Vim</title><content type='html'>&lt;div style="text-align: justify;"&gt;Edit: After my second OS X post, I went back and created a service to perform Edit with Vim.  I actually forgot about the .app that I made with automator.  Then I upgraded to Lion and was all sorts of confused when two entries for Edit with Vim popped up in my context menu.  Wouldn't you know it?  Lion puts all automator Services and Applications into the right click context menu.  So I've actually deleted this script and am using the one mentioned &lt;a href="http://trendystephen.blogspot.com/2011/07/os-x-right-click-menu-additions.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;OS X comes with vim preinstalled.  Nice.  It's not that retarded version Ubuntu comes with by default, either.  It's the full vim.  So then, why the hell can't I right click something, choose open with, and then choose vim?  Why can't I pass arguments to the terminal to tell it to run arbitrary commands (such as vim) from the open with dialog?&lt;br /&gt;&lt;br /&gt;It appears that OS X only lets you pick Apps as the target application for performing an "Open with".  So, to get what I want, I have to use Automator in conjunction with a bash shell script in order to run osascript in order to pop up a new terminal with vim in it and whatever files are selected (or dropped on the app).&lt;br /&gt;&lt;br /&gt;Here's what I have in my bash script, aptly named TellTerminal:&lt;br /&gt;&lt;iframe src="http://pastebin.com/embed_iframe.php?i=NfHZJ5ZN" style="border:none;width:100%"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;This script sends whatever it's arguments are to the Terminal.app and tells it to run them.  Then it tells the Terminal.app to activate itself so that it jumps to the foreground.  Without this, the terminal will still open, but there's a chance that it will be sitting in the background somewhere.  A really, really good chance.&lt;br /&gt;&lt;br /&gt;To invoke this script, I had to create an Automator Application (not a workspace, only the .app can be invoked as an application) and add an action 'Run shell script'.  This is the shell script that it runs:&lt;br /&gt;&lt;br /&gt;&lt;iframe src="http://pastebin.com/embed_iframe.php?i=3gfii9fM" style="border:none;width:100%"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;This script (which only exists in the Automator app that I've named EditWithVim.app,)  loops over all the arguments that were passed to it in order to invoke vim and pass it the quoted file names.  This is to avoid having a space within a file name break my script.  Also, this script looks for a BashScripts directory in my user's Library directory within the user's home.&lt;br /&gt;&lt;br /&gt;Now I can set things to be opened with vim.  It's extremely convoluted, but it does seem to be working.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5764775246593834691-4695652786748107577?l=trendystephen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trendystephen.blogspot.com/feeds/4695652786748107577/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5764775246593834691&amp;postID=4695652786748107577' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/4695652786748107577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/4695652786748107577'/><link rel='alternate' type='text/html' href='http://trendystephen.blogspot.com/2011/07/os-x-open-with-vim.html' title='OS X Open With Vim'/><author><name>stephen</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5764775246593834691.post-3951802041489235404</id><published>2011-04-20T19:37:00.000-07:00</published><updated>2011-04-20T19:42:23.827-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ham'/><title type='text'>Thanks, FCC!</title><content type='html'>&lt;div style="text-align: justify;"&gt;Apparently you can just download the FCC database of Ham users.  Then you can just grep the list instead of doing something lame like scraping a 3rd party website.  Thanks, FCC.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Link &lt;a href="http://wireless.fcc.gov/uls/data/complete/l_amat.zip"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5764775246593834691-3951802041489235404?l=trendystephen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trendystephen.blogspot.com/feeds/3951802041489235404/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5764775246593834691&amp;postID=3951802041489235404' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/3951802041489235404'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/3951802041489235404'/><link rel='alternate' type='text/html' href='http://trendystephen.blogspot.com/2011/04/thanks-fcc.html' title='Thanks, FCC!'/><author><name>stephen</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5764775246593834691.post-4157169374118204683</id><published>2011-04-17T20:08:00.000-07:00</published><updated>2011-04-20T19:41:25.048-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bash'/><category scheme='http://www.blogger.com/atom/ns#' term='ham'/><title type='text'>Ham Lookup Bash Script (fragile)</title><content type='html'>&lt;div style="text-align: justify;"&gt;Earlier today I wanted to quickly find some info on some Hams, but I couldn't remember the FCC link.  Then I found the QRZ site. Not bad, but I didn't want to have to launch Firefox just to look someone up, so I thought maybe I'd write a python script.  Except then I couldn't think of an easy Regex to parse the HTML  So I fetched the page source, found the form that looks up names and callsigns, pulled down my own info, and before I knew it, I had a series of ugly greps and seds pulling out the relevant information.  Then something strange happened.  I lost interest in pursuing the python angle.  I dumped my two queries into two separate bash scripts named lookupname and lookupsign.  It was quick and painless, even though the "code" is horribly fragile and entirely dependant on the HTML coming back, but it (currently) works so I'm calling it good for now.&lt;br /&gt;&lt;br /&gt;A few minutes ago I was sitting on a different computer and wanted to lookup a callsign, again, so I dumped the two separate bash scripts into a single script and I guess I'll share that in case I want it again in the future.  Here's the script:&lt;/div&gt;&lt;br /&gt;&lt;font color="#ffff00"&gt;&amp;nbsp;1 &lt;/font&gt;&lt;font color="#8080ff"&gt;#!/bin/bash&lt;/font&gt;&lt;br /&gt;&lt;font color="#ffff00"&gt;&amp;nbsp;2 &lt;/font&gt;&lt;br /&gt;&lt;font color="#ffff00"&gt;&amp;nbsp;3 &lt;/font&gt;&lt;font color="#00ffff"&gt;SIGN&lt;/font&gt;=&lt;font color="#ffff00"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff40ff"&gt;`echo &lt;/font&gt;&lt;font color="#ff40ff"&gt;$@&lt;/font&gt;&lt;font color="#ff40ff"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="#ffff00"&gt;|&lt;/font&gt;&lt;font color="#ff40ff"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="#ffff00"&gt;sed&lt;/font&gt;&lt;font color="#ff40ff"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&lt;font color="#ff6060"&gt;s/\ /+/g&lt;/font&gt;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&lt;font color="#ff40ff"&gt;`&lt;/font&gt;&lt;font color="#ffff00"&gt;&amp;quot;&lt;/font&gt;&lt;br /&gt;&lt;font color="#ffff00"&gt;&amp;nbsp;4 &lt;/font&gt;&lt;br /&gt;&lt;font color="#ffff00"&gt;&amp;nbsp;5 &lt;/font&gt;&lt;font color="#ffff00"&gt;echo&lt;/font&gt;&lt;font color="#ff6060"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="#ffff00"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff40ff"&gt;$SIGN&lt;/font&gt;&lt;font color="#ffff00"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff6060"&gt;&amp;nbsp;&lt;/font&gt;| &lt;font color="#ffff00"&gt;grep&lt;/font&gt;&amp;nbsp;+&lt;br /&gt;&lt;font color="#ffff00"&gt;&amp;nbsp;6 &lt;/font&gt;&lt;br /&gt;&lt;font color="#ffff00"&gt;&amp;nbsp;7 &lt;/font&gt;&lt;font color="#ffff00"&gt;if &lt;/font&gt;&lt;font color="#ffff00"&gt;[&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff40ff"&gt;$?&lt;/font&gt;&lt;font color="#ffff00"&gt;&amp;quot;&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;-eq&lt;/font&gt;&amp;nbsp;&lt;font color="#ff6060"&gt;0&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;]&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;;&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;then&lt;/font&gt;&lt;br /&gt;&lt;font color="#ffff00"&gt;&amp;nbsp;8 &lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#ffff00"&gt;echo&lt;/font&gt;&lt;font color="#ff6060"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="#ffff00"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff6060"&gt;Looking for name &lt;/font&gt;&lt;font color="#ff40ff"&gt;$SIGN&lt;/font&gt;&lt;font color="#ffff00"&gt;&amp;quot;&lt;/font&gt;&lt;br /&gt;&lt;font color="#ffff00"&gt;&amp;nbsp;9 &lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wget --post-&lt;font color="#00ffff"&gt;data&lt;/font&gt;=&lt;font color="#ffff00"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff6060"&gt;callsign=&lt;/font&gt;&lt;font color="#ff40ff"&gt;$SIGN&lt;/font&gt;&lt;font color="#ffff00"&gt;&amp;quot;&lt;/font&gt;&amp;nbsp;&lt;a href="http://www.qrz.com/db/"&gt;http://www.qrz.com/db/&lt;/a&gt; &lt;font color="#ffff00"&gt;-O&lt;/font&gt;&amp;nbsp;- &lt;font color="#ff6060"&gt;2&lt;/font&gt;&lt;font color="#ffff00"&gt;&amp;gt;&lt;/font&gt;/dev/null &lt;font color="#ffff00"&gt;|&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;egrep&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;-o&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&lt;font color="#ff6060"&gt;&amp;lt;td class=&amp;quot;(rc|ra)&amp;quot;&amp;gt;.*&amp;lt;/td&amp;gt;&lt;/font&gt;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;|&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;egrep&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;-o&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&lt;font color="#ff6060"&gt;&amp;gt;(([A-Z]|[a-z]|[0-9])|([A-Z]|[a-z]|[., ]))*&amp;lt;&lt;/font&gt;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;|&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;sed&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&lt;font color="#ff6060"&gt;s/&amp;lt;//g&lt;/font&gt;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;|&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;sed&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&lt;font color="#ff6060"&gt;s/&amp;gt;//g&lt;/font&gt;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;|&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;grep&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;-v&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&lt;font color="#ff6060"&gt;^$&lt;/font&gt;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&lt;br /&gt;&lt;font color="#ffff00"&gt;10 &lt;/font&gt;&lt;font color="#ffff00"&gt;else&lt;/font&gt;&lt;br /&gt;&lt;font color="#ffff00"&gt;11 &lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#ffff00"&gt;echo&lt;/font&gt;&lt;font color="#ff6060"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="#ffff00"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff6060"&gt;Looking for callsign &lt;/font&gt;&lt;font color="#ff40ff"&gt;$SIGN&lt;/font&gt;&lt;font color="#ffff00"&gt;&amp;quot;&lt;/font&gt;&lt;br /&gt;&lt;font color="#ffff00"&gt;12 &lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wget --post-&lt;font color="#00ffff"&gt;data&lt;/font&gt;=&lt;font color="#ffff00"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff6060"&gt;callsign=&lt;/font&gt;&lt;font color="#ff40ff"&gt;$1&lt;/font&gt;&lt;font color="#ffff00"&gt;&amp;quot;&lt;/font&gt;&amp;nbsp;&lt;a href="http://www.qrz.com/db/"&gt;http://www.qrz.com/db/&lt;/a&gt; &lt;font color="#ffff00"&gt;-O&lt;/font&gt;&amp;nbsp;- &lt;font color="#ff6060"&gt;2&lt;/font&gt;&lt;font color="#ffff00"&gt;&amp;gt;&lt;/font&gt;/dev/null &lt;font color="#ffff00"&gt;|&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;egrep&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&lt;font color="#ff6060"&gt;&amp;lt;p&amp;gt;.*&amp;lt;/p&amp;gt;&lt;/font&gt;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;|&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;sed&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&lt;font color="#ff6060"&gt;s/&amp;lt;b.*&amp;quot;&amp;gt;//g&lt;/font&gt;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;|&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;sed&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&lt;font color="#ff6060"&gt;s/&amp;lt;\/b&amp;gt;//g&lt;/font&gt;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;|&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;sed&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&lt;font color="#ff6060"&gt;s/&amp;lt;p&amp;gt;//g&lt;/font&gt;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;|&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;sed&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&lt;font color="#ff6060"&gt;s/&amp;lt;\/p&amp;gt;//g&lt;/font&gt;&lt;font color="#ffff00"&gt;'&lt;/font&gt;&lt;br /&gt;&lt;font color="#ffff00"&gt;13 &lt;/font&gt;&lt;br /&gt;&lt;font color="#ffff00"&gt;14 &lt;/font&gt;&lt;font color="#ffff00"&gt;fi&lt;/font&gt;&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;Here's the same &lt;a href="http://pastebin.com/embed_iframe.php?i=ADzDmcxb"&gt;script&lt;/a&gt;.  Invoke it with either a callsign or a person's name.  Basically, if you want to do a callsign lookup make sure there are no spaces in the invokation, ex: lookupham AB2CDE.  If you want to do a name lookup then make sure you provide a first and last or if you're clever make sure there is a space in the parameter list.  ex: lookupham John Doe.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5764775246593834691-4157169374118204683?l=trendystephen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trendystephen.blogspot.com/feeds/4157169374118204683/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5764775246593834691&amp;postID=4157169374118204683' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/4157169374118204683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/4157169374118204683'/><link rel='alternate' type='text/html' href='http://trendystephen.blogspot.com/2011/04/ham-lookup-bash-script-fragile.html' title='Ham Lookup Bash Script (fragile)'/><author><name>stephen</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5764775246593834691.post-4000936566845603521</id><published>2011-03-27T09:55:00.001-07:00</published><updated>2011-03-27T10:13:09.931-07:00</updated><title type='text'>vim + xxd = easy binary patching</title><content type='html'>&lt;div style="text-align: justify;"&gt;&lt;br /&gt;I know this is somewhat common knowledge and can be found elsewhere, but it's just so awesome that I have to repost it.  I had always used xxd to generate a listing, edited that listing with vim, and then used xxd -r to re-create the binary file.  Instead, you can use vim to open the binary file, shell out to xxd using the current buffer as input, modify the binary content by editing the hex digits (that's right, no need to edit the ascii, that's just for show,) and then shell out to xxd with the current buffer again to get the binary representation.&lt;br /&gt;&lt;br /&gt;Once more for posterity...&lt;br /&gt;&lt;br /&gt;vim -b binaryfile&lt;br /&gt;&lt;br /&gt;:%!xxd&lt;br /&gt;&lt;br /&gt;Edit the hex column in the center.&lt;br /&gt;&lt;br /&gt;:%!xxd -r&lt;br /&gt;&lt;br /&gt;Save the file and it's patched.&lt;br /&gt;&lt;br /&gt;For some extra goodness (prettier columns):&lt;br /&gt;set syntax=xxd&lt;br /&gt;&lt;br /&gt;So, that was pretty cool, but also check out :help xxd.  Vim's built-in help has a nice bit of code to put in your .vimrc and then vim -b will automatically handle shelling out to xxd when you open a binary file and then shell out to xxd when you save the modified buffer.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5764775246593834691-4000936566845603521?l=trendystephen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trendystephen.blogspot.com/feeds/4000936566845603521/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5764775246593834691&amp;postID=4000936566845603521' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/4000936566845603521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/4000936566845603521'/><link rel='alternate' type='text/html' href='http://trendystephen.blogspot.com/2011/03/vim-xxd-easy-binary-patching.html' title='vim + xxd = easy binary patching'/><author><name>stephen</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5764775246593834691.post-7421776168448162177</id><published>2011-03-15T20:40:00.000-07:00</published><updated>2011-03-16T21:01:56.102-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pe file'/><category scheme='http://www.blogger.com/atom/ns#' term='rich header'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Revised Rich Header Parser</title><content type='html'>&lt;div style="text-align: justify;"&gt;I've revised the rich.py script.  It's much better but doesn't actually do anything more than it used to.  I'll be making some more additions in the very near future, but I wanted to post this before I misplaced it.&lt;br /&gt;&lt;br /&gt;New script here: &lt;a href="http://pastebin.com/embed_iframe.php?i=LfqQHvih"&gt;rich.py&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5764775246593834691-7421776168448162177?l=trendystephen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trendystephen.blogspot.com/feeds/7421776168448162177/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5764775246593834691&amp;postID=7421776168448162177' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/7421776168448162177'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/7421776168448162177'/><link rel='alternate' type='text/html' href='http://trendystephen.blogspot.com/2011/03/revised-rich-header-parser.html' title='Revised Rich Header Parser'/><author><name>stephen</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5764775246593834691.post-789377126142804352</id><published>2011-01-08T18:25:00.000-08:00</published><updated>2011-03-16T20:59:56.010-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Fujitsu Lifebook B3020D Touchscreen and Linux</title><content type='html'>&lt;div style="text-align: justify;"&gt;(I actually did this at the tail end of 2009, then I revised the python script it in 2010.  I've been thinking of attacking the problem with un-smooth lines when the cursor is dragged...)&lt;br /&gt;&lt;br /&gt;A friend gave me one of these Fujitsu B3020D Lifebooks.  It's quite beat up.  No, really, the screen is cracked in the lower left corner and a failing hard drive or bad RAM requires that I reboot the thing periodically.  It's currently running Windows 7 and Skype with a Zoom adapter so I can plug cordless telephone bases into it.  But before that, it was running Ubuntu.  It ran Ubuntu for a good week to a week and a half.  The touchscreen didn't work on it, and the screen was cracked even then, but it wasn't a bad little system.  The battery life was good, the wireless worked without having to fight with it, and I thought it would be fun to reverse engineer the touchscreen and write some kind of mouse driver.&lt;br /&gt;&lt;br /&gt;It didn't take me long to see that the touchscreen is actually exposed to the system as a serial device.  That's damn cool.  If you just start cating out the serial ports at the console and then touching the screen, you'll eventually see it spew a bunch of numbers.  That's how I figured out which serial port it was using.  After that you can pretty much tell what the values mean just by trial and error.  There's a byte that indicates the type of event (push/release/drag) and then a series of bytes indicating the x and y coordinates.  I suggest piping the output of cat through xxd in order to see the byte values in hex.  For example: cat /dev/ttyS2 | xxd -&lt;br /&gt;&lt;br /&gt;I don't recall from memory what the different byte values were, but you can kind of tell from the python script I wrote for it.  This script reads the touch screen and will tell X11 to move the mouse around the screen and click the left mouse button in pretty much the way you would expect it.  However, if you run the gimp or some other paint program, you'll notice that touching and dragging results in a rather imperfect line.  Instead of nice diagonal lines, you get these crazy little semi-circles.  If I ever get a second system set up to run my Skype phone (or can borrow another one of these laptops,) I'll revisit the script and see if I can fix it, but otherwise it works okay.&lt;br /&gt;&lt;br /&gt;Here's the script via pastebin: &lt;a href="http://pastebin.com/yLQ1hbwt"&gt;touchmy.py&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5764775246593834691-789377126142804352?l=trendystephen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trendystephen.blogspot.com/feeds/789377126142804352/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5764775246593834691&amp;postID=789377126142804352' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/789377126142804352'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/789377126142804352'/><link rel='alternate' type='text/html' href='http://trendystephen.blogspot.com/2011/01/fujitsu-lifebook-b3020d-touchscreen-and.html' title='Fujitsu Lifebook B3020D Touchscreen and Linux'/><author><name>stephen</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5764775246593834691.post-2164379374097603845</id><published>2011-01-08T17:44:00.000-08:00</published><updated>2011-03-16T20:58:51.084-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>SEN-08634 Magnetic Card Reader/Writer</title><content type='html'>&lt;div style="text-align: justify;"&gt;The SEN-08634 Magnetic Card Reader/Writer is exactly what it sounds like: it reads and writes to magnetic strip cards.  &lt;a href="http://www.sparkfun.com/products/8634" rel="nofollow"&gt;SparkFun&lt;/a&gt; has them.&lt;br /&gt;&lt;br /&gt;This device will connect to your host as a serial device (/dev/ttyUSB0, for example) but if you try to cat it out, it will immediately return.  The damn thing doesn't buffer!  Well, okay, that's not true, it will buffer, but it throws the buffer away after a very short period of time.  So, if you wanted to use the device with some clever bash scripting, you would have to do something like while [ "1" ] ; do echo -n `cat /dev/ttyUSB0` ; done&lt;br /&gt;&lt;br /&gt;I didn't actually try that command while I had the device, it didn't occur to me until just now.&lt;br /&gt;&lt;br /&gt;Anyway, I borrowed one of these and wrote a python script that can use it.  It reads high coercivity cards and reads and writes low coercivity cards, but that's about the only thing that works.  For some reason, all the commands that the documentation claims should work don't return anything.  My script is heavily commented and I don't recommend simply running it unless you're ready to lose the data on whatever card you swipe through it.  The main body of the script will attempt to write hello world to track 1 and then a couple strings of numbers to track 2 and 3.  It will not backup what's on the card before writing.  That didn't occur to me either.  I don't have the device any more, so I'm not going to update the script.&lt;br /&gt;&lt;br /&gt;Here's the script via pastebin: &lt;a href="http://pastebin.com/ukG79YYN"&gt;magstripe.py&lt;/a&gt;.&lt;br /&gt;If you want to see documentation for it, you can do something like this: doxygen -g magstrip.doxy ; doxygen magstrip.doxy&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5764775246593834691-2164379374097603845?l=trendystephen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trendystephen.blogspot.com/feeds/2164379374097603845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5764775246593834691&amp;postID=2164379374097603845' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/2164379374097603845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/2164379374097603845'/><link rel='alternate' type='text/html' href='http://trendystephen.blogspot.com/2011/01/sen-08634-magnetic-card-readerwriter.html' title='SEN-08634 Magnetic Card Reader/Writer'/><author><name>stephen</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5764775246593834691.post-1561906017931258942</id><published>2009-11-13T20:53:00.000-08:00</published><updated>2011-07-02T21:46:14.229-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='diablo'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Diablo 2 Cloner GUI</title><content type='html'>&lt;div style="text-align: justify;"&gt;I threw this together just for practice, though not very good practice since it spits most of the output to the terminal...  It uses GtkBuilder under python so it requires the Gtk runtime in addition to python.&lt;br /&gt;&lt;br /&gt;This is the file to run: &lt;a href="http://docs.google.com/Doc?docid=0Aaq7NqfzI43FZGNuNzY0ZmdfNGZ2aHZ4bXF0&amp;hl=en"&gt;d2gui.py&lt;/a&gt;&lt;br /&gt;Here's the file that does the actual work:&lt;a href="http://pastebin.com/download.php?i=xjmBkJfi"&gt;d2functions.py&lt;/a&gt;&lt;br /&gt;And here's the interface xml document: &lt;a href="http://docs.google.com/Doc?docid=0Aaq7NqfzI43FZGNuNzY0ZmdfM3dqeDVidGZ6&amp;hl=en"&gt;d2gui.glade&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5764775246593834691-1561906017931258942?l=trendystephen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trendystephen.blogspot.com/feeds/1561906017931258942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5764775246593834691&amp;postID=1561906017931258942' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/1561906017931258942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/1561906017931258942'/><link rel='alternate' type='text/html' href='http://trendystephen.blogspot.com/2009/11/diablo-2-cloner-gui.html' title='Diablo 2 Cloner GUI'/><author><name>stephen</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5764775246593834691.post-8804084407535372280</id><published>2009-11-13T20:52:00.001-08:00</published><updated>2011-03-16T21:01:11.575-07:00</updated><title type='text'>Wordpress is no better</title><content type='html'>&lt;div style="text-align: justify;"&gt;Wordpress didn't turn out to be any better.  Perhaps if I had my own domain it would be more configurable, but I'm far too lazy for that.&lt;p&gt;So now I have both blogs and I'll have to make a few more posts here to see which one I want to keep.  After that I'll consolidate my posts to one location and tear down the old one.&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5764775246593834691-8804084407535372280?l=trendystephen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trendystephen.blogspot.com/feeds/8804084407535372280/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5764775246593834691&amp;postID=8804084407535372280' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/8804084407535372280'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/8804084407535372280'/><link rel='alternate' type='text/html' href='http://trendystephen.blogspot.com/2009/11/wordpress-is-no-better.html' title='Wordpress is no better'/><author><name>stephen</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5764775246593834691.post-7954269013931098981</id><published>2008-02-23T12:49:00.000-08:00</published><updated>2008-02-23T13:17:38.759-08:00</updated><title type='text'>So long and thanks for all the fish</title><content type='html'>Blogger was a pain.  I'm still not satisfied with the layout and complete lack of ability to upload files.  I'm going to try wordpress for a while.  If google ever fixes things, maybe I'll return.  Or, if it turns out that WordPress is even worse, I might return.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://trendystephen.wordpress.com/"&gt;WordPress Blog&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5764775246593834691-7954269013931098981?l=trendystephen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trendystephen.blogspot.com/feeds/7954269013931098981/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5764775246593834691&amp;postID=7954269013931098981' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/7954269013931098981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/7954269013931098981'/><link rel='alternate' type='text/html' href='http://trendystephen.blogspot.com/2008/02/so-long-and-thanks-for-all-fish.html' title='So long and thanks for all the fish'/><author><name>stephen</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5764775246593834691.post-6498228932132295949</id><published>2008-01-14T00:57:00.001-08:00</published><updated>2011-03-15T20:56:30.976-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pe file'/><category scheme='http://www.blogger.com/atom/ns#' term='rich header'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Rich Header</title><content type='html'>&lt;div style="text-align: justify;"&gt;The Rich header is that bit of data in a Portable Executable (PE) File&lt;sup&gt;[&lt;a href="http://trendystephen.blogspot.com/2008/01/rich-header.html#sources"&gt;1&lt;/a&gt;]&lt;/sup&gt; that follows the DOS Stub, but preceeds the actual PE Header.  It's format is only documented in a handfull of places on the searchable net, and that documentation isn't terribly in-depth.&lt;sup&gt;&lt;a href="http://trendystephen.blogspot.com/2008/01/rich-header.html#sources"&gt;[2]&lt;/a&gt;&lt;/sup&gt;  This post tries to shed some light on the Rich Header, but I fear it poses more questions than it answers.&lt;br /&gt;&lt;br /&gt;While looking into the format of the PE Header, I became curious about an odd collection of consistent data in PE files produced by Visual Studio.  It always began with the word Rich, and it wasn't in any of the documents made public by Microsoft.  After spending some quality time with google, I found a bunch of references to the Rich header, but nothing described it in depth.  Most just said it wasn't used by Windows and could be safely removed to save a few bytes.  So I gave up.&lt;br /&gt;&lt;br /&gt;Later on, I was reading something about anti-disassembling that discussed some fun modifications that one could do to a PE File.  I don't recall where I saw this document&lt;sup&gt;&lt;a href="http://trendystephen.blogspot.com/2008/01/rich-header.html#sources"&gt;[3]&lt;/a&gt;&lt;/sup&gt;, as it occurred quite some time ago, but it basically dealt with crashing various debuggers and disassemblers.  At one point, this document talked about how the Rich header had been used in some court case to attribute a virus to its creator.  That was all the document said, and THAT got my attention.&lt;br /&gt;&lt;br /&gt;Some additional quality time with google eventually led me to the forum posting&lt;sup&gt;&lt;a href="http://trendystephen.blogspot.com/2008/01/rich-header.html#sources"&gt;[2]&lt;/a&gt;&lt;/sup&gt; by lifewire, who I'm assuming is some russian hacker or something.  It described, with a couple of confusing typos, a little bit more information about the Rich header.  In fact, most of what will be described here can be ascertained by reading his rich.txt file.  (I'd post that file, but I haven't figured out how to put up attachments.)  Unfortunately, I couldn't get the details through my thick skull without taking his document and firing up a free copy of IDA Pro&lt;sup&gt;&lt;a href="http://trendystephen.blogspot.com/2008/01/rich-header.html#sources"&gt;[4]&lt;/a&gt;&lt;/sup&gt; to disassemble the link.exe file provided in Microsoft Visual Studio .Net 2003.&lt;br /&gt;&lt;br /&gt;Using IDA Pro and frequently referring to lifewire's rich.txt file, I learned that the Rich header begins with a marker, a checksum that is repeated three times, some encoded values, the word Rich in ascii, and finally ends with the checksum value, again.&lt;br /&gt;&lt;br /&gt;The encoded values are "comp.id" fields from Visual Studio.  I don't entirely understand them, and they're really key in making the Rich header forensically useful.  &lt;del&gt;For every library file that is linked against, for every object file that is compiled in, and for every tool in Visual Studio that touches data in the build process, there is a compid that is recorded.&lt;/del&gt;&lt;sup&gt;&lt;a href="http://trendystephen.blogspot.com/2008/01/rich-header.html#sources"&gt;[5]&lt;/a&gt;&lt;/sup&gt;   Some of the Visual Studio tools have an associated compid.  These compids are encoded along with an occurrence count.  So the format of the encoded data in the Rich header is compid XOR checksum followed by the number of times that compid is referenced XORed with the checksum.  That is, the compid is XORed with the checksum and then the occurrence count is XORed with the checksum, and then these values are written to the header.&lt;br /&gt;&lt;br /&gt;The checksum itself is computed by iterating over every byte of the DOS Header, skipping the elfanew field, copying the byte into a 32-bit field, rotating the field left by the field's offset in the PE header, and then adding that to a sum.  But that's not all.  Next, that sum is then added to each compid XORed with its occurrence count.  That is, the 32-bit sum is added to the value resulting from compid XOR occurrence, for every compid in the list.&lt;br /&gt;&lt;br /&gt;The last detail I have is that the marker that appears at the beginning of the Rich header is the checksum value that was computed XORed with 0x536e6144.  (Note that it's DanS in ascii; another name to put with MZ and Rich.)&lt;br /&gt;&lt;br /&gt;So what does the Rich header tell us about the executable?  It can tell us how many different object files, libraries, and tools where used to create the executable.  What additional information could it tell us?  If one were to create a table of compids and the corresponding components in Microsoft's tools, the Rich header would tell us what tools were used to create that executable.  Additionally, by verifying the checksum, one can make guesses about whether the PE file were modified.  I suspect that a table of components used to build the PE might provide enough details to extrapolate whether the executable itself were modified manually by testing to see if the object files and tools that were specified by the compids actually left a mark on the rest of the PE file.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;In closing, here's some python (forgive it's rough edges, I'm new to python) that parses compids from PE files: &lt;a href="http://docs.google.com/Doc?id=dcn764fg_2j54gzfc"&gt;rich.py&lt;/a&gt; via GoogleDocs&lt;br /&gt;&lt;br /&gt;EDIT: here's a revised one via pastebin: &lt;a href="http://pastebin.com/embed_iframe.php?i=LfqQHvih"&gt;rich.py&lt;/a&gt;&lt;br /&gt;&lt;span style="color: rgb(102, 102, 102);font-family:courier new;font-size:85%;"  &gt;&lt;/span&gt;&lt;br /&gt;Sources:&lt;a name="sources"&gt;&lt;/a&gt;&lt;br /&gt;[1] &lt;a href="http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx"&gt;PE Coff Format Spec&lt;/a&gt;&lt;br /&gt;[2] &lt;a href="http://www.woodmann.net/forum/showthread.php?t=5925"&gt;Forum Posting&lt;/a&gt; of rich.txt by lifewire&lt;br /&gt;[3] If anyone recognized this description, please post a comment!&lt;br /&gt;[4] &lt;a href="http://www.hex-rays.com/idapro/idadownfreeware.htm"&gt;IDA Pro Freeware Download&lt;/a&gt;&lt;br /&gt;[5] This was speculation incorrectly included as though it were fact -- and it's false&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5764775246593834691-6498228932132295949?l=trendystephen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trendystephen.blogspot.com/feeds/6498228932132295949/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5764775246593834691&amp;postID=6498228932132295949' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/6498228932132295949'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5764775246593834691/posts/default/6498228932132295949'/><link rel='alternate' type='text/html' href='http://trendystephen.blogspot.com/2008/01/rich-header.html' title='Rich Header'/><author><name>stephen</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry></feed>
