Value * read_value(Globals *g) { Value *v; while (g->buflen > 0) { switch (PEEK_CHAR(g)) { case ' ': case '\t': case '\n': case '\0': NEXT_CHAR(g); break; case '\"': /* begin string */ NEXT_CHAR(g); return read_string(g); break; case '(': NEXT_CHAR(g); return read_list(g); break; case ')': case '.': return NULL; break; default: return read_num_or_symbol(g); break; } } ABORT(g, 23); }
/** * Reads until encounter of a SPACE, CR or LF. * Writes read bytes int *buffer, without terminating SPACE, CR and LF. * Reallocs buffer if necessary. * Returns the last char read (i.e. either SPACE, CR, LF) or 0 on error. */ static char getToken(char** buffer, size_t* bufferLength) { size_t writeIndex = 0; char c; NEXT_CHAR(c); while( (SPACE != c) && (CR != c) && (LF != c) ) { if(writeIndex >= *bufferLength - 2) { if(MAX_TOKEN_LENGTH <= *bufferLength) { return 0; } if(0 == *bufferLength) { *bufferLength = MIN_TOKEN_LENGTH; } *bufferLength *= 2; *buffer = realloc(*buffer, *bufferLength); } (*buffer)[writeIndex] = c; writeIndex++; NEXT_CHAR(c); } (*buffer)[writeIndex] = 0; return c; }
int gettag(FILE* html,char* tag) { int c=0; char* p=tag; int lim=MAX_TAG-2; do { c=NEXT_CHAR(html); if (c==EOF) break; } while (c!='<'); if (c==EOF) goto END_OF_FILE; SKIP_WS(html,c); do { if (lim--<0) break; *tag++=c; c=NEXT_CHAR(html); } while (!IS_SPACE(c)); *tag='\0'; return 1; END_OF_FILE: *tag='\0'; return 0; }
Value * read_string(Globals *g) { int strpos = 0; Value *v; char c; #define ADD_CHAR(c) \ if (strpos >= g->strbuflen) \ expand_strbuf(g); \ g->strbuf[strpos++] = (c) while (1) { switch (PEEK_CHAR(g)) { case '\"': NEXT_CHAR(g); v = ALLOC_VALUE(); v->tag = string; v->value.s.length = strpos; v->value.s.string = (char *) malloc(v->value.s.length); bcopy(g->strbuf, v->value.s.string, v->value.s.length); return v; break; case '\\': NEXT_CHAR(g); if (read_escape(g, &c)) ADD_CHAR(c); break; default: ADD_CHAR(PEEK_CHAR(g)); NEXT_CHAR(g); break; } } }
Value * read_list(Globals *g) { Value *list; Value **tail; Value *v; tail = &list; while (g->buflen > 0) { if (NULL == (v = read_value(g))) { switch (PEEK_CHAR(g)) { case ')': if (tail != NULL) { /* if no last cdr yet, use nil */ *tail = NULL; } NEXT_CHAR(g); return list; break; case '.': /* set last cdr explicitly */ NEXT_CHAR(g); *tail = read_value(g); if (*tail == NULL) { /* badly formed input ??? */ ABORT(g, 13); } tail = NULL; break; default: /* badly formed input ??? */ ABORT(g, 13); break; } } else { /* read a value, add it to the list */ if (NULL == tail) { /* two values after a . in a list. very bad! ??? */ ABORT(g, 13); } *tail = ALLOC_VALUE(); (*tail)->tag = cons; (*tail)->value.cons.car = v; tail = &(*tail)->value.cons.cdr; } } }
int getproperty(FILE* html,char* property) { int c=0; char* p=property; int outword=0; int lim=MAX_PROPERTY-2; SKIP_WS(html,c); do { if (IS_SPACE(c)) {outword=1;SKIP_WS(html,c);} if (c==EOF) goto END_OF_FILE; if (c=='=') break; if (outword) {property=p;outword=0;} *property++=c; if (lim--<0) break; c=NEXT_CHAR(html); if (c==EOF) goto END_OF_FILE; } while (c!='='); *property='\0'; return 1; END_OF_FILE: *property='\0'; return 0; }
static GstASMScan * gst_asm_scan_new (const gchar * buffer) { GstASMScan *scan; scan = g_new0 (GstASMScan, 1); scan->buffer = buffer; NEXT_CHAR (scan); return scan; }
static void gst_asm_scan_string (GstASMScan * scan, gchar delim) { gchar ch; gint i = 0; ch = THIS_CHAR (scan); while ((ch != delim) && (ch != '\0')) { if (i < MAX_RULE_LENGTH - 1) scan->val[i++] = ch; ch = NEXT_CHAR (scan); if (ch == '\\') ch = NEXT_CHAR (scan); } scan->val[i] = '\0'; if (ch == delim) NEXT_CHAR (scan); scan->token = GST_ASM_TOKEN_STRING; }
int getvalue(FILE* html,char* value) { int c=0; int quote_non=0; int quote_sng=0; int quote_dbl=0; int lim=MAX_VALUE-2; SKIP_WS(html,c); switch (c) { case '\"' : quote_dbl=1; break; case '\'' : quote_sng=1; break; default : quote_non=1; *value++=c; if (lim--<0) break; break; } do { c=NEXT_CHAR(html); if (END_OF_VALUE(c)) break; else { if (lim--<0) break; *value++=c; } } while (c!=EOF) ; if (c==EOF) goto END_OF_FILE; *value='\0'; // printf("%s\n",value); return 1; END_OF_FILE: *value='\0'; // printf("%s\n",value); return 0; }
extern void print_byte(unsigned char *ptr, unsigned int size) { unsigned char *first_character; int ch; first_character = FIRST_CHAR(ptr, size); for (ch=1; ch<=size; ++ch) { printf("%.2x", *first_character); fputc(' ', stdout); NEXT_CHAR(first_character); } fputc('\n', stdout); }
static void gst_asm_scan_identifier (GstASMScan * scan) { gchar ch; gint i = 0; ch = THIS_CHAR (scan); /* real strips all spaces that are not inside quotes for identifiers */ while ((IS_CHAR (ch) || IS_SPACE (ch))) { if (i < (MAX_RULE_LENGTH - 1) && !IS_SPACE (ch)) scan->val[i++] = ch; ch = NEXT_CHAR (scan); } scan->val[i] = '\0'; scan->token = GST_ASM_TOKEN_IDENTIFIER; }
/** * This function performes a run-length decoding and writes back to * *dstpacket*, but no more than *maxsize* bytes. * * @param srcpacket: the encoded packet. * @param maxsize: the maximal size of the decoded packet. */ static char *gdbwrap_run_length_decode(char *dstpacket, const char *srcpacket, unsigned maxsize) { /* Protocol specifies to take the following value and substract 29 and repeat by this number the previous character. Note that the compression may be used multiple times in a packet. */ char *encodestr; char valuetocopy; uint8_t numberoftimes; unsigned iter; unsigned strlenc; unsigned check; if (!srcpacket || !dstpacket) return NULL; ASSERT(dstpacket != NULL && srcpacket != NULL && srcpacket[0] != GDBWRAP_START_ENCODC); if (srcpacket != dstpacket) strncpy(dstpacket, srcpacket, maxsize); encodestr = strstr(dstpacket, GDBWRAP_START_ENCOD); check = strlen(dstpacket); while (encodestr != NULL) { /* This is OK to take encodestr[-1], since we assert(srcpacket[0] != GDBWRAP_START_ENCODC). */ valuetocopy = encodestr[-1]; numberoftimes = encodestr[1] - 29; ASSERT((check += numberoftimes) < maxsize); strlenc = strlen(encodestr); /* We move the string to the right, then set the bytes. We substract 2, because we have <number>*<char> where * and <char> are filled with the value of <number> (ie 2 chars). */ for (iter = 0; iter < strlenc; iter++) encodestr[strlenc + numberoftimes - iter - 2] = encodestr[strlenc - iter]; memset(encodestr, valuetocopy, numberoftimes); encodestr = strstr(NEXT_CHAR(encodestr), GDBWRAP_START_ENCOD); } return dstpacket; }
int read_escape(Globals *g, char *c) { int valid = 1; /* ??? handle octal \nnn notation? urgh. */ switch (PEEK_CHAR(g)) { case '\n': valid = 0; break; case 'n': *c = '\n'; break; case 't': *c = '\t'; break; default: *c = PEEK_CHAR(g); break; } NEXT_CHAR(g); return valid; }
static void gst_asm_scan_number (GstASMScan * scan) { gchar ch; gint i = 0; gboolean have_float = FALSE; ch = THIS_CHAR (scan); /* real strips all spaces that are not inside quotes for numbers */ while ((IS_NUMBER (ch) || IS_SPACE (ch))) { if (i < (MAX_RULE_LENGTH - 1) && !IS_SPACE (ch)) scan->val[i++] = ch; if (ch == '.') have_float = TRUE; ch = NEXT_CHAR (scan); } scan->val[i] = '\0'; if (have_float) scan->token = GST_ASM_TOKEN_FLOAT; else scan->token = GST_ASM_TOKEN_INT; }
/*----------------------------------------------------------------------------*/ int http_readRequest(HttpRequest* request) { /* * Request constitutes of * request-lineCRLF * Header1: *Value1CRLF * ...CRLF * CRLF * Body */ enum {None, Cr1, Lf1, Cr2, Lf2} crLfReadingState; int numCrLf = 0; signed char c = 0; signed char c2 = 0; enum { BEFORE, READING, DONE } readingState = BEFORE; /* Read method */ while(DONE != readingState) { NEXT_CHAR(c); switch( toupper(c) ) { case LF: case CR: if(BEFORE != readingState) { LOG_CON(ERROR, socketFd, "Premature end of HTTP request\n"); return -1; } break; case 'G': request->type = GET; EXPECT('E', c); EXPECT('T', c); EXPECT(SPACE, c); readingState = DONE; LOG_CON(INFO, socketFd, "Got GET request"); break; case 'H': request->type = HEAD; EXPECT('E', c); EXPECT('A', c); EXPECT('D', c); EXPECT(SPACE, c); readingState = DONE; LOG_CON(INFO, socketFd, "Got HEAD request"); break; default: LOG_CON(ERROR, socketFd, "Could not parse HTTP request - " " Unsupported HTTP method?\n"); return -1; }; }; if(SPACE != getToken(request->url, &request->urlMaxLength) ) { LOG_CON(ERROR, socketFd, "Could not read URL for HTTP requst\n"); return -1; } LOG_CON(INFO, socketFd, "Read URL"); EXPECT('H', c); EXPECT('T', c); EXPECT('T', c); EXPECT('P', c); EXPECT('/', c); NEXT_CHAR(request->majVersion); EXPECT('.', c); NEXT_CHAR(request->minVersion); EXPECT(CR, c); EXPECT(LF, c); crLfReadingState = Lf1; /* Read until end of header */ while(Lf2 != crLfReadingState) { NEXT_CHAR(c); if(CR == c) { if(Lf1 == crLfReadingState) { crLfReadingState = Cr2; } else { crLfReadingState = Cr1; } } else if(LF == c) { if(Cr1 == crLfReadingState) { crLfReadingState = Lf1; } else if(Cr2 == crLfReadingState) { crLfReadingState = Lf2; } else { crLfReadingState = None; } } else { crLfReadingState = None; } } /* Line should be terminated by CRLF, but LF might be missing */ return 0; }
static GstASMToken gst_asm_scan_next_token (GstASMScan * scan) { gchar ch; ch = THIS_CHAR (scan); /* skip spaces */ while (IS_SPACE (ch)) ch = NEXT_CHAR (scan); /* remove \ which is common in front of " */ while (ch == '\\') ch = NEXT_CHAR (scan); switch (ch) { case '#': scan->token = GST_ASM_TOKEN_HASH; NEXT_CHAR (scan); break; case ';': scan->token = GST_ASM_TOKEN_SEMICOLON; NEXT_CHAR (scan); break; case ',': scan->token = GST_ASM_TOKEN_COMMA; NEXT_CHAR (scan); break; case '=': scan->token = GST_ASM_TOKEN_EQUAL; if (NEXT_CHAR (scan) == '=') NEXT_CHAR (scan); break; case '!': if (NEXT_CHAR (scan) == '=') { scan->token = GST_ASM_TOKEN_NOTEQUAL; NEXT_CHAR (scan); } break; case '&': scan->token = GST_ASM_TOKEN_AND; if (NEXT_CHAR (scan) == '&') NEXT_CHAR (scan); break; case '|': scan->token = GST_ASM_TOKEN_OR; if (NEXT_CHAR (scan) == '|') NEXT_CHAR (scan); break; case '<': scan->token = GST_ASM_TOKEN_LESS; if (NEXT_CHAR (scan) == '=') { scan->token = GST_ASM_TOKEN_LESSEQUAL; NEXT_CHAR (scan); } break; case '>': scan->token = GST_ASM_TOKEN_GREATER; if (NEXT_CHAR (scan) == '=') { scan->token = GST_ASM_TOKEN_GREATEREQUAL; NEXT_CHAR (scan); } break; case '$': scan->token = GST_ASM_TOKEN_DOLLAR; NEXT_CHAR (scan); break; case '(': scan->token = GST_ASM_TOKEN_LPAREN; NEXT_CHAR (scan); break; case ')': scan->token = GST_ASM_TOKEN_RPAREN; NEXT_CHAR (scan); break; case '"': NEXT_CHAR (scan); gst_asm_scan_string (scan, '"'); break; case '\'': NEXT_CHAR (scan); gst_asm_scan_string (scan, '\''); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': gst_asm_scan_number (scan); break; case '\0': scan->token = GST_ASM_TOKEN_EOF; break; default: gst_asm_scan_identifier (scan); break; } gst_asm_scan_print_token (scan); return scan->token; }
Value * read_num_or_symbol(Globals *g) { Value *v; int strpos = 0; char c; int i; int is_integer; #define ADD_CHAR(c) \ if (strpos >= g->strbuflen) \ expand_strbuf(g); \ g->strbuf[strpos++] = (c) while (g->buflen > 0) { switch (PEEK_CHAR(g)) { case ' ': case '\t': case '\n': case '\0': case '\"': case '(': case ')': case '.': goto done; break; case '\\': NEXT_CHAR(g); ADD_CHAR(PEEK_CHAR(g)); NEXT_CHAR(g); break; default: ADD_CHAR(PEEK_CHAR(g)); NEXT_CHAR(g); break; } } ABORT(g, 23); done: /* is this a number or a symbol? */ /* assume integer to start */ is_integer = 1; /* assume no empty strings? */ /* if the first character is '+' or '-' and that's not the only */ /* character it can still be an integer */ if (strpos > 1 && (g->strbuf[0] == '-' || g->strbuf[0] == '+')) i = 1; else if (strpos == 1) { i = 0; is_integer = 0; } else i = 0; while (is_integer && i < strpos) { if (g->strbuf[i] < '0' || g->strbuf[i] > '9') is_integer = 0; i++; } if (is_integer) { /* it's an integer */ v = ALLOC_VALUE(); v->tag = integer; ADD_CHAR('\0'); v->value.integer.i = atoi(g->strbuf); } else { /* it's a symbol */ if (3 == strpos && !bcmp(g->strbuf, "nil", 3)) { v = NULL; } else { v = ALLOC_VALUE(); v->tag = symbol; v->value.s.length = strpos; v->value.s.string = (char *) malloc(v->value.s.length); bcopy(g->strbuf, v->value.s.string, v->value.s.length); } } return v; }
token_t Scanner::NextToken(bool hungry) // ---------------------------------------------------------------------------- // Return the next token, and compute the token text and value // ---------------------------------------------------------------------------- { textValue = ""; tokenText = ""; intValue = 0; realValue = 0.0; base = 0; // Check if input was opened correctly if (!input.good()) return tokEOF; // Check if we unindented far enough for multiple indents hadSpaceBefore = true; while (indents.back() > indent) { indents.pop_back(); return tokUNINDENT; } // Read next character int c = input.get(); position++; // Skip spaces and check indendation hadSpaceBefore = false; while (isspace(c) && c != EOF) { hadSpaceBefore = true; if (c == '\n') { // New line: start counting indentation checkingIndent = true; lineStart = position; } else if (checkingIndent) { // Can't mix tabs and spaces if (c == ' ' || c == '\t') { if (!indentChar) indentChar = c; else if (indentChar != c) errors.Log(Error("Mixed tabs and spaces in indentation", position)); } } // Keep looking for more spaces if (c == '\n') textValue += c; c = input.get(); position++; } // End of space testing // Stop counting indentation if (checkingIndent) { input.unget(); position--; checkingIndent = false; ulong column = position - lineStart; if (settingIndent) { // We set a new indent, for instance after opening paren indents.push_back(indent); indent = column; settingIndent = false; return tokNEWLINE; } else if (column > indent) { // Strictly deeper indent : report indent = column; indents.push_back(indent); return tokINDENT; } else if (column < indents.back()) { // Unindenting: remove rightmost indent level ELFE_ASSERT(indents.size()); indents.pop_back(); indent = column; // If we unindented, but did not go as far as the // most recent indent, report inconsistency. if (indents.back() < column) { errors.Log(Error("Unindenting to the right " "of previous indentation", position)); return tokERROR; } // Otherwise, report that we unindented // We may report multiple tokUNINDENT if we unindented deep return tokUNINDENT; } else { // Exactly the same indent level as before return tokNEWLINE; } } // Report end of input if that's what we've got if (input.eof()) return tokEOF; // Clear spelling from whitespaces textValue = ""; // Look for numbers if (isdigit(c)) { bool floating_point = false; bool basedNumber = false; base = 10; intValue = 0; // Take integral part (or base) do { while (digit_values[c] < base) { intValue = base * intValue + digit_values[c]; NEXT_CHAR(c); if (c == '_') // Skip a single underscore { IGNORE_CHAR(c); if (c == '_') errors.Log(Error("Two _ characters in a row look ugly", position)); } } // Check if this is a based number if (c == '#' && !basedNumber) { base = intValue; if (base < 2 || base > 36) { base = 36; errors.Log(Error("The base $1 is not valid, not in 2..36", position).Arg(textValue)); } NEXT_CHAR(c); intValue = 0; basedNumber = true; } else { basedNumber = false; } } while (basedNumber); // Check for fractional part realValue = intValue; if (c == '.') { int nextDigit = input.peek(); if (digit_values[nextDigit] >= base) { // This is something else following an integer: 1..3, 1.(3) input.unget(); position--; hadSpaceAfter = false; return tokINTEGER; } else { floating_point = true; double comma_position = 1.0; NEXT_CHAR(c); while (digit_values[c] < base) { comma_position /= base; realValue += comma_position * digit_values[c]; NEXT_CHAR(c); if (c == '_') { IGNORE_CHAR(c); if (c == '_') errors.Log(Error("Two _ characters in a row " "look really ugly", position)); } } } } // Check if we have a second '#' at end of based number if (c == '#') NEXT_CHAR(c); // Check for the exponent if (c == 'e' || c == 'E') { NEXT_CHAR(c); uint exponent = 0; bool negative_exponent = false; // Exponent sign if (c == '+') { NEXT_CHAR(c); } else if (c == '-') { NEXT_CHAR(c); negative_exponent = true; floating_point = true; } // Exponent value while (digit_values[c] < 10) { exponent = 10 * exponent + digit_values[c]; NEXT_CHAR(c); if (c == '_') IGNORE_CHAR(c); } // Compute base^exponent double exponent_value = 1.0; double multiplier = base; while (exponent) { if (exponent & 1) exponent_value *= multiplier; exponent >>= 1; multiplier *= multiplier; } // Compute actual value if (negative_exponent) realValue /= exponent_value; else realValue *= exponent_value; intValue = (ulong) realValue; } // Return the token input.unget(); position--; hadSpaceAfter = isspace(c); return floating_point ? tokREAL : tokINTEGER; } // Numbers
// !! this function modifies data pointed with sCmdLine parameter! size_t srvParseCmdLine(cEnvironmentHelper* pEnvironmentHelper, tstring sCmdLine, tcstring sDefaultDir, tcstring* params, size_t max_params_count, bool bInterpreteur) { assert((params && max_params_count) || (!params && !max_params_count)); bool bCMD = bInterpreteur; size_t params_count = 0; tstring pwchPtr = sCmdLine; tstring param; tchar wc; if (sCmdLine == NULL) return 0; if (!params && !max_params_count) max_params_count = SIZE_MAX; wc = tstrchar(pwchPtr); while (wc>0 && wc<=' ') wc = NEXT_CHAR(); sCmdLine = pwchPtr; if (wc != '\"') // first param not quoted { wc = tstrchar(pwchPtr); while (wc) { // find delimiter while (wc != 0 && !IS_DELIM(wc, bCMD)) wc = NEXT_CHAR(); tstrchar(pwchPtr) = 0; tstring file = pEnvironmentHelper->PathFindExecutable(sCmdLine, sDefaultDir); // check long file name without quotes tstrchar(pwchPtr) = wc; if (file) { if (params) { params[0] = sCmdLine; tstrchar(pwchPtr) = 0; } params_count++; sCmdLine = pwchPtr; if (wc) // we have more args sCmdLine++; tstrfree(file); break; } if (wc) wc = NEXT_CHAR(); } } pwchPtr = sCmdLine; while (params_count < max_params_count) { wc = tstrchar(pwchPtr); // skip delimiters at start while (wc != 0 && IS_DELIM(wc, bCMD)) wc = NEXT_CHAR(); if (wc == 0) // end reached break; if (wc == '\"') // quoted param { wc = NEXT_CHAR(); if (bCMD && wc == '\"') wc = NEXT_CHAR(); if (wc == 0) // end reached break; param = pwchPtr; while (wc != 0 && wc != '\"') wc = NEXT_CHAR(); } else { //if (wc != '/') // if not switch param = pwchPtr; // modified by Sobko was: while (wc != 0 && !IS_DELIM(wc) && wc != '\"') while (wc != 0 && !IS_DELIM(wc, bCMD) && wc != '\"') wc = NEXT_CHAR(); } if (param != pwchPtr) { if (params) { params[params_count] = param; tstrchar(pwchPtr) = 0; // zero terminate parameter } if (params_count == 0) { tchar c = tstrchar(pwchPtr); tstrchar(pwchPtr) = 0; // zero terminate parameter if (tstring file = pEnvironmentHelper->PathFindExecutable(param, sDefaultDir)) // check long file name without quotes { if (srvComparePath(pEnvironmentHelper, file, _T("%ComSpec%"))) bCMD = true; tstrfree(file); } tstrchar(pwchPtr) = c; // restore terminate parameter } params_count++; } if (wc == 0) // end reached break; wc = NEXT_CHAR(); } return params_count; }
/* msg_quote_phrase_or_addr * * Given a single mailbox, this quotes the characters in it which need * to be quoted; it writes into `address' and returns a new length. * `address' is assumed to be long enough; worst case, its size will * be (N*2)+2. */ static int msg_quote_phrase_or_addr(char *address, PRInt32 length, PRBool addr_p) { int quotable_count = 0, in_quote = 0; int unquotable_count = 0; PRInt32 new_length, full_length = length; char *in, *out, *orig_out, *atsign = NULL, *orig_address = address; PRBool user_quote = PR_FALSE; PRBool quote_all = PR_FALSE; /* If the entire address is quoted, fall out now. */ if (address[0] == '\"' && address[length - 1] == '\"') return length; /* Check to see if there is a routing prefix. If there is one, we can * skip quoting it because by definition it can't need to be quoted. */ if (addr_p && *address && *address == '@') { for (in = address; *in; NEXT_CHAR(in)) { if (*in == ':') { length -= ++in - address; address = in; break; } else if (!IS_DIGIT(*in) && !IS_ALPHA(*in) && *in != '@' && *in != '.') break; } } for (in = address; in < address + length; NEXT_CHAR(in)) { if (*in == 0) return full_length; /* #### horrible kludge... */ else if (*in == '@' && addr_p && !atsign && !in_quote) { /* Exactly one unquoted at-sign is allowed in an address. */ if (atsign) quotable_count++; atsign = in; /* If address is of the form '"userid"@somewhere.com' don't quote * the quotes around 'userid'. Also reset the quotable count, since * any quotables we've seen are already inside quotes. */ if (address[0] == '\"' && in > address + 2 && *(in - 1) == '\"' && *(in - 2) != '\\') unquotable_count -= 2, quotable_count = 0, user_quote = PR_TRUE; } else if (*in == '\\') { if (in + 1 < address + length && (*(in + 1) == '\\' || *(in + 1) == '\"')) /* If the next character is a backslash or quote, this backslash */ /* is an escape backslash; ignore it and the next character. */ in++; else /* If the name contains backslashes or quotes, they must be escaped. */ unquotable_count++; } else if (*in == '\"') /* If the name contains quotes, they must be escaped. */ unquotable_count++, in_quote = !in_quote; else if ( /* *in >= 127 || *in < 0 ducarroz: 8bits characters will be mime encoded therefore they are not a problem ||*/ (*in == ';' && !addr_p) || *in == '$' || *in == '(' || *in == ')' || *in == '<' || *in == '>' || *in == '@' || *in == ',') /* If the name contains control chars or Header specials, it needs to * be enclosed in quotes. Double-quotes and backslashes will be dealt * with separately. * * The ":" character is explicitly not in this list, though Header says * it should be quoted, because that has been seen to break VMS * systems. (Rather, it has been seen that there are Unix SMTP servers * which accept RCPT TO:<host::user> but not RCPT TO:<"host::user"> or * RCPT TO:<host\:\:user>, which is the syntax that VMS/DECNET hosts * use. * * For future reference: it is also claimed that some VMS SMTP servers * allow \ quoting but not "" quoting; and that sendmail uses self- * contradcitory quoting conventions that violate both RFCs 821 and * 822, so any address quoting on a sendmail system will lose badly. * * The ";" character in an address is a group delimiter, therefore it * should not be quoted in that case. */ quotable_count++; else if (!atsign && (*in == '[' || *in == ']')) /* Braces are normally special characters, except when they're * used for domain literals (e.g. johndoe@[127.0.0.1].acme.com). */ quotable_count++; else if (addr_p && *in == ' ') /* Naked spaces are allowed in names, but not addresses. */ quotable_count++; else if ( !addr_p && (*in == '.' || *in == '!' || *in == '$' || *in == '%')) /* Naked dots are allowed in addresses, but not in names. * The other characters (!$%) are technically allowed in names, but * are surely going to cause someone trouble, so we quote them anyway. */ quotable_count++; } if (quotable_count == 0 && unquotable_count == 0) return full_length; /* We must quote the entire string if there are quotables outside the user * quote. */ if (!atsign || (user_quote && quotable_count > 0)) quote_all = PR_TRUE, atsign = NULL; /* Add 2 to the length for the quotes, plus one for each character * which will need a backslash, plus one for a null terminator. */ new_length = length + quotable_count + unquotable_count + 3; in = address; out = orig_out = (char *)PR_Malloc(new_length); if (!out) { *orig_address = 0; return 0; } /* Start off with a quote. */ *out++ = '\"'; while (*in) { if (*in == '@') { if (atsign == in) *out++ = '\"'; *out++ = *in++; continue; } else if (*in == '\"') { if (!user_quote || (in != address && in != atsign - 1)) *out++ = '\\'; *out++ = *in++; continue; } else if (*in == '\\') { if (*(in + 1) == '\\' || *(in + 1) == '\"') *out++ = *in++; else *out++ = '\\'; *out++ = *in++; continue; } else COPY_CHAR(out, in); NEXT_CHAR(in); } /* Add a final quote if we are quoting the entire string. */ if (quote_all) *out++ = '\"'; *out++ = 0; NS_ASSERTION(new_length >= (out - orig_out), ""); memcpy(address, orig_out, new_length); PR_FREEIF(orig_out); /* make sure we release the string we allocated */ return full_length + unquotable_count + 2; }
/* msg_unquote_phrase_or_addr * * Given a name or address that might have been quoted * it will take out the escape and double quotes * The caller is responsible for freeing the resulting * string. */ static nsresult msg_unquote_phrase_or_addr(const char *line, PRBool preserveIntegrity, char **lineout) { if (!line || !lineout) return NS_OK; /* If the first character isn't a double quote, there is nothing to do */ if (*line != '\"') { *lineout = strdup(line); if (!*lineout) return NS_ERROR_OUT_OF_MEMORY; else return NS_OK; } /* in preserveIntegrity mode, we must preserve the quote if the name contains a comma */ if (preserveIntegrity) { const char * open_quote = nsnull; const char * comma = nsnull;; const char * at_sign = nsnull; const char * readPos = line + 1; while (*readPos) { if (*readPos == ',') { if (!open_quote) comma = readPos; } else if (*readPos == '@') { at_sign = readPos; break; } else if (*readPos == '"') { if (!open_quote) open_quote = readPos; else open_quote = nsnull; } readPos ++; } if (comma && at_sign) { *lineout = strdup(line); if (!*lineout) return NS_ERROR_OUT_OF_MEMORY; else return NS_OK; } } /* Don't copy the first double quote */ *lineout = strdup(line + 1); if (!*lineout) return NS_ERROR_OUT_OF_MEMORY; const char *lineptr = line + 1; char *outptr = *lineout; PRBool escaped = PR_FALSE; while (*lineptr) { /* If the character is an '\' then output the character that was * escaped. If it was part of the quote then don't output it. */ if (*lineptr == '\\') { escaped = PR_TRUE; lineptr++; } if (*lineptr == '\"' && !escaped) lineptr++; escaped = PR_FALSE; if (*lineptr) { COPY_CHAR(outptr, lineptr); NEXT_CHAR(lineptr); } } *outptr = '\0'; return NS_OK; }
/* * NumPyOS_ascii_ftolf: * * fp: FILE pointer * * value: Place to store the value read * * Similar to PyOS_ascii_strtod, except that it reads input from a file. * * Similarly to fscanf, this function always consumes leading whitespace, * and any text that could be the leading part in valid input. * * Return value: similar to fscanf. * * 0 if no number read, * * 1 if a number read, * * EOF if end-of-file met before reading anything. */ NPY_NO_EXPORT int NumPyOS_ascii_ftolf(FILE *fp, double *value) { char buffer[FLOAT_FORMATBUFLEN + 1]; char *endp; char *p; int c; int ok; /* * Pass on to PyOS_ascii_strtod the leftmost matching part in regexp * * \s*[+-]? ( [0-9]*\.[0-9]+([eE][+-]?[0-9]+) * | nan ( \([:alphanum:_]*\) )? * | inf(inity)? * ) * * case-insensitively. * * The "do { ... } while (0)" wrapping in macros ensures that they behave * properly eg. in "if ... else" structures. */ #define END_MATCH() \ goto buffer_filled #define NEXT_CHAR() \ do { \ if (c == EOF || endp >= buffer + FLOAT_FORMATBUFLEN) \ END_MATCH(); \ *endp++ = (char)c; \ c = getc(fp); \ } while (0) #define MATCH_ALPHA_STRING_NOCASE(string) \ do { \ for (p=(string); *p!='\0' && (c==*p || c+('a'-'A')==*p); ++p) \ NEXT_CHAR(); \ if (*p != '\0') END_MATCH(); \ } while (0) #define MATCH_ONE_OR_NONE(condition) \ do { if (condition) NEXT_CHAR(); } while (0) #define MATCH_ONE_OR_MORE(condition) \ do { \ ok = 0; \ while (condition) { NEXT_CHAR(); ok = 1; } \ if (!ok) END_MATCH(); \ } while (0) #define MATCH_ZERO_OR_MORE(condition) \ while (condition) { NEXT_CHAR(); } /* 1. emulate fscanf EOF handling */ c = getc(fp); if (c == EOF) { return EOF; } /* 2. consume leading whitespace unconditionally */ while (NumPyOS_ascii_isspace(c)) { c = getc(fp); } /* 3. start reading matching input to buffer */ endp = buffer; /* 4.1 sign (optional) */ MATCH_ONE_OR_NONE(c == '+' || c == '-'); /* 4.2 nan, inf, infinity; [case-insensitive] */ if (c == 'n' || c == 'N') { NEXT_CHAR(); MATCH_ALPHA_STRING_NOCASE("an"); /* accept nan([:alphanum:_]*), similarly to strtod */ if (c == '(') { NEXT_CHAR(); MATCH_ZERO_OR_MORE(NumPyOS_ascii_isalnum(c) || c == '_'); if (c == ')') { NEXT_CHAR(); } } END_MATCH(); } else if (c == 'i' || c == 'I') { NEXT_CHAR(); MATCH_ALPHA_STRING_NOCASE("nfinity"); END_MATCH(); } /* 4.3 mantissa */ MATCH_ZERO_OR_MORE(NumPyOS_ascii_isdigit(c)); if (c == '.') { NEXT_CHAR(); MATCH_ONE_OR_MORE(NumPyOS_ascii_isdigit(c)); } /* 4.4 exponent */ if (c == 'e' || c == 'E') { NEXT_CHAR(); MATCH_ONE_OR_NONE(c == '+' || c == '-'); MATCH_ONE_OR_MORE(NumPyOS_ascii_isdigit(c)); } END_MATCH(); buffer_filled: ungetc(c, fp); *endp = '\0'; /* 5. try to convert buffer. */ *value = NumPyOS_ascii_strtod(buffer, &p); /* return 1 if something read, else 0 */ return (buffer == p) ? 0 : 1; }
/* msg_parse_Header_addresses * * Given a string which contains a list of Header addresses, parses it into * their component names and mailboxes. * * The returned value is the number of addresses, or a negative error code; * the names and addresses are returned into the provided pointers as * consecutive null-terminated strings. It is up to the caller to free them. * Note that some of the strings may be zero-length. * * Either of the provided pointers may be NULL if the caller is not interested * in those components. * * quote_names_p and quote_addrs_p control whether the returned strings should * be quoted as Header entities, or returned in a more human-presentable (but * not necessarily parsable) form. * * If first_only_p is true, then only the first element of the list is * returned; we don't bother parsing the rest. */ static int msg_parse_Header_addresses (const char *line, char **names, char **addresses, PRBool quote_names_p, PRBool quote_addrs_p, PRBool first_only_p) { PRUint32 addr_count = 0; size_t line_length; const char *line_end; const char *this_start; char *name_buf = 0, *name_out, *name_start; char *addr_buf = 0, *addr_out, *addr_start; if (names) *names = 0; if (addresses) *addresses = 0; NS_ASSERTION(line, ""); if (!line) return -1; line_length = strlen(line); if (line_length == 0) return 0; name_buf = (char *)PR_Malloc(line_length * 2 + 10); if (!name_buf) return NS_ERROR_OUT_OF_MEMORY; addr_buf = (char *)PR_Malloc(line_length * 2 + 10); if (!addr_buf) { FREEIF(name_buf); return NS_ERROR_OUT_OF_MEMORY; } line_end = line; addr_out = addr_buf; name_out = name_buf; name_start = name_buf; addr_start = addr_buf; this_start = line; /* Skip over extra whitespace or commas before addresses. */ while (*line_end && (IS_SPACE(*line_end) || *line_end == ',')) NEXT_CHAR(line_end); while (*line_end) { PRUint32 paren_depth = 0; const char *oparen = 0; const char *mailbox_start = 0; const char *mailbox_end = 0; while ( *line_end && !( *line_end == ',' && paren_depth <= 0 /* comma is ok inside () */ && (!mailbox_start || mailbox_end))) /* comma is ok inside <> */ { if (*line_end == '\\') { line_end++; if (!*line_end) /* otherwise, we walk off end of line, right? */ break; } else if (*line_end == '\"') { int leave_quotes = 0; line_end++; /* remove open " */ /* handle '"John.Van Doe"@space.com' case */ if (paren_depth == 0 && !mailbox_start) { const char *end_quote; /* search for the closing quote but ignored escaped quote \" */ for (end_quote = line_end;; end_quote++) { end_quote = PL_strchr(end_quote, '"'); if (!end_quote || *(end_quote - 1) != '\\') break; } const char *mailbox = end_quote ? PL_strchr(end_quote, '<') : (char *)NULL; const char *comma = end_quote ? PL_strchr(end_quote, ',') : (char *)NULL; if (!mailbox || (comma && comma < mailbox)) { leave_quotes = 1; /* no mailbox for this address */ *addr_out++ = '\"'; } } while (*line_end) { if (*line_end == '\\') { line_end++; if (paren_depth == 0 && (*line_end == '\\' || *line_end == '\"')) *addr_out++ = *line_end++; continue; } else if (*line_end == '\"') { line_end++; /* remove close " */ break; } if (paren_depth == 0) COPY_CHAR(addr_out, line_end); NEXT_CHAR(line_end); } if (leave_quotes) *addr_out++ = '\"'; continue; } if (*line_end == '(') { if (paren_depth == 0) oparen = line_end; paren_depth++; } else if (*line_end == '<' && paren_depth == 0) { mailbox_start = line_end; } else if (*line_end == '>' && mailbox_start && paren_depth == 0) { mailbox_end = line_end; } else if (*line_end == ')' && paren_depth > 0) { paren_depth--; if (paren_depth == 0) { const char *s = oparen + 1; /* Copy the chars inside the parens onto the "name" buffer. */ /* Push out some whitespace before the paren, if * there is non-whitespace there already. */ if (name_out > name_start && !IS_SPACE(name_out [-1])) *name_out++ = ' '; /* Skip leading whitespace. */ while (IS_SPACE(*s) && s < line_end) s++; while (s < line_end) { /* Strip out " within () unless backslashed */ if (*s == '\"') { s++; continue; } if (*s == '\\') /* remove one \ */ s++; if (IS_SPACE(*s) && name_out > name_start && IS_SPACE(name_out[-1])) /* collapse consecutive whitespace */; else COPY_CHAR(name_out, s); NEXT_CHAR(s); } oparen = 0; } } else { /* If we're not inside parens or a <mailbox>, tack this * on to the end of the addr_buf. */ if (paren_depth == 0 && (!mailbox_start || mailbox_end)) { /* Eat whitespace at the beginning of the line, * and eat consecutive whitespace within the line. */ if (IS_SPACE(*line_end) && (addr_out == addr_start || IS_SPACE(addr_out[-1]))) /* skip it */; else COPY_CHAR(addr_out, line_end); } } NEXT_CHAR(line_end); } /* Now we have extracted a single address from the comma-separated * list of addresses. The characters have been divided among the * various buffers: the parts inside parens have been placed in the * name_buf, and everything else has been placed in the addr_buf. * Quoted strings and backslashed characters have been `expanded.' * * If there was a <mailbox> spec in it, we have remembered where it was. * Copy that on to the addr_buf, replacing what was there, and copy the * characters not inside <> onto the name_buf, replacing what is there * now (which was just the parenthesized parts.) (And we need to do the * quote and backslash hacking again, since we're coming from the * original source.) * * Otherwise, we're already done - the addr_buf and name_buf contain * the right data already (de-quoted.) */ if (mailbox_end) { const char *s; NS_ASSERTION(*mailbox_start == '<', ""); NS_ASSERTION(*mailbox_end == '>', ""); /* First, copy the name. */ name_out = name_start; s = this_start; /* Skip leading whitespace. */ while (IS_SPACE(*s) && s < mailbox_start) s++; /* Copy up to (not including) the < */ while (s < mailbox_start) { if (*s == '\"' && !quote_names_p) { s++; continue; } if (*s == '\\' && !quote_names_p) { s++; if (s < mailbox_start && (*s == '\\' || *s == '\"')) *name_out++ = *s++; continue; } if (IS_SPACE(*s) && name_out > name_start && IS_SPACE(name_out[-1])) /* collapse consecutive whitespace */; else COPY_CHAR(name_out, s); NEXT_CHAR(s); } /* Push out one space. */ TRIM_WHITESPACE(name_start, name_out, ' '); s = mailbox_end + 1; /* Skip whitespace after > */ while (IS_SPACE(*s) && s < line_end) s++; /* Copy from just after > to the end. */ while (s < line_end) { if (*s == '\"' && !quote_names_p) { s++; continue; } if (*s == '\\' && !quote_names_p) { s++; if (s < line_end && (*s == '\\' || *s == '\"')) *name_out++ = *s++; continue; } if (IS_SPACE(*s) && name_out > name_start && IS_SPACE(name_out[-1])) /* collapse consecutive whitespace */; else COPY_CHAR(name_out, s); NEXT_CHAR(s); } TRIM_WHITESPACE(name_start, name_out, 0); /* Now, copy the address. */ mailbox_start++; addr_out = addr_start; s = mailbox_start; /* Skip leading whitespace. */ while (IS_SPACE(*s) && s < mailbox_end) s++; /* Copy up to (not including) the > */ while (s < mailbox_end) { if (*s == '\"' && !quote_addrs_p) { s++; continue; } if (*s == '\\' && !quote_addrs_p) { s++; if (s < mailbox_end && (*s == '\\' || *s == '\"')) *addr_out++ = *s++; continue; } COPY_CHAR(addr_out, s); NEXT_CHAR(s); } TRIM_WHITESPACE(addr_start, addr_out, 0); } /* No component of <mailbox> form. */ else { TRIM_WHITESPACE(addr_start, addr_out, 0); TRIM_WHITESPACE(name_start, name_out, 0); } /* Now re-quote the names and addresses if necessary. */ #ifdef BUG11892 // **** jefft - we don't want and shouldn't to requtoe the name, this // violate the RFC822 spec if (quote_names_p && names) { int L = name_out - name_start - 1; L = msg_quote_phrase_or_addr(name_start, L, PR_FALSE); name_out = name_start + L + 1; } #endif if (quote_addrs_p && addresses) { int L = addr_out - addr_start - 1; L = msg_quote_phrase_or_addr(addr_start, L, PR_TRUE); addr_out = addr_start + L + 1; } addr_count++; /* If we only want the first address, we can stop now. */ if (first_only_p) break; if (*line_end) NEXT_CHAR(line_end); /* Skip over extra whitespace or commas between addresses. */ while (*line_end && (IS_SPACE(*line_end) || *line_end == ',')) line_end++; this_start = line_end; name_start = name_out; addr_start = addr_out; } /* Make one more pass through and convert all whitespace characters * to SPC. We could do that in the first pass, but this is simpler. */ { char *s; for (s = name_buf; s < name_out; NEXT_CHAR(s)) if (IS_SPACE(*s) && *s != ' ') *s = ' '; for (s = addr_buf; s < addr_out; NEXT_CHAR(s)) if (IS_SPACE(*s) && *s != ' ') *s = ' '; } if (names) *names = name_buf; else PR_Free(name_buf); if (addresses) *addresses = addr_buf; else PR_Free(addr_buf); return addr_count; }