You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by ch...@apache.org on 2008/05/01 14:36:33 UTC
svn commit: r652498 [2/4] - in /incubator/shindig/trunk/php: ./ gadgets/
src/ src/common/ src/gadgets/ src/gadgets/http/
src/gadgets/samplecontainer/ src/socialdata/ src/socialdata/http/
src/socialdata/opensocial/ src/socialdata/opensocial/model/ src/s...
Added: incubator/shindig/trunk/php/src/gadgets/GadgetSpecParser.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/GadgetSpecParser.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/GadgetSpecParser.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/GadgetSpecParser.php Thu May 1 05:36:31 2008
@@ -0,0 +1,188 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+class SpecParserException extends Exception {
+}
+
+class GadgetSpecParser {
+
+ //public function parse(GadgetId $id, String $xml)
+ public function parse($xml, $context)
+ {
+ 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>");
+ }
+ $gadget = new Gadget($context->getGadgetId(), $context);
+ // process ModulePref attributes
+ $this->processModulePrefs($gadget, $doc->ModulePrefs);
+ // process UserPrefs, if any
+ foreach ( $doc->UserPref as $pref ) {
+ $this->processUserPref($gadget, $pref);
+ }
+ foreach ( $doc->Content as $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($gadget, $feature, true);
+ }
+ foreach ( $doc->ModulePrefs->Optional as $feature ) {
+ $this->processFeature($gadget, $feature, false);
+ }
+ //TODO java version has a todo here for parsing icons
+ return $gadget;
+ }
+
+ private function processModulePrefs(&$gadget, $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)
+ // See http://code.google.com/apis/gadgets/docs/gadgets-extended-xsd.html
+ $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']) : '';
+ // Extended spec fields
+ $gadget->authorAffiliation = isset($attributes['author_affiliation']) ? trim($attributes['author_affiliation']) : '';
+ $gadget->authorLocation = isset($attributes['author_location']) ? trim($attributes['author_location']) : '';
+ $gadget->authorPhoto = isset($attributes['author_photo']) ? trim($attributes['author_photo']) : '';
+ $gadget->authorAboutMe = isset($attributes['author_aboutme']) ? trim($attributes['author_aboutme']) : '';
+ $gadget->authorQuote = isset($attributes['author_quote']) ? trim($attributes['author_quote']) : '';
+ $gadget->authorLink = isset($attributes['author_link']) ? trim($attributes['author_link']) : '';
+ $gadget->showStats = isset($attributes['show_stats']) ? trim($attributes['show_stats']) : '';
+ $gadget->showInDirectory = isset($attributes['show_in_directory']) ? trim($attributes['show_in_directory']) : '';
+ $gadget->string = isset($attributes['string']) ? trim($attributes['string']) : '';
+ $gadget->width = isset($attributes['width']) ? trim($attributes['width']) : '';
+ $gadget->height = isset($attributes['height']) ? trim($attributes['height']) : '';
+ $gadget->category = isset($attributes['category']) ? trim($attributes['category']) : '';
+ $gadget->category2 = isset($attributes['category2']) ? trim($attributes['category2']) : '';
+ $gadget->singleton = isset($attributes['singleton']) ? trim($attributes['singleton']) : '';
+ $gadget->renderInline = isset($attributes['render_inline']) ? trim($attributes['render_inline']) : '';
+ $gadget->scaling = isset($attributes['scaling']) ? trim($attributes['scaling']) : '';
+ $gadget->scrolling = isset($attributes['scrolling']) ? trim($attributes['scrolling']) : '';
+ foreach ( $ModulePrefs->Locale as $locale ) {
+ $gadget->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 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;
+ $locale->locale = new Locale($languageAttr, $countryAttr);
+ return $locale;
+ }
+
+ private function processUserPref(&$gadget, $pref)
+ {
+ $attributes = $pref->attributes();
+ $preference = new UserPref();
+ 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;
+ }
+ }
+ $gadget->userPrefs[] = $preference;
+ }
+
+ private function processContent(&$gadget, $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']);
+ $gadget->contentType = 'URL';
+ $gadget->contentHref = $url;
+ } else {
+ $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 ) {
+ $gadget->addContent($view, $html);
+ }
+ }
+ }
+
+ private function processFeature(&$gadget, $feature, $required)
+ {
+ $featureSpec = new FeatureSpec();
+ $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;
+ }
+ $gadget->requires[$featureSpec->name] = $featureSpec;
+ }
+}
Added: incubator/shindig/trunk/php/src/gadgets/GadgetToken.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/GadgetToken.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/GadgetToken.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/GadgetToken.php Thu May 1 05:36:31 2008
@@ -0,0 +1,70 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+/**
+ * An abstract representation of a signing token.
+ * Use in conjunction with @code GadgetTokenDecoder.
+ */
+abstract class GadgetToken {
+
+ //FIXME Hmm seems php is refusing to let me make abstract static functions? odd
+ static public function createFromToken($token, $maxage) {}
+ static public function createFromValues($owner, $viewer, $app, $domain, $appUrl, $moduleId) {}
+
+
+ /**
+ * 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();
+
+ /**
+ * @return the owner from the token, or null if there is none.
+ */
+ abstract public function getOwnerId();
+
+ /**
+ * @return the viewer from the token, or null if there is none.
+ */
+ abstract public function getViewerId();
+
+ /**
+ * @return the application id from the token, or null if there is none.
+ */
+ abstract public function getAppId();
+
+ /**
+ * @return the domain from the token, or null if there is none.
+ */
+ abstract public function getDomain();
+
+ /**
+ * @return the URL of the application
+ */
+ abstract public function getAppUrl();
+
+ /**
+ * @return the module ID of the application
+ */
+ abstract public function getModuleId();
+}
Added: incubator/shindig/trunk/php/src/gadgets/GadgetTokenDecoder.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/GadgetTokenDecoder.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/GadgetTokenDecoder.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/GadgetTokenDecoder.php Thu May 1 05:36:31 2008
@@ -0,0 +1,34 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Handles verification of gadget security tokens.
+ */
+abstract class GadgetTokenDecoder {
+
+ /**
+ * Decrypts and verifies a gadget security token to return a gadget token.
+ *
+ * @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($tokenString);
+}
Added: incubator/shindig/trunk/php/src/gadgets/JsFeatureLoader.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/JsFeatureLoader.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/JsFeatureLoader.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/JsFeatureLoader.php Thu May 1 05:36:31 2008
@@ -0,0 +1,154 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+class JsFeatureLoader {
+ private $debug;
+
+ public function __construct($debug)
+ {
+ $this->debug = $debug;
+ }
+
+ public function loadFeatures($path, $registry)
+ {
+ $registered = array();
+ $entries = array();
+ $deps = array();
+ $deps = $this->loadFiles($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)) {
+ foreach ( glob("$path/*") as $file ) {
+ // prevents us from looping over '.', '..' and 'hidden files', this last bit IS
+ // different from the java version but it's the unix standard really..
+ if (substr(basename($file), 0, 1) != '.') {
+ $features = $this->loadFiles($file, $features);
+ }
+ }
+ } 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, $this->debug);
+ 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/src/gadgets/JsLibrary.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/JsLibrary.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/JsLibrary.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/JsLibrary.php Thu May 1 05:36:31 2008
@@ -0,0 +1,119 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+class JsLibrary {
+ private $types = array('FILE', 'RESOURCE', 'URL', 'INLINE');
+ private $type;
+ private $content;
+ private $featureName; // used to track what feature this belongs to
+
+
+ public function __construct($type, $content, $featureName = '')
+ {
+ $this->featureName = $featureName;
+ $this->type = $type;
+ $this->content = $content;
+ }
+
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ public function getContent()
+ {
+ return $this->content;
+ }
+
+ public function getFeatureName()
+ {
+ return $this->featureName;
+ }
+
+ 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, $debug)
+ {
+ $feature = '';
+ if ($type == 'FILE') {
+ $feature = dirname($content);
+ if (substr($feature, strlen($feature) - 1, 1) == '/') {
+ // strip tailing /, if any, so that the following strrpos works in any situation
+ $feature = substr($feature, 0, strlen($feature) - 1);
+ }
+ $feature = substr($feature, strrpos($feature, '/') + 1);
+ $content = JsLibrary::loadData($content, $type, $debug);
+ }
+ return new JsLibrary($type, $content, $feature);
+ }
+
+ static private function loadData($name, $type, $debug)
+ {
+ // we don't really do 'resources', so limiting this to files only
+ if ($type == 'FILE') {
+ return JsLibrary::loadFile($name, $debug);
+ }
+ return null;
+ }
+
+ static private function loadFile($fileName, $debug)
+ {
+ global $config;
+ 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 ($debug || empty($config['compress_command'])) {
+ if (! ($content = @file_get_contents($fileName))) {
+ throw new Exception("JsLibrary error reading file: $fileName");
+ }
+ } else {
+ // attempt to compress the feature javascript file
+ $input_file = escapeshellarg($fileName);
+ $output_file = tempnam($config['cache_root'], 'js-comp');
+ $cmd = sprintf($config['compress_command'], $input_file, $output_file);
+ $null = $status = 0;
+ exec($cmd, $null, $status);
+ if ($status === 0) {
+ // successfully compressed.
+ $content = file_get_contents($output_file);
+ } else {
+ // if the compress_command isn't functioning, just return the plain uncompressed content
+ $content = @file_get_contents($fileName);
+ }
+ }
+ return $content;
+ }
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/src/gadgets/JsLibraryFeatureFactory.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/JsLibraryFeatureFactory.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/JsLibraryFeatureFactory.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/JsLibraryFeatureFactory.php Thu May 1 05:36:31 2008
@@ -0,0 +1,73 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+class JsLibraryFeatureFactory extends GadgetFeatureFactory {
+ private $JsLibraryFeature;
+
+ public function __construct($gadgetLibraries, $containerLibraries)
+ {
+ // since we don't do strict type checking, this is one constructor for both a class, or a array of classes
+ $this->JsLibraryFeature = new JsLibraryFeature($gadgetLibraries, $containerLibraries);
+ }
+
+ public function create()
+ {
+ return $this->JsLibraryFeature;
+ }
+
+ public function getLibraries($context)
+ {
+ return $context == 'GADGET' ? $this->JsLibraryFeature->gadgetLibraries : $this->JsLibraryFeature->containerLibraries;
+ }
+}
+
+class JsLibraryFeature extends GadgetFeature {
+ public $containerLibraries = array();
+ public $gadgetLibraries = array();
+
+ public function __construct($gadgetLibraries, $containerLibraries)
+ {
+ // we have a single constructor for both a single and multiple libraries, so handle it in code instead
+ if ($gadgetLibraries != null && is_array($gadgetLibraries)) {
+ $this->gadgetLibraries = array_merge($this->gadgetLibraries, $gadgetLibraries);
+ } elseif ($gadgetLibraries != null && $gadgetLibraries instanceof JsLibrary) {
+ $this->gadgetLibraries[] = $gadgetLibraries;
+ }
+ if ($containerLibraries != null && is_array($containerLibraries)) {
+ $this->containerLibraries = array_merge($this->containerLibraries, $containerLibraries);
+ } elseif ($containerLibraries != null && $containerLibraries instanceof JsLibrary) {
+ $this->containerLibraries[] = $containerLibraries;
+ }
+ }
+
+ public function prepare($gadget, $context, $params)
+ {
+ // do nothing
+ }
+
+ public function process($gadget, $context, $params)
+ {
+ $libraries = array();
+ $libraries = $context->getRenderingContext() == 'GADGET' ? $this->gadgetLibraries : $this->containerLibraries;
+ foreach ( $libraries as $library ) {
+ $gadget->addJsLibrary($library);
+ }
+ }
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/src/gadgets/JsonRpcGadgetContext.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/JsonRpcGadgetContext.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/JsonRpcGadgetContext.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/JsonRpcGadgetContext.php Thu May 1 05:36:31 2008
@@ -0,0 +1,37 @@
+<?php
+
+class JsonRpcGadgetContext extends GadgetContext {
+ private $locale = null;
+ private $view = null;
+ private $url = null;
+ private $container = null;
+
+ public function __construct($jsonContext, $url)
+ {
+ parent::__construct('GADGET');
+ $this->url = $url;
+ $this->view = $jsonContext->view;
+ $this->locale = new Locale($jsonContext->language, $jsonContext->country);
+ $this->container = $jsonContext->container;
+ }
+
+ public function getUrl()
+ {
+ return $this->url;
+ }
+
+ public function getView()
+ {
+ return $this->view;
+ }
+
+ public function getLocale()
+ {
+ return $this->locale;
+ }
+
+ public function getContainer()
+ {
+ return $this->container;
+ }
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/src/gadgets/JsonRpcHandler.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/JsonRpcHandler.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/JsonRpcHandler.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/JsonRpcHandler.php Thu May 1 05:36:31 2008
@@ -0,0 +1,76 @@
+<?php
+
+class JsonRpcHandler {
+
+ public function process($requests)
+ {
+ $response = array();
+ foreach ( $requests->gadgets as $gadget ) {
+ try {
+ $gadgetUrl = $gadget->url;
+ $gadgetModuleId = $gadget->moduleId;
+ $context = new JsonRpcGadgetContext($requests->context, $gadgetUrl);
+ $gadgetServer = new GadgetServer();
+ $gadget = $gadgetServer->processGadget($context);
+ $response[] = $this->makeResponse($gadget, $gadgetModuleId, $gadgetUrl);
+ } catch ( Exception $e ) {
+ $response[] = array('errors' => array($e->getMessage()), 'moduleId' => $gadgetModuleId, 'url' => $gadgetUrl);
+ }
+ }
+ return $response;
+ }
+
+ private function makeResponse($gadget, $gadgetModuleId, $gadgetUrl)
+ {
+ $response = array();
+ $prefs = array();
+ foreach ($gadget->getUserPrefs() as $pref) {
+ $prefs[$pref->getName()] = array(
+ 'displayName' => $pref->getDisplayName(),
+ 'type' => $pref->getDataType(),
+ 'default' => $pref->getDefaultValue(),
+ 'enumValues' => $pref->getEnumValues()
+ );
+ }
+ $features = array();
+ foreach ($gadget->getRequires() as $feature) {
+ $features[] = $feature->getName();
+ }
+
+ $views = array();
+
+ //TODO add views and actual iframe url
+ $response['showInDirectory'] = $gadget->getShowInDirectory();
+ $response['width'] = $gadget->getWidth();
+ $response['title'] = $gadget->getTitle();
+ $response['singleton'] = $gadget->getSingleton();
+ $response['categories'] = Array($gadget->getCategory(), $gadget->getCategory2());
+ $response['views'] ='';
+ /*stdClass Object
+ (
+ $response['default'] = stdClass Object
+ (
+ $response['type'] = html
+ $response['quirks'] = 1
+ )
+
+ )*/
+ $response['description'] = $gadget->getDescription();
+ $response['screenshot'] = $gadget->getScreenShot();
+ $response['thumbnail'] = $gadget->getThumbnail();
+ $response['height'] = $gadget->getHeight();
+ $response['scaling'] = $gadget->getScaling();
+ $response['moduleId'] = $gadgetModuleId;
+ $response['features'] = $features;
+ $response['showStats'] = $gadget->getShowStats();
+ $response['scrolling'] = $gadget->getScrolling();
+ $response['url'] = $gadgetUrl;
+ $response['authorEmail'] = $gadget->getAuthorEmail();
+ $response['titleUrl'] = $gadget->getTitleUrl();
+ $response['directoryTitle'] = $gadget->getDirectoryTitle();
+ $response['author'] = $gadget->getAuthor();
+ $response['iframeUrl'] = "/gadgets/ifr?url=http%3A%2F%2Fwww.google.com%2Fig%2Fmodules%2Fhello.xml&container=default&mid=1&v=db18c863f15d5d1e758a91f2a44881b4&lang=en&country=US";
+ $response['userPrefs'] = $prefs;
+ return $response;
+ }
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/src/gadgets/LocaleSpec.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/LocaleSpec.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/LocaleSpec.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/LocaleSpec.php Thu May 1 05:36:31 2008
@@ -0,0 +1,40 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+class 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;
+ }
+}
Added: incubator/shindig/trunk/php/src/gadgets/MessageBundle.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/MessageBundle.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/MessageBundle.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/MessageBundle.php Thu May 1 05:36:31 2008
@@ -0,0 +1,33 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+class MessageBundle {
+ private $messages;
+
+ public function __construct($messages = array())
+ {
+ $this->messages = $messages;
+ }
+
+ public function getMessages()
+ {
+ return $this->messages;
+ }
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/src/gadgets/MessageBundleParser.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/MessageBundleParser.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/MessageBundleParser.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/MessageBundleParser.php Thu May 1 05:36:31 2008
@@ -0,0 +1,40 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+class MessageBundleParser {
+
+ private function processMessage(&$messages, $msg)
+ {
+ $attr = $msg->attributes();
+ if (isset($attr['name'])) {
+ $messages[trim($attr['name'])] = trim($msg);
+ }
+ }
+
+ public function parse($xml)
+ {
+ $doc = simplexml_load_string($xml);
+ $messages = array();
+ foreach ( $doc->msg as $msg ) {
+ $this->processMessage($messages, $msg);
+ }
+ return new MessageBundle($messages);
+ }
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/src/gadgets/ProxyHandler.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/ProxyHandler.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/ProxyHandler.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/ProxyHandler.php Thu May 1 05:36:31 2008
@@ -0,0 +1,255 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+// according to features/core/io.js, this is high on the list of things to scrap
+define('UNPARSEABLE_CRUFT', "throw 1; < don't be evil' >");
+
+/**
+ * The ProxyHandler class does the actual proxy'ing work. it deals both with
+ * GET and POST based input, and peforms a request based on the input, headers and
+ * httpmethod params. It also deals with request signing and verification thru the
+ * authz and st (security token) params.
+ *
+ */
+class ProxyHandler {
+ private $context;
+
+ public function __construct($context)
+ {
+ $this->context = $context;
+ }
+
+ /**
+ * Fetches content and returns it in JSON format
+ *
+ * @param string $url the url to fetch
+ * @param GadgetSigner $signer the request signer to use
+ * @param string $method the http method to use (get or post) in making the request
+ */
+ public function fetchJson($url, $signer, $method)
+ {
+ $token = $this->extractAndValidateToken($signer);
+ $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, $method);
+ $status = (int)$result->getHttpCode();
+ //header("HTTP/1.1 $status", true);
+ if ($status == 200) {
+ $output = '';
+ $json = array($url => array('body' => $result->getResponseContent(), 'rc' => $status));
+ $json = json_encode($json);
+ $output = UNPARSEABLE_CRUFT . $json;
+ $this->setCachingHeaders();
+ header("Content-Type: application/json; charset=utf-8", true);
+ echo $output;
+ } else {
+ @ob_end_clean();
+ header("HTTP/1.0 404 Not Found", true);
+ echo "<html><body><h1>404 - Not Found</h1></body></html>";
+ }
+ die();
+ }
+
+ /**
+ * Fetches the content and returns it as-is using the headers as returned
+ * by the remote host.
+ *
+ * @param string $url the url to retrieve
+ * @param GadgetSigner $signer the GadgetSigner to use
+ * @param string $method either get or post
+ */
+ public function fetch($url, $signer, $method)
+ {
+ $token = $this->extractAndValidateToken($signer);
+ $originalUrl = $this->validateUrl($url);
+ $signedUrl = $this->signUrl($originalUrl, $token);
+ //TODO: Fetcher needs to handle variety of HTTP methods.
+ $result = $this->fetchContent($signedUrl, $method);
+ // TODO: Fetcher needs to handle variety of HTTP methods.
+ $status = (int)$result->getHttpCode();
+ if ($status == 200) {
+ $headers = explode("\n", $result->getResponseHeaders());
+ foreach ( $headers as $header ) {
+ if (strpos($header, ':')) {
+ $key = trim(substr($header, 0, strpos($header, ':')));
+ $val = trim(substr($header, strpos($header, ':') + 1));
+ // filter out headers that would otherwise mess up our output
+ if (strcasecmp($key, "Transfer-Encoding") != 0 && strcasecmp($key, "Cache-Control") != 0 && strcasecmp($key, "Expires") != 0 && strcasecmp($key, "Content-Length") != 0) {
+ 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();
+ }
+
+ /**
+ * Both fetch and fetchJson call this function to retrieve the actual content
+ *
+ * @param string $signedUrl the signed url to fetch
+ * @param string $method either get or post
+ * @return the filled in request (RemoteContentRequest)
+ */
+ 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 = '';
+ $context = new GadgetContext('GADGET');
+ $requestHeaders = $this->request_headers();
+ foreach ( $requestHeaders as $key => $val ) {
+ if ($key != 'Keep-alive' && $key != 'Connection' && $key != 'Host' && $key != 'Accept' && $key != 'Accept-Encoding') {
+ // propper curl header format according to http://www.php.net/manual/en/function.curl-setopt.php#80099
+ $headers .= "$key: $val\n";
+ }
+ }
+ if ($method == 'POST') {
+ $data = isset($_GET['postData']) ? $_GET['postData'] : false;
+ if (! $data) {
+ $data = isset($_POST['postData']) ? $_POST['postData'] : false;
+ }
+ $postData = '';
+ if ($data) {
+ $data = urldecode($data);
+ $entries = explode('&', $data);
+ foreach ( $entries as $entry ) {
+ $parts = explode('=', $entry);
+ // Process only if its a valid value=something pair
+ if (count($parts) == 2) {
+ $postData .= urlencode($parts[0]) . '=' . urlencode($parts[1]) . '&';
+ }
+ }
+ // chop of the trailing &
+ if (strlen($postData)) {
+ $postData = substr($postData, 0, strlen($postData) - 1);
+ }
+ }
+ // even if postData is an empty string, it will still post (since RemoteContentRquest checks if its false)
+ // so the request to POST is still honored
+ $request = new RemoteContentRequest($signedUrl, $headers, $postData);
+ $request = $this->context->getHttpFetcher()->fetch($request, $context);
+ } else {
+ $request = new RemoteContentRequest($signedUrl, $headers);
+ $request = $this->context->getHttpFetcher()->fetch($request, $context);
+ }
+ return $request;
+ }
+
+ /**
+ * Sets the caching headers (overwriting anything the remote host set) to force
+ * the browser not to cache this.
+ *
+ */
+ private function setCachingHeaders()
+ {
+ // TODO: Re-implement caching behavior if appropriate.
+ header("Cache-Control: private; max-age=0", true);
+ header("Expires: " . gmdate("D, d M Y H:i:s", time() - 3000) . " GMT", true);
+ }
+
+ /**
+ * Empty function, should make something practical here some day.
+ * it's function should be to validate the given url if its in
+ * correct http(s):port://location/url format
+ *
+ * @param string $url
+ * @return string the 'validated' url
+ */
+ private function validateUrl($url)
+ {
+ //TODO should really make a PHP version of the URI class and validate in all the locations the java version does
+ return $url;
+ }
+
+ /**
+ * Extracts the 'st' token from the GET or POST params and calls the
+ * signer to validate the token
+ *
+ * @param GadgetSigner $signer the signer to use (configured in config.php)
+ * @return string the token to use in the signed url
+ */
+ private function extractAndValidateToken($signer)
+ {
+ if ($signer == null) {
+ return null;
+ }
+ $token = isset($_GET["st"]) ? $_GET["st"] : false;
+ if ($token) {
+ $token = isset($_POST['st']) ? $_POST['st'] : '';
+ }
+ return $signer->createToken($token);
+ }
+
+ /**
+ * Signs a url with the GadgetToken
+ *
+ * @param string $originalUrl
+ * @param GadgetToken $token
+ * @return unknown
+ */
+ private function signUrl($originalUrl, $token)
+ {
+ $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'] : false;
+ if ($method) {
+ $method = isset($_POST['httpMethod']) ? $_POST['httpMethod'] : 'GET';
+ }
+ return $token->signUrl($originalUrl, $method);
+ }
+
+ private function request_headers()
+ {
+ // Try to use apache's request headers if available
+ if (function_exists("apache_request_headers")) {
+ if (($headers = apache_request_headers())) {
+ return $headers;
+ }
+ }
+ // if that failed, try to create them from the _SERVER superglobal
+ $headers = array();
+ foreach ( array_keys($_SERVER) as $skey ) {
+ if (substr($skey, 0, 5) == "HTTP_") {
+ $headername = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($skey, 0, 5)))));
+ $headers[$headername] = $_SERVER[$skey];
+ }
+ }
+ return $headers;
+ }
+}
Added: incubator/shindig/trunk/php/src/gadgets/Substitutions.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/Substitutions.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/Substitutions.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/Substitutions.php Thu May 1 05:36:31 2008
@@ -0,0 +1,57 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+class Substitutions {
+ private $types = array('MESSAGE' => 'MSG', 'BIDI' => 'BIDI', 'USER_PREF' => 'UP', 'MODULE' => 'MODULE');
+
+ private $substitutions = array();
+
+ public function __construct()
+ {
+ foreach ( $this->types as $type ) {
+ $this->substitutions[$type] = array();
+ }
+ }
+
+ public function addSubstitution($type, $key, $value)
+ {
+ $this->substitutions[$type]["__{$type}_{$key}__"] = $value;
+ }
+
+ public function addSubstitutions($type, $array)
+ {
+ foreach ( $array as $key => $value ) {
+ $this->addSubstitution($type, $key, $value);
+ }
+ }
+
+ public function substitute($input)
+ {
+ foreach ( $this->types as $type ) {
+ $input = $this->substituteType($type, $input);
+ }
+ return $input;
+ }
+
+ public function substituteType($type, $input)
+ {
+ return str_replace(array_keys($this->substitutions[$type]), array_values($this->substitutions[$type]), $input);
+ }
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/src/gadgets/UserPref.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/UserPref.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/UserPref.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/UserPref.php Thu May 1 05:36:31 2008
@@ -0,0 +1,60 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+class 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;
+ }
+}
Added: incubator/shindig/trunk/php/src/gadgets/UserPrefs.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/UserPrefs.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/UserPrefs.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/UserPrefs.php Thu May 1 05:36:31 2008
@@ -0,0 +1,38 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+class UserPrefs {
+ private $prefs = array();
+
+ public function __construct($prefs)
+ {
+ $this->prefs = $prefs;
+ }
+
+ public function getPrefs()
+ {
+ return $this->prefs;
+ }
+
+ public function getPref($name)
+ {
+ return isset($this->prefs[$name]) ? $this->prefs[$name] : null;
+ }
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/src/gadgets/http/FilesServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/http/FilesServlet.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/http/FilesServlet.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/http/FilesServlet.php Thu May 1 05:36:31 2008
@@ -0,0 +1,68 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+/**
+ * This class serves files from the shindig_root/javascript directory, it was created
+ * so that the shindig examples and javascript files would work out of the box with
+ * the php version too
+ */
+class FilesServlet extends HttpServlet {
+
+ /**
+ * Handles the get file request, if the file exists and is in the correct
+ * location it's echo'd to the browser (with a basic content type guessing
+ * based on the file extention, ie .js becomes text/javascript).
+ * If the file location falls outside of the shindig/javascript root a
+ * 400 Bad Request is returned, and if the file is inside of the root
+ * but doesn't exist a 404 error is returned
+ */
+ public function doGet()
+ {
+ $file = str_replace(Config::get('web_prefix') . '/gadgets/files/', '', $_SERVER["REQUEST_URI"]);
+ $file = Config::get('javascript_path') . $file;
+ // make sure that the real path name is actually in the javascript_path, so people can't abuse this to read
+ // your private data from disk .. otherwise this would be a huge privacy and security issue
+ if (substr(realpath($file), 0, strlen(realpath(Config::get('javascript_path')))) != realpath(Config::get('javascript_path'))) {
+ header("HTTP/1.0 400 Bad Request", true);
+ echo "<html><body><h1>400 - Bad Request</h1></body></html>";
+ die();
+ }
+ // if the file doesn't exist or can't be read, give a 404 error
+ if (!file_exists($file) || !is_readable($file) || !is_file($file)) {
+ header("HTTP/1.0 404 Not Found", true);
+ echo "<html><body><h1>404 - Not Found</h1></body></html>";
+ die();
+ }
+ $dot = strrpos($file, '.');
+ if ($dot) {
+ $ext = strtolower(substr($file, $dot+1));
+ if ($ext == 'html' || $ext == 'htm') {
+ $this->setContentType('text/html');
+ } elseif ($ext == 'js') {
+ $this->setContentType('text/javascript');
+ } elseif ($ext == 'css') {
+ $this->setContentType('text/css');
+ }
+ }
+ $this->setNoCache(true);
+ $this->setLastModified(filemtime($file));
+ readfile($file);
+ }
+}
Added: incubator/shindig/trunk/php/src/gadgets/http/GadgetRenderingServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/http/GadgetRenderingServlet.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/http/GadgetRenderingServlet.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/http/GadgetRenderingServlet.php Thu May 1 05:36:31 2008
@@ -0,0 +1,298 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+/**
+ * This class deals with the gadget rendering requests (in default config this
+ * would be /gadgets/ifr?url=<some gadget's url>). It uses the gadget server and
+ * gadget context to render the xml to a valid html file, and outputs it.
+ *
+ */
+class GadgetRenderingServlet extends HttpServlet {
+ private $context;
+
+ /**
+ * Creates the gadget using the GadgetServer class and calls outputGadget
+ *
+ */
+ public function doGet()
+ {
+ try {
+ if (empty($_GET['url'])) {
+ throw new GadgetException("Missing required parameter: url");
+ }
+ // GadgetContext builds up all the contextual variables (based on the url or post)
+ // plus instances all required classes (feature registry, fetcher, blacklist, etc)
+ $this->context = new GadgetContext('GADGET');
+ // Unfortunatly we can't do caja content filtering here, hoping we'll have a RPC service
+ // or command line caja to use for this at some point
+ $gadgetServer = new GadgetServer();
+ $gadget = $gadgetServer->processGadget($this->context);
+ $this->outputGadget($gadget, $this->context);
+ } catch ( Exception $e ) {
+ $this->outputError($e);
+ }
+ }
+
+ /**
+ * If an error occured (Exception) this function echo's the Exception's message
+ * and if the config['debug'] is true, shows the debug backtrace in a div
+ *
+ * @param Exception $e the exception to show
+ */
+ private function outputError($e)
+ {
+ header("HTTP/1.0 400 Bad Request", true, 400);
+ echo "<html><body>";
+ echo "<h1>Error</h1>";
+ echo $e->getMessage();
+ if (Config::get('debug')) {
+ echo "<p><b>Debug backtrace</b></p><div style='overflow:auto; height:300px; border:1px solid #000000'><pre>";
+ print_r(debug_backtrace());
+ echo "</pre></div>>";
+ }
+ echo "</body></html>";
+ }
+
+ /**
+ * Takes the gadget to output, and depending on its content type calls either outputHtml-
+ * or outputUrlGadget
+ *
+ * @param Gadget $gadget gadget to render
+ * @param string $view the view to render (only valid with a html content type)
+ */
+ private function outputGadget($gadget, $view)
+ {
+ switch ( $gadget->getContentType()) {
+ case 'HTML' :
+ $this->outputHtmlGadget($gadget, $view);
+ break;
+ case 'URL' :
+ $this->outputUrlGadget($gadget);
+ break;
+ }
+ }
+
+ /**
+ * Outputs a html content type gadget.
+ * It creates a html page, with the javascripts from the features inline into the page, plus
+ * calls to 'gadgets.config.init' with the container configuration (config/container.js) and
+ * 'gadgets.Prefs.setMessages_' with all the substitutions. For external javascripts it adds
+ * a <script> tag.
+ *
+ * @param Gadget $gadget
+ * @param GadgetContext $context
+ */
+ private function outputHtmlGadget($gadget, $context)
+ {
+ $this->setContentType("text/html; charset=UTF-8");
+ $output = '';
+ $output .= "<html>\n<head>\n";
+ // TODO: This is so wrong. (todo copied from java shindig, but i would agree with it :))
+ $output .= "<style type=\"text/css\">body,td,div,span,p{font-family:arial,sans-serif;} a {color:#0000cc;}a:visited {color:#551a8b;}a:active {color:#ff0000;}body{margin: 0px;padding: 0px;background-color:white;}</style>\n";
+ $output .= "</head>\n<body>\n";
+ $externJs = "";
+ $inlineJs = "";
+ $externFmt = "<script src=\"%s\"></script>";
+ $forcedLibs = $context->getForcedJsLibs();
+ foreach ( $gadget->getJsLibraries() as $library ) {
+ $type = $library->getType();
+ if ($type == 'URL') {
+ // TODO: This case needs to be handled more gracefully by the js
+ // servlet. We should probably inline external JS as well.
+ $externJs .= sprintf($externFmt, $library->getContent()) . "\n";
+ } else if ($type == 'INLINE') {
+ $inlineJs .= $library->getContent() . "\n";
+ } else {
+ // FILE or RESOURCE
+ if ($forcedLibs == null) {
+ $inlineJs .= $library->getContent() . "\n";
+ }
+ // otherwise it was already included by config.forceJsLibs.
+ }
+ }
+ // Forced libs first.
+ if (! empty($forcedLibs)) {
+ $libs = explode(':', $forcedLibs);
+ $output .= sprintf($externFmt, $this->getJsUrl($libs)) . "\n";
+ }
+ if (strlen($inlineJs) > 0) {
+ $output .= "<script><!--\n" . $inlineJs . "\n-->\n</script>\n";
+ }
+ if (strlen($externJs) > 0) {
+ $output .= $externJs;
+ }
+
+ $output .= "<script><!--\n";
+ $output .= $this->appendJsConfig($context, $gadget);
+ $output .= $this->appendMessages($gadget);
+ $output .= "-->\n</script>\n";
+
+ $gadgetExceptions = array();
+ $content = $gadget->getContentData($context->getView());
+ if (empty($content)) {
+ // unknown view
+ $gadgetExceptions[] = "View: '" . $context->getView() . "' invalid for gadget: " . $gadget->getId()->getKey();
+ }
+ if (count($gadgetExceptions)) {
+ throw new GadgetException(print_r($gadgetExceptions, true));
+ }
+ $output .= $content . "\n";
+ $output .= "<script>gadgets.util.runOnLoadHandlers();</script>\n";
+ $output .= "</body>\n</html>";
+ if (Config::get('P3P') != '') {
+ header("P3P: ".Config::get('P3P'));
+ }
+ echo $output;
+ }
+
+ /**
+ * Output's a URL content type gadget, it adds libs=<list:of:js:libraries>.js and user preferences
+ * to the href url, and redirects the browser to it
+ *
+ * @param Gadget $gadget
+ */
+ private function outputUrlGadget($gadget)
+ {
+ // Preserve existing query string parameters.
+ $redirURI = $gadget->getContentHref();
+ $queryStr = strpos($redirURI, '?') !== false ? substr($redirURI, strpos($redirURI, '?')) : '';
+ $query = $queryStr;
+ // TODO: userprefs on the fragment rather than query string
+ $query .= $this->getPrefsQueryString($gadget->getUserPrefValues());
+ $libs = array();
+ $forcedLibs = Config::get('focedJsLibs');
+ if ($forcedLibs == null) {
+ $reqs = $gadget->getRequires();
+ foreach ( $reqs as $key => $val ) {
+ $libs[] = $key;
+ }
+ } else {
+ $libs = explode(':', $forcedLibs);
+ }
+ $query .= $this->appendLibsToQuery($libs, $gadget);
+ // code bugs out with me because of the invalid url syntax since we dont have a URI class to fix it for us
+ // this works around that
+ if (substr($query, 0, 1) == '&') {
+ $query = '?' . substr($query, 1);
+ }
+ $redirURI .= $query;
+ header('Location: ' . $redirURI);
+ die();
+ }
+
+ /**
+ * Returns the requested libs (from getjsUrl) with the libs_param_name prepended
+ * ie: in libs=core:caja:etc.js format
+ *
+ * @param string $libs the libraries
+ * @param Gadget $gadget
+ * @return string the libs=... string to append to the redirection url
+ */
+ private function appendLibsToQuery($libs, $gadget)
+ {
+ $ret = "&";
+ $ret .= Config::get('libs_param_name');
+ $ret .= "=";
+ $ret .= $this->getJsUrl($libs, $gadget);
+ return $ret;
+ }
+
+ /**
+ * Returns the user preferences in &up_<name>=<val> format
+ *
+ * @param array $libs array of features this gadget requires
+ * @param Gadget $gadget
+ * @return string the up_<name>=<val> string to use in the redirection url
+ */
+ private function getPrefsQueryString($prefVals)
+ {
+ $ret = '';
+ foreach ( $prefVals->getPrefs() as $key => $val ) {
+ $ret .= '&';
+ $ret .= Config::get('userpref_param_prefix');
+ $ret .= urlencode($key);
+ $ret .= '=';
+ $ret .= urlencode($val);
+ }
+ return $ret;
+ }
+
+ /**
+ * generates the library string (core:caja:etc.js) including a checksum of all the
+ * javascript content (?v=<sha1 of js) for cache busting
+ *
+ * @param string $libs
+ * @param Gadget $gadget
+ * @return string the list of libraries in core:caja:etc.js?v=checksum> format
+ */
+ private function getJsUrl($libs, $gadget)
+ {
+ $buf = '';
+ if (! is_array($libs) || ! count($libs)) {
+ $buf = 'core';
+ } else {
+ $firstDone = false;
+ foreach ( $libs as $lib ) {
+ if ($firstDone) {
+ $buf .= ':';
+ } else {
+ $firstDone = true;
+ }
+ $buf .= $lib;
+ }
+ }
+ // 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;
+ }
+
+ private function appendJsConfig($context, $gadget)
+ {
+ $container = $context->getContainer();
+ $containerConfig = $context->getContainerConfig();
+ $gadgetConfig = array();
+ $featureConfig = $containerConfig->getConfig($container, 'gadgets.features');
+ foreach ( $gadget->getJsLibraries() as $library ) {
+ $feature = $library->getFeatureName();
+ if (! isset($gadgetConfig[$feature]) && ! empty($featureConfig[$feature])) {
+ $gadgetConfig[$feature] = $featureConfig[$feature];
+ }
+ }
+ return "gadgets.config.init(" . json_encode($gadgetConfig) . ");\n";
+ }
+
+ private function appendMessages($gadget)
+ {
+ $msgs = '';
+ if ($gadget->getMessageBundle()) {
+ $bundle = $gadget->getMessageBundle();
+ $msgs = json_encode($bundle->getMessages());
+ }
+ return "gadgets.Prefs.setMessages_($msgs);\n";
+ }
+}
Added: incubator/shindig/trunk/php/src/gadgets/http/JsServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/http/JsServlet.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/http/JsServlet.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/http/JsServlet.php Thu May 1 05:36:31 2008
@@ -0,0 +1,103 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+/**
+ * This event handler deals with the /js/core:caja:etc.js request which content type=url gadgets can use
+ * to retrieve our features javascript code
+ */
+class JsServlet extends HttpServlet {
+
+ public function doGet()
+ {
+ $this->noHeaders = true;
+ if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
+ header("HTTP/1.1 304 Not Modified");
+ header('Content-Length: 0');
+ die();
+ }
+ $uri = strtolower($_SERVER["REQUEST_URI"]);
+ $uri = substr($uri, strrpos($uri, '/') + 1);
+ // remove any params that would confuse our parser
+ if (strpos($uri, '?')) {
+ $uri = substr($uri, 0, strpos($uri, '?'));
+ }
+ if (strpos($uri, '.js') !== false) {
+ $uri = substr($uri, 0, strlen($uri) - 3);
+ }
+ $needed = array();
+ if (strpos($uri, ':')) {
+ $needed = explode(':', $uri);
+ } else {
+ $needed[] = $uri;
+ }
+ $found = array();
+ $missing = array();
+ $registry = new GadgetFeatureRegistry(Config::get('features_path'));
+ if ($registry->getIncludedFeatures($needed, $found, $missing)) {
+ $containerParam = isset($_GET["c"]) ? $_GET["c"] : '';
+ $context = $containerParam == '1' ? 'CONTAINER' : 'GADGET';
+ $jsData = '';
+ $done = array();
+ do {
+ foreach ($found as $entry) {
+ if (! in_array($entry, $done)) {
+ $feat = $registry->getEntry($entry);
+ $feature = $feat->getFeature();
+ if ($feature instanceof JsLibraryFeatureFactory) {
+ $jsLib = $feature;
+ foreach ($jsLib->getLibraries($context) as $lib) {
+ if ($lib->getType() != 'URL') {
+ $jsData .= $lib->getContent();
+ }
+ }
+ }
+ $done[] = $entry;
+ }
+ }
+ } while (count($done) != count($found));
+ if (! strlen($jsData)) {
+ header("HTTP/1.0 404 Not Found", true);
+ die();
+ }
+ if (! isset($_GET['c']) || $_GET['c'] != 1) {
+ $contents = preg_replace('/\/\/.*$/m', '', preg_replace('@/\\*(?:.|[\\n\\r])*?\\*/@', '', file_get_contents(Config::get('container_config'))));
+ $containerData = json_decode($contents, true);
+ $jsData .= "\ngadgets.config.init(" . json_encode($containerData['gadgets.features']) . ");\n";
+ }
+ $this->setCachingHeaders();
+ header('Content-Length: ' . strlen($jsData));
+ header("Content-Type: text/javascript");
+ echo $jsData;
+ } else {
+ header("HTTP/1.0 404 Not Found", true);
+
+ }
+ die();
+ }
+
+ private function setCachingHeaders()
+ {
+ header("Expires: Tue, 01 Jan 2030 00:00:01 GMT");
+ // IE seems to need this (10 years should be enough).
+ header("Cache-Control: public,max-age=315360000");
+ // Firefox requires this for certain cases.
+ header("Last-Modified: " . gmdate('D, d M Y H:i:s', time()));
+ }
+}
Added: incubator/shindig/trunk/php/src/gadgets/http/JsonRpcServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/http/JsonRpcServlet.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/http/JsonRpcServlet.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/http/JsonRpcServlet.php Thu May 1 05:36:31 2008
@@ -0,0 +1,57 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+class JsonRpcServlet extends HttpServlet {
+ public function doPost()
+ {
+ try {
+ // we support both a raw http post (without application/x-www-form-urlencoded headers) like java does
+ // and a more php / curl safe version of a form post with 'request' as the post field that holds the request json data
+ if (isset($GLOBALS['HTTP_RAW_POST_DATA']) || isset($_POST['request'])) {
+ $request = json_decode(isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : $_POST['request']);
+ if ($request == (isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : $_POST['request'])) {
+ throw new Exception("Malformed json string");
+ }
+ $handler = new JsonRpcHandler();
+ $response = $handler->process($request);
+ echo json_encode(array('gadgets' => $response));
+ } else {
+ throw new Exception("No post data set");
+ }
+ } catch (Exception $e) {
+ header("HTTP/1.0 500 Internal Server Error", true, 500);
+ echo "<html><body><h1>Internal Server Error</h1><br />";
+ if (Config::get('debug')) {
+ echo $e->getMessage()."<br /><pre>";
+ print_r(debug_backtrace());
+ echo "</pre>";
+ }
+ echo "</body></html>";
+ }
+ }
+
+ public function doGet()
+ {
+ header("HTTP/1.0 400 Bad Request", true, 400);
+ echo "<html><body>";
+ echo "<h1>Error</h1>";
+ echo "<body></html>";
+ }
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/src/gadgets/http/ProxyServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/http/ProxyServlet.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/http/ProxyServlet.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/http/ProxyServlet.php Thu May 1 05:36:31 2008
@@ -0,0 +1,56 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+class ProxyServlet extends HttpServlet {
+
+ public function doGet()
+ {
+ global $config;
+ $this->noHeaders = true;
+ $context = new GadgetContext('GADGET');
+ // those should be doable in one statement, but php seems to still evauluate the second ? and : pair,
+ // so throws an error about undefined index on post, even though it found it in get ... odd bug
+ $url = isset($_GET['url']) ? $_GET['url'] : false;
+ if (! $url) {
+ $url = isset($_POST['url']) ? $_POST['url'] : false;
+ }
+ $url = urldecode($url);
+ $method = isset($_GET['httpMethod']) ? $_GET['httpMethod'] : false;
+ if (! $method) {
+ $method = isset($_POST['httpMethod']) ? $_POST['httpMethod'] : 'GET';
+ }
+ if (! $url) {
+ header("HTTP/1.0 400 Bad Request", true);
+ echo "<html><body><h1>400 - Missing url parameter</h1></body></html>";
+ }
+ $gadgetSigner = new $config['gadget_signer']();
+ $proxyHandler = new ProxyHandler($context);
+ if (! empty($_GET['output']) && $_GET['output'] == 'js') {
+ $proxyHandler->fetchJson($url, $gadgetSigner, $method);
+ } else {
+ $proxyHandler->fetch($url, $gadgetSigner, $method);
+ }
+ }
+
+ public function doPost()
+ {
+ $this->doGet();
+ }
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/src/gadgets/samplecontainer/BasicBlobCrypter.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/samplecontainer/BasicBlobCrypter.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/samplecontainer/BasicBlobCrypter.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/samplecontainer/BasicBlobCrypter.php Thu May 1 05:36:31 2008
@@ -0,0 +1,36 @@
+<?php
+/**
+ * This class provides basic binary blob encryption and decryption, for use with the security token
+ *
+ */
+
+//FIXME make this compatible with the java's blobcrypter
+class BasicBlobCrypter extends BlobCrypter {
+
+ /**
+ * {@inheritDoc}
+ */
+ public function wrap($in)
+ {
+ if(is_array($in)) {
+ $in = implode(":", $in);
+ }
+ return $in;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function unwrap($in, $maxAgeSec)
+ {
+ $data = explode(":", $in);
+ $rta = array();
+ $rta['o'] = $data[0];
+ $rta['a'] = $data[1];
+ $rta['v'] = $data[2];
+ $rta['d'] = $data[3];
+ $rta['u'] = $data[4];
+ $rta['m'] = $data[5];
+ return $rta;
+ }
+}
Added: incubator/shindig/trunk/php/src/gadgets/samplecontainer/BasicGadgetBlacklist.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/samplecontainer/BasicGadgetBlacklist.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/samplecontainer/BasicGadgetBlacklist.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/samplecontainer/BasicGadgetBlacklist.php Thu May 1 05:36:31 2008
@@ -0,0 +1,43 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+class 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/src/gadgets/samplecontainer/BasicGadgetToken.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/samplecontainer/BasicGadgetToken.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/samplecontainer/BasicGadgetToken.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/samplecontainer/BasicGadgetToken.php Thu May 1 05:36:31 2008
@@ -0,0 +1,137 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+/**
+ * Primitive token implementation that uses stings as tokens.
+ */
+class BasicGadgetToken extends GadgetToken {
+ /** serialized form of the token */
+ private $token;
+
+ /** data from the token */
+ private $tokenData;
+
+ /** tool to use for signing and encrypting the token */
+ private $crypter;
+
+ private $INSECURE_KEY = "{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}";
+
+ private $OWNER_KEY = "o";
+ private $APP_KEY = "a";
+ private $VIEWER_KEY = "v";
+ private $DOMAIN_KEY = "d";
+ private $APPURL_KEY = "u";
+ private $MODULE_KEY = "m";
+
+ /**
+ * {@inheritDoc}
+ */
+ public function toSerialForm()
+ {
+ return $this->token;
+ }
+
+ /**
+ * Generates a token from an input string
+ * @param token String form of token
+ * @param maxAge max age of the token (in seconds)
+ * @throws BlobCrypterException
+ */
+ static public function createFromToken($token, $maxAge)
+ {
+ return new BasicBlobCrypter($token, $maxAge, null, null, null, null, null, null);
+ }
+
+ /**
+ * Generates a token from an input array of values
+ * @param owner owner of this gadget
+ * @param viewer viewer of this gadget
+ * @param app application id
+ * @param domain domain of the container
+ * @param appUrl url where the application lives
+ * @param moduleId module id of this gadget
+ * @throws BlobCrypterException
+ */
+ static public function createFromValues($owner, $viewer, $app, $domain, $appUrl, $moduleId)
+ {
+ return new BasicBlobCrypter(null, null, $owner, $viewer, $app, $domain, $appUrl, $moduleId);
+ }
+
+
+ public function __construct($token, $maxAge, $owner, $viewer, $app, $domain, $appUrl, $moduleId)
+ {
+ $this->crypter = new BasicBlobCrypter();
+ if (!empty($token)) {
+ $this->token = $token;
+ $this->tokenData = $this->crypter->unwrap($token, $maxAge);
+ } else {
+ $this->tokenData = array();
+ $this->tokenData[$this->OWNER_KEY] = $owner;
+ $this->tokenData[$this->VIEWER_KEY] = $viewer;
+ $this->tokenData[$this->APP_KEY] = $app;
+ $this->tokenData[$this->DOMAIN_KEY] = $domain;
+ $this->tokenData[$this->APPURL_KEY] = $appUrl;
+ $this->tokenData[$this->MODULE_KEY] = $moduleId;
+ $this->token = $this->crypter->wrap($this->tokenData);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getAppId() {
+ return $this->tokenData[$this->APP_KEY];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getDomain() {
+ return $this->tokenData[$this->DOMAIN_KEY];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getOwnerId() {
+ return $this->tokenData[$this->OWNER_KEY];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getViewerId() {
+ return $this->tokenData[$this->VIEWER_KEY];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getAppUrl() {
+ return $this->tokenData[$this->APPURL_KEY];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getModuleId() {
+ return intval($this->tokenData[$this->MODULE_KEY]);
+ }
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/src/gadgets/samplecontainer/BasicGadgetTokenDecoder.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/samplecontainer/BasicGadgetTokenDecoder.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/samplecontainer/BasicGadgetTokenDecoder.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/samplecontainer/BasicGadgetTokenDecoder.php Thu May 1 05:36:31 2008
@@ -0,0 +1,61 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * A GadgetTokenDecoder implementation that just provides dummy data to satisfy
+ * tests and API calls. Do not use this for any security applications.
+ */
+class BasicGadgetTokenDecoder extends GadgetTokenDecoder {
+ private $OWNER_INDEX = 0;
+ private $VIEWER_INDEX = 1;
+ private $APP_ID_INDEX = 2;
+ private $CONTAINER_INDEX = 3;
+ private $APP_URL_INDEX = 4;
+ private $MODULE_ID_INDEX = 5;
+
+ /**
+ * {@inheritDoc}
+ *
+ * Returns a token with some faked out values.
+ */
+ public function createToken($stringToken)
+ {
+ if (empty($stringToken)) {
+ //FIXME an empty token should generate an exception instead of
+ // being ignored, however currently a proxy request always has
+ // an empty token (bug presumably), so without this hack it doesn't work
+ // reinstate the throw new GadgetException('INVALID_GADGET_TOKEN'); once thats fixed
+ return;
+ }
+ try {
+ $tokens = explode(":", $stringToken);
+ return new BasicGadgetToken(null,null,
+ urldecode($tokens[$this->OWNER_INDEX]),
+ urldecode($tokens[$this->VIEWER_INDEX]),
+ urldecode($tokens[$this->APP_ID_INDEX]),
+ urldecode($tokens[$this->CONTAINER_INDEX]),
+ urldecode($tokens[$this->APP_URL_INDEX]),
+ urldecode($tokens[$this->MODULE_ID_INDEX])
+ );
+ } catch (Exception $e) {
+ throw new GadgetException('INVALID_GADGET_TOKEN');
+ }
+ }
+}
Added: incubator/shindig/trunk/php/src/gadgets/samplecontainer/BasicRemoteContent.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/samplecontainer/BasicRemoteContent.php?rev=652498&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/samplecontainer/BasicRemoteContent.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/samplecontainer/BasicRemoteContent.php Thu May 1 05:36:31 2008
@@ -0,0 +1,43 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+class BasicRemoteContent extends RemoteContent {
+
+ public function fetch($request, $context)
+ {
+ global $config;
+ $cache = new $config['data_cache']();
+ $remoteContentFetcher = new BasicRemoteContentFetcher();
+ 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 (! $context->getIgnoreCache() && ($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);
+ }
+ }
+ return $ret;
+ }
+}
\ No newline at end of file