Beispiel #1
0
  boolean proxyCommand(
      final String tag,
      final byte[] payload,
      final boolean includeTaggedResponse,
      final boolean isIdle)
      throws IOException {
    //        System.out.write(payload);  System.out.flush();
    ImapConnection conn = writeRequest(payload);

    MailInputStream min = conn.getInputStream();
    OutputStream out = mHandler.mOutputStream;
    if (out == null) {
      dropConnection();
      throw new IOException("proxy connection already closed");
    }

    // copy the response back to the handler's output (i.e. the original client)
    boolean success = false;
    int first;
    while ((first = min.peek()) != -1) {
      // XXX: may want to check that the "tagged" response's tag actually matches the request's
      // tag...
      boolean tagged = first != '*' && first != '+';
      boolean structured = first == '*';
      boolean proxy = (first != '+' || isIdle) && (!tagged || includeTaggedResponse);

      ByteArrayOutputStream line = proxy ? new ByteArrayOutputStream() : null;
      StringBuilder debug =
          proxy && ZimbraLog.imap.isDebugEnabled() ? new StringBuilder("  pxy: ") : null;
      StringBuilder condition = new StringBuilder(10);

      boolean quoted = false, escaped = false, space1 = false, space2 = false;
      int c, literal = -1;
      while ((c = min.read()) != -1) {
        // check for success and also determine whether we should be paying attention to structure
        if (!space2) {
          if (c == ' ' && !space1) {
            space1 = true;
          } else if (c == ' ') {
            space2 = true;
            String code = condition.toString().toUpperCase();
            if (tagged) success = code.equals("OK") || (isIdle && code.equals("BAD"));
            structured &= !UNSTRUCTURED_CODES.contains(code);
          } else if (space1) {
            condition.append((char) c);
          }
        }

        // if it's a structured response, pay attention to quoting, literals, etc.
        if (structured) {
          if (escaped) escaped = false;
          else if (quoted && c == '\\') escaped = true;
          else if (c == '"') quoted = !quoted;
          else if (!quoted && c == '{') literal = 0;
          else if (literal != -1 && c >= '0' && c <= '9') literal = literal * 10 + (c - '0');
        }

        if (!quoted && c == '\r' && min.peek() == '\n') {
          // skip the terminal LF
          min.read();
          // write the line back to the client
          if (proxy) {
            out.write(line.toByteArray());
            out.write(ImapHandler.LINE_SEPARATOR_BYTES);
            line.reset();
            if (isIdle) out.flush();
          }
          // if it's end of line (i.e. no literal), we're done
          if (literal == -1) break;
          // if there's a literal, copy it and then handle the following line
          byte buffer[] = literal == 0 ? null : new byte[Math.min(literal, 65536)];
          while (literal > 0) {
            int read = min.read(buffer, 0, Math.min(literal, buffer.length));
            if (read == -1) break;
            if (proxy) out.write(buffer, 0, read);
            literal -= read;
          }
          literal = -1;
          if (isIdle) out.flush();
        } else if (proxy) {
          line.write(c);
          if (debug != null) debug.append((char) c);
        }
      }

      if (debug != null) ZimbraLog.imap.debug(debug.toString());

      if (tagged) break;
    }

    out.flush();
    return success;
  }