summaryrefslogtreecommitdiff
path: root/src/recursivedescent.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/recursivedescent.cc')
-rw-r--r--src/recursivedescent.cc1055
1 files changed, 1055 insertions, 0 deletions
diff --git a/src/recursivedescent.cc b/src/recursivedescent.cc
new file mode 100644
index 0000000..be9c560
--- /dev/null
+++ b/src/recursivedescent.cc
@@ -0,0 +1,1055 @@
+/** --------------------------------------------------------------------
+ * @file recursivedescent.cc
+ * @brief Implementation of a recursive descent IMAP command parser.
+ * @author Andreas Aardal Hanssen
+ * @date 2002-2005
+ * ----------------------------------------------------------------- **/
+#include "imapparser.h"
+#include "recursivedescent.h"
+#include "iodevice.h"
+#include "iofactory.h"
+#include "convert.h"
+#include "session.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stack>
+#include <iostream>
+#include <iomanip>
+
+using namespace ::std;
+using namespace Binc;
+
+stack<int> Binc::inputBuffer;
+int Binc::charnr = 0;
+
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectThisString(const string &s_in)
+{
+ Session &session = Session::getInstance();
+
+ string tmp;
+
+ bool match = true;
+ for (string::const_iterator i = s_in.begin(); i != s_in.end(); ++i) {
+
+ char c;
+ if (!bincClient.readChar(&c)) {
+ session.setLastError(bincClient.getLastErrorString());
+
+ if (bincClient.getLastError() == IODevice::Timeout) return Operator::TIMEOUT;
+ return Operator::ERROR;
+ }
+
+ tmp += c;
+
+ if (toupper(*i) != toupper(c)) {
+ match = false;
+ break;
+ }
+ }
+
+ if (!match) {
+ bincClient.unreadStr(tmp);
+ return Operator::REJECT;
+ } else
+ return Operator::ACCEPT;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectDateTime(string &s_in)
+{
+ Session &session = Session::getInstance();
+
+ if (expectThisString("\"") != Operator::ACCEPT)
+ return Operator::REJECT;
+
+ unsigned int digit1, digit2;
+ if (expectSPACE() == Operator::ACCEPT) {
+ digit1 = 0;
+ Operator::ParseResult res;
+ if ((res = expectDigit(digit2)) != Operator::ACCEPT) {
+ session.setLastError("expected digit (day) after \" and a SPACE.");
+ return res;
+ }
+ } else {
+ Operator::ParseResult res;
+ if ((res = expectDigit(digit1)) != Operator::ACCEPT) {
+ session.setLastError("expected first digit of day");
+ return res;
+ }
+ if ((res = expectDigit(digit2)) != Operator::ACCEPT) {
+ session.setLastError("expected second digit of day");
+ return res;
+ }
+ }
+
+ int day = digit1 * 10 + digit2;
+
+ BincStream daystr;
+
+ if (day < 10)
+ daystr << '0';
+ daystr << day;
+
+ s_in += daystr.str();
+
+ Operator::ParseResult res;
+ if ((res = expectThisString("-")) != Operator::ACCEPT) {
+ session.setLastError("expected -");
+ return res;
+ }
+
+ s_in += "-";
+
+ /* month */
+ if ((res = expectThisString("Jan")) == Operator::ACCEPT) s_in += "Jan";
+ else if ((res = expectThisString("Feb")) == Operator::ACCEPT) s_in += "Feb";
+ else if ((res = expectThisString("Mar")) == Operator::ACCEPT) s_in += "Mar";
+ else if ((res = expectThisString("Apr")) == Operator::ACCEPT) s_in += "Apr";
+ else if ((res = expectThisString("May")) == Operator::ACCEPT) s_in += "May";
+ else if ((res = expectThisString("Jun")) == Operator::ACCEPT) s_in += "Jun";
+ else if ((res = expectThisString("Jul")) == Operator::ACCEPT) s_in += "Jul";
+ else if ((res = expectThisString("Aug")) == Operator::ACCEPT) s_in += "Aug";
+ else if ((res = expectThisString("Sep")) == Operator::ACCEPT) s_in += "Sep";
+ else if ((res = expectThisString("Oct")) == Operator::ACCEPT) s_in += "Oct";
+ else if ((res = expectThisString("Nov")) == Operator::ACCEPT) s_in += "Nov";
+ else if ((res = expectThisString("Dec")) == Operator::ACCEPT) s_in += "Dec";
+ else {
+ session.setLastError("expected month");
+ return res;
+ }
+
+ if ((res = expectThisString("-")) != Operator::ACCEPT) {
+ session.setLastError("expected -");
+ return res;
+ }
+
+ s_in += "-";
+
+ /* year */
+ unsigned int year, c;
+ if ((res = expectDigit(year)) != Operator::ACCEPT) {
+ session.setLastError("expected digit (first digit of year)");
+ return res;
+ }
+
+ if ((res = expectDigit(c)) != Operator::ACCEPT) {
+ session.setLastError("expected digit (second digit of year)");
+ return res;
+ }
+
+ year = (year * 10) + c;
+
+ if ((res = expectDigit(c)) != Operator::ACCEPT) {
+ session.setLastError("expected digit (third digit of year)");
+ return res;
+ }
+
+ year = (year * 10) + c;
+
+ if ((res = expectDigit(c)) != Operator::ACCEPT) {
+ session.setLastError("expected digit (last digit of year)");
+ return res;
+ }
+
+ year = (year * 10) + c;
+
+ BincStream yearstr;
+
+ yearstr << year;
+
+ s_in += yearstr.str();
+
+ if ((res = expectSPACE()) != Operator::ACCEPT) {
+ session.setLastError("expected SPACE");
+ return res;
+ }
+
+ s_in += " ";
+
+ if ((res = expectTime(s_in)) != Operator::ACCEPT) {
+ session.setLastError("expected time");
+ return res;
+ }
+
+ if ((res = expectSPACE()) != Operator::ACCEPT) {
+ session.setLastError("expected SPACE");
+ return res;
+ }
+
+ s_in += " ";
+
+ if ((res = expectZone(s_in)) != Operator::ACCEPT) {
+ session.setLastError("expected zone");
+ return res;
+ }
+
+ if ((res = expectThisString("\"")) != Operator::ACCEPT) {
+ session.setLastError("expected \"");
+ return res;
+ }
+
+ return Operator::ACCEPT;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectTime(string &s_in)
+{
+ Session &session = Session::getInstance();
+
+ unsigned int c, t;
+ Operator::ParseResult res;
+ if ((res = expectDigit(t)) != Operator::ACCEPT)
+ return res;
+
+ if ((res = expectDigit(c)) != Operator::ACCEPT) {
+ session.setLastError("expected digit");
+ return res;
+ }
+
+ t = (t * 10) + c;
+
+ BincStream tstr;
+
+ tstr << t;
+
+ s_in += tstr.str();
+
+ if ((res = expectThisString(":")) != Operator::ACCEPT) {
+ session.setLastError("expected colon");
+ return res;
+ }
+
+ s_in += ":";
+
+ if ((res = expectDigit(t)) != Operator::ACCEPT) {
+ session.setLastError("expected digit");
+ return res;
+ }
+
+ if ((res = expectDigit(c)) != Operator::ACCEPT) {
+ session.setLastError("expected digit");
+ return res;
+ }
+
+ t = (t * 10) + c;
+
+ tstr.clear();
+
+ tstr << t;
+
+ s_in += tstr.str();
+
+ if ((res = expectThisString(":")) != Operator::ACCEPT) {
+ session.setLastError("expected colon");
+ return res;
+ }
+
+ s_in += ":";
+
+ if ((res = expectDigit(t)) != Operator::ACCEPT) {
+ session.setLastError("expected digit");
+ return res;
+ }
+
+ if ((res = expectDigit(c)) != Operator::ACCEPT) {
+ session.setLastError("expected digit");
+ return res;
+ }
+
+ t = (t * 10) + c;
+
+ tstr.clear();
+
+ tstr << t;
+
+ s_in += tstr.str();
+
+ return Operator::ACCEPT;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectZone(string &s_in)
+{
+ Session &session = Session::getInstance();
+
+ Operator::ParseResult res;
+ if ((res = expectThisString("-")) == Operator::ACCEPT)
+ s_in += "-";
+ else if ((res = expectThisString("+")) == Operator::ACCEPT)
+ s_in += "+";
+ else
+ return res;
+
+ unsigned int c, t;
+ if ((res = expectDigit(t)) != Operator::ACCEPT) {
+ session.setLastError("expected digit");
+ return res;
+ }
+
+ if ((res = expectDigit(c)) != Operator::ACCEPT) {
+ session.setLastError("expected digit");
+ return res;
+ }
+
+ t = (t * 10) + c;
+
+ if ((res = expectDigit(c)) != Operator::ACCEPT) {
+ session.setLastError("expected digit");
+ return res;
+ }
+
+ t = (t * 10) + c;
+
+ if ((res = expectDigit(c)) != Operator::ACCEPT) {
+ session.setLastError("expected digit");
+ return res;
+ }
+
+ t = (t * 10) + c;
+
+ BincStream tstr;
+
+ tstr << t;
+
+ s_in += tstr.str();
+
+ return Operator::ACCEPT;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectListWildcards(int &c_in)
+{
+ Operator::ParseResult res;
+ if ((res = expectThisString("%")) == Operator::ACCEPT) {
+ c_in = '%';
+ return Operator::ACCEPT;
+ } else if ((res = expectThisString("*")) == Operator::ACCEPT) {
+ c_in = '*';
+ return Operator::ACCEPT;
+ } else
+ return res;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectListMailbox(string &s_in)
+{
+ Operator::ParseResult res;
+ if ((res = expectString(s_in)) == Operator::ACCEPT)
+ return Operator::ACCEPT;
+
+ int c;
+ if ((res = expectAtomChar(c)) == Operator::ACCEPT
+ || (res = expectListWildcards(c)) == Operator::ACCEPT
+ || (res = expectThisString("]")) == Operator::ACCEPT) {
+ do {
+ s_in += (char) c;
+ if ((res = expectAtomChar(c)) != Operator::ACCEPT
+ && (res = expectListWildcards(c)) != Operator::ACCEPT
+ && (res = expectThisString("]")) != Operator::ACCEPT)
+ return Operator::ACCEPT;
+ } while (1);
+ }
+
+ bincClient.unreadStr(s_in);
+
+ return res;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectFlag(vector<string> &v_in)
+{
+ Session &session = Session::getInstance();
+
+ Operator::ParseResult res;
+ string flag;
+ if ((res = expectThisString("\\Answered")) == Operator::ACCEPT)
+ v_in.push_back("\\Answered");
+ else if ((res = expectThisString("\\Flagged")) == Operator::ACCEPT)
+ v_in.push_back("\\Flagged");
+ else if ((res = expectThisString("\\Deleted")) == Operator::ACCEPT)
+ v_in.push_back("\\Deleted");
+ else if ((res = expectThisString("\\Seen")) == Operator::ACCEPT)
+ v_in.push_back("\\Seen");
+ else if ((res = expectThisString("\\Draft")) == Operator::ACCEPT)
+ v_in.push_back("\\Draft");
+ else if ((res = expectThisString("\\Answered")) == Operator::ACCEPT)
+ v_in.push_back("\\Answered");
+ else {
+ if ((res = expectThisString("\\")) == Operator::ACCEPT) {
+ if ((res = expectAtom(flag)) == Operator::ACCEPT)
+ v_in.push_back("\\" + flag);
+ else {
+ session.setLastError("expected atom");
+ return res;
+ }
+
+ } else if (expectAtom(flag) == Operator::ACCEPT) {
+ v_in.push_back(flag);
+ } else
+ return res;
+ }
+
+ return Operator::ACCEPT;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectDate(string &s_in)
+{
+ Session &session = Session::getInstance();
+
+ Operator::ParseResult res;
+ bool quoted = false;
+ if ((res = expectThisString("\"")) == Operator::ACCEPT)
+ quoted = true;
+
+ /* day */
+ unsigned int day, c;
+ if ((res = expectDigit(c)) == Operator::ACCEPT) {
+ day = c;
+ if ((res = expectDigit(c)) == Operator::ACCEPT)
+ day = (day * 10) + c;
+
+ BincStream daystr;
+
+ daystr << day;
+
+ s_in += daystr.str();
+ } else {
+ session.setLastError("expected digit");
+ return res;
+ }
+
+ /* - */
+ if ((res = expectThisString("-")) != Operator::ACCEPT) {
+ session.setLastError("expected -");
+ return res;
+ }
+
+ s_in += '-';
+
+ /* month */
+ if ((res = expectThisString("Jan")) == Operator::ACCEPT) s_in += "Jan";
+ else if ((res = expectThisString("Feb")) == Operator::ACCEPT) s_in += "Feb";
+ else if ((res = expectThisString("Mar")) == Operator::ACCEPT) s_in += "Mar";
+ else if ((res = expectThisString("Apr")) == Operator::ACCEPT) s_in += "Apr";
+ else if ((res = expectThisString("May")) == Operator::ACCEPT) s_in += "May";
+ else if ((res = expectThisString("Jun")) == Operator::ACCEPT) s_in += "Jun";
+ else if ((res = expectThisString("Jul")) == Operator::ACCEPT) s_in += "Jul";
+ else if ((res = expectThisString("Aug")) == Operator::ACCEPT) s_in += "Aug";
+ else if ((res = expectThisString("Sep")) == Operator::ACCEPT) s_in += "Sep";
+ else if ((res = expectThisString("Oct")) == Operator::ACCEPT) s_in += "Oct";
+ else if ((res = expectThisString("Nov")) == Operator::ACCEPT) s_in += "Nov";
+ else if ((res = expectThisString("Dec")) == Operator::ACCEPT) s_in += "Dec";
+ else {
+ session.setLastError("expected month");
+ return res;
+ }
+
+ /* - */
+ if ((res = expectThisString("-")) != Operator::ACCEPT) {
+ session.setLastError("expected -");
+ return res;
+ }
+
+ s_in += '-';
+
+ /* year */
+ unsigned int year;
+ if ((res = expectDigit(year)) != Operator::ACCEPT) {
+ session.setLastError("expected digit");
+ return res;
+ }
+
+ if ((res = expectDigit(c)) != Operator::ACCEPT) {
+ session.setLastError("expected digit");
+ return res;
+ }
+
+ year = (year * 10) + c;
+
+ if ((res = expectDigit(c)) != Operator::ACCEPT) {
+ session.setLastError("expected digit");
+ return res;
+ }
+
+ year = (year * 10) + c;
+
+ if ((res = expectDigit(c)) != Operator::ACCEPT) {
+ session.setLastError("expected digit");
+ return res;
+ }
+
+ year = (year * 10) + c;
+
+ BincStream yearstr;
+
+ yearstr << year;
+
+ s_in += yearstr.str();
+
+ if (quoted)
+ if ((res = expectThisString("\"")) != Operator::ACCEPT) {
+ session.setLastError("expected \"");
+ return res;
+ }
+
+ return Operator::ACCEPT;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectCRLF(void)
+{
+ Operator::ParseResult res;
+ if ((res = expectCR()) == Operator::ACCEPT
+ && (res = expectLF()) == Operator::ACCEPT)
+ return Operator::ACCEPT;
+ else
+ return res;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectCR(void)
+{
+ Session &session = Session::getInstance();
+
+ char c;
+ if (!bincClient.readChar(&c)) {
+ session.setLastError(bincClient.getLastErrorString());
+
+ if (bincClient.getLastError() == IODevice::Timeout)
+ return Operator::TIMEOUT;
+ return Operator::ERROR;
+ }
+
+ if (c == 0x0d)
+ return Operator::ACCEPT;
+ else {
+ bincClient.unreadChar(c);
+ return Operator::REJECT;
+ }
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectLF(void)
+{
+ Session &session = Session::getInstance();
+
+ char c;
+ if (!bincClient.readChar(&c)) {
+ session.setLastError(bincClient.getLastErrorString());
+
+ if (bincClient.getLastError() == IODevice::Timeout)
+ return Operator::TIMEOUT;
+ return Operator::ERROR;
+ }
+
+ if (c == 0x0a)
+ return Operator::ACCEPT;
+ else {
+ bincClient.unreadChar(c);
+ return Operator::REJECT;
+ }
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectTagChar(int &c_in)
+{
+ Session &session = Session::getInstance();
+
+ char c;
+ if (!bincClient.readChar(&c)) {
+ session.setLastError(bincClient.getLastErrorString());
+
+ if (bincClient.getLastError() == IODevice::Timeout)
+ return Operator::TIMEOUT;
+ return Operator::ERROR;
+ }
+
+ switch (c) {
+ case 041: case 043: case 044: case 046: case 047: case 054:
+ case 055: case 056: case 057: case 060: case 061: case 062:
+ case 063: case 064: case 065: case 066: case 067: case 070:
+ case 071: case 072: case 073: case 074: case 075: case 076:
+ case 077: case 0100: case 0101: case 0102: case 0103: case 0104:
+ case 0105: case 0106: case 0107: case 0110: case 0111: case 0112:
+ case 0113: case 0114: case 0115: case 0116: case 0117: case 0120:
+ case 0121: case 0122: case 0123: case 0124: case 0125: case 0126:
+ case 0127: case 0130: case 0131: case 0132: case 0133: case 0135:
+ case 0136: case 0137: case 0140: case 0141: case 0142: case 0143:
+ case 0144: case 0145: case 0146: case 0147: case 0150: case 0151:
+ case 0152: case 0153: case 0154: case 0155: case 0156: case 0157:
+ case 0160: case 0161: case 0162: case 0163: case 0164: case 0165:
+ case 0166: case 0167: case 0170: case 0171: case 0172: case 0174:
+ case 0175: case 0176:
+ c_in = c;
+ return Operator::ACCEPT;
+ default:
+ break;
+ }
+
+ bincClient.unreadChar(c);
+
+ return Operator::REJECT;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectTag(string &s_in)
+{
+ string tag;
+ int tagchar;
+
+ int eres = expectTagChar(tagchar);
+ if (eres == Operator::REJECT)
+ return Operator::REJECT;
+ else if (eres == Operator::ERROR)
+ return Operator::ERROR;
+ else if (eres == Operator::TIMEOUT)
+ return Operator::TIMEOUT;
+ else {
+ tag += tagchar;
+
+ bool done = false;
+
+ while (!done) {
+ switch (expectTagChar(tagchar)) {
+ case Operator::ACCEPT:
+ tag += tagchar;
+ break;
+ case Operator::REJECT:
+ done = true;
+ break;
+ case Operator::ERROR:
+ return Operator::ERROR;
+ case Operator::TIMEOUT:
+ return Operator::TIMEOUT;
+ }
+ }
+ }
+
+ s_in = tag;
+
+ return Operator::ACCEPT;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectSPACE(void)
+{
+ Session &session = Session::getInstance();
+
+ char c;
+ if (!bincClient.readChar(&c)) {
+ session.setLastError(bincClient.getLastErrorString());
+
+ if (bincClient.getLastError() == IODevice::Timeout)
+ return Operator::TIMEOUT;
+ return Operator::ERROR;
+ }
+
+ if (c == ' ')
+ return Operator::ACCEPT;
+ else {
+ bincClient.unreadChar(c);
+ return Operator::REJECT;
+ }
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectMailbox(string &s_in)
+{
+ return expectAstring(s_in);
+}
+
+//----------------------------------------------------------------------
+// FIXME: This rule is wrong.
+Operator::ParseResult Binc::expectAstring(string &s_in)
+{
+ Operator::ParseResult res;
+ if ((res = expectAtom(s_in)) == Operator::ACCEPT)
+ return Operator::ACCEPT;
+
+ if ((res = expectString(s_in)) == Operator::ACCEPT)
+ return Operator::ACCEPT;
+
+ return res;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectAtomChar(int &c_in)
+{
+ Session &session = Session::getInstance();
+
+ char c;
+ if (!bincClient.readChar(&c)) {
+ session.setLastError(bincClient.getLastErrorString());
+
+ if (bincClient.getLastError() == IODevice::Timeout)
+ return Operator::TIMEOUT;
+ return Operator::ERROR;
+ }
+
+ switch (c) {
+ case 041: case 043: case 044: case 046: case 047: case 053:
+ case 054: case 055: case 056: case 057: case 060: case 061:
+ case 062: case 063: case 064: case 065: case 066: case 067:
+ case 070: case 071: case 072: case 073: case 074: case 075:
+ case 076: case 077: case 0100: case 0101: case 0102: case 0103:
+ case 0104: case 0105: case 0106: case 0107: case 0110: case 0111:
+ case 0112: case 0113: case 0114: case 0115: case 0116: case 0117:
+ case 0120: case 0121: case 0122: case 0123: case 0124: case 0125:
+ case 0126: case 0127: case 0130: case 0131: case 0132: case 0133:
+ case 0135: case 0136: case 0137: case 0140: case 0141: case 0142:
+ case 0143: case 0144: case 0145: case 0146: case 0147: case 0150:
+ case 0151: case 0152: case 0153: case 0154: case 0155: case 0156:
+ case 0157: case 0160: case 0161: case 0162: case 0163: case 0164:
+ case 0165: case 0166: case 0167: case 0170: case 0171: case 0172:
+ case 0174: case 0175: case 0176:
+ c_in = c;
+ return Operator::ACCEPT;
+ default:
+ break;
+ }
+
+ bincClient.unreadChar(c);
+ return Operator::REJECT;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectAtom(string &s_in)
+{
+ string atom;
+ int atomchar;
+
+ Operator::ParseResult res;
+ while ((res = expectAtomChar(atomchar)) == Operator::ACCEPT)
+ atom += atomchar;
+
+ if (atom == "") {
+ bincClient.unreadStr(atom);
+ return res;
+ } else
+ s_in = atom;
+
+ return Operator::ACCEPT;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectString(string &s_in)
+{
+ Operator::ParseResult res;
+ if ((res = expectQuoted(s_in)) == Operator::ACCEPT)
+ return Operator::ACCEPT;
+
+ if ((res = expectLiteral(s_in)) == Operator::ACCEPT)
+ return Operator::ACCEPT;
+
+ return res;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectQuoted(string &s_in)
+{
+ string quoted;
+ int quotedchar;
+ Operator::ParseResult res;
+
+ if ((res = expectThisString("\"")) != Operator::ACCEPT)
+ return res;
+
+ while ((res = expectQuotedChar(quotedchar)) == Operator::ACCEPT)
+ quoted += quotedchar;
+
+ if ((res = expectThisString("\"")) != Operator::ACCEPT) {
+ bincClient.unreadStr("\"" + quoted);
+ return res;
+ }
+
+ s_in = quoted;
+ return Operator::ACCEPT;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectQuotedChar(int &c_in)
+{
+ Session &session = Session::getInstance();
+
+ char c;
+ if (!bincClient.readChar(&c)) {
+ session.setLastError(bincClient.getLastErrorString());
+
+ if (bincClient.getLastError() == IODevice::Timeout)
+ return Operator::TIMEOUT;
+ return Operator::ERROR;
+ }
+
+ switch (c) {
+ case 01: case 02: case 03: case 04: case 05: case 06: case 07:
+ case 010: case 011: case 013: case 014: case 016: case 017:
+ case 020: case 021: case 022: case 023: case 024: case 025: case 026: case 027:
+ case 030: case 031: case 032: case 033: case 034: case 035: case 036: case 037:
+ case 040: case 041: case 043: case 044: case 045: case 046: case 047:
+ case 050: case 051: case 052: case 053: case 054: case 055: case 056: case 057:
+ case 060: case 061: case 062: case 063: case 064: case 065: case 066: case 067:
+ case 070: case 071: case 072: case 073: case 074: case 075: case 076: case 077:
+ case 0100: case 0101: case 0102: case 0103: case 0104: case 0105: case 0106: case 0107:
+ case 0110: case 0111: case 0112: case 0113: case 0114: case 0115: case 0116: case 0117:
+ case 0120: case 0121: case 0122: case 0123: case 0124: case 0125: case 0126: case 0127:
+ case 0130: case 0131: case 0132: case 0133: case 0135: case 0136: case 0137:
+ case 0140: case 0141: case 0142: case 0143: case 0144: case 0145: case 0146: case 0147:
+ case 0150: case 0151: case 0152: case 0153: case 0154: case 0155: case 0156: case 0157:
+ case 0160: case 0161: case 0162: case 0163: case 0164: case 0165: case 0166: case 0167:
+ case 0170: case 0171: case 0172: case 0173: case 0174: case 0175: case 0176: case 0177:
+ c_in = c;
+ return Operator::ACCEPT;
+ case '\\': {
+ char d;
+ if (!bincClient.readChar(&d)) {
+ session.setLastError(bincClient.getLastErrorString());
+
+ if (bincClient.getLastError() == IODevice::Timeout) return Operator::TIMEOUT;
+ return Operator::ERROR;
+ }
+
+ if (d == '\"' || d == '\\') {
+ c_in = d;
+ return Operator::ACCEPT;
+ } else {
+ bincClient.unreadChar(d);
+ bincClient.unreadChar(c);
+ return Operator::REJECT;
+ }
+ }
+ default:
+ break;
+ }
+
+ bincClient.unreadChar(c);
+ return Operator::REJECT;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectLiteral(string &s_in)
+{
+ Session &session = Session::getInstance();
+
+ string literal;
+ Operator::ParseResult res;
+
+ if ((res = expectThisString("{")) != Operator::ACCEPT) return res;
+
+ unsigned int nchar;
+
+ if ((res = expectNumber(nchar)) != Operator::ACCEPT) {
+ session.setLastError("expected number");
+ return res;
+ }
+
+ // rfc2088 describes the non-synchronizing literal, or LITERAL+, as
+ // sent by the client with an extra '+' appended after the octet
+ // count.
+ bool literalPlus = false;
+ if ((res = expectThisString("+")) == Operator::ACCEPT)
+ literalPlus = true;
+
+ if ((res = expectThisString("}")) != Operator::ACCEPT) {
+ session.setLastError("expected }");
+ return res;
+ }
+
+ if ((res = expectCRLF()) != Operator::ACCEPT) {
+ session.setLastError("expected CRLF");
+ return Operator::ERROR;
+ }
+
+ // Only send the reply if the client did not send a LITERAL+
+ // request.
+ if (!literalPlus) {
+ bincClient << "+ ok, send " << nchar << " bytes of data." << endl;
+ bincClient.flush();
+ }
+
+ for (unsigned int i = 0; i < nchar; ++i) {
+ char c;
+ if (!bincClient.readChar(&c)) {
+ session.setLastError(bincClient.getLastErrorString());
+ if (bincClient.getLastError() == IODevice::Timeout) return Operator::TIMEOUT;
+ return Operator::ERROR;
+ }
+
+ literal += c;
+ }
+
+ s_in = literal;
+
+ return Operator::ACCEPT;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectNumber(unsigned int &i_in)
+{
+ i_in = 0;
+ unsigned int n;
+ Operator::ParseResult res;
+
+ while ((res = expectDigit(n)) == Operator::ACCEPT) {
+ if (i_in == 0)
+ i_in = n;
+ else
+ i_in = (i_in * 10) + n;
+ }
+
+ if (res == Operator::TIMEOUT)
+ return res;
+
+ return Operator::ACCEPT;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectDigit(unsigned int &i_in)
+{
+ Session &session = Session::getInstance();
+
+ char c;
+ if (!bincClient.readChar(&c)) {
+ session.setLastError(bincClient.getLastErrorString());
+
+ if (bincClient.getLastError() == IODevice::Timeout)
+ return Operator::TIMEOUT;
+ return Operator::ERROR;
+ }
+
+ if (c == '0') {
+ i_in = 0;
+ return Operator::ACCEPT;
+ } else
+ bincClient.unreadChar(c);
+
+ if (expectDigitNZ(i_in) != Operator::ACCEPT)
+ return Operator::REJECT;
+
+ return Operator::ACCEPT;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectDigitNZ(unsigned int &i_in)
+{
+ Session &session = Session::getInstance();
+
+ char c;
+ if (!bincClient.readChar(&c)) {
+ session.setLastError(bincClient.getLastErrorString());
+
+ if (bincClient.getLastError() == IODevice::Timeout)
+ return Operator::TIMEOUT;
+ return Operator::ERROR;
+ }
+
+ switch (c) {
+ case '1': i_in = 1; break;
+ case '2': i_in = 2; break;
+ case '3': i_in = 3; break;
+ case '4': i_in = 4; break;
+ case '5': i_in = 5; break;
+ case '6': i_in = 6; break;
+ case '7': i_in = 7; break;
+ case '8': i_in = 8; break;
+ case '9': i_in = 9; break;
+ case -1:
+ session.setLastError(bincClient.getLastErrorString());
+ return Operator::ERROR;
+ case -2:
+ return Operator::TIMEOUT;
+ default:
+ bincClient.unreadChar(c);
+ return Operator::REJECT;
+ }
+
+ return Operator::ACCEPT;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectSet(SequenceSet &s_in)
+{
+ Session &session = Session::getInstance();
+ unsigned int seqnum = (unsigned int) -1;
+
+ Operator::ParseResult res;
+
+ /* if a set does not start with a sequencenum, then it's not a
+ * set. :-) seqnum == -1 means '*'. */
+ if ((res = expectSequenceNum(seqnum)) != Operator::ACCEPT)
+ return res;
+
+ /* the first number is always a part of the set */
+ s_in.addNumber(seqnum);
+
+ /* if _after_ a set there is a ':', then there will always be a
+ * sequencenum after the colon. if not, it's a syntax error. a
+ * colon delimits two numbers in a range. */
+ if ((res = expectThisString(":")) == Operator::ACCEPT) {
+ unsigned int seqnum2 = (unsigned int) -1;
+ if ((res = expectSequenceNum(seqnum2)) != Operator::ACCEPT) {
+ session.setLastError("expected sequencenum");
+ return res;
+ }
+
+ s_in.addRange(seqnum, seqnum2);
+ }
+
+ /* if _after_ a set there is a ',', then there will always be
+ * a set after the comma. if not, it's a syntax error. */
+ if ((res = expectThisString(",")) == Operator::ACCEPT)
+ if ((res = expectSet(s_in)) != Operator::ACCEPT) {
+ session.setLastError("expected set");
+ return res;
+ }
+
+ return Operator::ACCEPT;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectSequenceNum(unsigned int &i_in)
+{
+ Session &session = Session::getInstance();
+
+ char c;
+ if (!bincClient.readChar(&c)) {
+ session.setLastError(bincClient.getLastErrorString());
+
+ if (bincClient.getLastError() == IODevice::Timeout)
+ return Operator::TIMEOUT;
+ return Operator::ERROR;
+ }
+
+ if (c == '*') {
+ i_in = (unsigned int) -1;
+ return Operator::ACCEPT;
+ } else
+ bincClient.unreadChar(c);
+
+ if (expectNZNumber(i_in) != Operator::ACCEPT)
+ return Operator::REJECT;
+ else
+ return Operator::ACCEPT;
+}
+
+//----------------------------------------------------------------------
+Operator::ParseResult Binc::expectNZNumber(unsigned int &i_in)
+{
+ unsigned int c;
+ Operator::ParseResult res;
+
+ if ((res = expectDigitNZ(c)) != Operator::ACCEPT)
+ return res;
+
+ i_in = c;
+ while ((res = expectDigit(c)) == Operator::ACCEPT)
+ i_in = (i_in * 10) + c;
+
+ if (res == Operator::TIMEOUT)
+ return res;
+
+ return Operator::ACCEPT;
+}