Rev 12288 | Rev 12373 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
10 | reyssat | 1 | /* Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis |
2 | * |
||
3 | * This program is free software; you can redistribute it and/or modify |
||
4 | * it under the terms of the GNU General Public License as published by |
||
5 | * the Free Software Foundation; either version 2 of the License, or |
||
6 | * (at your option) any later version. |
||
7 | * |
||
8 | * This program is distributed in the hope that it will be useful, |
||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
11 | * GNU General Public License for more details. |
||
12 | * |
||
13 | * You should have received a copy of the GNU General Public License |
||
14 | * along with this program; if not, write to the Free Software |
||
15 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
||
16 | */ |
||
17 | |||
8155 | bpr | 18 | /* Web exerciser */ |
10 | reyssat | 19 | |
8178 | bpr | 20 | #include "wims.h" |
21 | |||
8121 | bpr | 22 | struct { |
12263 | bpr | 23 | char *name; |
24 | char *font; |
||
8121 | bpr | 25 | } charname[]={ |
12263 | bpr | 26 | {"en","windows-1252"}, |
27 | {"fr","windows-1252"}, |
||
28 | {"es","windows-1252"}, |
||
29 | {"cn","gb2312"}, |
||
30 | {"de","windows-1252"}, |
||
31 | {"it","windows-1252"}, |
||
32 | {"nl","windows-1252"}, |
||
33 | {"si","iso-8859-2"}, |
||
34 | {"ar","iso-8859-6"}, |
||
35 | {"tw","big5"}, |
||
36 | {"pt","windows-1252"}, |
||
37 | {"ca","windows-1252"}, |
||
38 | {"pt","windows-1252"}, |
||
39 | {"ru","iso-8859-5"}, |
||
40 | {"ty","iso-8859-13"} |
||
8121 | bpr | 41 | }; |
42 | |||
43 | #define charname_no (sizeof(charname)/sizeof(charname[0])) |
||
44 | |||
8155 | bpr | 45 | /* left to right or right to left writing */ |
8121 | bpr | 46 | struct { |
12263 | bpr | 47 | char *name; |
48 | char *dirn; |
||
8121 | bpr | 49 | } dirnname[]={ |
12263 | bpr | 50 | {"en","ltr"}, |
51 | {"fr","ltr"}, |
||
52 | {"es","ltr"}, |
||
53 | {"cn","ltr"}, |
||
54 | {"de","ltr"}, |
||
55 | {"it","ltr"}, |
||
56 | {"nl","ltr"}, |
||
57 | {"si","ltr"}, |
||
58 | {"ar","rtl"}, |
||
59 | {"tw","ltr"}, |
||
60 | {"pt","ltr"}, |
||
61 | {"ca","ltr"}, |
||
62 | {"pt","ltr"}, |
||
63 | {"ru","ltr"}, |
||
64 | {"ty","ltr"} |
||
8121 | bpr | 65 | |
66 | }; |
||
67 | |||
68 | #define dirnname_no (sizeof(dirnname)/sizeof(dirnname[0])) |
||
69 | |||
70 | |||
10 | reyssat | 71 | #define evalue strevalue |
72 | char *robot_session="../tmp/robot"; |
||
73 | int robot_access=0,human_access=0; |
||
74 | int user_error_nolog=0; |
||
75 | char *good_agent[]={ |
||
12263 | bpr | 76 | "Mozilla","Netscape","Opera","WIMS", |
77 | "MSIE","Konqueror","Java" |
||
10 | reyssat | 78 | }; |
79 | #define good_agent_no (sizeof(good_agent)/sizeof(good_agent[0])) |
||
80 | |||
81 | char *bad_agent[]={ /* These are really bad agents: prohibited. */ |
||
12263 | bpr | 82 | "HTTrack","MemoWeb","Teleport","Offline","Wget","eCatch", |
83 | "Powermarks","EmailSiphon", "WebCopier" |
||
10 | reyssat | 84 | }; |
85 | #define bad_agent_no (sizeof(bad_agent)/sizeof(bad_agent[0])) |
||
86 | |||
87 | /* used for debugging */ |
||
88 | int debug=0; |
||
89 | |||
90 | char class_dir[MAX_FNAME+1]; /* directory name of this class */ |
||
91 | |||
8185 | bpr | 92 | struct user_variable user_variable[MAX_VAR_NUM]; |
10 | reyssat | 93 | int user_var_no; |
94 | |||
8185 | bpr | 95 | struct VAR_DEF var_def[MAX_VAR_NUM]; |
10 | reyssat | 96 | int defined_var_total; |
97 | |||
7673 | bpr | 98 | /* Destinated to module error messages */ |
10 | reyssat | 99 | WORKING_FILE m_file,svar_file,mcache[MAX_MCACHE]; |
100 | int mcachecnt; |
||
101 | |||
7673 | bpr | 102 | /* Limit for any data working files. */ |
10 | reyssat | 103 | int WORKFILE_LIMIT=2048*1024; |
104 | |||
7673 | bpr | 105 | /* whether the user has defined language */ |
10 | reyssat | 106 | int user_lang=0; |
107 | |||
7673 | bpr | 108 | /* for instex grouping */ |
10 | reyssat | 109 | int instex_cnt=0, getwimstexsize=1; |
110 | char instex_src[MAX_LINELEN+1], instex_fname[MAX_LINELEN+1]; |
||
111 | char *instex_processor="tex..gif"; |
||
112 | |||
7673 | bpr | 113 | /* Cookie management */ |
10 | reyssat | 114 | char cookiegot[256], cookieset[256], cookieheader[64]="WIMSUSER="; |
115 | |||
7673 | bpr | 116 | /* multipart boundary */ |
10 | reyssat | 117 | char mpboundary[1024]; |
118 | int deplen=0; /* length of deposit */ |
||
119 | |||
120 | int confset=0; /* set to 1 if setvar for config */ |
||
121 | |||
7673 | bpr | 122 | /* Operating mode: default, popup, raw, etc. */ |
8185 | bpr | 123 | |
10 | reyssat | 124 | int mode=mode_default; |
125 | |||
7673 | bpr | 126 | /* Switch; notice subroutines wherether we are outputing. */ |
10 | reyssat | 127 | int outputing; |
128 | |||
129 | char *home_module="home"; /* name of home module */ |
||
7673 | bpr | 130 | extern char **environ; /* table of environment variables */ |
10 | reyssat | 131 | int module_defined=0; |
132 | |||
133 | /* directory prefix buffers */ |
||
134 | char session_prefix[MAX_FNAME+1], s2_prefix[MAX_FNAME+1], module_prefix[MAX_FNAME+1]; |
||
135 | |||
136 | char *stdinbuf; |
||
7673 | bpr | 137 | int sesrandomtab[MAX_SESRANDOM]; /* session random values */ |
10 | reyssat | 138 | char multiexec_random[64]; |
139 | int executed_gotos; /* number of goto's executed. to check with GOTO_LIMIT. */ |
||
140 | int insert_no; /* number of instex, insplot, insPLOT. */ |
||
141 | int output_length; /* length of the output. */ |
||
7673 | bpr | 142 | int isexam=0; /* non-zero if request is exam */ |
143 | int simuxam=0; /* exam is simulation */ |
||
144 | int is_multiexec=0; /* for execredirected */ |
||
10 | reyssat | 145 | int multiexec_index; |
146 | int direct_datafile=0; |
||
147 | int exec_is_module=0; |
||
148 | /* root directory of modules */ |
||
149 | char *module_dir="modules"; |
||
150 | int new_session=0; /* =1 if new session created */ |
||
7673 | bpr | 151 | int good_httpd=0; /* Whether the http server is intelligent */ |
10 | reyssat | 152 | /* int internal_sql=0; */ /* for internal sql use */ |
153 | int direct_exec=0; /* calc routine is exected by exec if 1 */ |
||
154 | int print_precision=8; /* precision when printing real numbers */ |
||
155 | int session_serial; /* request serial for session control */ |
||
7673 | bpr | 156 | int form_access=0; /* identifies form access, for robot identification */ |
157 | int lastout_file=-1; /* file to hold last output */ |
||
158 | char *instex_style=""; /* "": text "$": math "$$": displaymath */ |
||
159 | int instex_usedynamic=0; /* always dynamic if 1 */ |
||
160 | int wrapexec=0; /* if set to 1, change uid (nobody) to euid (wims). |
||
161 | * if set to -1, change euid to uid when exec(). */ |
||
162 | int parm_restore=0; /* Restoring saved parameters? */ |
||
163 | int exec_wait=1; /* whether to wait for fork return */ |
||
164 | int execnt=0; /* count executions */ |
||
165 | int readnest; /* nested read count */ |
||
166 | int mfilecnt=0; /* count working files */ |
||
167 | int forceresume=0; /* force user to resume old request */ |
||
168 | int manageable=0; /* whether the connection may be site manager |
||
169 | * 0: no; 1: maybe; 2: sure */ |
||
170 | int ismhelp=0; /* 1 if session is in mhelp. */ |
||
171 | int getvar_len; /* length of the last-got variable. */ |
||
172 | int noout=0; /* if set to 1 then output is skipped */ |
||
173 | char tmp_dir[MAX_FNAME+1]; /* temporary directory */ |
||
174 | char *bin_dir="bin"; /* directory containing executable scripts and programs. */ |
||
175 | char cwdbuf[MAX_FNAME+1]; /* store current working directory */ |
||
176 | char var_hacking=0; /* Trying to hack a variable? */ |
||
10 | reyssat | 177 | char *tmp_debug="no"; |
11104 | bpr | 178 | char *tmp_debug_var=""; |
7673 | bpr | 179 | char ins_alt[MAX_LINELEN+1]; /* dynamic insertion alternative text */ |
180 | char *devel_modules="close"; /* whether to open devel modules */ |
||
181 | int isclassmodule=0; /* 1 if the module is class module */ |
||
182 | int isdevelmodule=0; /* development module? */ |
||
183 | int setcookie=0; /* 1 if need to set cookie */ |
||
184 | int killpid=0; /* pid of process to kill by alarm */ |
||
185 | char *mathalign_sup1, *mathalign_sup2; /* see mathalign_base */ |
||
186 | int substnest=0; /* nesting level of substit() */ |
||
10 | reyssat | 187 | int exodepOK=1; |
7673 | bpr | 188 | long int startmtime; /* start time in milliseconds */ |
189 | long int startmtime2; /* start time in microseconds */ |
||
190 | int backslash_insmath=0; /* \(...) substitution? */ |
||
191 | char examlogf[MAX_FNAME+1]; /* examlog file name */ |
||
192 | char examlogd[MAX_FNAME+1]; /* examlog file name */ |
||
193 | char exam_sheetexo[32]; /* sheet data of an exam */ |
||
10 | reyssat | 194 | char loadavg[64]; |
7673 | bpr | 195 | /* user file variable access control. */ |
10 | reyssat | 196 | char *var_readable, *var_writable, *var_nr, *var_nw, *var_pfx; |
197 | int hostcquota; |
||
7673 | bpr | 198 | int var_noexport; /* do not export variable */ |
10 | reyssat | 199 | |
7673 | bpr | 200 | char tmplbuf[MAX_LINELEN+1]; /* for temporary uses not thru subroutines. */ |
10 | reyssat | 201 | |
7673 | bpr | 202 | struct tm *now, Now; /* time of request */ |
10 | reyssat | 203 | time_t nowtime, limtime, limtimex; |
204 | char nowstr[32]; |
||
205 | |||
7673 | bpr | 206 | /* Resource limits. Capital names are reserved by system. */ |
207 | int rlimit_cpu=20; /* cpu time in seconds */ |
||
10 | reyssat | 208 | int rlimit_fsize=8388608;/* file size */ |
5222 | guerimand | 209 | int rlimit_as=614457600;/* virtual memory size */ |
210 | int rlimit_data=204857600;/* data segment size; maxima requires a lot (must be lower than rlimit_as)*/ |
||
10 | reyssat | 211 | int rlimit_stack=2097152;/* stack size */ |
7673 | bpr | 212 | int rlimit_core=0; /* core dump size */ |
213 | int rlimit_rss=16777216; /* resident size */ |
||
214 | int rlimit_nproc=1024; /* number of processes */ |
||
215 | int rlimit_nofile=512; /* number of open files */ |
||
10 | reyssat | 216 | int rlimit_memlock=2097152;/* locked-in-memory address space */ |
217 | |||
218 | char *var_str; /* malloc'ed buffer to hold translated query_string */ |
||
219 | |||
7673 | bpr | 220 | /* buffer to hold module's variable definition file, malloc'ed. */ |
10 | reyssat | 221 | char *var_def_buf; |
222 | |||
8185 | bpr | 223 | /* job_identifier is even a reserved variable name */ |
10 | reyssat | 224 | char job_identifier[32]; |
225 | |||
8185 | bpr | 226 | /* site manager definition IPv4 IPv6*/ |
4648 | bpr | 227 | char *manager_site="127.0.0.1 ::1"; |
10 | reyssat | 228 | int manager_https=0; |
229 | |||
8185 | bpr | 230 | /* sheet and exercise information */ |
10 | reyssat | 231 | int wims_sheet=0,wims_exo=0; |
232 | |||
8185 | bpr | 233 | /* Form method: get or post */ |
10 | reyssat | 234 | char *default_form_method="post"; |
235 | |||
8185 | bpr | 236 | /* Je suis maintenant oblige de passer a l'anglais |
237 | * pour la langue de defaut. |
||
238 | */ |
||
10 | reyssat | 239 | char lang[16]="en"; |
240 | char available_lang[MAX_LANGUAGES][4]={"en","fr"}; |
||
241 | int available_lang_no=2; |
||
242 | char pre_language[4]=""; |
||
10051 | bpr | 243 | FILE *trace_file; |
11104 | bpr | 244 | int trace_indent=0; |
10 | reyssat | 245 | char *protocol="http"; /* http or https */ |
246 | |||
8185 | bpr | 247 | /* check for coordinate input. This will mean that |
248 | * the request is manual, but not robot. |
||
249 | */ |
||
10 | reyssat | 250 | int coord_input=0; |
251 | |||
8155 | bpr | 252 | /* These are readonly environment variable names |
253 | * special parm used for special cmds (getins, etc). |
||
254 | */ |
||
10 | reyssat | 255 | char *ro_name[]={ |
12271 | bpr | 256 | "cmd", |
12263 | bpr | 257 | "empty", |
12271 | bpr | 258 | "lang", |
259 | "module", |
||
260 | "session", |
||
12263 | bpr | 261 | "special_parm", |
262 | "special_parm2", |
||
263 | "special_parm3", |
||
264 | "special_parm4", |
||
265 | "useropts" , |
||
266 | "wims_session", |
||
267 | "wims_subsession", |
||
268 | "wims_window", |
||
269 | "worksheet" |
||
10 | reyssat | 270 | }; |
271 | |||
8185 | bpr | 272 | int RO_NAME_NO=(sizeof(ro_name)/sizeof(ro_name[0])); |
273 | |||
10 | reyssat | 274 | int cmd_type; |
275 | char *commands[]={ |
||
276 | "intro" , "new" , "renew" , "reply" , "config" , "hint" , "help" , |
||
277 | "resume", "next", "getins", "getframe", "getfile", "close", "ref" |
||
278 | }; |
||
279 | |||
8185 | bpr | 280 | int CMD_NO=(sizeof(commands)/sizeof(commands[0])); |
281 | |||
8155 | bpr | 282 | /* stat=0: saved variables |
283 | * all names starting with wims_priv_ are also internal. |
||
284 | */ |
||
8185 | bpr | 285 | struct internal_name internal_name[]={ |
12263 | bpr | 286 | {"accessright", 1}, /* right to access commercial resources */ |
287 | {"caller", 1}, /* caller session */ |
||
288 | {"check", 1}, /* for exam check use */ |
||
289 | {"class", 1}, |
||
290 | {"class_examlog", 1}, |
||
291 | {"class_exolog", 1}, |
||
292 | {"class_limit", 1}, |
||
293 | {"class_quota", 1}, |
||
294 | {"class_regpass", 1}, |
||
295 | {"class_user_limit", 1}, |
||
296 | {"classdir", 1}, |
||
297 | {"classname", 1}, |
||
298 | {"devel_modules", 1}, |
||
299 | {"developer", 1}, |
||
300 | {"doc_quota", 1}, |
||
301 | {"doc_regpass", 1}, |
||
302 | {"email", 1}, |
||
303 | {"exo", 0}, /* exercise number */ |
||
304 | {"exoption", 1}, /* exercise option */ |
||
305 | {"firstname", 1}, |
||
306 | {"forum_limit", 1}, |
||
307 | {"home", 1}, |
||
308 | {"institutionname", 1}, |
||
309 | {"isexam", 0}, /* whether the sheet is an exam sheet */ |
||
310 | {"ismanager", 0}, |
||
311 | {"lastname", 1}, |
||
312 | {"mode", 0}, /* operating mode */ |
||
313 | {"module_start_time", 0}, |
||
314 | {"now", 1}, /* date and time, yyyymmdd.hh:mm:ss */ |
||
315 | {"nowseconds", 1}, /* date and time, seconds since EPOCH */ |
||
316 | {"nr", 1}, /* non-readable variables in user file, words */ |
||
317 | {"nw", 1}, /* non-writable variables in user file, words */ |
||
318 | {"otherclass", 1}, /* Remember other logins */ |
||
319 | {"participate", 1}, /* superclass definition */ |
||
320 | {"prefix", 1}, /* user file prefix */ |
||
321 | {"protocol", 0}, /* http protocol */ |
||
322 | {"rafale", 0}, /* rapidfire request information */ |
||
323 | {"readable", 1}, /* readable variables in user file, words */ |
||
324 | {"realuser", 1}, /* real user for supervisor in gateway */ |
||
325 | {"req_time", 0}, /* time of the request */ |
||
326 | {"sclassdir", 1}, |
||
327 | {"scorereg", 0}, /* score registration flag */ |
||
328 | {"seed", 0}, |
||
329 | {"seed_repeat",0}, |
||
330 | {"seed_score", 0}, |
||
12363 | bpr | 331 | {"seedcnt",0}, |
332 | {"seedlastcnt",0}, |
||
12263 | bpr | 333 | {"sequence", 0}, /* sequence number */ |
334 | {"sescookie", 1}, /* session cookie */ |
||
335 | {"sesdir", 1}, |
||
336 | {"session_serial", 0}, /* request serial in the session */ |
||
337 | {"session_start_time", 0}, |
||
338 | {"sheet", 0}, /* sheet number */ |
||
339 | {"sup_secure", 1}, /* secure level of supervisor */ |
||
340 | {"superclass", 1}, /* superclass code */ |
||
341 | {"superclass_quota", 1}, |
||
342 | {"supertype", 1}, /* superclass type */ |
||
343 | {"supervise", 1}, /* superclass definition */ |
||
344 | {"supervisor", 1}, /* real name of the supervisor */ |
||
345 | {"supervisormail",1}, /* email of supervisor */ |
||
346 | {"trustfile", 1}, /* trusted files in special adm modules */ |
||
347 | {"useropts", 1}, /* user options */ |
||
348 | {"writable", 1}, /* writable variables in user file, words */ |
||
10 | reyssat | 349 | }; |
8185 | bpr | 350 | int INTERNAL_NAME_NO=(sizeof(internal_name)/sizeof(internal_name[0])); |
10 | reyssat | 351 | |
352 | char *httpd_vars[]={ |
||
12263 | bpr | 353 | "HTTP_ACCEPT", |
354 | "HTTP_ACCEPT_CHARSET", |
||
355 | "HTTP_ACCEPT_LANGUAGE", |
||
356 | "HTTP_COOKIE", |
||
357 | "HTTP_HOST", |
||
358 | "HTTP_USER_AGENT", |
||
359 | "HTTP_X_REQUESTED_WITH", |
||
360 | "HTTPS", |
||
361 | "QUERY_STRING", |
||
362 | "REMOTE_HOST", |
||
363 | "REMOTE_ADDR", |
||
364 | "REMOTE_PORT", |
||
365 | "REQUEST_METHOD", |
||
366 | "SCRIPT_NAME", |
||
367 | "SERVER_NAME", |
||
368 | "SERVER_SOFTWARE", |
||
369 | "SERVER_PROTOCOL" |
||
10 | reyssat | 370 | }; |
371 | #define HTTPD_VAR_NO (sizeof(httpd_vars)/sizeof(httpd_vars[0])) |
||
372 | |||
8155 | bpr | 373 | /* security: these variables will not be visible to child processes */ |
10 | reyssat | 374 | char *unsetvars[]={ |
12263 | bpr | 375 | "DOCUMENT_ROOT","SERVER_SIGNATURE","SERVER_SOFTWARE", |
10 | reyssat | 376 | "UNIQUE_ID","HTTP_KEEP_ALIVE","SSL_SESSION_ID" |
377 | }; |
||
378 | #define unsetvarcnt (sizeof(unsetvars)/sizeof(unsetvars[0])) |
||
379 | |||
380 | int httpd_type=httpd_apache; |
||
381 | |||
7673 | bpr | 382 | char *remote_addr=""; /* storing for performance */ |
10 | reyssat | 383 | char *remote_host=""; |
384 | |||
385 | char ref_name[2048], ref_base[2048]; |
||
386 | |||
387 | void put_special_page(char *pname); |
||
388 | void useropts(void); |
||
389 | |||
7673 | bpr | 390 | /* Make certain httpd variables readable by modules */ |
10 | reyssat | 391 | void take_httpd_vars(void) |
392 | { |
||
12263 | bpr | 393 | int i; |
394 | char *p, buf[MAX_NAMELEN+1]; |
||
395 | var_noexport=1; |
||
396 | for(i=0;i<HTTPD_VAR_NO;i++) { |
||
397 | snprintf(buf,sizeof(buf),"httpd_%s",httpd_vars[i]); |
||
398 | if((p=getenv(httpd_vars[i]))!=NULL) setvar(buf,p); |
||
399 | } |
||
400 | var_noexport=0; |
||
7673 | bpr | 401 | |
12263 | bpr | 402 | for(i=0;i<unsetvarcnt;i++) unsetenv(unsetvars[i]); |
403 | /* IPv4 IPv6*/ |
||
404 | p=getenv("REMOTE_ADDR");if(p!=NULL && (strcmp(p,"127.0.0.1")==0 || strcmp(p,"::1")==0)) human_access=1; |
||
405 | p=getenv("HTTP_REFERER"); if(p!=NULL && *p!=0) setvar("wims_referer",p); |
||
10 | reyssat | 406 | } |
407 | |||
11735 | obado | 408 | /* cookie2session */ |
10 | reyssat | 409 | void cookie2session(void) |
410 | { |
||
12263 | bpr | 411 | char cksession[64], psession[32], *ckey, *p; |
412 | char nbuf[MAX_FNAME+1]; |
||
10 | reyssat | 413 | |
12263 | bpr | 414 | if(mode==mode_popup) return; |
415 | if(cookiegot[0]==0) { |
||
416 | ckset: cookiegot[0]=0; setcookie=1; return; |
||
417 | } |
||
418 | p=getvar("special_parm"); |
||
419 | if(p!=NULL && strcmp(p,"ignorecookie")==0) return; |
||
420 | mystrncpy(cksession,cookiegot,sizeof(cksession)); |
||
421 | ckey=strchr(cksession,'-'); |
||
422 | if(ckey==NULL) goto ckset; else *ckey++=0; |
||
423 | p=getvar("wims_session"); if(p==NULL) p=""; |
||
424 | if(strstr(p,"new")!=NULL) goto ckset; |
||
425 | mystrncpy(psession,p,sizeof(psession)); |
||
426 | p=strchr(psession,'_'); if(p!=NULL) *p=0; |
||
427 | if(psession[0]!=0) { |
||
428 | if(strcmp(psession,cksession)==0) return; |
||
429 | if(session_exists(psession)) goto ckset; |
||
430 | if(session_exists(cksession)) goto change; |
||
431 | } |
||
432 | else { |
||
433 | if(!session_exists(cksession)) return; |
||
434 | change: |
||
435 | p=getenv("HTTPS"); |
||
436 | if(p!=NULL && strcasecmp(p,"on")==0) goto ckset; |
||
437 | mkfname(nbuf,"%s/%s/var",session_dir,cksession); |
||
438 | getdef(nbuf,"w_wims_ismanager",tmplbuf); |
||
439 | if(tmplbuf[0]!=0 && tmplbuf[0]!='0') goto ckset; |
||
440 | getdef(nbuf,"w_wims_protocol",tmplbuf); |
||
441 | if(strcasecmp(tmplbuf,"https")==0) goto ckset; |
||
442 | mkfname(nbuf,"%s/%s/var.stat",session_dir,cksession); |
||
443 | getdef(nbuf,"wims_user",tmplbuf); |
||
444 | if(tmplbuf[0]!=0) goto ckset; |
||
445 | force_setvar(ro_name[ro_session],cksession); |
||
446 | setsesdir(cksession); |
||
447 | force_setvar("wims_subsession",""); |
||
448 | session_serial=0; |
||
449 | } |
||
10 | reyssat | 450 | } |
451 | |||
452 | void determine_font(char *l) |
||
453 | { |
||
12263 | bpr | 454 | int i; |
7673 | bpr | 455 | |
12263 | bpr | 456 | if(l==NULL || *l==0) return; |
457 | for(i=0;i<charname_no && memcmp(charname[i].name,l,2);i++); |
||
458 | if(i<charname_no) setvar("wims_main_font",charname[i].font); |
||
10 | reyssat | 459 | } |
460 | |||
3278 | reyssat | 461 | void determine_dirn(char *l) |
462 | { |
||
12263 | bpr | 463 | int i; |
7673 | bpr | 464 | |
12263 | bpr | 465 | if(l==NULL || *l==0) return; |
466 | for(i=0;i<dirnname_no && memcmp(dirnname[i].name,l,2);i++); |
||
467 | if(i<dirnname_no) setvar("wims_main_dirn",dirnname[i].dirn); |
||
3278 | reyssat | 468 | } |
469 | |||
10 | reyssat | 470 | void predetermine_language(void) |
471 | { |
||
12263 | bpr | 472 | char *p; |
473 | int i,n; |
||
10 | reyssat | 474 | |
12263 | bpr | 475 | if(pre_language[0]!=0) p=pre_language; |
476 | else p=getenv("HTTP_ACCEPT_LANGUAGE"); |
||
477 | if(p!=NULL && strlen(p)>=2) { |
||
10 | reyssat | 478 | for(i=0;i<available_lang_no && memcmp(p,available_lang[i],2)!=0;i++); |
12263 | bpr | 479 | if(i<available_lang_no) goto lend; |
480 | } |
||
481 | p=getenv("HTTP_USER_AGENT"); |
||
482 | if(p!=NULL && strlen(p)>=5) { |
||
483 | char *q; |
||
484 | if((q=strchr(p,'['))!=NULL && islower(*(q+1)) && islower(*(q+2)) && *(q+3)==']') { |
||
485 | char bb[4]; |
||
486 | bb[0]=*(q+1);bb[1]=*(q+2);bb[2]=0; |
||
487 | for(i=0;i<available_lang_no && memcmp(bb,available_lang[i],2)!=0;i++); |
||
488 | if(i<available_lang_no) { |
||
489 | memmove(lang,bb,2); lang[2]=0; |
||
490 | goto lend2; |
||
491 | } |
||
10 | reyssat | 492 | } |
12263 | bpr | 493 | } |
494 | p=getenv("HTTP_HOST"); if(p==NULL) goto lend2; |
||
495 | n=strlen(p); if(n<=3 || *(p+n-3)!='.') goto lend2; |
||
496 | p=p+n-2; |
||
497 | for(i=0;i<available_lang_no && memcmp(p,available_lang[i],2)!=0;i++); |
||
498 | if(i<available_lang_no) { |
||
499 | lend: memmove(lang,p,2); lang[2]=0; |
||
500 | lend2: determine_font(lang);determine_dirn(lang); |
||
501 | } |
||
10 | reyssat | 502 | } |
503 | |||
7673 | bpr | 504 | /* print a special page */ |
10 | reyssat | 505 | void put_special_page(char *pname) |
506 | { |
||
12263 | bpr | 507 | determine_font(lang); |
508 | determine_dirn(lang); |
||
509 | phtml_put_base(mkfname(NULL,"%s.phtml.%s",pname,lang),0); |
||
510 | write_logs();free(var_str); |
||
10 | reyssat | 511 | } |
512 | |||
7673 | bpr | 513 | /* check whether the connection is a site manager. */ |
10 | reyssat | 514 | void manager_check(void) |
515 | { |
||
12263 | bpr | 516 | char *p, *pp, buf[16]; |
517 | struct stat confstat; |
||
518 | int i; |
||
7673 | bpr | 519 | |
12263 | bpr | 520 | manageable=0; |
521 | if(robot_access || *manager_site==0 || checkhost(manager_site)<1) |
||
522 | goto mend; |
||
523 | if(manager_https) { |
||
524 | p=getenv("HTTPS"); |
||
525 | if(p==NULL || strcmp(p,"on")!=0) goto mend; |
||
526 | } |
||
8185 | bpr | 527 | /* IPv4 IPv6*/ |
12263 | bpr | 528 | if(strcmp(remote_addr,"127.0.0.1")==0 || strcmp(remote_addr,"::1")==0) { |
529 | int port, port2; |
||
530 | char tester[128]; |
||
531 | p=getenv("REMOTE_PORT"); if(p==NULL) goto mend; |
||
532 | port=atoi(p); if(port<1024 || port>65535) goto mend; |
||
533 | p=getenv("SERVER_PORT"); if(p==NULL) goto mend; |
||
534 | port2=atoi(p); if(port2>=10000 || port2<=0) goto mend; |
||
7673 | bpr | 535 | /* this is very non-portable */ |
12263 | bpr | 536 | manageable=1; |
537 | accessfile(tmplbuf,"r","/proc/net/tcp"); |
||
538 | snprintf(tester,sizeof(tester)," 0100007F:%04X 0100007F:%04X ", |
||
539 | port,port2); |
||
540 | p=strstr(tmplbuf,tester); |
||
541 | if(p!=NULL) { |
||
542 | pp=strchr(p,'\n'); if(pp!=NULL) *pp=0; |
||
543 | if(strlen(p)>=75) { |
||
544 | p=find_word_start(p+70); *find_word_end(p)=0; |
||
545 | if(atoi(p)==geteuid()) manageable=2; |
||
7673 | bpr | 546 | } |
10 | reyssat | 547 | } |
12263 | bpr | 548 | } |
549 | else manageable=1; |
||
550 | i=stat(config_file,&confstat); |
||
551 | if(i==0 && manageable>0 && (confstat.st_mode&(S_IRWXO|S_IRWXG))!=0) manageable=-1; |
||
552 | if(manageable>0 && !trusted_module()) manageable=0; |
||
553 | if(manageable==1) { |
||
554 | accessfile(tmplbuf,"r","%s/.manager",session_prefix); |
||
555 | if(strstr(tmplbuf,"yes")!=NULL) manageable=2; |
||
556 | } |
||
557 | if(manageable==1) { |
||
558 | p=getvar(ro_name[ro_module]); |
||
559 | if(p!=NULL && strncmp(p,"adm/manage",strlen("adm/manage"))==0) { |
||
560 | struct stat pstat; |
||
561 | if(stat("../log/.wimspass",&pstat)==0) { |
||
562 | if((S_IFMT&pstat.st_mode)!=S_IFREG || |
||
563 | ((S_IRWXO|S_IRWXG)&pstat.st_mode)!=0) |
||
564 | manageable=-2; |
||
7673 | bpr | 565 | } |
10 | reyssat | 566 | } |
12263 | bpr | 567 | } |
568 | mend: |
||
569 | mystrncpy(buf,int2str(manageable),sizeof(buf)); |
||
570 | force_setvar("wims_ismanager",buf); |
||
571 | if(manageable>=2) { |
||
572 | struct rlimit rlim; |
||
573 | rlimit_cpu*=10; |
||
574 | rlim.rlim_cur=rlim.rlim_max=rlimit_cpu; |
||
575 | setrlimit(RLIMIT_CPU,&rlim); |
||
576 | mystrncpy(buf,int2str(rlimit_cpu),sizeof(buf)); |
||
577 | setvar("wims_cpu_limit",buf); |
||
578 | initalarm(); |
||
579 | } |
||
10 | reyssat | 580 | } |
581 | |||
7673 | bpr | 582 | /* check for robot access */ |
10 | reyssat | 583 | void robot_check(void) |
584 | { |
||
12263 | bpr | 585 | char *ua, *p, *ses, *c, *mod; |
586 | int i; |
||
10 | reyssat | 587 | |
12263 | bpr | 588 | if(human_access) return; |
589 | mod=getvar(ro_name[ro_module]); |
||
590 | if(mod!=NULL && strcmp(mod,"adm/raw")==0) return; |
||
591 | ses=getvar(ro_name[ro_session]); |
||
7673 | bpr | 592 | /* user has valid session; OK */ |
12263 | bpr | 593 | if(ses!=NULL && strncmp(ses,robot_session,strlen(robot_session))!=0 |
594 | && strchr(ses,'/')==NULL |
||
595 | && ftest(mkfname(NULL,"%s/%s",s2_dir,ses))==is_dir) |
||
596 | return; |
||
597 | ua=getenv("HTTP_USER_AGENT"); if(ua==NULL) ua=""; |
||
598 | ua=find_word_start(ua); |
||
599 | if(strncasecmp(ua,"Mozilla",strlen("Mozilla"))==0 && |
||
600 | (p=strstr(ua,"compatible"))!=NULL) |
||
601 | ua=find_word_start(find_word_end(p)); |
||
602 | if(*ua) { |
||
603 | for(i=0;i<good_agent_no |
||
604 | && strncasecmp(ua,good_agent[i],strlen(good_agent[i]));i++); |
||
605 | if(i<good_agent_no) return; |
||
606 | for(i=0;i<bad_agent_no |
||
607 | && strstr(ua,bad_agent[i])==NULL;i++); |
||
608 | if(i<bad_agent_no) user_error("trapped"); |
||
609 | } |
||
610 | force_setvar(ro_name[ro_session],robot_session); |
||
611 | setsesdir(robot_session); |
||
612 | c=getvar(ro_name[ro_cmd]); |
||
613 | robot_access=1; |
||
614 | if(c!=NULL && strcmp(c,"new") && strcmp(c,"intro")) { |
||
615 | force_setvar(ro_name[ro_cmd],"robot_error"); |
||
616 | nph_header(450); put_special_page("robot"); |
||
617 | flushoutput(); flushlog(); exit(0); |
||
618 | } |
||
10 | reyssat | 619 | } |
620 | |||
7673 | bpr | 621 | /* type=0: ordinary; type=1: multipart/form-data */ |
10 | reyssat | 622 | void parse_query_string(int len, int type) |
623 | { |
||
12263 | bpr | 624 | int i,j,l,v,cmd_defined; |
625 | int parenth=-1, ll, lb, dlen; |
||
626 | char *start, *p, *p1, *pt, *b1=""; |
||
7673 | bpr | 627 | |
12263 | bpr | 628 | cmd_defined=0; |
629 | setvar("wims_subsession",""); |
||
630 | ll=lb=0; |
||
631 | if(type) { |
||
632 | ll=strlen(mpboundary); |
||
633 | start=strstr(var_str,mpboundary); |
||
634 | if(start==NULL) start=var_str+strlen(var_str); |
||
635 | if(strstr(var_str,"\r\n\r\n")!=NULL) b1="\r\n\r\n"; |
||
636 | else b1="\n\n"; |
||
637 | lb=strlen(b1); |
||
638 | } |
||
639 | else start=var_str; |
||
640 | for(v=0, p1=start;p1<var_str+len;p1+=l) { |
||
10 | reyssat | 641 | if(type) { |
12263 | bpr | 642 | char *p2, *p3, *p4, *p5; |
643 | p2=p1+ll; p3=memstr(p2,mpboundary,var_str+len-p2); l=p3-p1; |
||
644 | p=memstr(p2,b1,var_str+len-p2); if(p>=p3) continue; |
||
645 | p+=lb; |
||
646 | if(p3<var_str+len) { |
||
647 | while(*p3!='\n' && p3>p2) p3--; |
||
648 | *p3=0; |
||
649 | p3--; if(*p3=='\r') *p3=0; |
||
650 | } |
||
651 | dlen=p3-p; |
||
652 | p2=memstr(p2,"name=",p3-p2); if(p2>=p3) continue; |
||
653 | p2+=strlen("name="); if(*p2=='"') p2++; |
||
654 | for(p3=p2; myisalnum(*p3) || strchr("._",*p3)!=NULL; p3++); |
||
655 | if(p3==p2) continue; |
||
656 | if(p3-p2==strlen("wims_deposit") && |
||
657 | strncmp(p2,"wims_deposit",p3-p2)==0) { |
||
658 | p4=memstr(p1,"filename=",p-p1); if(p4<p) { |
||
659 | p4+=strlen("filename="); if(*p4=='"') { |
||
660 | p4++; p5=strchr(p4,'"'); |
||
661 | if(p5==NULL || p5-p4>=MAX_FNAME) goto emptyquote; |
||
7673 | bpr | 662 | } |
12263 | bpr | 663 | else { |
664 | emptyquote: |
||
665 | for(p5=p4; p5<p && !isspace(*p5) && |
||
666 | strchr(";\"~#*?=,'",*p5)==NULL; p5++); |
||
667 | } |
||
668 | if(p5>p4) { |
||
669 | *p5=0; |
||
670 | for(p5--; |
||
671 | p5>=p4 && !isspace(*p5) && strchr("/\\:",*p5)==NULL; |
||
672 | p5--); |
||
673 | if(p5>=p4) p4=p5+1; |
||
674 | if(*p4==0) goto noname; |
||
675 | if(strstr(p4,"..")!=NULL || *p4=='.') |
||
676 | p4="noname.file"; |
||
677 | setvar("wims_deposit",p4); |
||
678 | } |
||
679 | else { |
||
680 | noname: setvar("wims_deposit","noname.file"); |
||
681 | } |
||
7673 | bpr | 682 | } |
12263 | bpr | 683 | deplen=dlen; |
684 | } |
||
685 | *p3=0; l-=p2-p1; p1=p2; |
||
686 | } |
||
687 | else { |
||
688 | p1=find_word_start(p1); |
||
689 | l=strlen(p1)+1; p=strchr(p1,'='); |
||
690 | if(p==NULL) p=p1+strlen(p1); |
||
691 | if(*p==0 && l>1) { |
||
692 | user_variable[v].name="no_name"; |
||
693 | user_variable[v].value=p1; |
||
694 | coord_input=1; |
||
695 | goto nnext; |
||
7673 | bpr | 696 | } |
12263 | bpr | 697 | *p++=0; |
698 | } |
||
7673 | bpr | 699 | /* empty name or empty value: ignore */ |
12263 | bpr | 700 | if(*p1==0 || *p==0) continue; |
7673 | bpr | 701 | /* We do not treat names containing '.' */ |
12263 | bpr | 702 | for(pt=strchr(p1,'.'); pt; pt=strchr(++pt,'.')) *pt='_'; |
7673 | bpr | 703 | /* Restrictions on variable names */ |
12263 | bpr | 704 | for(pt=p1; myisalnum(*pt) || *pt=='_'; pt++); |
705 | if(*pt) continue; |
||
706 | if(strcmp(p1,"wims_deposit")!=0) _tolinux(p); |
||
7673 | bpr | 707 | /* This is a restriction: |
8155 | bpr | 708 | * Every parameter must have matching parentheses. |
709 | */ |
||
12263 | bpr | 710 | if(parenth==-1 && strncmp(p1,"freepar_",strlen("freepar_"))!=0 |
7673 | bpr | 711 | && strcmp(p1,"wims_deposit")!=0 |
712 | && check_parentheses(p,1)) parenth=v; |
||
12263 | bpr | 713 | if(strcmp(p1,"special_parm")==0 && strcmp(p,"wims")==0) |
7673 | bpr | 714 | human_access=1; |
12263 | bpr | 715 | j=search_list(ro_name,RO_NAME_NO,sizeof(ro_name[0]),p1); |
716 | if(j>=0) { |
||
717 | if(j==ro_session) { |
||
718 | p=find_word_start(p); *find_word_end(p)=0; |
||
719 | if(strlen(p)>MAX_SESSIONLEN) continue; |
||
720 | if(strcmp(p,robot_session)==0) p=""; |
||
721 | if(strcasecmp(p,"popup")==0) { |
||
722 | mode=mode_popup; |
||
723 | force_setvar("wims_mode","popup"); |
||
724 | force_setvar("session",""); |
||
7673 | bpr | 725 | continue; |
12263 | bpr | 726 | } |
7673 | bpr | 727 | } |
12263 | bpr | 728 | if(j==ro_module) module_defined=1; |
729 | if(j==ro_cmd) { |
||
730 | p=find_word_start(p); *find_word_end(p)=0; |
||
731 | if(strlen(p)>16) continue; |
||
732 | cmd_defined=1; |
||
7673 | bpr | 733 | } |
12263 | bpr | 734 | if(j==ro_lang) { |
735 | if(strlen(p)!=2) continue; |
||
736 | for(i=0;i<available_lang_no && strcmp(available_lang[i],p)!=0;i++); |
||
737 | if(i<available_lang_no) {user_lang=1; ovlstrcpy(lang,p);} |
||
738 | else continue; |
||
739 | } |
||
740 | /* strip leading and trailing '/'s in module name */ |
||
741 | if(j==ro_module) { |
||
742 | p=find_word_start(p); *find_word_end(p)=0; |
||
743 | while(*p=='/') p++; |
||
744 | while(*p!=0 && *(p+strlen(p)-1)=='/') *(p+strlen(p)-1)=0; |
||
745 | if(strlen(p)>MAX_MODULELEN) continue; |
||
746 | } |
||
747 | setvar(p1,p); |
||
748 | if(j==ro_session && mode!=mode_popup) { |
||
749 | char *pp, *pr; |
||
750 | char buf[1024]; |
||
751 | mystrncpy(buf,p,sizeof(buf)); |
||
752 | if((pp=strchr(buf,'.'))!=NULL) { |
||
753 | *pp++=0; session_serial=atoi(pp); |
||
754 | if(pp<0) pp=0; |
||
755 | } |
||
756 | else session_serial=0; |
||
757 | pp=strchr(buf,'_'); |
||
758 | if(pp!=NULL && (pr=strstr(pp,"_mhelp"))!=NULL) { |
||
759 | *pr=0; ismhelp=1; lastout_file=-1; |
||
760 | setvar("wims_inssub","mh"); |
||
761 | } |
||
762 | force_setvar("wims_session",buf); |
||
763 | if(pp!=NULL) force_setvar("wims_subsession",pp); |
||
764 | } |
||
765 | continue; |
||
10 | reyssat | 766 | } |
12263 | bpr | 767 | user_variable[v].name=p1; |
768 | user_variable[v].value=p; |
||
769 | nnext:v++; if(v>=MAX_VAR_NUM) user_error("too_many_variables"); |
||
770 | } |
||
771 | user_var_no=v; |
||
772 | if(parenth>=0) { |
||
773 | char buf[16]; |
||
774 | mystrncpy(buf,int2str(user_var_no),sizeof(buf)); |
||
775 | setvar("user_var_no",buf); |
||
776 | for(i=0;i<user_var_no;i++) { |
||
777 | snprintf(buf,sizeof(buf),"name%d",i); |
||
778 | setvar(buf,user_variable[i].name); |
||
779 | snprintf(buf,sizeof(buf),"value%d",i); |
||
780 | setvar(buf,user_variable[i].value); |
||
10 | reyssat | 781 | } |
12263 | bpr | 782 | mystrncpy(buf,int2str(parenth),sizeof(buf)); |
783 | setvar("bad_parentheses",buf); |
||
784 | user_error("unmatched_parentheses"); |
||
785 | } |
||
786 | p=getenv("SCRIPT_NAME"); |
||
787 | if(p!=NULL && (p=strstr(p,"/getfile/"))!=NULL) { |
||
788 | p+=strlen("/getfile/"); |
||
789 | force_setvar(ro_name[ro_cmd],commands[cmd_getfile]); |
||
790 | force_setvar("special_parm",p); |
||
791 | cmd_defined=1; |
||
792 | } |
||
793 | if(module_defined && !cmd_defined) setvar(ro_name[ro_cmd],commands[cmd_intro]); |
||
794 | robot_check(); cookie2session(); |
||
10 | reyssat | 795 | } |
796 | |||
7673 | bpr | 797 | /* parse special commands */ |
10 | reyssat | 798 | void special_cmds(void) |
799 | { |
||
12263 | bpr | 800 | char *c, *p; |
801 | int i; |
||
802 | long int l=-1; |
||
7673 | bpr | 803 | |
12263 | bpr | 804 | c=getvar(ro_name[ro_cmd]); |
805 | if(c==NULL || *c==0) { /* no module name nor command */ |
||
806 | setvar(ro_name[ro_module],home_module); |
||
807 | setvar(ro_name[ro_cmd],commands[cmd_new]); |
||
808 | return; |
||
809 | } |
||
810 | for(i=0;i<CMD_NO && strcmp(commands[i],c)!=0; i++); |
||
811 | switch(i) { |
||
812 | case cmd_intro: { |
||
813 | set_module_prefix(); |
||
814 | default_form_method="get"; |
||
815 | if(ftest(mkfname(NULL,"%s/%s",module_prefix,intro_file))<0) { |
||
816 | force_setvar(ro_name[ro_cmd],commands[cmd_new]); |
||
817 | return; |
||
818 | } |
||
819 | p=getvar("wims_session"); |
||
820 | if(p!=NULL && *p!=0) { |
||
821 | if(set_session_prefix()==0) check_session(); |
||
822 | else { |
||
823 | trap_check(p); |
||
824 | if(strchr(p,'_')!=NULL && strchr(p,'/')==NULL) { |
||
825 | get_static_session_var(); |
||
7673 | bpr | 826 | } |
12263 | bpr | 827 | } |
828 | } |
||
7673 | bpr | 829 | /* determine http protocol name. How to detect? */ |
12263 | bpr | 830 | p=getenv("HTTPS"); |
831 | if(p!=NULL && strcmp(p,"on")==0) { |
||
832 | protocol="https"; set_protocol(); |
||
7673 | bpr | 833 | } |
12263 | bpr | 834 | force_setvar("wims_protocol",protocol); |
835 | determine_font(lang); |
||
836 | determine_dirn(lang); |
||
837 | main_phtml_put(intro_file); debug_output(); |
||
838 | introend: write_logs();free(var_str); |
||
839 | delete_pid(); exit(0); |
||
840 | } |
||
841 | case cmd_ref: { |
||
842 | set_module_prefix(); |
||
843 | default_form_method="get"; |
||
844 | p=getvar("wims_session"); |
||
845 | if(p!=NULL && *p!=0) { |
||
846 | if(set_session_prefix()==0) check_session(); |
||
847 | else trap_check(p); |
||
7673 | bpr | 848 | } |
12263 | bpr | 849 | determine_font(lang); |
850 | determine_dirn(lang); |
||
851 | main_phtml_put(ref_file); goto introend; |
||
852 | } |
||
853 | case cmd_getins: { |
||
854 | c=getvar(ro_name[ro_special_parm]); |
||
855 | if(c==NULL || *c==0) { |
||
856 | user_error_nolog=1; user_error("no_insnum"); |
||
857 | } |
||
858 | if(*c=='/' || strstr(c,"..")!=NULL) goto badins; |
||
859 | set_session_prefix(); |
||
860 | if(strstr(session_prefix,"robot")!=NULL) exit(0); |
||
861 | l=filelength("%s/%s",s2_prefix,c); |
||
862 | if(l<0) { |
||
863 | badins: user_error_nolog=1; user_error("bad_insnum"); |
||
864 | } |
||
865 | { |
||
866 | char *fmt; |
||
867 | fmt=strchr(c,'.'); |
||
868 | if(fmt==NULL) { |
||
869 | user_error_nolog=1; user_error("bad_insnum"); |
||
870 | } |
||
871 | else fmt++; |
||
7673 | bpr | 872 | |
12263 | bpr | 873 | nph_header(200); |
10 | reyssat | 874 | /* insert format problem; bricolage */ |
12263 | bpr | 875 | printf("Content-type: image/%s\r\n\ |
10 | reyssat | 876 | Content-length: %ld\r\n\r\n",fmt,l); |
12263 | bpr | 877 | catfile(stdout,"%s/%s",s2_prefix,c); exit(0); |
7673 | bpr | 878 | } |
12263 | bpr | 879 | } |
880 | case cmd_getfile: { |
||
881 | char fname[MAX_FNAME+1]; |
||
882 | c=getvar(ro_name[ro_special_parm]); |
||
883 | if(c==NULL || *c==0) { |
||
884 | user_error_nolog=1; user_error("no_insnum"); |
||
885 | } |
||
886 | if(*c=='/' || strstr(c,"..")!=NULL) goto badfile; |
||
7673 | bpr | 887 | |
12263 | bpr | 888 | set_session_prefix(); |
889 | if(strstr(session_prefix,"robot")!=NULL) exit(0); |
||
890 | mkfname(fname,"%s/getfile/%s",session_prefix,c); |
||
891 | l=filelength("%s",fname); |
||
892 | if(l<0 && strchr(session_prefix,'_')!=NULL) { |
||
893 | char *pt; |
||
894 | mystrncpy(fname,session_prefix,sizeof(fname)); |
||
895 | pt=strrchr(fname,'_'); if(pt) *pt=0; |
||
896 | snprintf(fname+(pt-fname),sizeof(fname)-(pt-fname), |
||
897 | "/getfile/%s",c); |
||
898 | l=filelength("%s",fname); |
||
899 | } |
||
900 | if(l<0) { |
||
901 | badfile: user_error_nolog=1; user_error("bad_insnum"); |
||
902 | } |
||
903 | if(l>512*1024) { |
||
904 | struct rlimit rlim; |
||
905 | rlimit_cpu*=l/(10*1024); |
||
906 | rlim.rlim_cur=rlim.rlim_max=rlimit_cpu; |
||
907 | initalarm(); |
||
908 | } |
||
909 | { |
||
910 | char *p1; |
||
911 | char mime[MAX_LINELEN+1]; |
||
912 | for(p1=c+strlen(c);p1>c && isalpha(*(p1-1)); p1--); |
||
913 | ovlstrcpy(mime,"application/octet-stream"); |
||
914 | if(p1>c && *(p1-1)=='.') { |
||
915 | setvar("translator_unknown",mime); |
||
916 | setvar("dictionary","bases/sys/mime"); |
||
917 | snprintf(mime,sizeof(mime),"translator %s",p1); |
||
918 | calc_exec(mime); |
||
919 | } |
||
920 | nph_header(200); |
||
921 | printf("Content-type: %s\r\n\ |
||
10 | reyssat | 922 | Content-length: %ld\r\n\r\n",mime,l); |
12263 | bpr | 923 | catfile(stdout,"%s",fname); exit(0); |
7673 | bpr | 924 | } |
12263 | bpr | 925 | } |
7673 | bpr | 926 | case cmd_close: { |
12263 | bpr | 927 | char *p, b2[32]; int w; |
928 | char nbuf[MAX_FNAME+1], vbuf[MAX_LINELEN+1]; |
||
929 | p=getvar(ro_name[ro_session]); |
||
930 | if(p==NULL || strlen(p)<10 || |
||
931 | strchr(p,'/')!=NULL) return; |
||
932 | mystrncpy(b2,p,sizeof(b2)); |
||
933 | p=strchr(b2,'.'); if(p!=NULL) *p=0; |
||
934 | mkfname(nbuf,"%s/%s/var.stat",session_dir,b2); |
||
935 | getdef(nbuf,"wims_caller",vbuf); |
||
936 | if(vbuf[0]!=0) force_setvar(ro_name[ro_session],vbuf); |
||
937 | w=wrapexec; wrapexec=1; |
||
938 | call_sh("rm -Rf %s/%s* %s/%s* >/dev/null 2>&1",session_dir,b2,s2_dir,b2); |
||
939 | wrapexec=w; cookiegot[0]=0; |
||
940 | force_setvar(ro_name[ro_cmd],"new"); |
||
7673 | bpr | 941 | } |
942 | default: return; |
||
12263 | bpr | 943 | } |
10 | reyssat | 944 | } |
945 | |||
7673 | bpr | 946 | /* This is run only when manually invoking the program. |
8155 | bpr | 947 | * Verifies the orderedness of various list tables. |
948 | */ |
||
10 | reyssat | 949 | int verify_tables(void) |
950 | { |
||
951 | if(verify_order(calc_routine,CALC_FN_NO,sizeof(calc_routine[0]))) return -1; |
||
952 | if(verify_order(exec_routine,EXEC_FN_NO,sizeof(exec_routine[0]))) return -1; |
||
953 | if(verify_order(main_config,MAIN_CONFIG_NO,sizeof(main_config[0]))) return -1; |
||
954 | if(verify_order(mathname,mathname_no,sizeof(mathname[0]))) return -1; |
||
955 | if(verify_order(hmname,hmname_no,sizeof(hmname[0]))) return -1; |
||
956 | if(verify_order(ro_name,RO_NAME_NO,sizeof(ro_name[0]))) return -1; |
||
957 | if(verify_order(distr_cmd,distr_cmd_no,sizeof(distr_cmd[0]))) return -1; |
||
958 | if(verify_order(internal_name,INTERNAL_NAME_NO, |
||
7673 | bpr | 959 | sizeof(internal_name[0]))) return -1; |
10 | reyssat | 960 | if(verify_order(tmathfn,tmathfn_no,sizeof(tmathfn[0]))) return -1; |
961 | if(verify_order(tmathvar,tmathvar_no,sizeof(tmathvar[0]))) return -1; |
||
962 | if(verify_order(modindex,MODINDEX_NO,sizeof(modindex[0]))) return -1; |
||
963 | if(verify_order(exportvars,exportvarcnt,sizeof(exportvars[0]))) return -1; |
||
964 | if(evaltab_verify()) return -1; |
||
965 | if(textab_verify()) return -1; |
||
966 | return 0; |
||
967 | } |
||
968 | |||
969 | void config_defaults(void) |
||
970 | { |
||
3857 | kbelabas | 971 | int i; |
10 | reyssat | 972 | for(i=0;i<MAIN_CONFIG_NO;i++) { |
7673 | bpr | 973 | if((1&main_config[i].is_integer)==1) { |
974 | int *pi = (int*)main_config[i].address; |
||
975 | printf("DF_%s=%d\n",main_config[i].name, *pi); |
||
3857 | kbelabas | 976 | } |
7673 | bpr | 977 | else { |
3857 | kbelabas | 978 | char **ps = (char**)main_config[i].address; |
7673 | bpr | 979 | printf("DF_%s=%s\n",main_config[i].name,*ps); |
3857 | kbelabas | 980 | } |
10 | reyssat | 981 | } |
982 | } |
||
983 | |||
7673 | bpr | 984 | /* get and set useroptions */ |
10 | reyssat | 985 | void useropts(void) |
986 | { |
||
987 | char *p; |
||
988 | setvar("lang",lang); |
||
989 | p=getvar("useropts"); |
||
990 | if(p==NULL || *p==0) p=getvar("wims_useropts"); |
||
991 | if(p!=NULL && *p!=0) { |
||
6178 | bpr | 992 | if(myisdigit(p[0])) { |
993 | usertexsize=p[0]-'0'; |
||
6184 | bpr | 994 | /* fourth digit is for special fonts*/ |
6178 | bpr | 995 | if(p[1]!=0) { mathalign_base=p[1]-'0'; } |
996 | } |
||
6184 | bpr | 997 | if(myisdigit(p[3]) && p[3]!=0){ spec_font=p[3]-'0';} |
998 | } |
||
999 | if(mathalign_base==1) { |
||
6178 | bpr | 1000 | mathalign_sup1="<sup>"; mathalign_sup2="</sup>"; |
6184 | bpr | 1001 | } else mathalign_sup1=mathalign_sup2=""; |
10 | reyssat | 1002 | } |
1003 | |||
7673 | bpr | 1004 | /* popup module help */ |
10 | reyssat | 1005 | void mhelp(void) |
1006 | { |
||
1007 | char *p, buf[MAX_LINELEN+1]; |
||
1008 | main_phtml_put(""); buf[0]=0; |
||
1009 | if(cmd_type!=cmd_help) { |
||
7673 | bpr | 1010 | phtml_put_base("closemhelp.phtml",0); |
10 | reyssat | 1011 | } |
1012 | else { |
||
7673 | bpr | 1013 | phtml_put_base("mhelpheader.phtml",0); |
1014 | p=getvar("special_parm"); |
||
1015 | if(p!=NULL && strcmp(p,"about")==0) |
||
1016 | phtml_put("about.phtml",0); |
||
11125 | georgesk | 1017 | else phtml_put("help.phtml",0); |
1018 | phtml_put_base("mhelptail.phtml",0); |
||
7673 | bpr | 1019 | exec_tail(buf); |
10 | reyssat | 1020 | } |
1021 | } |
||
1022 | |||
1023 | #define READSTDIN_WINDOW 4096 |
||
1024 | |||
1025 | void readstdin(int len) |
||
1026 | { |
||
1027 | int ll, l1, lt, lr; |
||
1028 | int cpulim; |
||
7673 | bpr | 1029 | |
10 | reyssat | 1030 | cpulim=rlimit_cpu; rlimit_cpu=3; |
1031 | lr=len; l1=0; |
||
1032 | while(lr>0) { |
||
7673 | bpr | 1033 | nowtime=time(0); initalarm(); |
1034 | ll=lr; if(ll>READSTDIN_WINDOW) ll=READSTDIN_WINDOW; |
||
1035 | lt=fread(stdinbuf+l1,1,ll,stdin); |
||
1036 | if(lt!=ll) user_error("parm_too_long"); |
||
1037 | lr-=ll; l1+=ll; |
||
10 | reyssat | 1038 | } |
1039 | if(l1!=len) user_error("parm_too_long"); |
||
1040 | stdinbuf[len]=0; rlimit_cpu=cpulim; |
||
1041 | } |
||
1042 | |||
7673 | bpr | 1043 | /* input: p=QUERY_STRING. output: parameter length. */ |
1044 | /* Netscape puts form content into /tmp. */ |
||
10 | reyssat | 1045 | int formdata(char *p) |
1046 | { |
||
1047 | char *pp; |
||
1048 | int inlen; |
||
1049 | char *ctype; |
||
1050 | inlen=0; ctype=getenv("CONTENT_TYPE"); |
||
1051 | if(ctype==NULL || strstr(ctype,"multipart/form-data")==NULL |
||
1052 | || (p=strstr(ctype,"boundary="))==NULL) { |
||
7673 | bpr | 1053 | bad: stdinbuf=""; return 0; |
10 | reyssat | 1054 | } |
1055 | pp=getenv("CONTENT_LENGTH"); |
||
1056 | if(pp==NULL) goto bad; |
||
1057 | inlen=atoi(pp); if(inlen<=10) goto bad; |
||
1058 | if(inlen>=MAX_DEPOSITLEN) user_error("parm_too_long"); |
||
1059 | stdinbuf=xmalloc(inlen+1); readstdin(inlen); |
||
1060 | p+=strlen("boundary="); |
||
1061 | for(pp=p;myisalnum(*pp) || *pp=='-'; pp++); |
||
1062 | if(pp-p<sizeof(mpboundary)-2) { |
||
7673 | bpr | 1063 | memmove(mpboundary,p,pp-p); mpboundary[pp-p]=0; |
10 | reyssat | 1064 | } |
7673 | bpr | 1065 | /* empty data */ |
10 | reyssat | 1066 | if(strstr(stdinbuf,mpboundary)==NULL || strstr(stdinbuf,"name=")==NULL) { |
7673 | bpr | 1067 | free(stdinbuf); goto bad; |
10 | reyssat | 1068 | } |
1069 | form_access=1; post_log(); |
||
1070 | return inlen; |
||
1071 | } |
||
1072 | |||
7673 | bpr | 1073 | /* get the content of POST */ |
10 | reyssat | 1074 | void getpost(void) |
1075 | { |
||
1076 | int ll; |
||
1077 | char *pp; |
||
1078 | pp=getenv("CONTENT_LENGTH"); |
||
1079 | if(pp==NULL || (ll=atoi(pp))<=0) { |
||
7673 | bpr | 1080 | stdinbuf=xmalloc(16); stdinbuf[0]=0; |
10 | reyssat | 1081 | } |
1082 | else { |
||
7673 | bpr | 1083 | if(ll>QUERY_STRING_LIMIT) user_error("parm_too_long"); |
1084 | stdinbuf=xmalloc(ll+16); readstdin(ll); |
||
1085 | if(ll>0) { |
||
1086 | setenv("QUERY_STRING",stdinbuf,1); |
||
1087 | form_access=1; post_log(); |
||
1088 | } |
||
10 | reyssat | 1089 | } |
1090 | } |
||
1091 | |||
1092 | void buffer_init(void) |
||
1093 | { |
||
1094 | struct timeval tv; |
||
7673 | bpr | 1095 | |
10 | reyssat | 1096 | mcachecnt=readnest=0; |
1097 | mpboundary[0]=cookiegot[0]=cookieset[0]=cwdbuf[0]=0; |
||
1098 | rscore_class[0]=rscore_user[0]=multiexec_random[0]=0; |
||
1099 | lastftest[0]=0; |
||
1100 | lastdatafile[0]=0; lastdata=xmalloc(WORKFILE_LIMIT); |
||
1101 | outptr=outbuf; |
||
1102 | instex_src[0]=instex_fname[0]=module_prefix[0]=0; |
||
1103 | examlogf[0]=examlogd[0]=exam_sheetexo[0]=0; |
||
1104 | stdinbuf=NULL; |
||
1105 | mkfname(tmp_dir,"../tmp/forall"); |
||
1106 | mkfname(session_dir,"../%s",SESSION_BASE); |
||
1107 | mkfname(s2_dir,"../%s",S2_BASE); |
||
1108 | if(gettimeofday(&tv,NULL)) startmtime=startmtime2=0; |
||
1109 | else { |
||
7673 | bpr | 1110 | startmtime=((tv.tv_sec%10000)*1000+tv.tv_usec/1000); |
1111 | startmtime2=(tv.tv_sec%1000)*1000000+tv.tv_usec; |
||
10 | reyssat | 1112 | } |
1113 | } |
||
1114 | |||
8216 | bpr | 1115 | /** |
1116 | * runs the test suite, to check whether the documented commands of modtool |
||
1117 | * behave properly. |
||
1118 | * @param prefix path to the proc file to process |
||
1119 | * @param p name of the proc file to proceed |
||
1120 | * @param vars a list of var names to print. |
||
1121 | **/ |
||
1122 | void test_suite(char *prefix, char *p, char *vars){ |
||
1123 | char *v, *nextv; |
||
1124 | mystrncpy(module_prefix, prefix, sizeof(module_prefix)); |
||
1125 | exec_read(p); |
||
1126 | nextv=vars; |
||
1127 | while (*nextv!='\0'){ |
||
1128 | v=find_word_start(nextv); |
||
1129 | nextv=find_word_end(v); |
||
1130 | if (*nextv != '\0'){ |
||
1131 | *nextv++='\0'; |
||
1132 | } |
||
8925 | bpr | 1133 | v=getvar(v); |
1134 | if(v) puts(v); else putchar('\n'); |
||
8216 | bpr | 1135 | } |
1136 | } |
||
1137 | |||
10 | reyssat | 1138 | int main(int argc, char *argv[], char *envp[]) |
1139 | { |
||
12011 | bpr | 1140 | char *p, homebuf[MAX_FNAME+1], lbuf[32], buf[64]; |
10 | reyssat | 1141 | int inlen=0; |
8155 | bpr | 1142 | /* int mfd; */ |
8195 | bpr | 1143 | |
10 | reyssat | 1144 | class_dir[0]=0; |
1145 | substitute=substit; buffer_init(); var_init(); |
||
7673 | bpr | 1146 | /* WIMS internal locale is always C. */ |
10 | reyssat | 1147 | setenv("LANG","C",1); umask(022); |
1148 | setenv("LANGUAGE","us",1); |
||
1149 | setenv("LC_ALL","C",1); |
||
1150 | if(argc>1) { |
||
7673 | bpr | 1151 | if(strcasecmp(argv[1],"table")==0) { |
1152 | if(verify_tables()) internal_error("Table disorder."); |
||
1153 | else printf("Table orders OK.\n"); |
||
1154 | return 0; |
||
1155 | } |
||
1156 | if(strcasecmp(argv[1],"version")==0) { |
||
1157 | printf("%s",wims_version); return 0; |
||
1158 | } |
||
1159 | if(strcasecmp(argv[1],"defaults")==0) { |
||
1160 | config_defaults(); return 0; |
||
1161 | } |
||
8216 | bpr | 1162 | if(strcasecmp(argv[1],"test")==0) { |
8851 | bpr | 1163 | /* launches a test suite */ |
12288 | bpr | 1164 | if (argc < 5) { |
1165 | printf("Not enough arguments to launch a test; usage:\n"); |
||
1166 | printf("wims test path_to_file name_of_proc_file 'var1 var2 ...'\n\n"); |
||
1167 | printf("the file at path_to_file/name_of_proc_file will be evaluated by wims for\nexec commands, then the values of var1, var2, ... will be printed\nin the standard output, one per line.\n"); |
||
1168 | return 1; |
||
1169 | } |
||
1170 | test_suite(argv[2], argv[3], argv[4]); |
||
1171 | return 0; |
||
1172 | } |
||
10 | reyssat | 1173 | } |
1174 | p=getenv("SERVER_SOFTWARE"); if(p!=NULL && strcasecmp(p,"WIMS")==0) |
||
1175 | httpd_type=httpd_wims; |
||
1176 | p=getenv("REMOTE_ADDR"); if(p!=NULL) remote_addr=p; |
||
1177 | p=getenv("REMOTE_HOST"); if(p!=NULL) remote_host=p; |
||
1178 | nowtime=time(0); now=localtime(&nowtime); |
||
9286 | bpr | 1179 | /* nowtime contains the seconds elapsed from EPOCH (1970) |
1180 | but tm_year is set to current year-1900. |
||
1181 | */ |
||
10 | reyssat | 1182 | memmove(&Now, now, sizeof(Now)); now=&Now; |
1183 | snprintf(nowstr,sizeof(nowstr),"%04d%02d%02d.%02d:%02d:%02d", |
||
7673 | bpr | 1184 | (now->tm_year)+1900,(now->tm_mon)+1,now->tm_mday, |
1185 | now->tm_hour,now->tm_min,now->tm_sec); |
||
10 | reyssat | 1186 | p=getenv("QUERY_STRING"); |
1187 | if(p==NULL || *p==0) getpost(); |
||
1188 | else if(strncmp(p,"form-data",9)==0) inlen=formdata(p); |
||
7673 | bpr | 1189 | |
10 | reyssat | 1190 | force_setvar("wims_now",nowstr); |
1191 | snprintf(lbuf,sizeof(lbuf),"%lu",nowtime); |
||
1192 | force_setvar("wims_nowseconds",lbuf); |
||
1193 | nowtime=time(0); |
||
1194 | initalarm(); |
||
7673 | bpr | 1195 | |
10 | reyssat | 1196 | executed_gotos=insert_no=output_length=0; ins_alt[0]=0; |
7673 | bpr | 1197 | setvar("empty",""); /* lock this variable */ |
10 | reyssat | 1198 | setvar("wims_version",wims_version); |
1199 | setvar("wims_version_date",wims_version_date); |
||
1200 | setvar("wims_main_font","utf-8"); |
||
1201 | take_httpd_vars(); |
||
1202 | |||
1203 | main_configure(); |
||
1204 | checklogd(); |
||
8155 | bpr | 1205 | /* mfd=shm_open(SHM_NAME,O_RDONLY,-1); |
1206 | * if(mfd==-1) internal_error("Unable to find shared memory."); |
||
1207 | * shmptr=mmap(0,SHM_SIZE,PROT_READ,MAP_SHARED,mfd,0); |
||
1208 | * if(shmptr==MAP_FAILED) internal_error("Shared memory failure."); |
||
1209 | */ |
||
7673 | bpr | 1210 | getppid(); /* this is the first sysmask trigger, must be after checklogd() */ |
10 | reyssat | 1211 | predetermine_language(); |
6784 | kbelabas | 1212 | /* modify a few rlimits for 64-bit processors */ |
1213 | if (sizeof(long) == 8) { |
||
1214 | rlimit_as*=2; /* virtual memory size */ |
||
1215 | rlimit_data*=2; /* data segment size; maxima requires a lot */ |
||
1216 | rlimit_stack*=2; /* stack size */ |
||
1217 | } |
||
10 | reyssat | 1218 | set_rlimits(); |
12011 | bpr | 1219 | /*init_random();*/ |
12363 | bpr | 1220 | seed_time(); |
1221 | p=getvar("wims_seed"); |
||
1222 | mystrncpy(buf,p,sizeof(buf)); |
||
1223 | exec_setseed(buf); |
||
10 | reyssat | 1224 | module_configure(); |
1225 | set_job_ident(); |
||
1226 | m_file.name[0]=0;m_file.linecnt=m_file.linepointer=0; |
||
1227 | p=getenv("QUERY_STRING"); |
||
1228 | if(p==NULL || strlen(p)==0) { |
||
7673 | bpr | 1229 | setvar("lang",lang); |
1230 | snprintf(homebuf,sizeof(homebuf),"module=%s",home_module); |
||
1231 | p=homebuf; |
||
10 | reyssat | 1232 | } |
1233 | if(strlen(p)>=QUERY_STRING_LIMIT) user_error("parm_too_long"); |
||
1234 | if(mpboundary[0]==0) { |
||
7673 | bpr | 1235 | var_str=xmalloc(strlen(p)+2); |
1236 | parse_query_string(http2env(var_str,p),0); |
||
10 | reyssat | 1237 | } |
1238 | else { |
||
7673 | bpr | 1239 | var_str=stdinbuf; |
1240 | parse_query_string(inlen,1); |
||
10 | reyssat | 1241 | } |
1242 | if(ismhelp) { |
||
7673 | bpr | 1243 | p=getvar(ro_name[ro_cmd]); |
1244 | if(p==NULL || (strcmp(p,"help")!=0 && strcmp(p,"getins")!=0)) { |
||
1245 | mhelp(); goto outgo; |
||
1246 | } |
||
10 | reyssat | 1247 | } |
1248 | check_exam(); |
||
1249 | useropts(); |
||
1250 | special_cmds(); |
||
1251 | parse_ro_names(); |
||
1252 | manager_check(); |
||
1253 | access_check(0); |
||
11132 | bpr | 1254 | /* it is really for developing in wims, so no use in general */ |
12263 | bpr | 1255 | if (1==1) { |
10051 | bpr | 1256 | if(strstr(tmp_debug,"yes")!=NULL && checkhost(manager_site)>=1) |
12363 | bpr | 1257 | trace_file = fopen(mkfname(NULL,"%s/%s",tmp_dir,"trace.txt"),"a"); |
12263 | bpr | 1258 | } |
1259 | set_variables(); |
||
1260 | determine_font(getvar("module_language")); |
||
1261 | determine_dirn(getvar("module_language")); |
||
1262 | if(!robot_access && session_prefix[0]!=0 && cmd_type!=cmd_help && !ismhelp) |
||
1263 | lastout_file=creat(mkfname(NULL,"%s/%s",s2_prefix,lastout), |
||
1264 | S_IRUSR|S_IWUSR); |
||
1265 | p=getvar("module_score"); |
||
1266 | if(p!=NULL) force_setvar("wims_seed_score",p); |
||
1267 | p=getvar("module_category"); |
||
1268 | if(p==NULL || strstr(p,"tool")==NULL) default_form_method="get"; |
||
1269 | if(noout) { |
||
1270 | write_logs(); save_session_vars(); |
||
1271 | goto outgo; |
||
1272 | } |
||
1273 | if(ismhelp) { |
||
1274 | mhelp(); |
||
1275 | } |
||
1276 | else { |
||
1277 | main_phtml_put(html_file); |
||
1278 | if(lastout_file!=-1) { |
||
1279 | flushoutput(); close(lastout_file); putlastout(); |
||
10 | reyssat | 1280 | } |
12263 | bpr | 1281 | write_logs(); save_session_vars(); |
1282 | } |
||
1283 | outgo: |
||
1284 | debug_output(); |
||
1285 | if (trace_file) { fclose(trace_file); trace_file=NULL; } |
||
1286 | if(var_str!=stdinbuf) free(var_str); |
||
1287 | delete_pid(); |
||
1288 | if(mode!=mode_popup && trusted_module()) { |
||
1289 | p=getvar("wims_mode"); |
||
1290 | if(p!=NULL && strcmp(p,"popup")==0) mode=mode_popup; |
||
1291 | } |
||
1292 | if(mode==mode_popup && insert_no==0) { |
||
1293 | p=getvar("wims_mode"); |
||
1294 | if(p!=NULL && strcmp(p,"popup")==0) { |
||
1295 | remove_tree(session_prefix); |
||
7673 | bpr | 1296 | |
12263 | bpr | 1297 | remove_tree(s2_prefix); |
10 | reyssat | 1298 | } |
12263 | bpr | 1299 | } |
1300 | return 0; |
||
10 | reyssat | 1301 | } |