Changeset 8434


Ignore:
Timestamp:
02/27/13 14:34:31 (8 years ago)
Author:
gf
Message:

webif: Create and use private templates array.

This allows storing of additional information along with templates
data (which is const).

For now we store name hash but in the future the data that comes from
struct templates (in webif/pages.c) may need to be preprocessed
(uncompressed for example) and the abstraction in this commit makes
it easier to do such changes.

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/module-webif-tpl.c

    r8433 r8434  
    88
    99extern uint8_t cs_http_use_utf8;
    10 extern const struct template templates[];
    11 
    12 static int8_t *tplchksum;
     10
     11/* struct template templates[] that comes from webif/pages.c is recreated as
     12   struct tpl tpls[] because we need to add additional fields such as tpl_name_hash
     13   and possibly preprocess templates[] struct before using it. */
     14
     15struct tpl {
     16    uint32_t tpl_name_hash;
     17    const char *tpl_name;
     18    const char *tpl_data;
     19    const char *tpl_deps;
     20    uint32_t tpl_data_len;
     21};
     22
     23static struct tpl *tpls;
     24static int tpls_count;
     25
     26void webif_tpls_prepare(void) {
     27    int i;
     28    extern const struct template templates[];
     29    tpls_count = templates_count();
     30    if (!cs_malloc(&tpls, tpls_count * sizeof(struct tpl))) {
     31        tpls_count = 0;
     32        return;
     33    }
     34    for(i = 0; i < tpls_count; ++i) {
     35        tpls[i].tpl_name_hash = jhash(templates[i].tpl_name, strlen(templates[i].tpl_name));
     36        tpls[i].tpl_name      = templates[i].tpl_name;
     37        tpls[i].tpl_data      = templates[i].tpl_data;
     38        tpls[i].tpl_deps      = templates[i].tpl_deps;
     39        tpls[i].tpl_data_len  = templates[i].tpl_data_len;
     40    }
     41}
     42
     43void webif_tpls_free(void) {
     44    free(tpls);
     45}
    1346
    1447/* Adds a name->value-mapping or appends to it. You will get a reference back which you may freely
     
    204237char *tpl_getUnparsedTpl(const char* name, int8_t removeHeader, const char* subdir) {
    205238    int32_t i;
    206     int32_t tplcnt = tpl_count();
    207239    char *result;
    208240
     
    316348    } // if
    317349
    318     int8_t chksum = 0;
    319     for (i = strlen(name); i > 0; --i) {
    320         chksum += name[i];
    321     }
    322 
    323     for(i = 0; i < tplcnt; ++i) {
    324         const struct template *tpl = &templates[i];
    325         if (tplchksum && chksum == tplchksum[i] && name[0] == tpl->tpl_name[0]) { // basic check to save strcmp calls as we are doing this hundreds of times per page in some cases
    326             if (strcmp(name, tpl->tpl_name) == 0) break;
    327         }
    328     }
    329 
    330     if (i >= 0 && i < tplcnt) {
    331         const char *tpl_data = templates[i].tpl_data;
    332         int32_t len = strlen(tpl_data) + 1;
    333         if (!cs_malloc(&result, len)) return NULL;
    334         memcpy(result, tpl_data, len);
     350    bool found = 0;
     351    uint32_t name_hash = jhash(name, strlen(name));
     352    for(i = 0; i < tpls_count; i++) {
     353        if (tpls[i].tpl_name_hash == name_hash) {
     354            found = 1;
     355            break;
     356        }
     357    }
     358
     359    if (found) {
     360        const struct tpl *tpl = &tpls[i];
     361        if (!cs_malloc(&result, tpl->tpl_data_len + 1)) return NULL; // +1 to accomodate \0 at the end
     362        memcpy(result, tpl->tpl_data, tpl->tpl_data_len);
    335363    } else {
    336         if (!cs_malloc(&result, 1)) return NULL;
    337         result[0] = '\0';
     364        if (!cs_malloc(&result, 1)) return NULL; // Return empty string
    338365    }
    339366    return result;
     
    397424/* Saves all templates to the specified paths. Existing files will be overwritten! */
    398425int32_t tpl_saveIncludedTpls(const char *path) {
    399     int32_t tplcnt = tpl_count();
    400426    int32_t i, cnt = 0;
    401427    char tmp[256];
    402428    FILE *fp;
    403     for (i = 0; i < tplcnt; ++i) {
    404         const struct template *tpl = &templates[i];
     429    for (i = 0; i < tpls_count; ++i) {
     430        const struct tpl *tpl = &tpls[i];
    405431        if (strlen(tpl_getTplPath(tpl->tpl_name, path, tmp, 256)) > 0 && (fp = fopen(tmp,"w")) != NULL) {
    406             int32_t len = strlen(tpl->tpl_data);
    407432            if (strncmp(tpl->tpl_name, "IC", 2) != 0) {
    408                 fprintf(fp, "<!--OSCam;%lu;%s;%s;%s-->\n", crc32(0L, (unsigned char *)tpl->tpl_data, len), CS_VERSION, CS_SVN_VERSION, tpl->tpl_deps);
     433                fprintf(fp, "<!--OSCam;%lu;%s;%s;%s-->\n", crc32(0L, (unsigned char *)tpl->tpl_data, tpl->tpl_data_len), CS_VERSION, CS_SVN_VERSION, tpl->tpl_deps);
    409434            }
    410             fwrite(tpl->tpl_data, sizeof(char), len, fp);
     435            fwrite(tpl->tpl_data, tpl->tpl_data_len, 1, fp);
    411436            fclose (fp);
    412437            ++cnt;
     
    420445    char dirpath[255] = "\0";
    421446    snprintf(dirpath, 255, "%s%s", cfg.http_tpl ? cfg.http_tpl : "", subdir);
    422     int32_t i, tplcnt = tpl_count();
     447    int32_t i;
    423448    char path[255];
    424     for(i = 0; i < tplcnt; ++i) {
    425         const struct template *tpl = &templates[i];
     449    for(i = 0; i < tpls_count; ++i) {
     450        const struct tpl *tpl = &tpls[i];
    426451        if (strncmp(tpl->tpl_name, "IC", 2) != 0 && strlen(tpl_getTplPath(tpl->tpl_name, dirpath, path, 255)) > 0 && file_exists(path)) {
    427452            int8_t error = 1;
    428453            char *tplorg = tpl_getUnparsedTpl(tpl->tpl_name, 0, subdir);
    429             unsigned long checksum = 0, curchecksum = crc32(0L, (unsigned char*)tpl->tpl_data, strlen(tpl->tpl_data));
     454            unsigned long checksum = 0, curchecksum = crc32(0L, (unsigned char*)tpl->tpl_data, tpl->tpl_data_len);
    430455            char *ifdefs = "", *pch1 = strstr(tplorg,"<!--OSCam");
    431456            if (pch1 != NULL) {
     
    487512}
    488513
    489 /* Create some easy checksums (but they should be sufficient for our needs) in order to speedup lookup of templates. */
    490 void prepareTplChecksums(void) {
    491     int32_t i, j;
    492     int32_t tplcnt = tpl_count();
    493     if (!cs_malloc(&tplchksum, tplcnt))
    494         return;
    495     for(i = 0; i < tplcnt; ++i) {
    496         tplchksum[i] = 0;
    497         const char *tpl_name = templates[i].tpl_name;
    498         for(j = strlen(tpl_name); j > 0; --j) {
    499             tplchksum[i] += tpl_name[j];
    500         }
    501     }
    502 }
    503 
    504514/* Helper function for urldecode.*/
    505515static int32_t x2i(int32_t i) {
  • trunk/module-webif-tpl.h

    r8421 r8434  
    11#ifndef MODULE_WEBIF_TPL_H_
    22#define MODULE_WEBIF_TPL_H_
     3
     4#ifdef WEBIF
    35
    46/* Templates: Adds a variable. The variable can be used as often as wanted. */
     
    2628};
    2729
     30void    webif_tpls_prepare(void);
     31void    webif_tpls_free(void);
     32
    2833struct templatevars *tpl_create(void);
    2934void                 tpl_clear(struct templatevars *vars);
     
    4550void    tpl_checkDiskRevisions(void);
    4651
    47 void    prepareTplChecksums(void);
    48 
    4952char    *urlencode(struct templatevars *vars, char *str);
    5053char    *xml_encode(struct templatevars *vars, char *chartoencode);
    5154char    *sec2timeformat(struct templatevars *vars, int32_t seconds);
    5255
     56#else
     57static inline void webif_tpls_free(void) { return; }
    5358#endif
     59
     60#endif
  • trunk/module-webif.c

    r8432 r8434  
    52055205    /* Prepare base64 decoding array */
    52065206    b64prepare();
    5207     prepareTplChecksums();
     5207    webif_tpls_prepare();
    52085208
    52095209    tpl_checkDiskRevisions();
  • trunk/oscam-string.c

    r8421 r8434  
    429429}
    430430
     431// https://en.wikipedia.org/wiki/Jenkins_hash_function
     432uint32_t jhash(const char *key, size_t len) {
     433    uint32_t hash, i;
     434    for (hash = i = 0; i < len; i++) {
     435        hash += key[i];
     436        hash += (hash << 10);
     437        hash ^= (hash >> 6);
     438    }
     439    hash += (hash << 3);
     440    hash ^= (hash >> 11);
     441    hash += (hash << 15);
     442    return hash;
     443}
     444
    431445/* Converts a char to it's hex representation. See char_to_hex on how to use it. */
    432446char to_hex(char code)
  • trunk/oscam-string.h

    r8421 r8434  
    3636
    3737unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned int len);
     38uint32_t jhash(const char *key, size_t len);
    3839
    3940char to_hex(char code);
  • trunk/oscam.c

    r8395 r8434  
    1717#include "module-stat.h"
    1818#include "module-webif.h"
     19#include "module-webif-tpl.h"
    1920#include "module-cw-cycle-check.h"
    2021#include "oscam-chk.h"
     
    14731474        unlink(oscam_pidfile);
    14741475
     1476    webif_tpls_free();
    14751477    init_free_userdb(cfg.account);
    14761478    cfg.account = NULL;
  • trunk/webif/pages_gen.c

    r8427 r8434  
    4343        char file[128];
    4444        char deps[256];
     45        uint32_t data_len;
    4546        enum { TXT, BIN } type;
    4647    } data[MAX_TEMPLATES];
     
    204205}
    205206
    206 static void parse_deps(int tpl_idx) {
     207static void print_template(int tpl_idx) {
    207208    static bool ifdef_open = 0;
    208209    char *prev_deps = "";
     
    240241    }
    241242
    242     fprintf(output_file, "\t{ .tpl_name=\"%s\", .tpl_data=%s%s, .tpl_deps=\"%s\" },\n",
     243    fprintf(output_file, "\t{ .tpl_name=\"%s\", .tpl_data=%s%s, .tpl_deps=\"%s\", .tpl_data_len=%u },\n",
    243244        ident,
    244245        templates.data[tpl_idx].type == TXT ? "TPL" : "", ident,
    245         deps);
     246        deps,
     247        templates.data[tpl_idx].data_len
     248    );
    246249
    247250    if (ifdef_open && strcmp(deps, next_deps) != 0) {
     
    251254}
    252255
    253 static void dump_text(char *ident, uint8_t *buf, size_t buf_len) {
     256static uint32_t dump_text(char *ident, uint8_t *buf, size_t buf_len) {
    254257    int i;
    255258    fprintf(output_file, "#define TPL%s \\\n\"", ident);
     
    268271    }
    269272    fprintf(output_file, "\"\n\n");
     273    return buf_len;
    270274}
    271275
     
    282286}
    283287
    284 static void dump_base64(char *ident, char *mime, uint8_t *buf, size_t buf_len) {
     288static uint32_t dump_base64(char *ident, char *mime, uint8_t *buf, size_t buf_len) {
     289    char tpl_type[32];
    285290    size_t b64_buf_len = buf_len * 4 + 16;
    286291    uint8_t *b64_buf = malloc(b64_buf_len);
     
    288293        die("%s: can't alloc %zd bytes\n", __func__, b64_buf_len);
    289294    int i, b64_len = b64_encode(buf, buf_len, b64_buf, b64_buf_len);
    290     fprintf(output_file, "#define %s \"data:%s;base64,\\\n", ident, mime);
     295    snprintf(tpl_type, sizeof(tpl_type), "data:%s;base64,", mime);
     296    fprintf(output_file, "#define %s \"%s\\\n", ident, tpl_type);
    291297    for (i = 0; i < b64_len; i++) {
    292298        if (i && i % 76 == 0)
     
    296302    fprintf(output_file, "\"\n\n");
    297303    free(b64_buf);
     304    return strlen(tpl_type) + b64_len;
    298305}
    299306
     
    311318    fprintf(output_file, "  char *tpl_data;\n");
    312319    fprintf(output_file, "  char *tpl_deps;\n");
     320    fprintf(output_file, "  uint32_t tpl_data_len;\n");
    313321    fprintf(output_file, "};\n");
    314322    fprintf(output_file, "\n");
    315     fprintf(output_file, "int32_t tpl_count(void);\n");
     323    fprintf(output_file, "int32_t templates_count(void);\n");
    316324    fprintf(output_file, "\n");
    317325    fprintf(output_file, "#endif\n");
     
    328336    for (i = 0; i < templates.num; i++) {
    329337        uint8_t *buf;
    330         size_t buf_len;
     338        size_t buf_len, data_len = 0;
    331339        readfile(templates.data[i].file, &buf, &buf_len);
    332340        switch (templates.data[i].type) {
    333             case TXT: dump_text(templates.data[i].ident, buf, buf_len); break;
    334             case BIN: dump_base64(templates.data[i].ident, get_mime(templates.data[i].file), buf, buf_len); break;
     341            case TXT: data_len = dump_text(templates.data[i].ident, buf, buf_len); break;
     342            case BIN: data_len = dump_base64(templates.data[i].ident, get_mime(templates.data[i].file), buf, buf_len); break;
    335343        }
    336344        free(buf);
     345        templates.data[i].data_len = data_len;
    337346    }
    338347
    339348    fprintf(output_file, "const struct template templates[] = {\n");
    340349    for (i = 0; i < templates.num; i++) {
    341         parse_deps(i);
     350        print_template(i);
    342351    }
    343352    fprintf(output_file, "};\n");
    344353    fprintf(output_file, "\n");
    345     fprintf(output_file, "int32_t tpl_count(void) { return sizeof(templates) / sizeof(struct template); }\n");
     354    fprintf(output_file, "int32_t templates_count(void) { return sizeof(templates) / sizeof(struct template); }\n");
    346355    fprintf(output_file, "\n");
    347356    fprintf(output_file, "#endif\n");
Note: See TracChangeset for help on using the changeset viewer.