Fix desktop file Categories and add Keywords
[claws.git] / src / plugins / rssyl / feedprops.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2004 Hiroyuki Yamamoto
4  * This file (C) 2005 Andrej Kacian <andrej@kacian.sk>
5  *
6  * - functions for handling feeds.xml file
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #  include "config.h"
25 #endif
26
27 #include <glib.h>
28
29 #include <libxml/parser.h>
30 #include <libxml/xpath.h>
31
32 #include "folder.h"
33
34 #include "feed.h"
35 #include "feedprops.h"
36 #include "rssyl.h"
37 #include "rssyl_prefs.h"
38
39 static gchar *rssyl_get_props_path(void)
40 {
41         return g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, RSSYL_DIR,
42                         G_DIR_SEPARATOR_S, RSSYL_PROPS_FILE, NULL);
43 }
44
45
46 /* rssyl_store_feed_props()
47  *
48  * Stores feed properties into feeds.xml file in the rcdir. Updates if already
49  * stored for this feed.
50  */
51 void rssyl_store_feed_props(RSSylFolderItem *ritem)
52 {
53         gchar *path;
54         xmlDocPtr doc;
55         xmlNodePtr node, rootnode;
56         xmlXPathObjectPtr result;
57         xmlXPathContextPtr context;
58         FolderItem *item = &ritem->item;
59         gboolean found = FALSE, def_ri, def_ex;
60         gint i;
61
62         g_return_if_fail(ritem != NULL);
63         g_return_if_fail(ritem->url != NULL);
64
65         def_ri = ritem->default_refresh_interval;
66         if( def_ri )
67                 ritem->refresh_interval = rssyl_prefs_get()->refresh;
68
69         def_ex = ritem->default_expired_num;
70         if( def_ex )
71                 ritem->expired_num = rssyl_prefs_get()->expired;
72
73         path = rssyl_get_props_path();
74
75         if( !(doc = xmlParseFile(path)) ) {
76                 debug_print("RSSyl: file %s doesn't exist, creating it\n", path);
77                 doc = xmlNewDoc("1.0");
78
79                 rootnode = xmlNewNode(NULL, "feeds");
80                 xmlDocSetRootElement(doc, rootnode);
81         } else {
82                 rootnode = xmlDocGetRootElement(doc);
83         }
84
85         context = xmlXPathNewContext(doc);
86         if( !(result = xmlXPathEvalExpression(RSSYL_PROPS_XPATH, context)) ) {
87                 debug_print("RSSyl: XML - no result found for %s\n", RSSYL_PROPS_XPATH);
88                 xmlXPathFreeContext(context);
89         } else {
90                 for( i = 0; i < result->nodesetval->nodeNr; i++ ) {
91                         gchar *tmp, *t_prop = NULL;
92                         node = result->nodesetval->nodeTab[i];
93                         tmp = xmlGetProp(node, RSSYL_PROP_NAME);
94
95                         if( !strcmp(tmp, item->name) ) {
96                                 debug_print("RSSyl: XML - updating node for '%s'\n", item->name);
97
98                                 xmlSetProp(node, RSSYL_PROP_NAME, item->name);
99                                 xmlSetProp(node, RSSYL_PROP_OFFICIAL_NAME, 
100                                                 ritem->official_name?ritem->official_name:item->name);
101                                 xmlSetProp(node, RSSYL_PROP_URL, ritem->url);
102
103                                 xmlSetProp(node, RSSYL_PROP_DEF_REFRESH, (def_ri ? "1" : "0") );
104                                 if( !def_ri ) {
105                                         t_prop = g_strdup_printf("%d", ritem->refresh_interval);
106                                         xmlSetProp(node, RSSYL_PROP_REFRESH,
107                                                         t_prop );
108                                         g_free(t_prop);
109                                 }
110
111                                 xmlSetProp(node, RSSYL_PROP_DEF_EXPIRED, (def_ex ? "1" : "0") );
112                                 if( !def_ex ) {
113                                         t_prop = g_strdup_printf("%d", ritem->expired_num);
114                                         xmlSetProp(node, RSSYL_PROP_EXPIRED,
115                                                         t_prop );
116                                         g_free(t_prop);
117                                 }
118                                 xmlSetProp(node, RSSYL_PROP_FETCH_COMMENTS,
119                                                 (ritem->fetch_comments ? "1" : "0"));
120                                 t_prop = g_strdup_printf("%d", ritem->fetch_comments_for);
121                                 xmlSetProp(node, RSSYL_PROP_FETCH_COMMENTS_FOR, t_prop);
122                                 g_free(t_prop);
123
124                                 t_prop = g_strdup_printf("%d", ritem->silent_update);
125                                 xmlSetProp(node, RSSYL_PROP_SILENT_UPDATE, t_prop);
126                                 g_free(t_prop);
127
128                                 t_prop = g_strdup_printf("%d", ritem->ssl_verify_peer);
129                                 xmlSetProp(node, RSSYL_PROP_SSL_VERIFY_PEER, t_prop);
130                                 g_free(t_prop);
131
132                                 found = TRUE;
133                         }
134                         xmlFree(tmp);
135                 }
136         }
137
138         xmlXPathFreeContext(context);
139         xmlXPathFreeObject(result);
140
141         /* node for our feed doesn't exist, let's make one */
142         if( !found ) {
143                 debug_print("RSSyl: XML - creating node for '%s', storing URL '%s'\n",
144                                 item->name, ritem->url);
145                 node = xmlNewTextChild(rootnode, NULL, "feed", NULL);
146                 xmlSetProp(node, RSSYL_PROP_NAME, item->name);
147                 xmlSetProp(node, RSSYL_PROP_OFFICIAL_NAME, 
148                                 ritem->official_name?ritem->official_name:item->name);
149                 xmlSetProp(node, RSSYL_PROP_URL, ritem->url);
150                 xmlSetProp(node, RSSYL_PROP_DEF_REFRESH, (def_ri ? "1" : "0") );
151                 if( !def_ri )
152                         xmlSetProp(node, RSSYL_PROP_REFRESH,
153                                         g_strdup_printf("%d", ritem->refresh_interval) );
154                 xmlSetProp(node, RSSYL_PROP_DEF_EXPIRED, (def_ex ? "1" : "0") );
155                 if( !def_ex )
156                         xmlSetProp(node, RSSYL_PROP_EXPIRED,
157                                         g_strdup_printf("%d", ritem->expired_num) );
158         }
159
160         xmlSaveFormatFile(path, doc, 1);
161         xmlFreeDoc(doc);
162         g_free(path);
163 }
164
165 /* rssyl_get_feed_props()
166  *
167  * Retrieves props for feed from feeds.xml file in the rcdir.
168  */
169 void rssyl_get_feed_props(RSSylFolderItem *ritem)
170 {
171         gchar *path, *tmp = NULL;
172         xmlDocPtr doc;
173         xmlNodePtr node;
174         xmlXPathObjectPtr result;
175         xmlXPathContextPtr context;
176         FolderItem *item = &ritem->item;
177         gint i, tmpi;
178         gboolean force_update = FALSE;
179         RSSylPrefs *rsprefs = NULL;
180
181         g_return_if_fail(ritem != NULL);
182
183         if( ritem->url ) {
184                 g_free(ritem->url);
185                 ritem->url = NULL;
186         }
187
188         ritem->default_refresh_interval = TRUE;
189         ritem->refresh_interval = rssyl_prefs_get()->refresh;
190         ritem->expired_num = rssyl_prefs_get()->expired;
191
192         path = rssyl_get_props_path();
193
194         doc = xmlParseFile(path);
195         g_return_if_fail(doc != NULL);
196
197         context = xmlXPathNewContext(doc);
198         if( !(result = xmlXPathEvalExpression(RSSYL_PROPS_XPATH, context)) ) {
199                 debug_print("RSSyl: XML - no result found for %s\n", RSSYL_PROPS_XPATH);
200                 xmlXPathFreeContext(context);
201         } else {
202                 for( i = 0; i < result->nodesetval->nodeNr; i++ ) {
203                         gchar *property = NULL;
204                         node = result->nodesetval->nodeTab[i];
205                         property = xmlGetProp(node, RSSYL_PROP_NAME);
206                         if( !strcmp(property, item->name) ) {
207                                 /* official name */
208                                 tmp = xmlGetProp(node, RSSYL_PROP_OFFICIAL_NAME);
209                                 ritem->official_name = (tmp ? g_strdup(tmp) : g_strdup(item->name));
210                                 if (tmp == NULL)
211                                         force_update = TRUE;
212                                 xmlFree(tmp);
213                                 tmp = NULL;
214
215                                 /* URL */
216                                 tmp = xmlGetProp(node, RSSYL_PROP_URL);
217                                 ritem->url = (tmp ? g_strdup(tmp) : NULL);
218                                 xmlFree(tmp);
219                                 tmp = NULL;
220
221                                 tmp = xmlGetProp(node, RSSYL_PROP_DEF_REFRESH);
222                                 tmpi = 0;
223                                 if( tmp )
224                                         tmpi = atoi(tmp);
225                                 ritem->default_refresh_interval = (tmpi ? TRUE : FALSE );
226                                 xmlFree(tmp);
227                                 tmp = NULL;
228
229                                 /* refresh_interval */
230                                 tmp = xmlGetProp(node, RSSYL_PROP_REFRESH);
231                                 if( ritem->default_refresh_interval )
232                                         ritem->refresh_interval = rssyl_prefs_get()->refresh;
233                                 else {
234                                         tmpi = -1;
235                                         if( tmp )
236                                                 tmpi = atoi(tmp);
237
238                                         ritem->refresh_interval =
239                                                 (tmpi != -1 ? tmpi : rssyl_prefs_get()->refresh);
240                                 }
241                                 
242                                 xmlFree(tmp);
243                                 tmp = NULL;
244
245                                 /* expired_num */
246                                 tmp = xmlGetProp(node, RSSYL_PROP_DEF_EXPIRED);
247                                 tmpi = 0;
248                                 if( tmp ) {
249                                         tmpi = atoi(tmp);
250                                         ritem->default_expired_num = tmpi;
251                                 }
252                                 xmlFree(tmp);
253                                 tmp = NULL;
254
255                                 /* fetch_comments */
256                                 tmp = xmlGetProp(node, RSSYL_PROP_FETCH_COMMENTS);
257                                 tmpi = 0;
258                                 if( tmp ) {
259                                         tmpi = atoi(tmp);
260                                         ritem->fetch_comments = tmpi;
261                                 }
262                                 xmlFree(tmp);
263                                 tmp = NULL;
264
265                                 /* fetch_comments_for */
266                                 tmp = xmlGetProp(node, RSSYL_PROP_FETCH_COMMENTS_FOR);
267                                 tmpi = 0;
268                                 if( tmp ) {
269                                         tmpi = atoi(tmp);
270                                         ritem->fetch_comments_for = tmpi;
271                                 }
272                                 xmlFree(tmp);
273                                 tmp = NULL;
274
275                                 /* silent_update */
276                                 tmp = xmlGetProp(node, RSSYL_PROP_SILENT_UPDATE);
277                                 tmpi = 0;
278                                 if( tmp ) {
279                                         tmpi = atoi(tmp);
280                                         ritem->silent_update = tmpi;
281                                 }
282                                 xmlFree(tmp);
283                                 tmp = NULL;
284
285                                 /* ssl_verify_peer */
286                                 tmp = xmlGetProp(node, RSSYL_PROP_SSL_VERIFY_PEER);
287                                 tmpi = 0;
288                                 if( tmp ) {
289                                         tmpi = atoi(tmp);
290                                         ritem->ssl_verify_peer = tmpi;
291                                 }
292                                 xmlFree(tmp);
293                                 tmp = NULL;
294
295                                 tmp = xmlGetProp(node, RSSYL_PROP_EXPIRED);
296
297                                 if( ritem->default_expired_num )
298                                         ritem->expired_num = rssyl_prefs_get()->expired;
299                                 else {
300                                         tmpi = -2;
301                                         if( tmp )
302                                                 tmpi = atoi(tmp);
303
304                                         ritem->expired_num = (tmpi != -2 ? tmpi : rssyl_prefs_get()->expired);
305                                 }
306
307                                 xmlFree(tmp);
308                                 tmp = NULL;
309
310                                 debug_print("RSSyl: XML - props for '%s' loaded\n", item->name);
311
312                                 /* Start automatic refresh timer, if necessary */
313                                 if( ritem->refresh_id == 0 ) {
314                                         /* Check if user wants the default for this feed */
315                                         if( ritem->default_refresh_interval ) {
316                                                 rsprefs = rssyl_prefs_get();
317                                                 ritem->refresh_interval = rsprefs->refresh;
318                                         }
319
320                                         /* Start the timer, if determined interval is >0 */
321                                         if( ritem->refresh_interval >= 0 )
322                                                 rssyl_start_refresh_timeout(ritem);
323                                 }
324                         }
325                         xmlFree(property);
326                 }
327         }
328
329         xmlXPathFreeObject(result);
330         xmlXPathFreeContext(context);
331         xmlFreeDoc(doc);
332         g_free(path);
333         if (force_update)
334                 rssyl_store_feed_props(ritem);
335 }
336
337 void rssyl_remove_feed_props(RSSylFolderItem *ritem)
338 {
339         gchar *path;
340         xmlDocPtr doc;
341         xmlNodePtr node;
342         xmlXPathObjectPtr result;
343         xmlXPathContextPtr context;
344         FolderItem *item = &ritem->item;
345         gint i;
346
347         g_return_if_fail(ritem != NULL);
348
349         path = rssyl_get_props_path();
350
351         doc = xmlParseFile(path);
352         g_return_if_fail(doc != NULL);
353
354         context = xmlXPathNewContext(doc);
355         if( !(result = xmlXPathEvalExpression(RSSYL_PROPS_XPATH, context)) ) {
356                 debug_print("RSSyl: XML - no result found for %s\n", RSSYL_PROPS_XPATH);
357                 xmlXPathFreeContext(context);
358         } else {
359                 for( i = 0; i < result->nodesetval->nodeNr; i++ ) {
360                         gchar *tmp;
361                         node = result->nodesetval->nodeTab[i];
362                         tmp = xmlGetProp(node, RSSYL_PROP_NAME);
363                         if( !strcmp(tmp, item->name) ) {
364                                 debug_print("RSSyl: XML - found node for '%s', removing\n", item->name);
365                                 xmlUnlinkNode(node);
366                         }
367                         xmlFree(tmp);
368                 }
369         }
370
371         xmlXPathFreeObject(result);
372         xmlXPathFreeContext(context);
373
374         xmlSaveFormatFile(path, doc, 1);
375
376         xmlFreeDoc(doc);
377         g_free(path);
378 }
379
380 void rssyl_props_update_name(RSSylFolderItem *ritem, gchar *new_name)
381 {
382         gchar *path;
383         xmlDocPtr doc;
384         xmlNodePtr node, rootnode;
385         xmlXPathObjectPtr result;
386         xmlXPathContextPtr context;
387         FolderItem *item = &ritem->item;
388         gboolean found = FALSE;
389         gint i;
390
391         g_return_if_fail(ritem != NULL);
392         g_return_if_fail(ritem->url != NULL);
393
394         path = rssyl_get_props_path();
395
396         if( !(doc = xmlParseFile(path)) ) {
397                 debug_print("RSSyl: file %s doesn't exist, creating it\n", path);
398                 doc = xmlNewDoc("1.0");
399
400                 rootnode = xmlNewNode(NULL, "feeds");
401                 xmlDocSetRootElement(doc, rootnode);
402         } else {
403                 rootnode = xmlDocGetRootElement(doc);
404         }
405
406         context = xmlXPathNewContext(doc);
407         if( !(result = xmlXPathEvalExpression(RSSYL_PROPS_XPATH, context)) ) {
408                 debug_print("RSSyl: XML - no result found for %s\n", RSSYL_PROPS_XPATH);
409                 xmlXPathFreeContext(context);
410         } else {
411                 for( i = 0; i < result->nodesetval->nodeNr; i++ ) {
412                         gchar *tmp;
413                         node = result->nodesetval->nodeTab[i];
414                         tmp = xmlGetProp(node, RSSYL_PROP_NAME);
415                         if( !strcmp(tmp, item->name) ) {
416                                 debug_print("RSSyl: XML - updating node for '%s'\n", item->name);
417                                 xmlSetProp(node, "name", new_name);
418                                 found = TRUE;
419                         }
420                         xmlFree(tmp);
421                 }
422         }
423
424         xmlXPathFreeContext(context);
425         xmlXPathFreeObject(result);
426
427         if( !found )
428                 debug_print("couldn't find feed\n");
429
430         xmlSaveFormatFile(path, doc, 1);
431         xmlFreeDoc(doc);
432         g_free(path);
433 }