[vlc-devel] [PATCH 05/10][RFC][WIP] cloudstorage: add access module integrating libcloudstorage
Diogo Silva
dbtdsilva at gmail.com
Thu Aug 17 03:08:13 CEST 2017
This module supports multiple providers and users. At this point it is
using microhttpd and curl dependency from libcloudstorage. However,
those are replaced in the following patches.
---
NEWS | 2 +
configure.ac | 5 +
modules/MODULES_LIST | 3 +-
modules/access/Makefile.am | 10 +
modules/access/cloudstorage.cpp | 41 ++++
modules/access/cloudstorage/access.cpp | 248 ++++++++++++++++++++++++
modules/access/cloudstorage/access.h | 53 +++++
modules/access/cloudstorage/provider_callback.h | 114 +++++++++++
po/POTFILES.in | 4 +
9 files changed, 479 insertions(+), 1 deletion(-)
create mode 100644 modules/access/cloudstorage.cpp
create mode 100644 modules/access/cloudstorage/access.cpp
create mode 100644 modules/access/cloudstorage/access.h
create mode 100644 modules/access/cloudstorage/provider_callback.h
diff --git a/NEWS b/NEWS
index ef31c19a83..4dcc89f127 100644
--- a/NEWS
+++ b/NEWS
@@ -56,6 +56,8 @@ Access:
* New SAT>IP access module, to receive DVB-S via IP networks
* Improvements on DVB scanning
* BluRay module can open ISO over network and has full BD-J support
+ * New cloudstorage access module using libcloudstorage supporting cloud
+ services, such as Google Drive, Dropbox and others
Decoder:
* OMX GPU-zerocopy support for decoding and display on Android using OpenMax IL
diff --git a/configure.ac b/configure.ac
index 8487fea895..0c232c0ef2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1807,6 +1807,11 @@ dnl liBDSM access module
dnl
PKG_ENABLE_MODULES_VLC([DSM], [dsm], [libdsm >= 0.2.0], [libdsm SMB/CIFS access/sd module], [auto])
+dnl
+dnl cloud access support with libcloudstorage
+dnl
+PKG_ENABLE_MODULES_VLC([CLOUDSTORAGE], [cloudstorage], [libcloudstorage], [cloudstorage access], [auto])
+
dnl
dnl sftp access support
dnl
diff --git a/modules/MODULES_LIST b/modules/MODULES_LIST
index 9509eba71d..4d0613d4a7 100644
--- a/modules/MODULES_LIST
+++ b/modules/MODULES_LIST
@@ -1,4 +1,4 @@
-List of vlc plugins (475)
+List of vlc plugins (489)
$Id$
* a52: A/52 audio decoder plugin, using liba52
* aa: Ascii art video output
@@ -80,6 +80,7 @@ $Id$
* chroma_yuv_neon: ARM NEON video chroma conversion
* ci_filters: CoreImage hardware-accelerated adjust/invert/posterize/sepia/sharpen filters
* clone: Clone video filter
+ * cloudstorage: Cloud storage services module using libcloudstorage
* colorthres: Theshold color based on similarity to reference color Video filter
* compressor: Dynamic range compressor
* console_logger: Logger outputting in the terminal
diff --git a/modules/access/Makefile.am b/modules/access/Makefile.am
index dd485a2767..75e4afa885 100644
--- a/modules/access/Makefile.am
+++ b/modules/access/Makefile.am
@@ -313,6 +313,16 @@ endif
### Network streams ###
+libcloudstorage_plugin_la_SOURCES = \
+ access/cloudstorage.cpp \
+ access/cloudstorage/access.h access/cloudstorage/access.cpp \
+ access/cloudstorage/provider_callback.h
+libcloudstorage_plugin_la_CXXFLAGS = $(CXXFLAGS_cloudstorage) $(AM_CXXFLAGS)
+libcloudstorage_plugin_la_LIBADD = $(LIBS_cloudstorage)
+libcloudstorage_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(accessdir)'
+access_LTLIBRARIES += $(LTLIBcloudstorage)
+EXTRA_LTLIBRARIES += libcloudstorage_plugin.la
+
libftp_plugin_la_SOURCES = access/ftp.c
libftp_plugin_la_LIBADD = $(SOCKET_LIBS)
access_LTLIBRARIES += libftp_plugin.la
diff --git a/modules/access/cloudstorage.cpp b/modules/access/cloudstorage.cpp
new file mode 100644
index 0000000000..152f2067c7
--- /dev/null
+++ b/modules/access/cloudstorage.cpp
@@ -0,0 +1,41 @@
+/*****************************************************************************
+ * cloudstorage.cpp: cloud access module using libcloudstorage for VLC
+ *****************************************************************************
+ * Copyright (C) 2017 VideoLabs and VideoLAN
+ *
+ * Authors: William Ung <williamung at msn.com>
+ * Diogo Silva <dbtdsilva at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <vlc_plugin.h>
+
+#include "cloudstorage/access.h"
+
+vlc_module_begin()
+ set_shortname(N_("cloudstorage"))
+ set_capability("access", 0)
+ set_description(N_("Cloud storage services (such as Drive, Dropbox) input"
+ " using libcloudstorage"))
+ set_category(CAT_INPUT)
+ set_subcategory(SUBCAT_INPUT_ACCESS)
+ // callbacks are defined under cloudstorage/access.h
+ set_callbacks(Open, Close)
+vlc_module_end()
diff --git a/modules/access/cloudstorage/access.cpp b/modules/access/cloudstorage/access.cpp
new file mode 100644
index 0000000000..e8a48af47d
--- /dev/null
+++ b/modules/access/cloudstorage/access.cpp
@@ -0,0 +1,248 @@
+/*****************************************************************************
+ * access.cpp: cloud storage access module using libcloudstorage
+ *****************************************************************************
+ * Copyright (C) 2017 VideoLabs and VideoLAN
+ *
+ * Authors: William Ung <williamung at msn.com>
+ * Diogo Silva <dbtdsilva at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include "access.h"
+
+#include <algorithm>
+#include <sstream>
+#include <fstream>
+#include <ICloudStorage.h>
+#include <IRequest.h>
+
+#include "provider_callback.h"
+
+using cloudstorage::ICloudStorage;
+using cloudstorage::ICloudProvider;
+using cloudstorage::IDownloadFileCallback;
+using cloudstorage::IItem;
+using cloudstorage::IRequest;
+
+static int AddItem( struct access_fsdir *, stream_t *, IItem::Pointer );
+static int GetCredentials( stream_t * );
+static int InitProvider( stream_t * );
+static int ReadDir( stream_t *, input_item_node_t * );
+static std::string ReadFile( const std::string& path );
+static int ParseMRL( stream_t * );
+
+int Open( vlc_object_t *p_this )
+{
+ int err = VLC_EGENERIC;
+ stream_t *p_access = (stream_t*) p_this;
+ access_sys_t *p_sys;
+
+ p_access->p_sys = p_sys = new access_sys_t();
+ if ( p_sys == nullptr )
+ return VLC_ENOMEM;
+
+ if ( (err = ParseMRL( p_access )) != VLC_SUCCESS )
+ goto error;
+ if ( (err = GetCredentials( p_access )) != VLC_SUCCESS )
+ goto error;
+ if ( (err = InitProvider( p_access )) != VLC_SUCCESS )
+ goto error;
+
+ if ( p_sys->current_item->type() == IItem::FileType::Directory )
+ {
+ p_access->pf_control = access_vaDirectoryControlHelper;
+ p_access->pf_readdir = ReadDir;
+ return VLC_SUCCESS;
+ }
+ else
+ {
+ p_sys->current_item = p_sys->provider->
+ getItemDataAsync( p_sys->current_item->id() )->result().right();
+ p_access->psz_url = strdup( p_sys->current_item->url().c_str() );
+ err = VLC_ACCESS_REDIRECT;
+ }
+
+error:
+ Close( p_this );
+ return err;
+}
+
+void Close( vlc_object_t *p_this )
+{
+ stream_t *p_access = (stream_t *) p_this;
+ access_sys_t *p_sys = (access_sys_t *) p_access->p_sys;
+
+ if ( p_sys != nullptr ) {
+ vlc_UrlClean( &p_sys->url );
+ delete p_sys;
+ }
+}
+
+static int ParseMRL( stream_t * p_access )
+{
+ access_sys_t *p_sys = (access_sys_t *) p_access->p_sys;
+
+ // Correct the path if there are any invalid characters like spaces and
+ // Parse the URL into a VLC object
+ char *url = vlc_uri_fixup( p_access->psz_url );
+ int error = vlc_UrlParse( &p_sys->url, url );
+ free( url );
+ if ( error != VLC_SUCCESS )
+ return error;
+
+ // If no path was specific, then it is root
+ if ( p_sys->url.psz_path == NULL )
+ p_sys->url.psz_path = strdup("/");
+ // Since there is no info to store the authenticated user, creates a dummy
+ // user and stores it temporarly under a in-memory credentials.
+ if ( p_sys->url.psz_username == NULL )
+ {
+ p_sys->memory_keystore = true;
+ p_sys->url.psz_username = strdup("dummy_user");
+ }
+
+ return VLC_SUCCESS;
+}
+
+static int GetCredentials( stream_t * p_access )
+{
+ access_sys_t *p_sys = (access_sys_t *) p_access->p_sys;
+ // Init credentials and clean within the same scope to prevent the keystore
+ // to be loaded at all times
+ vlc_credential credentials;
+ vlc_credential_init( &credentials, &p_sys->url );
+ if ( vlc_credential_get( &credentials, p_access,
+ NULL, NULL, NULL, NULL) )
+ {
+ std::string stored_value = std::string( credentials.psz_password );
+ if ( !ICloudProvider::deserializeSession(stored_value,
+ p_sys->token, p_sys->hints) )
+ {
+ msg_Warn( p_access, "Cloudstorage found invalid credentials in the "
+ "keystore under %s@%s, it is going to overwrite them.",
+ p_sys->url.psz_username, p_sys->url.psz_host );
+ }
+ }
+ vlc_credential_clean( &credentials );
+ return VLC_SUCCESS;
+}
+
+static int InitProvider( stream_t * p_access )
+{
+ access_sys_t *p_sys = (access_sys_t *) p_access->p_sys;
+ ICloudProvider::Hints hints;
+ std::string redirect_port = std::to_string(
+ config_GetInt( p_access, "http-port" ) );
+
+ // Get predifined port and prefix
+ hints["redirect_uri"] = "http://localhost:" + redirect_port + "/auth";
+ hints["file_url"] = "http://localhost:" + redirect_port + "/files";
+
+ // Initialize the provider
+ p_sys->provider = cloudstorage::ICloudStorage::
+ create()->provider( p_sys->url.psz_host );
+ if ( !p_sys->provider ) {
+ msg_Err( p_access, "Failed to load the given provider" );
+ return VLC_EGENERIC;
+ }
+ p_sys->provider->initialize({
+ p_sys->token,
+ std::unique_ptr<Callback>( new Callback( p_access ) ),
+ nullptr,
+ nullptr,
+ nullptr,
+ hints
+ });
+
+ msg_Dbg( p_access, "Path: %s", p_sys->url.psz_path );
+ p_sys->current_item = p_sys->provider->
+ getItemAsync( vlc_uri_decode( p_sys->url.psz_path ) )->
+ result().right();
+ if ( p_sys->current_item == nullptr )
+ {
+ msg_Err( p_access, "Item %s does not exist in the provider %s",
+ p_sys->url.psz_path, p_sys->url.psz_host );
+ return VLC_EGENERIC;
+ }
+ return VLC_SUCCESS;
+}
+
+static int AddItem( struct access_fsdir *p_fsdir, stream_t *p_access,
+ IItem::Pointer item )
+{
+ std::stringstream url;
+ int i_type;
+
+ url << p_access->psz_url;
+ if ( strlen( p_access->psz_url ) == 0 ||
+ p_access->psz_url[strlen( p_access->psz_url ) - 1] != '/' )
+ url << "/";
+
+ char* url_encoded = vlc_uri_encode( item->filename().c_str() );
+ url << url_encoded;
+ free( url_encoded );
+
+ i_type = item->type() == IItem::FileType::Directory ?
+ ITEM_TYPE_DIRECTORY : ITEM_TYPE_FILE;
+
+ return access_fsdir_additem( p_fsdir, url.str().c_str(),
+ item->filename().c_str(), i_type, ITEM_NET );
+}
+
+static int ReadDir( stream_t *p_access, input_item_node_t *p_node )
+{
+ access_sys_t *p_sys = (access_sys_t *) p_access->p_sys;
+ struct access_fsdir fsdir;
+
+ ICloudProvider::ListDirectoryRequest::Pointer list_directory_request =
+ p_sys->provider->listDirectoryAsync( p_sys->current_item );
+
+ access_fsdir_init( &fsdir, p_access, p_node );
+ int error_code = VLC_SUCCESS;
+ for ( auto &i : *list_directory_request->result().right() )
+ {
+ if ( AddItem( &fsdir, p_access, i ) != VLC_SUCCESS )
+ {
+ error_code = VLC_EGENERIC;
+ break;
+ }
+ }
+ access_fsdir_finish( &fsdir, error_code == VLC_SUCCESS );
+ return error_code;
+}
+
+static std::string ReadFile( const std::string& filename )
+{
+ char * base_path = config_GetDataDir();
+
+ std::string data_filename;
+ data_filename.append( base_path );
+ free( base_path );
+ data_filename.append( DIR_SEP );
+ data_filename.append( filename );
+ std::ifstream stream( data_filename, std::ios::in | std::ios::binary );
+ if ( !stream )
+ return "";
+
+ std::string contents;
+ stream.seekg( 0, std::ios::end );
+ contents.resize( stream.tellg() );
+ stream.seekg( 0, std::ios::beg );
+ stream.read( &contents[0], contents.size() );
+ stream.close();
+
+ return contents;
+}
diff --git a/modules/access/cloudstorage/access.h b/modules/access/cloudstorage/access.h
new file mode 100644
index 0000000000..f755600aaa
--- /dev/null
+++ b/modules/access/cloudstorage/access.h
@@ -0,0 +1,53 @@
+/*****************************************************************************
+ * access.cpp: cloud storage access module using libcloudstorage
+ *****************************************************************************
+ * Copyright (C) 2017 VideoLabs and VideoLAN
+ *
+ * Authors: William Ung <williamung at msn.com>
+ * Diogo Silva <dbtdsilva at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef VLC_CLOUDSTORAGE_ACCESS_H
+#define VLC_CLOUDSTORAGE_ACCESS_H
+
+#include <string>
+#include <ICloudProvider.h>
+#include <IItem.h>
+
+#include <vlc_common.h>
+#include <vlc_access.h>
+#include <vlc_input.h>
+#include <vlc_keystore.h>
+#include <vlc_url.h>
+
+int Open( vlc_object_t * );
+void Close( vlc_object_t * );
+
+struct access_sys_t
+{
+ // Parsed parameters
+ vlc_url_t url;
+ bool memory_keystore;
+
+ // Loaded on Open
+ cloudstorage::ICloudProvider::Pointer provider;
+ std::string token;
+ cloudstorage::ICloudProvider::Hints hints;
+ cloudstorage::IItem::Pointer current_item;
+};
+
+#endif
diff --git a/modules/access/cloudstorage/provider_callback.h b/modules/access/cloudstorage/provider_callback.h
new file mode 100644
index 0000000000..f400f08e55
--- /dev/null
+++ b/modules/access/cloudstorage/provider_callback.h
@@ -0,0 +1,114 @@
+/*****************************************************************************
+ * provider_callback.h: Inherit class ICallback from libcloudstorage
+ *****************************************************************************
+ * Copyright (C) 2017 VideoLabs and VideoLAN
+ *
+ * Authors: Diogo Silva <dbtdsilva at gmail.com>
+ * William Ung <williamung at msn.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef VLC_CLOUDSTORAGE_PROVIDER_CALLBACK_H
+#define VLC_CLOUDSTORAGE_PROVIDER_CALLBACK_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <string>
+#include <vlc_dialog.h>
+
+#include "access.h"
+
+using cloudstorage::ICloudProvider;
+using cloudstorage::EitherError;
+
+class Callback : public ICloudProvider::IAuthCallback {
+public:
+ Callback( stream_t *access ) :
+ p_access( access ), p_sys( (access_sys_t *) access->p_sys )
+ {}
+
+ Status userConsentRequired( const ICloudProvider& provider ) override
+ {
+ std::string authorize_url = provider.authorizeLibraryUrl();
+ int i_ret = vlc_spawn_browser( p_access, authorize_url.c_str(),
+ "Authentication required", "This function requires login through a "
+ "website and will open a webbrowser." );
+ if ( i_ret != 1 )
+ return Status::None;
+ msg_Info( p_access, "User ConsentRequired at : %s",
+ authorize_url.c_str() );
+ return Status::WaitForAuthorizationCode;
+ }
+
+ void done( const ICloudProvider& provider,
+ EitherError<void> error ) override
+ {
+ // An error occurred
+ if ( error.left() )
+ {
+ msg_Err( p_access, "Authorization Error %d: %s",
+ error.left()->code_, error.left()->description_.c_str() );
+ }
+ else // No error occurred
+ {
+ accepted( provider );
+ }
+ }
+
+ void accepted( const ICloudProvider& provider )
+ {
+ vlc_credential credentials;
+ vlc_credential_init( &credentials, &p_sys->url );
+ bool found = vlc_credential_get( &credentials, p_access,
+ NULL, NULL, NULL, NULL );
+
+ p_sys->token = provider.token();
+ p_sys->hints = provider.hints();
+
+ // Store hints and token
+ std::string serialized_value = ICloudProvider::serializeSession(
+ p_sys->token, p_sys->hints );
+
+ // Store the data related with the session using the credentials API
+ credentials.b_store = !p_sys->memory_keystore;
+ credentials.psz_password = serialized_value.c_str();
+ if ( !vlc_credential_store( &credentials, p_access ) )
+ {
+ msg_Warn( p_access, "Failed to store the credentials");
+ }
+
+ // Inform about new authentications
+ if ( !found )
+ {
+ msg_Dbg( p_access, "%s (new) was authenticated at %s",
+ p_sys->url.psz_username, p_sys->url.psz_host );
+ std::stringstream ss_user;
+ ss_user << p_sys->url.psz_username << "@" << p_sys->url.psz_host;
+ var_SetString( p_access->obj.libvlc, "cloudstorage-new-auth",
+ ss_user.str().c_str() );
+ }
+ vlc_credential_clean( &credentials );
+ msg_Dbg( p_access, "Accepted credentials!");
+ }
+
+private:
+ stream_t *p_access;
+ access_sys_t *p_sys;
+};
+
+#endif
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 01388cb324..d47d046f41 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -177,6 +177,10 @@ modules/access/attachment.c
modules/access/avio.h
modules/access/bluray.c
modules/access/cdda.c
+modules/access/cloudstorage.cpp
+modules/access/cloudstorage/access.cpp
+modules/access/cloudstorage/access.h
+modules/access/cloudstorage/provider_callback.h
modules/access/concat.c
modules/access/dc1394.c
modules/access/dcp/dcp.cpp
--
2.14.1
More information about the vlc-devel
mailing list