Compare with Previous | Blame | View Log
<?php
/**
* ShareOnOvi - A PHP class for interacting with Nokia's "Share on Ovi" service.
*
* The Share on Ovi service from Nokia, a website and related applications that allow
* for media sharing, provides the facility to upload new items using the Atom
* Publishing Protocol (APP). This PHP class implements a subset of the APP to
* allow new JPEG images (only, for the time being) to by uploaded to Share on Ovi
* programatically.
*
* Requirements for use:
*
* - PHP 5 or greater
* - class.wsse.php (available from http://www.dentedreality.com.au/phpatomapi/)
* - a Share on Ovi account
*
* To do:
*
* - additional error checking at possible failure points
* - support additional media types (currently supports only JPEG)
* - additional functionality to support edit of existing media
*
* Usage example:
*
* require_once 'class.ovi.php';
* $son = new ShareOnOvi('username','password');
* $son->Upload("~/images/test.jpg","My Test Image","A picture of my dog",array("dog","animal"),"public");
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* @version 1.2, July 13, 2008
* @link http://ruk.ca/w/index.php/Share_on_Ovi_API Documentation
* @link http://share.ovi.com/ Share on Ovi website
* @link http://www.ietf.org/rfc/rfc5023.txt Atom Publishing Protocol - RFC 5023
* @author Peter Rukavina <peter@rukavina.net>
* @copyright Copyright © 2008, Reinvented Inc.
* @license http://www.fsf.org/licensing/licenses/gpl.txt GNU Public License
*/
class ShareOnOvi {
private $userAgent = "ShareOnOvi PHP/1.0";
private $endPoint = "http://share.ovi.com/api/atom/1.0/";
/**
* Creates a ShareOnOvi object
* @param string $username the Share on Ovi username
* @param string $password the Share on Ovi password
*/
function __construct($username, $password) {
$this->username = $username;
$this->password = $password;
$this->xmlskeleton = $this->makeMetadataSkeleton();
}
/**
* Uploads a file to Share On Ovi.
* @param string $filename the filename (complete path) of the file to upload (supports JPEG images only right now)
* @param string $title the title to give the image on Share on Ovi
* @param string $summary the summary ("description") to give the image on Share on Ovi
* @param array $tags the tags to give the image on Share on Ovi
* @param string $channel the channel to upload to (i.e. "mymedia" or "public") - must already exist
* @return string the URL of the Share on OVI object
*/
function Upload($filename,$title,$summary,$tags,$channel) {
// Check to see if the file we want to upload actually exists.
if (!file_exists($filename) and !($this->is_url($filename))) {
die("ERROR: The file '$filename' does not exist. You must pass the complete path.\n");
}
// We need class.wsse.php to package up the WSSE authentication header.
require_once("class.wsse.php");
// Create a new cURL object.
$ch = curl_init($this->endPoint . $this->username . "." . $channel);
// Construct a WSSE header array from the username and password.
$WSSE = new WSSE($this->username,$this->password);
$this->WSSE = $WSSE->get_header(true);
// The headers for the HTTP POST.
$headers = array("Content-Type: image/jpeg",
"User-Agent: " . $this->userAgent);
// Add the WSSE headers into the mix.
$headers = array_merge($this->WSSE,$headers);
// Grab the file we're going to upload (requires the complete path).
$upload = file_get_contents($filename);
// Add the headers to the cURL object.
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Don't return the headers as part of the response.
curl_setopt($ch, CURLOPT_HEADER, 0);
// Return the response as the return vaalue of the curl_exec.
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// This is just a straight binary POST, not a key-value pair POST, so we use a custom request.
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
// Set the binary data as the POST payload.
curl_setopt($ch, CURLOPT_POSTFIELDS, $upload);
// Do the actual cURL magic.
$output = curl_exec($ch);
// Close the cURL object.
curl_close($ch);
// If we got back a simple 'Authentication failed.' response, then we exit with an error message.
if ($output == "Authentication failed.") {
die("ERROR: Share on Ovi authentication failed. Check the username and password.\n");
}
// Take the response we got from cURL as XML and turn it into a PHP object.
$response = new SimpleXMLElement($output);
// Look for the links with attributes of 'edit' (the endpoint for PUTing metadata) and 'alternate' (the URL for the new object on OVI)
foreach($response->link as $key => $link) {
$attrs = $link->attributes();
if ($attrs['rel'] == 'edit') {
$editURL = $attrs['href'];
}
else if ($attrs['rel'] == 'alternate') {
$objectURL = $attrs['href'];
}
}
// If we didn't get a link in the XML returned to PUT the metadata, then something went wrong and we exit.
if ($editURL == '') {
die("ERROR: No endpoint returned from Share on Ovi to PUT image metadata.\n");
}
// Contruct a new SimpleXML object, using the 'metadata-skeleton.xml' file as a template.
$xml = new SimpleXMLElement($this->xmlskeleton);
// Add image title element, with attribute type=text.
$xml_title = $xml->addChild('title',$title);
$xml_title->addAttribute("type","text");
// Add image summary element.
$xml_summary = $xml->addChild('summary',$summary);
// Add a category element, setting privacy to public.
$xml_term = $xml->addChild('category',null);
$xml_term->addAttribute("term","public");
$xml_term->addAttribute("scheme","http://schemas.nokia.com/onlinesharing/2006/category#privacylevels");
// Add category elements for each tag.
foreach($tags as $key => $value) {
$xml_tag = $xml->addChild('category',null);
$xml_tag->addAttribute("term",$value);
$xml_tag->addAttribute("scheme","http://schemas.nokia.com/onlinesharing/2006/category#tags");
}
// Convert the SimpleXML object into XML text.
$xml_request = $xml->asXML();
$content_length = strlen($xml_request);
// Create a new cURL object.
$ch = curl_init($editURL);
// Construct a WSSE header array from the username and password (each request demands a brand-new WSSE header).
$WSSE = new WSSE($this->username,$this->password);
$this->WSSE = $WSSE->get_header(true);
// The headers for the HTTP POST.
$headers = array("Content-Type: application/atom+xml; charset=utf-8",
"Content-Length: " . $content_length,
"User-Agent: " . $this->userAgent);
// Add the WSSE headers into the mix.
$headers = array_merge($this->WSSE,$headers);
// Add the headers to the cURL object.
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Don't return the headers as part of the response.
curl_setopt($ch, CURLOPT_HEADER, 0);
// Return the response as the return vaalue of the curl_exec.
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// This is going to be an HTTP PUT (using CURLOPT_CUSTOMREQUEST because CURLOPT_PUT caused issues with headers)
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
// Set the binary data as the PUT payload.
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_request);
// Do the actual cURL magic.
$output = curl_exec($ch);
// Close the cURL object.
curl_close($ch);
// Return the Share on Ovi URL of the object we created.
return $objectURL;
}
/**
* Returns the skelton XML required to PUT metadata.
* @return string XML skeleton
*/
function makeMetadataSkeleton() {
$xml = <<<END
<?xml version="1.0" encoding="utf-8" ?>
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:atom03="http://purl.org/atom/ns#"
xmlns:thr="http://purl.org/syndication/thread/1.0"
xmlns:georss="http://www.georss.org/georss"
xmlns:nokia="http://schemas.nokia.com/onlinesharing/2006">
<atom03:generator>ShareOnOvi PHP/1.0</atom03:generator>
</entry>
END;
return $xml;
}
/**
* Sanity check, is it really an URL?
* From http://crunchbang.org/wiki/php-function-isurl/
*/
function is_url($url){
$url = substr($url,-1) == "/" ? substr($url,0,-1) : $url;
if ( !$url || $url=="" ) return false;
if ( !( $parts = @parse_url( $url ) ) ) return false;
else {
if ( $parts[scheme] != "http" && $parts[scheme] != "https" && $parts[scheme] != "ftp" && $parts[scheme] != "gopher" ) return false;
else if ( !eregi( "^[0-9a-z]([-.]?[0-9a-z])*.[a-z]{2,4}$", $parts[host], $regs ) ) return false;
else if ( !eregi( "^([0-9a-z-]|[_])*$", $parts[user], $regs ) ) return false;
else if ( !eregi( "^([0-9a-z-]|[_])*$", $parts[pass], $regs ) ) return false;
else if ( !eregi( "^[0-9a-z/_.@~-]*$", $parts[path], $regs ) ) return false;
else if ( !eregi( "^[0-9a-z?&=#,]*$", $parts[query], $regs ) ) return false;
}
return true;
}
}