Пример #1
0
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 */
}
Пример #2
0
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;
}