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

Last change on this file since 1693 was 1693, checked in by merek, 11 years ago

Merge Webinterface into Trunk - Use -DWEBIF=1 with cmake to build with Webinterface - For make add -DWEBIF to target in Makefile to build with Webinterface for, thanks to Alno and Streamboard community

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