IMPORTANT! Some of the information in this post is not correct. I will be updating it soon.
Updated: See section on serving the update.xml file
OK, now that we have MAR files, how do we get them to our users?
Setting Up a Firefox Update Server
A Firefox update server is actually not that complex of a setup. Basically a Firefox update server takes a URL that describes a particular Firefox version, and if there is an update available, it returns an XML file that identifies the location of the update. So let’s take a look at this URL.
If you are to go into about:config and search for app.update.url, you would see the following:
https://aus2.mozilla.org/update/1/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/update.xml
When Firefox 2.0.0.3 looks for an upgrade (English on Windows), the URL looks like this:
https://aus2.mozilla.org/update/1/Firefox/2.0.0.3/2007030919/WINNT_x86-msvc/en-US/release/update.xml
Most of this URL is self explanatory. The only part we need to explain is BUILD_ID. The build ID of a Firefox is a unique identifer that conveys the exact date down to the hour when a build was created. For the build above, that data is March 9, 2007 at 7:00 PM. You can see the build ID for any Firefox build by type about: in the URL bar. Note that selecting Help->About does not display the complete build ID. If you build a custom version of Firefox, you can see the build ID by looking in the file mozilla/obj/config/nsBuildID.h. If you see a build ID of 0000000000 in this file, it means that you forgot to set MOZILLA_OFFICIAL and BUILD_OFFICIAL before building.
If we look at the URL that is served, it ends in update.xml. So what do these update.xml files look like? Here’s the update.xml to upgrade from Firefox 2.0.0.2 to Firefox 2.0.0.3. (https://aus2.mozilla.org/update/1/Firefox/2.0.0.2/2007021917/WINNT_x86-msvc/en-US/release/update.xml)
<?xml version="1.0"?>
<updates>
<update type="minor"
version="2.0.0.3"
extensionVersion="2.0.0.3"
buildID="2007030919"
detailsURL="http://en-US.www.mozilla.com/en-US/firefox/2.0.0.3/releasenotes/">
<patch type="complete"
URL="http://download.mozilla.org/?product=firefox-2.0.0.3-complete&os=win&lang=en-US"
hashFunction="SHA1"
hashValue="bc64376c13867b5524d71e87f7ad98e727f2d3f4"
size="7617299"/>
<patch type="partial"
URL="http://download.mozilla.org/?product=firefox-2.0.0.3-partial-2.0.0.2&os=win&lang=en-US"
hashFunction="SHA1"
hashValue="2555dcad94c9bc1c7327cb3699844f633888ea4a"
size="270514"/>
</update>
</updates>
Rather then go into a lot of detail here about this file, I’d rather point you to wiki.mozilla.org which has a great explanation of this file. (Incidentally, the wiki you can lots of other great information about the Software Update process) One thing you might be wondering is how to generate the hashValue. Microsoft has a tool available called FCIV that can be used to generate the hashes.
OK, we know the URL and we have the update.xml file, so how do we serve it to the browser?
Update: as
Benjamin Smedberg pointed out, I am doing a lot of work for nothing. mod_rewrite can be used to accomplish this task. Create a file called “noupdate.xml” that contains
<updates></updates>Then put this in a .htaccess file:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*) noupdate.xml
What this says is if you find the file, serve it, if you don’t, serve the file that represents the empty update.
At first, it looks like we can just setup directories that correspond to the URL, but this won’t work since we need to send an XML file that looks like:
<updates>
</updates>
If there are no updates available. So I’m going to use a simple PHP file to function as our update server. We’ll need to do some changes to our web server configuration as well. Note I am using Apache.
First go into httpd.conf and make sure that mod_rewrite is available. Then go into your main web directory and add or edit the file .htaccess with this:
RewriteEngine on
RewriteRule ^/?update/(.*) /update.php/$1 [L]
What this rule says is whenever you see a URL that begins with “update” send it to update.php. The actual update.php file looks like this:
<?php
header("Content-type: text/xml");
$url_array=explode("/",$_SERVER["REQUEST_URI"]);
$noidea=$url_array[2];
$product=$url_array[3];
$version=$url_array[4];
$build_id=$url_array[5];
$build_target=$url_array[6];
$locale=$url_array[7];
$channel=$url_array[8];
$filename=$url_array[9];
$updatefile = "$noidea/$product/$version/$build_id/$build_target/$locale/$channel/$filename";
//echo "$updatefile";
if (file_exists($updatefile)) {
$handle = fopen($updatefile, "r");
$contents = fread($handle, filesize($updatefile));
echo "$contents";
fclose($handle);
} else {
echo '';
echo '';
}
?>
This PHP simply looks for the presence of an update.xml directory structure specified by the URL and if it is available, it returns it, otherwise it returns <updates></updates>
So how do we publish updates then? We simply create an update.xml file and place it in the appropriate subdirectory.
The last step is updating the browser to point to our new update URL. Your first thought might have been to simple update app.update.url in about:config, but that will not work. When app.update.url is queried by Firefox, it always looks for the “default preference” which means that even if a user changes the preference, it won’t be used. For testing purposes, you can add a new preference called “app.update.url.override” that will work, but when you go to deploy your updates, you should set app.update.url in an extension like the CCK. That will cause it to become a “default preference.”
One more installment to go. I’ll try to address some general deployment issues, and if you have questions (any questions), PLEASE let me know.