/*
     * Reads an entry from an input stream. A typical entry looks like this:
     *   http://google.com/foo
     *   GET
     *   2
     *   Accept-Language: fr-CA
     *   Accept-Charset: UTF-8
     *   HTTP/1.1 200 OK
     *   3
     *   Content-Type: image/png
     *   Content-Length: 100
     *   Cache-Control: max-age=600
     *
     * A typical HTTPS file looks like this:
     *   https://google.com/foo
     *   GET
     *   2
     *   Accept-Language: fr-CA
     *   Accept-Charset: UTF-8
     *   HTTP/1.1 200 OK
     *   3
     *   Content-Type: image/png
     *   Content-Length: 100
     *   Cache-Control: max-age=600
     *
     *   AES_256_WITH_MD5
     *   2
     *   base64-encoded peerCertificate[0]
     *   base64-encoded peerCertificate[1]
     *   -1
     *
     * The file is newline separated. The first two lines are the URL and
     * the request method. Next is the number of HTTP Vary request header
     * lines, followed by those lines.
     *
     * Next is the response status line, followed by the number of HTTP
     * response header lines, followed by those lines.
     *
     * HTTPS responses also contain SSL session information. This begins
     * with a blank line, and then a line containing the cipher suite. Next
     * is the length of the peer certificate chain. These certificates are
     * base64-encoded and appear each on their own line. The next line
     * contains the length of the local certificate chain. These
     * certificates are also base64-encoded and appear each on their own
     * line. A length of -1 is used to encode a null array.
     */
    public Entry(InputStream in) throws IOException {
      try {
        StrictLineReader reader = new StrictLineReader(in, Charsets.US_ASCII);
        uri = reader.readLine();
        requestMethod = reader.readLine();
        varyHeaders = new RawHeaders();
        int varyRequestHeaderLineCount = reader.readInt();
        for (int i = 0; i < varyRequestHeaderLineCount; i++) {
          varyHeaders.addLine(reader.readLine());
        }

        responseHeaders = new RawHeaders();
        responseHeaders.setStatusLine(reader.readLine());
        int responseHeaderLineCount = reader.readInt();
        for (int i = 0; i < responseHeaderLineCount; i++) {
          responseHeaders.addLine(reader.readLine());
        }

        //                if (isHttps()) {
        //                    String blank = reader.readLine();
        //                    if (blank.length() != 0) {
        //                        throw new IOException("expected \"\" but was \"" + blank + "\"");
        //                    }
        //                    cipherSuite = reader.readLine();
        //                    peerCertificates = readCertArray(reader);
        //                    localCertificates = readCertArray(reader);
        //                } else {
        cipherSuite = null;
        peerCertificates = null;
        localCertificates = null;
        //                }
      } finally {
        in.close();
      }
    }
    public void writeTo(DiskLruCache.Editor editor) throws IOException {
      OutputStream out = editor.newOutputStream(ENTRY_METADATA);
      Writer writer = new BufferedWriter(new OutputStreamWriter(out, Charsets.UTF_8));

      writer.write(uri + '\n');
      writer.write(requestMethod + '\n');
      writer.write(Integer.toString(varyHeaders.length()) + '\n');
      for (int i = 0; i < varyHeaders.length(); i++) {
        writer.write(varyHeaders.getFieldName(i) + ": " + varyHeaders.getValue(i) + '\n');
      }

      writer.write(responseHeaders.getStatusLine() + '\n');
      writer.write(Integer.toString(responseHeaders.length()) + '\n');
      for (int i = 0; i < responseHeaders.length(); i++) {
        writer.write(responseHeaders.getFieldName(i) + ": " + responseHeaders.getValue(i) + '\n');
      }

      if (isHttps()) {
        writer.write('\n');
        writer.write(cipherSuite + '\n');
        writeCertArray(writer, peerCertificates);
        writeCertArray(writer, localCertificates);
      }
      writer.close();
    }
 @Override
 public void onHeaders(RawHeaders headers) {
   if (headers.getResponseCode() == 401) {
     Log.e(TAG, "Refresh failed:\n" + headers.toHeaderString());
     AccountManager am = AccountManager.get(mContext);
     if (am != null) {
       am.invalidateAuthToken("com.google", mAuthToken);
     }
     removeRnrse();
   }
 }
