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 2009/02/15 18:35:07 UTC

svn commit: r744702 [2/3] - in /incubator/shindig/trunk/php: ./ config/ src/common/ src/gadgets/ src/gadgets/render/ src/gadgets/rewrite/ src/gadgets/servlet/ test/misc/

Added: incubator/shindig/trunk/php/src/gadgets/MakeRequestHandler.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/MakeRequestHandler.php?rev=744702&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/MakeRequestHandler.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/MakeRequestHandler.php Sun Feb 15 17:35:05 2009
@@ -0,0 +1,274 @@
+<?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.
+ */
+
+// 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' >");
+
+/**
+ * Handles the gadget.io.makeRequest requests
+ */
+class MakeRequestHandler extends ProxyBase {
+  public $signingFetcher;
+
+  public function __construct($context, $signingFetcher) {
+    $this->context = $context;
+    $this->signingFetcher = $signingFetcher;
+  }
+
+  /**
+   * Fetches content and returns it in JSON format
+   *
+   * @param string $url the url to fetch
+   * @param GadgetSigner $signer the request signer to use
+   * @param string $method the http method to use (get or post) in making the request
+   */
+  public function fetchJson($url, $signer, $method) {
+    $url = $this->validateUrl($url);
+    // 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)) {
+      //OAuthFetcher only
+      $metadata = $this->oauthFetcher->getResponseMetadata();
+      $json = array($url => $metadata);
+      $json = json_encode($json);
+      $output = UNPARSEABLE_CRUFT . $json;
+      $this->setCachingHeaders();
+      header("Content-Type: application/json; charset=utf-8", true);
+      echo $output;
+      die();
+    }
+    $status = (int)$result->getHttpCode();
+    header("HTTP/1.1 $status", true);
+    header("Content-Type: application/json; charset=utf-8", true);
+    $output = '';
+    if (isset($_REQUEST['contentType']) && $_REQUEST['contentType'] == 'FEED' && $status == 200) {
+      $this->parseFeed($result, $url);
+    } else {
+      $resp = $result->getResponseContent();
+    }
+    $json = array($url => array('body' => $resp, 'rc' => $status));
+    $json = json_encode($json);
+    $output = UNPARSEABLE_CRUFT . $json;
+    $this->setCachingHeaders();
+    echo $output;
+  }
+
+  /**
+   * Fetches content using either OAUTH, SIGNED or NONE type signing
+   *
+   * @param string $url
+   * @param string $method
+   * @param SingingFetcher $signer
+   * @return RemoteContentRequest
+   */
+  private function fetchContentDivert($url, $method, $signer) {
+    $authz = isset($_GET['authz']) ? $_GET['authz'] : (isset($_POST['authz']) ? $_POST['authz'] : '');
+    $token = $this->context->extractAndValidateToken($signer);
+    switch (strtoupper($authz)) {
+      case 'SIGNED':
+        $fetcher = $this->signingFetcher->getSigningFetcher(new BasicRemoteContentFetcher(), $token);
+        return $fetcher->fetch($url, $method);
+      case 'OAUTH':
+        $params = new OAuthRequestParams();
+        $fetcher = $this->signingFetcher->getSigningFetcher(new BasicRemoteContentFetcher(), $token);
+        $oAuthFetcherFactory = new OAuthFetcherFactory($fetcher);
+        $this->oauthFetcher = $oAuthFetcherFactory->getOAuthFetcher($fetcher, $token, $params);
+        $request = new RemoteContentRequest($url);
+        $request->createRemoteContentRequestWithUri($url);
+        return $this->oauthFetcher->fetch($request);
+    }
+    return $this->fetchContent($url, $method);
+  }
+
+  /**
+   * Handles (RSS & Atom) Type.FEED parsing using Zend's feed parser
+   *
+   * @return response string, either a json encoded feed structure or an error message
+   */
+  private function parseFeed($result, $url) {
+    require 'external/Zend/Feed.php';
+    $numEntries = $_REQUEST['numEntries'];
+    $getSummaries = ! empty($_REQUEST['getSummaries']) && $_REQUEST['getSummaries'] != 'false' ? true : false;
+    $channel = array();
+    if ((int)$result->getHttpCode() == 200) {
+      $content = $result->getResponseContent();
+      try {
+        $feed = Zend_Feed::importString($content);
+        if ($feed instanceof Zend_Feed_Rss) {
+          // Try get author
+          if ($feed->author()) {
+            $author = $feed->author();
+          } else {
+            if ($feed->creator()) {
+              $author = $feed->creator();
+            } else {
+              $author = null;
+            }
+          }
+          // Loop over each channel item and store relevant data
+          $counter = 0;
+          $channel['Entry'] = array();
+          foreach ($feed as $item) {
+            if ($counter >= $numEntries) {
+              break;
+            }
+            $_entry = array();
+            $_entry['Title'] = $item->title();
+            $_entry['Link'] = $item->link();
+            if ($getSummaries && $item->description()) {
+              $_entry['Summary'] = $item->description();
+            }
+            $date = 0;
+            if ($item->date()) {
+              $date = strtotime($item->date());
+            } else {
+              if ($item->pubDate()) {
+                $date = strtotime($item->pubDate());
+              }
+            }
+            $_entry['Date'] = $date;
+            $channel['Entry'][] = $_entry;
+            // Remember author if first found
+            if (empty($author) && $item->author()) {
+              $author = $item->author();
+            } else if ($item->creator()) {
+              $author = $item->creator();
+            }
+            $counter ++;
+          }
+          $channel['Title'] = $feed->title();
+          $channel['URL'] = $url;
+          $channel['Description'] = $feed->description();
+          if ($feed->link()) {
+            if (is_array($feed->link())) {
+              foreach ($feed->link() as $_link) {
+                if ($_link->nodeValue) $channel['Link'] = $_link->nodeValue;
+              }
+            } else {
+              $channel['Link'] = $feed->link();
+            }
+          }
+          if ($author != null) {
+            $channel['Author'] = $author;
+          }
+        } elseif ($feed instanceof Zend_Feed_Atom) {
+          // Try get author
+          if ($feed->author()) {
+            if ($feed->author->name()) {
+              $author = $feed->author->name();
+            } else if ($feed->author->email()) {
+              $author = $feed->author->email();
+            } else {
+              $author = $feed->author();
+            }
+          } else {
+            $author = null;
+          }
+          // Loop over each entries and store relevant data
+          $counter = 0;
+          $channel['Entry'] = array();
+          foreach ($feed as $entry) {
+            if ($counter >= $numEntries) {
+              break;
+            }
+            $_entry = array();
+            $_entry['Title'] = $entry->title();
+            // get Link if rel="alternate"
+            if ($entry->link('alternate')) {
+              $_entry['Link'] = $entry->link('alternate');
+            } else {
+              // if there's no alternate, pick the one without "rel" attribtue
+              $_links = $entry->link;
+              if (is_array($_links)) {
+                foreach ($_links as $_link) {
+                  if (empty($_link['rel'])) {
+                    $_entry['Link'] = $_link['href'];
+                    break;
+                  }
+                }
+              } else {
+                $_entry['Link'] = $_links['href'];
+              }
+            }
+            if ($getSummaries && $entry->summary()) {
+              $_entry['Summary'] = $entry->summary();
+            }
+            $date = 0;
+            if ($entry->updated()) {
+              $date = strtotime($entry->updated());
+            } else {
+              if ($entry->published()) {
+                $date = strtotime($entry->published());
+              }
+            }
+            $_entry['Date'] = $date;
+            $channel['Entry'][] = $_entry;
+            // Remember author if first found
+            if (empty($author) && $entry->author()) {
+              if ($entry->author->name()) {
+                $author = $entry->author->name();
+              } else if ($entry->author->email()) {
+                $author = $entry->author->email();
+              } else {
+                $author = $entry->author();
+              }
+            } elseif (empty($author)) {
+              $author = null;
+            }
+            $counter ++;
+          }
+          $channel['Title'] = $feed->title();
+          $channel['URL'] = $url;
+          $channel['Description'] = $feed->subtitle();
+          // get Link if rel="alternate"
+          if ($feed->link('alternate')) {
+            $channel['Link'] = $feed->link('alternate');
+          } else {
+            // if there's no alternate, pick the one without "rel" attribtue
+            $_links = $feed->link;
+            if (is_array($_links)) {
+              foreach ($_links as $_link) {
+                if (empty($_link['rel'])) {
+                  $channel['Link'] = $_link['href'];
+                  break;
+                }
+              }
+            } else {
+              $channel['Link'] = $_links['href'];
+            }
+          }
+          if (! empty($author)) {
+            $channel['Author'] = $author;
+          }
+        } else {
+          throw new Exception('Invalid feed type');
+        }
+        $resp = json_encode($channel);
+      } catch (Zend_Feed_Exception $e) {
+        $resp = 'Error parsing feed: ' . $e->getMessage();
+      }
+    } else {
+      // feed import failed
+      $resp = "Error fetching feed, response code: " . $result->getHttpCode();
+    }
+    return $resp;
+  }
+}

Modified: incubator/shindig/trunk/php/src/gadgets/MetadataContext.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/MetadataContext.php?rev=744702&r1=744701&r2=744702&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/MetadataContext.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/MetadataContext.php Sun Feb 15 17:35:05 2009
@@ -24,7 +24,7 @@
     parent::__construct('GADGET');
     $this->url = $url;
     $this->view = $jsonContext->view;
