Hijax

4:06, Tuesday January 10th, 2006 • feeling webmasterly • 3 comments

Got back from Mobile Monday drunk, snoozed for an hour and now I'm learning new hacking tricks! I surely do have the strangest working hours. I have an excuse, Louise started a new job working nights this week, she finishes at four and will be back in an hour. I wanted to stay up and wait for her.

Anyway, Hijax is the combination of two very cool ideas: 1. Ajax, 2. Progressive enhancement. Progressive enhancement, advocated by Jeremy Keith, in his book DOM Scripting (which I do not own and have not read), suggests that whizzy JavaScript functionality should be automatically added to a simple HTML page after the fact. So instead of building an app with a bunch of links that call JS functions, I'd create a vanilla web app with links to new pages. Then I would write JS code that goes and finds those vanilla links and hijacks them, replacing them in the DOM with links to teh whizzy.

This idea doesn't just relate to Ajax of course, but it provides a foundation for building higher-quality Ajax apps. As Mr Keith so eloquently puts it: "progressive enhancement automatically guarantees graceful degradation." Because the old links are still there for non-JS users (old browsers, browsers with no JS, search engines, etc) my app still works perfectly well, if less whizzily.

This is the single coolest JS trick I've ever come across, way cooler than all that Ajax rubbish :-). Deployment of JS whizzitronics follows the same model as the deployment of CSS beauty. The underlying content is preserved, so you can have your cake and eat it too. I highly recommend reading Jeremy's blog and the sample chapter as he explains this stuff much better than me in my tired, post-booze state.

MultiInfoCMS

0:55, Thursday November 18th, 2004 • feeling webmasterly • no comments

An InfoCMS-alike.

The InfoCMS-alike is multi-site which is a neat idea. I've deployed about four sites on InfoCMS now and I'm getting bored of cvs update-ing them. I'm only going to have more, since we're using it for all our in-house web projects. Handling multiple sites on one install would require extensive changes to the codebase. There would need to be a concept of sites at the model level. Secondarily there would need to be a way to split assets and configuration files (sitemap.xml, transform.xsl, application.ini). Finally, how would a site be defined from the point of view of the controller? Are http://server1.com/ and http://server2.com different sites? Almost certainly. But what about http://server3.com/afternoon/ and http://server3.com/someoneelse/? How could these differences be accomodated within a system that depends on mod_rewrite? Certainly the rewrite rules would have to be quite potent.

One way to do it would be to use rewrite rules to pass requests to the same code but adding query string flags. http://server2.com/ could be rewritten to http://server1.com/?site=2. However, mod_rewrite is optional for InfoCMS, though very strongly recommended. The alternative is to incorporate some kind of similar functionality into InfoCMS itself, adding a sites table with a regex column used for sorting the wheat from the chaff. That's not ideal though, regexs can be very complex to debug, what if two overlap? What should InfoCMS serve in that case?

For the site configuration the answer has to be on the filesystem. For one the information about how to get to the database is in there, though that would be site non-specific. Secondly there's the assets. Thirdly however, InfoCMS currently has no web configuration mechanism. Moving the config to the DB would require one, as hacking the DB with the MySQL client or something similar is a right pain in the ass. I guess the solution would have to be a set of folders, but how would defaults be handled? How could it be kept simple for the most common case, which is that InfoCMS is only used to serve one site?

Also, a recipe for the ultimate blog

Ahhhh ha hahaha!

5:00, Friday August 13th, 2004 • feeling webmasterly • no comments

I've been hacking heavily on InfoCMS and I'm really starting to create cool stuff now:

I'm feeling pretty chuffed now.

Permanent logins with PHP sessions

16:09, Monday May 3rd, 2004 • feeling webmasterly • 19 comments

Disclaimer: I think this works, but it's only endured light testing so far. I may be wrong. Please let me know if you think I am.

PHP sessions are a great addition to the application programming environment. The first time I used cookies I used PHP's setcookie() function to roll my own system, which can only be described as flaky. Browsers seem to have an overwhelming disdain for cookies in general, each one requiring a complex set of chicken dances to work. PHP sessions may or may not do lots of clever stuff under the hood to address these problems, but they have always worked 100% reliably for me and that confidence has been enough for me to deploy and forget the technology, something which is critical if we are to get on with the business of developing actual software and not constantly writing our own libraries.

