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

Last change on this file since 3168 was 3168, checked in by _network, 10 years ago

merge modular branch with trunk

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