You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by bh...@apache.org on 2011/01/26 10:24:14 UTC

svn commit: r1063653 - in /shindig/trunk: extras/src/main/php/ extras/src/main/php/extras/ php/ php/config/ php/src/gadgets/servlet/ php/test/gadgets/

Author: bhofmann
Date: Wed Jan 26 09:24:14 2011
New Revision: 1063653

URL: http://svn.apache.org/viewvc?rev=1063653&view=rev
Log:
* Refactored PHP GadgetRenderingServlet to allow additional GadgetRenderer
* Added PHP extras package for experimental or not yet specified implementations
* Added GadgetUrlAuthRenderer to allow content type URL redirects to be authorized
* SHINDIG-952: Added further phpdoc comments for

Added:
    shindig/trunk/extras/src/main/php/
    shindig/trunk/extras/src/main/php/extras/
    shindig/trunk/extras/src/main/php/extras/GadgetUrlAuthRenderer.php
    shindig/trunk/php/test/gadgets/GadgetRenderingServletTest.php
Modified:
    shindig/trunk/php/config/container.php
    shindig/trunk/php/index.php
    shindig/trunk/php/src/gadgets/servlet/ContentFilesServlet.php
    shindig/trunk/php/src/gadgets/servlet/GadgetRenderingServlet.php
    shindig/trunk/php/src/gadgets/servlet/ResourcesFilesServlet.php

Added: shindig/trunk/extras/src/main/php/extras/GadgetUrlAuthRenderer.php
URL: http://svn.apache.org/viewvc/shindig/trunk/extras/src/main/php/extras/GadgetUrlAuthRenderer.php?rev=1063653&view=auto
==============================================================================
--- shindig/trunk/extras/src/main/php/extras/GadgetUrlAuthRenderer.php (added)
+++ shindig/trunk/extras/src/main/php/extras/GadgetUrlAuthRenderer.php Wed Jan 26 09:24:14 2011
@@ -0,0 +1,170 @@
+<?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 GadgetUrlAuthRenderer extends GadgetRenderer {
+
+  /**
+   * Renders an 'URL' type view (where the iframe is redirected to the specified url)
+   * This is more a legacy iGoogle support feature than 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) {
+    $redirURI = $this->getSubstitutedUrl($gadget, $view);
+    header('Location: ' . $redirURI);
+  }
+
+  /**
+   * retrieves url of content tag and substitutes it
+   *
+   * @param Gadget $gadget
+   * @param string $view
+   * @return string
+   */
+  public function getSubstitutedUrl(Gadget $gadget, $view) {
+    // Preserve existing query string parameters.
+    $redirURI = $view['href'];
+    $query = $this->getPrefsQueryString($gadget->gadgetSpec->userPrefs);
+
+    // deal with features
+    $registry = $this->context->getRegistry();
+    // since the URL mode doesn't actually have the gadget XML body, it can't inline
+    // the javascript content anyway - thus could us just ignore the 'forcedJsLibs' part.
+    $sortedFeatures = array();
+    $registry->sortFeatures($gadget->features, $sortedFeatures);
+
+    $query .= $this->appendLibsToQuery($sortedFeatures);
+    $query .= '&lang=' . urlencode(isset($_GET['lang']) ? $_GET['lang'] : 'en');
+    $query .= '&country=' . urlencode(isset($_GET['country']) ? $_GET['country'] : 'US');
+
+    $redirURI = $gadget->substitutions->substituteUri(null, $redirURI);
+    if (strpos($redirURI, '?') !== false) {
+      $redirURI = $redirURI . $query;
+    } elseif (substr($query, 0, 1) == '&') {
+      $redirURI = $redirURI . '?' . substr($query, 1);
+    } else {
+      $redirURI = $redirURI . '?' . $query;
+    }
+
+    $authz = $this->getAuthz($view);
+
+    if ($authz === 'signed') {
+      $gadgetSigner = Config::get('security_token_signer');
+      $gadgetSigner = new $gadgetSigner();
+      $token = $gadget->gadgetContext->extractAndValidateToken($gadgetSigner);
+
+      $signingFetcherFactory = new SigningFetcherFactory(Config::get("private_key_file"));
+
+      $redirURI .= '&xoauth_signature_publickey=' . urlencode($signingFetcherFactory->getKeyName());
+      $redirURI .= '&xoauth_public_key=' . urlencode($signingFetcherFactory->getKeyName());
+
+      if ($this->getSignOwner($view)) {
+        $redirURI .= '&opensocial_owner_id=' . urlencode($token->getOwnerId());
+      }
+      if ($this->getSignViewer($view)) {
+        $redirURI .= '&opensocial_viewer_id=' . urlencode($token->getViewerId());
+      }
+
+      $redirURI .= '&opensocial_app_url=' . urlencode($token->getAppUrl());
+      $redirURI .= '&opensocial_app_id=' . urlencode($token->getAppId());
+      $redirURI .= '&opensocial_instance_id=' . urlencode($token->getModuleId());
+
+      $consumer = new OAuthConsumer(NULL, NULL, NULL);
+      $signatureMethod = new ShindigRsaSha1SignatureMethod($signingFetcherFactory->getPrivateKey(), null);
+      $req_req = OAuthRequest::from_consumer_and_token($consumer, NULL, 'GET', $redirURI);
+      $req_req->sign_request($signatureMethod, $consumer, NULL);
+      $redirURI = $req_req->to_url();
+
+
+    }
+
+    return $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;
+  }
+
+  /**
+   * Returns the authz attribute of the view, can be 'none', 'signed' or 'oauth'
+   *
+   * @param array $view
+   * @return string authz attribute
+   */
+  private function getAuthz($view) {
+    return ! empty($view['authz']) ? strtolower($view['authz']) : 'none';
+  }
+
+
+  /**
+   * Returns the signOwner attribute of the view (true or false, default is true)
+   *
+   * @param array $view
+   * @return string signOwner attribute
+   */
+  private function getSignOwner($view) {
+    return ! empty($view['signOwner']) && strcasecmp($view['signOwner'], 'false') == 0 ? false : true;
+  }
+
+  /**
+   * Returns the signViewer attribute of the view (true or false, default is true)
+   *
+   * @param array $view
+   * @return string signViewer attribute
+   */
+  private function getSignViewer($view) {
+    return ! empty($view['signViewer']) && strcasecmp($view['signViewer'], 'false') == 0 ? false : true;
+  }
+}

