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 [2/2] - in /incubator/shindig/trunk: config/ php/ php/gadgets/ php/gadgets/src/ php/gadgets/src/http/ php/js/

Added: incubator/shindig/trunk/php/gadgets/src/JsLibraryFeatureFactory.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/JsLibraryFeatureFactory.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/JsLibraryFeatureFactory.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/JsLibraryFeatureFactory.php Wed Mar  5 11:43:14 2008
@@ -0,0 +1,73 @@
+<?
+/*
+ * 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/gadgets/src/MessageBundle.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/MessageBundle.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/MessageBundle.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/MessageBundle.php Wed Mar  5 11:43:14 2008
@@ -0,0 +1,33 @@
+<?
+/*
+ * 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/gadgets/src/MessageBundleParser.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/MessageBundleParser.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/MessageBundleParser.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/MessageBundleParser.php Wed Mar  5 11:43:14 2008
@@ -0,0 +1,39 @@
+<?
+/*
+ * 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/gadgets/src/MessageBundleSubstituter.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/MessageBundleSubstituter.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/MessageBundleSubstituter.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/MessageBundleSubstituter.php Wed Mar  5 11:43:14 2008
@@ -0,0 +1,100 @@
+<?
+/*
+ * 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 MessageBundleSubstituter extends GadgetFeatureFactory {
+	public function create()
+	{
+		return new MessageBundleSubstituterFeature();
+	}
+}
+
+class MessageBundleSubstituterFeature extends GadgetFeature {
+	private $parser;
+	private $bundle = null;
+	
+	public function __construct()
+	{
+		$this->parser = new MessageBundleParser();
+	}
+	
+	private function getLocaleSpec($spec, $locale)
+	{
+		$localeSpecs = $spec->getLocaleSpecs();
+		foreach ( $localeSpecs as $locSpec ) {
+			//fix me
+			if ($locSpec->getLocale()->equals($locale)) {
+				return $locSpec;
+			}
+		}
+		return null;
+	}
+	
+	public function prepare($gadget, $context, $params)
+	{
+		$locale = $context->getLocale();
+		// en-US
+		$localeData = $this->getLocaleSpec($gadget, $locale);
+		if ($localeData == null) {
+			// en-all
+			$localeData = $this->getLocaleSpec($gadget, new Locale($locale->getLanguage(), "all"));
+		}
+		if ($localeData == null) {
+			// all-all
+			$localeData = $this->getLocaleSpec($gadget, new Locale("all", "all"));
+		}
+		if ($localeData != null) {
+			$uri = $localeData->getURI();
+			if ($uri != null) {
+				// We definitely need a bundle, now we need to fetch it.
+				// Doing it a little different then the java version since our fetcher and cache are intergrated
+				$fetcher = $context->getHttpFetcher();
+				list($response) = $fetcher->fetch(new remoteContentRequest($uri), $context->getOptions());
+				//TODO caching the parsed bundle instead of just the xml data would be a lot more efficient and speedy
+				$this->bundle = $this->parser->parse($response->getResponseContent());				
+			}
+		}
+	}
+	
+	public function process($gadget, $context, $params)
+	{
+		$js = '';
+		$moduleId = $gadget->getId()->getModuleId();
+		$locale = $context->getLocale();
+		$setLangFmt = "gadgets.prefs_.setLanguage(%d, \"%s\");";
+		$setCountryFmt = "gadgets.prefs_.setCountry(%d, \"%s\");";
+		$js .= sprintf($setLangFmt, $moduleId, $locale->getLanguage());
+		$js .= sprintf($setCountryFmt, $moduleId, $locale->getCountry());
+		if ($this->bundle != null) {
+			$gadget->setCurrentMessageBundle($this->bundle);
+			$gadget->getSubstitutions()->addSubstitutions('MSG', $this->bundle->getMessages());
+			$rc = $context->getRenderingContext();
+			if ($rc == 'GADGET') {
+				$msgs = $this->bundle->getMessages();
+				$json = array();
+				foreach ( $msgs as $key => $value ) {
+					$json[$key] = $value;
+				}
+				$setMsgFmt = "gadgets.prefs_.setMsg(%d, %s);";
+				$js .= sprintf($setMsgFmt, $moduleId, json_encode($json));
+			}
+		}
+		$gadget->addJsLibrary(JsLibrary::create('INLINE', $js));
+	}
+}
\ No newline at end of file

Added: incubator/shindig/trunk/php/gadgets/src/ModuleSubstituter.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/ModuleSubstituter.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/ModuleSubstituter.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/ModuleSubstituter.php Wed Mar  5 11:43:14 2008
@@ -0,0 +1,50 @@
+<?
+/*
+ * 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 ModuleSubstituter extends GadgetFeatureFactory {
+	private $feature;
+	public function __construct()
+	{
+		$this->feature = new ModuleSubstituterFeature();
+	}
+	public function create()
+	{
+		return $this->feature;
+	}
+}
+
+class ModuleSubstituterFeature extends GadgetFeature {
+	
+	public function prepare($gadget, $context, $params)
+	{
+		//TODO Auto-generated method stub
+	}
+	
+	public function process($gadget, $context, $params)
+	{
+		$gadget->getSubstitutions()->addSubstitution('MODULE', "ID", $gadget->getId()->getModuleId());
+		if ($context->getRenderingContext() == 'GADGET') {
+			$format = "gadgets.prefs_.setDefaultModuleId(%d);";
+			$fmtStr = sprintf($format, $gadget->getId()->getModuleId());
+			$gadget->addJsLibrary(JsLibrary::create('INLINE', $fmtStr));
+		}
+	}
+}
+ 
\ No newline at end of file

Added: incubator/shindig/trunk/php/gadgets/src/ProcessingOptions.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/ProcessingOptions.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/ProcessingOptions.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/ProcessingOptions.php Wed Mar  5 11:43:14 2008
@@ -0,0 +1,34 @@
+<?
+/*
+ * 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 ProcessingOptions {
+	public $ignoreCache = false;
+	public $focedJsLibs = null;
+	
+	public function getIgnoreCache()
+	{
+		return $this->ignoreCache;
+	}
+	
+	public function getForcedJsLibs()
+	{
+		return $this->focedJsLibs;
+	}
+}
\ No newline at end of file

Added: incubator/shindig/trunk/php/gadgets/src/RemoteContent.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/RemoteContent.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/RemoteContent.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/RemoteContent.php Wed Mar  5 11:43:14 2008
@@ -0,0 +1,31 @@
+<?
+/*
+ * 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.
+ * 
+ */
+
+/*
+ * remoteContent* classes, we departed from the shindig java base style a bit here
+ * We want to use curl_multi for our content fetching because we don't have any fancy 
+ * worker queue's where the java variant does. 
+ * So a different methodlogy which calls for a different working unfortunatly, however
+ * it's kept in the spirit of the java variant as much as possible
+ */
+
+abstract class RemoteContent {
+	abstract public function fetch($requests, $options);
+}
\ No newline at end of file

