Stephen Ulmerhttp://www.ulmer.org/ulmer@ulmer.orgulmer.orgtag:www.ulmer.org,2011-06-11:/atom/http://www.ulmer.org/favicon.icohttp://www.ulmer.org/feed-logo.png2014-09-05T20:30:00ZacrylamidEmpty Mail.app Outboxtag:www.ulmer.org,2014-09-05:/2014/empty-mail-app-outbox2014-09-05T20:30:00ZStephen Ulmerhttp://www.ulmer.org/ulmer@ulmer.org<h4>Background</h4>
<p>Users can extend the functionality of Mail.app for OS X by installing
software packages called "Mail Bundles". I use three such bundes of joy on a daily basis:</p>
<ul>
<li>The <a href="http://support.omnigroup.com/omnifocus-clip-o-tron/" title="Clip-O-Tron Download Page">Clip-o-Tron 3000</a> for <a href="https://www.omnigroup.com/omnifocus/" title="OmniFocus Home Page">OmniFocus</a></li>
<li><a href="http://www.indev.ca/MailActOn.html" title="Mail Act-On Home Page">Mail Act-On</a></li>
<li><a href="https://gpgtools.org/" title="GPG Tools Home Page">GPG Tools</a></li>
</ul>
<p>Each of these is essential to my workflow, and not having one of them
severely imapcts my productivity.</p>
<h4>The Problem</h4>
<p>One of them is broken, and none of them will admit it. The problem
began after applying the OS X 10.9.3 update.</p>
<p>At irregular intervals, Mail.app will stop servicing the Outbox. That
is, messages to be sent will be placed into the Outbox folder, and
then remain there. I have my suspicions, but I'm not able to trace
Mail.app's execution deeply enough to figure out who is
repsonsible. The problem is not related to the system's network
location, or the actual mail payload itself (that I can
tell). Restarting Mail (usually) doesn't help.</p>
<p>Apple Support is essentially useless if there is a problem that's not
a short between the keyboard and chair. Despite the fact that the
problem had never once occurred previously and started literally
<em>minutes</em> after updating to OS X 10.9.3, they washed their hands of it
after determining that I could sometimes access my iCloud
account. This is completly reasonable since no Apple programmer has
<em>ever</em> made a coding error in recorded history.</p>
<p>While annoying, this did provide a clue: If the Mail Bundles are
uninstalled the outbox immediately empties when Mail is restarted.</p>
<p>Okay, so the update broke something on which one of the bundles
depends! I'll just contact the authors and submit a bug report!</p>
<p>Yeah... Not to easy.</p>
<p>I know it's not GPG Tools, because when that is the only bundle the
problem never happens -- it has to be the <a href="http://support.omnigroup.com/omnifocus-clip-o-tron/" title="Clip-O-Tron Download Page">Clip-O-Tron</a> or <a href="http://www.indev.ca/MailActOn.html" title="Mail Act-On Home Page">Mail
Act-On</a>. Both of these are made by <em>great</em> companies, so I submit
problems to both of them... and they both essentially say, "We're
happy to help once you prove it's our Bundle."</p>
<p>Thanks, guys. If I had the tools to do that (like your source code), I
would have just sent you a patch. How about you at least tell me how
to run your junk in debug mode?</p>
<h4>Solution</h4>
<p>So failing any meaningful help or direction, what's left to do? Script it! Below is an AppleScript that:</p>
<ul>
<li>Stops Mail.app</li>
<li>Moves the Bundles out of the way so Mail.app doesn't load them</li>
<li>Empties the Outbox folder<ul>
<li>Starts Mail.app</li>
<li>Waits until the Outbox has no messages</li>
<li>Stops Mail.app</li>
</ul>
</li>
<li>Moves the Bundles back into place</li>
<li>Starts Mail.app</li>
</ul>
<h5>Restart Mail.app AppleScript</h5>
<div class="highlight"><pre><span class="k">set</span> <span class="nv">mailDir</span> <span class="k">to</span> <span class="s2">"Macintosh HD:Users:ulmer:Library:Mail"</span> <span class="k">as</span> <span class="nv">alias</span>
<span class="k">tell</span> <span class="nb">application</span> <span class="s2">"Mail"</span>
<span class="nb">quit</span>
<span class="k">end</span> <span class="k">tell</span>
<span class="nv">waitForExit</span><span class="p">(</span><span class="s2">"Mail"</span><span class="p">)</span>
<span class="k">tell</span> <span class="nb">application</span> <span class="s2">"Finder"</span>
<span class="k">set</span> <span class="nb">the</span> <span class="na">name</span> <span class="k">of</span> <span class="nv">folder</span> <span class="s2">"Bundles"</span> <span class="k">of</span> <span class="nv">mailDir</span> <span class="k">to</span> <span class="s2">"Bundles.not"</span>
<span class="k">end</span> <span class="k">tell</span>
<span class="k">tell</span> <span class="nb">application</span> <span class="s2">"Mail"</span>
<span class="nb">activate</span>
<span class="k">repeat</span> <span class="k">until</span> <span class="ow">not</span> <span class="p">(</span><span class="nb">exists</span> <span class="nv">messages</span> <span class="k">in</span> <span class="nv">mailbox</span> <span class="s2">"Outbox"</span><span class="p">)</span>
<span class="nb">delay</span> <span class="mi">1</span>
<span class="k">end</span> <span class="k">repeat</span>
<span class="nb">quit</span>
<span class="k">end</span> <span class="k">tell</span>
<span class="nv">waitForExit</span><span class="p">(</span><span class="s2">"Mail"</span><span class="p">)</span>
<span class="k">tell</span> <span class="nb">application</span> <span class="s2">"Finder"</span>
<span class="k">set</span> <span class="nb">the</span> <span class="na">name</span> <span class="k">of</span> <span class="nv">folder</span> <span class="s2">"Bundles.not"</span> <span class="k">of</span> <span class="nv">mailDir</span> <span class="k">to</span> <span class="s2">"Bundles"</span>
<span class="k">end</span> <span class="k">tell</span>
<span class="k">tell</span> <span class="nb">application</span> <span class="s2">"Mail"</span>
<span class="nb">activate</span>
<span class="k">end</span> <span class="k">tell</span>
<span class="c">-- Wait until the process named as parameter is not running</span>
<span class="k">on</span> <span class="nv">waitForExit</span><span class="p">(</span><span class="nv">appName</span><span class="p">)</span>
<span class="k">tell</span> <span class="nb">application</span> <span class="s2">"System Events"</span>
<span class="k">repeat</span>
<span class="k">if</span> <span class="ow">not</span> <span class="p">(</span><span class="nb">exists</span> <span class="nb">application</span> <span class="nv">process</span> <span class="nv">appName</span><span class="p">)</span> <span class="k">then</span> <span class="k">exit</span> <span class="k">repeat</span>
<span class="nb">delay</span> <span class="mi">1</span>
<span class="k">end</span> <span class="k">repeat</span>
<span class="k">end</span> <span class="k">tell</span>
<span class="k">end</span> <span class="nv">waitForExit</span>
</pre></div>Hazel Rule for Hurley Travel Receiptstag:www.ulmer.org,2014-08-14:/2014/hazel-rule-for-hurley-travel-receipts2014-08-14T05:38:00ZStephen Ulmerhttp://www.ulmer.org/ulmer@ulmer.org<p>This article is a specific implementation of the concepts discussed in
<a href="http://www.ulmer.org/2014/hazel-for-expense-receipts/">Hazel for Expense Receipts</a>.</p>
<p>This rule is specifically so I can report the cost of an airline
ticket. My employer pays for the tickets directly, but we're still
required to add them as a non-reimbursable item on the appropriate
report. All other items in the itinerary get their own receipt from
the vendor (hotel or car rental company, et cetera).</p>
<p>My employer has had more than one travel agent, but all of their
documents have a <em>very</em> similar format. I suspect that all agents
booking for American Express Travel (Concur) will have formats that
are similar enough to adapt this rule.</p>
<p>I like to use the last leg of a flight as the date for reporting, in
case the trip goes over the end of a month.</p>
<p>The document contains a table that has a row for each "travel
event". So for each fight, hotel stay, or car rental there is a
row. I've never had an itinerary where the last row wasn't the final
flight, so I use that date -- your mileage may vary.</p>
<p>These are the details:</p>
<p><img alt="Rule Overview" src="http://www.ulmer.org/media/screenshots/hazel-hurley-travel-1.png" title="Rule Overiew"/></p>
<p>Notice that this rule matches two separate strings within the
document. When we book with this travel agent, we get a confirmation
of the request first, and once everythign is ticketed we get a second
message with a real itinerary attached.</p>
<p><img alt="Content for Match Pattern" src="http://www.ulmer.org/media/screenshots/hazel-hurley-travel-3.png" title="Content for Match Pattern"/></p>
<p>We have to look for a date (in the pattern below) that follows a word,
comma, and space. The last occurrance in the file is picked because
the search is configured to start at the end.</p>
<p><img alt="Date Pattern for Match" src="http://www.ulmer.org/media/screenshots/hazel-hurley-travel-4.png" title="Date Pattern for Match"/></p>
<p>The for this match, I named the pattern to reflect what it matches. So
two-digit month (zero padded), one digit day (no padding), four digit
year -- all separated by slashes.</p>
<p><img alt="Token Re-Use for Sorting" src="http://www.ulmer.org/media/screenshots/hazel-hurley-travel-5.png" title="Token Re-Use for Sorting"/></p>
<p>This just shows that you can reference the matched text from the
"match" area in the "action" area.</p>
<p><img alt="Date Patern Changed for Sorting" src="http://www.ulmer.org/media/screenshots/hazel-hurley-travel-6.png" title="Date Pattern Change for Sorting"/></p>
<p>Here we can see that the date pattern has been altered for use -- it's
been re-ordered, and the day has been removed.</p>Hazel Rule for Hertz Receiptstag:www.ulmer.org,2014-08-14:/2014/hazel-rule-for-hertz-receipts2014-08-14T05:31:00ZStephen Ulmerhttp://www.ulmer.org/ulmer@ulmer.org<p>This article is a specific implementation of the concepts discussed in
<a href="http://www.ulmer.org/2014/hazel-for-expense-receipts/">Hazel for Expense Receipts</a>.</p>
<p>This rule sorts an emailed receipt from Hertz Rent-A-Car into a folder
named for the year and month of the last day of the rental.</p>
<p>These are the details:</p>
<p><img alt="Rule Overview" src="http://www.ulmer.org/media/screenshots/hazel-hertz-receipt-2.png" title="Rule Overiew"/></p>
<p>We just check that the document is from Hertz, and then try to pick
out the correct date.</p>
<p><img alt="Content for Match Pattern" src="http://www.ulmer.org/media/screenshots/hazel-hertz-receipt-3.png" title="Content for Match Pattern"/></p>
<p>We have to look for a date (in the pattern below) that follows the
word "Date", a colon, and some amount of other text. The first
occurrance in the file is used, because this is the date that the
receipt was generated (which is always the last day of the rental).</p>
<p><img alt="Date Pattern for Match" src="http://www.ulmer.org/media/screenshots/hazel-hertz-receipt-4.png" title="Date Pattern for Match"/></p>
<p>The pattern for this match, which is named to reflect what it
matches. So two-digit month (zero padded), one digit day (no padding),
four digit year -- all separated by slashes.</p>
<p><img alt="Token Re-Use for Sorting" src="http://www.ulmer.org/media/screenshots/hazel-hertz-receipt-5.png" title="Token Re-Use for Sorting"/></p>
<p>This just shows that you can reference the matched text from the
"match" area in the "action" area.</p>
<p><img alt="Date Patern Changed for Sorting" src="http://www.ulmer.org/media/screenshots/hazel-hertz-receipt-6.png" title="Date Pattern Change for Sorting"/></p>
<p>Here we can see that the date pattern has been altered for use -- it's
been re-ordered, and the day has been removed.</p>Hazel for Expense Receiptstag:www.ulmer.org,2014-08-04:/2014/hazel-for-expense-receipts2014-08-04T04:45:00ZStephen Ulmerhttp://www.ulmer.org/ulmer@ulmer.org<p><a href="http://www.noodlesoft.com">Hazel</a> is a wonderful tool for
automatically sorting files. In fact, I've written a family of rules
that sort differnt types of receipts into folders for expense report
backup. These rules are assigned to my Downloads folder, which is used
as a "sorting folder".</p>
<p>Most of the expense document sorting rules have the same general
recipe:</p>
<ul>
<li>Identify the type of document (usually PDF)</li>
<li>Pick at least one unique text string</li>
<li>Somehow match the a date in the document contents that is used to
determine into which month's folder it will be sorted.</li>
<li>If the file name is not already unique, rename it such that it
(probably) is.</li>
<li>Move the file into ~/Work/Expenses.</li>
<li>Sort the file into a subfolder, creating it if necessary, with the
pattern YYYY-MM.</li>
</ul>
<h4>Other Articles</h4>
<ul>
<li><a href="http://www.ulmer.org/2014/hazel-rule-for-hertz-receipts/">Hazel Rule for Hertz Receipts</a></li>
<li><a href="http://www.ulmer.org/2014/hazel-rule-for-hurley-travel-receipts">Hazel Rule for Hurley Travel
Receipts</a></li>
</ul>Building HDF5 for OS X Maverickstag:www.ulmer.org,2014-02-14:/2014/building-hdf5-for-os-x-mavericks2014-02-14T15:45:00ZStephen Ulmerhttp://www.ulmer.org/ulmer@ulmer.org<p>There aren't always Mac versions of binary distributions of OSS, so
sometimes the package needs to be built with Xcode. This isn't a big
deal other than that I try to maintain a repeatable installation
discipline, and I like to be able to undo operations that are
performed on my systems. The best way to accomplish this is with
packages.</p>
<p>I needed to build HDF5 for a project. The Python bits are trivially
installed with pip, but they depend on native libraries... so I set
out to learn how to package the non-python dependencies.</p>
<p>Brew and macports just don't interest me right now. All told, there
are probably less than ten things that I need to compile and maintain,
so adding <em>another</em> package manger into the mix is just silly.</p>
<p>After some research -- <em>maybe</em> an hour total -- this is what I came up
with:</p>
<h3>SZIP</h3>
<div class="highlight"><pre><span class="p">.</span><span class="o">/</span><span class="n">configure</span> <span class="o">--</span><span class="n">prefix</span><span class="o">=/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span>
<span class="n">make</span>
<span class="n">DESTDIR</span><span class="o">=</span><span class="err">$</span><span class="p">(</span><span class="n">pwd</span><span class="p">)</span><span class="o">/</span><span class="n">DEST</span> <span class="n">make</span> <span class="n">install</span>
<span class="n">pkgbuild</span> <span class="o">--</span><span class="n">root</span> <span class="n">DEST</span> \
<span class="o">--</span><span class="n">ownership</span> <span class="n">recommended</span> \
<span class="o">--</span><span class="n">identifier</span> <span class="n">org</span><span class="p">.</span><span class="n">hdfgroup</span><span class="p">.</span><span class="n">szip</span> \
<span class="o">--</span><span class="n">version</span> <span class="mf">2.1</span> \
<span class="n">szip</span><span class="o">-</span><span class="mf">2.1</span><span class="p">.</span><span class="n">pkg</span>
</pre></div>
<h3>HDF5</h3>
<div class="highlight"><pre><span class="p">.</span><span class="o">/</span><span class="n">configure</span> <span class="o">--</span><span class="n">prefix</span><span class="o">=/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span> <span class="o">--</span><span class="n">with</span><span class="o">-</span><span class="n">szip</span><span class="o">=/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span>
<span class="n">make</span>
<span class="n">DESTDIR</span><span class="o">=</span><span class="err">$</span><span class="p">(</span><span class="n">pwd</span><span class="p">)</span><span class="o">/</span><span class="n">DEST</span> <span class="n">make</span> <span class="n">install</span>
<span class="n">pkgbuild</span> <span class="o">--</span><span class="n">root</span> <span class="n">DEST</span> \
<span class="o">--</span><span class="n">ownership</span> <span class="n">recommended</span> \
<span class="o">--</span><span class="n">identifier</span> <span class="n">org</span><span class="p">.</span><span class="n">hdfgroup</span><span class="p">.</span><span class="n">hdf5</span> \
<span class="o">--</span><span class="n">version</span> <span class="mf">1.8.12</span> \
<span class="n">hdf5</span><span class="o">-</span><span class="mf">1.8.12</span><span class="p">.</span><span class="n">pkg</span>
</pre></div>
<p>Obviuously the first paragraph of each example just configures and
builds an autoconf'd package. The second paragraph is the best
invocation for the OS X native package builder that I could make
before my attention span ran out. :) It literally just specifies from
where to get the files, what the installed permisions should be, the
name of the package for the receipts database and the name of the
output (package) file.</p>
<p>This was not hard.</p>Zero Configuration Web Galleriestag:www.ulmer.org,2014-01-30:/2014/zero-configuration-web-galleries2014-01-31T02:28:00ZStephen Ulmerhttp://www.ulmer.org/ulmer@ulmer.org<h4>Background</h4>
<p>Having migrated to static web generation, a full-featured web gallery
system just isn't an option. I don't want or need an RDBMS to store
meta-data, and there's certainly no reason to install an entire CMS
framework just to pubish some pictures. However, having a
four-year-old and a family that doesn't actually live in my back yard
makes some kind of web gallery a necessity.</p>
<p>Yes, there are many picture sharing social media venues. All of them:</p>
<ul>
<li>have terms of service that can change with little notice and no consent</li>
<li>have some kind of profit motive, mostly undisclosed</li>
<li>are conflicted between security and accessibility</li>
</ul>
<p>So we're on our own.</p>
<h4>Problem Domain</h4>
<p>Our household is firmly planted in the Apple Computer ecosystem. (No,
that's not part of the problem!) This means that we have iDevices, and
that we use iPhoto and Aperture to deal with the deluge of "kid
pictures."</p>
<p>Aperture is fine photo management software, and it is capable of
creating "web galleries". That is, it has built-in templates that can
be used to export self-contained, nicely-themed, chunks of web space
that one can upload to their own server. Unfortunately, Apple doesn't
make it readily apparent how to create your own templates. Also the
system to generate the galleries is IMHO more complex than required by
the level of flexibiity allowed.</p>
<p>I knew that I wanted a cool Lightbox-style slide show, but I also
wanted something that would "just work" if I uploaded a bunch of
pictures into a directory. Again, trying to avoid any actual
processing on the server.</p>
<h4>Solution Landscape</h4>
<h5>Lightbox Software</h5>
<p>I eventually settled on <a href="http://fancyapps.com/fancybox/" title="Fancybox Home Page">Fancybox</a> for two reasons:</p>
<ul>
<li>It has user-definable callbacks for many events. I was hoping that
some of these could be used by other software to pull captions (and
other information) from the EXIF data in the pictures and display
them.</li>
<li>It's based on <a href="http://jquery.com/" title="jQuery">jQuery</a>, and the Javascript EXIF parser that I found
also had a jQuery version. Sharing code is good.</li>
</ul>
<p>I also looked at other implementations:</p>
<ul>
<li><a href="http://lokeshdhakar.com/projects/lightbox2/">Lightbox2</a>, which is the rightious sucessor to the original
<a href="http://lokeshdhakar.com/projects/lightbox/">Lightbox</a>.</li>
<li><a href="http://lytebox.com/">Lytebox</a>, because there was already a <a href="http://www.jasonashdown.co.uk/2008/08/lytebox-with-javascript-exif-data/">project</a> to make use of
<a href="http://blog.nihilogic.dk/2008/05/reading-exif-data-with-javascript.html">EXIF</a> data.</li>
</ul>
<h5>Meta-data Extraction</h5>
<p>Part of the original problem specification was to get a "caption" out
of "the EXIF data." This goal is mal-formed.</p>
<p>EXIF doesn't really have a place for a "caption" -- there is an
exntirely different standard for shoving meta-data into digital
photographs called <a href="http://www.iptc.org/site/Home/">IPTC</a> - which was created by journalists.</p>
<p>Of course Aperture does "the right thing" and puts the caption in the
IPTC payload, not the EXIF payload. I had found a Javascript implementation
of an EXIF parser, not an IPTC parser. Yeah... so auto-captions will
have to wait for another day.</p>
<h5>Aperture Export</h5>
<p>Most Lightbox software requires two images - a full-size version and a
thumbail. In my case, I also needed a manifest of the images in order
to have Javascript dynamically insert the appropriate elements into
the DOM.</p>
<p>I created three presets in Aperture:</p>
<ul>
<li>export settings for the full-size images</li>
<li>export settings for the thumbnail images</li>
<li>a directory export setting that put the output in "thumbs" under the
target directory</li>
</ul>
<p>Next, it was straight forward to build AppleScript that would export
the current selection using those presets. It took a little fiddling
to get the file names out of the list of version objects, but I
evntually made it happen.</p>
<h4>Solution</h4>
<h5>Gallery Export AppleScript</h5>
<p>This is the AppleScript that exports the current selection into a
selected folder in such a way that the Javascript can build the Lightbox:</p>
<div class="highlight"><pre><span class="k">tell</span> <span class="nb">application</span> <span class="s2">"Finder"</span>
<span class="k">set</span> <span class="nv">destination</span> <span class="k">to</span> <span class="nb">choose folder</span>
<span class="k">end</span> <span class="k">tell</span>
<span class="k">tell</span> <span class="nb">application</span> <span class="s2">"Aperture"</span>
<span class="k">set</span> <span class="nv">lightbox</span> <span class="k">to</span> <span class="nb">first</span> <span class="nv">export</span> <span class="nv">setting</span> <span class="nb">whose</span> <span class="na">name</span> <span class="ow">is</span> <span class="s2">"Gallery Lightbox"</span>
<span class="k">set</span> <span class="nv">thumbnails</span> <span class="k">to</span> <span class="nb">first</span> <span class="nv">export</span> <span class="nv">setting</span> <span class="nb">whose</span> <span class="na">name</span> <span class="ow">is</span> <span class="s2">"Gallery Thumbnail"</span>
<span class="k">set</span> <span class="nv">dirPolicy</span> <span class="k">to</span> <span class="nb">first</span> <span class="nv">folder</span> <span class="nv">naming</span> <span class="nv">policy</span> <span class="nb">whose</span> <span class="na">name</span> <span class="ow">is</span> <span class="s2">"Project Name"</span>
<span class="k">set</span> <span class="nv">thumbDirPolicy</span> <span class="k">to</span> <span class="nb">first</span> <span class="nv">folder</span> <span class="nv">naming</span> <span class="nv">policy</span> <span class="nb">whose</span> <span class="na">name</span> <span class="ow">is</span> <span class="s2">"Gallery Thumbnails"</span>
<span class="k">set</span> <span class="nv">oVers</span> <span class="k">to</span> <span class="nv">selection</span> <span class="k">as</span> <span class="nv">list</span>
<span class="k">if</span> <span class="nv">oVers</span> <span class="ow">is</span> <span class="p">{}</span> <span class="k">then</span>
<span class="k">error</span> <span class="s2">"Please select some images to export!"</span>
<span class="k">else</span>
<span class="c">-- need to exclude versions with referenced, missing master</span>
<span class="k">set</span> <span class="nv">verList</span> <span class="k">to</span> <span class="nv">export</span> <span class="nv">oVers</span> <span class="nv">using</span> <span class="nv">lightbox</span> <span class="k">to</span> <span class="nv">destination</span> <span class="nv">naming</span> <span class="nv">folders</span> <span class="nv">with</span> <span class="nv">dirPolicy</span>
<span class="k">set</span> <span class="nv">thumbList</span> <span class="k">to</span> <span class="nv">export</span> <span class="nv">oVers</span> <span class="nv">using</span> <span class="nv">thumbnails</span> <span class="k">to</span> <span class="nv">destination</span> <span class="nv">naming</span> <span class="nv">folders</span> <span class="nv">with</span> <span class="nv">thumbDirPolicy</span>
<span class="c">-- Write one file name per line to MANIFEST</span>
<span class="k">try</span>
<span class="k">set</span> <span class="nv">projDir</span> <span class="k">to</span> <span class="nv">value</span> <span class="k">of</span> <span class="nv">other</span> <span class="na">tag</span> <span class="s2">"MasterLocation"</span> <span class="k">of</span> <span class="nb">the</span> <span class="nb">first</span> <span class="nb">item</span> <span class="k">in</span> <span class="nv">oVers</span>
<span class="k">set</span> <span class="nv">default_delimiters</span> <span class="k">to</span> <span class="no">AppleScript</span>'s <span class="no">text item delimiters</span>
<span class="k">set</span> <span class="no">AppleScript</span>'s <span class="no">text item delimiters</span> <span class="k">to</span> <span class="s2">":"</span>
<span class="k">set</span> <span class="nv">manifest</span> <span class="k">to</span> <span class="nb">open for access</span> <span class="nv">file</span> <span class="p">((</span><span class="nv">destination</span> <span class="k">as </span><span class="nc">string</span><span class="p">)</span> <span class="o">&</span> <span class="p">(</span><span class="nv">projDir</span> <span class="k">as </span><span class="nc">string</span><span class="p">)</span> <span class="o">&</span> <span class="s2">":MANIFEST"</span><span class="p">)</span> <span class="nv">with</span> <span class="nb">write</span> <span class="nv">permission</span>
<span class="k">repeat</span> <span class="nv">with</span> <span class="nv">ver</span> <span class="k">in</span> <span class="nv">verList</span>
<span class="nb">write</span> <span class="nb">text</span> <span class="nb">item</span> <span class="o">-</span><span class="mi">1</span> <span class="k">of</span> <span class="p">(</span><span class="nv">ver</span> <span class="k">as</span> <span class="na">rich text</span><span class="p">)</span> <span class="k">to</span> <span class="nv">manifest</span> <span class="k">as</span> <span class="na">rich text</span>
<span class="nb">write</span> <span class="p">(</span><span class="nb">ASCII character</span> <span class="mi">10</span><span class="p">)</span> <span class="k">to</span> <span class="nv">manifest</span>
<span class="k">end</span> <span class="k">repeat</span>
<span class="k">set</span> <span class="no">AppleScript</span>'s <span class="no">text item delimiters</span> <span class="k">to</span> <span class="nv">default_delimiters</span>
<span class="nb">close access</span> <span class="nv">manifest</span>
<span class="nb">on</span> <span class="k">error</span>
<span class="k">try</span>
<span class="k">set</span> <span class="no">AppleScript</span>'s <span class="no">text item delimiters</span> <span class="k">to</span> <span class="nv">default_delimiters</span>
<span class="nb">close access</span> <span class="nv">manifest</span>
<span class="no">return</span> <span class="no">false</span>
<span class="k">end</span> <span class="k">try</span>
<span class="k">end</span> <span class="k">try</span>
<span class="nb">display dialog</span> <span class="s2">"Export to "</span> <span class="o">&</span> <span class="nv">destination</span> <span class="o">&</span> <span class="s2">"complete."</span>
<span class="k">end</span> <span class="k">if</span>
<span class="k">end</span> <span class="k">tell</span>
</pre></div>
<h5>Dynamic Gallery Javascript</h5>
<p>This is the Jacascript that will build a Lightbox, given an export
arranged by the preceeding AppleScript:</p>
<div class="highlight"><pre> <span class="nx">$</span><span class="p">(</span><span class="nb">document</span><span class="p">).</span><span class="nx">ready</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">$</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s2">"MANIFEST"</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">lines</span> <span class="o">=</span> <span class="nx">data</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">'\n'</span><span class="p">);</span> <span class="c1">// one pic per line</span>
<span class="kd">var</span> <span class="nx">gallery</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="s1">'#gallery-container'</span><span class="p">);</span>
<span class="nx">lines</span> <span class="o">=</span> <span class="nx">$</span><span class="p">.</span><span class="nx">grep</span><span class="p">(</span><span class="nx">lines</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">n</span><span class="p">){</span> <span class="k">return</span><span class="p">(</span><span class="nx">n</span><span class="p">)</span> <span class="p">});</span> <span class="c1">// remove empty elements</span>
<span class="nx">$</span><span class="p">.</span><span class="nx">each</span><span class="p">(</span><span class="nx">lines</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">lineNo</span><span class="p">,</span> <span class="nx">line</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">$</span><span class="p">(</span><span class="s2">"<a />"</span><span class="p">,</span> <span class="p">{</span>
<span class="s2">"class"</span><span class="o">:</span> <span class="s2">"fancybox"</span><span class="p">,</span>
<span class="s2">"data-fancybox-group"</span><span class="o">:</span> <span class="s2">"gallery2"</span><span class="p">,</span>
<span class="s2">"href"</span><span class="o">:</span> <span class="nx">line</span><span class="p">,</span>
<span class="s2">"html"</span><span class="o">:</span> <span class="nx">$</span><span class="p">(</span><span class="s2">"<img />"</span><span class="p">,</span> <span class="p">{</span>
<span class="s2">"src"</span><span class="o">:</span> <span class="s2">"thumbs/"</span> <span class="o">+</span> <span class="nx">line</span>
<span class="p">})</span>
<span class="p">}).</span><span class="nx">appendTo</span><span class="p">(</span><span class="nx">gallery</span><span class="p">);</span>
<span class="p">});</span> <span class="c1">// each</span>
<span class="p">});</span> <span class="c1">// get MANIFEST</span>
<span class="cm">/*</span>
<span class="cm"> * Simple image gallery. Uses default settings.</span>
<span class="cm"> */</span>
<span class="nx">$</span><span class="p">(</span><span class="s1">'.fancybox'</span><span class="p">).</span><span class="nx">fancybox</span><span class="p">({</span>
<span class="nx">afterLoad</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="p">},</span> <span class="c1">// afterLoad</span>
<span class="nx">beforeShow</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="p">}</span> <span class="c1">// beforeShow</span>
<span class="p">});</span> <span class="c1">// fancybox</span>
<span class="p">});</span> <span class="c1">// ready</span>
</pre></div>
<h5>Apache Configuration</h5>
<p>In my web space, each gallery is a sub-folder of /pics. In order to
avoid special set-up for each new gallery, we to do the following:</p>
<ul>
<li>let mod_index create the list of galleries, prepending a header and
appending a footer generated for the web site theme -- this is the
only server-side "processing"</li>
<li>for any subdiretory of /pics, use gallery.html as the index file
(for the index.html document or just the gallery location URL)</li>
</ul>
<p>This .htaccess fragment accomplishes that:</p>
<div class="highlight"><pre><span class="nb">Options</span> +FollowSymlinks
<span class="nb">IndexOptions</span> NameWidth=*
<span class="nb">IndexIgnore</span> FOOTER* gallery.html
<span class="nb">HeaderName</span> HEADER.HTML
<span class="nb">ReadmeName</span> FOOTER.HTML
<span class="nb">RewriteEngine</span> <span class="k">on</span>
<span class="nb">RewriteCond</span> %{HTTPS} <span class="k">off</span>
<span class="nb">RewriteRule</span> (.*) https://%{HTTP_HOST}%{REQUEST_URI}
<span class="nb">RewriteBase</span> <span class="sx">/pics</span>
<span class="nb">RewriteRule</span> ^.+/$ <span class="sx">/pics/gallery.html</span> [L]
<span class="nb">RewriteRule</span> ^.+/index.html$ <span class="sx">/pics/gallery.html</span> [L]
</pre></div>
<h4>Summary</h4>
<p>It's not trivial, but all of the components are pretty simple. At
least now I can spend my gallery management time curating pictures.</p>A Tale of Two Chickenstag:www.ulmer.org,2013-09-13:/2013/a-tale-of-two-chickens2013-09-13T23:04:00ZStephen Ulmerhttp://www.ulmer.org/ulmer@ulmer.org<p>A while ago, I decided that I wanted to develop better skills for
working with whole food products. Even though I had been cooking for
years, I had never broken down a whole chicken <em>before</em> it was cooked!
Also, we were spending <em>way</em> too much money on food...</p>
<p>Most food products can be acquired in a less processed form, but the
easiest thing to tackle seemed to be chickens. By tackle I mean cut
up, because it would be silly for me to actually chase chickens around
and tackle them (unless we then proceded to eat them). At that time,
we were buying bags of boneless, skinless, Individually Quick Frozen
(IQF) chicken breasts from Sam's Club -- which is a convenient, but
very expensive way to buy chicken.</p>
<p>So the plan was to buy and use two whole chickens a week. Prices
increase during the winter, but for most of the year whole chickens
cost about 99 cents a pound at our local supermarket -- so two
chickens are about $10.</p>
<p>The chickens get broken down, and the wing tips, back, neck, and keel
bones are frozen for stock. The leg quarters and wings are used
immediately to cook-ahead some meals for the week. If I'm on the ball,
the cooked chicken is pulled while it's still hot and the roasted
bones go into a different bag in the freezer for stock. The breasts
get deboned, vacuum sealed and frozen for future use.</p>
<p>That's 8 chickens, or $40, per month. From that, my family gets:</p>
<ul>
<li>16-18 meal portions, depending on the application (leg quarters and wings)</li>
<li>2-3 gallons of home-made chicken stock (all of the bones)</li>
<li>Equivalent of 1.5 bags of IQF chicken breasts (deboned breasts)</li>
</ul>
<p>That makes the leg quarters about $2.25 per meal. Now thats not the
<em>best</em> food cost, but it's <em>so much less</em> than we were paying
before... and that doesn't even take into account the $60 worth of
chicken breasts and stock!</p>
<p>So far the favorite applications for pulled chicken seem to be:</p>
<ul>
<li>Just eating it (usually the first day)</li>
<li>Enchiladas</li>
<li>Chicken noodle soup (with homemade stock)</li>
<li>Quesadillas</li>
</ul>TSA "Response" to my complainttag:www.ulmer.org,2007-07-27:/2007/tsa-response-to-my-complaint2007-07-27T22:45:00ZStephen Ulmerhttp://www.ulmer.org/ulmer@ulmer.org<p>This is a copy of the response I received from the TSA about my complaint:</p>
<blockquote>
<p>Thank you for your e-mail.</p>
<p>The Transportation Security Administration's current security
screening procedures require all carry-on luggage and accessible
property be screened before passengers take them onboard an
aircraft. Regardless of whether an item is on the prohibited or
permitted items list, the Transportation Security Officers (TSO's)
have discretion to prohibit an individual from carrying an item
through the screening checkpoint or onboard an aircraft if the item
poses a security threat.</p>
<p>Therefore, TSA security screening personnel make the final decision
on whether to permit items like a Tide pen into the sterile area of
the airport. Should you need additional assistance, feel free to
contact us at toll free 866-289-9673.</p>
<p>Please visit our website at www.tsa.gov (http://www.tsa.gov/) for
additional information about TSA. We continue to add new information
and encourage you to check the website frequently for updated
information.</p>
<p>We hope this information is helpful.</p>
<p>TSA Contact Center
</p>
</blockquote>My TSA complainttag:www.ulmer.org,2007-07-27:/2007/my-tsa-complaint2007-07-27T13:30:00ZStephen Ulmerhttp://www.ulmer.org/ulmer@ulmer.org<p>This is the copy I received of the complaint I filed using the free
wireless access from the secure area of the Gainesville, FL (GNV)
airport.</p>
<blockquote>
<p>To: tsa-contactcenter@dhs.gov<br />
Category: Complaints<br />
Sub Category: All Other Complaints </p>
<p>Message: </p>
<p>While passing through security at the Gainesville Regional Airport
(GNV), my Tide(R) pen was confiscated from my quart zipper-top bag by
a TSA agent.</p>
<p>When asked why, I was told that bleach was not allowed on the
airplane. When I pointed out that the product does not contain bleach,
I was told that all hazardous substances were not allowed. I asked
that about the soap and water inside the Tide pen was hazardous, and
was told to "get going".</p>
<p>I can understand an agent at a busy airport having a bad day -- but
GNV is by no means busy, the TSA checkpoint was (over)-fully staffed,
and there was no reason to confiscate my item.</p>
<p>It is very clear to me that the agent made a mistake and then didn't
want to admit to that mistake in front of his co-workers or a
customer, there was very little that was professional about out
interaction.</p>
<p>I have the right to understand why items are confiscated form me -
particularly common items that I have flown with -- form the same
airport, with the same agent checking my bag -- dozens of times.</p>
<p>Please educate your agents, and maybe start looking out for security
rather than buys-work.</p>
<p>Regards,<br />
Stephen Ulmer</p>
</blockquote>Remember, Federal is Professional...tag:www.ulmer.org,2007-07-27:/2007/remember-federal-is-professional2007-07-27T13:10:00ZStephen Ulmerhttp://www.ulmer.org/ulmer@ulmer.org<p>Yet another example of idiocy provided by the Transportation Security
Administration (TSA): While travelling from Gainesville, FL (GNV) to
Atlanta, GA (ATL) on Delta airlines, my Tide Pen was confiscated.</p>
<p>Why am I angry about this? Well, I can tell you it's not because of
the $4 that my government has illegally confiscated -- if that
bothered me I'd make a FairTax reference. No, I'm angry because the
<em>reason</em> that my Tide Pen was confiscated is because the dolt of a TSA
agent arbitrarily decided that he was going to take <em>mine</em>. That's
it. More you say?</p>
<p>So the agent looks at the items in my 1 qt. zipper-top bag, removes my
Tide Pen, and then tells me that I can't have that in the
airport. When asked why, I was told that you can't take bleach on an
airplane. Well duh. So I pointed out that the confiscated product did
not contain any bleach what-so-ever. I was then told that all
hazardous substances were banned form airplanes. Okay. So i asked what
about the product was hazardous, and if the rules had been change
recently. <em>That was when I was told to move along.</em> So the guy who has
probably just figured out that he is a federal employee has refused to
answer my question.</p>
<p>While cro mangon man was pointedly ignoring me, I asked to speak to a
supervisor. It was at this point he told me <em>that I should move along
or face arrest</em>. For asking a question in a not-busy third-tier
airport after having been deprived of my property? <em>Arrest?</em></p>
<p>Had I been traveling under different circumstances, I might have
called his bluff -- I could do with owning where-ever this guy
lives...</p>Renewed Interest in Musictag:www.ulmer.org,2006-04-09:/2006/renewed-interest-in-music2006-04-09T04:00:00ZStephen Ulmerhttp://www.ulmer.org/ulmer@ulmer.org<p>I listen almost exclusively to talk radio and music to which I've
danced. Of course there is the occasional southern rock band, or
novelty record. Okay, lots of novelty records...but I digress.</p>
<p>WSKY, 97.3 FM, is a local News/Talk station in Gainesville, FL. Some
of the local jocks had been using tunes by <a href="http://www.cmt.com/artists/the-right-brothers/" title="The Right Brothers at CMT">The Right Brothers</a> as
bumper music. Well one of them managed to get the the whole band (both
of them) as guests on an afternoon show. They're hilarious! In
particular, I like their song, "What About the Issues?" (free
download)</p>
<p>They composed this song after getting several thousand emails, of
which only two were interested in having an actual persuasive
discussion -- the rest were just as you might expect from the
title. Their music seems to be varied in style: I would describe some
of it as metal and some as country (go figure). These guys appear to
be real musicians -- not synthesizer pilots. They lyrics are what you
might expect if Rush had had Neal Boortz writing their songs instead
of Neil Pert -- well, if Boortz had been introduced to them before
Libertarianism had taken over his <em>entire</em> brain.</p>
<p>Come to think of it, I'd like to hear a collaboration by those two...</p>Sell Me What's On the Label!tag:www.ulmer.org,2006-03-13:/2006/sell-me-what-s-on-the-label2006-03-13T04:00:00ZStephen Ulmerhttp://www.ulmer.org/ulmer@ulmer.org<p>One of my pet peeves is when a store tries to hide the fact that
they're selling me a returned item.</p>
<p>Now don't get me wrong, I'll buy the price-reduced open-box item at
<a href="http://www.bestbuy.com/" title="Best Buy Online Store">Best Buy</a> before I'll buy the new one. However, in that case, the
store actually lists what's missing from the package. At the very
least, they've marked the item such that I can compare it to a new one
and decide for myself if I'm willing to accept it instead of a new
one.</p>
<p>I went to the local Lowe's Home Improvement Store yesterday to buy
some sandpaper. I picked up a roll of adhesive backed paper that's
labelled "4 1/2in x 10yds, 120 grit" -- it's clearly a roll of 80 grit
sandpaper. How can the person who accepted that return possibly be
worth whatever they're paid to work there. I understand that not
everyone is handy, but it's hard to mistake 80 grit paper for 120 grit
paper.</p>
<p>But wait, there's more!</p>
<p>I pick up another roll of paper that's <em>maybe</em> 1/3 the size of the
first roll -- and it has the same stinkin' label. Obviously these
rolls of sandpaper can't be the same length! So I took both packages
to the service desk and explained that I wanted to complain. After
only 5 minutes of explaining I managed to convince them that maybe
someone should go look at all of the paper on the display (I'm still
pretty sure that they didn't understand that two identical products
shouldn't be different shapes, sizes and weights).</p>
<p>So I came home and ordered everything I needed from <a href="http://www.onlineindustrialsupply.com/" title="Online Industrial Supply Home Page">Online Industrial
Supply Corporation</a>, who ironically has better prices.</p>My congressman isn't listeningtag:www.ulmer.org,2006-02-15:/2006/my-congressman-isn-t-listening2006-02-15T04:00:00ZStephen Ulmerhttp://www.ulmer.org/ulmer@ulmer.org<p>I sent my congressman <a href="http://www.ulmer.org/2006/my-congressman-isn-t-listening/mailto:fl03reply@mail.house.gov">Representative Corrine Brown</a> a request for
support from the <a href="http://www.fairtax.org/" title="Fair Tax website">Fair Tax Website</a>. Her reply (which was sent
twice, 13 minutes apart) did not contain the word "tax" , and the only
occurance of the word "fair" was in reference to the 2000 and 2004
elections.</p>
<p>Her response, clearly a form message, is only surprising in that it
doesn't contain the word "tax" at all -- I'm surprised that <em>any</em>
congressman is able to avoid that three letter word in a 606 word
email.</p>
<p>I am also amused that it's 2006 and a point of focus for my elected
U.S. representative is the 2000 Presidential Election. Shouldn't we,
in the year 2006, look forward? How about focusing on something that I
care about? Oh, wait! Maybe the thing I asked about, the Fair Tax!</p>
<p>It disgusts me that I might have to become a single-issue voter.</p>