But eventually the time came when I wanted to have the option for people to be logged in permanently (or at least for a very long time, let's say 90 days). Finding a solution to this problem took me a little while, so I thought I'd write it up. I got quite a lot of help from this discussion at the Experts Exchange and obviously the sessions section of the PHP manual.

First piece of knowledge: PHP garbage collects session files when their modified time reaches a predefined timeout, the default being 1440 seconds - about 24 minutes. PHP has a series of INI file settings that govern the sessions system. These allow you, amongst other things, to control this garbage collection, by either raising the timeout, or reducing the probability of collection after that timeout has expired. For my purposes, I wanted the session files to remain intact on disk for up to 90 days (7776000 seconds). The php.ini key for garbage collection is session.gc_maxlifetime. If you have control over your php.ini file, simply locate and alter that value. If you don't, you can change these options via a .htaccess file (see below). It's not enough to change these options using the ini_set function as the value needs to be maintained for all instances of PHP that are working in the session dir.

According to one expert at the Experts Exchange, changing your session.gc_maxlifetime will cause problems when PHP instances running other scripts (e.g. belonging to others on a shared server). This can be fixed by moving the session save path to a different location. This can be acheived with session.save_path parameter.

Presumably, if you set your session.gc_maxlifetime and then move your session path with ini_set(), your sessions will be untouched by other PHP instances, meaning you can use just ini_set to do the initial lifetime change. I haven't tested this however.

I also decided to specify that my sessions should use cookies only. I set both session.use_cookies and session.use_only_cookies to "on" and session.use_trans_sid to "off".

As I don't have access to the php.ini on my production server, I put the following block into the .htaccess for my application:

<IfModule mod_php4.c>
    php_value session.gc_maxlifetime "7776000"
    php_value session.save_path "sessions"
    php_value session.use_cookies "on"
    php_value session.use_only_cookies "on"
    php_value session.use_trans_sid "off"
</IfModule>

OK, so now a user's session will be waiting on the server for them to come back, we have to ensure that the other half of the equation - the browser cookie - will wait just as long.

Second piece of knowledge: session_start() always sends a Set-Cookie header with the default path and no expiry time. No expiry time means that the cookie will be removed when the browser is closed. If session_start() sends a cookie with an expiry we don't want, don't we have something of a chicken egg situation? We need to run session_start() before we can access our session data, but to make the cookie optionally permanent you have to store that somebody wants a permanent cookie somewhere: the session. There are other options, but they are less then ideal. For example you could store the option in a database, but what if the user wants to be permanently logged in on their home machine, but not when they visit your site from a net café?

The solution is to stop and then restart the session with the new timeout parameter. The algorithm looks like this:

  1. Call session_start(), this sends a duff cookie, but it does give us access to $_SESSION
  2. Look in the session for the permanent flag, and copy it
  3. If the user wants a permanent login:
    1. Run session_write_close(), this commits the session to file and closes it
    2. Use session_set_cookie_params() with just one argument to set the cookie timeout, 7776000 seconds in our case.
    3. Run session_start again, this time it sends a good cookie

All you need to do when the user logs in is create the permanent flag in the session if they want it.

This solution has been tested and works on Mozilla, IE5/Mac, Safari, IE6/PC and IE5/PC.

Because two Set-Cookie headers are sent with each response, it's conceivable, even likely, that some browser somewhere will get confused and set the expiry time wrong. In this case it should be possible to do the work of the original session_start() call manually. Get the cookie using the $_COOKIE array, find the session file, parse the file for the perma flag (unserialize() didn't work as I hoped it might have done) and then resume the original process at step 3. I haven't implemented such a system myself as yet, so this approach is untested.

Mmm, rsync

19:53, Monday March 29th, 2004 • feeling webmasterly • 1 comment

Sync a folder to a server to which you have SSH access (and which has rsync installed). The options include compressing, checksumming, being verbose and archving, which does a bunch of stuff. Also, I don't want to put Vim's swapfiles up to the server, so by excluding them here I can run this command while editing. Excluding .DS_Store is a must for OS X users. Pesky .DS_Store files.

rsync -cavz --exclude=\*.swp --exclude=.DS_Store --rsh=/usr/bin/ssh folder server.com:dest

Page 1 of 19

next page →

Choose another page: 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19.

Last updated at 0:35, Monday December 1st, 2008. All times are shown in 24-hour clock format and are GMT.

Rate my journal on bloghop.com: the best pretty good ok pretty bad the worst

aftnn.orgafternoon's journal → webmasterly mood entries