-    $this->locale = new Locale($jsonContext->language, $jsonContext->country);
+    $this->locale = array('lang' => $jsonContext->language, 'country' => $jsonContext->country);
     $this->container = $jsonContext->container;
   }
 

Modified: incubator/shindig/trunk/php/src/gadgets/MetadataHandler.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/MetadataHandler.php?rev=744702&r1=744701&r2=744702&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/MetadataHandler.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/MetadataHandler.php Sun Feb 15 17:35:05 2009
@@ -27,12 +27,11 @@
         $gadgetUrl = $gadget->url;
         $gadgetModuleId = $gadget->moduleId;
         $context = new MetadataGadgetContext($requests->context, $gadgetUrl);
-        $gadgetServer = new GadgetServer();
-        $gadget = $gadgetServer->processGadget($context);
+        $gadgetServer = new GadgetFactory($context, null);
+        $gadget = $gadgetServer->createGadget($gadgetUrl);
         $response[] = $this->makeResponse($gadget, $gadgetModuleId, $gadgetUrl, $context);
       } catch (Exception $e) {
-        $response[] = array('errors' => array($e->getMessage()), 
-            'moduleId' => $gadgetModuleId, 'url' => $gadgetUrl);
+        $response[] = array('errors' => array($e->getMessage()), 'moduleId' => $gadgetModuleId, 'url' => $gadgetUrl);
       }
     }
     return $response;
