<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom">
  <title>Bill Lovett</title>
  <link href="http://ilovett.com" />
  <link rel="self" href="http://ilovett.com/blog/feed" />
  <updated>2010-01-02T00:00:00-08:00</updated>
  <author>
    <name>Bill Lovett</name>
    <uri>http://ilovett.com</uri>
  </author>
  <id>http://ilovett.com/</id>
    <entry>
    <title>Disabling i18n in CakePHP</title>
    <link href="http://ilovett.com/blog/programming/cakephp-disable-i18n" />
    <id>http://ilovett.com/blog/programming/cakephp-disable-i18n</id>
    <published>2010-01-02T00:00:00-08:00</published>
    <updated>2010-01-02T00:00:00-08:00</updated>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
      </div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>I ran into an unusual problem in CakePHP recently. A site I'm
working on uses CakePHP's internationalization and localization
features unnecessarily. The codebase is full of references to
the <code>__()</code> function, but they're pointless because the site
isn't actually multi-lingual. So I have this capability that I don't
necessarily want right now, but getting rid of it isn't trivial and at
some point I may have a need for it.</p>

<p>Just about everything comes with a performance cost, and this
feature is no
exception. Using <a href="http://code.google.com/p/webgrind/"
rel="external">webgrind</a>, I could see the I18n class sucking up
time and resources even though it was doing a whole lot of nothing. I
wanted to correct that.</p>

<p>The solution was to create a stub class. If CakePHP sees that a
class named I18n has not been loaded, it will attempt to load it. I
could have prevented that from happening by editing the file, but that
would complicate future upgrades. Loading a stub class which has
the same interface but none of the bloat avoids that.</p>

<p>For lack of a better place, I put my stub class
in <code>app/vendors/i18n.php</code> and loaded it from
the <code>AppController</code> constructor. It contains a single
function, <code>translate()</code>, which returns its first argument
unmodified. Ordinarily that would be dumb, but in this case it's an
optimization.</p>

<p>Webgrind still shows the same number of invocations for
the I18n class, but they're taking much less time.</p>

      </div>
    </content>
  </entry>
    <entry>
    <title>Updating WordPress via Phing</title>
    <link href="http://ilovett.com/blog/programming/updating-wordpress-via-phing" />
    <id>http://ilovett.com/blog/programming/updating-wordpress-via-phing</id>
    <published>2009-12-26T00:00:00-08:00</published>
    <updated>2009-12-26T00:00:00-08:00</updated>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
      </div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>Here's what I'm using to upgrade WordPress:</p>

<script src="http://gist.github.com/264140.js"></script>


<p>A WordPress installation can be divided into three parts. The first
part involves the core WordPress folders: <code>wp-admin</code> and
<code>wp-includes</code>. You normally don't change anything in these
folders, so upgrading them can just be a matter of deleting what
you've got and replacing it.</p>

<p>The second part involves customized folders. The most important of
these is <code>wp-content</code>, since it contains your site's theme
and plugins, but you might have other folders that are similarly
off-limits as far as upgrading is concerned. Whatever happens during
the upgrade process, we don't want to touch this stuff.</p>

<p>The final part involves the PHP files at the root level of the
site. These are mostly <code>wp-*</code> files that aren't changed,
except for <code>wp-config.php</code>, which is.</p>

<p>Conveniently, the URL for the latest version of WordPress is always
the same. I use <code>curl</code> to download it to <code>/tmp</code>
because it allows me to pipe the download straight into tar. After
deleting the core WordPress folders recursively, I rename
<code>wp-config.php</code> and any other custom PHP files (in this
example, <code>share-via-email.php</code>) with a <code>.bak</code>
extension so that they'll be preserved during the subsequent wipeout
of all PHP, HTML, and TXT files in the site root.</p>

<p>From this point, it's just a matter of copying in the new files and
restoring the <code>.bak</code> files to their original name. Since
the deletion process was restricted to known extensions, the only risk
is in forgetting to make an exception for customized files. Version
control can help with that, especially if you've accidentally
deleted or overwritten something important.</p>

<p>I haven't accounted for <code>.svn</code> folders within the core
folders. If you ran this target as-is, Subversion would complain about
the sudden absence of <code>.svn</code> folders within the
newly-copied <code>wp-admin</code> and <code>wp-includes</code>. This
is a great reason for exploring other options like <code>git</code>
that centralize all their stuff in a single directory.</p>



      </div>
    </content>
  </entry>
    <entry>
    <title>A Phing Tipping Point</title>
    <link href="http://ilovett.com/blog/programming/phing-tipping-point" />
    <id>http://ilovett.com/blog/programming/phing-tipping-point</id>
    <published>2009-12-24T00:00:00-08:00</published>
    <updated>2009-12-24T00:00:00-08:00</updated>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
      </div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>One of the most benefical tools I picked up this year is <a