Added: incubator/shindig/trunk/php/gadgets/src/RemoteContentException.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/RemoteContentException.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/RemoteContentException.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/RemoteContentException.php Wed Mar  5 11:43:14 2008
@@ -0,0 +1,22 @@
+<?
+/*
+ * 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 RemoteContentException extends Exception {
+}
\ No newline at end of file

Added: incubator/shindig/trunk/php/gadgets/src/RemoteContentFetcher.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/RemoteContentFetcher.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/RemoteContentFetcher.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/RemoteContentFetcher.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 RemoteContentFetcher {
+	abstract public function addRequests($requests);
+	abstract public function addRequest(remoteContentRequest $request);
+	abstract public function fetchRequests();
+	abstract public function pendingRequests();
+}
\ No newline at end of file

Added: incubator/shindig/trunk/php/gadgets/src/RemoteContentRequest.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/RemoteContentRequest.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/RemoteContentRequest.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/RemoteContentRequest.php Wed Mar  5 11:43:14 2008
@@ -0,0 +1,138 @@
+<?
+/*
+ * 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 RemoteContentRequest {
+	// these are used for making the request
+	private $url = '';
+	private $headers = false;
+	private $postBody = false;
+	// these fields are filled in once the request has completed
+	private $responseContent = false;
+	private $responseSize = false;
+	private $responseHeaders = false;
+	private $httpCode = false;
+	private $contentType = null;
+	public $handle = false;
+	
+	public function __construct($url, $headers = false, $postBody = false)
+	{
+		$this->url = $url;
+		$this->headers = $headers;
+		$this->postBody = $postBody;
+	}
+	
+	// returns a hash code which identifies this request, used for caching
+	// takes url, headers and postbody into account for constructing the md5 checksum
+	public function toHash()
+	{
+		return md5($this->url . $this->headers . $this->postBody);
+	}
+	
+	public function getContentType()
+	{
+		return $this->contentType;
+	}
+	
+	public function getHttpCode()
+	{
+		return $this->httpCode;
+	}
+	
+	public function getResponseContent()
+	{
+		return $this->responseContent;
+	}
+	
+	public function getResponseHeaders()
+	{
+		return $this->responseHeaders;
+	}
+	
+	public function getResponseSize()
+	{
+		return $this->responseSize;
+	}
+	
+	public function getHeaders()
+	{
+		return $this->headers;
+	}
+	
+	public function isPost()
+	{
+		return ! empty($this->postBody);
+	}
+	
+	public function hasHeaders()
+	{
+		return ! empty($this->headers);
+	}
+	
+	public function getPostBody()
+	{
+		return $this->postBody;
+	}
+	
+	public function getUrl()
+	{
+		return $this->url;
+	}
+	
+	public function setContentType($type)
+	{
+		$this->contentType;
+	}
+	
+	public function setHttpCode($code)
+	{
+		$this->httpCode = intval($code);
+	}
+	
+	public function setResponseContent($content)
+	{
+		$this->responseContent = $content;
+	}
+	
+	public function setResponseHeaders($headers)
+	{
+		$this->responseHeaders = $headers;
+	}
+	
+	public function setResponseSize($size)
+	{
+		$this->responseSize = intval($size);
+	}
+	
+	public function setHeaders($headers)
+	{
+		$this->headers = $headers;
+	}
+	
+	public function setPostBody($postBody)
+	{
+		$this->postBody = $postBody;
+	}
+	
+	public function setUrl($url)
+	{
+		$this->url = $url;
+	}
+
+}
\ No newline at end of file

Added: incubator/shindig/trunk/php/gadgets/src/SpecParserException.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/SpecParserException.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/SpecParserException.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/SpecParserException.php Wed Mar  5 11:43:14 2008
@@ -0,0 +1,22 @@
+<?
+/*
+ * 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 {
+}

Added: incubator/shindig/trunk/php/gadgets/src/Substitutions.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/Substitutions.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/Substitutions.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/Substitutions.php Wed Mar  5 11:43:14 2008
@@ -0,0 +1,78 @@
+<?
+/*
+ * 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 $key => $type) {
+			$this->substitutions[$type] = array();
+		}
+	}
+
+	public function addSubstitution($type, $key, $value)
+	{
+		$this->substitutions[$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 $key => $type) {
+			$input = $this->substituteType($type, $input);
+		}
+		return $input;
+	}
+	
+	public function substituteType($type, $input)
+	{
+		$prefix = "__{$type}_";
+		if (empty($input) || (count($this->substitutions[$type]) == 0) || (strpos($input, $prefix) === false)) {
+			return $input;
+		}
+		while (($start = strpos($input, $prefix) + strlen($prefix)) !== false) {
+			$end   = strpos($input, '__', $start);
+			if ($end !== false) {
+				$name = substr($input, $start, $end - $start);
+				if (isset($this->substitutions[$type][$name])) {
+					$replacement = $this->substitutions[$type][$name];
+					$input       = str_replace("{$prefix}{$name}__", $replacement, $input);
+				}
+			} else {
+				break;
+			}
+		}
+		return $input;
+	}
+}
\ No newline at end of file

Added: incubator/shindig/trunk/php/gadgets/src/UserPrefSubstituter.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/UserPrefSubstituter.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/UserPrefSubstituter.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/UserPrefSubstituter.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.
+ * 
+ */
+
+class UserPrefSubstituter extends GadgetFeatureFactory {
+	private $feature;
+	public function __construct()
+	{
+		$this->feature = new UserPrefSubstituterFeature();
+	}
+	
+	public function create()
+	{
+		return $this->feature;
+	}
+}
+
+class UserPrefSubstituterFeature extends GadgetFeature {
+	
+	public function prepare($gadget, $context, $params)
+	{
+	}
+	
+	public function process($gadget, $context, $params)
+	{
+		$substitutions = $gadget->getSubstitutions();
+		$upValues = $gadget->getUserPrefValues();
+		$json = array();
+		foreach ( $gadget->getUserPrefs() as $pref ) {
+			$name = $pref->getName();
+			$value = $upValues->getPref($name);
+			if ($value == null) {
+				$value = $pref->getDefaultValue();
+			}
+			if ($value == null) {
+				$value = "";
+			}
+			$substitutions->addSubstitution('USER_PREF', $name, $value);
+			
+			if ($context->getRenderingContext() == 'GADGET') {
+				$json[$name] = $value;
+			}
+		}
+		if (count($json)) {
+			$setPrefFmt = "gadgets.prefs_.setPref(%d, %s);";
+			$moduleId = $gadget->getId()->getModuleId();
+			$setPrefStr = sprintf($setPrefFmt, $moduleId, json_encode($json));
+			$gadget->addJsLibrary(JsLibrary::create('INLINE', $setPrefStr));
+		}
+	}
+}

