Commit 8e8e6441 authored by Antoine Cellerier's avatar Antoine Cellerier

src/playlist/loadsave.c, modules/demux/playlist/*, modules/gui/*,

modules/misc/playlist/*, modules/access/http.c: XSPF playlist support
(read and write) by Daniel Stranger. Many thanks

src/misc/modules.c, src/misc/strings.c, include/vlc_strings.h: string
handling functions.

modules/control/http/*, modules/services_discovery/upnp_intel.cpp: use
these string handling functions.
parent d78b7c38
/*****************************************************************************
* vlc_strings.h: String functions
*****************************************************************************
* Copyright (C) 2006 the VideoLAN team
* $Id$
*
* Authors: Antoine Cellerier <dionoea at videolan dot org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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_STRINGS_H
#define _VLC_STRINGS_H 1
#include <vlc/vlc.h>
/**
* \defgroup strings Strings
* @{
*/
VLC_EXPORT( char *, decode_encoded_URI_duplicate, ( const char *psz ) );
VLC_EXPORT( void, decode_encoded_URI, ( char *psz ) );
VLC_EXPORT( void, resolve_xml_special_chars, ( char *psz_value ) );
VLC_EXPORT( char *, convert_xml_special_chars, ( const char *psz_content ) );
/**
* @}
*/
#endif
......@@ -480,6 +480,10 @@ struct module_symbols_t
double (*us_atof_inner) (const char *);
double (*us_strtod_inner) (const char *, char **);
lldiv_t (*vlc_lldiv_inner) (long long numer, long long denom);
void (*decode_encoded_URI_inner) (char *psz);
char * (*convert_xml_special_chars_inner) (const char *psz_content);
char * (*decode_encoded_URI_duplicate_inner) (const char *psz);
void (*resolve_xml_special_chars_inner) (char *psz_value);
};
# if defined (__PLUGIN__)
# define aout_FiltersCreatePipeline (p_symbols)->aout_FiltersCreatePipeline_inner
......@@ -940,6 +944,10 @@ struct module_symbols_t
# define us_atof (p_symbols)->us_atof_inner
# define us_strtod (p_symbols)->us_strtod_inner
# define vlc_lldiv (p_symbols)->vlc_lldiv_inner
# define decode_encoded_URI (p_symbols)->decode_encoded_URI_inner
# define convert_xml_special_chars (p_symbols)->convert_xml_special_chars_inner
# define decode_encoded_URI_duplicate (p_symbols)->decode_encoded_URI_duplicate_inner
# define resolve_xml_special_chars (p_symbols)->resolve_xml_special_chars_inner
# elif defined (HAVE_DYNAMIC_PLUGINS) && !defined (__BUILTIN__)
/******************************************************************
* STORE_SYMBOLS: store VLC APIs into p_symbols for plugin access.
......@@ -1403,6 +1411,10 @@ struct module_symbols_t
((p_symbols)->us_atof_inner) = us_atof; \
((p_symbols)->us_strtod_inner) = us_strtod; \
((p_symbols)->vlc_lldiv_inner) = vlc_lldiv; \
((p_symbols)->decode_encoded_URI_inner) = decode_encoded_URI; \
((p_symbols)->convert_xml_special_chars_inner) = convert_xml_special_chars; \
((p_symbols)->decode_encoded_URI_duplicate_inner) = decode_encoded_URI_duplicate; \
((p_symbols)->resolve_xml_special_chars_inner) = resolve_xml_special_chars; \
(p_symbols)->net_ConvertIPv4_deprecated = NULL; \
(p_symbols)->__stats_CounterGet_deprecated = NULL; \
(p_symbols)->__stats_TimerDumpAll_deprecated = NULL; \
......
......@@ -403,6 +403,9 @@ connect:
/* Grrrr! detect ultravox server and force NSV demuxer */
p_access->psz_demux = strdup( "nsv" );
}
else if( p_sys->psz_mime &&
!strcasecmp( p_sys->psz_mime, "application/xspf+xml" ) )
p_access->psz_demux = strdup( "xspf-open" );
if( p_sys->b_reconnect ) msg_Dbg( p_access, "auto re-connect enabled" );
......
......@@ -420,44 +420,8 @@ void E_(EvaluateRPN)( intf_thread_t *p_intf, mvar_t *vars,
{
char *psz_src = E_(SSPop)( st );
char *psz_dest;
char *str = psz_src;
p = psz_dest = malloc( strlen( str ) * 6 + 1 );
while( *str != '\0' )
{
if( *str == '&' )
{
strcpy( p, "&amp;" );
p += 5;
}
else if( *str == '\"' )
{
strcpy( p, "&quot;" );
p += 6;
}
else if( *str == '\'' )
{
strcpy( p, "&#039;" );
p += 6;
}
else if( *str == '<' )
{
strcpy( p, "&lt;" );
p += 4;
}
else if( *str == '>' )
{
strcpy( p, "&gt;" );
p += 4;
}
else
{
*p++ = *str;
}
str++;
}
*p = '\0';
psz_dest = convert_xml_special_chars( psz_src );
E_(SSPush)( st, psz_dest );
free( psz_src );
......
......@@ -24,6 +24,7 @@
*****************************************************************************/
#include "http.h"
#include "vlc_strings.h"
/****************************************************************************
* File and directory functions
......@@ -747,38 +748,7 @@ char *E_(ExtractURIValue)( char *psz_uri, const char *psz_name,
void E_(DecodeEncodedURI)( char *psz )
{
char *dup = strdup( psz );
char *p = dup;
while( *p )
{
if( *p == '%' )
{
char val[3];
p++;
if( !*p )
{
break;
}
val[0] = *p++;
val[1] = *p++;
val[2] = '\0';
*psz++ = strtol( val, NULL, 16 );
}
else if( *p == '+' )
{
*psz++ = ' ';
p++;
}
else
{
*psz++ = *p++;
}
}
*psz++ = '\0';
free( dup );
decode_encoded_URI( psz );
}
/* Since the resulting string is smaller we can work in place, so it is
......
SOURCES_playlist = playlist.c \
playlist.h \
old.c \
m3u.c \
b4s.c \
pls.c \
dvb.c \
podcast.c
SOURCES_playlist = \
playlist.c \
playlist.h \
old.c \
m3u.c \
b4s.c \
pls.c \
dvb.c \
podcast.c \
xspf.c \
xspf.h \
$(NULL)
......@@ -84,6 +84,11 @@ vlc_module_begin();
add_shortcut( "podcast" );
set_capability( "demux2", 10 );
set_callbacks( E_(Import_podcast), E_(Close_podcast) );
add_submodule();
set_description( _("XSPF playlist import") );
add_shortcut( "xspf-open" );
set_capability( "demux2", 10 );
set_callbacks( E_(xspf_import_Activate), NULL );
vlc_module_end();
......
......@@ -45,3 +45,5 @@ void E_(Close_DVB) ( vlc_object_t * );
int E_(Import_podcast) ( vlc_object_t * );
void E_(Close_podcast) ( vlc_object_t * );
int E_(xspf_import_Activate) ( vlc_object_t * );
This diff is collapsed.
/*****************************************************************************
* Copyright (C) 2006 Daniel Stränger <vlc at schmaller dot de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*******************************************************************************/
/**
* \file modules/demux/playlist/xspf.h
* \brief XSPF playlist import: prototypes, datatypes, defines
*/
/* defines */
#define FREE_NAME() if (psz_name) {free(psz_name);psz_name=NULL;}
#define FREE_VALUE() if (psz_value) {free(psz_value);psz_value=NULL;}
#define FREE_ATT() FREE_NAME();FREE_VALUE()
#define UNKNOWN_CONTENT 0
#define SIMPLE_CONTENT 1
#define COMPLEX_CONTENT 2
#define SIMPLE_INTERFACE (playlist_item_t *p_item,\
const char *psz_name,\
char *psz_value)
#define COMPLEX_INTERFACE (demux_t *p_demux,\
playlist_t *p_playlist,\
playlist_item_t *p_item,\
xml_reader_t *p_xml_reader,\
const char *psz_element)
/* prototypes */
int xspf_import_Demux( demux_t *);
int xspf_import_Control( demux_t *, int, va_list );
static vlc_bool_t parse_playlist_node COMPLEX_INTERFACE;
static vlc_bool_t parse_tracklist_node COMPLEX_INTERFACE;
static vlc_bool_t parse_track_node COMPLEX_INTERFACE;
static vlc_bool_t set_item_info SIMPLE_INTERFACE;
static vlc_bool_t skip_element COMPLEX_INTERFACE;
static vlc_bool_t insert_new_item( playlist_t *, playlist_item_t *, playlist_item_t **, char *);
/* datatypes */
typedef struct
{
const char *name;
int type;
union
{
vlc_bool_t (*smpl) SIMPLE_INTERFACE;
vlc_bool_t (*cmplx) COMPLEX_INTERFACE;
} pf_handler;
} xml_elem_hnd_t;
......@@ -229,14 +229,16 @@ void Dialogs::showChangeSkin()
void Dialogs::showPlaylistLoad()
{
showFileGeneric( _("Open playlist"),
_("All playlists|*.pls;*.m3u;*.asx;*.b4s|M3U files|*.m3u"),
_("All playlists|*.pls;*.m3u;*.asx;*.b4s;*.xspf|"
"M3U files|*.m3u|"
"XSPF playlist|*.xspf"),
showPlaylistLoadCB, kOPEN );
}
void Dialogs::showPlaylistSave()
{
showFileGeneric( _("Save playlist"), _("M3U file|*.m3u"),
showFileGeneric( _("Save playlist"), _("M3U file|*.m3u|XSPF playlist|*.xspf"),
showPlaylistSaveCB, kSAVE );
}
......
......@@ -908,7 +908,9 @@ void Playlist::OnSave( wxCommandEvent& WXUNUSED(event) )
char *psz_desc;
char *psz_filter;
char *psz_module;
} formats[] = {{ _("M3U file"), "*.m3u", "export-m3u" }};
} formats[] = {{ _("M3U file"), "*.m3u", "export-m3u" },
{ _("XSPF playlist"), "*.xspf", "export-xspf"}
};
wxString filter = wxT("");
......@@ -943,7 +945,7 @@ void Playlist::OnSave( wxCommandEvent& WXUNUSED(event) )
void Playlist::OnOpen( wxCommandEvent& WXUNUSED(event) )
{
wxFileDialog dialog( this, wxU(_("Open playlist")), wxT(""), wxT(""),
wxT("All playlists|*.pls;*.m3u;*.asx;*.b4s|M3U files|*.m3u"), wxOPEN );
wxT("All playlists|*.pls;*.m3u;*.asx;*.b4s;*.xspf|XSPF playlist|*.xspf|M3U files|*.m3u"), wxOPEN );
if( dialog.ShowModal() == wxID_OK )
{
......
SOURCES_export = export.c \
m3u.c \
old.c
SOURCES_export = \
export.c \
m3u.c \
xspf.c \
xspf.h \
old.c \
$(NULL)
......@@ -31,7 +31,7 @@
***************************************************************************/
int Export_M3U ( vlc_object_t *p_intf );
int Export_Old ( vlc_object_t *p_intf );
int E_(xspf_export_playlist)( vlc_object_t *p_intf );
/*****************************************************************************
* Module descriptor
......@@ -52,4 +52,10 @@ vlc_module_begin();
set_capability( "playlist export" , 0);
set_callbacks( Export_Old , NULL );
add_submodule();
set_description( _("XSPF playlist export") );
add_shortcut( "export-xspf" );
set_capability( "playlist export" , 0);
set_callbacks( E_(xspf_export_playlist) , NULL );
vlc_module_end();
/******************************************************************************
* Copyright (C) 2006 Daniel Stränger <vlc at schmaller dot de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*******************************************************************************/
/**
* \file modules/misc/playlist/xspf.c
* \brief XSPF playlist export functions
*/
#include <stdio.h>
#include <vlc/vlc.h>
#include <vlc/intf.h>
#include "vlc_meta.h"
#include "vlc_strings.h"
#include "xspf.h"
/**
* \brief Prints the XSPF header to file, writes each item by xspf_export_item()
* and closes the open xml elements
* \param p_this the VLC playlist object
* \return VLC_SUCCESS if some memory is available, otherwise VLC_ENONMEM
*/
int E_(xspf_export_playlist)( vlc_object_t *p_this )
{
const playlist_t *p_playlist = (playlist_t *)p_this;
const playlist_export_t *p_export =
(playlist_export_t *)p_playlist->p_private;
int i;
char *psz;
char *psz_temp;
playlist_item_t **pp_items = NULL;
int i_size;
playlist_item_t *p_node;
/* write XSPF XML header - since we don't use <extension>,
* we get by with version 0 */
fprintf( p_export->p_file, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
fprintf( p_export->p_file,
"<playlist version=\"0\" xmlns=\"http://xspf.org/ns/0/\">\n" );
/* save tho whole playlist or only the current node */
#define p_item p_playlist->status.p_item
if ( p_item )
{
for (i = 0; i < p_item->i_parents; i++ )
{
if ( p_item->pp_parents[i]->p_parent->input.i_type
== ITEM_TYPE_PLAYLIST )
{
/* set the current node and its children */
p_node = p_item->pp_parents[i]->p_parent;
pp_items = p_node->pp_children;
i_size = p_node->i_children;
#undef p_item
/* save name of the playlist node */
psz_temp = convert_xml_special_chars( p_node->input.psz_name );
if ( *psz_temp )
fprintf( p_export->p_file, "\t<title>%s</title>\n",
psz_temp );
free( psz_temp );
/* save the creator of the playlist node */
psz = vlc_input_item_GetInfo( &p_node->input,
_(VLC_META_INFO_CAT),
_(VLC_META_ARTIST) );
if ( psz && !*psz )
{
free ( psz );
psz = NULL;
}
if ( !psz )
psz = vlc_input_item_GetInfo( &p_node->input,
_(VLC_META_INFO_CAT),
_(VLC_META_AUTHOR) );
psz_temp = convert_xml_special_chars( psz );
if ( psz ) free( psz );
if ( *psz_temp )
fprintf( p_export->p_file, "\t<creator>%s</creator>\n",
psz_temp );
free( psz_temp );
/* save location of the playlist node */
psz = assertUTF8URI( p_export->psz_filename );
if ( psz && *psz )
{
fprintf( p_export->p_file, "\t<location>%s</location>\n",
psz );
free( psz );
}
break;
}
}
}
/* prepare all the playlist children for export */
if ( !pp_items )
{
pp_items = p_playlist->pp_items;
i_size = p_playlist->i_size;
}
/* export all items */
fprintf( p_export->p_file, "\t<trackList>\n" );
for ( i = 0; i < i_size; i++ )
{
xspf_export_item( pp_items[i], p_export->p_file );
}
/* close the header elements */
fprintf( p_export->p_file, "\t</trackList>\n" );
fprintf( p_export->p_file, "</playlist>\n" );
return VLC_SUCCESS;
}
/**
* \brief exports one item to file or traverse if item is a node
* \param p_item playlist item to export
* \param p_file file to write xml-converted item to
*/
static void xspf_export_item( playlist_item_t *p_item, FILE *p_file )
{
int i; /**< iterator for all children if the current item is a node */
char *psz;
char *psz_temp;
if ( !p_item )
return;
/** \todo only "flat" playlists supported at this time.
* extend to save the tree structure.
*/
/* if we get a node here, we must traverse it */
if ( p_item->i_children > 0 )
{
for ( i = 0; i < p_item->i_children; i++ )
{
xspf_export_item( p_item->pp_children[i], p_file );
}
return;
}
/* leaves can be written directly */
fprintf( p_file, "\t\t<track>\n" );
/* -> the location */
if ( p_item->input.psz_uri && *p_item->input.psz_uri )
{
psz = assertUTF8URI( p_item->input.psz_uri );
fprintf( p_file, "\t\t\t<location>%s</location>\n", psz );
free( psz );
}
/* -> the name/title (only if different from uri)*/
if ( p_item->input.psz_name &&
p_item->input.psz_uri &&
strcmp( p_item->input.psz_uri, p_item->input.psz_name ) )
{
psz_temp = convert_xml_special_chars( p_item->input.psz_name );
if ( *psz_temp )
fprintf( p_file, "\t\t\t<title>%s</title>\n", psz_temp );
free( psz_temp );
}
/* -> the artist/creator */
psz = vlc_input_item_GetInfo( &p_item->input,
_(VLC_META_INFO_CAT),
_(VLC_META_ARTIST) );
if ( psz && !*psz )
{
free ( psz );
psz = NULL;
}
if ( !psz )
psz = vlc_input_item_GetInfo( &p_item->input,
_(VLC_META_INFO_CAT),
_(VLC_META_AUTHOR) );
psz_temp = convert_xml_special_chars( psz );
if ( psz ) free( psz );
if ( *psz_temp )
fprintf( p_file, "\t\t\t<creator>%s</creator>\n", psz_temp );
free( psz_temp );
/* -> the album */
psz = vlc_input_item_GetInfo( &p_item->input,
_(VLC_META_INFO_CAT),
_(VLC_META_COLLECTION) );
psz_temp = convert_xml_special_chars( psz );
if ( psz ) free( psz );
if ( *psz_temp )
fprintf( p_file, "\t\t\t<album>%s</album>\n", psz_temp );
free( psz_temp );
/* -> the track number */
psz = vlc_input_item_GetInfo( &p_item->input,
_(VLC_META_INFO_CAT),
_(VLC_META_SEQ_NUM) );
if ( psz )
{
if ( *psz )
fprintf( p_file, "\t\t\t<trackNum>%i</trackNum>\n", atoi( psz ) );
free( psz );
}
/* -> the duration */
if ( p_item->input.i_duration > 0 )
{
fprintf( p_file, "\t\t\t<duration>%ld</duration>\n",
(long)(p_item->input.i_duration / 1000) );
}
fprintf( p_file, "\t\t</track>\n" );
return;
}
/**
* \param psz_name the location of the media ressource (e.g. local file,
* device, network stream, etc.)
* \return a new char buffer which asserts that the location is valid UTF-8
* and a valid URI
* \note the returned buffer must be freed, when it isn't used anymore
*/
static char *assertUTF8URI( char *psz_name )
{
char *psz_ret = NULL; /**< the new result buffer to return */
char *psz_s = NULL, *psz_d = NULL; /**< src & dest pointers for URI conversion */
vlc_bool_t b_name_is_uri = VLC_FALSE;
if ( !psz_name || !*psz_name )
return NULL;
/* check that string is valid UTF-8 */
/* XXX: Why do we even need to do that ? (all strings in core are UTF-8 encoded */
if( !( psz_s = EnsureUTF8( psz_name ) ) )
return NULL;
/* max. 3x for URI conversion (percent escaping) and
8 bytes for "file://" and NULL-termination */
psz_ret = (char *)malloc( sizeof(char)*strlen(psz_name)*6*3+8 );
if ( !psz_ret )
return NULL;
/** \todo check for a valid scheme part preceding the colon */
if ( strchr( psz_s, ':' ) )
{
psz_d = psz_ret;
b_name_is_uri = VLC_TRUE;
}
/* assume "file" scheme if no scheme-part is included */
else
{
strcpy( psz_ret, "file://" );
psz_d = psz_ret + 7;
}
while ( *psz_s )
{
/* percent-encode all non-ASCII and the XML special characters and the percent sign itself */
if ( *psz_s & B10000000 ||
*psz_s == '<' ||
*psz_s == '>' ||
*psz_s == '&' ||
*psz_s == ' ' ||
( *psz_s == '%' && !b_name_is_uri ) )
{
*psz_d++ = '%';
*psz_d++ = hexchars[(*psz_s >> 4) & B00001111];
*psz_d++ = hexchars[*psz_s & B00001111];
} else
*psz_d++ = *psz_s;
psz_s++;
}
*psz_d = '\0';
return (char *)realloc( psz_ret, sizeof(char)*strlen( psz_ret ) + 1 );
}
/*****************************************************************************
* Copyright (C) 2006 Daniel Stränger <vlc at schmaller dot de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*******************************************************************************/
/**
* \file modules/misc/playlist/xspf.h
* \brief XSPF playlist export module header file
*/
/* defs */
#define B10000000 0x80
#define B01000000 0x40
#define B11000000 0xc0
#define B00001111 0x0f
#define XSPF_MAX_CONTENT 2000
/* constants */
const char hexchars[16] = "0123456789ABCDEF";
/* prototypes */
int E_(xspf_export_playlist)( vlc_object_t * );
static void xspf_export_item( playlist_item_t *, FILE * );
static char *assertUTF8URI( char * );
This diff is collapsed.
......@@ -89,6 +89,7 @@ HEADERS_include = \
../include/vlc_playlist.h \
../include/vlc_spu.h \
../include/vlc_stream.h \
../include/vlc_strings.h \
../include/vlc_symbols.h \
../include/vlc_threads_funcs.h \
../include/vlc_threads.h \
......@@ -321,6 +322,7 @@ SOURCES_libvlc_common = \
misc/modules.c \
misc/threads.c \
misc/stats.c \
misc/strings.c \
misc/unicode.c \
misc/cpu.c \
misc/configuration.c \
......
......@@ -110,6 +110,7 @@
#include "vlc_osd.h"
#include "vlc_update.h"
#include "vlc_strings.h"
#if defined( _MSC_VER ) && defined( UNDER_CE )
# include "modules_builtin_evc.h"
......
/*****************************************************************************
* strings.c: String related functions
*****************************************************************************
* Copyright (C) 2006 the VideoLAN team
* $Id$
*
* Authors: Antoine Cellerier <dionoea at videolan dot org>
* Daniel Stranger <vlc at schmaller dot de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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
*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "vlc_strings.h"
/**
* Decode URI encoded string
* \return decoded duplicated string
*/
char *decode_encoded_URI_duplicate( const char *psz )
{
char *psz_dup = strdup( psz );
decode_encoded_URI( psz_dup );
return psz_dup;
}
/**
* Decode URI encoded string
* \return nothing
*/
void decode_encoded_URI( char *psz )
{
char *dup = strdup( psz );
char *p = dup;
while( *p )
{
if( *p == '%' )
{
char val[3];
p++;
if( !*p )
{
break;
}
val[0] = *p++;
val[1] = *p++;
val[2] = '\0';
*psz++ = strtol( val, NULL, 16 );
}
else if( *p == '+' )
{
*psz++ = ' ';
p++;
}
else
{
*psz++ = *p++;
}
}
*psz++ = '\0';
free( dup );
}
/**
* Converts "&lt;", "&gt;" and "&amp;" to "<", ">" and "&"
* \param string to convert
*/
void resolve_xml_special_chars( char *psz_value )
{
char *p_pos = psz_value;
while ( *psz_value )
{
if( !strncmp( psz_value, "&lt;", 4 ) )
{
*p_pos = '<';
psz_value += 4;
}
else if( !strncmp( psz_value, "&gt;", 4 ) )
{
*p_pos = '>';
psz_value += 4;
}
else if( !strncmp( psz_value, "&amp;", 5 ) )
{
*p_pos = '&';
psz_value += 5;
}
else if( !strncmp( psz_value, "&quot;", 6 ) )
{
*p_pos = '\"';
psz_value += 6;
}
else if( !strncmp( psz_value, "&#039;", 6 ) )
{
*p_pos = '\'';
psz_value += 6;
}
else
{
*p_pos = *psz_value;
psz_value++;
}
p_pos++;
}
*p_pos = '\0';
}
/**
* Converts '<', '>', '\"', '\'' and '&' to their html entities
* \param psz_content simple element content that is to be converted
*/
char *convert_xml_special_chars( const char *psz_content )
{
char *psz_temp = malloc( 6 * strlen( psz_content ) + 1 );
const char *p_from = psz_content;
char *p_to = psz_temp;
while ( *p_from )
{
if ( *p_from == '<' )
{
strcpy( p_to, "&lt;" );
p_to += 4;
}
else if ( *p_from == '>' )
{
strcpy( p_to, "&gt;" );
p_to += 4;
}
else if ( *p_from == '&' )
{
strcpy( p_to, "&amp;" );
p_to += 5;
}
else if( *p_from == '\"' )
{
strcpy( p_to, "&quot;" );
p_to += 6;
}
else if( *p_from == '\'' )
{
strcpy( p_to, "&#039;" );
p_to += 6;
}
else
{
*p_to = *p_from;
p_to++;
}
p_from++;
}
*p_to = '\0';
return psz_temp;
}
......@@ -127,6 +127,9 @@ int playlist_Export( playlist_t * p_playlist, const char *psz_filename ,
msg_Err( p_playlist, "out of memory");
return VLC_ENOMEM;
}
p_export->psz_filename = NULL;
if ( psz_filename )
p_export->psz_filename = strdup( psz_filename );
p_export->p_file = utf8_fopen( psz_filename, "wt" );
if( !p_export->p_file )
{
......@@ -149,8 +152,12 @@ int playlist_Export( playlist_t * p_playlist, const char *psz_filename ,
}
module_Unneed( p_playlist , p_module );
/* Clean up */
fclose( p_export->p_file );
if ( p_export->psz_filename )
free( p_export->psz_filename );
free ( p_export );
p_playlist->p_private = NULL;
vlc_mutex_unlock( &p_playlist->object_lock );
return VLC_SUCCESS;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment