X-Git-Url: https://git.wpitchoune.net/gitweb/?a=blobdiff_plain;f=src%2Fhtml.c;fp=src%2Fhtml.c;h=9a35c1450740ff0c866770fcda4b31de598049df;hb=0ffa32c4daf36b425e7aca8caf1d2f81809be2ee;hp=314b9a03f761c9548600d01c8222f23b05e7c7ae;hpb=57e685a242d6a8429f240a01c83587d50429b8e4;p=ppastats.git diff --git a/src/html.c b/src/html.c index 314b9a0..9a35c14 100644 --- a/src/html.c +++ b/src/html.c @@ -17,15 +17,146 @@ 02110-1301 USA */ +#include +#include #include +#include +#include +#include + +#include -#include "chart.h" #include "html.h" +#include "lp.h" #include "lp_ws.h" #include "ppastats.h" -#include -#include +enum file_copy_error { + FILE_COPY_ERROR_OPEN_SRC = 1, + FILE_COPY_ERROR_OPEN_DST, + FILE_COPY_ERROR_READ, + FILE_COPY_ERROR_WRITE, + FILE_COPY_ERROR_ALLOC_BUFFER +}; + +#define HTML_PKG_TEMPLATE \ +"\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ +

N/A

\n\ +

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

\n\ +
\n\ +
Versions:
\n\ + \n\ +" + +#define HTML_VERSION_TEMPLATE \ +"\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\ +" + +#define FCOPY_BUF_SZ 4096 +static int file_copy(FILE * src, FILE * dst) +{ + int ret = 0; + char *buf = malloc(FCOPY_BUF_SZ); + int n; + + if (!buf) + return FILE_COPY_ERROR_ALLOC_BUFFER; + + while (!ret) { + n = fread(buf, 1, FCOPY_BUF_SZ, src); + if (n) { + if (fwrite(buf, 1, n, dst) != n) + ret = FILE_COPY_ERROR_WRITE; + } else { + if (!feof(src)) + ret = FILE_COPY_ERROR_READ; + else + break; + } + } + + free(buf); + + return ret; +} + +int +fcopy(const char *src, const char *dst) +{ + FILE *fsrc, *fdst; + int ret = 0; + + if (debug) + printf("DEBUG: copy: %s to %s\n", src, dst); + + fsrc = fopen(src, "r"); + + if (fsrc) { + fdst = fopen(dst, "w+"); + + if (fdst) { + ret = file_copy(fsrc, fdst); + fclose(fdst); + } else { + ret = FILE_COPY_ERROR_OPEN_DST; + } + + fclose(fsrc); + } else { + ret = FILE_COPY_ERROR_OPEN_SRC; + } + + return ret; +} static char *get_path(const char *dir, const char *file) { @@ -42,45 +173,246 @@ static char *get_path(const char *dir, const char *file) 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 char *pkg_to_json(struct ppa_stats *ppa, struct package_stats *pkg) +{ + json_object *json, *json_versions; + char *ret; + struct version_stats **versions; + + 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++; + } + + json_add_ddts(json, pkg->daily_download_totals); + + ret = strdup(json_object_to_json_string(json)); + + json_object_put(json); + + return ret; +} + +static char *version_to_json(struct ppa_stats *ppa, + struct package_stats *pkg, + struct version_stats *ver) +{ + json_object *json; + char *ret; + + 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); + + ret = strdup(json_object_to_json_string(json)); + + json_object_put(json); + + return ret; +} + static void -packages_to_html(struct package_stats **packages, +pkg_to_html(struct ppa_stats *ppa, struct package_stats *pkg, const char *dir) +{ + char *path; + FILE *f; + char *json; + + path = get_path(dir, pkg->name); + f = fopen(path, "w"); + + if (!f) { + fprintf(stderr, "ERROR: failed to open: %s\n", path); + return ; + } + + json = pkg_to_json(ppa, pkg); + + fprintf(f, HTML_PKG_TEMPLATE, json); + + fclose(f); + + free(path); + free(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 = get_path(dir, f_name); + 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)); + + fclose(f); + + free(path); + free(f_name); +} + +static void +packages_to_html(struct ppa_stats *ppa, + struct package_stats **packages, const char *dir) { struct package_stats **cur; - struct package_stats *p; - char *path; + struct version_stats **versions; cur = packages; while (*cur) { - p = *cur; + pkg_to_html(ppa, *cur, dir); - path = get_path(dir, p->name); - generate_chart(path, p->name, p->name, - p->daily_download_totals); - free(path); + versions = (*cur)->versions; + while (*versions) { + version_to_html(ppa, *cur, *versions, dir); + + versions++; + } cur++; } } +static char *append_path(const char *odir, const char *name) +{ + char *dir; + + dir = malloc(strlen(odir)+1+strlen(name)+1); + + sprintf(dir, "%s/%s", odir, name); + + return dir; +} + void ppa_to_html(const char *owner, const char *ppa, const char *package_status, const char *output_dir) { - char *path; struct ppa_stats *ppastats; struct daily_download_total **totals; + 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"/ppastats.css", "css/ppastats.css", + DEFAULT_WWW_DIR"/jquery.jqplot.min.css", + "css/jquery.jqplot.min.css" }; + + css_dir = append_path(output_dir, "css"); + js_dir = append_path(output_dir, "js"); + + mkdir(css_dir, 0777); + mkdir(js_dir, 0777); + + for (i = 0; i < 6; i++) { + f_dst = append_path(output_dir, www_files[2*i+1]); + fcopy(www_files[2*i], f_dst); + + free(f_dst); + } ppastats = create_ppa_stats(owner, ppa, package_status); totals = ppastats->daily_download_totals; path = get_path(output_dir, "ppa"); - generate_chart(path, "PPA Statistics", ppa, totals); - free(path); - packages_to_html(ppastats->packages, output_dir); + packages_to_html(ppastats, ppastats->packages, output_dir); ppa_stats_free(ppastats); + + free(path); + free(css_dir); + free(js_dir); }