Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-2-2
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-2-2
Commits
29f4fe99
Commit
29f4fe99
authored
Feb 07, 2014
by
Francois Cartegnie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
addons: add local storage module
parent
1a8ead40
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
952 additions
and
1 deletion
+952
-1
modules/misc/Modules.am
modules/misc/Modules.am
+4
-1
modules/misc/addons/fsstorage.c
modules/misc/addons/fsstorage.c
+870
-0
modules/misc/addons/xmlreading.h
modules/misc/addons/xmlreading.h
+78
-0
No files found.
modules/misc/Modules.am
View file @
29f4fe99
...
@@ -59,9 +59,12 @@ endif
...
@@ -59,9 +59,12 @@ endif
libstats_plugin_la_SOURCES = stats.c
libstats_plugin_la_SOURCES = stats.c
libaddonsfsstorage_plugin_la_SOURCES = addons/fsstorage.c addons/xmlreading.h
misc_LTLIBRARIES += \
misc_LTLIBRARIES += \
liblogger_plugin.la \
liblogger_plugin.la \
libstats_plugin.la
libstats_plugin.la \
libaddonsfsstorage_plugin.la
if ENABLE_SOUT
if ENABLE_SOUT
misc_LTLIBRARIES += \
misc_LTLIBRARIES += \
...
...
modules/misc/addons/fsstorage.c
0 → 100644
View file @
29f4fe99
/*****************************************************************************
* addonsstorage.c : Addons Local filesystem storage
*****************************************************************************
* Copyright (C) 2014 VLC authors and VideoLAN
*
* 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.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_modules.h>
#include <vlc_stream.h>
#include <vlc_addons.h>
#include <vlc_fs.h>
#include <vlc_strings.h>
#include <vlc_xml.h>
#include "xmlreading.h"
#include <sys/stat.h>
#include <errno.h>
/*****************************************************************************
* Local prototypes
*****************************************************************************/
#define ADDONS_DIR ""
#define ADDONS_SCRIPTS_DIR ADDONS_DIR DIR_SEP "lua"
#define ADDONS_CATALOG ADDONS_DIR DIR_SEP "catalog.xml"
static
struct
{
addon_type_t
t
;
const
char
const
*
psz_dir
;
}
const
addons_dirs
[]
=
{
{
ADDON_EXTENSION
,
ADDONS_SCRIPTS_DIR
DIR_SEP
"extensions"
},
{
ADDON_PLAYLIST_PARSER
,
ADDONS_SCRIPTS_DIR
DIR_SEP
"playlist"
},
{
ADDON_SERVICE_DISCOVERY
,
ADDONS_SCRIPTS_DIR
DIR_SEP
"sd"
},
{
ADDON_SKIN2
,
ADDONS_DIR
DIR_SEP
"skins2"
},
};
static
int
OpenStorage
(
vlc_object_t
*
);
static
void
CloseStorage
(
vlc_object_t
*
);
static
int
OpenLister
(
vlc_object_t
*
);
static
void
CloseLister
(
vlc_object_t
*
);
static
int
LoadCatalog
(
addons_finder_t
*
);
/*****************************************************************************
* Module descriptor
****************************************************************************/
vlc_module_begin
()
set_category
(
CAT_ADVANCED
)
set_subcategory
(
SUBCAT_ADVANCED_MISC
)
set_shortname
(
N_
(
"addons local storage"
))
add_shortcut
(
"addons.store.install"
)
set_description
(
N_
(
"Addons local storage installer"
))
set_capability
(
"addons storage"
,
10
)
set_callbacks
(
OpenStorage
,
CloseStorage
)
add_submodule
()
set_category
(
CAT_ADVANCED
)
set_subcategory
(
SUBCAT_ADVANCED_MISC
)
add_shortcut
(
"addons.store.list"
)
set_description
(
N_
(
"Addons local storage lister"
)
)
set_capability
(
"addons finder"
,
0
)
set_callbacks
(
OpenLister
,
CloseLister
)
vlc_module_end
()
static
char
*
getAddonInstallDir
(
addon_type_t
t
)
{
const
char
*
psz_subdir
=
NULL
;
char
*
psz_dir
;
char
*
psz_userdir
=
config_GetUserDir
(
VLC_DATA_DIR
);
if
(
!
psz_userdir
)
return
NULL
;
for
(
unsigned
int
i
=
0
;
i
<
ARRAY_SIZE
(
addons_dirs
);
i
++
)
{
if
(
addons_dirs
[
i
].
t
==
t
)
{
psz_subdir
=
addons_dirs
[
i
].
psz_dir
;
break
;
}
}
if
(
!
psz_subdir
)
{
free
(
psz_userdir
);
return
NULL
;
}
if
(
asprintf
(
&
psz_dir
,
"%s%s"
,
psz_userdir
,
psz_subdir
)
<
1
)
{
free
(
psz_userdir
);
return
NULL
;
}
free
(
psz_userdir
);
return
psz_dir
;
}
static
int
ListSkin_filter
(
const
char
*
psz_filename
)
{
int
i_len
=
strlen
(
psz_filename
);
if
(
i_len
<=
4
)
return
0
;
else
return
!
strcmp
(
psz_filename
+
i_len
-
4
,
".vlt"
);
}
static
int
ListScript_filter
(
const
char
*
psz_filename
)
{
int
i_len
=
strlen
(
psz_filename
);
if
(
i_len
<=
4
)
return
0
;
else
return
!
strcmp
(
psz_filename
+
i_len
-
4
,
".lua"
);
}
static
int
ParseSkins2Info
(
addons_finder_t
*
p_finder
,
stream_t
*
p_stream
,
char
**
ppsz_title
,
char
**
ppsz_source
)
{
const
char
*
p_node
;
int
i_current_node_type
;
bool
b_done
=
false
;
xml_reader_t
*
p_xml_reader
=
xml_ReaderCreate
(
p_finder
,
p_stream
);
if
(
!
p_xml_reader
)
return
VLC_EGENERIC
;
if
(
xml_ReaderNextNode
(
p_xml_reader
,
&
p_node
)
!=
XML_READER_STARTELEM
)
{
msg_Err
(
p_finder
,
"invalid xml file"
);
goto
error
;
}
if
(
strcmp
(
p_node
,
"Theme"
)
)
{
msg_Err
(
p_finder
,
"unsupported XML data format"
);
goto
error
;
}
while
(
!
b_done
&&
(
i_current_node_type
=
xml_ReaderNextNode
(
p_xml_reader
,
&
p_node
))
>
0
)
{
switch
(
i_current_node_type
)
{
case
XML_READER_STARTELEM
:
{
if
(
!
strcmp
(
p_node
,
"ThemeInfo"
)
)
{
const
char
*
attr
,
*
value
;
while
(
(
attr
=
xml_ReaderNextAttr
(
p_xml_reader
,
&
value
))
)
{
if
(
!
strcmp
(
attr
,
"name"
)
)
*
ppsz_title
=
strdup
(
value
);
else
if
(
!
strcmp
(
attr
,
"webpage"
)
)
*
ppsz_source
=
strdup
(
value
);
}
b_done
=
true
;
}
break
;
}
default:
break
;
}
}
xml_ReaderDelete
(
p_xml_reader
);
return
(
b_done
)
?
VLC_SUCCESS
:
VLC_EGENERIC
;
error:
xml_ReaderDelete
(
p_xml_reader
);
return
VLC_EGENERIC
;
}
static
int
ListSkins
(
addons_finder_t
*
p_finder
)
{
char
*
psz_dir
=
getAddonInstallDir
(
ADDON_SKIN2
);
if
(
!
psz_dir
)
return
VLC_EGENERIC
;
char
**
ppsz_list
=
NULL
;
int
i_count
=
vlc_scandir
(
psz_dir
,
&
ppsz_list
,
ListSkin_filter
,
NULL
);
for
(
int
i
=
0
;
i
<
i_count
;
i
++
)
{
char
*
psz_file
=
ppsz_list
[
i
];
if
(
!
psz_file
)
break
;
char
*
psz_uri
;
if
(
asprintf
(
&
psz_uri
,
"unzip://%s/%s!/theme.xml"
,
psz_dir
,
psz_file
)
>=
0
)
{
int
i_ret
;
char
*
psz_name
=
NULL
;
char
*
psz_source
=
NULL
;
stream_t
*
p_stream
=
stream_UrlNew
(
p_finder
,
psz_uri
);
free
(
psz_uri
);
if
(
!
p_stream
)
{
i_ret
=
VLC_EGENERIC
;
}
else
{
i_ret
=
ParseSkins2Info
(
p_finder
,
p_stream
,
&
psz_name
,
&
psz_source
);
if
(
i_ret
!=
VLC_SUCCESS
)
{
free
(
psz_name
);
free
(
psz_source
);
}
stream_Delete
(
p_stream
);
}
addon_entry_t
*
p_entry
=
addon_entry_New
();
p_entry
->
e_type
=
ADDON_SKIN2
;
p_entry
->
e_state
=
ADDON_INSTALLED
;
if
(
i_ret
==
VLC_SUCCESS
)
{
p_entry
->
psz_name
=
psz_name
;
p_entry
->
psz_description
=
strdup
(
"Skins2 theme"
);
p_entry
->
psz_source_uri
=
psz_source
;
}
else
{
p_entry
->
e_flags
|=
ADDON_BROKEN
;
p_entry
->
psz_name
=
strdup
(
psz_file
);
p_entry
->
psz_description
=
strdup
(
"Skins2 theme"
);
}
ARRAY_APPEND
(
p_finder
->
entries
,
p_entry
);
}
free
(
psz_file
);
}
free
(
ppsz_list
);
free
(
psz_dir
);
return
VLC_SUCCESS
;
}
static
bool
FileBelongsToManagedAddon
(
addons_finder_t
*
p_finder
,
const
addon_type_t
e_type
,
const
char
*
psz_file
)
{
FOREACH_ARRAY
(
const
addon_entry_t
*
p_entry
,
p_finder
->
entries
)
if
(
(
p_entry
->
e_flags
&
ADDON_MANAGEABLE
)
==
0
)
continue
;
FOREACH_ARRAY
(
const
addon_file_t
*
p_file
,
p_entry
->
files
)
if
(
p_file
->
e_filetype
==
e_type
&&
!
strcmp
(
p_file
->
psz_filename
,
psz_file
)
)
return
true
;
FOREACH_END
();
FOREACH_END
();
return
false
;
}
static
int
ListScripts
(
addons_finder_t
*
p_finder
,
addon_type_t
type
)
{
char
*
psz_dir
=
getAddonInstallDir
(
type
);
if
(
!
psz_dir
)
return
VLC_EGENERIC
;
char
**
ppsz_list
=
NULL
;
int
i_count
=
vlc_scandir
(
psz_dir
,
&
ppsz_list
,
ListScript_filter
,
NULL
);
for
(
int
i
=
0
;
i
<
i_count
;
i
++
)
{
char
*
psz_file
=
ppsz_list
[
i
];
if
(
!
psz_file
)
break
;
if
(
FileBelongsToManagedAddon
(
p_finder
,
type
,
psz_file
)
)
continue
;
addon_entry_t
*
p_entry
=
addon_entry_New
();
p_entry
->
e_state
=
ADDON_INSTALLED
;
p_entry
->
e_type
=
type
;
p_entry
->
e_flags
|=
ADDON_BROKEN
;
p_entry
->
psz_name
=
strdup
(
psz_file
);
p_entry
->
psz_description
=
strdup
(
"Lua script"
);
ARRAY_APPEND
(
p_finder
->
entries
,
p_entry
);
free
(
psz_file
);
}
free
(
ppsz_list
);
free
(
psz_dir
);
return
VLC_SUCCESS
;
}
static
int
List
(
addons_finder_t
*
p_finder
)
{
addon_type_t
types
[]
=
{
ADDON_EXTENSION
,
ADDON_PLAYLIST_PARSER
,
ADDON_SERVICE_DISCOVERY
};
unsigned
int
i_type
=
0
;
LoadCatalog
(
p_finder
);
/* Browse dirs to find rogue files */
while
(
i_type
<
ARRAY_SIZE
(
types
)
)
{
ListScripts
(
p_finder
,
types
[
i_type
++
]
);
}
ListSkins
(
p_finder
);
return
VLC_SUCCESS
;
}
static
int
recursive_mkdir
(
vlc_object_t
*
p_this
,
const
char
*
psz_dirname
)
{
/* stolen from config_CreateDir() */
if
(
!
psz_dirname
||
!*
psz_dirname
)
return
-
1
;
if
(
vlc_mkdir
(
psz_dirname
,
0700
)
==
0
)
return
0
;
switch
(
errno
)
{
case
EEXIST
:
return
0
;
case
ENOENT
:
{
/* Let's try to create the parent directory */
char
psz_parent
[
strlen
(
psz_dirname
)
+
1
],
*
psz_end
;
strcpy
(
psz_parent
,
psz_dirname
);
psz_end
=
strrchr
(
psz_parent
,
DIR_SEP_CHAR
);
if
(
psz_end
&&
psz_end
!=
psz_parent
)
{
*
psz_end
=
'\0'
;
if
(
recursive_mkdir
(
p_this
,
psz_parent
)
==
0
)
{
if
(
!
vlc_mkdir
(
psz_dirname
,
0700
)
)
return
0
;
}
}
}
}
msg_Warn
(
p_this
,
"could not create %s: %m"
,
psz_dirname
);
return
-
1
;
}
static
int
InstallFile
(
addons_storage_t
*
p_this
,
const
char
*
psz_downloadlink
,
const
char
*
psz_dest
)
{
stream_t
*
p_stream
;
FILE
*
p_destfile
;
char
buffer
[
1
<<
10
];
int
i_read
=
0
;
p_stream
=
stream_UrlNew
(
p_this
,
psz_downloadlink
);
if
(
!
p_stream
)
{
msg_Err
(
p_this
,
"Failed to access Addon download url %s"
,
psz_downloadlink
);
return
VLC_EGENERIC
;
}
char
*
psz_path
=
strdup
(
psz_dest
);
if
(
!
psz_path
)
{
stream_Delete
(
p_stream
);
return
VLC_ENOMEM
;
}
char
*
psz_buf
=
strrchr
(
psz_path
,
DIR_SEP_CHAR
);
if
(
psz_buf
)
{
*++
psz_buf
=
'\0'
;
/* ensure directory exists */
if
(
!
EMPTY_STR
(
psz_path
)
)
recursive_mkdir
(
VLC_OBJECT
(
p_this
),
psz_path
);
free
(
psz_path
);
}
p_destfile
=
vlc_fopen
(
psz_dest
,
"w"
);
if
(
!
p_destfile
)
{
msg_Err
(
p_this
,
"Failed to open Addon storage file %s"
,
psz_dest
);
stream_Delete
(
p_stream
);
return
VLC_EGENERIC
;
}
while
(
(
i_read
=
stream_Read
(
p_stream
,
&
buffer
,
1
<<
10
)
)
)
{
if
(
fwrite
(
&
buffer
,
i_read
,
1
,
p_destfile
)
<
1
)
{
msg_Err
(
p_this
,
"Failed to write to Addon file"
);
fclose
(
p_destfile
);
stream_Delete
(
p_stream
);
return
VLC_EGENERIC
;
}
}
fclose
(
p_destfile
);
stream_Delete
(
p_stream
);
return
VLC_SUCCESS
;
}
static
int
InstallAllFiles
(
addons_storage_t
*
p_this
,
const
addon_entry_t
*
p_entry
)
{
const
addon_file_t
*
p_file
;
char
*
psz_dest
;
if
(
p_entry
->
files
.
i_size
<
1
)
return
VLC_EGENERIC
;
FOREACH_ARRAY
(
p_file
,
p_entry
->
files
)
switch
(
p_file
->
e_filetype
)
{
case
ADDON_EXTENSION
:
case
ADDON_PLAYLIST_PARSER
:
case
ADDON_SERVICE_DISCOVERY
:
case
ADDON_SKIN2
:
{
if
(
strstr
(
p_file
->
psz_filename
,
".."
)
)
return
VLC_EGENERIC
;
char
*
psz_dir
=
getAddonInstallDir
(
p_file
->
e_filetype
);
if
(
!
psz_dir
||
asprintf
(
&
psz_dest
,
"%s"
DIR_SEP
"%s"
,
psz_dir
,
p_file
->
psz_filename
)
<
1
)
{
free
(
psz_dir
);
return
VLC_EGENERIC
;
}
free
(
psz_dir
);
if
(
InstallFile
(
p_this
,
p_file
->
psz_download_uri
,
psz_dest
)
!=
VLC_SUCCESS
)
{
free
(
psz_dest
);
return
VLC_EGENERIC
;
}
free
(
psz_dest
);
break
;
}
/* Ignore all other unhandled files */
case
ADDON_UNKNOWN
:
case
ADDON_PLUGIN
:
case
ADDON_OTHER
:
default:
break
;
}
FOREACH_END
()
return
VLC_SUCCESS
;
}
static
int
Install
(
addons_storage_t
*
p_storage
,
addon_entry_t
*
p_entry
)
{
vlc_object_t
*
p_this
=
VLC_OBJECT
(
p_storage
);
int
i_ret
=
VLC_EGENERIC
;
if
(
!
p_entry
->
psz_source_module
)
return
i_ret
;
/* Query origin module for download path */
addons_finder_t
*
p_finder
=
vlc_object_create
(
p_this
,
sizeof
(
addons_finder_t
)
);
if
(
!
p_finder
)
return
VLC_ENOMEM
;
module_t
*
p_module
=
module_need
(
p_finder
,
"addons finder"
,
p_entry
->
psz_source_module
,
true
);
if
(
p_module
)
{
vlc_mutex_lock
(
&
p_entry
->
lock
);
if
(
p_finder
->
pf_retrieve
(
p_finder
,
p_entry
)
==
VLC_SUCCESS
)
{
/* Do things while retrieved data is here */
i_ret
=
InstallAllFiles
(
p_storage
,
p_entry
);
/* !Do things while retrieved data is here */
}
vlc_mutex_unlock
(
&
p_entry
->
lock
);
module_unneed
(
p_finder
,
p_module
);
}
vlc_object_release
(
p_finder
);
return
i_ret
;
}
#define WRITE_WITH_ENTITIES( formatstring, varname ) \
if ( varname ) \
{\
psz_tempstring = convert_xml_special_chars( varname );\
fprintf( p_catalog, formatstring, psz_tempstring );\
free( psz_tempstring );\
}\
static
int
WriteCatalog
(
addons_storage_t
*
p_storage
,
addon_entry_t
**
pp_entries
,
int
i_entries
)
{
addon_entry_t
*
p_entry
;
char
*
psz_file
;
char
*
psz_tempstring
=
NULL
;
char
*
psz_userdir
=
config_GetUserDir
(
VLC_DATA_DIR
);
if
(
!
psz_userdir
)
return
VLC_ENOMEM
;
if
(
asprintf
(
&
psz_file
,
"%s%s"
,
psz_userdir
,
ADDONS_CATALOG
)
<
1
)
{
free
(
psz_userdir
);
return
VLC_ENOMEM
;
}
free
(
psz_userdir
);
char
*
psz_path
=
strdup
(
psz_file
);
if
(
!
psz_path
)
{
free
(
psz_file
);
return
VLC_ENOMEM
;
}
char
*
psz_buf
=
strrchr
(
psz_path
,
DIR_SEP_CHAR
);
if
(
psz_buf
)
{
*++
psz_buf
=
'\0'
;
/* ensure directory exists */
if
(
!
EMPTY_STR
(
psz_path
)
)
recursive_mkdir
(
VLC_OBJECT
(
p_storage
),
psz_path
);
free
(
psz_path
);
}
FILE
*
p_catalog
=
vlc_fopen
(
psz_file
,
"wt"
);
free
(
psz_file
);
if
(
!
p_catalog
)
return
VLC_EGENERIC
;
/* write XML header */
fprintf
(
p_catalog
,
"<?xml version=
\"
1.0
\"
encoding=
\"
UTF-8
\"
?>
\n
"
);
fprintf
(
p_catalog
,
"<videolan xmlns=
\"
http://videolan.org/ns/vlc/addons/1.0
\"
>
\n
"
);
fprintf
(
p_catalog
,
"
\t
<addons>
\n
"
);
for
(
int
i
=
0
;
i
<
i_entries
;
i
++
)
{
p_entry
=
pp_entries
[
i
];
vlc_mutex_lock
(
&
p_entry
->
lock
);
if
(
(
p_entry
->
e_state
!=
ADDON_INSTALLED
)
||
!
(
p_entry
->
e_flags
&
ADDON_MANAGEABLE
)
)
{
vlc_mutex_unlock
(
&
p_entry
->
lock
);
continue
;
}
if
(
p_entry
->
psz_source_module
)
psz_tempstring
=
convert_xml_special_chars
(
p_entry
->
psz_source_module
);
char
*
psz_uuid
=
addons_uuid_to_psz
(
(
const
addon_uuid_t
*
)
&
p_entry
->
uuid
);
fprintf
(
p_catalog
,
"
\t\t
<addon source=
\"
%s
\"
type=
\"
%s
\"
id=
\"
%s
\"
"
"downloads=
\"
%ld
\"
score=
\"
%ld
\"
"
,
(
psz_tempstring
)
?
psz_tempstring
:
""
,
getTypePsz
(
p_entry
->
e_type
),
psz_uuid
,
p_entry
->
i_downloads
,
p_entry
->
i_score
);
free
(
psz_uuid
);
free
(
psz_tempstring
);
WRITE_WITH_ENTITIES
(
" version=
\"
%s
\"
>
\n
"
,
p_entry
->
psz_version
)
WRITE_WITH_ENTITIES
(
"
\t\t\t
<name>%s</name>
\n
"
,
p_entry
->
psz_name
)
WRITE_WITH_ENTITIES
(
"
\t\t\t
<summary>%s</summary>
\n
"
,
p_entry
->
psz_summary
)
if
(
p_entry
->
psz_description
)
{
psz_tempstring
=
p_entry
->
psz_description
;
/* FIXME: do real escaping */
while
(
(
psz_tempstring
=
strstr
(
psz_tempstring
,
"]]>"
)
)
)
*
psz_tempstring
=
' '
;
fprintf
(
p_catalog
,
"
\t\t\t
<description><![CDATA[%s]]></description>
\n
"
,
p_entry
->
psz_description
);
}
WRITE_WITH_ENTITIES
(
"
\t\t\t
<image>%s</image>
\n
"
,
p_entry
->
psz_image_data
)
WRITE_WITH_ENTITIES
(
"
\t\t\t
<archive>%s</archive>
\n
"
,
p_entry
->
psz_archive_uri
)
fprintf
(
p_catalog
,
"
\t\t\t
<authorship>
\n
"
);
WRITE_WITH_ENTITIES
(
"
\t\t\t\t
<creator>%s</creator>
\n
"
,
p_entry
->
psz_author
)
WRITE_WITH_ENTITIES
(
"
\t\t\t\t
<sourceurl>%s</sourceurl>
\n
"
,
p_entry
->
psz_source_uri
)
fprintf
(
p_catalog
,
"
\t\t\t
</authorship>
\n
"
);
FOREACH_ARRAY
(
addon_file_t
*
p_file
,
p_entry
->
files
)
psz_tempstring
=
convert_xml_special_chars
(
p_file
->
psz_filename
);
fprintf
(
p_catalog
,
"
\t\t\t
<resource type=
\"
%s
\"
>%s</resource>
\n
"
,
getTypePsz
(
p_file
->
e_filetype
),
psz_tempstring
);
free
(
psz_tempstring
);
FOREACH_END
();
fprintf
(
p_catalog
,
"
\t\t
</addon>
\n
"
);
vlc_mutex_unlock
(
&
p_entry
->
lock
);
}
fprintf
(
p_catalog
,
"
\t
</addons>
\n
"
);
fprintf
(
p_catalog
,
"</videolan>
\n
"
);
fclose
(
p_catalog
);
return
VLC_SUCCESS
;
}
static
int
LoadCatalog
(
addons_finder_t
*
p_finder
)
{
char
*
psz_path
;
char
*
psz_userdir
=
config_GetUserDir
(
VLC_DATA_DIR
);
if
(
!
psz_userdir
)
return
VLC_ENOMEM
;
if
(
asprintf
(
&
psz_path
,
"file://%s%s"
,
psz_userdir
,
ADDONS_CATALOG
)
<
1
)
{
free
(
psz_userdir
);
return
VLC_ENOMEM
;
}
free
(
psz_userdir
);
addon_entry_t
*
p_entry
=
NULL
;
const
char
*
p_node
;
int
i_current_node_type
;
int
i_ret
=
VLC_SUCCESS
;
/* attr */
const
char
*
attr
,
*
value
;
/* temp reading */
char
*
psz_filename
=
NULL
;
int
i_filetype
=
-
1
;
struct
stat
stat_
;
if
(
vlc_stat
(
psz_path
,
&
stat_
)
||
!
stat_
.
st_blocks
)
{
free
(
psz_path
);
return
VLC_EGENERIC
;
}
stream_t
*
p_stream
=
stream_UrlNew
(
p_finder
,
psz_path
);
free
(
psz_path
);
if
(
!
p_stream
)
return
VLC_EGENERIC
;
xml_reader_t
*
p_xml_reader
=
xml_ReaderCreate
(
p_finder
,
p_stream
);
if
(
!
p_xml_reader
)
{
stream_Delete
(
p_stream
);
return
VLC_EGENERIC
;
}
if
(
xml_ReaderNextNode
(
p_xml_reader
,
&
p_node
)
!=
XML_READER_STARTELEM
)
{
msg_Err
(
p_finder
,
"invalid catalog"
);
i_ret
=
VLC_EGENERIC
;
goto
end
;
}
if
(
strcmp
(
p_node
,
"videolan"
)
)
{
msg_Err
(
p_finder
,
"unsupported catalog data format"
);
i_ret
=
VLC_EGENERIC
;
goto
end
;
}
while
(
(
i_current_node_type
=
xml_ReaderNextNode
(
p_xml_reader
,
&
p_node
))
>
0
)
{
switch
(
i_current_node_type
)
{
case
XML_READER_STARTELEM
:
{
if
(
!
strcmp
(
p_node
,
"addon"
)
)
{
p_entry
=
addon_entry_New
();
//p_entry->psz_source_module = strdup( ADDONS_MODULE_SHORTCUT );
p_entry
->
e_flags
=
ADDON_MANAGEABLE
;
p_entry
->
e_state
=
ADDON_INSTALLED
;
while
(
(
attr
=
xml_ReaderNextAttr
(
p_xml_reader
,
&
value
))
)
{
if
(
!
strcmp
(
attr
,
"type"
)
)
{
p_entry
->
e_type
=
ReadType
(
value
);
}
else
if
(
!
strcmp
(
attr
,
"id"
)
)
{
addons_uuid_read
(
value
,
&
p_entry
->
uuid
);
}
else
if
(
!
strcmp
(
attr
,
"downloads"
)
)
{
p_entry
->
i_downloads
=
atoi
(
value
);
}
else
if
(
!
strcmp
(
attr
,
"score"
)
)
{
p_entry
->
i_score
=
atol
(
value
);
}
else
if
(
!
strcmp
(
attr
,
"source"
)
)
{
p_entry
->
psz_source_module
=
strdup
(
value
);
}
else
if
(
!
strcmp
(
attr
,
"version"
)
)
{
p_entry
->
psz_version
=
strdup
(
value
);
}
}
break
;
}
if
(
!
p_entry
)
break
;
BINDNODE
(
"name"
,
p_entry
->
psz_name
,
TYPE_STRING
)
BINDNODE
(
"archive"
,
p_entry
->
psz_archive_uri
,
TYPE_STRING
)
BINDNODE
(
"summary"
,
p_entry
->
psz_summary
,
TYPE_STRING
)
BINDNODE
(
"description"
,
p_entry
->
psz_description
,
TYPE_STRING
)
BINDNODE
(
"image"
,
p_entry
->
psz_image_data
,
TYPE_STRING
)
BINDNODE
(
"resource"
,
psz_filename
,
TYPE_STRING
)
BINDNODE
(
"creator"
,
p_entry
->
psz_author
,
TYPE_STRING
)
BINDNODE
(
"sourceurl"
,
p_entry
->
psz_source_uri
,
TYPE_STRING
)
data_pointer
.
e_type
=
TYPE_NONE
;
if
(
!
strcmp
(
p_node
,
"resource"
)
)
{
while
(
(
attr
=
xml_ReaderNextAttr
(
p_xml_reader
,
&
value
))
)
{
if
(
!
strcmp
(
attr
,
"type"
)
)
{
i_filetype
=
ReadType
(
value
);
}
}
}
break
;
}
case
XML_READER_TEXT
:
if
(
data_pointer
.
e_type
==
TYPE_NONE
||
!
p_entry
)
break
;
if
(
data_pointer
.
e_type
==
TYPE_STRING
)
*
data_pointer
.
u_data
.
ppsz
=
strdup
(
p_node
);
else
if
(
data_pointer
.
e_type
==
TYPE_LONG
)
*
data_pointer
.
u_data
.
pl
=
atol
(
p_node
);
else
if
(
data_pointer
.
e_type
==
TYPE_INTEGER
)
*
data_pointer
.
u_data
.
pi
=
atoi
(
p_node
);
break
;
case
XML_READER_ENDELEM
:
if
(
!
p_entry
)
break
;
if
(
!
strcmp
(
p_node
,
"addon"
)
)
{
/* then append entry */
ARRAY_APPEND
(
p_finder
->
entries
,
p_entry
);
p_entry
=
NULL
;
}
if
(
!
strcmp
(
p_node
,
"resource"
)
)
{
if
(
p_entry
&&
psz_filename
&&
i_filetype
>=
0
)
{
addon_file_t
*
p_file
=
malloc
(
sizeof
(
addon_file_t
)
);
p_file
->
e_filetype
=
i_filetype
;
p_file
->
psz_filename
=
psz_filename
;
p_file
->
psz_download_uri
=
NULL
;
ARRAY_APPEND
(
p_entry
->
files
,
p_file
);
}
/* reset temp */
psz_filename
=
NULL
;
i_filetype
=
-
1
;
}
data_pointer
.
e_type
=
TYPE_NONE
;
break
;
default:
break
;
}
}
end:
xml_ReaderDelete
(
p_xml_reader
);
stream_Delete
(
p_stream
);
return
i_ret
;
}
static
int
Remove
(
addons_storage_t
*
p_storage
,
addon_entry_t
*
p_entry
)
{
vlc_mutex_lock
(
&
p_entry
->
lock
);
FOREACH_ARRAY
(
addon_file_t
*
p_file
,
p_entry
->
files
)
switch
(
p_file
->
e_filetype
)
{
case
ADDON_EXTENSION
:
case
ADDON_PLAYLIST_PARSER
:
case
ADDON_SERVICE_DISCOVERY
:
case
ADDON_SKIN2
:
{
char
*
psz_dest
;
char
*
psz_dir
=
getAddonInstallDir
(
p_file
->
e_filetype
);
if
(
!
psz_dir
||
asprintf
(
&
psz_dest
,
"%s"
DIR_SEP
"%s"
,
psz_dir
,
p_file
->
psz_filename
)
<
1
)
{
free
(
psz_dir
);
return
VLC_EGENERIC
;
}
free
(
psz_dir
);
vlc_unlink
(
psz_dest
);
msg_Dbg
(
p_storage
,
"removing %s"
,
psz_dest
);
free
(
psz_dest
);
break
;
}
/* Ignore all other unhandled files */
case
ADDON_UNKNOWN
:
case
ADDON_PLUGIN
:
case
ADDON_OTHER
:
default:
break
;
}
FOREACH_END
()
/* Remove file info on success */
FOREACH_ARRAY
(
addon_file_t
*
p_file
,
p_entry
->
files
)
free
(
p_file
->
psz_filename
);
free
(
p_file
->
psz_download_uri
);
free
(
p_file
);
FOREACH_END
()
ARRAY_RESET
(
p_entry
->
files
);
vlc_mutex_unlock
(
&
p_entry
->
lock
);
return
VLC_SUCCESS
;
}
static
int
OpenStorage
(
vlc_object_t
*
p_this
)
{
addons_storage_t
*
p_storage
=
(
addons_storage_t
*
)
p_this
;
p_storage
->
pf_install
=
Install
;
p_storage
->
pf_remove
=
Remove
;
p_storage
->
pf_catalog
=
WriteCatalog
;
return
VLC_SUCCESS
;
}
static
void
CloseStorage
(
vlc_object_t
*
p_this
)
{
VLC_UNUSED
(
p_this
);
}
static
int
OpenLister
(
vlc_object_t
*
p_this
)
{
addons_finder_t
*
p_finder
=
(
addons_finder_t
*
)
p_this
;
p_finder
->
pf_find
=
List
;
p_finder
->
pf_retrieve
=
NULL
;
return
VLC_SUCCESS
;
}
static
void
CloseLister
(
vlc_object_t
*
p_this
)
{
VLC_UNUSED
(
p_this
);
}
modules/misc/addons/xmlreading.h
0 → 100644
View file @
29f4fe99
/*****************************************************************************
* xmlreading.h : Videolan.org's Addons xml readers helper
*****************************************************************************
* Copyright (C) 2014 VLC authors and VideoLAN
*
* 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.
*****************************************************************************/
#define BINDNODE(name,target,type)\
if ( ! strcmp(p_node, name) )\
{\
if ( type == TYPE_STRING ) \
data_pointer.u_data.ppsz = (char**)⌖\
else if ( type == TYPE_LONG ) \
data_pointer.u_data.pl = (long*)⌖\
else \
data_pointer.u_data.pi = (int*)⌖\
data_pointer.e_type = type;\
} else
struct
{
union
{
char
**
ppsz
;
int
*
pi
;
long
*
pl
;
}
u_data
;
enum
{
TYPE_NONE
,
TYPE_STRING
,
TYPE_INTEGER
,
TYPE_LONG
}
e_type
;
}
data_pointer
=
{
{
NULL
},
TYPE_NONE
};
static
int
ReadType
(
const
char
*
value
)
{
if
(
!
strcmp
(
value
,
"playlist"
)
)
return
ADDON_PLAYLIST_PARSER
;
else
if
(
!
strcmp
(
value
,
"skin"
)
)
return
ADDON_SKIN2
;
else
if
(
!
strcmp
(
value
,
"discovery"
)
)
return
ADDON_SERVICE_DISCOVERY
;
else
if
(
!
strcmp
(
value
,
"extension"
)
)
return
ADDON_EXTENSION
;
else
return
ADDON_UNKNOWN
;
}
static
const
char
*
getTypePsz
(
int
i_type
)
{
switch
(
i_type
)
{
case
ADDON_PLAYLIST_PARSER
:
return
"playlist"
;
case
ADDON_SKIN2
:
return
"skin"
;
case
ADDON_SERVICE_DISCOVERY
:
return
"discovery"
;
case
ADDON_EXTENSION
:
return
"extension"
;
case
ADDON_UNKNOWN
:
default:
return
"unknown"
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment