int timlex(mystring_t **outstr, unsigned long *outnum, struct protstream *stream) { int ch; char *buff_ptr; char *buff_end; unsigned long tmpnum = 0; unsigned long count=0; int result = TIMSIEVE_OK; buff_ptr = buffer; /* ptr into the buffer */ buff_end = buffer + maxscriptsize - 10; /* ptr to end of buffer */ while (1) { /* get a character this may block on a read if there is nothing in the buffer */ ch=prot_getc(stream); if (ch==EOF) { /* Lost connection */ return EOF; } switch (lexer_state) { case LEXER_STATE_RECOVER: if (ch == '\n') { lexer_state=LEXER_STATE_NORMAL; } if (ch == '\r') lexer_state=LEXER_STATE_RECOVER_CR; break; case LEXER_STATE_RECOVER_CR: if (ch == '\n') lexer_state=LEXER_STATE_NORMAL; break; case LEXER_STATE_CR: if (ch == '\n') { lexer_state=LEXER_STATE_NORMAL; return EOL; } /* otherwise, life is bad */ ERR_PUSHBACK(); case LEXER_STATE_QSTR: if (ch == '\"') { /* End of the string */ if (outstr!=NULL) { *outstr = NULL; result = string_allocate(buff_ptr - buffer, buffer, outstr); if (result != TIMSIEVE_OK) ERR_PUSHBACK(); } /*} */ lexer_state=LEXER_STATE_NORMAL; return STRING; } /* illegal character */ if (ch == '\0' || ch == '\r' || ch == '\n' || 0x7F < ((unsigned char)ch)) { ERR_PUSHBACK(); } /* Otherwise, we're appending a character */ if (buff_end <= buff_ptr) ERR_PUSHBACK(); /* too long! */ if (ch == '\\') { ch=prot_getc(stream); if (result != TIMSIEVE_OK) ERR(); if (ch != '\"' && ch != '\\') ERR_PUSHBACK(); } *buff_ptr++ = ch; break; case LEXER_STATE_LITERAL: if (('0' <= ch) && (ch <= '9')) { unsigned long newcount = count * 10 + (ch - '0'); if (newcount < count) ERR_PUSHBACK(); /* overflow */ /* * XXX This should be fatal if non-synchronizing. */ count = newcount; break; } if (ch != '+') ERR_PUSHBACK(); ch=prot_getc(stream); if (ch != '}') ERR_PUSHBACK(); ch=prot_getc(stream); if (ch < 0) ERR(); if (ch != '\r') ERR_PUSHBACK(); ch=prot_getc(stream); if (ch < 0) ERR(); if (ch != '\n') ERR_PUSHBACK(); if (count > maxscriptsize) { /* too big, eat the input */ for(;count > 0;count--) { if(prot_getc(stream)==EOF) break; } ERR(); } if (outstr!=NULL) { *outstr = NULL; result = string_allocate(count, NULL, outstr); if (result != TIMSIEVE_OK) ERR_PUSHBACK(); } /* there is a literal string on the wire. let's read it */ if (outstr!=NULL) { char *it = string_DATAPTR(*outstr), *end = it + count; while (it < end) { *it=prot_getc(stream); it++; } } else { /* just read the chars and throw them away */ unsigned long lup; for (lup=0;lup<count;lup++) (void)prot_getc(stream); } lexer_state=LEXER_STATE_NORMAL; return STRING; case LEXER_STATE_NUMBER: if (Uisdigit(ch)) { unsigned long newcount = tmpnum * 10 + (ch - '0'); if (newcount < tmpnum) ERR_PUSHBACK(); /* overflow */ tmpnum = newcount; } else { lexer_state=LEXER_STATE_NORMAL; prot_ungetc(ch, stream); if (outnum) *outnum = tmpnum; return NUMBER; } break; case LEXER_STATE_NORMAL: if (Uisalpha(ch)) { lexer_state=LEXER_STATE_ATOM; *buff_ptr++ = tolower(ch); break; } if (Uisdigit(ch)) { lexer_state=LEXER_STATE_NUMBER; tmpnum = ch -'0'; break; } switch (ch) { case '(': return '('; case ')': return ')'; case ' ': return ' '; case '\"': lexer_state=LEXER_STATE_QSTR; break; case '*': return '*'; case '{': count = 0; lexer_state=LEXER_STATE_LITERAL; break; case '\r': lexer_state=LEXER_STATE_CR; break; case '\n': lexer_state=LEXER_STATE_NORMAL; return EOL; break; default: return ch; } break; case LEXER_STATE_ATOM: if (!Uisalpha(ch)) { int token; buffer[ buff_ptr - buffer] = '\0'; /* We've got the atom. */ token = token_lookup((char *) buffer, (int) (buff_ptr - buffer)); if (token!=-1) { lexer_state=LEXER_STATE_NORMAL; prot_ungetc(ch, stream); return token; } else ERR_PUSHBACK(); } if (buff_end <= buff_ptr) ERR_PUSHBACK(); /* atom too long */ *buff_ptr++ = tolower(ch); break; } } /* while (1) */ /* never reached */ }
static int parse_rfc822(const char *s, time_t *tp, int dayonly) { const char *origs = s; struct tm tm; time_t t; char month[4]; int zone_off = 0; if (!s) goto baddate; memset(&tm, 0, sizeof(tm)); s = skip_fws(s); if (!s) goto baddate; if (Uisalpha(*s)) { /* Day name -- skip over it */ s++; if (!Uisalpha(*s)) goto baddate; s++; if (!Uisalpha(*s)) goto baddate; s++; s = skip_fws(s); if (!s || *s++ != ',') goto baddate; s = skip_fws(s); if (!s) goto baddate; } if (!Uisdigit(*s)) goto baddate; tm.tm_mday = *s++ - '0'; if (Uisdigit(*s)) { tm.tm_mday = tm.tm_mday*10 + *s++ - '0'; } /* Parse month name */ s = skip_fws(s); if (!s) goto baddate; month[0] = *s++; if (!Uisalpha(month[0])) goto baddate; month[1] = *s++; if (!Uisalpha(month[1])) goto baddate; month[2] = *s++; if (!Uisalpha(month[2])) goto baddate; month[3] = '\0'; for (tm.tm_mon = 0; tm.tm_mon < 12; tm.tm_mon++) { if (!strcasecmp(month, monthname[tm.tm_mon])) break; } if (tm.tm_mon == 12) goto baddate; /* Parse year */ s = skip_fws(s); if (!s || !Uisdigit(*s)) goto baddate; tm.tm_year = *s++ - '0'; if (!Uisdigit(*s)) goto baddate; tm.tm_year = tm.tm_year * 10 + *s++ - '0'; if (Uisdigit(*s)) { if (tm.tm_year < 19) goto baddate; tm.tm_year -= 19; tm.tm_year = tm.tm_year * 10 + *s++ - '0'; if (!Uisdigit(*s)) goto baddate; tm.tm_year = tm.tm_year * 10 + *s++ - '0'; } else { if (tm.tm_year < 70) { /* two-digit year, probably after 2000. * This patent was overturned, right? */ tm.tm_year += 100; } } if (Uisdigit(*s)) { /* five-digit date */ goto baddate; } if (tm.tm_mday > monthdays(tm.tm_year, tm.tm_mon)) goto baddate; s = skip_fws(s); if (s && !dayonly) { /* Parse hour */ if (!s || !Uisdigit(*s)) goto badtime; tm.tm_hour = *s++ - '0'; if (!Uisdigit(*s)) goto badtime; tm.tm_hour = tm.tm_hour * 10 + *s++ - '0'; if (!s || *s++ != ':') goto badtime; /* Parse min */ if (!s || !Uisdigit(*s)) goto badtime; tm.tm_min = *s++ - '0'; if (!Uisdigit(*s)) goto badtime; tm.tm_min = tm.tm_min * 10 + *s++ - '0'; if (*s == ':') { /* Parse sec */ if (!++s || !Uisdigit(*s)) goto badtime; tm.tm_sec = *s++ - '0'; if (!Uisdigit(*s)) goto badtime; tm.tm_sec = tm.tm_sec * 10 + *s++ - '0'; } s = skip_fws(s); if (s) { /* Parse timezone offset */ if (*s == '+' || *s == '-') { /* Parse numeric offset */ int east = (*s++ == '-'); if (!s || !Uisdigit(*s)) goto badzone; zone_off = *s++ - '0'; if (!s || !Uisdigit(*s)) goto badzone; zone_off = zone_off * 10 + *s++ - '0'; if (!s || !Uisdigit(*s)) goto badzone; zone_off = zone_off * 6 + *s++ - '0'; if (!s || !Uisdigit(*s)) goto badzone; zone_off = zone_off * 10 + *s++ - '0'; if (east) zone_off = -zone_off; } else if (Uisalpha(*s)) { char zone[4]; zone[0] = *s++; if (!Uisalpha(*s)) { /* Parse military (single-char) zone */ zone[1] = '\0'; lcase(zone); if (zone[0] < 'j') zone_off = (zone[0] - 'a' + 1) * 60; else if (zone[0] == 'j') goto badzone; else if (zone[0] <= 'm') zone_off = (zone[0] - 'a') * 60; else if (zone[0] < 'z') zone_off = ('m' - zone[0]) * 60; else zone_off = 0; } else { zone[1] = *s++; if (!Uisalpha(*s)) { /* Parse UT (universal time) */ zone[2] = '\0'; lcase(zone); if (strcmp(zone, "ut")) goto badzone; zone_off = 0; } else { /* Parse 3-char time zone */ char *p; zone[2] = *s; zone[3] = '\0'; lcase(zone); /* GMT (Greenwich mean time) */ if (!strcmp(zone, "gmt")) zone_off = 0; /* US time zone */ else { p = strchr("aecmpyhb", zone[0]); if (!p || zone[2] != 't') goto badzone; zone_off = (strlen(p) - 12) * 60; if (zone[1] == 'd') zone_off += 60; else if (zone[1] != 's') goto badzone; } } } } else badzone: zone_off = 0; } } else badtime: tm.tm_hour = 12; tm.tm_isdst = -1; if (!dayonly) t = mkgmtime(&tm); else { assert(zone_off == 0); t = mktime(&tm); } if (t >= 0) { *tp = (t - zone_off * 60); return s - origs; } baddate: return -1; }