You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by li...@apache.org on 2008/03/06 16:43:52 UTC

svn commit: r634310 - in /incubator/shindig/trunk/php/gadgets: ./ src/ src/http/

Author: lindner
Date: Thu Mar  6 07:43:50 2008
New Revision: 634310

URL: http://svn.apache.org/viewvc?rev=634310&view=rev
Log:
Patch by Chris Chabot for SHINDIG-112
- Changed *RemoteContent* to do single requests, curl_multi was acting up on some of my systems and wasn't used in practice anyhow, so simplifying it to single requests resolved these issues.
- Refactored Gadget / GadgetView / GadgetSpec into a single class. Simple class structure fits better with PHP, and makes it easier to read too.
- Moved http processing options into the config array, this way they you can override then if desired, and saves code.
- Removed a few bits of unused code (Icons, NoOop feature).
- Removed abstract base classes for things that don't have to be replaced by site's own implementations (featurespec, userpref and localespec).
- Moved the caching of the feature loader a bit up in the chain, saves a good bit on processing time and has the same effect.
- Fixed a silly oversight where the cache key for url's was md5'd twice, thus increasing the change of a key collision.
- Removed a few more include's that are now handled by the __autoloader.
- Now using sha1 instead of md5 for keys (larger keys, theoretically less chance of key collisions).
- Fixed a bug in the proxy where httpMethod was ignored if fetchJson was called.
- Fixed a bug in the proxy where it didn't always look in the post variables for url/method/etc, and made this generally more consistent
- Implemented the missing sha1 checksum for the js libs query (?js=<version>) for href gadget content.
- Added a noHeaders option to the base http servlet class, so we can properly use its destructor without breaking the JS and Proxy servlets.
- Improved header handling in the proxy code, uses apache's get all headers where available and otherwise falls back on a _SERVER based work around, also blacklisted a few headers for the passthru and thus fixing a few bugs where the browser didn't understand the request so well.
- Fixed handling of postData in the proxy.
- Fixed setCachingHeaders in the proxy.
- Fixed the mixed naming of jsLibrary / JsLibrary which was causing the autoloader to fail 


Added:
    incubator/shindig/trunk/php/gadgets/src/GadgetId.php
    incubator/shindig/trunk/php/gadgets/src/Locale.php
Removed:
    incubator/shindig/trunk/php/gadgets/src/GadgetException.php
    incubator/shindig/trunk/php/gadgets/src/GadgetSpec.php
    incubator/shindig/trunk/php/gadgets/src/GadgetView.php
    incubator/shindig/trunk/php/gadgets/src/GadgetViewID.php
    incubator/shindig/trunk/php/gadgets/src/HttpProcessingOptions.php
    incubator/shindig/trunk/php/gadgets/src/ProcessingOptions.php
    incubator/shindig/trunk/php/gadgets/src/RemoteContentException.php
    incubator/shindig/trunk/php/gadgets/src/SpecParserException.php
Modified:
    incubator/shindig/trunk/php/gadgets/config.php
    incubator/shindig/trunk/php/gadgets/src/BasicRemoteContent.php
    incubator/shindig/trunk/php/gadgets/src/BasicRemoteContentFetcher.php
    incubator/shindig/trunk/php/gadgets/src/Gadget.php
    incubator/shindig/trunk/php/gadgets/src/GadgetContext.php
    incubator/shindig/trunk/php/gadgets/src/GadgetFeatureRegistry.php
    incubator/shindig/trunk/php/gadgets/src/GadgetServer.php
    incubator/shindig/trunk/php/gadgets/src/GadgetSpecParser.php
    incubator/shindig/trunk/php/gadgets/src/JsFeatureLoader.php
    incubator/shindig/trunk/php/gadgets/src/JsLibrary.php
    incubator/shindig/trunk/php/gadgets/src/MessageBundleSubstituter.php
    incubator/shindig/trunk/php/gadgets/src/RemoteContent.php
    incubator/shindig/trunk/php/gadgets/src/RemoteContentFetcher.php
    incubator/shindig/trunk/php/gadgets/src/RemoteContentRequest.php
    incubator/shindig/trunk/php/gadgets/src/Substitutions.php
    incubator/shindig/trunk/php/gadgets/src/http/GadgetRenderingServlet.php
    incubator/shindig/trunk/php/gadgets/src/http/HttpServlet.php
    incubator/shindig/trunk/php/gadgets/src/http/JsServlet.php
    incubator/shindig/trunk/php/gadgets/src/http/ProxyHandler.php
    incubator/shindig/trunk/php/gadgets/src/http/ProxyServlet.php

Modified: incubator/shindig/trunk/php/gadgets/config.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/config.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/config.php (original)
+++ incubator/shindig/trunk/php/gadgets/config.php Thu Mar  6 07:43:50 2008
@@ -5,12 +5,10 @@
  * would be horribly slow (db, xml, ini files etc), so ... here's our config.php
  */
 
-// The base prefix under which the gadget url's live, if its the root set this to ''
-// don't forget to update your .htaccess to reflect this, as well as your container 
-// javascript like: gadget.setServerBase('/gadgets/');
-
 $config = array(
-	// the prefix of where this code resides
+	// The base prefix under which the gadget url's live, if its the root set this to ''
+	// don't forget to update your .htaccess to reflect this, as well as your container 
+	// javascript like: gadget.setServerBase('/gadgets/');
 	'web_prefix' => '/gadgets',
 
 	// location of the features directory on disk. The default setting assumes you did a 
@@ -43,5 +41,10 @@
 	'cache_root'=> '/tmp/shindig',
 	
 	// In some cases we need to know the site root (for features forinstance)
-	'base_path'=> realpath(dirname(__FILE__))
+	'base_path'=> realpath(dirname(__FILE__)),
+
+	// We combine global and per request state in the config since it saves a good bit of code
+	// and global classes & variables, these are the HttpProcessingOptions
+	'ignoreCache' => (isset($_GET['nocache']) && intval($_GET['nocache']) == 1) || (isset($_GET['bpc']) && intval($_GET['bpc']) == 1),
+	'focedJsLibs' => isset($_GET['libs']) ? trim($_GET['libs']) : null
 );

