You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by li...@apache.org on 2008/03/06 16:43:52 UTC
svn commit: r634310 - in /incubator/shindig/trunk/php/gadgets: ./ src/
src/http/
Author: lindner
Date: Thu Mar 6 07:43:50 2008
New Revision: 634310
URL: http://svn.apache.org/viewvc?rev=634310&view=rev
Log:
Patch by Chris Chabot for SHINDIG-112
- Changed *RemoteContent* to do single requests, curl_multi was acting up on some of my systems and wasn't used in practice anyhow, so simplifying it to single requests resolved these issues.
- Refactored Gadget / GadgetView / GadgetSpec into a single class. Simple class structure fits better with PHP, and makes it easier to read too.
- Moved http processing options into the config array, this way they you can override then if desired, and saves code.
- Removed a few bits of unused code (Icons, NoOop feature).
- Removed abstract base classes for things that don't have to be replaced by site's own implementations (featurespec, userpref and localespec).
- Moved the caching of the feature loader a bit up in the chain, saves a good bit on processing time and has the same effect.
- Fixed a silly oversight where the cache key for url's was md5'd twice, thus increasing the change of a key collision.
- Removed a few more include's that are now handled by the __autoloader.
- Now using sha1 instead of md5 for keys (larger keys, theoretically less chance of key collisions).
- Fixed a bug in the proxy where httpMethod was ignored if fetchJson was called.
- Fixed a bug in the proxy where it didn't always look in the post variables for url/method/etc, and made this generally more consistent
- Implemented the missing sha1 checksum for the js libs query (?js=<version>) for href gadget content.
- Added a noHeaders option to the base http servlet class, so we can properly use its destructor without breaking the JS and Proxy servlets.
- Improved header handling in the proxy code, uses apache's get all headers where available and otherwise falls back on a _SERVER based work around, also blacklisted a few headers for the passthru and thus fixing a few bugs where the browser didn't understand the request so well.
- Fixed handling of postData in the proxy.
- Fixed setCachingHeaders in the proxy.
- Fixed the mixed naming of jsLibrary / JsLibrary which was causing the autoloader to fail
Added:
incubator/shindig/trunk/php/gadgets/src/GadgetId.php
incubator/shindig/trunk/php/gadgets/src/Locale.php
Removed:
incubator/shindig/trunk/php/gadgets/src/GadgetException.php
incubator/shindig/trunk/php/gadgets/src/GadgetSpec.php
incubator/shindig/trunk/php/gadgets/src/GadgetView.php
incubator/shindig/trunk/php/gadgets/src/GadgetViewID.php
incubator/shindig/trunk/php/gadgets/src/HttpProcessingOptions.php
incubator/shindig/trunk/php/gadgets/src/ProcessingOptions.php
incubator/shindig/trunk/php/gadgets/src/RemoteContentException.php
incubator/shindig/trunk/php/gadgets/src/SpecParserException.php
Modified:
incubator/shindig/trunk/php/gadgets/config.php
incubator/shindig/trunk/php/gadgets/src/BasicRemoteContent.php
incubator/shindig/trunk/php/gadgets/src/BasicRemoteContentFetcher.php
incubator/shindig/trunk/php/gadgets/src/Gadget.php
incubator/shindig/trunk/php/gadgets/src/GadgetContext.php
incubator/shindig/trunk/php/gadgets/src/GadgetFeatureRegistry.php
incubator/shindig/trunk/php/gadgets/src/GadgetServer.php
incubator/shindig/trunk/php/gadgets/src/GadgetSpecParser.php
incubator/shindig/trunk/php/gadgets/src/JsFeatureLoader.php
incubator/shindig/trunk/php/gadgets/src/JsLibrary.php
incubator/shindig/trunk/php/gadgets/src/MessageBundleSubstituter.php
incubator/shindig/trunk/php/gadgets/src/RemoteContent.php
incubator/shindig/trunk/php/gadgets/src/RemoteContentFetcher.php
incubator/shindig/trunk/php/gadgets/src/RemoteContentRequest.php
incubator/shindig/trunk/php/gadgets/src/Substitutions.php
incubator/shindig/trunk/php/gadgets/src/http/GadgetRenderingServlet.php
incubator/shindig/trunk/php/gadgets/src/http/HttpServlet.php
incubator/shindig/trunk/php/gadgets/src/http/JsServlet.php
incubator/shindig/trunk/php/gadgets/src/http/ProxyHandler.php
incubator/shindig/trunk/php/gadgets/src/http/ProxyServlet.php
Modified: incubator/shindig/trunk/php/gadgets/config.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/config.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/config.php (original)
+++ incubator/shindig/trunk/php/gadgets/config.php Thu Mar 6 07:43:50 2008
@@ -5,12 +5,10 @@
* would be horribly slow (db, xml, ini files etc), so ... here's our config.php
*/
-// The base prefix under which the gadget url's live, if its the root set this to ''
-// don't forget to update your .htaccess to reflect this, as well as your container
-// javascript like: gadget.setServerBase('/gadgets/');
-
$config = array(
- // the prefix of where this code resides
+ // The base prefix under which the gadget url's live, if its the root set this to ''
+ // don't forget to update your .htaccess to reflect this, as well as your container
+ // javascript like: gadget.setServerBase('/gadgets/');
'web_prefix' => '/gadgets',
// location of the features directory on disk. The default setting assumes you did a
@@ -43,5 +41,10 @@
'cache_root'=> '/tmp/shindig',
// In some cases we need to know the site root (for features forinstance)
- 'base_path'=> realpath(dirname(__FILE__))
+ 'base_path'=> realpath(dirname(__FILE__)),
+
+ // We combine global and per request state in the config since it saves a good bit of code
+ // and global classes & variables, these are the HttpProcessingOptions
+ 'ignoreCache' => (isset($_GET['nocache']) && intval($_GET['nocache']) == 1) || (isset($_GET['bpc']) && intval($_GET['bpc']) == 1),
+ 'focedJsLibs' => isset($_GET['libs']) ? trim($_GET['libs']) : null
);
Modified: incubator/shindig/trunk/php/gadgets/src/BasicRemoteContent.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/BasicRemoteContent.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/BasicRemoteContent.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/BasicRemoteContent.php Thu Mar 6 07:43:50 2008
@@ -20,36 +20,23 @@
class BasicRemoteContent extends RemoteContent {
- public function fetch($requests, $options)
+ public function fetch($request)
{
global $config;
$cache = new $config['data_cache']();
- if ($requests instanceof RemoteContentRequest) {
- $requests = array($requests);
- }
$remoteContentFetcher = new BasicRemoteContentFetcher();
- $ret = array();
- foreach ( $requests as $request ) {
- if (! ($request instanceof RemoteContentRequest)) {
- throw new RemoteContentException("Invalid request type in remoteContent");
- }
- // determine which requests we can load from cache, and which we have to actually fetch
- if (! $options->ignoreCache && ($cachedRequest = $cache->get(md5($request->toHash()))) !== false) {
- $ret[] = $cachedRequest;
- } else {
- $remoteContentFetcher->addRequest($request);
- }
+ if (! ($request instanceof RemoteContentRequest)) {
+ throw new RemoteContentException("Invalid request type in remoteContent");
}
- if ($remoteContentFetcher->pendingRequests()) {
- $requests = $remoteContentFetcher->fetchRequests();
- // store the objects we just fetched in cache
- foreach ( $requests as $request ) {
- if ($request->getHttpCode() == '200') {
- // only cache requests that returned a 200 OK
- $cache->set(md5($request->toHash()), $request);
- }
+ // determine which requests we can load from cache, and which we have to actually fetch
+ if (! $config['ignoreCache'] && ($cachedRequest = $cache->get($request->toHash())) !== false) {
+ $ret = $cachedRequest;
+ } else {
+ $ret = $remoteContentFetcher->fetchRequest($request);
+ // only cache requests that returned a 200 OK
+ if ($request->getHttpCode() == '200') {
+ $cache->set($request->toHash(), $request);
}
- $ret = array_merge($requests, $ret);
}
return $ret;
}
Modified: incubator/shindig/trunk/php/gadgets/src/BasicRemoteContentFetcher.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/BasicRemoteContentFetcher.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/BasicRemoteContentFetcher.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/BasicRemoteContentFetcher.php Thu Mar 6 07:43:50 2008
@@ -25,73 +25,57 @@
class BasicRemoteContentFetcher extends remoteContentFetcher {
private $requests = array();
- public function addRequests($requests)
+ public function fetchRequest($request)
{
- foreach ( $request as $request ) {
- $this->addRequest($request);
- }
- }
-
- public function addRequest(remoteContentRequest $request)
- {
- $url = $request->getUrl();
- if (empty($url)) {
- throw new remoteContentException("Invalid or empty url specified in remoteContentFetcher");
- }
- $this->requests[] = $request;
- }
-
- public function fetchRequests()
- {
- $ret = array();
- $mh = curl_multi_init();
- // Setup each request based on its options
- foreach ( $this->requests as $request ) {
- $request->handle = curl_init();
- curl_setopt($request->handle, CURLOPT_URL, $request->getUrl());
- curl_setopt($request->handle, CURLOPT_FOLLOWLOCATION, 1);
- curl_setopt($request->handle, CURLOPT_RETURNTRANSFER, 1);
- curl_setopt($request->handle, CURLOPT_HEADER, 1);
- if ($request->hasHeaders()) {
- curl_setopt($request->handle, CURLOPT_HTTPHEADER, array($request->getHeaders()));
+ $request->handle = curl_init();
+ curl_setopt($request->handle, CURLOPT_URL, $request->getUrl());
+ curl_setopt($request->handle, CURLOPT_FOLLOWLOCATION, 1);
+ curl_setopt($request->handle, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($request->handle, CURLOPT_AUTOREFERER, 1);
+ curl_setopt($request->handle, CURLOPT_MAXREDIRS, 10);
+ curl_setopt($request->handle, CURLOPT_CONNECTTIMEOUT, 10);
+ curl_setopt($request->handle, CURLOPT_TIMEOUT, 20);
+ curl_setopt($request->handle, CURLOPT_HEADER, 1);
+ if ($request->hasHeaders()) {
+ $headers = explode("\n", $request->getHeaders());
+ $outHeaders = array();
+ foreach ( $headers as $header ) {
+ if (strpos($header, ':')) {
+ $key = trim(substr($header, 0, strpos($header, ':')));
+ $val = trim(substr($header, strpos($header, ':') + 1));
+ if (strcasecmp($key, "Transfer-Encoding") != 0 && strcasecmp($key, "Cache-Control") != 0 && strcasecmp($key, "Expires") != 0 && strcasecmp($key, "Content-Length") != 0) {
+ $outHeaders[] = "$key: $val";
+ }
+ }
}
- if ($request->isPost()) {
- curl_setopt($request->handle, CURLOPT_POST, 1);
- curl_setopt($request->handle, CURLOPT_POSTFIELDS, $request->getPostBody());
- }
- curl_multi_add_handle($mh, $request->handle);
+ curl_setopt($request->handle, CURLOPT_HTTPHEADER, $outHeaders);
+ }
+ if ($request->isPost()) {
+ curl_setopt($request->handle, CURLOPT_POST, 1);
+ curl_setopt($request->handle, CURLOPT_POSTFIELDS, $request->getPostBody());
}
- // Execute the multi fetch
- $running = null;
- do {
- curl_multi_exec($mh, $running);
- } while ( $running > 0 );
-
- // Done, close handles
- foreach ( $this->requests as $key => $request ) {
- $content = curl_multi_getcontent($request->handle);
- $body = substr($content, strpos($content, "\r\n\r\n") + 4);
+ // Execute the request
+ $content = @curl_exec($request->handle);
+ $header = '';
+ $body = '';
+ // on redirects and such we get multiple headers back from curl it seems, we really only want the last one
+ while ( substr($content, 0, strlen('HTTP')) == 'HTTP' && strpos($content, "\r\n\r\n") !== false) {
$header = substr($content, 0, strpos($content, "\r\n\r\n"));
- $httpCode = curl_getinfo($request->handle, CURLINFO_HTTP_CODE);
- $contentType = curl_getinfo($request->handle, CURLINFO_CONTENT_TYPE);
- $request->setHttpCode($httpCode);
- $request->setContentType($contentType);
- $request->setResponseHeaders($header);
- $request->setResponseContent($body);
- $request->setResponseSize(strlen($content));
- curl_multi_remove_handle($mh, $request->handle);
- unset($request->handle);
+ $body = substr($content, strlen($header) + 4);
+ $content = substr($content, strlen($header) + 4);
}
- curl_multi_close($mh);
-
- $ret = $this->requests;
- // empty our requests queue
- $this->requests = array();
- return $ret;
- }
-
- public function pendingRequests()
- {
- return count($this->requests);
+ $httpCode = curl_getinfo($request->handle, CURLINFO_HTTP_CODE);
+ $contentType = curl_getinfo($request->handle, CURLINFO_CONTENT_TYPE);
+ if (!$httpCode) {
+ $httpCode = '404';
+ }
+ $request->setHttpCode($httpCode);
+ $request->setContentType($contentType);
+ $request->setResponseHeaders($header);
+ $request->setResponseContent($body);
+ $request->setResponseSize(strlen($content));
+ curl_close($request->handle);
+ unset($request->handle);
+ return $request;
}
}
Modified: incubator/shindig/trunk/php/gadgets/src/Gadget.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/Gadget.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/Gadget.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/Gadget.php Thu Mar 6 07:43:50 2008
@@ -18,76 +18,80 @@
*
*/
-final class GadgetId extends GadgetViewID {
- private $uri;
- private $moduleId;
-
- public function GadgetId($uri, $moduleId)
- {
- $this->uri = $uri;
- $this->moduleId = $moduleId;
- }
-
- public function getURI()
- {
- return $this->uri;
- }
-
- public function getModuleId()
- {
- return $this->moduleId;
- }
-
- public function getKey()
- {
- return $this->getURI();
- }
-}
+/*
+ * In Java terms this would be the Gadget, GadgetView and GadgetSpec all rolled into one
+ * We combined it into one class since it makes more sense in PHP and provides a nice
+ * speedup too.
+ */
-class Gadget extends GadgetSpec {
- public $baseSpec;
+class GadgetException extends Exception {}
+
+class Gadget {
private $jsLibraries;
private $substitutions;
private $userPrefValues;
private $currentMessageBundle = array();
+ // As in UserPref, no enums so fake it
+ public $contentTypes = array('HTML', 'URL');
+ public $id;
+ public $author;
+ public $authorEmail;
+ public $description;
+ public $directoryTitle;
+ public $contentType;
+ public $contentHref;
+ public $contentData = array();
+ public $localeSpecs = array();
+ public $preloads = array();
+ public $requires = array();
+ public $screenshot;
+ public $thumbnail;
+ public $title;
+ public $titleUrl = null;
+ public $userPrefs = array();
- public function __construct($id, GadgetSpec $baseSpec, $prefs)
+ public function __construct($id = false, $prefs = false)
{
- $this->id = $id;
- $this->baseSpec = $baseSpec;
+ if ($id) $this->id = $id;
+ if ($prefs) $this->userPrefValues = $prefs;
$this->substitutions = new Substitutions();
- $this->userPrefValues = $prefs;
$this->jsLibraries = array();
}
- public function getAuthor()
+ public function setId($id)
{
- return $this->substitutions->substitute($this->baseSpec->getAuthor());
+ $this->id = $id;
}
- public function getAuthorEmail()
+ public function setPrefs($prefs)
{
- return $this->substitutions->substitute($this->baseSpec->getAuthorEmail());
+ $this->userPrefValues = $prefs;
}
- public function getBaseSpec()
+ public function getAuthor()
{
- return $this->baseSpec;
+ return $this->substitutions->substitute($this->author);
}
- public function getContentData($view = false)
+ public function getAuthorEmail()
{
- return $this->substitutions->substitute($this->baseSpec->getContentData($view));
+ return $this->substitutions->substitute($this->authorEmail);
}
-
- public function getContentHref()
+
+ public function getContentData($view = false)
{
- return $this->substitutions->substitute($this->baseSpec->getContentHref());
+ if ($this->contentType != 'HTML') {
+ throw new SpecParserException("getContentData() requires contentType HTML");
+ }
+ if (empty($view) || !$view) {
+ $view = DEFAULT_VIEW;
+ }
+ return $this->substitutions->substitute(isset($this->contentData[$view]) ? trim($this->contentData[$view]) : '');
}
- public function getContentType()
+ public function getContentHref()
{
- return $this->baseSpec->getContentType();
+ return $this->substitutions->substitute($this->getContentType() == 'URL' ? $this->contentHref : null);
}
public function getCurrentMessageBundle()
@@ -97,19 +101,14 @@
public function getDescription()
{
- return $this->substitutions->substitute($this->baseSpec->getDescription());
+ return $this->substitutions->substitute($this->description);
}
public function getDirectoryTitle()
{
- return $this->substitutions->substitute($this->baseSpec->getDirectoryTitle());
- }
-
- public function getIcons()
- {
- return $this->baseSpec->getIcons();
+ return $this->substitutions->substitute($this->directoryTitle);
}
-
+
public function getId()
{
return $this->id;
@@ -127,7 +126,7 @@
public function getLocaleSpecs()
{
- return $this->baseSpec->getLocaleSpecs();
+ return $this->localeSpecs;
}
public function getFeatureParams($gadget, $feature)
@@ -145,7 +144,7 @@
public function getPreloads()
{
$ret = array();
- foreach ( $this->baseSpec->getPreloads() as $preload ) {
+ foreach ( $this->preloads as $preload ) {
$ret[] = $this->substitutions->substitute($preload);
}
return $ret;
@@ -153,12 +152,12 @@
public function getRequires()
{
- return $this->baseSpec->getRequires();
+ return $this->requires;
}
public function getScreenshot()
{
- return $this->substitutions->substitute($this->baseSpec->getScreenshot());
+ return $this->substitutions->substitute($this->screenshot);
}
public function getSubstitutions()
@@ -168,26 +167,26 @@
public function getThumbnail()
{
- return $this->substitutions->substitute($this->baseSpec->getThumbnail());
+ return $this->substitutions->substitute($this->thumbnail);
}
public function getTitle()
{
- return $this->substitutions->substitute($this->baseSpec->getTitle());
+ return $this->substitutions->substitute($this->title);
}
public function getTitleURI()
{
$ret = null;
- if (($uri = $this->baseSpec->getTitleURI()) != null) {
- $ret = $this->substitutions->substitute($uri);
+ if (!empty($this->titleURI)) {
+ $ret = $this->substitutions->substitute($this->titleURI);
}
return $ret;
}
public function getUserPrefs()
{
- return $this->baseSpec->getUserPrefs();
+ return $this->userPrefs;
}
public function getUserPrefValues()
@@ -199,4 +198,104 @@
{
$this->currentMessageBundle = $messageBundle;
}
-}
\ No newline at end of file
+
+ /* gadget Spec functions */
+ public function addContent($view, $data)
+ {
+ if (empty($view)) {
+ $view = DEFAULT_VIEW;
+ }
+ if (! isset($this->contentData[$view])) {
+ $this->contentData[$view] = '';
+ }
+ $this->contentData[$view] .= $data;
+ }
+
+ public function getContentType()
+ {
+ return $this->contentType;
+ }
+}
+
+class LocaleSpec {
+ public $url;
+ public $locale;
+ public $rightToLeft;
+
+ public function getURI()
+ {
+ return $this->url;
+ }
+
+ public function getLocale()
+ {
+ return $this->locale;
+ }
+
+ public function isRightToLeft()
+ {
+ return $this->rightToLeft;
+ }
+}
+
+class FeatureSpec {
+ public $name;
+ public $params = array();
+ public $optional;
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function getParams()
+ {
+ return $this->params;
+ }
+
+ public function isOptional()
+ {
+ return $this->optional;
+ }
+}
+
+class UserPref {
+ public $DataTypes = array('STRING', 'HIDDEN', 'BOOL', 'ENUM', 'LIST', 'NUMBER');
+ public $dataType;
+ public $name;
+ public $displayName;
+ public $defaultValue;
+ public $required;
+ public $enumValues;
+ public $contentType;
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function getDisplayName()
+ {
+ return $this->displayName;
+ }
+
+ public function getDefaultValue()
+ {
+ return $this->defaultValue;
+ }
+
+ public function isRequired()
+ {
+ return $this->required;
+ }
+
+ public function getDataType()
+ {
+ return $this->dataType;
+ }
+
+ public function getEnumValues()
+ {
+ return $this->enumValues;
+ }
+}
Modified: incubator/shindig/trunk/php/gadgets/src/GadgetContext.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetContext.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetContext.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetContext.php Thu Mar 6 07:43:50 2008
@@ -26,16 +26,14 @@
class GadgetContext {
private $httpFetcher;
private $locale;
- private $options;
private $renderingContext;
private $registry;
- public function __construct(RemoteContent $httpFetcher, Locale $locale, $renderingContext, ProcessingOptions $options, GadgetFeatureRegistry $registry)
+ public function __construct(RemoteContent $httpFetcher, Locale $locale, $renderingContext, GadgetFeatureRegistry $registry)
{
$this->httpFetcher = $httpFetcher;
$this->locale = $locale;
$this->renderingContext = $renderingContext;
- $this->options = $options;
$this->registry = $registry;
}
@@ -58,10 +56,4 @@
{
return $this->registry;
}
-
- public function getOptions()
- {
- return $this->options;
- }
-
}
Modified: incubator/shindig/trunk/php/gadgets/src/GadgetFeatureRegistry.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetFeatureRegistry.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetFeatureRegistry.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetFeatureRegistry.php Thu Mar 6 07:43:50 2008
@@ -158,13 +158,3 @@
}
}
-class NoOpFeature extends GadgetFeature {
-
- public function prepare($gadget, $context, $params)
- {
- }
-
- public function process($gadget, $context, $params)
- {
- }
-}
Added: incubator/shindig/trunk/php/gadgets/src/GadgetId.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetId.php?rev=634310&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetId.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetId.php Thu Mar 6 07:43:50 2008
@@ -0,0 +1,27 @@
+<?
+
+class GadgetId {
+ private $uri;
+ private $moduleId;
+
+ public function GadgetId($uri, $moduleId)
+ {
+ $this->uri = $uri;
+ $this->moduleId = $moduleId;
+ }
+
+ public function getURI()
+ {
+ return $this->uri;
+ }
+
+ public function getModuleId()
+ {
+ return $this->moduleId;
+ }
+
+ public function getKey()
+ {
+ return $this->getURI();
+ }
+}
\ No newline at end of file
Modified: incubator/shindig/trunk/php/gadgets/src/GadgetServer.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetServer.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetServer.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetServer.php Thu Mar 6 07:43:50 2008
@@ -30,11 +30,10 @@
private $gadgetId;
private $userPrefs;
private $renderingContext;
- private $options;
private $locale;
private $httpFetcher;
- public function processGadget($gadgetId, $userPrefs, $locale, $rctx, $options, $httpFetcher, $registry)
+ public function processGadget($gadgetId, $userPrefs, $locale, $rctx, $httpFetcher, $registry)
{
global $config;
$this->gadgetId = $gadgetId;
@@ -42,9 +41,8 @@
$this->renderingContext = $rctx;
$this->locale = $locale;
$this->registry = $registry;
- $this->options = $options;
$this->httpFetcher = $httpFetcher;
- $this->gc = new GadgetContext($httpFetcher, $locale, $rctx, $options, $registry);
+ $this->gc = new GadgetContext($httpFetcher, $locale, $rctx, $registry);
$this->blacklist = new $config['blacklist_class']();
$gadget = $this->specLoad();
$this->featuresLoad($gadget);
@@ -57,13 +55,12 @@
throw new GadgetException("Gadget is blacklisted");
}
$request = new remoteContentRequest($this->gadgetId->getURI());
- list($xml) = $this->httpFetcher->fetch($request, $this->options);
+ $xml = $this->httpFetcher->fetch($request);
if ($xml->getHttpCode() != '200') {
throw new GadgetException("Failed to retrieve gadget content");
}
$specParser = new GadgetSpecParser();
- $spec = $specParser->parse($xml->getResponseContent());
- $gadget = new Gadget($this->gadgetId, $spec, $this->userPrefs);
+ $gadget = $specParser->parse($xml->getResponseContent(), $this->gadgetId, $this->userPrefs);
return $gadget;
}
Modified: incubator/shindig/trunk/php/gadgets/src/GadgetSpecParser.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetSpecParser.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetSpecParser.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetSpecParser.php Thu Mar 6 07:43:50 2008
@@ -18,11 +18,13 @@
*
*/
+class SpecParserException extends Exception {
+}
+
class GadgetSpecParser {
//public function parse(GadgetId $id, String $xml)
- public function parse($xml)
+ public function parse($xml, $id, $prefs)
{
- $id = 1;
if (empty($xml)) {
throw new SpecParserException("Empty XML document");
}
@@ -33,29 +35,28 @@
if (count($doc->ModulePrefs) != 1) {
throw new SpecParserException("Missing or duplicated <ModulePrefs>");
}
- $spec = new ParsedGadgetSpec();
- $spec->id = $id;
+ $gadget = new Gadget($id, $prefs);
// process ModulePref attributes
- $this->processModulePrefs($id, $spec, $doc->ModulePrefs);
+ $this->processModulePrefs($id, $gadget, $doc->ModulePrefs);
// process UserPrefs, if any
foreach ( $doc->UserPref as $pref ) {
- $this->processUserPref($spec, $pref);
+ $this->processUserPref($gadget, $pref);
}
foreach ( $doc->Content as $content ) {
- $this->processContent($spec, $content);
+ $this->processContent($gadget, $content);
}
//FIXME : should we add an else { throw new SpecParserException("Missing <Content> block"); } here ? Java version doesn't but it seems like we should ?
foreach ( $doc->ModulePrefs->Require as $feature ) {
- $this->processFeature($spec, $feature, true);
+ $this->processFeature($gadget, $feature, true);
}
foreach ( $doc->ModulePrefs->Optional as $feature ) {
- $this->processFeature($spec, $feature, false);
+ $this->processFeature($gadget, $feature, false);
}
//TODO java version has a todo here for parsing icons
- return $spec;
+ return $gadget;
}
- private function processModulePrefs($id, &$spec, $ModulePrefs)
+ private function processModulePrefs($id, &$gadget, $ModulePrefs)
{
$attributes = $ModulePrefs->attributes();
if (empty($attributes['title'])) {
@@ -63,16 +64,16 @@
}
// Get ModulePrefs attributes
// (trim is used here since it not only cleans up the text, but also auto-casts the SimpleXMLElement to a string)
- $spec->title = trim($attributes['title']);
- $spec->author = isset($attributes['author']) ? trim($attributes['author']) : '';
- $spec->authorEmail = isset($attributes['author_email']) ? trim($attributes['author_email']) : '';
- $spec->description = isset($attributes['description']) ? trim($attributes['description']) : '';
- $spec->directoryTitle = isset($attributes['directory_title']) ? trim($attributes['directory_title']) : '';
- $spec->screenshot = isset($attributes['screenshot']) ? trim($attributes['screenshot']) : '';
- $spec->thumbnail = isset($attributes['thumbnail']) ? trim($attributes['thumbnail']) : '';
- $spec->titleUrl = isset($attributes['title_url']) ? trim($attributes['title_url']) : '';
+ $gadget->title = trim($attributes['title']);
+ $gadget->author = isset($attributes['author']) ? trim($attributes['author']) : '';
+ $gadget->authorEmail = isset($attributes['author_email']) ? trim($attributes['author_email']) : '';
+ $gadget->description = isset($attributes['description']) ? trim($attributes['description']) : '';
+ $gadget->directoryTitle = isset($attributes['directory_title']) ? trim($attributes['directory_title']) : '';
+ $gadget->screenshot = isset($attributes['screenshot']) ? trim($attributes['screenshot']) : '';
+ $gadget->thumbnail = isset($attributes['thumbnail']) ? trim($attributes['thumbnail']) : '';
+ $gadget->titleUrl = isset($attributes['title_url']) ? trim($attributes['title_url']) : '';
foreach ( $ModulePrefs->Locale as $locale ) {
- $spec->localeSpecs[] = $this->processLocale($locale);
+ $gadget->localeSpecs[] = $this->processLocale($locale);
}
}
@@ -85,7 +86,7 @@
$countryAttr = isset($attributes['country']) ? trim($attributes['country']) : 'all';
$rtlAttr = isset($attributes['language_direction']) ? trim($attributes['language_direction']) : '';
$rightToLeft = $rtlAttr == 'rtl';
- $locale = new ParsedMessageBundle();
+ $locale = new LocaleSpec();
$locale->rightToLeft = $rightToLeft;
//FIXME java seems to use a baseurl here, probably for the http:// part but i'm not sure yet. Should verify behavior later to see if i got it right
$locale->url = $messageAttr;
@@ -93,10 +94,10 @@
return $locale;
}
- private function processUserPref(&$spec, $pref)
+ private function processUserPref(&$gadget, $pref)
{
$attributes = $pref->attributes();
- $preference = new ParsedUserPref();
+ $preference = new UserPref();
if (empty($attributes['name'])) {
throw new SpecParserException("All UserPrefs must have name attributes.");
}
@@ -117,10 +118,10 @@
$preference->enumValues[$valueText] = $displayText;
}
}
- $spec->userPrefs[] = $preference;
+ $gadget->userPrefs[] = $preference;
}
- private function processContent(&$spec, $content)
+ private function processContent(&$gadget, $content)
{
$attributes = $content->attributes();
if (empty($attributes['type'])) {
@@ -132,22 +133,22 @@
throw new SpecParserException("Malformed <Content> href value");
}
$url = trim($attributes['href']);
- $spec->contentType = 'URL';
- $spec->contentHref = $url;
+ $gadget->contentType = 'URL';
+ $gadget->contentHref = $url;
} else {
- $spec->contentType = 'HTML';
+ $gadget->contentType = 'HTML';
$html = (string)$content; // no trim here since empty lines can have structural meaning, so typecast to string instead
$view = isset($attributes['view']) ? trim($attributes['view']) : '';
$views = explode(',', $view);
foreach ( $views as $view ) {
- $spec->addContent($view, $html);
+ $gadget->addContent($view, $html);
}
}
}
- private function processFeature(&$spec, $feature, $required)
+ private function processFeature(&$gadget, $feature, $required)
{
- $featureSpec = new ParsedFeatureSpec();
+ $featureSpec = new FeatureSpec();
$attributes = $feature->attributes();
if (empty($attributes['feature'])) {
throw new SpecParserException("Feature not specified in <" . (required ? "Required" : "Optional") . "> tag");
@@ -163,226 +164,6 @@
$value = trim($param);
$featureSpec->params[$name] = $value;
}
- $spec->requires[$featureSpec->name] = $featureSpec;
+ $gadget->requires[$featureSpec->name] = $featureSpec;
}
}
-
-class ParsedIcon extends Icon {
- public $mode;
- public $url;
- public $type;
-
- public function getMode()
- {
- return $this->mode;
- }
-
- public function getURI()
- {
- return $this->url;
- }
-
- public function getType()
- {
- return $this->type;
- }
-}
-
-class ParsedFeatureSpec extends FeatureSpec {
- public $name;
- public $params = array();
- public $optional;
-
- public function getName()
- {
- return $this->name;
- }
-
- public function getParams()
- {
- return $this->params;
- }
-
- public function isOptional()
- {
- return $this->optional;
- }
-}
-
-class ParsedUserPref extends UserPref {
- public $name;
- public $displayName;
- public $defaultValue;
- public $required;
- public $enumValues;
- public $contentType;
-
- public function getName()
- {
- return $this->name;
- }
-
- public function getDisplayName()
- {
- return $this->displayName;
- }
-
- public function getDefaultValue()
- {
- return $this->defaultValue;
- }
-
- public function isRequired()
- {
- return $this->required;
- }
-
- public function getDataType()
- {
- return $this->dataType;
- }
-
- public function getEnumValues()
- {
- return $this->enumValues;
- }
-}
-
-class ParsedMessageBundle extends LocaleSpec {
- public $url;
- public $locale;
- public $rightToLeft;
-
- public function getURI()
- {
- return $this->url;
- }
-
- public function getLocale()
- {
- return $this->locale;
- }
-
- public function isRightToLeft()
- {
- return $this->rightToLeft;
- }
-}
-
-class ParsedGadgetSpec extends GadgetSpec {
- public $id;
- public $author;
- public $authorEmail;
- public $description;
- public $directoryTitle;
- public $contentType;
- public $contentHref;
- public $contentData = array();
- public $icons = array();
- public $localeSpecs = array();
- public $preloads = array();
- public $requires = array();
- public $screenshot;
- public $thumbnail;
- public $title;
- public $titleUrl;
- public $userPrefs = array();
-
- public function addContent($view, $data)
- {
- if (empty($view)) {
- $view = DEFAULT_VIEW;
- }
- if (! isset($this->contentData[$view])) {
- $this->contentData[$view] = '';
- }
- $this->contentData[$view] .= $data;
- }
-
- public function getAuthor()
- {
- return $this->author;
- }
-
- public function getAuthorEmail()
- {
- return $this->authorEmail;
- }
-
- public function getContentData($view = false)
- {
- if ($this->contentType != 'HTML') {
- throw new SpecParserException("getContentData() requires contentType HTML");
- }
- if (empty($view) || !$view) {
- $view = DEFAULT_VIEW;
- }
- return isset($this->contentData[$view]) ? trim($this->contentData[$view]) : '';
- }
-
- public function getContentHref()
- {
- return $this->getContentType() == 'URL' ? $this->contentHref : null;
- }
-
- public function getContentType()
- {
- return $this->contentType;
- }
-
- public function getDescription()
- {
- return $this->description;
- }
-
- public function getDirectoryTitle()
- {
- return $this->directoryTitle;
- }
-
- public function getIcons()
- {
- return $this->icons;
- }
-
- public function getLocaleSpecs()
- {
- return $this->localeSpecs;
- }
-
- public function getPreloads()
- {
- return $this->preloads;
- }
-
- public function getRequires()
- {
- return $this->requires;
- }
-
- public function getScreenshot()
- {
- return $this->screenshot;
- }
-
- public function getThumbnail()
- {
- return $this->thumbnail;
- }
-
- public function getTitle()
- {
- return $this->title;
- }
-
- public function getTitleURI()
- {
- return $this->titleUrl;
- }
-
- public function getUserPrefs()
- {
- return $this->userPrefs;
- }
-}
-
Modified: incubator/shindig/trunk/php/gadgets/src/JsFeatureLoader.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/JsFeatureLoader.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/JsFeatureLoader.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/JsFeatureLoader.php Thu Mar 6 07:43:50 2008
@@ -30,10 +30,7 @@
// so the caching of the dep loading just about doubles our performance :)
// Only downside is that if you modify the features directory, your have to clean the cache too
$cache = new $config['data_cache']();
- if (($deps = $cache->get(md5($path))) === false) {
- $deps = $this->loadFiles($path, $deps);
- $cache->set(md5($path), $deps);
- }
+ $deps = $this->loadFiles($path, $deps);
// This ensures that we register everything in the right order.
foreach ( $deps as $entry ) {
$feature = $entry;
@@ -124,7 +121,6 @@
// inline content
$type = 'INLINE';
$content = (string)$script;
-
} else {
$content = trim($attributes['src']);
if (strtolower(substr($content, 0, strlen("http://"))) == "http://") {
@@ -137,7 +133,7 @@
$content = $feature->basePath.'/'.$content;
}
}
- $library = jsLibrary::create($type, $content);
+ $library = JsLibrary::create($type, $content);
if ($library != null) {
if ($isContainer) {
$feature->containerJs[] = $library;
Modified: incubator/shindig/trunk/php/gadgets/src/JsLibrary.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/JsLibrary.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/JsLibrary.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/JsLibrary.php Thu Mar 6 07:43:50 2008
@@ -18,7 +18,7 @@
*
*/
-class jsLibrary {
+class JsLibrary {
private $types = array('FILE', 'RESOURCE', 'URL', 'INLINE');
private $type;
private $content;
@@ -51,7 +51,7 @@
static function create($type, $content)
{
if ($type == 'FILE' || $type == 'RESOURCE') {
- $content = jsLibrary::loadData($content, $type);
+ $content = JsLibrary::loadData($content, $type);
}
return new JsLibrary($type, $content);
}
@@ -60,7 +60,7 @@
{
// we don't really do 'resources', so limiting this to files only
if ($type == 'FILE') {
- return jsLibrary::loadFile($name);
+ return JsLibrary::loadFile($name);
}
return null;
}
@@ -80,7 +80,7 @@
throw new Exception("JsLibrary file not readable: $fileName");
}
if (!($content = @file_get_contents($fileName))) {
- throw new Exception("jsLibrary error reading file: $fileName");
+ throw new Exception("JsLibrary error reading file: $fileName");
}
return $content;
}
Added: incubator/shindig/trunk/php/gadgets/src/Locale.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/Locale.php?rev=634310&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/Locale.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/Locale.php Thu Mar 6 07:43:50 2008
@@ -0,0 +1,30 @@
+<?
+
+// Locale class doesn't exist in php, so to allow the code base to be closer to the java one, were faking one
+class Locale {
+ public $language;
+ public $country;
+
+ public function __construct($language, $country)
+ {
+ $this->language = $language;
+ $this->country = $country;
+ }
+ public function equals($obj)
+ {
+ if (!($obj instanceof Locale)) {
+ return false;
+ }
+ return ($obj->language == $this->language && $obj->country == $this->country);
+ }
+
+ public function getLanguage()
+ {
+ return $this->language;
+ }
+
+ public function getCountry()
+ {
+ return $this->country;
+ }
+}
\ No newline at end of file
Modified: incubator/shindig/trunk/php/gadgets/src/MessageBundleSubstituter.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/MessageBundleSubstituter.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/MessageBundleSubstituter.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/MessageBundleSubstituter.php Thu Mar 6 07:43:50 2008
@@ -65,7 +65,7 @@
// We definitely need a bundle, now we need to fetch it.
// Doing it a little different then the java version since our fetcher and cache are intergrated
$fetcher = $context->getHttpFetcher();
- list($response) = $fetcher->fetch(new remoteContentRequest($uri), $context->getOptions());
+ $response = $fetcher->fetch(new remoteContentRequest($uri));
//TODO caching the parsed bundle instead of just the xml data would be a lot more efficient and speedy
$this->bundle = $this->parser->parse($response->getResponseContent());
}
Modified: incubator/shindig/trunk/php/gadgets/src/RemoteContent.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/RemoteContent.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/RemoteContent.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/RemoteContent.php Thu Mar 6 07:43:50 2008
@@ -26,6 +26,9 @@
* it's kept in the spirit of the java variant as much as possible
*/
+class RemoteContentException extends Exception {
+}
+
abstract class RemoteContent {
- abstract public function fetch($requests, $options);
+ abstract public function fetch($request);
}
Modified: incubator/shindig/trunk/php/gadgets/src/RemoteContentFetcher.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/RemoteContentFetcher.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/RemoteContentFetcher.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/RemoteContentFetcher.php Thu Mar 6 07:43:50 2008
@@ -19,8 +19,5 @@
*/
abstract class RemoteContentFetcher {
- abstract public function addRequests($requests);
- abstract public function addRequest(remoteContentRequest $request);
- abstract public function fetchRequests();
- abstract public function pendingRequests();
+ abstract public function fetchRequest($request);
}
Modified: incubator/shindig/trunk/php/gadgets/src/RemoteContentRequest.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/RemoteContentRequest.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/RemoteContentRequest.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/RemoteContentRequest.php Thu Mar 6 07:43:50 2008
@@ -39,10 +39,10 @@
}
// returns a hash code which identifies this request, used for caching
- // takes url, headers and postbody into account for constructing the md5 checksum
+ // takes url and postbody into account for constructing the sha1 checksum
public function toHash()
{
- return md5($this->url . $this->headers . $this->postBody);
+ return sha1($this->url . $this->postBody);
}
public function getContentType()
@@ -77,7 +77,7 @@
public function isPost()
{
- return ! empty($this->postBody);
+ return ($this->postBody != false);
}
public function hasHeaders()
@@ -97,7 +97,7 @@
public function setContentType($type)
{
- $this->contentType;
+ $this->contentType = $type;
}
public function setHttpCode($code)
Modified: incubator/shindig/trunk/php/gadgets/src/Substitutions.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/Substitutions.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/Substitutions.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/Substitutions.php Thu Mar 6 07:43:50 2008
@@ -30,14 +30,14 @@
public function __construct()
{
- foreach ($this->types as $key => $type) {
+ foreach ($this->types as $type) {
$this->substitutions[$type] = array();
}
}
public function addSubstitution($type, $key, $value)
{
- $this->substitutions[$type][$key] = $value;
+ $this->substitutions[$type]["__{$type}_{$key}__"] = $value;
}
public function addSubstitutions($type, $array)
@@ -49,7 +49,7 @@
public function substitute($input)
{
- foreach ($this->types as $key => $type) {
+ foreach ($this->types as $type) {
$input = $this->substituteType($type, $input);
}
return $input;
@@ -57,22 +57,6 @@
public function substituteType($type, $input)
{
- $prefix = "__{$type}_";
- if (empty($input) || (count($this->substitutions[$type]) == 0) || (strpos($input, $prefix) === false)) {
- return $input;
- }
- while (($start = strpos($input, $prefix) + strlen($prefix)) !== false) {
- $end = strpos($input, '__', $start);
- if ($end !== false) {
- $name = substr($input, $start, $end - $start);
- if (isset($this->substitutions[$type][$name])) {
- $replacement = $this->substitutions[$type][$name];
- $input = str_replace("{$prefix}{$name}__", $replacement, $input);
- }
- } else {
- break;
- }
- }
- return $input;
+ return str_replace(array_keys($this->substitutions[$type]), array_values($this->substitutions[$type]), $input);
}
}
Modified: incubator/shindig/trunk/php/gadgets/src/http/GadgetRenderingServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/http/GadgetRenderingServlet.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/http/GadgetRenderingServlet.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/http/GadgetRenderingServlet.php Thu Mar 6 07:43:50 2008
@@ -18,14 +18,9 @@
*
*/
-include_once ('src/UserPrefs.php');
-include_once ('src/Gadget.php');
-include_once ('src/GadgetException.php');
-include_once ('src/GadgetServer.php');
-include_once ('src/GadgetSpecParser.php');
-include_once ('src/GadgetFeatureRegistry.php');
-include_once ('src/HttpProcessingOptions.php');
-include_once ("src/{$config['remote_content']}.php");
+include ('src/Gadget.php');
+
+define('DEFAULT_VIEW', 'default');
class GadgetRenderingServlet extends HttpServlet {
@@ -38,18 +33,23 @@
}
$url = trim($_GET['url']);
$moduleId = isset($_GET['mid']) && is_numeric($_GET['mid']) ? intval($_GET['mid']) : 0;
- $options = new HttpProcessingOptions();
$httpFetcher = new $config['remote_content']();
$view = ! empty($_GET['view']) ? $_GET['view'] : DEFAULT_VIEW;
$gadgetId = new GadgetId($url, $moduleId);
$prefs = $this->getPrefsFromRequest();
$locale = $this->getLocaleFromRequest();
- $registry = new GadgetFeatureRegistry($config['features_path']);
+ $cache = new $config['data_cache']();
+ // Profiling showed 40% of the processing time was spend in the feature registry
+ // So by caching this and making it a one time initialization, we almost double the performance
+ if (! ($registry = $cache->get(sha1($config['features_path'])))) {
+ $registry = new GadgetFeatureRegistry($config['features_path']);
+ $cache->set(sha1($config['features_path']), $registry);
+ }
// skipping the contentFilters bit, since there's no way to include caja yet
// hopefully a rpc service or command line version will be available at some point
$gadgetServer = new GadgetServer();
- $gadget = $gadgetServer->processGadget($gadgetId, $prefs, $locale, 'GADGET', $options, $httpFetcher, $registry);
- $this->outputGadget($gadget, $view, $options);
+ $gadget = $gadgetServer->processGadget($gadgetId, $prefs, $locale, 'GADGET', $httpFetcher, $registry);
+ $this->outputGadget($gadget, $view);
} catch ( Exception $e ) {
$this->outputError($e);
}
@@ -62,26 +62,26 @@
echo "<h1>Error</h1>";
echo $e->getMessage();
if ($config['debug']) {
- echo "<p><b>Debug info:</b></p><div style='overflow:auto; height:300px; border:1px solid #000000'><pre>";
+ echo "<p><b>Debug backtrace (set debug to false in the config to disable this)</b></p><div style='overflow:auto; height:300px; border:1px solid #000000'><pre>";
print_r(debug_backtrace());
echo "</pre></div>>";
}
echo "</body></html>";
}
- private function outputGadget($gadget, $view, $options)
+ private function outputGadget($gadget, $view)
{
switch ( $gadget->getContentType()) {
case 'HTML' :
- $this->outputHtmlGadget($gadget, $view, $options);
+ $this->outputHtmlGadget($gadget, $view);
break;
case 'URL' :
- $this->outputUrlGadget($gadget, $options);
+ $this->outputUrlGadget($gadget);
break;
}
}
- private function outputHtmlGadget($gadget, $view, $options)
+ private function outputHtmlGadget($gadget, $view)
{
global $config;
$this->setContentType("text/html; charset=UTF-8");
@@ -93,7 +93,7 @@
$externJs = "";
$inlineJs = "";
$externFmt = "<script src=\"%s\"></script>";
- $forcedLibs = $options->getForcedJsLibs();
+ $forcedLibs = $config['focedJsLibs'];
foreach ( $gadget->getJsLibraries() as $library ) {
$type = $library->getType();
if ($type == 'URL') {
@@ -107,7 +107,7 @@
if ($forcedLibs == null) {
$inlineJs .= $library->getContent() . "\n";
}
- // otherwise it was already included by options.forceJsLibs.
+ // otherwise it was already included by config.forceJsLibs.
}
}
// Forced libs first.
@@ -123,13 +123,13 @@
$output .= $externJs;
}
//FIXME quick hack to make it work with the new syndicator.js config, needs a propper implimentation later
- if (!file_exists($config['syndicator_config']) || !is_readable($config['syndicator_config'])) {
+ if (! file_exists($config['syndicator_config']) || ! is_readable($config['syndicator_config'])) {
throw new GadgetException("Invalid syndicator config");
}
// remove both /* */ and // style comments, they crash the json_decode function
- $contents = preg_replace('/\/\/.*$/m','',preg_replace('@/\\*(?:.|[\\n\\r])*?\\*/@', '', file_get_contents($config['syndicator_config'])));
+ $contents = preg_replace('/\/\/.*$/m', '', preg_replace('@/\\*(?:.|[\\n\\r])*?\\*/@', '', file_get_contents($config['syndicator_config'])));
$syndData = json_decode($contents, true);
- $output .= '<script>gadgets.config.init('.json_encode($syndData['gadgets.features']).');</script>';
+ $output .= '<script>gadgets.config.init(' . json_encode($syndData['gadgets.features']) . ');</script>';
$gadgetExceptions = array();
$content = $gadget->getContentData($view);
if (empty($content)) {
@@ -145,8 +145,9 @@
echo $output;
}
- private function outputUrlGadget($gadget, $options)
+ private function outputUrlGadget($gadget)
{
+ global $config;
// Preserve existing query string parameters.
$redirURI = $gadget->getContentHref();
$queryStr = strpos($redirURI, '?') !== false ? substr($redirURI, strpos($redirURI, '?')) : '';
@@ -154,7 +155,7 @@
// TODO: userprefs on the fragment rather than query string
$query .= $this->getPrefsQueryString($gadget->getUserPrefValues());
$libs = array();
- $forcedLibs = $options->getForcedJsLibs();
+ $forcedLibs = $config['focedJsLibs'];
if ($forcedLibs == null) {
$reqs = $gadget->getRequires();
foreach ( $reqs as $key => $val ) {
@@ -163,7 +164,7 @@
} else {
$libs = explode(':', $forcedLibs);
}
- $query .= $this->appendLibsToQuery($libs);
+ $query .= $this->appendLibsToQuery($libs, $gadget);
// code bugs out with me because of the invalid url syntax since we dont have a URI class to fix it for us
// this works around that
if (substr($query, 0, 1) == '&') {
@@ -174,12 +175,13 @@
die();
}
- private function appendLibsToQuery($libs)
+ private function appendLibsToQuery($libs, $gadget)
{
+ global $config;
$ret = "&";
- $ret .= LIBS_PARAM_NAME;
+ $ret .= $config['libs_param_name'];
$ret .= "=";
- $ret .= $this->getJsUrl($libs);
+ $ret .= $this->getJsUrl($libs, $gadget);
return $ret;
}
@@ -197,8 +199,9 @@
return $ret;
}
- private function getJsUrl($libs)
+ private function getJsUrl($libs, $gadget)
{
+ global $config;
$buf = '';
if (! is_array($libs) || ! count($libs)) {
$buf = 'core';
@@ -213,8 +216,16 @@
$buf .= $lib;
}
}
- //FIXME add sha1 / md5 checksum of all js content as unique key as 'version'
- $buf .= ".js?v=";
+ // Build a version string from the sha1() checksum of all included javascript
+ // to ensure the client always has the right version
+ $inlineJs = '';
+ foreach ( $gadget->getJsLibraries() as $library ) {
+ $type = $library->getType();
+ if ($type != 'URL') {
+ $inlineJs .= $library->getContent() . "\n";
+ }
+ }
+ $buf .= ".js?v=" . sha1($inlineJs);
return $buf;
}
Modified: incubator/shindig/trunk/php/gadgets/src/http/HttpServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/http/HttpServlet.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/http/HttpServlet.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/http/HttpServlet.php Thu Mar 6 07:43:50 2008
@@ -31,6 +31,7 @@
private $lastModified = false;
private $contentType = 'text/html';
private $charset = 'UTF-8';
+ public $noHeaders = false;
public function __construct()
{
@@ -40,47 +41,49 @@
public function __destruct()
{
- die();
- // attempt at some propper header handling from php
- // this departs a little from the shindig code but it should give is valid http protocol handling
- header("Content-Type: $this->contentType; charset={$this->charset}");
- header('Connection: Keep-Alive');
- header('Keep-Alive: timeout=15, max=30');
- header('Accept-Ranges: bytes');
- header('Content-Length: ' . ob_get_length());
- header('Cache-Control: public,max-age=' . CACHE_TIME . ',must-revalidate');
- header("Expires: " . gmdate("D, d M Y H:i:s", time() + CACHE_TIME) . " GMT");
- $content = ob_get_clean();
- // Obey browsers (or proxy's) request to send a fresh copy if we recieve a no-cache pragma or cache-control request
- if (! isset($_SERVER['HTTP_PRAGMA']) || ! strstr(strtolower($_SERVER['HTTP_PRAGMA']), 'no-cache') && (! isset($_SERVER['HTTP_CACHE_CONTROL']) || ! strstr(strtolower($_SERVER['HTTP_CACHE_CONTROL']), 'no-cache'))) {
- // If the browser send us a E-TAG check if it matches (sha1 sum of content), if so send a not modified header instead of content
- $etag = md5($content);
- if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $etag) {
- header("ETag: \"$etag\"");
- if ($this->lastModified) {
- header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $this->lastModified));
- }
- header("HTTP/1.1 304 Not Modified");
- header('Content-Length: 0');
- die();
- }
- header("ETag: \"$etag\"");
- // If no etag is present, then check if maybe this browser supports if_modified_since tags,
- // check it against our lastModified (if it's set)
- if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $this->lastModified && ! isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
- $if_modified_since = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
- if ($this->lastModified <= $if_modified_since) {
- header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $this->lastModified));
+ global $config;
+ if (!$this->noHeaders) {
+ // attempt at some propper header handling from php
+ // this departs a little from the shindig code but it should give is valid http protocol handling
+ header("Content-Type: $this->contentType; charset={$this->charset}");
+ header('Connection: Keep-Alive');
+ header('Keep-Alive: timeout=15, max=30');
+ header('Accept-Ranges: bytes');
+ header('Content-Length: ' . ob_get_length());
+ header('Cache-Control: public,max-age=' . $config['cache_time'] . ',must-revalidate');
+ header("Expires: " . gmdate("D, d M Y H:i:s", time() + $config['cache_time']) . " GMT");
+ $content = ob_get_clean();
+ // Obey browsers (or proxy's) request to send a fresh copy if we recieve a no-cache pragma or cache-control request
+ if (! isset($_SERVER['HTTP_PRAGMA']) || ! strstr(strtolower($_SERVER['HTTP_PRAGMA']), 'no-cache') && (! isset($_SERVER['HTTP_CACHE_CONTROL']) || ! strstr(strtolower($_SERVER['HTTP_CACHE_CONTROL']), 'no-cache'))) {
+ // If the browser send us a E-TAG check if it matches (sha1 sum of content), if so send a not modified header instead of content
+ $etag = sha1($content);
+ if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $etag) {
+ header("ETag: \"$etag\"");
+ if ($this->lastModified) {
+ header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $this->lastModified));
+ }
header("HTTP/1.1 304 Not Modified");
header('Content-Length: 0');
die();
}
+ header("ETag: \"$etag\"");
+ // If no etag is present, then check if maybe this browser supports if_modified_since tags,
+ // check it against our lastModified (if it's set)
+ if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $this->lastModified && ! isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
+ $if_modified_since = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
+ if ($this->lastModified <= $if_modified_since) {
+ header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $this->lastModified));
+ header("HTTP/1.1 304 Not Modified");
+ header('Content-Length: 0');
+ die();
+ }
+ }
+ if ($this->lastModified) {
+ header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $this->lastModified));
+ }
}
- if ($this->lastModified) {
- header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $this->lastModified));
- }
+ echo $content;
}
- echo $content;
}
public function setContentType($type)
Modified: incubator/shindig/trunk/php/gadgets/src/http/JsServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/http/JsServlet.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/http/JsServlet.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/http/JsServlet.php Thu Mar 6 07:43:50 2008
@@ -23,6 +23,7 @@
public function doGet()
{
global $config;
+ $this->noHeaders = true;
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
header("HTTP/1.1 304 Not Modified");
header('Content-Length: 0');
Modified: incubator/shindig/trunk/php/gadgets/src/http/ProxyHandler.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/http/ProxyHandler.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/http/ProxyHandler.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/http/ProxyHandler.php Thu Mar 6 07:43:50 2008
@@ -20,9 +20,6 @@
include_once ("src/{$config['gadget_token']}.php");
include_once ("src/{$config['gadget_signer']}.php");
-include_once ("src/HttpProcessingOptions.php");
-
-//TODO make sure this all works, especially the header passthru and post parts
// according to features/core/io.js, this is high on the list of things to scrap
define('UNPARSEABLE_CRUFT', "throw 1; < don't be evil' >");
@@ -35,85 +32,107 @@
$this->fetcher = $fetcher;
}
- public function fetchJson($signer, $method)
+ public function fetchJson($url, $signer, $method)
{
$token = $this->extractAndValidateToken($signer);
- $url = $_GET['url'];
$originalUrl = $this->validateUrl($url);
$signedUrl = $this->signUrl($originalUrl, $token);
// Fetch the content and convert it into JSON.
// TODO: Fetcher needs to handle variety of HTTP methods.
- $result = $this->fetchContent($signedUrl, new HttpProcessingOptions(), $method);
+ $result = $this->fetchContent($signedUrl, $method);
$status = (int)$result->getHttpCode();
- header("HTTP/1.1 $status", true);
+ //header("HTTP/1.1 $status", true);
if ($status == 200) {
$output = '';
- $json = array('body' => $result->getResponseContent(), 'rc' => $status, 'url' => $url);
+ $json = array($url => array('body' => $result->getResponseContent(), 'rc' => $status));
$json = json_encode($json);
$output = UNPARSEABLE_CRUFT . $json;
$this->setCachingHeaders();
- header("application/json; charset=utf-8");
- header("Content-Disposition", "attachment;filename=p.txt");
+ header("application/json; charset=utf-8", true);
echo $output;
+ } else {
+ @ob_end_clean();
+ header("HTTP/1.0 404 Not Found", true);
+ echo "<html><body><h1>404 - Not Found</h1></body></html>";
}
+ die();
}
- public function fetch($signer, $method)
+ public function fetch($url, $signer, $method)
{
$token = $this->extractAndValidateToken($signer);
- $originalUrl = $this->validateUrl($_GET['url']);
+ $originalUrl = $this->validateUrl($url);
$signedUrl = $this->signUrl($originalUrl, $token);
//TODO: Fetcher needs to handle variety of HTTP methods.
- $result = $this->fetchContent($signedUrl, new HttpProcessingOptions(), $method);
+ $result = $this->fetchContent($signedUrl, $method);
// TODO: Fetcher needs to handle variety of HTTP methods.
$status = (int)$result->getHttpCode();
- header("HTTP/1.1 $status", true);
if ($status == 200) {
$headers = explode("\n", $result->getResponseHeaders());
foreach ( $headers as $header ) {
- header($header);
+ if (strpos($header, ':')) {
+ $key = trim(substr($header, 0, strpos($header, ':')));
+ $val = trim(substr($header, strpos($header, ':') + 1));
+ if (strcasecmp($key, "Transfer-Encoding") != 0 && strcasecmp($key, "Cache-Control") != 0 && strcasecmp($key, "Expires") != 0 && strcasecmp($key, "Content-Length") != 0) {
+ header("$key: $val");
+ }
+ }
}
$this->setCachingHeaders();
// then echo the content
echo $result->getResponseContent();
+ } else {
+ @ob_end_clean();
+ header("HTTP/1.0 404 Not Found", true);
+ echo "<html><body><h1>404 - Not Found ($status)</h1>";
+ echo "</body></html>";
}
+ // make sure the HttpServlet destructor doesn't override ours
+ die();
}
- private function fetchContent($signedUrl, $procOptions, $method)
+ private function fetchContent($signedUrl, $method)
{
//TODO get actual character encoding from the request
// Extract the request headers from the $_SERVER super-global (this -does- unfortunatly mean that any header that php doesn't understand won't be proxied thru though)
// if this turns out to be a problem we could add support for HTTP_RAW_HEADERS, but this depends on a php.ini setting, so i'd rather prevent that from being required
$headers = '';
- foreach ( $_SERVER as $key => $val ) {
- if (substr($key, 0, strlen('HTTP_')) == 'HTTP_') {
- // massage the header key to something a bit more propper (example 'HTTP_ACCEPT_LANGUAGE' becomes 'Accept-Language')
- // TODO: We probably need to test variations as well.
- $key = str_replace(' ', '_', ucwords(strtolower(str_replace('-', ' ', substr($key, strlen('HTTP_'))))));
- if ($key != 'Keep_alive' && $key != 'Connection' && $key != 'Host' && $key != 'Accept' && $key != 'Accept-Encoding') {
- // propper curl header format according to http://www.php.net/manual/en/function.curl-setopt.php#80099
- $headers .= "$key: $val\n";
- }
+ $requestHeaders = $this->request_headers();
+ foreach ( $requestHeaders as $key => $val ) {
+ if ($key != 'Keep-alive' && $key != 'Connection' && $key != 'Host' && $key != 'Accept' && $key != 'Accept-Encoding') {
+ // propper curl header format according to http://www.php.net/manual/en/function.curl-setopt.php#80099
+ $headers .= "$key: $val\n";
}
}
if ($method == 'POST') {
+ $data = isset($_GET['postData']) ? $_GET['postData'] : false;
+ if (! $data) {
+ $data = isset($_POST['postData']) ? $_POST['postData'] : false;
+ }
$postData = '';
- $first = true;
- foreach ( $_POST as $key => $val ) {
- if (! $first) {
- $postData .= '&';
- } else {
- $first = false;
+ if ($data) {
+ $data = urldecode($data);
+ $entries = explode('&', $data);
+ foreach ( $entries as $entry ) {
+ $parts = explode('=', $entry);
+ // Process only if its a valid value=something pair
+ if (count($parts) == 2) {
+ $postData .= urlencode($parts[0]) . '=' . urlencode($parts[1]) . '&';
+ }
+ }
+ // chop of the trailing &
+ if (strlen($postData)) {
+ $postData = substr($postData, 0, strlen($postData) - 1);
}
- // make sure all the keys and val's are propperly encoded
- $postData .= urlencode(urldecode($key)) . '=' . urlencode(urldecode($val));
}
+ // even if postData is an empty string, it will still post (since RemoteContentRquest checks if its false)
+ // so the request to POST is still honored
$request = new RemoteContentRequest($signedUrl, $headers, $postData);
- list($request) = $this->fetcher->fetch($request, $procOptions);
+ $request = $this->fetcher->fetch($request);
} else {
$request = new RemoteContentRequest($signedUrl, $headers);
- list($request) = $this->fetcher->fetch($request, $procOptions);
+ $request = $this->fetcher->fetch($request);
}
return $request;
}
@@ -121,8 +140,8 @@
private function setCachingHeaders()
{
// TODO: Re-implement caching behavior if appropriate.
- header("Cache-Control", "private; max-age=0");
- header("Expires", time() - 30);
+ header("Cache-Control: private; max-age=0", true);
+ header("Expires: " . gmdate("D, d M Y H:i:s", time() - 3000) . " GMT", true);
}
private function validateUrl($url)
@@ -136,17 +155,45 @@
if ($signer == null) {
return null;
}
- $token = isset($_GET["st"]) ? $_GET["st"] : '';
+ $token = isset($_GET["st"]) ? $_GET["st"] : false;
+ if ($token) {
+ $token = isset($_POST['st']) ? $_POST['st'] : '';
+ }
return $signer->createToken($token);
}
private function signUrl($originalUrl, $token)
{
- if ($token == null || (isset($_GET['authz']) && $_GET['authz'] != 'signed')) {
+ $authz = isset($_GET['authz']) ? $_GET['authz'] : false;
+ if (! $authz) {
+ $authz = isset($_POST['authz']) ? $_POST['authz'] : '';
+ }
+ if ($token == null || $authz != 'signed') {
return $originalUrl;
}
- $method = isset($_GET['httpMethod']) ? $_GET['httpMethod'] : 'GET';
+ $method = isset($_GET['httpMethod']) ? $_GET['httpMethod'] : false;
+ if ($method) {
+ $method = isset($_POST['httpMethod']) ? $_POST['httpMethod'] : 'GET';
+ }
return $token->signUrl($originalUrl, $method);
}
-
+
+ function request_headers()
+ {
+ // Try to use apache's request headers if available
+ if (function_exists("apache_request_headers")) {
+ if (($headers = apache_request_headers())) {
+ return $headers;
+ }
+ }
+ // if that failed, try to create them from the _SERVER superglobal
+ $headers = array();
+ foreach ( array_keys($_SERVER) as $skey ) {
+ if (substr($skey, 0, 5) == "HTTP_") {
+ $headername = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($skey, 0, 5)))));
+ $headers[$headername] = $_SERVER[$skey];
+ }
+ }
+ return $headers;
+ }
}
Modified: incubator/shindig/trunk/php/gadgets/src/http/ProxyServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/http/ProxyServlet.php?rev=634310&r1=634309&r2=634310&view=diff
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/http/ProxyServlet.php (original)
+++ incubator/shindig/trunk/php/gadgets/src/http/ProxyServlet.php Thu Mar 6 07:43:50 2008
@@ -23,10 +23,22 @@
class ProxyServlet extends HttpServlet {
- public function doGet($method = 'GET')
+ public function doGet()
{
global $config;
- if (empty($_GET['url'])) {
+ $this->noHeaders = true;
+ // those should be doable in one statement, but php seems to still evauluate the second ? and : pair,
+ // so throws an error about undefined index on post, even though it found it in get ... odd bug
+ $url = isset($_GET['url']) ? $_GET['url'] : false;
+ if (!$url) {
+ $url = isset($_POST['url']) ? $_POST['url'] : false;
+ }
+ $url = urldecode($url);
+ $method = isset($_GET['httpMethod']) ? $_GET['httpMethod'] : false;
+ if (!$method) {
+ $method = isset($_POST['httpMethod']) ? $_POST['httpMethod'] : 'GET';
+ }
+ if (!$url) {
header("HTTP/1.0 400 Bad Request", true);
echo "<html><body><h1>400 - Missing url parameter</h1></body></html>";
}
@@ -34,14 +46,14 @@
$httpFetcher = new $config['remote_content']();
$proxyHandler = new ProxyHandler($httpFetcher);
if (! empty($_GET['output']) && $_GET['output'] == 'js') {
- $proxyHandler->fetchJson($gadgetSigner, $method);
+ $proxyHandler->fetchJson($url, $gadgetSigner, $method);
} else {
- $proxyHandler->fetch($gadgetSigner, $method);
+ $proxyHandler->fetch($url, $gadgetSigner, $method);
}
}
public function doPost()
{
- $this->doGet('POST');
+ $this->doGet();
}
}