You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by ch...@apache.org on 2008/06/13 19:05:58 UTC

svn commit: r667596 - in /incubator/shindig/trunk/php/src: common/ gadgets/ gadgets/http/ gadgets/oauth/

Author: chabotc
Date: Fri Jun 13 10:05:57 2008
New Revision: 667596

URL: http://svn.apache.org/viewvc?rev=667596&view=rev
Log:
SHINDIG-359 Adds support for preloading resources, and authenticated preloading (0.8 feature)

Added:
    incubator/shindig/trunk/php/src/gadgets/Auth.php
    incubator/shindig/trunk/php/src/gadgets/Preload.php
Modified:
    incubator/shindig/trunk/php/src/common/RemoteContentRequest.php
    incubator/shindig/trunk/php/src/gadgets/Gadget.php
    incubator/shindig/trunk/php/src/gadgets/GadgetContext.php
    incubator/shindig/trunk/php/src/gadgets/GadgetServer.php
    incubator/shindig/trunk/php/src/gadgets/GadgetSpecParser.php
    incubator/shindig/trunk/php/src/gadgets/ProxyHandler.php
    incubator/shindig/trunk/php/src/gadgets/Substitutions.php
    incubator/shindig/trunk/php/src/gadgets/http/GadgetRenderingServlet.php
    incubator/shindig/trunk/php/src/gadgets/oauth/OAuth.php
    incubator/shindig/trunk/php/src/gadgets/oauth/OAuthFetcher.php

Modified: incubator/shindig/trunk/php/src/common/RemoteContentRequest.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/common/RemoteContentRequest.php?rev=667596&r1=667595&r2=667596&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/common/RemoteContentRequest.php (original)
+++ incubator/shindig/trunk/php/src/common/RemoteContentRequest.php Fri Jun 13 10:05:57 2008
@@ -1,4 +1,5 @@
 <?php
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -33,7 +34,6 @@
 	private $options;
 	public $handle = false;
 	public static $DEFAULT_CONTENT_TYPE = "application/x-www-form-urlencoded; charset=utf-8";
