1 #define MODULE_LOG_PREFIX "webif"
6 #include "webif/pages.h"
7 #include "module-webif-tpl.h"
8 #include "oscam-files.h"
9 #include "oscam-string.h"
10 #ifdef COMPRESSED_TEMPLATES
11 #include "minilzo/minilzo.h"
14 extern uint8_t cs_http_use_utf8
;
16 /* struct template templates[] that comes from webif/pages.c is recreated as
17 struct tpl tpls[] because we need to add additional fields such as tpl_name_hash
18 and possibly preprocess templates[] struct before using it. */
22 uint32_t tpl_name_hash
;
27 uint32_t tpl_data_len
;
31 static struct tpl
*tpls
;
32 static char *tpls_data
;
33 static int tpls_count
;
35 static void tpl_init_base64(struct tpl
*tpl
)
37 // The rest of OSCam expects images to be base64 encoded and contain mime type.
38 if(!template_is_image(tpl
->tpl_type
))
40 size_t b64_buf_len
= 32 + BASE64_LENGTH(tpl
->tpl_data_len
); // Enough for base64 and 32 for header (data:XXX;base64,)
42 if(!cs_malloc(&b64_buf
, b64_buf_len
))
45 tpl
->tpl_data_len
= 0;
48 int hdr_len
= snprintf(b64_buf
, b64_buf_len
, "data:%s;base64,", template_get_mimetype(tpl
->tpl_type
));
49 base64_encode(tpl
->tpl_data
, tpl
->tpl_data_len
, b64_buf
+ hdr_len
, b64_buf_len
- hdr_len
);
50 tpl
->tpl_data
= tpl
->extra_data
= b64_buf
;
51 tpl
->tpl_data_len
= strlen(b64_buf
);
54 void webif_tpls_prepare(void)
57 const struct template *templates
= templates_get();
58 tpls_count
= templates_count();
59 if(!cs_malloc(&tpls
, tpls_count
* sizeof(struct tpl
)))
64 #ifdef COMPRESSED_TEMPLATES
65 const char *templates_cdata
;
66 size_t tpls_data_len
, tpls_data_olen
;
67 templates_get_data(&templates_cdata
, &tpls_data_len
, &tpls_data_olen
);
68 if(!cs_malloc(&tpls_data
, tpls_data_olen
))
74 lzo_uint new_len
= tpls_data_olen
;
75 int r
= lzo1x_decompress_safe((uint8_t *)templates_cdata
, tpls_data_len
, (uint8_t *)tpls_data
, &new_len
, NULL
);
76 if(r
== LZO_E_OK
&& new_len
== tpls_data_olen
)
78 cs_log("webif: decompressed %zu bytes back into %zu bytes", tpls_data_len
, tpls_data_olen
);
82 /* this should NEVER happen */
83 cs_log("internal error - decompression failed: %d\n", r
);
88 for(i
= 0; i
< tpls_count
; ++i
)
90 tpls
[i
].tpl_name
= tpls_data
+ templates
[i
].tpl_name_ofs
;
91 tpls
[i
].tpl_data
= tpls_data
+ templates
[i
].tpl_data_ofs
;
92 tpls
[i
].tpl_deps
= tpls_data
+ templates
[i
].tpl_deps_ofs
;
93 tpls
[i
].tpl_data_len
= templates
[i
].tpl_data_len
;
94 tpls
[i
].tpl_type
= templates
[i
].tpl_type
;
95 tpls
[i
].tpl_name_hash
= jhash(tpls
[i
].tpl_name
, strlen(tpls
[i
].tpl_name
));
96 tpl_init_base64(&tpls
[i
]);
99 for(i
= 0; i
< tpls_count
; ++i
)
101 tpls
[i
].tpl_name_hash
= jhash(templates
[i
].tpl_name
, strlen(templates
[i
].tpl_name
));
102 tpls
[i
].tpl_name
= templates
[i
].tpl_name
;
103 tpls
[i
].tpl_data
= templates
[i
].tpl_data
;
104 tpls
[i
].tpl_deps
= templates
[i
].tpl_deps
;
105 tpls
[i
].tpl_data_len
= templates
[i
].tpl_data_len
;
106 tpls
[i
].tpl_type
= templates
[i
].tpl_type
;
107 tpl_init_base64(&tpls
[i
]);
112 void webif_tpls_free(void)
119 for(i
= 0; i
< tmp
; ++i
)
121 NULLFREE(tpls
[i
].extra_data
);
127 /* Adds a name->value-mapping or appends to it. You will get a reference back which you may freely
128 use (but you should not call free/realloc on this!)*/
129 void tpl_addVar(struct templatevars
*vars
, uint8_t addmode
, const char *name
, const char *value
)
131 if(name
== NULL
) { return; }
132 if(value
== NULL
) { value
= ""; }
134 char *tmp
= NULL
, *result
= NULL
;
135 for(i
= (*vars
).varscnt
- 1; i
>= 0; --i
)
137 if(strcmp((*vars
).names
[i
], name
) == 0)
139 result
= (*vars
).values
[i
];
145 if((*vars
).varsalloc
<= (*vars
).varscnt
)
147 if(!cs_realloc(&(*vars
).names
, (*vars
).varsalloc
* 2 * sizeof(char **))) { return; }
148 if(!cs_realloc(&(*vars
).values
, (*vars
).varsalloc
* 2 * sizeof(char **))) { return; }
149 if(!cs_realloc(&(*vars
).vartypes
, (*vars
).varsalloc
* 2 * sizeof(uint8_t *))) { return; }
150 (*vars
).varsalloc
= (*vars
).varscnt
* 2;
152 int32_t len
= strlen(name
) + 1;
153 if(!cs_malloc(&tmp
, len
)) { return; }
154 memcpy(tmp
, name
, len
);
155 (*vars
).names
[(*vars
).varscnt
] = tmp
;
156 len
= strlen(value
) + 1;
157 if(!cs_malloc(&tmp
, len
))
159 NULLFREE((*vars
).names
[(*vars
).varscnt
]);
162 memcpy(tmp
, value
, len
);
163 (*vars
).values
[(*vars
).varscnt
] = tmp
;
164 (*vars
).vartypes
[(*vars
).varscnt
] = addmode
;
169 int32_t oldlen
= 0, newlen
= strlen(value
);
170 if(addmode
== TPLAPPEND
|| addmode
== TPLAPPENDONCE
) { oldlen
= strlen((*vars
).values
[i
]); }
171 if(!cs_realloc(&((*vars
).values
[i
]), oldlen
+ newlen
+ 1)) { return; }
172 memcpy((*vars
).values
[i
] + oldlen
, value
, newlen
+ 1);
173 (*vars
).vartypes
[i
] = addmode
;
178 /* Adds a message to be output on the page using the TPLMESSAGE template. */
179 void tpl_addMsg(struct templatevars
*vars
, const char *value
)
181 tpl_addVar(vars
, TPLADDONCE
, "MESSAGE", value
);
183 tpl_addVar(vars
, TPLAPPEND
, "MESSAGES", tpl_getTpl(vars
, "MESSAGEBIT"));
186 /* Allows to add a char array which has been allocated by malloc. It will automatically get
187 freed when calling tpl_clear(). Please do NOT free the memory yourself or realloc
188 it after having added the array here! */
189 static char *tpl_addTmp(struct templatevars
*vars
, char *value
)
191 if(value
== NULL
) { return ""; }
192 if((*vars
).tmpalloc
<= (*vars
).tmpcnt
)
194 if(!cs_realloc(&(*vars
).tmp
, (*vars
).tmpalloc
* 2 * sizeof(char **))) { return value
; }
195 (*vars
).tmpalloc
= (*vars
).tmpcnt
* 2;
197 (*vars
).tmp
[(*vars
).tmpcnt
] = value
;
202 /* Allows to do a dynamic printf without knowing and defining the needed memory size. If you specify
203 varname, the printf-result will be added/appended to the varlist, if varname=NULL it will only be returned.
204 In either case you will always get a reference back which you may freely use (but you should not call
205 free/realloc on this as it will be automatically cleaned!)*/
206 void tpl_printf(struct templatevars
*vars
, uint8_t addmode
, const char *varname
, const char *fmtstring
, ...)
212 va_start(argptr
, fmtstring
);
213 needed
= vsnprintf(test
, 1, fmtstring
, argptr
);
217 if(!cs_malloc(&result
, needed
+ 1)) { return; }
218 va_start(argptr
, fmtstring
);
219 vsnprintf(result
, needed
+ 1, fmtstring
, argptr
);
222 if(varname
== NULL
) { tpl_addTmp(vars
, result
); }
225 tpl_addVar(vars
, addmode
, varname
, result
);
231 /* Returns the value for a name or an empty string if nothing was found. */
232 char *tpl_getVar(struct templatevars
*vars
, const char *name
)
236 for(i
= (*vars
).varscnt
- 1; i
>= 0; --i
)
238 if(strcmp((*vars
).names
[i
], name
) == 0)
240 result
= (*vars
).values
[i
];
244 if(result
== NULL
) { return ""; }
247 if((*vars
).vartypes
[i
] == TPLADDONCE
|| (*vars
).vartypes
[i
] == TPLAPPENDONCE
)
249 // This is a one-time-use variable which gets cleaned up automatically after retrieving it
250 if(!cs_malloc(&(*vars
).values
[i
], 1))
252 (*vars
).values
[i
] = result
;
258 (*vars
).values
[i
][0] = '\0';
259 return tpl_addTmp(vars
, result
);
262 else { return result
; }
266 /* Initializes all variables for a templatevar-structure and returns a pointer to it. Make
267 sure to call tpl_clear() when you are finished or you'll run into a memory leak! */
268 struct templatevars
*tpl_create(void)
270 struct templatevars
*vars
;
271 if(!cs_malloc(&vars
, sizeof(struct templatevars
))) { return NULL
; }
272 (*vars
).varsalloc
= 64;
274 (*vars
).tmpalloc
= 64;
276 if(!cs_malloc(&(*vars
).names
, (*vars
).varsalloc
* sizeof(char **)))
281 if(!cs_malloc(&(*vars
).values
, (*vars
).varsalloc
* sizeof(char **)))
283 NULLFREE((*vars
).names
);
287 if(!cs_malloc(&(*vars
).vartypes
, (*vars
).varsalloc
* sizeof(uint8_t *)))
289 NULLFREE((*vars
).names
);
290 NULLFREE((*vars
).values
);
294 if(!cs_malloc(&(*vars
).tmp
, (*vars
).tmpalloc
* sizeof(char **)))
296 NULLFREE((*vars
).names
);
297 NULLFREE((*vars
).values
);
298 NULLFREE((*vars
).vartypes
);
305 /* Clears all allocated memory for the specified templatevar-structure. */
306 void tpl_clear(struct templatevars
*vars
)
309 for(i
= (*vars
).varscnt
- 1; i
>= 0; --i
)
311 NULLFREE((*vars
).names
[i
]);
312 NULLFREE((*vars
).values
[i
]);
314 NULLFREE((*vars
).names
);
315 NULLFREE((*vars
).values
);
316 NULLFREE((*vars
).vartypes
);
317 for(i
= (*vars
).tmpcnt
- 1; i
>= 0; --i
)
319 NULLFREE((*vars
).tmp
[i
]);
321 NULLFREE((*vars
).tmp
);
325 /* Creates a path to a template file. You need to set the resultsize to the correct size of result. */
326 char *tpl_getFilePathInSubdir(const char *path
, const char *subdir
, const char *name
, const char *ext
, char *result
, uint32_t resultsize
)
328 int path_len
= strlen(path
);
329 const char *path_fixup
= "";
330 if(path_len
&& path
[path_len
- 1] != '/')
331 { path_fixup
= "/"; }
332 if(path_len
+ strlen(path_fixup
) + strlen(name
) + strlen(subdir
) + strlen(ext
) < resultsize
)
334 snprintf(result
, resultsize
, "%s%s%s%s%s", path
, path_fixup
, subdir
, name
, ext
);
336 else { result
[0] = '\0'; }
340 char *tpl_getTplPath(const char *name
, const char *path
, char *result
, uint32_t resultsize
)
342 return tpl_getFilePathInSubdir(path
, "", name
, ".tpl", result
, resultsize
);
345 #define check_conf(CONFIG_VAR, text) \
346 if (config_enabled(CONFIG_VAR) && strncmp(#CONFIG_VAR, text, len) == 0) { ok = 1; break; }
348 /* Returns an unparsed template either from disk or from internal templates.
349 Note: You must free() the result after using it and you may get NULL if an error occured!*/
350 char *tpl_getUnparsedTpl(const char *name
, int8_t removeHeader
, const char *subdir
)
356 tpl_path
= (cfg
.http_piconpath
&& strlen(name
) > 3 && name
[0] == 'I' && name
[1] == 'C' && name
[2] == '_') ? cfg
.http_piconpath
: cfg
.http_tpl
;
361 if((strlen(tpl_getFilePathInSubdir(tpl_path
, subdir
, name
, ".tpl", path
, 255)) > 0 && file_exists(path
))
362 || (strlen(subdir
) > 0
364 && strcmp(subdir
, TOUCH_SUBDIR
)
366 && strlen(tpl_getFilePathInSubdir(tpl_path
, "" , name
, ".tpl", path
, 255)) > 0 && file_exists(path
)))
370 memset(buffer
, 0, sizeof(buffer
));
371 int32_t readen
, allocated
= 1025, offset
, size
= 0;
372 if(!cs_malloc(&result
, allocated
)) { return NULL
; }
373 if((fp
= fopen(path
, "r")) != NULL
)
375 // Use as read size sizeof(buffer) - 1 to ensure that buffer is
376 // zero terminated otherwise strstr can segfault!
377 while((readen
= fread(buffer
, 1, sizeof(buffer
) - 1, fp
)) > 0)
380 if(size
== 0 && removeHeader
)
382 /* Remove version string from output and check if it is valid for output */
383 char *pch1
= strstr(buffer
, "<!--OSCam");
386 char *pch2
= strstr(pch1
, "-->");
389 offset
= pch2
- buffer
+ 4;
392 char *ptr1
, *ptr2
, *saveptr1
= NULL
, *saveptr2
= NULL
;
393 for(i
= 0, ptr1
= strtok_r(pch1
+ 10, ";", &saveptr1
); (ptr1
) && i
< 4 ; ptr1
= strtok_r(NULL
, ";", &saveptr1
), i
++)
395 if(i
== 3 && strlen(ptr1
) > 2)
398 for(ptr2
= strtok_r(ptr1
, ",", &saveptr2
); (ptr2
) && ok
== 0 ; ptr2
= strtok_r(NULL
, ",", &saveptr2
))
400 size_t len
= strlen(ptr2
);
401 check_conf(WITH_CARDREADER
, ptr2
);
402 check_conf(CARDREADER_PHOENIX
, ptr2
);
403 check_conf(CARDREADER_DRECAS
, ptr2
);
404 check_conf(CARDREADER_INTERNAL_AZBOX
, ptr2
);
405 check_conf(CARDREADER_INTERNAL_COOLAPI
, ptr2
);
406 check_conf(CARDREADER_INTERNAL_SCI
, ptr2
);
407 check_conf(CARDREADER_SC8IN1
, ptr2
);
408 check_conf(CARDREADER_MP35
, ptr2
);
409 check_conf(CARDREADER_SMARGO
, ptr2
);
410 check_conf(CARDREADER_PCSC
, ptr2
);
411 check_conf(CARDREADER_SMART
, ptr2
);
412 check_conf(CARDREADER_DB2COM
, ptr2
);
413 check_conf(CARDREADER_STAPI
, ptr2
);
414 check_conf(CARDREADER_STAPI5
, ptr2
);
415 check_conf(WEBIF_LIVELOG
, ptr2
);
416 check_conf(WEBIF_JQUERY
, ptr2
);
417 check_conf(TOUCH
, ptr2
);
418 check_conf(CS_ANTICASC
, ptr2
);
419 check_conf(CS_CACHEEX
, ptr2
);
420 check_conf(HAVE_DVBAPI
, ptr2
);
421 check_conf(WITH_NEUTRINO
, ptr2
);
422 check_conf(READ_SDT_CHARSETS
, ptr2
);
423 check_conf(CLOCKFIX
, ptr2
);
424 check_conf(IPV6SUPPORT
, ptr2
);
425 check_conf(IRDETO_GUESSING
, ptr2
);
426 check_conf(LCDSUPPORT
, ptr2
);
427 check_conf(LEDSUPPORT
, ptr2
);
428 check_conf(MODULE_CAMD33
, ptr2
);
429 check_conf(MODULE_CAMD35
, ptr2
);
430 check_conf(MODULE_CAMD35_TCP
, ptr2
);
431 check_conf(MODULE_CCCAM
, ptr2
);
432 check_conf(MODULE_CCCSHARE
, ptr2
);
433 check_conf(MODULE_CONSTCW
, ptr2
);
434 check_conf(MODULE_GBOX
, ptr2
);
435 check_conf(MODULE_GHTTP
, ptr2
);
436 check_conf(MODULE_MONITOR
, ptr2
);
437 check_conf(MODULE_NEWCAMD
, ptr2
);
438 check_conf(MODULE_PANDORA
, ptr2
);
439 check_conf(MODULE_RADEGAST
, ptr2
);
440 check_conf(MODULE_SERIAL
, ptr2
);
441 check_conf(MODULE_CW_CYCLE_CHECK
, ptr2
);
442 check_conf(READER_BULCRYPT
, ptr2
);
443 check_conf(READER_CONAX
, ptr2
);
444 check_conf(READER_CRYPTOWORKS
, ptr2
);
445 check_conf(READER_GRIFFIN
, ptr2
);
446 check_conf(READER_DGCRYPT
, ptr2
);
447 check_conf(READER_DRE
, ptr2
);
448 check_conf(READER_IRDETO
, ptr2
);
449 check_conf(READER_NAGRA
, ptr2
);
450 check_conf(READER_NAGRA_MERLIN
, ptr2
);
451 check_conf(READER_SECA
, ptr2
);
452 check_conf(READER_TONGFANG
, ptr2
);
453 check_conf(READER_VIACCESS
, ptr2
);
454 check_conf(READER_VIDEOGUARD
, ptr2
);
455 check_conf(WITH_CARDREADER
, ptr2
);
456 check_conf(WITH_DEBUG
, ptr2
);
457 check_conf(WITH_LB
, ptr2
);
458 check_conf(WITH_LIBCRYPTO
, ptr2
);
459 check_conf(WITH_SSL
, ptr2
);
460 check_conf(WITH_STAPI
, ptr2
);
461 check_conf(WITH_STAPI5
, ptr2
);
462 check_conf(WITH_EMU
, ptr2
);
475 if(allocated
< size
+ readen
+ 1)
477 allocated
+= size
+ 1024;
478 if(!cs_realloc(&result
, allocated
))
484 memcpy(result
+ size
, buffer
+ offset
, readen
);
495 uint32_t name_hash
= jhash(name
, strlen(name
));
496 for(i
= 0; i
< tpls_count
; i
++)
498 if(tpls
[i
].tpl_name_hash
== name_hash
)
507 const struct tpl
*tpl
= &tpls
[i
];
508 if(!cs_malloc(&result
, tpl
->tpl_data_len
+ 1)) { return NULL
; } // +1 to accomodate \0 at the end
509 memcpy(result
, tpl
->tpl_data
, tpl
->tpl_data_len
);
513 if(!cs_malloc(&result
, 1)) { return NULL
; } // Return empty string
518 /* Returns the specified template with all variables/other templates replaced or an
519 empty string if the template doesn't exist. Do not free the result yourself, it
520 will get automatically cleaned up! */
521 char *tpl_getTpl(struct templatevars
*vars
, const char *name
)
523 char *tplorg
= tpl_getUnparsedTpl(name
, 1, tpl_getVar(vars
, "SUBDIR"));
524 if(!tplorg
) { return ""; }
525 char *tplend
= tplorg
+ strlen(tplorg
);
526 char *pch
, *pch2
, *tpl
= tplorg
;
529 int32_t tmp
, respos
= 0;
530 int32_t allocated
= 2 * strlen(tpl
) + 1;
532 if(!cs_malloc(&result
, allocated
)) { return ""; }
536 if(tpl
[0] == '#' && tpl
[1] == '#' && tpl
[2] != '#')
540 while(pch
[0] != '\0' && (pch
[0] != '#' || pch
[1] != '#')) { ++pch
; }
541 if(pch
- pch2
< 32 && pch
[0] == '#' && pch
[1] == '#')
543 memcpy(varname
, pch2
+ 2, pch
- pch2
- 2);
544 varname
[pch
- pch2
- 2] = '\0';
545 if(strncmp(varname
, "TPL", 3) == 0)
547 if((*vars
).messages
> 0 || strncmp(varname
, "TPLMESSAGE", 10) != 0)
548 { pch2
= tpl_getTpl(vars
, varname
+ 3); }
553 pch2
= tpl_getVar(vars
, varname
);
556 if(tmp
+ respos
+ 2 >= allocated
)
558 allocated
= tmp
+ respos
+ 256;
559 if(!cs_realloc(&result
, allocated
)) { return ""; }
561 memcpy(result
+ respos
, pch2
, tmp
);
568 if(respos
+ 2 >= allocated
)
570 allocated
= respos
+ 256;
571 if(!cs_realloc(&result
, allocated
)) { return ""; }
573 result
[respos
] = tpl
[0];
579 result
[respos
] = '\0';
580 tpl_addTmp(vars
, result
);
584 /* Saves all templates to the specified paths. Existing files will be overwritten! */
585 int32_t tpl_saveIncludedTpls(const char *path
)
590 for(i
= 0; i
< tpls_count
; ++i
)
592 const struct tpl
*tpl
= &tpls
[i
];
593 if(strlen(tpl_getTplPath(tpl
->tpl_name
, path
, tmp
, 256)) > 0 && (fp
= fopen(tmp
, "w")) != NULL
)
595 if(strncmp(tpl
->tpl_name
, "IC", 2) != 0)
597 fprintf(fp
, "<!--OSCam;%d;%s;%s;%s-->\n", crc32(0, (uint8_t *)tpl
->tpl_data
, tpl
->tpl_data_len
), CS_VERSION
, CS_SVN_VERSION
, tpl
->tpl_deps
);
599 fwrite(tpl
->tpl_data
, tpl
->tpl_data_len
, 1, fp
);
607 /* Checks all disk templates in a directory if they are still current or may need upgrade! */
608 void tpl_checkOneDirDiskRevisions(const char *subdir
)
610 char dirpath
[255] = "\0";
611 snprintf(dirpath
, 255, "%s%s", cfg
.http_tpl
? cfg
.http_tpl
: "", subdir
);
614 for(i
= 0; i
< tpls_count
; ++i
)
616 const struct tpl
*tpl
= &tpls
[i
];
617 if(strncmp(tpl
->tpl_name
, "IC", 2) != 0 && strlen(tpl_getTplPath(tpl
->tpl_name
, dirpath
, path
, 255)) > 0 && file_exists(path
))
620 char *tplorg
= tpl_getUnparsedTpl(tpl
->tpl_name
, 0, subdir
);
621 unsigned long checksum
= 0, curchecksum
= crc32(0L, (uint8_t *)tpl
->tpl_data
, tpl
->tpl_data_len
);
622 char *ifdefs
= "", *pch1
= strstr(tplorg
, "<!--OSCam");
625 char *version
= "?", *revision
= "?";
626 char *pch2
= strstr(pch1
, "-->");
631 char *ptr1
, *saveptr1
= NULL
;
632 for(j
= 0, ptr1
= strtok_r(pch1
+ 10, ";", &saveptr1
); (ptr1
) && j
< 4 ; ptr1
= strtok_r(NULL
, ";", &saveptr1
), j
++)
634 if(j
== 0) { checksum
= strtoul(ptr1
, NULL
, 10); }
635 else if(j
== 1) { version
= ptr1
; }
636 else if(j
== 2) { revision
= ptr1
; }
637 else if(j
== 3) { ifdefs
= ptr1
; }
640 if(checksum
!= curchecksum
)
642 cs_log("WARNING: Your http disk template %s was created for an older revision of OSCam and was changed in original OSCam (%s,r%s). Please consider upgrading it!", path
, version
, revision
);
646 else { cs_log("WARNING: Your http disk template %s is in the old template format without revision info. Please consider upgrading it!", path
); }
647 if(error
) { cs_log("If you are sure that it is current, add the following line at the beginning of the template to suppress this warning: <!--OSCam;%lu;%s;%s;%s-->", curchecksum
, CS_VERSION
, CS_SVN_VERSION
, ifdefs
); }
653 /* Checks whether disk templates need upgrade - including sub-directories */
654 void tpl_checkDiskRevisions(void)
660 tpl_checkOneDirDiskRevisions("");
663 struct dirent
*result
;
665 if((hdir
= opendir(cfg
.http_tpl
)) != NULL
)
667 while(cs_readdir_r(hdir
, &entry
, &result
) == 0 && result
!= NULL
)
669 if(strcmp(".", entry
.d_name
) == 0 || strcmp("..", entry
.d_name
) == 0)
673 snprintf(dirpath
, 255, "%.31s%.31s", cfg
.http_tpl
, entry
.d_name
);
674 if(stat(dirpath
, &s
) == 0)
676 if(s
.st_mode
& S_IFDIR
)
678 snprintf(subdir
, 255,
685 tpl_checkOneDirDiskRevisions(subdir
);
694 /* Helper function for urldecode.*/
695 static int32_t x2i(int32_t i
)
699 if(i
> 9) { i
= i
- 'A' + '9' + 1; }
703 /* Decodes values in a http url. Note: The original value is modified! */
704 void urldecode(char *s
)
713 if(c
== '+') { c
= ' '; }
714 else if(c
== '%' && n
> 2)
719 c
= 16 * x2i(c1
) + x2i(c
);
728 /* Encode values in a http url. Do not call free() or realloc on the returned reference or you will get memory corruption! */
729 char *urlencode(struct templatevars
*vars
, const char *str
)
732 if(!cs_malloc(&buf
, strlen(str
) * 3 + 1)) { return ""; }
733 const char *pstr
= str
;
738 if(isalnum((uint8_t)*pstr
) || *pstr
== '-' || *pstr
== '_' || *pstr
== '.' || *pstr
== '~') { *pbuf
++ = *pstr
; }
739 else if(*pstr
== ' ') { *pbuf
++ = '+'; }
743 *pbuf
++ = to_hex(*pstr
>> 4);
744 *pbuf
++ = to_hex(*pstr
& 15);
749 /* Allocate the needed memory size and store it in the templatevars */
750 if(!cs_realloc(&buf
, strlen(buf
) + 1)) { return ""; }
751 return tpl_addTmp(vars
, buf
);
754 /* XML-Escapes a char array. The returned reference will be automatically cleaned through the templatevars-mechanism tpl_clear().
755 Do not call free() or realloc on the returned reference or you will get memory corruption! */
756 char *xml_encode(struct templatevars
*vars
, const char *chartoencode
)
758 if(!chartoencode
) { return ""; }
759 int32_t i
, pos
= 0, len
= strlen(chartoencode
);
762 /* In worst case, every character could get converted to 6 chars (we only support ASCII, for Unicode it would be 7)*/
763 if(!cs_malloc(&encoded
, len
* 6 + 1)) { return ""; }
764 for(i
= 0; i
< len
; ++i
)
766 uint8_t tmp
= chartoencode
[i
];
770 memcpy(encoded
+ pos
, "&", 5);
774 memcpy(encoded
+ pos
, "<", 4);
778 memcpy(encoded
+ pos
, ">", 4);
782 memcpy(encoded
+ pos
, """, 6);
786 memcpy(encoded
+ pos
, "'", 5);
788 break; // ' not supported on older IE
790 memcpy(encoded
+ pos
, "\n", 1);
794 if(tmp
< 32 || (cs_http_use_utf8
!= 1 && tmp
> 127))
796 snprintf(buffer
, 7, "&#%d;", tmp
);
797 memcpy(encoded
+ pos
, buffer
, strlen(buffer
));
798 pos
+= strlen(buffer
);
807 /* Reduce to the really needed memory size and store it in the templatevars */
808 if(!cs_realloc(&encoded
, pos
+ 1)) { return ""; }
810 return tpl_addTmp(vars
, encoded
);
813 /* Format a seconds integer to hh:mm:ss or dd hh:mm:ss depending hrs >24 */
814 char *sec2timeformat(struct templatevars
*vars
, int32_t seconds
)
818 { return "00:00:00"; }
819 if(!cs_malloc(&value
, 16))
820 { return "00:00:00"; }
821 int32_t secs
= 0, fullmins
= 0, mins
= 0, fullhours
= 0, hours
= 0, days
= 0;
825 fullmins
= seconds
/ 60;
826 mins
= fullmins
% 60;
829 fullhours
= fullmins
/ 60;
830 hours
= fullhours
% 24;
831 days
= fullhours
/ 24;
835 { snprintf(value
, 16, "%02d:%02d:%02d", hours
, mins
, secs
); }
837 { snprintf(value
, 16, "%02dd %02d:%02d:%02d", days
, hours
, mins
, secs
); }
838 return tpl_addTmp(vars
, value
);