Thursday 20 December 2007

Reference: What we can do to style disabled input elements in IE6

.. Not a lot, by the looks of things. Here's one example of what can be done though; it involves manually adding a class to all disabled form elements...

if nothing else, it allows the styling of the background colour and changing the font-size, weight etc... Anyway, here's the code:


For a far more detailed discussion on the subject, you can also look at these sites:
http://www.456bereastreet.com/lab/styling-form-controls-revisited/disabled/#ie6-xp
http://www.askthecssguy.com/2007/05/shawn_asks_the_css_guy_about_s_1.html

Monday 12 November 2007

First Look At the Android SDK

I just saw the articles regarding Google's latest offering - the Android SDK; there's a load of video clips here which no doubt are currently doing the rounds all over:
http://www.engadget.com/2007/11/12/googles-android-os-early-look-sdk-now-available/ega

Like many people today, I downloaded the SDK and installed the eclipse plugin following these steps here:
http://code.google.com/android/intro/installing.html

And after following the instructions for the HelloAndroid application, thought I'd play around with the emulator. It's great - well worth having a look at and really feels like a phone you can have some fun with :)



Now all I need is a portable device to run it on...

Saturday 3 November 2007

Plone 3: Deployment using buildout

A new feature of Plone 3 is the buildout process. It's a much smarter way of setting plone up and could be useful if you're managing several plone sites. But equally, if you're interested in taking Plone 3 for a testdrive, getting started by using the buildout system is probably a great way to get up and running quickly.

If anyone's interested in a rough guide for getting started with Plone 3 (and using buildout to set-up a zope 2 / plone 3 environment, here's my notes (and some reference links) on setting things up.

Firstly, I've set this up using Ubuntu 7.10 (Gutsy); the process should be pretty similar for other distros though.

Before you read any further, here's a disclaimer: Plone 3 currently only works with Python 2.4. Ubuntu 7.10 ships with Python 2.5. The install method I'm outlining here doesn't require uninstalling Python 2.5 although I can't make any promises. You will need to install Python 2.4 on your machine - and I can't promise that setting this up won't break anything else on your system. You have been warned.. :)

Ok, so with that out of the way, here's a note of the steps I took to get things up and running (and links to other good articles for further reading):

1. Install python2.4 and python2.4-dev:
sudo apt-get install python2.4
sudo apt-get install python2.4-dev

2. Set python 2.4 as default (please read disclaimer first!):
- remove the symlink for python 2.5
sudo rm /usr/bin/python

- replace symlink with one for python2.4
sudo ln -s /usr/bin/python2.4 /usr/bin/python

- edit the debian defaults file
sudo vim /usr/share/python/debian_defaults

- Change the default version from python2.5 to python2.4 like so:

[DEFAULT]
# the default python version
default-version = python2.4

I'd like to acknowledge the ProgProg site for this solution - check the original post here: (http://www.progprog.com/articles/tag/ubuntu)

Once you've made those changes, check by running 'python' from the command-line (Ctrl+D exits).. If it's been successful, you should now be running v2.4.4 by default

If it is, you should be ready to get started with the Plone buildout. Most of the initial information I got for setting this up is from Martin Aspeli's *awesome* article on the Plone site - well worth a read:
http://plone.org/documentation/tutorial/buildout/introduction

Now we have Python 2.4 running, we need to install a few things - starting with easy install and PIL (the Python Imaging Library):
sudo apt-get install python-setuptools
sudo apt-get install python-imaging

When I first tried running this, I had problems with the version of setuptools that apt-get installed (it was older than the one required). I solved this by grabbing the latest .egg file from the cheese shop:

- go to the site and download the egg file to your machine:
http://cheeseshop.python.org/pypi/setuptools#using-setuptools-and-easyinstall
- Install the egg using easy_install:
sudo easy_install -U setuptools-0.6c7-py2.4.egg