-	public static $DEFAULT_OPTIONS = array();
 
 	public function __construct($uri, $headers = false, $postBody = false)
 	{
@@ -55,16 +55,14 @@
 			$tmpHeaders = '';
 			foreach ($headers as $key => $value) {
 				// Proxies should be bypassed with the Pragma: no-cache check.
-				//TODO double check array is good for options
-				if ($key == "Pragma" && @$options['ignoreCache']) {
+				if ($key == "Pragma" && $options->ignoreCache) {
 					$value = "no-cache";
 					$setPragmaHeader = true;
 				}
 				$tmpHeaders .= $key . ":" . $value . "\n";
 			}
 			// Bypass caching in proxies as well.
-			//TODO double check array is good for options
-			if (! $setPragmaHeader && @$options['ignoreCache']) {
+			if (! $setPragmaHeader && $options->ignoreCache) {
 				$tmpHeaders .= "Pragma:no-cache\n";
 			}
 			$this->headers = $tmpHeaders;
@@ -106,7 +104,7 @@
 	 */
 	public function createRemoteContentRequestWithUri($uri)
 	{
-		$this->createRemoteContentRequest("GET", $uri, null, null, RemoteContentRequest::$DEFAULT_OPTIONS);
+		$this->createRemoteContentRequest("GET", $uri, null, null, RemoteContentRequest::getDefaultOptions());
 	}
 
 	/**
@@ -127,7 +125,7 @@
 	 */
 	public function RemoteContentRequestWithUriHeaders($uri, $headers)
 	{
-		$this->createRemoteContentRequest("GET", $uri, $headers, null, RemoteContentRequest::$DEFAULT_OPTIONS);
+		$this->createRemoteContentRequest("GET", $uri, $headers, null, RemoteContentRequest::getDefaultOptions());
 	}
 
 	/**
@@ -148,7 +146,7 @@
 	 */
 	public function RemoteContentRequestWithUriPostBody($uri, $postBody)
 	{
-		$this->createRemoteContentRequest("POST", $uri, null, $postBody, RemoteContentRequest::$DEFAULT_OPTIONS);
+		$this->createRemoteContentRequest("POST", $uri, null, $postBody, RemoteContentRequest::getDefaultOptions());
 	}
 
 	/**
@@ -170,7 +168,7 @@
 	 */
 	public function createRemoteContentRequestWithUriHeadersPostBody($uri, $headers, $postBody)
 	{
-		$this->createRemoteContentRequest("POST", $uri, $headers, $postBody, RemoteContentRequest::$DEFAULT_OPTIONS);
+		$this->createRemoteContentRequest("POST", $uri, $headers, $postBody, RemoteContentRequest::getDefaultOptions());
 	}
 
 	/**
@@ -205,6 +203,11 @@
 		return md5($this->uri . $this->postBody);
 	}
 
+	public static function getDefaultOptions()
+	{
+		return new Options();
+	}
+
 	public function getContentType()
 	{
 		return $this->contentType;
@@ -262,6 +265,9 @@
 
 	public function getOptions()
 	{
+		if (empty($this->options)) {
+			return new Options();
+		}
 		return $this->options;
 	}
 
@@ -328,4 +334,21 @@
  */
 class Options {
 	public $ignoreCache = false;
+	public $ownerSigned = true;
+	public $viewerSigned = true;
+
+	public function __construct()
+	{
+	}
+
+	/**
+	 * Copy constructor
+	 */
+	public function copyOptions(Options $copyFrom)
+	{
+		$this->ignoreCache = $copyFrom->ignoreCache;
+		$this->ownerSigned = $copyFrom->ownerSigned;
+		$this->viewerSigned = $copyFrom->viewerSigned;
+	}
+
 }

Added: incubator/shindig/trunk/php/src/gadgets/Auth.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/Auth.php?rev=667596&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/Auth.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/Auth.php Fri Jun 13 10:05:57 2008
@@ -0,0 +1,51 @@
+<?php
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+class Auth {
+	
+	public static $NONE = "NONE";
+	public static $SIGNED = "SIGNED";
+	public static $AUTHENTICATED = "AUTHENTICATED";
+
+	/**
+	 * @param value
+	 * @return The parsed value (defaults to NONE)
+	 */
+	public static function parse($value)
+	{
+		if (! empty($value)) {
+			$value = trim($value);
+			if (strlen($value) == 0)
+				return Auth::$NONE;
+			if (strtoupper($value == Auth::$SIGNED)) {
+				return Auth::$SIGNED;
+			} else 
+				if (strtoupper($value == Auth::$AUTHENTICATED)) {
+					return Auth::$AUTHENTICATED;
+				} else {
+					return Auth::$NONE;
+				}
+		} else {
+			return Auth::$NONE;
+		}
+	}
+
+}
\ No newline at end of file

Modified: incubator/shindig/trunk/php/src/gadgets/Gadget.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/Gadget.php?rev=667596&r1=667595&r2=667596&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/Gadget.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/Gadget.php Fri Jun 13 10:05:57 2008
@@ -1,4 +1,5 @@
 <?php
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -146,11 +147,7 @@
 
 	public function getPreloads()
 	{
-		$ret = array();
-		foreach ($this->preloads as $preload) {
-			$ret[] = $this->substitutions->substitute($preload);
-		}
-		return $ret;
+		return $this->preloads;
 	}
 
 	public function getRequires()

Modified: incubator/shindig/trunk/php/src/gadgets/GadgetContext.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/GadgetContext.php?rev=667596&r1=667595&r2=667596&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/GadgetContext.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/GadgetContext.php Fri Jun 13 10:05:57 2008
@@ -15,7 +15,7 @@
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  * KIND, either express or implied. See the License for the
  * specific language governing permissions and limitations under the License.
- * 
+ *
  */
 
 define('DEFAULT_VIEW', 'profile');
@@ -154,7 +154,7 @@
 	private function instanceRegistry()
 	{
 		// 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  
+		// So by caching this and making it a one time initialization, we almost double the performance
 		if (! ($registry = $this->getCache()->get(md5(Config::get('features_path'))))) {
 			$registry = new GadgetFeatureRegistry(Config::get('features_path'));
 			$this->getCache()->set(md5(Config::get('features_path')), $registry);
@@ -164,7 +164,7 @@
 
 	private function instanceLocale()
 	{
-		// Get language and country params, try the GET params first, if their not set try the POST, else use 'all' as default 
+		// Get language and country params, try the GET params first, if their not set try the POST, else use 'all' as default
 		$language = ! empty($_GET['lang']) ? $_GET['lang'] : (! empty($_POST['lang']) ? $_POST['lang'] : 'all');
 		$country = ! empty($_GET['country']) ? $_GET['country'] : (! empty($_POST['country']) ? $_POST['country'] : 'all');
 		return new Locale($language, $country);
@@ -363,4 +363,24 @@
 	{
 		return $this->registry;
 	}
+
+	/**
+	 * Extracts the 'st' token from the GET or POST params and calls the
+	 * signer to validate the token
+	 *
+	 * @param GadgetSigner $signer the signer to use (configured in config.php)
+	 * @return string the token to use in the signed url
+	 */
+	public function extractAndValidateToken($signer)
+	{
+		if ($signer == null) {
+			return null;
+		}
+		$token = isset($_GET["st"]) ? $_GET["st"] : '';
+		if (! isset($token) || $token == '') {
+			$token = isset($_POST['st']) ? $_POST['st'] : '';
+		}
+		return $signer->createToken($token);
+	}
+
 }

Modified: incubator/shindig/trunk/php/src/gadgets/GadgetServer.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/GadgetServer.php?rev=667596&r1=667595&r2=667596&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/GadgetServer.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/GadgetServer.php Fri Jun 13 10:05:57 2008
@@ -1,4 +1,5 @@
 <?php
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -96,7 +97,7 @@
 		return $localeSpec;
 	}
 
-	private function featuresLoad($gadget, $context)
+	private function featuresLoad(Gadget $gadget, $context)
 	{
 		//NOTE i've been a bit liberal here with folding code into this function, while it did get a bit long, the many include()'s are slowing us down
 		// Should really clean this up a bit in the future though
@@ -129,6 +130,8 @@
 		$substitutor->addSubstitution('BIDI', "DIR", $rtl ? "rtl" : "ltr");
 		$substitutor->addSubstitution('BIDI', "REVERSE_DIR", $rtl ? "ltr" : "rtl");
 		
+		$this->substitutePreloads($gadget, $substitutor);
+		
 		// userPref's
 		$upValues = $gadget->getUserPrefValues();
 		foreach ($gadget->getUserPrefs() as $pref) {
@@ -184,6 +187,15 @@
 			$feature->process($gadget, $context, $params);
 		}
 	}
+
+	private function substitutePreloads(Gadget $gadget, $substituter)
+	{
+		$preloads = array();
+		foreach ($gadget->preloads as $preload) {
+			$preloads[] = $preload->substitute($substituter);
+		}
+		$gadget->preloads = $preloads;
+	}
 }
 
 

Modified: incubator/shindig/trunk/php/src/gadgets/GadgetSpecParser.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/GadgetSpecParser.php?rev=667596&r1=667595&r2=667596&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/GadgetSpecParser.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/GadgetSpecParser.php Fri Jun 13 10:05:57 2008
@@ -1,4 +1,5 @@
 <?php
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -44,6 +45,9 @@
 		foreach ($doc->Content as $content) {
 			$this->processContent($gadget, $content);
 		}
+		foreach ($doc->ModulePrefs->Preload as $feature) {
+			$gadget->preloads[] = new Preload($feature);
+		}
 		foreach ($doc->ModulePrefs->Require as $feature) {
 			$this->processFeature($gadget, $feature, true);
 		}
@@ -206,4 +210,5 @@
 		}
 		$gadget->requires[$featureSpec->name] = $featureSpec;
 	}
+
 }

