66
68
static RBPodcastItem *
67
69
rb_podcast_initializa_item ()
69
RBPodcastItem *data = g_new0 (RBPodcastItem, 1);
71
RBPodcastItem *data = g_new0 (RBPodcastItem, 1);
74
rb_set_channel_value (struct RBPoadcastLoadContext* ctx, const char* name, const char* value)
76
rb_set_channel_value (struct RBPoadcastLoadContext *ctx,
80
dvalue = xmlCharStrdup (value);
81
g_strstrip ((char *)dvalue);
88
dvalue = xmlCharStrdup (value);
89
g_strstrip ((char *)dvalue);
83
if (!strcmp (name, "title")) {
84
ctx->channel_data->title = dvalue;
85
} else if (!strcmp (name, "language")) {
86
ctx->channel_data->lang = dvalue;
87
} else if (!strcmp (name, "itunes:subtitle")) {
88
ctx->channel_data->subtitle = dvalue;
89
} else if (!strcmp (name, "itunes:summary")) {
90
ctx->channel_data->summary = dvalue;
91
} else if (!strcmp (name, "description")) {
92
ctx->channel_data->description = dvalue;
93
} else if (!strcmp (name, "generator") ||
94
!strcmp (name, "itunes:author")) {
95
ctx->channel_data->author = dvalue;
96
} else if (!strcmp (name, "webMaster")) {
97
ctx->channel_data->contact = dvalue;
98
} else if (!strcmp (name, "pubDate")) {
99
ctx->channel_data->pub_date = rb_podcast_parse_date ((char *)dvalue);
101
} else if (!strcmp (name, "copyright")) {
102
ctx->channel_data->copyright = dvalue;
103
} else if (!strcmp (name, "img")) {
104
ctx->channel_data->img = dvalue;
91
if (!strcmp (name, "title")) {
92
ctx->channel_data->title = dvalue;
93
} else if (!strcmp (name, "language")) {
94
ctx->channel_data->lang = dvalue;
95
} else if (!strcmp (name, "itunes:subtitle")) {
96
ctx->channel_data->subtitle = dvalue;
97
} else if (!strcmp (name, "itunes:summary")) {
98
ctx->channel_data->summary = dvalue;
99
} else if (!strcmp (name, "description")) {
100
ctx->channel_data->description = dvalue;
101
} else if (!strcmp (name, "generator") ||
102
!strcmp (name, "itunes:author")) {
103
ctx->channel_data->author = dvalue;
104
} else if (!strcmp (name, "webMaster")) {
105
ctx->channel_data->contact = dvalue;
106
} else if (!strcmp (name, "pubDate")) {
107
ctx->channel_data->pub_date = rb_podcast_parse_date ((char *)dvalue);
109
} else if (!strcmp (name, "copyright")) {
110
ctx->channel_data->copyright = dvalue;
111
} else if (!strcmp (name, "img")) {
112
ctx->channel_data->img = dvalue;
112
rb_set_item_value (struct RBPoadcastLoadContext* ctx, const char* name, const char* value)
120
rb_set_item_value (struct RBPoadcastLoadContext *ctx,
115
dvalue = xmlCharStrdup (value);
116
g_strstrip ((char *)dvalue);
118
if (!strcmp (name, "title")) {
119
ctx->item_data->title = dvalue;
120
} else if (!strcmp (name, "url")) {
121
ctx->item_data->url = dvalue;
122
} else if (!strcmp (name, "pubDate")) {
123
ctx->item_data->pub_date = rb_podcast_parse_date ((char *)dvalue);
125
} else if (!strcmp (name, "description")) {
126
ctx->item_data->description = dvalue;
127
} else if (!strcmp (name, "author")) {
128
ctx->item_data->author = dvalue;
129
} else if (!strcmp (name, "itunes:duration")) {
130
ctx->item_data->duration = rb_podcast_parse_time ((char*)dvalue);
132
} else if (!strcmp (name, "length")) {
133
ctx->item_data->filesize = g_ascii_strtoull ((char*)dvalue, NULL, 10);
126
dvalue = xmlCharStrdup (value);
127
g_strstrip ((char *)dvalue);
129
if (!strcmp (name, "title")) {
130
ctx->item_data->title = dvalue;
131
} else if (!strcmp (name, "url")) {
132
ctx->item_data->url = dvalue;
133
} else if (!strcmp (name, "pubDate")) {
134
ctx->item_data->pub_date = rb_podcast_parse_date ((char *)dvalue);
136
} else if (!strcmp (name, "description")) {
137
ctx->item_data->description = dvalue;
138
} else if (!strcmp (name, "author")) {
139
ctx->item_data->author = dvalue;
140
} else if (!strcmp (name, "itunes:duration")) {
141
ctx->item_data->duration = rb_podcast_parse_time ((char *)dvalue);
143
} else if (!strcmp (name, "length")) {
144
ctx->item_data->filesize = g_ascii_strtoull ((char *)dvalue, NULL, 10);
141
rb_insert_item (struct RBPoadcastLoadContext* ctx)
152
rb_insert_item (struct RBPoadcastLoadContext *ctx)
143
154
RBPodcastItem *data = ctx->item_data;
156
rb_debug ("Inserting item as post");
159
rb_debug ("Item does not have a URL, skipping");
148
ctx->channel_data->posts = g_list_prepend (ctx->channel_data->posts, (void *) ctx->item_data);
163
ctx->channel_data->posts = g_list_prepend (ctx->channel_data->posts, ctx->item_data);
151
static gboolean rb_validate_channel_propert (const char *name)
167
rb_validate_channel_propert (const char *name)
153
if (!strcmp(name, "title") ||
154
!strcmp(name, "language") ||
155
!strcmp(name, "itunes:subtitle") ||
156
!strcmp(name, "itunes:summary") ||
157
!strcmp(name, "description") ||
158
!strcmp(name, "generator") ||
159
!strcmp(name, "itunes:author") ||
160
!strcmp(name, "webMaster") ||
161
!strcmp(name, "lastBuildDate") ||
162
!strcmp(name, "pubDate") ||
163
!strcmp(name, "copyright"))
173
if (!strcmp (name, "title") ||
174
!strcmp (name, "language") ||
175
!strcmp (name, "itunes:subtitle") ||
176
!strcmp (name, "itunes:summary") ||
177
!strcmp (name, "description") ||
178
!strcmp (name, "generator") ||
179
!strcmp (name, "itunes:author") ||
180
!strcmp (name, "webMaster") ||
181
!strcmp (name, "lastBuildDate") ||
182
!strcmp (name, "pubDate") ||
183
!strcmp (name, "copyright")) {
170
static gboolean rb_validate_item_propert (const char *name)
192
rb_validate_item_propert (const char *name)
172
if (!strcmp(name, "title") ||
173
!strcmp(name, "url") ||
174
!strcmp(name, "pubDate") ||
175
!strcmp(name, "description") ||
176
!strcmp(name, "author") ||
177
!strcmp(name, "itunes:duration") )
198
if (!strcmp (name, "title") ||
199
!strcmp (name, "url") ||
200
!strcmp (name, "pubDate") ||
201
!strcmp (name, "description") ||
202
!strcmp (name, "author") ||
203
!strcmp (name, "itunes:duration") ) {
186
rb_podcast_parser_start_element (struct RBPoadcastLoadContext* ctx, const char *name, const char **attrs)
213
rb_podcast_parser_start_element (struct RBPoadcastLoadContext *ctx,
218
rb_debug ("Start element: %s state: %d", name, ctx->state);
220
switch (ctx->state) {
191
221
case RB_PODCAST_PARSER_STATE_START:
193
if (!strcmp(name, "rss")) {
194
ctx->state = RB_PODCAST_PARSER_STATE_RSS;
197
ctx->in_unknown_elt++;
223
if (!strcmp (name, "rss")) {
224
ctx->state = RB_PODCAST_PARSER_STATE_RSS;
226
ctx->in_unknown_elt++;
201
232
case RB_PODCAST_PARSER_STATE_RSS:
203
if (!strcmp(name, "channel")) {
204
ctx->state = RB_PODCAST_PARSER_STATE_CHANNEL;
207
ctx->in_unknown_elt++;
234
if (!strcmp (name, "channel")) {
235
ctx->state = RB_PODCAST_PARSER_STATE_CHANNEL;
237
ctx->in_unknown_elt++;
211
243
case RB_PODCAST_PARSER_STATE_CHANNEL:
214
if (!strcmp(name, "image")) {
215
ctx->state = RB_PODCAST_PARSER_STATE_IMG;
217
} else if (!strcmp(name, "item")) {
218
ctx->item_data = rb_podcast_initializa_item(); // g_new0(RBPodcastItem, 1);
219
ctx->state = RB_PODCAST_PARSER_STATE_ITEM;
221
} else if (!rb_validate_channel_propert (name)) {
222
ctx->in_unknown_elt++;
246
if (strcmp (name, "image") == 0
247
|| strcmp (name, "itunes:image") == 0) {
248
ctx->state = RB_PODCAST_PARSER_STATE_IMG;
249
} else if (!strcmp (name, "item")) {
250
ctx->item_data = rb_podcast_initializa_item ();
251
ctx->state = RB_PODCAST_PARSER_STATE_ITEM;
252
} else if (!rb_validate_channel_propert (name)) {
253
rb_debug ("Unknown property");
254
ctx->in_unknown_elt++;
256
ctx->state = RB_PODCAST_PARSER_STATE_CHANNEL_PROPERTY;
226
ctx->state = RB_PODCAST_PARSER_STATE_CHANNEL_PROPERTY;
230
262
case RB_PODCAST_PARSER_STATE_ITEM:
232
if (!strcmp(name, "enclosure")) {
233
for (; *attrs; attrs +=2) {
234
if (!strcmp (*attrs, "url")) {
235
const char *url_value = *(attrs+1);
236
rb_set_item_value(ctx, "url", url_value);
237
} else if (!strcmp (*attrs, "length")) {
238
const char *length_value = *(attrs+1);
239
rb_set_item_value(ctx, "length", length_value);
242
} else if (!rb_validate_item_propert (name)) {
243
ctx->in_unknown_elt++;
248
ctx->state = RB_PODCAST_PARSER_STATE_ITEM_PROPERTY;
264
if (!strcmp (name, "enclosure")) {
265
for (; *attrs; attrs +=2) {
266
if (!strcmp (*attrs, "url")) {
267
const char *url_value = *(attrs + 1);
268
rb_set_item_value (ctx, "url", url_value);
269
} else if (!strcmp (*attrs, "length")) {
270
const char *length_value = *(attrs + 1);
271
rb_set_item_value (ctx, "length", length_value);
275
ctx->state = RB_PODCAST_PARSER_STATE_ITEM_PROPERTY;
277
} else if (!rb_validate_item_propert (name)) {
278
ctx->in_unknown_elt++;
280
ctx->state = RB_PODCAST_PARSER_STATE_ITEM_PROPERTY;
252
286
case RB_PODCAST_PARSER_STATE_IMG:
254
if (strcmp(name, "url") != 0) {
255
ctx->in_unknown_elt++;
288
if (strcmp (name, "url") != 0) {
289
ctx->in_unknown_elt++;
291
ctx->state = RB_PODCAST_PARSER_STATE_IMG_PROPERTY;
259
ctx->state = RB_PODCAST_PARSER_STATE_IMG_PROPERTY;
263
297
case RB_PODCAST_PARSER_STATE_CHANNEL_PROPERTY:
264
298
case RB_PODCAST_PARSER_STATE_ITEM_PROPERTY:
265
299
case RB_PODCAST_PARSER_STATE_IMG_PROPERTY:
266
300
case RB_PODCAST_PARSER_STATE_END:
303
g_warning ("Unknown podcast parser state: %d", ctx->state);
273
rb_podcast_parser_end_element (struct RBPoadcastLoadContext* ctx,
310
rb_podcast_parser_end_element (struct RBPoadcastLoadContext *ctx,
276
// if (*ctx->die == TRUE) {
277
// xmlStopParser (ctx->xmlctx);
313
rb_debug ("End element: %s state: %d", name, ctx->state);
281
if (ctx->in_unknown_elt > 0) {
282
ctx->in_unknown_elt--;
315
if (ctx->in_unknown_elt > 0) {
316
ctx->in_unknown_elt--;
317
rb_debug ("Unknown element");
321
switch (ctx->state) {
288
322
case RB_PODCAST_PARSER_STATE_START:
289
ctx->state = RB_PODCAST_PARSER_STATE_END;
323
ctx->state = RB_PODCAST_PARSER_STATE_END;
292
326
case RB_PODCAST_PARSER_STATE_RSS:
293
ctx->state = RB_PODCAST_PARSER_STATE_START;
327
ctx->state = RB_PODCAST_PARSER_STATE_START;
296
330
case RB_PODCAST_PARSER_STATE_CHANNEL:
297
ctx->state = RB_PODCAST_PARSER_STATE_RSS;
331
ctx->state = RB_PODCAST_PARSER_STATE_RSS;
300
334
case RB_PODCAST_PARSER_STATE_CHANNEL_PROPERTY:
302
rb_set_channel_value(ctx, name, ctx->prop_value->str);
303
ctx->state = RB_PODCAST_PARSER_STATE_CHANNEL;
304
g_string_truncate (ctx->prop_value, 0);
336
rb_set_channel_value (ctx, name, ctx->prop_value->str);
337
ctx->state = RB_PODCAST_PARSER_STATE_CHANNEL;
338
g_string_truncate (ctx->prop_value, 0);
308
342
case RB_PODCAST_PARSER_STATE_ITEM:
311
ctx->state = RB_PODCAST_PARSER_STATE_CHANNEL;
344
rb_insert_item (ctx);
345
ctx->state = RB_PODCAST_PARSER_STATE_CHANNEL;
315
349
case RB_PODCAST_PARSER_STATE_ITEM_PROPERTY:
317
rb_set_item_value(ctx, name, ctx->prop_value->str);
318
ctx->state = RB_PODCAST_PARSER_STATE_ITEM;
319
g_string_truncate (ctx->prop_value, 0);
351
rb_set_item_value (ctx, name, ctx->prop_value->str);
352
ctx->state = RB_PODCAST_PARSER_STATE_ITEM;
353
g_string_truncate (ctx->prop_value, 0);
323
357
case RB_PODCAST_PARSER_STATE_IMG_PROPERTY:
325
rb_set_channel_value(ctx, "img", ctx->prop_value->str);
326
ctx->state = RB_PODCAST_PARSER_STATE_IMG;
327
g_string_truncate (ctx->prop_value, 0);
359
rb_set_channel_value (ctx, "img", ctx->prop_value->str);
360
ctx->state = RB_PODCAST_PARSER_STATE_IMG;
361
g_string_truncate (ctx->prop_value, 0);
331
365
case RB_PODCAST_PARSER_STATE_IMG:
332
ctx->state = RB_PODCAST_PARSER_STATE_CHANNEL;
366
ctx->state = RB_PODCAST_PARSER_STATE_CHANNEL;
335
369
case RB_PODCAST_PARSER_STATE_END:
373
g_warning ("Unknown podcast parser state: %d", ctx->state);
342
rb_podcast_parser_characters (struct RBPoadcastLoadContext* ctx, const char *data,
380
rb_podcast_parser_characters (struct RBPoadcastLoadContext *ctx,
384
switch (ctx->state) {
347
385
case RB_PODCAST_PARSER_STATE_CHANNEL_PROPERTY:
348
386
case RB_PODCAST_PARSER_STATE_ITEM_PROPERTY:
349
387
case RB_PODCAST_PARSER_STATE_IMG_PROPERTY:
355
393
case RB_PODCAST_PARSER_STATE_CHANNEL:
356
394
case RB_PODCAST_PARSER_STATE_ITEM:
357
395
case RB_PODCAST_PARSER_STATE_END:
398
g_warning ("Unknown podcast parser state: %d", ctx->state);
364
rb_podcast_parse_load_feed(RBPodcastChannel *data, const char *file_name) {
366
xmlParserCtxtPtr ctxt;
367
xmlSAXHandlerPtr sax_handler = g_new0 (xmlSAXHandler, 1);
368
GnomeVFSResult result;
369
GnomeVFSFileInfo *info;
373
struct RBPoadcastLoadContext *ctx = g_new0 (struct RBPoadcastLoadContext, 1);
375
data->url = xmlCharStrdup (file_name);
377
ctx->in_unknown_elt = 0;
378
ctx->channel_data = data;
380
if (!gnome_vfs_initialized ()) {
384
info = gnome_vfs_file_info_new();
385
result = gnome_vfs_get_file_info (file_name, info, GNOME_VFS_FILE_INFO_DEFAULT);
386
if ((result != GNOME_VFS_OK) ||
387
(info->mime_type == NULL) ||
388
((strstr (info->mime_type, "xml") == NULL) &&
389
(strstr (info->mime_type, "rss") == NULL) &&
390
(strstr (file_name, ".rss") == NULL))) {
391
rb_debug ("Invalid mime-type in podcatst feed %s\n", info->mime_type);
392
gnome_vfs_file_info_unref (info);
396
//firts download file by gnome_vfs for use gnome network configuration
397
result = gnome_vfs_read_entire_file (file_name, &file_size, &buffer);
398
if (result != GNOME_VFS_OK)
405
rb_podcast_parse_load_feed (RBPodcastChannel *data,
406
const char *file_name)
408
xmlParserCtxtPtr ctxt;
409
xmlSAXHandlerPtr sax_handler = NULL;
410
GnomeVFSResult result;
411
GnomeVFSFileInfo *info;
415
struct RBPoadcastLoadContext *ctx = NULL;
417
data->url = xmlCharStrdup (file_name);
419
if (!gnome_vfs_initialized ()) {
423
if (!g_str_has_suffix (file_name, ".rss") && !g_str_has_suffix (file_name, ".xml")) {
424
gboolean invalid_mime_type;
426
info = gnome_vfs_file_info_new ();
428
result = gnome_vfs_get_file_info (file_name, info, GNOME_VFS_FILE_INFO_DEFAULT);
431
&& info->mime_type != NULL
432
&& strstr (info->mime_type, "xml") == NULL
433
&& strstr (info->mime_type, "rss") == NULL) {
434
invalid_mime_type = TRUE;
436
invalid_mime_type = FALSE;
439
if ((result != GNOME_VFS_OK) || invalid_mime_type) {
440
rb_debug ("Invalid mime-type in podcast feed %s", info->mime_type);
441
gnome_vfs_file_info_unref (info);
445
gnome_vfs_file_info_unref (info);
448
/* first download file by gnome_vfs for use gnome network configuration */
449
result = gnome_vfs_read_entire_file (file_name, &file_size, &buffer);
450
if (result != GNOME_VFS_OK)
404
sax_handler->startElement = (startElementSAXFunc) rb_podcast_parser_start_element;
405
sax_handler->endElement = (endElementSAXFunc) rb_podcast_parser_end_element;
406
sax_handler->characters = (charactersSAXFunc) rb_podcast_parser_characters;
407
xmlSubstituteEntitiesDefault (1);
454
/* initializing parse */
455
sax_handler = g_new0 (xmlSAXHandler, 1);
456
sax_handler->startElement = (startElementSAXFunc) rb_podcast_parser_start_element;
457
sax_handler->endElement = (endElementSAXFunc) rb_podcast_parser_end_element;
458
sax_handler->characters = (charactersSAXFunc) rb_podcast_parser_characters;
459
xmlSubstituteEntitiesDefault (1);
409
ctx->prop_value = g_string_sized_new(512);
461
ctx = g_new0 (struct RBPoadcastLoadContext, 1);
462
ctx->in_unknown_elt = 0;
463
ctx->channel_data = data;
464
ctx->prop_value = g_string_sized_new (512);
411
ctxt = xmlCreateMemoryParserCtxt (buffer, file_size);
414
ctxt->userData = ctx;
415
ctxt->sax = sax_handler;
416
xmlParseDocument (ctxt);
418
xmlFreeParserCtxt (ctxt);
421
g_string_free(ctx->prop_value, TRUE);
422
ctx->channel_data->posts = g_list_reverse (ctx->channel_data->posts);
466
ctxt = xmlCreateMemoryParserCtxt (buffer, file_size);
468
ctxt->userData = ctx;
469
ctxt->sax = sax_handler;
470
xmlParseDocument (ctxt);
472
g_free (sax_handler);
474
xmlFreeParserCtxt (ctxt);
477
g_string_free (ctx->prop_value, TRUE);
480
data->posts = g_list_reverse (data->posts);
430
rb_podcast_parse_date(const char* date_str)
484
rb_podcast_parse_date (const char *date_str)
489
/* RFC 2822 date format */
435
490
result = strptime (date_str, "%a, %d %b %Y %T", &tm);
492
/* format without weekday */
436
493
if (result == NULL) {
437
494
memset (&tm, 0, sizeof (struct tm));
438
495
result = strptime (date_str, "%d %b %Y %T", &tm);
498
/* reversed day and long month */
499
if (result == NULL) {
500
memset (&tm, 0, sizeof (struct tm));
501
result = strptime (date_str, "%a, %B %d %Y %T", &tm);
505
if (result == NULL) {
506
memset (&tm, 0, sizeof (struct tm));
507
result = strptime (date_str, "%Y-%m-%d %T", &tm);
510
/* Broken weekday short names */
511
if (result == NULL) {
514
/* strip off the erroneous weekday */
515
tmp = strstr (date_str, ",");
518
memset (&tm, 0, sizeof (struct tm));
519
result = strptime (tmp, "%d %b %Y %T", &tm);
440
523
if (result == NULL) {
441
524
memset (&tm, 0, sizeof (struct tm));
442
525
rb_debug ("unable to convert date string %s", date_str);