~ubuntu-branches/ubuntu/precise/rhythmbox/precise-201203091205

« back to all changes in this revision

Viewing changes to podcast/rb-podcast-parse.c

Tags: upstream-0.9.2cvs20060102
ImportĀ upstreamĀ versionĀ 0.9.2cvs20060102

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
 
2
 *
2
3
 *  arch-tag: Implementation of podcast parse
3
4
 *
4
5
 *  Copyright (C) 2005 Renato Araujo Oliveira Filho - INdT <renato.filho@indt.org.br>
20
21
 */
21
22
 
22
23
#define _XOPEN_SOURCE
 
24
#include <string.h>
23
25
#include <time.h>
 
26
 
24
27
#include <libxml/entities.h>
25
28
#include <libxml/SAX.h>
26
29
#include <libxml/parserInternals.h>
27
30
#include <libgnomevfs/gnome-vfs.h>
28
 
#include <string.h>
29
31
 
30
32
#include "rb-debug.h"
31
33
#include "rb-podcast-parse.h" 
34
36
 
35
37
struct RBPoadcastLoadContext
36
38
{
37
 
    guint in_unknown_elt;
38
 
    xmlParserCtxtPtr xmlctx;
39
 
    GString *prop_value;
40
 
    RBPodcastChannel *channel_data;
41
 
    RBPodcastItem *item_data;
 
39
        guint in_unknown_elt;
 
40
        xmlParserCtxtPtr xmlctx;
 
41
        GString *prop_value;
 
42
        RBPodcastChannel *channel_data;
 
43
        RBPodcastItem *item_data;
42
44
    
43
 
    enum {
44
 
        RB_PODCAST_PARSER_STATE_START,
45
 
        RB_PODCAST_PARSER_STATE_RSS,
46
 
        RB_PODCAST_PARSER_STATE_CHANNEL,
47
 
        RB_PODCAST_PARSER_STATE_CHANNEL_PROPERTY,
48
 
        RB_PODCAST_PARSER_STATE_IMG,
49
 
        RB_PODCAST_PARSER_STATE_IMG_PROPERTY,
50
 
        RB_PODCAST_PARSER_STATE_ITEM,
51
 
        RB_PODCAST_PARSER_STATE_ITEM_PROPERTY,
52
 
        RB_PODCAST_PARSER_STATE_END,
53
 
    } state;
 
45
        enum {
 
46
                RB_PODCAST_PARSER_STATE_START,
 
47
                RB_PODCAST_PARSER_STATE_RSS,
 
48
                RB_PODCAST_PARSER_STATE_CHANNEL,
 
49
                RB_PODCAST_PARSER_STATE_CHANNEL_PROPERTY,
 
50
                RB_PODCAST_PARSER_STATE_IMG,
 
51
                RB_PODCAST_PARSER_STATE_IMG_PROPERTY,
 
52
                RB_PODCAST_PARSER_STATE_ITEM,
 
53
                RB_PODCAST_PARSER_STATE_ITEM_PROPERTY,
 
54
                RB_PODCAST_PARSER_STATE_END,
 
55
        } state;
54
56
};
55
57
 
56
58
static gboolean rb_validate_channel_propert (const char *name);
66
68
static RBPodcastItem *
67
69
rb_podcast_initializa_item ()
68
70
{
69
 
    RBPodcastItem *data = g_new0 (RBPodcastItem, 1);
70
 
    return data;
 
71
        RBPodcastItem *data = g_new0 (RBPodcastItem, 1);
 
72
        return data;
71
73
}
72
74
 
73
75
static void
74
 
rb_set_channel_value (struct RBPoadcastLoadContext* ctx, const char* name, const char* value)
 
76
rb_set_channel_value (struct RBPoadcastLoadContext *ctx,
 
77
                      const char *name,
 
78
                      const char *value)
