Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
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
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