1 /* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*-
2 * vim: ts=4 sw=4 noet ai cindent syntax=c
4 * Conky, a system monitor, based on torsmo
6 * Copyright (c) 2008 Asbjørn Zweidorff Kjær
7 * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al.
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "text_object.h"
33 #include <sys/types.h>
36 #include <libxml/parser.h>
37 #include <libxml/tree.h>
38 #include <libxml/xmlwriter.h>
40 #include <curl/curl.h>
41 #include <curl/types.h>
42 #include <curl/easy.h>
47 #define EVE_UPDATE_DELAY 60
70 Character eveCharacters[MAXCHARS];
72 static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)
75 struct xmlData *data = 0;
76 data = (struct xmlData *)stream;
77 realsize = size * nmemb;
79 data->data = (char *)realloc(data->data, data->size + realsize + 1);
81 memcpy(&(data->data[data->size]), ptr, realsize);
82 data->size += realsize;
83 data->data[data->size] = '\0';
89 int parseTrainingXml(char *data, Character * s)
91 char *skill, *level, *ends, *cache;
95 struct tm end_tm, cache_tm;
100 doc = xmlReadMemory(data, strlen(data), "", NULL, 0);
101 root = xmlDocGetRootElement(doc);
102 for (n = root->children; n; n = n->next) {
103 if (n->type == XML_ELEMENT_NODE) {
104 if (!strcasecmp((const char *)n->name, "error")) {
106 } else if (!strcasecmp((const char *)n->name, "result")) {
108 for (c = n->children; c; c = c->next) {
109 if (!strcasecmp((const char *)c->name, "trainingEndTime")) {
110 ends = (char *)c->children->content;
111 } else if (!strcasecmp((const char *)c->name, "trainingTypeID")) {
112 if (c->children->content)
113 skill = (char *)c->children->content;
114 } else if (!strcasecmp((const char *)c->name, "trainingToLevel")) {
115 level = (char *)c->children->content;
118 } else if (!strcasecmp((const char *)n->name, "cachedUntil")) {
119 cache = (char *)n->children->content;
124 strptime(ends, "%Y-%m-%d %H:%M:%S", &end_tm);
125 strptime(cache, "%Y-%m-%d %H:%M:%S", &cache_tm);
126 s->skill = atoi(skill);
127 s->level = atoi(level);
135 static char *getXmlFromAPI(const char *userid, const char *apikey, const char *charid, const char *url)
137 struct curl_httppost *post = NULL;
138 struct curl_httppost *last = NULL;
148 curl_global_init(CURL_GLOBAL_ALL);
149 curl_handle = curl_easy_init();
150 curl_easy_setopt(curl_handle, CURLOPT_FAILONERROR, 1);
151 curl_easy_setopt(curl_handle, CURLOPT_URL, url);
152 curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1);
153 curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);
154 curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chr);
156 if (userid != NULL && apikey != NULL && charid != NULL) {
157 curl_formadd(&post, &last, CURLFORM_COPYNAME, "userID", CURLFORM_COPYCONTENTS, userid, CURLFORM_END);
158 curl_formadd(&post, &last, CURLFORM_COPYNAME, "apiKey", CURLFORM_COPYCONTENTS, apikey, CURLFORM_END);
159 curl_formadd(&post, &last, CURLFORM_COPYNAME, "characterID", CURLFORM_COPYCONTENTS, charid, CURLFORM_END);
161 curl_easy_setopt(curl_handle, CURLOPT_HTTPPOST, post);
164 if ((rc = curl_easy_perform(curl_handle)) != CURLE_OK) {
168 content = strdup(chr.data);
169 curl_easy_cleanup(curl_handle);
174 static void init_eve(void)
178 for (i = 0; i < MAXCHARS; i++) {
179 eveCharacters[i].charid = NULL;
180 eveCharacters[i].skillname = NULL;
181 eveCharacters[i].time = NULL;
182 eveCharacters[i].level = 0;
183 eveCharacters[i].skill = 0;
184 eveCharacters[i].delay = 0;
188 static int isCacheValid(struct tm cached)
197 gettimeofday(&tv, &tz);
198 offset = (double)(tz.tz_minuteswest * 60);
200 cache = mktime(&cached);
201 diff = difftime(cache, now);
209 static char *formatTime(struct tm *ends)
220 gettimeofday(&tv, &tz);
221 offset = (double)(tz.tz_minuteswest * 60);
223 tEnds = mktime(ends);
230 int days = (int)(diff / 60 / 60 / 24);
231 int hours = (int)((diff / 60 / 60) - (days * 24));
232 int minutes = (int)((diff / 60) - ((hours * 60) + (days * 60 * 24)));
233 int seconds = (int)(diff - ((minutes * 60) + (hours * 60 * 60) + (days * 60 * 60 * 24)));
234 char *output = malloc(100 * sizeof(char));
237 sprintf(output, "%dd, %dh, %02dm and %02ds", days, hours, minutes, seconds);
239 sprintf(output, "%dh, %02dm and %02ds", hours, minutes, seconds);
241 sprintf(output, "%02dm and %02ds", minutes, seconds);
245 char *output = strdup("Done");
250 static int file_exists(const char *filename)
254 if ((stat(filename, &fi)) == 0) {
263 static void writeSkilltree(char *content, const char *filename)
265 FILE *fp = fopen(filename, "w");
266 fwrite(content, sizeof(char), strlen(content), fp);
270 static char *getSkillname(const char *file, int skillid)
278 if (!file_exists(file)) {
279 skilltree = getXmlFromAPI(NULL, NULL, NULL, EVEURL_SKILLTREE);
280 writeSkilltree(skilltree, file);
284 doc = xmlReadFile(file, NULL, 0);
288 root = xmlDocGetRootElement(doc);
290 for (n = root->children; n; n = n->next) {
292 for (o = n->children; o; o = o->next) {
294 for (p = o->children; p; p = p->next) {
296 for (q = p->children; q; q = q->next) {
298 for (r = q->children; r; r = r->next) {
299 xmlElementPtr ele = (xmlElementPtr) r;
300 xmlAttrPtr attr = (xmlAttrPtr) ele->attributes;
302 int id, assigned = 0;
304 while (attr != NULL) {
305 if (!strcasecmp((const char *)attr->name, "typeName")) {
306 mySkill = strdup((const char *)attr->children->content);
308 } else if (!strcasecmp((const char *)attr->name, "typeID")) {
309 id = atoi((const char *)attr->children->content);
315 skill = strdup(mySkill);
332 static char *eve(char *userid, char *apikey, char *charid)
334 Character *chr = NULL;
335 const char *skillfile = "/tmp/.cesf";
345 for (i = 0; i < MAXCHARS; i++) {
346 if (eveCharacters[i].charid != NULL) {
347 if (strcasecmp(eveCharacters[i].charid, charid) == 0) {
348 chr = &eveCharacters[i];
355 if (num_chars == MAXCHARS - 1)
357 chr = &eveCharacters[num_chars];
358 chr->charid = strdup(charid);
362 if (chr->delay > 0) {
364 if (now < chr->delay) {
365 output = strdup("Server error");
371 if (isCacheValid(chr->cache)) {
372 output = (char *)malloc(200 * sizeof(char));
373 timel = strdup(formatTime(&chr->ends));
374 sprintf(output, EVE_OUTPUT_FORMAT, chr->skillname, chr->level, timel);
378 content = getXmlFromAPI(userid, apikey, charid, EVEURL_TRAINING);
379 if (content == NULL) {
380 error = strdup("Server error");
382 now += (time_t) 1800;
387 if (parseTrainingXml(content, chr)) {
388 output = (char *)malloc(200 * sizeof(char));
389 sprintf(output, "API error");
393 output = (char *)malloc(200 * sizeof(char));
394 timel = formatTime(&chr->ends);
395 skill = getSkillname(skillfile, chr->skill);
397 chr->skillname = strdup(skill);
399 sprintf(output, EVE_OUTPUT_FORMAT, chr->skillname, chr->level, timel);
406 void scan_eve(struct text_object *obj, const char *arg)
409 char *userid = (char *) malloc(20 * sizeof(char));
410 char *apikey = (char *) malloc(64 * sizeof(char));
411 char *charid = (char *) malloc(20 * sizeof(char));
413 argc = sscanf(arg, "%20s %64s %20s", userid, apikey, charid);
414 obj->data.eve.charid = charid;
415 obj->data.eve.userid = userid;
416 obj->data.eve.apikey = apikey;
421 void print_eve(struct text_object *obj, char *p, int p_max_size)
423 snprintf(p, p_max_size, "%s",
424 eve(obj->data.eve.userid,
425 obj->data.eve.apikey, obj->data.eve.charid));