If you get errors with the install (if easy_install doesn't appear to be working as expected), grab the latest version and run it:

wget http://peak.telecommunity.com/dist/ez_setup.py
sudo python ez_setup.py

Once that's all done, we can start working:

- Install ZopeSkel:
sudo easy_install -U ZopeSkel

To test ZopeSkel:
paster create --list-templates

If successful, you should see a list of templates (like this):

Available templates:
archetype: A Plone project that uses Archetypes
basic_namespace: A project with a namespace package
basic_package: A basic setuptools-enabled package
basic_zope: A Zope project
nested_namespace: A project with two nested namespaces.
paste_deploy: A web application deployed through paste.deploy
plone: A Plone project
plone2.5_buildout: A buildout for Plone 2.5 projects
plone2.5_theme: A Theme for Plone 2.5
plone2_theme: A Theme Product for Plone 2.1 & Plone 2.5
plone3_buildout: A buildout for Plone 3 projects
plone3_portlet: A Plone 3 portlet
plone3_theme: A Theme for Plone 3.0
plone_app: A Plone App project
plone_hosting: Plone hosting: buildout with ZEO and any Plone version

If you do, you're now ready to set up the environment. Either you can set up a dedicated user (e.g. www, plone or whatever you choose to call it), or if you're just testing it out, you could use your own account.

From your home-directory (or within a folder in your home-directory):
paster create -t plone3_buildout myploneproject

- here, plone3_buildout is the name of the template you're using and myproject is the name of the folder you're going to create your build in.

It will ask you a series of questions, leaving most of these blank should get you a working fresh zope 2 / plone 3 instance. You'll need to enter a username and password to allow you to manage the control panel; I'll leave this for you to decide upon.

Here's an example using mostly the defauts (note that I'm using admin / mypassword for this example):

user@mypc:~/plone$ paster create -t plone3_buildout myploneproject
Selected and implied templates:
ZopeSkel#plone3_buildout A buildout for Plone 3 projects

Variables:
egg: myploneproject
package: myploneproject
project: myploneproject
Enter zope2_install (Path to Zope 2 installation; leave blank to fetch one) ['']:
Enter plone_products_install (Path to directory containing Plone products; leave blank to fetch one) ['']:
Enter zope_user (Zope root admin user) ['admin']: admin
Enter zope_password (Zope root admin password) ['']: mypassword
Enter http_port (HTTP port) [8080]: 8080
Enter debug_mode (Should debug mode be "on" or "off"?) ['off']:
Enter verbose_security (Should verbose security be "on" or "off"?) ['off']:

After that's done, cd into the folder for the project you just created:
cd myploneproject

And run the bootstrap script:
python bootstrap.py

Let's create a generic buildout and test it before adding some extra bits in:
bin/buildout -v
(if that doesn't work, try ./bin/buildout -v)

This should take a little while, but watch as the buildout handles all the dependencies for you and sets everything up automatically :)

When you get your terminal prompt back, you should now be able to build and run your initial zope 2 instance:
./bin/instance fg

Give it a few minutes to set everything up for the first time and check your zope instance:
Point your browser to:
http://localhost:8080/manage

And enter the username and password you just specified (e.g. admin | mypassword)

