diff --git a/libavformat/httpauth.c b/libavformat/httpauth.c index 47db46b8ac..58e0e82ed1 100644 --- a/libavformat/httpauth.c +++ b/libavformat/httpauth.c @@ -28,62 +28,6 @@ #include "avformat.h" #include -static void parse_key_value(const char *params, - void (*callback_get_buf)(HTTPAuthState *state, - const char *key, int key_len, - char **dest, int *dest_len), HTTPAuthState *state) -{ - const char *ptr = params; - - /* Parse key=value pairs. */ - for (;;) { - const char *key; - char *dest = NULL, *dest_end; - int key_len, dest_len = 0; - - /* Skip whitespace and potential commas. */ - while (*ptr && (isspace(*ptr) || *ptr == ',')) - ptr++; - if (!*ptr) - break; - - key = ptr; - - if (!(ptr = strchr(key, '='))) - break; - ptr++; - key_len = ptr - key; - - callback_get_buf(state, key, key_len, &dest, &dest_len); - dest_end = dest + dest_len - 1; - - if (*ptr == '\"') { - ptr++; - while (*ptr && *ptr != '\"') { - if (*ptr == '\\') { - if (!ptr[1]) - break; - if (dest && dest < dest_end) - *dest++ = ptr[1]; - ptr += 2; - } else { - if (dest && dest < dest_end) - *dest++ = *ptr; - ptr++; - } - } - if (*ptr == '\"') - ptr++; - } else { - for (; *ptr && !(isspace(*ptr) || *ptr == ','); ptr++) - if (dest && dest < dest_end) - *dest++ = *ptr; - } - if (dest) - *dest = 0; - } -} - static void handle_basic_params(HTTPAuthState *state, const char *key, int key_len, char **dest, int *dest_len) { @@ -149,18 +93,21 @@ void ff_http_auth_handle_header(HTTPAuthState *state, const char *key, state->auth_type <= HTTP_AUTH_BASIC) { state->auth_type = HTTP_AUTH_BASIC; state->realm[0] = 0; - parse_key_value(p, handle_basic_params, state); + ff_parse_key_value(p, (ff_parse_key_val_cb) handle_basic_params, + state); } else if (av_stristart(value, "Digest ", &p) && state->auth_type <= HTTP_AUTH_DIGEST) { state->auth_type = HTTP_AUTH_DIGEST; memset(&state->digest_params, 0, sizeof(DigestParams)); state->realm[0] = 0; - parse_key_value(p, handle_digest_params, state); + ff_parse_key_value(p, (ff_parse_key_val_cb) handle_digest_params, + state); choose_qop(state->digest_params.qop, sizeof(state->digest_params.qop)); } } else if (!strcmp(key, "Authentication-Info")) { - parse_key_value(value, handle_digest_update, state); + ff_parse_key_value(value, (ff_parse_key_val_cb) handle_digest_update, + state); } } diff --git a/libavformat/internal.h b/libavformat/internal.h index 6d3ec23767..1b33fb153a 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -192,4 +192,28 @@ int ff_get_line(ByteIOContext *s, char *buf, int maxlen); #define SPACE_CHARS " \t\r\n" +/** + * Callback function type for ff_parse_key_value. + * + * @param key a pointer to the key + * @param key_len the number of bytes that belong to the key, including the '=' + * char + * @param dest return the destination pointer for the value in *dest, may + * be null to ignore the value + * @param dest_len the length of the *dest buffer + */ +typedef void (*ff_parse_key_val_cb)(void *context, const char *key, + int key_len, char **dest, int *dest_len); +/** + * Parse a string with comma-separated key=value pairs. The value strings + * may be quoted and may contain escaped characters within quoted strings. + * + * @param str the string to parse + * @param callback_get_buf function that returns where to store the + * unescaped value string. + * @param context the opaque context pointer to pass to callback_get_buf + */ +void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf, + void *context); + #endif /* AVFORMAT_INTERNAL_H */ diff --git a/libavformat/utils.c b/libavformat/utils.c index 3fe5eaf635..117179715c 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -3707,3 +3707,57 @@ int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt, return av_write_frame(dst, &local_pkt); } +void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf, + void *context) +{ + const char *ptr = str; + + /* Parse key=value pairs. */ + for (;;) { + const char *key; + char *dest = NULL, *dest_end; + int key_len, dest_len = 0; + + /* Skip whitespace and potential commas. */ + while (*ptr && (isspace(*ptr) || *ptr == ',')) + ptr++; + if (!*ptr) + break; + + key = ptr; + + if (!(ptr = strchr(key, '='))) + break; + ptr++; + key_len = ptr - key; + + callback_get_buf(context, key, key_len, &dest, &dest_len); + dest_end = dest + dest_len - 1; + + if (*ptr == '\"') { + ptr++; + while (*ptr && *ptr != '\"') { + if (*ptr == '\\') { + if (!ptr[1]) + break; + if (dest && dest < dest_end) + *dest++ = ptr[1]; + ptr += 2; + } else { + if (dest && dest < dest_end) + *dest++ = *ptr; + ptr++; + } + } + if (*ptr == '\"') + ptr++; + } else { + for (; *ptr && !(isspace(*ptr) || *ptr == ','); ptr++) + if (dest && dest < dest_end) + *dest++ = *ptr; + } + if (dest) + *dest = 0; + } +} +