Here at EchoDitto, most of our servers are running CentOS Linux, which is a 100% binary-compatible version of the industry standard Red Hat Enterprise Linux (RHEL) without any of the fees. The problem with RHEL/CentOS is that they shipped with PHP 5.1.6, and as of this writing PHP is at 5.2.9. That's not a big deal, being a minor point revision behind, until you come across an application or module that needs a minimum of version 5.2. The last thing I want to do is install packages from a third-party or build it from source and risk breaking other packages. So what's the answer? Building it from the source rpm. There's no better way to keep the system free of third-party packages but also up to date.
After working on some 50-odd Drupal projects over the past few years and inheriting a number of (often questionable) others, it occurred to us it'd be a good idea to have a script that detects hacks and/or "modifications" to Drupal core for a given Drupal install. The result is this remedial PHP script (or core agent) that detects your version of Drupal, downloads the appropriate tarball from Drupal.org, runs a diff on /modules, /misc and /includes, and returns you the results.
So! The FCC decided last week that the white spaces between frequencies used by TV broadcasters should be open for public use.
What are White Spaces, you ask? Basically, it's the frequencies between the ones used on TV. When you see a snowy image on an unused channel -- that's the unused "white space" in the frequency range that was previously reserved only for the big broadcasters to use.
So what's the big deal? Well, those frequencies are really good at going through walls and plants and stuff, unlike the frequencies used for the wifi we all know and love. That means that if those frequencies were used for something like the internet connectivity, you'd rarely run into problems with weak signal. Plus, it has a nice social justice/leveling bent, as places less served by large numbers of TV channels (like rural areas) would have a greater range of frequencies to play with for other connected devices.
Basically, the FCC making these frequencies open for use is a big win for everyone who isn't Comcast or Verizon. We can do more and faster, in more places, for much less money.
It should be noted that Free Press, one of our clients, was a big proponent of opening up these frequencies. This is a huge win for them, and we're pretty darn thrilled.
An excellent and understandable breakdown of this stuff is on this week's episode of Search Engine. It used to be a regular broadcast show on the CBC, but now it's podcast-only. Still rules. You can download the show here. Better yet, subscribe to the podcast.
Jeff Atwood has an interesting discussion of the HttpOnly flag and how it can help protect your site from cross-site scripting attacks. For those hoping for a quicker rundown than Jeff's excellent explanation: XSS attacks are based upon the injection of third-party Javascript into your site. This usually happens via a comment or search form — really, it can be anything that accepts user input that is then rendered as part of the site's HTML. If that user input isn't properly sanitized it can trick other users' browsers into running the attacker's Javascript as if it were part of your site.
Once that happens the attacker has access to all sorts of goodies. The most valuable is the document.cookie object, which will generally contain the string that identifies your session to the site. They'll shuttle its contents off to their own server, and with your session in hand they can pretend to be you (at least until the session expires), doing whatever sorts of authenticated tasks you have access to on the site.
The HttpOnly flag tells most modern browsers that scripts shouldn't be allowed access to the cookie — it's for the webserver's eyes only. Handy! So what would it take to get this into Drupal?
Well, with the caveat that I haven't previously dug into Drupal's session-handling code, it looks like a relatively simple fix. In both d5 and d6 there's a function called sess_regenerate that's called at login and which sets the session cookie. This seems to be the only call to setcookie() in core, in fact, making me think that it's the whole enchilada as far as HttpOnly support goes. The line in question looks like this:
Art in DC is excellent, although not typically fodder for tech-focused blogs. Hooray for exceptions.
Leo Villareal's installations are really something to behold. He makes big LED-based works whose lighting patterns are based on rule sets of his design. He claims Conway's Game of Life as a major inspiration. And goodness, does video make his stuff look cool. Lucky for us, he's currently working on his largest installation yet, and in DC! At the National Gallery of Art! The concourse between the NGA's East and West wings will be lit by somewhere around 40,000 LEDs for the next year. Installation is going on now. I've never had a chance to see the artist's work in person, and I'm really, really excited to walk through it.
He's also going to be showing at the soon-to-reopen (and historically awesome) Conner Contemporary gallery, starting on September 27th until November 9th. The gallery plans to have an opening reception on the first day, but the press release says it's invite only. Something tells me that nerdy programmers won't have an easy time making the list. Still, I'm excited to get over to their new spot in NE. Bigger is always better.
Art!
I've been messing around with Capistrano over the last few days. The system is best known for deploying Rails applications, but at its heart it's really just a Ruby-based way of making it easier to manage repetitive server tasks over SSH.
There's one task in particular that I've used it to automate, and which you might find useful, too. Here at EchoDitto we're spread out over a number of offices — DC, Boston, New York, and often who-knows-where-else. This presents some development challenges when collaborating on sites built on a system that, like Drupal, puts alot of site configuration in the database, where version control systems can't be used to manage it.
Of course we do development locally when possible, but we also run a remote dev server to let us collaborate off a single database (and to allow clients to see our work). The obvious solution is to tunnel our local server's database traffic to the central server, allowing different developers' filesystems to connect to the same datastore. But this is slooow.
So other options: setting up MySQL replication? Well, that seems like overkill, and precludes offline development. The solution I've come up with is automating a simple database dump from the dev server. When I need to make config changes I do it on the dev site; when I'm working in the filesystem and need fresh data, I simply invoke a command to pull down the dev DB. For most sites this only takes a few seconds to run, and invoking it is as simple as running `cap get_db` from anywhere within the dev site directory structure.
I used to do this with a somewhat horrible bash script. But it made various assumptions about filesystem and had to be modified for each new local project. Capistrano has let me make this a bit more abstract and reusable. The following script still makes a few assumptions about our servers and configuration, but you might find it useful, too.
Well, I'm not in Hungary, and it's a drag. Drupalcon has begun! It looks pretty exciting, but at EchoDitto I think we're collectively keeping our fingers cross for Drupalcon DC.
Still, I'm doing my best to review the stuff coming out of Szeged. So far it's just a few sets of slides, but I'm optimistic that we'll get some podcasts or maybe even Qik streaming before too long. Inspired by Alex's list, here are the sessions I'm bummed to be missing — not that I could have physically attended them all, of course. But these are the ones that look particularly interesting to me:
This may be old hat to some of you, but it was a near-revelation to me (and tough to find through Googling) so I thought I'd share it and potentially save others some hair pulling.
If your Drupal 5 site goes crazy when you turn on CSS aggregation, try examining your stylesheet(s) for absolutely-addressed url()s. There was (and is) a bug in Drupal 5's CSS aggregator code — since aggregated CSS has to live in a different directory from the original stylesheets, all those URLs have to be rewritten. The function that rewrites them expects them all to be relative, though. So:
background-image: url(/sites/all/themes/zen/xxx/images/something.gif);
gets turned into:
background-image: url(/sites/all/themes/zen/xxx//sites/all/themes/zen/xxx/images/something.gif);
That's obviously no good. Instead, simply make sure that your URLs are all relatively-addressed:
background-image: url(./images/something.gif);
That should be rewritten properly by the aggregator.
The more complete solution, of course, is to fix drupal_build_css_cache(). There is a patch available, but since the issue has been more thoroughly addressed in Drupal 6 and 7, not much attention is being paid to fixing it in 5. And that's probably okay: in most cases it's going to be quicker and easier to simply edit your stylesheet to use relative paths. It's best to avoid patching core when possible, and this is no exception.
We've recently begun putting together the infrastructure for a number of upcoming projects which will organize people around the world toward some pretty powerful, ambitious goals. While the details of those sites are still in the works, working with Drupal to create multi-language sites has been a great experience involving a great deal of learning. This is the first of a two part series covering how Drupal works with multiple languages and the best practices/tricks of the trade for making the most of the Drupal Local, i18n and L10n systems.
Don’t be scared by the geekspeak! “i18n” and “L10n” are just abbreviations for “internationalization” and “localization”, the engineering methodologies used to create software packages and websites which can be used by speakers of different languages. i18n is the process of engineering an application so that it can be adapted for use by speakers of different languages or in different regions without needing major modifications and L10n is the related step of providing conversions between languages, date formats, etc. so the software or site can be accessed in any particular language (see the Wikipedia article on i18n and L10n for more).
We shuffled some servers around today, and the Full-text RSS utility seems to be a casualty, likely due to the transition from PHP4 to PHP5. Apologies to everyone for the inconvenience; as you might imagine, our internal sites and projects tend to get less attention during these transitions than those of our clients. I'll be having a look tomorrow and doing my best to get the script upgraded ASAP.
Well, that was fast: It was just a missing PEAR library, as it turns out. Everything should be back to normal. Again, sorry for the inconvenience.
Every 6 months or so I take a stab at setting up line-level, breakpoint style debugging for PHP. In the past I've been able to get the debugger installed, but the lack of a decent interface to use in setting breakpoints and watches has limited the value of a debugger (one thing that I have found helpful is XDebug's profiling feature that lists all function calls in a nested format along with performance timing). The recent announcement of a new XDebug client for OS X got me back on that track, and while I wasn't able to get MacGDBP working as I wanted, it did lead me to re-evaluate the newest Eclipse offering for PHP coders: PDT. PDT has come a long way, and the combination of a robust IDE, nimble 'jumpt to' shortcuts and killer debugger integration are more than I can pass up. Here's how I got everything working on a Mac OS X 10.5 box.
Much of what follows was made possible by and incorporates instructions from these very good tutorials:
I hope that most of you have already seen the upside-downternet. This hack has been around for a while, but that doesn't make it any less brilliant: thanks to some Linux trickery, every user connected to your network gets served their images upside down. It's pretty clever.
It's also similar to a related but not-quite-identical application I've had in mind. So how does it work? The magic arrives in the form of transparent proxying, a technique whereby a router sends its traffic through a proxy server without the user responsible for that traffic noticing anything (or having to change their configuration). This is called "transparent proxying". In the case of the upside-downternet the Proxy server was Squid, an awesomely powerful, sprawling application. In this case Squid runs on its own machine; the router is configured to reroute its traffic through the Squid server before letting it out onto the net. The Squid server keeps an eye on the URLs being requested and uses a custom script to rewrite any that look like images. The replacement URLs point at a web-accessible script on the Squid server that knows to fetch the original image, flip it upside down, then serve it back.
As I said, I wanted to do approximately the same thing. But I wanted to do it all on the router. And I don't mean router in the systems engineer sense of "router". I don't mean a box sitting in a datacenter with fiber channel running into the back. I mean a box sitting on a shelf in Best Buy with a peel-off coupon on the front.
It's been too busy around these parts for me to put together a post about the exciting things happening in the DC tech community, particularly in the hobbyist electronics space (short version: they're exciting!). But I can at least share this tip.
Many of you are probably using the newly-released Firefox 3 release candidate, and it seems likely that some of you are running into the same problems with Firebug that I was, particularly when using its Javascript console. Big, angry errors with "NS" and "SECURITY" in them? Yup, that's the one.
Well, get thee over to the firebug downloads page and grab the latest alpha. It solves this problem, but introduces a new one for those debugging a jQuery-enabled page: the jQuery object is nowhere to be found.
Actually, it's not that bad: you just need to do something like this
$ = window.$;
Before you start mucking around with scripting from the console. It's irritating, but I'm sure it'll be fixed soon. And in the meantime, you could always whip up a Greasemonkey script to do this job automatically.
...look no further than the comments on this TechCrunch post. Reacting to the scoop that Twitter is dumping Ruby on Rails (which almost immediately turned out to be wrong), more than 150 people decided to chime in about what Twitter's scaling problems are and how their own preferred web framework never would have encountered them. A whopping one person managed to refer to Twitter's custom message queueing software by name.
The rest presumably just like the (drag & drop HTML creation in Visual Studio|error detection in Zend|Google-enabled buzz surrounding Python), and have read "Rails doesn't scale" somewhere. I suppose their prattling is still slightly more meaningful than the yammerings of the web's legions of widget evangelists, social network triumphalists and self-proclaimed "SEO experts". But not by much.
At any rate, I think this is a good reminder of the signal:noise ratio facing our clients as they attempt to find technical help in a crowded marketplace. If you're not a technical person it's genuinely hard to tell the difference between someone who knows what they're talking about and someone who's simply regurgitating buzzwords. My rule of thumb when encountering bold pronouncements like the ones in that TC thread: ask "why?", then count the number of unexplained acronyms and buzzwords in the answer.
One of the things that I've learned over my years at EchoDitto — that's been hammered home again and again — is the importance of email. Twitter's cool, social networking is great, but your online strategy absolutely has to account for email. It's not glamorous, but it's important.
The same is true on the tech side of things. It's easy to forget: on a day-to-day basis, my wranglings with email generally include dealing with spam blacklists, ensuring that scripts don't function as open relays, and writing templating systems that'll be used to send mail. All of it's pretty boring. But it's worth keeping in mind that email, when piped to a script, can serve as the infrastructure for some pretty neat services, too.
I did this two years ago for SXSW, building an SMS app on the cheap by counting on the mobile carriers' SMS-to-email functionality. It worked pretty well, although it was a rat's nest of Perl scripts.
This week I took a pass at another application in Ruby (with a PHP frontend), and this time the resulting code is a bit less cringeworthy. The idea is simple: set your Twitter "new follower" email notifications to go to a custom email address. They'll be piped to a script, disassembled and the new follower's statistics analyzed. If it looks like the new guy is a spammer or bot, they'll automatically be blocked. If not, they won't be. Either way you'll get an RSS notification about it. You can try it out here, if you'd like.
It's not exactly going to set the world on fire, particularly since Twitter is expected to release similar functionality soon. But the project does serve as a pretty good template for how a piped email service can work.