diff options
Diffstat (limited to 'src/recursivedescent.cc')
-rw-r--r-- | src/recursivedescent.cc | 1055 |
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; +} |