2 * Copyright (C) 2011-2014 jeanfi@gmail.com
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 #define _(String) gettext(String)
41 /** Default ws.size value for the getPublishedBinaries request. */
42 static const int DEFAULT_WS_SIZE = 150;
44 static const char *QUERY_GET_DOWNLOAD_COUNT = "?ws.op=getDownloadCount";
46 QUERY_GET_DAILY_DOWNLOAD_TOTALS = "?ws.op=getDailyDownloadTotals";
48 static json_object *get_json_object(const char *url)
50 json_object *obj = NULL;
53 body = get_url_content(url, 0);
56 obj = json_tokener_parse(body);
66 static char *get_bpph_list_cache_key(const char *archive_url)
70 key = malloc(strlen(archive_url + 7) + strlen("/bpph") + 1);
71 sprintf(key, "%s/bpph", archive_url + 7);
76 static char *get_ddts_list_cache_key(const char *url)
80 key = malloc(strlen(url + 7) + strlen("/ddts") + 1);
81 sprintf(key, "%s/ddts", url + 7);
86 static struct bpph **get_bpph_list_from_cache(const char *key)
92 content = fcache_get(key);
96 json = json_tokener_parse(content);
100 list = json_object_to_bpph_list(json);
102 json_object_put(json);
108 static char *get_last_creation_date(struct bpph **list)
116 for (cur = list; *cur; cur++) {
117 t = (*cur)->date_created;
123 return time_to_ISO8601_time(&last);
129 * 'archive_url': LP URL of the archive.
130 * 'size': size of the reply array. Between 1-300, else default value is used.
132 static char *create_query_get_bpph(const char *archive_url,
136 static const char *default_opt = "?ws.op=getPublishedBinaries&ws.size=";
137 static const char *status_opt = "&status=";
141 if (size < 1 || size > 300)
142 size = DEFAULT_WS_SIZE;
144 n = strlen(archive_url) + strlen(default_opt) + 3 + 1;
147 n += strlen(status_opt) + strlen(status);
150 sprintf(url, "%s%s%d", archive_url, default_opt, size);
153 strcat(url, status_opt);
160 struct bpph **get_bpph_list(const char *archive_url,
161 const char *pkg_status,
164 char *url, *key, *tmp;
165 struct bpph **result;
166 struct json_object *o, *bpph_json, *o_next;
170 url = create_query_get_bpph(archive_url, pkg_status, ws_size);
172 key = get_bpph_list_cache_key(archive_url);
174 result = get_bpph_list_from_cache(key);
177 date = get_last_creation_date(result);
180 tmp = malloc(strlen(url)
181 + strlen("&created_since_date=")
184 strcat(tmp, "&created_since_date=");
196 o = get_json_object(url);
205 result = bpph_list_append_list(result,
206 json_object_to_bpph_list(o));
208 o_next = json_object_object_get(o, "next_collection_link");
211 url = strdup(json_object_get_string(o_next));
217 bpph_json = bpph_list_to_json(result);
218 fcache_put(key, json_object_to_json_string(bpph_json));
219 json_object_put(bpph_json);
227 int get_download_count(const char *archive_url)
229 int n = strlen(archive_url) + strlen(QUERY_GET_DOWNLOAD_COUNT) + 1;
230 char *url = malloc(n);
234 strcpy(url, archive_url);
235 strcat(url, QUERY_GET_DOWNLOAD_COUNT);
237 obj = get_json_object(url);
243 result = json_object_get_int(obj);
245 json_object_put(obj);
250 const struct distro_arch_series *get_distro_arch_series(const char *url)
253 const struct distro_arch_series *distro;
256 distro = cache_get(url);
258 return (struct distro_arch_series *)distro;
260 content = get_url_content(url, 1);
265 obj = json_tokener_parse(content);
272 distro = json_object_to_distro_arch_series(obj);
274 json_object_put(obj);
276 cache_put(url, distro, (void (*)(void *))&distro_arch_series_free);
281 const struct distro_series *get_distro_series(const char *url)
284 const struct distro_series *distro;
287 distro = cache_get(url);
289 return (struct distro_series *)distro;
291 content = get_url_content(url, 1);
296 obj = json_tokener_parse(content);
303 distro = json_object_to_distro_series(obj);
305 json_object_put(obj);
307 cache_put(url, distro, (void (*)(void *))&distro_series_free);
313 Convert ddts older than 4 weeks to the same JSON representation than
314 the LP one. Newer ddts are not stored in the cache because the data
315 may change during following days. It avoids to miss downloads which
316 are not yet taken in consideration by LP.
318 static json_object *ddts_to_json_for_cache(struct daily_download_total **ddts)
321 struct daily_download_total *ddt;
327 j_ddts = json_object_new_object();
329 tv = malloc(sizeof(struct timeval));
330 gettimeofday(tv, NULL);
332 while (ddts && *ddts) {
335 t = mktime(&(ddt->date));
337 d = difftime(tv->tv_sec, t);
339 if (d > 4 * 7 * 24 * 60 * 60) { /* older than 4 weeks */
340 date = tm_to_ISO8601_date(&ddt->date);
341 json_object_object_add(j_ddts,
343 json_object_new_int(ddt->count));
355 char *create_ddts_query(const char *binary_url, time_t st, time_t et)
361 sdate = time_to_ISO8601_date(&st);
363 q = malloc(strlen(binary_url)
364 + strlen(QUERY_GET_DAILY_DOWNLOAD_TOTALS)
365 + strlen("&start_date=YYYY-MM-DD")
366 + strlen("&end_date=YYYY-MM-DD")
368 strcpy(q, binary_url);
369 strcat(q, QUERY_GET_DAILY_DOWNLOAD_TOTALS);
370 strcat(q, "&start_date=");
374 edate = time_to_ISO8601_date(&et);
375 strcat(q, "&end_date=");
382 q = malloc(strlen(binary_url)
383 + strlen(QUERY_GET_DAILY_DOWNLOAD_TOTALS)
385 strcpy(q, binary_url);
386 strcat(q, QUERY_GET_DAILY_DOWNLOAD_TOTALS);
392 static struct daily_download_total **retrieve_ddts(const char *binary_url,
397 struct daily_download_total **ddts, **tmp;
400 url = create_ddts_query(binary_url, date_since, 0);
401 json = get_json_object(url);
405 ddts = json_object_to_daily_download_totals(json);
406 json_object_put(json);
411 while (date_since < crt) {
412 url = create_ddts_query(binary_url, date_since, date_since);
413 json = get_json_object(url);
419 tmp = json_object_to_daily_download_totals(json);
420 json_object_put(json);
421 ddts = ddts_merge(ddts, tmp);
424 date_since = date_since + 24 * 60 * 60; /* +1 day */
426 url = create_ddts_query(binary_url, date_since, 0);
427 json = get_json_object(url);
431 tmp = json_object_to_daily_download_totals(json);
432 json_object_put(json);
433 ddts = ddts_merge(ddts, tmp);
443 struct daily_download_total **get_daily_download_totals(const char *binary_url,
447 json_object *j_ddts, *json;
448 struct daily_download_total **retrieved_ddts = NULL;
449 struct daily_download_total **cached_ddts;
450 struct daily_download_total **ddts;
453 key = get_ddts_list_cache_key(binary_url);
455 content = fcache_get(key);
457 json = json_tokener_parse(content);
464 cached_ddts = json_object_to_daily_download_totals(json);
465 json_object_put(json);
466 last_t = ddts_get_last_date(cached_ddts);
473 retrieved_ddts = retrieve_ddts(binary_url, last_t);
475 retrieved_ddts = retrieve_ddts(binary_url, date_created);
477 ddts = ddts_merge(cached_ddts, retrieved_ddts);
480 j_ddts = ddts_to_json_for_cache(ddts);
481 fcache_put(key, json_object_get_string(j_ddts));
482 json_object_put(j_ddts);
486 if (ddts != cached_ddts)
487 daily_download_total_list_free(cached_ddts);
488 daily_download_total_list_free(retrieved_ddts);