Beispiel #4
0
  public static boolean isKeepAlive(RawHeaders headers) {
    boolean keepAlive;
    String connection = headers.get("Connection");
    if (connection != null) {
      keepAlive = "keep-alive".equalsIgnoreCase(connection);
    } else {
      keepAlive = headers.getHttpMinorVersion() >= 1;
    }

    return keepAlive;
  }
 public boolean matches(
     URI uri, String requestMethod, Map<String, List<String>> requestHeaders) {
   return this.uri.equals(uri.toString())
       && this.requestMethod.equals(requestMethod)
       && new ResponseHeaders(uri, responseHeaders)
           .varyMatches(varyHeaders.toMultimap(), requestHeaders);
 }
Beispiel #6
0
  public static AsyncHttpRequestBody getBody(
      DataEmitter emitter, CompletedCallback reporter, RawHeaders headers) {
    String contentType = headers.get("Content-Type");
    if (contentType != null) {
      String[] values = contentType.split(";");
      for (int i = 0; i < values.length; i++) {
        values[i] = values[i].trim();
      }
      for (String ct : values) {
        if (UrlEncodedFormBody.CONTENT_TYPE.equals(ct)) {
          return new UrlEncodedFormBody();
        }
        if (JSONObjectBody.CONTENT_TYPE.equals(ct)) {
          return new JSONObjectBody();
        }
        if (StringBody.CONTENT_TYPE.equals(ct)) {
          return new StringBody();
        }
        if (MultipartFormDataBody.CONTENT_TYPE.equals(ct)) {
          return new MultipartFormDataBody(contentType, values);
        }
      }
    }

    return null;
  }
 @Override
 public void onStringAvailable(String s) {
   try {
     if (mRawHeaders.getStatusLine() == null) {
       mRawHeaders.setStatusLine(s);
     } else if (!"\r".equals(s)) {
       mRawHeaders.addLine(s);
     } else {
       mHeaders = new ResponseHeaders(mRequest.getUri(), mRawHeaders);
       onHeadersReceived();
       // socket may get detached after headers (websocket)
       if (mSocket == null) return;
       DataEmitter emitter = Util.getBodyDecoder(mSocket, mRawHeaders, false, mReporter);
       setDataEmitter(emitter);
     }
   } catch (Exception ex) {
     report(ex);
   }
 }
