static void hdr_write(string_t *str, struct message_header_line *hdr) { if (!hdr->continued) { str_append(str, hdr->name); str_append_n(str, hdr->middle, hdr->middle_len); } str_append_n(str, hdr->value, hdr->value_len); if (!hdr->no_newline) { if (hdr->crlf_newline) str_append_c(str, '\r'); str_append_c(str, '\n'); } }
static void xml_encode_data(string_t *dest, const unsigned char *data, unsigned int len) { unichar_t chr; unsigned int i; for (i = 0; i < len; i++) { switch (data[i]) { case '&': str_append(dest, "&"); break; case '<': str_append(dest, "<"); break; case '>': str_append(dest, ">"); break; case '\t': case '\n': case '\r': /* exceptions to the following control char check */ str_append_c(dest, data[i]); break; default: if (data[i] < 32) { /* SOLR doesn't like control characters. replace them with spaces. */ str_append_c(dest, ' '); } else if (data[i] >= 0x80) { /* make sure the character is valid for XML so we don't get XML parser errors */ unsigned int char_len = uni_utf8_char_bytes(data[i]); if (i + char_len <= len && uni_utf8_get_char_n(data + i, char_len, &chr) == 1 && is_valid_xml_char(chr)) str_append_n(dest, data + i, char_len); else { str_append_n(dest, utf8_replacement_char, UTF8_REPLACEMENT_CHAR_LEN); } i += char_len - 1; } else { str_append_c(dest, data[i]); } break; } } }
int rfc822_parse_mime_token(struct rfc822_parser_context *ctx, string_t *str) { const unsigned char *start; for (start = ctx->data; ctx->data != ctx->end; ctx->data++) { if (IS_ATEXT_NON_TSPECIAL(*ctx->data) || *ctx->data == '.') continue; str_append_n(str, start, ctx->data - start); return rfc822_skip_lwsp(ctx); } str_append_n(str, start, ctx->data - start); return 0; }
static void mbox_save_append_keyword_headers(struct mbox_save_context *ctx, struct mail_keywords *keywords) { unsigned char space[MBOX_HEADER_PADDING+1 + sizeof("Content-Length: \n")-1 + MAX_INT_STRLEN]; const ARRAY_TYPE(keywords) *keyword_names_list; const char *const *keyword_names; unsigned int i, count, keyword_names_count; keyword_names_list = mail_index_get_keywords(ctx->mbox->box.index); keyword_names = array_get(keyword_names_list, &keyword_names_count); str_append(ctx->headers, "X-Keywords:"); count = keywords == NULL ? 0 : keywords->count; for (i = 0; i < count; i++) { i_assert(keywords->idx[i] < keyword_names_count); str_append_c(ctx->headers, ' '); str_append(ctx->headers, keyword_names[keywords->idx[i]]); } memset(space, ' ', sizeof(space)); str_append_n(ctx->headers, space, sizeof(space)); ctx->space_end_idx = str_len(ctx->headers); str_append_c(ctx->headers, '\n'); }
void str_sanitize_append(string_t *dest, const char *src, size_t max_bytes) { unsigned int initial_pos = str_len(dest); unichar_t chr; size_t i; for (i = 0; i < max_bytes && src[i] != '\0'; ) { int len = uni_utf8_get_char_n(src+i, max_bytes-i, &chr); if (len == 0) break; /* input ended too early */ if (len < 0) { /* invalid UTF-8 */ str_append_c(dest, '?'); i++; continue; } if ((unsigned char)src[i] < 32) str_append_c(dest, '?'); else str_append_n(dest, src+i, len); i += len; } if (src[i] != '\0') { if (max_bytes < 3) str_truncate(dest, initial_pos); else { while (str_len(dest) - initial_pos > max_bytes-3) str_sanitize_truncate_char(dest, initial_pos); } str_append(dest, "..."); } }
int client_auth_read_line(struct client *client) { const unsigned char *data; size_t i, size; unsigned int len; if (i_stream_read_data(client->input, &data, &size, 0) == -1) { client_destroy(client, "Disconnected"); return -1; } /* see if we have a full line */ for (i = 0; i < size; i++) { if (data[i] == '\n') break; } if (client->auth_response == NULL) client->auth_response = str_new(default_pool, I_MAX(i+1, 256)); if (str_len(client->auth_response) + i > LOGIN_MAX_AUTH_BUF_SIZE) { client_destroy(client, "Authentication response too large"); return -1; } str_append_n(client->auth_response, data, i); i_stream_skip(client->input, i == size ? size : i+1); /* drop trailing \r */ len = str_len(client->auth_response); if (len > 0 && str_c(client->auth_response)[len-1] == '\r') str_truncate(client->auth_response, len-1); return i < size; }
static int rfc822_parse_domain_literal(struct rfc822_parser_context *ctx, string_t *str) { const unsigned char *start; /* domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS] dcontent = dtext / quoted-pair dtext = NO-WS-CTL / ; Non white space controls %d33-90 / ; The rest of the US-ASCII %d94-126 ; characters not including "[", ; "]", or "\" */ i_assert(*ctx->data == '['); for (start = ctx->data; ctx->data != ctx->end; ctx->data++) { if (*ctx->data == '\\') { ctx->data++; if (ctx->data == ctx->end) break; } else if (*ctx->data == ']') { ctx->data++; str_append_n(str, start, ctx->data - start); return rfc822_skip_lwsp(ctx); } } /* missing ']' */ return -1; }
void checkpassword_child_input(struct chkpw_auth_request *request) { unsigned char buf[1024]; ssize_t ret; ret = read(request->fd_in, buf, sizeof(buf)); if (ret <= 0) { if (ret < 0) { auth_request_log_error(request->request, "checkpassword", "read() failed: %m"); } auth_request_log_debug(request->request, "checkpassword", "Received no input"); checkpassword_request_close(request); request->half_finish_callback(request); } else { if (request->input_buf == NULL) request->input_buf = str_new(default_pool, 512); str_append_n(request->input_buf, buf, ret); auth_request_log_debug(request->request, "checkpassword", "Received input: %s", str_c(request->input_buf)); } }
static char *i_stream_next_line_finish(struct istream_private *stream, size_t i) { char *ret; size_t end; if (i > 0 && stream->buffer[i-1] == '\r') { end = i - 1; stream->line_crlf = TRUE; } else { end = i; stream->line_crlf = FALSE; } if (stream->w_buffer != NULL) { /* modify the buffer directly */ stream->w_buffer[end] = '\0'; ret = (char *)stream->w_buffer + stream->skip; } else { /* use a temporary string to return it */ if (stream->line_str == NULL) stream->line_str = str_new(default_pool, 256); str_truncate(stream->line_str, 0); str_append_n(stream->line_str, stream->buffer + stream->skip, end - stream->skip); ret = str_c_modifiable(stream->line_str); } if (i < stream->pos) i++; stream->istream.v_offset += i - stream->skip; stream->skip = i; return ret; }
const char *str_escape(const char *str) { const char *p; string_t *ret; /* see if we need to quote it */ for (p = str; *p != '\0'; p++) { if (IS_ESCAPED_CHAR(*p)) break; } if (*p == '\0') return str; /* quote */ ret = t_str_new((size_t) (p - str) + 128); str_append_n(ret, str, (size_t) (p - str)); for (; *p != '\0'; p++) { if (IS_ESCAPED_CHAR(*p)) str_append_c(ret, '\\'); str_append_c(ret, *p); } return str_c(ret); }
static void fs_sis_replace_hash_file(struct sis_fs_file *file) { const char *hash_fname, *path = fs_file_path(&file->file); struct fs *super_fs = file->super->fs; string_t *temp_path; int ret; if (file->hash_input == NULL) { /* hash file didn't exist previously. we should be able to create it with link() */ if (fs_link(super_fs, path, file->hash_path) < 0) { if (errno == EEXIST) { /* the file was just created. it's probably a duplicate, but it's too much trouble trying to deduplicate it anymore */ } else { i_error("fs-sis: %s", fs_last_error(super_fs)); } } return; } temp_path = t_str_new(256); hash_fname = strrchr(file->hash_path, '/'); if (hash_fname == NULL) hash_fname = file->hash_path; else { str_append_n(temp_path, file->hash_path, (hash_fname-file->hash_path) + 1); hash_fname++; } str_printfa(temp_path, "%s%s.tmp", super_fs->set.temp_file_prefix, hash_fname); /* replace existing hash file atomically */ ret = fs_link(super_fs, path, str_c(temp_path)); if (ret < 0 && errno == EEXIST) { /* either someone's racing us or it's a stale file. try to continue. */ if (fs_unlink(super_fs, str_c(temp_path)) < 0 && errno != ENOENT) i_error("fs-sis: %s", fs_last_error(super_fs)); ret = fs_link(super_fs, path, str_c(temp_path)); } if (ret < 0) { i_error("fs-sis: %s", fs_last_error(super_fs)); return; } if (fs_rename(super_fs, str_c(temp_path), file->hash_path) < 0) { if (errno == ENOENT) { /* apparently someone else just renamed it. ignore. */ } else { i_error("fs-sis: %s", fs_last_error(super_fs)); } (void)fs_unlink(super_fs, str_c(temp_path)); } }
static void stream_data(string_t *str, const unsigned char *data, size_t size) { const char *text; str_truncate(str, 0); str_append_n(str, data, size); text = str_tabunescape(str_c_modifiable(str)); doveadm_print_stream(text, strlen(text)); }
int rfc822_skip_comment(struct rfc822_parser_context *ctx) { const unsigned char *start; int level = 1; i_assert(*ctx->data == '('); if (ctx->last_comment != NULL) str_truncate(ctx->last_comment, 0); start = ++ctx->data; for (; ctx->data != ctx->end; ctx->data++) { switch (*ctx->data) { case '(': level++; break; case ')': if (--level == 0) { if (ctx->last_comment != NULL) { str_append_n(ctx->last_comment, start, ctx->data - start); } ctx->data++; return ctx->data != ctx->end; } break; case '\\': if (ctx->last_comment != NULL) { str_append_n(ctx->last_comment, start, ctx->data - start); } start = ctx->data + 1; ctx->data++; if (ctx->data == ctx->end) return -1; break; } } /* missing ')' */ return -1; }
int rfc822_parse_dot_atom(struct rfc822_parser_context *ctx, string_t *str) { const unsigned char *start; int ret; /* dot-atom = [CFWS] dot-atom-text [CFWS] dot-atom-text = 1*atext *("." 1*atext) atext = ; Any character except controls, SP, and specials. For RFC-822 compatibility allow LWSP around '.' */ if (ctx->data == ctx->end || !IS_ATEXT(*ctx->data)) return -1; for (start = ctx->data++; ctx->data != ctx->end; ) { if (IS_ATEXT(*ctx->data)) { ctx->data++; continue; } str_append_n(str, start, ctx->data - start); if ((ret = rfc822_skip_lwsp(ctx)) <= 0) return ret; if (*ctx->data != '.') return 1; ctx->data++; str_append_c(str, '.'); if ((ret = rfc822_skip_lwsp(ctx)) <= 0) return ret; start = ctx->data; } str_append_n(str, start, ctx->data - start); return 0; }
static void decode_test(const char *qp_input, const char *output, bool broken_input, unsigned int buffer_size) { unsigned int qp_input_len = strlen(qp_input); struct istream *input_data, *input; const unsigned char *data; size_t i, size; string_t *str = t_str_new(32); int ret = 0; input_data = test_istream_create_data(qp_input, qp_input_len); test_istream_set_max_buffer_size(input_data, buffer_size); test_istream_set_allow_eof(input_data, FALSE); input = i_stream_create_qp_decoder(input_data); for (i = 1; i <= qp_input_len; i++) { test_istream_set_size(input_data, i); while ((ret = i_stream_read_more(input, &data, &size)) > 0) { str_append_n(str, data, size); i_stream_skip(input, size); } if (ret == -1 && broken_input) break; test_assert(ret == 0); } if (ret == 0) { test_istream_set_allow_eof(input_data, TRUE); while ((ret = i_stream_read_more(input, &data, &size)) > 0) { str_append_n(str, data, size); i_stream_skip(input, size); } } test_assert(ret == -1); test_assert((input->stream_errno == 0 && !broken_input) || (input->stream_errno == EINVAL && broken_input)); test_assert(strcmp(str_c(str), output) == 0); i_stream_unref(&input); i_stream_unref(&input_data); }
int rfc822_parse_atom(struct rfc822_parser_context *ctx, string_t *str) { const unsigned char *start; /* atom = [CFWS] 1*atext [CFWS] atext = ; Any character except controls, SP, and specials. */ if (ctx->data == ctx->end || !IS_ATEXT(*ctx->data)) return -1; for (start = ctx->data++; ctx->data != ctx->end; ctx->data++) { if (IS_ATEXT(*ctx->data)) continue; str_append_n(str, start, ctx->data - start); return rfc822_skip_lwsp(ctx); } str_append_n(str, start, ctx->data - start); return 0; }
static void auth_cache_key_add_var(string_t *str, const char *data, unsigned int len) { if (str_len(str) > 0) str_append_c(str, '\t'); str_append_c(str, '%'); if (len == 1) str_append_c(str, data[0]); else { str_append_c(str, '{'); str_append_n(str, data, len); str_append_c(str, '}'); } }
static void test_str_append_n(void) { string_t *str = t_str_new(32); test_begin("str_append_n()"); str_append_n(str, "foo", 0); test_assert(str->used == 0); str_append_n(str, "\0foo", 4); test_assert(str->used == 0); str_append_n(str, "foo", 3); test_assert(str->used == 3 && memcmp(str_data(str), "foo", 3) == 0); str_truncate(str, 0); str_append_n(str, "foo", 2); test_assert(str->used == 2 && memcmp(str_data(str), "fo", 2) == 0); str_truncate(str, 0); str_append_n(str, "foo\0bar", 7); test_assert(str->used == 3 && memcmp(str_data(str), "foo", 3) == 0); str_truncate(str, 0); test_end(); }
static int rfc822_parse_atom_or_dot(struct rfc822_parser_context *ctx, string_t *str) { const unsigned char *start; /* atom = [CFWS] 1*atext [CFWS] atext = ; Any character except controls, SP, and specials. The difference between this function and rfc822_parse_dot_atom() is that this doesn't just silently skip over all the whitespace. */ for (start = ctx->data; ctx->data != ctx->end; ctx->data++) { if (IS_ATEXT(*ctx->data) || *ctx->data == '.') continue; str_append_n(str, start, ctx->data - start); return rfc822_skip_lwsp(ctx); } str_append_n(str, start, ctx->data - start); return 0; }
int rfc822_parse_quoted_string(struct rfc822_parser_context *ctx, string_t *str) { const unsigned char *start; size_t len; i_assert(*ctx->data == '"'); ctx->data++; for (start = ctx->data; ctx->data != ctx->end; ctx->data++) { switch (*ctx->data) { case '"': str_append_n(str, start, ctx->data - start); ctx->data++; return rfc822_skip_lwsp(ctx); case '\n': /* folding whitespace, remove the (CR)LF */ len = ctx->data - start; if (len > 0 && start[len-1] == '\r') len--; str_append_n(str, start, len); start = ctx->data + 1; break; case '\\': ctx->data++; if (ctx->data == ctx->end) return -1; str_append_n(str, start, ctx->data - start); start = ctx->data; break; } } /* missing '"' */ return -1; }
const char *str_tabescape(const char *str) { string_t *tmp; const char *p; for (p = str; *p != '\0'; p++) { if (*p <= '\r') { tmp = t_str_new(128); str_append_n(tmp, str, p-str); str_append_tabescaped(tmp, p); return str_c(tmp); } } return str; }
static int uri_parse_ip_literal(struct uri_parser *parser, string_t *literal, struct in6_addr *ip6_r) { const unsigned char *p; const char *address; int ret; /* IP-literal = "[" ( IPv6address / IPvFuture ) "]" * IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) * IPv6address = ; Syntax not relevant: parsed using inet_pton() */ /* "[" already verified */ /* Scan for end of address */ for (p = parser->cur+1; p < parser->end; p++) { if (*p == ']') break; } if (p >= parser->end || *p != ']') { parser->error = "Expecting ']' at end of IP-literal"; return -1; } if (literal != NULL) str_append_n(literal, parser->cur, p-parser->cur+1); address = t_strdup_until(parser->cur+1, p); parser->cur = p + 1; if (*address == '\0') { parser->error = "Empty IPv6 host address"; return -1; } if (*address == 'v') { parser->error = t_strdup_printf( "Future IP host address '%s' not supported", address); return -1; } if ((ret = inet_pton(AF_INET6, address, ip6_r)) <= 0) { parser->error = t_strdup_printf( "Invalid IPv6 host address '%s'", address); return -1; } return 1; }
static void server_flush_field(struct server_connection *conn, string_t *str, const unsigned char *data, size_t size) { if (conn->streaming) { conn->streaming = FALSE; if (size > 0) stream_data(str, data, size); doveadm_print_stream("", 0); } else { const char *text; str_truncate(str, 0); str_append_n(str, data, size); text = str_tabunescape(str_c_modifiable(str)); doveadm_print(text); } }
const char *str_sanitize(const char *src, size_t max_len) { string_t *str; size_t i; if (src == NULL) return NULL; i = str_sanitize_skip_start(src, max_len); if (src[i] == '\0') return src; str = t_str_new(I_MIN(max_len, 256)); str_append_n(str, src, i); str_sanitize_append(str, src + i, max_len - i); return str_c(str); }
/* push current expression */ static void push_expr(ParseCtx *ctx) { STR_DEFINE(expr_text, STR_SIZE); Expr *expr; Sym *expr_p; Bool last_was_prefix; /* build expression text - split constant prefixes from numbers and names */ str_clear(expr_text); last_was_prefix = FALSE; for (expr_p = ctx->expr_start; expr_p < ctx->p; expr_p++) { if (last_was_prefix && expr_p->tlen > 0 && (isalnum(*expr_p->tstart) || *expr_p->tstart == '"')) { str_append_char(expr_text, ' '); last_was_prefix = FALSE; } str_append_n(expr_text, expr_p->tstart, expr_p->tlen); if (expr_p->tlen > 0) { switch (expr_p->tstart[expr_p->tlen - 1]) { case '@': case '%': case '$': last_was_prefix = TRUE; break; default: last_was_prefix = FALSE; } } } /* parse expression */ expr = parse_expr(str_data(expr_text)); /* push the new expression, or NULL on error */ utarray_push_back(ctx->exprs, &expr); STR_DELETE(expr_text); }
void str_append_tabunescaped(string_t *dest, const void *src, size_t src_size) { const unsigned char *src_c = src; size_t start = 0, i = 0; while (i < src_size) { for (; i < src_size; i++) { if (src_c[i] == '\001') break; } str_append_n(dest, src_c + start, i-start); if (i < src_size) { i++; if (i < src_size) { switch (src_c[i]) { case '0': str_append_c(dest, '\000'); break; case '1': str_append_c(dest, '\001'); break; case 't': str_append_c(dest, '\t'); break; case 'r': str_append_c(dest, '\r'); break; case 'n': str_append_c(dest, '\n'); break; default: str_append_c(dest, src_c[i]); break; } i++; } } start = i; } }
static int http_header_parse_name(struct http_header_parser *parser) { const unsigned char *first = parser->cur; /* field-name = token token = 1*tchar */ while (parser->cur < parser->end && http_char_is_token(*parser->cur)) parser->cur++; str_append_n(parser->name, first, parser->cur-first); if (parser->cur == parser->end) return 0; if (str_len(parser->name) == 0) { parser->error = "Empty header field name"; return -1; } return 1; }
void smtp_xtext_encode(string_t *out, const unsigned char *data, size_t size) { const unsigned char *p, *pbegin, *pend; p = data; pend = p + size; while (p < pend) { pbegin = p; while (p < pend && smtp_char_is_xtext(*p)) p++; str_append_n(out, pbegin, p-pbegin); if (p >= pend) break; str_printfa(out, "+%02X", (unsigned int)*p); p++; } }
void str_append_unescaped(string_t *dest, const void *src, size_t src_size) { const unsigned char *src_c = src; size_t start = 0, i = 0; while (i < src_size) { for (; i < src_size; i++) { if (src_c[i] == '\\') break; } str_append_n(dest, src_c + start, i-start); if (i < src_size) { if (++i == src_size) break; str_append_c(dest, src_c[i++]); } start = i; } }
void smtp_string_write(string_t *out, const char *value) { bool quoted = FALSE; const unsigned char *p, *pend, *pblock; size_t begin = str_len(out); if (value == NULL) return; p = (const unsigned char *)value; pend = p + strlen(value); while (p < pend) { pblock = p; while (p < pend && smtp_char_is_atext(*p)) p++; if (!quoted && p < pend) { quoted = TRUE; str_insert(out, begin, "\""); } str_append_n(out, pblock, p-pblock); if (p >= pend) break; i_assert(quoted); i_assert(smtp_char_is_qpair(*p)); if (!smtp_char_is_qtext(*p)) str_append_c(out, '\\'); str_append_c(out, *p); p++; } if (quoted) str_append_c(out, '\"'); }