source: trunk/oscam-http-helpers.c@ 3790

Last change on this file since 3790 was 3790, checked in by alno, 10 years ago

WebIf: implement usage of javascript in webif. Path for script to set in 'httpjscript=<path>/oscam.js'
If path is empty an internal script is used but it is empty in the moment. Hope for good ideas of community

File size: 13.7 KB
Line 
1//FIXME Not checked on threadsafety yet; after checking please remove this line
2#include "globals.h"
3#ifdef WEBIF
4#include "oscam-http.h"
5
6/* Adds a name->value-mapping or appends to it. You will get a reference back which you may freely
7 use (but you should not call free/realloc on this!)*/
8char *tpl_addVar(struct templatevars *vars, int append, char *name, char *value){
9 int i;
10 char *tmp,*result = NULL;
11 for(i = (*vars).varscnt-1; i >= 0; --i){
12 if(strcmp((*vars).names[i], name) == 0){
13 result = (*vars).values[i];
14 break;
15 }
16 }
17 if(result == NULL){
18 if((*vars).varsalloc <= (*vars).varscnt){
19 (*vars).varsalloc = (*vars).varscnt * 2;
20 (*vars).names = (char**) realloc ((*vars).names, (*vars).varsalloc * sizeof(char**));
21 (*vars).values = (char**) realloc ((*vars).values, (*vars).varsalloc * sizeof(char**));
22 }
23 tmp = (char *) malloc((strlen(name) + 1) * sizeof(char));
24 strcpy(tmp, name);
25 (*vars).names[(*vars).varscnt] = tmp;
26 tmp = (char *) malloc((strlen(value) + 1) * sizeof(char));
27 strcpy(tmp, value);
28 (*vars).values[(*vars).varscnt] = tmp;
29 (*vars).varscnt = (*vars).varscnt + 1;
30 } else {
31 int newlen = strlen(value);
32 if(append == 1){
33 int oldlen = strlen((*vars).values[i]);
34 tmp = (char*) malloc ((oldlen + newlen + 1) * sizeof(char));
35 memcpy(tmp, (*vars).values[i], oldlen);
36 strcpy(tmp + oldlen, value);
37 } else {
38 tmp = (char*) malloc ((newlen + 1) * sizeof(char));
39 strcpy(tmp, value);
40 }
41 free((*vars).values[i]);
42 (*vars).values[i] = tmp;
43 }
44 return tmp;
45}
46
47/* Allows to add a char array which has been allocated by malloc. It will automatically get
48 freed when calling tpl_clear(). Please do NOT free the memory yourself or realloc
49 it after having added the array here! */
50char *tpl_addTmp(struct templatevars *vars, char *value){
51 if((*vars).tmpalloc <= (*vars).tmpcnt){
52 (*vars).tmpalloc = (*vars).tmpcnt * 2;
53 (*vars).tmp = (char**) realloc ((*vars).tmp, (*vars).tmpalloc * sizeof(char**));
54 }
55 (*vars).tmp[(*vars).tmpcnt] = value;
56 (*vars).tmpcnt = (*vars).tmpcnt + 1;
57 return value;
58}
59
60/* Allows to do a dynamic printf without knowing and defining the needed memory size. If you specify
61 varname, the printf-result will be added/appended to the varlist. You will always get a reference
62 back which you may freely use (but you should not call free/realloc on this!)*/
63char *tpl_printf(struct templatevars *vars, int append, char *varname, char *fmtstring, ...){
64 unsigned int allocated = strlen(fmtstring) - (strlen(fmtstring)%16) + 16;
65 char *result, *tmp = (char *) malloc(allocated * sizeof(char));
66 va_list argptr;
67
68 va_start(argptr,fmtstring);
69 vsnprintf(tmp ,allocated, fmtstring, argptr);
70 va_end(argptr);
71 while (strlen(tmp) + 1 == allocated){
72 allocated += 16;
73 tmp = (char *) realloc(tmp, allocated * sizeof(char));
74 va_start(argptr,fmtstring);
75 vsnprintf(tmp, allocated, fmtstring, argptr);
76 va_end(argptr);
77 }
78 result = (char *) malloc(strlen(tmp) + 1 * sizeof(char));
79 strcpy(result, tmp);
80 free(tmp);
81 if(varname == NULL) tpl_addTmp(vars, result);
82 else {
83 char *tmp = tpl_addVar(vars, append, varname, result);
84 free(result);
85 result = tmp;
86 }
87 return result;
88}
89
90/* Returns the value for a name or an empty string if nothing was found. */
91char *tpl_getVar(struct templatevars *vars, char *name){
92 int i;
93 char *result = NULL;
94 for(i = (*vars).varscnt-1; i >= 0; --i){
95 if(strcmp((*vars).names[i], name) == 0){
96 result = (*vars).values[i];
97 break;
98 }
99 }
100 if(result == NULL) return "";
101 else return result;
102}
103
104/* Initializes all variables vor a templatevar-structure and returns a pointer to it. Make
105 sure to call tpl_clear() when you are finished or you'll run into a memory leak! */
106struct templatevars *tpl_create(){
107 struct templatevars *vars = (struct templatevars *) malloc(sizeof(struct templatevars));
108 (*vars).varsalloc = 16;
109 (*vars).varscnt = 0;
110 (*vars).tmpalloc = 16;
111 (*vars).tmpcnt = 0;
112 (*vars).names = (char**) malloc ((*vars).varsalloc * sizeof(char**));
113 (*vars).values = (char**) malloc ((*vars).varsalloc * sizeof(char**));
114 (*vars).tmp = (char**) malloc ((*vars).tmpalloc * sizeof(char**));
115 return vars;
116}
117
118/* Clears all allocated memory for the specified templatevar-structure. */
119void tpl_clear(struct templatevars *vars){
120 int i;
121 for(i = (*vars).varscnt-1; i >= 0; --i){
122 free((*vars).names[i]);
123 free((*vars).values[i]);
124 }
125 free((*vars).names);
126 free((*vars).values);
127 for(i = (*vars).tmpcnt-1; i >= 0; --i){
128 free((*vars).tmp[i]);
129 }
130 free((*vars).tmp);
131 free(vars);
132}
133
134/* Creates a path to a template file. You need to set the resultsize to the correct size of result. */
135char *tpl_getTplPath(const char *name, const char *path, char *result, unsigned int resultsize){
136 char *pch;
137 if((strlen(path) + strlen(name) + 6) <= resultsize){
138 strcpy(result, path);
139 strcat(result, name);
140 strcat(result, ".tpl");
141 result[resultsize - 1] = '\0';
142 for(pch = result + strlen(path); pch[0] != '\0'; ++pch){
143 if(pch[0] == '/' || pch[0] == '\\') pch[0] = ' ';
144 }
145 } else result[0] = '\0';
146 return result;
147}
148
149/* Returns an unparsed template either from disk or from internal templates.
150 Note: You must free() the result after using it!*/
151char *tpl_getUnparsedTpl(const char* name){
152 int i;
153 int tplcnt = sizeof(tpl)/sizeof(char *);
154 int tplmapcnt = sizeof(tplmap)/sizeof(char *);
155 char *result;
156
157 for(i = 0; i < tplcnt; ++i){
158 if(strcmp(name, tpl[i]) == 0) break;
159 }
160
161 if(strlen(cfg->http_tpl) > 0){
162 char path[200];
163 if(strlen(tpl_getTplPath(name, cfg->http_tpl, path, 200)) > 0 && file_exists(path)){
164 FILE *fp;
165 char buffer[1024];
166 int read, allocated = 1025, size = 0;
167 result = (char *) malloc(allocated * sizeof(char));
168 if((fp = fopen(path,"r"))!=NULL){
169 while((read = fread(&buffer,sizeof(char),1024,fp)) > 0){
170 if(allocated < size + read + 1) {
171 allocated += size + 1024;
172 result = (char *) realloc(result, allocated * sizeof(char));
173 }
174 memcpy(result + size, buffer, read);
175 size += read;
176 }
177 result[size] = '\0';
178 fclose (fp);
179 return result;
180 }
181 }
182 }
183 if(i >= 0 && i < tplmapcnt){
184 int len = (strlen(tplmap[i])) + 1;
185 result = (char *) malloc(len * sizeof(char));
186 memcpy(result, tplmap[i], len);
187 } else {
188 result = (char *) malloc(1 * sizeof(char));
189 result[0] = '\0';
190 }
191 return result;
192}
193
194/* Returns the specified template with all variables/other templates replaced or an
195 empty string if the template doesn't exist*/
196char *tpl_getTpl(struct templatevars *vars, const char* name){
197 char *tplorg = tpl_getUnparsedTpl(name);
198 char *tplend = tplorg + strlen(tplorg);
199 char *pch, *pch2, *tpl=tplorg;
200 char varname[33];
201
202 int tmp,respos = 0;
203 int allocated = 2 * strlen(tpl) + 1;
204 char *result = (char *) malloc(allocated * sizeof(char));
205
206 while(tpl < tplend){
207 if(tpl[0] == '#' && tpl[1] == '#' && tpl[2] != '#'){
208 pch2 = tpl;
209 pch = tpl + 2;
210 while(pch[0] != '\0' && (pch[0] != '#' || pch[1] != '#')) ++pch;
211 if(pch - pch2 < 32 && pch[0] == '#' && pch[1] == '#'){
212 memcpy(varname, pch2 + 2, pch - pch2 - 2);
213 varname[pch - pch2 - 2] = '\0';
214 if(strncmp(varname, "TPL", 3) == 0){
215 pch2 = tpl_getTpl(vars, varname + 3);
216 } else {
217 pch2 = tpl_getVar(vars, varname);
218 }
219 tmp = strlen(pch2);
220 if(tmp + respos + 2 >= allocated){
221 allocated = tmp + respos + 256;
222 result = (char *) realloc(result, allocated * sizeof(char));
223 }
224 memcpy(result + respos, pch2, tmp);
225 respos += tmp;
226 tpl = pch + 2;
227 }
228 } else {
229 if(respos + 2 >= allocated){
230 allocated = respos + 256;
231 result = (char *) realloc(result, allocated * sizeof(char));
232 }
233 result[respos] = tpl[0];
234 ++respos;
235 ++tpl;
236 }
237 }
238 free(tplorg);
239 result[respos] = '\0';
240 tpl_addTmp(vars, result);
241 return result;
242}
243
244/* Saves all templates to the specified paths. Existing files will be overwritten! */
245int tpl_saveIncludedTpls(const char *path){
246 int tplcnt = sizeof(tpl)/sizeof(char *);
247 int tplmapcnt = sizeof(tplmap)/sizeof(char *);
248 int i, cnt = 0;
249 char tmp[200];
250 FILE *fp;
251 for(i = 0; i < tplcnt && i < tplmapcnt; ++i){
252 if(strlen(tpl_getTplPath(tpl[i], path, tmp, 200)) > 0 && (fp = fopen(tmp,"w")) != NULL){
253 fwrite(tplmap[i], sizeof(char), strlen(tplmap[i]), fp);
254 fclose (fp);
255 ++cnt;
256 }
257 }
258 return cnt;
259}
260
261/* Parses a value in an authentication string by removing all quotes/whitespace. Note that the original array is modified*/
262char *parse_auth_value(char *value){
263 char *pch = value;
264 char *pch2;
265 value = strstr(value, "=");
266 if(value != NULL){
267 do{
268 ++value;
269 } while (value[0] == ' ' || value[0] == '"');
270 pch = value;
271 for(pch2 = value + strlen(value) - 1; pch2 >= value && (pch2[0] == ' ' || pch2[0] == '"' || pch2[0] == '\r' || pch2[0] == '\n'); --pch2) pch2[0] = '\0';
272 }
273 return pch;
274}
275
276/* Calculates the currently valid nonce value and copies it to result*/
277void calculate_nonce(char *result, int resultlen){
278 char *expectednonce, *noncetmp;
279 noncetmp = (char*) malloc (128*sizeof(char));
280 sprintf(noncetmp, "%d", (int)time(NULL)/AUTHNONCEVALIDSECS);
281 strcat(noncetmp, ":");
282 strcat(noncetmp, noncekey);
283 fflush(stdout);
284 expectednonce =char_to_hex(MD5((unsigned char*)noncetmp, strlen(noncetmp), NULL), MD5_DIGEST_LENGTH, hex2ascii);
285 cs_strncpy(result, expectednonce, resultlen);
286 free(noncetmp);
287 free(expectednonce);
288}
289
290/* Checks if authentication is correct. Returns -1 if not correct, 1 if correct and 2 if nonce isn't valid anymore */
291int check_auth(char *authstring, char *method, char *path, char *expectednonce){
292 int authok = 0, uriok = 0;
293 char *authnonce;
294 char *authnc;
295 char *authcnonce;
296 char *uri;
297 char *authresponse;
298 char *A1tmp, *A2tmp, *A3tmp;
299 char *A1, *A2, *A3;
300 char *pch, *pch2;
301
302 authnonce = "";
303 authnc = "";
304 authcnonce = "";
305 authresponse = "";
306 uri = "";
307 pch = authstring + 22;
308 pch = strtok (pch,",");
309 while (pch != NULL){
310 pch2 = pch;
311 while(pch2[0] == ' ' && pch2[0] != '\0') ++pch2;
312 if(strncmp(pch2, "nonce", 5) == 0){
313 authnonce=parse_auth_value(pch2);
314 } else if (strncmp(pch2, "nc", 2) == 0){
315 authnc=parse_auth_value(pch2);
316 } else if (strncmp(pch2, "cnonce", 6) == 0){
317 authcnonce=parse_auth_value(pch2);
318 } else if (strncmp(pch2, "response", 8) == 0){
319 authresponse=parse_auth_value(pch2);
320 } else if (strncmp(pch2, "uri", 3) == 0){
321 uri=parse_auth_value(pch2);
322 }
323 pch = strtok (NULL, ",");
324 }
325 if(strncmp(uri, path, strlen(path)) == 0) uriok = 1;
326 else {
327 pch2 = uri;
328 for(pch = uri; pch[0] != '\0'; ++pch) {
329 if(pch[0] == '/') pch2 = pch;
330 }
331 if(strncmp(pch2, path, strlen(path)) == 0) uriok = 1;
332 }
333 if(uriok == 1){
334 A1tmp = (char*) malloc ((3 + strlen(cfg->http_user) + strlen(AUTHREALM) + strlen(cfg->http_pwd))*sizeof(char));
335 strcpy(A1tmp, cfg->http_user);
336 strcat(A1tmp, ":");
337 strcat(A1tmp, AUTHREALM);
338 strcat(A1tmp, ":");
339 strcat(A1tmp, cfg->http_pwd);
340 A2tmp = (char*) malloc ((2 + strlen(method) + strlen(uri))*sizeof(char));
341 strcpy(A2tmp, method);
342 strcat(A2tmp, ":");
343 strcat(A2tmp, uri);
344 A1=char_to_hex(MD5((unsigned char*)A1tmp, strlen(A1tmp), NULL), MD5_DIGEST_LENGTH, hex2ascii);
345 A2=char_to_hex(MD5((unsigned char*)A2tmp, strlen(A2tmp), NULL), MD5_DIGEST_LENGTH, hex2ascii);
346 A3tmp = (char*) malloc ((10 + strlen(A1) + strlen(A2) + strlen(authnonce) + strlen(authnc) + strlen(authcnonce))*sizeof(char));
347 strcpy(A3tmp, A1);
348 strcat(A3tmp, ":");
349 strcat(A3tmp, authnonce);
350 strcat(A3tmp, ":");
351 strcat(A3tmp, authnc);
352 strcat(A3tmp, ":");
353 strcat(A3tmp, authcnonce);
354 strcat(A3tmp, ":auth:");
355 strcat(A3tmp, A2);
356 A3=char_to_hex(MD5((unsigned char*)A3tmp, strlen(A3tmp), NULL), MD5_DIGEST_LENGTH, hex2ascii);
357 if(strcmp(A3, authresponse) == 0) {
358 if(strcmp(expectednonce, authnonce) == 0) authok = 1;
359 else authok = 2;
360 }
361 free(A1tmp);
362 free(A2tmp);
363 free(A3tmp);
364 free(A1);
365 free(A2);
366 free(A3);
367 }
368 return authok;
369}
370
371void send_headers(FILE *f, int status, char *title, char *extra, char *mime){
372
373 time_t now;
374 char timebuf[128];
375
376 fprintf(f, "%s %d %s\r\n", PROTOCOL, status, title);
377 fprintf(f, "Server: %s\r\n", SERVER);
378
379 now = time(NULL);
380 strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&now));
381 fprintf(f, "Date: %s\r\n", timebuf);
382
383 if (extra)
384 fprintf(f, "%s\r\n", extra);
385
386 if (mime)
387 fprintf(f, "Content-Type: %s\r\n", mime);
388
389 strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&now));
390 fprintf(f, "Cache-Control: no-store, no-cache, must-revalidate\r\n");
391 fprintf(f, "Expires: Sat, 26 Jul 1997 05:00:00 GMT\r\n");
392 fprintf(f, "Last-Modified: %s\r\n", timebuf);
393 fprintf(f, "Connection: close\r\n");
394 fprintf(f, "\r\n");
395}
396
397void send_css(FILE *f){
398 if(strlen(cfg->http_css) > 0 && file_exists(cfg->http_css) == 1){
399 FILE *fp;
400 char buffer[1024];
401 int read;
402
403 if((fp = fopen(cfg->http_css,"r"))==NULL) return;
404 while((read = fread(&buffer,sizeof(char),1024,fp)) > 0) fwrite(&buffer, sizeof(char), read, f);
405 fclose (fp);
406 } else {
407 fputs(CSS, f);
408 }
409}
410
411void send_js(FILE *f){
412 if(strlen(cfg->http_jscript) > 0 && file_exists(cfg->http_jscript) == 1){
413 FILE *fp;
414 char buffer[1024];
415 int read;
416
417 if((fp = fopen(cfg->http_jscript,"r"))==NULL) return;
418 while((read = fread(&buffer,sizeof(char),1024,fp)) > 0) fwrite(&buffer, sizeof(char), read, f);
419 fclose (fp);
420 } else {
421 fputs(JSCRIPT, f);
422 }
423}
424
425void send_error(FILE *f, int status, char *title, char *extra, char *text){
426 send_headers(f, status, title, extra, "text/html");
427 fprintf(f, "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\r\n", status, title);
428 fprintf(f, "<BODY><H4>%d %s</H4>\r\n", status, title);
429 fprintf(f, "%s\r\n", text);
430 fprintf(f, "</BODY></HTML>\r\n");
431}
432
433char *getParam(struct uriparams *params, char *name){
434 int i;
435 for(i=(*params).paramcount-1; i>=0; --i){
436 if(strcmp((*params).params[i], name) == 0) return (*params).values[i];
437 }
438 return "";
439}
440
441char *getParamDef(struct uriparams *params, char *name, char* def){
442 int i;
443 for(i=(*params).paramcount-1; i>=0; --i){
444 if(strcmp((*params).params[i], name) == 0) return (*params).values[i];
445 }
446 return def;
447}
448#endif
Note: See TracBrowser for help on using the repository browser.