/* * Skip RFC822 Commenting Folding Whitespace. * * data - pointer into header body * len - length of data, minus any trailing (not required) NULL. * result - on success is set to first character after skipped space * rlen - on success returns the length of skipped space * * Note that there may be no space to be skipped, so result will * be equal to data and rlen will be 0. If all of the input is * consumed while within a comment, result is set to NULL and rlen */ void skip_rfc822_cfws(const char* data, unsigned int len, const char** result, unsigned int* rlen) { const char* p = data; const char* end = data + len; int clevel = 0; int escape = 0; int newline = 0; while (p < end) { if (escape) { /* * Previously read character was a \ within a comment. * All characters are escapable except carriage * return and newline, so check for those here. If we * find either one, we don't increment p, and continue * the loop, so that the improperly escaped character * gets processed as if it was not escaped. */ escape = 0; if ( (*p != '\r') && (*p != '\n') ) { p++; continue; } /* * Not a legally escapable character, so fall through for standard * processing. */ continue; } else if (newline) { /* * Previously read character was a newline. In this * case we need to check if the newline is followed * by whitespace characters, which indicate folding * whitespace. Otherwise we have reached the end of * this header and must stop. */ newline = 0; if ( (*p == ' ') || (*p == '\t') ) { p++; continue; } else { *result = p; *rlen = p - data; return; } } else { switch (*p) { case ' ': case '\t': case '\r': p++; break; case '\n': newline = 1; p++; break; case '(': clevel++; p++; break; case ')': clevel--; p++; break; case '\\': /* An escape can only be skipped if it is within a comment. */ if (clevel > 0) { escape = 1; p++; break; } else { *result = p; *rlen = p - data; return; } default: if (clevel > 0) { p++; break; } else { *result = p; *rlen = p - data; return; } } } } if (clevel == 0) { *result = p; *rlen = p - data; } else { *result = '\0'; *rlen = 0; } return; }