Added: incubator/shindig/trunk/php/src/gadgets/Preload.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/Preload.php?rev=667596&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/Preload.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/Preload.php Fri Jun 13 10:05:57 2008
@@ -0,0 +1,100 @@
+<?php
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+class Preload {
+	
+	public static $AUTHZ_ATTR = "authz";
+	
+	private $href;
+	private $auth;
+	private $signViewer;
+	private $signOwner;
+	private $views = array();
+
+	public function getHref()
+	{
+		return $this->href;
+	}
+
+	public function getAuth()
+	{
+		return $this->auth;
+	}
+
+	public function isSignViewer()
+	{
+		return $this->signViewer;
+	}
+
+	public function isSignOwner()
+	{
+		return $this->signOwner;
+	}
+
+	public function getViews()
+	{
+		return $this->views;
+	}
+
+	public function substitute($substituter)
+	{
+		return $this->fillPreload($this, $substituter);
+	}
+
+	/**
+	 * Creates a new Preload from an xml node.
+	 *
+	 * @param preload The Preload to create
+	 */
+	public function __construct(SimpleXMLElement $preload)
+	{
+		$attributes = $preload->attributes();
+		$this->signOwner = isset($attributes['sign_owner']) ? trim($attributes['sign_owner']) : true;
+		$this->signViewer = isset($attributes['sign_viewer']) ? trim($attributes['sign_viewer']) : true;
+		$this->href = isset($attributes['href']) ? trim($attributes['href']) : '';
+		if (empty($this->href)) {
+			throw new SpecParserException("Preload/@href is missing or invalid.");
+		}
+		// Record all the associated views
+		$viewNames = isset($attributes['views']) ? trim($attributes['views']) : '';
+		$views = array();
+		$arrViewNames = explode(",", $viewNames);
+		foreach ($arrViewNames as $view) {
+			$view = trim($view);
+			if (strlen($view) > 0) {
+				$views[] = $view;
+			}
+		}
+		$this->views = $views;
+		$this->auth = Auth::parse($attributes[Preload::$AUTHZ_ATTR]);
+	}
+
+	private function fillPreload(Preload $preload, $substituter)
+	{
+		$this->signOwner = $preload->signOwner;
+		$this->signViewer = $preload->signViewer;
+		$this->views = $preload->views;
+		$this->auth = $preload->auth;
+		$this->href = $substituter->substituteUri(null, $preload->href);
+		return $this;
+	}
+
+}
\ No newline at end of file