Modified: incubator/shindig/trunk/php/gadgets/src/BasicRemoteContent.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/BasicRemoteContent.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/BasicRemoteContent.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/BasicRemoteContent.php Thu Mar  6 07:43:50 2008
@@ -20,36 +20,23 @@
 
 class BasicRemoteContent extends RemoteContent {
 	
-	public function fetch($requests, $options)
+	public function fetch($request)
 	{
 		global $config;
 		$cache = new $config['data_cache']();
-		if ($requests instanceof RemoteContentRequest) {
-			$requests = array($requests);
-		}
 		$remoteContentFetcher = new BasicRemoteContentFetcher();
-		$ret = array();
-		foreach ( $requests as $request ) {
-			if (! ($request instanceof RemoteContentRequest)) {
-				throw new RemoteContentException("Invalid request type in remoteContent");
-			}
-			// determine which requests we can load from cache, and which we have to actually fetch
-			if (! $options->ignoreCache && ($cachedRequest = $cache->get(md5($request->toHash()))) !== false) {
-				$ret[] = $cachedRequest;
-			} else {
-				$remoteContentFetcher->addRequest($request);
-			}
+		if (! ($request instanceof RemoteContentRequest)) {
+			throw new RemoteContentException("Invalid request type in remoteContent");
 		}
-		if ($remoteContentFetcher->pendingRequests()) {
-			$requests = $remoteContentFetcher->fetchRequests();
-			// store the objects we just fetched in cache
-			foreach ( $requests as $request ) {
-				if ($request->getHttpCode() == '200') {
-					// only cache requests that returned a 200 OK
-					$cache->set(md5($request->toHash()), $request);
-				}
+		// determine which requests we can load from cache, and which we have to actually fetch
+		if (! $config['ignoreCache'] && ($cachedRequest = $cache->get($request->toHash())) !== false) {
+			$ret = $cachedRequest;
+		} else {
+			$ret = $remoteContentFetcher->fetchRequest($request);
+			// only cache requests that returned a 200 OK
+			if ($request->getHttpCode() == '200') {
+				$cache->set($request->toHash(), $request);
 			}
-			$ret = array_merge($requests, $ret);
 		}
 		return $ret;
 	}

Modified: incubator/shindig/trunk/php/gadgets/src/BasicRemoteContentFetcher.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/BasicRemoteContentFetcher.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/BasicRemoteContentFetcher.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/BasicRemoteContentFetcher.php Thu Mar  6 07:43:50 2008
@@ -25,73 +25,57 @@
 class BasicRemoteContentFetcher extends remoteContentFetcher {
 	private $requests = array();
 	
-	public function addRequests($requests)
+	public function fetchRequest($request)
 	{
-		foreach ( $request as $request ) {
-			$this->addRequest($request);
-		}
-	}
-	
-	public function addRequest(remoteContentRequest $request)
-	{
-		$url = $request->getUrl();
-		if (empty($url)) {
-			throw new remoteContentException("Invalid or empty url specified in remoteContentFetcher");
-		}
-		$this->requests[] = $request;
-	}
-	
-	public function fetchRequests()
-	{
-		$ret = array();
-		$mh = curl_multi_init();
-		// Setup each request based on its options
-		foreach ( $this->requests as $request ) {
-			$request->handle = curl_init();
-			curl_setopt($request->handle, CURLOPT_URL, $request->getUrl());
-			curl_setopt($request->handle, CURLOPT_FOLLOWLOCATION, 1);
-			curl_setopt($request->handle, CURLOPT_RETURNTRANSFER, 1);
-			curl_setopt($request->handle, CURLOPT_HEADER, 1);
-			if ($request->hasHeaders()) {
-				curl_setopt($request->handle, CURLOPT_HTTPHEADER, array($request->getHeaders()));
+		$request->handle = curl_init();
+		curl_setopt($request->handle, CURLOPT_URL, $request->getUrl());
+		curl_setopt($request->handle, CURLOPT_FOLLOWLOCATION, 1);
+		curl_setopt($request->handle, CURLOPT_RETURNTRANSFER, 1);
+		curl_setopt($request->handle, CURLOPT_AUTOREFERER, 1);
+		curl_setopt($request->handle, CURLOPT_MAXREDIRS, 10);
+		curl_setopt($request->handle, CURLOPT_CONNECTTIMEOUT, 10);
+		curl_setopt($request->handle, CURLOPT_TIMEOUT, 20);
+		curl_setopt($request->handle, CURLOPT_HEADER, 1);
+		if ($request->hasHeaders()) {
+			$headers = explode("\n", $request->getHeaders());
+			$outHeaders = array();
+			foreach ( $headers as $header ) {
+				if (strpos($header, ':')) {
+					$key = trim(substr($header, 0, strpos($header, ':')));
+					$val = trim(substr($header, strpos($header, ':') + 1));
+					if (strcasecmp($key, "Transfer-Encoding") != 0 && strcasecmp($key, "Cache-Control") != 0 && strcasecmp($key, "Expires") != 0 && strcasecmp($key, "Content-Length") != 0) {
+						$outHeaders[] = "$key: $val";
+					}
+				}
 			}
-			if ($request->isPost()) {
-				curl_setopt($request->handle, CURLOPT_POST, 1);
-				curl_setopt($request->handle, CURLOPT_POSTFIELDS, $request->getPostBody());
-			}
-			curl_multi_add_handle($mh, $request->handle);
+			curl_setopt($request->handle, CURLOPT_HTTPHEADER, $outHeaders);
+		}
+		if ($request->isPost()) {
+			curl_setopt($request->handle, CURLOPT_POST, 1);
+			curl_setopt($request->handle, CURLOPT_POSTFIELDS, $request->getPostBody());
 		}
-		// Execute the multi fetch
-		$running = null;
-		do {
-			curl_multi_exec($mh, $running);
-		} while ( $running > 0 );
-		
-		// Done, close handles
-		foreach ( $this->requests as $key => $request ) {
-			$content = curl_multi_getcontent($request->handle);
-			$body = substr($content, strpos($content, "\r\n\r\n") + 4);
+		// Execute the request
+		$content = @curl_exec($request->handle);
+		$header = '';
+		$body = '';
+		// on redirects and such we get multiple headers back from curl it seems, we really only want the last one
+		while ( substr($content, 0, strlen('HTTP')) == 'HTTP' && strpos($content, "\r\n\r\n") !== false) {
 			$header = substr($content, 0, strpos($content, "\r\n\r\n"));
-			$httpCode = curl_getinfo($request->handle, CURLINFO_HTTP_CODE);
-			$contentType = curl_getinfo($request->handle, CURLINFO_CONTENT_TYPE);
-			$request->setHttpCode($httpCode);
-			$request->setContentType($contentType);
-			$request->setResponseHeaders($header);
-			$request->setResponseContent($body);
-			$request->setResponseSize(strlen($content));
-			curl_multi_remove_handle($mh, $request->handle);
-			unset($request->handle);
+			$body = substr($content, strlen($header) + 4);
+			$content = substr($content, strlen($header) + 4);
 		}
-		curl_multi_close($mh);
-		
-		$ret = $this->requests;
-		// empty our requests queue
-		$this->requests = array();
-		return $ret;
-	}
-	
-	public function pendingRequests()
-	{
-		return count($this->requests);
+		$httpCode = curl_getinfo($request->handle, CURLINFO_HTTP_CODE);
+		$contentType = curl_getinfo($request->handle, CURLINFO_CONTENT_TYPE);
+		if (!$httpCode) {
+			$httpCode = '404';
+		}
+		$request->setHttpCode($httpCode);
+		$request->setContentType($contentType);
+		$request->setResponseHeaders($header);
+		$request->setResponseContent($body);
+		$request->setResponseSize(strlen($content));
+		curl_close($request->handle);
+		unset($request->handle);		
+		return $request;
 	}
 }

Modified: incubator/shindig/trunk/php/gadgets/src/Gadget.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/Gadget.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/Gadget.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/Gadget.php Thu Mar  6 07:43:50 2008
@@ -18,76 +18,80 @@
  * 
  */
 
-final class GadgetId extends GadgetViewID {
-	private $uri;
-	private $moduleId;
-	
-	public function GadgetId($uri, $moduleId)
-	{
-		$this->uri = $uri;
-		$this->moduleId = $moduleId;
-	}
-	
-	public function getURI()
-	{
-		return $this->uri;
-	}
-	
-	public function getModuleId()
-	{
-		return $this->moduleId;
-	}
-	
-	public function getKey()
-	{
-		return $this->getURI();
-	}
-}
+/*
+ * In Java terms this would be the Gadget, GadgetView and GadgetSpec all rolled into one
+ * We combined it into one class since it makes more sense in PHP and provides a nice 
+ * speedup too.
+ */
 
-class Gadget extends GadgetSpec {
-	public $baseSpec;
+class GadgetException extends Exception {}
+
+class Gadget {
 	private $jsLibraries;
 	private $substitutions;
 	private $userPrefValues;
 	private $currentMessageBundle = array();
+	// As in UserPref, no enums so fake it
+	public $contentTypes    = array('HTML', 'URL');
+	public $id;
+	public $author;
+	public $authorEmail;
+	public $description;
+	public $directoryTitle;
+	public $contentType;
+	public $contentHref;
+	public $contentData = array();
+	public $localeSpecs = array();
+	public $preloads = array();
+	public $requires = array();
+	public $screenshot;
+	public $thumbnail;
+	public $title;
+	public $titleUrl = null;
+	public $userPrefs = array();
 	
-	public function __construct($id, GadgetSpec $baseSpec, $prefs)
+	public function __construct($id = false, $prefs = false)
 	{
-		$this->id = $id;
-		$this->baseSpec = $baseSpec;
+		if ($id) $this->id = $id;
+		if ($prefs) $this->userPrefValues = $prefs;
 		$this->substitutions = new Substitutions();
-		$this->userPrefValues = $prefs;
 		$this->jsLibraries = array();
 	}
 	
-	public function getAuthor()
+	public function setId($id)
 	{
-		return $this->substitutions->substitute($this->baseSpec->getAuthor());
+		$this->id = $id;
 	}
 	
-	public function getAuthorEmail()
+	public function setPrefs($prefs)
 	{
-		return $this->substitutions->substitute($this->baseSpec->getAuthorEmail());
+		$this->userPrefValues = $prefs;
 	}
 	
-	public function getBaseSpec()
+	public function getAuthor()
 	{
-		return $this->baseSpec;
+		return $this->substitutions->substitute($this->author);
 	}
 	
-	public function getContentData($view = false)
+	public function getAuthorEmail()
 	{
-		return $this->substitutions->substitute($this->baseSpec->getContentData($view));
+		return $this->substitutions->substitute($this->authorEmail);
 	}
-	
-	public function getContentHref()
+		
+	public function getContentData($view = false)
 	{
-		return $this->substitutions->substitute($this->baseSpec->getContentHref());
+		if ($this->contentType != 'HTML') {
+			throw new SpecParserException("getContentData() requires contentType HTML");
+		}
+		if (empty($view) || !$view) {
+			$view = DEFAULT_VIEW;
+		}
+		return $this->substitutions->substitute(isset($this->contentData[$view]) ? trim($this->contentData[$view]) : '');
 	}
 	
-	public function getContentType()
+	public function getContentHref()
 	{
-		return $this->baseSpec->getContentType();
+		return $this->substitutions->substitute($this->getContentType() == 'URL' ? $this->contentHref : null);
 	}
 	
 	public function getCurrentMessageBundle()
@@ -97,19 +101,14 @@
 	
 	public function getDescription()
 	{
-		return $this->substitutions->substitute($this->baseSpec->getDescription());
+		return $this->substitutions->substitute($this->description);
 	}
 	
 	public function getDirectoryTitle()
 	{
-		return $this->substitutions->substitute($this->baseSpec->getDirectoryTitle());
-	}
-	
-	public function getIcons()
-	{
-		return $this->baseSpec->getIcons();
+		return $this->substitutions->substitute($this->directoryTitle);
 	}
-	
+		
 	public function getId()
 	{
 		return $this->id;
@@ -127,7 +126,7 @@
 	
 	public function getLocaleSpecs()
 	{
-		return $this->baseSpec->getLocaleSpecs();
+		return $this->localeSpecs;
 	}
 	
 	public function getFeatureParams($gadget, $feature)
@@ -145,7 +144,7 @@
 	public function getPreloads()
 	{
 		$ret = array();
-		foreach ( $this->baseSpec->getPreloads() as $preload ) {
+		foreach ( $this->preloads as $preload ) {
 			$ret[] = $this->substitutions->substitute($preload);
 		}
 		return $ret;
@@ -153,12 +152,12 @@
 	
 	public function getRequires()
 	{
-		return $this->baseSpec->getRequires();
+		return $this->requires;
 	}
 	
 	public function getScreenshot()
 	{
-		return $this->substitutions->substitute($this->baseSpec->getScreenshot());
+		return $this->substitutions->substitute($this->screenshot);
 	}
 	
 	public function getSubstitutions()
@@ -168,26 +167,26 @@
 	
 	public function getThumbnail()
 	{
-		return $this->substitutions->substitute($this->baseSpec->getThumbnail());
+		return $this->substitutions->substitute($this->thumbnail);
 	}
 	
 	public function getTitle()
 	{
-		return $this->substitutions->substitute($this->baseSpec->getTitle());
+		return $this->substitutions->substitute($this->title);
 	}
 	
 	public function getTitleURI()
 	{
 		$ret = null;
-		if (($uri = $this->baseSpec->getTitleURI()) != null) {
-			$ret = $this->substitutions->substitute($uri);
+		if (!empty($this->titleURI)) {
+			$ret = $this->substitutions->substitute($this->titleURI);
 		}
 		return $ret;
 	}
 	
 	public function getUserPrefs()
 	{
-		return $this->baseSpec->getUserPrefs();
+		return $this->userPrefs;
 	}
 	
 	public function getUserPrefValues()
@@ -199,4 +198,104 @@
 	{
 		$this->currentMessageBundle = $messageBundle;
 	}
-}
\ No newline at end of file
+	
+	/* gadget Spec functions */
+	public function addContent($view, $data)
+	{
+		if (empty($view)) {
+			$view = DEFAULT_VIEW;
+		}
+		if (! isset($this->contentData[$view])) {
+			$this->contentData[$view] = '';
+		}
+		$this->contentData[$view] .= $data;
+	}
+				
+	public function getContentType()
+	{
+		return $this->contentType;
+	}
+}
+
+class LocaleSpec {
+	public $url;
+	public $locale;
+	public $rightToLeft;
+	
+	public function getURI()
+	{
+		return $this->url;
+	}
+	
+	public function getLocale()
+	{
+		return $this->locale;
+	}
+	
+	public function isRightToLeft()
+	{
+		return $this->rightToLeft;
+	}
+}
+
+class FeatureSpec {
+	public $name;
+	public $params = array();
+	public $optional;
+	
+	public function getName()
+	{
+		return $this->name;
+	}
+	
+	public function getParams()
+	{
+		return $this->params;
+	}
+	
+	public function isOptional()
+	{
+		return $this->optional;
+	}
+}
+
+class UserPref {
+	public $DataTypes = array('STRING', 'HIDDEN', 'BOOL', 'ENUM', 'LIST', 'NUMBER');
+	public $dataType;
+	public $name;
+	public $displayName;
+	public $defaultValue;
+	public $required;
+	public $enumValues;
+	public $contentType;
+	
+	public function getName()
+	{
+		return $this->name;
+	}
+	
+	public function getDisplayName()
+	{
+		return $this->displayName;
+	}
+	
+	public function getDefaultValue()
+	{
+		return $this->defaultValue;
+	}
+	
+	public function isRequired()
+	{
+		return $this->required;
+	}
+	
+	public function getDataType()
+	{
+		return $this->dataType;
+	}
+	
+	public function getEnumValues()
+	{
+		return $this->enumValues;
+	}
+}

Modified: incubator/shindig/trunk/php/gadgets/src/GadgetContext.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetContext.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetContext.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetContext.php Thu Mar  6 07:43:50 2008
@@ -26,16 +26,14 @@
 class GadgetContext {
 	private $httpFetcher;
 	private $locale;
-	private $options;
 	private $renderingContext;
 	private $registry;
 	
-	public function __construct(RemoteContent $httpFetcher, Locale $locale, $renderingContext, ProcessingOptions $options, GadgetFeatureRegistry $registry)
+	public function __construct(RemoteContent $httpFetcher, Locale $locale, $renderingContext, GadgetFeatureRegistry $registry)
 	{
 		$this->httpFetcher = $httpFetcher;
 		$this->locale = $locale;
 		$this->renderingContext = $renderingContext;
-		$this->options = $options;
 		$this->registry = $registry;
 	}
 	
@@ -58,10 +56,4 @@
 	{
 		return $this->registry;
 	}
-	
-	public function getOptions()
-	{
-		return $this->options;
-	}
-
 }

Modified: incubator/shindig/trunk/php/gadgets/src/GadgetFeatureRegistry.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetFeatureRegistry.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetFeatureRegistry.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetFeatureRegistry.php Thu Mar  6 07:43:50 2008
@@ -158,13 +158,3 @@
 	}
 }
 
-class NoOpFeature extends GadgetFeature {
-	
-	public function prepare($gadget, $context, $params)
-	{
-	}
-	
-	public function process($gadget, $context, $params)
-	{
-	}
-}

Added: incubator/shindig/trunk/php/gadgets/src/GadgetId.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetId.php?rev=634310&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetId.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetId.php Thu Mar  6 07:43:50 2008
@@ -0,0 +1,27 @@
+<?
+
+class GadgetId {
+	private $uri;
+	private $moduleId;
+	
+	public function GadgetId($uri, $moduleId)
+	{
+		$this->uri = $uri;
+		$this->moduleId = $moduleId;
+	}
+	
+	public function getURI()
+	{
+		return $this->uri;
+	}
+	
+	public function getModuleId()
+	{
+		return $this->moduleId;
+	}
+	
+	public function getKey()
+	{
+		return $this->getURI();
+	}
+}
\ No newline at end of file

Modified: incubator/shindig/trunk/php/gadgets/src/GadgetServer.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetServer.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetServer.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetServer.php Thu Mar  6 07:43:50 2008
@@ -30,11 +30,10 @@
 	private $gadgetId;
 	private $userPrefs;
 	private $renderingContext;
-	private $options;
 	private $locale;
 	private $httpFetcher;
 	
-	public function processGadget($gadgetId, $userPrefs, $locale, $rctx, $options, $httpFetcher, $registry)
+	public function processGadget($gadgetId, $userPrefs, $locale, $rctx, $httpFetcher, $registry)
 	{
 		global $config;
 		$this->gadgetId = $gadgetId;
@@ -42,9 +41,8 @@
 		$this->renderingContext = $rctx;
 		$this->locale = $locale;
 		$this->registry = $registry;
-		$this->options = $options;
 		$this->httpFetcher = $httpFetcher;
-		$this->gc = new GadgetContext($httpFetcher, $locale, $rctx, $options, $registry);
+		$this->gc = new GadgetContext($httpFetcher, $locale, $rctx, $registry);
 		$this->blacklist = new $config['blacklist_class']();
 		$gadget = $this->specLoad();
 		$this->featuresLoad($gadget);
@@ -57,13 +55,12 @@
 			throw new GadgetException("Gadget is blacklisted");
 		}
 		$request = new remoteContentRequest($this->gadgetId->getURI());
-		list($xml) = $this->httpFetcher->fetch($request, $this->options);
+		$xml = $this->httpFetcher->fetch($request);
 		if ($xml->getHttpCode() != '200') {
 			throw new GadgetException("Failed to retrieve gadget content");
 		}
 		$specParser = new GadgetSpecParser();
-		$spec = $specParser->parse($xml->getResponseContent());
-		$gadget = new Gadget($this->gadgetId, $spec, $this->userPrefs);
+		$gadget = $specParser->parse($xml->getResponseContent(), $this->gadgetId, $this->userPrefs);
 		return $gadget;
 	}
 	

Modified: incubator/shindig/trunk/php/gadgets/src/GadgetSpecParser.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetSpecParser.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetSpecParser.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetSpecParser.php Thu Mar  6 07:43:50 2008
@@ -18,11 +18,13 @@
  * 
  */
 
+class SpecParserException extends Exception {
+}
+
 class GadgetSpecParser {
 	//public function parse(GadgetId $id, String $xml)
-	public function parse($xml)
+	public function parse($xml, $id, $prefs)
 	{
-		$id = 1;
 		if (empty($xml)) {
 			throw new SpecParserException("Empty XML document");
 		}
@@ -33,29 +35,28 @@
 		if (count($doc->ModulePrefs) != 1) {
 			throw new SpecParserException("Missing or duplicated <ModulePrefs>");
 		}
-		$spec = new ParsedGadgetSpec();
-		$spec->id = $id;
+		$gadget = new Gadget($id, $prefs);
 		// process ModulePref attributes
-		$this->processModulePrefs($id, $spec, $doc->ModulePrefs);
+		$this->processModulePrefs($id, $gadget, $doc->ModulePrefs);
 		// process UserPrefs, if any
 		foreach ( $doc->UserPref as $pref ) {
-			$this->processUserPref($spec, $pref);
+			$this->processUserPref($gadget, $pref);
 		}
 		foreach ( $doc->Content as $content ) {
-			$this->processContent($spec, $content);
+			$this->processContent($gadget, $content);
 		}
 		//FIXME : should we add an else { throw new SpecParserException("Missing <Content> block"); } here ? Java version doesn't but it seems like we should ?
 		foreach ( $doc->ModulePrefs->Require as $feature ) {
-			$this->processFeature($spec, $feature, true);
+			$this->processFeature($gadget, $feature, true);
 		}
 		foreach ( $doc->ModulePrefs->Optional as $feature ) {
-			$this->processFeature($spec, $feature, false);
+			$this->processFeature($gadget, $feature, false);
 		}
 		//TODO java version has a todo here for parsing icons
-		return $spec;
+		return $gadget;
 	}
 	
-	private function processModulePrefs($id, &$spec, $ModulePrefs)
+	private function processModulePrefs($id, &$gadget, $ModulePrefs)
 	{
 		$attributes = $ModulePrefs->attributes();
 		if (empty($attributes['title'])) {
@@ -63,16 +64,16 @@
 		}
 		// Get ModulePrefs attributes
 		// (trim is used here since it not only cleans up the text, but also auto-casts the SimpleXMLElement to a string)
-		$spec->title = trim($attributes['title']);
-		$spec->author = isset($attributes['author']) ? trim($attributes['author']) : '';
-		$spec->authorEmail = isset($attributes['author_email']) ? trim($attributes['author_email']) : '';
-		$spec->description = isset($attributes['description']) ? trim($attributes['description']) : '';
-		$spec->directoryTitle = isset($attributes['directory_title']) ? trim($attributes['directory_title']) : '';
-		$spec->screenshot = isset($attributes['screenshot']) ? trim($attributes['screenshot']) : '';
-		$spec->thumbnail = isset($attributes['thumbnail']) ? trim($attributes['thumbnail']) : '';
-		$spec->titleUrl = isset($attributes['title_url']) ? trim($attributes['title_url']) : '';
+		$gadget->title = trim($attributes['title']);
+		$gadget->author = isset($attributes['author']) ? trim($attributes['author']) : '';
+		$gadget->authorEmail = isset($attributes['author_email']) ? trim($attributes['author_email']) : '';
+		$gadget->description = isset($attributes['description']) ? trim($attributes['description']) : '';
+		$gadget->directoryTitle = isset($attributes['directory_title']) ? trim($attributes['directory_title']) : '';
+		$gadget->screenshot = isset($attributes['screenshot']) ? trim($attributes['screenshot']) : '';
+		$gadget->thumbnail = isset($attributes['thumbnail']) ? trim($attributes['thumbnail']) : '';
+		$gadget->titleUrl = isset($attributes['title_url']) ? trim($attributes['title_url']) : '';
 		foreach ( $ModulePrefs->Locale as $locale ) {
-			$spec->localeSpecs[] = $this->processLocale($locale);
+			$gadget->localeSpecs[] = $this->processLocale($locale);
 		}
 	
 	}
@@ -85,7 +86,7 @@
 		$countryAttr = isset($attributes['country']) ? trim($attributes['country']) : 'all';
 		$rtlAttr = isset($attributes['language_direction']) ? trim($attributes['language_direction']) : '';
 		$rightToLeft = $rtlAttr == 'rtl';
-		$locale = new ParsedMessageBundle();
+		$locale = new LocaleSpec();
 		$locale->rightToLeft = $rightToLeft;
 		//FIXME java seems to use a baseurl here, probably for the http:// part but i'm not sure yet. Should verify behavior later to see if i got it right
 		$locale->url = $messageAttr;
@@ -93,10 +94,10 @@
 		return $locale;
 	}
 	
-	private function processUserPref(&$spec, $pref)
+	private function processUserPref(&$gadget, $pref)
 	{
 		$attributes = $pref->attributes();
-		$preference = new ParsedUserPref();
+		$preference = new UserPref();
 		if (empty($attributes['name'])) {
 			throw new SpecParserException("All UserPrefs must have name attributes.");
 		}
@@ -117,10 +118,10 @@
 				$preference->enumValues[$valueText] = $displayText;
 			}
 		}
-		$spec->userPrefs[] = $preference;
+		$gadget->userPrefs[] = $preference;
 	}
 	
-	private function processContent(&$spec, $content)
+	private function processContent(&$gadget, $content)
 	{
 		$attributes = $content->attributes();
 		if (empty($attributes['type'])) {
@@ -132,22 +133,22 @@
 				throw new SpecParserException("Malformed <Content> href value");
 			}
 			$url = trim($attributes['href']);
-			$spec->contentType = 'URL';
-			$spec->contentHref = $url;
+			$gadget->contentType = 'URL';
+			$gadget->contentHref = $url;
 		} else {
-			$spec->contentType = 'HTML';
+			$gadget->contentType = 'HTML';
 			$html = (string)$content; // no trim here since empty lines can have structural meaning, so typecast to string instead
 			$view = isset($attributes['view']) ? trim($attributes['view']) : '';
 			$views = explode(',', $view);
 			foreach ( $views as $view ) {
-				$spec->addContent($view, $html);
+				$gadget->addContent($view, $html);
 			}
 		}
 	}
 	
-	private function processFeature(&$spec, $feature, $required)
+	private function processFeature(&$gadget, $feature, $required)
 	{
-		$featureSpec = new ParsedFeatureSpec();
+		$featureSpec = new FeatureSpec();
 		$attributes = $feature->attributes();
 		if (empty($attributes['feature'])) {
 			throw new SpecParserException("Feature not specified in <" . (required ? "Required" : "Optional") . "> tag");
@@ -163,226 +164,6 @@
 			$value = trim($param);
 			$featureSpec->params[$name] = $value;
 		}
-		$spec->requires[$featureSpec->name] = $featureSpec;
+		$gadget->requires[$featureSpec->name] = $featureSpec;
 	}
 }
-
-class ParsedIcon extends Icon {
-	public $mode;
-	public $url;
-	public $type;
-	
-	public function getMode()
-	{
-		return $this->mode;
-	}
-	
-	public function getURI()
-	{
-		return $this->url;
-	}
-	
-	public function getType()
-	{
-		return $this->type;
-	}
-}
-
-class ParsedFeatureSpec extends FeatureSpec {
-	public $name;
-	public $params = array();
-	public $optional;
-	
-	public function getName()
-	{
-		return $this->name;
-	}
-	
-	public function getParams()
-	{
-		return $this->params;
-	}
-	
-	public function isOptional()
-	{
-		return $this->optional;
-	}
-}
-
-class ParsedUserPref extends UserPref {
-	public $name;
-	public $displayName;
-	public $defaultValue;
-	public $required;
-	public $enumValues;
-	public $contentType;
-	
-	public function getName()
-	{
-		return $this->name;
-	}
-	
-	public function getDisplayName()
-	{
-		return $this->displayName;
-	}
-	
-	public function getDefaultValue()
-	{
-		return $this->defaultValue;
-	}
-	
-	public function isRequired()
-	{
-		return $this->required;
-	}
-	
-	public function getDataType()
-	{
-		return $this->dataType;
-	}
-	
-	public function getEnumValues()
-	{
-		return $this->enumValues;
-	}
-}
-
-class ParsedMessageBundle extends LocaleSpec {
-	public $url;
-	public $locale;
-	public $rightToLeft;
-	
-	public function getURI()
-	{
-		return $this->url;
-	}
-	
-	public function getLocale()
-	{
-		return $this->locale;
-	}
-	
-	public function isRightToLeft()
-	{
-		return $this->rightToLeft;
-	}
-}
-
-class ParsedGadgetSpec extends GadgetSpec {
-	public $id;
-	public $author;
-	public $authorEmail;
-	public $description;
-	public $directoryTitle;
-	public $contentType;
-	public $contentHref;
-	public $contentData = array();
-	public $icons = array();
-	public $localeSpecs = array();
-	public $preloads = array();
-	public $requires = array();
-	public $screenshot;
-	public $thumbnail;
-	public $title;
-	public $titleUrl;
-	public $userPrefs = array();
-	
-	public function addContent($view, $data)
-	{
-		if (empty($view)) {
-			$view = DEFAULT_VIEW;
-		}
-		if (! isset($this->contentData[$view])) {
-			$this->contentData[$view] = '';
-		}
-		$this->contentData[$view] .= $data;
-	}
-	
-	public function getAuthor()
-	{
-		return $this->author;
-	}
-	
-	public function getAuthorEmail()
-	{
-		return $this->authorEmail;
-	}
-	
-	public function getContentData($view = false)
-	{
-		if ($this->contentType != 'HTML') {
-			throw new SpecParserException("getContentData() requires contentType HTML");
-		}
-		if (empty($view) || !$view) {
-			$view = DEFAULT_VIEW;
-		}
-		return isset($this->contentData[$view]) ? trim($this->contentData[$view]) : '';
-	}
-	
-	public function getContentHref()
-	{
-		return $this->getContentType() == 'URL' ? $this->contentHref : null;
-	}
-	
-	public function getContentType()
-	{
-		return $this->contentType;
-	}
-	
-	public function getDescription()
-	{
-		return $this->description;
-	}
-	
-	public function getDirectoryTitle()
-	{
-		return $this->directoryTitle;
-	}
-	
-	public function getIcons()
-	{
-		return $this->icons;
-	}
-	
-	public function getLocaleSpecs()
-	{
-		return $this->localeSpecs;
-	}
-	
-	public function getPreloads()
-	{
-		return $this->preloads;
-	}
-	
-	public function getRequires()
-	{
-		return $this->requires;
-	}
-	
-	public function getScreenshot()
-	{
-		return $this->screenshot;
-	}
-	
-	public function getThumbnail()
-	{
-		return $this->thumbnail;
-	}
-	
-	public function getTitle()
-	{
-		return $this->title;
-	}
-	
-	public function getTitleURI()
-	{
-		return $this->titleUrl;
-	}
-	
-	public function getUserPrefs()
-	{
-		return $this->userPrefs;
-	}
-}
-

Modified: incubator/shindig/trunk/php/gadgets/src/JsFeatureLoader.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/JsFeatureLoader.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/JsFeatureLoader.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/JsFeatureLoader.php Thu Mar  6 07:43:50 2008
@@ -30,10 +30,7 @@
 		// so the caching of the dep loading just about doubles our performance :)
 		// Only downside is that if you modify the features directory, your have to clean the cache too
 		$cache = new $config['data_cache']();
-		if (($deps = $cache->get(md5($path))) === false) {
-			$deps = $this->loadFiles($path, $deps);
-			$cache->set(md5($path), $deps);
-		}
+		$deps = $this->loadFiles($path, $deps);
 		// This ensures that we register everything in the right order.
 		foreach ( $deps as $entry ) {
 			$feature = $entry;
@@ -124,7 +121,6 @@
 				// inline content
 				$type = 'INLINE';
 				$content = (string)$script;
-			
 			} else {
 				$content = trim($attributes['src']);
 				if (strtolower(substr($content, 0, strlen("http://"))) == "http://") {
@@ -137,7 +133,7 @@
 					$content = $feature->basePath.'/'.$content;
 				}
 			}
-			$library = jsLibrary::create($type, $content);
+			$library = JsLibrary::create($type, $content);
 			if ($library != null) {
 				if ($isContainer) {
 					$feature->containerJs[] = $library;

Modified: incubator/shindig/trunk/php/gadgets/src/JsLibrary.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/JsLibrary.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/JsLibrary.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/JsLibrary.php Thu Mar  6 07:43:50 2008
@@ -18,7 +18,7 @@
  * 
  */
 
-class jsLibrary {
+class JsLibrary {
 	private $types = array('FILE', 'RESOURCE', 'URL', 'INLINE');
 	private $type;
 	private $content;
@@ -51,7 +51,7 @@
 	static function create($type, $content)
 	{
 		if ($type == 'FILE' || $type == 'RESOURCE') {
-			$content = jsLibrary::loadData($content, $type);
+			$content = JsLibrary::loadData($content, $type);
 		}
 		return new JsLibrary($type, $content);
 	}
@@ -60,7 +60,7 @@
 	{
 		// we don't really do 'resources', so limiting this to files only
 		if ($type == 'FILE') {
-			return jsLibrary::loadFile($name);
+			return JsLibrary::loadFile($name);
 		}
 		return null;
 	}
@@ -80,7 +80,7 @@
 			throw new Exception("JsLibrary file not readable: $fileName");
 		}
 		if (!($content = @file_get_contents($fileName))) {
-			throw new Exception("jsLibrary error reading file: $fileName");
+			throw new Exception("JsLibrary error reading file: $fileName");
 		}
 		return $content;
 	}

Added: incubator/shindig/trunk/php/gadgets/src/Locale.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/Locale.php?rev=634310&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/Locale.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/Locale.php Thu Mar  6 07:43:50 2008
@@ -0,0 +1,30 @@
+<?
+
+// Locale class doesn't exist in php, so to allow the code base to be closer to the java one, were faking one
+class Locale {
+	public $language;
+	public $country;
+	
+	public function __construct($language, $country)
+	{
+		$this->language = $language;
+		$this->country = $country;
+	}
+	public function equals($obj)
+	{
+		if (!($obj instanceof Locale)) {
+			return false;
+		}
+		return ($obj->language == $this->language && $obj->country == $this->country);
+	}
+	
+	public function getLanguage()
+	{
+		return $this->language;
+	}
+	
+	public function getCountry()
+	{
+		return $this->country;
+	}
+}
\ No newline at end of file

Modified: incubator/shindig/trunk/php/gadgets/src/MessageBundleSubstituter.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/MessageBundleSubstituter.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/MessageBundleSubstituter.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/MessageBundleSubstituter.php Thu Mar  6 07:43:50 2008
@@ -65,7 +65,7 @@
 				// We definitely need a bundle, now we need to fetch it.
 				// Doing it a little different then the java version since our fetcher and cache are intergrated
 				$fetcher = $context->getHttpFetcher();
-				list($response) = $fetcher->fetch(new remoteContentRequest($uri), $context->getOptions());
+				$response = $fetcher->fetch(new remoteContentRequest($uri));
 				//TODO caching the parsed bundle instead of just the xml data would be a lot more efficient and speedy
 				$this->bundle = $this->parser->parse($response->getResponseContent());				
 			}

Modified: incubator/shindig/trunk/php/gadgets/src/RemoteContent.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/RemoteContent.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/RemoteContent.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/RemoteContent.php Thu Mar  6 07:43:50 2008
@@ -26,6 +26,9 @@
  * it's kept in the spirit of the java variant as much as possible
  */
 
+class RemoteContentException extends Exception {
+}
+
 abstract class RemoteContent {
-	abstract public function fetch($requests, $options);
+	abstract public function fetch($request);
 }

Modified: incubator/shindig/trunk/php/gadgets/src/RemoteContentFetcher.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/RemoteContentFetcher.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/RemoteContentFetcher.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/RemoteContentFetcher.php Thu Mar  6 07:43:50 2008
@@ -19,8 +19,5 @@
  */
 
 abstract class RemoteContentFetcher {
-	abstract public function addRequests($requests);
-	abstract public function addRequest(remoteContentRequest $request);
-	abstract public function fetchRequests();
-	abstract public function pendingRequests();
+	abstract public function fetchRequest($request);
 }

Modified: incubator/shindig/trunk/php/gadgets/src/RemoteContentRequest.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/RemoteContentRequest.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/RemoteContentRequest.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/RemoteContentRequest.php Thu Mar  6 07:43:50 2008
@@ -39,10 +39,10 @@
 	}
 	
 	// returns a hash code which identifies this request, used for caching
-	// takes url, headers and postbody into account for constructing the md5 checksum
+	// takes url and postbody into account for constructing the sha1 checksum
 	public function toHash()
 	{
-		return md5($this->url . $this->headers . $this->postBody);
+		return sha1($this->url . $this->postBody);
 	}
 	
 	public function getContentType()
@@ -77,7 +77,7 @@
 	
 	public function isPost()
 	{
-		return ! empty($this->postBody);
+		return ($this->postBody != false);
 	}
 	
 	public function hasHeaders()
@@ -97,7 +97,7 @@
 	
 	public function setContentType($type)
 	{
-		$this->contentType;
+		$this->contentType = $type;
 	}
 	
 	public function setHttpCode($code)

Modified: incubator/shindig/trunk/php/gadgets/src/Substitutions.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/Substitutions.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/Substitutions.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/Substitutions.php Thu Mar  6 07:43:50 2008
@@ -30,14 +30,14 @@
 	
 	public function __construct()
 	{
-		foreach ($this->types as $key => $type) {
+		foreach ($this->types as $type) {
 			$this->substitutions[$type] = array();
 		}
 	}
 
 	public function addSubstitution($type, $key, $value)
 	{
-		$this->substitutions[$type][$key] = $value;
+		$this->substitutions[$type]["__{$type}_{$key}__"] = $value;
 	}
 	
 	public function addSubstitutions($type, $array)
@@ -49,7 +49,7 @@
 	
 	public function substitute($input)
 	{
-		foreach ($this->types as $key => $type) {
+		foreach ($this->types as $type) {
 			$input = $this->substituteType($type, $input);
 		}
 		return $input;
@@ -57,22 +57,6 @@
 	
 	public function substituteType($type, $input)
 	{
-		$prefix = "__{$type}_";
-		if (empty($input) || (count($this->substitutions[$type]) == 0) || (strpos($input, $prefix) === false)) {
-			return $input;
-		}
-		while (($start = strpos($input, $prefix) + strlen($prefix)) !== false) {
-			$end   = strpos($input, '__', $start);
-			if ($end !== false) {
-				$name = substr($input, $start, $end - $start);
-				if (isset($this->substitutions[$type][$name])) {
-					$replacement = $this->substitutions[$type][$name];
-					$input       = str_replace("{$prefix}{$name}__", $replacement, $input);
-				}
-			} else {
-				break;
-			}
-		}
-		return $input;
+		return str_replace(array_keys($this->substitutions[$type]), array_values($this->substitutions[$type]), $input); 
 	}
 }

Modified: incubator/shindig/trunk/php/gadgets/src/http/GadgetRenderingServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/http/GadgetRenderingServlet.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/http/GadgetRenderingServlet.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/http/GadgetRenderingServlet.php Thu Mar  6 07:43:50 2008
@@ -18,14 +18,9 @@
  * 
  */
 
-include_once ('src/UserPrefs.php');
-include_once ('src/Gadget.php');
-include_once ('src/GadgetException.php');
-include_once ('src/GadgetServer.php');
-include_once ('src/GadgetSpecParser.php');
-include_once ('src/GadgetFeatureRegistry.php');
-include_once ('src/HttpProcessingOptions.php');
-include_once ("src/{$config['remote_content']}.php");
+include ('src/Gadget.php');
+
+define('DEFAULT_VIEW', 'default');
 
 class GadgetRenderingServlet extends HttpServlet {
 	
@@ -38,18 +33,23 @@
 			}
 			$url = trim($_GET['url']);
 			$moduleId = isset($_GET['mid']) && is_numeric($_GET['mid']) ? intval($_GET['mid']) : 0;
-			$options = new HttpProcessingOptions();
 			$httpFetcher = new $config['remote_content']();
 			$view = ! empty($_GET['view']) ? $_GET['view'] : DEFAULT_VIEW;
 			$gadgetId = new GadgetId($url, $moduleId);
 			$prefs = $this->getPrefsFromRequest();
 			$locale = $this->getLocaleFromRequest();
-			$registry = new GadgetFeatureRegistry($config['features_path']);
+			$cache = new $config['data_cache']();
+			// Profiling showed 40% of the processing time was spend in the feature registry
+			// So by caching this and making it a one time initialization, we almost double the performance  
+			if (! ($registry = $cache->get(sha1($config['features_path'])))) {
+				$registry = new GadgetFeatureRegistry($config['features_path']);
+				$cache->set(sha1($config['features_path']), $registry);
+			}
 			// skipping the contentFilters bit, since there's no way to include caja yet
 			// hopefully a rpc service or command line version will be available at some point
 			$gadgetServer = new GadgetServer();
-			$gadget = $gadgetServer->processGadget($gadgetId, $prefs, $locale, 'GADGET', $options, $httpFetcher, $registry);
-			$this->outputGadget($gadget, $view, $options);
+			$gadget = $gadgetServer->processGadget($gadgetId, $prefs, $locale, 'GADGET', $httpFetcher, $registry);
+			$this->outputGadget($gadget, $view);
 		} catch ( Exception $e ) {
 			$this->outputError($e);
 		}
@@ -62,26 +62,26 @@
 		echo "<h1>Error</h1>";
 		echo $e->getMessage();
 		if ($config['debug']) {
-			echo "<p><b>Debug info:</b></p><div style='overflow:auto; height:300px; border:1px solid #000000'><pre>";
+			echo "<p><b>Debug backtrace (set debug to false in the config to disable this)</b></p><div style='overflow:auto; height:300px; border:1px solid #000000'><pre>";
 			print_r(debug_backtrace());
 			echo "</pre></div>>";
 		}
 		echo "</body></html>";
 	}
 	
-	private function outputGadget($gadget, $view, $options)
+	private function outputGadget($gadget, $view)
 	{
 		switch ( $gadget->getContentType()) {
 			case 'HTML' :
-				$this->outputHtmlGadget($gadget, $view, $options);
+				$this->outputHtmlGadget($gadget, $view);
 				break;
 			case 'URL' :
-				$this->outputUrlGadget($gadget, $options);
+				$this->outputUrlGadget($gadget);
 				break;
 		}
 	}
 	
-	private function outputHtmlGadget($gadget, $view, $options)
+	private function outputHtmlGadget($gadget, $view)
 	{
 		global $config;
 		$this->setContentType("text/html; charset=UTF-8");
@@ -93,7 +93,7 @@
 		$externJs = "";
 		$inlineJs = "";
 		$externFmt = "<script src=\"%s\"></script>";
-		$forcedLibs = $options->getForcedJsLibs();
+		$forcedLibs = $config['focedJsLibs'];
 		foreach ( $gadget->getJsLibraries() as $library ) {
 			$type = $library->getType();
 			if ($type == 'URL') {
@@ -107,7 +107,7 @@
 				if ($forcedLibs == null) {
 					$inlineJs .= $library->getContent() . "\n";
 				}
-				// otherwise it was already included by options.forceJsLibs.
+				// otherwise it was already included by config.forceJsLibs.
 			}
 		}
 		// Forced libs first.
@@ -123,13 +123,13 @@
 			$output .= $externJs;
 		}
 		//FIXME quick hack to make it work with the new syndicator.js config, needs a propper implimentation later
-		if (!file_exists($config['syndicator_config']) || !is_readable($config['syndicator_config'])) {
+		if (! file_exists($config['syndicator_config']) || ! is_readable($config['syndicator_config'])) {
 			throw new GadgetException("Invalid syndicator config");
 		}
 		// remove both /* */ and // style comments, they crash the json_decode function
-		$contents = preg_replace('/\/\/.*$/m','',preg_replace('@/\\*(?:.|[\\n\\r])*?\\*/@', '', file_get_contents($config['syndicator_config'])));
+		$contents = preg_replace('/\/\/.*$/m', '', preg_replace('@/\\*(?:.|[\\n\\r])*?\\*/@', '', file_get_contents($config['syndicator_config'])));
 		$syndData = json_decode($contents, true);
-		$output .= '<script>gadgets.config.init('.json_encode($syndData['gadgets.features']).');</script>';
+		$output .= '<script>gadgets.config.init(' . json_encode($syndData['gadgets.features']) . ');</script>';
 		$gadgetExceptions = array();
 		$content = $gadget->getContentData($view);
 		if (empty($content)) {
@@ -145,8 +145,9 @@
 		echo $output;
 	}
 	
-	private function outputUrlGadget($gadget, $options)
+	private function outputUrlGadget($gadget)
 	{
+		global $config;
 		// Preserve existing query string parameters.
 		$redirURI = $gadget->getContentHref();
 		$queryStr = strpos($redirURI, '?') !== false ? substr($redirURI, strpos($redirURI, '?')) : '';
@@ -154,7 +155,7 @@
 		// TODO: userprefs on the fragment rather than query string
 		$query .= $this->getPrefsQueryString($gadget->getUserPrefValues());
 		$libs = array();
-		$forcedLibs = $options->getForcedJsLibs();
+		$forcedLibs = $config['focedJsLibs'];
 		if ($forcedLibs == null) {
 			$reqs = $gadget->getRequires();
 			foreach ( $reqs as $key => $val ) {
@@ -163,7 +164,7 @@
 		} else {
 			$libs = explode(':', $forcedLibs);
 		}
-		$query .= $this->appendLibsToQuery($libs);
+		$query .= $this->appendLibsToQuery($libs, $gadget);
 		// code bugs out with me because of the invalid url syntax since we dont have a URI class to fix it for us
 		// this works around that
 		if (substr($query, 0, 1) == '&') {
@@ -174,12 +175,13 @@
 		die();
 	}
 	
-	private function appendLibsToQuery($libs)
+	private function appendLibsToQuery($libs, $gadget)
 	{
+		global $config;
 		$ret = "&";
-		$ret .= LIBS_PARAM_NAME;
+		$ret .= $config['libs_param_name'];
 		$ret .= "=";
-		$ret .= $this->getJsUrl($libs);
+		$ret .= $this->getJsUrl($libs, $gadget);
 		return $ret;
 	}
 	
@@ -197,8 +199,9 @@
 		return $ret;
 	}
 	
-	private function getJsUrl($libs)
+	private function getJsUrl($libs, $gadget)
 	{
+		global $config;
 		$buf = '';
 		if (! is_array($libs) || ! count($libs)) {
 			$buf = 'core';
@@ -213,8 +216,16 @@
 				$buf .= $lib;
 			}
 		}
-		//FIXME add sha1 / md5 checksum of all js content as unique key as 'version'
-		$buf .= ".js?v=";
+		// Build a version string from the sha1() checksum of all included javascript
+		// to ensure the client always has the right version
+		$inlineJs = '';
+		foreach ( $gadget->getJsLibraries() as $library ) {
+			$type = $library->getType();
+			if ($type != 'URL') {
+				$inlineJs .= $library->getContent() . "\n";
+			}
+		}
+		$buf .= ".js?v=" . sha1($inlineJs);
 		return $buf;
 	}
 	

Modified: incubator/shindig/trunk/php/gadgets/src/http/HttpServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/http/HttpServlet.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/http/HttpServlet.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/http/HttpServlet.php Thu Mar  6 07:43:50 2008
@@ -31,6 +31,7 @@
 	private $lastModified = false;
 	private $contentType = 'text/html';
 	private $charset = 'UTF-8';
+	public  $noHeaders = false;
 	
 	public function __construct()
 	{
@@ -40,47 +41,49 @@
 	
 	public function __destruct()
 	{
-		die();
-		// attempt at some propper header handling from php
-		// this departs a little from the shindig code but it should give is valid http protocol handling
-		header("Content-Type: $this->contentType; charset={$this->charset}");
-		header('Connection: Keep-Alive');
-		header('Keep-Alive: timeout=15, max=30');
-		header('Accept-Ranges: bytes');
-		header('Content-Length: ' . ob_get_length());
-		header('Cache-Control: public,max-age=' . CACHE_TIME . ',must-revalidate');
-		header("Expires: " . gmdate("D, d M Y H:i:s", time() + CACHE_TIME) . " GMT");
-		$content = ob_get_clean();
-		// Obey browsers (or proxy's) request to send a fresh copy if we recieve a no-cache pragma or cache-control request
-		if (! isset($_SERVER['HTTP_PRAGMA']) || ! strstr(strtolower($_SERVER['HTTP_PRAGMA']), 'no-cache') && (! isset($_SERVER['HTTP_CACHE_CONTROL']) || ! strstr(strtolower($_SERVER['HTTP_CACHE_CONTROL']), 'no-cache'))) {
-			// If the browser send us a E-TAG check if it matches (sha1 sum of content), if so send a not modified header instead of content
-			$etag = md5($content);
-			if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $etag) {
-				header("ETag: \"$etag\"");
-				if ($this->lastModified) {
-					header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $this->lastModified));
-				}
-				header("HTTP/1.1 304 Not Modified");
-				header('Content-Length: 0');
-				die();
-			}
-			header("ETag: \"$etag\"");
-			// If no etag is present, then check if maybe this browser supports if_modified_since tags,
-			// check it against our lastModified (if it's set)
-			if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $this->lastModified && ! isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
-				$if_modified_since = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
-				if ($this->lastModified <= $if_modified_since) {
-					header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $this->lastModified));
+		global $config;
+		if (!$this->noHeaders) {
+			// attempt at some propper header handling from php
+			// this departs a little from the shindig code but it should give is valid http protocol handling
+			header("Content-Type: $this->contentType; charset={$this->charset}");
+			header('Connection: Keep-Alive');
+			header('Keep-Alive: timeout=15, max=30');
+			header('Accept-Ranges: bytes');
+			header('Content-Length: ' . ob_get_length());
+			header('Cache-Control: public,max-age=' . $config['cache_time'] . ',must-revalidate');
+			header("Expires: " . gmdate("D, d M Y H:i:s", time() + $config['cache_time']) . " GMT");
+			$content = ob_get_clean();
+			// Obey browsers (or proxy's) request to send a fresh copy if we recieve a no-cache pragma or cache-control request
+			if (! isset($_SERVER['HTTP_PRAGMA']) || ! strstr(strtolower($_SERVER['HTTP_PRAGMA']), 'no-cache') && (! isset($_SERVER['HTTP_CACHE_CONTROL']) || ! strstr(strtolower($_SERVER['HTTP_CACHE_CONTROL']), 'no-cache'))) {
+				// If the browser send us a E-TAG check if it matches (sha1 sum of content), if so send a not modified header instead of content
+				$etag = sha1($content);
+				if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $etag) {
+					header("ETag: \"$etag\"");
+					if ($this->lastModified) {
+						header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $this->lastModified));
+					}
 					header("HTTP/1.1 304 Not Modified");
 					header('Content-Length: 0');
 					die();
 				}
+				header("ETag: \"$etag\"");
+				// If no etag is present, then check if maybe this browser supports if_modified_since tags,
+				// check it against our lastModified (if it's set)
+				if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $this->lastModified && ! isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
+					$if_modified_since = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
+					if ($this->lastModified <= $if_modified_since) {
+						header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $this->lastModified));
+						header("HTTP/1.1 304 Not Modified");
+						header('Content-Length: 0');
+						die();
+					}
+				}
+				if ($this->lastModified) {
+					header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $this->lastModified));
+				}
 			}
