/** * @file recursivedescent.cc * @brief Implementation of a recursive descent IMAP command parser. * @author Andreas Aardal Hanssen * @date 2002-2005 */ #include "recursivedescent.h" #include "convert.h" #include "imapparser.h" #include "iodevice.h" #include "iofactory.h" #include "session.h" #include #include #include #include #include using namespace Binc; using std::string; std::stack 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(std::vector &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() { Operator::ParseResult res; if ((res = expectCR()) == Operator::ACCEPT && (res = expectLF()) == Operator::ACCEPT) return Operator::ACCEPT; else return res; } Operator::ParseResult Binc::expectCR() { 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() { 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() { 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." << std::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; }