Modified: shindig/trunk/php/config/container.php
URL: http://svn.apache.org/viewvc/shindig/trunk/php/config/container.php?rev=1063653&r1=1063652&r2=1063653&view=diff
==============================================================================
--- shindig/trunk/php/config/container.php (original)
+++ shindig/trunk/php/config/container.php Wed Jan 26 09:24:14 2011
@@ -184,6 +184,16 @@ $shindigConfig = array(
     'mediaitems' => array('class' => 'InputMediaItemsConverter', 'targetField' => 'mediaItem'),
   ),
  
+  // available gadget renderer with the class as key and the needed attributes in the
+  // view's content block to choose this renderer. If constraint's value is a string
+  // the attribute value has to match this string, if it's a boolean the attribute
+  // just has to be available or not available
+  'gadget_renderer' => array(
+    'GadgetHtmlRenderer' => array('type' => 'HTML', 'href' => false),
+    'GadgetHrefRenderer' => array('type' => 'HTML', 'href' => true),
+    'GadgetUrlRenderer'  => array('type' => 'URL'),
+    //'GadgetUrlAuthRenderer'  => array('type' => 'URL'),
+  ),
  
   'gadget_class' => 'Gadget',
   'gadget_context_class' => 'GadgetContext',
@@ -215,6 +225,8 @@ $shindigConfig = array(
   'media_item_service' => 'JsonDbOpensocialService',
 
   // Also scan these directories when looking for <Class>.php files. You can include multiple paths by seperating them with a ,
+  // To enable classes in the extras package you have to add this class path
+  // 'extension_class_paths' => '../extras/src/main/php/extras',
   'extension_class_paths' => '',
 
   'userpref_param_prefix' => 'up_',

Modified: shindig/trunk/php/index.php
URL: http://svn.apache.org/viewvc/shindig/trunk/php/index.php?rev=1063653&r1=1063652&r2=1063653&view=diff
==============================================================================
--- shindig/trunk/php/index.php (original)
+++ shindig/trunk/php/index.php Wed Jan 26 09:24:14 2011
@@ -56,7 +56,7 @@ if (Config::get('debug')) {
 // To load these, we scan our entire directory structure
 function __autoload($className) {
   $locations = array('src/common', 'src/common/sample', 'src/gadgets', 'src/gadgets/servlet', 
-      'src/gadgets/oauth', 'src/gadgets/sample', 'src/social', 'src/social/servlet', 
+      'src/gadgets/oauth', 'src/gadgets/render', 'src/gadgets/sample', 'src/social', 'src/social/servlet',
       'src/social/service', 'src/social/opensocial', 'src/social/model', 'src/social/spi', 
       'src/social/converters', 'src/social/oauth', 'src/social/sample');
   $extension_class_paths = Config::get('extension_class_paths');

Modified: shindig/trunk/php/src/gadgets/servlet/ContentFilesServlet.php
URL: http://svn.apache.org/viewvc/shindig/trunk/php/src/gadgets/servlet/ContentFilesServlet.php?rev=1063653&r1=1063652&r2=1063653&view=diff
==============================================================================
--- shindig/trunk/php/src/gadgets/servlet/ContentFilesServlet.php (original)
+++ shindig/trunk/php/src/gadgets/servlet/ContentFilesServlet.php Wed Jan 26 09:24:14 2011
@@ -20,6 +20,9 @@
 
 class ContentFilesServlet extends FilesServlet
 {
+  /**
+   * @return string
+   */
   protected function getPath() {
     return Config::get('javascript_path');
   }

Modified: shindig/trunk/php/src/gadgets/servlet/GadgetRenderingServlet.php
URL: http://svn.apache.org/viewvc/shindig/trunk/php/src/gadgets/servlet/GadgetRenderingServlet.php?rev=1063653&r1=1063652&r2=1063653&view=diff
==============================================================================
--- shindig/trunk/php/src/gadgets/servlet/GadgetRenderingServlet.php (original)
+++ shindig/trunk/php/src/gadgets/servlet/GadgetRenderingServlet.php Wed Jan 26 09:24:14 2011
@@ -39,8 +39,15 @@ require_once 'src/gadgets/rewrite/Gadget
 require_once 'src/gadgets/rewrite/DomRewriter.php';
 
 class GadgetRenderingServlet extends HttpServlet {
+  /**
+   *
+   * @var GadgetContext
+   */
   protected $context;
 
+  /**
+   * @throws GadgetException
+   */
   public function doGet() {
     try {
       if (empty($_GET['url'])) {
@@ -70,23 +77,58 @@ class GadgetRenderingServlet extends Htt
     }
   }
 
+  /**
+   *
+   * @param Gadget $gadget
+   * @throws GadgetException
+   */
   protected 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");
+    $renderClasses = Config::get('gadget_renderer');
+
+    foreach ($renderClasses as $renderClass => $constraints) {
+      // if current view meets the configurated renderer constraints
+      // render the gadget and stop checking
+      if ($this->checkConstraints($view, $constraints)) {
+        $gadgetRenderer = new $renderClass($this->context);
+        $gadgetRenderer->renderGadget($gadget, $view);
+        return;
+      }
+    }
+
+    throw new GadgetException("Invalid view type");   
+  }
+
+  /**
+   * checks if the current view meets the given gadget renderer constraints
+   *
+   * constraint format:
+   * 
+   * array(
+   *   attributeName => expectedValue or boolean to indicate if the attribute is 
+   *                      required or not
+   * )
+   *
+   * @param array $view
+   * @param array $constraints
+   * @return boolean
+   */
+  public function checkConstraints($view, $constraints) {
+    foreach ($constraints as $attribute => $expected) {
+      if ($expected === false && isset($view[$attribute]) && $view[$attribute]) {
+        return false;
+      } else if ($expected === true && !(isset($view[$attribute]) && $view[$attribute])) {
+        return false;
+      } else if (! is_bool($expected) && $view[$attribute] !== $expected) {
+        return false;
+      }
     }
-    $gadgetRenderer->renderGadget($gadget, $view);
+    return true;
   }
 
+  /**
+   * 
+   */
   protected function setCachingHeaders() {
     $this->setContentType("text/html; charset=UTF-8");
     if ($this->context->getIgnoreCache()) {
@@ -101,6 +143,10 @@ class GadgetRenderingServlet extends Htt
     }
   }
 
+  /**
+   *
+   * @param Exception $e
+   */
   protected function showError($e) {
     header("HTTP/1.0 400 Bad Request", true, 400);
     echo "<html><body>";

Modified: shindig/trunk/php/src/gadgets/servlet/ResourcesFilesServlet.php
URL: http://svn.apache.org/viewvc/shindig/trunk/php/src/gadgets/servlet/ResourcesFilesServlet.php?rev=1063653&r1=1063652&r2=1063653&view=diff
==============================================================================
--- shindig/trunk/php/src/gadgets/servlet/ResourcesFilesServlet.php (original)
+++ shindig/trunk/php/src/gadgets/servlet/ResourcesFilesServlet.php Wed Jan 26 09:24:14 2011
@@ -20,6 +20,9 @@
 
 class ResourcesFilesServlet extends FilesServlet
 {
+  /**
+   * @return string
+   */
   protected function getPath() {
     return Config::get('resources_path');
   }

Added: shindig/trunk/php/test/gadgets/GadgetRenderingServletTest.php
URL: http://svn.apache.org/viewvc/shindig/trunk/php/test/gadgets/GadgetRenderingServletTest.php?rev=1063653&view=auto
==============================================================================
--- shindig/trunk/php/test/gadgets/GadgetRenderingServletTest.php (added)
+++ shindig/trunk/php/test/gadgets/GadgetRenderingServletTest.php Wed Jan 26 09:24:14 2011
@@ -0,0 +1,65 @@
+<?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 GadgetRenderingServletTest extends PHPUnit_Framework_TestCase {
+    public function testCheckConstraints() {
+        $servlet = new GadgetRenderingServlet();
+        ob_end_flush();
+
+        $constraints = array('type' => 'HTML', 'href' => false);
+
+        $view = array('type' => 'HTML', 'foo' => 'bar');
+        $this->assertTrue($servlet->checkConstraints($view, $constraints));
+        $view = array('type' => 'HTML', 'foo' => 'bar', 'href' => '');
+        $this->assertTrue($servlet->checkConstraints($view, $constraints));
+        $view = array('type' => 'HTML', 'foo' => 'bar', 'href' => 'blub');
+        $this->assertFalse($servlet->checkConstraints($view, $constraints));
+        $view = array('type' => 'URL', 'foo' => 'bar', 'href' => 'blub');
+        $this->assertFalse($servlet->checkConstraints($view, $constraints));
+        $view = array('type' => 'URL', 'foo' => 'bar');
+        $this->assertFalse($servlet->checkConstraints($view, $constraints));
+
+        $constraints = array('type' => 'HTML', 'href' => true);
+
+        $view = array('type' => 'HTML', 'foo' => 'bar');
+        $this->assertFalse($servlet->checkConstraints($view, $constraints));
+        $view = array('type' => 'HTML', 'foo' => 'bar', 'href' => '');
+        $this->assertFalse($servlet->checkConstraints($view, $constraints));
+        $view = array('type' => 'HTML', 'foo' => 'bar', 'href' => 'blub');
+        $this->assertTrue($servlet->checkConstraints($view, $constraints));
+        $view = array('type' => 'URL', 'foo' => 'bar', 'href' => 'blub');
+        $this->assertFalse($servlet->checkConstraints($view, $constraints));
+        $view = array('type' => 'URL', 'foo' => 'bar');
+        $this->assertFalse($servlet->checkConstraints($view, $constraints));
+
+        $constraints = array('type' => 'URL');
+
+        $view = array('type' => 'HTML', 'foo' => 'bar');
+        $this->assertFalse($servlet->checkConstraints($view, $constraints));
+        $view = array('type' => 'HTML', 'foo' => 'bar', 'href' => '');
+        $this->assertFalse($servlet->checkConstraints($view, $constraints));
+        $view = array('type' => 'HTML', 'foo' => 'bar', 'href' => 'blub');
+        $this->assertFalse($servlet->checkConstraints($view, $constraints));
+        $view = array('type' => 'URL', 'foo' => 'bar', 'href' => 'blub');
+        $this->assertTrue($servlet->checkConstraints($view, $constraints));
+        $view = array('type' => 'URL', 'foo' => 'bar');
+        $this->assertTrue($servlet->checkConstraints($view, $constraints));
+    }
+}