-			if ($this->lastModified) {
-				header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $this->lastModified));
-			}
+			echo $content;
 		}
-		echo $content;
 	}
 	
 	public function setContentType($type)

Modified: incubator/shindig/trunk/php/gadgets/src/http/JsServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/http/JsServlet.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/http/JsServlet.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/http/JsServlet.php Thu Mar  6 07:43:50 2008
@@ -23,6 +23,7 @@
 	public function doGet()
 	{
 		global $config;
+		$this->noHeaders = true;
 		if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
 			header("HTTP/1.1 304 Not Modified");
 			header('Content-Length: 0');

Modified: incubator/shindig/trunk/php/gadgets/src/http/ProxyHandler.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/http/ProxyHandler.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/http/ProxyHandler.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/http/ProxyHandler.php Thu Mar  6 07:43:50 2008
@@ -20,9 +20,6 @@
 
 include_once ("src/{$config['gadget_token']}.php");
 include_once ("src/{$config['gadget_signer']}.php");
-include_once ("src/HttpProcessingOptions.php");
-
-//TODO make sure this all works, especially the header passthru and post parts
 
 // according to features/core/io.js, this is high on the list of things to scrap
 define('UNPARSEABLE_CRUFT', "throw 1; < don't be evil' >");
@@ -35,85 +32,107 @@
 		$this->fetcher = $fetcher;
 	}
 	
