I'm trying to port an open source RETS client to the Android platform.
The original client used Apache httpclient. I'm trying to test login
to a demo RETS server that uses basic authentication. The demo login
works fine when I test from web browsers. When I try a login from the
emulator I get a 401 status code. The login URL is
http://demo.crt.realtors.org:6103/rets/login. The user name is "Joe"
and the password is "Schmoe". I pasted my modified client code.

Grant

public class CommonsHttpClient extends RetsHttpClient {
    private static final Logger LOG =
Logger.getLogger(CommonsHttpClient.class.toString());

    private static final int DEFAULT_TIMEOUT = 300000;
    private static final String RETS_VERSION = "RETS-Version";
    private static final String RETS_SESSION_ID = "RETS-Session-ID";
    private static final String RETS_REQUEST_ID = "RETS-Request-ID";
    private static final String USER_AGENT = "User-Agent";
    private static final String RETS_UA_AUTH_HEADER = "RETS-UA-
Authorization";
    private static final String ACCEPT_ENCODING = "Accept-Encoding";
    public static final String CONTENT_ENCODING = "Content-Encoding";
    public static final String DEFLATE_ENCODINGS = "gzip,deflate";

    private final ConcurrentHashMap<String, String> defaultHeaders;
    private final DefaultHttpClient httpClient;

    // method choice improvement
    private final String userAgentPassword;

    public CommonsHttpClient() {
        this(DEFAULT_TIMEOUT, null, true);
    }

    public CommonsHttpClient(int timeout, String userAgentPassword,
boolean gzip) {
        this.defaultHeaders = new ConcurrentHashMap<String, String>();
        this.userAgentPassword = userAgentPassword;

        // setup the HTTP parameters
        HttpParams httpParams = new BasicHttpParams();
        HttpConnectionParams.setConnectionTimeout(httpParams,
timeout);
        HttpConnectionParams.setSoTimeout(httpParams, timeout);
        HttpProtocolParams.setVersion(httpParams,
HttpVersion.HTTP_1_1);
        // set to rfc 2109 as it puts the ASP (IIS) cookie _FIRST_,
this is critical for interealty
        HttpClientParams.setCookiePolicy(httpParams,
CookiePolicy.RFC_2109);

        // create a scheme registry for HTTP and HTTPS
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", new PlainSocketFactory(),
80));
        registry.register(new Scheme("https",
SSLSocketFactory.getSocketFactory(), 443));

        // create a thread-safe connection manager. Allows multiple
threaded requests from client
        ThreadSafeClientConnManager multiThreadedConnectionManager =
                new ThreadSafeClientConnManager(httpParams, registry);
        this.httpClient = new
DefaultHttpClient(multiThreadedConnectionManager, httpParams);

        // we only support basic authentication
        BasicScheme basicScheme = new BasicScheme();
        AuthSchemeRegistry authRegistry = new AuthSchemeRegistry();
        authRegistry.register(basicScheme.getSchemeName(), new
BasicSchemeFactory());
        this.httpClient.setAuthSchemes(authRegistry);
        this.httpClient.setCredentialsProvider(new
BasicCredentialsProvider());

        // ask the server if we can use gzip
        if (gzip) this.addDefaultHeader(ACCEPT_ENCODING,
DEFLATE_ENCODINGS);
    }

    public HttpClient getHttpClient() {
        return this.httpClient;
    }

    //----------------------method implementations
    @Override
    public void setUserCredentials(String userName, String password) {
        this.httpClient.getCredentialsProvider().setCredentials(
                new AuthScope(AuthScope.ANY_HOST,
                        AuthScope.ANY_PORT,
                        AuthScope.ANY_REALM,
                        AuthScope.ANY_SCHEME),
                new UsernamePasswordCredentials(userName, password));
    }

    @Override
    public RetsHttpResponse doRequest(String httpMethod,
RetsHttpRequest request)
            throws RetsException {
        return "GET".equals(StringUtils.upperCase(httpMethod)) ?
this.doGet(request) : this.doPost(request);
    }

    //----------------------method implementations
    public RetsHttpResponse doGet(RetsHttpRequest request) throws
