enum message_cte message_decoder_parse_cte(struct message_header_line *hdr) { struct rfc822_parser_context parser; enum message_cte message_cte; string_t *value; value = t_str_new(64); rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL); rfc822_skip_lwsp(&parser); (void)rfc822_parse_mime_token(&parser, value); message_cte = MESSAGE_CTE_UNKNOWN; switch (str_len(value)) { case 4: if (i_memcasecmp(str_data(value), "7bit", 4) == 0 || i_memcasecmp(str_data(value), "8bit", 4) == 0) message_cte = MESSAGE_CTE_78BIT; break; case 6: if (i_memcasecmp(str_data(value), "base64", 6) == 0) message_cte = MESSAGE_CTE_BASE64; else if (i_memcasecmp(str_data(value), "binary", 6) == 0) message_cte = MESSAGE_CTE_BINARY; break; case 16: if (i_memcasecmp(str_data(value), "quoted-printable", 16) == 0) message_cte = MESSAGE_CTE_QP; break; } return message_cte; }
void http_client_request_remove_header(struct http_client_request *req, const char *key) { const unsigned char *data, *p; size_t size, line_len, line_start_pos; unsigned int key_len = strlen(key); i_assert(req->state == HTTP_REQUEST_STATE_NEW || /* allow calling for retries */ req->state == HTTP_REQUEST_STATE_GOT_RESPONSE || req->state == HTTP_REQUEST_STATE_ABORTED); data = str_data(req->headers); size = str_len(req->headers); while ((p = memchr(data, '\n', size)) != NULL) { line_len = (p+1) - data; if (size > key_len && i_memcasecmp(data, key, key_len) == 0 && data[key_len] == ':' && data[key_len+1] == ' ') { /* key was found from header, replace its value */ line_start_pos = str_len(req->headers) - size; str_delete(req->headers, line_start_pos, line_len); break; } size -= line_len; data += line_len; } }
static int mbox_parse_month(const unsigned char *msg, struct tm *tm) { int i; for (i = 0; i < 12; i++) { if (i_memcasecmp(months[i], msg, 3) == 0) { tm->tm_mon = i; break; } } if (i == 12 && memcmp(msg, "???", 3) == 0) { /* just a hack to parse one special mbox I have :) */ i = 0; } if (i == 12 || msg[3] != ' ') return -1; return 0; }
static bool message_date_parser_tokens(struct message_date_parser_context *ctx, time_t *timestamp_r, int *timezone_offset_r) { struct tm tm; const unsigned char *value; size_t i, len; int ret; /* [weekday_name "," ] dd month_name [yy]yy hh:mi[:ss] timezone */ memset(&tm, 0, sizeof(tm)); rfc822_skip_lwsp(&ctx->parser); /* skip the optional weekday */ if (next_token(ctx, &value, &len) <= 0) return FALSE; if (len == 3) { if (*ctx->parser.data != ',') return FALSE; ctx->parser.data++; rfc822_skip_lwsp(&ctx->parser); if (next_token(ctx, &value, &len) <= 0) return FALSE; } /* dd */ if (len < 1 || len > 2 || !i_isdigit(value[0])) return FALSE; tm.tm_mday = value[0]-'0'; if (len == 2) { if (!i_isdigit(value[1])) return FALSE; tm.tm_mday = (tm.tm_mday * 10) + (value[1]-'0'); } /* month name */ if (next_token(ctx, &value, &len) <= 0 || len < 3) return FALSE; for (i = 0; i < 12; i++) { if (i_memcasecmp(month_names[i], value, 3) == 0) { tm.tm_mon = i; break; } } if (i == 12) return FALSE; /* [yy]yy */ if (next_token(ctx, &value, &len) <= 0 || (len != 2 && len != 4)) return FALSE; for (i = 0; i < len; i++) { if (!i_isdigit(value[i])) return FALSE; tm.tm_year = tm.tm_year * 10 + (value[i]-'0'); } if (len == 2) { /* two digit year, assume 1970+ */ if (tm.tm_year < 70) tm.tm_year += 100; } else { if (tm.tm_year < 1900) return FALSE; tm.tm_year -= 1900; } /* hh, allow also single digit */ if (next_token(ctx, &value, &len) <= 0 || len < 1 || len > 2 || !i_isdigit(value[0])) return FALSE; tm.tm_hour = value[0]-'0'; if (len == 2) { if (!i_isdigit(value[1])) return FALSE; tm.tm_hour = tm.tm_hour * 10 + (value[1]-'0'); } /* :mm (may be the last token) */ if (!IS_TIME_SEP(*ctx->parser.data)) return FALSE; ctx->parser.data++; rfc822_skip_lwsp(&ctx->parser); if (next_token(ctx, &value, &len) < 0 || len != 2 || !i_isdigit(value[0]) || !i_isdigit(value[1])) return FALSE; tm.tm_min = (value[0]-'0') * 10 + (value[1]-'0'); /* [:ss] */ if (ctx->parser.data != ctx->parser.end && IS_TIME_SEP(*ctx->parser.data)) { ctx->parser.data++; rfc822_skip_lwsp(&ctx->parser); if (next_token(ctx, &value, &len) <= 0 || len != 2 || !i_isdigit(value[0]) || !i_isdigit(value[1])) return FALSE; tm.tm_sec = (value[0]-'0') * 10 + (value[1]-'0'); } if ((ret = next_token(ctx, &value, &len)) < 0) return FALSE; if (ret == 0) { /* missing timezone */ *timezone_offset_r = 0; } else { /* timezone */ *timezone_offset_r = parse_timezone(value, len); } tm.tm_isdst = -1; *timestamp_r = utc_mktime(&tm); if (*timestamp_r == (time_t)-1) return FALSE; *timestamp_r -= *timezone_offset_r * 60; return TRUE; }
static void imap_parser_save_arg(struct imap_parser *parser, const unsigned char *data, size_t size) { struct imap_arg *arg; char *str; arg = imap_arg_create(parser); switch (parser->cur_type) { case ARG_PARSE_ATOM: case ARG_PARSE_TEXT: if (size == 3 && i_memcasecmp(data, "NIL", 3) == 0) { /* NIL argument. it might be an actual NIL, but if we're reading astring, it's an atom and we can't lose its case. */ arg->type = IMAP_ARG_NIL; } else { /* simply save the string */ arg->type = IMAP_ARG_ATOM; } arg->_data.str = imap_parser_strdup(parser, data, size); arg->str_len = size; break; case ARG_PARSE_STRING: /* data is quoted and may contain escapes. */ i_assert(size > 0); arg->type = IMAP_ARG_STRING; str = p_strndup(parser->pool, data+1, size-1); /* remove the escapes */ if (parser->str_first_escape >= 0 && (parser->flags & IMAP_PARSE_FLAG_NO_UNESCAPE) == 0) { /* -1 because we skipped the '"' prefix */ (void)str_unescape(str + parser->str_first_escape-1); } arg->_data.str = str; arg->str_len = strlen(str); break; case ARG_PARSE_LITERAL_DATA: if ((parser->flags & IMAP_PARSE_FLAG_LITERAL_SIZE) != 0) { /* save literal size */ arg->type = parser->literal_nonsync ? IMAP_ARG_LITERAL_SIZE_NONSYNC : IMAP_ARG_LITERAL_SIZE; arg->_data.literal_size = parser->literal_size; arg->literal8 = parser->literal8; break; } /* fall through */ case ARG_PARSE_LITERAL_DATA_FORCED: if ((parser->flags & IMAP_PARSE_FLAG_LITERAL_TYPE) != 0) arg->type = IMAP_ARG_LITERAL; else arg->type = IMAP_ARG_STRING; arg->_data.str = imap_parser_strdup(parser, data, size); arg->literal8 = parser->literal8; arg->str_len = size; break; default: i_unreached(); } parser->cur_type = ARG_PARSE_NONE; }