~ubuntu-branches/ubuntu/vivid/liferea/vivid-proposed

« back to all changes in this revision

Viewing changes to src/metadata.c

  • Committer: Package Import Robot
  • Author(s): bojo42
  • Date: 2012-03-29 14:17:21 UTC
  • mfrom: (1.3.9) (3.2.5 sid)
  • Revision ID: package-import@ubuntu.com-20120329141721-tbfopcrc5797wxt7
Tags: 1.8.3-0.1ubuntu1
* New upstream release (LP: #290666, #371754, #741543, #716688)
* Merge from Debian unstable (LP: #935147), remaining changes:
* debian/patches:
  - drop gtk-status-icon.patch & notification-append as in upstream
  - drop fix_systray_behavior as mostly upstreamed and rest seems unused
  - 01_ubuntu_feedlists: update & rename, move planets to "Open Source"  
  - add_X-Ubuntu-Gettext-Domain: rebase
  - libunity.patch: rebase, apply before indicator patch (liferea_shell.c)
  - libindicate_increase_version.patch: exclude from libindicate.patch
  - deactivate libindicate.patch, seems partly upstreamed and needs rework
* debian/control: libindicate-dev, libindicate-gtk-dev & libunity-dev
* debian/liferea.indicate & liferea.install: ship indicator desktop file
* debian/rules: enable libindicate

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 * @file metadata.c  handling of typed item and feed meta data
3
3
 *
4
4
 * Copyright (C) 2004-2006 Nathan J. Conrad <t98502@users.sourceforge.net>
5
 
 * Copyright (C) 2004-2008 Lars Lindner <lars.lindner@gmail.com>
 
5
 * Copyright (C) 2004-2010 Lars Lindner <lars.lindner@gmail.com>
6
6
 *
7
7
 * This program is free software; you can redistribute it and/or modify
8
8
 * it under the terms of the GNU General Public License as published by
19
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
20
 */
21
21
 
22
 
#ifdef HAVE_CONFIG_H
23
 
#  include <config.h>
24
 
#endif
25
 
 
26
22
#include <glib.h>
27
23
#include <string.h>
28
24
 
36
32
   date values are always text values but maybe of different type depending
37
33
   on their usage type. */
38
34
 
39
 
/** Metadata value types */
40
 
enum {
41
 
        METADATA_TYPE_ASCII = 1,        /**< metadata can be any character data */
42
 
        METADATA_TYPE_URL = 2,          /**< metadata is an URL and guaranteed to be valid for use in XML */
43
 
        METADATA_TYPE_HTML = 3          /**< metadata is XHTML content and valid to be embedded in XML */
44
 
};
45
 
 
46
35
static GHashTable *metadataTypes = NULL;        /**< hash table with all registered meta data types */
47
36
 
48
37
struct pair {
50
39
        GSList          *data;          /** list of metadata values */
51
40
};
52
41
 
53
 
static void
54
 
metadata_type_register (const gchar *name, gint type)
55
 
{
56
 
        if (!metadataTypes)
57
 
                metadataTypes = g_hash_table_new (g_str_hash, g_str_equal);
58
 
                
59
 
        g_hash_table_insert (metadataTypes, (gpointer)name, GINT_TO_POINTER (type));
60
 
}
61
 
 
 
42
/* register metadata types to check validity on adding */
62
43
static void
63
44
metadata_init (void)
64
45
{
65
 
        /* register metadata types to check validity on adding */
 
46
        g_assert (NULL == metadataTypes);
 
47
        
 
48
        metadataTypes = g_hash_table_new (g_str_hash, g_str_equal);
66
49
        
67
50
        /* generic types */
68
51
        metadata_type_register ("author",               METADATA_TYPE_HTML);
69
52
        metadata_type_register ("contributor",          METADATA_TYPE_HTML);
70
53
        metadata_type_register ("copyright",            METADATA_TYPE_HTML);
71
54
        metadata_type_register ("language",             METADATA_TYPE_HTML);
72
 
        metadata_type_register ("pubDate",              METADATA_TYPE_ASCII);
73
 
        metadata_type_register ("contentUpdateDate",    METADATA_TYPE_ASCII);
 
55
        metadata_type_register ("pubDate",              METADATA_TYPE_TEXT);
 
56
        metadata_type_register ("contentUpdateDate",    METADATA_TYPE_TEXT);
74
57
        metadata_type_register ("managingEditor",       METADATA_TYPE_HTML);
75
58
        metadata_type_register ("webmaster",            METADATA_TYPE_HTML);
76
59
        metadata_type_register ("feedgenerator",        METADATA_TYPE_HTML);
77
60
        metadata_type_register ("imageUrl",             METADATA_TYPE_URL);
 
61
        metadata_type_register ("icon",                 METADATA_TYPE_URL);
78
62
        metadata_type_register ("homepage",             METADATA_TYPE_URL);
79
63
        metadata_type_register ("textInput",            METADATA_TYPE_HTML);
80
64
        metadata_type_register ("errorReportsTo",       METADATA_TYPE_HTML);
81
65
        metadata_type_register ("feedgeneratorUri",     METADATA_TYPE_URL);
82
66
        metadata_type_register ("category",             METADATA_TYPE_HTML);
83
 
        metadata_type_register ("enclosure",            METADATA_TYPE_ASCII);
 
67
        metadata_type_register ("enclosure",            METADATA_TYPE_TEXT);
84
68
        metadata_type_register ("commentsUri",          METADATA_TYPE_URL);
85
69
        metadata_type_register ("commentFeedUri",       METADATA_TYPE_URL);
86
70
        metadata_type_register ("feedTitle",            METADATA_TYPE_HTML);
88
72
        
89
73
        /* types for aggregation NS */
90
74
        metadata_type_register ("agSource",             METADATA_TYPE_URL);
91
 
        metadata_type_register ("agTimestamp",          METADATA_TYPE_ASCII);
 
75
        metadata_type_register ("agTimestamp",          METADATA_TYPE_TEXT);
92
76
 
93
77
        /* types for blog channel */
94
78
        metadata_type_register ("blogChannel",          METADATA_TYPE_HTML);
122
106
        metadata_type_register ("related",              METADATA_TYPE_URL);
123
107
 
124
108
        /* for georss:point */
125
 
        metadata_type_register ("point",                METADATA_TYPE_ASCII);
 
109
        metadata_type_register ("point",                METADATA_TYPE_TEXT);
126
110
 
127
111
        return;
128
112
}
129
113
 
 
114
void
 
115
metadata_type_register (const gchar *name, gint type)
 
116
{
 
117
        if (!metadataTypes)
 
118
                metadata_init ();       
 
119
        
 
120
        g_hash_table_insert (metadataTypes, (gpointer)name, GINT_TO_POINTER (type));
 
121
}
 
122
 
 
123
gboolean
 
124
metadata_is_type_registered (const gchar *strid)
 
125
{
 
126
        if (!metadataTypes)
 
127
                metadata_init ();
 
128
 
 
129
        if (g_hash_table_lookup (metadataTypes, strid))
 
130
                return TRUE;
 
131
        else
 
132
                return FALSE;
 
133
}
 
134
 
130
135
static gint
131
136
metadata_get_type (const gchar *name)
132
137
{
137
142
 
138
143
        type = GPOINTER_TO_INT (g_hash_table_lookup (metadataTypes, (gpointer)name));
139
144
        if (0 == type)
140
 
                debug1 (DEBUG_PARSING, "unknown metadata type (%s)", name);
 
145
                g_warning ("Unknown metadata type: %s, please report this Liferea bug!", name);
141
146
        
142
147
        return type;
143
148
}
144
149
 
145
 
GSList * metadata_list_append(GSList *metadata, const gchar *strid, const gchar *data) {
 
150
GSList *
 
151
metadata_list_append (GSList *metadata, const gchar *strid, const gchar *data)
 
152
{
146
153
        GSList          *iter = metadata;
147
154
        gchar           *tmp, *checked_data = NULL;
148
155
        struct pair     *p;
149
156
        
150
 
        if(NULL == data)
 
157
        if (!data)
151
158
                return metadata;
152
159
        
153
160
        /* lookup type and check format */
154
 
        switch(metadata_get_type(strid)) {
155
 
                case METADATA_TYPE_ASCII:
 
161
        switch (metadata_get_type (strid)) {
 
162
                case METADATA_TYPE_TEXT:
156
163
                        /* No check because renderer will process further */
157
 
                        checked_data = g_strdup(data);
 
164
                        checked_data = g_strdup (data);
158
165
                        break;
159
166
                case METADATA_TYPE_URL:
160
167
                        /* Simple sanity check to see if it doesn't break XML */
161
 
                        if(!strchr(data, '<') && !(strchr(data, '>')) && !(strchr(data, '&'))) {
162
 
                                checked_data = g_strdup(data);
 
168
                        if (!strchr(data, '<') && !(strchr (data, '>')) && !(strchr (data, '&'))) {
 
169
                                checked_data = g_strdup (data);
163
170
                        } else {
164
 
                                checked_data = common_uri_escape(data);
 
171
                                checked_data = common_uri_escape (data);
165
172
                        }
166
173
                        
167
174
                        /* finally strip whitespace */
168
175
                        checked_data = g_strchomp (checked_data);
169
176
                        break;
170
177
                default:
171
 
                        debug1(DEBUG_CACHE, "Unknown metadata type \"%s\", this is a program bug! Treating as HTML.", strid);
 
178
                        g_warning ("Unknown metadata type: %s (id=%d), please report this Liferea bug! Treating as HTML.", strid, metadata_get_type (strid));
172
179
                case METADATA_TYPE_HTML:
173
180
                        /* Needs to check for proper XHTML */
174
181
                        if (xhtml_is_well_formed (data)) {
184
191
                        break;
185
192
        }
186
193
        
187
 
        while(iter) {
 
194
        while (iter) {
188
195
                p = (struct pair*)iter->data; 
189
 
                if(g_str_equal(p->strid, strid)) {
190
 
                        p->data = g_slist_append(p->data, checked_data);
 
196
                if (g_str_equal (p->strid, strid)) {
 
197
                        p->data = g_slist_append (p->data, checked_data);
191
198
                        return metadata;
192
199
                }
193
200
                iter = iter->next;
194
201
        }
195
 
        p = g_new(struct pair, 1);
196
 
        p->strid = g_strdup(strid);
197
 
        p->data = g_slist_append(NULL, checked_data);
198
 
        metadata = g_slist_append(metadata, p);
 
202
        p = g_new (struct pair, 1);
 
203
        p->strid = g_strdup (strid);
 
204
        p->data = g_slist_append (NULL, checked_data);
 
205
        metadata = g_slist_append (metadata, p);
199
206
        return metadata;
200
207
}
201
208
 
202
 
void metadata_list_set(GSList **metadata, const gchar *strid, const gchar *data) {
 
209
void
 
210
metadata_list_set (GSList **metadata, const gchar *strid, const gchar *data)
 
211
{
203
212
        GSList  *iter = *metadata;
204
213
        struct pair *p;
205
214
        
206
 
        while(iter) {
 
215
        while (iter) {
207
216
                p = (struct pair*)iter->data; 
208
 
                if(g_str_equal(p->strid, strid)) {
209
 
                        if(p->data) {
 
217
                if (g_str_equal (p->strid, strid)) {
 
218
                        if (p->data) {
210
219
                                /* exchange old value */
211
 
                                g_free(((GSList *)p->data)->data);
212
 
                                ((GSList *)p->data)->data = g_strdup(data);
 
220
                                g_free (((GSList *)p->data)->data);
 
221
                                ((GSList *)p->data)->data = g_strdup (data);
213
222
                        } else {
214
 
                                p->data = g_slist_append(p->data, g_strdup(data));
 
223
                                p->data = g_slist_append (p->data, g_strdup (data));
215
224
                        }
216
225
                        return;
217
226
                }
218
227
                iter = iter->next;
219
228
        }
220
 
        p = g_new(struct pair, 1);
221
 
        p->strid = g_strdup(strid);
222
 
        p->data = g_slist_append(NULL, g_strdup(data));
223
 
        *metadata = g_slist_append(*metadata, p);
 
229
        p = g_new (struct pair, 1);
 
230
        p->strid = g_strdup (strid);
 
231
        p->data = g_slist_append (NULL, g_strdup (data));
 
232
        *metadata = g_slist_append (*metadata, p);
224
233
}
225
234
 
226
 
void metadata_list_foreach(GSList *metadata, metadataForeachFunc func, gpointer user_data) {
 
235
void
 
236
metadata_list_foreach (GSList *metadata, metadataForeachFunc func, gpointer user_data)
 
237
{
227
238
        GSList  *list = metadata;
228
239
        guint   index = 0;
229
240
        
230
 
        while(list) {
 
241
        while (list) {
231
242
                struct pair *p = (struct pair*)list->data; 
232
243
                GSList *values = (GSList *)p->data;
233
 
                while(values) {
 
244
                while (values) {
234
245
                        index++;
235
246
                        (*func)(p->strid, values->data, index, user_data);
236
 
                        values = g_slist_next(values);
 
247
                        values = g_slist_next (values);
237
248
                }
238
249
                list = list->next;
239
250
        }
240
251
}
241
252
 
242
 
GSList * metadata_list_get_values(GSList *metadata, const gchar *strid) {
 
253
GSList *
 
254
metadata_list_get_values (GSList *metadata, const gchar *strid)
 
255
{
243
256
        GSList *list = metadata;
244
257
        
245
 
        while(list) {
 
258
        while (list) {
246
259
                struct pair *p = (struct pair*)list->data; 
247
 
                if(g_str_equal(p->strid, strid))
 
260
                if (g_str_equal (p->strid, strid))
248
261
                        return p->data;
249
262
                list = list->next;
250
263
        }
251
264
        return NULL;
252
265
}
253
266
 
254
 
const gchar * metadata_list_get(GSList *metadata, const gchar *strid) {
 
267
const gchar *
 
268
metadata_list_get (GSList *metadata, const gchar *strid)
 
269
{
255
270
        GSList  *values;
256
271
        
257
 
        values = metadata_list_get_values(metadata, strid);
 
272
        values = metadata_list_get_values (metadata, strid);
258
273
        return values?values->data:NULL;
259
274
 
260
275
}
261
276
 
262
 
GSList * metadata_list_copy(GSList *list) {
 
277
GSList *
 
278
metadata_list_copy (GSList *list)
 
279
{
263
280
        GSList          *copy = NULL;
264
 
        GSList          *list2, *iter2, *iter = list;
 
281
        GSList          *iter2, *iter = list;
265
282
        struct pair     *p;
266
283
        
267
 
        while(iter) {
 
284
        while (iter) {
268
285
                p = (struct pair*)iter->data;
269
 
                iter2 = list2 = p->data;
270
 
                while(iter2) {
271
 
                        copy = metadata_list_append(copy, p->strid, iter2->data);
 
286
                iter2 = p->data;
 
287
                while (iter2) {
 
288
                        copy = metadata_list_append (copy, p->strid, iter2->data);
272
289
                        iter2 = iter2->next;
273
290
                }
274
291
                iter = iter->next;
277
294
        return copy;
278
295
}
279
296
 
280
 
void metadata_list_free(GSList *metadata) {
 
297
void
 
298
metadata_list_free (GSList *metadata)
 
299
{
281
300
        GSList          *list2, *iter2, *iter = metadata;
282
301
        struct pair     *p;
283
302
        
284
 
        while(iter != NULL) {
 
303
        while (iter) {
285
304
                p = (struct pair*)iter->data;
286
305
                list2 = p->data;
287
306
                iter2 = list2;
288
 
                while(iter2 != NULL) {
289
 
                        g_free(iter2->data);
 
307
                while (iter2) {
 
308
                        g_free (iter2->data);
290
309
                        iter2 = iter2->next;
291
310
                }
292
 
                g_slist_free(list2);
293
 
                g_free(p->strid);
294
 
                g_free(p);
 
311
                g_slist_free (list2);
 
312
                g_free (p->strid);
 
313
                g_free (p);
295
314
                iter = iter->next;
296
315
        }
297
 
        g_slist_free(metadata);
 
316
        g_slist_free (metadata);
298
317
}
299
318
 
300
 
void metadata_add_xml_nodes(GSList *metadata, xmlNodePtr parentNode) {
 
319
void
 
320
metadata_add_xml_nodes (GSList *metadata, xmlNodePtr parentNode)
 
321
{
301
322
        GSList *list = metadata;
302
323
        xmlNodePtr attribute;
303
 
        xmlNodePtr metadataNode = xmlNewChild(parentNode, NULL, "attributes", NULL);
 
324
        xmlNodePtr metadataNode = xmlNewChild (parentNode, NULL, "attributes", NULL);
304
325
        
305
 
        while(list) {
 
326
        while (list) {
306
327
                struct pair *p = (struct pair*)list->data; 
307
328
                GSList *list2 = p->data;
308
 
                while(list2) {
309
 
                        attribute = xmlNewTextChild(metadataNode, NULL, "attribute", list2->data);
310
 
                        xmlNewProp(attribute, "name", p->strid);
 
329
                while (list2) {
 
330
                        attribute = xmlNewTextChild (metadataNode, NULL, "attribute", list2->data);
 
331
                        xmlNewProp (attribute, "name", p->strid);
311
332
                        list2 = list2->next;
312
333
                }
313
334
                list = list->next;
314
335
        }
315
336
}
316
337
 
317
 
GSList * metadata_parse_xml_nodes(xmlNodePtr cur) {
 
338
GSList *
 
339
metadata_parse_xml_nodes (xmlNodePtr cur)
 
340
{
318
341
        xmlNodePtr      attribute = cur->xmlChildrenNode;
319
342
        GSList          *metadata = NULL;
320
343
        
321
 
        while(attribute) {
322
 
                if(attribute->type == XML_ELEMENT_NODE &&
323
 
                    !xmlStrcmp(attribute->name, BAD_CAST"attribute")) {
324
 
                        xmlChar *name = xmlGetProp(attribute, BAD_CAST"name");
325
 
                        if(name) {
326
 
                                gchar *value = xmlNodeListGetString(cur->doc, attribute->xmlChildrenNode, TRUE);
327
 
                                if(value) {
328
 
                                        metadata = metadata_list_append(metadata, name, value);
329
 
                                        xmlFree(value);
 
344
        while (attribute) {
 
345
                if (attribute->type == XML_ELEMENT_NODE &&
 
346
                    !xmlStrcmp (attribute->name, BAD_CAST"attribute")) {
 
347
                        xmlChar *name = xmlGetProp (attribute, BAD_CAST"name");
 
348
                        if (name) {
 
349
                                gchar *value = xmlNodeListGetString (cur->doc, attribute->xmlChildrenNode, TRUE);
 
350
                                if (value) {
 
351
                                        metadata = metadata_list_append (metadata, name, value);
 
352
                                        xmlFree (value);
330
353
                                }
331
 
                                xmlFree(name);
 
354
                                xmlFree (name);
332
355
                        }
333
356
                }
334
357
                attribute = attribute->next;