75
79
{
76
 
   xmlChar *dvalue;
77
 
   if (!value)
78
 
       return;
79
 
 
80
 
   dvalue = xmlCharStrdup (value);
81
 
   g_strstrip ((char *)dvalue);
 
80
        xmlChar *dvalue;
 
81
 
 
82
        if (value == NULL)
 
83
                return;
 
84
 
 
85
        if (name == NULL)
 
86
                return;
 
87
 
 
88
        dvalue = xmlCharStrdup (value);
 
89
        g_strstrip ((char *)dvalue);
82
90
   
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);
100
 
        g_free (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;
105
 
   } else {
106
 
        g_free (dvalue);
107
 
   }
 
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);
 
108
                g_free (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;
 
113
        } else {
 
114
                g_free (dvalue);
 
115
        }
108
116
}
109
117
 
110
118
 
111
119
static void
112
 
rb_set_item_value (struct RBPoadcastLoadContext* ctx, const char* name, const char* value)
 
120
rb_set_item_value (struct RBPoadcastLoadContext *ctx,
 
121
                   const char *name,
 
122
                   const char *value)
113
123
{
114
 
   xmlChar *dvalue;
115
 
   dvalue = xmlCharStrdup (value);
116
 
   g_strstrip ((char *)dvalue);
117
 
 
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);
124
 
       g_free (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);
131
 
       g_free (dvalue);
132
 
   } else if (!strcmp (name, "length")) {
133
 
       ctx->item_data->filesize = g_ascii_strtoull ((char*)dvalue, NULL, 10);
134
 
   } else {
135
 
       g_free (dvalue);
136
 
   }
 
124
        xmlChar *dvalue;
 
125
 
 
126
        dvalue = xmlCharStrdup (value);
 
127
        g_strstrip ((char *)dvalue);
 
128
 
 
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);
 
135
                g_free (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);
 
142
                g_free (dvalue);
 
143
        } else if (!strcmp (name, "length")) {
 
144
                ctx->item_data->filesize = g_ascii_strtoull ((char *)dvalue, NULL, 10);
 
145
        } else {
 
146
                g_free (dvalue);
 
147
        }
137
148
}
138
149
 
139
150
 
140
151
static void
141
 
rb_insert_item (struct RBPoadcastLoadContext* ctx)
 
152
rb_insert_item (struct RBPoadcastLoadContext *ctx)
142
153
{
143
154
        RBPodcastItem *data = ctx->item_data;
144
155
 
145
 
        if (!data->url)
 
156
        rb_debug ("Inserting item as post");
 
157
 
 
158
        if (!data->url) {
 
159
                rb_debug ("Item does not have a URL, skipping");
146
160
                return;
 
161
        }
147
162
 
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);
149
164
}
150
165
 
151
 
static gboolean rb_validate_channel_propert (const char *name)
 
166
static gboolean
 
167
rb_validate_channel_propert (const char *name)
152
168
{
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"))
164
 
        return TRUE;
165
 
    else
166
 
        return FALSE;
 
169
        if (name == NULL) {
 
170
                return FALSE;
 
171
        }
 
172
 
 
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")) {
 
184
                return TRUE;
 
185
        } else {
 
186
                return FALSE;
 
187
        }
167
188
    
168
189
}
169
190
 
170
 
static gboolean rb_validate_item_propert (const char *name)
 
191
static gboolean
 
192
rb_validate_item_propert (const char *name)
171
193
{
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") )
 
194
        if (name == NULL) {
 
195
                return FALSE;
 
196
        }
 
197
 
 
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") ) {
178
204
            
179
 
        return TRUE;
180
 
    else
181
 
        return FALSE;
 
205
                return TRUE;
 
206
        } else {
 
207
                return FALSE;
 
208
        }
182
209
}
183
210
 
184
211
 
185
212
static void 
186
 
rb_podcast_parser_start_element (struct RBPoadcastLoadContext* ctx, const char *name, const char **attrs)
 
213
rb_podcast_parser_start_element (struct RBPoadcastLoadContext *ctx,
 
214
                                 const char *name,
 
215
                                 const char **attrs)
