/*
 * 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.
 */
package org.apache.shindig.auth;

import com.google.common.collect.Maps;
import com.google.inject.Inject;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

/**
 * Produces security tokens by extracting the "st" parameter from the request url or post body.
 */
public class UrlParameterAuthenticationHandler implements AuthenticationHandler {
  private static final String SECURITY_TOKEN_PARAM = "st";
  private static final String OAUTH2_TOKEN_PARAM = "oauth_token";
  private final SecurityTokenDecoder securityTokenDecoder;

  @Inject
  public UrlParameterAuthenticationHandler(SecurityTokenDecoder securityTokenDecoder) {
    this.securityTokenDecoder = securityTokenDecoder;
  }

  public String getName() {
    return AuthenticationMode.SECURITY_TOKEN_URL_PARAMETER.name();
  }

  public SecurityToken getSecurityTokenFromRequest(HttpServletRequest request)
      throws InvalidAuthenticationException {
    Map<String, String> parameters = getMappedParameters(request);
    try {
      if (parameters.get(SecurityTokenDecoder.SECURITY_TOKEN_NAME) == null) {
        return null;
      }
      return securityTokenDecoder.createToken(parameters);
    } catch (SecurityTokenException e) {
      throw new InvalidAuthenticationException("Malformed security token " +
          parameters.get(SecurityTokenDecoder.SECURITY_TOKEN_NAME), e);
    }
  }

  public String getWWWAuthenticateHeader(String realm) {
    return null;
  }

  protected SecurityTokenDecoder getSecurityTokenDecoder() {
    return this.securityTokenDecoder;
  }

  protected Map<String, String> getMappedParameters(final HttpServletRequest request) {
    Map<String, String> params = Maps.newHashMap();

    String oauth_token_value = request.getParameter(OAUTH2_TOKEN_PARAM);

    if (request.isSecure() && oauth_token_value != null) {
      params.put(SecurityTokenDecoder.SECURITY_TOKEN_NAME, oauth_token_value);
    } else {
      params.put(SecurityTokenDecoder.SECURITY_TOKEN_NAME, request.getParameter(SECURITY_TOKEN_PARAM));
    }
    params.put(SecurityTokenDecoder.ACTIVE_URL_NAME, getActiveUrl(request));
    return params;
  }
  
  protected String getActiveUrl(HttpServletRequest request) {
    return request.getRequestURL().toString();
  }
}

@@ -906,29 +906,229 @@
 ct;%0A
-%0Aimport java.util.Map
+import net.oauth.OAuth;%0Aimport net.oauth.OAuthMessage;%0A%0Aimport java.util.ArrayList;%0Aimport java.util.Enumeration;%0Aimport java.util.List;%0Aimport java.util.Map;%0Aimport java.util.regex.Matcher;%0Aimport java.util.regex.Pattern
 ;%0A%0Ai
@@ -2549,24 +2549,221 @@
 coder;%0A  %7D%0A%0A
+  // From OAuthMessage%0A  private static final Pattern AUTHORIZATION = Pattern.compile(%22%5C%5Cs*(%5C%5Cw*)%5C%5Cs+(.*)%22);%0A  private static final Pattern NVP = Pattern.compile(%22(%5C%5CS*)%5C%5Cs*%5C%5C=%5C%5Cs*%5C%22(%5B%5E%5C%22%5D*)%5C%22%22);%0A%0A
   protected 
@@ -2890,17 +2890,16 @@
 hMap();%0A
-%0A
     Stri
@@ -2901,33 +2901,99 @@
  String 
-oauth_token_value
+token = null;%0A%0A    // old style security token%0A    if (token == null) %7B%0A      token
  = reque
@@ -3008,22 +3008,24 @@
 rameter(
-OAUTH2
+SECURITY
 _TOKEN_P
@@ -3035,162 +3035,739 @@
 M);%0A
-%0A    if (request.isSecure() && oauth_token_value != null) %7B%0A      params.put(SecurityTokenDecoder.SECURITY_TOKEN_NAME, oauth_token_value);%0A    %7D else %7B%0A  
+    %7D%0A%0A    // OAuth token as a param%0A    if (token == null && request.isSecure()) %7B%0A      token = request.getParameter(OAUTH2_TOKEN_PARAM);%0A    %7D%0A%0A    // token in authorization header%0A    if (token == null) %7B%0A      for (Enumeration%3CString%3E headers = request.getHeaders(%22Authorization%22); headers != null && headers.hasMoreElements();) %7B%0A        Matcher m = AUTHORIZATION.matcher(headers.nextElement());%0A        if (m.matches() && %22Token%22.equalsIgnoreCase(m.group(1))) %7B%0A          for (String nvp : m.group(2).split(%22%5C%5Cs*,%5C%5Cs*%22)) %7B%0A            m = NVP.matcher(nvp);%0A            if (m.matches() && %22token%22.equals(m.group(1))) %7B%0A              token = OAuth.decodePercent(m.group(2));%0A            %7D%0A          %7D%0A        %7D%0A      %7D%0A    %7D%0A%0A
     
@@ -3823,58 +3823,15 @@
 ME, 
-request.getParameter(SECURITY_TOKEN_PARAM));%0A    %7D
+token);
 %0A   

Allow oauth2 authorization headers