<commit_before>/* 
   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 <NAME>
   Copyright (C) 2003, 2004 <NAME> <<EMAIL>>

   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., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301  USA.

   Author: <NAME> <<EMAIL>>
 */

#include "config.h"

#ifndef TOTEM_PL_PARSER_MINI
#include <string.h>
#include <glib.h>
#include <glib/gi18n-lib.h>
#include <libxml/tree.h>
#include <libxml/parser.h>

#include "totem-pl-parser.h"
#endif /* !TOTEM_PL_PARSER_MINI */

#include "totem-pl-parser-mini.h"
#include "totem-pl-parser-xspf.h"
#include "totem-pl-parser-private.h"

#ifndef TOTEM_PL_PARSER_MINI

#define SAFE_FREE(x) { if (x != NULL) xmlFree (x); }

static xmlDocPtr
totem_pl_parser_parse_xml_file (GFile *file)
{
	xmlDocPtr doc;
	char *contents;
	gsize size;

	if (g_file_load_contents (file, NULL, &contents, &size, NULL, NULL) == FALSE)
		return NULL;

	/* Try to remove HTML style comments */
	{
		char *needle;

		while ((needle = strstr (contents, "<!--")) != NULL) {
			while (strncmp (needle, "-->", 3) != 0) {
				*needle = ' ';
				needle++;
				if (*needle == '\0')
					break;
			}
		}
	}

	doc = xmlParseMemory (contents, size);
	if (doc == NULL)
		doc = xmlRecoverMemory (contents, size);
	g_free (contents);

	return doc;
}

static struct {
	const char *field;
	const char *element;
} fields[] = {
	{ TOTEM_PL_PARSER_FIELD_TITLE, "title" },
	{ TOTEM_PL_PARSER_FIELD_AUTHOR, "creator" },
	{ TOTEM_PL_PARSER_FIELD_IMAGE_URI, "image" },
	{ TOTEM_PL_PARSER_FIELD_ALBUM, "album" },
	{ TOTEM_PL_PARSER_FIELD_DURATION_MS, "duration" },
	{ TOTEM_PL_PARSER_FIELD_GENRE, NULL },
};

gboolean
totem_pl_parser_save_xspf (TotemPlParser    *parser,
                           TotemPlPlaylist  *playlist,
                           GFile            *output,
                           const char       *title,
                           GError          **error)
{
        TotemPlPlaylistIter iter;
	GFileOutputStream *stream;
	char *buf;
	gboolean valid, success;

	stream = g_file_replace (output, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error);
	if (stream == NULL)
		return FALSE;

	buf = g_strdup_printf ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
				"<playlist version=\"1\" xmlns=\"http://xspf.org/ns/0/\">\n"
				" <trackList>\n");
	success = totem_pl_parser_write_string (G_OUTPUT_STREAM (stream), buf, error);
	g_free (buf);
	if (success == FALSE)
		return FALSE;

        valid = totem_pl_playlist_iter_first (playlist, &iter);

        while (valid) {
		char *uri, *uri_escaped, *relative;
		GFile *file;
		guint i;

                totem_pl_playlist_get (playlist, &iter,
                                       TOTEM_PL_PARSER_FIELD_URI, &uri,
                                       NULL);


                if (!uri) {
			valid = totem_pl_playlist_iter_next (playlist, &iter);
                        continue;
		}

                file = g_file_new_for_uri (uri);

		if (totem_pl_parser_scheme_is_ignored (parser, file) != FALSE) {
			valid = totem_pl_playlist_iter_next (playlist, &iter);
			g_object_unref (file);
			g_free (uri);
			continue;
		}
		g_object_unref (file);

		relative = totem_pl_parser_relative (output, uri);
		uri_escaped = g_markup_escape_text (relative ? relative : uri, -1);
		buf = g_strdup_printf ("  <track>\n"
                                       "   <location>%s</location>\n", uri_escaped);
		success = totem_pl_parser_write_string (G_OUTPUT_STREAM (stream), buf, error);
		g_free (uri);
		g_free (uri_escaped);
		g_free (relative);
		g_free (buf);

                if (success == FALSE)
			return FALSE;

		for (i = 0; i < G_N_ELEMENTS (fields); i++) {
			char *str, *escaped;

			totem_pl_playlist_get (playlist, &iter,
					       fields[i].field, &str,
					       NULL);
			if (!str)
				continue;
			escaped = g_markup_escape_text (str, -1);
			g_free (str);
			if (!escaped)
				continue;
			if (g_str_equal (fields[i].field, TOTEM_PL_PARSER_FIELD_GENRE) == FALSE) {
				buf = g_strdup_printf ("   <%s>%s</%s>\n",
						       fields[i].element,
						       escaped,
						       fields[i].element);
			} else {
				buf = g_strdup_printf ("   <extension application=\"http://www.rhythmbox.org\">\n"
						       "     <genre>%s</genre>\n"
						       "   </extension>\n",
						       escaped);
			}

			success = totem_pl_parser_write_string (G_OUTPUT_STREAM (stream), buf, error);
			g_free (buf);
			g_free (escaped);

			if (success == FALSE)
				break;
		}

                if (success == FALSE)
			return FALSE;

		success = totem_pl_parser_write_string (G_OUTPUT_STREAM (stream), "  </track>\n", error);
		if (success == FALSE)
			return FALSE;

                valid = totem_pl_playlist_iter_next (playlist, &iter);
	}

	buf = g_strdup_printf (" </trackList>\n"
                               "</playlist>");
	success = totem_pl_parser_write_string (G_OUTPUT_STREAM (stream), buf, error);
	g_free (buf);

	g_object_unref (stream);

	return success;<commit_msg>plparser: Add support for saving GNOME XSPF extensions<commit_after>/* 
   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 <NAME>
   Copyright (C) 2003, 2004 <NAME> <<EMAIL>>

   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., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301  USA.

   Author: <NAME> <<EMAIL>>
 */

