• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 Google Inc. All Rights Reserved.
2 
3 package com.android.exchange.utility;
4 
5 import android.os.Build;
6 import android.util.Base64;
7 import android.util.Log;
8 
9 import com.android.exchange.Eas;
10 
11 import org.apache.http.Header;
12 import org.apache.http.HttpEntity;
13 import org.apache.http.HttpEntityEnclosingRequest;
14 import org.apache.http.HttpRequest;
15 import org.apache.http.HttpRequestInterceptor;
16 import org.apache.http.client.methods.HttpUriRequest;
17 import org.apache.http.impl.client.RequestWrapper;
18 import org.apache.http.protocol.HttpContext;
19 
20 import java.io.ByteArrayOutputStream;
21 import java.io.IOException;
22 import java.net.URI;
23 
24 /**
25  * Logs cURL commands equivalent to requests.
26  * Curl Logging is copied over from AndroidHttpClient. Just switching to AndroidHttpClient is
27  * not trivial so it's easier to borrow the curl logging code this way.
28  */
29 public class CurlLogger implements HttpRequestInterceptor {
30     private static final String TAG = Eas.LOG_TAG;
31 
32     @Override
process(HttpRequest request, HttpContext context)33     public void process(HttpRequest request, HttpContext context) throws IOException {
34         if (request instanceof HttpUriRequest) {
35             if ((Build.TYPE.equals("userdebug") || Build.TYPE.equals("eng"))
36                     &&  Log.isLoggable(TAG, Log.VERBOSE)) {
37                 // Allow us to log auth token on dev devices - this is not a big security risk
38                 // because dev devices have a readable account.db file where all the auth tokens
39                 // are stored.
40                 Log.d(TAG, toCurl((HttpUriRequest) request, true));
41             } else  if (Log.isLoggable(TAG, Log.DEBUG)) {
42                 Log.d(TAG, toCurl((HttpUriRequest) request, false));
43             }
44         }
45     }
46 
47     /**
48      * Generates a cURL command equivalent to the given request.
49      */
toCurl(HttpUriRequest request, boolean logAuthToken)50     private static String toCurl(HttpUriRequest request, boolean logAuthToken) throws IOException {
51         StringBuilder builder = new StringBuilder();
52 
53         builder.append("curl ");
54 
55         for (Header header: request.getAllHeaders()) {
56             builder.append("--header \"");
57             if (!logAuthToken
58                     && (header.getName().equals("Authorization") ||
59                     header.getName().equals("Cookie"))) {
60 
61                 builder.append(header.getName()).append(": ").append("${token}");
62             } else {
63                 builder.append(header.toString().trim());
64             }
65             builder.append("\" ");
66         }
67 
68         URI uri = request.getURI();
69 
70         // If this is a wrapped request, use the URI from the original
71         // request instead. getURI() on the wrapper seems to return a
72         // relative URI. We want an absolute URI.
73         if (request instanceof RequestWrapper) {
74             HttpRequest original = ((RequestWrapper) request).getOriginal();
75             if (original instanceof HttpUriRequest) {
76                 uri = ((HttpUriRequest) original).getURI();
77             }
78         }
79 
80         builder.append("\"");
81         builder.append(uri);
82         builder.append("\"");
83 
84         if (request instanceof HttpEntityEnclosingRequest) {
85             HttpEntityEnclosingRequest entityRequest =
86                     (HttpEntityEnclosingRequest) request;
87             HttpEntity entity = entityRequest.getEntity();
88             if (entity != null && entity.isRepeatable()) {
89                 if (entity.getContentLength() < 1024) {
90                     ByteArrayOutputStream stream = new ByteArrayOutputStream();
91                     entity.writeTo(stream);
92 
93                     String base64 = Base64.encodeToString(stream.toByteArray(), Base64.NO_WRAP);
94                     builder.insert(0, "echo '" + base64 + "' | base64 -d > /tmp/$$.bin; ");
95                     builder.append(" --data-binary @/tmp/$$.bin");
96                 } else {
97                     builder.append(" [TOO MUCH DATA TO INCLUDE]");
98                 }
99             }
100         }
101 
102         return builder.toString();
103     }
104 
105 }
106