1 /*
2  * Copyright (C) 2006 Andrej Kacian <andrej@kacian.sk>
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public
15  * License along with this program; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 
20 #include <glib.h>
21 #include <curl/curl.h>
22 #include <expat.h>
23 #include <string.h>
24 #include <ctype.h>
25 
26 #include <common/codeconv.h>
27 
28 #include "feed.h"
29 
30 #include "parser.h"
31 #include "parser_opml.h"
32 
_opml_parser_start(void * data,const gchar * el,const gchar ** attr)33 static void _opml_parser_start(void *data, const gchar *el, const gchar **attr)
34 {
35 	OPMLProcessCtx *ctx = (OPMLProcessCtx *)data;
36 	gchar *title = NULL, *type = NULL, *url = NULL, *tmp = NULL;
37 
38 	if( ctx->body_reached ) {
39 		if( ctx->depth >= 2 && !strcmp(el, "outline") ) {
40 			title = feed_parser_get_attribute_value(attr, "title");
41 			type = feed_parser_get_attribute_value(attr, "type");
42 			if( type != NULL && strcmp(type, "folder") ) {
43 				url = feed_parser_get_attribute_value(attr, "xmlUrl");
44 
45 				if( url != NULL ) {
46 					if( !strncmp(url, "feed://", 7) )
47 						tmp = g_strdup(url+7);
48 					else if( !strncmp(url, "feed:", 5) )
49 						tmp = g_strdup(url+5);
50 
51 					if( tmp != NULL ) {
52 						g_free(url);
53 						url = tmp;
54 					}
55 				}
56 			}
57 
58 			if( ctx->user_function != NULL ) {
59 				ctx->user_function(title, url, ctx->depth, ctx->user_data);
60 			}
61 		}
62 	}
63 
64 	if( ctx->depth == 1 ) {
65 		if( !strcmp(el, "body") ) {
66 			ctx->body_reached = TRUE;
67 		}
68 	}
69 
70 	ctx->depth++;
71 }
72 
_opml_parser_end(void * data,const gchar * el)73 static void _opml_parser_end(void *data, const gchar *el)
74 {
75 	OPMLProcessCtx *ctx = (OPMLProcessCtx *)data;
76 
77 	ctx->depth--;
78 }
79 
opml_process(gchar * path,OPMLProcessFunc function,gpointer data)80 void opml_process(gchar *path, OPMLProcessFunc function, gpointer data)
81 {
82 	OPMLProcessCtx *ctx = NULL;
83 	gchar *contents = NULL;
84 	GError *error = NULL;
85 	gint status, err;
86 
87 	/* Initialize our context */
88 	ctx = malloc( sizeof(OPMLProcessCtx) );
89 	ctx->parser = XML_ParserCreate(NULL);
90 	ctx->depth = 0;
91 	ctx->str = NULL;
92 	ctx->user_function = function;
93 	ctx->body_reached = FALSE;
94 	ctx->user_data = data;
95 
96 	/* Set expat parser handlers */
97 	XML_SetUserData(ctx->parser, (void *)ctx);
98 	XML_SetElementHandler(ctx->parser,
99 			_opml_parser_start,
100 			_opml_parser_end);
101 	XML_SetCharacterDataHandler(ctx->parser, libfeed_expat_chparse);
102 	XML_SetUnknownEncodingHandler(ctx->parser,
103 			feed_parser_unknown_encoding_handler, NULL);
104 
105 	g_file_get_contents(path, &contents, NULL, &error);
106 
107 	if( error || !contents )
108 		return;
109 
110 /*
111 	lines = g_strsplit(contents, '\n', 0);
112 
113 	while( lines[i] ) {
114 		status = XML_Parse(ctx->parser, lines[i], strlen(lines[i]), FALSE);
115 		if( status == XML_STATUS_ERROR ) {
116 			err = XML_GetErrorCode(ctx->parser);
117 			sprintf(stderr, "\nExpat: --- %s\n\n", XML_ErrorString(err));
118 		}
119 	}
120 */
121 
122 	status = XML_Parse(ctx->parser, contents, strlen(contents), FALSE);
123 	err = XML_GetErrorCode(ctx->parser);
124 	fprintf(stderr, "\nExpat: --- %s (%s)\n\n", XML_ErrorString(err),
125 			(status == XML_STATUS_OK ? "OK" : "NOT OK"));
126 
127 	XML_Parse(ctx->parser, "", 0, TRUE);
128 
129 	XML_ParserFree(ctx->parser);
130 	g_free(ctx);
131 }
132