summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-10-31 14:32:45 +0100
committerDavid Herrmann <dh.herrmann@gmail.com>2013-10-31 14:32:45 +0100
commitc6c2ebef53b652b53e83f54e98ae1abd7bb71ab0 (patch)
tree8a87a92273e86bd91ce36d909bfc266758d1a3c0
parentf3ee9fb8425e64c9f8d16c3bb8f1f24978b5c701 (diff)
owfd: rtsp: support quoted strings
Our rtsp parser must support quoted strings in header-lines. We don't tokenize, yet, so no need to transform them, yet. Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
-rw-r--r--src/rtsp_decoder.c86
1 files changed, 75 insertions, 11 deletions
diff --git a/src/rtsp_decoder.c b/src/rtsp_decoder.c
index 73c643e..b64b1bf 100644
--- a/src/rtsp_decoder.c
+++ b/src/rtsp_decoder.c
@@ -35,6 +35,7 @@
enum state {
STATE_NEW,
STATE_HEADER,
+ STATE_HEADER_QUOTE,
STATE_HEADER_NL,
STATE_BODY,
};
@@ -47,6 +48,7 @@ struct owfd_rtsp_decoder {
unsigned int state;
char last_chr;
size_t remaining_body;
+ unsigned int quoted : 1;
size_t header_size;
struct owfd_rtsp_msg msg;
@@ -182,29 +184,47 @@ static size_t sanitize_header_line(struct owfd_rtsp_decoder *dec,
{
char *src, *dst, c, prev, last_c;
size_t i;
+ bool quoted, escaped;
src = line;
dst = line;
last_c = 0;
+ quoted = 0;
+ escaped = 0;
for (i = 0; i < len; ++i) {
c = *src++;
prev = last_c;
last_c = c;
- /* ignore any binary 0 */
- if (c == '\0')
- continue;
+ if (quoted) {
+ if (prev == '\\' && !escaped) {
+ escaped = 1;
+ } else {
+ escaped = 0;
+ if (c == '"')
+ quoted = 0;
+ }
+ } else {
+ /* ignore any binary 0 */
+ if (c == '\0')
+ continue;
+
+ /* turn new-lines/tabs into white-space */
+ if (c == '\r' || c == '\n' || c == '\t') {
+ c = ' ';
+ last_c = c;
+ }
- /* turn new-lines/tabs into white-space */
- if (c == '\r' || c == '\n' || c == '\t') {
- c = ' ';
- last_c = c;
- }
+ /* trim whitespace */
+ if (c == ' ' && prev == ' ')
+ continue;
- /* trim whitespace */
- if (c == ' ' && prev == ' ')
- continue;
+ if (c == '"') {
+ quoted = 1;
+ escaped = 0;
+ }
+ }
*dst++ = c;
}
@@ -367,6 +387,22 @@ static ssize_t feed_char_header(struct owfd_rtsp_decoder *dec,
++rlen;
}
break;
+ case '"':
+ /* Last line was already completed and this is no whitespace,
+ * thus it's not a continuation line. Finish the line. */
+ if (dec->last_chr == '\r' || dec->last_chr == '\n') {
+ /* don't include new char in line */
+ r = finish_header_line(dec, rlen);
+ if (r < 0)
+ return r;
+ rlen = 0;
+ }
+
+ /* Push character into new line and go to STATE_HEADER_QUOTE */
+ dec->state = STATE_HEADER_QUOTE;
+ dec->quoted = 0;
+ ++rlen;
+ break;
case '\t':
case ' ':
/* Whitespace. Simply push into buffer and don't do anything.
@@ -393,6 +429,31 @@ static ssize_t feed_char_header(struct owfd_rtsp_decoder *dec,
return rlen;
}
+static ssize_t feed_char_header_quote(struct owfd_rtsp_decoder *dec,
+ char ch, size_t rlen)
+{
+ if (dec->last_chr == '\\' && !dec->quoted) {
+ /* This character is quoted, so copy it unparsed. To handle
+ * double-backslash, we set the "quoted" bit. */
+ ++rlen;
+ dec->quoted = 1;
+ } else {
+ dec->quoted = 0;
+
+ switch (ch) {
+ case '"':
+ dec->state = STATE_HEADER;
+ ++rlen;
+ break;
+ default:
+ ++rlen;
+ break;
+ }
+ }
+
+ return rlen;
+}
+
static ssize_t feed_char_body(struct owfd_rtsp_decoder *dec,
char ch, size_t rlen)
{
@@ -471,6 +532,9 @@ static ssize_t feed_char(struct owfd_rtsp_decoder *dec, char ch, size_t rlen)
case STATE_HEADER:
r = feed_char_header(dec, ch, rlen);
break;
+ case STATE_HEADER_QUOTE:
+ r = feed_char_header_quote(dec, ch, rlen);
+ break;
case STATE_HEADER_NL:
r = feed_char_header_nl(dec, ch, rlen);
break;