Subversion Repositories wimsdev

Rev

Rev 11735 | Rev 12263 | 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 {
23
    char *name;
24
    char *font;
25
} charname[]={
11735 obado 26
      {"en","windows-1252"},
27
      {"fr","windows-1252"},
28
      {"es","windows-1252"},
8121 bpr 29
      {"cn","gb2312"},
11735 obado 30
      {"de","windows-1252"},
31
      {"it","windows-1252"},
32
      {"nl","windows-1252"},
8121 bpr 33
      {"si","iso-8859-2"},
34
      {"ar","iso-8859-6"},
35
      {"tw","big5"},
11735 obado 36
      {"pt","windows-1252"},
37
      {"ca","windows-1252"},
38
      {"pt","windows-1252"},
8121 bpr 39
      {"ru","iso-8859-5"},
40
      {"ty","iso-8859-13"}
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 {
47
    char *name;
48
    char *dirn;
49
} dirnname[]={
11735 obado 50
      {"en","ltr"},
8121 bpr 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"}
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[]={
76
      "Mozilla","Netscape","Opera","WIMS",
77
      "MSIE","Konqueror","Java"
78
};
79
#define good_agent_no (sizeof(good_agent)/sizeof(good_agent[0]))
80
 
81
char *bad_agent[]={ /* These are really bad agents: prohibited. */
7673 bpr 82
      "HTTrack","MemoWeb","Teleport","Offline","Wget","eCatch",
10 reyssat 83
      "Powermarks","EmailSiphon", "WebCopier"
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[]={
256
      "cmd" ,
257
      "empty",
258
      "lang" ,
259
      "module" ,
260
      "session" ,
261
      "special_parm",
262
      "special_parm2",
1970 guerimand 263
      "special_parm3",
1980 guerimand 264
      "special_parm4",
10 reyssat 265
      "useropts" ,
266
      "wims_session",
267
      "wims_subsession",
268
      "wims_window",
269
      "worksheet"
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[]={
7673 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},
10 reyssat 298
      {"devel_modules", 1},
7673 bpr 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 */
12011 bpr 328
      {"seed", 0},
329
      {"seed_repeat",0},
330
      {"seed_score", 0},
331
      {"sequence", 0}, /* sequence number */
7673 bpr 332
      {"sescookie", 1}, /* session cookie */
333
      {"sesdir", 1},
334
      {"session_serial", 0}, /* request serial in the session */
335
      {"session_start_time", 0},
336
      {"sheet", 0}, /* sheet number */
337
      {"sup_secure", 1}, /* secure level of supervisor */
338
      {"superclass", 1}, /* superclass code */
339
      {"superclass_quota", 1},
340
      {"supertype", 1}, /* superclass type */
341
      {"supervise", 1}, /* superclass definition */
342
      {"supervisor", 1}, /* real name of the supervisor */
343
      {"supervisormail",1}, /* email of supervisor */
344
      {"trustfile", 1}, /* trusted files in special adm modules */
345
      {"useropts", 1}, /* user options */
346
      {"writable", 1}, /* writable variables in user file, words */
10 reyssat 347
};
8185 bpr 348
int INTERNAL_NAME_NO=(sizeof(internal_name)/sizeof(internal_name[0]));
10 reyssat 349
 
350
char *httpd_vars[]={
351
      "HTTP_ACCEPT",
352
      "HTTP_ACCEPT_CHARSET",
353
      "HTTP_ACCEPT_LANGUAGE",
354
      "HTTP_COOKIE",
355
      "HTTP_HOST",
356
      "HTTP_USER_AGENT",
11735 obado 357
      "HTTP_X_REQUESTED_WITH",
10 reyssat 358
      "HTTPS",
359
      "QUERY_STRING",
360
      "REMOTE_HOST",
361
      "REMOTE_ADDR",
362
      "REMOTE_PORT",
363
      "REQUEST_METHOD",
364
      "SCRIPT_NAME",
365
      "SERVER_NAME",
366
      "SERVER_SOFTWARE",
367
      "SERVER_PROTOCOL"
368
};
369
#define HTTPD_VAR_NO (sizeof(httpd_vars)/sizeof(httpd_vars[0]))
370
 
8155 bpr 371
/* security: these variables will not be visible to child processes */
10 reyssat 372
char *unsetvars[]={
7673 bpr 373
 "DOCUMENT_ROOT","SERVER_SIGNATURE","SERVER_SOFTWARE",
10 reyssat 374
      "UNIQUE_ID","HTTP_KEEP_ALIVE","SSL_SESSION_ID"
375
};
376
#define unsetvarcnt (sizeof(unsetvars)/sizeof(unsetvars[0]))
377
 
378
int httpd_type=httpd_apache;
379
 
7673 bpr 380
char *remote_addr=""; /* storing for performance */
10 reyssat 381
char *remote_host="";
382
 
383
char ref_name[2048], ref_base[2048];
384
 
385
void put_special_page(char *pname);
386
void useropts(void);
387
 
7673 bpr 388
/* Make certain httpd variables readable by modules */
10 reyssat 389
void take_httpd_vars(void)
390
{
391
    int i;
392
    char *p, buf[MAX_NAMELEN+1];
393
    var_noexport=1;
394
    for(i=0;i<HTTPD_VAR_NO;i++) {
7673 bpr 395
     snprintf(buf,sizeof(buf),"httpd_%s",httpd_vars[i]);
396
     if((p=getenv(httpd_vars[i]))!=NULL) setvar(buf,p);
10 reyssat 397
    }
398
    var_noexport=0;
7673 bpr 399
 
10 reyssat 400
    for(i=0;i<unsetvarcnt;i++) unsetenv(unsetvars[i]);
4648 bpr 401
     /* IPv4 IPv6*/
402
    p=getenv("REMOTE_ADDR");if(p!=NULL && (strcmp(p,"127.0.0.1")==0 || strcmp(p,"::1")==0)) human_access=1;
10 reyssat 403
    p=getenv("HTTP_REFERER"); if(p!=NULL && *p!=0) setvar("wims_referer",p);
404
}
405
 
11735 obado 406
/* cookie2session */
10 reyssat 407
void cookie2session(void)
408
{
409
    char cksession[64], psession[32], *ckey, *p;
410
    char nbuf[MAX_FNAME+1];
411
 
412
    if(mode==mode_popup) return;
6796 kbelabas 413
    if(cookiegot[0]==0) {
7673 bpr 414
     ckset: cookiegot[0]=0; setcookie=1; return;
10 reyssat 415
    }
416
    p=getvar("special_parm");
417
    if(p!=NULL && strcmp(p,"ignorecookie")==0) return;
418
    mystrncpy(cksession,cookiegot,sizeof(cksession));
419
    ckey=strchr(cksession,'-');
420
    if(ckey==NULL) goto ckset; else *ckey++=0;
421
    p=getvar("wims_session"); if(p==NULL) p="";
422
    if(strstr(p,"new")!=NULL) goto ckset;
423
    mystrncpy(psession,p,sizeof(psession));
424
    p=strchr(psession,'_'); if(p!=NULL) *p=0;
425
    if(psession[0]!=0) {
7673 bpr 426
      if(strcmp(psession,cksession)==0) return;
427
      if(session_exists(psession)) goto ckset;
428
      if(session_exists(cksession)) goto change;
10 reyssat 429
    }
430
    else {
7673 bpr 431
      if(!session_exists(cksession)) return;
432
      change:
433
      p=getenv("HTTPS");
434
      if(p!=NULL && strcasecmp(p,"on")==0) goto ckset;
435
      mkfname(nbuf,"%s/%s/var",session_dir,cksession);
436
      getdef(nbuf,"w_wims_ismanager",tmplbuf);
437
      if(tmplbuf[0]!=0 && tmplbuf[0]!='0') goto ckset;
438
      getdef(nbuf,"w_wims_protocol",tmplbuf);
439
      if(strcasecmp(tmplbuf,"https")==0) goto ckset;
440
      mkfname(nbuf,"%s/%s/var.stat",session_dir,cksession);
441
      getdef(nbuf,"wims_user",tmplbuf);
442
      if(tmplbuf[0]!=0) goto ckset;
443
      force_setvar(ro_name[ro_session],cksession);
444
      setsesdir(cksession);
445
      force_setvar("wims_subsession","");
446
      session_serial=0;
10 reyssat 447
    }
448
}
449
 
450
void determine_font(char *l)
451
{
452
    int i;
7673 bpr 453
 
10 reyssat 454
    if(l==NULL || *l==0) return;
455
    for(i=0;i<charname_no && memcmp(charname[i].name,l,2);i++);
456
    if(i<charname_no) setvar("wims_main_font",charname[i].font);
457
}
458
 
3278 reyssat 459
void determine_dirn(char *l)
460
{
461
    int i;
7673 bpr 462
 
3278 reyssat 463
    if(l==NULL || *l==0) return;
464
    for(i=0;i<dirnname_no && memcmp(dirnname[i].name,l,2);i++);
465
    if(i<dirnname_no) setvar("wims_main_dirn",dirnname[i].dirn);
466
}
467
 
10 reyssat 468
void predetermine_language(void)
469
{
470
    char *p;
471
    int i,n;
472
 
473
    if(pre_language[0]!=0) p=pre_language;
474
    else p=getenv("HTTP_ACCEPT_LANGUAGE");
475
    if(p!=NULL && strlen(p)>=2) {
476
      for(i=0;i<available_lang_no && memcmp(p,available_lang[i],2)!=0;i++);
477
      if(i<available_lang_no) goto lend;
478
    }
479
    p=getenv("HTTP_USER_AGENT");
480
    if(p!=NULL && strlen(p)>=5) {
7673 bpr 481
      char *q;
482
      if((q=strchr(p,'['))!=NULL && islower(*(q+1)) && islower(*(q+2)) && *(q+3)==']') {
483
          char bb[4];
484
          bb[0]=*(q+1);bb[1]=*(q+2);bb[2]=0;
485
          for(i=0;i<available_lang_no && memcmp(bb,available_lang[i],2)!=0;i++);
486
          if(i<available_lang_no) {
487
            memmove(lang,bb,2); lang[2]=0;
488
            goto lend2;
489
          }
490
      }
10 reyssat 491
    }
492
    p=getenv("HTTP_HOST"); if(p==NULL) goto lend2;
493
    n=strlen(p); if(n<=3 || *(p+n-3)!='.') goto lend2;
494
    p=p+n-2;
495
    for(i=0;i<available_lang_no && memcmp(p,available_lang[i],2)!=0;i++);
496
    if(i<available_lang_no) {
7673 bpr 497
      lend: memmove(lang,p,2); lang[2]=0;
498
      lend2: determine_font(lang);determine_dirn(lang);
10 reyssat 499
    }
500
}
501
 
7673 bpr 502
/* print a special page */
10 reyssat 503
void put_special_page(char *pname)
504
{
505
    determine_font(lang);
3278 reyssat 506
    determine_dirn(lang);
10 reyssat 507
    phtml_put_base(mkfname(NULL,"%s.phtml.%s",pname,lang),0);
508
    write_logs();free(var_str);
509
}
510
 
7673 bpr 511
/* check whether the connection is a site manager. */
10 reyssat 512
void manager_check(void)
513
{
514
    char *p, *pp, buf[16];
515
    struct stat confstat;
516
    int i;
7673 bpr 517
 
10 reyssat 518
    manageable=0;
519
    if(robot_access || *manager_site==0 || checkhost(manager_site)<1)
520
      goto mend;
521
    if(manager_https) {
7673 bpr 522
      p=getenv("HTTPS");
523
      if(p==NULL || strcmp(p,"on")!=0) goto mend;
10 reyssat 524
    }
8185 bpr 525
/* IPv4 IPv6*/
4648 bpr 526
    if(strcmp(remote_addr,"127.0.0.1")==0 || strcmp(remote_addr,"::1")==0) {
7673 bpr 527
      int port, port2;
528
      char tester[128];
529
      p=getenv("REMOTE_PORT"); if(p==NULL) goto mend;
530
      port=atoi(p); if(port<1024 || port>65535) goto mend;
531
      p=getenv("SERVER_PORT"); if(p==NULL) goto mend;
532
      port2=atoi(p); if(port2>=10000 || port2<=0) goto mend;
533
/* this is very non-portable */
534
      manageable=1;
535
      accessfile(tmplbuf,"r","/proc/net/tcp");
536
      snprintf(tester,sizeof(tester)," 0100007F:%04X 0100007F:%04X ",
537
             port,port2);
538
      p=strstr(tmplbuf,tester);
539
      if(p!=NULL) {
540
          pp=strchr(p,'\n'); if(pp!=NULL) *pp=0;
541
          if(strlen(p)>=75) {
542
            p=find_word_start(p+70); *find_word_end(p)=0;
543
            if(atoi(p)==geteuid()) manageable=2;
544
          }
545
      }
10 reyssat 546
    }
547
    else manageable=1;
548
    i=stat(config_file,&confstat);
549
    if(i==0 && manageable>0 && (confstat.st_mode&(S_IRWXO|S_IRWXG))!=0) manageable=-1;
550
    if(manageable>0 && !trusted_module()) manageable=0;
551
    if(manageable==1) {
7673 bpr 552
      accessfile(tmplbuf,"r","%s/.manager",session_prefix);
553
      if(strstr(tmplbuf,"yes")!=NULL) manageable=2;
10 reyssat 554
    }
555
    if(manageable==1) {
7673 bpr 556
      p=getvar(ro_name[ro_module]);
557
      if(p!=NULL && strncmp(p,"adm/manage",strlen("adm/manage"))==0) {
558
          struct stat pstat;
559
          if(stat("../log/.wimspass",&pstat)==0) {
560
            if((S_IFMT&pstat.st_mode)!=S_IFREG ||
561
               ((S_IRWXO|S_IRWXG)&pstat.st_mode)!=0)
562
              manageable=-2;
563
          }
564
      }
10 reyssat 565
    }
566
    mend:
567
    mystrncpy(buf,int2str(manageable),sizeof(buf));
568
    force_setvar("wims_ismanager",buf);
569
    if(manageable>=2) {
7673 bpr 570
      struct rlimit rlim;
571
      rlimit_cpu*=10;
572
      rlim.rlim_cur=rlim.rlim_max=rlimit_cpu;
573
      setrlimit(RLIMIT_CPU,&rlim);
574
      mystrncpy(buf,int2str(rlimit_cpu),sizeof(buf));
575
      setvar("wims_cpu_limit",buf);
576
      initalarm();
10 reyssat 577
    }
578
}
579
 
7673 bpr 580
/* check for robot access */
10 reyssat 581
void robot_check(void)
582
{
583
    char *ua, *p, *ses, *c, *mod;
584
    int i;
585
 
586
    if(human_access) return;
587
    mod=getvar(ro_name[ro_module]);
588
    if(mod!=NULL && strcmp(mod,"adm/raw")==0) return;
589
    ses=getvar(ro_name[ro_session]);
7673 bpr 590
/* user has valid session; OK */
10 reyssat 591
    if(ses!=NULL && strncmp(ses,robot_session,strlen(robot_session))!=0
592
       && strchr(ses,'/')==NULL
593
       && ftest(mkfname(NULL,"%s/%s",s2_dir,ses))==is_dir)
594
      return;
595
    ua=getenv("HTTP_USER_AGENT"); if(ua==NULL) ua="";
596
    ua=find_word_start(ua);
7673 bpr 597
    if(strncasecmp(ua,"Mozilla",strlen("Mozilla"))==0 &&
598
       (p=strstr(ua,"compatible"))!=NULL)
10 reyssat 599
      ua=find_word_start(find_word_end(p));
600
    if(*ua) {
7673 bpr 601
      for(i=0;i<good_agent_no
602
          && strncasecmp(ua,good_agent[i],strlen(good_agent[i]));i++);
603
      if(i<good_agent_no) return;
604
      for(i=0;i<bad_agent_no
605
          && strstr(ua,bad_agent[i])==NULL;i++);
606
      if(i<bad_agent_no) user_error("trapped");
10 reyssat 607
    }
608
    force_setvar(ro_name[ro_session],robot_session);
609
    setsesdir(robot_session);
610
    c=getvar(ro_name[ro_cmd]);
611
    robot_access=1;
612
    if(c!=NULL && strcmp(c,"new") && strcmp(c,"intro")) {
7673 bpr 613
      force_setvar(ro_name[ro_cmd],"robot_error");
614
      nph_header(450); put_special_page("robot");
615
      flushoutput(); flushlog(); exit(0);
10 reyssat 616
    }
617
}
618
 
7673 bpr 619
/* type=0: ordinary; type=1: multipart/form-data */
10 reyssat 620
void parse_query_string(int len, int type)
621
{
622
    int i,j,l,v,cmd_defined;
623
    int parenth=-1, ll, lb, dlen;
624
    char *start, *p, *p1, *pt, *b1="";
7673 bpr 625
 
10 reyssat 626
    cmd_defined=0;
627
    setvar("wims_subsession","");
628
    ll=lb=0;
629
    if(type) {
7673 bpr 630
      ll=strlen(mpboundary);
631
      start=strstr(var_str,mpboundary);
632
      if(start==NULL) start=var_str+strlen(var_str);
633
      if(strstr(var_str,"\r\n\r\n")!=NULL) b1="\r\n\r\n";
634
      else b1="\n\n";
635
      lb=strlen(b1);
10 reyssat 636
    }
637
    else start=var_str;
638
    for(v=0, p1=start;p1<var_str+len;p1+=l) {
7673 bpr 639
      if(type) {
640
          char *p2, *p3, *p4, *p5;
641
          p2=p1+ll; p3=memstr(p2,mpboundary,var_str+len-p2); l=p3-p1;
642
          p=memstr(p2,b1,var_str+len-p2); if(p>=p3) continue;
643
          p+=lb; if(p3<var_str+len) {
11125 georgesk 644
            while(*p3!='\n' && p3>p2) p3--;
11132 bpr 645
            *p3=0;
7673 bpr 646
            p3--; if(*p3=='\r') *p3=0;
647
          }
648
          dlen=p3-p;
649
          p2=memstr(p2,"name=",p3-p2); if(p2>=p3) continue;
650
          p2+=strlen("name="); if(*p2=='"') p2++;
651
          for(p3=p2; myisalnum(*p3) || strchr("._",*p3)!=NULL; p3++);
652
          if(p3==p2) continue;
653
          if(p3-p2==strlen("wims_deposit") &&
654
             strncmp(p2,"wims_deposit",p3-p2)==0) {
655
            p4=memstr(p1,"filename=",p-p1); if(p4<p) {
656
                p4+=strlen("filename="); if(*p4=='"') {
657
                  p4++; p5=strchr(p4,'"');
658
                  if(p5==NULL || p5-p4>=MAX_FNAME) goto emptyquote;
659
                }
660
                else {
661
                  emptyquote:
662
                  for(p5=p4; p5<p && !isspace(*p5) &&
663
                      strchr(";\"~#*?=,'",*p5)==NULL; p5++);
664
                }
665
                if(p5>p4) {
666
                  *p5=0;
667
                  for(p5--;
668
                      p5>=p4 && !isspace(*p5) && strchr("/\\:",*p5)==NULL;
669
                      p5--);
11125 georgesk 670
                  if(p5>=p4) p4=p5+1;
11132 bpr 671
                  if(*p4==0) goto noname;
7673 bpr 672
                  if(strstr(p4,"..")!=NULL || *p4=='.')
673
                    p4="noname.file";
674
                  setvar("wims_deposit",p4);
675
                }
676
                else {
677
                  noname: setvar("wims_deposit","noname.file");
678
                }
679
            }
680
            deplen=dlen;
681
          }
682
          *p3=0; l-=p2-p1; p1=p2;
683
      }
684
      else {
685
          p1=find_word_start(p1);
686
          l=strlen(p1)+1; p=strchr(p1,'=');
687
          if(p==NULL) p=p1+strlen(p1);
688
          if(*p==0 && l>1) {
689
            user_variable[v].name="no_name";
690
            user_variable[v].value=p1;
691
            coord_input=1;
692
            goto nnext;
693
          }
694
          *p++=0;
695
      }
696
/* empty name or empty value: ignore */
10 reyssat 697
        if(*p1==0 || *p==0) continue;
7673 bpr 698
/* We do not treat names containing '.' */
699
      for(pt=strchr(p1,'.'); pt; pt=strchr(++pt,'.')) *pt='_';
700
/* Restrictions on variable names */
701
      for(pt=p1; myisalnum(*pt) || *pt=='_'; pt++);
702
      if(*pt) continue;
703
      if(strcmp(p1,"wims_deposit")!=0) _tolinux(p);
704
/* This is a restriction:
8155 bpr 705
 * Every parameter must have matching parentheses.
706
 */
7673 bpr 707
      if(parenth==-1 && strncmp(p1,"freepar_",strlen("freepar_"))!=0
708
         && strcmp(p1,"wims_deposit")!=0
709
         && check_parentheses(p,1)) parenth=v;
710
      if(strcmp(p1,"special_parm")==0 && strcmp(p,"wims")==0)
711
        human_access=1;
712
      j=search_list(ro_name,RO_NAME_NO,sizeof(ro_name[0]),p1);
713
      if(j>=0) {
714
          if(j==ro_session) {
715
            p=find_word_start(p); *find_word_end(p)=0;
716
            if(strlen(p)>MAX_SESSIONLEN) continue;
717
            if(strcmp(p,robot_session)==0) p="";
718
            if(strcasecmp(p,"popup")==0) {
719
                mode=mode_popup;
720
                force_setvar("wims_mode","popup");
721
                force_setvar("session","");
722
                continue;
723
            }
724
          }
725
          if(j==ro_module) module_defined=1;
726
          if(j==ro_cmd) {
727
            p=find_word_start(p); *find_word_end(p)=0;
728
            if(strlen(p)>16) continue;
729
            cmd_defined=1;
730
          }
731
          if(j==ro_lang) {
732
            if(strlen(p)!=2) continue;
733
            for(i=0;i<available_lang_no && strcmp(available_lang[i],p)!=0;i++);
734
            if(i<available_lang_no) {user_lang=1; ovlstrcpy(lang,p);}
735
            else continue;
736
          }
737
/* strip leading and trailing '/'s in module name */
738
          if(j==ro_module) {
739
            p=find_word_start(p); *find_word_end(p)=0;
740
            while(*p=='/') p++;
741
            while(*p!=0 && *(p+strlen(p)-1)=='/') *(p+strlen(p)-1)=0;
742
            if(strlen(p)>MAX_MODULELEN) continue;
743
          }
744
          setvar(p1,p);
745
          if(j==ro_session && mode!=mode_popup) {
746
            char *pp, *pr;
747
            char buf[1024];
748
            mystrncpy(buf,p,sizeof(buf));
749
            if((pp=strchr(buf,'.'))!=NULL) {
750
                *pp++=0; session_serial=atoi(pp);
751
                if(pp<0) pp=0;
752
            }
753
            else session_serial=0;
754
            pp=strchr(buf,'_');
755
            if(pp!=NULL && (pr=strstr(pp,"_mhelp"))!=NULL) {
756
                *pr=0; ismhelp=1; lastout_file=-1;
757
                setvar("wims_inssub","mh");
758
            }
759
            force_setvar("wims_session",buf);
760
            if(pp!=NULL) force_setvar("wims_subsession",pp);
761
          }
762
          continue;
763
      }
764
      user_variable[v].name=p1;
765
      user_variable[v].value=p;
766
nnext:v++; if(v>=MAX_VAR_NUM) user_error("too_many_variables");
10 reyssat 767
    }
768
    user_var_no=v;
769
    if(parenth>=0) {
7673 bpr 770
      char buf[16];
771
      mystrncpy(buf,int2str(user_var_no),sizeof(buf));
772
      setvar("user_var_no",buf);
773
      for(i=0;i<user_var_no;i++) {
774
          snprintf(buf,sizeof(buf),"name%d",i);
775
          setvar(buf,user_variable[i].name);
776
          snprintf(buf,sizeof(buf),"value%d",i);
777
          setvar(buf,user_variable[i].value);
778
      }
779
      mystrncpy(buf,int2str(parenth),sizeof(buf));
780
      setvar("bad_parentheses",buf);
781
      user_error("unmatched_parentheses");
10 reyssat 782
    }
7673 bpr 783
    p=getenv("SCRIPT_NAME");
10 reyssat 784
    if(p!=NULL && (p=strstr(p,"/getfile/"))!=NULL) {
7673 bpr 785
      p+=strlen("/getfile/");
786
      force_setvar(ro_name[ro_cmd],commands[cmd_getfile]);
787
      force_setvar("special_parm",p);
788
      cmd_defined=1;
10 reyssat 789
    }
790
    if(module_defined && !cmd_defined) setvar(ro_name[ro_cmd],commands[cmd_intro]);
791
    robot_check(); cookie2session();
792
}
793
 
7673 bpr 794
/* parse special commands */
10 reyssat 795
void special_cmds(void)
796
{
797
    char *c, *p;
798
    int i;
799
    long int l=-1;
7673 bpr 800
 
10 reyssat 801
    c=getvar(ro_name[ro_cmd]);
802
    if(c==NULL || *c==0) {  /* no module name nor command */
7673 bpr 803
      setvar(ro_name[ro_module],home_module);
804
      setvar(ro_name[ro_cmd],commands[cmd_new]);
805
      return;
10 reyssat 806
    }
807
    for(i=0;i<CMD_NO && strcmp(commands[i],c)!=0; i++);
808
    switch(i) {
7673 bpr 809
      case cmd_intro: {
810
          set_module_prefix();
811
          default_form_method="get";
812
          if(ftest(mkfname(NULL,"%s/%s",module_prefix,intro_file))<0) {
813
            force_setvar(ro_name[ro_cmd],commands[cmd_new]);
814
            return;
815
          }
816
          p=getvar("wims_session");
817
          if(p!=NULL && *p!=0) {
818
            if(set_session_prefix()==0) check_session();
819
            else {
820
                trap_check(p);
821
                if(strchr(p,'_')!=NULL && strchr(p,'/')==NULL) {
822
                  get_static_session_var();
823
                }
824
            }
825
          }
826
/* determine http protocol name. How to detect? */
827
          p=getenv("HTTPS"); if(p!=NULL && strcmp(p,"on")==0) {
828
            protocol="https"; set_protocol();
829
          }
830
          force_setvar("wims_protocol",protocol);
831
          determine_font(lang);
832
          determine_dirn(lang);
833
          main_phtml_put(intro_file); debug_output();
834
          introend: write_logs();free(var_str);
835
          delete_pid(); exit(0);
836
      }
837
      case cmd_ref: {
838
          set_module_prefix();
839
          default_form_method="get";
840
          p=getvar("wims_session");
841
          if(p!=NULL && *p!=0) {
842
            if(set_session_prefix()==0) check_session();
843
            else trap_check(p);
844
          }
845
          determine_font(lang);
846
          determine_dirn(lang);
847
          main_phtml_put(ref_file); goto introend;
848
      }
849
      case cmd_getins: {
850
          c=getvar(ro_name[ro_special_parm]);
851
          if(c==NULL || *c==0) {
852
            user_error_nolog=1; user_error("no_insnum");
853
          }
854
          if(*c=='/' || strstr(c,"..")!=NULL) goto badins;
855
          set_session_prefix();
856
          if(strstr(session_prefix,"robot")!=NULL) exit(0);
857
          l=filelength("%s/%s",s2_prefix,c);
858
          if(l<0) {
859
            badins: user_error_nolog=1; user_error("bad_insnum");
860
          }
861
          {
862
            char *fmt;
863
            fmt=strchr(c,'.');
864
            if(fmt==NULL) {
865
                user_error_nolog=1; user_error("bad_insnum");
866
            }
867
            else fmt++;
868
 
869
            nph_header(200);
10 reyssat 870
/* insert format problem; bricolage */
7673 bpr 871
            printf("Content-type: image/%s\r\n\
10 reyssat 872
Content-length: %ld\r\n\r\n",fmt,l);
7673 bpr 873
            catfile(stdout,"%s/%s",s2_prefix,c); exit(0);
874
          }
875
      }
876
      case cmd_getfile: {
877
          char fname[MAX_FNAME+1];
878
          c=getvar(ro_name[ro_special_parm]);
879
          if(c==NULL || *c==0) {
880
            user_error_nolog=1; user_error("no_insnum");
881
          }
882
          if(*c=='/' || strstr(c,"..")!=NULL) goto badfile;
883
 
884
          set_session_prefix();
885
          if(strstr(session_prefix,"robot")!=NULL) exit(0);
886
          mkfname(fname,"%s/getfile/%s",session_prefix,c);
887
          l=filelength("%s",fname);
888
          if(l<0 && strchr(session_prefix,'_')!=NULL) {
889
            char *pt;
890
            mystrncpy(fname,session_prefix,sizeof(fname));
891
            pt=strrchr(fname,'_'); if(pt) *pt=0;
892
            snprintf(fname+(pt-fname),sizeof(fname)-(pt-fname),
893
                  "/getfile/%s",c);
894
            l=filelength("%s",fname);
895
          }
896
          if(l<0) {
897
            badfile: user_error_nolog=1; user_error("bad_insnum");
898
          }
899
          if(l>512*1024) {
900
            struct rlimit rlim;
901
            rlimit_cpu*=l/(10*1024);
902
            rlim.rlim_cur=rlim.rlim_max=rlimit_cpu;
903
            initalarm();
904
          }
905
          {
906
            char *p1;
907
            char mime[MAX_LINELEN+1];
908
            for(p1=c+strlen(c);p1>c && isalpha(*(p1-1)); p1--);
909
            ovlstrcpy(mime,"application/octet-stream");
910
            if(p1>c && *(p1-1)=='.') {
911
                setvar("translator_unknown",mime);
912
                setvar("dictionary","bases/sys/mime");
913
                snprintf(mime,sizeof(mime),"translator %s",p1);
914
                calc_exec(mime);
915
            }
916
            nph_header(200);
917
            printf("Content-type: %s\r\n\
10 reyssat 918
Content-length: %ld\r\n\r\n",mime,l);
7673 bpr 919
            catfile(stdout,"%s",fname); exit(0);
920
          }
921
      }
922
      case cmd_close: {
923
          char *p, b2[32]; int w;
924
          char nbuf[MAX_FNAME+1], vbuf[MAX_LINELEN+1];
925
          p=getvar(ro_name[ro_session]);
926
          if(p==NULL || strlen(p)<10 ||
927
             strchr(p,'/')!=NULL) return;
928
          mystrncpy(b2,p,sizeof(b2));
929
          p=strchr(b2,'.'); if(p!=NULL) *p=0;
930
          mkfname(nbuf,"%s/%s/var.stat",session_dir,b2);
931
          getdef(nbuf,"wims_caller",vbuf);
932
          if(vbuf[0]!=0) force_setvar(ro_name[ro_session],vbuf);
933
          w=wrapexec; wrapexec=1;
934
          call_sh("rm -Rf %s/%s* %s/%s* >/dev/null 2>&1",session_dir,b2,s2_dir,b2);
935
          wrapexec=w; cookiegot[0]=0;
936
          force_setvar(ro_name[ro_cmd],"new");
937
      }
938
      default: return;
10 reyssat 939
    }
940
}
941
 
7673 bpr 942
/* This is run only when manually invoking the program.
8155 bpr 943
 * Verifies the orderedness of various list tables.
944
 */
10 reyssat 945
int verify_tables(void)
946
{
947
    if(verify_order(calc_routine,CALC_FN_NO,sizeof(calc_routine[0]))) return -1;
948
    if(verify_order(exec_routine,EXEC_FN_NO,sizeof(exec_routine[0]))) return -1;
949
    if(verify_order(main_config,MAIN_CONFIG_NO,sizeof(main_config[0]))) return -1;
950
    if(verify_order(mathname,mathname_no,sizeof(mathname[0]))) return -1;
951
    if(verify_order(hmname,hmname_no,sizeof(hmname[0]))) return -1;
952
    if(verify_order(ro_name,RO_NAME_NO,sizeof(ro_name[0]))) return -1;
953
    if(verify_order(distr_cmd,distr_cmd_no,sizeof(distr_cmd[0]))) return -1;
954
    if(verify_order(internal_name,INTERNAL_NAME_NO,
7673 bpr 955
                sizeof(internal_name[0]))) return -1;
10 reyssat 956
    if(verify_order(tmathfn,tmathfn_no,sizeof(tmathfn[0]))) return -1;
957
    if(verify_order(tmathvar,tmathvar_no,sizeof(tmathvar[0]))) return -1;
958
    if(verify_order(modindex,MODINDEX_NO,sizeof(modindex[0]))) return -1;
959
    if(verify_order(exportvars,exportvarcnt,sizeof(exportvars[0]))) return -1;
960
    if(evaltab_verify()) return -1;
961
    if(textab_verify()) return -1;
962
    return 0;
963
}
964
 
965
void config_defaults(void)
966
{
3857 kbelabas 967
    int i;
10 reyssat 968
    for(i=0;i<MAIN_CONFIG_NO;i++) {
7673 bpr 969
      if((1&main_config[i].is_integer)==1) {
970
          int *pi = (int*)main_config[i].address;
971
          printf("DF_%s=%d\n",main_config[i].name, *pi);
3857 kbelabas 972
        }
7673 bpr 973
      else {
3857 kbelabas 974
            char **ps = (char**)main_config[i].address;
7673 bpr 975
          printf("DF_%s=%s\n",main_config[i].name,*ps);
3857 kbelabas 976
        }
10 reyssat 977
    }
978
}
979
 
7673 bpr 980
/* get and set useroptions */
10 reyssat 981
void useropts(void)
982
{
983
    char *p;
984
    setvar("lang",lang);
985
    p=getvar("useropts");
986
    if(p==NULL || *p==0) p=getvar("wims_useropts");
987
    if(p!=NULL && *p!=0) {
6178 bpr 988
      if(myisdigit(p[0])) {
989
        usertexsize=p[0]-'0';
6184 bpr 990
        /* fourth digit is for special fonts*/
6178 bpr 991
        if(p[1]!=0) { mathalign_base=p[1]-'0'; }
992
      }
6184 bpr 993
      if(myisdigit(p[3]) && p[3]!=0){ spec_font=p[3]-'0';}
994
    }
995
    if(mathalign_base==1) {
6178 bpr 996
        mathalign_sup1="<sup>"; mathalign_sup2="</sup>";
6184 bpr 997
    } else mathalign_sup1=mathalign_sup2="";
10 reyssat 998
}
999
 
7673 bpr 1000
/* popup module help */
10 reyssat 1001
void mhelp(void)
1002
{
1003
    char *p, buf[MAX_LINELEN+1];
1004
    main_phtml_put(""); buf[0]=0;
1005
    if(cmd_type!=cmd_help) {
7673 bpr 1006
      phtml_put_base("closemhelp.phtml",0);
10 reyssat 1007
    }
1008
    else {
7673 bpr 1009
      phtml_put_base("mhelpheader.phtml",0);
1010
      p=getvar("special_parm");
1011
      if(p!=NULL && strcmp(p,"about")==0)
1012
        phtml_put("about.phtml",0);
11125 georgesk 1013
      else phtml_put("help.phtml",0);
1014
      phtml_put_base("mhelptail.phtml",0);
7673 bpr 1015
      exec_tail(buf);
10 reyssat 1016
    }
1017
}
1018
 
1019
#define READSTDIN_WINDOW 4096
1020
 
1021
void readstdin(int len)
1022
{
1023
    int ll, l1, lt, lr;
1024
    int cpulim;
7673 bpr 1025
 
10 reyssat 1026
    cpulim=rlimit_cpu; rlimit_cpu=3;
1027
    lr=len; l1=0;
1028
    while(lr>0) {
7673 bpr 1029
      nowtime=time(0); initalarm();
1030
      ll=lr; if(ll>READSTDIN_WINDOW) ll=READSTDIN_WINDOW;
1031
      lt=fread(stdinbuf+l1,1,ll,stdin);
1032
      if(lt!=ll) user_error("parm_too_long");
1033
      lr-=ll; l1+=ll;
10 reyssat 1034
    }
1035
    if(l1!=len) user_error("parm_too_long");
1036
    stdinbuf[len]=0; rlimit_cpu=cpulim;
1037
}
1038
 
7673 bpr 1039
/* input: p=QUERY_STRING. output: parameter length. */
1040
/* Netscape puts form content into /tmp. */
10 reyssat 1041
int formdata(char *p)
1042
{
1043
    char *pp;
1044
    int inlen;
1045
    char *ctype;
1046
    inlen=0; ctype=getenv("CONTENT_TYPE");
1047
    if(ctype==NULL || strstr(ctype,"multipart/form-data")==NULL
1048
       || (p=strstr(ctype,"boundary="))==NULL) {
7673 bpr 1049
      bad: stdinbuf=""; return 0;
10 reyssat 1050
    }
1051
    pp=getenv("CONTENT_LENGTH");
1052
    if(pp==NULL) goto bad;
1053
    inlen=atoi(pp); if(inlen<=10) goto bad;
1054
    if(inlen>=MAX_DEPOSITLEN) user_error("parm_too_long");
1055
    stdinbuf=xmalloc(inlen+1); readstdin(inlen);
1056
    p+=strlen("boundary=");
1057
    for(pp=p;myisalnum(*pp) || *pp=='-'; pp++);
1058
    if(pp-p<sizeof(mpboundary)-2) {
7673 bpr 1059
      memmove(mpboundary,p,pp-p); mpboundary[pp-p]=0;
10 reyssat 1060
    }
7673 bpr 1061
/* empty data */
10 reyssat 1062
    if(strstr(stdinbuf,mpboundary)==NULL || strstr(stdinbuf,"name=")==NULL) {
7673 bpr 1063
      free(stdinbuf); goto bad;
10 reyssat 1064
    }
1065
    form_access=1; post_log();
1066
    return inlen;
1067
}
1068
 
7673 bpr 1069
/* get the content of POST */
10 reyssat 1070
void getpost(void)
1071
{
1072
    int ll;
1073
    char *pp;
1074
    pp=getenv("CONTENT_LENGTH");
1075
    if(pp==NULL || (ll=atoi(pp))<=0) {
7673 bpr 1076
      stdinbuf=xmalloc(16); stdinbuf[0]=0;
10 reyssat 1077
    }
1078
    else {
7673 bpr 1079
      if(ll>QUERY_STRING_LIMIT) user_error("parm_too_long");
1080
      stdinbuf=xmalloc(ll+16); readstdin(ll);
1081
      if(ll>0) {
1082
          setenv("QUERY_STRING",stdinbuf,1);
1083
          form_access=1; post_log();
1084
      }
10 reyssat 1085
    }
1086
}
1087
 
1088
void buffer_init(void)
1089
{
1090
    struct timeval tv;
7673 bpr 1091
 
10 reyssat 1092
    mcachecnt=readnest=0;
1093
    mpboundary[0]=cookiegot[0]=cookieset[0]=cwdbuf[0]=0;
1094
    rscore_class[0]=rscore_user[0]=multiexec_random[0]=0;
1095
    lastftest[0]=0;
1096
    lastdatafile[0]=0; lastdata=xmalloc(WORKFILE_LIMIT);
1097
    outptr=outbuf;
1098
    instex_src[0]=instex_fname[0]=module_prefix[0]=0;
1099
    examlogf[0]=examlogd[0]=exam_sheetexo[0]=0;
1100
    stdinbuf=NULL;
1101
    mkfname(tmp_dir,"../tmp/forall");
1102
    mkfname(session_dir,"../%s",SESSION_BASE);
1103
    mkfname(s2_dir,"../%s",S2_BASE);
1104
    if(gettimeofday(&tv,NULL)) startmtime=startmtime2=0;
1105
    else {
7673 bpr 1106
      startmtime=((tv.tv_sec%10000)*1000+tv.tv_usec/1000);
1107
      startmtime2=(tv.tv_sec%1000)*1000000+tv.tv_usec;
10 reyssat 1108
    }
1109
}
1110
 
8216 bpr 1111
/**
1112
 * runs the test suite, to check whether the documented commands of modtool
1113
 * behave properly.
1114
 * @param prefix path to the proc file to process
1115
 * @param p      name of the proc file to proceed
1116
 * @param vars a list of var names to print.
1117
 **/
1118
void test_suite(char *prefix, char *p, char *vars){
1119
  char *v, *nextv;
1120
  mystrncpy(module_prefix, prefix, sizeof(module_prefix));
1121
  exec_read(p);
1122
  nextv=vars;
1123
  while (*nextv!='\0'){
1124
    v=find_word_start(nextv);
1125
    nextv=find_word_end(v);
1126
    if (*nextv != '\0'){
1127
      *nextv++='\0';
1128
    }
8925 bpr 1129
    v=getvar(v);
1130
    if(v) puts(v); else putchar('\n');
8216 bpr 1131
  }
1132
}
1133
 
10 reyssat 1134
int main(int argc, char *argv[], char *envp[])
1135
{
12011 bpr 1136
    char *p, homebuf[MAX_FNAME+1], lbuf[32], buf[64];
10 reyssat 1137
    int inlen=0;
8155 bpr 1138
/*    int mfd; */
8195 bpr 1139
 
10 reyssat 1140
    class_dir[0]=0;
1141
    substitute=substit; buffer_init(); var_init();
7673 bpr 1142
/* WIMS internal locale is always C. */
10 reyssat 1143
    setenv("LANG","C",1); umask(022);
1144
    setenv("LANGUAGE","us",1);
1145
    setenv("LC_ALL","C",1);
1146
    if(argc>1) {
7673 bpr 1147
      if(strcasecmp(argv[1],"table")==0) {
1148
          if(verify_tables()) internal_error("Table disorder.");
1149
          else printf("Table orders OK.\n");
1150
          return 0;
1151
      }
1152
      if(strcasecmp(argv[1],"version")==0) {
1153
          printf("%s",wims_version); return 0;
1154
      }
1155
      if(strcasecmp(argv[1],"defaults")==0) {
1156
          config_defaults(); return 0;
1157
      }
8216 bpr 1158
      if(strcasecmp(argv[1],"test")==0) {
8851 bpr 1159
/* launches a test suite */
1160
         if (argc < 5) {
1161
           printf("Not enough arguments to launch a test; usage:\n");
1162
           printf("wims test path_to_file name_of_proc_file 'var1 var2 ...'\n\n");
1163
           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");
1164
           return 1;
1165
         }
1166
         test_suite(argv[2], argv[3], argv[4]);
1167
         return 0;
1168
       }
10 reyssat 1169
    }
1170
    p=getenv("SERVER_SOFTWARE"); if(p!=NULL && strcasecmp(p,"WIMS")==0)
1171
      httpd_type=httpd_wims;
1172
    p=getenv("REMOTE_ADDR"); if(p!=NULL) remote_addr=p;
1173
    p=getenv("REMOTE_HOST"); if(p!=NULL) remote_host=p;
1174
    nowtime=time(0); now=localtime(&nowtime);
9286 bpr 1175
/* nowtime contains the seconds elapsed from EPOCH (1970)
1176
   but tm_year is set to current year-1900.
1177
 */
10 reyssat 1178
    memmove(&Now, now, sizeof(Now)); now=&Now;
1179
    snprintf(nowstr,sizeof(nowstr),"%04d%02d%02d.%02d:%02d:%02d",
7673 bpr 1180
           (now->tm_year)+1900,(now->tm_mon)+1,now->tm_mday,
1181
           now->tm_hour,now->tm_min,now->tm_sec);
10 reyssat 1182
    p=getenv("QUERY_STRING");
1183
    if(p==NULL || *p==0) getpost();
1184
    else if(strncmp(p,"form-data",9)==0) inlen=formdata(p);
7673 bpr 1185
 
10 reyssat 1186
    force_setvar("wims_now",nowstr);
1187
    snprintf(lbuf,sizeof(lbuf),"%lu",nowtime);
1188
    force_setvar("wims_nowseconds",lbuf);
1189
    nowtime=time(0);
1190
    initalarm();
7673 bpr 1191
 
10 reyssat 1192
    executed_gotos=insert_no=output_length=0; ins_alt[0]=0;
7673 bpr 1193
    setvar("empty","");       /* lock this variable */
10 reyssat 1194
    setvar("wims_version",wims_version);
1195
    setvar("wims_version_date",wims_version_date);
1196
    setvar("wims_main_font","utf-8");
1197
    take_httpd_vars();
1198
 
1199
    main_configure();
1200
    checklogd();
8155 bpr 1201
/* mfd=shm_open(SHM_NAME,O_RDONLY,-1);
1202
 * if(mfd==-1) internal_error("Unable to find shared memory.");
1203
 * shmptr=mmap(0,SHM_SIZE,PROT_READ,MAP_SHARED,mfd,0);
1204
 * if(shmptr==MAP_FAILED) internal_error("Shared memory failure.");
1205
 */
7673 bpr 1206
    getppid(); /* this is the first sysmask trigger, must be after checklogd() */
10 reyssat 1207
    predetermine_language();
6784 kbelabas 1208
    /* modify a few rlimits for 64-bit processors */
1209
    if (sizeof(long) == 8) {
1210
      rlimit_as*=2;    /* virtual memory size */
1211
      rlimit_data*=2;  /* data segment size; maxima requires a lot */
1212
      rlimit_stack*=2; /* stack size */
1213
    }
10 reyssat 1214
    set_rlimits();
12011 bpr 1215
    /*init_random();*/
1216
    seed_time(); p=getvar("wims_seed"); mystrncpy(buf,p,sizeof(buf)); exec_setseed(buf);
10 reyssat 1217
    module_configure();
1218
    set_job_ident();
1219
    m_file.name[0]=0;m_file.linecnt=m_file.linepointer=0;
1220
    p=getenv("QUERY_STRING");
1221
    if(p==NULL || strlen(p)==0) {
7673 bpr 1222
      setvar("lang",lang);
1223
      snprintf(homebuf,sizeof(homebuf),"module=%s",home_module);
1224
      p=homebuf;
10 reyssat 1225
    }
1226
    if(strlen(p)>=QUERY_STRING_LIMIT) user_error("parm_too_long");
1227
    if(mpboundary[0]==0) {
7673 bpr 1228
      var_str=xmalloc(strlen(p)+2);
1229
      parse_query_string(http2env(var_str,p),0);
10 reyssat 1230
    }
1231
    else {
7673 bpr 1232
      var_str=stdinbuf;
1233
      parse_query_string(inlen,1);
10 reyssat 1234
    }
1235
    if(ismhelp) {
7673 bpr 1236
      p=getvar(ro_name[ro_cmd]);
1237
      if(p==NULL || (strcmp(p,"help")!=0 && strcmp(p,"getins")!=0)) {
1238
          mhelp(); goto outgo;
1239
      }
10 reyssat 1240
    }
1241
    check_exam();
1242
    useropts();
1243
    special_cmds();
1244
    parse_ro_names();
1245
    manager_check();
1246
    access_check(0);
11132 bpr 1247
/* it is really for developing in wims, so no use in general */
11104 bpr 1248
   if (1==1) {
10051 bpr 1249
    if(strstr(tmp_debug,"yes")!=NULL && checkhost(manager_site)>=1)
1250
       trace_file = fopen(mkfname(NULL,"%s/%s",tmp_dir,"trace.txt"),"a");
10129 bpr 1251
   }
10 reyssat 1252
    set_variables();
1253
    determine_font(getvar("module_language"));
3278 reyssat 1254
    determine_dirn(getvar("module_language"));
10 reyssat 1255
    if(!robot_access && session_prefix[0]!=0 && cmd_type!=cmd_help && !ismhelp)
1256
      lastout_file=creat(mkfname(NULL,"%s/%s",s2_prefix,lastout),
7673 bpr 1257
                   S_IRUSR|S_IWUSR);
12011 bpr 1258
    p=getvar("module_score");
1259
    if(p!=NULL) force_setvar("wims_seed_score",p);
10 reyssat 1260
    p=getvar("module_category");
1261
    if(p==NULL || strstr(p,"tool")==NULL) default_form_method="get";
1262
    if(noout) {
7673 bpr 1263
      write_logs(); save_session_vars();
1264
      goto outgo;
10 reyssat 1265
    }
1266
    if(ismhelp) {
7673 bpr 1267
      mhelp();
10 reyssat 1268
    }
1269
    else {
7673 bpr 1270
      main_phtml_put(html_file);
1271
      if(lastout_file!=-1) {
1272
          flushoutput(); close(lastout_file); putlastout();
1273
      }
1274
      write_logs(); save_session_vars();
10 reyssat 1275
    }
1276
    outgo:
1277
    debug_output();
10291 bpr 1278
    if (trace_file)  { fclose(trace_file); trace_file=NULL; }
10 reyssat 1279
    if(var_str!=stdinbuf) free(var_str);
1280
    delete_pid();
1281
    if(mode!=mode_popup && trusted_module()) {
7673 bpr 1282
      p=getvar("wims_mode");
1283
      if(p!=NULL && strcmp(p,"popup")==0) mode=mode_popup;
10 reyssat 1284
    }
1285
    if(mode==mode_popup && insert_no==0) {
7673 bpr 1286
      p=getvar("wims_mode");
1287
      if(p!=NULL && strcmp(p,"popup")==0) {
1288
          remove_tree(session_prefix);
1289
 
1290
          remove_tree(s2_prefix);
1291
      }
10 reyssat 1292
    }
1293
    return 0;
1294
}