You should see a dropdown menu to the right, find 'Plone Site' in the listing and select it. Enter the Id name (I'm going to use testplone for this example) and hit 'Add Plone Site'

When you get back to the control panel, you should now see something like 'testplone (Site)' in the listings. If so, point your browser to:
http://localhost:8080/testplone

And after a few seconds, you should see your test instance of Plone!

I'm going to bring the site down, make a couple of quick modifications and bring it back up just to demonstrate the power of buildout:

Go back to:
http://localhost:8080/manage
Select the Control Panel link from the left and hit the Shutdown link.

Go back to the terminal (and your project directory) and edit buildout.cfg file:
vim buildout.cfg

Find this:

# elementtree is required by Plone
eggs =
elementtree

And add this below element tree:
plone.portlet.static

So it should now look like this:
# elementtree is required by Plone
eggs =
elementtree
plone.portlet.static

Also find this:
# e.g. zcml = my.package my.other.package
zcml =

And add plone.portlet.static here too - so it should look like:

# e.g. zcml = my.package my.other.package
zcml =
plone.portlet.static

These lines will add the "static html portlet" to Plone 3 - this allows you to create a portlet on your site which you can just put plain html into - rather useful.

I'm also going to add a 'classic' plone2 plugin, ZWiki0.60 into the build - here's an example -
Find this:

[productdistros]
recipe = plone.recipe.distros
urls =

And add the URL for the current build of ZWiki here:
http://zwiki.org/releases/ZWiki-0.60.0.tgz
(or check http://zwiki.org/FrontPage#download for the latest version)

So you should now have:
[productdistros]
recipe = plone.recipe.distros
urls =
http://zwiki.org/releases/ZWiki-0.60.0.tgz
nested-packages =
version-suffix-packages =


Save the file and quit the editor.

Rebuild and re-deploy:
bin/buildout -v
./bin/instance fg

Go back to your plone instance and to the control panel:
http://localhost:8080/testplone/plone_control_panel

Select Install products (or go here):
http://localhost:8080/testplone/prefs_install_products_form

You can now check Zwiki and Static text portlet as installable products!

Sunday 22 July 2007

Image Alignment Example (improved)

This one is similar to the previous post, only now we have images stacked vertically (using two different classes) and with captions underneath the images:

If you want to copy/use/test this example, remember to save the file with a .xhtml extension; you may find the browser has problems rendering it if you save the file with, for example an .htm or an .html extension.

Friday 20 July 2007

Image Alignment example

Here's some sample code for using css and xhtml to align an image to the left or right within a paragraph:

Friday 13 July 2007

Starting Firefox with the Profile Manager

If you need to create a "test" user for firefox (for example, if you're testing user settings or want to test out an add-on but not damage your normal profile:

Run firefox from the commandline:

firefox -ProfileManager

You can then create a test user.

Monday 2 July 2007

Quick Perl template for Line and String Manipulation

We've got to tamper with some flat files (ultimately turning them into valid xml) - here's some quick notes (in the form of a *very* simple perl script) on the steps involved in:

- taking a filename as an argument (argv[0])
- opening the file
- keeping tabs on the line you're working on within the file (we use $. for this)
- getting access to the contents of each line within perl (we use $_ for this)

With this in mind, I can now use some extra arguments in the loop to start cutting up the data any which way. But here's a basic perl template for showing the line number and the string of text for each file in perl:

you would run this using something like:

./the-name-of-your-file.pl the-name-of-the-textfile.txt

Friday 29 June 2007

Viewing Posted Xform instance and Environment Variables

Here's a cgi-bin script that you can use to echo posted form information back to yourself:

Monday 18 June 2007

Using XSLT 2 (Saxon 8) with Ant...

Update: I had this problem again today, my notes from last time didn't work. To get saxon 8 working with ANT (1.7), first get the most up-to-date jars (important!) from sourceforge (8.9.0.4 at the time of writing):

http://sourceforge.net/project/showfiles.php?group_id=29872

Unpack them somewhere (e.g. a /lib directory)

Saxon is called in ANT using something like this:



I hope this helps someone :)

Ok - this is a short post; although I might extend it later on with some examples. If you're having a problem with Ant not using saxon to run the transforms (say, using xalan instead).. But you've added the classpath and you're sure it knows it's supposed to be using saxon, adding this line between your xslt tags might just help...

Friday 15 June 2007

Eclipse, Ant and SSH

Getting Ant to work with a secure (SSH) connection requires a few more steps in the process.

Here's some guidelines which may help anyone wanting to run ant builds using SSH:

1. Once you've installed Eclipse, Ant and all the other bits, go and grab this:

http://www.sshtools.com/downloadProduct.do?productCode=MAVERICK-ANT

2. Copy the jar files in the archive over to wherever you installed Ant (in Windows, could be something like C:/Apps/apache-ant-1.6.5/lib/; on Linux it could be something like /home/{YOUR_USER_NAME}/apps/apache-ant-1.6.5/lib/)

3. Add maverick-ant.jar to your classpath in Eclipse (Window > Preferences > Ant > Editor > Runtime > Add External Jars) OR set the Ant Home (using the Ant Home button) and point to the base folder {YOUR_LOCATION}/apps/apache-ant-1.6.5

4. Go and get puttygen from http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html

5. Select 'Generate' and move the mouse around; this will create a random key pair.

6. Create (and confirm) a key passphrase to add another layer of security

7. Copy the Public key information Putty Key Generator has returned

8. Log into your server (wherever you're SSHing to) using the normal method (we're using Putty here)

9. edit /home/YOUR_USER_ID/.ssh/authorized_keys using your favourite editor and append the key information to that file, write the file and quit.

(I put an empty line in between the entries and this worked fine)

10. Save the private key locally using the save private key button in puttygen (you'll need to be able to refer to this in your ANT xml below)

11. Test it out in eclipse - create a build.xml file in your project, use the information below as a template and run the xml as an Ant build.

i. A basic ANT script for authentication should look like this - I've added the ls command in to show it working, so the ant file will authenticate (and show you the stages of authentication) and will then execute 'ls' to retrieve a directory listing:

<?xml version="1.0" encoding="UTF-8"?>

<project name="ssh" default="files" basedir=".">


<taskdef name="ssh"
classname="com.sshtools.ant.Ssh"
classpath="{THE_PATH_TO_YOUR_ANT_FOLDER}/lib/maverick-ant.jar" />

<target name="files">
<ssh host="{THE_NAME_OR_IP_ADDRESS_OF_YOUR_SERVER}"
username="YOUR_USER_NAME"
passphrase="YOUR_PASSWORD"
keyfile="{THE_NAME_AND_PATH_OF_YOUR_PRIVATE_KEY_FILE}.ppk">
<exec cmd="ls" />

</ssh>
</target>
</project>

Hope this helps. More information (as a tutorial) regarding ANT can be found here:
http://en.wikibooks.org/wiki/Programming:Apache_Ant

And check the documentation that came with Maverick Ant for more information:
http://www.sshtools.com/downloadProduct.do?productCode=MAVERICK-ANT

Sunday 10 June 2007

Mp3 Playback in Java

Setting this up took a while and I can't really be sure exactly what I did to get all the things working; if I ever do a clean install, I'll try and document the process. Here's a very quick outline before I post the code -

I grabbed all the jars from here:
http://java.sun.com/products/java-media/jmf/2.1.1/download.html
And grabbed the mp3 handler here:
http://java.sun.com/products/java-media/jmf/mp3/download.html

The jars you'll need to drop into eclipse are (I think):
mp3plugin.jar
mediaplayer.jar
jmf.jar
multiplayer.jar

Here were some other links I found handy:
http://java.sun.com/products/java-media/jmf/2.1.1/setup-linux.html
http://java.sun.com/products/java-media/jmf/2.1.1/jmfdiagnostics.html
http://ubuntuforums.org/showthread.php?t=436053
http://weblogs.java.net/blog/jonathansimon/archive/2004/11/suns_mp3_plugin.html
http://forum.java.sun.com/thread.jspa?threadID=686681&messageID=3996185

Just a prewarning:
I kept getting errors that looked like this -
Unable to handle format: mpeglayer3, 44100.0 Hz, 16-bit, Stereo,
LittleEndian, Signed, 16000.0 frame rate, FrameSize=32768 bits
Failed to realize: com.sun.media.PlaybackEngine@12dd76
Error: Unable to realize com.sun.media.PlaybackEngine@12dd76
Failed to realize: input media not supported: mpeglayer3 audio

If you keep seeing these, try a number of different mp3 files; I had to try 3 before I had something working. I found testing the mp3 files using jmstudio was a reliable way to test - if jmstudio can open and play the file automatically, then it should work fine with the code listed below.

You can see a forum discussion regarding some of the common problems here:
http://www.velocityreviews.com/forums/t149533-mp3-playback-using-java-sound-and-sun-mp3-plugin.html

A common alternative to the sun offering seems to be:
http://www.tritonus.org/plugins.html

-----------------------------------------------------
Ok - if everything is set up and appears to be working, you can try some of these classes. I found the original examples by looking around on forums, but had to make some changes to get them to work completely.

The simplest example I could find of a java class able to play an mp3 file:




Another example I found in a few forums used this code as a base:
http://forum.java.sun.com/thread.jspa?threadID=625352&messageID=3565801

I had to make a few modifications to get the code to work. Here is the class:



To test the class, I created a calling class called TestPlayMp3Thread:



Hope this is useful for someone else.

Wednesday 6 June 2007

Simple Saxon Java example

I'd been wanting to create the *simplest* class possible to enable me to transform xsl files within a java application.

I looked around for a really simple example of this process. After a bit of digging around, I "ripped" these bits from the very comprehensive TraxExamples.java file provided within saxon-resources8-9.zip (the original file authored by Scott Boag) and now I have a class containing something like this:



The "void main" bit:



For this to work, you can get the real handleException method from the TraxExamples.java, or for the minimal amount of code to make it work (and not necessarily to make it too useful):



Using eclipse, all the imports were pulled in via Source > Organize Imports (Ctrl + Shift + O)

Does the trick for me :)

Viewing XForms and (x)html from the SVN web viewer

So we had a problem the other day, we wanted to be able to view html / xhtml examples as working pages direct from the SVN repository using a browser.

If you've committed a load of xhtml files (e.g. xforms) and you want to be able to view them as "applications" (or rendered html) from within svn, you need to set a property called svn:mime-type for all of the relevant files.

For old-skool html - you can use this mime-type:
text/html *.html (and any other extensions)

And in order to make xforms work properly - you can use this mime-type:
application/xhtml+xml *.xhtml

------------------------------
Within eclipse, right-click on the file (e.g. index.xhtml), go to Team > Set property, select svn:mime-type from the dropdown (or just type it) and enter the text property in the box below (e.g. application/xhtml+xml *.xhtml).

Eclipse/Subclipse also has a "Set property recursively) checkbox, selecting this should change the properties where there are several folders.

You can also select show properties to display the properties in a panel within the perspective.

For eclipse instructions - remember that you need subclipse installed (see my previous post)...

Tuesday 5 June 2007

Using google's free SVN repository with Eclipse

Ok - here are some very quick notes on getting a google svn hosting account set up with eclipse; as google is offering us all such an amazing resource, I have a feeling I'll be doing this again some time whilst working on other projects...

If you already have a gmail account, make sure you're logged in (that way, your repository and your account will be linked).

Start here:
http://code.google.com/hosting/
Go to the 'Create a new Project' link and create your project...

Install eclipse if you haven't already (current recent version is 3.5):
http://www.eclipse.org/downloads/

Now you need to install the subclipse plugin from within eclipse..
Here are some step-by-step instructions:
http://subclipse.tigris.org/install.html

Once that's done you should be able to open your repository as a new project within eclipse.

Within the package explorer (the panel on the left if you're in the java developer perspective), right click to get the context menu and go to 'New' and 'Other...'

expand the SVN folder and select 'Checkout Projects from SVN' and select Next

Select the Create a new repository location and select Next

The URL will be:

https://[YOUR_PROJECT_NAME].googlecode.com/svn

If you don't use https:// you'll check out the repository as read only

Select (highlight) the folder to check out as an eclipse project (e.g. trunk) and select Next.

Select the check out as a project configured using the New Project Wizard and select 'Finish'

For this exercise, I'm checking mine out as a java project, so I'm selecting Java Project and Next on the wizard box.

Give the Project a name (e.g. myProject), select Finish and OK

Let it check out your project...

You should see something like myProject [trunk] in the package explorer.
You can now right click on the folder and go to New > Folder and create a new folder

When you're ready, right click on the folder you've created, go to the Team context menu and select 'Add to Version Control'; you'll probably need to do this for any new files you subsequently add...

From then, commit will add new changes and update will refresh a stale repository.

One other note: to check out the project, I used my gmail username. The svn password isn't the same as your gmail password though.

I found the password for the code repository (when logged in) here - so hopefully this will help:

http://code.google.com/hosting/settings

NB: I've seen situations where subclipse (or subversion) would keep asking for a password; I managed to stop it from doing this by going into the Eclipse > Window > Preferences, expanding the Team folder, selecting SVN and ensuring that the SVN interface was selection was set to SVNKit (Pure Java).

Thursday 5 April 2007

Notes on Backing stuff up...

So I don't forget:

To backup the (or a) svn repository to the user home directory:

python hot-backup.py --archive-type=gz /path/to/svn/repository ~/

To backup the trac instance and pipe the hotcopy output to a gzipped file:

trac-admin /path/to/trac/instance hotcopy ~/my-trac-backup-folder | tar cvpzf ~/tracbackup.tgz

Also note for tar (and if working from a different folder) that the syntax runs like this:

tar cvzf /path/to/compressed-filename.tgz /path/of/folder-to-be-archived/

This will 'tar up' all the files within that particular folder (and subfolders).

And for the overly cautious - to backup *everything* from the root folder into one huuuuuge gzipped file:

tar cvpzf ~/my-filesystem-backup-file.tgz / –exclude=/name/of/folder/to/be/excluded

Friday 2 March 2007

Setting up xssi parsing for included files

I've set this up a few times now and sometimes it takes me a while to remember what steps were required to make this work... so here are some rough notes:

httpd.conf must have the mod_include module loaded (so this needs to be copied / compiled if not in there automatically)

LoadModule include_module path/to/apache/mods/mod_include.so

"Include" needs to be added to your options

Options Indexes FollowSymLinks Includes

<IfModule mime_module>
# this section should contain the following:

AddType text/html .shtml .sssi
AddOutputFilter INCLUDES .shtml .sssi

# so any includes named *.sssi will be parsed by apache
</IfModule>

After an apachectl restart, you can make a page called test.shtml which contains this call:

<!--#include file="includes/footer.sssi" -->

And footer.sssi can contain something like this:

<!--#if expr="{$QUERY_STRING} = /printenv/" -->
<div id="debug-footer">
<h3>Debug Footer</h2>
<p>File last modified <!--#flastmod file="$DOCUMENT_NAME" --></p>
<pre><!--#printenv --></pre>
</div>
<!--#else -->
<h3>Standard Footer</h3>
<!--#endif -->


Now when you open test.shtml?printenv you'll see your environment variables.

Opening a new browser window and maximising it..

I'm usually vehemently against this method of web development (never, ever break the back button!) but someone I know wanted to do this for their client, so I worked out a solution - I've pasted the code here so I can dole it out as and when needed... Obviously the usual disclaimer applies: don't do this unless you really have to!

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>
<title>Home page</title>
<script type="text/javascript">

var uri;
var myWindow;

function openme(uri){
myWindow = window.open(uri, 'myWindow', 'toolbar=0,status=0,width=800,height=600')
myWindow.moveTo(0,0);
if (navigator.appVersion.indexOf("Mac",0)>0) {
myWindow.resizeTo(screen.availWidth,screen.availHeight);
} else {
myWindow.resizeTo(screen.width,screen.height);
}
myWindow.focus();
}

</script>

</head>

<body>
<h1>Index Page</h1>
<a href="javascript:void(0)" onClick="javascript:openme('home.html')">open me</a>
<p>This opens a new browser window</p>
</body>
</html>

Thursday 22 February 2007

XSLT 2.0 Feature

Just saw this on the altova forum - could be useful...

A character map lets you tell the XSLT processor "when this character is on its way to the result tree, put this string there instead."

http://www.altova.com/forum/default.aspx?g=profile&u=1034868265

Friday 16 February 2007

Apache XSSI Notes (Draft)

As and when I get time, I hope to make some more detailed notes on creating navigation lists using the XSSI portion of apache. This is very much a work in progress - so please bear this in mind if you're reading this at the moment.

I'll start with a very simple XSSI example; this one will instruct apache to work out (from examining the URI) which page is currently open, and to apply a new id attribute name to the relevant page:

The XSSI navigation code



<ul class="navigation">
<li><a class="link" id="home<!--#if expr="(${DOCUMENT_URI}=/index.shtml/)" -->-selected<!--#endif -->" href="index.shtml"><span>Home</span></a></li>
<li><a class="link" id="about<!--#if expr="(${DOCUMENT_URI}=/about/)" -->-selected<!--#endif -->" href="about.shtml"><span>About</span></a></li>
<li><a class="link" id="contact<!--#if expr="(${DOCUMENT_URI}=/contact/)" -->-selected<!--#endif -->" href="contact.shtml"><span>Contact</span></a></li>
</ul>

In the above code sample, apache pattern matches against the URI given to the browser. I've set up a series of id attributes and given them the same names as the pages themselves.

The Output


Opening the default home page (index.shtml) will produce something like this:

<ul class="navigation">
<li><a class="link" id="home-selected"> href="index.shtml"><span>Home</span></a></li>
<li><a class="link" id="about"> href="about.shtml"><span>About</span></a></li>
<li><a class="link" id="contact"> href="contact.shtml"><span>Contact</span></a></li>
</ul>

By default, pages that need to be parsed by apache (to make the XSSI code work) should be saved with an .shtml extension.

Thursday 15 February 2007

First Posting

Here's a place for my ideas - mostly commentaries on what I'm working on / what I've learned..

Blog Archive