| // 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(); |
| } |
| |
| } |