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)
28 #include <sys/types.h>
30 #include <json/json.h>
40 static const char *footer;
41 static const char *ppa_body;
42 static const char *pkg_body;
43 static const char *pkg_version_body;
44 static const char *header;
46 static char *path_new(const char *dir, const char *file, const char *suffixe)
50 /* [dir]/[file][suffixe] */
51 path = malloc(strlen(dir)+1+
53 (suffixe ? strlen(suffixe) : 0) +
59 strcat(path, suffixe);
64 static char *get_header(const char *title, const char *script)
70 path = DEFAULT_WWW_DIR"/header.tpl";
71 header = file_get_content(path);
74 log_err("Failed to read header template: %s", path);
81 res = strrep(tmp, "@SCRIPT@", script);
87 res = strrep(tmp, "@TITLE@", title);
95 static const char *get_footer()
100 path = DEFAULT_WWW_DIR"/footer.tpl";
101 footer = file_get_content(path);
104 log_err("Failed to read footer template: %s", path);
110 static const char *get_pkg_version_body()
114 if (!pkg_version_body) {
115 path = DEFAULT_WWW_DIR"/pkg_version.tpl";
116 pkg_version_body = file_get_content(path);
118 if (!pkg_version_body)
119 log_err("Failed to read package version template: %s",
123 return pkg_version_body;
125 static const char *get_ppa_body()
130 path = DEFAULT_WWW_DIR"/ppa.tpl";
131 ppa_body = file_get_content(path);
134 log_err("Failed to read PPA template: %s", path);
140 static const char *get_pkg_body()
145 path = DEFAULT_WWW_DIR"/pkg.tpl";
146 pkg_body = file_get_content(path);
149 log_err("Failed to read package template: %s", path);
155 static struct json_object *date_to_json(struct tm *tm)
159 json = json_object_new_array();
160 json_object_array_add(json, json_object_new_int(tm->tm_year+1900));
161 json_object_array_add(json, json_object_new_int(tm->tm_mon+1));
162 json_object_array_add(json, json_object_new_int(tm->tm_mday));
167 static void json_add_ddts(json_object *json,
168 struct daily_download_total **ddts)
170 json_object *json_ddt, *json_ddts;
171 struct daily_download_total *ddt;
173 json_ddts = json_object_new_array();
174 json_object_object_add(json, "ddts", json_ddts);
182 json_ddt = json_object_new_object();
183 json_object_object_add(json_ddt,
185 json_object_new_int(ddt->count));
186 json_object_object_add(json_ddt,
188 date_to_json(&ddt->date));
190 json_object_array_add(json_ddts, json_ddt);
196 static json_object *distro_to_json(struct distro_stats *d)
200 json = json_object_new_object();
202 json_object_object_add(json,
204 json_object_new_string(d->name));
206 json_object_object_add(json,
208 json_object_new_int(d->download_count));
210 json_add_ddts(json, d->ddts);
216 pkg_to_json(struct ppa_stats *ppa, struct package_stats *pkg)
218 json_object *json, *json_versions, *json_distros, *json_distro;
219 struct version_stats **versions;
220 struct distro_stats **distros, *d;
222 json = json_object_new_object();
224 json_object_object_add(json,
225 "ppa_name", json_object_new_string(ppa->name));
226 json_object_object_add(json,
228 json_object_new_string(ppa->owner));
230 json_object_object_add(json,
231 "name", json_object_new_string(pkg->name));
233 json_versions = json_object_new_array();
234 json_object_object_add(json, "versions", json_versions);
235 versions = pkg->versions;
237 json_object_array_add
239 json_object_new_string((*versions)->version));
244 distros = pkg->distros;
246 json_distros = json_object_new_array();
247 json_object_object_add(json, "distros", json_distros);
252 if (d->download_count) {
253 json_distro = distro_to_json(d);
255 json_object_array_add(json_distros,
263 json_add_ddts(json, pkg->daily_download_totals);
268 static char *version_to_json(struct ppa_stats *ppa,
269 struct package_stats *pkg,
270 struct version_stats *ver)
273 struct distro_stats **distros, *distro;
274 json_object *json, *json_distros, *json_distro, *json_archs, *json_arch;
275 struct arch_stats **archs;
277 json = json_object_new_object();
279 json_object_object_add(json,
280 "ppa_name", json_object_new_string(ppa->name));
281 json_object_object_add(json,
283 json_object_new_string(ppa->owner));
285 json_object_object_add(json,
286 "pkg_name", json_object_new_string(pkg->name));
288 json_object_object_add(json,
289 "name", json_object_new_string(ver->version));
291 json_add_ddts(json, ver->daily_download_totals);
293 distros = ver->distros;
294 json_distros = json_object_new_array();
295 json_object_object_add(json, "distros", json_distros);
298 json_distro = json_object_new_object();
300 json_object_array_add(json_distros, json_distro);
302 json_object_object_add(json_distro,
304 json_object_new_string(distro->name));
306 archs = distro->archs;
307 json_archs = json_object_new_array();
308 json_object_object_add(json_distro, "archs", json_archs);
310 json_arch = json_object_new_object();
312 json_object_object_add
315 json_object_new_string((*archs)->name));
317 json_object_object_add
320 json_object_new_int((*archs)->download_count));
322 json_object_array_add(json_archs, json_arch);
329 ret = strdup(json_object_to_json_string(json));
331 json_object_put(json);
336 static json_object *ppa_to_json(struct ppa_stats *ppa)
338 json_object *json, *json_pkgs, *json_pkg;
339 struct package_stats **pkgs;
341 json = json_object_new_object();
343 json_object_object_add(json,
344 "ppa_name", json_object_new_string(ppa->name));
345 json_object_object_add(json,
347 json_object_new_string(ppa->owner));
349 json_add_ddts(json, ppa->daily_download_totals);
351 pkgs = ppa->packages;
352 json_pkgs = json_object_new_array();
353 json_object_object_add(json, "packages", json_pkgs);
355 json_pkg = json_object_new_object();
356 json_object_array_add(json_pkgs, json_pkg);
358 json_object_object_add(json_pkg, "name",
359 json_object_new_string((*pkgs)->name));
361 json_object_object_add
363 json_object_new_int((*pkgs)->download_count));
372 create_html(const char *path,
374 const char *body_template,
383 header = get_header(title, script);
385 log_err(_("Failed to get the header template"));
389 f = fopen(path, "w");
392 log_err(_("Failed to open: %s"), path);
397 fputs(body_template, f);
399 footer = get_footer();
411 static char *ppa_display_name(const struct ppa_stats *ppa)
415 ret = malloc(4+strlen(ppa->name)+1+strlen(ppa->owner)+1);
417 sprintf(ret, "ppa:%s/%s", ppa->owner, ppa->name);
423 index_to_html(struct ppa_stats *ppa, const char *dir)
425 char *path, *json_path, *dname;
429 body = get_ppa_body();
431 log_err("Failed to create PPA page");
435 json = ppa_to_json(ppa);
436 json_path = path_new(dir, "index", ".json");
438 log_debug(_("generating %s"), json_path);
439 json_object_to_file(json_path, json);
440 json_object_put(json);
443 path = path_new(dir, "index", ".html");
444 dname = ppa_display_name(ppa);
445 create_html(path, dname, body, "ppastats_ppa();");
451 version_to_html(struct ppa_stats *ppa,
452 struct package_stats *pkg,
453 struct version_stats *version,
458 const char *script_tpl;
461 body = get_pkg_version_body();
463 log_err("Failed to create package version page");
467 json = version_to_json(ppa, pkg, version);
469 log_err("Failed to create package version page");
473 f_name = malloc(strlen(pkg->name)+1+strlen(version->version)+1);
474 sprintf(f_name, "%s_%s", pkg->name, version->version);
476 path = path_new(dir, f_name, ".html");
478 script_tpl = "var data = %s;\n ppastats_ver();";
479 script = malloc(strlen(script_tpl) - 2 + strlen(json) + 1);
480 sprintf(script, script_tpl, json);
482 create_html(path, f_name, body, script);
490 pkg_to_html(struct ppa_stats *ppa, struct package_stats *pkg, const char *dir)
492 char *path, *json_path, *script;
496 body = get_pkg_body();
498 log_err("Failed to create package page: %s", pkg->name);
502 json_path = path_new(dir, pkg->name, ".json");
503 json = pkg_to_json(ppa, pkg);
504 log_debug(_("Generating %s"), json_path);
506 json_object_to_file(json_path, json);
507 json_object_put(json);
510 path = path_new(dir, pkg->name, ".html");
511 script = malloc(strlen("ppastats_pkg(\"\");")+
515 sprintf(script, "ppastats_pkg(\"%s%s\");", pkg->name, ".json");
517 log_debug(_("Generating %s"), path);
519 create_html(path, pkg->name, body, script);
525 pkgs_to_html(struct ppa_stats *ppa,
526 struct package_stats **pkgs,
529 struct version_stats **versions;
532 pkg_to_html(ppa, *pkgs, dir);
534 versions = (*pkgs)->versions;
536 version_to_html(ppa, *pkgs, *versions, dir);
546 ppa_to_html(const char *owner,
548 const char *package_status,
549 const char *output_dir,
550 const int install_static_files,
553 struct ppa_stats *ppastats;
555 char *css_dir, *js_dir;
557 static char *www_files[]
558 = { DEFAULT_WWW_DIR"/jquery.min.js", "js/jquery.min.js",
559 DEFAULT_WWW_DIR"/ppastats.js", "js/ppastats.js",
560 DEFAULT_WWW_DIR"/jqplot.dateAxisRenderer.min.js",
561 "js/jqplot.dateAxisRenderer.min.js",
562 DEFAULT_WWW_DIR"/jquery.jqplot.min.js",
563 "js/jquery.jqplot.min.js",
564 DEFAULT_WWW_DIR"/excanvas.js", "js/excanvas.js",
565 DEFAULT_WWW_DIR"/ppastats.css", "css/ppastats.css",
566 DEFAULT_WWW_DIR"/wpitchoune.css", "css/wpitchoune.css",
567 DEFAULT_WWW_DIR"/jquery.jqplot.min.css",
568 "css/jquery.jqplot.min.css" };
570 mkdirs(output_dir, 0777);
572 if (install_static_files) {
573 css_dir = path_append(output_dir, "css");
574 js_dir = path_append(output_dir, "js");
576 mkdir(css_dir, 0777);
579 for (i = 0; i < 8; i++) {
580 f_dst = path_append(output_dir, www_files[2*i+1]);
582 log_debug(_("Copying %s %s"), www_files[2*i], f_dst);
583 fcopy(www_files[2*i], f_dst);
591 ppastats = create_ppa_stats(owner, ppa, package_status, ws_size);
593 path = path_new(output_dir, "ppa", ".html");
595 pkgs_to_html(ppastats, ppastats->packages, output_dir);
597 index_to_html(ppastats, output_dir);
599 ppa_stats_free(ppastats);