use of com.zimbra.cs.mailclient.MailInputStream in project zm-mailbox by Zimbra.
the class ImapProxy method proxyCommand.
private boolean proxyCommand(byte[] payload, boolean includeTaggedResponse, boolean isIdle) throws ImapProxyException {
ImapConnection conn = writeRequest(payload);
MailInputStream min = conn.getInputStream();
OutputStream out = handler.output;
if (out == null) {
dropConnection();
throw new ImapProxyException("client connection already closed");
}
// copy the response back to the handler's output (i.e. the original client)
boolean success = false;
int first;
try {
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;
boolean escaped = false;
boolean space1 = false;
boolean space2 = false;
int c;
int 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 ("BYE".equals(code)) {
// unexpected BYE
dropConnection();
throw new ImapProxyException("proxy connection already closed");
}
if (tagged) {
success = "OK".equals(code) || (isIdle && "BAD".equals(code));
}
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();
} catch (ImapProxyException e) {
throw e;
} catch (IOException e) {
throw new ImapProxyException(e);
}
return success;
}
Aggregations