-	public function fetchJson($signer, $method)
+	public function fetchJson($url, $signer, $method)
 	{
 		$token = $this->extractAndValidateToken($signer);
-		$url = $_GET['url'];
 		$originalUrl = $this->validateUrl($url);
 		$signedUrl = $this->signUrl($originalUrl, $token);
 		// Fetch the content and convert it into JSON.
 		// TODO: Fetcher needs to handle variety of HTTP methods.
-		$result = $this->fetchContent($signedUrl, new HttpProcessingOptions(), $method);
+		$result = $this->fetchContent($signedUrl, $method);
 		$status = (int)$result->getHttpCode();
-		header("HTTP/1.1 $status", true);
+		//header("HTTP/1.1 $status", true);
 		if ($status == 200) {
 			$output = '';
-			$json = array('body' => $result->getResponseContent(), 'rc' => $status, 'url' => $url);
+			$json = array($url => array('body' => $result->getResponseContent(), 'rc' => $status));
 			$json = json_encode($json);
 			$output = UNPARSEABLE_CRUFT . $json;
 			$this->setCachingHeaders();
-			header("application/json; charset=utf-8");
-			header("Content-Disposition", "attachment;filename=p.txt");
+			header("application/json; charset=utf-8", true);
 			echo $output;
+		} else {
+			@ob_end_clean();
+			header("HTTP/1.0 404 Not Found", true);
+			echo "<html><body><h1>404 - Not Found</h1></body></html>";
 		}
+		die();
 	}
 	