Added: incubator/shindig/trunk/php/gadgets/src/UserPrefs.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/UserPrefs.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/UserPrefs.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/UserPrefs.php Wed Mar  5 11:43:14 2008
@@ -0,0 +1,38 @@
+<?
+/*
+ * 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/gadgets/src/http/FilesServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/http/FilesServlet.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/http/FilesServlet.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/http/FilesServlet.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 FilesServlet extends HttpServlet {
+	
+	public function doGet()
+	{
+		global $config;
+		$file = str_replace($config['web_prefix'] . '/files/', '', $_SERVER["REQUEST_URI"]);
+		$file = $config['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['javascript_path']))) != realpath($config['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();
+		}
+		readfile($file);
+	}
+}

Added: incubator/shindig/trunk/php/gadgets/src/http/GadgetRenderingServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/http/GadgetRenderingServlet.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/http/GadgetRenderingServlet.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/http/GadgetRenderingServlet.php Wed Mar  5 11:43:14 2008
@@ -0,0 +1,260 @@
+<?
+/*
+ * 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.
+ * 
+ */
+
+include_once ('src/UserPrefs.php');
+include_once ('src/Gadget.php');
+include_once ('src/GadgetException.php');
+include_once ('src/GadgetServer.php');
+include_once ('src/GadgetSpecParser.php');
+include_once ('src/GadgetFeatureRegistry.php');
+include_once ('src/HttpProcessingOptions.php');
+include_once ("src/{$config['remote_content']}.php");
+
+class GadgetRenderingServlet extends HttpServlet {
+	
+	public function doGet()
+	{
+		global $config;
+		try {
+			if (empty($_GET['url'])) {
+				throw new GadgetException("Missing required parameter: url");
+			}
+			$url = trim($_GET['url']);
+			$moduleId = isset($_GET['mid']) && is_numeric($_GET['mid']) ? intval($_GET['mid']) : 0;
+			$options = new HttpProcessingOptions();
+			$httpFetcher = new $config['remote_content']();
+			$view = ! empty($_GET['view']) ? $_GET['view'] : DEFAULT_VIEW;
+			$gadgetId = new GadgetId($url, $moduleId);
+			$prefs = $this->getPrefsFromRequest();
+			$locale = $this->getLocaleFromRequest();
+			$registry = new GadgetFeatureRegistry($config['features_path']);
+			// skipping the contentFilters bit, since there's no way to include caja yet
+			// hopefully a rpc service or command line version will be available at some point
+			$gadgetServer = new GadgetServer();
+			$gadget = $gadgetServer->processGadget($gadgetId, $prefs, $locale, 'GADGET', $options, $httpFetcher, $registry);
+			$this->outputGadget($gadget, $view, $options);
+		} catch ( Exception $e ) {
+			$this->outputError($e);
+		}
+	}
+	private function outputError($e)
+	{
+		global $config;
+		header("HTTP/1.0 400 Bad Request", true, 400);
+		echo "<html><body>";
+		echo "<h1>Error</h1>";
+		echo $e->getMessage();
+		if ($config['debug']) {
+			echo "<p><b>Debug info:</b></p><div style='overflow:auto; height:300px; border:1px solid #000000'><pre>";
+			print_r(debug_backtrace());
+			echo "</pre></div>>";
+		}
+		echo "</body></html>";
+	}
+	
+	private function outputGadget($gadget, $view, $options)
+	{
+		switch ( $gadget->getContentType()) {
+			case 'HTML' :
+				$this->outputHtmlGadget($gadget, $view, $options);
+				break;
+			case 'URL' :
+				$this->outputUrlGadget($gadget, $options);
+				break;
+		}
+	}
+	
+	private function outputHtmlGadget($gadget, $view, $options)
+	{
+		global $config;
+		$this->setContentType("text/html; charset=UTF-8");
+		$output = '';
+		$output .= "<html><head>";
+		// 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>";
+		$output .= "</head><body>";
+		$externJs = "";
+		$inlineJs = "";
+		$externFmt = "<script src=\"%s\"></script>";
+		$forcedLibs = $options->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());
+			} 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 options.forceJsLibs.
+			}
+		}
+		// Forced libs first.
+		//FIXME this doesnt make any sense to me yet, should make it actually do something :-)
+		if (! empty($forcedLibs)) {
+			$libs = explode(':', $forcedLibs);
+			$output .= sprintf($externFmt, $this->getJsUrl($libs));
+		}
+		if (strlen($inlineJs) > 0) {
+			$output .= "<script><!--\n" . $inlineJs . "\n-->\n</script>";
+		}
+		if (strlen($externJs) > 0) {
+			$output .= $externJs;
+		}
+		//FIXME quick hack to make it work with the new syndicator.js config, needs a propper implimentation later
+		if (!file_exists($config['syndicator_config']) || !is_readable($config['syndicator_config'])) {
+			throw new GadgetException("Invalid syndicator config");
+		}
+		// remove both /* */ and // style comments, they crash the json_decode function
+		$contents = preg_replace('/\/\/.*$/m','',preg_replace('@/\\*(?:.|[\\n\\r])*?\\*/@', '', file_get_contents($config['syndicator_config'])));
+		$syndData = json_decode($contents, true);
+		$output .= '<script>gadgets.config.init('.json_encode($syndData['gadgets.features']).');</script>';
+		$gadgetExceptions = array();
+		$content = $gadget->getContentData($view);
+		if (empty($content)) {
+			// unknown view
+			$gadgetExceptions[] = "View: '" . $view . "' 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>";
+		$output .= "</body></html>";
+		echo $output;
+	}
+	
+	private function outputUrlGadget($gadget, $options)
+	{
+		// 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 = $options->getForcedJsLibs();
+		if ($forcedLibs == null) {
+			$reqs = $gadget->getRequires();
+			foreach ( $reqs as $key => $val ) {
+				$libs[] = $key;
+			}
+		} else {
+			$libs = explode(':', $forcedLibs);
+		}
+		$query .= $this->appendLibsToQuery($libs);
+		// 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();
+	}
+	
+	private function appendLibsToQuery($libs)
+	{
+		$ret = "&";
+		$ret .= LIBS_PARAM_NAME;
+		$ret .= "=";
+		$ret .= $this->getJsUrl($libs);
+		return $ret;
+	}
+	
+	private function getPrefsQueryString($prefVals)
+	{
+		global $config;
+		$ret = '';
+		foreach ( $prefVals->getPrefs() as $key => $val ) {
+			$ret .= '&';
+			$ret .= $config['userpref_param_prefix'];
+			$ret .= urlencode($key);
+			$ret .= '=';
+			$ret .= urlencode($val);
+		}
+		return $ret;
+	}
+	
+	private function getJsUrl($libs)
+	{
+		$buf = '';
+		if (! is_array($libs) || ! count($libs)) {
+			$buf = 'core';
+		} else {
+			$firstDone = false;
+			foreach ( $libs as $lib ) {
+				if ($firstDone) {
+					$buf .= ':';
+				} else {
+					$firstDone = true;
+				}
+				$buf .= $lib;
+			}
+		}
+		//FIXME add sha1 / md5 checksum of all js content as unique key as 'version'
+		$buf .= ".js?v=";
+		return $buf;
+	}
+	
+	// since we don't have a java style request.locale. we create our own
+	// this parses formats like 'en', 'en-us', 'en-us;en-gb' etc
+	//TODO should really verify that this really works with all locale strings and that it doesn't trip over priority weight fields
+	private function getLocaleFromRequest()
+	{
+		$language = 'all';
+		$country = 'all';
+		if (! empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
+			$acceptLanguage = explode(';', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
+			$acceptLanguage = $acceptLanguage[0];
+			if (strpos($acceptLanguage, '-') !== false) {
+				$lang = explode('-', $acceptLanguage);
+				$language = $lang[0];
+				$country = $lang[1];
+				if (strpos($country, ',') !== false) {
+					$country = explode(',', $country);
+					$country = $country[0];
+				}
+			} else {
+				$language = $acceptLanguage;
+			}
+		
+		}
+		return new Locale($language, $country);
+	}
+	
+	private function getPrefsFromRequest()
+	{
+		global $config;
+		$prefs = array();
+		foreach ( $_GET as $key => $val ) {
+			if (substr($key, 0, strlen($config['userpref_param_prefix'])) == $config['userpref_param_prefix']) {
+				$name = substr($key, strlen($config['userpref_param_prefix']));
+				$prefs[$name] = $val;
+			}
+		}
+		return new UserPrefs($prefs);
+	}
+
+}
\ No newline at end of file

