X-Git-Url: http://git.wpitchoune.net/gitweb/?a=blobdiff_plain;f=trunk%2Fsrc%2Fhtml.c;fp=trunk%2Fsrc%2Fhtml.c;h=2fd1eef4407f5291cf2e6cc7845eb05822efa5eb;hb=b19be7b6db9f737f9a9a22b3079abc774cc7583c;hp=0000000000000000000000000000000000000000;hpb=b19f912053682528d7efa15aa5641a1f055f3038;p=ppastats.git diff --git a/trunk/src/html.c b/trunk/src/html.c new file mode 100644 index 0000000..2fd1eef --- /dev/null +++ b/trunk/src/html.c @@ -0,0 +1,563 @@ +/* + Copyright (C) 2011 jeanfi@gmail.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#include +#include +#include +#include +#include +#include + +#include + +#include "html.h" +#include "io.h" +#include "lp.h" +#include "lp_ws.h" +#include "ppastats.h" + +#define HTML_FOOTER \ +"
Generated by \ +ppastats
\n\ + \n\ +" + +#define HTML_PKG_TEMPLATE \ +"

N/A

\n\ +
\n\ +
\n\ +
\n\ +
\n\ +
\n\ + PPA: \n\ + \n\ + N/A/\n\ + N/A\n\ + \n\ +\n\ +
Distros:
\n\ +
Versions:
\n\ +
" + +#define HTML_VERSION_TEMPLATE \ +"\n\ + \n\ + \n\ + \n\ + \n\ +\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ +

N/A

\n\ +
Version:
\n\ +

PPA: \n\ + \n\ + N/A/N/A\n\ +

