clarifying licensing
[monky] / src / rss.c
1 /*
2  * Conky, a system monitor, based on torsmo
3  *
4  * Any original torsmo code is licensed under the BSD license
5  *
6  * All code written since the fork of torsmo is licensed under the GPL
7  *
8  * Please see COPYING for details
9  *
10  * Copyright (c) 2007 Toni Spets
11  * Copyright (c) 2005-2007 Brenden Matthews, Philip Kovacs, et. al. (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
29 #include <stdio.h>
30 #include <string.h>
31 #include <time.h>
32 #include <assert.h>
33 #include "prss.h"
34 #include <curl/curl.h>
35 #include <curl/types.h>
36 #include <curl/easy.h>
37 #include "conky.h"
38
39 #define MAX_FEEDS 16
40
41 struct MemoryStruct {
42         char *memory;
43         size_t size;
44 };
45
46 typedef struct feed_ {
47         char* uri;
48         int last_update;
49         PRSS* data;
50 } feed;
51
52 int num_feeds = 0;
53 feed feeds[MAX_FEEDS];
54
55 size_t
56 WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
57 {
58         size_t realsize = size * nmemb;
59         struct MemoryStruct *mem = (struct MemoryStruct *)data;
60
61         mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1);
62         if (mem->memory) {
63                 memcpy(&(mem->memory[mem->size]), ptr, realsize);
64                 mem->size += realsize;
65                 mem->memory[mem->size] = 0;
66         }
67         return realsize;
68 }
69
70
71 int rss_delay(int *wait, int delay)
72 {
73         time_t now = time(NULL);
74
75         // make it minutes
76         if(delay < 1) delay = 1;
77         delay *= 60;
78
79         if(!*wait) {
80                 *wait = now + delay;
81                 return 1;
82         }
83
84         if(now >= *wait + delay) {
85                 *wait = now + delay;
86                 return 1;
87         }
88
89         return 0;
90 }
91
92 void init_rss_info()
93 {
94         int i;
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()
103 {
104         int i;
105         for(i = 0; i < num_feeds; i++)
106                 if(feeds[i].uri != NULL)
107                         free(feeds[i].uri);
108 }
109
110 PRSS*
111 get_rss_info(char *uri, int delay)
112 {
113         CURL *curl = NULL;
114         CURLcode res;
115         // curl temps
116         struct MemoryStruct chunk;
117         chunk.memory = NULL;
118         chunk.size = 0;
119
120         // pointers to struct
121         feed *curfeed = NULL;
122         PRSS *curdata = NULL;
123         int *last_update = 0;
124
125         int i;
126
127         // first seek for the uri in list
128         for(i = 0; i < num_feeds; i++) {
129                 if(feeds[i].uri != NULL)
130                         if(!strcmp(feeds[i].uri, uri)) {
131                                 curfeed = &feeds[i];
132                                 break;
133                         }
134         }
135
136         if(!curfeed) { // new feed
137                 if(num_feeds == MAX_FEEDS-1) return NULL;
138                 curfeed = &feeds[num_feeds];
139                 curfeed->uri = strdup(uri);
140                 num_feeds++;
141         }
142
143         last_update = &curfeed->last_update;
144         curdata = curfeed->data;
145
146         if(!rss_delay(last_update, delay))
147                 return curdata; // wait for delay to pass
148
149         if(curdata != NULL) {
150                 prss_free(curdata); // clean up old data
151                 curdata = NULL;
152         }
153
154         curl = curl_easy_init();
155         if(curl) {
156                 curl_easy_setopt(curl, CURLOPT_URL, uri);
157                 curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
158                 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
159                 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
160                 curl_easy_setopt(curl, CURLOPT_USERAGENT, "conky-rss/1.0");
161
162                 res = curl_easy_perform(curl);
163                 if(chunk.size) {
164                         curdata = prss_parse_data(chunk.memory);
165                         free(chunk.memory);
166                 } else
167                         ERR("No data from server");
168
169                 curl_easy_cleanup(curl);
170         }
171
172         curfeed->data = curdata;
173
174         return curdata;
175 }