Added: incubator/shindig/trunk/php/gadgets/src/http/HttpServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/http/HttpServlet.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/http/HttpServlet.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/http/HttpServlet.php Wed Mar  5 11:43:14 2008
@@ -0,0 +1,112 @@
+<?
+/*
+ * 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 is a somewhat liberal interpretation of the HttpServlet class
+ * Mixed with some essentials to make propper http header handling
+ * happen in php.
+ */
+
+class ServletException extends Exception {
+}
+
+class HttpServlet {
+	private $lastModified = false;
+	private $contentType = 'text/html';
+	private $charset = 'UTF-8';
+	
+	public function __construct()
+	{
+		// to do our header magic, we need output buffering on
+		ob_start();
+	}
+	
+	public function __destruct()
+	{
+		die();
+		// attempt at some propper header handling from php
+		// this departs a little from the shindig code but it should give is valid http protocol handling
+		header("Content-Type: $this->contentType; charset={$this->charset}");
+		header('Connection: Keep-Alive');
+		header('Keep-Alive: timeout=15, max=30');
+		header('Accept-Ranges: bytes');
+		header('Content-Length: ' . ob_get_length());
+		header('Cache-Control: public,max-age=' . CACHE_TIME . ',must-revalidate');
+		header("Expires: " . gmdate("D, d M Y H:i:s", time() + CACHE_TIME) . " GMT");
+		$content = ob_get_clean();
+		// Obey browsers (or proxy's) request to send a fresh copy if we recieve a no-cache pragma or cache-control request
+		if (! isset($_SERVER['HTTP_PRAGMA']) || ! strstr(strtolower($_SERVER['HTTP_PRAGMA']), 'no-cache') && (! isset($_SERVER['HTTP_CACHE_CONTROL']) || ! strstr(strtolower($_SERVER['HTTP_CACHE_CONTROL']), 'no-cache'))) {
+			// If the browser send us a E-TAG check if it matches (sha1 sum of content), if so send a not modified header instead of content
+			$etag = md5($content);
+			if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $etag) {
+				header("ETag: \"$etag\"");
+				if ($this->lastModified) {
+					header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $this->lastModified));
+				}
+				header("HTTP/1.1 304 Not Modified");
+				header('Content-Length: 0');
+				die();
+			}
+			header("ETag: \"$etag\"");
+			// If no etag is present, then check if maybe this browser supports if_modified_since tags,
+			// check it against our lastModified (if it's set)
+			if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $this->lastModified && ! isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
+				$if_modified_since = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
+				if ($this->lastModified <= $if_modified_since) {
+					header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $this->lastModified));
+					header("HTTP/1.1 304 Not Modified");
+					header('Content-Length: 0');
+					die();
+				}
+			}
+			if ($this->lastModified) {
+				header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $this->lastModified));
+			}
+		}
+		echo $content;
+	}
+	
+	public function setContentType($type)
+	{
+		$this->contentType = $type;
+	}
+	
+	public function getContentType()
+	{
+		return $this->contentType;
+	}
+	
+	public function getLastModified()
+	{
+		return $this->lastModified;
+	}
+	
+	public function setLastModified($modified)
+	{
+		$this->lastModified = max($this->lastModified, $modified);
+	}
+	
+	public function error($msg)
+	{
+		@ob_end_clean();
+		header("HTTP/1.0 400 Bad Request", true);
+		echo "<html><body><h1>400 - $msg</h1></body></html>";
+	}
+}
\ No newline at end of file