#include "config.h"

#ifndef TOTEM_PL_PARSER_MINI
#include <string.h>
#include <glib.h>
#include <glib/gi18n-lib.h>
#include <libxml/tree.h>
#include <libxml/parser.h>

#include "totem-pl-parser.h"
#endif /* !TOTEM_PL_PARSER_MINI */

#include "totem-pl-parser-mini.h"
#include "totem-pl-parser-xspf.h"
#include "totem-pl-parser-private.h"

#ifndef TOTEM_PL_PARSER_MINI

#define SAFE_FREE(x) { if (x != NULL) xmlFree (x); }

static xmlDocPtr
totem_pl_parser_parse_xml_file (GFile *file)
{
	xmlDocPtr doc;
	char *contents;
	gsize size;

	if (g_file_load_contents (file, NULL, &contents, &size, NULL, NULL) == FALSE)
		return NULL;

	/* Try to remove HTML style comments */
	{
		char *needle;

		while ((needle = strstr (contents, "<!--")) != NULL) {
			while (strncmp (needle, "-->", 3) != 0) {
				*needle = ' ';
				needle++;
				if (*needle == '\0')
					break;
			}
		}
	}

	doc = xmlParseMemory (contents, size);
	if (doc == NULL)
		doc = xmlRecoverMemory (contents, size);
	g_free (contents);

	return doc;
}

static struct {
	const char *field;
	const char *element;
} fields[] = {
	{ TOTEM_PL_PARSER_FIELD_TITLE, "title" },
	{ TOTEM_PL_PARSER_FIELD_AUTHOR, "creator" },
	{ TOTEM_PL_PARSER_FIELD_IMAGE_URI, "image" },
	{ TOTEM_PL_PARSER_FIELD_ALBUM, "album" },
	{ TOTEM_PL_PARSER_FIELD_DURATION_MS, "duration" },
	{ TOTEM_PL_PARSER_FIELD_GENRE, NULL },
	{ TOTEM_PL_PARSER_FIELD_SUBTITLE_URI, NULL },
	{ TOTEM_PL_PARSER_FIELD_PLAYING, NULL },
	{ TOTEM_PL_PARSER_FIELD_CONTENT_TYPE, NULL }
};

