[rtmpdump] [PATCH] Better URL decoding support

Steven Penny svnpenn at gmail.com
Tue Oct 23 16:12:13 CEST 2012


Currently RtmpDump has limited URL decoding support. If you use Bastien’s patch
as shown here
http://lists.mplayerhq.hu/pipermail/rtmpdump/2012-September/002093.html
You can pass encoded characters like this

  rtmpdump -o a.flv -i "rtmp://server.com/app playpath=foobar\0a"

Where "\0a" will be decoded as a newline.

Also the Playpath can be decoded using an unpatched RtmpDump, as long as it is
part of the "-r" parameter and properly parsed. Example

  rtmpdump -o a.flv -r rtmp://server.com/app/foobar%0a

Where "%0a" will be decoded as a newline. This presents two problems. One, many
times RtmpDump is unable to correctly parse the Playpath, mixing it with the
"app". Two, if you explicitly state the Playpath with "-y", you lose the URL
decoding support. I have simply moved the URL decoding function that Howard
wrote to parseurl.c and declared it in rtmp.h, so that it can be used across the
project.
---
 librtmp/parseurl.c |   73 +++++++++++++++++++++++++++++++++++++---------------
 librtmp/rtmp.h     |    1 +
 rtmpdump.c         |    1 +
 rtmpgw.c           |   47 ---------------------------------
 4 files changed, 54 insertions(+), 68 deletions(-)

diff --git a/librtmp/parseurl.c b/librtmp/parseurl.c
index 57abfe7..07fbbb9 100644
--- a/librtmp/parseurl.c
+++ b/librtmp/parseurl.c
@@ -206,7 +206,7 @@ void RTMP_ParsePlaypath(AVal *in, AVal *out) {
 	const char *playpath = in->av_val;
 	const char *temp, *q, *ext = NULL;
 	const char *ppstart = playpath;
-	char *streamname, *destptr, *p;
+	char *streamname, *destptr;
 
 	int pplen = in->av_len;
 
@@ -265,26 +265,57 @@ void RTMP_ParsePlaypath(AVal *in, AVal *out) {
 		}
 	}
 
- 	for (p=(char *)ppstart; pplen >0;) {
-		/* skip extension */
-		if (subExt && p == ext) {
-			p += 4;
-			pplen -= 4;
-			continue;
-		}
-		if (*p == '%') {
-			unsigned int c;
-			sscanf(p+1, "%02x", &c);
-			*destptr++ = c;
-			pplen -= 3;
-			p += 3;
-		} else {
-			*destptr++ = *p++;
-			pplen--;
-		}
-	}
-	*destptr = '\0';
+	memcpy(destptr, ppstart, pplen * sizeof(char));
+	destptr[pplen] = '\0';
+	http_unescape(streamname);
 
 	out->av_val = streamname;
-	out->av_len = destptr - streamname;
+	out->av_len = strlen(streamname);
+}
+
+/* inplace http unescape. This is possible .. strlen(unescaped_string)  <= strlen(esacped_string) */
+void
+http_unescape(char *data)
+{
+  char hex[3];
+  char *stp;
+  int src_x = 0;
+  int dst_x = 0;
+
+  int length = (int) strlen(data);
+  hex[2] = 0;
+
+  while (src_x < length)
+    {
+      if (strncmp(data + src_x, "%", 1) == 0 && src_x + 2 < length)
+	{
+	  //
+	  // Since we encountered a '%' we know this is an escaped character
+	  //
+	  hex[0] = data[src_x + 1];
+	  hex[1] = data[src_x + 2];
+	  data[dst_x] = (char) strtol(hex, &stp, 16);
+	  dst_x += 1;
+	  src_x += 3;
+	}
+      else if (src_x != dst_x)
+	{
+	  //
+	  // This doesn't need to be unescaped. If we didn't unescape anything previously
+	  // there is no need to copy the string either
+	  //
+	  data[dst_x] = data[src_x];
+	  src_x += 1;
+	  dst_x += 1;
+	}
+      else
+	{
+	  //
+	  // This doesn't need to be unescaped, however we need to copy the string
+	  //
+	  src_x += 1;
+	  dst_x += 1;
+	}
+    }
+  data[dst_x] = '\0';
 }
diff --git a/librtmp/rtmp.h b/librtmp/rtmp.h
index bd85a17..242a536 100644
--- a/librtmp/rtmp.h
+++ b/librtmp/rtmp.h
@@ -285,6 +285,7 @@ extern "C"
 		     unsigned int *port, AVal *playpath, AVal *app);
 
   void RTMP_ParsePlaypath(AVal *in, AVal *out);
+  void http_unescape(char *data);
   void RTMP_SetBufferMS(RTMP *r, int size);
   void RTMP_UpdateBufferMS(RTMP *r);
 
diff --git a/rtmpdump.c b/rtmpdump.c
index e52f7d4..a6cbdfd 100644
--- a/rtmpdump.c
+++ b/rtmpdump.c
@@ -963,6 +963,7 @@ main(int argc, char **argv)
 	    }
 	  break;
 	case 'y':
+	  http_unescape(optarg);
 	  STR2AVAL(playpath, optarg);
 	  break;
 	case 'Y':
diff --git a/rtmpgw.c b/rtmpgw.c
index 0cf56bb..50b8c2a 100644
--- a/rtmpgw.c
+++ b/rtmpgw.c
@@ -220,53 +220,6 @@ FILE *netstackdump = NULL;
 FILE *netstackdump_read = NULL;
 #endif
 
-/* inplace http unescape. This is possible .. strlen(unescaped_string)  <= strlen(esacped_string) */
-void
-http_unescape(char *data)
-{
-  char hex[3];
-  char *stp;
-  int src_x = 0;
-  int dst_x = 0;
-
-  int length = (int) strlen(data);
-  hex[2] = 0;
-
-  while (src_x < length)
-    {
-      if (strncmp(data + src_x, "%", 1) == 0 && src_x + 2 < length)
-	{
-	  //
-	  // Since we encountered a '%' we know this is an escaped character
-	  //
-	  hex[0] = data[src_x + 1];
-	  hex[1] = data[src_x + 2];
-	  data[dst_x] = (char) strtol(hex, &stp, 16);
-	  dst_x += 1;
-	  src_x += 3;
-	}
-      else if (src_x != dst_x)
-	{
-	  //
-	  // This doesn't need to be unescaped. If we didn't unescape anything previously
-	  // there is no need to copy the string either
-	  //
-	  data[dst_x] = data[src_x];
-	  src_x += 1;
-	  dst_x += 1;
-	}
-      else
-	{
-	  //
-	  // This doesn't need to be unescaped, however we need to copy the string
-	  //
-	  src_x += 1;
-	  dst_x += 1;
-	}
-    }
-  data[dst_x] = '\0';
-}
-
 TFTYPE
 controlServerThread(void *unused)
 {
-- 
1.7.9



More information about the rtmpdump mailing list