Modified: incubator/shindig/trunk/php/src/gadgets/ProxyHandler.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/ProxyHandler.php?rev=667596&r1=667595&r2=667596&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/ProxyHandler.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/ProxyHandler.php Fri Jun 13 10:05:57 2008
@@ -29,17 +29,17 @@
  *
  */
 class ProxyHandler {
-	private $context;
-	private $signingFetcher;
+	private $context;
+	private $signingFetcher;
 	private $oauthFetcher;
-	
+
 	public function __construct($context, $signingFetcher = null, $oauthFetcher = null)
 	{
-		$this->context = $context;
+		$this->context = $context;
 		$this->signingFetcher = $signingFetcher;
 		$this->oauthFetcher = $oauthFetcher;
 	}
-	
+
 	/**
 	 * Fetches content and returns it in JSON format
 	 *
@@ -50,7 +50,7 @@
 	public function fetchJson($url, $signer, $method)
 	{
 		try {
-			$token = $this->extractAndValidateToken($signer);
+			$token = $this->context->extractAndValidateToken($signer);
 		} catch (Exception $e) {
 			$token = '';
 			// no token given, safe to ignore
@@ -59,16 +59,16 @@
 		// Fetch the content and convert it into JSON.
 		// TODO: Fetcher needs to handle variety of HTTP methods.
 		$result = $this->fetchContentDivert($url, $method, $signer);
-		if (!isset($result)) {
+		if (! isset($result)) {
 			//OAuthFetcher only
 			$metadata = $this->oauthFetcher->getResponseMetadata();
 			$json = array($url => $metadata);
-			$json = json_encode($json);
+			$json = json_encode($json);
 			$output = UNPARSEABLE_CRUFT . $json;
 			$this->setCachingHeaders();
 			header("Content-Type: application/json; charset=utf-8", true);
 			echo $output;
-			die();	
+			die();
 		}
 		$status = (int)$result->getHttpCode();
 		//header("HTTP/1.1 $status", true);
@@ -86,66 +86,55 @@
 					try {
 						$feed = Zend_Feed::importString($content);
 						if ($feed instanceof Zend_Feed_Rss) {
-							$channel = array(
-							    'title'       	=> $feed->title(),
-							    'link'        	=> $feed->link(),
-							    'description' 	=> $feed->description(),
-							 	'pubDate' 		=> $feed->pubDate(),
-							 	'language' 		=> $feed->language(),
-							 	'category' 		=> $feed->category(),
-							    'items'       	=> array()
-							);
+							$channel = array('title' => $feed->title(), 
+									'link' => $feed->link(), 
+									'description' => $feed->description(), 
+									'pubDate' => $feed->pubDate(), 
+									'language' => $feed->language(), 
+									'category' => $feed->category(), 'items' => array());
 							// Loop over each channel item and store relevant data
 							$counter = 0;
 							foreach ($feed as $item) {
 								if ($counter >= $numEntries) {
 									break;
 								}
-								$counter++;
-							    $channel['items'][] = array(
-							        'title'			=> $item->title(),
-							        'link'			=> $item->link(),
-							    	'author'		=> $item->author(),
-							    	'description'	=> $getSummaries ? $item->description() : '',
-							    	'category'		=> $item->category(),
-							    	'comments'		=> $item->comments(),
-							    	'pubDate'		=> $item->pubDate()
-							    );
+								$counter ++;
+								$channel['items'][] = array('title' => $item->title(), 
+										'link' => $item->link(), 
+										'author' => $item->author(), 
+										'description' => $getSummaries ? $item->description() : '', 
+										'category' => $item->category(), 
+										'comments' => $item->comments(), 
+										'pubDate' => $item->pubDate());
 							}
 						} elseif ($feed instanceof Zend_Feed_Atom) {
-							$channel = array(
-								'title'			=> $feed->title(),
-								'link'        	=> $feed->link(),
-								'id'        	=> $feed->id(),
-							    'subtitle' 		=> $feed->subtitle(),
-								'items'       	=> array()
-							);
+							$channel = array('title' => $feed->title(), 
+									'link' => $feed->link(), 'id' => $feed->id(), 
+									'subtitle' => $feed->subtitle(), 'items' => array());
 							$counter = 0;
 							foreach ($feed as $entry) {
 								if ($counter >= $numEntries) {
 									break;
 								}
-								$channel['items'][] = array(
-									'id' 		=> $entry->id(),
-									'title' 	=> $entry->title(),
-									'link' 		=> $entry->link(),
-									'summary' 	=> $entry->summary(),
-									'content' 	=> $entry->content(),
-									'author' 	=> $entry->author(),
-									'published' => $entry->published(),
-									'updated' 	=> $entry->updated()
-								);
+								$channel['items'][] = array('id' => $entry->id(), 
+										'title' => $entry->title(), 
+										'link' => $entry->link(), 
+										'summary' => $entry->summary(), 
+										'content' => $entry->content(), 
+										'author' => $entry->author(), 
+										'published' => $entry->published(), 
+										'updated' => $entry->updated());
 							}
 						} else {
 							throw new Exception('Invalid feed type');
 						}
 						$resp = json_encode($channel);
 					} catch (Zend_Feed_Exception $e) {
-						$resp = 'Error parsing feed: '.$e->getMessage();
+						$resp = 'Error parsing feed: ' . $e->getMessage();
 					}
 				} else {
-				    // feed import failed
-				    $resp = "Error fetching feed, response code: ".$result->getHttpCode();
+					// feed import failed
+					$resp = "Error fetching feed, response code: " . $result->getHttpCode();
 				}
 			} else {
 				$resp = $result->getResponseContent();
@@ -175,7 +164,7 @@
 	public function fetch($url, $signer, $method)
 	{
 		try {
-			$token = $this->extractAndValidateToken($signer);
+			$token = $this->context->extractAndValidateToken($signer);
 		} catch (Exception $e) {
 			$token = '';
 			// no token given, safe to ignore
@@ -187,7 +176,7 @@
 		$status = (int)$result->getHttpCode();
 		if ($status == 200) {
 			$headers = explode("\n", $result->getResponseHeaders());
-			foreach ( $headers as $header ) {
+			foreach ($headers as $header) {
 				if (strpos($header, ':')) {
 					$key = trim(substr($header, 0, strpos($header, ':')));
 					$val = trim(substr($header, strpos($header, ':') + 1));
@@ -209,7 +198,7 @@
 		// make sure the HttpServlet destructor doesn't override ours
 		die();
 	}
-	
+
 	/**
 	 * Both fetch and fetchJson call this function to retrieve the actual content
 	 *
@@ -220,13 +209,14 @@
 	private function fetchContent($url, $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 = '';
 		$context = new GadgetContext('GADGET');
 		$requestHeaders = $this->request_headers();
-		foreach ( $requestHeaders as $key => $val ) {
+		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";
@@ -241,7 +231,7 @@
 			if ($data) {
 				$data = urldecode($data);
 				$entries = explode('&', $data);
-				foreach ( $entries as $entry ) {
+				foreach ($entries as $entry) {
 					$parts = explode('=', $entry);
 					// Process only if its a valid value=something pair
 					if (count($parts) == 2) {
@@ -267,7 +257,7 @@
 	private function fetchContentDivert($url, $method, $signer)
 	{
 		$authz = isset($_GET['authz']) ? $_GET['authz'] : (isset($_POST['authz']) ? $_POST['authz'] : '');
-		$token = $this->extractAndValidateToken($signer);
+		$token = $this->context->extractAndValidateToken($signer);
 		switch (strtoupper($authz)) {
 			case 'SIGNED':
 				$fetcher = $this->signingFetcher->getSigningFetcher(new BasicRemoteContentFetcher(), $token);
@@ -285,12 +275,12 @@
 				return $this->fetchContent($url, $method);
 		}
 	}
-	
+
 	public function setContentFetcher($contentFetcherFactory)
 	{
 		$this->contentFetcherFactory = $contentFetcherFactory;
 	}
-	
+
 	/**
 	 * Sets the caching headers (overwriting anything the remote host set) to force
 	 * the browser not to cache this. 
@@ -302,7 +292,7 @@
 		header("Cache-Control: private; max-age=0", true);
 		header("Expires: " . gmdate("D, d M Y H:i:s", time() - 3000) . " GMT", true);
 	}
-	
+
 	/**
 	 * Empty function, should make something practical here some day.
 	 * it's function should be to validate the given url if its in
@@ -317,26 +307,7 @@
 		// why not use Zend::Uri:
 		return $url;
 	}
-	
-	/**
-	 * Extracts the 'st' token from the GET or POST params and calls the
-	 * signer to validate the token
-	 *
-	 * @param GadgetSigner $signer the signer to use (configured in config.php)
-	 * @return string the token to use in the signed url
-	 */
-	private function extractAndValidateToken($signer)
-	{
-		if ($signer == null) {
-			return null;
-		}
-		$token = isset($_GET["st"]) ? $_GET["st"] : '';
-		if (!isset($token) || $token == '') {
-			$token = isset($_POST['st']) ? $_POST['st'] : '';
-		}
-		return $signer->createToken($token);
-	}
-		
+
 	private function request_headers()
 	{
 		// Try to use apache's request headers if available
@@ -347,7 +318,7 @@
 		}
 		// if that failed, try to create them from the _SERVER superglobal
 		$headers = array();
-		foreach ( array_keys($_SERVER) as $skey ) {
+		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];

Modified: incubator/shindig/trunk/php/src/gadgets/Substitutions.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/Substitutions.php?rev=667596&r1=667595&r2=667596&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/Substitutions.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/Substitutions.php Fri Jun 13 10:05:57 2008
@@ -15,13 +15,13 @@
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  * KIND, either express or implied. See the License for the
  * specific language governing permissions and limitations under the License.
- * 
+ *
  */
 
 class Substitutions {
 	private $types = array('MESSAGE' => 'MSG', 'BIDI' => 'BIDI', 'USER_PREF' => 'UP', 
 			'MODULE' => 'MODULE');
-	
+
 	private $substitutions = array();
 
 	public function __construct()
@@ -53,6 +53,26 @@
 
 	public function substituteType($type, $input)
 	{
+		if (empty($this->substitutions[$type])) {
+			return $input;
+		}
 		return str_replace(array_keys($this->substitutions[$type]), array_values($this->substitutions[$type]), $input);
 	}
+
+	/**
+	 * Substitutes a uri
+	 * @param type The type to substitute, or null for all types.
+	 * @param uri
+	 * @return The substituted uri, or a dummy value if the result is invalid.
+	 */
+	public function substituteUri($type, $uri) {
+		if (empty($uri)) {
+			return null;
+		}
+		try {
+			return $this->substituteType($type, $uri);
+		} catch (Exception $e) {
+			return "";
+		}
+	}
 }
\ No newline at end of file

Modified: incubator/shindig/trunk/php/src/gadgets/http/GadgetRenderingServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/http/GadgetRenderingServlet.php?rev=667596&r1=667595&r2=667596&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/http/GadgetRenderingServlet.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/http/GadgetRenderingServlet.php Fri Jun 13 10:05:57 2008
@@ -157,15 +157,16 @@
 				// TODO: This case needs to be handled more gracefully by the js
 				// servlet. We should probably inline external JS as well.
 				$externJs .= sprintf($externFmt, $library->getContent()) . "\n";
-			} else if ($type == 'INLINE') {
-				echo $library->getContent();
-			} else {
-				// FILE or RESOURCE
-				if ($forcedLibs == null) {
-					echo $library->getContent() . "\n";
+			} else 
+				if ($type == 'INLINE') {
+					echo $library->getContent();
+				} else {
+					// FILE or RESOURCE
+					if ($forcedLibs == null) {
+						echo $library->getContent() . "\n";
+					}
+					// otherwise it was already included by config.forceJsLibs.
 				}
-				// otherwise it was already included by config.forceJsLibs.
-			}
 		}
 		echo "\n-->\n</script>\n";
 		// Forced libs first.
@@ -176,8 +177,7 @@
 		if (strlen($externJs) > 0) {
 			echo $externJs;
 		}
-		echo "<script><!--\n" . $this->appendJsConfig($context, $gadget) . $this->appendMessages($gadget) . "-->\n</script>\n";
-		
+		echo "<script><!--\n" . $this->appendJsConfig($context, $gadget) . $this->appendMessages($gadget) . $this->appendPreloads($gadget, $context) . "-->\n</script>\n";
 		$gadgetExceptions = array();
 		$content = $gadget->getSubstitutions()->substitute($view->getContent());
 		if (empty($content)) {
@@ -323,4 +323,60 @@
 		}
 		return "gadgets.Prefs.setMessages_($msgs);\n";
 	}
-}
+
+	/**
+	 * Appends data from <Preload> elements to make them available to
+	 * gadgets.io.
+	 *
+	 * @param gadget
+	 */
+	private function appendPreloads(Gadget $gadget, GadgetContext $context)
+	{
+		$resp = '';
+		$gadgetSigner = Config::get('security_token_signer');
+		$gadgetSigner = new $gadgetSigner();
+		$token = '';
+		try {
+			$token = $context->extractAndValidateToken($gadgetSigner);
+		} catch (Exception $e) {
+			$token = '';
+			// no token given, safe to ignore
+		}
+		foreach ($gadget->getPreloads() as $preload) {
+			try {
+				if (($preload->getAuth() == Auth::$NONE || $token != null) && (count($preload->getViews()) == 0 || in_array($context->getView(), $preload->getViews()))) {
+					$request = new RemoteContentRequest($preload->getHref());
+					$request->createRemoteContentRequestWithUri($preload->getHref());
+					$request->getOptions()->ownerSigned = $preload->isSignOwner();
+					$request->getOptions()->viewerSigned = $preload->isSignViewer();
+					switch (strtoupper(trim($preload->getAuth()))) {
+						case "NONE":
+							$brc = new BasicRemoteContent();
+							$response = $brc->fetch($request, $context);
+							break;
+						case "SIGNED":
+							$signingFetcherFactory = new SigningFetcherFactory(Config::get("private_key_file"));
+							$fetcher = $signingFetcherFactory->getSigningFetcher(new BasicRemoteContentFetcher(), $token);
+							$response = $fetcher->fetch($preload->getHref(), $request->getMethod());
+							break;
+						default:
+							@ob_end_clean();
+							header("HTTP/1.0 500 Internal Server Error", true);
+							echo "<html><body><h1>" . "500 - Internal Server Error" . "</h1></body></html>";
+							die();
+					}
+					$json = array(
+							$preload->getHref() => array(
+									'body' => $response->getResponseContent(), 
+									'rc' => $response->getHttpCode()));
+					$resp .= json_encode($json);
+				}
+			} catch (Exception $e) {
+				throw new Exception($e);
+			}
+		}
+		$resp = $resp == '' ? "{}" : $resp;
+		return "gadgets.io.preloaded_ = " . $resp . ";\n";
+	}
+
+}
\ No newline at end of file

