blob: b57d9b91f4d4892e05efaa3009f5091d202b6e2e [file] [log] [blame]
// Copyright 2013 Google Inc. All Rights Reserved.
package com.android.exchange.utility;
import android.os.Build;
import android.util.Base64;
import android.util.Log;
import com.android.exchange.Eas;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.RequestWrapper;
import org.apache.http.protocol.HttpContext;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URI;
/**
* Logs cURL commands equivalent to requests.
* Curl Logging is copied over from AndroidHttpClient. Just switching to AndroidHttpClient is
* not trivial so it's easier to borrow the curl logging code this way.
*/
public class CurlLogger implements HttpRequestInterceptor {
private static final String TAG = Eas.LOG_TAG;
@Override
public void process(HttpRequest request, HttpContext context) throws IOException {
if (request instanceof HttpUriRequest) {
if ((Build.TYPE.equals("userdebug") || Build.TYPE.equals("eng"))
&& Log.isLoggable(TAG, Log.VERBOSE)) {
// Allow us to log auth token on dev devices - this is not a big security risk
// because dev devices have a readable account.db file where all the auth tokens
// are stored.
Log.d(TAG, toCurl((HttpUriRequest) request, true));
} else if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, toCurl((HttpUriRequest) request, false));
}
}
}
/**
* Generates a cURL command equivalent to the given request.
*/
private static String toCurl(HttpUriRequest request, boolean logAuthToken) throws IOException {
StringBuilder builder = new StringBuilder();
builder.append("curl ");
for (Header header: request.getAllHeaders()) {
builder.append("--header \"");
if (!logAuthToken
&& (header.getName().equals("Authorization") ||
header.getName().equals("Cookie"))) {
builder.append(header.getName()).append(": ").append("${token}");
} else {
builder.append(header.toString().trim());
}
builder.append("\" ");
}
URI uri = request.getURI();
// If this is a wrapped request, use the URI from the original
// request instead. getURI() on the wrapper seems to return a
// relative URI. We want an absolute URI.
if (request instanceof RequestWrapper) {
HttpRequest original = ((RequestWrapper) request).getOriginal();
if (original instanceof HttpUriRequest) {
uri = ((HttpUriRequest) original).getURI();
}
}
builder.append("\"");
builder.append(uri);
builder.append("\"");
if (request instanceof HttpEntityEnclosingRequest) {
HttpEntityEnclosingRequest entityRequest =
(HttpEntityEnclosingRequest) request;
HttpEntity entity = entityRequest.getEntity();
if (entity != null && entity.isRepeatable()) {
if (entity.getContentLength() < 1024) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
entity.writeTo(stream);
String base64 = Base64.encodeToString(stream.toByteArray(), Base64.NO_WRAP);
builder.insert(0, "echo '" + base64 + "' | base64 -d > /tmp/$$.bin; ");
builder.append(" --data-binary @/tmp/$$.bin");
} else {
builder.append(" [TOO MUCH DATA TO INCLUDE]");
}
}
}
return builder.toString();
}
}