Changeset 8445


Ignore:
Timestamp:
03/01/13 11:56:47 (8 years ago)
Author:
gf
Message:

webif: Do not store images in templates array as base64.

Save a little bit of binary size.

This commit introduces no user visible changes.

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/globals.h

    r8444 r8445  
    232232//checking if (X) free(X) unneccessary since freeing a null pointer doesnt do anything
    233233#define NULLFREE(X) {if (X) {void *tmpX=X; X=NULL; free(tmpX); }}
    234 
    235 #define BASE64_LENGTH(inlen) ((((inlen) + 2) / 3) * 4) 
    236234
    237235/* ===========================
  • trunk/module-ghttp.c

    r8341 r8445  
    4040 
    4141  return 0;
    42 }
    43 
    44 
    45 static inline unsigned char to_uchar (char ch)
    46 {
    47   return ch;
    48 }
    49 
    50 void base64_encode(const char *in, size_t inlen, char *out, size_t outlen)
    51 {
    52   static const char b64str[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    53   while (inlen && outlen) {
    54     *out++ = b64str[(to_uchar (in[0]) >> 2) & 0x3f];
    55     if (!--outlen) break;
    56     *out++ = b64str[((to_uchar (in[0]) << 4) + (--inlen ? to_uchar (in[1]) >> 4 : 0)) & 0x3f];
    57     if (!--outlen) break;
    58     *out++ = (inlen ? b64str[((to_uchar (in[1]) << 2) + (--inlen ? to_uchar (in[2]) >> 6 : 0)) & 0x3f] : '=');
    59     if (!--outlen) break;
    60     *out++ = inlen ? b64str[to_uchar (in[2]) & 0x3f] : '=';
    61     if (!--outlen) break;
    62     if (inlen) inlen--;
    63     if (inlen) in += 3;
    64 
    65     if (outlen) *out = '\0';
    66   }
    67 }
    68 
    69 size_t b64encode(const char *in, size_t inlen, char **out)
    70 {
    71   size_t outlen = 1 + BASE64_LENGTH (inlen);
    72   if (inlen > outlen) {
    73     *out = NULL;
    74     return 0;
    75   }
    76   if(!cs_malloc(out, outlen)) return -1;
    77   base64_encode (in, inlen, *out, outlen);
    78   return outlen - 1;
    7942}
    8043
  • trunk/module-webif-tpl.c

    r8438 r8445  
    1818    const char *tpl_data;
    1919    const char *tpl_deps;
     20    char *extra_data;
    2021    uint32_t tpl_data_len;
     22    uint8_t tpl_type;
    2123};
    2224
    2325static struct tpl *tpls;
    2426static int tpls_count;
     27
     28static void tpl_init_base64(struct tpl *tpl) {
     29    // The rest of OSCam expects images to be base64 encoded and contain mime type.
     30    if (!template_is_image(tpl->tpl_type))
     31        return;
     32    size_t b64_buf_len = 32 + BASE64_LENGTH(tpl->tpl_data_len); // Enough for base64 and 32 for header (data:XXX;base64,)
     33    char *b64_buf;
     34    if (!cs_malloc(&b64_buf, b64_buf_len)) {
     35        tpl->tpl_data = "";
     36        tpl->tpl_data_len = 0;
     37        return;
     38    }
     39    int hdr_len = snprintf(b64_buf, b64_buf_len, "data:%s;base64,", template_get_mimetype(tpl->tpl_type));
     40    base64_encode(tpl->tpl_data, tpl->tpl_data_len, b64_buf + hdr_len, b64_buf_len - hdr_len);
     41    tpl->tpl_data = tpl->extra_data = b64_buf;
     42    tpl->tpl_data_len = strlen(b64_buf);
     43}
    2544
    2645void webif_tpls_prepare(void) {
     
    3857        tpls[i].tpl_deps      = templates[i].tpl_deps;
    3958        tpls[i].tpl_data_len  = templates[i].tpl_data_len;
     59        tpls[i].tpl_type      = templates[i].tpl_type;
     60        tpl_init_base64(&tpls[i]);
    4061    }
    4162}
    4263
    4364void webif_tpls_free(void) {
     65    int32_t i;
     66    for(i = 0; i < tpls_count; ++i) {
     67        free(tpls[i].extra_data);
     68    }
    4469    free(tpls);
    4570}
  • trunk/oscam-string.c

    r8434 r8445  
    463463    }
    464464}
     465
     466static inline unsigned char to_uchar(char ch) {
     467    return ch;
     468}
     469
     470void base64_encode(const char *in, size_t inlen, char *out, size_t outlen)
     471{
     472    static const char b64str[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
     473    while (inlen && outlen) {
     474        *out++ = b64str[(to_uchar (in[0]) >> 2) & 0x3f];
     475        if (!--outlen) break;
     476        *out++ = b64str[((to_uchar (in[0]) << 4) + (--inlen ? to_uchar (in[1]) >> 4 : 0)) & 0x3f];
     477        if (!--outlen) break;
     478        *out++ = (inlen ? b64str[((to_uchar (in[1]) << 2) + (--inlen ? to_uchar (in[2]) >> 6 : 0)) & 0x3f] : '=');
     479        if (!--outlen) break;
     480        *out++ = inlen ? b64str[to_uchar (in[2]) & 0x3f] : '=';
     481        if (!--outlen) break;
     482        if (inlen) inlen--;
     483        if (inlen) in += 3;
     484        if (outlen) *out = '\0';
     485    }
     486}
     487
     488size_t b64encode(const char *in, size_t inlen, char **out)
     489{
     490    size_t outlen = 1 + BASE64_LENGTH(inlen);
     491    if (inlen > outlen) {
     492        *out = NULL;
     493        return 0;
     494    }
     495    if (!cs_malloc(out, outlen))
     496        return -1;
     497    base64_encode(in, inlen, *out, outlen);
     498    return outlen - 1;
     499}
  • trunk/oscam-string.h

    r8434 r8445  
    4141void char_to_hex(const unsigned char *p_array, uint32_t p_array_len, unsigned char *result);
    4242
     43#define BASE64_LENGTH(inlen) ((((inlen) + 2) / 3) * 4)
     44void base64_encode(const char *in, size_t inlen, char *out, size_t outlen);
     45size_t b64encode(const char *in, size_t inlen, char **out);
     46
    4347#endif
  • trunk/webif/pages_gen.c

    r8438 r8445  
    4545        uint32_t data_len;
    4646        enum { TXT, BIN } type;
     47        uint8_t mime_type;
    4748    } data[MAX_TEMPLATES];
    4849};
     
    8485}
    8586
    86 static const char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    87 static const char Pad64 = '=';
    88 
    89 int b64_encode(const uint8_t *src, size_t srclength, uint8_t *target, size_t targsize)
    90 {
    91     size_t datalength = 0;
    92     uint8_t input[3] = {0,0,0};
    93     uint8_t output[4] = {0,0,0,0};
    94     unsigned int i;
    95 
    96     while (2 < srclength) {
    97         input[0] = *src++;
    98         input[1] = *src++;
    99         input[2] = *src++;
    100         srclength -= 3;
    101         output[0] = input[0] >> 2;
    102         output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
    103         output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
    104         output[3] = input[2] & 0x3f;
    105         if (datalength + 4 > targsize)
    106             return -1;
    107         target[datalength++] = Base64[output[0]];
    108         target[datalength++] = Base64[output[1]];
    109         target[datalength++] = Base64[output[2]];
    110         target[datalength++] = Base64[output[3]];
    111     }
    112 
    113     /* Now we worry about padding. */
    114     if (0 != srclength) {
    115         /* Get what's left. */
    116         input[0] = input[1] = input[2] = '\0';
    117         for (i = 0; i < srclength; i++)
    118             input[i] = *src++;
    119 
    120         output[0] = input[0] >> 2;
    121         output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
    122         output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
    123 
    124         if (datalength + 4 > targsize)
    125             return (-1);
    126         target[datalength++] = Base64[output[0]];
    127         target[datalength++] = Base64[output[1]];
    128         if (srclength == 1)
    129             target[datalength++] = Pad64;
    130         else
    131             target[datalength++] = Base64[output[2]];
    132         target[datalength++] = Pad64;
    133     }
    134     if (datalength >= targsize)
    135         return -1;
    136     target[datalength] = '\0'; /* Returned value doesn't count \0. */
    137     return datalength;
    138 }
    139 
    14087static bool is_text(char *filename) {
    14188    char *ext = strchr(basename(filename), '.');
     
    15097    }
    15198    return false;
     99}
     100
     101static uint8_t mime_type_from_filename(char *filename) {
     102    char *ext = strchr(basename(filename), '.');
     103    if (ext) {
     104        ext++;
     105        // See "enum template_types" bellow
     106        if      (strcmp(ext, "png") == 0) return 1;
     107        else if (strcmp(ext, "gif") == 0) return 2;
     108        else if (strcmp(ext, "ico") == 0) return 3;
     109        else if (strcmp(ext, "jpg") == 0) return 4;
     110    }
     111    return 0;
    152112}
    153113
     
    196156
    197157        templates.data[templates.num].type = is_text(file) ? TXT : BIN;
     158        templates.data[templates.num].mime_type = mime_type_from_filename(file);
    198159        templates.num++;
    199160        if (templates.num == MAX_TEMPLATES - 1) {
     
    241202    }
    242203
    243     fprintf(output_file, "\t{ .tpl_name=\"%s\", .tpl_data=%s%s, .tpl_deps=\"%s\", .tpl_data_len=%u },\n",
    244         ident,
    245         templates.data[tpl_idx].type == TXT ? "TPL" : "", ident,
    246         deps,
    247         templates.data[tpl_idx].data_len
     204    fprintf(output_file, "\t{ .tpl_name=\"%s\", .tpl_data=TPL%s, .tpl_deps=\"%s\", .tpl_data_len=%u, .tpl_type=%u },\n",
     205        ident, ident, deps, templates.data[tpl_idx].data_len, templates.data[tpl_idx].mime_type
    248206    );
    249207
     
    254212}
    255213
    256 static uint32_t dump_text(char *ident, uint8_t *buf, size_t buf_len) {
     214static void dump_text(char *ident, uint8_t *buf, size_t buf_len) {
    257215    int i;
    258216    fprintf(output_file, "#define TPL%s \\\n\"", ident);
     
    271229    }
    272230    fprintf(output_file, "\"\n\n");
    273     return buf_len;
    274 }
    275 
    276 static char *get_mime(char *filename) {
    277     char *ext = strchr(filename, '.');
    278     if (ext) {
    279         ext++;
    280         if      (strcmp(ext, "png") == 0) return "image/png";
    281         else if (strcmp(ext, "gif") == 0) return "image/gif";
    282         else if (strcmp(ext, "jpg") == 0) return "image/jpg";
    283         else if (strcmp(ext, "ico") == 0) return "image/x-icon";
    284     }
    285     return "unknown";
    286 }
    287 
    288 static uint32_t dump_base64(char *ident, char *mime, uint8_t *buf, size_t buf_len) {
    289     char tpl_type[32];
    290     size_t b64_buf_len = buf_len * 4 + 16;
    291     uint8_t *b64_buf = malloc(b64_buf_len);
    292     if (!b64_buf)
    293         die("%s: can't alloc %zd bytes\n", __func__, b64_buf_len);
    294     int i, b64_len = b64_encode(buf, buf_len, b64_buf, b64_buf_len);
    295     snprintf(tpl_type, sizeof(tpl_type), "data:%s;base64,", mime);
    296     fprintf(output_file, "#define %s \"%s\\\n", ident, tpl_type);
    297     for (i = 0; i < b64_len; i++) {
    298         if (i && i % 76 == 0)
    299             fprintf(output_file, "\\\n");
    300         fprintf(output_file, "%c", b64_buf[i]);
     231}
     232
     233static void dump_binary(char *ident, uint8_t *buf, size_t buf_len) {
     234    fprintf(output_file, "#define TPL%s \\\n\"", ident);
     235    int i;
     236    for (i = 0; i < buf_len; i++) {
     237        fprintf(output_file, "\\x%02x", buf[i]);
    301238    }
    302239    fprintf(output_file, "\"\n\n");
    303     free(b64_buf);
    304     return strlen(tpl_type) + b64_len;
    305240}
    306241
     
    313248    fprintf(output_file, "#ifndef WEBIF_PAGES_H_\n");
    314249    fprintf(output_file, "#define WEBIF_PAGES_H_\n");
     250    fprintf(output_file, "\n");
     251    fprintf(output_file, "enum template_types {\n");
     252    fprintf(output_file, "  TEMPLATE_TYPE_TEXT = 0,\n");
     253    fprintf(output_file, "  TEMPLATE_TYPE_PNG  = 1,\n");
     254    fprintf(output_file, "  TEMPLATE_TYPE_GIF  = 2,\n");
     255    fprintf(output_file, "  TEMPLATE_TYPE_ICO  = 3,\n");
     256    fprintf(output_file, "  TEMPLATE_TYPE_JPG  = 4,\n");
     257    fprintf(output_file, "};\n");
    315258    fprintf(output_file, "\n");
    316259    fprintf(output_file, "struct template {\n");
     
    319262    fprintf(output_file, "  char *tpl_deps;\n");
    320263    fprintf(output_file, "  uint32_t tpl_data_len;\n");
     264    fprintf(output_file, "  uint8_t tpl_type;\n");
    321265    fprintf(output_file, "};\n");
    322266    fprintf(output_file, "\n");
    323267    fprintf(output_file, "int32_t templates_count(void);\n");
     268    fprintf(output_file, "bool template_is_image(enum template_types tpl_type);\n");
     269    fprintf(output_file, "const char *template_get_mimetype(enum template_types tpl_type);\n");
    324270    fprintf(output_file, "\n");
    325271    fprintf(output_file, "#endif\n");
     
    336282    for (i = 0; i < templates.num; i++) {
    337283        uint8_t *buf;
    338         size_t buf_len, data_len = 0;
     284        size_t buf_len;
    339285        readfile(templates.data[i].file, &buf, &buf_len);
     286        templates.data[i].data_len = buf_len;
    340287        switch (templates.data[i].type) {
    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;
     288            case TXT: dump_text(templates.data[i].ident, buf, buf_len); break;
     289            case BIN: dump_binary(templates.data[i].ident, buf, buf_len); break;
    343290        }
    344291        free(buf);
    345         templates.data[i].data_len = data_len;
    346292    }
    347293
     
    354300    fprintf(output_file, "int32_t templates_count(void) { return sizeof(templates) / sizeof(struct template); }\n");
    355301    fprintf(output_file, "\n");
     302    fprintf(output_file, "bool template_is_image(enum template_types tpl_type) {\n");
     303    fprintf(output_file, "  switch (tpl_type) {\n");
     304    fprintf(output_file, "  case TEMPLATE_TYPE_PNG:\n");
     305    fprintf(output_file, "  case TEMPLATE_TYPE_GIF:\n");
     306    fprintf(output_file, "  case TEMPLATE_TYPE_ICO:\n");
     307    fprintf(output_file, "  case TEMPLATE_TYPE_JPG:\n");
     308    fprintf(output_file, "      return true;\n");
     309    fprintf(output_file, "  default:\n");
     310    fprintf(output_file, "      return false;\n");
     311    fprintf(output_file, "  }\n");
     312    fprintf(output_file, "  return false;\n");
     313    fprintf(output_file, "}\n");
     314    fprintf(output_file, "\n");
     315    fprintf(output_file, "const char *template_get_mimetype(enum template_types tpl_type) {\n");
     316    fprintf(output_file, "  switch (tpl_type) {\n");
     317    fprintf(output_file, "  case TEMPLATE_TYPE_TEXT: return \"text/plain\";\n");
     318    fprintf(output_file, "  case TEMPLATE_TYPE_PNG : return \"image/png\";\n");
     319    fprintf(output_file, "  case TEMPLATE_TYPE_GIF : return \"image/gif\";\n");
     320    fprintf(output_file, "  case TEMPLATE_TYPE_ICO : return \"image/x-icon\";\n");
     321    fprintf(output_file, "  case TEMPLATE_TYPE_JPG : return \"image/jpg\";\n");
     322    fprintf(output_file, "  }\n");
     323    fprintf(output_file, "  return \"\";\n");
     324    fprintf(output_file, "}\n");
     325    fprintf(output_file, "\n");
    356326    fprintf(output_file, "#endif\n");
    357327    fclose(output_file);
Note: See TracChangeset for help on using the changeset viewer.