Using Apache Server Side Includes From CGI Scripts

You know the story, you’ve inherited a lovely design and XHTML page build from your designer. The pages are modular and built using server side includes (SSI). The site is easy to update, until you’re asked to make something dynamic.

Normally, I’d use Perl‘s excellent Template Toolkit, and just convert the SSIs to Template Toolkit INCLUDEs. However in this case, the SSIs were nested so I couldn’t take this approach.

The solution turns out to be quite easy, especially as I’m using Apache 2 as my webserver.

Apache 2 has output filters, so I can get the output of my CGI scripts to be parsed by Apache for SSIs directly using mod_include.

In my apache conf file, I need to do something like the following.

<Location /cgi-bin/withssi/>
SetHandler cgi-script
SetOutputFilter INCLUDES
Options +ExecCGI +Includes
</Location>

This will turn on SSI parsing on the output of CGI scripts served from the location of /cgi-bin/withssi.

The key line to notice here is SetOutputFilter INCLUDES as that makes sure the output returned is parsed by mod_include before it reaches the web browser.

Knowing When It’s Safe To Talk To Flash From JavaScript – Part 2

In the previous article Knowing When It’s Safe To Talk To Flash From JavaScript we saw how to call Flash from JavaScript.

We embedded the Flash movie directly into the page, however there are times when we may want to insert the movie dynamically using JavaScript. How can we do this?

Well it turns out fairly easily, especially if we use one of the modern JavaScript framework libraries like jQuery.

jQuery is very extendable, and has a powerful plugin based architecture. Thankfully someone has done the hard work for us and written a plugin to handle the embedding of Flash. Take a look at the jQuery.flash plugin.

How do we use it, well first we need to add the two libraries to the page, jQuery and jQuery.flash.

<script type="text/javascript" src="jquery-1.3.2.js"></script>
<script type="text/javascript" src="jquery.flash.js"></script>

In our page body, we’ll add a bit of HTML that will have it’s content replaced by the Flash movie.

<-- the content of the following div will be replaced. -->
<div id="example">Flash here</div>

Now let’s add the JavaScript that will replace the div’s content. We’ll wrap it inside jQuery’s ready function to make sure everything we need is in place. This is a better version of the window.onload function we saw in the previous article that waits until the page can be manipulated, and not until everythting has been downloaded.


$(document).ready(function() {
$('#example').flash(
{
src: 'test.swf',
height: 1,
width: 1,
flashvars: {onLoad: 'flashLoaded'}
},
{ version: 8}
);
});

This creates the object or embed as necessary, and loads the movie “test.swf”, with a height and width of 1 pixel and the flashvars parameters we saw in the previous article. In this case, the onLoad parameter has a value of flashLoaded, the name of the function we want to call when the flash has loaded and is ready to execute. There is also a parameter saying the minimum version of the Flash player we need, let’s use version 8 here.

Now when the page is loaded, the <div> block will be replaced with the flash movie, and this in turn will call our callback function flashLoaded.

Update: Using Mootools

Mootools is another excellent JavaScript framework library, and it has Flash support built into it’s core using the Swiff class.

For Mootools, firstly we need to make sure it’s loaded.

<!-- load the mootools library -->
<script type="text/javascript" src="mootools.js"></script>

Now we’ll wrap our Swiff object creation in Mootools domready event. This is the equivilant to what we did earlier in jQuery with the ready event.

window.addEvent('domready', function() {
var flash = new Swiff('test.swf', {
container: $('example'),
width: 1,
height: 1,
callBacks: {
onLoad: flashLoaded
}
});
});

Here we’re creating a new Swiff object, and telling it to place the flash object / embed tag it creates inside the div with the id of example like we did with the jQuery example. We specify the height and width both of 1 pixel and setup the callback.

As you can see, Mootools specifically calls this a callback unlike jQuery’s flashvars. They mean the same thing here, so we say the onLoad callback function in the Flash movie’s ActionScript will call the local JavaScript function flashLoaded.

Knowing When It’s Safe To Talk To Flash From JavaScript

I’ve been doing some work lately where JavaScript in an XHTML page needs to talk to some ActionScript 3.0 in a Flash movie.

The most common problem here is knowing when you can start talking to the Flash movie. The browser may have loaded all the scripts and started to execute them, but the flash movie may not have loaded or initialised at that point. If you try to talk to the movie at this point, you’ll get errors.

There are a couple of ways around this. You could code the flash movie into the page using <object> and <embed> html tags, then make sure your JavaScript calls the movie after the onload event has been called. E.g.

function flashLoaded() {
alert("Flash loaded");
}
window.onload = function() {
// flash should have loaded by now.
flashLoaded();
}

Now that isn’t ideal, the flash may have loaded, but the movie may not have initialised so you could still have problems.

