Handle curl errors better (in weather and rss).
[monky] / src / rss.c
1 /* Conky, a system monitor, based on torsmo
2  *
3  * Please see COPYING for details
4  *
5  * Copyright (c) 2007 Toni Spets
6  * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al.
7  *      (see AUTHORS)
8  * All rights reserved.
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "conky.h"
25 #include "logging.h"
26 #include "prss.h"
27 #include <time.h>
28 #include <assert.h>
29 #include <curl/curl.h>
30 #include <curl/types.h>
31 #include <curl/easy.h>
32
33 #define MAX_FEEDS 16
34
35 typedef struct feed_ {
36         char *uri;
37         int last_update;
38         PRSS *data;
39 } feed;
40
41 int num_feeds = 0;
42 feed feeds[MAX_FEEDS];
43
44 int rss_delay(int *wait_time, int delay)
45 {
46         time_t now = time(NULL);
47
48         // make it minutes
49         if (delay < 1) {
50                 delay = 1;
51         }
52         delay *= 60;
53
54         if (!*wait_time) {
55                 *wait_time = now + delay;
56                 return 1;
57         }
58
59         if (now >= *wait_time + delay) {
60                 *wait_time = now + delay;
61                 return 1;
62         }
63
64         return 0;
65 }
66
67 void init_rss_info(void)
68 {
69         int i;
70
71         for (i = 0; i < MAX_FEEDS; i++) {
72                 feeds[i].uri = NULL;
73                 feeds[i].data = NULL;
74                 feeds[i].last_update = 0;
75         }
76 }
77
78 void free_rss_info(void)
79 {
80         int i;
81
82         for (i = 0; i < num_feeds; i++) {
83                 if (feeds[i].uri != NULL) {
84                         free(feeds[i].uri);
85                 }
86         }
87 }
88
89 PRSS *get_rss_info(char *uri, int delay)
90 {
91         CURL *curl = NULL;
92         CURLcode res;
93
94         // pointers to struct
95         feed *curfeed = NULL;
96         PRSS *curdata = NULL;
97         int *last_update = 0;
98
99         int i;
100
101         // curl temps
102         struct MemoryStruct chunk;
103
104         chunk.memory = NULL;
105         chunk.size = 0;
106
107         // first seek for the uri in list
108         for (i = 0; i < num_feeds; i++) {
109                 if (feeds[i].uri != NULL) {
110                         if (!strcmp(feeds[i].uri, uri)) {
111                                 curfeed = &feeds[i];
112                                 break;
113                         }
114                 }
115         }
116
117         if (!curfeed) { // new feed
118                 if (num_feeds == MAX_FEEDS - 1) {
119                         return NULL;
120                 }
121                 curfeed = &feeds[num_feeds];
122                 curfeed->uri = strndup(uri, text_buffer_size);
123                 num_feeds++;
124         }
125
126         last_update = &curfeed->last_update;
127         curdata = curfeed->data;
128
129         if (!rss_delay(last_update, delay)) {
130                 return curdata; // wait for delay to pass
131         }
132
133         if (curdata != NULL) {
134                 prss_free(curdata);     // clean up old data
135                 curdata = NULL;
136         }
137
138         curl = curl_easy_init();
139         if (curl) {
140                 curl_easy_setopt(curl, CURLOPT_URL, uri);
141                 curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
142                 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
143                 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &chunk);
144                 curl_easy_setopt(curl, CURLOPT_USERAGENT, "conky-rss/1.0");
145
146                 res = curl_easy_perform(curl);
147                 if (res == CURLE_OK && chunk.size) {
148                         curdata = prss_parse_data(chunk.memory);
149                         free(chunk.memory);
150                 } else {
151                         ERR("No data from server");
152                 }
153
154                 curl_easy_cleanup(curl);
155         }
156
157         curfeed->data = curdata;
158
159         return curdata;
160 }