[vlc-commits] playlist: partly fix relative URL resolution

Rémi Denis-Courmont git at videolan.org
Mon Jul 25 23:44:46 CEST 2016


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Tue Jul 26 00:41:24 2016 +0300| [f6d5ec36fc419bf0de0393421e38ebbd609edb75] | committer: Rémi Denis-Courmont

playlist: partly fix relative URL resolution

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=f6d5ec36fc419bf0de0393421e38ebbd609edb75
---

 modules/demux/playlist/playlist.c | 105 +++++++++++++++++++++-----------------
 1 file changed, 59 insertions(+), 46 deletions(-)

diff --git a/modules/demux/playlist/playlist.c b/modules/demux/playlist/playlist.c
index 75aeab1..bd99d50 100644
--- a/modules/demux/playlist/playlist.c
+++ b/modules/demux/playlist/playlist.c
@@ -220,64 +220,77 @@ input_item_t * GetCurrentItem(demux_t *p_demux)
 }
 
 /**
- * Find directory part of the path to the playlist file, in case of
- * relative paths inside
+ * Computes the base URL.
+ *
+ * Rebuilds the base URL for the playlist.
  */
-char *FindPrefix( demux_t *p_demux )
+char *FindPrefix(demux_t *p_demux)
 {
-    char *psz_url;
-
-    if( asprintf( &psz_url, "%s://%s", p_demux->psz_access,
-                  p_demux->psz_location ) == -1 )
-        return NULL;
+    char *url;
 
-    char *psz_file = strrchr( psz_url, '/' );
-    assert( psz_file != NULL );
-    psz_file[1] = '\0';
-
-    return psz_url;
+    if (unlikely(asprintf(&url, "%s://%s", p_demux->psz_access,
+                          p_demux->psz_location) == -1))
+        url = NULL;
+    return url;
 }
 
 /**
- * Add the directory part of the playlist file to the start of the
- * mrl, if the mrl is a relative file path
+ * Resolves a playlist location.
+ *
+ * Resolves a resource location within the playlist relative to the playlist
+ * base URL.
  */
-char *ProcessMRL( const char *psz_mrl, const char *psz_prefix )
+char *ProcessMRL(const char *str, const char *base)
 {
-    /* Check for a protocol name.
-     * for URL, we should look for "://"
-     * for MRL (Media Resource Locator) ([[<access>][/<demux>]:][<source>]),
-     * we should look for ":", so we end up looking simply for ":"
-     * PB: on some file systems, ':' are valid characters though */
-
-    /* Simple cases first */
-    if( !psz_mrl || !*psz_mrl )
+    if (str == NULL)
         return NULL;
 
-    /* Check if the line specifies an absolute path */
-    /* FIXME: that's wrong if the playlist is not a local file */
-    if( *psz_mrl == DIR_SEP_CHAR )
-        goto uri;
-#if defined( _WIN32 ) || defined( __OS2__ )
-    /* Drive letter (this assumes URL scheme are not a single character) */
-    if( isalpha((unsigned char)psz_mrl[0]) && psz_mrl[1] == ':' )
-        goto uri;
+#if (DIR_SEP_CHAR == '\\')
+    /* UNC path prefix? */
+    if (strncmp(str, "\\\\", 2) == 0
+    /* Drive letter prefix? */
+     || (isalpha((unsigned char)str[0]) && str[1] == ':'))
+        /* Assume this an absolute file path - usually true */
+        return vlc_path2uri(str, NULL);
+    /* TODO: drive-relative path: if (str[0] == '\\') */
 #endif
-    if( strstr( psz_mrl, "://" ) )
-        return strdup( psz_mrl );
 
-    /* This a relative path, prepend the prefix */
-    char *ret;
-    char *postfix = vlc_uri_encode( psz_mrl );
-    /* FIXME: postfix may not be encoded correctly (esp. slashes) */
-    if( postfix == NULL
-     || asprintf( &ret, "%s%s", psz_prefix, postfix ) == -1 )
-        ret = NULL;
-    free( postfix );
-    return ret;
-
-uri:
-    return vlc_path2uri( psz_mrl, NULL );
+#ifdef HAVE_OPEN_MEMSTREAM
+    /* The base URL is always an URL: it is the URL of the playlist.
+     *
+     * However it is not always known if the input string is a valid URL, a
+     * broken URL or a local file path. As a rule, if it looks like a valid
+     * URL, it must be treated as such, since most playlist formats use URLs.
+     *
+     * There are a few corner cases file paths that look like an URL but whose
+     * URL representation does not match, notably when they contain a
+     * percentage sign, a colon, a hash or a question mark. Luckily, they are
+     * rather exceptional (and can be encoded as URL to make the playlist
+     * work properly).
+     *
+     * If the input is not a valid URL, then we try to fix it up. It works in
+     * all cases for URLs with incorrectly encoded segments, such as URLs with
+     * white spaces or non-ASCII Unicode code points. It also works in most
+     * cases where the input is a Unix-style file path, but not all.
+     * It fails miserably if the playlist character encoding is misdetected.
+     */
+    char *rel = vlc_uri_fixup(str);
+    if (rel != NULL)
+        str = rel;
+
+    char *abs = vlc_uri_resolve(base, str);
+    free(rel);
+    return abs;
+#else
+    const char *split = strrchr(base, '/');
+    char *abs;
+
+    assert(split != NULL);
+
+    if (asprintf(&abs, "%.*s/%s", (int)(split - base), base, str) == -1)
+        abs = NULL;
+    return abs;
+#endif
 }
 
 /**



More information about the vlc-commits mailing list