About the Author

Chris Shiflett

Hi, I’m Chris: entrepreneur, community leader, husband, and father. I live and work in Boulder, CO.


All posts for Jan 2007

Consulting Rates

I'm subscribed to a lot of mailing lists - PHP, mod_perl, MySQL, web application security, etc. This week, there was an interesting conversation on the NYPHP mailing list - consulting rates.

It all started with an email from Edward Potter. He had previously emailed the list to inquire about consulting rates and was sharing the results with everyone:

Just to keep everyone up to date, based on interviews to date, the going rate for a 6 month contract with someone with a solid PHP/developer background/graduate degree in IT right now seems to top out at $60/hour based on a 6 month contract.

To be clear, he's suggesting that a good developer with a graduate degree can expect to charge a consulting rate of $60/hour at best. I tried to put this into perspective in my reply:

Doing some math in reverse:

$60 / 2.4 = $25
$25/hour = $50,000/year

Therefore, $60/hour as a consultant is roughly equivalent to $50,000/year as a full-time employee with benefits.

A few people questioned the 2.4 factor, and although I've seen plenty of references to this value (even in SLOCCount's cost estimating feature, something Zak has discussed), I was unable to find a definitive source for it, nor do I know what it's called. Anyone know? I have been using it to calculate rates for a few years.

What do you think the average salary is (or should be) for a good developer?

By the way, OmniTI is always looking for good PHP and Perl developers, and we offer better salaries, lots of benefits, and other perks such as a friendly, collegiate environment and the chance to work with and learn from some of the best minds in the industry.

URL Vanity

I'm a perfectionist. As a web architect, I tend to obsess about URLs. I want them to be simple, user-friendly, and descriptive. I want them to be beautiful. I dislike underscores, file extensions, and superfluous characters. I hate the www subdomain, avoid trailing slashes, and try to maintain a shallow hierarchy. Oh, and URLs should never change.

For the most part, shiflett.org has been adhering to these guidelines since I relaunched it in 2003. However, there are a few things that need improving.

Standalone articles such as Foiling Cross-Site Attacks and The Truth about Sessions have always had good URLs. My columns, until recently, have not. I used names like security-corner-dec2004 in the URL for the article that appeared in the December 2004 issue of php|architect. Not only is this ugly, it focuses on something people don't care about (the name of the column) instead of something they do (what the column is about). This is the real problem with not putting enough thought into your URL structure before publishing something. It's easy to change just about everything else about your web site, but changing URLs is like changing an API. You can do it, but it hurts. (In many ways, URLs are the API to your web site.)

The aforementioned security-corner-dec2004 has been renamed to cross-site-request-forgeries. Because I use a permanent redirect (301) for requests made to the old URL, indexes know to use the new one. In fact, a Google search for CSRF finds my article on cross-site request forgeries with the new, updated URL. You can generate a 301 response with PHP by sending a Location header as follows:

<?php
 
header('Location: http://example.org/', TRUE, 301);
 
?>

This mitigates most of the pain caused by changing URLs, but it doesn't update old bookmarks, del.icio.us history, and the like. Therefore, I plan to accommodate the old URLs forever. Or a really, really long time. :-)

The other thing that needs improving is the URL structure for my blog. My primary dislikes are:

  • Blog posts are identified by a sequential number, which has almost no semantic value.
  • Blog posts are organized under /archive in the URL, which sounds like a place for old posts.
  • The blog archive has no organization other than being sorted by date. It's a dump.

I want to rectify this situation with an approach similar to what I did for articles. However, there are a few key differences:

  • There are far more blog posts than articles, so the organization needs to be able to scale.
  • Although it hasn't happened yet, I want to accommodate duplicate titles. For example, there are only so many ways to say "OmniTI is hiring again." (We really are, by the way.)
  • There needs to be an elegant solution for browsing the blog history, and the URL structure should reflect this.

Using /blog instead of /archive is an easy choice, but /blog/omniti-is-hiring-again can only be used once, so there needs to be something else in the URL.

I could keep the sequential number. For example, /blog/289-url-vanity. This would also make renaming easier, but I don't like the idea of keeping that useless number in the URL. It's ugly.

After much debate with Jon, I am warming up to the idea of including the date in the URL, but only the year and month. For example, /blog/2007/jan/url-vanity. I could use 01 instead of jan, but the latter seems more user-friendly.

This approach also lets me offer /blog/2007/jan as an interface for browsing posts from January 2007 (full posts) and /blog/2007 as an interface for browsing posts from all of 2007 (abstracts). I hate URLs that you can't ascend.

Which URL structure would you choose? Do you suffer from URL vanity?

Adobe PDF XSS Vulnerability