Added: incubator/shindig/trunk/php/gadgets/src/http/JsServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/http/JsServlet.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/http/JsServlet.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/http/JsServlet.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.
+ * 
+ */
+
+class JsServlet extends HttpServlet {
+	
+	public function doGet()
+	{
+		global $config;
+		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['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['syndicator_config'])));
+				$syndData = json_decode($contents, true);
+				$jsData .= "\ngadgets.config.init(".json_encode($syndData['gadgets.features']).");\n";
+			}
+			$this->setCachingHeaders();
+			header('Content-Length: ' . strlen($jsData));
+			echo $jsData;
+			//FIXME quick hack to make it work with the new syndicator.js config, needs a propper implimentation later
+			if (!file_exists($config['syndicator_config']) || !is_readable($config['syndicator_config'])) {
+				throw new GadgetException("Invalid syndicator config");
+			}
+		} 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/gadgets/src/http/ProxyHandler.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/http/ProxyHandler.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/http/ProxyHandler.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/http/ProxyHandler.php Wed Mar  5 11:43:14 2008
@@ -0,0 +1,152 @@
+<?
+/*
+ * 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.
+ * 
+ */
+
+include_once ("src/{$config['gadget_token']}.php");
+include_once ("src/{$config['gadget_signer']}.php");
+include_once ("src/HttpProcessingOptions.php");
+
+//TODO make sure this all works, especially the header passthru and post parts
+
+// according to features/core/io.js, this is high on the list of things to scrap
+define('UNPARSEABLE_CRUFT', "throw 1; < don't be evil' >");
+
+class ProxyHandler {
+	private $fetcher;
+	
+	public function __construct($fetcher)
+	{
+		$this->fetcher = $fetcher;
+	}
+	
+	public function fetchJson($signer, $method)
+	{
+		$token = $this->extractAndValidateToken($signer);
+		$url = $_GET['url'];
+		$originalUrl = $this->validateUrl($url);
+		$signedUrl = $this->signUrl($originalUrl, $token);
+		// Fetch the content and convert it into JSON.
+		// TODO: Fetcher needs to handle variety of HTTP methods.
+		$result = $this->fetchContent($signedUrl, new HttpProcessingOptions(), $method);
+		$status = (int)$result->getHttpCode();
+		header("HTTP/1.1 $status", true);
+		if ($status == 200) {
+			$output = '';
+			$json = array('body' => $result->getResponseContent(), 'rc' => $status, 'url' => $url);
+			$json = json_encode($json);
+			$output = UNPARSEABLE_CRUFT . $json;
+			$this->setCachingHeaders();
+			header("application/json; charset=utf-8");
+			header("Content-Disposition", "attachment;filename=p.txt");
+			echo $output;
+		}
+	}
+	
+	public function fetch($signer, $method)
+	{
+		$token = $this->extractAndValidateToken($signer);
+		$originalUrl = $this->validateUrl($_GET['url']);
+		$signedUrl = $this->signUrl($originalUrl, $token);
+		//TODO: Fetcher needs to handle variety of HTTP methods.
+		$result = $this->fetchContent($signedUrl, new HttpProcessingOptions(), $method);
+		// TODO: Fetcher needs to handle variety of HTTP methods.
+		$status = (int)$result->getHttpCode();
+		header("HTTP/1.1 $status", true);
+		if ($status == 200) {
+			$headers = explode("\n", $result->getResponseHeaders());
+			foreach ( $headers as $header ) {
+				header($header);
+			}
+			$this->setCachingHeaders();
+			// then echo the content
+			echo $result->getResponseContent();
+		}
+	}
+	
+	private function fetchContent($signedUrl, $procOptions, $method)
+	{
+		//TODO get actual character encoding from the request
+
+		// Extract the request headers from the $_SERVER super-global (this -does- unfortunatly mean that any header that php doesn't understand won't be proxied thru though)
+		// if this turns out to be a problem we could add support for HTTP_RAW_HEADERS, but this depends on a php.ini setting, so i'd rather prevent that from being required
+		$headers = '';
+		foreach ( $_SERVER as $key => $val ) {
+			if (substr($key, 0, strlen('HTTP_')) == 'HTTP_') {
+				// massage the header key to something a bit more propper (example 'HTTP_ACCEPT_LANGUAGE' becomes 'Accept-Language')
+				// TODO: We probably need to test variations as well.
+				$key = str_replace(' ', '_', ucwords(strtolower(str_replace('-', ' ', substr($key, strlen('HTTP_'))))));
+				if ($key != 'Keep_alive' && $key != 'Connection' && $key != 'Host' && $key != 'Accept' && $key != 'Accept-Encoding') {
+					// propper curl header format according to http://www.php.net/manual/en/function.curl-setopt.php#80099
+					$headers .= "$key: $val\n";
+				}
+			}
+		}
+		if ($method == 'POST') {
+			$postData = '';
+			$first = true;
+			foreach ( $_POST as $key => $val ) {
+				if (! $first) {
+					$postData .= '&';
+				} else {
+					$first = false;
+				}
+				// make sure all the keys and val's are propperly encoded
+				$postData .= urlencode(urldecode($key)) . '=' . urlencode(urldecode($val));
+			}
+			$request = new RemoteContentRequest($signedUrl, $headers, $postData);
+			list($request) = $this->fetcher->fetch($request, $procOptions);
+		} else {
+			$request = new RemoteContentRequest($signedUrl, $headers);
+			list($request) = $this->fetcher->fetch($request, $procOptions);
+		}
+		return $request;
+	}
+	
+	private function setCachingHeaders()
+	{
+		// TODO: Re-implement caching behavior if appropriate.
+		header("Cache-Control", "private; max-age=0");
+		header("Expires", time() - 30);
+	}
+	
+	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;
+	}
+	
+	private function extractAndValidateToken($signer)
+	{
+		if ($signer == null) {
+			return null;
+		}
+		$token = isset($_GET["st"]) ? $_GET["st"] : '';
+		return $signer->createToken($token);
+	}
+	
+	private function signUrl($originalUrl, $token)
+	{
+		if ($token == null || (isset($_GET['authz']) && $_GET['authz'] != 'signed')) {
+			return $originalUrl;
+		}
+		$method = isset($_GET['httpMethod']) ? $_GET['httpMethod'] : 'GET';
+		return $token->signUrl($originalUrl, $method);
+	}
+
+}
\ No newline at end of file

