Subversion Repositories wimsdev

Rev

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