@@ -40,46 +39,43 @@
 
   private function makeResponse($gadget, $gadgetModuleId, $gadgetUrl, $context) {
     $response = array();
+
     $prefs = array();
-    foreach ($gadget->getUserPrefs() as $pref) {
-      $prefs[$pref->getName()] = array('displayName' => $pref->getDisplayName(), 
-          'type' => $pref->getDataType(), 'default' => $pref->getDefaultValue(), 
-          'enumValues' => $pref->getEnumValues(), 
-          'required' => $pref->isRequired());
-    }
-    $features = array();
-    foreach ($gadget->getRequires() as $feature) {
-      $features[] = $feature->getName();
+    foreach ($gadget->gadgetSpec->userPrefs as $pref) {
+      $prefs[$pref['name']] = $pref;
     }
+
     $views = array();
-    foreach ($gadget->getViews() as $view) {
+    foreach ($gadget->gadgetSpec->views as $name => $view) {
       // we want to include all information, except for the content
-      unset($view->content);
-      $views[$view->getName()] = $view;
-    }
-    $links = array();
-    foreach ($gadget->links as $link) {
-      $links[] = $link;
-    }
-    $icons = array();
-    foreach ($gadget->getIcons() as $icon) {
-      $icons[] = $icon;
+      unset($view['content']);
+      $views[$name] = $view;
     }
+
     $oauth = array();
+
+    //FIXME missing from the spec parsing still
+    /*
     $oauthspec = $gadget->getOAuthSpec();
     if (! empty($oauthspec)) {
       foreach ($oauthspec->getServices() as $oauthservice) {
-        $oauth[$oauthservice->getName()] = array(
-            "request" => $oauthservice->getRequestUrl(), 
-            "access" => $oauthservice->getAccessUrl(), 
-            "authorization" => $oauthservice->getAuthorizationUrl());
+        $oauth[$oauthservice->getName()] = array("request" => $oauthservice->getRequestUrl(), "access" => $oauthservice->getAccessUrl(), "authorization" => $oauthservice->getAuthorizationUrl());
       }
     }
+    */
+
+    //FIXME UrlGenerator needs fixin' still
+    //$response['iframeUrl'] = UrlGenerator::getIframeURL($gadget, $context);
+
+    $response['features'] = $gadget->features;
+    $response['links'] = $gadget->gadgetSpec->links;
+    $response['icons'] = $gadget->gadgetSpec->icon;
+    $response['views'] = $views;
+
     $response['author'] = $gadget->getAuthor();
     $response['authorEmail'] = $gadget->getAuthorEmail();
     $response['description'] = $gadget->getDescription();
     $response['directoryTitle'] = $gadget->getDirectoryTitle();
-    $response['features'] = $features;
     $response['screenshot'] = $gadget->getScreenShot();
     $response['thumbnail'] = $gadget->getThumbnail();
     $response['title'] = $gadget->getTitle();
@@ -98,12 +94,10 @@
     $response['singleton'] = $gadget->getSingleton();
     $response['scaling'] = $gadget->getScaling();
     $response['scrolling'] = $gadget->getScrolling();
-    $response['links'] = $links;
-    $response['views'] = $views;
-    $response['icons'] = $icons;
+
     $response['moduleId'] = $gadgetModuleId;
     $response['url'] = $gadgetUrl;
-    $response['iframeUrl'] = UrlGenerator::getIframeURL($gadget, $context);
+
     $response['userPrefs'] = $prefs;
     $response['oauth'] = $oauth;
     return $response;

Added: incubator/shindig/trunk/php/src/gadgets/ProxyBase.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/ProxyBase.php?rev=744702&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/ProxyBase.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/ProxyBase.php Sun Feb 15 17:35:05 2009
@@ -0,0 +1,151 @@
+<?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.
+ */
+
+/**
+ * This class contains the shared methods between the Proxy and makeRequest handlers
+ */
+class ProxyBase {
+  public $context;
+  protected $disallowedHeaders = array('Keep-Alive', 'Host', 'Accept-Encoding', 'Set-Cookie', 'Content-Length', 'Content-Encoding', 'ETag', 'Last-Modified', 'Accept-Ranges', 'Vary', 'Expires', 'Date', 'Pragma', 'Cache-Control', 'Transfer-Encoding');
+
+  public function __construct($context) {
+    $this->context = $context;
+  }
+
+  /**
+   * Retrieves the actual content
+   *
+   * @param string $url the url to fetch
+   * @return the filled in request (RemoteContentRequest)
+   */
+  protected function fetchContent($url, $method = 'GET') {
+    // Check the protocol requested - curl doesn't really support file://
+    // requests but the 'error' should be handled properly
+    $protocolSplit = explode('://', $url, 2);
+    if (count($protocolSplit) < 2) {
+      throw new Exception("Invalid protocol specified");
+    } else {
+      $protocol = strtoupper($protocolSplit[0]);
+      if ($protocol != "HTTP" && $protocol != "HTTPS") {
+        throw new Exception("Invalid protocol specified in url: " . htmlentities($protocol));
+      }
+    }
+    $headers = '';
+    $requestHeaders = $this->request_headers();
+    foreach ($requestHeaders as $key => $val) {
+      $key = str_replace(' ', '-', ucwords(str_replace('-', ' ', $key))); // force the header name to have the proper Header-Name casing
+      if (! in_array($key, $this->disallowedHeaders)) {
+        // 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 = '';
+      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);
+        }
+      }
+      // 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($url, $headers, $postData);
+      $request = $this->context->getHttpFetcher()->fetch($request, $this->context);
+    } else {
+      $request = new RemoteContentRequest($url, $headers);
+      $request = $this->context->getHttpFetcher()->fetch($request, $this->context);
+    }
+    return $request;
+  }
+
+  /**
+   * Sets the caching (Cache-Control & Expires) with a cache age of $lastModified
+   * or if $lastModified === false, sets Pragma: no-cache & Cache-Control: no-cache
+   */
+  protected function setCachingHeaders($lastModified = false) {
+    $maxAge = $this->context->getIgnoreCache() ? false : $this->context->getRefreshInterval();
+    if ($maxAge) {
+      if ($lastModified) {
+        header("Last-Modified: $lastModified");
+      }
+      // time() is a kernel call, so lets avoid it and use the request time instead
+      $time = $_SERVER['REQUEST_TIME'];
+      $expires = $maxAge !== false ? $time + $maxAge : $time - 3000;
+      $public = $maxAge ? 'public' : 'private';
+      $maxAge = $maxAge === false ? '0' : $maxAge;
+      header("Cache-Control: {$public}; max-age={$maxAge}", true);
+      header("Expires: " . gmdate("D, d M Y H:i:s", $expires) . " GMT", true);
+    } else {
+      header("Cache-Control: no-cache", true);
+      header("Pragma: no-cache", true);
+    }
+  }
+
+  /**
+   * Does a quick-and-dirty url validation
+   *
+   * @param string $url
+   * @return string the 'validated' url
+   */
+  protected function validateUrl($url) {
+    if (! @parse_url($url)) {
+      throw new Exception("Invalid Url");
+    } else {
+      return $url;
+    }
+  }
+
+  /**
+   * Returns the request headers, using the apache_request_headers function if it's
+   * available, and otherwise tries to guess them from the $_SERVER superglobal
+   *
+   * @return unknown
+   */
+  protected 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/src/gadgets/ProxyHandler.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/ProxyHandler.php?rev=744702&r1=744701&r2=744702&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/ProxyHandler.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/ProxyHandler.php Sun Feb 15 17:35:05 2009
@@ -24,252 +24,20 @@
 /**
  * The ProxyHandler class does the actual proxy'ing work. it deals both with
  * GET and POST based input, and peforms a request based on the input, headers and
- * httpmethod params. It also deals with request signing and verification thru the
- * authz and st (security token) params.
+ * httpmethod params.
  *
  */
-class ProxyHandler {
-  private $context;
-  private $signingFetcher;
-  private $oauthFetcher;
-
-  public function __construct($context, $signingFetcher = null, $oauthFetcher = null) {
-    $this->context = $context;
-    $this->signingFetcher = $signingFetcher;
-    $this->oauthFetcher = $oauthFetcher;
-  }
-
-  /**
-   * Fetches content and returns it in JSON format
-   *
-   * @param string $url the url to fetch
-   * @param GadgetSigner $signer the request signer to use
-   * @param string $method the http method to use (get or post) in making the request
-   */
-  public function fetchJson($url, $signer, $method) {
-    try {
-      $token = $this->context->extractAndValidateToken($signer);
-    } catch (Exception $e) {
-      $token = '';
-      // no token given, safe to ignore
-    }
-    $url = $this->validateUrl($url);
-    // 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)) {
-      //OAuthFetcher only
-      $metadata = $this->oauthFetcher->getResponseMetadata();
-      $json = array($url => $metadata);
-      $json = json_encode($json);
-      $output = UNPARSEABLE_CRUFT . $json;
-      $this->setCachingHeaders();
-      header("Content-Type: application/json; charset=utf-8", true);
-      echo $output;
-      die();
-    }
-    $status = (int)$result->getHttpCode();
-    //header("HTTP/1.1 $status", true);
-    if ($status == 200) {
-      $output = '';
-      if (isset($_REQUEST['contentType']) && $_REQUEST['contentType'] == 'FEED') {
-        require 'external/Zend/Feed.php';
-        $numEntries = $_REQUEST['numEntries'];
-        $getSummaries = ! empty($_REQUEST['getSummaries']) && $_REQUEST['getSummaries'] != 'false' ? true : false;
-        $channel = array();
-        $request = new RemoteContentRequest($url);
-        $request = $this->context->getHttpFetcher()->fetch($request, $this->context);
-        if ((int)$result->getHttpCode() == 200) {
-          $content = $result->getResponseContent();
-          try {
-            $feed = Zend_Feed::importString($content);
-            if ($feed instanceof Zend_Feed_Rss) {
-              // Try get author
-              if ($feed->author()) {
-                $author = $feed->author();
-              } else {
-                if ($feed->creator()) {
-                  $author = $feed->creator();
-                } else {
-                  $author = null;
-                }
-              }
-              // Loop over each channel item and store relevant data
-              $counter = 0;
-              $channel['Entry'] = array();
-              foreach ($feed as $item) {
-                if ($counter >= $numEntries) {
-                  break;
-                }
-                $_entry = array();
-                $_entry['Title'] = $item->title();
-                $_entry['Link'] = $item->link();
-                if ($getSummaries && $item->description()) {
-                  $_entry['Summary'] = $item->description();
-                }
-                $date = 0;
-                if ($item->date()) {
-                  $date = strtotime($item->date());
-                } else {
-                  if ($item->pubDate()) {
-                    $date = strtotime($item->pubDate());
-                  }
-                }
-                $_entry['Date'] = $date;
-                $channel['Entry'][] = $_entry;
-                // Remember author if first found
-                if (empty($author) && $item->author()) {
-                  $author = $item->author();
-                } else if ($item->creator()) {
-                  $author = $item->creator();
-                }
-                $counter ++;
-              }
-              $channel['Title'] = $feed->title();
-              $channel['URL'] = $url;
-              $channel['Description'] = $feed->description();
-              if ($feed->link()) {
-                if (is_array($feed->link())) {
-                  foreach ($feed->link() as $_link) {
-                    if ($_link->nodeValue) $channel['Link'] = $_link->nodeValue;
-                  }
-                } else {
-                  $channel['Link'] = $feed->link();
-                }
-              }
-              if ($author != null) {
-                $channel['Author'] = $author;
-              }
-            } elseif ($feed instanceof Zend_Feed_Atom) {
-              // Try get author
-              if ($feed->author()) {
-                if ($feed->author->name()) {
-                  $author = $feed->author->name();
-                } else if ($feed->author->email()) {
-                  $author = $feed->author->email();
-                } else {
-                  $author = $feed->author();
-                }
-              } else {
-                $author = null;
-              }
-              // Loop over each entries and store relevant data
-              $counter = 0;
-              $channel['Entry'] = array();
-              foreach ($feed as $entry) {
-                if ($counter >= $numEntries) {
-                  break;
-                }
-                $_entry = array();
-                $_entry['Title'] = $entry->title();
-                // get Link if rel="alternate"
-                if ($entry->link('alternate')) {
-                  $_entry['Link'] = $entry->link('alternate');
-                } else {
-                  // if there's no alternate, pick the one without "rel" attribtue
-                  $_links = $entry->link;
-                  if (is_array($_links)) {
-                    foreach ($_links as $_link) {
-                      if (empty($_link['rel'])) {
-                        $_entry['Link'] = $_link['href'];
-                        break;
-                      }
-                    }
-                  } else {
-                    $_entry['Link'] = $_links['href'];
-                  }
-                }
-                if ($getSummaries && $entry->summary()) {
-                  $_entry['Summary'] = $entry->summary();
-                }
-                $date = 0;
-                if ($entry->updated()) {
-                  $date = strtotime($entry->updated());
-                } else {
-                  if ($entry->published()) {
-                    $date = strtotime($entry->published());
-                  }
-                }
-                $_entry['Date'] = $date;
-                $channel['Entry'][] = $_entry;
-                // Remember author if first found
-                if (empty($author) && $entry->author()) {
-                  if ($entry->author->name()) {
-                    $author = $entry->author->name();
-                  } else if ($entry->author->email()) {
-                    $author = $entry->author->email();
-                  } else {
-                    $author = $entry->author();
-                  }
-                } elseif (empty($author)) {
-                  $author = null;
-                }
-                $counter ++;
-              }
-              $channel['Title'] = $feed->title();
-              $channel['URL'] = $url;
-              $channel['Description'] = $feed->subtitle();
-              // get Link if rel="alternate"
-              if ($feed->link('alternate')) {
-                $channel['Link'] = $feed->link('alternate');
-              } else {
-                // if there's no alternate, pick the one without "rel" attribtue
-                $_links = $feed->link;
-                if (is_array($_links)) {
-                  foreach ($_links as $_link) {
-                    if (empty($_link['rel'])) {
-                      $channel['Link'] = $_link['href'];
-                      break;
-                    }
-                  }
-                } else {
-                  $channel['Link'] = $_links['href'];
-                }
-              }
-              if (! empty($author)) {
-                $channel['Author'] = $author;
-              }
-            } else {
-              throw new Exception('Invalid feed type');
-            }
-            $resp = json_encode($channel);
-          } catch (Zend_Feed_Exception $e) {
-            $resp = 'Error parsing feed: ' . $e->getMessage();
-          }
-        } else {
-          // feed import failed
-          $resp = "Error fetching feed, response code: " . $result->getHttpCode();
-        }
-      } else {
-        $resp = $result->getResponseContent();
-      }
-      $json = array($url => array('body' => $resp, 'rc' => $status));
-      $json = json_encode($json);
-      $output = UNPARSEABLE_CRUFT . $json;
-      $this->setCachingHeaders();
-      //	header("Content-Type: 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();
-  }
+class ProxyHandler extends ProxyBase {
 
   /**
    * Fetches the content and returns it as-is using the headers as returned
    * by the remote host.
    *
    * @param string $url the url to retrieve
-   * @param GadgetSigner $signer the GadgetSigner to use
-   * @param string $method either get or post
    */
-  public function fetch($url, $signer, $method) {
+  public function fetch($url) {
     $url = $this->validateUrl($url);
-    //TODO: Fetcher needs to handle variety of HTTP methods.
-    $result = $this->fetchContent($url, $method);
-    // TODO: Fetcher needs to handle variety of HTTP methods.
+    $result = $this->fetchContent($url, 'GET');
     $status = (int)$result->getHttpCode();
     if ($status == 200) {
       $headers = explode("\n", $result->getResponseHeaders());
@@ -277,12 +45,14 @@
       foreach ($headers as $header) {
         if (strpos($header, ':')) {
           $key = trim(substr($header, 0, strpos($header, ':')));
+          $key = str_replace(' ', '-', ucwords(str_replace('-', ' ', $key))); // force the header name to have the proper Header-Name casing
           $val = trim(substr($header, strpos($header, ':') + 1));
           // filter out headers that would otherwise mess up our output
-          if (strcasecmp($key, "Transfer-Encoding") != 0 && strcasecmp($key, "Cache-Control") != 0 && strcasecmp($key, "Expires") != 0 && strcasecmp($key, "Content-Length") != 0 && strcasecmp($key, "ETag") != 0) {
-            header("$key: $val");
+          if (! in_array($key, $this->disallowedHeaders)) {
+            header("$key: $val", true);
+          } else {
           }
-          if ($key == 'Content-Type' && $val == 'application/x-shockwave-flash') {
+          if ($key == 'Content-Type' && strtolower($val) == 'application/x-shockwave-flash') {
             // We're skipping the content disposition header for flash due to an issue with Flash player 10
             // This does make some sites a higher value phishing target, but this can be mitigated by
             // additional referer checks.
@@ -290,28 +60,21 @@
           }
         }
       }
-      if (!$isShockwaveFlash) {
+      if (! $isShockwaveFlash) {
         header('Content-Disposition: attachment;filename=p.txt');
       }
-      $etag = md5($result->getResponseContent());
       $lastModified = $result->getResponseHeader('Last-Modified') != null ? $result->getResponseHeader('Last-Modified') : gmdate('D, d M Y H:i:s', $result->getCreated()) . ' GMT';
       $notModified = false;
-      // If HTTP_PRAGMA | HTTP_CACHE_CONTROL == no-cache, the browser wants to do a 'forced reload'
-      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 (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $etag) {
-          // if e-tag's match, set not modified, and no need to check the if-modified-since headers
+      if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $lastModified && ! isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
+        $if_modified_since = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
+        // Use the request's Last-Modified, otherwise fall back on our internal time keeping (the time the request was created)
+        $lastModified = strtotime($lastModified);
+        if ($lastModified <= $if_modified_since) {
           $notModified = true;
-        } elseif (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $lastModified && ! isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
-          $if_modified_since = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
-          // Use the request's Last-Modified, otherwise fall back on our internal time keeping (the time the request was created)
-          $lastModified = strtotime($lastModified);
-          if ($lastModified <= $if_modified_since) {
-            $notModified = true;
-          }
         }
       }
-      $this->setCachingHeaders($etag, $this->context->getRefreshInterval(), $lastModified);
-      // If the cached file time is within the refreshInterval params value and the ETag match, return not-modified
+      $this->setCachingHeaders($lastModified);
+      // If the cached file time is within the refreshInterval params value, return not-modified
       if ($notModified) {
         header('HTTP/1.0 304 Not Modified', true);
         header('Content-Length: 0', true);
@@ -325,150 +88,5 @@
       echo "<html><body><h1>404 - Not Found ($status)</h1>";
       echo "</body></html>";
     }
-    // make sure the HttpServlet destructor doesn't override ours
-    die();
-  }
-
-  /**
-   * Both fetch and fetchJson call this function to retrieve the actual content
-   *
-   * @param string $url the url to fetch
-   * @param string $method either get or post
-   * @return the filled in request (RemoteContentRequest)
-   */
-  private function fetchContent($url, $method) {
-    //TODO get actual character encoding from the request
-
-    // Check the protocol requested - curl doesn't really support file://
-    // requests but the 'error' should be handled properly
-    $protocolSplit = explode('://', $url, 2);
-    if (count($protocolSplit) < 2) {
-      throw new Exception("Invalid protocol specified");
-    } else {
-      $protocol = strtoupper($protocolSplit[0]);
-      if ($protocol != "HTTP" && $protocol != "HTTPS" && $protocol != "FTP") {
-        throw new Exception("Invalid protocol specified in url ($protocol)");
-      }
-    }
-
-    // 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) {
-      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 = '';
-      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);
-        }
-      }
-      // 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($url, $headers, $postData);
-      $request = $this->context->getHttpFetcher()->fetch($request, $context);
-    } else {
-      $request = new RemoteContentRequest($url, $headers);
-      $request = $this->context->getHttpFetcher()->fetch($request, $context);
-    }
-    return $request;
-  }
-
-  private function fetchContentDivert($url, $method, $signer) {
-    $authz = isset($_GET['authz']) ? $_GET['authz'] : (isset($_POST['authz']) ? $_POST['authz'] : '');
-    $token = $this->context->extractAndValidateToken($signer);
-    switch (strtoupper($authz)) {
-      case 'SIGNED':
-        $fetcher = $this->signingFetcher->getSigningFetcher(new BasicRemoteContentFetcher(), $token);
-        return $fetcher->fetch($url, $method);
-      case 'OAUTH':
-        $params = new OAuthRequestParams();
-        $fetcher = $this->signingFetcher->getSigningFetcher(new BasicRemoteContentFetcher(), $token);
-        $oAuthFetcherFactory = new OAuthFetcherFactory($fetcher);
-        $this->oauthFetcher = $oAuthFetcherFactory->getOAuthFetcher($fetcher, $token, $params);
-        $request = new RemoteContentRequest($url);
-        $request->createRemoteContentRequestWithUri($url);
-        return $this->oauthFetcher->fetch($request);
-      case 'NONE':
-      default:
-        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.
-   *
-   */
-  private function setCachingHeaders($etag = false, $maxAge = false, $lastModified = false) {
-    if ($etag) {
-      header("ETag: $etag");
-    }
-    if ($lastModified) {
-      header("Last-Modified: $lastModified");
-    }
-    $expires = $maxAge !== false ? time() + $maxAge : time() - 3000;
-    $public = $maxAge ? 'public' : 'private';
-    $maxAge = $maxAge === false ? '0' : $maxAge;
-    header("Cache-Control: {$public}; max-age={$maxAge}", true);
-    header("Expires: " . gmdate("D, d M Y H:i:s", $expires) . " GMT", true);
-  }
-
-  /**
-   * Empty function, should make something practical here some day.
-   * it's function should be to validate the given url if its in
-   * correct http(s):port://location/url format
-   *
-   * @param string $url
-   * @return string the 'validated' url
-   */
-  private function validateUrl($url) {
-    if (! @parse_url($url)) {
-      throw new Exception("Invalid Url");
-    } else {
-      return $url;
-    }
-  }
-
-  private 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;
   }
 }

Added: incubator/shindig/trunk/php/src/gadgets/render/GadgetHrefRenderer.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/render/GadgetHrefRenderer.php?rev=744702&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/render/GadgetHrefRenderer.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/render/GadgetHrefRenderer.php Sun Feb 15 17:35:05 2009
@@ -0,0 +1,25 @@
+<?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 GadgetHrefRenderer extends GadgetRenderer {
+  public function renderGadget(Gadget $gadget, $view) {
+    echo "render href";
+  }
+}

Added: incubator/shindig/trunk/php/src/gadgets/render/GadgetHtmlRenderer.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/render/GadgetHtmlRenderer.php?rev=744702&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/render/GadgetHtmlRenderer.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/render/GadgetHtmlRenderer.php Sun Feb 15 17:35:05 2009
@@ -0,0 +1,149 @@
+<?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 EmptyClass {
+}
+
+/**
+ * Renders a Gadget's Content type="html" view, inlining the content, feature javascript and javascript initialization
+ * into the gadget's content
+ *
+ */
+class GadgetHtmlRenderer extends GadgetRenderer {
+
+  public function renderGadget(Gadget $gadget, $view) {
+
+    // Was a privacy policy header configured? if so set it
+    if (Config::get('P3P') != '') {
+      header("P3P: " . Config::get('P3P'));
+    }
+
+    $content = '';
+    // Set doctype if quirks = false or empty in the view
+    if (! empty($view['quirks']) || ! $view['quirks']) {
+      $content .= "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n";
+    }
+    $content .= "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/><style type=\"text/css\">" . Config::get('gadget_css') . "</style></head><body>\n";
+
+    // Inject the OpenSocial feature javascripts
+    $forcedJsLibs = $this->getForcedJsLibs();
+    if (! empty($forcedJsLibs)) {
+      // if some of the feature libraries are externalized (through a browser cachable <script src="/gadgets/js/opensocial-0.9:settitle.js"> type url)
+      // we inject the tag and don't inline those libs (and their dependencies)
+      $forcedJsLibs = explode(':', $forcedJsLibs);
+      $content .= sprintf("<script src=\"%s\"></script>\n", Config::get('default_js_prefix') . $this->getJsUrl($forcedJsLibs, $gadget) . "&container=" . $this->context->getContainer()) . "\n";
+      $registry = $this->context->getRegistry();
+      $missing = array();
+      $registry->resolveFeatures($forcedJsLibs, $forcedJsLibs, $missing);
+    }
+    $content .= "<script>\n";
+    foreach ($gadget->features as $feature) {
+      if (! count($forcedJsLibs) || ! in_array($feature, $forcedJsLibs)) {
+        $content .= $this->context->getRegistry()->getFeatureContent($feature, $this->context, true);
+      }
+    }
+
+    // Add the JavaScript initialization strings for the configuration, localization and preloads
+    $content .= $this->appendJsConfig($gadget, count($forcedJsLibs));
+    $content .= $this->appendMessages($gadget);
+    $content .= $this->appendPreloads($gadget);
+    $content .= "</script>";
+
+    // Append the content from the view
+    $content .= $gadget->substitutions->substitute($view['content']);
+
+    // And add our runOnLoadHandlers() call
+    $content .= "\n<script>gadgets.util.runOnLoadHandlers();</script></body>\n</html>";
+    echo $content;
+  }
+
+  /**
+   * Retrieve the forced javascript libraries (if any), using either the &libs= from the query
+   * or if that's empty, from the config
+   *
+   * @return unknown
+   */
+  private function getForcedJsLibs() {
+    $forcedJsLibs = $this->context->getForcedJsLibs();
+    // allow the &libs=.. param to override our forced js libs configuration value
+    if (empty($forcedJsLibs)) {
+      $forcedJsLibs = Config::get('focedJsLibs');
+    }
+    return $forcedJsLibs;
+  }
+
+  /**
+   * Appends the javascript features configuration string
+   *
+   * @param Gadget $gadget
+   * @param unknown_type $hasForcedLibs
+   * @return string
+   */
+  private function appendJsConfig(Gadget $gadget, $hasForcedLibs) {
+    $container = $this->context->getContainer();
+    $containerConfig = $this->context->getContainerConfig();
+    //TODO some day we should parse the forcedLibs too, and include their config selectivly as well for now we just include everything if forced libs is set.
+    if ($hasForcedLibs) {
+      $gadgetConfig = $containerConfig->getConfig($container, 'gadgets.features');
+    } else {
+      $gadgetConfig = array();
+      $featureConfig = $containerConfig->getConfig($container, 'gadgets.features');
+      foreach ($gadget->getJsLibraries() as $library) {
+        $feature = $library->getFeatureName();
+        if (! isset($gadgetConfig[$feature]) && ! empty($featureConfig[$feature])) {
+          $gadgetConfig[$feature] = $featureConfig[$feature];
+        }
+      }
+    }
+    // Add gadgets.util support. This is calculated dynamically based on request inputs.
+    // See java/org/apache/shindig/gadgets/render/RenderingContentRewriter.java for reference.
+    $requires = array();
+    foreach ($gadget->features as $feature) {
+      $requires[$feature] = new EmptyClass();
+    }
+    $gadgetConfig['core.util'] = $requires;
+    return "gadgets.config.init(" . json_encode($gadgetConfig) . ");\n";
+  }
+
+  /**
+   * Injects the relevant translation message bundle into the javascript api
+   *
+   * @param Gadget $gadget
+   * @return string
+   */
+  private function appendMessages(Gadget $gadget) {
+    $msgs = '';
+    if (! empty($gadget->gadgetSpec->locales)) {
+      $msgs = json_encode($gadget->gadgetSpec->locales);
+    }
+    return "gadgets.Prefs.setMessages_($msgs);\n";
+  }
+
+  /**
+   * Injects the preloaded content into the javascript api
+   *
+   * @param Gadget $gadget
+   * @return string
+   */
+  private function appendPreloads(Gadget $gadget) {
+    return "gadgets.io.preloaded_ = " . (count($gadget->gadgetSpec->preloads) ? json_encode($gadget->gadgetSpec->preloads) : "{}") . ";\n";
+  }
+}

Added: incubator/shindig/trunk/php/src/gadgets/render/GadgetRenderer.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/render/GadgetRenderer.php?rev=744702&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/render/GadgetRenderer.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/render/GadgetRenderer.php Sun Feb 15 17:35:05 2009
@@ -0,0 +1,63 @@
+<?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.
+ */
+
+abstract class GadgetRenderer {
+  protected $context;
+
+  public function __construct(GadgetContext $context) {
+    $this->context = $context;
+  }
+
+  /**
+   * generates the library string (core:caja:etc.js) including a checksum of all the
+   * javascript content (?v=<md5 of js>) for cache busting
+   *
+   * @param string $libs
+   * @param Gadget $gadget
+   * @return string the list of libraries in core:caja:etc.js?v=checksum> format
+   */
+  protected function getJsUrl($features) {
+    $ret = '';
+    if (! is_array($features) || ! count($features)) {
+      $ret = 'core';
+    } else {
+      $ret = implode(':', $features);
+    }
+    $cache = Config::get('feature_cache');
+    $cache = new $cache();
+    if (($md5 = $cache->get(md5('getJsUrlMD5'))) === false) {
+      $registry = $this->context->getRegistry();
+      $features = $registry->features;
+
+      // Build a version string from the md5() checksum of all included javascript
+      // to ensure the client always has the right version
+      $inlineJs = '';
+      foreach ($features as $feature => $content) {
+        $inlineJs .= $registry->getFeatureContent($feature, $this->context, true);
+      }
+      $md5 = md5($inlineJs);
+      $cache->set(md5('getJsUrlMD5'), $md5);
+    }
+    $ret .= ".js?v=" . $md5;
+    return $ret;
+  }
+
+  abstract function renderGadget(Gadget $gadget, $view);
+}
\ No newline at end of file

Added: incubator/shindig/trunk/php/src/gadgets/render/GadgetUrlRenderer.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/render/GadgetUrlRenderer.php?rev=744702&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/render/GadgetUrlRenderer.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/render/GadgetUrlRenderer.php Sun Feb 15 17:35:05 2009
@@ -0,0 +1,90 @@
+<?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 GadgetUrlRenderer extends GadgetRenderer {
+
+  /**
+   * Renders an 'URL' type view (where the iframe is redirected to the specified url)
+   * This is more a legacy iGoogle support feature then something that should be actually
+   * used. Proxied content is the socially aware (and higher performance) version of this
+   * See GadgetHrefRenderer for it's implementation.
+   *
+   * @param Gadget $gadget
+   * @param Array $view
+   */
+  public function renderGadget(Gadget $gadget, $view) {
+    // Preserve existing query string parameters.
+    $redirURI = $view['href'];
+    $queryStr = strpos($redirURI, '?') !== false ? substr($redirURI, strpos($redirURI, '?')) : '';
+    $query = $queryStr;
+    $query .= $this->getPrefsQueryString($gadget->gadgetSpec->userPrefs);
+    $features = array();
+    $forcedLibs = Config::get('focedJsLibs');
+    if ($forcedLibs == null) {
+      $features = $gadget->features;
+    } else {
+      $features = explode(':', $forcedLibs);
+    }
+    $query .= $this->appendLibsToQuery($features);
+    // 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) == '&') {
+      $query = '?' . substr($query, 1);
+    }
+    $redirURI .= $query;
+    header('Location: ' . $redirURI);
+  }
+
+  /**
+   * Returns the requested libs (from getjsUrl) with the libs_param_name prepended
+   * ie: in libs=core:caja:etc.js format
+   *
+   * @param string $libs the libraries
+   * @param Gadget $gadget
+   * @return string the libs=... string to append to the redirection url
+   */
+  private function appendLibsToQuery($features) {
+    $ret = "&";
+    $ret .= Config::get('libs_param_name');
+    $ret .= "=";
+    $ret .= str_replace('?', '&', $this->getJsUrl($features));
+    return $ret;
+  }
+
+  /**
+   * Returns the user preferences in &up_<name>=<val> format
+   *
+   * @param array $libs array of features this gadget requires
+   * @param Gadget $gadget
+   * @return string the up_<name>=<val> string to use in the redirection url
+   */
+  private function getPrefsQueryString($prefs) {
+    $ret = '';
+    foreach ($prefs as $pref) {
+      $ret .= '&';
+      $ret .= Config::get('userpref_param_prefix');
+      $ret .= urlencode($pref['name']);
+      $ret .= '=';
+      $ret .= urlencode($pref['value']);
+    }
+    return $ret;
+  }
+}

Modified: incubator/shindig/trunk/php/src/gadgets/servlet/GadgetRenderingServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/servlet/GadgetRenderingServlet.php?rev=744702&r1=744701&r2=744702&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/servlet/GadgetRenderingServlet.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/servlet/GadgetRenderingServlet.php Sun Feb 15 17:35:05 2009
@@ -18,131 +18,76 @@
  * under the License.
  */
 
-require 'src/common/HttpServlet.php';
-require 'src/gadgets/GadgetContext.php';
-require 'src/gadgets/GadgetServer.php';
-require 'src/common/RemoteContentRequest.php';
-require 'src/common/RemoteContent.php';
-require 'src/common/Cache.php';
-require 'src/common/RemoteContentFetcher.php';
-require 'src/gadgets/GadgetSpecParser.php';
-require 'src/gadgets/Gadget.php';
-require 'src/gadgets/GadgetId.php';
-require 'src/gadgets/UserPrefs.php';
-require 'src/gadgets/Substitutions.php';
-require 'src/gadgets/LocaleSpec.php';
-require 'src/gadgets/LocaleMessageBundle.php';
-require 'src/gadgets/GadgetBlacklist.php';
-require 'src/common/Locale.php';
-require 'src/gadgets/UserPref.php';
-require 'src/gadgets/ViewSpec.php';
-require 'src/gadgets/FeatureSpec.php';
-require 'src/gadgets/MessageBundleParser.php';
-require 'src/gadgets/MessageBundle.php';
-require 'src/gadgets/GadgetFeatureRegistry.php';
-require 'src/gadgets/GadgetFeatureFactory.php';
-require 'src/gadgets/GadgetFeature.php';
-require 'src/gadgets/JsLibraryFeatureFactory.php';
-require 'src/gadgets/JsLibrary.php';
-require 'src/gadgets/HttpUtil.php';
-require 'src/gadgets/ContainerConfig.php';
-require 'src/common/JsMin.php';
-require 'src/common/SecurityTokenDecoder.php';
-require 'src/common/SecurityToken.php';
-require 'src/common/BlobCrypter.php';
-require 'src/gadgets/rewrite/ContentRewriter.php';
-require 'src/gadgets/rewrite/ContentRewriteFeature.php';
+require_once 'src/common/HttpServlet.php';
+require_once 'src/common/JsMin.php';
+require_once 'src/common/SecurityTokenDecoder.php';
+require_once 'src/common/SecurityToken.php';
+require_once 'src/common/BlobCrypter.php';
+require_once 'src/common/RemoteContentRequest.php';
+require_once 'src/common/RemoteContent.php';
+require_once 'src/common/Cache.php';
+require_once 'src/common/RemoteContentFetcher.php';
+require_once 'src/common/sample/BasicRemoteContent.php';
+require_once 'src/common/sample/BasicRemoteContentFetcher.php';
+require_once 'src/gadgets/GadgetSpecParser.php';
+require_once 'src/gadgets/GadgetBlacklist.php';
+require_once 'src/gadgets/sample/BasicGadgetBlacklist.php';
+require_once 'src/gadgets/GadgetContext.php';
+require_once 'src/gadgets/GadgetFactory.php';
+require_once 'src/gadgets/GadgetSpec.php';
+require_once 'src/gadgets/Gadget.php';
+require_once 'src/gadgets/render/GadgetRenderer.php';
 
-/**
- * This class deals with the gadget rendering requests (in default config this
- * would be /gadgets/ifr?url=<some gadget's url>). It uses the gadget server and
- * gadget context to render the xml to a valid html file, and outputs it.
- *
- */
 class GadgetRenderingServlet extends HttpServlet {
   private $context;
 
-  /**
-   * Creates the gadget using the GadgetServer class and calls outputGadget
-   *
-   */
   public function doGet() {
     try {
       if (empty($_GET['url'])) {
         throw new GadgetException("Missing required parameter: url");
       }
-      // GadgetContext builds up all the contextual variables (based on the url or post)
-      // plus instances all required classes (feature registry, fetcher, blacklist, etc)
       $this->context = new GadgetContext('GADGET');
-      // Unfortunatly we can't do caja content filtering here, hoping we'll have a RPC service
-      // or command line caja to use for this at some point
-      $gadgetServer = new GadgetServer();
-      $gadget = $gadgetServer->processGadget($this->context);
-      $this->outputGadget($gadget, $this->context);
+      $gadgetSigner = Config::get('security_token_signer');
+      $gadgetSigner = new $gadgetSigner();
+      try {
+        $token = $this->context->extractAndValidateToken($gadgetSigner);
+      } catch (Exception $e) {
+        // no token given, this is a fatal error if 'render_token_required' is set to true
+        if (Config::get('render_token_required')) {
+          $this->showError($e);
+        } else {
+          $token = '';
+        }
+      }
+      $gadgetSpecFactory = new GadgetFactory($this->context, $token);
+      $gadget = $gadgetSpecFactory->createGadget();
+      $this->setCachingHeaders();
+      $this->renderGadget($gadget);
     } catch (Exception $e) {
-      $this->outputError($e);
-    }
-  }
-
-  /**
-   * If an error occured (Exception) this function echo's the Exception's message
-   * and if the config['debug'] is true, shows the debug backtrace in a div
-   *
-   * @param Exception $e the exception to show
-   */
-  private function outputError($e) {
-    header("HTTP/1.0 400 Bad Request", true, 400);
-    echo "<html><body>";
-    echo "<h1>Error</h1>";
-    echo $e->getMessage();
-    if (Config::get('debug')) {
-      echo "<p><b>Debug backtrace</b></p><div style='overflow:auto; height:300px; border:1px solid #000000'><pre>";
-      print_r(debug_backtrace());
-      echo "</pre></div>>";
+      $this->showError($e);
     }
-    echo "</body></html>";
   }
 
-  /**
-   * Takes the gadget to output, and depending on its content type calls either outputHtml-
-   * or outputUrlGadget
-   *
-   * @param Gadget $gadget gadget to render
-   * @param string $view the view to render (only valid with a html content type)
-   */
-  private function outputGadget($gadget, $context) {
-    $view = HttpUtil::getView($gadget, $context);
-    switch ($view->getType()) {
-      case 'HTML':
-        $this->outputHtmlGadget($gadget, $context, $view);
-        break;
-      case 'URL':
-        $this->outputUrlGadget($gadget, $context, $view);
-        break;
+  private function renderGadget(Gadget $gadget) {
+    $view = $gadget->getView($this->context->getView());
+    if ($view['type'] == 'URL') {
+      require_once "src/gadgets/render/GadgetUrlRenderer.php";
+      $gadgetRenderer = new GadgetUrlRenderer($this->context);
+    } elseif ($view['type'] == 'HTML' && empty($view['href'])) {
+      require_once "src/gadgets/render/GadgetHtmlRenderer.php";
+      $gadgetRenderer = new GadgetHtmlRenderer($this->context);
+    } elseif (empty($view['type']) || ! empty($view['href'])) {
+      require_once "src/gadgets/render/GadgetHrefRenderer.php";
+      $gadgetRenderer = new GadgetHrefRenderer($this->context);
+    } else {
+      throw new GadgetException("Invalid view type");
     }
+    $gadgetRenderer->renderGadget($gadget, $view);
   }
 
-  /**
-   * Outputs a html content type gadget.
-   * It creates a html page, with the javascripts from the features inline into the page, plus
-   * calls to 'gadgets.config.init' with the container configuration (config/container.js) and
-   * 'gadgets.Prefs.setMessages_' with all the substitutions. For external javascripts it adds
-   * a <script> tag.
-   *
-   * @param Gadget $gadget
-   * @param GadgetContext $context
-   */
-  private function outputHtmlGadget($gadget, $context, $view) {
-    $content = '';
-    $externJs = '';
-    $externFmt = "<script src=\"%s\"></script>";
-    $forcedLibs = $context->getForcedJsLibs();
-    // allow the &libs=.. param to override our forced js libs configuration value
-    if (empty($forcedLibs)) {
-      $forcedLibs = Config::get('focedJsLibs');
-    }
+  private function setCachingHeaders() {
     $this->setContentType("text/html; charset=UTF-8");
-    if ($context->getIgnoreCache()) {
+    if ($this->context->getIgnoreCache()) {
       // no cache was requested, set non-caching-headers
       $this->setNoCache(true);
     } elseif (isset($_GET['v'])) {
@@ -152,299 +97,19 @@
       // no version was given, cache for 5 minutes
       $this->setCacheTime(5 * 60);
     }
-    // Was a privacy policy header configured? if so set it
-    if (Config::get('P3P') != '') {
-      header("P3P: " . Config::get('P3P'));
-    }
-    if (! $view->getQuirks()) {
-      $content .= "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n";
-    }
-    $content .= "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/><style type=\"text/css\">" . Config::get('gadget_css') . "</style></head><body>\n";
-    // Forced libs first.
-    if (! empty($forcedLibs)) {
-      $libs = explode(':', $forcedLibs);
-      $content .= sprintf($externFmt, Config::get('default_js_prefix') . $this->getJsUrl($libs, $gadget) . "&container=" . $context->getContainer()) . "\n";
-    }
-    $content .= "<script>\n";
-
-    if (! empty($forcedLibs)) {
-      // if some of the feature libraries are externalized (through a browser cachable <script src="/gadgets/js/opensocial-0.7:settitle.js">
-      // type url), then we don't want to include dependencies twice, so find the complete features chain, so we can skip over those
-      $forcedLibsArray = explode(':', $forcedLibs);
-      $registry = $this->context->getRegistry();
-      $missing = array();
-      $registry->getIncludedFeatures($forcedLibsArray, $forcedLibsArray, $missing);
-    }
-    foreach ($gadget->getJsLibraries() as $library) {
-      $type = $library->getType();
-      if ($type == 'URL') {
-        // 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 check if there are no forcedLibs, or if it wasn't included in their dep chain
-      } elseif (empty($forcedLibs) || ! in_array($library->getFeatureName(), $forcedLibsArray)) {
-        $content .= $library->getContent();
-      }
-      // otherwise it was already included by config.forceJsLibs.
-    }
-    $content .= $this->appendJsConfig($context, $gadget, ! empty($forcedLibs)) . $this->appendMessages($gadget) . $this->appendPreloads($gadget, $context) . "</script>";
-    if (strlen($externJs) > 0) {
-      $content .= $externJs;
-    }
-    $gadgetExceptions = array();
-    $rewriter = new ContentRewriter();
-    if ($rewriter->rewriteGadgetView($gadget, $view)) {
-      $content .= $gadget->getSubstitutions()->substitute($view->getRewrittenContent());
-    } else {
-      $content .= $gadget->getSubstitutions()->substitute($view->getContent());
-    }
-    if (empty($content)) {
-      // Unknown view
-      $gadgetExceptions[] = "View: '" . $context->getView() . "' invalid for gadget: " . $gadget->getId()->getKey();
-    }
-    if (count($gadgetExceptions)) {
-      throw new GadgetException(print_r($gadgetExceptions, true));
-    }
-    $content .= "\n<script>gadgets.util.runOnLoadHandlers();</script></body>\n</html>";
-    echo $content;
   }
 
-  /**
-   * Output's a URL content type gadget, it adds libs=<list:of:js:libraries>.js and user preferences
-   * to the href url, and redirects the browser to it
-   *
-   * @param Gadget $gadget
-   */
-  private function outputUrlGadget($gadget, $context, $view) {
-    // Preserve existing query string parameters.
-    $redirURI = $view->getHref();
-    $queryStr = strpos($redirURI, '?') !== false ? substr($redirURI, strpos($redirURI, '?')) : '';
-    $query = $queryStr;
-    // TODO: userprefs on the fragment rather than query string
-    $query .= $this->getPrefsQueryString($gadget->getUserPrefValues());
-    $libs = array();
-    $forcedLibs = Config::get('focedJsLibs');
-    if ($forcedLibs == null) {
-      $reqs = $gadget->getRequires();
-      foreach ($reqs as $key => $val) {
-        $libs[] = $key;
-      }
-    } else {
-      $libs = explode(':', $forcedLibs);
-    }
-    $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) == '&') {
-      $query = '?' . substr($query, 1);
+  private function showError($e) {
+    header("HTTP/1.0 400 Bad Request", true, 400);
+    echo "<html><body>";
+    echo "<h1>Error</h1>";
+    echo $e->getMessage();
+    if (Config::get('debug')) {
+      echo "<p><b>Debug backtrace</b></p><div style='overflow:auto; height:300px; border:1px solid #000000'><pre>";
+      print_r(debug_backtrace());
+      echo "</pre></div>>";
     }
-    $redirURI .= $query;
-    header('Location: ' . $redirURI);
+    echo "</body></html>";
     die();
   }
-
-  /**
-   * Returns the requested libs (from getjsUrl) with the libs_param_name prepended
-   * ie: in libs=core:caja:etc.js format
-   *
-   * @param string $libs the libraries
-   * @param Gadget $gadget
-   * @return string the libs=... string to append to the redirection url
-   */
-  private function appendLibsToQuery($libs, $gadget) {
-    $ret = "&";
-    $ret .= Config::get('libs_param_name');
-    $ret .= "=";
-    $ret .= $this->getJsUrl($libs, $gadget);
-    return $ret;
-  }
-
-  /**
-   * Returns the user preferences in &up_<name>=<val> format
-   *
-   * @param array $libs array of features this gadget requires
-   * @param Gadget $gadget
-   * @return string the up_<name>=<val> string to use in the redirection url
-   */
-  private function getPrefsQueryString($prefVals) {
-    $ret = '';
-    foreach ($prefVals->getPrefs() as $key => $val) {
-      $ret .= '&';
-      $ret .= Config::get('userpref_param_prefix');
-      $ret .= urlencode($key);
-      $ret .= '=';
-      $ret .= urlencode($val);
-    }
-    return $ret;
-  }
-
-  /**
-   * generates the library string (core:caja:etc.js) including a checksum of all the
-   * javascript content (?v=<md5 of js>) for cache busting
-   *
-   * @param string $libs
-   * @param Gadget $gadget
-   * @return string the list of libraries in core:caja:etc.js?v=checksum> format
-   */
-  private function getJsUrl($libs, $gadget) {
-    $buf = '';
-    if (! is_array($libs) || ! count($libs)) {
-      $buf = 'core';
-    } else {
-      $firstDone = false;
-      foreach ($libs as $lib) {
-        if ($firstDone) {
-          $buf .= ':';
-        } else {
-          $firstDone = true;
-        }
-        $buf .= $lib;
-      }
-    }
-    $cache = Config::get('feature_cache');
-    $cache = new $cache();
-    if (($md5 = $cache->get(md5('getJsUrlMD5'))) === false) {
-      $registry = $this->context->getRegistry();
-      $features = $registry->getAllFeatures();
-      // Build a version string from the md5() checksum of all included javascript
-      // to ensure the client always has the right version
-      $inlineJs = '';
-      foreach ($features as $feature) {
-        $library = $feature->getFeature();
-        $libs = $library->getLibraries($this->context->getRenderingContext());
-        foreach ($libs as $lib) {
-          $inlineJs .= $lib->getContent();
-        }
-      }
-      $md5 = md5($inlineJs);
-      $cache->set(md5('getJsUrlMD5'), $md5);
-    }
-    $buf .= ".js?v=" . $md5;
-    return $buf;
-  }
-
-  private function appendJsConfig($context, $gadget, $hasForcedLibs) {
-    $container = $context->getContainer();
-    $containerConfig = $context->getContainerConfig();
-    //TODO some day we should parse the forcedLibs too, and include their config selectivly as well
-    // for now we just include everything if forced libs is set.
-    if ($hasForcedLibs) {
-      $gadgetConfig = $containerConfig->getConfig($container, 'gadgets.features');
-    } else {
-      $gadgetConfig = array();
-      $featureConfig = $containerConfig->getConfig($container, 'gadgets.features');
-      foreach ($gadget->getJsLibraries() as $library) {
-        $feature = $library->getFeatureName();
-        if (! isset($gadgetConfig[$feature]) && ! empty($featureConfig[$feature])) {
-          $gadgetConfig[$feature] = $featureConfig[$feature];
-        }
-      }
-    }
-
-    // Add gadgets.util support. This is calculated dynamically based on request inputs.
-    // See java/org/apache/shindig/gadgets/render/RenderingContentRewriter.java for reference.
-    $requires = array();
-    foreach ($gadget->getRequires() as $feature) {
-      $requires[$feature->name] = new EmptyClass();
-    }
-    $gadgetConfig['core.util'] = $requires;
-
-    return "gadgets.config.init(" . json_encode($gadgetConfig) . ");\n";
-  }
-
-  private function appendMessages($gadget) {
-    $msgs = '';
-    if ($gadget->getMessageBundle()) {
-      $bundle = $gadget->getMessageBundle();
-      $msgs = json_encode($bundle->getMessages());
-    }
-    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 = Array();
-    $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
-    }
-    $unsignedRequests = $unsignedContexts = Array();
-    $signedRequests = Array();
-    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":
-              //						Unify all unsigned requests to one single multi request
-              $unsignedRequests[] = $request;
-              $unsignedContexts[] = $context;
-              break;
-            case "SIGNED":
-              //						Unify all signed requests to one single multi request
-              $signingFetcherFactory = new SigningFetcherFactory(Config::get("private_key_file"));
-              $fetcher = $signingFetcherFactory->getSigningFetcher(new BasicRemoteContentFetcher(), $token);
-              $req = $fetcher->signRequest($preload->getHref(), $request->getMethod());
-              $req->setNotSignedUri($preload->getHref());
-              $signedRequests[] = $req;
-              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();
-          }
-        }
-      } catch (Exception $e) {
-        throw new Exception($e);
-      }
-    }
-    if (count($unsignedRequests)) {
-      try {
-        $brc = new BasicRemoteContent();
-        $responses = $brc->multiFetch($unsignedRequests, $unsignedContexts);
-        foreach ($responses as $response) {
-          $resp[$response->getUrl()] = array(
-              'body' => $response->getResponseContent(),
-              'rc' => $response->getHttpCode());
-        }
-      } catch (Exception $e) {
-        throw new Exception($e);
-      }
-    }
-    if (count($signedRequests)) {
-      try {
-        $fetcher = $signingFetcherFactory->getSigningFetcher(new BasicRemoteContentFetcher(), $token);
-        $responses = $fetcher->multiFetchRequest($signedRequests);
-        foreach ($responses as $response) {
-          $resp[$response->getNotSignedUrl()] = array(
-              'body' => $response->getResponseContent(),
-              'rc' => $response->getHttpCode());
-        }
-      } catch (Exception $e) {
-        throw new Exception($e);
-      }
-    }
-    $resp = count($resp) ? json_encode($resp) : "{}";
-    return "gadgets.io.preloaded_ = " . $resp . ";\n";
-  }
-}
-
-/*
- * An empty class for generate "{}" code in JavaScript.
- */
-class EmptyClass {
 }

Modified: incubator/shindig/trunk/php/src/gadgets/servlet/JsServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/servlet/JsServlet.php?rev=744702&r1=744701&r2=744702&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/servlet/JsServlet.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/servlet/JsServlet.php Sun Feb 15 17:35:05 2009
@@ -19,12 +19,8 @@
  */
 
 require 'src/common/HttpServlet.php';
+require 'src/gadgets/GadgetContext.php';
 require 'src/gadgets/GadgetFeatureRegistry.php';
-require 'src/gadgets/JsFeatureLoader.php';
-require 'src/gadgets/JsLibrary.php';
-require 'src/gadgets/GadgetFeatureFactory.php';
-require 'src/gadgets/GadgetFeature.php';
-require 'src/gadgets/JsLibraryFeatureFactory.php';
 
 /**
  * This event handler deals with the /js/core:caja:etc.js request which content type=url gadgets can use
@@ -58,29 +54,14 @@
     }
     $found = array();
     $missing = array();
+    $context = new GadgetContext('GADGET');
     $registry = new GadgetFeatureRegistry(Config::get('features_path'));
-    if ($registry->getIncludedFeatures($needed, $found, $missing)) {
-      $containerParam = isset($_GET["c"]) ? $_GET["c"] : '';
-      $context = $containerParam == '1' ? 'CONTAINER' : 'GADGET';
+    if ($registry->resolveFeatures($needed, $found, $missing)) {
+      $isGadgetContext = !isset($_GET["c"]) || $_GET['c'] == 0 ? true : false;
       $jsData = '';
-      $done = array();
-      do {
-        foreach ($found as $entry) {
-          if (! in_array($entry, $done)) {
-            $feat = $registry->getEntry($entry);
-            $feature = $feat->getFeature();
-            if ($feature instanceof JsLibraryFeatureFactory) {
-              $jsLib = $feature;
-              foreach ($jsLib->getLibraries($context) as $lib) {
-                if ($lib->getType() != 'URL') {
-                  $jsData .= $lib->getContent() . "\n";
-                }
-              }
-            }
-            $done[] = $entry;
-          }
-        }
-      } while (count($done) != count($found));
+      foreach ($found as $feature) {
+        $jsData .= $registry->getFeatureContent($feature, $context, $isGadgetContext);
+      }
       if (! strlen($jsData)) {
         header("HTTP/1.0 404 Not Found", true);
         die();
@@ -95,6 +76,7 @@
   }
 
   private function setCachingHeaders() {
+    // Expires far into the future
     header("Expires: Tue, 01 Jan 2030 00:00:01 GMT");
     // IE seems to need this (10 years should be enough).
     header("Cache-Control: public,max-age=315360000");

Added: incubator/shindig/trunk/php/src/gadgets/servlet/MakeRequestServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/servlet/MakeRequestServlet.php?rev=744702&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/servlet/MakeRequestServlet.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/servlet/MakeRequestServlet.php Sun Feb 15 17:35:05 2009
@@ -0,0 +1,62 @@
+<?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.
+ */
+
+require 'src/common/HttpServlet.php';
+require 'src/gadgets/GadgetContext.php';
+require 'src/gadgets/ProxyBase.php';
+require 'src/gadgets/MakeRequestHandler.php';
+require 'src/common/RemoteContentRequest.php';
+require 'src/common/RemoteContent.php';
+require 'src/common/Cache.php';
+require 'src/common/RemoteContentFetcher.php';
+require 'src/gadgets/oauth/OAuth.php';
+require 'src/gadgets/oauth/OAuthStore.php';
+
+class MakeRequestServlet extends HttpServlet {
+
+  public function doGet() {
+    try {
+      $this->noHeaders = true;
+      $context = new GadgetContext('GADGET');
+      $url = urldecode(isset($_GET['url']) ? $_GET['url'] : (isset($_POST['url']) ? $_POST['url'] : false));
+      if (! $url || empty($url)) {
+        header("HTTP/1.0 400 Bad Request", true);
+        echo "<html><body><h1>400 - Missing url parameter</h1></body></html>";
+      }
+      $method = (isset($_GET['httpMethod']) ? $_GET['httpMethod'] : (isset($_POST['httpMethod']) ? $_POST['httpMethod'] : 'GET'));
+      $signingFetcherFactory = $gadgetSigner = false;
+      if (! empty($_GET['authz']) || ! empty($_POST['authz'])) {
+        $gadgetSigner = Config::get('security_token_signer');
+        $gadgetSigner = new $gadgetSigner();
+        $signingFetcherFactory = new SigningFetcherFactory(Config::get("private_key_file"));
+      }
+      $makeRequestHandler = new MakeRequestHandler($context, $signingFetcherFactory);
+      $makeRequestHandler->fetchJson($url, $gadgetSigner, $method);
+    } catch (Exception $e) {
+      // catch all exceptions and give a 500 server error
+      header("HTTP/1.0 500 Internal Server Error");
+      echo "<h1>Internal server error</h1><p>" . $e->getMessage() . "</p>";
+    }
+  }
+
+  public function doPost() {
+    $this->doGet();
+  }
+}

Modified: incubator/shindig/trunk/php/src/gadgets/servlet/MetadataServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/servlet/MetadataServlet.php?rev=744702&r1=744701&r2=744702&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/servlet/MetadataServlet.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/servlet/MetadataServlet.php Sun Feb 15 17:35:05 2009
@@ -18,38 +18,26 @@
  * under the License.
  */
 
-require 'src/common/HttpServlet.php';
-require 'src/gadgets/MetadataHandler.php';
-require 'src/gadgets/GadgetContext.php';
-require 'src/gadgets/MetadataContext.php';
-require 'src/common/Locale.php';
-require 'src/gadgets/GadgetServer.php';
-require 'src/common/RemoteContentRequest.php';
-require 'src/common/RemoteContent.php';
-require 'src/common/Cache.php';
-require 'src/common/RemoteContentFetcher.php';
-require 'src/gadgets/GadgetSpecParser.php';
-require 'src/gadgets/Gadget.php';
-require 'src/gadgets/GadgetId.php';
-require 'src/gadgets/UserPrefs.php';
-require 'src/gadgets/Substitutions.php';
-require 'src/gadgets/ViewSpec.php';
-require 'src/gadgets/GadgetFeatureRegistry.php';
-require 'src/gadgets/GadgetFeatureFactory.php';
-require 'src/gadgets/GadgetFeature.php';
-require 'src/gadgets/JsLibraryFeatureFactory.php';
-require 'src/gadgets/JsLibrary.php';
-require 'src/common/UrlGenerator.php';
-require 'src/gadgets/HttpUtil.php';
-require 'src/gadgets/LocaleSpec.php';
-require 'src/gadgets/LocaleMessageBundle.php';
-require 'src/gadgets/UserPref.php';
-require 'src/gadgets/FeatureSpec.php';
-require 'src/gadgets/MessageBundleParser.php';
-require 'src/gadgets/MessageBundle.php';
-require 'src/gadgets/GadgetException.php';
-require 'src/gadgets/rewrite/ContentRewriter.php';
-require 'src/gadgets/rewrite/ContentRewriteFeature.php';
+require_once 'src/common/HttpServlet.php';
+require_once 'src/common/JsMin.php';
+require_once 'src/common/SecurityTokenDecoder.php';
+require_once 'src/common/SecurityToken.php';
+require_once 'src/common/BlobCrypter.php';
+require_once 'src/common/RemoteContentRequest.php';
+require_once 'src/common/RemoteContent.php';
+require_once 'src/common/Cache.php';
+require_once 'src/common/RemoteContentFetcher.php';
+require_once 'src/common/sample/BasicRemoteContent.php';
+require_once 'src/common/sample/BasicRemoteContentFetcher.php';
+require_once 'src/gadgets/GadgetSpecParser.php';
+require_once 'src/gadgets/GadgetBlacklist.php';
+require_once 'src/gadgets/sample/BasicGadgetBlacklist.php';
+require_once 'src/gadgets/GadgetContext.php';
+require_once 'src/gadgets/GadgetSpec.php';
+require_once 'src/gadgets/Gadget.php';
+require_once 'src/gadgets/GadgetFactory.php';
+require_once 'src/gadgets/MetadataContext.php';
+require_once 'src/gadgets/MetadataHandler.php';
 
 class MetadataServlet extends HttpServlet {
 

Modified: incubator/shindig/trunk/php/src/gadgets/servlet/ProxyServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/servlet/ProxyServlet.php?rev=744702&r1=744701&r2=744702&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/servlet/ProxyServlet.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/servlet/ProxyServlet.php Sun Feb 15 17:35:05 2009
@@ -20,51 +20,28 @@
 
 require 'src/common/HttpServlet.php';
 require 'src/gadgets/GadgetContext.php';
-require 'src/common/SecurityTokenDecoder.php';
+require 'src/gadgets/ProxyBase.php';
 require 'src/gadgets/ProxyHandler.php';
-require 'src/gadgets/GadgetException.php';
 require 'src/common/RemoteContentRequest.php';
 require 'src/common/RemoteContent.php';
 require 'src/common/Cache.php';
 require 'src/common/RemoteContentFetcher.php';
-require 'src/gadgets/oauth/OAuth.php';
-require 'src/gadgets/oauth/OAuthStore.php';
-require 'src/gadgets/rewrite/ContentRewriter.php';
-require 'src/gadgets/rewrite/ContentRewriteFeature.php';
 
 class ProxyServlet extends HttpServlet {
 
   public function doGet() {
     try {
+      // Make sure the HttpServlet doesn't overwrite our headers
       $this->noHeaders = true;
       $context = new GadgetContext('GADGET');
-      // 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';
-      }
+      $url = (isset($_GET['url']) ? $_GET['url'] : (isset($_POST['url']) ? $_POST['url'] : false));
+      $url = urldecode($url);
       if (! $url) {
         header("HTTP/1.0 400 Bad Request", true);
         echo "<html><body><h1>400 - Missing url parameter</h1></body></html>";
       }
-      $signingFetcherFactory = $gadgetSigner = false;
-      if (! empty($_GET['authz']) || ! empty($_POST['authz'])) {
-        $gadgetSigner = Config::get('security_token_signer');
-        $gadgetSigner = new $gadgetSigner();
-        $signingFetcherFactory = new SigningFetcherFactory(Config::get("private_key_file"));
-      }
-      $proxyHandler = new ProxyHandler($context, $signingFetcherFactory);
-      if (! empty($_GET['output']) && $_GET['output'] == 'js') {
-        $proxyHandler->fetchJson($url, $gadgetSigner, $method);
-      } else {
-        $proxyHandler->fetch($url, $gadgetSigner, $method);
-      }
+      $proxyHandler = new ProxyHandler($context);
+      $proxyHandler->fetch($url);
     } catch (Exception $e) {
       // catch all exceptions and give a 500 server error
       header("HTTP/1.0 500 Internal Server Error");