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