\n\ +
\n\ +
\n\ +
\n\ +
\n\ +
\n\ + Distros:\n\ +
    \n\ +
    \n\ +
    \n\ +%s" + +#define HTML_HEADER \ +"\n\ + \n\ + %s\n\ + \n\ + \n\ + \n\ +\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n" + +#define HTML_INDEX_TEMPLATE \ +"

    N/A

    \n\ +
    \n\ +
    \n\ + Packages:\n\ +
      \n\ +
      \n\ +
      \n\ +
      \n\ +
      \n\ +
      \n" + +static char *path_new(const char *dir, const char *file, const char *suffixe) +{ + char *path = malloc(strlen(dir)+1+ + strlen(file)+ + strlen(".html")+ + (suffixe ? strlen(suffixe) : 0) + + 1); + + strcpy(path, dir); + strcat(path, "/"); + strcat(path, file); + strcat(path, suffixe); + + return path; +} + +static struct json_object *date_to_json(struct tm *tm) +{ + json_object *json; + + json = json_object_new_array(); + json_object_array_add(json, json_object_new_int(tm->tm_year+1900)); + json_object_array_add(json, json_object_new_int(tm->tm_mon+1)); + json_object_array_add(json, json_object_new_int(tm->tm_mday)); + + return json; +} + +static void json_add_ddts(json_object *json, + struct daily_download_total **ddts) +{ + json_object *json_ddt, *json_ddts; + struct daily_download_total *ddt; + + json_ddts = json_object_new_array(); + json_object_object_add(json, "ddts", json_ddts); + + if (!ddts) + return ; + + while (*ddts) { + ddt = *ddts; + + json_ddt = json_object_new_object(); + json_object_object_add(json_ddt, + "value", + json_object_new_int(ddt->count)); + json_object_object_add(json_ddt, + "time", + date_to_json(&ddt->date)); + + json_object_array_add(json_ddts, json_ddt); + + ddts++; + } +} + +static json_object *distro_to_json(struct distro_stats *d) +{ + json_object *json; + + json = json_object_new_object(); + + json_object_object_add(json, + "name", + json_object_new_string(d->name)); + + json_object_object_add(json, + "count", + json_object_new_int(d->download_count)); + + json_add_ddts(json, d->ddts); + + return json; +} + +static json_object * +pkg_to_json(struct ppa_stats *ppa, struct package_stats *pkg) +{ + json_object *json, *json_versions, *json_distros, *json_distro; + struct version_stats **versions; + struct distro_stats **distros, *d; + + json = json_object_new_object(); + + json_object_object_add(json, + "ppa_name", json_object_new_string(ppa->name)); + json_object_object_add(json, + "ppa_owner", + json_object_new_string(ppa->owner)); + + json_object_object_add(json, + "name", json_object_new_string(pkg->name)); + + json_versions = json_object_new_array(); + json_object_object_add(json, "versions", json_versions); + versions = pkg->versions; + while (*versions) { + json_object_array_add + (json_versions, + json_object_new_string((*versions)->version)); + + versions++; + } + + distros = pkg->distros; + if (distros) { + json_distros = json_object_new_array(); + json_object_object_add(json, "distros", json_distros); + + while (*distros) { + d = *distros; + + if (d->download_count) { + json_distro = distro_to_json(d); + + json_object_array_add(json_distros, + json_distro); + } + + distros++; + } + } + + json_add_ddts(json, pkg->daily_download_totals); + + return json; +} + +static char *version_to_json(struct ppa_stats *ppa, + struct package_stats *pkg, + struct version_stats *ver) +{ + char *ret; + struct distro_stats **distros, *distro; + json_object *json, *json_distros, *json_distro, *json_archs, *json_arch; + struct arch_stats **archs; + + json = json_object_new_object(); + + json_object_object_add(json, + "ppa_name", json_object_new_string(ppa->name)); + json_object_object_add(json, + "ppa_owner", + json_object_new_string(ppa->owner)); + + json_object_object_add(json, + "pkg_name", json_object_new_string(pkg->name)); + + json_object_object_add(json, + "name", json_object_new_string(ver->version)); + + json_add_ddts(json, ver->daily_download_totals); + + distros = ver->distros; + json_distros = json_object_new_array(); + json_object_object_add(json, "distros", json_distros); + while (*distros) { + distro = *distros; + json_distro = json_object_new_object(); + + json_object_array_add(json_distros, json_distro); + + json_object_object_add(json_distro, + "name", + json_object_new_string(distro->name)); + + archs = distro->archs; + json_archs = json_object_new_array(); + json_object_object_add(json_distro, "archs", json_archs); + while (*archs) { + json_arch = json_object_new_object(); + + json_object_object_add + (json_arch, + "name", + json_object_new_string((*archs)->name)); + + json_object_object_add + (json_arch, + "count", + json_object_new_int((*archs)->download_count)); + + json_object_array_add(json_archs, json_arch); + archs++; + } + + distros++; + } + + ret = strdup(json_object_to_json_string(json)); + + json_object_put(json); + + return ret; +} + +static json_object *ppa_to_json(struct ppa_stats *ppa) +{ + json_object *json, *json_pkgs, *json_pkg; + struct package_stats **pkgs; + + json = json_object_new_object(); + + json_object_object_add(json, + "ppa_name", json_object_new_string(ppa->name)); + json_object_object_add(json, + "ppa_owner", + json_object_new_string(ppa->owner)); + + json_add_ddts(json, ppa->daily_download_totals); + + pkgs = ppa->packages; + json_pkgs = json_object_new_array(); + json_object_object_add(json, "packages", json_pkgs); + while (*pkgs) { + json_pkg = json_object_new_object(); + json_object_array_add(json_pkgs, json_pkg); + + json_object_object_add(json_pkg, "name", + json_object_new_string((*pkgs)->name)); + + json_object_object_add + (json_pkg, "count", + json_object_new_int((*pkgs)->download_count)); + + pkgs++; + } + + return json; +} + +static void +version_to_html(struct ppa_stats *ppa, + struct package_stats *pkg, + struct version_stats *version, + const char *dir) +{ + char *f_name, *path; + FILE *f; + + f_name = malloc(strlen(pkg->name)+1+strlen(version->version)+1); + sprintf(f_name, "%s_%s", pkg->name, version->version); + + path = path_new(dir, f_name, ".html"); + f = fopen(path, "w"); + + if (!f) { + fprintf(stderr, "ERROR: failed to open: %s\n", path); + return ; + } + + fprintf(f, HTML_VERSION_TEMPLATE, + version_to_json(ppa, pkg, version), + HTML_FOOTER); + + fclose(f); + + free(path); + free(f_name); +} + +static void +create_html(const char *path, + const char *title, + const char *body_template, + const char *script) +{ + FILE *f; + + f = fopen(path, "w"); + + if (!f) { + fprintf(stderr, "ERROR: failed to open: %s\n", path); + return ; + } + + fprintf(f, HTML_HEADER, title, script); + fputs(body_template, f); + fputs(HTML_FOOTER, f); + + fclose(f); +} + +static char *ppa_display_name(const struct ppa_stats *ppa) +{ + char *ret; + + ret = malloc(4+strlen(ppa->name)+1+strlen(ppa->owner)+1); + + sprintf(ret, "ppa:%s/%s", ppa->owner, ppa->name); + + return ret; +} + +static void +index_to_html(struct ppa_stats *ppa, const char *dir) +{ + char *path, *json_path, *dname; + json_object *json; + + json = ppa_to_json(ppa); + json_path = path_new(dir, "index", ".json"); + if (debug) + printf("DEBUG: generating %s\n", json_path); + json_object_to_file(json_path, json); + json_object_put(json); + free(json_path); + + path = path_new(dir, "index", ".html"); + dname = ppa_display_name(ppa); + create_html(path, dname, HTML_INDEX_TEMPLATE, "ppastats_ppa();"); + free(path); + free(dname); +} + +static void +pkg_to_html(struct ppa_stats *ppa, struct package_stats *pkg, const char *dir) +{ + char *path, *json_path, *script; + json_object *json; + + json_path = path_new(dir, pkg->name, ".json"); + json = pkg_to_json(ppa, pkg); + if (debug) + printf("DEBUG: generating %s\n", json_path); + json_object_to_file(json_path, json); + json_object_put(json); + free(json_path); + + path = path_new(dir, pkg->name, ".html"); + script = malloc(strlen("ppastats_pkg(\"\");")+ + strlen(pkg->name)+ + strlen(".json")+ + 1); + sprintf(script, "ppastats_pkg(\"%s%s\");", pkg->name, ".json"); + + if (debug) + printf("DEBUG: generating %s\n", path); + + create_html(path, pkg->name, HTML_PKG_TEMPLATE, script); + free(path); + free(script); +} + +static void +pkgs_to_html(struct ppa_stats *ppa, + struct package_stats **pkgs, + const char *dir) +{ + struct version_stats **versions; + + while (*pkgs) { + pkg_to_html(ppa, *pkgs, dir); + + versions = (*pkgs)->versions; + while (*versions) { + version_to_html(ppa, *pkgs, *versions, dir); + + versions++; + } + + pkgs++; + } +} + +void +ppa_to_html(const char *owner, + const char *ppa, + const char *package_status, + const char *output_dir, + const int install_static_files) +{ + struct ppa_stats *ppastats; + char *path, *f_dst; + char *css_dir, *js_dir; + int i; + static char *www_files[] + = { DEFAULT_WWW_DIR"/jquery.min.js", "js/jquery.min.js", + DEFAULT_WWW_DIR"/ppastats.js", "js/ppastats.js", + DEFAULT_WWW_DIR"/jqplot.dateAxisRenderer.min.js", + "js/jqplot.dateAxisRenderer.min.js", + DEFAULT_WWW_DIR"/jquery.jqplot.min.js", + "js/jquery.jqplot.min.js", + DEFAULT_WWW_DIR"/excanvas.js", "js/excanvas.js", + DEFAULT_WWW_DIR"/ppastats.css", "css/ppastats.css", + DEFAULT_WWW_DIR"/jquery.jqplot.min.css", + "css/jquery.jqplot.min.css" }; + + mkdirs(output_dir, 0777); + + if (install_static_files) { + css_dir = path_append(output_dir, "css"); + js_dir = path_append(output_dir, "js"); + + mkdir(css_dir, 0777); + mkdir(js_dir, 0777); + + for (i = 0; i < 7; i++) { + f_dst = path_append(output_dir, www_files[2*i+1]); + + if (debug) + printf("DEBUG: copying %s %s\n", + www_files[2*i], f_dst); + fcopy(www_files[2*i], f_dst); + + free(f_dst); + } + free(css_dir); + free(js_dir); + } + + ppastats = create_ppa_stats(owner, ppa, package_status); + + path = path_new(output_dir, "ppa", ".html"); + + pkgs_to_html(ppastats, ppastats->packages, output_dir); + + index_to_html(ppastats, output_dir); + + ppa_stats_free(ppastats); + + free(path); +}