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 /* struct template templates[] that comes from webif/pages.c is recreated as
15 struct tpl tpls[] because we need to add additional fields such as tpl_name_hash
16 and possibly preprocess templates[] struct before using it. */
20 uint32_t tpl_name_hash
;
25 uint32_t tpl_data_len
;
29 static struct tpl
*tpls
;
30 static char *tpls_data
;
31 static int tpls_count
;
33 static void tpl_init_base64(struct tpl
*tpl
)
35 // The rest of OSCam expects images to be base64 encoded and contain mime type.
36 if(!template_is_image(tpl
->tpl_type
))
38 size_t b64_buf_len
= 32 + BASE64_LENGTH(tpl
->tpl_data_len
); // Enough for base64 and 32 for header (data:XXX;base64,)
40 if(!cs_malloc(&b64_buf
, b64_buf_len
))
43 tpl
->tpl_data_len
= 0;
46 int hdr_len
= snprintf(b64_buf
, b64_buf_len
, "data:%s;base64,", template_get_mimetype(tpl
->tpl_type
));
47 base64_encode(tpl
->tpl_data
, tpl
->tpl_data_len
, b64_buf
+ hdr_len
, b64_buf_len
- hdr_len
);
48 tpl
->tpl_data
= tpl
->extra_data
= b64_buf
;
49 tpl
->tpl_data_len
= cs_strlen(b64_buf
);
52 void webif_tpls_prepare(void)
55 const struct template *templates
= templates_get();
56 tpls_count
= templates_count();
57 if(!cs_malloc(&tpls
, tpls_count
* sizeof(struct tpl
)))
62 #ifdef COMPRESSED_TEMPLATES
63 const char *templates_cdata
;
64 size_t tpls_data_len
, tpls_data_olen
;
65 templates_get_data(&templates_cdata
, &tpls_data_len
, &tpls_data_olen
);
66 if(!cs_malloc(&tpls_data
, tpls_data_olen
))
72 lzo_uint new_len
= tpls_data_olen
;
73 int r
= lzo1x_decompress_safe((uint8_t *)templates_cdata
, tpls_data_len
, (uint8_t *)tpls_data
, &new_len
, NULL
);
74 if(r
== LZO_E_OK
&& new_len
== tpls_data_olen
)
76 cs_log("webif: decompressed %zu bytes back into %zu bytes", tpls_data_len
, tpls_data_olen
);
80 /* this should NEVER happen */
81 cs_log("internal error - decompression failed: %d\n", r
);
86 for(i
= 0; i
< tpls_count
; ++i
)
88 tpls
[i
].tpl_name
= tpls_data
+ templates
[i
].tpl_name_ofs
;
89 tpls
[i
].tpl_data
= tpls_data
+ templates
[i
].tpl_data_ofs
;
90 tpls
[i
].tpl_deps
= tpls_data
+ templates
[i
].tpl_deps_ofs
;
91 tpls
[i
].tpl_data_len
= templates
[i
].tpl_data_len
;
92 tpls
[i
].tpl_type
= templates
[i
].tpl_type
;
93 tpls
[i
].tpl_name_hash
= jhash(tpls
[i
].tpl_name
, cs_strlen(tpls
[i
].tpl_name
));
94 tpl_init_base64(&tpls
[i
]);
97 for(i
= 0; i
< tpls_count
; ++i
)
99 tpls
[i
].tpl_name_hash
= jhash(templates
[i
].tpl_name
, cs_strlen(templates
[i
].tpl_name
));
100 tpls
[i
].tpl_name
= templates
[i
].tpl_name
;
101 tpls
[i
].tpl_data
= templates
[i
].tpl_data
;
102 tpls
[i
].tpl_deps
= templates
[i
].tpl_deps
;
103 tpls
[i
].tpl_data_len
= templates
[i
].tpl_data_len
;
104 tpls
[i
].tpl_type
= templates
[i
].tpl_type
;
105 tpl_init_base64(&tpls
[i
]);
110 void webif_tpls_free(void)
117 for(i
= 0; i
< tmp
; ++i
)
119 NULLFREE(tpls
[i
].extra_data
);
125 /* Adds a name->value-mapping or appends to it. You will get a reference back which you may freely
126 use (but you should not call free/realloc on this!)*/
127 void tpl_addVar(struct templatevars
*vars
, uint8_t addmode
, const char *name
, const char *value
)
129 if(name
== NULL
) { return; }
130 if(value
== NULL
) { value
= ""; }
132 char *tmp
= NULL
, *result
= NULL
;
133 for(i
= (*vars
).varscnt
- 1; i
>= 0; --i
)
135 if(strcmp((*vars
).names
[i
], name
) == 0)
137 result
= (*vars
).values
[i
];
143 if((*vars
).varsalloc
<= (*vars
).varscnt
)
145 if(!cs_realloc(&(*vars
).names
, (*vars
).varsalloc
* 2 * sizeof(char **))) { return; }
146 if(!cs_realloc(&(*vars
).values
, (*vars
).varsalloc
* 2 * sizeof(char **))) { return; }
147 if(!cs_realloc(&(*vars
).vartypes
, (*vars
).varsalloc
* 2 * sizeof(uint8_t *))) { return; }
148 (*vars
).varsalloc
= (*vars
).varscnt
* 2;
150 int32_t len
= cs_strlen(name
) + 1;
151 if(!cs_malloc(&tmp
, len
)) { return; }
152 memcpy(tmp
, name
, len
);
153 (*vars
).names
[(*vars
).varscnt
] = tmp
;
154 len
= cs_strlen(value
) + 1;
155 if(!cs_malloc(&tmp
, len
))
157 NULLFREE((*vars
).names
[(*vars
).varscnt
]);
160 memcpy(tmp
, value
, len
);
161 (*vars
).values
[(*vars
).varscnt
] = tmp
;
162 (*vars
).vartypes
[(*vars
).varscnt
] = addmode
;
167 int32_t oldlen
= 0, newlen
= cs_strlen(value
);
168 if(addmode
== TPLAPPEND
|| addmode
== TPLAPPENDONCE
) { oldlen
= cs_strlen((*vars
).values
[i
]); }
169 if(!cs_realloc(&((*vars
).values
[i
]), oldlen
+ newlen
+ 1)) { return; }
170 memcpy((*vars
).values
[i
] + oldlen
, value
, newlen
+ 1);
171 (*vars
).vartypes
[i
] = addmode
;
176 /* Adds a message to be output on the page using the TPLMESSAGE template. */
177 void tpl_addMsg(struct templatevars
*vars
, const char *value
)
179 tpl_addVar(vars
, TPLADDONCE
, "MESSAGE", value
);
181 tpl_addVar(vars
, TPLAPPEND
, "MESSAGES", tpl_getTpl(vars
, "MESSAGEBIT"));
184 /* Allows to add a char array which has been allocated by malloc. It will automatically get
185 freed when calling tpl_clear(). Please do NOT free the memory yourself or realloc
186 it after having added the array here! */
187 static char *tpl_addTmp(struct templatevars
*vars
, char *value
)
189 if(value
== NULL
) { return ""; }
190 if((*vars
).tmpalloc
<= (*vars
).tmpcnt
)
192 if(!cs_realloc(&(*vars
).tmp
, (*vars
).tmpalloc
* 2 * sizeof(char **))) { return value
; }
193 (*vars
).tmpalloc
= (*vars
).tmpcnt
* 2;
195 (*vars
).tmp
[(*vars
).tmpcnt
] = value
;
200 /* Allows to do a dynamic printf without knowing and defining the needed memory size. If you specify
201 varname, the printf-result will be added/appended to the varlist, if varname=NULL it will only be returned.
202 In either case you will always get a reference back which you may freely use (but you should not call
203 free/realloc on this as it will be automatically cleaned!)*/
204 void tpl_printf(struct templatevars
*vars
, uint8_t addmode
, const char *varname
, const char *fmtstring
, ...)
210 va_start(argptr
, fmtstring
);
211 needed
= vsnprintf(test
, 1, fmtstring
, argptr
);
215 if(!cs_malloc(&result
, needed
+ 1)) { return; }
216 va_start(argptr
, fmtstring
);
217 vsnprintf(result
, needed
+ 1, fmtstring
, argptr
);
220 if(varname
== NULL
) { tpl_addTmp(vars
, result
); }
223 tpl_addVar(vars
, addmode
, varname
, result
);
229 /* Returns the value for a name or an empty string if nothing was found. */
230 char *tpl_getVar(struct templatevars
*vars
, const char *name
)
234 for(i
= (*vars
).varscnt
- 1; i
>= 0; --i
)
236 if(strcmp((*vars
).names
[i
], name
) == 0)
238 result
= (*vars
).values
[i
];
242 if(result
== NULL
) { return ""; }
245 if((*vars
).vartypes
[i
] == TPLADDONCE
|| (*vars
).vartypes
[i
] == TPLAPPENDONCE
)
247 // This is a one-time-use variable which gets cleaned up automatically after retrieving it
248 if(!cs_malloc(&(*vars
).values
[i
], 1))
250 (*vars
).values
[i
] = result
;
256 (*vars
).values
[i
][0] = '\0';
257 return tpl_addTmp(vars
, result
);
260 else { return result
; }
264 /* Initializes all variables for a templatevar-structure and returns a pointer to it. Make
265 sure to call tpl_clear() when you are finished or you'll run into a memory leak! */
266 struct templatevars
*tpl_create(void)
268 struct templatevars
*vars
;
269 if(!cs_malloc(&vars
, sizeof(struct templatevars
))) { return NULL
; }
270 (*vars
).varsalloc
= 64;
272 (*vars
).tmpalloc
= 64;
274 if(!cs_malloc(&(*vars
).names
, (*vars
).varsalloc
* sizeof(char **)))
279 if(!cs_malloc(&(*vars
).values
, (*vars
).varsalloc
* sizeof(char **)))
281 NULLFREE((*vars
).names
);
285 if(!cs_malloc(&(*vars
).vartypes
, (*vars
).varsalloc
* sizeof(uint8_t *)))
287 NULLFREE((*vars
).names
);
288 NULLFREE((*vars
).values
);
292 if(!cs_malloc(&(*vars
).tmp
, (*vars
).tmpalloc
* sizeof(char **)))
294 NULLFREE((*vars
).names
);
295 NULLFREE((*vars
).values
);
296 NULLFREE((*vars
).vartypes
);
303 /* Clears all allocated memory for the specified templatevar-structure. */
304 void tpl_clear(struct templatevars
*vars
)
307 for(i
= (*vars
).varscnt
- 1; i
>= 0; --i
)
309 NULLFREE((*vars
).names
[i
]);
310 NULLFREE((*vars
).values
[i
]);
312 NULLFREE((*vars
).names
);
313 NULLFREE((*vars
).values
);
314 NULLFREE((*vars
).vartypes
);
315 for(i
= (*vars
).tmpcnt
- 1; i
>= 0; --i
)
317 NULLFREE((*vars
).tmp
[i
]);
319 NULLFREE((*vars
).tmp
);
323 /* Creates a path to a template file. You need to set the resultsize to the correct size of result. */
324 char *tpl_getFilePathInSubdir(const char *path
, const char *subdir
, const char *name
, const char *ext
, char *result
, uint32_t resultsize
)
326 int path_len
= cs_strlen(path
);
327 const char *path_fixup
= "";
328 if(path_len
&& path
[path_len
- 1] != '/')
329 { path_fixup
= "/"; }
330 if(path_len
+ cs_strlen(path_fixup
) + cs_strlen(name
) + cs_strlen(subdir
) + cs_strlen(ext
) < resultsize
)
332 snprintf(result
, resultsize
, "%s%s%s%s%s", path
, path_fixup
, subdir
, name
, ext
);
334 else { result
[0] = '\0'; }
338 char *tpl_getTplPath(const char *name
, const char *path
, char *result
, uint32_t resultsize
)
340 return tpl_getFilePathInSubdir(path
, "", name
, ".tpl", result
, resultsize
);
343 #define check_conf(CONFIG_VAR, text) \
344 if (config_enabled(CONFIG_VAR) && strncmp(#CONFIG_VAR, text, len) == 0) { ok = 1; break; }
346 /* Returns an unparsed template either from disk or from internal templates.
347 Note: You must free() the result after using it and you may get NULL if an error occured!*/
348 char *tpl_getUnparsedTpl(const char *name
, int8_t removeHeader
, const char *subdir
)
354 tpl_path
= (cfg
.http_piconpath
&& cs_strlen(name
) > 3 && name
[0] == 'I' && name
[1] == 'C' && name
[2] == '_') ? cfg
.http_piconpath
: cfg
.http_tpl
;
359 if((cs_strlen(tpl_getFilePathInSubdir(tpl_path
, subdir
, name
, ".tpl", path
, 255)) > 0 && file_exists(path
))
360 || (cs_strlen(subdir
) > 0
361 && cs_strlen(tpl_getFilePathInSubdir(tpl_path
, "" , name
, ".tpl", path
, 255)) > 0 && file_exists(path
)))
365 memset(buffer
, 0, sizeof(buffer
));
366 int32_t readen
, allocated
= 1025, offset
, size
= 0;
367 if(!cs_malloc(&result
, allocated
)) { return NULL
; }
368 if((fp
= fopen(path
, "r")) != NULL
)
370 // Use as read size sizeof(buffer) - 1 to ensure that buffer is
371 // zero terminated otherwise strstr can segfault!
372 while((readen
= fread(buffer
, 1, sizeof(buffer
) - 1, fp
)) > 0)
375 if(size
== 0 && removeHeader
)
377 /* Remove version string from output and check if it is valid for output */
378 char *pch1
= strstr(buffer
, "<!--OSCam");
381 char *pch2
= strstr(pch1
, "-->");
384 offset
= pch2
- buffer
+ 4;
387 char *ptr1
, *ptr2
, *saveptr1
= NULL
, *saveptr2
= NULL
;
388 for(i
= 0, ptr1
= strtok_r(pch1
+ 10, ";", &saveptr1
); (ptr1
) && i
< 4 ; ptr1
= strtok_r(NULL
, ";", &saveptr1
), i
++)
390 if(i
== 3 && cs_strlen(ptr1
) > 2)
393 for(ptr2
= strtok_r(ptr1
, ",", &saveptr2
); (ptr2
) && ok
== 0 ; ptr2
= strtok_r(NULL
, ",", &saveptr2
))
395 size_t len
= cs_strlen(ptr2
);
396 check_conf(WITH_CARDREADER
, ptr2
);
397 check_conf(CARDREADER_PHOENIX
, ptr2
);
398 check_conf(CARDREADER_DRECAS
, ptr2
);
399 check_conf(CARDREADER_INTERNAL_AZBOX
, ptr2
);
400 check_conf(CARDREADER_INTERNAL_COOLAPI
, ptr2
);
401 check_conf(CARDREADER_INTERNAL_SCI
, ptr2
);
402 check_conf(CARDREADER_SC8IN1
, ptr2
);
403 check_conf(CARDREADER_MP35
, ptr2
);
404 check_conf(CARDREADER_SMARGO
, ptr2
);
405 check_conf(CARDREADER_PCSC
, ptr2
);
406 check_conf(CARDREADER_SMART
, ptr2
);
407 check_conf(CARDREADER_DB2COM
, ptr2
);
408 check_conf(CARDREADER_STAPI
, ptr2
);
409 check_conf(CARDREADER_STAPI5
, ptr2
);
410 check_conf(WEBIF_LIVELOG
, ptr2
);
411 check_conf(WEBIF_JQUERY
, ptr2
);
412 check_conf(CS_ANTICASC
, ptr2
);
413 check_conf(CS_CACHEEX
, ptr2
);
414 check_conf(CS_CACHEEX_AIO
, ptr2
);
415 check_conf(HAVE_DVBAPI
, ptr2
);
416 check_conf(WITH_NEUTRINO
, ptr2
);
417 check_conf(READ_SDT_CHARSETS
, ptr2
);
418 check_conf(CLOCKFIX
, ptr2
);
419 check_conf(IPV6SUPPORT
, ptr2
);
420 check_conf(LCDSUPPORT
, ptr2
);
421 check_conf(LEDSUPPORT
, ptr2
);
422 check_conf(MODULE_CAMD33
, ptr2
);
423 check_conf(MODULE_CAMD35
, ptr2
);
424 check_conf(MODULE_CAMD35_TCP
, ptr2
);
425 check_conf(MODULE_CCCAM
, ptr2
);
426 check_conf(MODULE_CCCSHARE
, ptr2
);
427 check_conf(MODULE_CONSTCW
, ptr2
);
428 check_conf(MODULE_GBOX
, ptr2
);
429 check_conf(MODULE_GHTTP
, ptr2
);
430 check_conf(MODULE_MONITOR
, ptr2
);
431 check_conf(MODULE_NEWCAMD
, ptr2
);
432 check_conf(MODULE_PANDORA
, ptr2
);
433 check_conf(MODULE_RADEGAST
, ptr2
);
434 check_conf(MODULE_SERIAL
, ptr2
);
435 check_conf(MODULE_CW_CYCLE_CHECK
, ptr2
);
436 check_conf(READER_BULCRYPT
, ptr2
);
437 check_conf(READER_CONAX
, ptr2
);
438 check_conf(READER_CRYPTOWORKS
, ptr2
);
439 check_conf(READER_GRIFFIN
, ptr2
);
440 check_conf(READER_DGCRYPT
, ptr2
);
441 check_conf(READER_DRE
, ptr2
);
442 check_conf(READER_IRDETO
, ptr2
);
443 check_conf(READER_NAGRA
, ptr2
);
444 check_conf(READER_NAGRA_MERLIN
, ptr2
);
445 check_conf(READER_SECA
, ptr2
);
446 check_conf(READER_TONGFANG
, ptr2
);
447 check_conf(READER_VIACCESS
, ptr2
);
448 check_conf(READER_VIDEOGUARD
, ptr2
);
449 check_conf(WITH_CARDREADER
, ptr2
);
450 check_conf(WITH_DEBUG
, ptr2
);
451 check_conf(WITH_LB
, ptr2
);
452 check_conf(WITH_LIBCRYPTO
, ptr2
);
453 check_conf(WITH_SSL
, ptr2
);
454 check_conf(WITH_STAPI
, ptr2
);
455 check_conf(WITH_STAPI5
, ptr2
);
456 check_conf(WITH_EMU
, ptr2
);
469 if(allocated
< size
+ readen
+ 1)
471 allocated
+= size
+ 1024;
472 if(!cs_realloc(&result
, allocated
))
478 memcpy(result
+ size
, buffer
+ offset
, readen
);
489 uint32_t name_hash
= jhash(name
, cs_strlen(name
));
490 for(i
= 0; i
< tpls_count
; i
++)
492 if(tpls
[i
].tpl_name_hash
== name_hash
)
501 const struct tpl
*tpl
= &tpls
[i
];
502 if(!cs_malloc(&result
, tpl
->tpl_data_len
+ 1)) { return NULL
; } // +1 to accomodate \0 at the end
503 memcpy(result
, tpl
->tpl_data
, tpl
->tpl_data_len
);
507 if(!cs_malloc(&result
, 1)) { return NULL
; } // Return empty string
512 /* Returns the specified template with all variables/other templates replaced or an
513 empty string if the template doesn't exist. Do not free the result yourself, it
514 will get automatically cleaned up! */
515 char *tpl_getTpl(struct templatevars
*vars
, const char *name
)
517 char *tplorg
= tpl_getUnparsedTpl(name
, 1, tpl_getVar(vars
, "SUBDIR"));
518 if(!tplorg
) { return ""; }
519 char *tplend
= tplorg
+ cs_strlen(tplorg
);
520 char *pch
, *pch2
, *tpl
= tplorg
;
523 int32_t tmp
, respos
= 0;
524 int32_t allocated
= 2 * cs_strlen(tpl
) + 1;
526 if(!cs_malloc(&result
, allocated
)) { return ""; }
530 if(tpl
[0] == '#' && tpl
[1] == '#' && tpl
[2] != '#')
534 while(pch
[0] != '\0' && (pch
[0] != '#' || pch
[1] != '#')) { ++pch
; }
535 if(pch
- pch2
< 32 && pch
[0] == '#' && pch
[1] == '#')
537 memcpy(varname
, pch2
+ 2, pch
- pch2
- 2);
538 varname
[pch
- pch2
- 2] = '\0';
539 if(strncmp(varname
, "TPL", 3) == 0)
541 if((*vars
).messages
> 0 || strncmp(varname
, "TPLMESSAGE", 10) != 0)
542 { pch2
= tpl_getTpl(vars
, varname
+ 3); }
547 pch2
= tpl_getVar(vars
, varname
);
549 tmp
= cs_strlen(pch2
);
550 if(tmp
+ respos
+ 2 >= allocated
)
552 allocated
= tmp
+ respos
+ 256;
553 if(!cs_realloc(&result
, allocated
)) { return ""; }
555 memcpy(result
+ respos
, pch2
, tmp
);
562 if(respos
+ 2 >= allocated
)
564 allocated
= respos
+ 256;
565 if(!cs_realloc(&result
, allocated
)) { return ""; }
567 result
[respos
] = tpl
[0];
573 result
[respos
] = '\0';
574 tpl_addTmp(vars
, result
);
578 /* Saves all templates to the specified paths. Existing files will be overwritten! */
579 int32_t tpl_saveIncludedTpls(const char *path
)
584 for(i
= 0; i
< tpls_count
; ++i
)
586 const struct tpl
*tpl
= &tpls
[i
];
587 if(cs_strlen(tpl_getTplPath(tpl
->tpl_name
, path
, tmp
, 256)) > 0 && (fp
= fopen(tmp
, "w")) != NULL
)
589 if(strncmp(tpl
->tpl_name
, "IC", 2) != 0)
591 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
);
593 fwrite(tpl
->tpl_data
, tpl
->tpl_data_len
, 1, fp
);
601 /* Checks all disk templates in a directory if they are still current or may need upgrade! */
602 void tpl_checkOneDirDiskRevisions(const char *subdir
)
604 char dirpath
[255] = "\0";
605 snprintf(dirpath
, 255, "%s%s", cfg
.http_tpl
? cfg
.http_tpl
: "", subdir
);
608 for(i
= 0; i
< tpls_count
; ++i
)
610 const struct tpl
*tpl
= &tpls
[i
];
611 if(strncmp(tpl
->tpl_name
, "IC", 2) != 0 && cs_strlen(tpl_getTplPath(tpl
->tpl_name
, dirpath
, path
, 255)) > 0 && file_exists(path
))
614 char *tplorg
= tpl_getUnparsedTpl(tpl
->tpl_name
, 0, subdir
);
615 unsigned long checksum
= 0, curchecksum
= crc32(0L, (uint8_t *)tpl
->tpl_data
, tpl
->tpl_data_len
);
616 char *ifdefs
= "", *pch1
= strstr(tplorg
, "<!--OSCam");
619 char *version
= "?", *revision
= "?";
620 char *pch2
= strstr(pch1
, "-->");
625 char *ptr1
, *saveptr1
= NULL
;
626 for(j
= 0, ptr1
= strtok_r(pch1
+ 10, ";", &saveptr1
); (ptr1
) && j
< 4 ; ptr1
= strtok_r(NULL
, ";", &saveptr1
), j
++)
628 if(j
== 0) { checksum
= strtoul(ptr1
, NULL
, 10); }
629 else if(j
== 1) { version
= ptr1
; }
630 else if(j
== 2) { revision
= ptr1
; }
631 else if(j
== 3) { ifdefs
= ptr1
; }
634 if(checksum
!= curchecksum
)
636 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
);
640 else { cs_log("WARNING: Your http disk template %s is in the old template format without revision info. Please consider upgrading it!", path
); }
641 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
); }
647 /* Checks whether disk templates need upgrade - including sub-directories */
648 void tpl_checkDiskRevisions(void)
654 tpl_checkOneDirDiskRevisions("");
657 struct dirent
*result
;
659 if((hdir
= opendir(cfg
.http_tpl
)) != NULL
)
661 while(cs_readdir_r(hdir
, &entry
, &result
) == 0 && result
!= NULL
)
663 if(strcmp(".", entry
.d_name
) == 0 || strcmp("..", entry
.d_name
) == 0)
667 snprintf(dirpath
, 255, "%.31s%.31s", cfg
.http_tpl
, entry
.d_name
);
668 if(stat(dirpath
, &s
) == 0)
670 if(s
.st_mode
& S_IFDIR
)
672 snprintf(subdir
, 255,
679 tpl_checkOneDirDiskRevisions(subdir
);
688 /* Helper function for urldecode.*/
689 static int32_t x2i(int32_t i
)
693 if(i
> 9) { i
= i
- 'A' + '9' + 1; }
697 /* Decodes values in a http url. Note: The original value is modified! */
698 void urldecode(char *s
)
707 if(c
== '+') { c
= ' '; }
708 else if(c
== '%' && n
> 2)
713 c
= 16 * x2i(c1
) + x2i(c
);
722 /* Encode values in a http url. Do not call free() or realloc on the returned reference or you will get memory corruption! */
723 char *urlencode(struct templatevars
*vars
, const char *str
)
726 if(!cs_malloc(&buf
, cs_strlen(str
) * 3 + 1)) { return ""; }
727 const char *pstr
= str
;
732 if(isalnum((uint8_t)*pstr
) || *pstr
== '-' || *pstr
== '_' || *pstr
== '.' || *pstr
== '~') { *pbuf
++ = *pstr
; }
733 else if(*pstr
== ' ') { *pbuf
++ = '+'; }
737 *pbuf
++ = to_hex(*pstr
>> 4);
738 *pbuf
++ = to_hex(*pstr
& 15);
743 /* Allocate the needed memory size and store it in the templatevars */
744 if(!cs_realloc(&buf
, cs_strlen(buf
) + 1)) { return ""; }
745 return tpl_addTmp(vars
, buf
);
748 /* XML-Escapes a char array. The returned reference will be automatically cleaned through the templatevars-mechanism tpl_clear().
749 Do not call free() or realloc on the returned reference or you will get memory corruption! */
750 char *xml_encode(struct templatevars
*vars
, const char *chartoencode
)
752 if(!chartoencode
) { return ""; }
753 int32_t i
, pos
= 0, len
= cs_strlen(chartoencode
);
756 /* In worst case, every character could get converted to 6 chars (we only support ASCII, for Unicode it would be 7)*/
757 if(!cs_malloc(&encoded
, len
* 6 + 1)) { return ""; }
758 for(i
= 0; i
< len
; ++i
)
760 uint8_t tmp
= chartoencode
[i
];
764 memcpy(encoded
+ pos
, "&", 5);
768 memcpy(encoded
+ pos
, "<", 4);
772 memcpy(encoded
+ pos
, ">", 4);
776 memcpy(encoded
+ pos
, """, 6);
780 memcpy(encoded
+ pos
, "'", 6);
784 memcpy(encoded
+ pos
, "\n", 1);
788 if(tmp
< 32 || tmp
> 127)
790 snprintf(buffer
, 7, "&#%d;", tmp
);
791 memcpy(encoded
+ pos
, buffer
, cs_strlen(buffer
));
792 pos
+= cs_strlen(buffer
);
801 /* Reduce to the really needed memory size and store it in the templatevars */
802 if(!cs_realloc(&encoded
, pos
+ 1)) { return ""; }
804 return tpl_addTmp(vars
, encoded
);
807 /* Format a seconds integer to hh:mm:ss or dd hh:mm:ss depending hrs >24 */
808 char *sec2timeformat(struct templatevars
*vars
, int32_t seconds
)
812 { return "00:00:00"; }
813 if(!cs_malloc(&value
, 16))
814 { return "00:00:00"; }
815 int32_t secs
= 0, fullmins
= 0, mins
= 0, fullhours
= 0, hours
= 0, days
= 0;
819 fullmins
= seconds
/ 60;
820 mins
= fullmins
% 60;
823 fullhours
= fullmins
/ 60;
824 hours
= fullhours
% 24;
825 days
= fullhours
/ 24;
829 { snprintf(value
, 16, "%02d:%02d:%02d", hours
, mins
, secs
); }
831 { snprintf(value
, 16, "%02dd %02d:%02d:%02d", days
, hours
, mins
, secs
); }
832 return tpl_addTmp(vars
, value
);