Modified: incubator/shindig/trunk/php/src/gadgets/oauth/OAuth.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/oauth/OAuth.php?rev=667596&r1=667595&r2=667596&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/oauth/OAuth.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/oauth/OAuth.php Fri Jun 13 10:05:57 2008
@@ -1,4 +1,5 @@
 <?php
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -264,9 +265,10 @@
 			$header_parameters = OAuthRequest::split_header($request_headers['Authorization']);
 			if ($http_method == "GET") {
 				$req_parameters = $_GET;
-			} else if ($http_method = "POST") {
-				$req_parameters = $_POST;
-			}
+			} else 
+				if ($http_method = "POST") {
+					$req_parameters = $_POST;
+				}
 			$parameters = array_merge($header_parameters, $req_parameters);
 			$req = new OAuthRequest($http_method, $http_url, $parameters);
 		} elseif ($http_method == "GET") {
@@ -285,8 +287,7 @@
 		$parameters = is_array($parameters) ? $parameters : array();
 		$defaults = array("oauth_nonce" => OAuthRequest::generate_nonce(), 
 				"oauth_timestamp" => OAuthRequest::generate_timestamp(), 
-				"oauth_consumer_key" => $consumer->key, // quick hack to make this demo'able
-'synd' => 'partuza', 
+				"oauth_consumer_key" => $consumer->key, 'synd' => 'partuza', 
 				'container' => 'partuza');
 		$parameters = array_merge($defaults, $parameters);
 		if (isset($token)) {
@@ -867,7 +868,9 @@
 		$explodedForm = explode("&", $form);
 		foreach ($explodedForm as $params) {
 			$value = explode("=", $params);
-			$parameters[OAuthUtil::urldecodeRFC3986($value[0])] = OAuthUtil::urldecodeRFC3986($value[1]);
+			if (! empty($value[0]) && ! empty($value[1])) {
+				$parameters[OAuthUtil::urldecodeRFC3986($value[0])] = OAuthUtil::urldecodeRFC3986($value[1]);
+			}
 		}
 		return $parameters;
 	}

Modified: incubator/shindig/trunk/php/src/gadgets/oauth/OAuthFetcher.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/oauth/OAuthFetcher.php?rev=667596&r1=667595&r2=667596&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/oauth/OAuthFetcher.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/oauth/OAuthFetcher.php Fri Jun 13 10:05:57 2008
@@ -1,4 +1,5 @@
 <?php
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements. See the NOTICE file distributed with this
@@ -15,7 +16,7 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
-
+
 /**
  * Implements the OAuth dance (http://oauth.net/core/1.0/) for gadgets.
  *
@@ -26,7 +27,7 @@
  * requires OAuth signing.
  */
 class OAuthFetcher extends RemoteContentFetcher {
-
+	
 	// We store some blobs of data on the client for later reuse; the blobs
 	// contain key/value pairs, and these are the key names.
 	private static $REQ_TOKEN_KEY = "r";
@@ -34,66 +35,66 @@
 	private static $ACCESS_TOKEN_KEY = "a";
 	private static $ACCESS_TOKEN_SECRET_KEY = "as";
 	private static $OWNER_KEY = "o";
-
+	
 	// names for the JSON values we return to the client
 	public static $CLIENT_STATE = "oauthState";
 	public static $APPROVAL_URL = "approvalUrl";
 	// names of additional OAuth parameters we include in outgoing requests
 	public static $XOAUTH_APP_URL = "xoauth_app_url";
-
+	
 	/**
 	 * Maximum age for our client state; if this is exceeded we start over. One
 	 * hour is a fairly arbitrary time limit here.
 	 */
 	private static $CLIENT_STATE_MAX_AGE_SECS = 3600;
-
+	
 	/**
 	 * The gadget security token, with info about owner/viewer/gadget.
 	 */
 	protected $authToken;
-
+	
 	/**
 	 * The gadget's nickname for the service provider.
 	 */
 	protected $serviceName;
-
+	
 	/**
 	 * The gadget's nickname for the token.
 	 */
 	protected $tokenName;
-
+	
 	/**
 	 * Reference to our persistent store for OAuth metadata.
 	 */
 	protected $tokenStore;
-
+	
 	/**
 	 * The accessor we use for signing messages. This also holds metadata about
 	 * the service provider, such as their URLs and the keys we use to access
 	 * those URLs.
 	 */
 	private $accessorInfo;
-
+	
 	/**
 	 * We use this to encrypt and sign the state we cache on the client.
 	 */
 	private $oauthCrypter;
-
+	
 	/**
 	 * State the client sent with their request.
 	 */
 	private $origClientState = array();
-
+	
 	/**
 	 * The request the client really wants to make.
 	 */
 	private $realRequest;
-
+	
 	/**
 	 * State to cache on the client.
 	 */
 	private $newClientState;
-
+	
 	/**
 	 * Authorization URL for the client
 	 */
@@ -120,8 +121,8 @@
 		if ($origClientState != null && strlen($origClientState) > 0) {
 			try {
 				$this->origClientState = $this->oauthCrypter->unwrap($origClientState, OAuthFetcher::$CLIENT_STATE_MAX_AGE_SECS);
-			} catch (BlobCrypterException $e) {	// Probably too old, pretend we never saw it at all.
-			}
+			} catch (BlobCrypterException $e) {// Probably too old, pretend we never saw it at all.
+}
 		}
 		if ($this->origClientState == null) {
 			$this->origClientState = array();
@@ -149,10 +150,11 @@
 		if (isset($this->origClientState[OAuthFetcher::$REQ_TOKEN_KEY])) {
 			$accessor->requestToken = $this->origClientState[OAuthFetcher::$REQ_TOKEN_KEY];
 			$accessor->tokenSecret = $this->origClientState[OAuthFetcher::$REQ_TOKEN_SECRET_KEY];
-		} else if (isset($this->origClientState[OAuthFetcher::$ACCESS_TOKEN_KEY])) {
-			$accessor->accessToken = $this->origClientState[OAuthFetcher::$ACCESS_TOKEN_KEY];
-			$accessor->tokenSecret = $this->origClientState[OAuthFetcher::$ACCESS_TOKEN_SECRET_KEY];
-		}
+		} else 
+			if (isset($this->origClientState[OAuthFetcher::$ACCESS_TOKEN_KEY])) {
+				$accessor->accessToken = $this->origClientState[OAuthFetcher::$ACCESS_TOKEN_KEY];
+				$accessor->tokenSecret = $this->origClientState[OAuthFetcher::$ACCESS_TOKEN_SECRET_KEY];
+			}
 	}
 
 	private function buildTokenKey()