187
216
{
188
217
 
189
 
    switch (ctx->state)
190
 
    {
 
218
        rb_debug ("Start element: %s state: %d", name, ctx->state);
 
219
 
 
220
        switch (ctx->state) {
191
221
        case RB_PODCAST_PARSER_STATE_START:
192
 
        {
193
 
            if (!strcmp(name, "rss")) {
194
 
                ctx->state = RB_PODCAST_PARSER_STATE_RSS;
195
 
            }
196
 
            else
197
 
                ctx->in_unknown_elt++;
198
 
            break;
199
 
        }
 
222
                {
 
223
                        if (!strcmp (name, "rss")) {
 
224
                                ctx->state = RB_PODCAST_PARSER_STATE_RSS;
 
225
                        } else {
 
226
                                ctx->in_unknown_elt++;
 
227
                        }
 
228
 
 
229
                        break;
 
230
                }
200
231
        
201
232
        case RB_PODCAST_PARSER_STATE_RSS:
202
 
        {
203
 
            if (!strcmp(name, "channel")) {
204
 
                ctx->state = RB_PODCAST_PARSER_STATE_CHANNEL;
205
 
            }
206
 
            else
207
 
                ctx->in_unknown_elt++;
208
 
            break;
209
 
        }
 
233
                {
 
234
                        if (!strcmp (name, "channel")) {
 
235
                                ctx->state = RB_PODCAST_PARSER_STATE_CHANNEL;
 
236
                        } else {
 
237
                                ctx->in_unknown_elt++;
 
238
                        }
 
239
 
 
240
                        break;
 
241
                }
210
242
 
211
243
        case RB_PODCAST_PARSER_STATE_CHANNEL:
212
 
        {
 
244
                {
213
245
 
214
 
            if (!strcmp(name, "image")) {
215
 
                ctx->state = RB_PODCAST_PARSER_STATE_IMG;
216
 
                break;
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;
220
 
                break;
221
 
            } else  if (!rb_validate_channel_propert (name)) {
222
 
                ctx->in_unknown_elt++;
223
 
                break;
224
 
            } 
 
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++;
 
255
                        } else {
 
256
                                ctx->state = RB_PODCAST_PARSER_STATE_CHANNEL_PROPERTY;
 
257
                        }
225
258
 
226
 
            ctx->state = RB_PODCAST_PARSER_STATE_CHANNEL_PROPERTY;
227
 
            break;
228
 
        }
 
259
                        break;
 
260
                }
229
261
 
230
262
        case RB_PODCAST_PARSER_STATE_ITEM:
231
 
        {
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);
240
 
                    }
241
 
                }
242
 
            } else  if (!rb_validate_item_propert (name)) {
243
 
                ctx->in_unknown_elt++;
244
 
                break;
245
 
            }
246
 
            
247
 
 
248
 
            ctx->state = RB_PODCAST_PARSER_STATE_ITEM_PROPERTY;
249
 
            break;
250
 
        }
 
263
                {
 
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);
 
272
                                        }
 
273
                                }
 
274
 
 
275
                                ctx->state = RB_PODCAST_PARSER_STATE_ITEM_PROPERTY;
 
276
 
 
277
                        } else if (!rb_validate_item_propert (name)) {
 
278
                                ctx->in_unknown_elt++;
 
279
                        } else {
 
280
                                ctx->state = RB_PODCAST_PARSER_STATE_ITEM_PROPERTY;
 
281
                        }
 
282
 
 
283
                        break;
 
284
                }
251
285
 
252
286
        case RB_PODCAST_PARSER_STATE_IMG:
253
 
        {
254
 
            if (strcmp(name, "url") != 0) {
255
 
                ctx->in_unknown_elt++;
256
 
                break;
257
 
            }
 
287
                {
 
288
                        if (strcmp (name, "url") != 0) {
 
289
                                ctx->in_unknown_elt++;
 
290
                        } else {
 
291
                                ctx->state = RB_PODCAST_PARSER_STATE_IMG_PROPERTY;
 
292
                        }
258
293
 
259
 
            ctx->state = RB_PODCAST_PARSER_STATE_IMG_PROPERTY;
260
 
            break;
261
 
        }
 
294
                        break;
 
295
                }
262
296
 
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:
267
 
        break;
268
 
    }
 
301
                break;
 
302
        default:
 