Beispiel #8
0
  public static DataEmitter getBodyDecoder(
      DataEmitter emitter, RawHeaders headers, boolean server) {
    long _contentLength;
    try {
      _contentLength = Long.parseLong(headers.get("Content-Length"));
    } catch (Exception ex) {
      _contentLength = -1;
    }
    final long contentLength = _contentLength;
    if (-1 != contentLength) {
      if (contentLength < 0) {
        EndEmitter ender =
            EndEmitter.create(
                emitter.getServer(),
                new BodyDecoderException(
                    "not using chunked encoding, and no content-length found."));
        ender.setDataEmitter(emitter);
        emitter = ender;
        return emitter;
      }
      if (contentLength == 0) {
        EndEmitter ender = EndEmitter.create(emitter.getServer(), null);
        ender.setDataEmitter(emitter);
        emitter = ender;
        return emitter;
      }
      ContentLengthFilter contentLengthWatcher = new ContentLengthFilter(contentLength);
      contentLengthWatcher.setDataEmitter(emitter);
      emitter = contentLengthWatcher;
    } else if ("chunked".equalsIgnoreCase(headers.get("Transfer-Encoding"))) {
      ChunkedInputFilter chunker = new ChunkedInputFilter();
      chunker.setDataEmitter(emitter);
      emitter = chunker;
    } else {
      if ((server || headers.getStatusLine().contains("HTTP/1.1"))
          && !"close".equalsIgnoreCase(headers.get("Connection"))) {
        // if this is the server, and the client has not indicated a request body, the client is
        // done
        EndEmitter ender = EndEmitter.create(emitter.getServer(), null);
        ender.setDataEmitter(emitter);
        emitter = ender;
        return emitter;
      }
    }

    if ("gzip".equals(headers.get("Content-Encoding"))) {
      GZIPInputFilter gunzipper = new GZIPInputFilter();
      gunzipper.setDataEmitter(emitter);
      emitter = gunzipper;
    } else if ("deflate".equals(headers.get("Content-Encoding"))) {
      InflaterInputFilter inflater = new InflaterInputFilter();
      inflater.setDataEmitter(emitter);
      emitter = inflater;
    }

    // conversely, if this is the client (http 1.0), and the server has not indicated a request
    // body, we do not report
    // the close/end event until the server actually closes the connection.
    return emitter;
  }
  // step 1) see if we can serve request from the cache directly.
  // also see if this can be turned into a conditional cache request.
  @Override
  public Cancellable getSocket(final GetSocketData data) {
    if (cache == null) return null;

    if (!caching) return null;
    if (data.request.getHeaders().isNoCache()) return null;
    //        Log.i(LOGTAG, "getting cache socket: " + request.getUri().toString());

    String key = uriToKey(data.request.getUri());
    DiskLruCache.Snapshot snapshot;
    Entry entry;
    try {
      snapshot = cache.get(key);
      if (snapshot == null) {
        //                Log.i(LOGTAG, "snapshot fail");
        return null;
      }
      entry = new Entry(snapshot.getInputStream(ENTRY_METADATA));
    } catch (IOException e) {
      // Give up because the cache cannot be read.
      return null;
    }

    if (!entry.matches(
        data.request.getUri(),
        data.request.getMethod(),
        data.request.getHeaders().getHeaders().toMultimap())) {
      snapshot.close();
      return null;
    }

    ResponseSource responseSource = ResponseSource.NETWORK;

    CacheResponse candidate =
        entry.isHttps()
            ? new EntrySecureCacheResponse(entry, snapshot)
            : new EntryCacheResponse(entry, snapshot);

    Map<String, List<String>> responseHeadersMap;
    InputStream cachedResponseBody;
    try {
      responseHeadersMap = candidate.getHeaders();
      cachedResponseBody = candidate.getBody();
    } catch (Exception e) {
      return null;
    }
    if (responseHeadersMap == null || cachedResponseBody == null) {
      try {
        cachedResponseBody.close();
      } catch (Exception e) {
      }
      return null;
    }

    RawHeaders rawResponseHeaders = RawHeaders.fromMultimap(responseHeadersMap);
    ResponseHeaders cachedResponseHeaders =
        new ResponseHeaders(data.request.getUri(), rawResponseHeaders);

    long now = System.currentTimeMillis();
    responseSource = cachedResponseHeaders.chooseResponseSource(now, data.request.getHeaders());

    if (responseSource == ResponseSource.CACHE) {
      cacheStoreCount++;
      final CachedSocket socket =
          entry.isHttps()
              ? new CachedSSLSocket((EntrySecureCacheResponse) candidate)
              : new CachedSocket((EntryCacheResponse) candidate);

      client
          .getServer()
          .post(
              new Runnable() {
                @Override
                public void run() {
                  data.connectCallback.onConnectCompleted(null, socket);
                  socket.spewInternal();
                }
              });
    } else if (responseSource == ResponseSource.CONDITIONAL_CACHE) {
      CacheData cacheData = new CacheData();
      cacheData.cachedResponseHeaders = cachedResponseHeaders;
      cacheData.candidate = candidate;
      data.state.putParcelable("cache-data", cacheData);

      return null;
    } else {
      // NETWORK or other
      try {
        cachedResponseBody.close();
      } catch (Exception e) {
      }
      return null;
    }

    return new SimpleCancelable();
  }
 protected AsyncHttpRequestBody onUnknownBody(RawHeaders headers) {
   return new UnknownRequestBody(headers.get("Content-Type"));
 }
Beispiel #11
0
 @Override
 public AsyncHttpRequest createAsyncHttpRequest(
     URI uri, String method, RawHeaders headers) {
   if (!TextUtils.isEmpty(userAgent)) headers.set("User-Agent", userAgent);
   return new AsyncHttpRequest(uri, method, headers);
 }