-	public function fetch($signer, $method)
+	public function fetch($url, $signer, $method)
 	{
 		$token = $this->extractAndValidateToken($signer);
-		$originalUrl = $this->validateUrl($_GET['url']);
+		$originalUrl = $this->validateUrl($url);
 		$signedUrl = $this->signUrl($originalUrl, $token);
 		//TODO: Fetcher needs to handle variety of HTTP methods.
-		$result = $this->fetchContent($signedUrl, new HttpProcessingOptions(), $method);
+		$result = $this->fetchContent($signedUrl, $method);
 		// TODO: Fetcher needs to handle variety of HTTP methods.
 		$status = (int)$result->getHttpCode();
-		header("HTTP/1.1 $status", true);
 		if ($status == 200) {
 			$headers = explode("\n", $result->getResponseHeaders());
 			foreach ( $headers as $header ) {
-				header($header);
+				if (strpos($header, ':')) {
+					$key = trim(substr($header, 0, strpos($header, ':')));
+					$val = trim(substr($header, strpos($header, ':') + 1));
+					if (strcasecmp($key, "Transfer-Encoding") != 0 && strcasecmp($key, "Cache-Control") != 0 && strcasecmp($key, "Expires") != 0 && strcasecmp($key, "Content-Length") != 0) {
+						header("$key: $val");
+					}
+				}
 			}
 			$this->setCachingHeaders();
 			// then echo the content
 			echo $result->getResponseContent();
+		} else {
+			@ob_end_clean();
+			header("HTTP/1.0 404 Not Found", true);
+			echo "<html><body><h1>404 - Not Found ($status)</h1>";
+			echo "</body></html>";
 		}
+		// make sure the HttpServlet destructor doesn't override ours
+		die();
 	}
 	