href="http://phing.info" rel="external">Phing</a>, a build system for
PHP based on Ant. I had known about it for a while, but never made
much headway because I didn't think I needed to do any building. I
already had rsync scripts--I figured I was set. It's just PHP.</p>

<p>WordPress deployment was my Phing tipping point. The first time you
deploy a WordPress site from development to staging and realize that
the paths inside your database dump are all wrong for is the first
clue you need Phing. The next clue happens when you need to pull from
production back to development, and face the same problem in
reverse.</p>

<p>I had previously been using Bash scripts for this sort of thing. I
had one for pushing out from dev, and another for pulling in. Bash
scripts are great. The problem is keeping track of them. A few months
later I needed to do some maintenance work, but the magical
combination of which scripts needed to be run in which order was no
longer apparent. Plus, I had done another WordPress project in the
meantime and set things up slightly differently. The changes hadn't
been propagated back to the first project. Things ended up
semi-automatic and half-effective.</p>

<p>Phing clicked for me once I figured out ExecTask was the gateway to
rsync. Rsync is crucial for getting files from point A to point B in a
sensible fashion, so I always gave up when I couldn't find any mention
of it in Phing's <a href="http://phing.info/docs/guide/stable/"
rel="external">manual</a>. Eventually I did find reference to a
third-party RsyncTask, but I stuck with ExecTask because it's built
into Phing and applicable to just about any shell command you might
want to run.</p>

<p>Once you can run shell commands, pretty anything is up for
grabs. Phing started to make a lot more sense because it was a
standard tool that could wrap the eccentricities of an individual
project with consistent behavior. I no longer needed extra bash
scripts in my source tree, just a single build.xml at the project
root.</p>

<p>Phing is great because it covers the basics but keeps PHP at close
hand if you need it. There's not much of a learning curve once you get
the hang of declaring and using variables (properties) within the
context of XML. If you keep things abstract enough, build targets are
pretty easy to reuse between projects. Once you figure out how to flip
your WordPress database between environments, the only things that
need changing from project to project are hostnames and filesystem
paths.</p>

<p>For example, in an earlier post on <a
href="http://ilovett.com/blog/programming/revving-file-names">revving
file names</a>, I described a way of using Phing to add hashes to
filenames for better cacheing. Dropping that into another project
doesn't cause much toolchain disruption because you have one thing
orchestrating everything from start to finish, instead of independent
scripts each doing their own thing.</p>

<p>That's the part that I was missing. I was managing the build and
deployment process every time I needed to make an upate, instead of
defining the process once and reaping the benefits of true
automation.</p>

      </div>
    </content>
  </entry>
    <entry>
    <title>Revving File Names with Hashes</title>
    <link href="http://ilovett.com/blog/programming/revving-file-names" />
    <id>http://ilovett.com/blog/programming/revving-file-names</id>
    <published>2009-11-01T14:00:00-08:00</published>
    <updated>2009-11-01T14:00:00-08:00</updated>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
      </div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>In <a href="http://www.amazon.com/gp/product/0596529309?ie=UTF8&amp;tag=ilovettcom-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0596529309">High Performance Web Sites</a>, Steve Souders explains the
value of adding a version number to resource filenames so that they
are both cacheable and replaceable. In <a
href="http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/">a
blog post</a>, he further explains why the querystring is not an optimal spot
for these numbers.</p>

<p>To create the version numbers, I've been using a variation on the technique described by Kevin Hale in <a href="http://particletree.com/notebook/automatically-version-your-css-and-javascript-files/">Automatically Version Your CSS and JavaScript Files</a>. His approach uses PHP to append the modification date of each file to its filename. An Apache rewrite rule allows those dates to be virtual, so that the client sees a path like <code>/css/structure.1194900443.css</code> but the server interprets it as <code>/css/structure.css</code>.</p>

<p>The first time I read Kevin's article, I wasn't keen on the PHP part. Even if the overhead of filemtime is miniscule, why have it there at all? My solution was to define a single PHP constant that could be populated by a build script during deployment, and then appended in all my CSS and JavaScript links. What could possibly go wrong?</p>

