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 json_object_object_get_ex(o, "next_collection_link", &o_next);
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,
415 json = get_json_object(url);
421 tmp = json_object_to_daily_download_totals(json);
422 json_object_put(json);
423 ddts = ddts_merge(ddts, tmp);
426 date_since = date_since + 24 * 60 * 60; /* +1 day */
428 url = create_ddts_query(binary_url, date_since, 0);
429 json = get_json_object(url);
433 tmp = json_object_to_daily_download_totals
435 json_object_put(json);
436 ddts = ddts_merge(ddts, tmp);
446 struct daily_download_total **get_daily_download_totals(const char *binary_url,
450 json_object *j_ddts, *json;
451 struct daily_download_total **retrieved_ddts = NULL;
452 struct daily_download_total **cached_ddts;
453 struct daily_download_total **ddts;
456 key = get_ddts_list_cache_key(binary_url);
458 content = fcache_get(key);
460 json = json_tokener_parse(content);
467 cached_ddts = json_object_to_daily_download_totals(json);
468 json_object_put(json);
469 last_t = ddts_get_last_date(cached_ddts);
476 retrieved_ddts = retrieve_ddts(binary_url, last_t);
478 retrieved_ddts = retrieve_ddts(binary_url, date_created);
480 ddts = ddts_merge(cached_ddts, retrieved_ddts);
483 j_ddts = ddts_to_json_for_cache(ddts);
484 fcache_put(key, json_object_get_string(j_ddts));
485 json_object_put(j_ddts);
489 if (ddts != cached_ddts)
490 daily_download_total_list_free(cached_ddts);
491 daily_download_total_list_free(retrieved_ddts);