RetsException {
        String url = request.getUrl();
        String args = request.getHttpParameters();
        if (args != null) {
            url = url + "?" + args;
        }
        HttpGet method = new HttpGet(url);
        LOG.fine(String.format("\n>>>\nGET %s", url));
        return execute(method, request.getHeaders());
    }

    public RetsHttpResponse doPost(RetsHttpRequest request)
            throws RetsException {
        try {
            String url = request.getUrl();
            String body = request.getHttpParameters();
            if (body == null) body = "";  // commons-httpclient 3.0
refuses to accept null entity (body)
            HttpPost method = new HttpPost(url);
            method.setEntity(new StringEntity(body));
            method.setHeader("Content-Type", "application/x-www-url-
encoded");
            LOG.fine(String.format("\n>>>\nPOST %s\nArgs: %s", url,
body));

            return execute(method, request.getHeaders());
        } catch (UnsupportedEncodingException e) {
            throw new RetsException(e.getMessage());
        }
    }

    private RetsHttpResponse execute(final HttpUriRequest uriRequest,
Map<String, String> headers)
            throws RetsException {
        try {
            // add the default headers
            if (this.defaultHeaders != null) {
                for (Map.Entry<String, String> entry :
this.defaultHeaders.entrySet()) {
                    uriRequest.setHeader(entry.getKey(),
entry.getValue());
                }
            }
            // add our request headers from rets
            if (headers != null) {
                for (Map.Entry<String, String> entry :
headers.entrySet()) {
                    uriRequest.setHeader(entry.getKey(),
entry.getValue());
                }
            }

            final Map<String, String> cookies = this.getCookies();

            // optional ua-auth stuff here
            if (this.userAgentPassword != null) {
                uriRequest.setHeader(RETS_UA_AUTH_HEADER,
                        this.calculateUaAuthHeader(uriRequest,
cookies));
            }
            // try to execute the request
            final HttpResponse httpResponse =
this.httpClient.execute(uriRequest);
            if (httpResponse.getStatusLine().getStatusCode() !=
HttpStatus.SC_OK) {
                throw new InvalidHttpStatusException(
                        httpResponse.getStatusLine().getStatusCode(),
 
httpResponse.getStatusLine().getReasonPhrase());
            }

            return new CommonsHttpClientResponse(httpResponse,
cookies);
        } catch (Exception e) {
            throw new RetsException(e);
        }
    }

    @Override
    public synchronized void addDefaultHeader(String key, String
value) {
        this.defaultHeaders.put(key, value);
        if (value == null) this.defaultHeaders.remove(key);
    }

    private Map<String, String> getCookies() {
        Map<String, String> cookieMap = new CaseInsensitiveTreeMap();
        for (Cookie cookie :
this.httpClient.getCookieStore().getCookies()) {
            cookieMap.put(cookie.getName(), cookie.getValue());
        }
        return cookieMap;
    }

    private String calculateUaAuthHeader(HttpUriRequest uriRequest,
Map<String, String> cookies) {
        final String userAgent = this.getHeaderValue(uriRequest,
USER_AGENT);
        final String requestId = this.getHeaderValue(uriRequest,
RETS_REQUEST_ID);
        final String sessionId = cookies.get(RETS_SESSION_ID);
        final String retsVersion = this.getHeaderValue(uriRequest,
RETS_VERSION);
        String secretHash = DigestUtils.md5Hex(String.format("%s:%s",
userAgent, this.userAgentPassword));
        String pieces = String.format("%s:%s:%s:%s", secretHash,
                StringUtils.trimToEmpty(requestId),
                StringUtils.trimToEmpty(sessionId),
                retsVersion);
        return String.format("Digest %s", DigestUtils.md5Hex(pieces));
    }

    private String getHeaderValue(HttpUriRequest uriRequest, String
key) {
        Header requestHeader = uriRequest.getHeaders(key)[0];
        if (requestHeader == null) return null;
        return requestHeader.getValue();
    }
}


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to