@@ -248,7 +250,7 @@
 		if (! isset($params)) {
 			throw new Exception("params was null in " + "newRequestMessage " + "Use newRequesMessage if you don't have a params to pass");
 		}
-
+		
 		switch ($this->accessorInfo->getSignatureType()) {
 			case OAuth::$RSA_SHA1:
 				$params[OAuth::$OAUTH_SIGNATURE_METHOD] = OAuth::$RSA_SHA1;
@@ -286,11 +288,13 @@
 	{
 		if (isset($method) && isset($url) && isset($params)) {
 			return $this->newRequestMessageMethod($method, $url, $params);
-		} else if (isset($url) && isset($params)) {
-			return $this->newRequestMessageParams($url, $params);
-		} else if (isset($url)) {
-			return $this->newRequestMessageUrlOnly($url);
-		}
+		} else 
+			if (isset($url) && isset($params)) {
+				return $this->newRequestMessageParams($url, $params);
+			} else 
+				if (isset($url)) {
+					return $this->newRequestMessageUrlOnly($url);
+				}
 	}
 
 	private function getAuthorizationHeader($oauthParams)
@@ -322,7 +326,7 @@
 				$authHeader = $this->getAuthorizationHeader($oauthParams);
 				$newHeaders["Authorization"] = $authHeader;
 				break;
