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/05 20:43:20 UTC
svn commit: r633998 [1/2] - in /incubator/shindig/trunk: config/ php/
php/gadgets/ php/gadgets/src/ php/gadgets/src/http/ php/js/
Author: lindner
Date: Wed Mar 5 11:43:14 2008
New Revision: 633998
URL: http://svn.apache.org/viewvc?rev=633998&view=rev
Log:
Apply patch from Chris Chabot that provides a new
PHP implementation as specified in SHINDIG-103
Added:
incubator/shindig/trunk/php/gadgets/
incubator/shindig/trunk/php/gadgets/.htaccess
incubator/shindig/trunk/php/gadgets/README
incubator/shindig/trunk/php/gadgets/config.php
incubator/shindig/trunk/php/gadgets/index.php
incubator/shindig/trunk/php/gadgets/src/
incubator/shindig/trunk/php/gadgets/src/BasicGadgetBlacklist.php
incubator/shindig/trunk/php/gadgets/src/BasicGadgetSigner.php
incubator/shindig/trunk/php/gadgets/src/BasicGadgetToken.php
incubator/shindig/trunk/php/gadgets/src/BasicRemoteContent.php
incubator/shindig/trunk/php/gadgets/src/BasicRemoteContentFetcher.php
incubator/shindig/trunk/php/gadgets/src/BidiSubstituter.php
incubator/shindig/trunk/php/gadgets/src/Cache.php
incubator/shindig/trunk/php/gadgets/src/FileCache.php
incubator/shindig/trunk/php/gadgets/src/Gadget.php
incubator/shindig/trunk/php/gadgets/src/GadgetBlacklist.php
incubator/shindig/trunk/php/gadgets/src/GadgetContext.php
incubator/shindig/trunk/php/gadgets/src/GadgetException.php
incubator/shindig/trunk/php/gadgets/src/GadgetFeature.php
incubator/shindig/trunk/php/gadgets/src/GadgetFeatureFactory.php
incubator/shindig/trunk/php/gadgets/src/GadgetFeatureRegistry.php
incubator/shindig/trunk/php/gadgets/src/GadgetServer.php
incubator/shindig/trunk/php/gadgets/src/GadgetSigner.php
incubator/shindig/trunk/php/gadgets/src/GadgetSpec.php
incubator/shindig/trunk/php/gadgets/src/GadgetSpecParser.php
incubator/shindig/trunk/php/gadgets/src/GadgetToken.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/JsFeatureLoader.php
incubator/shindig/trunk/php/gadgets/src/JsLibrary.php
incubator/shindig/trunk/php/gadgets/src/JsLibraryFeatureFactory.php
incubator/shindig/trunk/php/gadgets/src/MessageBundle.php
incubator/shindig/trunk/php/gadgets/src/MessageBundleParser.php
incubator/shindig/trunk/php/gadgets/src/MessageBundleSubstituter.php
incubator/shindig/trunk/php/gadgets/src/ModuleSubstituter.php
incubator/shindig/trunk/php/gadgets/src/ProcessingOptions.php
incubator/shindig/trunk/php/gadgets/src/RemoteContent.php
incubator/shindig/trunk/php/gadgets/src/RemoteContentException.php
incubator/shindig/trunk/php/gadgets/src/RemoteContentFetcher.php
incubator/shindig/trunk/php/gadgets/src/RemoteContentRequest.php
incubator/shindig/trunk/php/gadgets/src/SpecParserException.php
incubator/shindig/trunk/php/gadgets/src/Substitutions.php
incubator/shindig/trunk/php/gadgets/src/UserPrefSubstituter.php
incubator/shindig/trunk/php/gadgets/src/UserPrefs.php
incubator/shindig/trunk/php/gadgets/src/http/
incubator/shindig/trunk/php/gadgets/src/http/FilesServlet.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
incubator/shindig/trunk/php/gadgets/src/http/RpcServlet.php
Removed:
incubator/shindig/trunk/php/README
incubator/shindig/trunk/php/RSA.class.php
incubator/shindig/trunk/php/comframe.php
incubator/shindig/trunk/php/config.php
incubator/shindig/trunk/php/container.php
incubator/shindig/trunk/php/crypto.php
incubator/shindig/trunk/php/index.php
incubator/shindig/trunk/php/js/
incubator/shindig/trunk/php/key-modulo
incubator/shindig/trunk/php/key-private
incubator/shindig/trunk/php/key-public
incubator/shindig/trunk/php/proxy.php
Modified:
incubator/shindig/trunk/config/syndicator.js
Modified: incubator/shindig/trunk/config/syndicator.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/config/syndicator.js?rev=633998&r1=633997&r2=633998&view=diff
==============================================================================
--- incubator/shindig/trunk/config/syndicator.js (original)
+++ incubator/shindig/trunk/config/syndicator.js Wed Mar 5 11:43:14 2008
@@ -28,8 +28,8 @@
// as you would for javascript objects, e.g. gadgets.features
// rather than "features".
-// NOTE: Please leave trailing commas to reduce errors when adding new fields.
-// All known common server-side JSON parsers will handle this without issue.
+// NOTE: Please _don't_ leave trailing commas because the php json parser
+// errors out on this.
// Syndicator must be an array; this allows multiple syndicators
// to share configuration.
@@ -53,20 +53,20 @@
"core.io" : {
// Note: /proxy is an open proxy. Be careful how you explose this!
"proxyUrl" : "proxy?url=%url%",
- "jsonProxyUrl" : "proxy?output=js",
+ "jsonProxyUrl" : "proxy?output=js"
},
"views" : {
"default" : {
"isOnlyVisible" : false,
- "aliases": ["DASHBOARD"],
+ "aliases": ["DASHBOARD"]
},
"profile" : {
- "isOnlyVisible" : false,
+ "isOnlyVisible" : false
},
"canvas" : {
"isOnlyVisible" : true,
"aliases" : ["FULL_PAGE"]
- },
+ }
},
"rpc" : {
// Path to the relay file. Automatically appended to the parent
@@ -77,7 +77,7 @@
// If true, this will use the legacy ifpc wire format when making rpc
// requests.
- "useLegacyProtocol" : false,
+ "useLegacyProtocol" : false
},
// Skin defaults
"skins" : {
@@ -87,7 +87,7 @@
"BG_POSITION": "",
"BG_REPEAT": "",
"FONT_COLOR": "",
- "ANCHOR_COLOR": "",
+ "ANCHOR_COLOR": ""
}
- },
+ }
}}
Added: incubator/shindig/trunk/php/gadgets/.htaccess
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/.htaccess?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/.htaccess (added)
+++ incubator/shindig/trunk/php/gadgets/.htaccess Wed Mar 5 11:43:14 2008
@@ -0,0 +1,7 @@
+<IfModule mod_rewrite.c>
+RewriteEngine On
+RewriteBase /
+RewriteCond %{REQUEST_FILENAME} !-f
+RewriteCond %{REQUEST_FILENAME} !-d
+RewriteRule . /gadgets/index.php [L]
+</IfModule>
Added: incubator/shindig/trunk/php/gadgets/README
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/README?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/README (added)
+++ incubator/shindig/trunk/php/gadgets/README Wed Mar 5 11:43:14 2008
@@ -0,0 +1,17 @@
+Installing and Running The PHP Shindig Gadget Server
+============================================
+
+1) Make sure you have PHP 5.x installed and have the simplexml and json extentions enabled; It also
+ requires apache with .htaccess and mod_rewrite support
+
+2) Copy the files to your web root, and edit the config.php web_prefix and debug settings
+ to your liking. Make sure that the features and javascript directories are also copied
+ or edit your config.php to reflect their location.
+
+3) Hit server at http://<yourhost>/gadgets/ifr?url=<gadget-url>
+ Example: http://<yourhost>/gadgets/ifr?url=http://www.labpixies.com/campaigns/todo/todo.xml
+ Or hit the sample container at http://<yourhost>/gadgets/files/samplecontainer/samplecontainer.html
+
+The PHP source of the gadget server resides in gadgets/src.
+
+For more information, see http://incubator.apache.org/projects/shindig.html
Added: incubator/shindig/trunk/php/gadgets/config.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/config.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/config.php (added)
+++ incubator/shindig/trunk/php/gadgets/config.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,47 @@
+<?
+/*
+ * I really detest such config files to be honest, why put configuration in a web document!
+ * But since PHP lacks a propper way to set application configurations, and any other method
+ * 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
+ 'web_prefix' => '/gadgets',
+
+ // location of the features directory on disk. The default setting assumes you did a
+ // full checkout of the shindig project, and not just the php part.
+ // Otherwise also checkout the features, config and javascript directories and set
+ // these to their locations
+ 'features_path' => realpath(dirname(__FILE__)).'/../../features/',
+ 'syndicator_config' => realpath(dirname(__FILE__)).'/../../config/syndicator.js',
+ 'javascript_path' => realpath(dirname(__FILE__)).'/../../javascript/',
+
+ // Configurable classes to use, this way we provide extensibility for what
+ // backends the gadget server uses for its logic functionality.
+ 'blacklist_class' => 'BasicGadgetBlacklist',
+ 'remote_content' => 'BasicRemoteContent',
+ 'gadget_signer' => 'BasicGadgetSigner',
+ 'gadget_token' => 'BasicGadgetToken',
+ 'data_cache' => 'FileCache',
+
+ // gadget server specific settings
+ 'userpref_param_prefix'=> 'up_',
+ 'libs_param_name'=> 'libs',
+ 'default_js_prefix'=> '/js/',
+ 'default_iframe_prefix'=> 'ifr?',
+
+ // show debugging output ?
+ 'debug'=> true,
+
+ // global cache age policy and location
+ 'cache_time'=> 24*60*60,
+ 'cache_root'=> '/tmp/shindig',
+
+ // In some cases we need to know the site root (for features forinstance)
+ 'base_path'=> realpath(dirname(__FILE__))
+);
Added: incubator/shindig/trunk/php/gadgets/index.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/index.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/index.php (added)
+++ incubator/shindig/trunk/php/gadgets/index.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,68 @@
+<?
+/*
+ * 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.
+ */
+
+/*
+ * Written by Chris Chabot <ch...@xs4all.nl> - http://www.chabotc.com
+ *
+ * "It is not the strongest of the species that survives, nor the most intelligent that survives.
+ * It is the one that is the most adaptable to change" - Darwin
+ *
+ * So in this php version of shindig we make like java and act like a servlet setup, and using
+ * it's structures as our reference.
+ *
+ * The .htaccess file redirects all requests that are neither an existing file or directory
+ * to this index.php, and the $servletMap checks which class is associated with it, if a mapping
+ * doesn't exist it display's a 404 error.
+ *
+ * See config.php for the global settings and backend class selections.
+ *
+ */
+
+include_once ('config.php');
+
+function __autoload($className)
+{
+ require_once 'src/' . $className . '.php';
+}
+
+$servletMap = array($config['web_prefix'] . '/files' => 'FilesServlet', $config['web_prefix'] . '/js' => 'JsServlet', $config['web_prefix'] . '/proxy' => 'ProxyServlet', $config['web_prefix'] . '/ifr' => 'GadgetRenderingServlet', $config['web_prefix'] . '/rpc' => 'RpcServlet');
+$servlet = false;
+$uri = $_SERVER["REQUEST_URI"];
+foreach ( $servletMap as $url => $class ) {
+ if (substr($uri, 0, strlen($url)) == $url) {
+ $servlet = $class;
+ break;
+ }
+}
+if ($servlet) {
+ // its worth mentioning that $class comes from our internal data array and not from
+ // the url, so the dynamic include is safe :-)
+ include_once ('src/http/HttpServlet.php');
+ include_once ("src/http/{$class}.php");
+ $class = new $class();
+ if (count($_POST)) {
+ $class->doPost();
+ } else {
+ $class->doGet();
+ }
+} else {
+ // Unhandled event, display simple 404 error
+ header("HTTP/1.0 404 Not Found");
+ echo "<html><body><h1>404 Not Found</h1></body></html>";
+}
Added: incubator/shindig/trunk/php/gadgets/src/BasicGadgetBlacklist.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/BasicGadgetBlacklist.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/BasicGadgetBlacklist.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/BasicGadgetBlacklist.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,43 @@
+<?
+/*
+ * 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 BasicGadgetBlacklist {
+ private $rules = array();
+
+ public function __construct()
+ {
+ global $config;
+ $file = $config['base_path'].'/blacklist.txt';
+ //TODO make this a configurable location
+ if (file_exists($file) && is_readable($file)) {
+ $this->rules = explode("\n", file_get_contents($file));
+ }
+ }
+
+ function isBlacklisted($url)
+ {
+ foreach ($this->rules as $rule) {
+ if (preg_match($rule, $url)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/gadgets/src/BasicGadgetSigner.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/BasicGadgetSigner.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/BasicGadgetSigner.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/BasicGadgetSigner.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,58 @@
+<?
+/*
+ * 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.
+ *
+ */
+
+/*
+ * A GadgetSigner implementation that just provides dummy data to satisfy
+ * tests and API calls. Do not use this for any security applications.
+ */
+
+
+class BasicGadgetSigner extends GadgetSigner {
+ private $timeToLive;
+
+ /**
+ * Creates a signer with 24 hour token expiry
+ */
+ public function __construct($timeToLive = false)
+ {
+ $this->timeToLive = $timeToLive ? $timeToLive : 24 * 60 * 60 * 1000;
+ }
+
+ /**
+ * {@inheritDoc}
+ * This implementation only validates non-empty tokens. Empty tokens
+ * are considered to always be valid.
+ */
+ public function createToken($stringToken)
+ {
+ if ($stringToken != null && ! empty($stringToken)) {
+ $parts = explode('$', $stringToken);
+ if (count($parts) != 2) {
+ throw new GadgetException("Invalid token format.");
+ }
+ $expiry = intval($parts[1]);
+ $currentTimeMillis = time() * 1000;
+ if ($expiry < $currentTimeMillis) {
+ throw new GadgetException("Expired token.");
+ }
+ }
+ return new BasicGadgetToken($stringToken);
+ }
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/gadgets/src/BasicGadgetToken.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/BasicGadgetToken.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/BasicGadgetToken.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/BasicGadgetToken.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,53 @@
+<?
+/*
+ * 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.
+ *
+ */
+
+/*
+ * Primitive token implementation that uses stings as tokens.
+ */
+
+class BasicGadgetToken extends GadgetToken {
+ private $token;
+
+ /**
+ * {@inheritDoc}
+ */
+ public function toSerialForm()
+ {
+ return $this->token;
+ }
+
+ /**
+ * Generates a token from an input string
+ * @param token String form of token
+ */
+ public function BasicGadgetToken($token)
+ {
+ $this->token = $token;
+ }
+
+ /**
+ * {@inheritDoc}
+ * Signer that does not sign.
+ */
+ public function signUrl($uri, $httpMethod)
+ {
+ return $uri;
+ }
+}
Added: incubator/shindig/trunk/php/gadgets/src/BasicRemoteContent.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/BasicRemoteContent.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/BasicRemoteContent.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/BasicRemoteContent.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,56 @@
+<?
+/*
+ * 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 BasicRemoteContent extends RemoteContent {
+
+ public function fetch($requests, $options)
+ {
+ 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 ($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);
+ }
+ }
+ $ret = array_merge($requests, $ret);
+ }
+ return $ret;
+ }
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/gadgets/src/BasicRemoteContentFetcher.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/BasicRemoteContentFetcher.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/BasicRemoteContentFetcher.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/BasicRemoteContentFetcher.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,97 @@
+<?
+/*
+ * 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.
+ *
+ */
+
+/*
+ * Basic remote content fetcher, uses curl_multi to fetch multiple resources at the same time
+ */
+
+class BasicRemoteContentFetcher extends remoteContentFetcher {
+ private $requests = array();
+
+ public function addRequests($requests)
+ {
+ 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()));
+ }
+ 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);
+ }
+ // 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);
+ $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);
+ }
+ curl_multi_close($mh);
+
+ $ret = $this->requests;
+ // empty our requests queue
+ $this->requests = array();
+ return $ret;
+ }
+
+ public function pendingRequests()
+ {
+ return count($this->requests);
+ }
+}
Added: incubator/shindig/trunk/php/gadgets/src/BidiSubstituter.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/BidiSubstituter.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/BidiSubstituter.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/BidiSubstituter.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,74 @@
+<?
+/*
+ * 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 BidiSubstituter extends GadgetFeatureFactory {
+ private $feature;
+
+ public function __construct()
+ {
+ $this->feature = new BidiSubstituterFeature();
+ }
+
+ public function create()
+ {
+ return $this->feature;
+ }
+}
+
+class BidiSubstituterFeature extends GadgetFeature {
+ private function getLocaleSpec($spec, $locale)
+ {
+ $localeSpecs = $spec->getLocaleSpecs();
+ foreach ( $localeSpecs as $locSpec ) {
+ //FIXME equals, localeSpec, much unknown here still..
+ if ($locSpec->getLocale()->equals($locale)) {
+ return $locSpec;
+ }
+ }
+ return null;
+ }
+
+ public function prepare($spec, $context, $params)
+ {
+ // Nothing here.
+ }
+
+ public function process($gadget, $context, $params)
+ {
+ $subst = $gadget->getSubstitutions();
+ $locale = $context->getLocale();
+ // Find an appropriate locale for the ltr flag.
+ $locSpec = $this->getLocaleSpec($gadget, $locale);
+ if ($locSpec == null) {
+ $locSpec = $this->getLocaleSpec($gadget, new Locale($locale->getLanguage(), "all"));
+ }
+ if ($locSpec == null) {
+ $locSpec = $this->getLocaleSpec($gadget, new Locale("all", "all"));
+ }
+ $rtl = false;
+ if ($locSpec != null) {
+ $rtl = $locSpec->isRightToLeft();
+ }
+ $subst->addSubstitution('BIDI', "START_EDGE", $rtl ? "right" : "left");
+ $subst->addSubstitution('BIDI', "END_EDGE", $rtl ? "left" : "right");
+ $subst->addSubstitution('BIDI', "DIR", $rtl ? "rtl" : "ltr");
+ $subst->addSubstitution('BIDI', "REVERSE_DIR", $rtl ? "ltr" : "rtl");
+ }
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/gadgets/src/Cache.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/Cache.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/Cache.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/Cache.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,27 @@
+<?
+/*
+ * 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 CacheException extends Exception {}
+
+abstract class Cache {
+ abstract function get($key);
+ abstract function set($key, $value);
+ abstract function delete($key);
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/gadgets/src/FileCache.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/FileCache.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/FileCache.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/FileCache.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,90 @@
+<?
+/*
+ * 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 impliments a basic on disk caching. That will work fine on a single host
+ * but on a multi server setup this could lead to some problems due to inconsistencies
+ * between the various cached versions on the different servers. Other methods like
+ * memcached should be used instead really.
+ *
+ * When using this file based backend, its adviced to make a cron job that scans thru the
+ * cache dir, and removes all files that are older then 24 hours (or whatever your
+ * config's CACHE_TIME is set too).
+ */
+
+//TODO add cache stampeding prevention using file locking mechanisms
+
+class FileCache extends Cache {
+
+ function get($key)
+ {
+ global $config;
+ $cacheFile = $this->getCacheFile($key);
+ if (file_exists($cacheFile) && is_readable($cacheFile)) {
+ $now = time();
+ if (($mtime = filemtime($cacheFile)) !== false && ($now - $mtime) < $config['cache_time']) {
+ if (($data = @file_get_contents($cacheFile)) !== false){
+ $data = unserialize($data);
+ return $data;
+ }
+ }
+ }
+ return false;
+ }
+
+ function set($key, $value)
+ {
+ // use the first 2 characters of the hash as a directory prefix
+ // this should prevent slowdowns due to huge directory listings
+ // and thus give some basic amount of scalability
+ $cacheDir = $this->getCacheDir($key);
+ $cacheFile = $this->getCacheFile($key);
+ if (! is_dir($cacheDir)) {
+ if (! @mkdir($cacheDir, 0755, true)) {
+ throw new CacheException("Could not create cache directory");
+ }
+ }
+ // we serialize the whole request object, since we don't only want the
+ // responseContent but also the postBody used, headers, size, etc
+ $data = serialize($value);
+ if (! file_put_contents($cacheFile, $data)) {
+ throw new CacheException("Could not store data in cache file");
+ }
+ }
+
+ function delete($key)
+ {
+ $file = $this->getCacheFile($key);
+ if (! @unlink($file)) {
+ throw new CacheException("Cache file could not be deleted");
+ }
+ }
+
+ private function getCacheDir($hash)
+ {
+ global $config;
+ return $config['cache_root'] . '/' . substr($hash, 0, 2);
+ }
+
+ private function getCacheFile($hash)
+ {
+ return $this->getCacheDir($hash) . '/' . $hash;
+ }
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/gadgets/src/Gadget.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/Gadget.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/Gadget.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/Gadget.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,202 @@
+<?
+/*
+ * 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.
+ *
+ */
+
+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();
+ }
+}
+
+class Gadget extends GadgetSpec {
+ public $baseSpec;
+ private $jsLibraries;
+ private $substitutions;
+ private $userPrefValues;
+ private $currentMessageBundle = array();
+
+ public function __construct($id, GadgetSpec $baseSpec, $prefs)
+ {
+ $this->id = $id;
+ $this->baseSpec = $baseSpec;
+ $this->substitutions = new Substitutions();
+ $this->userPrefValues = $prefs;
+ $this->jsLibraries = array();
+ }
+
+ public function getAuthor()
+ {
+ return $this->substitutions->substitute($this->baseSpec->getAuthor());
+ }
+
+ public function getAuthorEmail()
+ {
+ return $this->substitutions->substitute($this->baseSpec->getAuthorEmail());
+ }
+
+ public function getBaseSpec()
+ {
+ return $this->baseSpec;
+ }
+
+ public function getContentData($view = false)
+ {
+ return $this->substitutions->substitute($this->baseSpec->getContentData($view));
+ }
+
+ public function getContentHref()
+ {
+ return $this->substitutions->substitute($this->baseSpec->getContentHref());
+ }
+
+ public function getContentType()
+ {
+ return $this->baseSpec->getContentType();
+ }
+
+ public function getCurrentMessageBundle()
+ {
+ return $this->currentMessageBundle;
+ }
+
+ public function getDescription()
+ {
+ return $this->substitutions->substitute($this->baseSpec->getDescription());
+ }
+
+ public function getDirectoryTitle()
+ {
+ return $this->substitutions->substitute($this->baseSpec->getDirectoryTitle());
+ }
+
+ public function getIcons()
+ {
+ return $this->baseSpec->getIcons();
+ }
+
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ public function getJsLibraries()
+ {
+ return $this->jsLibraries;
+ }
+
+ public function addJsLibrary($library)
+ {
+ $this->jsLibraries[] = $library;
+ }
+
+ public function getLocaleSpecs()
+ {
+ return $this->baseSpec->getLocaleSpecs();
+ }
+
+ public function getFeatureParams($gadget, $feature)
+ {
+ //FIXME not working atm
+ $spec = $gadget->getRequires();
+ $spec = isset($spec[$feature->getName()]) ? $spec[$feature->getName()] : null;
+ if ($spec == null) {
+ return array();
+ } else {
+ return $spec->getParams();
+ }
+ }
+
+ public function getPreloads()
+ {
+ $ret = array();
+ foreach ( $this->baseSpec->getPreloads() as $preload ) {
+ $ret[] = $this->substitutions->substitute($preload);
+ }
+ return $ret;
+ }
+
+ public function getRequires()
+ {
+ return $this->baseSpec->getRequires();
+ }
+
+ public function getScreenshot()
+ {
+ return $this->substitutions->substitute($this->baseSpec->getScreenshot());
+ }
+
+ public function getSubstitutions()
+ {
+ return $this->substitutions;
+ }
+
+ public function getThumbnail()
+ {
+ return $this->substitutions->substitute($this->baseSpec->getThumbnail());
+ }
+
+ public function getTitle()
+ {
+ return $this->substitutions->substitute($this->baseSpec->getTitle());
+ }
+
+ public function getTitleURI()
+ {
+ $ret = null;
+ if (($uri = $this->baseSpec->getTitleURI()) != null) {
+ $ret = $this->substitutions->substitute($uri);
+ }
+ return $ret;
+ }
+
+ public function getUserPrefs()
+ {
+ return $this->baseSpec->getUserPrefs();
+ }
+
+ public function getUserPrefValues()
+ {
+ return $this->userPrefValues;
+ }
+
+ public function setCurrentMessageBundle($messageBundle)
+ {
+ $this->currentMessageBundle = $messageBundle;
+ }
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/gadgets/src/GadgetBlacklist.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetBlacklist.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetBlacklist.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetBlacklist.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,23 @@
+<?
+/*
+ * 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 GadgetBlacklist {
+ abstract function isBlacklisted($url);
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/gadgets/src/GadgetContext.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetContext.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetContext.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetContext.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,67 @@
+<?
+/*
+ * 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.
+ *
+ */
+
+/*
+ * the httpFetcher (RemoteContentFetcher) is our cache too, so we skip the
+ * messageBundleCache vars and params.
+ */
+
+class GadgetContext {
+ private $httpFetcher;
+ private $locale;
+ private $options;
+ private $renderingContext;
+ private $registry;
+
+ public function __construct(RemoteContent $httpFetcher, Locale $locale, $renderingContext, ProcessingOptions $options, GadgetFeatureRegistry $registry)
+ {
+ $this->httpFetcher = $httpFetcher;
+ $this->locale = $locale;
+ $this->renderingContext = $renderingContext;
+ $this->options = $options;
+ $this->registry = $registry;
+ }
+
+ public function getRenderingContext()
+ {
+ return $this->renderingContext;
+ }
+
+ public function getHttpFetcher()
+ {
+ return $this->httpFetcher;
+ }
+
+ public function getLocale()
+ {
+ return $this->locale;
+ }
+
+ public function getFeatureRegistry()
+ {
+ return $this->registry;
+ }
+
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/gadgets/src/GadgetException.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetException.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetException.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetException.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,21 @@
+<?
+/*
+ * 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 GadgetException extends Exception {}
\ No newline at end of file
Added: incubator/shindig/trunk/php/gadgets/src/GadgetFeature.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetFeature.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetFeature.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetFeature.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,24 @@
+<?
+/*
+ * 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 GadgetFeature {
+ abstract public function prepare($gadget, $context, $params);
+ abstract public function process($gadget, $context, $params);
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/gadgets/src/GadgetFeatureFactory.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetFeatureFactory.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetFeatureFactory.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetFeatureFactory.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,23 @@
+<?
+/*
+ * 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 GadgetFeatureFactory {
+ abstract public function create();
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/gadgets/src/GadgetFeatureRegistry.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetFeatureRegistry.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetFeatureRegistry.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetFeatureRegistry.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,170 @@
+<?
+/*
+ * 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 GadgetFeatureRegistry {
+ private $features = array();
+ private $core = array();
+ private $coreDone = false;
+
+ public function __construct($featurePath)
+ {
+ $this->registerFeatures($featurePath);
+ }
+
+ public function registerFeatures($featurePath)
+ {
+ if (empty($featurePath) || $featurePath == null) {
+ return;
+ }
+ $FEAT_MSG_BUNDLE = "core.msgbundlesubst";
+ $FEAT_BIDI = "core.bidisubst";
+ $FEAT_MODULE = "core.modulesubst";
+ $FEAT_USER_PREF_SUBST = "core.prefsubst";
+ $coreDeps = array();
+ $loader = new JsFeatureLoader();
+ $jsFeatures = $loader->loadFeatures($featurePath, $this);
+ if (! $this->coreDone) {
+ foreach ( $jsFeatures as $entry ) {
+ if (strtolower(substr($entry->name, 0, strlen('core'))) == 'core') {
+ $coreDeps[] = $entry->name;
+ $this->core[$entry->name] = $entry->name;
+ }
+ }
+ $this->core[$FEAT_MSG_BUNDLE] = $FEAT_MSG_BUNDLE;
+ $this->register($FEAT_MSG_BUNDLE, $coreDeps, new MessageBundleSubstituter());
+ $this->core[$FEAT_BIDI] = $FEAT_BIDI;
+ $this->register($FEAT_BIDI, $coreDeps, new BidiSubstituter());
+ $this->core[$FEAT_MODULE] = $FEAT_MODULE;
+ $this->register($FEAT_MODULE, $coreDeps, new ModuleSubstituter());
+ $this->core[$FEAT_USER_PREF_SUBST] = $FEAT_USER_PREF_SUBST;
+ $this->register($FEAT_USER_PREF_SUBST, $coreDeps, new UserPrefSubstituter());
+ // Make sure non-core features depend on core.
+ foreach ( $jsFeatures as $entry ) {
+ if (strtolower(substr($entry->name, 0, strlen('core'))) != 'core') {
+ $entry->deps = array_merge($entry->deps, $this->core);
+ }
+ }
+ $this->coreDone = true;
+ }
+ }
+
+ public function register($name, $deps, $feature)
+ {
+ // Core entries must come first.
+ $entry = isset($this->features[$name]) ? $this->features[$name] : null;
+ if ($entry == null) {
+ $entry = new GadgetFeatureRegistryEntry($name, $deps, $feature, $this);
+ if ($this->coreDone) {
+ $entry->deps = array_merge($entry->deps, $this->core);
+ }
+ $this->features[$name] = $entry;
+ $this->validateFeatureGraph();
+ }
+ return $entry;
+ }
+
+ private function validateFeatureGraph()
+ {
+ // TODO: ensure that features form a DAG and that all deps are provided
+ }
+
+ public function getAllFeatures()
+ {
+ return $this->features;
+ }
+
+ public function getIncludedFeatures($needed, &$resultsFound, &$resultsMissing)
+ {
+ $resultsFound = array();
+ $resultsMissing = array();
+ if (! count($needed)) {
+ // Shortcut for gadgets that don't have any explicit dependencies.
+ $resultsFound = $this->core;
+ return true;
+ }
+ foreach ( $needed as $featureName ) {
+ $entry = isset($this->features[$featureName]) ? $this->features[$featureName] : null;
+ if ($entry == null) {
+ $resultsMissing[] = $featureName;
+ } else {
+ $this->addEntryToSet($resultsFound, $entry);
+ }
+ }
+ return count($resultsMissing) == 0;
+ }
+
+ private function addEntryToSet(&$results, $entry)
+ {
+ foreach ( $entry->deps as $dep ) {
+ $this->addEntryToSet($results, $this->features[$dep]);
+ }
+ $results[$entry->name] = $entry->name;
+ }
+
+ public function getEntry($name)
+ {
+ return $this->features[$name];
+ }
+}
+
+// poor man's namespacing
+class GadgetFeatureRegistryEntry {
+ public $name;
+ public $deps = array();
+ public $feature;
+
+ public function __construct($name, $deps, $feature, $registry)
+ {
+ $this->name = $name;
+ if ($deps != null) {
+ foreach ( $deps as $dep ) {
+ $entry = $registry->getEntry($dep);
+ $this->deps[$entry->name] = $entry->name;
+ }
+ }
+ $this->feature = $feature;
+ }
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function getDependencies()
+ {
+ return $this->deps;
+ }
+
+ public function getFeature()
+ {
+ return $this->feature;
+ }
+}
+
+class NoOpFeature extends GadgetFeature {
+
+ public function prepare($gadget, $context, $params)
+ {
+ }
+
+ public function process($gadget, $context, $params)
+ {
+ }
+}
Added: incubator/shindig/trunk/php/gadgets/src/GadgetServer.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetServer.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetServer.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetServer.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,115 @@
+<?
+/*
+ * 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 isn't a multi threaded java envirioment, so we do things a bit more straightforward with context blocks and workflows,
+ * which means departing from how the shinding java implementation works but it saves a lot 'dead' code here
+ */
+
+class GadgetServer {
+ private $registry;
+ private $blacklist;
+ private $gc;
+ private $gadgetId;
+ private $userPrefs;
+ private $renderingContext;
+ private $options;
+ private $locale;
+ private $httpFetcher;
+
+ public function processGadget($gadgetId, $userPrefs, $locale, $rctx, $options, $httpFetcher, $registry)
+ {
+ global $config;
+ $this->gadgetId = $gadgetId;
+ $this->userPrefs = $userPrefs;
+ $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->blacklist = new $config['blacklist_class']();
+ $gadget = $this->specLoad();
+ $this->featuresLoad($gadget);
+ return $gadget;
+ }
+
+ private function specLoad()
+ {
+ if ($this->blacklist != null && $this->blacklist->isBlacklisted($this->gadgetId->getURI())) {
+ throw new GadgetException("Gadget is blacklisted");
+ }
+ $request = new remoteContentRequest($this->gadgetId->getURI());
+ list($xml) = $this->httpFetcher->fetch($request, $this->options);
+ 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);
+ return $gadget;
+ }
+
+ private function featuresLoad($gadget)
+ {
+ $requires = $gadget->getRequires();
+ $needed = array();
+ $optionalNames = array();
+ foreach ( $requires as $key => $entry ) {
+ $needed[] = $key;
+ if ($entry->isOptional()) {
+ $optionalNames[] = $key;
+ }
+ }
+ $resultsFound = array();
+ $resultsMissing = array();
+ $missingOptional = array();
+ $missingRequired = array();
+ $this->registry->getIncludedFeatures($needed, $resultsFound, $resultsMissing);
+ foreach ( $resultsMissing as $missingResult ) {
+ if (in_array($missingResult, $optionalNames)) {
+ $missingOptional[$missingResult] = $missingResult;
+ } else {
+ $missingRequired[$missingResult] = $missingResult;
+ }
+ }
+ if (count($missingRequired)) {
+ throw new GadgetException("Unsupported feature(s): " . implode(', ', $missingRequired));
+ }
+ // create features
+ $features = array();
+ foreach ( $resultsFound as $entry ) {
+ $features[$entry] = $this->registry->getEntry($entry)->getFeature()->create();
+ }
+ // prepare them
+ foreach ( $features as $key => $feature ) {
+ $params = $gadget->getFeatureParams($gadget, $this->registry->getEntry($key));
+ $feature->prepare($gadget, $this->gc, $params);
+ }
+ // and process them
+ foreach ( $features as $key => $feature ) {
+ $params = $gadget->getFeatureParams($gadget, $this->registry->getEntry($key));
+ $feature->process($gadget, $this->gc, $params);
+ }
+ }
+}
+
+
+
Added: incubator/shindig/trunk/php/gadgets/src/GadgetSigner.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetSigner.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetSigner.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetSigner.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,48 @@
+<?
+/*
+ * 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.
+ *
+ */
+
+/**
+ * Handles generation of signing tokens for various request types.
+ * Implementations are free to define their own signing parameters in any
+ * way that is suitable for their site.
+ */
+abstract class GadgetSigner {
+ /**
+ * Generates a token for the given gadget.
+ * Implementations should also add their own user-related context data
+ * to the token.
+ *
+ * Or generates a token from an input string. This call must produce a token that
+ * will validate against a token produced directly from a gadget so that the
+ * following function will always returns a valid GadgetToken:
+ *
+ * <code>
+ * GadgetToken testToken(Gadget gadget, GadgetSigner signer) {
+ * GadgetToken token = signer.createToken(gadget);
+ * return signer.createToken(token.toSerialForm());
+ * }
+ * </code>
+ *
+ * @param tokenString String representation of the token to be created.
+ * @return The token representation of the input data.
+ * @throws GadgetException If tokenString is not a valid token
+ */
+ abstract public function createToken($gadget);
+}
Added: incubator/shindig/trunk/php/gadgets/src/GadgetSpec.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetSpec.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetSpec.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetSpec.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,102 @@
+<?
+/*
+ * 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.
+ *
+ */
+
+define('DEFAULT_VIEW', 'default');
+
+// 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;
+ }
+
+}
+
+abstract class Icon {
+ abstract public function getURI();
+ abstract public function getMode();
+ abstract public function getType();
+}
+
+abstract class LocaleSpec {
+ abstract public function getLocale();
+ abstract public function getURI();
+ abstract public function isRightToLeft();
+}
+
+abstract class FeatureSpec {
+ abstract public function getName();
+ abstract public function getParams();
+ abstract public function isOptional();
+}
+
+abstract class UserPref {
+ // enums are not suported in php, so we store our allowed values, and programaticly check for consitency later on
+ public $DataTypes = array('STRING', 'HIDDEN', 'BOOL', 'ENUM', 'LIST', 'NUMBER');
+ public $dataType;
+ abstract public function getName();
+ abstract public function getDisplayName();
+ abstract public function getDefaultValue();
+ abstract public function isRequired();
+ abstract public function getDataType();
+ abstract public function getEnumValues();
+}
+
+abstract class GadgetSpec {
+ // As in UserPref, no enums so fake it
+ public $contentTypes = array('HTML', 'URL');
+ abstract public function getAuthor();
+ abstract public function getAuthorEmail();
+ abstract public function getContentData($view = false);
+ abstract public function getContentHref();
+ abstract public function getContentType();
+ abstract public function getDescription();
+ abstract public function getDirectoryTitle();
+ abstract public function getIcons();
+ abstract public function getLocaleSpecs();
+ abstract public function getPreloads();
+ abstract public function getRequires();
+ abstract public function getScreenshot();
+ abstract public function getThumbnail();
+ abstract public function getTitle();
+ abstract public function getTitleURI();
+ abstract public function getUserPrefs();
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/gadgets/src/GadgetSpecParser.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetSpecParser.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetSpecParser.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetSpecParser.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,388 @@
+<?
+/*
+ * 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 GadgetSpecParser {
+ //public function parse(GadgetId $id, String $xml)
+ public function parse($xml)
+ {
+ $id = 1;
+ if (empty($xml)) {
+ throw new SpecParserException("Empty XML document");
+ }
+ //TODO add libxml_get_errors() functionality so we can have a bit more understandable errors..
+ if (($doc = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)) == false) {
+ throw new SpecParserException("Invalid XML document");
+ }
+ if (count($doc->ModulePrefs) != 1) {
+ throw new SpecParserException("Missing or duplicated <ModulePrefs>");
+ }
+ $spec = new ParsedGadgetSpec();
+ $spec->id = $id;
+ // process ModulePref attributes
+ $this->processModulePrefs($id, $spec, $doc->ModulePrefs);
+ // process UserPrefs, if any
+ foreach ( $doc->UserPref as $pref ) {
+ $this->processUserPref($spec, $pref);
+ }
+ foreach ( $doc->Content as $content ) {
+ $this->processContent($spec, $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);
+ }
+ foreach ( $doc->ModulePrefs->Optional as $feature ) {
+ $this->processFeature($spec, $feature, false);
+ }
+ //TODO java version has a todo here for parsing icons
+ return $spec;
+ }
+
+ private function processModulePrefs($id, &$spec, $ModulePrefs)
+ {
+ $attributes = $ModulePrefs->attributes();
+ if (empty($attributes['title'])) {
+ throw new SpecParserException("Missing or empty \"title\" attribute.");
+ }
+ // 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']) : '';
+ foreach ( $ModulePrefs->Locale as $locale ) {
+ $spec->localeSpecs[] = $this->processLocale($locale);
+ }
+
+ }
+
+ private function processLocale($locale)
+ {
+ $attributes = $locale->attributes();
+ $messageAttr = isset($attributes['messages']) ? trim($attributes['messages']) : '';
+ $languageAttr = isset($attributes['lang']) ? trim($attributes['lang']) : 'all';
+ $countryAttr = isset($attributes['country']) ? trim($attributes['country']) : 'all';
+ $rtlAttr = isset($attributes['language_direction']) ? trim($attributes['language_direction']) : '';
+ $rightToLeft = $rtlAttr == 'rtl';
+ $locale = new ParsedMessageBundle();
+ $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;
+ $locale->locale = new Locale($languageAttr, $countryAttr);
+ return $locale;
+ }
+
+ private function processUserPref(&$spec, $pref)
+ {
+ $attributes = $pref->attributes();
+ $preference = new ParsedUserPref();
+ if (empty($attributes['name'])) {
+ throw new SpecParserException("All UserPrefs must have name attributes.");
+ }
+ $preference->name = trim($attributes['name']);
+ $preference->displayName = isset($attributes['display_name']) ? trim($attributes['display_name']) : '';
+ // if its set -and- in our valid 'enum' of types, use it, otherwise assume STRING, to try and emulate java's enum behavior
+ $preference->dataType = isset($attributes['datatype']) && in_array(strtoupper($attributes['datatype']), $preference->DataTypes) ? strtoupper($attributes['datatype']) : 'STRING';
+ $preference->defaultValue = isset($attributes['default_value']) ? trim($attributes['default_value']) : '';
+ if (isset($pref->EnumValue)) {
+ foreach ( $pref->EnumValue as $enum ) {
+ $attr = $enum->attributes();
+ // java based shindig doesn't throw an exception here, but it -is- invalid and should trigger a parse error
+ if (empty($attr['value'])) {
+ throw new SpecParserException("EnumValue must have a value field.");
+ }
+ $valueText = trim($attr['value']);
+ $displayText = ! empty($attr['display_value']) ? trim($attr['display_value']) : $valueText;
+ $preference->enumValues[$valueText] = $displayText;
+ }
+ }
+ $spec->userPrefs[] = $preference;
+ }
+
+ private function processContent(&$spec, $content)
+ {
+ $attributes = $content->attributes();
+ if (empty($attributes['type'])) {
+ throw new SpecParserException("No content type specified!");
+ }
+ $type = trim($attributes['type']);
+ if ($type == 'url') {
+ if (empty($attributes['href'])) {
+ throw new SpecParserException("Malformed <Content> href value");
+ }
+ $url = trim($attributes['href']);
+ $spec->contentType = 'URL';
+ $spec->contentHref = $url;
+ } else {
+ $spec->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);
+ }
+ }
+ }
+
+ private function processFeature(&$spec, $feature, $required)
+ {
+ $featureSpec = new ParsedFeatureSpec();
+ $attributes = $feature->attributes();
+ if (empty($attributes['feature'])) {
+ throw new SpecParserException("Feature not specified in <" . (required ? "Required" : "Optional") . "> tag");
+ }
+ $featureSpec->name = trim($attributes['feature']);
+ $featureSpec->optional = ! $required;
+ foreach ( $feature->Param as $param ) {
+ $attr = $param->attributes();
+ if (empty($attr['name'])) {
+ throw new SpecParserException("Missing name attribute in <Param>.");
+ }
+ $name = trim($attr['name']);
+ $value = trim($param);
+ $featureSpec->params[$name] = $value;
+ }
+ $spec->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;
+ }
+}
+
Added: incubator/shindig/trunk/php/gadgets/src/GadgetToken.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetToken.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetToken.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetToken.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,46 @@
+<?
+/*
+ * 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.
+ *
+ */
+
+/**
+ * An abstract representation of a signing token.
+ * Use in conjuction with @code GadgetSigner.
+ */
+
+abstract class GadgetToken {
+
+ /**
+ * Serializes the token into a string. This can be the exact same as
+ * toString; using a different name here is only to force interface
+ * compliance.
+ *
+ * @return A string representation of the token.
+ */
+ abstract public function toSerialForm();
+
+ /**
+ * Sign a URL using this token
+ * @param uri The URL to sign
+ * @param httpMethod The HTTP method used
+ * @param parameters associated with the signing request
+ * @return The signed URL
+ * @throws GadgetException
+ */
+ abstract public function signUrl($uri, $httpMethod);
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/gadgets/src/GadgetView.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetView.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetView.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetView.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,26 @@
+<?
+/*
+ * 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 GadgetView extends GadgetSpec {
+ public $id; // ID
+ abstract public function getId();
+ abstract public function getSubstitutions();
+ abstract public function getCurrentMessageBundle();
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/gadgets/src/GadgetViewID.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/GadgetViewID.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/GadgetViewID.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/GadgetViewID.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,25 @@
+<?
+/*
+ * 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 GadgetViewID {
+ abstract public function getURI();
+ abstract public function getModuleId();
+ abstract public function getKey();
+}
Added: incubator/shindig/trunk/php/gadgets/src/HttpProcessingOptions.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/HttpProcessingOptions.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/HttpProcessingOptions.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/HttpProcessingOptions.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,27 @@
+<?
+/*
+ * 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 HttpProcessingOptions extends ProcessingOptions {
+ public function __construct()
+ {
+ $this->ignoreCache = (isset($_GET['nocache']) && intval($_GET['nocache']) == 1) || (isset($_GET['bpc']) && intval($_GET['bpc']) == 1);
+ $this->focedJsLibs = isset($_GET['libs']) ? trim($_GET['libs']) : null;
+ }
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/gadgets/src/JsFeatureLoader.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/JsFeatureLoader.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/JsFeatureLoader.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/JsFeatureLoader.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,159 @@
+<?
+/*
+ * 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 JsFeatureLoader {
+
+ public function loadFeatures($path, $registry)
+ {
+ global $config;
+ $registered = array();
+ $entries = array(); // list of GadgetFeatureEntry's
+ $deps = array();
+ // Profiling revealed that we spend ~50% of our processing time in loadFiles,
+ // 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);
+ }
+ // This ensures that we register everything in the right order.
+ foreach ( $deps as $entry ) {
+ $feature = $entry;
+ $feat = $this->register($registry, $feature, $registered, $deps);
+ if ($feat != null) {
+ $entries[] = $feat;
+ }
+ }
+ return $entries;
+ }
+
+ private function loadFiles($path, &$features)
+ {
+ if (is_dir($path)) {
+ $dh = @opendir($path);
+ while ( ($file = @readdir($dh)) !== false ) {
+ // prevents us from looping over '.', '..' and 'hidden files', this last bit IS
+ // different from the java version but unix standard really..
+ if (substr($file, 0, 1) != '.') {
+ $features = $this->loadFiles($path.'/'.$file, $features);
+ }
+ }
+ @closedir($dh);
+ } else {
+ if (basename($path) == 'feature.xml') {
+ $feature = $this->processFile($path);
+ if ($feature != null) {
+ $features[$feature->name] = $feature;
+ }
+ }
+ }
+ return $features;
+ }
+
+ private function processFile($file)
+ {
+ $feature = null;
+ if (file_exists($file) && is_file($file) && is_readable($file)) {
+ if (($content = @file_get_contents($file))) {
+ $feature = $this->parse($content, dirname($file) . '/');
+ }
+ }
+ return $feature;
+ }
+
+ private function register(&$registry, $feature, $registered, $all)
+ {
+ if (isset($registered[$feature->name])) {
+ return null;
+ }
+ foreach ( $feature->deps as $dep ) {
+ if (isset($all[$dep]) && ! in_array($dep, $registered)) {
+ $this->register($registry, $all[$dep], $registered, $all);
+ }
+ }
+ $factory = new JsLibraryFeatureFactory($feature->gadgetJs, $feature->containerJs);
+ $registered[] = $feature->name;
+ return $registry->register($feature->name, $feature->deps, $factory);
+ }
+
+ private function parse($content, $path)
+ {
+ $doc = simplexml_load_string($content);
+ $feature = new ParsedFeature();
+ $feature->basePath = $path;
+ if (! isset($doc->name)) {
+ throw new GadgetException('Invalid name in feature: ' . $path);
+ }
+ $feature->name = trim($doc->name);
+
+ foreach ( $doc->gadget as $gadget ) {
+ $feature = $this->processContext($feature, $gadget, false);
+ }
+ foreach ( $doc->container as $container ) {
+ $feature = $this->processContext($feature, $container, true);
+ }
+ foreach ( $doc->dependency as $dependency ) {
+ $feature->deps[] = trim($dependency);
+ }
+ return $feature;
+ }
+
+ private function processContext(&$feature, $context, $isContainer)
+ {
+ foreach ( $context->script as $script ) {
+ $attributes = $script->attributes();
+ if (! isset($attributes['src'])) {
+ // inline content
+ $type = 'INLINE';
+ $content = (string)$script;
+
+ } else {
+ $content = trim($attributes['src']);
+ if (strtolower(substr($content, 0, strlen("http://"))) == "http://") {
+ $type = 'URL';
+ } elseif (strtolower(substr($content, 0, strlen("//"))) == "//") {
+ $type = 'URL';
+ } else {
+ // as before, we skip over the resource parts since we dont support them
+ $type = 'FILE';
+ $content = $feature->basePath.'/'.$content;
+ }
+ }
+ $library = jsLibrary::create($type, $content);
+ if ($library != null) {
+ if ($isContainer) {
+ $feature->containerJs[] = $library;
+ } else {
+ $feature->gadgetJs[] = $library;
+ }
+ }
+ }
+ return $feature;
+ }
+}
+
+class ParsedFeature {
+ public $name = "";
+ public $basePath = "";
+ public $containerJs = array();
+ public $gadgetJs = array();
+ public $deps = array();
+}
Added: incubator/shindig/trunk/php/gadgets/src/JsLibrary.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/JsLibrary.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/JsLibrary.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/JsLibrary.php Wed Mar 5 11:43:14 2008
@@ -0,0 +1,87 @@
+<?
+/*
+ * 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 jsLibrary {
+ private $types = array('FILE', 'RESOURCE', 'URL', 'INLINE');
+ private $type;
+ private $content;
+
+ public function __construct($type, $content)
+ {
+ $this->type = $type;
+ $this->content = $content;
+ }
+
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ public function getContent()
+ {
+ return $this->content;
+ }
+
+ public function toString()
+ {
+ if ($this->type == 'URL') {
+ return "<script src=\"" . $this->content . "\"></script>";
+ } else {
+ return "<script><!--\n" . $this->content . "\n--></script>";
+ }
+ }
+
+ static function create($type, $content)
+ {
+ if ($type == 'FILE' || $type == 'RESOURCE') {
+ $content = jsLibrary::loadData($content, $type);
+ }
+ return new JsLibrary($type, $content);
+ }
+
+ static private function loadData($name, $type)
+ {
+ // we don't really do 'resources', so limiting this to files only
+ if ($type == 'FILE') {
+ return jsLibrary::loadFile($name);
+ }
+ return null;
+ }
+
+ static private function loadFile($fileName)
+ {
+ if (empty($fileName)) {
+ return '';
+ }
+ if (!file_exists($fileName)) {
+ throw new Exception("JsLibrary file missing: $fileName");
+ }
+ if (!is_file($fileName)) {
+ throw new Exception("JsLibrary file is not a file: $fileName");
+ }
+ if (!is_readable($fileName)) {
+ throw new Exception("JsLibrary file not readable: $fileName");
+ }
+ if (!($content = @file_get_contents($fileName))) {
+ throw new Exception("jsLibrary error reading file: $fileName");
+ }
+ return $content;
+ }
+}
\ No newline at end of file