-	private function fetchContent($signedUrl, $procOptions, $method)
+	private function fetchContent($signedUrl, $method)
 	{
 		//TODO get actual character encoding from the request
 
 		// Extract the request headers from the $_SERVER super-global (this -does- unfortunatly mean that any header that php doesn't understand won't be proxied thru though)
 		// if this turns out to be a problem we could add support for HTTP_RAW_HEADERS, but this depends on a php.ini setting, so i'd rather prevent that from being required
 		$headers = '';
-		foreach ( $_SERVER as $key => $val ) {
-			if (substr($key, 0, strlen('HTTP_')) == 'HTTP_') {
-				// massage the header key to something a bit more propper (example 'HTTP_ACCEPT_LANGUAGE' becomes 'Accept-Language')
-				// TODO: We probably need to test variations as well.
-				$key = str_replace(' ', '_', ucwords(strtolower(str_replace('-', ' ', substr($key, strlen('HTTP_'))))));
-				if ($key != 'Keep_alive' && $key != 'Connection' && $key != 'Host' && $key != 'Accept' && $key != 'Accept-Encoding') {
-					// propper curl header format according to http://www.php.net/manual/en/function.curl-setopt.php#80099
-					$headers .= "$key: $val\n";
-				}
+		$requestHeaders = $this->request_headers();
+		foreach ( $requestHeaders as $key => $val ) {
+			if ($key != 'Keep-alive' && $key != 'Connection' && $key != 'Host' && $key != 'Accept' && $key != 'Accept-Encoding') {
+				// propper curl header format according to http://www.php.net/manual/en/function.curl-setopt.php#80099
+				$headers .= "$key: $val\n";
 			}
 		}
 		if ($method == 'POST') {
+			$data = isset($_GET['postData']) ? $_GET['postData'] : false;
+			if (! $data) {
+				$data = isset($_POST['postData']) ? $_POST['postData'] : false;
+			}
 			$postData = '';
-			$first = true;
-			foreach ( $_POST as $key => $val ) {
-				if (! $first) {
-					$postData .= '&';
-				} else {
-					$first = false;
+			if ($data) {
+				$data = urldecode($data);
+				$entries = explode('&', $data);
+				foreach ( $entries as $entry ) {
+					$parts = explode('=', $entry);
+					// Process only if its a valid value=something pair
+					if (count($parts) == 2) {
+						$postData .= urlencode($parts[0]) . '=' . urlencode($parts[1]) . '&';
+					}
+				}
+				// chop of the trailing &
+				if (strlen($postData)) {
+					$postData = substr($postData, 0, strlen($postData) - 1);
 				}
-				// make sure all the keys and val's are propperly encoded
-				$postData .= urlencode(urldecode($key)) . '=' . urlencode(urldecode($val));
 			}
+			// even if postData is an empty string, it will still post (since RemoteContentRquest checks if its false)
+			// so the request to POST is still honored
 			$request = new RemoteContentRequest($signedUrl, $headers, $postData);
-			list($request) = $this->fetcher->fetch($request, $procOptions);
+			$request = $this->fetcher->fetch($request);
 		} else {
 			$request = new RemoteContentRequest($signedUrl, $headers);
-			list($request) = $this->fetcher->fetch($request, $procOptions);
+			$request = $this->fetcher->fetch($request);
 		}
 		return $request;
 	}
@@ -121,8 +140,8 @@
 	private function setCachingHeaders()
 	{
 		// TODO: Re-implement caching behavior if appropriate.
-		header("Cache-Control", "private; max-age=0");
-		header("Expires", time() - 30);
+		header("Cache-Control: private; max-age=0", true);
+		header("Expires: " . gmdate("D, d M Y H:i:s", time() - 3000) . " GMT", true);
 	}
 	
 	private function validateUrl($url)
@@ -136,17 +155,45 @@
 		if ($signer == null) {
 			return null;
 		}
-		$token = isset($_GET["st"]) ? $_GET["st"] : '';
+		$token = isset($_GET["st"]) ? $_GET["st"] : false;
+		if ($token) {
+			$token = isset($_POST['st']) ? $_POST['st'] : '';
+		}
 		return $signer->createToken($token);
 	}
 	
 	private function signUrl($originalUrl, $token)
 	{
-		if ($token == null || (isset($_GET['authz']) && $_GET['authz'] != 'signed')) {
+		$authz = isset($_GET['authz']) ? $_GET['authz'] : false;
+		if (! $authz) {
+			$authz = isset($_POST['authz']) ? $_POST['authz'] : '';
+		}
+		if ($token == null || $authz != 'signed') {
 			return $originalUrl;
 		}
-		$method = isset($_GET['httpMethod']) ? $_GET['httpMethod'] : 'GET';
+		$method = isset($_GET['httpMethod']) ? $_GET['httpMethod'] : false;
+		if ($method) {
+			$method = isset($_POST['httpMethod']) ? $_POST['httpMethod'] : 'GET';
+		}
 		return $token->signUrl($originalUrl, $method);
 	}
-
+	
+	function request_headers()
+	{
+		// Try to use apache's request headers if available
+		if (function_exists("apache_request_headers")) {
+			if (($headers = apache_request_headers())) {
+				return $headers;
+			}
+		}
+		// if that failed, try to create them from the _SERVER superglobal
+		$headers = array();
+		foreach ( array_keys($_SERVER) as $skey ) {
+			if (substr($skey, 0, 5) == "HTTP_") {
+				$headername = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($skey, 0, 5)))));
+				$headers[$headername] = $_SERVER[$skey];
+			}
+		}
+		return $headers;
+	}
 }

Modified: incubator/shindig/trunk/php/gadgets/src/http/ProxyServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/http/ProxyServlet.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/http/ProxyServlet.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/http/ProxyServlet.php Thu Mar  6 07:43:50 2008
@@ -23,10 +23,22 @@
 
 class ProxyServlet extends HttpServlet {
 	
-	public function doGet($method = 'GET')
+	public function doGet()
 	{
 		global $config;
-		if (empty($_GET['url'])) {
+		$this->noHeaders = true;	
+		// those should be doable in one statement, but php seems to still evauluate the second ? and : pair,
+		// so throws an error about undefined index on post, even though it found it in get ... odd bug 
+		$url = isset($_GET['url']) ? $_GET['url'] : false;
+		if (!$url) {
+			$url = isset($_POST['url']) ? $_POST['url'] : false;
+		}
+		$url = urldecode($url);
+		$method = isset($_GET['httpMethod']) ? $_GET['httpMethod'] : false;
+		if (!$method) {
+			$method = isset($_POST['httpMethod']) ? $_POST['httpMethod'] : 'GET'; 
+		}
+		if (!$url) {
 			header("HTTP/1.0 400 Bad Request", true);
 			echo "<html><body><h1>400 - Missing url parameter</h1></body></html>";
 		}
@@ -34,14 +46,14 @@
 		$httpFetcher = new $config['remote_content']();
 		$proxyHandler = new ProxyHandler($httpFetcher);
 		if (! empty($_GET['output']) && $_GET['output'] == 'js') {
-			$proxyHandler->fetchJson($gadgetSigner, $method);
+			$proxyHandler->fetchJson($url, $gadgetSigner, $method);
 		} else {
-			$proxyHandler->fetch($gadgetSigner, $method);
+			$proxyHandler->fetch($url, $gadgetSigner, $method);
 		}
 	}
 	
 	public function doPost()
 	{
-		$this->doGet('POST');
+		$this->doGet();
 	}
 }