-					
+			
 			case OAuthStoreVars::$OAuthParamLocation['POST_BODY']:
 				if (! OAuthUtil::isFormEncoded($contentType)) {
 					throw new GadgetException("Invalid param: OAuth param location can only " . "be post_body if post body if of type x-www-form-urlencoded");
@@ -333,12 +337,12 @@
 					$postBody = $postBody . "&" . OAuthUtil::getPostBodyString($oauthParams);
 				}
 				break;
-					
+			
 			case OAuthStoreVars::$OAuthParamLocation['URI_QUERY']:
 				$url = OAuthUtil::addParameters($url, $oauthParams);
 				break;
 		}
-		$postBodyBytes = ($postBody == null) ? null : null ;//$postBody->getBytes("UTF-8"); //See what can we do with this?
+		$postBodyBytes = ($postBody == null) ? null : null; //$postBody->getBytes("UTF-8"); //See what can we do with this?
 		$rcr = new RemoteContentRequest($url);
 		$rcr->createRemoteContentRequest($method, $url, $newHeaders, $postBodyBytes, $options);
 		return $rcr;
@@ -349,7 +353,7 @@
 	 */
 	private function sendOAuthMessage(OAuthRequest $request)
 	{
-		$rcr = $this->createRemoteContentRequest($this->filterOAuthParams($request), $request->get_normalized_http_method(), $request->get_url(), null, RemoteContentRequest::$DEFAULT_CONTENT_TYPE, null, RemoteContentRequest::$DEFAULT_OPTIONS);
+		$rcr = $this->createRemoteContentRequest($this->filterOAuthParams($request), $request->get_normalized_http_method(), $request->get_url(), null, RemoteContentRequest::$DEFAULT_CONTENT_TYPE, null, RemoteContentRequest::getDefaultOptions());
 		$content = $this->getNextFetcher()->fetchRequest($rcr);
 		$reply = OAuthRequest::from_request();
 		$params = OAuthUtil::decodeForm($content->getResponseContent());