gboolean
totem_pl_parser_save_xspf (TotemPlParser    *parser,
                           TotemPlPlaylist  *playlist,
                           GFile            *output,
                           const char       *title,
                           GError          **error)
{
        TotemPlPlaylistIter iter;
	GFileOutputStream *stream;
	char *buf;
	gboolean valid, success;

	stream = g_file_replace (output, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error);
	if (stream == NULL)
		return FALSE;

	buf = g_strdup_printf ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
				"<playlist version=\"1\" xmlns=\"http://xspf.org/ns/0/\">\n"
				" <trackList>\n");
	success = totem_pl_parser_write_string (G_OUTPUT_STREAM (stream), buf, error);
	g_free (buf);
	if (success == FALSE)
		return FALSE;

        valid = totem_pl_playlist_iter_first (playlist, &iter);

        while (valid) {
		char *uri, *uri_escaped, *relative;
		GFile *file;
		guint i;
		gboolean wrote_ext;

                totem_pl_playlist_get (playlist, &iter,
                                       TOTEM_PL_PARSER_FIELD_URI, &uri,
                                       NULL);


                if (!uri) {
			valid = totem_pl_playlist_iter_next (playlist, &iter);
                        continue;
		}

                file = g_file_new_for_uri (uri);

		if (totem_pl_parser_scheme_is_ignored (parser, file) != FALSE) {
			valid = totem_pl_playlist_iter_next (playlist, &iter);
			g_object_unref (file);
			g_free (uri);
			continue;
		}
		g_object_unref (file);

		/* Whether we already wrote the GNOME extensions section header
		 * for that particular track */
		wrote_ext = FALSE;

		relative = totem_pl_parser_relative (output, uri);
		uri_escaped = g_markup_escape_text (relative ? relative : uri, -1);
		buf = g_strdup_printf ("  <track>\n"
                                       "   <location>%s</location>\n", uri_escaped);
		success = totem_pl_parser_write_string (G_OUTPUT_STREAM (stream), buf, error);
		g_free (uri);
		g_free (uri_escaped);
		g_free (relative);
		g_free (buf);

                if (success == FALSE)
			return FALSE;

		for (i = 0; i < G_N_ELEMENTS (fields); i++) {
			char *str, *escaped;

			totem_pl_playlist_get (playlist, &iter,
					       fields[i].field, &str,
					       NULL);
			if (!str || *str == '\0') {
				g_free (str);
				continue;
			}
			escaped = g_markup_escape_text (str, -1);
			g_free (str);
			if (!escaped)
				continue;
			if (g_str_equal (fields[i].field, TOTEM_PL_PARSER_FIELD_GENRE)) {
				buf = g_strdup_printf ("   <extension application=\"http://www.rhythmbox.org\">\n"
						       "     <genre>%s</genre>\n"
						       "   </extension>\n",
						       escaped);
			} else if (g_str_equal (fields[i].field, TOTEM_PL_PARSER_FIELD_SUBTITLE_URI) ||
				   g_str_equal (fields[i].field, TOTEM_PL_PARSER_FIELD_PLAYING) ||
				   g_str_equal (fields[i].field, TOTEM_PL_PARSER_FIELD_CONTENT_TYPE)) {
				if (!wrote_ext) {
					buf = g_strdup_printf ("   <extension application=\"http://www.gnome.org\">\n"
							       "     <%s>%s</%s>\n",
							       fields[i].field, escaped, fields[i].field);
					wrote_ext = TRUE;
				} else {
					buf = g_strdup_printf ("     <%s>%s</%s>\n",
							       fields[i].field, escaped, fields[i].field);
				}
			} else if (g_str_equal (fields[i].field, TOTEM_PL_PARSER_FIELD_GENRE) == FALSE) {
				buf = g_strdup_printf ("   <%s>%s</%s>\n",
						       fields[i].element,
						       escaped,
						       fields[i].element);
			}

			success = totem_pl_parser_write_string (G_OUTPUT_STREAM (stream), buf, error);
			g_free (buf);
			g_free (escaped);

			if (success == FALSE)
				break;
		}

                if (success == FALSE)
			return FALSE;

		if (wrote_ext)
			success = totem_pl_parser_write_string (G_OUTPUT_STREAM (stream), "   </extension>\n", error);

		if (success == FALSE)
			return FALSE;

		success = totem_pl_parser_write_string (G_OUTPUT_STREAM (stream), "  </track>\n", error);
		if (success == FALSE)
			return FALSE;

                valid = totem_pl_playlist_iter_next (playlist, &iter);
	}

	buf = g_strdup_printf (" </trackList>\n"
                               "</playlist>");
	success = totem_pl_parser_write_string (G_OUTPUT_STREAM (stream), buf, error);
	g_free (buf);

	g_object_unref (stream);

	return success;
{'fraction_non_alphanumeric': 0.1250100425805415, 'fraction_numerical': 0.009239174098176267, 'mean_word_length': 2.7755535335153168, 'pattern_counts': {'":': 0, '<': 67, '<?xml version=': 2, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 3, 'xml': 20}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4203384', 'n_tokens_mistral': 4882, 'n_tokens_neox': 4336, 'n_words': 1062}