Added: incubator/shindig/trunk/php/gadgets/src/http/ProxyServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/http/ProxyServlet.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/http/ProxyServlet.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/http/ProxyServlet.php Wed Mar  5 11:43:14 2008
@@ -0,0 +1,47 @@
+<?/*
+ * 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.
+ * 
+ */
+
+include_once ("src/{$config['remote_content']}.php");
+include_once ("src/{$config['gadget_signer']}.php");
+include_once ("src/http/ProxyHandler.php");
+
+class ProxyServlet extends HttpServlet {
+	
+	public function doGet($method = 'GET')
+	{
+		global $config;
+		if (empty($_GET['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']();
+		$httpFetcher = new $config['remote_content']();
+		$proxyHandler = new ProxyHandler($httpFetcher);
+		if (! empty($_GET['output']) && $_GET['output'] == 'js') {
+			$proxyHandler->fetchJson($gadgetSigner, $method);
+		} else {
+			$proxyHandler->fetch($gadgetSigner, $method);
+		}
+	}
+	
+	public function doPost()
+	{
+		$this->doGet('POST');
+	}
+}
\ No newline at end of file

Added: incubator/shindig/trunk/php/gadgets/src/http/RpcServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/gadgets/src/http/RpcServlet.php?rev=633998&view=auto
==============================================================================
--- incubator/shindig/trunk/php/gadgets/src/http/RpcServlet.php (added)
+++ incubator/shindig/trunk/php/gadgets/src/http/RpcServlet.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.
+ * 
+ */
+
+class RpcServlet extends HttpServlet {
+//TODO this class ;)	
+}
\ No newline at end of file