Exploiting Live Gallery to upload to custom gallery

19 March 2008 Tags  , ,

My photo management tool of choice is Live Gallery (WLG): it's fast, free, and fairly featuresome.

One feature that is lacking however, is to upload to your own 'custom' gallery. Oh, sure, you can upload to Flickr, or Live Spaces, but honestly, who uses either of those services, pfft! Unfortunately, there doesn't seem to be a plugin API (yet?) for Live Gallery so it isn't possible to add your own image gallery service to upload - well, not as neatly as Flickr/Live Spaces.

Step 1: Add Your Gallery

To add your own custom gallery uploading to Live Gallery, we need to exploit the Online Printing functionality. Each printing service is actually defined in the registry, and the default "Print@Kodak" is a great starting point to seeing what data we need.

It is located at:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\PublishingWizard\InternetPho
toPrinting\DownloadedProviders\Print@Kodak

The registry values look like:

"displayname"="Print@Kodak"
"description"="Get Kodak photo quality prints from your digital camera!"
"href"="http://print.fotowire.com/webprint/xp/start.asp?WID=25900"
"icon"="fwPrint.ico"

To add your own, it is as simple as creating your own key inside of DownloadedProviders, however either Windows or WLG seems to delete the registry key after closing WLG. Instead of inside DownloadedProviders, create a Providers key (inside InternetPhotoPrinting), and then create your own Provider key, with the same sorts of values (displayname, href, description and icon) as the Kodak Provider.

It should look something like this image when you're done

image

There is another benefit to doing it this way, under the printing menu, you will now have 'Print', 'Order prints', and 'Order prints from foo'

image

Step 2: Prepare your gallery

While it is great we've thrown it a random URL, how do we know what data is actually being sent?

Thankfully Elmar Putz had figured out the XP Web Publishing Wizard (which is very, very similar), so that was most of the leg work done.

First, the page set in the Href in Registry. I'm going to cut to the chase and just list the HTML/Javascript, if you want more of an explanation, see Elmar's article (linked above). All you need to do is change the UploadURL and EndUrl

<html>
    <
head>
        <
script language="JavaScript">
            var
UploadURL = "http://mydomain/upload/";
            var EndURL = "http://mydomain/aftertheupload.html";
            function window.onload()
            {
                window.external.SetWizardButtons(0,1,0);   
            }

            function window.onback()
            {
                window.external.FinalBack();
            }
           
            function window.onnext()
            {
                var xml = window.external.Property("TransferManifest");
                var files = xml.selectNodes("transfermanifest/filelist/file");

                for (i = 0; i < files.length; i++)
                {           
                    var postTag = xml.createNode(1, "post", "");
                    postTag.setAttribute("href", UploadURL);
                    postTag.setAttribute("name", "myfile");

                    var dataTag = xml.createNode(1, "formdata", "");
                    dataTag.setAttribute("name", "MAX_FILE_SIZE");
                    dataTag.text = "2000000";
                    postTag.appendChild(dataTag);

                    var dataTag = xml.createNode(1, "formdata", "");
                    dataTag.setAttribute("name", "action");
                    dataTag.text = "Save";
                    postTag.appendChild(dataTag);

                    files.item(i).appendChild(postTag);
                }

                var uploadTag = xml.createNode(1, "uploadinfo", "");
                var htmluiTag = xml.createNode(1, "htmlui", "");
                htmluiTag.text = EndURL;
                uploadTag.appendChild(htmluiTag);

                xml.documentElement.appendChild(uploadTag);
               
                window.external.FinalNext();
            }
           
            function document.oncontextmenu()
            {
                return false;
            }
        </script>
    </
head>
<
body>
    <
h2>Click Next to upload</h2>
</
body>
</
html>

image

The code for the page at UploadURL would look something like…

ASP.NET

String uploadDir = "Images/";
HttpFileCollection hpC = System.Web.HttpContext.Current.Request.Files;
for (int i = 0; i < hpC.Count; i++)
{
    HttpPostedFile file = hpC[i];
    if (file.FileName != string.Empty)
    {
        file.SaveAs(Server.MapPath(uploadDir + file.FileName));
    }
}

PHP

<?php foreach ($_FILES["pictures"]["error"] as $key => $error) { if ($error == UPLOAD_ERR_OK) { $tmp_name = $_FILES["pictures"]["tmp_name"][$key]; $name = $_FILES["pictures"]["name"][$key]; move_uploaded_file($tmp_name, "uploadDirectory/$name"); } } ?>

Step 3: Reading the file (optional)

If you're writing your own gallery, or simply just want a way to avoid having to FTP in to upload files, it may look as if you've lost the meta-data (specifically I mean tags)  from your photos. Fear not, however, as there is a way!

All the tags are stored in 'XMP' format, which is essentially just embedded XML.

.NET 2.0
In .NET 2.0, there is no native way to read in XMP Information, so we need to use some XML parsing to get it. Microsoft blogger Omir Shahine, has a great post on accessing XMP data in .NET 2, including the code/general discussion on the matter.

.NET 3.x+
In .NET 3 and above, inside the Windows Imaging Component, there is the BitmapMetaClass. However this is both more and less complex than using regular expressions (above), in that you nave to use the proper 'paths' for accessing specific data. I won't cover it here, but WIC/BitmapMetaClass is what you should look into if you want the .NET 3+ method of accessing XMP/EXIF data.

PHP
Like .NET 2, there is no native way to read in XMP information. The below code will return an array of XMP Tags.

<?php function GetTags($filename) { $handle = fopen($filename, "r"); $image = fread($handle, filesize($filename)); fclose($handle); preg_match("/LastKeywordXMP>([\w\W\t\f\s]*)LastKeywordXMP>/i", $image, $matches); $tags =split("</rdf:li>",$matches[1]); for ($i=0;$i<count($tags);$i++) { $tags[$i] = trim(strip_tags($tags[$i])); } return $tags; }?>

Final Notes

Since there isn't an authentication option in the printing wizard, security is a concern, particularly in a multiuser environment. You could implement any/all of the following however

  • Since it is just HTML, there is absolutely no reason that you couldn't add in a HTML form for entering the username and password as the "first stage". The second page would be returned from the server, with the (javascript) settings to allow uploading. It is a hosted IE session, so it should store/access cookies - if they've logged in via IE, they should remain logged in!
  • create a 'secure private' hash and append that to the url, ie http://mygallery/upload.php?hash=DADGGSDGFS123
    This would mean user would have a separate (auto-generated I'd assume…) REG file to import
  • IP based filtering (okay idea, sucks if your IP changes, or if you're on a public network)

 



Comments

One Comment

Trackbacks / Pingbacks

Comments are closed