diff options
author | Bastien Nocera <hadess@hadess.net> | 2007-12-03 11:28:39 +0000 |
---|---|---|
committer | Bastien Nocera <hadess@src.gnome.org> | 2007-12-03 11:28:39 +0000 |
commit | 41b0fa00554cb45cf6845b73fc5adc25644a07a7 (patch) | |
tree | ec4d76a4e43522f20a3fbd7ba6b06510a5038b92 /plparse/totem-pl-parser-wm.c | |
download | totem-pl-parser-41b0fa00554cb45cf6845b73fc5adc25644a07a7.tar.gz |
Moved from Totem, export mini plparser for use in the browser plugin
2007-12-03 Bastien Nocera <hadess@hadess.net>
* *: Moved from Totem, export mini plparser
for use in the browser plugin (Closes: #462153)
svn path=/trunk/; revision=2
Diffstat (limited to 'plparse/totem-pl-parser-wm.c')
-rw-r--r-- | plparse/totem-pl-parser-wm.c | 445 |
1 files changed, 445 insertions, 0 deletions
diff --git a/plparse/totem-pl-parser-wm.c b/plparse/totem-pl-parser-wm.c new file mode 100644 index 0000000..fd1cdfa --- /dev/null +++ b/plparse/totem-pl-parser-wm.c @@ -0,0 +1,445 @@ +/* + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Bastien Nocera + Copyright (C) 2003, 2004 Colin Walters <walters@rhythmbox.org> + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Author: Bastien Nocera <hadess@hadess.net> + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include <glib.h> +#include <libgnomevfs/gnome-vfs-mime-utils.h> + +#ifndef TOTEM_PL_PARSER_MINI +#include "xmlparser.h" +#include <gtk/gtk.h> +#include <libgnomevfs/gnome-vfs.h> +#include <libgnomevfs/gnome-vfs-mime.h> +#include <libgnomevfs/gnome-vfs-utils.h> +#include "totem-pl-parser.h" +#include "totemplparser-marshal.h" +#include "totem-disc.h" +#endif /* !TOTEM_PL_PARSER_MINI */ + +#include "totem-pl-parser-mini.h" +#include "totem-pl-parser-wm.h" +#include "totem-pl-parser-lines.h" +#include "totem-pl-parser-private.h" + +#ifndef TOTEM_PL_PARSER_MINI + +static TotemPlParserResult +totem_pl_parser_add_asf_reference_parser (TotemPlParser *parser, + const char *url, const char *base, + gpointer data) +{ + char *contents, **lines, *ref, *split_char; + int size; + + if (gnome_vfs_read_entire_file (url, &size, &contents) != GNOME_VFS_OK) + return TOTEM_PL_PARSER_RESULT_ERROR; + + if (strstr(contents,"\x0d") == NULL) { + split_char = "\n"; + } else { + split_char = "\x0d\n"; + } + + lines = g_strsplit (contents, split_char, 0); + g_free (contents); + + /* Try to get Ref1 first */ + ref = totem_pl_parser_read_ini_line_string (lines, "Ref1", FALSE); + if (ref == NULL) { + g_strfreev (lines); + return totem_pl_parser_add_asx (parser, url, base, data); + } + + /* change http to mmsh, thanks Microsoft */ + if (g_str_has_prefix (ref, "http") != FALSE) + memcpy(ref, "mmsh", 4); + + totem_pl_parser_add_one_url (parser, ref, NULL); + g_free (ref); + + /* Don't try to get Ref2, as it's only ever + * supposed to be a fallback */ + + g_strfreev (lines); + + return TOTEM_PL_PARSER_RESULT_SUCCESS; +} + +static TotemPlParserResult +totem_pl_parser_add_asf_parser (TotemPlParser *parser, + const char *url, const char *base, + gpointer data) +{ + TotemPlParserResult retval = TOTEM_PL_PARSER_RESULT_UNHANDLED; + char *contents, *ref; + int size; + + /* NSC files are handled directly by GStreamer */ + if (g_str_has_prefix (data, "[Address]") != FALSE) + return TOTEM_PL_PARSER_RESULT_UNHANDLED; + + if (g_str_has_prefix (data, "ASF ") == FALSE) { + return totem_pl_parser_add_asf_reference_parser (parser, url, base, data); + } + + if (gnome_vfs_read_entire_file (url, &size, &contents) != GNOME_VFS_OK) + return TOTEM_PL_PARSER_RESULT_ERROR; + + if (size <= 4) { + g_free (contents); + return TOTEM_PL_PARSER_RESULT_ERROR; + } + + /* Skip 'ASF ' */ + ref = contents + 4; + if (g_str_has_prefix (ref, "http") != FALSE) { + memcpy(ref, "mmsh", 4); + totem_pl_parser_add_one_url (parser, ref, NULL); + retval = TOTEM_PL_PARSER_RESULT_SUCCESS; + } + + g_free (contents); + return retval; +} + +static gboolean +parse_asx_entry (TotemPlParser *parser, const char *base, xml_node_t *parent) +{ + xml_node_t *node; + TotemPlParserResult retval = TOTEM_PL_PARSER_RESULT_SUCCESS; + char *fullpath; + const char *url; + const char *title, *duration, *starttime, *author; + const char *moreinfo, *abstract, *copyright; + + fullpath = NULL; + title = NULL; + url = NULL; + duration = NULL; + starttime = NULL; + moreinfo = NULL; + abstract = NULL; + copyright = NULL; + author = NULL; + + for (node = parent->child; node != NULL; node = node->next) { + if (node->name == NULL) + continue; + + /* ENTRY can only have one title node but multiple REFs */ + if (g_ascii_strcasecmp (node->name, "ref") == 0) { + const char *tmp; + + tmp = xml_parser_get_property (node, "href"); + if (tmp == NULL) + continue; + /* FIXME, should we prefer mms streams, or non-mms? + * See bug #352559 */ + if (url == NULL) + url = tmp; + + continue; + } + + if (g_ascii_strcasecmp (node->name, "title") == 0) + title = node->data; + + if (g_ascii_strcasecmp (node->name, "author") == 0) + author = node->data; + + if (g_ascii_strcasecmp (node->name, "moreinfo") == 0) { + const char *tmp; + + tmp = xml_parser_get_property (node, "href"); + if (tmp == NULL) + continue; + moreinfo = tmp; + } + + if (g_ascii_strcasecmp (node->name, "copyright") == 0) + copyright = node->data; + + if (g_ascii_strcasecmp (node->name, "abstract") == 0) + abstract = node->data; + + if (g_ascii_strcasecmp (node->name, "duration") == 0) { + const char *tmp; + + tmp = xml_parser_get_property (node, "value"); + if (tmp == NULL) + continue; + duration = tmp; + } + + if (g_ascii_strcasecmp (node->name, "starttime") == 0) { + const char *tmp; + + tmp = xml_parser_get_property (node, "value"); + if (tmp == NULL) + continue; + starttime = tmp; + } + + if (g_ascii_strcasecmp (node->name, "param") == 0) { + const char *name, *value; + + name = xml_parser_get_property (node, "name"); + if (name == NULL || g_ascii_strcasecmp (name, "showwhilebuffering") != 0) + continue; + value = xml_parser_get_property (node, "value"); + if (value == NULL || g_ascii_strcasecmp (value, "true") != 0) + continue; + + /* We ignore items that are the buffering images */ + retval = TOTEM_PL_PARSER_RESULT_IGNORED; + goto bail; + } + } + + if (url == NULL) + return TOTEM_PL_PARSER_RESULT_ERROR; + + fullpath = totem_pl_parser_resolve_url (base, url); + + /* .asx files can contain references to other .asx files */ + retval = totem_pl_parser_parse_internal (parser, fullpath, NULL); + if (retval != TOTEM_PL_PARSER_RESULT_SUCCESS) { + totem_pl_parser_add_url (parser, + TOTEM_PL_PARSER_FIELD_URL, fullpath, + TOTEM_PL_PARSER_FIELD_TITLE, title, + TOTEM_PL_PARSER_FIELD_ABSTRACT, abstract, + TOTEM_PL_PARSER_FIELD_COPYRIGHT, copyright, + TOTEM_PL_PARSER_FIELD_AUTHOR, author, + TOTEM_PL_PARSER_FIELD_STARTTIME, starttime, + TOTEM_PL_PARSER_FIELD_DURATION, duration, + TOTEM_PL_PARSER_FIELD_MOREINFO, moreinfo, + NULL); + retval = TOTEM_PL_PARSER_RESULT_SUCCESS; + } + +bail: + g_free (fullpath); + + return retval; +} + +static gboolean +parse_asx_entryref (TotemPlParser *parser, const char *base, xml_node_t *node) +{ + TotemPlParserResult retval = TOTEM_PL_PARSER_RESULT_SUCCESS; + const char *url; + char *fullpath; + + fullpath = NULL; + url = NULL; + + url = xml_parser_get_property (node, "href"); + + if (url == NULL) { + return TOTEM_PL_PARSER_RESULT_ERROR; + } + + fullpath = totem_pl_parser_resolve_url (base, url); + + /* .asx files can contain references to other .asx files */ + retval = totem_pl_parser_parse_internal (parser, fullpath, NULL); + if (retval != TOTEM_PL_PARSER_RESULT_SUCCESS) { + totem_pl_parser_add_url (parser, + TOTEM_PL_PARSER_FIELD_URL, fullpath, + NULL); + retval = TOTEM_PL_PARSER_RESULT_SUCCESS; + } + + g_free (fullpath); + + return retval; +} + +//FIXME the retval is completely wrong +static gboolean +parse_asx_entries (TotemPlParser *parser, const char *url, const char *_base, xml_node_t *parent) +{ + char *title = NULL; + const char *newbase = NULL, *base = NULL; + xml_node_t *node; + TotemPlParserResult retval = TOTEM_PL_PARSER_RESULT_ERROR; + + base = _base; + + for (node = parent->child; node != NULL; node = node->next) { + if (node->name == NULL) + continue; + + if (g_ascii_strcasecmp (node->name, "title") == 0) { + g_free (title); + title = g_strdup (node->data); + totem_pl_parser_add_url (parser, + TOTEM_PL_PARSER_FIELD_IS_PLAYLIST, TRUE, + TOTEM_PL_PARSER_FIELD_URL, url, + TOTEM_PL_PARSER_FIELD_TITLE, title, + NULL); + } + if (g_ascii_strcasecmp (node->name, "base") == 0) { + newbase = xml_parser_get_property (node, "href"); + if (newbase != NULL) + base = newbase; + } + if (g_ascii_strcasecmp (node->name, "entry") == 0) { + /* Whee! found an entry here, find the REF and TITLE */ + if (parse_asx_entry (parser, base, node) != FALSE) + retval = TOTEM_PL_PARSER_RESULT_SUCCESS; + } + if (g_ascii_strcasecmp (node->name, "entryref") == 0) { + /* Found an entryref, extract the REF attribute */ + if (parse_asx_entryref (parser, base, node) != FALSE) + retval = TOTEM_PL_PARSER_RESULT_SUCCESS; + } + if (g_ascii_strcasecmp (node->name, "repeat") == 0) { + /* Repeat at the top-level */ + if (parse_asx_entries (parser, url, base, node) != FALSE) + retval = TOTEM_PL_PARSER_RESULT_SUCCESS; + } + } + + if (title != NULL) + totem_pl_parser_playlist_end (parser, url); + g_free (title); + + return retval; +} + +TotemPlParserResult +totem_pl_parser_add_asx (TotemPlParser *parser, + const char *url, + const char *base, + gpointer data) +{ + xml_node_t* doc; + char *_base, *contents; + int size; + TotemPlParserResult retval = TOTEM_PL_PARSER_RESULT_UNHANDLED; + + if (data != NULL && totem_pl_parser_is_uri_list (data, strlen (data)) != FALSE) { + return totem_pl_parser_add_ram (parser, url, data); + } + + if (gnome_vfs_read_entire_file (url, &size, &contents) != GNOME_VFS_OK) + return TOTEM_PL_PARSER_RESULT_ERROR; + + xml_parser_init (contents, size, XML_PARSER_CASE_INSENSITIVE); + if (xml_parser_build_tree_with_options (&doc, XML_PARSER_RELAXED | XML_PARSER_MULTI_TEXT) < 0) { + g_free (contents); + return TOTEM_PL_PARSER_RESULT_ERROR; + } + /* If the document has no name */ + if (doc->name == NULL + || g_ascii_strcasecmp (doc->name , "asx") != 0) { + g_free (contents); + xml_parser_free_tree (doc); + return TOTEM_PL_PARSER_RESULT_ERROR; + } + + if (base == NULL) { + _base = totem_pl_parser_base_url (url); + } else { + _base = g_strdup (base); + } + + if (parse_asx_entries (parser, url, _base, doc) != FALSE) + retval = TOTEM_PL_PARSER_RESULT_SUCCESS; + + g_free (_base); + g_free (contents); + xml_parser_free_tree (doc); + + return retval; +} + +TotemPlParserResult +totem_pl_parser_add_asf (TotemPlParser *parser, const char *url, + const char *base, gpointer data) +{ + if (data == NULL) { + totem_pl_parser_add_one_url (parser, url, NULL); + return TOTEM_PL_PARSER_RESULT_SUCCESS; + } + + if (totem_pl_parser_is_asf (data, strlen (data)) == FALSE) { + totem_pl_parser_add_one_url (parser, url, NULL); + return TOTEM_PL_PARSER_RESULT_SUCCESS; + } + + return totem_pl_parser_add_asf_parser (parser, url, base, data); +} + +#endif /* !TOTEM_PL_PARSER_MINI */ + +gboolean +totem_pl_parser_is_asx (const char *data, gsize len) +{ + char *buffer; + + if (len == 0) + return FALSE; + + if (g_ascii_strncasecmp (data, "<ASX", strlen ("<ASX")) == 0) + return TRUE; + + if (len > MIME_READ_CHUNK_SIZE) + len = MIME_READ_CHUNK_SIZE; + + /* FIXME would be nicer to have an strnstr */ + buffer = g_memdup (data, len); + if (buffer == NULL) { + g_warning ("Couldn't dup data in totem_pl_parser_is_asx"); + return FALSE; + } + buffer[len - 1] = '\0'; + if (strstr (buffer, "<ASX") != NULL + || strstr (buffer, "<asx") != NULL) { + g_free (buffer); + return TRUE; + } + g_free (buffer); + + return FALSE; +} + +gboolean +totem_pl_parser_is_asf (const char *data, gsize len) +{ + if (len == 0) + return FALSE; + + if (g_str_has_prefix (data, "[Reference]") != FALSE + || g_str_has_prefix (data, "ASF ") != FALSE + || g_str_has_prefix (data, "[Address]") != FALSE) { + return TRUE; + } + + return totem_pl_parser_is_asx (data, len); +} + |