The safest way is to include a callback function in your ActionScript that runs once the movie has finished initialising. This will call some JavaScript on your page letting you know the movie has loaded and can be interacted with. We can use the ExternalInterface class in the ActionsScript to achieve this.

Let’s assume our ActionScript class is called test, and we have a function in our JavaScript called flashLoaded. The following code is a quick way to let the JavaScript know the movie has loaded.

public function test():void
{
ExternalInterface.call("flashLoaded");
}

This is great, but it does mean we’ve had to hardcode the name of the calling function. What if we had two Flash movies in the page and they both called this function. This could cause problems. We need a way to pass in a function name dynamically.

Flash has something that used to be called FlashVars that can help us here. It’s basically a list of parameters and values that are passed and appended as a query string to the end of the movie files name. These are then available to ActionScript. In our object we alter the movie paramter accordingly.

<-- in the flash object tag -->
<param name="movie" value="test.swf?onLoad=flashLoaded" />

If you use the embed tag, make sure you alter the movie parameter there as well.

To see the passed parameters in ActionScript was need to use root.loaderInfo.parameters. Our initialiser function should be altered to use the following code, in this case we want to use the onLoad parameter.

public function test():void
{
ExternalInterface.call(root.loaderInfo.parameters.onLoad);
}

Great, we can now vary our the name of our callback. However problems could still occur. The movie may be loaded but the stage may not be ready. We need to add a little bit more wrapping code to handle this. The following code should do the trick.


package {
import flash.display.Sprite;
import flash.events.*;
import flash.external.ExternalInterface;
public class test extends Sprite
{
public function test():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
public function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
ExternalInterface.call(root.loaderInfo.parameters.onLoad);
}
}
}

As you can see we’ve moved the callback into the init function, and this is only called when the stage is ready.

You should now be safely able to script your flash movie from JavaScript.

See Knowing When It’s Safe To Talk To Flash From JavaScript – Part 2 for examples on how to integrate this with a modern JavaScript library like jQuery.

Redirects In Catalyst

I’ve been using Catalyst quite a bit recently. For those of you who don’t know what Catalyst is, the easiest buzzword compliant comparison is Ruby On Rails for Perl.

Normally in Catalyst if you want to break the flow from a current method, you use the forward method of the catalyst object to internally redirect to a new handler.

Imagine I have a handler responding to requests at /test.

If I want my request to be dealt with by the handler at /robspage I can issue a forward request in the handler at /test like this…

$c->forward($c->uri_for('/robspage'));
## code will continue here.

Once the code at /robspage has run, control returns to the calling handler.

This isn’t always what is needed, if I don’t want the handler to return and keep running I would need to use the detach method instead.

$c->detach($c->uri_for('/robspage'));
## code will not continue here.

This is great, however, the calling URL will not change and the user will not know they are actually seeing /robspage instead of /test. Sometimes this is the behaviour we want, however in this case I want the user to know a redirect has happened and for this to be reflected in their browser.

To achieve this, we have to use the redirect method of the the response object.

$c->res->redirect($c->uri_for('/robspage'));
$c->detach();

Note that I have added a $c->detach(); call after the redirect as I don’t want the processing chain to continue.

Q Radio Player

Q Radio Player

Q Radio officially relaunched today at 6pm with Samanthi’s QPM show.

I’ve been spending the past few weeks working on the new Q Radio Player.

Really it should have a “beta” somewhere in the title as it’s still being refined based on user feedback, like any other good site.

We have expanded on the old Q Radio Player on Whatson.com.

Improvements include…

  • Now playing information
  • Track artwork and links to buy on Amazon or iTunes
  • Listing previous tracks heard
  • Current show snformation
  • Previous and next show information
  • Listen again for previous shows, along with now playing information
  • Voting on tracks so users can feed back if they like the station output or not
  • Flash streaming, so more users can listen in
  • And more…

Comments (hopefully not bug reports, though they are welcome)? Just contact me.

getURL and Flash 9

We upgraded our Flash players to the current version today and found a few slides on our sites didn’t work as expected.

When clicked, they were supposed to take you to other pages, but with the upgrade, old code was found to be broken.

Looking around, it appears the security model changed and we weren’t aware of this. I think it’s time to subscribe to the Flash RSS feed to keep on top of bug fixes and upgrades.

Anyway, it turned out our code could be fixed by just setting AllowScriptAccess to be “always” or “sameDomain”, depending on the application. In the <object> tag this was achieved by adding…

<param name="allowScriptAccess" value="always">

… and in the embed tag…

allowScriptAccess="always"

Those of you using SWFObject, the following JavaScript code does the trick…

so.addParam("allScriptAccess", "always");

This means when we call getURL() from ActionScript it is able to navigate to other pages on a foreign or the same domain.

There is a bit more information on this on the Adobe Flash knowledge base, Links from SWF files in HTML page no longer function (Flash Player 9).

Using ExtraFields In Movable Type

I’ve been doing some work with Movable Type using the ExtraFields plugin recently.

One problem I had was offering an alternative if an extra field hadn’t been set. It turns out that it’s possible to nest an <MTElse> in the <MTIfExtraField> tag.

Here’s an example. I have an extrafield called externalurl on an entry, if it exists I want to use that for the link, if not I want to use the entry’s permalink.

<MTIfExtraField field="externalurl">
<$MTExtraFieldValue field="externalurl"$>
<MTElse>
<$MTEntryPermalink$>
</MTElse>
</MTIfExtraField>

This basically gives us the functionality of a <MTElseExtraField> tag.

CGI.pm Doesn’t Delete CGItemp Files Automatically

More late night server maintainence…

I noticed the /tmp drive on my server was very full, so had a quick peek. It was full of large CGItemp files.

It turns out the files I’m accepting using for upload using CGI.pm aren’t deleted automatically from the temporary directory as the documentation suggests.

When you’re dealing with a lot of large uploads, this can be a problem.

Deleting A Column Used As A Foreign Key In MySQL

I came across a rather cryptic MySQL error message today while working on a new database.

I had a foreign key I wanted to remove from a table due to a change in the database structure, however when I tried to remove it I kept getting the following error.

mysql> alter table band drop foreign key track_id;
ERROR 1025 (HY000): Error on rename of './rob/band' to './rob/#sql2-b0c-3588d' (errno: 152)

I thought this was a permissions problem to start with on the file structure, but in reality it’s InnoDB complaining that I can’t drop the column I’m using as the foreign key.

The solution is to drop the key first, before dropping the column.

But how do you find the name of the key?

Well for that you need to use show create table tablename, in my case tablename was band.

Running this on my code I found my key (as show in this snippet of SQL)…

...
PRIMARY KEY (`id`),
KEY `track_id` (`track_id`),
CONSTRAINT `id_trackkey` FOREIGN KEY (`track_id`) REFERENCES `track` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1

So I can see this is id_trackkey. The following SQL deleted the key and the column.

alter table band drop foreign key id_trackkey;
alter table band drop track_id;

Voila, the foreign key and the column are now deleted.

Atom Posting To Movable Type

For the Q Awards 2007, we wanted to have minute by minute blogging.

q awards minute by minute

We used Movable Type for the website, but didn’t want to have to rely on having a laptop available to blog from, so blogging from a mobile phone was the approach we took.

Originally we looked at Twitter for this, but we worried about connection speed. We also looked at Nokia Lifeblog, while good, it doesn’t really allow for just headline posting. Finally, we took the custom code approach.

Movable Type has an Atom interface, it’s what Nokia Lifeblog uses. This lets us post articles, so all we needed was a suitable client. Thankfully, using Perl, there is XML::Atom::Client.

Ben Hammersley provides an great tutorial on using the Atom API in Movable Type.

My code needed to take a line of text and post automatically to Movable Type in a certain category (called “livefeed”). I built a really simple HTML page that could be used by any internet enabled phone. It had one text box and one submit button. Copy entered here and submitted would appear in the Movable Type blog automatically.

I needed some glue Perl code behind this page to make this happen. It turned out to be really simple, and here’s the core functionality. I won’t bore you with CGI handling or display code, just the Atom meat.

my $api = XML::Atom::Client->new;
$api->username($username);
$api->password($password);
my $dc = XML::Atom::Namespace->new(dc => 'http://purl.org/dc/elements/1.1/');
my $entry = XML::Atom::Entry->new;
$entry->title($title);
$entry->content('');
$entry->set($dc, 'subject', 'livefeed');
my $edituri = $api->createEntry($posturl, $entry);
if ($edituri) {
## posted ok
} else {
## not posted, $api->errstr has the error message;
}

This code assumes you have a few variables in place, those are

  • $username – the poster’s username
  • $password – the poster’s web services password
  • $posturl – the web service’s post url
  • $subject – the copy to post to the blog

Movable Type has two different passwords per user, it is important we use the webservices password and not the users normal Movable Type password.

Now we were posting and creating entries each post, we wanted to show them all on one page. my collegue Ross wrote this block of code to display the posts.

<MTEntries category="livefeed">
<li>
<MTIfNonEmpty tag="EntryTitle">
<p class="time"><$MTEntryDate format="%I:%M %p"$></p>
<p><$MTEntryTitle$></p>
</MTIfNonEmpty>
</li>
</MTEntries>

This turned out to be a nice, fast solution to getting content up quickly on the day.