API: Return URLs in escaped (percent-encoded) form
authorToni Gundogdu <legatvs@gmail.com>
Thu, 24 Oct 2013 18:26:04 +0000 (24 21:26 +0300)
committerToni Gundogdu <legatvs@gmail.com>
Thu, 24 Oct 2013 18:51:51 +0000 (24 21:51 +0300)
- Extend `l_chk_s' and `l_chk_assign_s' functions to allow the caller
  set the `escape_url' arg to TRUE to tell the library to store the
  string value in URI escaped form

- All URLs returned by the library (e.g. media stream or thumbnail) are
  now stored in their escaped form, and passed as such to the
  applications querying them

- "Reserved chars" remain unescaped
  - https://tools.ietf.org/html/rfc3986#section-2.2

Affected API functions

- quvi_subtitle_lang_get (QUVI_SUBTITLE_LANG_PROPERTY_URL)
- quvi_playlist_get (QUVI_PLAYLIST_*_URL)
- quvi_media_get (QUVI_MEDIA_*_URL)

Rationale

- Address the potential problem of chars getting mangled when the URLs
  containing UTF8 chars are passed to the application trying to access
  the URL

Signed-off-by: Toni Gundogdu <legatvs@gmail.com>
src/api/media_get.c
src/api/playlist_get.c
src/api/subtitle_lang_get.c
src/lua/chk.c
src/lua/chk.h
src/lua/exec_media_script_parse.c
src/lua/exec_playlist_script_parse.c
src/lua/exec_subtitle_export_script_export.c
src/lua/exec_subtitle_export_script_ident.c
src/lua/exec_subtitle_script_parse.c

index d93de31..f1913e3 100644 (file)
@@ -160,11 +160,13 @@ static QuviError _media_get(_quvi_media_t qm, const QuviMediaProperty n, ...)
 /** @brief Return a media property
 @sa @ref parse_media
 @ingroup mediaprop
-@note Accessing any of the QUVI_MEDIA_STREAM_PROPERTY_* values using
-this function will cause the library to advance to the first stream
-in the list, this will conflict with @ref quvi_media_stream_next,
-causing @ref quvi_media_stream_next to advance from the second stream,
-not the first stream
+@note
+  - Accessing any of the QUVI_MEDIA_STREAM_PROPERTY_* values using this
+    function will cause the library to advance to the first stream in
+    the list, this will conflict with @ref quvi_media_stream_next,
+    causing @ref quvi_media_stream_next to advance from the second
+    stream, not the first stream
+  - URLs will be returned in the escaped form
 */
 void quvi_media_get(quvi_media_t handle, QuviMediaProperty property, ...)
 {
index f70e611..6ba65c0 100644 (file)
@@ -146,6 +146,7 @@ static QuviError _playlist_get(_quvi_playlist_t qp,
 /** @brief Return a playlist property
 @sa @ref parse_playlist
 @ingroup playlistprop
+@note URLs will be returned in the escaped form
 */
 void quvi_playlist_get(quvi_playlist_t handle,
                        QuviPlaylistProperty property, ...)
index 4e25e06..147e1a5 100644 (file)
@@ -113,6 +113,7 @@ static QuviError _get(_quvi_subtitle_lang_t qsl,
 /** @brief Return a subtitle property
 @sa @ref parse_subtitle
 @ingroup subprop
+@note URLs will be returned in the escaped form
 */
 void quvi_subtitle_lang_get(quvi_subtitle_lang_t handle,
                             QuviSubtitleLangProperty n, ...)
index ab2214f..7cc27d4 100644 (file)
@@ -1,5 +1,5 @@
 /* libquvi
- * Copyright (C) 2012  Toni Gundogdu <legatvs@gmail.com>
+ * Copyright (C) 2012,2013  Toni Gundogdu <legatvs@gmail.com>
  *
  * This file is part of libquvi <http://quvi.sourceforge.net/>.
  *
@@ -30,6 +30,7 @@
 /* -- */
 #include "lua/chk.h"
 #include "lua/def.h"
+#include "misc/url.h"
 #include "misc/re.h"
 
 /*
@@ -51,7 +52,7 @@ gboolean l_chk_can_parse_url(lua_State *l, _quvi_script_t qs,
   lua_pushnil(l);
   while (lua_next(l, LI_KEY))
     {
-      l_chk_assign_s(l, k_domains, qs->domains, TRUE);
+      l_chk_assign_s(l, k_domains, qs->domains, TRUE, FALSE);
       l_chk_assign_b(l, k_can_parse_url, &r);
       lua_pop(l, 1);
     }
@@ -70,7 +71,8 @@ gboolean l_chk_can_parse_url(lua_State *l, _quvi_script_t qs,
  *
  * NOTE: g_free the returned value when done using it.
  */
-gboolean l_chk_s(lua_State *l, const gchar *w, gchar **v, gboolean trim_flag)
+gboolean l_chk_s(lua_State *l, const gchar *w, gchar **v,
+                 gboolean trim_flag, gboolean escape_url)
 {
   if (lua_isstring(l, LI_KEY) && lua_isstring(l, LI_VALUE))
     {
@@ -80,6 +82,12 @@ gboolean l_chk_s(lua_State *l, const gchar *w, gchar **v, gboolean trim_flag)
           *v = (trim_flag == TRUE)
                ? m_trim_ws(s)
                : g_strdup(s);
+          if (escape_url == TRUE)
+            {
+              gchar *e = m_url_escaped_form(*v);
+              g_free(*v);
+              *v = e;
+            }
           return (TRUE);
         }
     }
@@ -87,10 +95,10 @@ gboolean l_chk_s(lua_State *l, const gchar *w, gchar **v, gboolean trim_flag)
 }
 
 gboolean l_chk_assign_s(lua_State *l, const gchar *k, GString *v,
-                        gboolean trim_flag)
+                        gboolean trim_flag, gboolean escape_url)
 {
   gchar *s = NULL;
-  if (l_chk_s(l, k, &s, trim_flag) == TRUE)
+  if (l_chk_s(l, k, &s, trim_flag, escape_url) == TRUE)
     {
       g_string_assign(v, s);
       g_free(s);
index d22bcf7..730937a 100644 (file)
@@ -1,5 +1,5 @@
 /* libquvi
- * Copyright (C) 2012  Toni Gundogdu <legatvs@gmail.com>
+ * Copyright (C) 2012,2013  Toni Gundogdu <legatvs@gmail.com>
  *
  * This file is part of libquvi <http://quvi.sourceforge.net/>.
  *
@@ -24,8 +24,9 @@
 gboolean l_chk_can_parse_url(lua_State*, _quvi_script_t, const gchar*,
                              const gchar*, const gchar*);
 
-gboolean l_chk_assign_s(lua_State*, const gchar*, GString*, gboolean);
-gboolean l_chk_s(lua_State*, const gchar*, gchar**, gboolean);
+gboolean l_chk_assign_s(lua_State*, const gchar*, GString*, gboolean,
+                        gboolean);
+gboolean l_chk_s(lua_State*, const gchar*, gchar**, gboolean, gboolean);
 
 gboolean l_chk_assign_n(lua_State*, const gchar*, gdouble*);
 gboolean l_chk_n(lua_State*, const gchar*, gdouble*);
index 370bc56..9bb5313 100644 (file)
@@ -52,7 +52,7 @@ static void _foreach_video_property(lua_State *l, _quvi_media_t qm,
   while (lua_next(l, LI_KEY))
     {
       l_chk_assign_n(l, MSS_VIDEO_BITRATE_KBIT_S, &qms->video.bitrate_kbit_s);
-      l_chk_assign_s(l, MSS_VIDEO_ENCODING, qms->video.encoding, TRUE);
+      l_chk_assign_s(l, MSS_VIDEO_ENCODING, qms->video.encoding, TRUE, FALSE);
       l_chk_assign_n(l, MSS_VIDEO_HEIGHT, &qms->video.height);
       l_chk_assign_n(l, MSS_VIDEO_WIDTH, &qms->video.width);
       lua_pop(l, 1);
@@ -66,7 +66,7 @@ static void _foreach_audio_property(lua_State *l, _quvi_media_t qm,
   while (lua_next(l, LI_KEY))
     {
       l_chk_assign_n(l, MSS_AUDIO_BITRATE_KBIT_S, &qms->audio.bitrate_kbit_s);
-      l_chk_assign_s(l, MSS_AUDIO_ENCODING, qms->audio.encoding, TRUE);
+      l_chk_assign_s(l, MSS_AUDIO_ENCODING, qms->audio.encoding, TRUE, FALSE);
       lua_pop(l, 1);
     }
 }
@@ -130,9 +130,9 @@ static _quvi_media_stream_t _new_stream(lua_State *l, _quvi_media_t qm,
       _chk_stream_sublevel(MSS_VIDEO, l, qm, qms, _foreach_video_property);
       _chk_stream_sublevel(MSS_AUDIO, l, qm, qms, _foreach_audio_property);
       _chk_stream_sublevel(MSS_FLAGS, l, qm, qms, _foreach_flag_property);
-      l_chk_assign_s(l, MSS_CONTAINER, qms->container, TRUE);
-      l_chk_assign_s(l, MSS_URL, qms->url, TRUE);
-      l_chk_assign_s(l, MSS_ID, qms->id, TRUE);
+      l_chk_assign_s(l, MSS_CONTAINER, qms->container, TRUE, FALSE);
+      l_chk_assign_s(l, MSS_URL, qms->url, TRUE, TRUE);
+      l_chk_assign_s(l, MSS_ID, qms->id, TRUE, FALSE);
       lua_pop(l, 1);
     }
   _has_stream_url(l, qms, script_path, i);
@@ -219,9 +219,9 @@ static void _chk_optional(lua_State *l, _quvi_media_t qm)
     {
       l_chk_assign_n(l, MS_START_TIME_MS, &qm->start_time_ms);
       l_chk_assign_n(l, MS_DURATION_MS, &qm->duration_ms);
-      l_chk_assign_s(l, MS_THUMB_URL, qm->url.thumbnail, TRUE);
-      l_chk_assign_s(l, MS_TITLE, qm->title, TRUE);
-      l_chk_assign_s(l, MS_ID, qm->id, TRUE);
+      l_chk_assign_s(l, MS_THUMB_URL, qm->url.thumbnail, TRUE, TRUE);
+      l_chk_assign_s(l, MS_TITLE, qm->title, TRUE, FALSE);
+      l_chk_assign_s(l, MS_ID, qm->id, TRUE, FALSE);
       lua_pop(l, 1);
     }
 }
@@ -232,7 +232,7 @@ static gboolean _chk_goto_instr(lua_State *l, _quvi_media_t qm)
   lua_pushnil(l);
   while (lua_next(l, LI_KEY))
     {
-      l_chk_assign_s(l, MS_GOTO_URL, qm->url.redirect_to, TRUE);
+      l_chk_assign_s(l, MS_GOTO_URL, qm->url.redirect_to, TRUE, TRUE);
       lua_pop(l, 1);
     }
   return ((qm->url.redirect_to->len >0) ? TRUE:FALSE);
index 6b85061..eb4c4c8 100644 (file)
@@ -63,8 +63,8 @@ static gboolean _new_media(lua_State *l, _quvi_playlist_t qp,
   while (lua_next(l, LI_KEY)) /* For each qargs.media */
     {
       l_chk_assign_n(l, PSM_DURATION_MS, &(*qpm)->duration_ms);
-      l_chk_assign_s(l, PSM_TITLE, (*qpm)->title, TRUE);
-      l_chk_assign_s(l, PSM_URL, (*qpm)->url, TRUE);
+      l_chk_assign_s(l, PSM_TITLE, (*qpm)->title, TRUE, FALSE);
+      l_chk_assign_s(l, PSM_URL, (*qpm)->url, TRUE, TRUE);
       lua_pop(l, 1);
     }
 
@@ -122,9 +122,9 @@ static void _chk_optional(lua_State *l, _quvi_playlist_t qp)
   lua_pushnil(l);
   while (lua_next(l, LI_KEY))
     {
-      l_chk_assign_s(l, PS_THUMB_URL, qp->url.thumbnail, TRUE);
-      l_chk_assign_s(l, PS_ID, qp->id.playlist, TRUE);
-      l_chk_assign_s(l, PS_TITLE, qp->title, TRUE);
+      l_chk_assign_s(l, PS_THUMB_URL, qp->url.thumbnail, TRUE, TRUE);
+      l_chk_assign_s(l, PS_ID, qp->id.playlist, TRUE, FALSE);
+      l_chk_assign_s(l, PS_TITLE, qp->title, TRUE, FALSE);
       lua_pop(l, 1);
     }
 }
index cc35d1d..072609f 100644 (file)
@@ -52,7 +52,7 @@ static QuviError _chk_result(lua_State *l, _quvi_subtitle_export_t qse,
   lua_pushnil(l);
   while (lua_next(l, LI_KEY))
     {
-      l_chk_assign_s(l, SUES_DATA, qse->data, FALSE);
+      l_chk_assign_s(l, SUES_DATA, qse->data, FALSE, FALSE);
       lua_pop(l, 1);
     }
 
index fc7d39c..2020efe 100644 (file)
@@ -51,7 +51,7 @@ static QuviError _chk_results(lua_State *l, _quvi_script_t qs)
   lua_pushnil(l);
   while (lua_next(l, LI_KEY))
     {
-      l_chk_assign_s(l, SUES_EXPORT_FORMAT, qs->export.format, TRUE);
+      l_chk_assign_s(l, SUES_EXPORT_FORMAT, qs->export.format, TRUE, FALSE);
       l_chk_assign_b(l, SUES_CAN_EXPORT_DATA, &r);
       lua_pop(l, 1);
     }
index a3d7811..43d4d1f 100644 (file)
@@ -130,11 +130,11 @@ static _quvi_subtitle_lang_t _new_lang(lua_State *l, const gchar *script_path,
   lua_pushnil(l);
   while (lua_next(l, LI_KEY))
     {
-      l_chk_assign_s(l, SUSSL_TRANSLATED, qsl->translated, TRUE);
-      l_chk_assign_s(l, SUSSL_ORIGINAL, qsl->original, TRUE);
-      l_chk_assign_s(l, SUSSL_CODE, qsl->code, TRUE);
-      l_chk_assign_s(l, SUSSL_URL, qsl->url, TRUE);
-      l_chk_assign_s(l, SUSSL_ID, qsl->id, TRUE);
+      l_chk_assign_s(l, SUSSL_TRANSLATED, qsl->translated, TRUE, FALSE);
+      l_chk_assign_s(l, SUSSL_ORIGINAL, qsl->original, TRUE, FALSE);
+      l_chk_assign_s(l, SUSSL_CODE, qsl->code, TRUE, FALSE);
+      l_chk_assign_s(l, SUSSL_URL, qsl->url, TRUE, TRUE);
+      l_chk_assign_s(l, SUSSL_ID, qsl->id, TRUE, FALSE);
       lua_pop(l, 1);
     }
   return (_chk_url(l, script_path, qsl, i));