303
                g_warning ("Unknown podcast parser state: %d", ctx->state);
 
304
                break;
 
305
        }
269
306
}
270
307
 
271
308
 
272
309
static void
273
 
rb_podcast_parser_end_element (struct RBPoadcastLoadContext* ctx, 
274
 
                                const char *name)
 
310
rb_podcast_parser_end_element (struct RBPoadcastLoadContext *ctx, 
 
311
                               const char *name)
275
312
{
276
 
//    if (*ctx->die == TRUE) {
277
 
//        xmlStopParser (ctx->xmlctx);
278
 
//        return;
279
 
//    }
 
313
        rb_debug ("End element: %s state: %d", name, ctx->state);
280
314
 
281
 
    if (ctx->in_unknown_elt > 0) {
282
 
        ctx->in_unknown_elt--;
283
 
        return;
284
 
    }
 
315
        if (ctx->in_unknown_elt > 0) {
 
316
                ctx->in_unknown_elt--;
 
317
                rb_debug ("Unknown element");
 
318
                return;
 
319
        }
285
320
               
286
 
    switch (ctx->state)
287
 
    {
 
321
        switch (ctx->state) {
288
322
        case RB_PODCAST_PARSER_STATE_START:
289
 
            ctx->state = RB_PODCAST_PARSER_STATE_END;
290
 
            break;
 
323
                ctx->state = RB_PODCAST_PARSER_STATE_END;
 
324
                break;
291
325
            
292
326
        case RB_PODCAST_PARSER_STATE_RSS:
293
 
            ctx->state = RB_PODCAST_PARSER_STATE_START;
294
 
            break;
 
327
                ctx->state = RB_PODCAST_PARSER_STATE_START;
 
328
                break;
295
329
 
296
330
        case RB_PODCAST_PARSER_STATE_CHANNEL:
297
 
            ctx->state = RB_PODCAST_PARSER_STATE_RSS;
298
 
            break;
 
331
                ctx->state = RB_PODCAST_PARSER_STATE_RSS;
 
332
                break;
299
333
            
300
334
        case RB_PODCAST_PARSER_STATE_CHANNEL_PROPERTY:
301
 
        {
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);
305
 
            break;
306
 
        }
 
335
                {
 
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);
 
339
                        break;
 
340
                }
307
341
 
308
342
        case RB_PODCAST_PARSER_STATE_ITEM:
309
 
        {
310
 
            rb_insert_item(ctx);
311
 
            ctx->state = RB_PODCAST_PARSER_STATE_CHANNEL;
312
 
            break;
313
 
        }
 
343
                {
 
344
                        rb_insert_item (ctx);
 
345
                        ctx->state = RB_PODCAST_PARSER_STATE_CHANNEL;
 
346
                        break;
 
347
                }
314
348
 
315
349
        case RB_PODCAST_PARSER_STATE_ITEM_PROPERTY:
316
 
        {
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);
320
 
            break;
321
 
        }
 
350
                {
 
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);
 
354
                        break;
 
355
                }
322
356
 
323
357
        case RB_PODCAST_PARSER_STATE_IMG_PROPERTY:
324
 
        {
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);
328
 
            break;
329
 
        }
 
358
                {
 
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);
 
362
                        break;
 
363
                }
330
364
 
331
365
        case RB_PODCAST_PARSER_STATE_IMG:
332
 
            ctx->state = RB_PODCAST_PARSER_STATE_CHANNEL;
333
 
            break;
 
366
                ctx->state = RB_PODCAST_PARSER_STATE_CHANNEL;
 
367
                break;
334
368
 
335
369
        case RB_PODCAST_PARSER_STATE_END:
336
 
            break;
337
 
    }
 
370
                break;
 
371
 
 
372
        default:
 
373
                g_warning ("Unknown podcast parser state: %d", ctx->state);
 
374
                break;
 
375
        }
338
376
}
339
377
    
340
378
 
341
379
static void
342
 
rb_podcast_parser_characters (struct RBPoadcastLoadContext* ctx, const char *data,
343
 
                                     guint len)
 
