Stephen Ulmer http://www.ulmer.org/ ulmer@ulmer.org ulmer.org tag:www.ulmer.org,2011-06-11:/atom/ http://www.ulmer.org/favicon.ico http://www.ulmer.org/feed-logo.png 2014-09-05T20:30:00Z acrylamid Empty Mail.app Outbox tag:www.ulmer.org,2014-09-05:/2014/empty-mail-app-outbox 2014-09-05T20:30:00Z Stephen Ulmer http://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">&quot;Macintosh HD:Users:ulmer:Library:Mail&quot;</span> <span class="k">as</span> <span class="nv">alias</span> <span class="k">tell</span> <span class="nb">application</span> <span class="s2">&quot;Mail&quot;</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">&quot;Mail&quot;</span><span class="p">)</span> <span class="k">tell</span> <span class="nb">application</span> <span class="s2">&quot;Finder&quot;</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">&quot;Bundles&quot;</span> <span class="k">of</span> <span class="nv">mailDir</span> <span class="k">to</span> <span class="s2">&quot;Bundles.not&quot;</span> <span class="k">end</span> <span class="k">tell</span> <span class="k">tell</span> <span class="nb">application</span> <span class="s2">&quot;Mail&quot;</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">&quot;Outbox&quot;</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">&quot;Mail&quot;</span><span class="p">)</span> <span class="k">tell</span> <span class="nb">application</span> <span class="s2">&quot;Finder&quot;</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">&quot;Bundles.not&quot;</span> <span class="k">of</span> <span class="nv">mailDir</span> <span class="k">to</span> <span class="s2">&quot;Bundles&quot;</span> <span class="k">end</span> <span class="k">tell</span> <span class="k">tell</span> <span class="nb">application</span> <span class="s2">&quot;Mail&quot;</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">&quot;System Events&quot;</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 Receipts tag:www.ulmer.org,2014-08-14:/2014/hazel-rule-for-hurley-travel-receipts 2014-08-14T05:38:00Z Stephen Ulmer http://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 Receipts tag:www.ulmer.org,2014-08-14:/2014/hazel-rule-for-hertz-receipts 2014-08-14T05:31:00Z Stephen Ulmer http://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 Receipts tag:www.ulmer.org,2014-08-04:/2014/hazel-for-expense-receipts 2014-08-04T04:45:00Z Stephen Ulmer http://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 Mavericks tag:www.ulmer.org,2014-02-14:/2014/building-hdf5-for-os-x-mavericks 2014-02-14T15:45:00Z Stephen Ulmer http://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 Galleries tag:www.ulmer.org,2014-01-30:/2014/zero-configuration-web-galleries 2014-01-31T02:28:00Z Stephen Ulmer http://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">&quot;Finder&quot;</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">&quot;Aperture&quot;</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">&quot;Gallery Lightbox&quot;</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">&quot;Gallery Thumbnail&quot;</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">&quot;Project Name&quot;</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">&quot;Gallery Thumbnails&quot;</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">&quot;Please select some images to export!&quot;</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">&quot;MasterLocation&quot;</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>&#39;s <span class="no">text item delimiters</span> <span class="k">set</span> <span class="no">AppleScript</span>&#39;s <span class="no">text item delimiters</span> <span class="k">to</span> <span class="s2">&quot;:&quot;</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">&amp;</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">&amp;</span> <span class="s2">&quot;:MANIFEST&quot;</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>&#39;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>&#39;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">&quot;Export to &quot;</span> <span class="o">&amp;</span> <span class="nv">destination</span> <span class="o">&amp;</span> <span class="s2">&quot;complete.&quot;</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">&quot;MANIFEST&quot;</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">&#39;\n&#39;</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">&#39;#gallery-container&#39;</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">&quot;&lt;a /&gt;&quot;</span><span class="p">,</span> <span class="p">{</span> <span class="s2">&quot;class&quot;</span><span class="o">:</span> <span class="s2">&quot;fancybox&quot;</span><span class="p">,</span> <span class="s2">&quot;data-fancybox-group&quot;</span><span class="o">:</span> <span class="s2">&quot;gallery2&quot;</span><span class="p">,</span> <span class="s2">&quot;href&quot;</span><span class="o">:</span> <span class="nx">line</span><span class="p">,</span> <span class="s2">&quot;html&quot;</span><span class="o">:</span> <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;&lt;img /&gt;&quot;</span><span class="p">,</span> <span class="p">{</span> <span class="s2">&quot;src&quot;</span><span class="o">:</span> <span class="s2">&quot;thumbs/&quot;</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">&#39;.fancybox&#39;</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 Chickens tag:www.ulmer.org,2013-09-13:/2013/a-tale-of-two-chickens 2013-09-13T23:04:00Z Stephen Ulmer http://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 complaint tag:www.ulmer.org,2007-07-27:/2007/tsa-response-to-my-complaint 2007-07-27T22:45:00Z Stephen Ulmer http://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 complaint tag:www.ulmer.org,2007-07-27:/2007/my-tsa-complaint 2007-07-27T13:30:00Z Stephen Ulmer http://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-professional 2007-07-27T13:10:00Z Stephen Ulmer http://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 Music tag:www.ulmer.org,2006-04-09:/2006/renewed-interest-in-music 2006-04-09T04:00:00Z Stephen Ulmer http://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-label 2006-03-13T04:00:00Z Stephen Ulmer http://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 listening tag:www.ulmer.org,2006-02-15:/2006/my-congressman-isn-t-listening 2006-02-15T04:00:00Z Stephen Ulmer http://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>