[vlc-commits] https: fold multiple header fields with identical names
Rémi Denis-Courmont
git at videolan.org
Sat Dec 19 21:59:57 CET 2015
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sat Dec 19 22:31:11 2015 +0200| [5a4d40028cff28a8f40e510755beeaed24478ba1] | committer: Rémi Denis-Courmont
https: fold multiple header fields with identical names
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=5a4d40028cff28a8f40e510755beeaed24478ba1
---
modules/access/http/message.c | 65 +++++++++++++++++++++++++++++++----------
1 file changed, 49 insertions(+), 16 deletions(-)
diff --git a/modules/access/http/message.c b/modules/access/http/message.c
index 0d7c150..a5dffbe 100644
--- a/modules/access/http/message.c
+++ b/modules/access/http/message.c
@@ -49,6 +49,15 @@ struct vlc_http_msg
static bool vlc_http_is_token(const char *);
+static ssize_t vlc_http_msg_find_header(const struct vlc_http_msg *m,
+ const char *name)
+{
+ for (unsigned i = 0; i < m->count; i++)
+ if (!vlc_ascii_strcasecmp(m->headers[i][0], name))
+ return i;
+ return -1;
+}
+
static int vlc_http_msg_vadd_header(struct vlc_http_msg *m, const char *name,
const char *fmt, va_list ap)
{
@@ -58,29 +67,52 @@ static int vlc_http_msg_vadd_header(struct vlc_http_msg *m, const char *name,
return -1;
}
+ char *value;
+ if (unlikely(vasprintf(&value, fmt, ap) < 0))
+ return -1;
+
+ /* IETF RFC7230 §3.2.4 */
+ for (char *p = value; *p; p++)
+ if (*p == '\r' || *p == '\n')
+ *p = ' ';
+
+ /* Fold identically named header field values. This is unfortunately not
+ * possible for Set-Cookie, while Cookie requires a special separator. */
+ ssize_t idx = vlc_http_msg_find_header(m, name);
+ if (idx >= 0 && vlc_ascii_strcasecmp(name, "Set-Cookie"))
+ {
+ char *merged;
+ char sep = vlc_ascii_strcasecmp(name, "Cookie") ? ',' : ';';
+
+ int val = asprintf(&merged, "%s%c %s", m->headers[idx][1], sep, value);
+
+ free(value);
+
+ if (unlikely(val == -1))
+ return -1;
+
+ free(m->headers[idx][1]);
+ m->headers[idx][1] = merged;
+ return 0;
+ }
+
char *(*h)[2] = realloc(m->headers, sizeof (char *[2]) * (m->count + 1));
if (unlikely(h == NULL))
+ {
+ free(value);
return -1;
+ }
m->headers = h;
h += m->count;
h[0][0] = strdup(name);
if (unlikely(h[0][0] == NULL))
- return -1;
-
- char *value;
- if (unlikely(vasprintf(&value, fmt, ap) < 0))
{
- free(h[0][0]);
+ free(value);
return -1;
}
- /* IETF RFC7230 §3.2.4 */
- for (char *p = value; *p; p++)
- if (*p == '\r' || *p == '\n')
- *p = ' ';
-
h[0][1] = value;
m->count++;
return 0;
@@ -103,12 +135,13 @@ int vlc_http_msg_add_header(struct vlc_http_msg *m, const char *name,
const char *vlc_http_msg_get_header(const struct vlc_http_msg *m,
const char *name)
{
- for (unsigned i = 0; i < m->count; i++)
- if (!vlc_ascii_strcasecmp(m->headers[i][0], name))
- return m->headers[i][1];
-
- errno = ENOENT;
- return NULL;
+ ssize_t idx = vlc_http_msg_find_header(m, name);
+ if (idx < 0)
+ {
+ errno = ENOENT;
+ return NULL;
+ }
+ return m->headers[idx][1];
}
int vlc_http_msg_get_status(const struct vlc_http_msg *m)
More information about the vlc-commits
mailing list