380
rb_podcast_parser_characters (struct RBPoadcastLoadContext *ctx,
 
381
                              const char *data,
 
382
                              guint len)
344
383
{
345
 
    switch (ctx->state)
346
 
    {
 
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:
358
 
            break;
359
 
    }
 
396
                break;
 
397
        default:
 
398
                g_warning ("Unknown podcast parser state: %d", ctx->state);
 
399
                break;
 
400
        }
360
401
}
361
402
 
362
403
 
363
404
void
364
 
rb_podcast_parse_load_feed(RBPodcastChannel *data, const char *file_name) {
365
 
 
366
 
    xmlParserCtxtPtr ctxt;
367
 
    xmlSAXHandlerPtr sax_handler = g_new0 (xmlSAXHandler, 1);
368
 
    GnomeVFSResult result;
369
 
    GnomeVFSFileInfo *info;
370
 
    gint file_size;
371
 
    gchar *buffer;
372
 
    
373
 
    struct RBPoadcastLoadContext *ctx = g_new0 (struct RBPoadcastLoadContext, 1);
374
 
 
375
 
    data->url = xmlCharStrdup (file_name);
376
 
    
377
 
    ctx->in_unknown_elt = 0;
378
 
    ctx->channel_data = data;
379
 
 
380
 
    if (!gnome_vfs_initialized ()) {
381
 
        goto end_function;
382
 
    }
383
 
 
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);
393
 
            return;
394
 
    }
395
 
    
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)
399
 
            return;
400
 
   
 
405
rb_podcast_parse_load_feed (RBPodcastChannel *data,
 
406
                            const char *file_name)
 
407
{
 
408
        xmlParserCtxtPtr ctxt;
 
409
        xmlSAXHandlerPtr sax_handler = NULL;
 
410
        GnomeVFSResult result;
 
411
        GnomeVFSFileInfo *info;
 
412
        gint file_size;
 
413
        gchar *buffer;
 
414
    
 
415
        struct RBPoadcastLoadContext *ctx = NULL;
 
416
 
 
417
        data->url = xmlCharStrdup (file_name);
 
418
 
 
419
        if (!gnome_vfs_initialized ()) {
 
420
                return;
 
421
        }
 
422
 
 
423
        if (!g_str_has_suffix (file_name, ".rss") && !g_str_has_suffix (file_name, ".xml")) {
 
424
                gboolean invalid_mime_type;
 
425
 
 
426
                info = gnome_vfs_file_info_new ();
 
427
 
 
428
                result = gnome_vfs_get_file_info (file_name, info, GNOME_VFS_FILE_INFO_DEFAULT);
 
429
 
 
430
                if (info != NULL
 
431
                    && info->mime_type != NULL
 
432
                    && strstr (info->mime_type, "xml") == NULL
 
433
                    && strstr (info->mime_type, "rss") == NULL) {
 
434
                        invalid_mime_type = TRUE;
 
435
                } else {
 
436
                        invalid_mime_type = FALSE;
 
437
                }
 
438
 
 
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);
 
442
                        return;
 
443
                }
 
444
 
 
445
                gnome_vfs_file_info_unref (info);
 
446
        }
 
447
    
 
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)
 
451
                return;
401
452
            
402
453
 
403
 
    //initializing parse 
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);
408
460
 
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);
410
465
                            
411
 
    ctxt = xmlCreateMemoryParserCtxt (buffer, file_size);
412
 
    ctx->xmlctx = ctxt;
413
 
    xmlFree (ctxt->sax);
414
 
    ctxt->userData = ctx;
415
 
    ctxt->sax = sax_handler;
416
 
    xmlParseDocument (ctxt);
417
 
    ctxt->sax = NULL;
418
 
    xmlFreeParserCtxt (ctxt);
419
 
 
420
 
    g_free (buffer);
421
 
    g_string_free(ctx->prop_value, TRUE);
422
 
    ctx->channel_data->posts = g_list_reverse (ctx->channel_data->posts);
423
 
 
424
 
end_function:
425
 
    g_free(sax_handler);    
426
 
    g_free(ctx);
 