<p>If you have one version number for all your files, you end up treating them as a set. That's not good. If you upload some new CSS the new version number will be applied across the board, even to files that haven't changed. That cuts down on the longevity of your cached files, which is the opposite of what we're trying to accomplish. I was generating version numbers from Unix time at the moment of deployment, but the same thing could have happened if I used the most recent source control revision. Each file really needs to be revved separately.</p>

<p>SHA1 to the rescue. Version numbers based on the sha1 hash of each file ensure that a change to one file won't impact the version number of any other file. They're also less fragile than date-based version numbers, which can be changed in the course of copying files around unless you're careful. I also prefer the anonymity of the hashes because they don't reveal anything about a file's age.</p>

<p>I've started using <a href="http://phing.info">Phing</a>, so generating and inserting the hashes is easy. A <a href="http://phing.info/trac/changeset/590">FileHash task</a> exists, but I'm using an ad-hoc task for now:</p>

<script src="http://gist.github.com/223683.js"></script>

      </div>
    </content>
  </entry>
    <entry>
    <title>Set The Size and Position of Emacs Frames</title>
    <link href="http://ilovett.com/blog/emacs/emacs-frame-size-position" />
    <id>http://ilovett.com/blog/emacs/emacs-frame-size-position</id>
    <published>2009-08-08T00:00:00-07:00</published>
    <updated>2009-08-08T00:00:00-07:00</updated>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
      </div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <h2>The Problem</h2>

When Emacs is launched, its initial window ("frame") is sized and
positioned according to application defaults instead of your own
preferences. Inevitably, you adjust it to your liking. But this fiddling
happens every time Emacs launches and it distracts you from
the task at hand. It would be more efficient if Emacs automatically sized the
frame according to your expectations.

<h2>The Solution</h2>
<script src="http://gist.github.com/164792.js"></script>
<noscript>
(defun arrange-frame (w h x y)
  "Set the width, height, and xy coordinates of the current frame, deleting all others"
  (let ((frame (selected-frame)))
    (delete-other-windows)
    (set-frame-position frame x y)
    (set-frame-size frame w h)))

(arrange-frame 160 50 2 22)
</noscript>

<p>I call this function immediately after defining it so that it takes
effect as soon as possible. There's a slight lag between the
time Emacs draws the initial frame at its default size and the time
the resize happens. It's not instantaneous, but it does happen fast.
That's good enough for me, because I just want to avoid unnecessary
window fiddling.</p>

<div align="center">
<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/8pMBgSt-UYU&amp;hl=en&amp;fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/8pMBgSt-UYU&amp;hl=en&amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object>
</div>

<p>Taking things a step further, you could have different window
configurations for different circumstances: a large window that
occupies the full screen on a laptop and a less wide but taller window
for a desktop monitor, or one setup for when you're on a Mac and
another for when you're not.</p>

