michael@0: /* michael@0: * ==================================================================== michael@0: * michael@0: * Licensed to the Apache Software Foundation (ASF) under one or more michael@0: * contributor license agreements. See the NOTICE file distributed with michael@0: * this work for additional information regarding copyright ownership. michael@0: * The ASF licenses this file to You under the Apache License, Version 2.0 michael@0: * (the "License"); you may not use this file except in compliance with michael@0: * the License. You may obtain a copy of the License at michael@0: * michael@0: * http://www.apache.org/licenses/LICENSE-2.0 michael@0: * michael@0: * Unless required by applicable law or agreed to in writing, software michael@0: * distributed under the License is distributed on an "AS IS" BASIS, michael@0: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. michael@0: * See the License for the specific language governing permissions and michael@0: * limitations under the License. michael@0: * ==================================================================== michael@0: * michael@0: * This software consists of voluntary contributions made by many michael@0: * individuals on behalf of the Apache Software Foundation. For more michael@0: * information on the Apache Software Foundation, please see michael@0: * . michael@0: * michael@0: */ michael@0: michael@0: package ch.boye.httpclientandroidlib.impl.auth; michael@0: michael@0: import ch.boye.httpclientandroidlib.annotation.NotThreadSafe; michael@0: michael@0: import ch.boye.httpclientandroidlib.FormattedHeader; michael@0: import ch.boye.httpclientandroidlib.Header; michael@0: import ch.boye.httpclientandroidlib.HttpRequest; michael@0: import ch.boye.httpclientandroidlib.auth.AUTH; michael@0: import ch.boye.httpclientandroidlib.auth.AuthenticationException; michael@0: import ch.boye.httpclientandroidlib.auth.ContextAwareAuthScheme; michael@0: import ch.boye.httpclientandroidlib.auth.Credentials; michael@0: import ch.boye.httpclientandroidlib.auth.MalformedChallengeException; michael@0: import ch.boye.httpclientandroidlib.protocol.HTTP; michael@0: import ch.boye.httpclientandroidlib.protocol.HttpContext; michael@0: import ch.boye.httpclientandroidlib.util.CharArrayBuffer; michael@0: michael@0: /** michael@0: * Abstract authentication scheme class that serves as a basis michael@0: * for all authentication schemes supported by HttpClient. This class michael@0: * defines the generic way of parsing an authentication challenge. It michael@0: * does not make any assumptions regarding the format of the challenge michael@0: * nor does it impose any specific way of responding to that challenge. michael@0: * michael@0: * michael@0: * @since 4.0 michael@0: */ michael@0: @NotThreadSafe // proxy michael@0: public abstract class AuthSchemeBase implements ContextAwareAuthScheme { michael@0: michael@0: /** michael@0: * Flag whether authenticating against a proxy. michael@0: */ michael@0: private boolean proxy; michael@0: michael@0: public AuthSchemeBase() { michael@0: super(); michael@0: } michael@0: michael@0: /** michael@0: * Processes the given challenge token. Some authentication schemes michael@0: * may involve multiple challenge-response exchanges. Such schemes must be able michael@0: * to maintain the state information when dealing with sequential challenges michael@0: * michael@0: * @param header the challenge header michael@0: * michael@0: * @throws MalformedChallengeException is thrown if the authentication challenge michael@0: * is malformed michael@0: */ michael@0: public void processChallenge(final Header header) throws MalformedChallengeException { michael@0: if (header == null) { michael@0: throw new IllegalArgumentException("Header may not be null"); michael@0: } michael@0: String authheader = header.getName(); michael@0: if (authheader.equalsIgnoreCase(AUTH.WWW_AUTH)) { michael@0: this.proxy = false; michael@0: } else if (authheader.equalsIgnoreCase(AUTH.PROXY_AUTH)) { michael@0: this.proxy = true; michael@0: } else { michael@0: throw new MalformedChallengeException("Unexpected header name: " + authheader); michael@0: } michael@0: michael@0: CharArrayBuffer buffer; michael@0: int pos; michael@0: if (header instanceof FormattedHeader) { michael@0: buffer = ((FormattedHeader) header).getBuffer(); michael@0: pos = ((FormattedHeader) header).getValuePos(); michael@0: } else { michael@0: String s = header.getValue(); michael@0: if (s == null) { michael@0: throw new MalformedChallengeException("Header value is null"); michael@0: } michael@0: buffer = new CharArrayBuffer(s.length()); michael@0: buffer.append(s); michael@0: pos = 0; michael@0: } michael@0: while (pos < buffer.length() && HTTP.isWhitespace(buffer.charAt(pos))) { michael@0: pos++; michael@0: } michael@0: int beginIndex = pos; michael@0: while (pos < buffer.length() && !HTTP.isWhitespace(buffer.charAt(pos))) { michael@0: pos++; michael@0: } michael@0: int endIndex = pos; michael@0: String s = buffer.substring(beginIndex, endIndex); michael@0: if (!s.equalsIgnoreCase(getSchemeName())) { michael@0: throw new MalformedChallengeException("Invalid scheme identifier: " + s); michael@0: } michael@0: michael@0: parseChallenge(buffer, pos, buffer.length()); michael@0: } michael@0: michael@0: michael@0: @SuppressWarnings("deprecation") michael@0: public Header authenticate( michael@0: final Credentials credentials, michael@0: final HttpRequest request, michael@0: final HttpContext context) throws AuthenticationException { michael@0: return authenticate(credentials, request); michael@0: } michael@0: michael@0: protected abstract void parseChallenge( michael@0: CharArrayBuffer buffer, int beginIndex, int endIndex) throws MalformedChallengeException; michael@0: michael@0: /** michael@0: * Returns true if authenticating against a proxy, false michael@0: * otherwise. michael@0: * michael@0: * @return true if authenticating against a proxy, false michael@0: * otherwise michael@0: */ michael@0: public boolean isProxy() { michael@0: return this.proxy; michael@0: } michael@0: michael@0: @Override michael@0: public String toString() { michael@0: return getSchemeName(); michael@0: } michael@0: michael@0: }