You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by et...@apache.org on 2008/03/29 01:43:13 UTC
svn commit: r642460 - in /incubator/shindig/trunk/java/gadgets/src:
main/java/org/apache/shindig/gadgets/
main/java/org/apache/shindig/gadgets/http/
main/java/org/apache/shindig/social/
main/java/org/apache/shindig/social/opensocial/ main/java/org/apac...
Author: etnu
Date: Fri Mar 28 17:43:10 2008
New Revision: 642460
URL: http://svn.apache.org/viewvc?rev=642460&view=rev
Log:
Reverting SHINDIG-157.
Modified:
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicRemoteContentFetcher.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/JsFeatureLoader.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/JsLibrary.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/NullRequestSigner.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContentFetcher.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContentRequest.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RequestSigner.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SignedFetchRequestSigner.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/CrossServletState.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultCrossServletState.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxyHandler.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/GadgetDataHandler.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/ActivitiesService.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/DataService.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/OpenSocialDataHandler.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/PeopleService.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicActivitiesService.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicDataService.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicPeopleService.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/StateFileDataHandler.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/XmlStateFileFetcher.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/util/BlobCrypter.java
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/EasyMockTestCase.java
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetTestFixture.java
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/JsLibraryTest.java
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/SignedFetchRequestSignerTest.java
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/ProxyHandlerTest.java
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/util/BlobCrypterTest.java
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicRemoteContentFetcher.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicRemoteContentFetcher.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicRemoteContentFetcher.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicRemoteContentFetcher.java Fri Mar 28 17:43:10 2008
@@ -30,7 +30,7 @@
* Implementation of a {@code RemoteObjectFetcher} using standard java.net
* classes.
*/
-public class BasicRemoteContentFetcher extends RemoteContentFetcher {
+public class BasicRemoteContentFetcher implements RemoteContentFetcher {
private static final int CONNECT_TIMEOUT_MS = 5000;
private final int maxObjSize;
@@ -41,7 +41,6 @@
* @param maxObjSize Maximum size, in bytes, of object to fetch
*/
public BasicRemoteContentFetcher(int maxObjSize) {
- super(null);
this.maxObjSize = maxObjSize;
}
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/JsFeatureLoader.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/JsFeatureLoader.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/JsFeatureLoader.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/JsFeatureLoader.java Fri Mar 28 17:43:10 2008
@@ -238,8 +238,7 @@
* @param renderingContext
*/
private void processContext(ParsedFeature feature, Element context,
- RenderingContext renderingContext)
- throws GadgetException {
+ RenderingContext renderingContext) {
String syndicator = XmlUtil.getAttribute(context, "synd",
SyndicatorConfig.DEFAULT_SYNDICATOR);
NodeList libraries = context.getElementsByTagName("script");
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/JsLibrary.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/JsLibrary.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/JsLibrary.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/JsLibrary.java Fri Mar 28 17:43:10 2008
@@ -113,10 +113,9 @@
* kept as a url reference, otherwise the file will be fetched and treated
* as a FILE type.
* @return The newly created library.
- * @throws GadgetException
*/
public static JsLibrary create(Type type, String content, String feature,
- RemoteContentFetcher fetcher) throws GadgetException {
+ RemoteContentFetcher fetcher) {
String optimizedContent = null;
String debugContent;
switch (type) {
@@ -169,10 +168,9 @@
* @param url
* @param fetcher
* @return The contents of the JS file, or null if it can't be fetched.
- * @throws GadgetException
*/
private static String loadDataFromUrl(String url,
- RemoteContentFetcher fetcher) throws GadgetException {
+ RemoteContentFetcher fetcher) {
try {
logger.info("Attempting to load js from: " + url);
URI uri = new URI(url);
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/NullRequestSigner.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/NullRequestSigner.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/NullRequestSigner.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/NullRequestSigner.java Fri Mar 28 17:43:10 2008
@@ -0,0 +1,38 @@
+/*
+ * Licensed 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.
+ */
+
+package org.apache.shindig.gadgets;
+
+import java.net.URL;
+
+/**
+ * Request signer interface that does nothing, for convenience of writing
+ * code that may or may not need to sign requests.
+ */
+public class NullRequestSigner implements RequestSigner {
+
+ public String getApprovalUrl() {
+ return null;
+ }
+
+ public Status getSigningStatus() {
+ return Status.OK;
+ }
+
+ @SuppressWarnings("unused")
+ public URL signRequest(String method, URL resource, String postBody) throws GadgetException {
+ return resource;
+ }
+
+}
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContentFetcher.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContentFetcher.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContentFetcher.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContentFetcher.java Fri Mar 28 17:43:10 2008
@@ -18,29 +18,11 @@
package org.apache.shindig.gadgets;
-/**
- * Fetches data over HTTP.
- *
- * Subclasses can use a chain-of-responsibility pattern to add functionality
- * to the fetching process. For example, a SigningFetcher can talk to a
- * CachingFetcher can talk to a ThrottlingFetcher that talks to a
- * RemoteFetcher that gets the actual data.
- */
-public abstract class RemoteContentFetcher {
-
- /** next fetcher in the chain, may be null */
- protected RemoteContentFetcher nextFetcher;
-
- protected RemoteContentFetcher(RemoteContentFetcher nextFetcher) {
- this.nextFetcher = nextFetcher;
- }
-
+public interface RemoteContentFetcher {
/**
- * Fetch HTTP content.
- *
+ * Fetch content using the HTTP GET method
* @param request The request to fetch.
* @return RemoteContent
- * @throws GadgetException
*/
- public abstract RemoteContent fetch(RemoteContentRequest request) throws GadgetException;
+ public RemoteContent fetch(RemoteContentRequest request);
}
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContentRequest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContentRequest.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContentRequest.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContentRequest.java Fri Mar 28 17:43:10 2008
@@ -33,6 +33,9 @@
* Holds request data for passing to a RemoteContentFetcher.
* Instances of this object are immutable.
*
+ * TODO: We should probably just stick the method in here. Having separate
+ * calls for POST vs. get seems unnecessary.
+ *
* TODO: This naming seems really ridiculous now. Why don't we just call it
* what it is -- an HTTP request?
*/
@@ -44,13 +47,6 @@
*/
public InputStream getPostBody() {
return new ByteArrayInputStream(postBody);
- }
-
- /**
- * @return the post body bytes
- */
- public byte[] getPostBodyBytes() {
- return postBody;
}
/**
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RequestSigner.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RequestSigner.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RequestSigner.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RequestSigner.java Fri Mar 28 17:43:10 2008
@@ -0,0 +1,60 @@
+/*
+ * Licensed 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.
+ */
+
+package org.apache.shindig.gadgets;
+
+import java.net.URL;
+
+/**
+ * Interface for generating signed requests and handling responses.
+ *
+ * Most of the functionality here isn't used at the moment, just enough to
+ * implement signed fetch. The status and approval bits will be used for
+ * full OAuth.
+ */
+public interface RequestSigner {
+
+ /**
+ * Whether the signing request succeeded.
+ */
+ public enum Status {
+ OK,
+ APPROVAL_NEEDED,
+ }
+
+ /**
+ * Signs a URL and post body, returning a modified URL including the
+ * signature. The post body is not modified.
+ *
+ * @param method how the request will be sent
+ * @param resource the URL to sign
+ * @param postBody the body of the request (may be null)
+ *
+ * @return a signed URL
+ * @throws GadgetException if an error occurs.
+ */
+ public URL signRequest(String method, URL resource, String postBody)
+ throws GadgetException;
+
+ /**
+ * @return the status associated with the last signing request. May return
+ * APPROVAL_NEEDED if user interaction is required.
+ */
+ public Status getSigningStatus();
+
+ /**
+ * @return the URL the user needs to visit to approve the access request.
+ */
+ public String getApprovalUrl();
+}
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SignedFetchRequestSigner.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SignedFetchRequestSigner.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SignedFetchRequestSigner.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SignedFetchRequestSigner.java Fri Mar 28 17:43:10 2008
@@ -0,0 +1,277 @@
+/*
+ * Licensed 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.
+ */
+
+package org.apache.shindig.gadgets;
+
+import net.oauth.OAuth;
+import net.oauth.OAuthAccessor;
+import net.oauth.OAuthConsumer;
+import net.oauth.OAuthMessage;
+import net.oauth.OAuth.Parameter;
+import net.oauth.signature.RSA_SHA1;
+
+import org.apache.shindig.util.Crypto;
+import org.apache.shindig.util.TimeSource;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.PrivateKey;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * Implements signed fetch based on the OAuth request signing algorithm.
+ *
+ * Subclasses can override signMessage to use their own crypto if they don't
+ * like the oauth.net code for some reason.
+ *
+ * Instances of this class are only accessed by a single thread at a time,
+ * but instances may be created by multiple threads.
+ */
+public class SignedFetchRequestSigner implements RequestSigner {
+
+ protected static final String OPENSOCIAL_OWNERID = "opensocial_owner_id";
+
+ protected static final String OPENSOCIAL_VIEWERID = "opensocial_viewer_id";
+
+ protected static final String OPENSOCIAL_APPID = "opensocial_app_id";
+
+ protected static final String XOAUTH_PUBLIC_KEY =
+ "xoauth_signature_publickey";
+
+ protected static final Pattern ALLOWED_PARAM_NAME = Pattern
+ .compile("[\\w_\\-]+");
+
+ protected final TimeSource clock = new TimeSource();
+
+ /**
+ * Authentication token for the user and gadget making the request.
+ */
+ protected GadgetToken authToken;
+
+ /**
+ * Private key we pass to the OAuth RSA_SHA1 algorithm. This can be a
+ * PrivateKey object, or a PEM formatted private key, or a DER encoded byte
+ * array for the private key. (No, really, they accept any of them.)
+ */
+ protected Object privateKeyObject;
+
+ /**
+ * The name of the key, included in the fetch to help with key rotation.
+ */
+ protected String keyName;
+
+ /**
+ * Constructor for subclasses that don't want this code to use their
+ * keys.
+ */
+ protected SignedFetchRequestSigner(GadgetToken authToken) {
+ init(authToken, null, null);
+ }
+
+ /**
+ * Constructor based on signing with the given PrivateKey object.
+ *
+ * @param authToken verified gadget security token
+ * @param keyName name of the key to include in the request
+ * @param privateKey the key to use for the signing
+ */
+ public SignedFetchRequestSigner(GadgetToken authToken, String keyName,
+ PrivateKey privateKey) {
+ init(authToken, keyName, privateKey);
+ }
+
+ /**
+ * Constructor based on signing with the given PrivateKey object.
+ *
+ * @param authToken verified gadget security token
+ * @param keyName name of the key to include in the request
+ * @param privateKey base64 encoded private key
+ */
+ public SignedFetchRequestSigner(GadgetToken authToken, String keyName,
+ String privateKey) {
+ init(authToken, keyName, privateKey);
+ }
+
+ /**
+ * Constructor based on signing with the given PrivateKey object.
+ *
+ * @param authToken verified gadget security token
+ * @param keyName name of the key to include in the request
+ * @param privateKey DER encoded private key
+ */
+ public SignedFetchRequestSigner(GadgetToken authToken, String keyName,
+ byte[] privateKey) {
+ init(authToken, keyName, privateKey);
+ }
+
+ protected void init(GadgetToken authToken, String keyName,
+ Object privateKeyObject) {
+ this.authToken = authToken;
+ this.keyName = keyName;
+ this.privateKeyObject = privateKeyObject;
+ }
+
+ /**
+ * Signed fetch doesn't require approvals, always returns null.
+ */
+ public String getApprovalUrl() {
+ return null;
+ }
+
+ /**
+ * Signed fetch doesn't require approvals, always returns Status.OK
+ */
+ public Status getSigningStatus() {
+ return Status.OK;
+ }
+
+ public URL signRequest(String method, URL resource, String postBody)
+ throws GadgetException {
+ try {
+ // Parse the request into parameters for OAuth signing, stripping out
+ // any OAuth or OpenSocial parameters injected by the client
+ String query = resource.getQuery();
+ resource = removeQuery(resource);
+ List<OAuth.Parameter> queryParams = sanitize(OAuth.decodeForm(query));
+ List<OAuth.Parameter> postParams = sanitize(OAuth.decodeForm(postBody));
+ List<OAuth.Parameter> msgParams = new ArrayList<OAuth.Parameter>();
+ msgParams.addAll(queryParams);
+ msgParams.addAll(postParams);
+
+ // Add the OpenSocial parameters
+ addOpenSocialParams(msgParams);
+
+ // Add the OAuth parameters
+ addOAuthParams(msgParams);
+
+ // Build and sign the OAuthMessage; note that the resource here has
+ // no query string, the parameters are all in msgParams
+ OAuthMessage message = new OAuthMessage(method, resource.toString(),
+ msgParams);
+
+ // Sign the message, this may jump into a subclass
+ signMessage(message);
+
+ // Rebuild the query string, including all of the parameters we added.
+ // We have to be careful not to copy POST parameters into the query.
+ // If post and query parameters share a name, they end up being removed
+ // from the query.
+ HashSet<String> forPost = new HashSet<String>();
+ for (OAuth.Parameter param : postParams) {
+ forPost.add(param.getKey());
+ }
+ List<Map.Entry<String, String>> newQuery =
+ new ArrayList<Map.Entry<String, String>>();
+ for (Map.Entry<String, String> param : message.getParameters()) {
+ if (! forPost.contains(param.getKey())) {
+ newQuery.add(param);
+ }
+ }
+ String finalQuery = OAuth.formEncode(newQuery);
+ return new URL(resource.getProtocol(), resource.getHost(),
+ resource.getPort(), resource.getPath() + '?' + finalQuery);
+ } catch (Exception e) {
+ throw new GadgetException(GadgetException.Code.INTERNAL_SERVER_ERROR,
+ e);
+ }
+ }
+
+ private URL removeQuery(URL resource) throws MalformedURLException {
+ return new URL(resource.getProtocol(), resource.getHost(),
+ resource.getPort(), resource.getPath());
+ }
+
+
+ private void addOpenSocialParams(List<Parameter> msgParams) {
+ String owner = authToken.getOwnerId();
+ if (owner != null) {
+ msgParams.add(new OAuth.Parameter(OPENSOCIAL_OWNERID, owner));
+ }
+
+ String viewer = authToken.getViewerId();
+ if (viewer != null) {
+ msgParams.add(new OAuth.Parameter(OPENSOCIAL_VIEWERID, viewer));
+ }
+
+ String app = authToken.getAppId();
+ if (app != null) {
+ msgParams.add(new OAuth.Parameter(OPENSOCIAL_APPID, app));
+ }
+
+ }
+
+ private void addOAuthParams(List<Parameter> msgParams) {
+ msgParams.add(new OAuth.Parameter(OAuth.OAUTH_TOKEN, ""));
+
+ String domain = authToken.getDomain();
+ if (domain != null) {
+ msgParams.add(new OAuth.Parameter(OAuth.OAUTH_CONSUMER_KEY, domain));
+ }
+
+ if (keyName != null) {
+ msgParams.add(new OAuth.Parameter(XOAUTH_PUBLIC_KEY, keyName));
+ }
+
+ String nonce = Long.toHexString(Crypto.rand.nextLong());
+ msgParams.add(new OAuth.Parameter(OAuth.OAUTH_NONCE, nonce));
+
+ String timestamp = Long.toString(clock.currentTimeMillis()/1000L);
+ msgParams.add(new OAuth.Parameter(OAuth.OAUTH_TIMESTAMP, timestamp));
+
+ msgParams.add(new OAuth.Parameter(OAuth.OAUTH_SIGNATURE_METHOD,
+ OAuth.RSA_SHA1));
+ }
+
+ /**
+ * Sign a message and append the oauth signature parameter to the message
+ * object.
+ *
+ * @param message the message to sign
+ *
+ * @throws Exception because the OAuth libraries require it.
+ */
+ protected void signMessage(OAuthMessage message) throws Exception {
+ OAuthConsumer consumer = new OAuthConsumer(null, null, null, null);
+ consumer.setProperty(RSA_SHA1.PRIVATE_KEY, privateKeyObject);
+ OAuthAccessor accessor = new OAuthAccessor(consumer);
+ message.sign(accessor);
+ }
+
+ /**
+ * Strip out any owner or viewer id passed by the client.
+ */
+ private List<Parameter> sanitize(List<Parameter> params) {
+ ArrayList<Parameter> list = new ArrayList<Parameter>();
+ for (Parameter p : params) {
+ if (allowParam(p.getKey())) {
+ list.add(p);
+ }
+ }
+ return list;
+ }
+
+ private boolean allowParam(String paramName) {
+ String canonParamName = paramName.toLowerCase();
+ return (!(canonParamName.startsWith("oauth") ||
+ canonParamName.startsWith("xoauth") ||
+ canonParamName.startsWith("opensocial")) &&
+ ALLOWED_PARAM_NAME.matcher(canonParamName).matches());
+ }
+
+
+}
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/CrossServletState.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/CrossServletState.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/CrossServletState.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/CrossServletState.java Fri Mar 28 17:43:10 2008
@@ -21,12 +21,10 @@
import org.apache.shindig.gadgets.Gadget;
import org.apache.shindig.gadgets.GadgetContext;
-import org.apache.shindig.gadgets.GadgetException;
import org.apache.shindig.gadgets.GadgetServer;
import org.apache.shindig.gadgets.GadgetSigner;
import org.apache.shindig.gadgets.GadgetToken;
-import org.apache.shindig.gadgets.RemoteContentFetcher;
-import org.apache.shindig.util.BlobCrypter;
+import org.apache.shindig.gadgets.RequestSigner;
import java.util.Set;
import java.util.logging.Logger;
@@ -107,16 +105,24 @@
public abstract String getIframeUrl(Gadget gadget);
/**
- * Constructs a RemoteFetcher object that signs requests and then forwards
- * them to the next content fetcher in the chain.
- *
- * @param remoteFetcher
+ * Constructs a RequestSigner object that can be used to sign requests from
+ * the given gadget token to implement signed fetch.
+ *
* @param token the decrypted, verified security token
* @return a request signer implementing signed fetch.
*
- * @see org.apache.shindig.gadgets.SigningFetcher
+ * @see org.apache.shindig.gadgets.SignedFetchRequestSigner
+ */
+ public abstract RequestSigner makeSignedFetchRequestSigner(GadgetToken token);
+
+ /**
+ * Constructs a RequestSigner object that can be used to sign requests from
+ * the given gadget token to implement full OAuth.
+ *
+ * @param token the decrypted, verified security token
+ * @return a request signer implementing signed fetch.
*/
- public abstract RemoteContentFetcher makeSigningFetcher(RemoteContentFetcher remoteFetcher, GadgetToken token);
+ public abstract RequestSigner makeOAuthRequestSigner(GadgetToken token);
/**
* Initializes this handler using the provided implementation.
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultCrossServletState.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultCrossServletState.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultCrossServletState.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultCrossServletState.java Fri Mar 28 17:43:10 2008
@@ -22,7 +22,6 @@
import org.apache.shindig.gadgets.BasicGadgetBlacklist;
import org.apache.shindig.gadgets.BasicGadgetSigner;
import org.apache.shindig.gadgets.BasicRemoteContentFetcher;
-import org.apache.shindig.gadgets.DataFetcher;
import org.apache.shindig.gadgets.Gadget;
import org.apache.shindig.gadgets.GadgetContext;
import org.apache.shindig.gadgets.GadgetException;
@@ -37,7 +36,8 @@
import org.apache.shindig.gadgets.JsLibrary;
import org.apache.shindig.gadgets.MessageBundleFetcher;
import org.apache.shindig.gadgets.RemoteContentFetcher;
-import org.apache.shindig.gadgets.SigningFetcher;
+import org.apache.shindig.gadgets.RequestSigner;
+import org.apache.shindig.gadgets.SignedFetchRequestSigner;
import org.apache.shindig.gadgets.SyndicatorConfig;
import org.apache.shindig.gadgets.UserPrefs;
import org.apache.shindig.gadgets.spec.GadgetSpec;
@@ -47,8 +47,6 @@
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
-import java.net.URI;
-import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Set;
@@ -229,8 +227,12 @@
}
@Override
- public RemoteContentFetcher makeSigningFetcher(
- RemoteContentFetcher fetcher, GadgetToken token) {
+ public RequestSigner makeOAuthRequestSigner(GadgetToken token) {
+ return null;
+ }
+
+ @Override
+ public RequestSigner makeSignedFetchRequestSigner(GadgetToken token) {
// Real implementations should use their own key, probably pulled from
// disk rather than hardcoded in the source.
final String PRIVATE_KEY_TEXT =
@@ -249,7 +251,7 @@
"AO/0isr/3aa6O6NLQxISLKcPDk2NOccAfS/xOtfOz4sJYM3+Bs4Io9+dZGSDCA54" +
"Lw03eHTNQghS0A==";
final String PRIVATE_KEY_NAME = "shindig-insecure-key";
- return SigningFetcher.makeFromB64PrivateKey(
- fetcher, token, PRIVATE_KEY_NAME, PRIVATE_KEY_TEXT);
+ return new SignedFetchRequestSigner(token, PRIVATE_KEY_NAME,
+ PRIVATE_KEY_TEXT);
}
}
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxyHandler.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxyHandler.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxyHandler.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxyHandler.java Fri Mar 28 17:43:10 2008
@@ -24,6 +24,7 @@
import org.apache.shindig.gadgets.RemoteContent;
import org.apache.shindig.gadgets.RemoteContentFetcher;
import org.apache.shindig.gadgets.RemoteContentRequest;
+import org.apache.shindig.gadgets.RequestSigner;
import org.apache.shindig.util.InputStreamConsumer;
import org.json.JSONException;
@@ -31,12 +32,15 @@
import java.io.IOException;
import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
+import java.net.URL;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.TreeMap;
import java.util.HashSet;
import java.util.List;
@@ -56,10 +60,8 @@
private static final String NOCACHE_PARAM = "nocache";
private static final String URL_PARAM = "url";
private static final String AUTHZ_PARAM = "authz";
- private static final String UNSIGNED_FETCH = "none";
- private static final String SIGNED_FETCH = "signed";
- private final RemoteContentFetcher remoteFetcher;
+ private final RemoteContentFetcher fetcher;
private final static Set<String> DISALLOWED_RESPONSE_HEADERS
= new HashSet<String>();
@@ -69,49 +71,25 @@
}
public ProxyHandler(RemoteContentFetcher fetcher) {
- this.remoteFetcher = fetcher;
+ this.fetcher = fetcher;
}
- /**
- * Information about our chain of RemoteContentFetchers.
- *
- * This class is kind of silly at the moment, but it'll be useful once
- * we need to peek at the state of intermediate fetchers in the chain.
- * (Which we will need to do for OAuth.)
- */
- private static class FetcherChain {
- public RemoteContentFetcher fetcher;
-
- public FetcherChain(RemoteContentFetcher fetcher) {
- this.fetcher = fetcher;
- }
- }
-
public void fetchJson(HttpServletRequest request,
HttpServletResponse response,
CrossServletState state)
throws ServletException, IOException, GadgetException {
-
- // Build up the request to make
- RemoteContentRequest rcr = buildRemoteContentRequest(request);
-
- // Figure out whether we need to sign the request
- FetcherChain chain = buildFetcherChain(request, response, state);
-
- // Dispatch the request and serialize the response.
- RemoteContent results = chain.fetcher.fetch(rcr);
+ // Fetch the content and convert it into JSON.
+ RemoteContent results = fetchContent(request, state);
+ response.setStatus(HttpServletResponse.SC_OK);
String output;
try {
- JSONObject resp = new JSONObject();
- response.setStatus(HttpServletResponse.SC_OK);
- if (results != null) {
- resp.put("body", results.getResponseAsString());
- resp.put("rc", results.getHttpStatusCode());
- }
// Use raw param as key as URL may have to be decoded
- String originalUrl = request.getParameter(URL_PARAM);
- JSONObject json = new JSONObject().put(originalUrl, resp);
+ JSONObject resp = new JSONObject()
+ .put("body", results.getResponseAsString())
+ .put("rc", results.getHttpStatusCode());
+ String url = request.getParameter(URL_PARAM);
+ JSONObject json = new JSONObject().put(url, resp);
output = UNPARSEABLE_CRUFT + json.toString();
} catch (JSONException e) {
output = "";
@@ -122,16 +100,67 @@
response.getWriter().write(output);
}
- @SuppressWarnings("unchecked")
- private RemoteContentRequest buildRemoteContentRequest(HttpServletRequest request)
- throws ServletException {
- try {
+ public void fetch(HttpServletRequest request,
+ HttpServletResponse response,
+ CrossServletState state)
+ throws ServletException, IOException, GadgetException {
+ RemoteContent results = fetchContent(request, state);
- String encoding = request.getCharacterEncoding();
- if (encoding == null) {
- encoding = "UTF-8";
+ if (request.getHeader("If-Modified-Since") != null) {
+ response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+ return;
+ }
+
+ int status = results.getHttpStatusCode();
+ response.setStatus(status);
+ if (status == HttpServletResponse.SC_OK) {
+ Map<String, List<String>> headers = results.getAllHeaders();
+ if (headers.get("Cache-Control") == null) {
+ // Cache for 1 hour by default for images.
+ HttpUtil.setCachingHeaders(response, 60 * 60);
}
+ for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
+ String name = entry.getKey();
+ List<String> values = entry.getValue();
+ if (name != null && values != null
+ && !DISALLOWED_RESPONSE_HEADERS.contains(name.toLowerCase())) {
+ for (String value : values) {
+ response.addHeader(name, value);
+ }
+ }
+ }
+ response.getOutputStream().write(
+ InputStreamConsumer.readToByteArray(results.getResponse()));
+ }
+ }
+ /**
+ * Fetch the content for a request
+ *
+ * @param request
+ */
+ @SuppressWarnings("unchecked")
+ private RemoteContent fetchContent(HttpServletRequest request,
+ CrossServletState state) throws ServletException, GadgetException {
+ String encoding = request.getCharacterEncoding();
+ if (encoding == null) {
+ encoding = "UTF-8";
+ }
+
+ try {
+ URL originalUrl = validateUrl(request.getParameter(URL_PARAM));
+ GadgetSigner signer = state.getGadgetSigner();
+ URL signedUrl;
+ if ("signed".equals(request.getParameter(AUTHZ_PARAM))) {
+ GadgetToken token = extractAndValidateToken(request, signer);
+ if (token == null) {
+ return new RemoteContent(HttpServletResponse.SC_UNAUTHORIZED,
+ "Invalid security token.".getBytes(), null);
+ }
+ signedUrl = signUrl(state, originalUrl, token, request);
+ } else {
+ signedUrl = originalUrl;
+ }
String method = request.getMethod();
Map<String, List<String>> headers = null;
byte[] postBody = null;
@@ -151,8 +180,7 @@
String[] parts = header.split("=");
if (parts.length != 2) {
// Malformed headers
- throw new GadgetException(GadgetException.Code.INTERNAL_SERVER_ERROR,
- "malformed header specified");
+ return RemoteContent.ERROR;
}
headers.put(URLDecoder.decode(parts[0], encoding),
Arrays.asList(URLDecoder.decode(parts[1], encoding)));
@@ -171,93 +199,19 @@
removeUnsafeHeaders(headers);
RemoteContentRequest.Options options
- = new RemoteContentRequest.Options();
+ = new RemoteContentRequest.Options();
options.ignoreCache = "1".equals(request.getParameter(NOCACHE_PARAM));
- URI target = validateUrl(request.getParameter(URL_PARAM));
RemoteContentRequest req = new RemoteContentRequest(
- method, target, headers, postBody, options);
-
- return req;
+ method, signedUrl.toURI(), headers, postBody, options);
+ return fetcher.fetch(req);
} catch (UnsupportedEncodingException e) {
throw new ServletException(e);
- } catch (GadgetException e) {
+ } catch (URISyntaxException e) {
throw new ServletException(e);
}
}
/**
- * At the moment our fetcher chain is short. In the future we might add
- * additional layers for things like caching or throttling.
- */
- private FetcherChain buildFetcherChain(HttpServletRequest request,
- HttpServletResponse response, CrossServletState state) throws GadgetException {
- String authzType = getParameter(request, AUTHZ_PARAM, "");
- if (authzType.equals("") || authzType.equals(UNSIGNED_FETCH)) {
- return new FetcherChain(remoteFetcher);
- }
- GadgetSigner signer = state.getGadgetSigner();
- if (signer == null) {
- throw new GadgetException(GadgetException.Code.UNSUPPORTED_FEATURE,
- "authenticated makeRequest not supported");
- }
- String tokenString = getParameter(request, SECURITY_TOKEN_PARAM, "");
- GadgetToken securityToken = signer.createToken(tokenString);
- if (securityToken == null) {
- throw new GadgetException(GadgetException.Code.INVALID_GADGET_TOKEN);
- }
- RemoteContentFetcher realFetcher = null;
- if (authzType.equals(SIGNED_FETCH)) {
- realFetcher = state.makeSigningFetcher(remoteFetcher, securityToken);
- }
- if (realFetcher == null) {
- throw new GadgetException(GadgetException.Code.UNSUPPORTED_FEATURE,
- String.format("Unsupported auth type %s", authzType));
- }
- return new FetcherChain(realFetcher);
- }
-
-
- /**
- * This is called for embedding images inline in gadgets, e.g. via img src links
- * created via IG_Embed.
- */
- public void fetch(HttpServletRequest request,
- HttpServletResponse response,
- CrossServletState state)
- throws ServletException, IOException, GadgetException {
- RemoteContentRequest rcr = buildRemoteContentRequest(request);
- RemoteContent results = remoteFetcher.fetch(rcr);
-
- // TODO: why are we checking for caching headers *after* we sent the request?
- if (request.getHeader("If-Modified-Since") != null) {
- response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
- return;
- }
-
- int status = results.getHttpStatusCode();
- response.setStatus(status);
- if (status == HttpServletResponse.SC_OK) {
- Map<String, List<String>> headers = results.getAllHeaders();
- if (headers.get("Cache-Control") == null) {
- // Cache for 1 hour by default for images.
- HttpUtil.setCachingHeaders(response, 60 * 60);
- }
- for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
- String name = entry.getKey();
- List<String> values = entry.getValue();
- if (name != null && values != null
- && !DISALLOWED_RESPONSE_HEADERS.contains(name.toLowerCase())) {
- for (String value : values) {
- response.addHeader(name, value);
- }
- }
- }
- response.getOutputStream().write(
- InputStreamConsumer.readToByteArray(results.getResponse()));
- }
- }
-
- /**
* Removes unsafe headers from the header set.
* @param headers
*/
@@ -275,14 +229,12 @@
/**
* Validates that the given url is valid for this request.
- *
- * non-private for testing only.
*
* @param urlToValidate
* @return A URL object of the URL
* @throws ServletException if the URL fails security checks or is malformed.
*/
- URI validateUrl(String urlToValidate) throws ServletException {
+ private URL validateUrl(String urlToValidate) throws ServletException {
if (urlToValidate == null) {
throw new ServletException("url parameter is missing.");
}
@@ -305,10 +257,39 @@
"/", url.getQuery(),
url.getFragment());
}
- return url;
+ return url.toURL();
} catch (URISyntaxException use) {
throw new ServletException("Malformed URL " + use.getMessage());
+ } catch (MalformedURLException mfe) {
+ throw new ServletException("Malformed URL " + mfe.getMessage());
}
+ }
+
+ /**
+ * @param request
+ * @return A valid token for the given input.
+ * @throws GadgetException
+ */
+ private GadgetToken extractAndValidateToken(HttpServletRequest request,
+ GadgetSigner signer) throws GadgetException {
+ if (signer == null) {
+ return null;
+ }
+ String token = getParameter(request, SECURITY_TOKEN_PARAM, "");
+ return signer.createToken(token);
+ }
+
+ /**
+ * Sign a URL with a GadgetToken if needed
+ * @return The signed url.
+ */
+ @SuppressWarnings("unchecked")
+ private URL signUrl(CrossServletState state, URL originalUrl, GadgetToken token,
+ HttpServletRequest request) throws GadgetException {
+ String method = getParameter(request, METHOD_PARAM, "GET");
+ String body = getParameter(request, POST_DATA_PARAM, null);
+ RequestSigner signer = state.makeSignedFetchRequestSigner(token);
+ return signer.signRequest(method, originalUrl, body);
}
/**
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/GadgetDataHandler.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/GadgetDataHandler.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/GadgetDataHandler.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/GadgetDataHandler.java Fri Mar 28 17:43:10 2008
@@ -17,8 +17,6 @@
*/
package org.apache.shindig.social;
-import org.apache.shindig.gadgets.GadgetException;
-
public interface GadgetDataHandler {
/**
* Determines whether this handler should be used to process the request
@@ -34,7 +32,6 @@
*
* @param request The request from the json
* @return The corresponding response item
- * @throws GadgetException
*/
- ResponseItem handleRequest(RequestItem request) throws GadgetException;
+ ResponseItem handleRequest(RequestItem request);
}
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/ActivitiesService.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/ActivitiesService.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/ActivitiesService.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/ActivitiesService.java Fri Mar 28 17:43:10 2008
@@ -17,7 +17,6 @@
*/
package org.apache.shindig.social.opensocial;
-import org.apache.shindig.gadgets.GadgetException;
import org.apache.shindig.gadgets.GadgetToken;
import org.apache.shindig.social.ResponseItem;
@@ -31,10 +30,9 @@
* @param ids The ids of the people to fetch activities for.
* @param token A valid GadgetToken
* @return a response item with the list of activities.
- * @throws GadgetException
*/
public ResponseItem<List<Activity>> getActivities(List<String> ids,
- GadgetToken token) throws GadgetException;
+ GadgetToken token);
/**
* Creates the passed in activity for the given user. Once createActivity is
@@ -43,8 +41,7 @@
* @param activity The activity to create.
* @param token A valid GadgetToken
* @return a response item containing any errors
- * @throws GadgetException
*/
public ResponseItem createActivity(String personId, Activity activity,
- GadgetToken token) throws GadgetException;
+ GadgetToken token);
}
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/DataService.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/DataService.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/DataService.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/DataService.java Fri Mar 28 17:43:10 2008
@@ -18,7 +18,6 @@
package org.apache.shindig.social.opensocial;
import org.apache.shindig.social.ResponseItem;
-import org.apache.shindig.gadgets.GadgetException;
import org.apache.shindig.gadgets.GadgetToken;
import java.util.List;
@@ -33,10 +32,9 @@
* @param token The GadgetToken for this request
* @return ResponseItem a response item with the error code set if
* there was a problem
- * @throws GadgetException
*/
public ResponseItem<Map<String, Map<String, String>>> getPersonData(
- List<String> ids, List<String> keys, GadgetToken token) throws GadgetException;
+ List<String> ids, List<String> keys, GadgetToken token);
/**
* Updates the data key for the given person with the new value.
@@ -47,8 +45,7 @@
* @param token The GadgetToken for this request
* @return ResponseItem a response item with the error code set if
* there was a problem
- * @throws GadgetException
*/
public ResponseItem updatePersonData(String id, String key,
- String value, GadgetToken token) throws GadgetException;
+ String value, GadgetToken token);
}
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/OpenSocialDataHandler.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/OpenSocialDataHandler.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/OpenSocialDataHandler.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/OpenSocialDataHandler.java Fri Mar 28 17:43:10 2008
@@ -21,7 +21,6 @@
import org.json.JSONObject;
import org.json.JSONArray;
-import org.apache.shindig.gadgets.GadgetException;
import org.apache.shindig.gadgets.GadgetToken;
import org.apache.shindig.social.samplecontainer.BasicPeopleService;
@@ -77,7 +76,7 @@
}
}
- public ResponseItem handleRequest(RequestItem request) throws GadgetException {
+ public ResponseItem handleRequest(RequestItem request) {
OpenSocialDataType type = OpenSocialDataType.valueOf(request.getType());
ResponseItem response = new ResponseItem<Object>(
ResponseError.NOT_IMPLEMENTED,
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/PeopleService.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/PeopleService.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/PeopleService.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/PeopleService.java Fri Mar 28 17:43:10 2008
@@ -22,7 +22,6 @@
import org.apache.shindig.social.opensocial.model.IdSpec;
import org.apache.shindig.social.opensocial.model.ApiCollection;
import org.apache.shindig.social.ResponseItem;
-import org.apache.shindig.gadgets.GadgetException;
import org.apache.shindig.gadgets.GadgetToken;
import java.util.List;
@@ -36,10 +35,9 @@
* @param idSpec The idSpec to translate into ids
* @return a list of person ids
* @throws JSONException If the idSpec is malformed
- * @throws GadgetException
*/
public List<String> getIds(IdSpec idSpec, GadgetToken token)
- throws JSONException, GadgetException;
+ throws JSONException;
public enum SortOrder {
topFriends, name
@@ -57,9 +55,8 @@
* @param first The index of the first person to fetch.
* @param max The max number of people to fetch.
* @return a list of people.
- * @throws GadgetException
*/
public ResponseItem<ApiCollection<Person>> getPeople(List<String> ids,
SortOrder sortOrder, FilterType filter, int first, int max,
- Set<String> profileDetails, GadgetToken token) throws GadgetException;
+ Set<String> profileDetails, GadgetToken token);
}
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicActivitiesService.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicActivitiesService.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicActivitiesService.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicActivitiesService.java Fri Mar 28 17:43:10 2008
@@ -17,7 +17,6 @@
*/
package org.apache.shindig.social.samplecontainer;
-import org.apache.shindig.gadgets.GadgetException;
import org.apache.shindig.gadgets.GadgetToken;
import org.apache.shindig.social.ResponseItem;
@@ -35,7 +34,7 @@
*/
public class BasicActivitiesService implements ActivitiesService {
public ResponseItem<List<Activity>> getActivities(List<String> ids,
- GadgetToken token) throws GadgetException {
+ GadgetToken token) {
Map<String, List<Activity>> allActivities =
XmlStateFileFetcher.get().getActivities();
@@ -53,7 +52,7 @@
}
public ResponseItem createActivity(String personId, Activity activity,
- GadgetToken token) throws GadgetException {
+ GadgetToken token) {
// TODO: Validate the activity and do any template expanding
activity.setUserId(personId);
activity.setPostedTime(new Date().getTime());
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicDataService.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicDataService.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicDataService.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicDataService.java Fri Mar 28 17:43:10 2008
@@ -17,7 +17,6 @@
*/
package org.apache.shindig.social.samplecontainer;
-import org.apache.shindig.gadgets.GadgetException;
import org.apache.shindig.gadgets.GadgetToken;
import org.apache.shindig.social.ResponseError;
import org.apache.shindig.social.ResponseItem;
@@ -31,7 +30,7 @@
public class BasicDataService implements DataService {
public ResponseItem<Map<String, Map<String, String>>> getPersonData(
- List<String> ids, List<String> keys, GadgetToken token) throws GadgetException {
+ List<String> ids, List<String> keys, GadgetToken token) {
Map<String, Map<String, String>> allData
= XmlStateFileFetcher.get().getAppData();
@@ -58,7 +57,7 @@
}
public ResponseItem updatePersonData(String id, String key, String value,
- GadgetToken token) throws GadgetException {
+ GadgetToken token) {
if (!isValidKey(key)) {
return new ResponseItem<Object>(ResponseError.BAD_REQUEST,
"The person data key had invalid characters",
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicPeopleService.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicPeopleService.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicPeopleService.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicPeopleService.java Fri Mar 28 17:43:10 2008
@@ -22,7 +22,6 @@
import org.apache.shindig.social.opensocial.model.IdSpec;
import org.apache.shindig.social.opensocial.model.Person;
import org.apache.shindig.social.opensocial.model.ApiCollection;
-import org.apache.shindig.gadgets.GadgetException;
import org.apache.shindig.gadgets.GadgetToken;
import org.json.JSONException;
@@ -45,7 +44,7 @@
public ResponseItem<ApiCollection<Person>> getPeople(List<String> ids,
SortOrder sortOrder, FilterType filter, int first, int max,
- Set<String> profileDetails, GadgetToken token) throws GadgetException {
+ Set<String> profileDetails, GadgetToken token) {
Map<String, Person> allPeople = XmlStateFileFetcher.get().getAllPeople();
List<Person> people = new ArrayList<Person>();
@@ -80,7 +79,7 @@
}
public List<String> getIds(IdSpec idSpec, GadgetToken token)
- throws JSONException, GadgetException {
+ throws JSONException {
Map<String, List<String>> friendIds
= XmlStateFileFetcher.get().getFriendIds();
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/StateFileDataHandler.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/StateFileDataHandler.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/StateFileDataHandler.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/StateFileDataHandler.java Fri Mar 28 17:43:10 2008
@@ -19,7 +19,6 @@
import org.json.JSONException;
import org.json.JSONObject;
-import org.apache.shindig.gadgets.GadgetException;
import org.apache.shindig.social.ResponseItem;
import org.apache.shindig.social.ResponseError;
import org.apache.shindig.social.GadgetDataHandler;
@@ -50,7 +49,7 @@
}
}
- public ResponseItem handleRequest(RequestItem request) throws GadgetException {
+ public ResponseItem handleRequest(RequestItem request) {
RequestType type = RequestType.valueOf(request.getType());
ResponseItem response = null;
@@ -94,4 +93,4 @@
return response;
}
-}
+}
\ No newline at end of file
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/XmlStateFileFetcher.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/XmlStateFileFetcher.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/XmlStateFileFetcher.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/XmlStateFileFetcher.java Fri Mar 28 17:43:10 2008
@@ -1,7 +1,6 @@
package org.apache.shindig.social.samplecontainer;
import org.apache.shindig.gadgets.BasicRemoteContentFetcher;
-import org.apache.shindig.gadgets.GadgetException;
import org.apache.shindig.gadgets.RemoteContent;
import org.apache.shindig.gadgets.RemoteContentFetcher;
import org.apache.shindig.gadgets.RemoteContentRequest;
@@ -95,7 +94,7 @@
this.doEvil = doEvil;
}
- private Document fetchStateDocument() throws GadgetException {
+ private Document fetchStateDocument() {
if (document != null) {
return document;
}
@@ -131,14 +130,14 @@
}
}
- public Map<String, Map<String, String>> getAppData() throws GadgetException {
+ public Map<String, Map<String, String>> getAppData() {
if (allData == null) {
setupAppData();
}
return allData;
}
- private void setupAppData() throws GadgetException {
+ private void setupAppData() {
allData = new HashMap<String, Map<String, String>>();
Element root = fetchStateDocument().getDocumentElement();
@@ -166,7 +165,7 @@
}
}
- public void setAppData(String id, String key, String value) throws GadgetException {
+ public void setAppData(String id, String key, String value) {
if (allData == null) {
setupAppData();
}
@@ -180,21 +179,21 @@
personData.put(key, value);
}
- public Map<String, List<String>> getFriendIds() throws GadgetException {
+ public Map<String, List<String>> getFriendIds() {
if (friendIdMap == null) {
setupPeopleData();
}
return friendIdMap;
}
- public Map<String, Person> getAllPeople() throws GadgetException {
+ public Map<String, Person> getAllPeople() {
if (allPeople == null) {
setupPeopleData();
}
return allPeople;
}
- private void setupPeopleData() throws GadgetException {
+ private void setupPeopleData() {
Element root = fetchStateDocument().getDocumentElement();
allPeople = new HashMap<String, Person>();
@@ -259,7 +258,7 @@
return friends;
}
- public Map<String, List<Activity>> getActivities() throws GadgetException {
+ public Map<String, List<Activity>> getActivities() {
if (allActivities == null) {
setupActivities();
}
@@ -267,7 +266,7 @@
return allActivities;
}
- private void setupActivities() throws GadgetException {
+ private void setupActivities() {
allActivities = new HashMap<String, List<Activity>>();
Element root = fetchStateDocument().getDocumentElement();
@@ -291,7 +290,7 @@
}
private void createActivities(Node streamItem, String userId,
- String streamTitle) throws GadgetException {
+ String streamTitle) {
NodeList activityItems = streamItem.getChildNodes();
if (activityItems != null) {
for (int i = 0; i < activityItems.getLength(); i++) {
@@ -337,7 +336,7 @@
return media;
}
- public void createActivity(String userId, Activity activity) throws GadgetException {
+ public void createActivity(String userId, Activity activity) {
if (allActivities == null) {
setupActivities();
}
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/util/BlobCrypter.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/util/BlobCrypter.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/util/BlobCrypter.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/util/BlobCrypter.java Fri Mar 28 17:43:10 2008
@@ -22,18 +22,16 @@
import org.apache.commons.codec.digest.DigestUtils;
import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.GeneralSecurityException;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.Map;
/**
* Utility class for managing signed, encrypted, and time stamped blobs.
* Blobs are made up of name/value pairs. Time stamps are automatically
* included under BlobCrypter.TIMESTAMP_KEY.
- *
- * Thread safe.
*/
public class BlobCrypter {
@@ -176,8 +174,8 @@
String[] items = base.split("[&=]");
Map<String, String> map = new HashMap<String, String>();
for (int i=0; i < items.length; ) {
- String key = URLDecoder.decode(items[i++], UTF8);
- String val = URLDecoder.decode(items[i++], UTF8);
+ String key = items[i++];
+ String val = items[i++];
map.put(key, val);
}
return map;
Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/EasyMockTestCase.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/EasyMockTestCase.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/EasyMockTestCase.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/EasyMockTestCase.java Fri Mar 28 17:43:10 2008
@@ -17,7 +17,7 @@
*/
package org.apache.shindig.gadgets;
-import org.easymock.classextension.EasyMock;
+import org.easymock.EasyMock;
import junit.framework.TestCase;
Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetTestFixture.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetTestFixture.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetTestFixture.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetTestFixture.java Fri Mar 28 17:43:10 2008
@@ -93,7 +93,12 @@
}
@Override
- public RemoteContentFetcher makeSigningFetcher(RemoteContentFetcher fetcher, GadgetToken token) {
+ public RequestSigner makeOAuthRequestSigner(GadgetToken token) {
+ return null;
+ }
+
+ @Override
+ public RequestSigner makeSignedFetchRequestSigner(GadgetToken token) {
// Real implementations should use their own key, probably pulled from
// disk rather than hardcoded in the source.
final String PRIVATE_KEY_TEXT =
@@ -112,8 +117,8 @@
"AO/0isr/3aa6O6NLQxISLKcPDk2NOccAfS/xOtfOz4sJYM3+Bs4Io9+dZGSDCA54" +
"Lw03eHTNQghS0A==";
final String PRIVATE_KEY_NAME = "shindig-insecure-key";
- return SigningFetcher.makeFromB64PrivateKey(
- fetcher, token, PRIVATE_KEY_NAME, PRIVATE_KEY_TEXT);
+ return new SignedFetchRequestSigner(token, PRIVATE_KEY_NAME,
+ PRIVATE_KEY_TEXT);
}
};
Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/JsLibraryTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/JsLibraryTest.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/JsLibraryTest.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/JsLibraryTest.java Fri Mar 28 17:43:10 2008
@@ -34,7 +34,7 @@
"};";
private final static String URL_JS = "while(true){alert('hello');}";
- public void testInline() throws GadgetException {
+ public void testInline() {
JsLibrary lib
= JsLibrary.create(JsLibrary.Type.INLINE, INLINE_JS, null, null);
assertEquals(JsLibrary.Type.INLINE, lib.getType());
Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/SignedFetchRequestSignerTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/SignedFetchRequestSignerTest.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/SignedFetchRequestSignerTest.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/SignedFetchRequestSignerTest.java Fri Mar 28 17:43:10 2008
@@ -0,0 +1,225 @@
+/*
+ * Licensed 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.
+ */
+
+package org.apache.shindig.gadgets;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import net.oauth.OAuth;
+import net.oauth.OAuthAccessor;
+import net.oauth.OAuthConsumer;
+import net.oauth.OAuthMessage;
+import net.oauth.OAuth.Parameter;
+import net.oauth.signature.RSA_SHA1;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * Tests the signed fetch code.
+ */
+public class SignedFetchRequestSignerTest extends TestCase {
+ private static final String PRIVATE_KEY_TEXT =
+ "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALRiMLAh9iimur8V" +
+ "A7qVvdqxevEuUkW4K+2KdMXmnQbG9Aa7k7eBjK1S+0LYmVjPKlJGNXHDGuy5Fw/d" +
+ "7rjVJ0BLB+ubPK8iA/Tw3hLQgXMRRGRXXCn8ikfuQfjUS1uZSatdLB81mydBETlJ" +
+ "hI6GH4twrbDJCR2Bwy/XWXgqgGRzAgMBAAECgYBYWVtleUzavkbrPjy0T5FMou8H" +
+ "X9u2AC2ry8vD/l7cqedtwMPp9k7TubgNFo+NGvKsl2ynyprOZR1xjQ7WgrgVB+mm" +
+ "uScOM/5HVceFuGRDhYTCObE+y1kxRloNYXnx3ei1zbeYLPCHdhxRYW7T0qcynNmw" +
+ "rn05/KO2RLjgQNalsQJBANeA3Q4Nugqy4QBUCEC09SqylT2K9FrrItqL2QKc9v0Z" +
+ "zO2uwllCbg0dwpVuYPYXYvikNHHg+aCWF+VXsb9rpPsCQQDWR9TT4ORdzoj+Nccn" +
+ "qkMsDmzt0EfNaAOwHOmVJ2RVBspPcxt5iN4HI7HNeG6U5YsFBb+/GZbgfBT3kpNG" +
+ "WPTpAkBI+gFhjfJvRw38n3g/+UeAkwMI2TJQS4n8+hid0uus3/zOjDySH3XHCUno" +
+ "cn1xOJAyZODBo47E+67R4jV1/gzbAkEAklJaspRPXP877NssM5nAZMU0/O/NGCZ+" +
+ "3jPgDUno6WbJn5cqm8MqWhW1xGkImgRk+fkDBquiq4gPiT898jusgQJAd5Zrr6Q8" +
+ "AO/0isr/3aa6O6NLQxISLKcPDk2NOccAfS/xOtfOz4sJYM3+Bs4Io9+dZGSDCA54" +
+ "Lw03eHTNQghS0A==";
+
+ private static final String CERTIFICATE_TEXT =
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIBpjCCAQ+gAwIBAgIBATANBgkqhkiG9w0BAQUFADAZMRcwFQYDVQQDDA5UZXN0\n" +
+ "IFByaW5jaXBhbDAeFw03MDAxMDEwODAwMDBaFw0zODEyMzEwODAwMDBaMBkxFzAV\n" +
+ "BgNVBAMMDlRlc3QgUHJpbmNpcGFsMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n" +
+ "gQC0YjCwIfYoprq/FQO6lb3asXrxLlJFuCvtinTF5p0GxvQGu5O3gYytUvtC2JlY\n" +
+ "zypSRjVxwxrsuRcP3e641SdASwfrmzyvIgP08N4S0IFzEURkV1wp/IpH7kH41Etb\n" +
+ "mUmrXSwfNZsnQRE5SYSOhh+LcK2wyQkdgcMv11l4KoBkcwIDAQABMA0GCSqGSIb3\n" +
+ "DQEBBQUAA4GBAGZLPEuJ5SiJ2ryq+CmEGOXfvlTtEL2nuGtr9PewxkgnOjZpUy+d\n" +
+ "4TvuXJbNQc8f4AMWL/tO9w0Fk80rWKp9ea8/df4qMq5qlFWlx6yOLQxumNOmECKb\n" +
+ "WpkUQDIDJEoFUzKMVuJf4KO/FJ345+BNLGgbJ6WujreoM1X/gYfdnJ/J\n" +
+ "-----END CERTIFICATE-----";
+
+ private SignedFetchRequestSigner signer;
+ private BasicGadgetToken authToken;
+ private OAuthAccessor accessor;
+
+ @Override
+ public void setUp() throws Exception {
+ authToken = new BasicGadgetToken("o", "v", "a", "d");
+ signer = new SignedFetchRequestSigner(authToken, "foo", PRIVATE_KEY_TEXT);
+ OAuthConsumer consumer = new OAuthConsumer(null, null, null, null);
+ consumer.setProperty(RSA_SHA1.X509_CERTIFICATE, CERTIFICATE_TEXT);
+ accessor = new OAuthAccessor(consumer);
+ }
+
+ public void testParametersSet() throws Exception {
+ URL unsigned = new URL("http://test");
+ URL out = signer.signRequest("GET", unsigned, null);
+ List<OAuth.Parameter> queryParams = OAuth.decodeForm(out.getQuery());
+ Assert.assertTrue(contains(queryParams, "opensocial_owner_id", "o"));
+ Assert.assertTrue(contains(queryParams, "opensocial_viewer_id", "v"));
+ Assert.assertTrue(contains(queryParams, "opensocial_app_id", "a"));
+ Assert.assertTrue(contains(queryParams, OAuth.OAUTH_CONSUMER_KEY, "d"));
+ Assert.assertTrue(
+ contains(queryParams, "xoauth_signature_publickey", "foo"));
+ }
+
+ public void testTrickyParametersInQuery() throws Exception {
+ String tricky = "%6fpensocial_owner_id=gotcha";
+ URL unsigned = new URL("http://test?" + tricky);
+ URL out = signer.signRequest("GET", unsigned, null);
+ Assert.assertFalse(out.getQuery().contains("gotcha"));
+ assertSignatureOK("GET", out.toString(), null);
+ }
+
+ public void testTrickyParametersInBody() throws Exception {
+ URL unsigned = new URL("http://test");
+ String tricky = "%6fpensocial_owner_id=gotcha";
+ URL out = signer.signRequest("POST", unsigned, tricky);
+ assertSignatureInvalid("POST", out.toString(), tricky);
+ }
+
+ public void testGetNoQuery() throws Exception {
+ URL unsigned = new URL("http://test");
+ URL out = signer.signRequest("GET", unsigned, null);
+ assertSignatureOK("GET", out.toString(), null);
+ }
+
+ public void testGetWithQuery() throws Exception {
+ URL unsigned = new URL("http://test?a=b");
+ URL out = signer.signRequest("GET", unsigned, null);
+ List<OAuth.Parameter> queryParams = OAuth.decodeForm(out.getQuery());
+ Assert.assertTrue(contains(queryParams, "a", "b"));
+ assertSignatureOK("GET", out.toString(), null);
+ }
+
+
+ public void testGetWithQueryMultiParam() throws Exception {
+ URL unsigned = new URL("http://test?a=b&a=c");
+ URL out = signer.signRequest("GET", unsigned, null);
+ List<OAuth.Parameter> queryParams = OAuth.decodeForm(out.getQuery());
+ Assert.assertTrue(contains(queryParams, "a", "b"));
+ Assert.assertTrue(contains(queryParams, "a", "c"));
+ assertSignatureOK("GET", out.toString(), null);
+ }
+
+ public void testPostNoQueryNoData() throws Exception {
+ URL unsigned = new URL("http://test");
+ URL out = signer.signRequest("POST", unsigned, null);
+ assertSignatureOK("POST", out.toString(), null);
+ }
+
+ public void testPostWithQueryNoData() throws Exception {
+ URL unsigned = new URL("http://test?name=value");
+ URL out = signer.signRequest("POST", unsigned, null);
+ List<OAuth.Parameter> queryParams = OAuth.decodeForm(out.getQuery());
+ Assert.assertTrue(contains(queryParams, "name", "value"));
+ assertSignatureOK("POST", out.toString(), null);
+ }
+
+ public void testPostNoQueryWithData() throws Exception {
+ URL unsigned = new URL("http://test");
+ URL out = signer.signRequest("POST", unsigned, "name=value");
+ List<OAuth.Parameter> queryParams = OAuth.decodeForm(out.getQuery());
+ Assert.assertFalse(contains(queryParams, "name", "value"));
+ assertSignatureOK("POST", out.toString(), "name=value");
+ }
+
+ public void testPostWithQueryWithData() throws Exception {
+ URL unsigned = new URL("http://test?queryName=queryValue");
+ URL out = signer.signRequest("POST", unsigned, "name=value");
+ List<OAuth.Parameter> queryParams = OAuth.decodeForm(out.getQuery());
+ Assert.assertTrue(contains(queryParams, "queryName", "queryValue"));
+ assertSignatureOK("POST", out.toString(), "name=value");
+ }
+
+ public void testStripOpenSocialParamsFromQuery() throws Exception {
+ URL unsigned = new URL("http://test?opensocial_foo=bar");
+ URL out = signer.signRequest("POST", unsigned, "name=value");
+ List<OAuth.Parameter> queryParams = OAuth.decodeForm(out.getQuery());
+ Assert.assertFalse(contains(queryParams, "opensocial_foo", "bar"));
+ assertSignatureOK("POST", out.toString(), "name=value");
+ }
+
+ public void testStripOAuthParamsFromQuery() throws Exception {
+ URL unsigned = new URL("http://test?oauth_foo=bar");
+ URL out = signer.signRequest("POST", unsigned, "name=value");
+ List<OAuth.Parameter> queryParams = OAuth.decodeForm(out.getQuery());
+ Assert.assertFalse(contains(queryParams, "oauth_foo", "bar"));
+ assertSignatureOK("POST", out.toString(), "name=value");
+ }
+
+ public void testStripOpenSocialParamsFromBody() throws Exception {
+ URL unsigned = new URL("http://test");
+ URL out = signer.signRequest("POST", unsigned, "opensocial_foo=bar");
+ assertSignatureInvalid("POST", out.toString(), "opensocial_foo=bar");
+ }
+
+ public void testStripOAuthParamsFromBody() throws Exception {
+ URL unsigned = new URL("http://test");
+ URL out = signer.signRequest("POST", unsigned, "oauth_foo=bar");
+ assertSignatureInvalid("POST", out.toString(), "oauth_foo=bar");
+ }
+
+ private void assertSignatureOK(String method, String urlStr, String body)
+ throws Exception {
+ URL url = new URL(urlStr);
+ URL noQuery = new URL(url.getProtocol(), url.getHost(), url.getPort(),
+ url.getPath());
+ List<OAuth.Parameter> queryParams = OAuth.decodeForm(url.getQuery());
+ List<OAuth.Parameter> postParams = OAuth.decodeForm(body);
+
+ ArrayList<OAuth.Parameter> msgParams = new ArrayList<OAuth.Parameter>();
+ msgParams.addAll(queryParams);
+ msgParams.addAll(postParams);
+
+ OAuthMessage message = new OAuthMessage(method, noQuery.toString(),
+ msgParams);
+
+ // Throws on failure
+ message.validateSignature(accessor);
+ }
+
+ private void assertSignatureInvalid(String method, String urlStr, String body) {
+ try {
+ assertSignatureOK(method, urlStr, body);
+ fail("Signature verification should have failed");
+ } catch (Exception e) {
+ // good
+ }
+ }
+
+ // Checks whether the given parameter list contains the specified
+ // key/value pair
+ private boolean contains(List<Parameter> params, String key, String value) {
+ for (Parameter p : params) {
+ if (p.getKey().equals(key) && p.getValue().equals(value)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/ProxyHandlerTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/ProxyHandlerTest.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/ProxyHandlerTest.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/ProxyHandlerTest.java Fri Mar 28 17:43:10 2008
@@ -25,7 +25,6 @@
import java.io.PrintWriter;
import java.net.URI;
-import org.apache.shindig.gadgets.GadgetException;
import org.apache.shindig.gadgets.GadgetTestFixture;
import org.apache.shindig.gadgets.RemoteContent;
import org.apache.shindig.gadgets.RemoteContentRequest;
@@ -143,54 +142,17 @@
writer.close();
}
- public void testSignedPostRequest() throws Exception {
- String postBody = "foo=bar%20baz";
- setupPostRequestMock(URL_ONE, postBody);
- expect(request.getParameter("st")).andReturn("fake-token").atLeastOnce();
- expect(request.getParameter("authz")).andReturn("signed").atLeastOnce();
- RemoteContent resp = new RemoteContent(200, DATA_ONE.getBytes(), null);
- expect(fetcher.fetch(
- looksLikeSignedFetch(URL_ONE, postBody.getBytes()))).andReturn(resp);
- replay();
- proxyHandler.fetchJson(request, response, state);
- verify();
- writer.close();
- }
-
- public void testInvalidSigningType() throws Exception {
- setupGetRequestMock(URL_ONE);
- expect(request.getParameter("st")).andReturn("fake-token").atLeastOnce();
- expect(request.getParameter("authz")).andReturn("garbage").atLeastOnce();
- replay();
- try {
- proxyHandler.fetchJson(request, response, state);
- fail("proxyHandler accepted invalid authz type");
- } catch (GadgetException e) {
- assertEquals(GadgetException.Code.UNSUPPORTED_FEATURE, e.getCode());
- }
- }
-
private RemoteContentRequest looksLikeSignedFetch(String url) {
- return looksLikeSignedFetch(url, null);
- }
-
- private RemoteContentRequest looksLikeSignedFetch(String url, byte[] postBody) {
- EasyMock.reportMatcher(new SignedFetchArgumentMatcher(url, postBody));
+ EasyMock.reportMatcher(new SignedFetchArgumentMatcher(url));
return null;
}
private class SignedFetchArgumentMatcher implements IArgumentMatcher {
private String expectedUrl;
- private byte[] postBody;
public SignedFetchArgumentMatcher(String expectedUrl) {
- this(expectedUrl, null);
- }
-
- public SignedFetchArgumentMatcher(String expectedUrl, byte[] postBody) {
this.expectedUrl = expectedUrl;
- this.postBody = postBody;
}
public void appendTo(StringBuffer sb) {
@@ -202,95 +164,11 @@
public boolean matches(Object arg0) {
RemoteContentRequest request = (RemoteContentRequest)arg0;
String url = request.getUri().toASCIIString();
- if (url.startsWith(expectedUrl) &&
- url.contains("opensocial_owner_id") &&
+ return (url.startsWith(expectedUrl) &&
+ url.contains("opensocial_owner_id") &&
url.contains("opensocial_viewer_id") &&
- url.contains("opensocial_app_id") &&
- byteArrayEquals(postBody, request.getPostBodyBytes())) {
- return true;
- }
- return false;
+ url.contains("opensocial_app_id"));
}
- private boolean byteArrayEquals(byte[] expected, byte[] actual) {
- if (expected == null) {
- expected = new byte[0];
- }
- if (actual == null) {
- actual = new byte[0];
- }
- if (expected.length != actual.length) {
- return false;
- }
- for (int i=0; i < expected.length; i++) {
- if (expected[i] != actual[i]) {
- return false;
- }
- }
- return true;
- }
- }
-
- public void testValidateUrlNoPath() throws Exception {
- URI url = proxyHandler.validateUrl("http://www.example.com");
- assertEquals("http", url.getScheme());
- assertEquals("www.example.com", url.getHost());
- assertEquals(-1, url.getPort());
- assertEquals("/", url.getPath());
- assertNull(url.getQuery());
- assertNull(url.getFragment());
- }
-
- public void testValidateUrlWithPath() throws Exception {
- URI url = proxyHandler.validateUrl("http://www.example.com/foo");
- assertEquals("http", url.getScheme());
- assertEquals("www.example.com", url.getHost());
- assertEquals(-1, url.getPort());
- assertEquals("/foo", url.getPath());
- assertNull(url.getQuery());
- assertNull(url.getFragment());
- }
-
- public void testValidateUrlWithPort() throws Exception {
- URI url = proxyHandler.validateUrl("http://www.example.com:8080/foo");
- assertEquals("http", url.getScheme());
- assertEquals("www.example.com", url.getHost());
- assertEquals(8080, url.getPort());
- assertEquals("/foo", url.getPath());
- assertNull(url.getQuery());
- assertNull(url.getFragment());
- }
-
- public void testValidateUrlWithEncodedPath() throws Exception {
- URI url = proxyHandler.validateUrl("http://www.example.com:8080/foo%20bar");
- assertEquals("http", url.getScheme());
- assertEquals("www.example.com", url.getHost());
- assertEquals(8080, url.getPort());
- assertEquals("/foo%20bar", url.getRawPath());
- assertEquals("/foo bar", url.getPath());
- assertNull(url.getQuery());
- assertNull(url.getFragment());
- }
-
- public void testValidateUrlWithEncodedQuery() throws Exception {
- URI url = proxyHandler.validateUrl("http://www.example.com:8080/foo?q=with%20space");
- assertEquals("http", url.getScheme());
- assertEquals("www.example.com", url.getHost());
- assertEquals(8080, url.getPort());
- assertEquals("/foo", url.getPath());
- assertEquals("q=with%20space", url.getRawQuery());
- assertEquals("q=with space", url.getQuery());
- assertNull(url.getFragment());
- }
-
- public void testValidateUrlWithNoPathAndEncodedQuery() throws Exception {
- URI url = proxyHandler.validateUrl("http://www.example.com?q=with%20space");
- assertEquals("http", url.getScheme());
- assertEquals("www.example.com", url.getHost());
- assertEquals(-1, url.getPort());
- assertEquals("/", url.getPath());
- assertEquals("q=with%20space", url.getRawQuery());
- assertEquals("q=with space", url.getQuery());
- assertNull(url.getFragment());
}
}
Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/util/BlobCrypterTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/util/BlobCrypterTest.java?rev=642460&r1=642459&r2=642460&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/util/BlobCrypterTest.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/util/BlobCrypterTest.java Fri Mar 28 17:43:10 2008
@@ -49,8 +49,6 @@
checkString("ab");
checkString("dfkljdasklsdfklasdjfklajsdfkljasdklfjasdkljfaskldjf");
checkString(Crypto.getRandomString(500));
- checkString("foo bar baz");
- checkString("foo\nbar\nbaz");
}
private void checkString(String string) throws Exception {