<h2>References</h2>
I started with the function from <a
href="http://blog.zenspider.com/2007/02/control-your-emacs-frames-prog.html"
rel="external">Control your emacs frames programatically</a> and
simplified it by removing the <code>nosplit</code> parameter, the
platform detection, and the hard-coded frame position
coordinates. Note that as of Emacs 23, the line <code>(when (equal
'mac (framep frame))</code> should be <code>(when (equal 'ns (framep frame))</code>



      </div>
    </content>
  </entry>
    <entry>
    <title>Automating HTML Image Tags in Emacs</title>
    <link href="http://ilovett.com/blog/emacs/automating-html-image-tags" />
    <id>http://ilovett.com/blog/emacs/automating-html-image-tags</id>
    <published>2009-08-01T00:00:00-07:00</published>
    <updated>2009-08-01T00:00:00-07:00</updated>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
      </div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <h2>The Problem</h2> <p>To write an image tag, you need to know the
width and height of the image. Determining those numbers forces you to
leave Emacs and consult another application such as Photoshop or your
file manager. Locating the target file is a timesink, as is typing the
height, width, and alt attributes. Omitting the width and height can
have undesireable side effects and is not a best practice.</p>

<h2>The Solution</h2>

<script src="http://gist.github.com/159869.js"></script>
<noscript>
(defun relpath (file &amp;optional skipinsert)
     (interactive "FPath: ")
     (let* (
           (basePath
            (file-name-directory
             (expand-file-name
              (buffer-file-name (current-buffer)))))
           (targetPath
            (expand-file-name file))
           (basePathSegments
            (split-string basePath "/"))
           (targetPathSegments
            (split-string targetPath "/"))
           segment1
           segment2
           )

       (while basePathSegments
         (setq segment1 (pop basePathSegments))
         (setq segment2 (pop targetPathSegments))
         (unless (equal segment1 segment2)
           (progn
             (push segment2 targetPathSegments)
             (if (> (length basePathSegments) 0)
                 (push ".." targetPathSegments)))
           ))
       (setq targetPath (mapconcat 'identity targetPathSegments "/"))
       (if (eq nil skipinsert)
           (insert targetPath)
         targetPath)))


(defun img-tag (file alt)
  "Create an image tag from the specified file path"
  (interactive "FPath: \nsAlt text: ")
  (let ((image-size
         (let ((ximg (create-image file)))
           (image-size ximg t)))
        (relative-path (relpath file t)))
        (insert "<img src=\"" relative-path "\" "
                "alt=\"" alt "\" "
                "width=\"" (number-to-string (car image-size))
                "\" "
                "height=\"" (number-to-string (cdr image-size))
                "\" />")))
</noscript>

<p>The function first prompts you for the image file. The usual
autocompletion features are in effect, so the typing shouldn't be too
onerous. Other than alt text, everything else is automatic. Emacs is
figuring out the image width and height on its own, so there's no
reliance on third-party tools.</p>

<div align="center">
<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/U1psMts1GrI&amp;hl=en&amp;fs=1&amp;color1=0x3a3a3a&amp;color2=0x999999"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/U1psMts1GrI&amp;hl=en&amp;fs=1&amp;color1=0x3a3a3a&amp;color2=0x999999" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object>
</div>


<h2>References</h2>

<ol>
  <li><a href="http://xahlee.org/emacs/elisp_image_tag.html" rel="external nofollow">Elisp Lesson: Writing image-linkify Function</a></li>
</ol>

<h2>Revisions</h2>
<ul>
<li>August 8, 2009: Added missing code for <code>relpath</code> function,
which is used by <code>img-tag</code></li>
</ul>


      </div>
    </content>
  </entry>
    <entry>
    <title>Smartening Subversion with Perl</title>
    <link href="http://ilovett.com/blog/programming/smartening-subversion-with-perl" />
    <id>http://ilovett.com/blog/programming/smartening-subversion-with-perl</id>
    <published>2007-08-06T14:20:00-07:00</published>
    <updated>2007-08-06T14:20:00-07:00</updated>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
      </div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>One thing I've never liked about using Subversion from the
command line is that it's tedious to add and remove
files. Although the <code>svn status</code> command tells you the
state of the files in your current checkout, its output is not
used when doing <code>svn add</code> or <code>svn
remove</code>. You end up retyping files paths, or copying and
pasting. That's not efficient.</p>

<p>A little interactivity would be much more helpful, and that's what
<a href="http://ilovett.com/public/downloads/svnask.txt">svnask.pl</a>
provides. It's a short and very simple Perl script that runs <code>svn
status</code>, looks for files with a state of "?" or "!", and prompts
for a yes-no on whether to add or remove each one from the
checkout. Since "yes" is the default, you can operate on a whole mess
of files with barely any effort.</p>

<p>Another efficiency problem I've come across with Subversion
involves keeping track of multiple checkouts from multiple
repositories. I have numerous projects in various states and bounce
around from one to another. Sometimes I forget to do a check in,
especially if I've only made a trivial change to one file. Weeks can
pass before I notice I have outstanding revisions. With <a
href="http://ilovett.com/public/downloads/svnstatus.txt">svnstatus.pl</a>
run daily via cron, this is no longer a problem. The script examines
one or more directories and runs <code>svn status</code>, producing an
accumulated status report of all known repositories. If there are
outstanding changes, cron will deliver the details in an email.</p>

      </div>
    </content>
  </entry>
    <entry>
    <title>Simplified Ad Blocking</title>
    <link href="http://ilovett.com/blog/projects/simplified-ad-blocking" />
    <id>http://ilovett.com/blog/projects/simplified-ad-blocking</id>
    <published>2007-07-28T10:54:00-07:00</published>
    <updated>2007-07-28T10:54:00-07:00</updated>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
      </div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>About a year ago, I <a
href="http://ilovett.com/blog/projects/apache-proxy">replaced the
Squid proxy on my home network with Apache's mod_proxy</a>. I
wanted to continue blocking annoying ads on web pages without
keeping an additional service running. It seemed like an obvious
choice since Apache was already in the picture and ready to serve.</p>

<p>Things weren't all they were cracked up to be with mod_proxy. Setup
and configuration took a lot of fiddling and fusing, and there was a
bottleneck somewhere along the way that often made pages load more
slowly. I had all sorts of URL rewriting power at my disposal, but not
a solution that worked all the time, every time. So I scrapped the
whole thing and did without.</p>

<p>Web page ads are still annoying though, and I still want to block
them. Now I think I've got the right mix of simplicity and
reliability. It's essentially the solution described at <a
href="http://macmerc.com/sections.php?op=viewarticle&amp;artid=83">Superior
Ad Blocking on OS X</a>: add the hostnames of known ad servers to your
hosts file, then configure Apache's ErrorDocument to return a blank
page rather than the default message.</p>

<p>The one change I made was to point ErrorDocument to a  1x1
pixel GIF rather than an empty HTML page. This prevents broken image
icons from appearing, and doesn't appear to create any problems with
requests that expect to receive text.</p>

<p>I'm also adding the names of ad servers to my hosts file by hand,
rather than grabbing one of the lists available from <a
href="http://en.wikipedia.org/wiki/Hosts_file">Wikipedia's page on the
Hosts file</a>. This way I'm only blocking the ad servers I've
actually encountered, and not hundreds or thousands I'd never
otherwise come across (if they're still in fact active).</p>

      </div>
    </content>
  </entry>
    <entry>
    <title>A Simple Way of Monitoring a Dynamic IP Address</title>
    <link href="http://ilovett.com/blog/programming/simple-ip-address-monitor" />
    <id>http://ilovett.com/blog/programming/simple-ip-address-monitor</id>
    <published>2006-11-13T16:45:00-08:00</published>
    <updated>2006-11-13T16:45:00-08:00</updated>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
      </div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>For the longest time, I've had a cron job running on my server at
home that used <code>ipcheck</code> (apt-cache show ipcheck) to update
<a href="http://www.dyndns.com/">DynDNS</a> with the current IP
address of my cable modem. Just in the off chance that said address
would change at an inconvenient time, leaving me without a path back
to home base.</p>

<p>That script and service did a fine job. Unfortunately, my cable
modem's IP address rarely changes. And even if it did, I probably
wouldn't be all that inconvenienced. Maybe a little. If the address
did change, I'd really only need to know the new one. I'm definitely
not in need of any fancy service monitoring. What's the simplest
solution then?</p>

<p>If you have a website and access to its access logs, the answer
might just be <code>curl</code>. By switching my cron job to
something like this:

<pre>
curl -I -A "hostname of my server" http://example.com &lt; /dev/null
</pre>

I'll end up with easily identifiable entries in my webserver
logs. Using HEAD requests (-I) keeps the request and response lean,
and I can grep based on that and/or the hostname of my server. As an
added bonus, I also end up with a basic availability heartbeat. If
there's nothing in the log files after a certain point in time,
something has more than likely gone wrong.</p>

<p>I should have gone this route all along. DynDNS is a better choice
when dealing with IP addresses directly would be otherwise
inconvenient. But I'm not exactly in that boat.</p>


      </div>
    </content>
  </entry>
    <entry>
    <title>Whitelisting Addresses in Gmail</title>
    <link href="http://ilovett.com/blog/projects/gmail-whitelist" />
    <id>http://ilovett.com/blog/projects/gmail-whitelist</id>
    <published>2006-10-26T15:58:00-07:00</published>
    <updated>2006-10-26T15:58:00-07:00</updated>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
      </div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>Gmail allows you filter incoming messages, but it only gives you a
couple options on what actions can be taken: Archive, Star, Label,
Forward, or Delete. There's no "Whitelist" or "Don't Flag as Spam"
option. Which is naturally what I was looking for.</p>

<p>Whitelisting can reduce the chances of false positives-- legitimate
messages that incorrectly end up in your Spam folder because Gmail
took them the wrong way for one reason or another.</p>

<p>Whitelisting is possible with Gmail, just not in correlation with
filters. I didn't realize that messages sent from addresses in your
Contacts list were automatically safeguarded; even better, it seems
that <a
href="http://ryanduff.net/archives/2006/08/17/whitelist-domains-in-gmail/">wildcarding
is accepted</a> and can allow you to whitelist an entire domain
instead of an individual address.</p>

<p>Features like these are easily missed when you take advantage of
Gmail's POP service and do all your writing and responding with
another email client.</p>

<p>What about importing addresses into your Gmail Contacts list? <a
href="http://homepage.mac.com/kenferry/software.html#AddressBookToCSV">AddressBookToCSV</a>
worked well for me. It's a script that turns the content of your OS X
Address Book into a CSV file that Gmail can import. Only name and
email address make it through however.</p>

      </div>
    </content>
  </entry>
  </feed>
