static svn_error_t * cdata_handler(svn_ra_serf__xml_parser_t *parser, void *userData, const char *data, apr_size_t len) { mergeinfo_context_t *mergeinfo_ctx = userData; mergeinfo_state_e state; state = parser->state->current_state; switch (state) { case MERGEINFO_PATH: if (mergeinfo_ctx->curr_path) svn_stringbuf_appendbytes(mergeinfo_ctx->curr_path, data, len); break; case MERGEINFO_INFO: if (mergeinfo_ctx->curr_info) svn_stringbuf_appendbytes(mergeinfo_ctx->curr_info, data, len); break; default: break; } return SVN_NO_ERROR; }
/* Append the concrete representation of SKEL to the string STR. Grow S with new space from POOL as necessary. */ static svn_stringbuf_t * unparse(const svn_skel_t *skel, svn_stringbuf_t *str, apr_pool_t *pool) { if (skel->is_atom) { /* Append an atom to STR. */ if (use_implicit(skel)) svn_stringbuf_appendbytes(str, skel->data, skel->len); else { /* Append the length to STR. */ char buf[200]; int length_len; length_len = putsize(buf, sizeof(buf), skel->len); SVN_ERR_ASSERT_NO_RETURN(length_len > 0); /* Make sure we have room for the length, the space, and the atom's contents. */ svn_stringbuf_ensure(str, str->len + length_len + 1 + skel->len); svn_stringbuf_appendbytes(str, buf, length_len); str->data[str->len++] = ' '; svn_stringbuf_appendbytes(str, skel->data, skel->len); } } else { /* Append a list to STR. */ svn_skel_t *child; /* Emit an opening parenthesis. */ svn_stringbuf_ensure(str, str->len + 1); str->data[str->len++] = '('; /* Append each element. Emit a space between each pair of elements. */ for (child = skel->children; child; child = child->next) { unparse(child, str, pool); if (child->next) { svn_stringbuf_ensure(str, str->len + 1); str->data[str->len++] = ' '; } } /* Emit a closing parenthesis. */ svn_stringbuf_appendbyte(str, ')'); } return str; }
/* Append to STR an implicit-length atom consisting of the byte BYTE, terminated by the character TERM. BYTE must be a name byte, and TERM must be a valid skel separator, or NULL. */ static void put_implicit_length_byte(svn_stringbuf_t *str, char byte, char term) { if (! skel_is_name(byte)) abort(); if (term != '\0' && ! skel_is_space(term) && ! skel_is_paren(term)) abort(); svn_stringbuf_appendbytes(str, &byte, 1); if (term != '\0') svn_stringbuf_appendbytes(str, &term, 1); }
/* If IN is a string that is >= MIN_COMPRESS_SIZE and the COMPRESSION_LEVEL is not SVN_DELTA_COMPRESSION_LEVEL_NONE, zlib compress it and places the result in OUT, with an integer prepended specifying the original size. If IN is < MIN_COMPRESS_SIZE, or if the compressed version of IN was no smaller than the original IN, OUT will be a copy of IN with the size prepended as an integer. */ static svn_error_t * zlib_encode(const char *data, apr_size_t len, svn_stringbuf_t *out, int compression_level) { unsigned long endlen; apr_size_t intlen; unsigned char buf[SVN__MAX_ENCODED_UINT_LEN], *p; svn_stringbuf_setempty(out); p = svn__encode_uint(buf, (apr_uint64_t)len); svn_stringbuf_appendbytes(out, (const char *)buf, p - buf); intlen = out->len; /* Compression initialization overhead is considered to large for short buffers. Also, if we don't actually want to compress data, ZLIB will produce an output no shorter than the input. Hence, the DATA would directly appended to OUT, so we can do that directly without calling ZLIB before. */ if (len < MIN_COMPRESS_SIZE || compression_level == SVN__COMPRESSION_NONE) { svn_stringbuf_appendbytes(out, data, len); } else { int zerr; svn_stringbuf_ensure(out, svnCompressBound(len) + intlen); endlen = out->blocksize; zerr = compress2((unsigned char *)out->data + intlen, &endlen, (const unsigned char *)data, len, compression_level); if (zerr != Z_OK) return svn_error_trace(svn_error__wrap_zlib( zerr, "compress2", _("Compression of svndiff data failed"))); /* Compression didn't help :(, just append the original text */ if (endlen >= len) { svn_stringbuf_appendbytes(out, data, len); return SVN_NO_ERROR; } out->len = endlen + intlen; out->data[out->len] = 0; } return SVN_NO_ERROR; }
/* Read a field, possibly with escaped bytes, from [*BUF, END), stopping at the terminator. Place the read string in *RESULT, or set *RESULT to NULL if it is the empty string. Allocate the returned string in POOL. Advance *BUF to point after the terminator. */ static svn_error_t * read_str(const char **result, char **buf, const char *end, apr_pool_t *pool) { svn_stringbuf_t *s = NULL; const char *start; if (*buf == end) return svn_error_create(SVN_ERR_WC_CORRUPT, NULL, _("Unexpected end of entry")); if (**buf == '\n') { *result = NULL; (*buf)++; return SVN_NO_ERROR; } start = *buf; while (*buf != end && **buf != '\n') { if (**buf == '\\') { char c; if (! s) s = svn_stringbuf_ncreate(start, *buf - start, pool); else svn_stringbuf_appendbytes(s, start, *buf - start); (*buf)++; SVN_ERR(read_escaped(&c, buf, end)); svn_stringbuf_appendbyte(s, c); start = *buf; } else (*buf)++; } if (*buf == end) return svn_error_create(SVN_ERR_WC_CORRUPT, NULL, _("Unexpected end of entry")); if (s) { svn_stringbuf_appendbytes(s, start, *buf - start); *result = s->data; } else *result = apr_pstrndup(pool, start, *buf - start); (*buf)++; return SVN_NO_ERROR; }
/* Append to STR an implicit-length atom containing every character that's legal in such atoms, terminated by the valid atom terminator TERM. */ static void put_implicit_length_all_chars(svn_stringbuf_t *str, char term) { apr_size_t len; char *name = gen_implicit_length_all_chars(&len); if (term != '\0' && ! skel_is_space(term) && ! skel_is_paren(term)) abort(); svn_stringbuf_appendbytes(str, name, len); if (term != '\0') svn_stringbuf_appendbytes(str, &term, 1); }
svn_error_t * svn_string_from_stream(svn_string_t **result, svn_stream_t *stream, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_stringbuf_t *work = svn_stringbuf_create_ensure(SVN__STREAM_CHUNK_SIZE, result_pool); char *buffer = apr_palloc(scratch_pool, SVN__STREAM_CHUNK_SIZE); while (1) { apr_size_t len = SVN__STREAM_CHUNK_SIZE; SVN_ERR(svn_stream_read(stream, buffer, &len)); svn_stringbuf_appendbytes(work, buffer, len); if (len < SVN__STREAM_CHUNK_SIZE) break; } SVN_ERR(svn_stream_close(stream)); *result = apr_palloc(result_pool, sizeof(**result)); (*result)->data = work->data; (*result)->len = work->len; return SVN_NO_ERROR; }
/* Generate a string of exactly LEN chars (plus terminating NUL). KEY is * an arbitrary integer that will be transformed into a character sequence * using entries of BASIC_STRINGS. The result will be allocated in POOL. */ static svn_stringbuf_t * generate_string(apr_uint64_t key, apr_size_t len, apr_pool_t *pool) { svn_stringbuf_t *result = svn_stringbuf_create_ensure(len, pool); apr_uint64_t temp = key; apr_uint64_t run = 0; while (len) { apr_size_t idx; apr_size_t add_len; if (temp == 0) { temp = key; run++; } idx = (temp + run) % STRING_COUNT; temp /= STRING_COUNT; add_len = strlen(basic_strings[idx]); add_len = MIN(len, add_len); svn_stringbuf_appendbytes(result, basic_strings[idx], add_len); len -= add_len; } return result; }
static svn_error_t * cdata_handler(void *baton, int state, const char *cdata, size_t len) { replay_baton_t *rb = baton; apr_size_t nlen = len; switch (state) { case ELEM_apply_textdelta: SVN_ERR(svn_stream_write(rb->base64_decoder, cdata, &nlen)); if (nlen != len) return svn_error_createf (SVN_ERR_STREAM_UNEXPECTED_EOF, NULL, _("Error writing stream: unexpected EOF")); break; case ELEM_change_dir_prop: case ELEM_change_file_prop: if (! rb->prop_accum) return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL, _("Got cdata content for a prop delete")); else svn_stringbuf_appendbytes(rb->prop_accum, cdata, len); break; } return SVN_NO_ERROR; }
static svn_error_t * write_fn (void *baton, const char *data, apr_size_t *len) { svn_stringbuf_appendbytes (baton, data, *len); return SVN_NO_ERROR; }
static svn_error_t * test_stream_base64(apr_pool_t *pool) { svn_stream_t *stream; svn_stringbuf_t *actual = svn_stringbuf_create_empty(pool); svn_stringbuf_t *expected = svn_stringbuf_create_empty(pool); int i; static const char *strings[] = { "fairly boring test data... blah blah", "A", "abc", "012345679", NULL }; stream = svn_stream_from_stringbuf(actual, pool); stream = svn_base64_decode(stream, pool); stream = svn_base64_encode(stream, pool); for (i = 0; strings[i]; i++) { apr_size_t len = strlen(strings[i]); svn_stringbuf_appendbytes(expected, strings[i], len); SVN_ERR(svn_stream_write(stream, strings[i], &len)); } SVN_ERR(svn_stream_close(stream)); SVN_TEST_STRING_ASSERT(actual->data, expected->data); return SVN_NO_ERROR; }
/* Append the concrete representation of SKEL to the string STR. */ static svn_stringbuf_t * unparse(const svn_skel_t *skel, svn_stringbuf_t *str) { if (skel->is_atom) { /* Append an atom to STR. */ if (use_implicit(skel)) svn_stringbuf_appendbytes(str, skel->data, skel->len); else { /* Append the length to STR. Ensure enough space for at least * one 64 bit int. */ char buf[200 + SVN_INT64_BUFFER_SIZE]; apr_size_t length_len; length_len = svn__ui64toa(buf, skel->len); SVN_ERR_ASSERT_NO_RETURN(length_len > 0); /* Make sure we have room for the length, the space, and the atom's contents. */ svn_stringbuf_ensure(str, str->len + length_len + 1 + skel->len); svn_stringbuf_appendbytes(str, buf, length_len); svn_stringbuf_appendbyte(str, ' '); svn_stringbuf_appendbytes(str, skel->data, skel->len); } } else { /* Append a list to STR: an opening parenthesis, the list elements * separated by a space, and a closing parenthesis. */ svn_skel_t *child; svn_stringbuf_appendbyte(str, '('); for (child = skel->children; child; child = child->next) { unparse(child, str); if (child->next) svn_stringbuf_appendbyte(str, ' '); } svn_stringbuf_appendbyte(str, ')'); } return str; }
static svn_error_t * write_handler_stringbuf(void *baton, const char *data, apr_size_t *len) { struct stringbuf_stream_baton *btn = baton; svn_stringbuf_appendbytes(btn->str, data, *len); return SVN_NO_ERROR; }
char * svn_cstring_join(const apr_array_header_t *strings, const char *separator, apr_pool_t *pool) { svn_stringbuf_t *new_str = svn_stringbuf_create("", pool); int sep_len = strlen(separator); int i; for (i = 0; i < strings->nelts; i++) { const char *string = APR_ARRAY_IDX(strings, i, const char *); svn_stringbuf_appendbytes(new_str, string, strlen(string)); svn_stringbuf_appendbytes(new_str, separator, sep_len); } return new_str->data; }
static svn_error_t * verify_expected_record(svn_fs_t *fs, const char *key, const char *expected_text, apr_size_t expected_len, trail_t *trail) { apr_size_t size; char buf[100]; svn_stringbuf_t *text; svn_filesize_t offset = 0; svn_filesize_t string_size; /* Check the string size. */ SVN_ERR(svn_fs_bdb__string_size(&string_size, fs, key, trail, trail->pool)); if (string_size > SVN_MAX_OBJECT_SIZE) return svn_error_createf(SVN_ERR_FS_GENERAL, NULL, "record size is too large " "(got %" SVN_FILESIZE_T_FMT ", " "limit is %" APR_SIZE_T_FMT ")", string_size, SVN_MAX_OBJECT_SIZE); size = (apr_size_t) string_size; if (size != expected_len) return svn_error_createf(SVN_ERR_FS_GENERAL, NULL, "record has unexpected size " "(got %" APR_SIZE_T_FMT ", " "expected %" APR_SIZE_T_FMT ")", size, expected_len); /* Read the string back in 100-byte chunks. */ text = svn_stringbuf_create_empty(trail->pool); while (1) { size = sizeof(buf); SVN_ERR(svn_fs_bdb__string_read(fs, key, buf, offset, &size, trail, trail->pool)); if (size == 0) break; svn_stringbuf_appendbytes(text, buf, size); offset += size; } /* Check the size and contents of the read data. */ if (text->len != expected_len) return svn_error_createf(SVN_ERR_FS_GENERAL, NULL, "record read returned unexpected size " "(got %" APR_SIZE_T_FMT ", " "expected %" APR_SIZE_T_FMT ")", size, expected_len); if (memcmp(expected_text, text->data, expected_len)) return svn_error_create(SVN_ERR_FS_GENERAL, NULL, "record read returned unexpected data"); return SVN_NO_ERROR; }
/* WARNING - Optimized code ahead! * This function has been hand-tuned for performance. Please read * the comments below before modifying the code. */ void svn_stringbuf_appendbyte(svn_stringbuf_t *str, char byte) { char *dest; apr_size_t old_len = str->len; /* In most cases, there will be pre-allocated memory left * to just write the new byte at the end of the used section * and terminate the string properly. */ if (str->blocksize > old_len + 1) { /* The following read does not depend this write, so we * can issue the write first to minimize register pressure: * The value of old_len+1 is no longer needed; on most processors, * dest[old_len+1] will be calculated implicitly as part of * the addressing scheme. */ str->len = old_len+1; /* Since the compiler cannot be sure that *src->data and *src * don't overlap, we read src->data *once* before writing * to *src->data. Replacing dest with str->data would force * the compiler to read it again after the first byte. */ dest = str->data; /* If not already available in a register as per ABI, load * "byte" into the register (e.g. the one freed from old_len+1), * then write it to the string buffer and terminate it properly. * * Including the "byte" fetch, all operations so far could be * issued at once and be scheduled at the CPU's descression. * Most likely, no-one will soon depend on the data that will be * written in this function. So, no stalls there, either. */ dest[old_len] = byte; dest[old_len+1] = '\0'; } else { /* we need to re-allocate the string buffer * -> let the more generic implementation take care of that part */ /* Depending on the ABI, "byte" is a register value. If we were * to take its address directly, the compiler might decide to * put in on the stack *unconditionally*, even if that would * only be necessary for this block. */ char b = byte; svn_stringbuf_appendbytes(str, &b, 1); } }
svn_error_t * svn_ra_neon__xml_collect_cdata(void *baton, int state, const char *cdata, size_t len) { svn_stringbuf_t **b = baton; if (*b) svn_stringbuf_appendbytes(*b, cdata, len); return SVN_NO_ERROR; }
static int collect_error_cdata(void *baton, int state, const char *cdata, size_t len) { svn_stringbuf_t **b = baton; if (*b) svn_stringbuf_appendbytes(*b, cdata, len); return 0; }
/* Append the end of a list to STR, using LEN bytes of the whitespace character SPACE. */ static void put_list_end(svn_stringbuf_t *str, char space, int len) { int i; if (len > 0 && ! skel_is_space(space)) abort(); for (i = 0; i < len; i++) svn_stringbuf_appendbytes(str, &space, 1); svn_stringbuf_appendcstr(str, ")"); }
static svn_error_t * cdata_handler(void *baton, int state, const char *cdata, size_t len) { struct mergeinfo_baton *mb = baton; apr_size_t nlen = len; switch (state) { case ELEM_mergeinfo_path: svn_stringbuf_appendbytes(mb->curr_path, cdata, nlen); break; case ELEM_mergeinfo_info: svn_stringbuf_appendbytes(mb->curr_info, cdata, nlen); break; default: break; } return mb->err; }
/* Take the ORIGINAL string and replace all occurrences of ":" without * limiting the key space. Allocate the result in POOL. */ static const char * normalize_key_part(const char *original, apr_pool_t *pool) { apr_size_t i; apr_size_t len = strlen(original); svn_stringbuf_t *normalized = svn_stringbuf_create_ensure(len, pool); for (i = 0; i < len; ++i) { char c = original[i]; switch (c) { case ':': svn_stringbuf_appendbytes(normalized, "%_", 2); break; case '%': svn_stringbuf_appendbytes(normalized, "%%", 2); break; default : svn_stringbuf_appendbyte(normalized, c); } } return normalized->data; }
static svn_error_t * wrapped_receiver(void *baton, apr_int64_t line_no, svn_revnum_t revision, const char *author, const char *date, const char *line, apr_pool_t *pool) { struct wrapped_receiver_baton_s *b = baton; svn_stringbuf_t *expanded_line = svn_stringbuf_create(line, pool); svn_stringbuf_appendbytes(expanded_line, "\r", 1); return b->orig_receiver(b->orig_baton, line_no, revision, author, date, expanded_line->data, pool); }
/* Append to STR the representation of the atom containing the LEN bytes at DATA, in explicit-length form, using SEP as the separator between the length and the data. */ static void put_explicit_length(svn_stringbuf_t *str, const char *data, apr_size_t len, char sep) { char *buf = malloc(len + 100); apr_size_t length_len; if (! skel_is_space(sep)) abort(); /* Generate the length and separator character. */ sprintf(buf, "%"APR_SIZE_T_FMT"%c", len, sep); length_len = strlen(buf); /* Copy in the real data (which may contain nulls). */ memcpy(buf + length_len, data, len); svn_stringbuf_appendbytes(str, buf, length_len + len); free(buf); }
/* Escape all non-ascii or control characters similar to * svn_xml_fuzzy_escape() and svn_utf_cstring_from_utf8_fuzzy(). * All of the encoding formats somewhat overlap with ascii (BMPString * and UniversalString are actually always wider so you'll end up * with a bunch of escaped nul bytes, but ideally we don't get here * for those). The result is always a nul-terminated C string. */ static const char * fuzzy_escape(const svn_string_t *src, apr_pool_t *result_pool) { const char *end = src->data + src->len; const char *p = src->data, *q; svn_stringbuf_t *outstr; char escaped_char[6]; /* ? \ u u u \0 */ for (q = p; q < end; q++) { if (!svn_ctype_isascii(*q) || svn_ctype_iscntrl(*q)) break; } if (q == end) return src->data; outstr = svn_stringbuf_create_empty(result_pool); while (1) { q = p; /* Traverse till either unsafe character or eos. */ while (q < end && svn_ctype_isascii(*q) && !svn_ctype_iscntrl(*q)) q++; /* copy chunk before marker */ svn_stringbuf_appendbytes(outstr, p, q - p); if (q == end) break; apr_snprintf(escaped_char, sizeof(escaped_char), "?\\%03u", (unsigned char) *q); svn_stringbuf_appendcstr(outstr, escaped_char); p = q + 1; } return outstr->data; }
static svn_error_t * test5(const char **msg, svn_boolean_t msg_only, svn_test_opts_t *opts, apr_pool_t *pool) { *msg = "append bytes, then compare two strings"; if (msg_only) return SVN_NO_ERROR; a = svn_stringbuf_create(phrase_1, pool); svn_stringbuf_appendbytes(a, "new bytes to append", 9); /* Test that length, data, and null-termination are correct. */ if (svn_stringbuf_compare (a, svn_stringbuf_create("hello, new bytes", pool))) return SVN_NO_ERROR; else return fail(pool, "test failed"); }
/* This implements the `svn_ra_svn__cdata_cb_t' prototype. */ static svn_error_t * getlocks_cdata_handler(void *userdata, int state, const char *cdata, size_t len) { get_locks_baton_t *baton = userdata; switch(state) { case ELEM_lock_path: case ELEM_lock_token: case ELEM_lock_owner: case ELEM_lock_comment: case ELEM_lock_creationdate: case ELEM_lock_expirationdate: /* accumulate cdata in the scratchpool. */ svn_stringbuf_appendbytes(baton->cdata_accum, cdata, len); break; } return SVN_NO_ERROR; }
/* Escape only NUL characters from a string that is presumed to * be UTF-8 encoded and return a nul-terminated C string. */ static const char * nul_escape(const svn_string_t *src, apr_pool_t *result_pool) { const char *end = src->data + src->len; const char *p = src->data, *q; svn_stringbuf_t *outstr; for (q = p; q < end; q++) { if (*q == '\0') break; } if (q == end) return src->data; outstr = svn_stringbuf_create_empty(result_pool); while (1) { q = p; /* Traverse till either unsafe character or eos. */ while (q < end && *q != '\0') q++; /* copy chunk before marker */ svn_stringbuf_appendbytes(outstr, p, q - p); if (q == end) break; svn_stringbuf_appendcstr(outstr, "?\\000"); p = q + 1; } return outstr->data; }
void svn_stringbuf_appendcstr(svn_stringbuf_t *targetstr, const char *cstr) { svn_stringbuf_appendbytes(targetstr, cstr, strlen(cstr)); }
void svn_stringbuf_appendstr(svn_stringbuf_t *targetstr, const svn_stringbuf_t *appendstr) { svn_stringbuf_appendbytes(targetstr, appendstr->data, appendstr->len); }
svn_error_t * SVNAuthData::cleanup_callback(svn_boolean_t *delete_cred, void *cleanup_baton, const char *cred_kind, const char *realmstring, apr_hash_t * hash, apr_pool_t * scratch_pool) { std::tuple<std::vector<std::tuple<CString, CString, SVNAuthDataInfo>>*, std::vector<std::tuple<CString, CString, SVNAuthDataInfo>>> * tupleBaton = (std::tuple<std::vector<std::tuple<CString, CString, SVNAuthDataInfo>>*, std::vector<std::tuple<CString, CString, SVNAuthDataInfo>>>*)cleanup_baton; auto authList = std::get<0>(*tupleBaton); auto delList = std::get<1>(*tupleBaton); CString s1, s2; if (cred_kind) s1 = CUnicodeUtils::GetUnicode(cred_kind); if (realmstring) s2 = CUnicodeUtils::GetUnicode(realmstring); SVNAuthDataInfo authinfodata; for (apr_hash_index_t *hi = apr_hash_first(scratch_pool, hash); hi; hi = apr_hash_next(hi)) { const void *vkey; void *val; apr_hash_this(hi, &vkey, NULL, &val); const char * key = (const char*)vkey; svn_string_t *value = (svn_string_t *)val; if (strcmp(key, SVN_CONFIG_AUTHN_PASSWORD_KEY) == 0) { CStringA data(value->data, (int)value->len); authinfodata.password = CUnicodeUtils::GetUnicode(data); } else if (strcmp(key, SVN_CONFIG_AUTHN_PASSPHRASE_KEY) == 0) { CStringA data(value->data, (int)value->len); authinfodata.passphrase = CUnicodeUtils::GetUnicode(data); } else if (strcmp(key, SVN_CONFIG_AUTHN_PASSTYPE_KEY) == 0) { CStringA data(value->data, (int)value->len); authinfodata.passtype = CUnicodeUtils::GetUnicode(data); } else if (strcmp(key, SVN_CONFIG_AUTHN_USERNAME_KEY) == 0) { CStringA data(value->data, (int)value->len); authinfodata.username = CUnicodeUtils::GetUnicode(data); } else if (strcmp(key, SVN_CONFIG_AUTHN_ASCII_CERT_KEY) == 0) { const svn_string_t * der_cert = nullptr; svn_x509_certinfo_t * certinfo = nullptr; const apr_array_header_t * hostnames = nullptr; svn_error_t *err; /* Convert header-less PEM to DER by undoing base64 encoding. */ der_cert = svn_base64_decode_string(value, scratch_pool); err = svn_x509_parse_cert(&certinfo, der_cert->data, der_cert->len, scratch_pool, scratch_pool); if (err) continue; authinfodata.subject = svn_x509_certinfo_get_subject(certinfo, scratch_pool); authinfodata.validfrom = svn_time_to_human_cstring(svn_x509_certinfo_get_valid_from(certinfo), scratch_pool); authinfodata.validuntil = svn_time_to_human_cstring(svn_x509_certinfo_get_valid_to(certinfo), scratch_pool); authinfodata.issuer = svn_x509_certinfo_get_issuer(certinfo, scratch_pool); authinfodata.fingerprint = svn_checksum_to_cstring_display(svn_x509_certinfo_get_digest(certinfo), scratch_pool); hostnames = svn_x509_certinfo_get_hostnames(certinfo); if (hostnames && !apr_is_empty_array(hostnames)) { int i; svn_stringbuf_t *buf = svn_stringbuf_create_empty(scratch_pool); for (i = 0; i < hostnames->nelts; ++i) { const char *hostname = APR_ARRAY_IDX(hostnames, i, const char*); if (i > 0) svn_stringbuf_appendbytes(buf, ", ", 2); svn_stringbuf_appendbytes(buf, hostname, strlen(hostname)); } authinfodata.hostname = buf->data; } } else if (strcmp(key, SVN_CONFIG_AUTHN_FAILURES_KEY) == 0)