466
        ctxt = xmlCreateMemoryParserCtxt (buffer, file_size);
 
467
        ctx->xmlctx = ctxt;
 
468
        ctxt->userData = ctx;
 
469
        ctxt->sax = sax_handler;
 
470
        xmlParseDocument (ctxt);
 
471
 
 
472
        g_free (sax_handler);
 
473
        ctxt->sax = NULL;
 
474
        xmlFreeParserCtxt (ctxt);
 
475
 
 
476
        g_free (buffer);
 
477
        g_string_free (ctx->prop_value, TRUE);
 
478
        g_free (ctx);
 
479
 
 
480
        data->posts = g_list_reverse (data->posts);
427
481
}
428
482
 
429
483
static uintmax_t
430
 
rb_podcast_parse_date(const char* date_str)
 
484
rb_podcast_parse_date (const char *date_str)
431
485
{
432
486
        struct tm tm;
433
487
        char *result;
434
488
 
 
489
        /* RFC 2822 date format */
435
490
        result = strptime (date_str, "%a, %d %b %Y %T", &tm);
 
491
 
 
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);
439
496
        }
 
497
 
 
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);
 
502
        }
 
503
 
 
504
        /* ISO date like */
 
505
        if (result == NULL) {
 
506
                memset (&tm, 0, sizeof (struct tm));
 
507
                result = strptime (date_str, "%Y-%m-%d %T", &tm);
 
508
        }
 
509
 
 
510
        /* Broken weekday short names */
 
511
        if (result == NULL) {
 
512
                char *tmp;
 
513
 
 
514
                /* strip off the erroneous weekday */
 
515
                tmp = strstr (date_str, ",");
 
516
                if (tmp != NULL) {
 
517
                        tmp++;
 
518
                        memset (&tm, 0, sizeof (struct tm));
 
519
                        result = strptime (tmp, "%d %b %Y %T", &tm);
 
520
                }
 
521
        }
 
522
 
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);
472
555
        
473
556
        g_list_foreach (data->posts, (GFunc) rb_podcast_parse_item_free, NULL);
474
557
        g_list_free (data->posts);
475
 
 
476
 
        if (data->url != NULL)
477
 
                g_free (data->url);
478
 
 
479
 
        if (data->title != NULL)
480
 
                g_free (data->title);
481
 
 
482
 
        if (data->lang != NULL)
483
 
                g_free (data->lang);
484
 
 
485
 
        if (data->subtitle != NULL)
486
 
                g_free (data->subtitle);
487
 
 
488
 
        if (data->summary != NULL)
489
 
                g_free (data->summary);
490
 
 
491
 
        if (data->description != NULL)
492
 
                g_free (data->description);
493
 
 
494
 
        if (data->author != NULL)
495
 
                g_free (data->author);
496
 
 
497
 
        if (data->contact != NULL)
498
 
                g_free (data->contact);
499
 
 
500
 
        if (data->img != NULL)
501
 
                g_free (data->img);
502
 
 
503
 
        if (data->copyright != NULL)
504
 
                g_free (data->copyright);
 
558
        data->posts = NULL;
 
559
 
 
560
        g_free (data->url);
 
561
        g_free (data->title);
 
562
        g_free (data->lang);
 
563
        g_free (data->subtitle);
 
564
        g_free (data->summary);
 
565
        g_free (data->description);
 
566
        g_free (data->author);
 
567
        g_free (data->contact);
 
568
        g_free (data->img);
 
569
        g_free (data->copyright);
505
570
        
506
571
        g_free (data);
 
572
        data = NULL;
507
573
}
508
574
                
509
575
void 
511
577
{
512
578
        g_return_if_fail (item != NULL);
513
579
        
514
 
        if (item->title != NULL)
515
 
                g_free (item->title);
516
 
 
517
 
        if (item->url != NULL)
518
 
                g_free (item->url);
519
 
 
520
 
        if (item->description != NULL)
521
 
                g_free (item->description);
 
580
        g_free (item->title);
 
581
        g_free (item->url);
 
582
        g_free (item->description);
522
583
 
523
584
        g_free (item);
524
585
}