I've been concentrating on work this past week, but I wanted to quickly mention the Adobe PDF XSS vulnerability discovered by Stefano Di Paola and Giorgio Fedon. This is being called UXSS (universal cross-site scripting) due to the fact that it can affect virtually any web site. (The web site just has to host a PDF.)

The basic attack is pretty straightforward:

http://example.org/foo.pdf#bar=javascript:alert('XSS');

If you have a vulnerable version of Acrobat / Reader, your browser will execute this JavaScript whenever you visit the URL. In other words, any site hosting a PDF is a potential target for such an attack, regardless of whether the site would otherwise not be vulnerable to XSS. (For example, my Security 2.0 slides.) Worse, RSnake found a local PDF that can be used for more malicious attacks:

file:///C:/Program%20Files/Adobe/Acrobat%207.0/Resource/ENUtxt.pdf

This path is clearly for Windows, but I'm sure similar local URLs can be found for other platforms.

This is all significant, because as I've mentioned before, XSS matters.

One thing missing from most of the discussion is that this issue does not affect the most recent version of Adobe Acrobat / Reader, which was released last year. I still think this is a very significant discovery, but I don't think such important information should be left out of the discussion to artificially increase concern. Adobe's security advisory provides more details about which versions are affected.

John Dowdell, who I mentioned before when discussing the YouTube security vulnerability, mentions this fact in a post on the topic, and he includes some insight from Leonard Rosenthol of the Adobe Acrobat team:

  • This issue only affects the Windows platform. Mac, Linux, etc. users are not affected.
  • We found this issue ourselves during our own security/vulnerability testing of Acrobat and introduced a fix as part of Acrobat/Reader 8 for Windows. As such, users of Acrobat/Reader 8 (regardless of browser) are not affected.
  • We already have patches prepared for earlier versions of Acrobat and will release those as soon as they are ready. This will address those users who are unable/unwilling to upgrade to Acrobat/Reader 8.

If you're a Windows user, your best bet is to either upgrade to Adobe Acrobat / Reader 8, or disable the plugin from opening within the browser.

If you're an application developer, you can opt to remove all PDFs from your site, or you can force PDFs to be downloaded instead of displayed inline. Richard Lynch has an old post / rant with some useful information. Rich Bowen offers the following advice:

AddType application/octet-stream .pdf

I keep reading about the "anchor tag" not being sent to the server. I finally realized that people mean to say fragment identifier. An anchor tag is just the <a> tag we use in HTML to create links. (I'll withhold another long-winded rant about technical vocabulary, although that was an interesting discussion.) Hopefully this tidbit can help you if you're trying to follow the ongoing discussion.

2006 Highlights

For the fourth consecutive year, I'm going to try to record my personal highlights from the previous year.

To get things started, here are a few memories from 2006 off the top of my head:

The most important event for me by far was when OmniTI acquired Brain Bulb. In some ways, I feel like I'm still settling in, but it has been a natural fit from the very beginning. I've got some new projects planned for 2007, and I think it's going to be a good year. Of course, there's always room for more. Maybe you'd like to join us? If you're a good PHP or Perl developer, we'd love to welcome you to our team.

One of my goals for 2006 was to speak at fewer conferences. I wasn't very successful:

  • Spoke at PHP Quebec for the second time. (29 - 31 Mar)
  • Spoke at LinuxWorld for the first time. (24 - 25 Apr)
  • Spoke at php|tek for the second time. (25 - 28 Apr)
  • Spoke at Boston PHP for the second time. (04 May)
  • Spoke at ApacheCon Europe for the second time. (26 - 30 Jun)
  • Spoke at OSCON for the fourth time. (24 - 28 Jul)
  • Spoke at php|works for the third time. (12 - 15 Sep)
  • Spoke at EuroOSCON for the first time (18 - 21 Sep)
  • Spoke at the DC PHP Conference for the first time. (19 - 20 Oct)
  • Spoke at ZendCon for the second time. (30 Oct - 02 Nov)
  • Spoke at the University of Arkansas for the first time. (01 Dec)
  • Spoke at Web Builder 2.0 for the first time. (04 - 06 Dec)

To be fair, not all of those are conferences, but everything that requires travel and preparation takes time that I'd like to devote to other areas this year.

Another goal for 2006 was to do more cool stuff. I certainly did some cool stuff (some was even work-related), but the primary projects I had in mind at the beginning of the year remain unfinished. That's a bit disappointing, but it gives me something to strive for in 2007.

Blogging more was another goal. In 2005, there were 93 posts. In 2006, that grew to 106. The 20 most popular posts were (in chronological order):

I hope everyone has a wonderful 2007. Now it's time to get back to blogging. :-)