1 /*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * Copyright (C) 2006 Andrej Kacian <andrej@kacian.sk>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the libEtPan! project nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #include "parser_atom10.h"
38
39 #include <string.h>
40
41 #include "newsfeed.h"
42 #include "newsfeed_item.h"
43 #include "newsfeed_private.h"
44 #include "date.h"
45 #include "parser.h"
46
47 enum {
48 FEED_LOC_ATOM10_NONE,
49 FEED_LOC_ATOM10_ENTRY,
50 FEED_LOC_ATOM10_AUTHOR
51 };
52
newsfeed_parser_atom10_start(void * data,const char * el,const char ** attr)53 void newsfeed_parser_atom10_start(void * data, const char * el, const char ** attr)
54 {
55 struct newsfeed_parser_context * ctx;
56 int r;
57
58 ctx = data;
59
60 if (ctx->depth == 1) {
61 if (strcasecmp(el, "entry") == 0) {
62 /* Start of new feed item found.
63 * Create a new FeedItem, freeing the one we already have, if any. */
64 if( ctx->curitem != NULL )
65 newsfeed_item_free(ctx->curitem);
66
67 ctx->curitem = newsfeed_item_new(ctx->feed);
68 if (ctx->curitem == NULL) {
69 ctx->error = NEWSFEED_ERROR_MEMORY;
70 return;
71 }
72
73 ctx->location = FEED_LOC_ATOM10_ENTRY;
74 }
75 else if (strcasecmp(el, "author") == 0) {
76 /* Start of author info for the feed found.
77 * Set correct location. */
78 ctx->location = FEED_LOC_ATOM10_AUTHOR;
79 }
80 else {
81 ctx->location = FEED_LOC_ATOM10_NONE;
82 }
83 }
84 else if (ctx->depth == 2) {
85 if (strcasecmp(el, "author") == 0) {
86 /* Start of author info for current feed item.
87 * Set correct location. */
88 ctx->location = FEED_LOC_ATOM10_AUTHOR;
89 }
90 else if (strcasecmp(el, "link") == 0) {
91 const char * url;
92
93 /* Capture item URL, from the "url" XML attribute. */
94 url = newsfeed_parser_get_attribute_value(attr, "href");
95 r = newsfeed_item_set_url(ctx->curitem, url);
96 if (r < 0) {
97 ctx->error = NEWSFEED_ERROR_MEMORY;
98 return;
99 }
100 ctx->location = FEED_LOC_ATOM10_ENTRY;
101 }
102 else {
103 ctx->location = FEED_LOC_ATOM10_ENTRY;
104 }
105 }
106
107 ctx->depth ++;
108 }
109
newsfeed_parser_atom10_end(void * data,const char * el)110 void newsfeed_parser_atom10_end(void *data, const char * el)
111 {
112 struct newsfeed_parser_context * ctx;
113 struct newsfeed * feed;
114 char * text;
115 int r;
116
117 ctx = data;
118 feed = ctx->feed;
119 text = ctx->str->str;
120
121 ctx->depth --;
122
123 switch (ctx->depth) {
124 case 0:
125 if (strcasecmp(el, "feed") == 0) {
126 /* We have finished parsing the feed. */
127 }
128 break;
129
130 case 1:
131 /* decide if we just received </entry>, so we can
132 * add a complete item to feed */
133 if (strcasecmp(el, "entry") == 0) {
134 /* append the complete feed item */
135 r = newsfeed_add_item(ctx->feed, ctx->curitem);
136 if (r < 0) {
137 ctx->error = NEWSFEED_ERROR_MEMORY;
138 return;
139 }
140
141 /* since it's in the linked list, lose this pointer */
142 ctx->curitem = NULL;
143 }
144 else if (strcasecmp(el, "title") == 0) {
145 /* so it wasn't end of item */
146 r = newsfeed_set_title(feed, text);
147 if (r < 0) {
148 ctx->error = NEWSFEED_ERROR_MEMORY;
149 return;
150 }
151 }
152 else if (strcasecmp(el, "summary") == 0) {
153 r = newsfeed_set_description(feed, text);
154 if (r < 0) {
155 ctx->error = NEWSFEED_ERROR_MEMORY;
156 return;
157 }
158 }
159 else if (strcasecmp(el, "updated") == 0) {
160 time_t date;
161
162 date = newsfeed_iso8601_date_parse(text);
163 newsfeed_set_date(feed, date);
164 }
165 /* TODO: add more later */
166 break;
167
168 case 2:
169 if( ctx->curitem == NULL )
170 break;
171
172 switch(ctx->location) {
173 case FEED_LOC_ATOM10_ENTRY:
174 /* We're in feed/entry */
175 if (strcasecmp(el, "title") == 0) {
176 r = newsfeed_item_set_title(ctx->curitem, text);
177 if (r < 0) {
178 ctx->error = NEWSFEED_ERROR_MEMORY;
179 return;
180 }
181 }
182 else if (strcasecmp(el, "summary") == 0) {
183 r = newsfeed_item_set_summary(ctx->curitem, text);
184 if (r < 0) {
185 ctx->error = NEWSFEED_ERROR_MEMORY;
186 return;
187 }
188 }
189 else if (strcasecmp(el, "content") == 0) {
190 r = newsfeed_item_set_text(ctx->curitem, text);
191 if (r < 0) {
192 ctx->error = NEWSFEED_ERROR_MEMORY;
193 return;
194 }
195 }
196 else if (strcasecmp(el, "id") == 0) {
197 r = newsfeed_item_set_id(ctx->curitem, text);
198 if (r < 0) {
199 ctx->error = NEWSFEED_ERROR_MEMORY;
200 return;
201 }
202 }
203 else if (strcasecmp(el, "issued") == 0) {
204 time_t date;
205
206 date = newsfeed_iso8601_date_parse(text);
207 newsfeed_item_set_date_published(ctx->curitem, date);
208 }
209 else if (strcasecmp(el, "updated") == 0) {
210 time_t date;
211
212 date = newsfeed_iso8601_date_parse(text);
213 newsfeed_item_set_date_modified(ctx->curitem, date);
214 }
215 break;
216
217 case FEED_LOC_ATOM10_AUTHOR:
218 /* We're in feed/author */
219 if (strcasecmp(el, "name") == 0) {
220 r = newsfeed_item_set_author(ctx->curitem, text);
221 if (r < 0) {
222 ctx->error = NEWSFEED_ERROR_MEMORY;
223 return;
224 }
225 }
226 /* TODO: construct a "Na Me <add@dre.ss>" string
227 * from available tags */
228
229 break;
230 }
231
232 break;
233
234 case 3:
235 if (ctx->curitem == NULL)
236 break;
237
238 if (ctx->location == FEED_LOC_ATOM10_AUTHOR) {
239 /* We're in feed/entry/author */
240 if (strcasecmp(el, "name") == 0) {
241 r = newsfeed_item_set_author(ctx->curitem, text);
242 if (r < 0) {
243 ctx->error = NEWSFEED_ERROR_MEMORY;
244 return;
245 }
246 }
247 }
248
249 break;
250 }
251
252 mmap_string_truncate(ctx->str, 0);
253 }
254