From ca9c67b0d095332e76c1d4b9b40873f3df6f1941 Mon Sep 17 00:00:00 2001
From: Thomas Guillem <thomas@gllm.fr>
Date: Fri, 16 Sep 2016 15:51:11 +0200
Subject: [PATCH 05/25] libvlc_media: add cookie_jar API

---
 include/vlc/libvlc_media.h | 35 +++++++++++++++++++++++++++++++++++
 lib/libvlc.sym             |  2 ++
 lib/media.c                | 25 +++++++++++++++++++++++++
 lib/media_internal.h       |  2 ++
 lib/media_player.c         |  7 +++++++
 5 files changed, 71 insertions(+)

diff --git a/include/vlc/libvlc_media.h b/include/vlc/libvlc_media.h
index 383f366b69..2a5666688d 100644
--- a/include/vlc/libvlc_media.h
+++ b/include/vlc/libvlc_media.h
@@ -884,6 +884,41 @@ LIBVLC_API
 void libvlc_media_slaves_release( libvlc_media_slave_t **pp_slaves,
                                   unsigned int i_count );
 
+/**
+ * Parse a value of an incoming Set-Cookie header (see RFC 6265) and append the
+ * cookie to the cookie jar if appropriate. The "secure" attribute can be added
+ * to psz_cookie to limit the scope of the cookie to secured channels (https).
+ *
+ * \note must be called before the first call of libvlc_media_player_play() to
+ * take effect. The cookie jar is only used for http/https accesses.
+ *
+ * \version LibVLC 3.0.0 and later.
+ *
+ * \param p_md media descriptor object
+ * \param psz_cookie header field value of Set-Cookie:
+ * "name=value<;attributes>" (must not be NULL)
+ * \param psz_host host to which the cookie will be sent (must not be NULL)
+ * \param psz_path scope of the cookie (must not be NULL)
+ *
+ * \return 0 on success, -1 on error.
+ */
+LIBVLC_API int
+libvlc_media_cookie_jar_store( libvlc_media_t *p_md, const char *psz_cookie,
+                               const char *psz_host, const char *psz_path );
+
+/**
+ * Clear the cookie jar of a media.
+ *
+ * \note must be called before the first call of libvlc_media_player_play() to
+ * take effect.
+ *
+ * \version LibVLC 3.0.0 and later.
+ *
+ * \param p_md media descriptor object
+ */
+LIBVLC_API void
+libvlc_media_cookie_jar_clear( libvlc_media_t *p_md );
+
 /** @}*/
 
 # ifdef __cplusplus
diff --git a/lib/libvlc.sym b/lib/libvlc.sym
index 482d95f6f1..8ae5da8d0f 100644
--- a/lib/libvlc.sym
+++ b/lib/libvlc.sym
@@ -217,6 +217,8 @@ libvlc_media_set_user_data
 libvlc_media_subitems
 libvlc_media_tracks_get
 libvlc_media_tracks_release
+libvlc_media_cookie_jar_store
+libvlc_media_cookie_jar_clear
 libvlc_new
 libvlc_playlist_play
 libvlc_release
diff --git a/lib/media.c b/lib/media.c
index 54875d6a0e..e1d23caaf5 100644
--- a/lib/media.c
+++ b/lib/media.c
@@ -406,6 +406,7 @@ libvlc_media_t * libvlc_media_new_from_input_item(
     p_md->p_subitems        = NULL;
 
     libvlc_event_manager_init( &p_md->event_manager, p_md );
+    p_md->p_cookie_jar      = NULL;
 
     input_item_Hold( p_md->p_input_item );
 
@@ -561,6 +562,9 @@ void libvlc_media_release( libvlc_media_t *p_md )
 
     input_item_Release( p_md->p_input_item );
 
+    if( p_md->p_cookie_jar )
+        vlc_http_cookies_destroy( p_md->p_cookie_jar );
+    
     vlc_cond_destroy( &p_md->parsed_cond );
     vlc_mutex_destroy( &p_md->parsed_lock );
     vlc_mutex_destroy( &p_md->subitems_lock );
@@ -1288,3 +1292,24 @@ void libvlc_media_slaves_release( libvlc_media_slave_t **pp_slaves,
     }
     free( pp_slaves );
 }
+
+int
+libvlc_media_cookie_jar_store( libvlc_media_t *p_md, const char *psz_cookie,
+                               const char *psz_host, const char *psz_path )
+{
+    if( !p_md->p_cookie_jar )
+    {
+        p_md->p_cookie_jar = vlc_http_cookies_new();
+        if( !p_md->p_cookie_jar )
+            return -1;
+    }
+    return vlc_http_cookies_store( p_md->p_cookie_jar, psz_cookie, psz_host,
+                                   psz_path ) ? 0 : -1;
+}
+
+void
+libvlc_media_cookie_jar_clear( libvlc_media_t *p_md )
+{
+    if( p_md->p_cookie_jar )
+        vlc_http_cookies_clear( p_md->p_cookie_jar );
+}
diff --git a/lib/media_internal.h b/lib/media_internal.h
index 5a67e9ff60..0f0341e260 100644
--- a/lib/media_internal.h
+++ b/lib/media_internal.h
@@ -30,6 +30,7 @@
 
 #include <vlc_common.h>
 #include <vlc_input.h>
+#include <vlc_http.h>
 
 struct libvlc_media_t
 {
@@ -48,6 +49,7 @@ struct libvlc_media_t
     libvlc_media_parsed_status_t parsed_status;
     bool is_parsed;
     bool has_asked_preparse;
+    vlc_http_cookie_jar_t *p_cookie_jar;
 };
 
 /* Media Descriptor */
diff --git a/lib/media_player.c b/lib/media_player.c
index a9a22fee15..fde008aaeb 100644
--- a/lib/media_player.c
+++ b/lib/media_player.c
@@ -621,6 +621,7 @@ libvlc_media_player_new( libvlc_instance_t *instance )
     var_Create (mp, "rate", VLC_VAR_FLOAT|VLC_VAR_DOINHERIT);
     var_Create (mp, "sout", VLC_VAR_STRING);
     var_Create (mp, "demux-filter", VLC_VAR_STRING);
+    var_Create (mp, "http-cookies", VLC_VAR_ADDRESS);
 
     /* Video */
     var_Create (mp, "vout", VLC_VAR_STRING|VLC_VAR_DOINHERIT);
@@ -985,6 +986,12 @@ int libvlc_media_player_play( libvlc_media_player_t *p_mi )
     for( size_t i = 0; i < ARRAY_SIZE( p_mi->selected_es ); ++i )
         p_mi->selected_es[i] = ES_INIT;
 
+    if( p_mi->p_md->p_cookie_jar )
+    {
+        vlc_value_t cookies = { .p_address = p_mi->p_md->p_cookie_jar };
+        var_SetChecked( p_mi, "http-cookies", VLC_VAR_ADDRESS, cookies );
+    }
+
     media_attach_preparsed_event( p_mi->p_md );
 
     p_input_thread = input_Create( p_mi, p_mi->p_md->p_input_item, NULL,
-- 
2.20.1

