Subversion Repositories wimsdev

Rev

Rev 17918 | 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
 
8185 bpr 18
/* this is part of wims server source.
19
 * This file does execution commands.
20
 */
21
#include "wims.h"
10 reyssat 22
 
23
static void _skip_contents(int isif);
24
 
8213 bpr 25
/* common routine for the two if's. */
10 reyssat 26
static void _exec_if_while(char *p, int numerical, int isif)
27
{
12245 bpr 28
  if(compare(p,numerical,0)==0) _skip_contents(isif); /* skip if false */
29
  else if(!isif) m_file.for_idx++;
30
  return;
10 reyssat 31
}
32
 
17442 obado 33
/* 'if' non-numerical (unless comparisons are < or >, etc.) */
10 reyssat 34
void exec_if(char *p)
35
{
17442 obado 36
  _exec_if_while(p,0,1);
10 reyssat 37
}
38
 
8213 bpr 39
/* 'if' numerical. */
10 reyssat 40
void exec_ifval(char *p)
41
{
12245 bpr 42
  _exec_if_while(p,1,1);
10 reyssat 43
}
44
 
45
void _exec_while(char *p, int numerical)
46
{
12245 bpr 47
  FOR_STACK *stk;
48
  if(m_file.for_idx>=MAX_FOR_LEVEL) module_error("too_many_fors");
49
  stk=&(m_file.for_stack[m_file.for_idx]);
50
  stk->lineno=m_file.l;
51
  memmove(stk->varname,"?",2);
52
  _exec_if_while(p,numerical,0);
10 reyssat 53
}
54
 
8213 bpr 55
/* 'while' non-numerical (unless comparisons are < or >, etc.) */
10 reyssat 56
void exec_while(char *p)
57
{
12245 bpr 58
  _exec_while(p,0);
10 reyssat 59
}
60
 
8213 bpr 61
/* 'while' numerical. */
10 reyssat 62
void exec_whileval(char *p)
63
{
12245 bpr 64
  _exec_while(p,1);
10 reyssat 65
}
66
 
67
void exec_endwhile(char *p)
68
{
12245 bpr 69
  FOR_STACK *stk;
70
  if(m_file.for_idx<=0) module_error("next_without_for");
71
  stk=&(m_file.for_stack[m_file.for_idx-1]);
72
  if(stk->varname[0]!='?') module_error("next_without_for");
73
  m_file.for_idx--; *p=0;
74
  m_file.linepointer=stk->lineno;
75
  executed_gotos++;
76
  if(executed_gotos>=GOTO_LIMIT) module_error("too_many_gotos");
10 reyssat 77
}
78
 
8213 bpr 79
/* Should provide a method to stop infinite loop. */
10 reyssat 80
void exec_goto(char *p)
81
{
12245 bpr 82
  char lbuf[MAX_NAMELEN+17];
83
  char *label_start, *line_start;
84
  int old_line;
85
  int i;
86
  executed_gotos++;
87
  if(executed_gotos>=GOTO_LIMIT) module_error("too_many_gotos");
88
  old_line=m_file.l;
89
  label_start=find_word_start(p);
90
  *find_word_end(label_start)=0;
91
  m_file.l=m_file.linepointer=0;
92
  for(i=0;i<m_file.linecnt;i++) {
93
    if(((m_file.lines[i].isstart)&4)==0) continue;
94
    line_start=find_word_start((m_file.lines[i]).address);
95
    if(line_start>(m_file.lines[i+1]).address && i<m_file.linecnt)
96
      continue;
97
    m_file.linepointer=i;
98
    wgetline(lbuf,MAX_NAMELEN+8,&m_file);
99
    line_start=find_word_start(lbuf);
100
    if(*line_start!=label_prefix_char) continue;
101
    line_start++;*find_word_end(line_start)=0;
102
    if(line_start[0]!='*' && strcmp(line_start,label_start)!=0) continue;
103
    *p=0; i++; return;
104
  }
105
  m_file.l=old_line;
106
  setvar(error_data_string,label_start); module_error("label_not_found");
107
/*    m_file.linepointer=m_file.linecnt; *p=0; return;
108
*/
109
}
10 reyssat 110
 
8213 bpr 111
/* 'else' with or without 'if'.
112
 * Philosophy: we implement a loosely checked grammar.
113
 * We cannot check 'if' grammar if we want to use 'goto'
114
 * together with 'if'.
115
 */
10 reyssat 116
void exec_else(char *p)
117
{
12245 bpr 118
  _skip_contents(1); return;
10 reyssat 119
}
120
 
8213 bpr 121
/* 'endif': nothing needs to be done here. */
10 reyssat 122
void exec_endif(char *p)
123
{
12245 bpr 124
  return;
10 reyssat 125
}
126
 
8213 bpr 127
/* find out the end of a for loop */
10 reyssat 128
void goto_for_end(void)
129
{
12245 bpr 130
  int inner;
131
  char buf[16];
132
  inner=0;
133
  while(m_file.linepointer<m_file.linecnt) {
134
    if((m_file.lines[m_file.linepointer].isstart&2)==0) {
135
      m_file.linepointer++; continue;
136
    }
137
    if(wgetline(buf,8,&m_file)==EOF) break;
138
    *find_word_end(buf)=0;
139
    if(strcmp(buf,"!for")==0) {
140
      inner++; continue;
141
    }
142
    if(strcmp(buf,"!next")==0) {
143
      if(inner>0) {
144
        inner--; continue;
7379 bpr 145
      }
12245 bpr 146
      else break;
10 reyssat 147
    }
12245 bpr 148
  }
10 reyssat 149
}
150
 
8213 bpr 151
/* for */
10 reyssat 152
void exec_for(char *p)
153
{
12245 bpr 154
  char *p1, *p2, *p3;
155
  double v1, v2, step;
156
  char buf[MAX_LINELEN+1];
157
  FOR_STACK *stk;
10 reyssat 158
 
12245 bpr 159
  if(m_file.for_idx>=MAX_FOR_LEVEL) module_error("too_many_fors");
160
  stk=&(m_file.for_stack[m_file.for_idx]);
161
  stk->lineno=m_file.l;
162
  p1=find_word_start(p);
163
  for(p2=p1; !isspace(*p2) && *p2!=0 && *p2!='=' ; p2++);
164
  if(*p2==0) syntax: module_error("for_syntax");
165
  if(p2-p1>MAX_NAMELEN) module_error("name_too_long");
166
  memmove(stk->varname,p1,p2-p1);
167
  stk->varname[p2-p1]=0;
168
  p1=find_word_start(p2); if(*p1==0) goto syntax;
169
  if(*p1=='=') {
170
    p1++;
171
    assign:
172
    stk->from=0;
173
    p2=wordchr(p1,"to");
174
    if(p2==NULL) p2=strstr(p1,"..");
175
    if(p2==NULL) goto syntax;
176
    *p2=0; p2+=2;
177
    p3=wordchr(p2,"step");
178
    if(p3!=NULL) {
179
      *p3=0; p3+=strlen("step");
180
      step=evalue(p3);
181
      if(step==0) module_error("zero_step");
182
    }
183
    else step=1;
184
      v1=evalue(p1); v2=evalue(p2);
185
      float2str(v1,buf); setvar(stk->varname, buf);
186
      if((step>0 && v1>v2) || (step<0 && v1<v2) ) {  /* condition not met */
10 reyssat 187
  loop_out:
7379 bpr 188
        goto_for_end();
189
      }
12245 bpr 190
    else {
191
      stk->varval=v1; stk->varend=v2; stk->step=step;
192
      stk->lineno=m_file.linepointer;
193
      m_file.for_idx++;
10 reyssat 194
    }
12245 bpr 195
    *p=0; return;
196
  }
197
  if(memcmp(p1,"from",strlen("from"))==0 && isspace(*(p1+strlen("from")))) {
198
    p1+=strlen("from"); goto assign;
199
  }
200
  if(memcmp(p1,"in",strlen("in"))==0 && isspace(*(p1+strlen("in")))) {
201
    stk->from=1; p1+=strlen("in");
202
    p1=find_word_start(p1); if(*p1==0) goto loop_out;
203
    p2=xmalloc(MAX_LINELEN+1);
204
    mystrncpy(p2,p1,MAX_LINELEN);
205
    substit(p2);
206
    strip_trailing_spaces(p2);
207
    if(*p2==0) goto loop_out;
208
    p1=strparchr(p2,','); stk->bufpt=p2;
209
    if(p1!=NULL) {
210
      *p1=0; stk->list_pt=find_word_start(p1+1);
10 reyssat 211
    }
12245 bpr 212
    else stk->list_pt=NULL;
213
    strip_trailing_spaces(p2); setvar(stk->varname,p2);
214
    stk->lineno=m_file.linepointer;
215
    m_file.for_idx++; *p=0; return;
216
  }
217
  goto syntax;
10 reyssat 218
}
219
 
8213 bpr 220
/* break a for loop */
10 reyssat 221
void exec_break(char *p)
222
{
12245 bpr 223
  FOR_STACK *stk;
224
  if(m_file.for_idx>0) {
225
    stk=&(m_file.for_stack[m_file.for_idx-1]);
226
    if(stk->varname[0]=='?') _skip_contents(0);
227
    else goto_for_end();
228
    m_file.for_idx--;
229
  }
230
  *p=0; return;
10 reyssat 231
}
232
 
8213 bpr 233
/* next */
10 reyssat 234
void exec_next(char *p)
235
{
12245 bpr 236
  double v1, v2, step;
237
  char *p1, *p2;
238
  char buf[MAX_LINELEN+1];
239
  FOR_STACK *stk;
240
  if(m_file.for_idx<=0) module_error("next_without_for");
241
  stk=&(m_file.for_stack[m_file.for_idx-1]);
242
  if(stk->varname[0]=='?') module_error("next_without_for");
243
  if(stk->from) { /* list style */
244
    if(stk->list_pt==NULL) {
245
      free(stk->bufpt);
246
      m_file.for_idx--;
247
      *p=0; return;
10 reyssat 248
    }
12245 bpr 249
    p1=strchr(stk->list_pt,',');
250
    if(p1!=NULL) {
251
      *p1=0; p2=find_word_start(p1+1);
10 reyssat 252
    }
12245 bpr 253
    else p2=NULL;
254
    strip_trailing_spaces(stk->list_pt);
255
    setvar(stk->varname,stk->list_pt);
256
    stk->list_pt=p2; goto loop_back;
257
  }
258
  v1=stk->varval; v2=stk->varend; step=stk->step;
259
  v1+=step; stk->varval=v1;
260
  float2str(v1,buf);
261
  setvar(stk->varname, buf);
262
  if((step>0 && v1<=v2) || (step<0 && v1>=v2)) { /* loop */
263
    loop_back:
264
    m_file.linepointer=stk->lineno;
265
    executed_gotos++;
266
    if(executed_gotos>=GOTO_LIMIT) module_error("too_many_gotos");
267
  }
268
  else m_file.for_idx--;
269
  *p=0; return;
10 reyssat 270
}
271
 
8213 bpr 272
/* Execution of a file in the module directory,
273
 * only for trusted modules.
274
 */
10 reyssat 275
void exec_mexec(char *p)
276
{
12245 bpr 277
  direct_exec=1;
278
  calc_mexec(p);
279
  direct_exec=0;
10 reyssat 280
}
281
 
8213 bpr 282
/* call shell. */
10 reyssat 283
void _exec_ex(char *p, char *arg0, char *arg1, int n)
284
{
12245 bpr 285
  char *abuf[8];
286
  char errorfname[MAX_FNAME+1];
10 reyssat 287
 
12245 bpr 288
  if(robot_access) {
289
    *p=0; return;
290
  }
291
  if(!noout || !trusted_module() || is_class_module) {
292
    _calc_exec(p,arg0,arg1,n); if(outputing) output0(p);
293
    return;
294
  }
295
  mkfname(errorfname,"%s/exec.err",tmp_dir);
296
  abuf[0]=arg0; abuf[1]=arg1; abuf[n]=p; abuf[n+1]=NULL;
297
  wrapexec=1; exportall();
298
  execredirected(abuf[0],NULL,NULL,errorfname,abuf);
10 reyssat 299
}
300
 
8213 bpr 301
/* call shell. */
10 reyssat 302
void exec_sh(char *p)
303
{
12245 bpr 304
  _exec_ex(p,"sh","-c",2);
10 reyssat 305
}
306
 
8213 bpr 307
/* call perl. */
10 reyssat 308
void exec_perl(char *p)
309
{
12245 bpr 310
  _exec_ex(p,"perl","-e",2);
10 reyssat 311
}
312
 
8213 bpr 313
/* file should not be cached */
10 reyssat 314
void exec_nocache(char *p)
315
{    m_file.nocache|=1; *p=0; }
316
 
8214 bpr 317
/*
318
 * Read another file.
319
 * Read a file in order to perform tests.
320
 * Relevant global variables:
321
 * - m_file, a WORKING_FILE structure (should be restored to its original
322
 *   value at the end of the procedure)
323
 * - untrust, an integer (should be restored to its original
324
 *   value at the end of the procedure)
325
 * - outputing, an integer; its value is juste read.
326
 * - readnest, an integer, which is incremented during the function
327
 *   and decremented when it finishes.
328
 * Relevant global variables used in subprograms:
329
 * - module_prefix, a const char * which will be preprended before
330
 *   the filename, (see lines.c, label = openit).
331
 * Relevant wims_environment parameters:
332
 * - wims_read_parm  (should be restored to its original
333
 *   value at the end of the procedure)
334
 * - wims_trustfile: this parameter is only read.
335
 * Important procedures called by this one:
336
 * - phtml_put(char*, int)
337
 * - var_proc(char*, int)
338
 * - module_error(const char*)
339
 * @param p pointer to the filename, possibly followed by parameters
340
 */
341
 
10 reyssat 342
void exec_read(char *p)
343
{
12245 bpr 344
  WORKING_FILE save;
345
  char parmsave[MAX_LINELEN+1];
346
  char *pp,*ps;
347
  int t,cache;
7379 bpr 348
 
12245 bpr 349
  strip_trailing_spaces(p);p=find_word_start(p);
350
  if(*p==0) return;
351
  pp=find_word_end(p); if(*pp) *pp++=0;
352
  pp=find_word_start(pp);
353
  ps=getvar("wims_read_parm"); if(ps==NULL) ps="";
354
  mystrncpy(parmsave,ps,sizeof(parmsave));
355
  setvar("wims_read_parm",pp);
356
  memmove(&save,&m_file,sizeof(WORKING_FILE));
357
  cache=1; if(p[0]=='.' && p[1]=='/') {p+=2; cache=0;}
358
  t=untrust;
359
  if(strncmp(p,"wimshome/",9)==0) {
360
    if((untrust&255)!=0 &&
7379 bpr 361
        (m_file.name[0]=='/' || strncmp(m_file.name,"wimshome/",9)==0))
12245 bpr 362
      module_error("Illegal_file_access");
13691 bpr 363
    untrust|=0x200;
364
  }
12245 bpr 365
  if((untrust&0x202)!=0) {
366
    pp=getvar("wims_trustfile");
367
    if(pp!=NULL && *pp!=0 && wordchr(pp,p)!=NULL)
368
      untrust&=0xfdfd;
369
  }
370
  readnest++; if(readnest>MAX_READNEST) module_error("too_many_nested_read");
371
  if(outputing) phtml_put(p,cache); else var_proc(p,cache);
372
  readnest--; untrust=t;
373
  memmove(&m_file,&save,sizeof(WORKING_FILE));
374
  if (trace_file){
375
    int i;
376
    putc('\n',trace_file);
377
    for(i=1; i<=2*trace_indent-2; i++) putc(' ',trace_file);
378
    fprintf(trace_file,"%s:",m_file.filepath); fflush(trace_file);
379
  }
380
  setvar("wims_read_parm",parmsave);
10 reyssat 381
}
382
 
8213 bpr 383
/* read a variable processing file */
10 reyssat 384
void exec_readproc(char *p)
385
{
12245 bpr 386
  int o=outputing; outputing=0; exec_read(p); outputing=o;
10 reyssat 387
}
388
 
389
void exec_defread(char *p)
390
{
12245 bpr 391
  int t,o;
392
  secure_exec();
393
  t=untrust; untrust|=0x400;
394
  o=outputing; outputing=0;
395
  exec_read(p); untrust=t; outputing=o;
10 reyssat 396
}
397
 
8213 bpr 398
/* Change to another file (no return) */
10 reyssat 399
void exec_changeto(char *p)
400
{
12245 bpr 401
  m_file.linepointer=m_file.linecnt;
402
  exec_read(p);
10 reyssat 403
}
404
 
405
int header_executed=0, tail_executed=0;
406
 
8213 bpr 407
/* internal routine: get other language versions */
10 reyssat 408
void other_langs(void)
409
{
12245 bpr 410
  int i,j,k;
411
  char *p, lbuf[4], pbuf[MAX_FNAME+1], *phtml;
412
  char namebuf[MAX_FNAME+1], listbuf[4*MAX_LANGUAGES];
413
  static int otherlangs_got=0;
10 reyssat 414
 
12245 bpr 415
  if(otherlangs_got) return;
416
  mystrncpy(namebuf,module_prefix,sizeof(namebuf));
417
  listbuf[0]=0;j=strlen(namebuf)-3; p=listbuf;
418
  if(j>=2 && strcmp("light",namebuf+j-2)==0) {
419
    setvar("wims_light_module","yes");
420
    phtml=getvar("phtml");
421
    if(phtml==NULL || *phtml==0) return;
422
    mystrncpy(pbuf,phtml,sizeof(pbuf));
423
    j=strlen(pbuf)-3;
424
    if(pbuf[j]!='.') return;
425
    j++; ovlstrcpy(lbuf,pbuf+j); pbuf[j]=0;
426
    j=strlen(namebuf);
427
    snprintf(namebuf+j,MAX_FNAME-j-10,"/pages/%s",pbuf);
428
    j=strlen(namebuf);
429
    for(i=k=0;i<available_lang_no;i++) {
430
      if(strcmp(lbuf,available_lang[i])==0) continue;
431
      mystrncpy(namebuf+j,available_lang[i],MAX_FNAME-j);
432
      if(ftest(namebuf)<0) continue;
433
      if(k>0) *p++=',';
434
      mystrncpy(p,available_lang[i],sizeof(listbuf)-4-(p-listbuf));
435
      p+=strlen(p);
436
      k++;
10 reyssat 437
    }
12245 bpr 438
  goto end;
439
  }
440
  if(j>0 && namebuf[j]=='.') {
441
    setvar("wims_light_module","");
442
    j++; ovlstrcpy(lbuf,namebuf+j); namebuf[j]=0;
443
    for(i=k=0;i<available_lang_no;i++) {
444
      if(strcmp(lbuf,available_lang[i])==0) continue;
445
      snprintf(namebuf+j,MAX_FNAME-j,"%s/main.phtml",
446
           available_lang[i]);
447
      if(ftest(namebuf)<0) continue;
448
      if(k>0) *p++=',';
449
      mystrncpy(p,available_lang[i],sizeof(listbuf)-4-(p-listbuf));
450
      p+=strlen(p);
451
      k++;
10 reyssat 452
    }
12245 bpr 453
  }
454
  end: setvar("wims_otherlangs",listbuf); otherlangs_got=1;
10 reyssat 455
}
456
 
8213 bpr 457
/* Standardised reference to wims home */
10 reyssat 458
void exec_homeref(char *p)
459
{
12245 bpr 460
  char *ref, *user;
7379 bpr 461
 
12245 bpr 462
  if(ismhelp || tail_executed) return;
463
  setvar("wims_homeref_parm",p); *p=0;
464
  user=getvar("wims_user");
465
  if(user==NULL) user="";
466
  if(*user==0 || robot_access) ref=home_referer;
467
  else {
468
    if(strcmp(user,"supervisor")==0) ref=home_referer_supervisor;
469
    else ref=home_referer_user;
470
  }
471
  if(user[0]==0 && !robot_access) other_langs();
472
  phtml_put_base(ref,0); tail_executed=1;
10 reyssat 473
}
474
 
8213 bpr 475
/* Standardised header menu */
10 reyssat 476
void exec_headmenu(char *p)
477
{
12245 bpr 478
  char *ref, *user;
7379 bpr 479
 
12245 bpr 480
  if(header_executed) return;
481
  setvar("wims_headmenu_parm",p); *p=0;
482
  user=getvar("wims_user");
483
  if(user==NULL) user="";
484
  if(*user==0 || robot_access) ref=header_menu;
485
  else {
486
    if(strcmp(user,"supervisor")==0) ref=header_menu_supervisor;
487
    else ref=header_menu_user;
488
  }
489
  if(user[0]==0 && !robot_access) other_langs();
490
  phtml_put_base(ref,0); header_executed=1;
10 reyssat 491
}
492
 
8213 bpr 493
/* uniformized title */
10 reyssat 494
void exec_title(char *p)
495
{
12245 bpr 496
  char *s;
497
  *p=0;
498
  if(!outputing) return;
499
  s=getvar("wims_title_title");
500
  if(s==NULL || *s==0) {
501
    s=getvar("module_title");
502
    if(s==NULL || *s==0) return;
503
    force_setvar("wims_title_title",s);
504
  }
505
  phtml_put_base(title_page,0);
10 reyssat 506
}
507
 
8213 bpr 508
/* standardized html tail */
10 reyssat 509
void exec_tail(char *p)
510
{
12245 bpr 511
  if(!outputing || tail_executed) {
512
    *p=0; return;
513
  }
514
  if(!ismhelp) exec_homeref(p);
515
  *p=0;
516
  _output_("</body></html>");
517
  tail_executed=1;
10 reyssat 518
}
519
 
5925 bpr 520
void exec_formend(char *p)
521
{
12245 bpr 522
  _output_("\n</div></form>");
5925 bpr 523
}
524
 
10 reyssat 525
void determine_font(char *l);
526
 
11071 schaersvoo 527
/* see changelog wims_mathml for history */
13744 obado 528
void _headmathjax (char *p)
7379 bpr 529
{
12737 obado 530
  _output_("\n<script>/*<![CDATA[*/\
9618 schaersvoo 531
function wims_mathml_zoom(id){\
532
var math = document.getElementById(id);\
533
if(math.getAttribute(\"mathsize\") == \"100%\"){\
10964 obado 534
  math.setAttribute(\"mathsize\",\"200%\");}else{\
535
  math.setAttribute(\"mathsize\",\"100%\");};\
9618 schaersvoo 536
};\
14608 obado 537
window.addEventListener(\"load\", function() {\
13744 obado 538
  var ua = navigator.userAgent.toLowerCase();\
539
  var gecko = ua.indexOf(\"gecko\") > -1 && ua.indexOf(\"khtml\") === -1 && ua.indexOf(\"trident\") === -1;\
540
  if(! gecko ){\
541
    var script = document.createElement(\"script\");\
16628 obado 542
    script.src  = \"scripts/js/mathjax/mml-chtml.js\";\
13744 obado 543
    document.head.appendChild(script);\
544
  };\
545
});/*]]>*/</script>\n");
12737 obado 546
 
547
  // Safari/MathJax bugfix : refresh display when document ready.
548
  _output_("\n<script>\
549
reload_mathML=function(){var t=document.getElementsByClassName(\"wims_mathml\");Array.prototype.filter.call(t,function(t){var e=t.style.display;t.style.display=\"none\",t.style.opacity=\"0\",setTimeout(function(){t.style.display=e},1e3),setTimeout(function(){t.style.opacity=\"1\"},1100)})},document.onreadystatechange=function(){\"complete\"===document.readyState&&(/^((?!chrome|android).)*safari/i.test(navigator.userAgent)&&reload_mathML())};\
550
</script>");
7370 bpr 551
}
552
 
8213 bpr 553
/* standardized header */
1050 bpr 554
void _header(char *p, int option)
10 reyssat 555
{
12245 bpr 556
  char *s1, *s2, hbuf[MAX_LINELEN+1], *ws="", *ws2="", *bo, *ol;
557
  char wsbuf[MAX_LINELEN+1],wsbuf2[MAX_LINELEN+1];
558
  setvar("wims_header_parm",p); *p=0;
559
  if(!outputing || header_executed) return;
560
  s1=getvar("wims_window");
561
  if(mode==mode_popup) {
562
    if(s1!=NULL && *s1!=0) {
563
      char *p1, *p2;
564
      int t1,t2/*,t3,t4*/;
565
      p1=find_word_start(s1);
566
      for(p2=p1; myisdigit(*p2); p2++);
567
      *p2=0; t1=atoi(p1); p1=p2+1;
568
      while(!myisdigit(*p1) && *p1) p1++;
569
      for(p2=p1; myisdigit(*p2); p2++);
570
      *p2=0; t2=atoi(p1); p1=p2+1;
7379 bpr 571
/*        while(!myisdigit(*p1) && *p1) p1++;
572
        for(p2=p1; myisdigit(*p2); p2++);
573
        *p2=0; t3=atoi(p1); p1=p2+1;
574
        while(!myisdigit(*p1) && *p1) p1++;
575
        for(p2=p1; myisdigit(*p2); p2++);
576
        *p2=0; t4=atoi(p1); p1=p2+1;
577
        while(!myisdigit(*p1) && *p1) p1++;
578
        for(p2=p1; myisdigit(*p2); p2++);
579
        if(t3<5) t3=5; if(t4<20) t4=20;
12245 bpr 580
*/     snprintf(wsbuf,sizeof(wsbuf),
7379 bpr 581
          "window.focus();window.resizeTo(%d,%d);",t1,t2); ws=wsbuf;
582
/*      snprintf(wsbuf,sizeof(wsbuf),
583
             "window.focus();window.resizeto(%d,%d);window.moveto(%d,%d);",
584
             t1,t2,t3,t4); ws=wsbuf;
12245 bpr 585
*/   }
586
  }
587
  else {
588
    if(s1!=NULL && strcmp(s1,"new")==0)
7379 bpr 589
      ws="window.focus();window.resizeTo(800,640);window.moveTo(15,35);";
12245 bpr 590
  }
591
  if(strstr(session_prefix,"_exam")!=NULL) {
7379 bpr 592
/*    char buf[64]; */
12245 bpr 593
    if(*ws==0) ws="window.focus();";
594
    else ws= "window.focus();window.moveTo(5,70);";
7379 bpr 595
/*    snprintf(buf,sizeof(buf),"name.phtml.%s",lang);
596
      phtml_put_base(buf);
597
      phtml_put_base("jsclock.phtml"); */
12245 bpr 598
  }
599
  s1=getvar("wims_html_header"); if(s1==NULL) s1="";
600
  determine_font(getvar("module_language"));
601
  s2=getvar("module_title"); if(s2!=NULL && *s2!=0) {
602
    mystrncpy(hbuf,s2,sizeof(hbuf)); calc_detag(hbuf);
603
    setvar("module_title2",hbuf);
604
  }
605
  mystrncpy(hbuf,s1,sizeof(hbuf)); substit(hbuf);
606
  s2=getvar("wims_htmlbody"); if(s2==NULL) s2="";
607
  bo=getvar("wims_html_bodyoption"); if(bo==NULL) bo="";
608
  ws2=getvar("wims_html_onload"); if(ws2==NULL) ws2="";
609
  snprintf(wsbuf2,sizeof(wsbuf2),"%s%s",ws,ws2);
610
  setvar("wims_html_onload",wsbuf2);
611
  if(wsbuf2[0]) ol=" onload="; else ol="";
13744 obado 612
 
613
  output("<!DOCTYPE html>\
614
    \n<html lang=\"%s\"><head>\n\
17170 bpr 615
    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, minimum-scale=1.0\">\n\
13744 obado 616
    %s\n", lang, hbuf);
15277 obado 617
  if(robot_access){
17170 bpr 618
    output("<link rel=\"stylesheet\" href=\"html/themes/_css/robots.css\">");
15277 obado 619
  }
13744 obado 620
 
621
  _headmathjax(p);
622
 
12245 bpr 623
  if(ol[0]) {
13744 obado 624
    output("</head>\n<body %s %s\"%s\" %s>", s2, ol, wsbuf2, bo);}
625
  else {
626
    output("</head>\n<body %s %s%s %s>", s2, ol, wsbuf2, bo);
12245 bpr 627
  }
628
  exec_headmenu(p);
629
  if(option) exec_title(p);
630
  if(cmd_type==cmd_help) {
631
    char *s=getvar("special_parm");
632
    if(s==NULL) s="";
633
    m_file.linepointer=m_file.linecnt;
634
    if(strcmp(s,"about")==0) ovlstrcpy(hbuf,"about.phtml");
635
    else ovlstrcpy(hbuf,"help.phtml");
636
    exec_read(hbuf); exec_tail(p); /* param of exec_...() must be readable */
637
    return;
638
  }
639
  header_executed=1;
10 reyssat 640
}
641
 
1050 bpr 642
void exec_header(char *p) { _header(p,1);}
643
void exec_header1(char *p) { _header(p,0);}
15502 bpr 644
void exec_headmathjax(char *p) { _headmathjax(p);}
1050 bpr 645
 
10 reyssat 646
char href_target[128];
647
char jsbuf[512];
5729 bpr 648
#define jsstr " onclick=\"%s=window.open('','%s','status=no,toolbar=no,location=no,menubar=no,scrollbars=yes,resizable=yes')\""
10 reyssat 649
int ref_mhelp=0;
650
int follow_list[]={
12245 bpr 651
  ro_session, ro_lang, ro_useropts, ro_module
10 reyssat 652
};
653
#define follow_no (sizeof(follow_list)/sizeof(follow_list[0]))
654
 
655
void _httpfollow(char b1[], char *wn, int new)
656
{
12245 bpr 657
  int i;
658
  char *p1, *s, *ss, sb[MAX_LINELEN+1], qbuf[MAX_LINELEN+1];
10 reyssat 659
 
12245 bpr 660
  sb[0]=0;
661
  for(i=0;i<follow_no;i++) {
662
    if(robot_access && follow_list[i]==ro_session) continue;
663
    if(!new && follow_list[i]!=ro_session
664
        && follow_list[i]!=ro_module && follow_list[i]!=ro_lang)
665
      continue;
666
    if(follow_list[i]==ro_module) {
667
      char *pp;
668
      if(new) continue;
669
      pp=strstr(b1,"cmd=");
670
      if(pp==NULL) continue;
671
      pp+=strlen("cmd=");
672
      if(memcmp(pp,"intro",strlen("intro"))==0 ||
673
         memcmp(pp,"new",strlen("new"))==0) continue;
674
    }
675
    s=getvar(ro_name[follow_list[i]]);
676
    ss=strstr(b1,ro_name[follow_list[i]]);
677
    if(s!=NULL && *s!=0 &&
678
      (ss==NULL || (ss>b1 && *(ss-1)!='&')
679
       || *(ss+strlen(ro_name[follow_list[i]]))!='=')) {
680
      if(follow_list[i]==ro_session && memcmp(href_target,"wims_",5)==0) {
681
        char st[MAX_LINELEN+1];
682
        char *s1;
683
        s1=getvar("wims_session");
684
        if(s1==NULL) internal_error("exec_href() error.\n");
685
        if(ref_mhelp) {
686
          if(strstr(s1,"_mhelp")!=0)
687
            snprintf(st,sizeof(st),"%s",s1);
688
          else
689
            snprintf(st,sizeof(st),"%s_mhelp",s1);
690
        }
7379 bpr 691
        else snprintf(st,sizeof(st),"%.10s%s",s1,href_target+4);
692
          s=st;
12245 bpr 693
      }
694
      snprintf(sb+strlen(sb),MAX_LINELEN-strlen(sb),"%s=%s&",
7379 bpr 695
             ro_name[follow_list[i]],s);
12245 bpr 696
      if(ismhelp && follow_list[i]==ro_session &&
7379 bpr 697
           strstr(sb,"_mhelp")==NULL)
12245 bpr 698
        snprintf(sb+strlen(sb)-1,MAX_LINELEN-strlen(sb)+1,"_mhelp&");
7379 bpr 699
      }
12245 bpr 700
  }
701
  snprintf(qbuf,MAX_LINELEN,"%s%s%s",wn,sb,b1);
702
  /* cleaning up query string */
703
  for(p1=qbuf;*p1;p1++) {
704
    if(*p1=='"') string_modify(qbuf,p1,p1+1,"%22");
705
    if(*p1=='&' && isalpha(*(p1+1))) {
706
      p1++; string_modify(qbuf,p1,p1,"+");
10 reyssat 707
    }
12245 bpr 708
  }
709
  mystrncpy(b1,qbuf,MAX_LINELEN);
10 reyssat 710
}
711
 
8213 bpr 712
/* Restart with a new module, using http code 302. */
10 reyssat 713
void exec_restart(char *p)
714
{
13887 obado 715
  /* buf will contain all the url parameters*/
716
  /* buf2 will be the final URL */
12245 bpr 717
  char buf[MAX_LINELEN+1], *rfn, buf2[MAX_LINELEN+1];
13887 obado 718
  /* long int t; */
7379 bpr 719
 
12245 bpr 720
  if(robot_access || outputing || !trusted_module() || is_class_module) return;
13887 obado 721
  /* accessfile(buf,"r","%s/restart.time",s2_prefix);
7379 bpr 722
    t=atoi(buf); if(t==nowtime) return;    */ /* possible looping */
12245 bpr 723
  mystrncpy(buf,find_word_start(p),sizeof(buf));
724
  *find_word_end(buf)=0;
725
  _httpfollow(buf,"",0);
13887 obado 726
  nph_header(302);
12245 bpr 727
  rfn=strchr(ref_name,':');
728
  if(rfn==NULL) {
729
    usual: snprintf(buf2,sizeof(buf2),"%s?%s",ref_name,buf);
730
  }
731
  else {
732
    char *p;
733
    p=getvar("wims_protocol");
734
    if(p!=NULL && strcmp(p,"https")==0) {
735
      snprintf(buf2,sizeof(buf2),"https%s?%s",rfn,buf);
10 reyssat 736
    }
12245 bpr 737
    else goto usual;
738
  }
739
  printf("Location: %s\r\n\r\n\
11726 bpr 740
<!DOCTYPE html>\
10 reyssat 741
<html><body><a href=\"%s\">%s</a></body></html>",buf2,buf2,buf2);
12245 bpr 742
  close_working_file(&m_file,0); write_logs();
743
  snprintf(buf,sizeof(buf),"%ld",(long)nowtime);
744
/*    accessfile(buf,"w","%s/restart.time",s2_prefix);*/
745
  delete_pid(); exit(0);
10 reyssat 746
}
747
 
12245 bpr 748
/*  extract target tag from parm string. */
10 reyssat 749
void href_find_target(char *p)
750
{
12245 bpr 751
  char *pp, *pe,buf1[MAX_LINELEN+1];
752
  href_target[0]=0; jsbuf[0]=0; ref_mhelp=0;
753
  for(pp=find_word_start(p);*pp!=0;pp=find_word_start(pe)) {
754
    pe=find_word_end(pp);
755
    if(strncasecmp(pp,"target=wims_",strlen("target=wims_"))!=0) continue;
756
    memmove(buf1,pp,pe-pp); buf1[pe-pp]=0; substit(buf1);
757
    if(strncasecmp(buf1,"target=wims_mhelp",strlen("target=wims_mhelp"))==0) {
758
      if(*pe!=0) *pe++=0;
759
      ovlstrcpy(href_target,"wims_help");
760
      ref_mhelp=1;
761
    }
762
    else {
763
      if(*pe!=0) *pe++=0;
764
        mystrncpy(href_target,buf1+strlen("target="),sizeof(href_target));
765
    }
766
    snprintf(jsbuf,sizeof(jsbuf),jsstr,href_target,href_target);
767
    ovlstrcpy(pp,pe);return;
768
  }
769
  pp=getvar("module_help");
770
  if(href_target[0]==0 && pp!=NULL && strcmp(pp,"popup")==0 &&
771
     (pe=strstr(p,"cmd=help"))!=NULL) {
772
    if(pe==p || *(pe-1)=='&') {
773
      ovlstrcpy(href_target,"wims_help"); ref_mhelp=1;
7379 bpr 774
      snprintf(jsbuf,sizeof(jsbuf),jsstr,href_target,href_target);
10 reyssat 775
    }
12245 bpr 776
  }
10 reyssat 777
}
778
 
779
void _href_getdef(char src[], char vname[], char buf[], int buflen)
780
{
12245 bpr 781
  char *p1, *p2, *p3;
782
  buf[0]=0;
783
  for(p1=strstr(src,vname); p1; p1=strstr(p2,vname)) {
784
    p2=p1+strlen(vname); if(*p2!='=') continue;
785
    if(p1>src && *(p1-1)!='&') continue;
786
    p2++; p3=strchr(p2,'&'); if(p3==NULL) p3=p2+strlen(p2);
787
    if(p3-p2>=buflen) return; /* too long */
788
    memmove(buf,p2, p3-p2); buf[p3-p2]=0; return;
789
  }
10 reyssat 790
}
791
 
8213 bpr 792
/* Create href to wims requests. subst() is not done. */
10 reyssat 793
void exec_href(char *p)
794
{
12245 bpr 795
  char *s, st[128], sti[128], stc[128], stt[128], *p1, *p2, *p3, *wn="";
796
  char *U="<span class=\"disabled_link\">%s</span>";
797
  char b1[MAX_LINELEN+1], b2[MAX_LINELEN+1];
798
  int new=0;
799
  if(!outputing) return;
800
  href_find_target(p);
801
  p1=find_word_start(p);
802
  p2=find_word_end(p1); if(*p2) *(p2++)=0;
803
  mystrncpy(b1,p1,sizeof(b1));
804
  mystrncpy(b2,find_word_start(p2),sizeof(b2));
805
  substit(b1); substit(b2);
806
  /* standard reference */
807
  if(*b2==0 && strchr(b1,'=')==NULL) {
808
    char b[MAX_LINELEN+1], *ll;
809
    p1=find_word_start(b1); *find_word_end(p1)=0;
810
    if(*p1==0 || strlen(p1)>64) return;
811
    ll=getvar("module_language");
812
    if(ll==NULL || *ll==0 || *(ll+1)==0 || *(ll+2)!=0) ll=lang;
813
    accessfile(b,"r","html/href.%s",ll);
814
    memmove(p1+1,p1,64); *p1='\n'; strcat(p1,"  ");
815
    p2=strstr(b,p1); if(p2==NULL) return;
816
    p1=find_word_start(p2+strlen(p1)); p2=find_word_end(p1);
817
    if(*p2) *(p2++)=0;
818
    p3=strchr(p2,'\n'); if(p3!=NULL) *p3=0;
10 reyssat 819
    mystrncpy(b1,p1,sizeof(b1));
820
    mystrncpy(b2,find_word_start(p2),sizeof(b2));
821
    substit(b1); substit(b2);
12245 bpr 822
  }
15277 obado 823
  /* for robots: only references without defining cmd. */
12245 bpr 824
  if(robot_access && strstr(b1,"cmd=")!=NULL &&
825
      strstr(b1,"module=adm/doc")==NULL) {
826
    _output_(b2); return;
827
  }
828
  if(robot_access && strstr(aliased_cgi,"yes")!=NULL) {
829
    char mbuf[256], lbuf[16];
830
    _href_getdef(b1,"module",mbuf,sizeof(mbuf));
831
    if(mbuf[0]==0) mystrncpy(mbuf,home_module,sizeof(mbuf));
832
    _href_getdef(b1,"lang",lbuf,sizeof(lbuf));
833
    if(strlen(lbuf)!=2) {mystrncpy(lbuf,lang,4);lbuf[2]=0;}
834
    if(strncmp(mbuf,"adm/doc",strlen("adm/doc"))==0) {
835
      char dbuf[256], bbuf[256];
836
      _href_getdef(b1,"doc",dbuf,sizeof(dbuf));
837
      _href_getdef(b1,"block",bbuf,sizeof(bbuf));
838
      if(!myisdigit(dbuf[0])) dbuf[0]=0;
839
      if(dbuf[0]!=0 && bbuf[0]==0) snprintf(bbuf,sizeof(bbuf),"main");
840
      if(dbuf[0]==0)
841
        output("<a href=\"%s%s_doc~.html\">%s</a>", ref_base,lbuf,b2);
842
      else
843
        output("<a href=\"%s%s_doc~%s~%s.html\">%s</a>",
844
           ref_base,lbuf,dbuf,bbuf,b2);
10 reyssat 845
    }
12245 bpr 846
    else {
847
      for(s=strchr(mbuf,'/'); s!=NULL; s=strchr(s+1,'/')) *s='~';
848
      output("<a href=\"%s%s_%s.html\">%s</a>", ref_base,lbuf,mbuf,b2);
849
    }
7379 bpr 850
    return;
12245 bpr 851
  }
852
  s=getvar("wims_ref_id");
853
  if(s!=NULL && *s!=0 && !isspace(*s)) {
854
    snprintf(sti,sizeof(sti)," id=\"%s\"",s);
855
  }
856
  else sti[0]=0;
7379 bpr 857
 
12245 bpr 858
  s=getvar("wims_ref_class");
859
  if(s!=NULL && *s!=0 && !isspace(*s)) {
17008 obado 860
    // If class contains "button", add "role=button" for accessibility
861
    if(strstr(s,"button")) {
862
      snprintf(stc,sizeof(stc)," class=\"%s\" role=\"button\"",s);
863
    } else {
864
      snprintf(stc,sizeof(stc)," class=\"%s\"",s);
865
    }
12245 bpr 866
  }
867
  else stc[0]=0;
7379 bpr 868
 
12245 bpr 869
  s=getvar("wims_ref_title");
870
  if(s!=NULL && *s!=0 && !isspace(*s)) {
871
    snprintf(stt,sizeof(stt)," title=\"%s\"",s);
872
  }
873
  else stt[0]=0;
7379 bpr 874
 
12245 bpr 875
  s=getvar("wims_ref_target");
876
  if(href_target[0]!=0) s=href_target;
877
  if(s!=NULL && *s!=0 && !isspace(*s)) {
878
    snprintf(st,sizeof(st)," target=\"%s\"",s);
879
    if(strcmp(s,"_parent")!=0) {
880
      new=1; wn="wims_window=new&";
10 reyssat 881
    }
12245 bpr 882
  }
883
  else st[0]=0;
884
  _httpfollow(b1,wn,new);
885
  tohttpquery(b1);
886
  if(strstr(session_prefix,"_check")!=NULL) {
887
    if(*b2) output(U,b2);
888
  else _output_("<a id=\"0\"></a>");
889
  return;
890
  }
891
  if(jsbuf[0]==0 && st[0]==0 && strstr(session_prefix,"_exam")!=NULL) {
892
    p1=strstr(b1,"cmd=");
893
    if(p1!=NULL) {
894
      p1+=strlen("cmd=");
895
      if(strncmp(p1,"new",3)==0 || strncmp(p1,"renew",5)==0 ||
896
          strncmp(p1,"intro",5)==0) {
897
        if(*b2) output(U,b2);
898
        else _output_("<a id=\"#\"></a>");
899
        return;
7379 bpr 900
      }
10 reyssat 901
    }
12245 bpr 902
  }
903
  if(*b2)
904
    output("<a href=\"%s?%s\"%s%s %s %s %s>%s</a>",
905
       ref_name, b1, st, jsbuf,sti,stc,stt,b2);
906
  else
907
    output("<a href=\"%s?%s\"%s%s %s %s %s>",ref_name, b1, st, jsbuf,sti,stc,stt);
908
  setvar("wims_ref_id","");
909
  setvar("wims_ref_class","");
910
  setvar("wims_ref_title","");
10 reyssat 911
}
912
 
8213 bpr 913
/* Create form refering to the page. */
10 reyssat 914
void exec_form(char *p)
915
{
15130 obado 916
  char *s, *p1, *p2, *a, *m, *opt, st[128], *wn="", *form_id;
917
  char abuf[128], idbuf[128];
12245 bpr 918
  int i, new=0;
919
  if(!outputing) return;
920
  href_find_target(p);
921
  s=getvar("wims_ref_target");
922
  if(href_target[0]!=0) s=href_target;
923
  if(s!=NULL && *s!=0 && !isspace(*s)) {
924
    snprintf(st,sizeof(st)," target=\"%s\"",s);
925
    if(strcmp(s,"_parent")!=0) {
17170 bpr 926
      new=1; wn="<input type=\"hidden\" name=\"wims_window\" value=\"yes\">\n";
10 reyssat 927
    }
12245 bpr 928
  }
929
  else st[0]=0;
930
  a=getvar("wims_ref_anchor"); if(a==NULL) a="";
931
  opt=find_word_start(find_word_end(find_word_start(p)));
932
  m=getvar("wims_form_method");
933
  if(m!=NULL) {
934
    m=find_word_start(m);
935
    if(strncasecmp(m,"post",4)==0) m="post";
936
    else if(strncasecmp(m,"get",3)==0) m="get";
937
      else if(strncasecmp(m,"file",4)==0) {
938
       m="post\" enctype=\"multipart/form-data";
939
      snprintf(abuf,sizeof(abuf),"?form-data%ld%s",random(),a); a=abuf;
940
      force_setvar("wims_form_method","");
10 reyssat 941
    }
942
    else m=default_form_method;
12245 bpr 943
  }
944
  else m=default_form_method;
15130 obado 945
 
12245 bpr 946
  if(strstr(session_prefix,"_check")!=NULL) {
947
    output("<form action=\"NON_EXISTING_PAGE\" onsubmit=\"window.close();\" %s>\n",
7379 bpr 948
           opt);
12245 bpr 949
    return;
950
  }
15130 obado 951
 
952
  form_id=getvar("wims_form_id");
953
  if(form_id==NULL || *form_id==0 || isspace(*form_id)){
954
    form_id="";
955
  } else {
956
    snprintf(idbuf,sizeof(idbuf),"id=\"%s\"",find_word_start(form_id));form_id=idbuf;
957
  }
958
  force_setvar("wims_form_id","");
959
 
960
  output("<form action=\"%s%s\"%s method=\"%s\" %s %s>\n<div class='wims_form'>%s",ref_name,a,st,m,opt,form_id,wn);
12245 bpr 961
  if(a!=abuf && a[0]) force_setvar("wims_ref_anchor","");
962
  for(i=0;i<follow_no;i++) {
963
    if(robot_access && follow_list[i]==ro_session) continue;
964
    if(!new && follow_list[i]!=ro_session
965
     && follow_list[i]!=ro_module && follow_list[i]!=ro_lang)
966
      continue;
967
    if(follow_list[i]==ro_module) continue;
968
    s=getvar(ro_name[follow_list[i]]);
969
    if(s!=NULL && *s!=0) {
970
      if(follow_list[i]==ro_session && memcmp(href_target,"wims_",5)==0) {
971
        char st[MAX_LINELEN+1];
972
        char *s1;
973
        s1=getvar("wims_session");
974
        if(s1==NULL) internal_error("exec_form() error.\n");
975
        snprintf(st,sizeof(st),"%.10s%s",s1,href_target+4);
976
        s=st;
977
      }
17170 bpr 978
      output("<input type=\"hidden\" name=\"%s\" value=\"%s\">\n",
7379 bpr 979
           ro_name[follow_list[i]],s);
10 reyssat 980
    }
12245 bpr 981
  }
982
  p1=find_word_start(p);p2=find_word_end(p1);
983
  if(p2>p1) {
984
    char buf[64];
985
    int i;
986
    i=p2-p1; if(i>60) i=60;
987
    memmove(buf,p1,i);buf[i]=0;
988
    for(i=0;i<CMD_NO && strcmp(buf,commands[i]);i++);
989
    if(i<CMD_NO) {
17170 bpr 990
      output("<input type=\"hidden\" name=\"cmd\" value=\"%s\">\n",buf);
12245 bpr 991
      if(i!=cmd_intro && i!=cmd_new)
17170 bpr 992
        output("<input type=\"hidden\" name=\"module\" value=\"%s\">\n",
12245 bpr 993
            getvar(ro_name[ro_module]));
994
    }
995
  }
10 reyssat 996
}
997
 
8213 bpr 998
/* Creat link to trap robot access, an internal command
999
 * which should not be documented
1000
 */
10 reyssat 1001
void exec_robottrap(char *p)
1002
{
12245 bpr 1003
  char buf[MAX_LINELEN+1];
1004
  if(robot_access) return;
1005
  ovlstrcpy(buf,"session=$wims_session.1&module=adm/trap");
1006
  _output_("<!-- "); exec_href(buf);_output_("Robot trapper, do not click!</a> -->");
15704 obado 1007
  _output_("<div class='wimstrap hide' aria-hidden='true'>");exec_href(buf); _output_("<span lang='en'>Robot trapper, do not go there!</span></a></div>");
10 reyssat 1008
}
1009
 
8213 bpr 1010
/* set definitions in a file. Trusted modules only. */
10 reyssat 1011
void exec_setdef(char *p)
1012
{
12245 bpr 1013
   char *p1, *pp;
1014
   char nbuf[MAX_LINELEN+1], fbuf[MAX_LINELEN+1], tbuf[MAX_LINELEN+1];
1015
   if(robot_access || !trusted_module() || is_class_module) return;
1016
   p1=wordchr(p,"in"); if(p1==NULL) module_error("syntax_error");
1017
   *p1=0; p1=find_word_start(p1+strlen("in"));
1018
   ovlstrcpy(nbuf,p);
1019
   mystrncpy(tbuf,p1,sizeof(tbuf));
1020
   substit(nbuf); substit(tbuf);
1021
   if(find_module_file(tbuf,fbuf,1)) return;
1022
   pp=find_word_start(nbuf); p1=find_word_start(fbuf); *find_word_end(p1)=0;
1023
   strip_trailing_spaces(pp);
1024
   setdef(p1,pp);
10 reyssat 1025
}
1026
 
8213 bpr 1027
/* Set a variable. */
10 reyssat 1028
void exec_set(char *name)
1029
{
12245 bpr 1030
  char *p, *defn, *parm;
1031
  char tbuf2[MAX_LINELEN+1], namebuf[MAX_LINELEN+1];
1032
  int i;
10 reyssat 1033
 
12245 bpr 1034
  p=strchr(name,'=');
1035
  if(p==NULL) return; /* warning or error! */
1036
  *p=0; defn=find_word_start(p+1);
1037
  *find_word_end(name)=0;
1038
  mystrncpy(namebuf,find_word_start(name),sizeof(namebuf));
1039
  /* we allow substit in names, to implement array */
1040
  substit(namebuf); *find_word_end(namebuf)=0;
1041
  if(*defn!=calc_prefix_char) {
1042
  /* substitute by default */
1043
    mystrncpy(tbuf2,defn,sizeof(tbuf2));
1044
    substit(tbuf2); setvar(namebuf,tbuf2); return;
1045
  }
1046
  /* called from !readdef */
1047
  if((untrust&4)!=0) module_error("not_trusted");
1048
  /* definition is a command  */
1049
  parm=find_word_end(defn+1);
1050
  if( *parm != 0 ) { *parm=0; parm=find_word_start(parm+1); }
1051
  i=m_file.lines[m_file.l].varcode;
1052
  if(i<0) {
1053
    i=search_list(calc_routine,CALC_FN_NO,sizeof(calc_routine[0]),defn+1);
1054
    m_file.lines[m_file.l].varcode=i;
1055
  }
1056
  if(i<0) {
1057
      /* replace by warning? */
1058
    setvar(error_data_string,defn+1); module_error("bad_cmd");
1059
    return;
1060
  }
1061
  mystrncpy(tbuf2,parm,sizeof(tbuf2)); execnt++;
1062
  if(calc_routine[i].tag==0) substit(tbuf2);
1063
  tbuf2[sizeof(tbuf2)-1]=0; calc_routine[i].routine(tbuf2);
1064
      /* remove trailing new line */
1065
  tbuf2[sizeof(tbuf2)-1]=0;
1066
  if(tbuf2[strlen(tbuf2)-1]=='\n') tbuf2[strlen(tbuf2)-1]=0;
10 reyssat 1067
    setvar(namebuf,tbuf2);
1068
}
1069
 
8213 bpr 1070
/* set but do not overwrite. */
10 reyssat 1071
void exec_default(char *p)
1072
{
12245 bpr 1073
  char *start, *end, c, *pp;
1074
  char namebuf[MAX_LINELEN+1];
1075
  start=find_word_start(p);
1076
  for(end=start;*end!=0 && !isspace(*end) && *end!='='; end++);
1077
  c=*end; *end=0;
1078
  if(end-start<=MAX_LINELEN-1) {
1079
    memmove(namebuf,start,end-start+1); substit(namebuf);
1080
    pp=getvar(namebuf);
1081
    if(pp!=NULL && *pp!=0) return;
1082
  }
1083
  *end=c; exec_set(p);
10 reyssat 1084
}
1085
 
8213 bpr 1086
/* Does nothing; just a comment. */
10 reyssat 1087
void exec_comment(char *p)
1088
{
12245 bpr 1089
  return;
10 reyssat 1090
}
1091
 
8213 bpr 1092
/* Exit the file under interpretation */
10 reyssat 1093
void exec_exit(char *p)
1094
{
12245 bpr 1095
  m_file.linepointer=m_file.linecnt;
1096
  return;
10 reyssat 1097
}
1098
 
13438 obado 1099
/* output a file. Aliases:
7379 bpr 1100
     * getfile, outfile, fileout */
10 reyssat 1101
void exec_getfile(char *p)
1102
{
14941 bpr 1103
  char *s, sti[128], stc[128], stt[128], sgf[128], *p1, url[MAX_LINELEN+1];
12245 bpr 1104
  char *prompt;
7379 bpr 1105
 
12245 bpr 1106
  p=find_word_start(p); prompt=find_word_end(p);
1107
  if(*prompt!=0) *prompt++=0;
1108
  prompt=find_word_start(prompt);
1109
  if(*p==0 || !outputing) return;
1110
  if(!trusted_module() || is_class_module) return;
1111
  s=getvar(ro_name[ro_session]);
1112
  if(s==NULL || *s==0 || strstr(s,"robot")!=NULL) return;
1113
  mystrncpy(url,ref_name,sizeof(url));
1114
  for(p1=url+strlen(url);p1>url && *(p1-1)!='/'; p1--);
1115
  if(good_httpd) snprintf(p1,sizeof(url)+p1-url,
1116
              "getfile/%s?&+session=%s&+modif=%ld",
1117
              p,s,(long)nowtime);
1118
  else snprintf(url,sizeof(url),
1119
      "%s?cmd=getfile&+session=%s&+special_parm=%s&+modif=%ld",
8895 bpr 1120
          ref_name,s,p,(long)nowtime);
12245 bpr 1121
  snprintf(jsbuf,sizeof(jsbuf),jsstr,"wims_file","wims_file");
13438 obado 1122
 
1123
  s=getvar("wims_ref_id");
1124
  if(s!=NULL && *s!=0 && !isspace(*s)) {
1125
    snprintf(sti,sizeof(sti)," id=\"%s\"",s);
1126
  }
1127
  else sti[0]=0;
1128
 
1129
  s=getvar("wims_ref_class");
1130
  if(s!=NULL && *s!=0 && !isspace(*s)) {
1131
    snprintf(stc,sizeof(stc)," class=\"%s\"",s);
1132
  }
1133
  else stc[0]=0;
1134
 
1135
  s=getvar("wims_ref_title");
1136
  if(s!=NULL && *s!=0 && !isspace(*s)) {
1137
    snprintf(stt,sizeof(stt)," title=\"%s\"",s);
1138
  }
1139
  else stt[0]=0;
1140
 
14941 bpr 1141
  s=getvar("wims_getfile_fname");
1142
  if(s!=NULL && *s!=0 && !isspace(*s)) {
1143
    snprintf(sgf,sizeof(sgf)," download=\"%s\"",s);
1144
  }
1145
  else sgf[0]=0;
1146
 
1147
  if(*prompt) output("<a href=\"%s\" %s %s %s %s>%s</a>\n", url,sti,stc,stt,sgf,prompt);
13438 obado 1148
  else output("<a href=\"%s\" %s %s %s></a>",url,sti,stc,stt);
1149
 
1150
  setvar("wims_ref_id","");
1151
  setvar("wims_ref_class","");
1152
  setvar("wims_ref_title","");
14941 bpr 1153
  setvar("wims_getfile_fname","");
10 reyssat 1154
}
1155
 
8213 bpr 1156
/* internal */
10 reyssat 1157
void count_insert(void)
1158
{
12245 bpr 1159
  insert_no++;
1160
  if(insert_no>=INS_LIMIT) module_error("too_many_ins");
10 reyssat 1161
}
1162
 
1163
int animated_ins=0;
1164
int grouped_ins=0;
1165
 
8185 bpr 1166
/* generic insertion */
10 reyssat 1167
void _exec_ins(char *p, char *script_name,char *format)
1168
{
17918 bpr 1169
  char *s, *b, *at, *tag, *tag2, *al, *fmt, *mh, *buftex=NULL;
12245 bpr 1170
  char *p1, *pt;
1171
  char buf[1024],buf2[1024],url[MAX_LINELEN+1],altbuf[1024];
1172
  char outbuf[1024];
1173
  int border, middle, vspace;
1174
  long int tel;
10 reyssat 1175
 
12245 bpr 1176
  if(robot_access) return;
1177
  count_insert(); outbuf[0]=0;
1178
  setenv("ins_source",p,1); /* value kept from user tamper */
1179
  if(animated_ins) fmt=getvar("anim_format"); else fmt=format;
1180
  if(fmt==NULL) fmt="gif";
1181
  if(ismhelp) mh="mh"; else mh="";
1182
  snprintf(buf,sizeof(buf),"%s/insert%s-%d.%s",s2_prefix,mh,insert_no,fmt);
1183
  if(grouped_ins) {unlink(buf); goto grouped;}
1184
  exportall();
1185
  call_ssh("%s/%s %d %s >%s/ins.out 2>%s/ins.err",
1186
      bin_dir,script_name,insert_no,tmp_dir,tmp_dir,tmp_dir);
1187
  unlink(buf); wrapexec=1;
1188
  if(trusted_module()) setenv("trusted_module","yes",1);
1189
  else if(untrust) setenv("trusted_module","no",1);
1190
  call_ssh("mv %s/insert%s-%d.%s %s >/dev/null 2>/dev/null",
1191
       tmp_dir,mh,insert_no,fmt,s2_prefix);
1192
  tel=filelength("%s", buf);
1193
  if(tel<=5) {
1194
    char bbuf[MAX_LINELEN+1];
1195
    accessfile(bbuf,"r","%s/ins.err",tmp_dir);
1196
    snprintf(url,sizeof(url),"gifs/badins.gif");
1197
    for(p1=bbuf;p1<bbuf+512 && *p1;p1++)
7379 bpr 1198
      if(*p1=='<' || *p1=='>') *p1='?';
13691 bpr 1199
    *p1=0;
1200
    if(bbuf[0]==0) snprintf(bbuf,sizeof(bbuf),"Fail");
1201
    snprintf(outbuf+strlen(outbuf),sizeof(outbuf)-strlen(outbuf),
17170 bpr 1202
       " <img src=\"%s\" alt=\"Error\"> <small><pre>%s</pre></small> <br> ",
13691 bpr 1203
       url,bbuf);
1204
    setvar("ins_warn","fail");
1205
    setvar("ins_cnt","0");
1206
    goto reset;
12245 bpr 1207
  }
1208
  grouped:
1209
  s=getvar(ro_name[ro_session]);
1210
  b=getvar("ins_border"); at=getvar("ins_attr");
1211
  tag=getvar("ins_tag");  al=getvar("ins_align");
1212
  if(at==NULL) at="";
1213
  if(tag==NULL) tag="";
1214
  if(al==NULL) al="";
1215
  al=find_word_start(al);
1216
  if(*al!=0) snprintf(buf2,sizeof(buf2),"vertical-align:%s",al); else buf2[0]=0;
1217
  if(strcasecmp(al,"middle")==0) middle=1; else middle=0;
1218
  tag2=""; vspace=0;
1219
  if(*tag!=0) {
1220
    mystrncpy(buf,tag,sizeof(buf)); tag=find_word_start(buf);
1221
    tag2=find_word_end(tag);
1222
    if(*tag2!=0) *tag2++=0;
1223
    tag2=find_word_start(tag2);
1224
  }
1225
  if(b==NULL || *b==0) border=0;
1226
  else border=atoi(b);
1227
  if(border<0) border=0;
1228
  if(border>100) border=100;
1229
  if(middle) {
1230
    snprintf(outbuf+strlen(outbuf),
1231
       sizeof(outbuf)-strlen(outbuf),"%s",mathalign_sup1);
1232
    vspace=2;
1233
  }
1234
  mystrncpy(url,ref_name,sizeof(url));
1235
  for(p1=url+strlen(url);p1>url && *(p1-1)!='/'; p1--);
1236
  snprintf(p1,sizeof(url)+p1-url,
7379 bpr 1237
         "wims.%s?cmd=getins&+session=%s&+special_parm=insert%s-%d.%s&+modif=%ld",
8895 bpr 1238
         fmt,s,mh,insert_no,fmt,(long)nowtime);
12245 bpr 1239
  if(strchr(ins_alt,'"')!=NULL || strlen(ins_alt)>256) ins_alt[0]=0;
1240
  pt=getvar("wims_ins_alt"); if(pt==NULL) pt="";
12526 bpr 1241
  if(strcmp(pt,"empty")==0) altbuf[0]=0;
1242
  else
1243
    if(ins_alt[0] && strcmp(pt,"none")!=0)
1244
      snprintf(altbuf,sizeof(altbuf)," alt=\"\"");
1245
    else
1246
      snprintf(altbuf,sizeof(altbuf)," alt=\"%s\"",ins_alt);
12245 bpr 1247
  if(strcasecmp(tag,"form")!=0) {
17918 bpr 1248
    if(strcasecmp(fmt,"tex")==0){
1249
      snprintf(buf,sizeof(buf), "%s/insert%s-%d.%s",s2_prefix,mh,insert_no,fmt);
1250
      buftex=readfile(buf,NULL,MAX_LINELEN);
1251
    }
1252
    else
1253
      snprintf(outbuf+strlen(outbuf),sizeof(outbuf)-strlen(outbuf),
17442 obado 1254
       "<img src=\"%s\" class=\"wims_mathimg\" style=\"border-width:%dpx;margin-bottom:%dpx;%s\" %s %s>",
12245 bpr 1255
       url, border, vspace, buf2, at, altbuf);
1256
  }
1257
  else {
1258
    char *n, *nend;
6168 bpr 1259
/* fix: add quotes at name=" " */
12245 bpr 1260
    if(*tag2!=0) {n="name=\"" ; nend="\"";} else {n=""; nend="";}
1261
    snprintf(outbuf+strlen(outbuf),sizeof(outbuf)-strlen(outbuf),
17170 bpr 1262
        "<input type=\"image\" %s%s%s src=\"%s\" style=\"border:solid;border-width:%dpx;margin-bottom:%dpx;%s\" %s %s>",
12245 bpr 1263
        n,tag2,nend,url,border,vspace,buf2,at,altbuf);
1264
  }
1265
  if(middle) snprintf(outbuf+strlen(outbuf),
1266
           sizeof(outbuf)-strlen(outbuf),"%s",mathalign_sup2);
1267
  setvar("ins_warn",""); ins_alt[0]=0;
1268
  setvar("ins_cnt",int2str(insert_no));
1269
  reset:
1270
  if(outputing) _output_(outbuf);
1271
  setvar("ins_out",outbuf);
1272
  setvar("ins_attr",""); setvar("ins_tag","");
1273
  setvar("ins_url",url);
17968 bpr 1274
  setvar("ins_tikz",buftex?buftex:"");
12245 bpr 1275
  snprintf(buf2,sizeof(buf2),"insert%s-%d.%s",mh,insert_no,fmt);
1276
  setvar("ins_filename",buf2);
1277
  animated_ins=0;
17918 bpr 1278
  if (buftex) free(buftex);
10 reyssat 1279
}
1280
 
8155 bpr 1281
/* instex: dynamically insert tex outputs */
10 reyssat 1282
void exec_instex(char *p)
1283
{
12245 bpr 1284
  char *ts, *tc, *f, *mh, buf[MAX_FNAME+1];
7379 bpr 1285
 
12245 bpr 1286
  if(robot_access) {
1287
    *p=0; return;
1288
  }
1289
  f=instex_check_static(p); substit(p);
1290
  if(f==NULL) {
8155 bpr 1291
/* Use static instex if there is no real substitution
1292
 * and the source file is not in sessions directory.
1293
 */
12245 bpr 1294
    calc_instexst(p); if(outputing) _output_(p);
1295
    return;
1296
  }
1297
  if(ismhelp) mh="mh"; else mh="";
1298
  fix_tex_size(); f="gif";
1299
  setenv("texgif_style",instex_style,1);
1300
  tc=getvar("instex_texheader"); if (tc) { setenv("texgif_texheader",tc,1);}
1301
  setenv("texgif_tmpdir",tmp_dir,1);
1302
  setenv("texgif_src",p,1);
1303
  if(ins_alt[0]==0) mystrncpy(ins_alt,p,sizeof(ins_alt));
1304
  mkfname(buf,"%s/insert%s-%d.gif",tmp_dir,mh,insert_no+1);
1305
  setenv("texgif_outfile",buf,1);
1306
  ts=getvar("wims_texsize"); tc=getvar("instex_color");
1307
  if(lastout_file!=-1 && (tc==NULL || *tc==0) &&
1308
      (ts==NULL || *ts==0 || strcmp(ts,"0")==0) &&
1309
     strstr(p,"\\begin{")==NULL) {
1310
    int ls, ln;
1311
    char *pagebreak;
1312
    ls=strlen(instex_src); ln=strlen(instex_fname);
1313
    if(ls+strlen(p)>=MAX_LINELEN-256 ||
1314
     ln+strlen(buf)>=MAX_LINELEN-16) {
1315
        instex_flush(); ls=ln=0;
10 reyssat 1316
    }
12245 bpr 1317
    if(instex_cnt>0) pagebreak="\\pagebreak\n"; else pagebreak="";
1318
    snprintf(instex_src+ls,MAX_LINELEN-ls,"%s %s %s %s\n",
7379 bpr 1319
         pagebreak,instex_style,p,instex_style);
12245 bpr 1320
    snprintf(instex_fname+ln,MAX_LINELEN-ln,"%s\n",buf);
7379 bpr 1321
      grouped_ins=1;
12245 bpr 1322
  }
1323
  mkfname(buf,"%s/texgif.dvi",tmp_dir); unlink(buf);
1324
  wrapexec=0; _exec_ins(p,instex_processor,f);
1325
  if(grouped_ins) instex_cnt++;
1326
  grouped_ins=0;
10 reyssat 1327
}
1328
 
8152 bpr 1329
/* patches the gnuplot integer division (mis)feature. */
10 reyssat 1330
void gnuplot_patch(char *p,int oneline)
1331
{
12245 bpr 1332
  char *pp;
1333
  for(pp=strchr(p,'/');pp!=NULL;pp=strchr(pp+1,'/')) {
1334
    char *p1;
1335
    if(pp<=p || !myisdigit(*(pp-1)) || !myisdigit(*(pp+1))) continue;
1336
    for(p1=pp-2;p1>=p && myisdigit(*p1);p1--);
1337
    if(p1>=p && *p1=='.') continue;
1338
    for(p1=pp+2;*p1 && myisdigit(*p1);p1++);
1339
    if(*p1=='.') continue;
1340
    string_modify(p,p1,p1,".0");
1341
  }
1342
  for(pp=strchr(p,'^');pp!=NULL;pp=strchr(pp+1,'^'))
1343
    string_modify(p,pp,pp+1,"**");
8155 bpr 1344
/* disallow new lines and ';' */
12245 bpr 1345
  if(oneline)
1346
    for(pp=p;*pp!=0;pp++) if(*pp==';' || *pp=='\n') *pp=' ';
10 reyssat 1347
}
1348
 
8152 bpr 1349
/* This is to disable pipe in the gnuplot plotting function.
1350
 * We do not allow ' followed by < .
1351
 */
10 reyssat 1352
void prepare_insplot_parm(char *p)
1353
{
12245 bpr 1354
  int i,j,multanim; char *pp, *s;
1355
  double d;
1356
  char setbuf[MAX_LINELEN+10],buf[MAX_LINELEN+1];
7379 bpr 1357
 
12245 bpr 1358
  j=strlen(p);
8155 bpr 1359
/* pipe in plot command */
12245 bpr 1360
  for(i=0;i<j;i++) {
1361
    if(*(p+i)!='\'' && *(p+i)!='"') continue;
1362
    pp=find_word_start(p+i+1); if(*pp=='<') module_error("illegal_plot_cmd");
1363
  }
1364
  gnuplot_patch(p,1);
8155 bpr 1365
/* multiplot */
12245 bpr 1366
  multanim=0;
1367
  pp=getvar("insplot_split");
1368
  if(pp!=NULL) i=linenum(pp); else i=0;
8155 bpr 1369
/* arbitrary limit: 16 multiplots */
12245 bpr 1370
  if(i>16) i=16;
1371
  if(i>1) {
1372
    char tbuf[MAX_LINELEN*(i+1)+100], bbuf[MAX_LINELEN+1];
1373
    tbuf[0]=0;
1374
    if(*p!=0) snprintf(tbuf,sizeof(tbuf),"%s\n",p);
1375
    snprintf(buf,sizeof(buf),"%d",i); setenv("multiplot",buf,1);
1376
    for(j=1;j<=i;j++) {
1377
      snprintf(buf,sizeof(buf),"insplot_parm_%d",j);
1378
      pp=getvar(buf);
1379
      if(pp==NULL || *pp==0) {
1380
        if(j==1 && *p!=0) continue;
1381
        pp="";
1382
      }
1383
      else {
1384
        mystrncpy(bbuf,pp,sizeof(bbuf));
1385
        gnuplot_patch(bbuf,1);
1386
      }
1387
      strcat(tbuf,bbuf);strcat(tbuf,"\n");
1388
    }
7379 bpr 1389
    setenv("insplot_source",tbuf,1);
1390
    if(varchr(tbuf,"s")!=NULL) multanim=1;
12245 bpr 1391
  }
8155 bpr 1392
/* no illegal chaining */
12245 bpr 1393
  pp=getvar("insplot_font"); if(pp!=NULL) {
1394
    for(s=pp;s<pp+MAX_LINELEN && *s;s++)
1395
    if(*s==';' || *s=='\n' || *s==' ') *s=0;
1396
    if(s>=pp+MAX_LINELEN) *s=0;
1397
    setvar("insplot_font",pp);
1398
  }
1399
  pp=getvar("insplot_set");
1400
  if(pp!=NULL) {
1401
    char tbuf[MAX_LINELEN+1];
1402
    mystrncpy(tbuf,pp,sizeof(tbuf));
1403
    i=strlen(tbuf)-1;
1404
    while(i>0 && isspace(tbuf[i])) i--;
1405
    if(tbuf[i]==';') tbuf[i]=0;
1406
    gnuplot_patch(tbuf,0);pp=tbuf;
1407
    ovlstrcpy(setbuf,"set "); j=strlen("set ");
1408
    for(i=0; *(pp+i)!=0 && j<MAX_LINELEN; i++) {
1409
      if(*(pp+i)=='\n') {setbuf[j++]=' '; continue;}
1410
      if(*(pp+i)!=';') {setbuf[j++]=*(pp+i); continue;}
1411
      ovlstrcpy(setbuf+j,"\nset "); j+=strlen("\nset ");
10 reyssat 1412
    }
12245 bpr 1413
    setbuf[j]=0;
1414
    setenv("insplot_set",setbuf,1);
1415
  }
1416
  else setenv("insplot_set","",1);
8155 bpr 1417
/* frames of animation */
12245 bpr 1418
  pp=getvar("ins_anim_frames");
1419
  if(pp!=NULL) i=evalue(pp); else i=1;
1420
  if(i>=ANIM_LIMIT) i=ANIM_LIMIT-1;
1421
  if(i<1) i=1;
1422
  if(strstr(setbuf,"step")==NULL && strstr(p,"step")==NULL
1423
     && varchr(setbuf,"s")==NULL && varchr(p,"s")==NULL && !multanim) i=1;
1424
  setenv("ins_anim_frames",int2str(i),1);
1425
  setvar("ins_anim_frames","");
1426
  if(i>1) {setvar("ins_animation","yes");animated_ins=1;}
1427
  else setvar("ins_animation","no");
8155 bpr 1428
/* delay of animation */
12245 bpr 1429
  pp=getvar("ins_anim_delay");
1430
  if(pp!=NULL) d=evalue(pp); else d=0;
1431
  if(d>=10) d=10;
1432
  if(d<0) d=0;
1433
  setenv("ins_anim_delay",int2str(d*100),1);
10 reyssat 1434
}
1435
 
8152 bpr 1436
/* Insert dynamic 2d plot */
10 reyssat 1437
void exec_insplot(char *p)
1438
{
12245 bpr 1439
  char *fmt;
1440
  if(robot_access) {
1441
    *p=0; return;
1442
  }
1443
  fmt=getvar("ins_format"); if(fmt==NULL || *fmt==0) fmt=DEFAULT_INS_FORMAT;
1444
  prepare_insplot_parm(p); setenv("insplot_method","2D",1);
1445
  _exec_ins(p,insplot_processor,fmt);
1446
  wrapexec=1;
10 reyssat 1447
/*    call_ssh("mv %s/insplot_cmd %s 2>/dev/null",tmp_dir,s2_prefix); */
12245 bpr 1448
   unsetenv("multiplot"); setvar("insplot_split","");
10 reyssat 1449
}
1450
 
8213 bpr 1451
/* Insert dynamic 3d plot */
10 reyssat 1452
void exec_insplot3d(char *p)
1453
{
12245 bpr 1454
  char *fmt;
1455
  if(robot_access) {
1456
    *p=0; return;
1457
  }
1458
  fmt=getvar("ins_format"); if(fmt==NULL || *fmt==0) fmt=DEFAULT_INS_FORMAT;
1459
  prepare_insplot_parm(p); setenv("insplot_method","3D",1);
1460
  _exec_ins(p,insplot_processor,fmt);
1461
  wrapexec=1;
10 reyssat 1462
/*     call_ssh("mv %s/insplot_cmd %s 2>/dev/null",tmp_dir,s2_prefix); */
12245 bpr 1463
  unsetenv("multiplot");setvar("insplot_split","");
10 reyssat 1464
}
1465
 
8155 bpr 1466
/* Insert dynamic gif draw. The parm preparation is specific to fly. */
10 reyssat 1467
void exec_insdraw(char *p)
1468
{
12245 bpr 1469
  char *pp, *fmt;
1470
  int i;
1471
  double d;
7379 bpr 1472
 
12245 bpr 1473
  if(robot_access) {
1474
    *p=0; return;
1475
  }
7370 bpr 1476
/*    calc_tolower(p);*/
12245 bpr 1477
  fmt=getvar("ins_format"); if(fmt==NULL || *fmt==0) fmt=DEFAULT_INS_FORMAT;
1478
  while((pp=wordchr(p,"output"))!=NULL) memmove(pp,"zqkwfx",6);
8155 bpr 1479
/* frames of animation */
12245 bpr 1480
  pp=getvar("ins_anim_frames");
1481
  if(pp!=NULL) i=evalue(pp); else i=1;
1482
  if(i>=ANIM_LIMIT) i=ANIM_LIMIT-1;
1483
  if(i<1) i=1;
1484
  if(i>1 && varchr(p,"s")==NULL && varchr(p,"animstep")==NULL
1485
     && varchr(p,"step")==NULL) i=1;
1486
  setenv("ins_anim_frames",int2str(i),1);
1487
  setvar("ins_anim_frames","");
1488
  if(i>1) {setvar("ins_animation","yes");animated_ins=1;}
1489
  else setvar("ins_animation","no");
8155 bpr 1490
/* delay of animation */
12245 bpr 1491
  pp=getvar("ins_anim_delay");
1492
  if(pp!=NULL) d=evalue(pp); else d=0;
1493
  if(d>=10) d=10;
1494
  if(d<0) d=0;
1495
  setenv("ins_anim_delay",int2str(d*100),1);
1496
  pp=getvar("insdraw_filebase");
1497
  if(pp!=NULL && strstr(pp,parent_dir_string)!=NULL)
1498
    setvar("insdraw_filebase","");
1499
  _exec_ins(p,insdraw_processor,fmt);
10 reyssat 1500
}
1501
 
1502
void exec_increase(char *p)
1503
{
12245 bpr 1504
  char *p1, *p2;
1505
  p1=find_word_start(p); p2=find_word_end(p1);
1506
  if(p2<=p1) {
1507
    *p=0; return;
1508
  }
1509
  *p2=0;p2=getvar(p1);
1510
  if(p2==NULL) p2="";
1511
  setvar(p1,int2str(atoi(p2)+1)); *p=0;
10 reyssat 1512
}
1513
 
8957 bpr 1514
void exec_setseed(char *p)
12245 bpr 1515
{
1516
  char buf[64];
1517
  snprintf(buf,sizeof(buf),"%s",p);
1518
  force_setvar("wims_seed",buf);
1519
  double d=evalue(p);
1520
  srandom(d); *p=0;
8957 bpr 1521
}
1522
 
7370 bpr 1523
/* bound a variable */
10 reyssat 1524
void exec_bound(char *p)
1525
{
12245 bpr 1526
  char *p1, *p2, *p3;
1527
  int doub,i,bcnt,defaulted;
1528
  double d1,d2,dd,val;
1529
  char nbuf[MAX_LINELEN+1],lbuf[MAX_LINELEN+1],dbuf[MAX_LINELEN+1];
1530
  char vbuf[MAX_LINELEN+1];
1531
  char *blist[2048];
7379 bpr 1532
 
12245 bpr 1533
  p1=find_word_start(p); p2=find_word_end(p1);
1534
  if(*p2==0) {
1535
    syntax: module_error("syntax_error");
1536
  }
1537
  *p2=0; ovlstrcpy(nbuf,p1);substit(nbuf); p1=find_word_start(p2+1);
1538
  p2=getvar(nbuf);if(p2==NULL) p2="";
1539
  mystrncpy(vbuf,find_word_start(p2),sizeof(vbuf));
1540
  strip_trailing_spaces(vbuf);
1541
  p2=find_word_end(p1); if(*p2==0) goto syntax;
1542
  *p2=0;p2++;
1543
  p3=wordchr(p2,"default");
1544
  if(p3!=NULL) {
1545
    *p3=0; defaulted=1;
1546
    p3=find_word_start(p3+strlen("default"));
1547
    ovlstrcpy(dbuf,p3); substit(dbuf);
1548
  }
1549
  else defaulted=0;
1550
  if(strcmp(p1,"between")==0) {
1551
    p1=find_word_start(p2);
1552
    i=strlen("integer");
1553
    if(strncmp(p1,"integer",i)==0 &&
1554
        (isspace(*(p1+i)) || (*(p1+i)=='s' && isspace(*(p1+i+1))))) {
1555
      doub=0; p1=find_word_start(find_word_end(p1));
1556
      val=rint(evalue(vbuf));
1557
      if(vbuf[0]) float2str(val,vbuf);
10 reyssat 1558
    }
12245 bpr 1559
    else {
1560
      doub=1;val=evalue(vbuf);
10 reyssat 1561
    }
12245 bpr 1562
    p2=wordchr(p1,"and"); p3=p2+strlen("and");
1563
    if(p2==NULL) {
1564
      p2=strchr(p1,','); p3=p2+1;
1565
    }
1566
    if(p2==NULL) goto syntax;
1567
   *p2=0;p2=find_word_start(p3);
1568
    if(*p1==0 || *p2==0) goto syntax;
1569
    d1=evalue(p1);d2=evalue(p2);
1570
    if(!isfinite(d1) || !isfinite(d2) ||
1571
      fabs(d1)>(double)(1E10) || fabs(d2)>(double)(1E10)) goto syntax;
1572
    if(d1>d2) {
1573
      dd=d1;d1=d2;d2=dd;
1574
    }
1575
    if(vbuf[0] && val<=d2 && val>=d1) {
1576
      if(!doub) setvar(nbuf,vbuf);
1577
      *p=0; return;
1578
    }
1579
    if(defaulted) ovlstrcpy(p,dbuf);
1580
    else {
7379 bpr 1581
      if(!doub) {
12245 bpr 1582
        d1=ceil(d1);d2=floor(d2);
7379 bpr 1583
      }
1584
      if(vbuf[0]==0 || val<d1) val=d1;
1585
      else val=d2;
1586
      float2str(val,p);
10 reyssat 1587
    }
12245 bpr 1588
    setvar(nbuf,p); *p=0; return;
1589
  }
1590
  else {
7379 bpr 1591
    if(strcmp(p1,"within")==0 || strcmp(p1,"among")==0) {
12245 bpr 1592
      ovlstrcpy(lbuf,p2);substit(lbuf);
1593
      bcnt=cutitems(lbuf,blist,2048);
1594
      if(bcnt<=0) {
1595
        *p=0; return;
1596
      }
1597
      for(i=0;i<bcnt;i++) {
1598
        if(strcmp(blist[i],vbuf)==0) {
7379 bpr 1599
          *p=0; return;
1600
        }
12245 bpr 1601
      }
1602
      if(defaulted) ovlstrcpy(p,dbuf); else ovlstrcpy(p,blist[0]);
1603
      setvar(nbuf,p); *p=0;
1604
      return;
10 reyssat 1605
    }
12245 bpr 1606
  else goto syntax;
1607
  }
10 reyssat 1608
}
1609
 
8155 bpr 1610
/* detrust the module. */
10 reyssat 1611
void exec_detrust(char *p)
12245 bpr 1612
{
1613
  untrust|=1; *p=0;
1614
}
10 reyssat 1615
 
1616
void exec_warn(char *p)
1617
{
12245 bpr 1618
  char *p1,*p2;
1619
  char buf[MAX_FNAME+1];
1620
  WORKING_FILE save;
10 reyssat 1621
 
12245 bpr 1622
  if(!outputing) goto end;
1623
  p1=find_word_start(p);p2=find_word_end(p1);
1624
  if(p2<=p1) goto end;
1625
  *p2=0;
1626
  snprintf(buf,sizeof(buf),"wims_warn_%s",p1);
1627
  p2=getvar(buf);
1628
  if(p2==NULL || *p2==0) goto end;
1629
  p2=getvar("module_language");if(p2==NULL) p2="en";
1630
  mkfname(buf,"msg/warn_%s.phtml.%s",p1,p2);
1631
  memmove(&save,&m_file,sizeof(WORKING_FILE));
1632
  if(open_working_file(&m_file,buf)==0) phtml_put(NULL,0);
1633
  memmove(&m_file,&save,sizeof(WORKING_FILE));
1634
  end:
1635
  *p=0; return;
10 reyssat 1636
}
1637
 
8155 bpr 1638
/* write an error message. */
10 reyssat 1639
void exec_msg(char *p)
1640
{
12245 bpr 1641
  char *p1,*p2, buf[64], *l;
1642
  secure_exec();
1643
  p1=find_word_start(p); p2=find_word_end(p1);
1644
  if(*p2) {
1645
    *p2=0; p2=find_word_start(p2+1);
1646
  }
1647
  force_setvar("wims_error",p1); force_setvar("wims_error_parm",p2);
1648
  l=getvar("module_language");
1649
  if(l!=NULL && strlen(l)==2) {
1650
    snprintf(buf,sizeof(buf),"msg.phtml.%s",l);
1651
    phtml_put_base(buf,0);
1652
  }
1653
  *p=0;
10 reyssat 1654
}
1655
 
8185 bpr 1656
struct distr_cmd distr_cmd[]={
12245 bpr 1657
  {"char",      NULL},
1658
  {"charof",    NULL},
1659
  {"chars",     NULL},
1660
  {"charsof",   NULL},
1661
  {"item",      cutitems},
1662
  {"itemof",    cutitems},
1663
  {"items",     cutitems},
1664
  {"itemsof",   cutitems},
1665
  {"line",      cutlines},
1666
  {"lineof",    cutlines},
1667
  {"lines",     cutlines},
1668
  {"linesof",   cutlines},
1669
  {"list",      cutitems},
1670
  {"word",      cutwords},
1671
  {"wordof",    cutwords},
1672
  {"words",     cutwords},
1673
  {"wordsof",   cutwords}
10 reyssat 1674
};
1675
 
8185 bpr 1676
int distr_cmd_no=(sizeof(distr_cmd)/sizeof(distr_cmd[0]));
10 reyssat 1677
 
8155 bpr 1678
/* distribute a number of lines, items, etc. into a list of vars. */
10 reyssat 1679
void exec_distribute(char *p)
1680
{
12245 bpr 1681
  int i,k,n;
1682
  char *p1, *p2;
1683
  char bf1[MAX_LINELEN+1],bf2[MAX_LINELEN+1];
1684
  char *names[4096],*vals[4096];
1685
  p1=find_word_start(p); p2=find_word_end(p1);
1686
  if(p2<=p1 || *p2==0) module_error("syntax_error");
1687
  *p2++=0;
1688
  i=search_list(distr_cmd,distr_cmd_no,sizeof(distr_cmd[0]),p1);
1689
  if(i<0) module_error("syntax_error");
1690
  p2=find_word_start(p2); p1=wordchr(p2,"into");
1691
  if(p1==NULL) module_error("syntax_error");
1692
  *p1=0;mystrncpy(bf1,p2,sizeof(bf1));
1693
  p1=find_word_start(p1+strlen("into"));
1694
  mystrncpy(bf2,p1,sizeof(bf2));
1695
  substit(bf1);substit(bf2);
1696
  strip_trailing_spaces(bf1);
1697
  items2words(bf2); n=cutwords(bf2,names,4096);
1698
  if(distr_cmd[i].routine!=NULL) {
1699
    k=distr_cmd[i].routine(bf1,vals,n);
1700
    for(i=0;i<k;i++) setvar(names[i],vals[i]);
1701
    for(;i<n;i++) setvar(names[i],"");
1702
  }
1703
  else {
1704
    char buf[2];
1705
    buf[1]=0;
1706
    for(p1=bf1,i=0;i<n;i++) {
1707
      buf[0]=*p1; if(*p1) p1++;
1708
      setvar(names[i],buf);
10 reyssat 1709
    }
12245 bpr 1710
  }
10 reyssat 1711
}
1712
 
15542 bpr 1713
/* reset variables - the syntax name[10] is allowed*/
10 reyssat 1714
void exec_reset(char *p)
1715
{
15542 bpr 1716
  char *p1, *p2, *p3, *p4, buf[100];
1717
  int i, n;
10 reyssat 1718
 
12245 bpr 1719
  items2words(p);
1720
  for(p1=find_word_start(p); *p1; p1=find_word_start(p2)) {
1721
    p2=find_word_end(p1); if(*p2) *p2++=0;
15542 bpr 1722
    substit(p1);
1723
    p3=strchr(p1,'[');
1724
    if (p3 != NULL) {
1725
      *p3++ = 0;
1726
      p4 = find_matching(p3, ']');
1727
      if (p4 == NULL) module_error("nomatching");
1728
      *p4=0;
1729
      n = atoi(p3);
1730
      for (i = 1; i<=n; ++i) {
1731
        snprintf(buf, sizeof(buf),"%s%d",p1,i);
1732
        setvar(buf,"");
1733
      }
1734
    }
1735
    else setvar(p1,"");
12245 bpr 1736
  }
10 reyssat 1737
}
1738
 
8155 bpr 1739
/* exchange the values of two variables */
10 reyssat 1740
void exec_exchange(char *p)
1741
{
12245 bpr 1742
  char buf[MAX_LINELEN+1],b1[MAX_LINELEN+1],b2[MAX_LINELEN+1];
1743
  char *p1,*p2,*pb;
1744
  p1=wordchr(p,"and");
1745
  if(p1!=NULL) {
1746
    *p1=0; p2=find_word_start(p1+strlen("and"));
1747
  }
1748
  else {
1749
    p1=strchr(p,',');
1750
    if(p1==NULL) module_error("syntax_error");
1751
    *p1=0; p2=find_word_start(p1+1);
1752
  }
1753
  p1=find_word_start(p);
1754
  mystrncpy(b1,p1,sizeof(b1)); substit(b1); *find_word_end(b1)=0;
1755
  mystrncpy(b2,p2,sizeof(b2)); substit(b2); *find_word_end(b2)=0;
1756
  if(*b1==0 || *b2==0) module_error("syntax_error");
1757
  pb=getvar(b1);if(pb==NULL) pb="";
1758
  mystrncpy(buf,pb,sizeof(buf));
1759
  pb=getvar(b2);if(pb==NULL) pb="";
1760
  setvar(b1,pb); setvar(b2,buf);
10 reyssat 1761
}
1762
 
15488 obado 1763
/**
1764
 * Send a mail
1765
 * p contains 4 lines :
1766
    $To\
1767
    $from\
1768
    $subject\
1769
    $body\
1770
   The first line ($mailheader) must contain the recipient address.
1771
 */
10 reyssat 1772
void exec_mailto(char *p)
1773
{
15488 obado 1774
  char *from,*subject,*body,*pp,*charset;
15490 obado 1775
  char mail_content[MAX_LINELEN+1],buf[MAX_LINELEN+1];
15488 obado 1776
  /*int status;
1777
  FILE *mailer;// need stdio.h */
10 reyssat 1778
 
12245 bpr 1779
  if(!trusted_module() || is_class_module) return;
15489 obado 1780
  // searches for the first occurrence of \n
15488 obado 1781
  from=strchr(p,'\n'); if(from==NULL) return;
15704 obado 1782
  // delimitate the 'To' string.
15488 obado 1783
  *from++=0; p=find_word_start(p);
12245 bpr 1784
  if(*p==0) return;
15489 obado 1785
 
15488 obado 1786
  subject=strchr(from,'\n'); if(subject==NULL) return;
15704 obado 1787
  // delimitate the 'From' string.
15488 obado 1788
  *subject++=0; from=find_word_start(from);
15491 bpr 1789
  if(*from!=0) snprintf(buf,sizeof(buf),"From:%s\n",from);
1790
    else buf[0]=0;
15488 obado 1791
  body=strchr(subject,'\n'); if(body==NULL) return;
15704 obado 1792
  // delimitate the 'Subject' string.
15488 obado 1793
  *body++=0; subject=find_word_start(subject);
1794
 
1795
  for(pp=subject;*pp;pp++) if(*pp=='"' || *pp=='\n') *pp=' ';
1796
 
1797
  charset=getvar("wims_main_font");if(charset==NULL) charset="windows-1252";
15490 obado 1798
  snprintf(mail_content,sizeof(mail_content),
1799
          "To:%s\n%sSubject:%s\nContent-Type: text/html;charset=\"%s\"\n\n%s\n",p,buf,subject,charset,body);
1800
 
15488 obado 1801
  accessfile(mail_content,"w","%s/mail.eml",tmp_dir);
12245 bpr 1802
  wrapexec=1;
15489 obado 1803
  // you can add option '-vv' to make sendmail more verbose.
1804
  call_sh("cat %s/mail.eml | /usr/sbin/sendmail -t 2> %s/sendmail.log",tmp_dir,tmp_dir);
15488 obado 1805
 
15704 obado 1806
  /*mailer = popen("/usr/sbin/sendmail -tvv", "w");
1807
  if (mailer == NULL){module_error("sendmail_popen_error");}
1808
  fprintf(mailer, "To:%s\nSubject:%s\nContent-Type: text/html;charset=\"windows-1252\"\n\n%s",p,subject,body);
1809
  status = pclose(mailer);
1810
  if (status == -1) {
1811
    // Error reported by pclose()
1812
    module_error("sendmail_error");
1813
  }*/
1814
 
1815
  //call_sh("iconv -f %s -t UTF-8//TRANSLIT %s/mail.eml > %s/mail.eml", charset, tmp_dir, tmp_dir);
1816
  /*call_sh("mail %s -s \" %s \nContent-Type: text/html\" %s <%s/mail.eml; chmod og-rwx %s/mail.eml",
1817
      mail_opt, p1,p,tmp_dir,tmp_dir);*/
1818
 
12245 bpr 1819
  mail_log(p);
1820
  *p=0;
10 reyssat 1821
}
1822
 
8155 bpr 1823
/* Generates a user error. Internal and undocumented. */
10 reyssat 1824
void exec_usererror(char *p)
1825
{
12245 bpr 1826
  if(trusted_module()) user_error(p);
10 reyssat 1827
}
1828
 
8155 bpr 1829
/* stop output. */
10 reyssat 1830
void exec_directout(char *p)
1831
{
12245 bpr 1832
  if(outputing || !trusted_module()) return;
1833
  printf("%s",p);
1834
  noout=1;
10 reyssat 1835
}
1836
 
1837
enum {
12245 bpr 1838
  EXEC_IF, EXEC_JUMP, EXEC_ELSE, EXEC_ENDIF, EXEC_EXEC,
1839
  EXEC_WHILE, EXEC_ENDWHILE,
1840
  EXEC_FOR, EXEC_VAR, EXEC_DEBUG, EXEC_DAEMON,
1841
  EXEC_SET, EXEC_DEFAULT, EXEC_COMMENT, EXEC_READ, EXEC_HREF,
1842
  EXEC_INS, EXEC_STRING, EXEC_PEDIA, EXEC_DIR,
1843
  EXEC_TRUST, EXEC_WARN, EXEC_ERROR, EXEC_SQL, EXEC_SCORE,
1844
  EXEC_MAIL, EXEC_OTHER
10 reyssat 1845
} EXEC_TYPES;
1846
#define EXEC_SUBST 0x1000
1847
#define EXEC_USECALC 0x2000
1848
#define EXEC_PROCTOO 0x4000
1849
MYFUNCTION exec_routine[]={
12245 bpr 1850
  {"!",        EXEC_COMMENT,        exec_comment},
1851
  {"TeXmath",  EXEC_STRING|EXEC_SUBST|EXEC_USECALC,texmath},
1852
  {"add",      EXEC_STRING|EXEC_USECALC,calc_sum},
1853
  {"advance",  EXEC_VAR|EXEC_SUBST,   exec_increase},
1854
  {"append",   EXEC_STRING|EXEC_USECALC,calc_append},
1855
  {"appendfile",EXEC_DIR|EXEC_SUBST,    fileappend},
1856
  {"bound",     EXEC_STRING,       exec_bound},
1857
  {"break",     EXEC_FOR,        exec_break},
1858
  {"call",      EXEC_EXEC|EXEC_SUBST|EXEC_PROCTOO|EXEC_USECALC,    calc_exec},
1859
  {"changeto",  EXEC_READ|EXEC_SUBST,    exec_changeto},
1860
  {"char",      EXEC_STRING|EXEC_USECALC,calc_charof},
1861
  {"chars",     EXEC_STRING|EXEC_USECALC,calc_charof},
1862
  {"checkhost", EXEC_STRING|EXEC_USECALC|EXEC_SUBST,calc_checkhost},
1863
  {"column",    EXEC_STRING|EXEC_USECALC,calc_columnof},
1864
  {"columns",   EXEC_STRING|EXEC_USECALC,calc_columnof},
1865
  {"comment",   EXEC_COMMENT,        exec_comment},
1866
  {"daemon",    EXEC_DAEMON|EXEC_USECALC|EXEC_SUBST,calc_daemon},
1867
  {"date",      EXEC_STRING|EXEC_USECALC|EXEC_SUBST,calc_date},
1868
  {"deaccent",  EXEC_STRING|EXEC_USECALC|EXEC_SUBST,deaccent},
1869
  {"debug",     EXEC_DEBUG,        calc_debug},
1870
  {"declosing", EXEC_STRING|EXEC_USECALC|EXEC_SUBST,calc_declosing},
1871
  {"def",       EXEC_SET,        exec_set},
1872
  {"default",   EXEC_SET,        exec_default},
1873
  {"define",    EXEC_SET,        exec_set},
1874
  {"definitionof", EXEC_SCORE|EXEC_USECALC,calc_defof},
1875
  {"defof",     EXEC_SCORE|EXEC_USECALC,calc_defof},
1876
  {"defread",   EXEC_READ|EXEC_SUBST,    exec_defread},
1877
  {"detag",     EXEC_STRING|EXEC_USECALC|EXEC_SUBST,calc_detag},
1878
  {"detrust",   EXEC_TRUST,        exec_detrust},
7379 bpr 1879
/*      {"dictionary",EXEC_STRING|EXEC_USECALC,calc_dictionary},    */
12245 bpr 1880
  {"dir",       EXEC_DIR|EXEC_SUBST|EXEC_USECALC,calc_listfile},
1881
  {"distribute",EXEC_STRING,        exec_distribute},
1882
  {"distrust",  EXEC_TRUST,        exec_detrust},
1883
  {"else",      EXEC_ELSE,        exec_else},
1884
  {"embraced",  EXEC_STRING|EXEC_USECALC,calc_embraced},
1885
  {"encyclo",   EXEC_PEDIA|EXEC_SUBST|EXEC_USECALC,pedia},
1886
  {"encyclopedia",EXEC_PEDIA|EXEC_SUBST|EXEC_USECALC,pedia},
1887
  {"endif",     EXEC_ENDIF,        exec_endif},
1888
  {"endwhile",  EXEC_ENDWHILE,        exec_endwhile},
1889
  {"evalsubst", EXEC_STRING|EXEC_USECALC,calc_evalsubst},
1890
  {"evalsubstit",EXEC_STRING|EXEC_USECALC,calc_evalsubst},
1891
  {"evalsubstitute",EXEC_STRING|EXEC_USECALC,calc_evalsubst},
1892
  {"evaluesubst",EXEC_STRING|EXEC_USECALC,calc_evalsubst},
1893
  {"evaluesubstit",EXEC_STRING|EXEC_USECALC,calc_evalsubst},
1894
  {"evaluesubstitute",EXEC_STRING|EXEC_USECALC,calc_evalsubst},
1895
  {"examscore", EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_examscore},
1896
  {"exchange",  EXEC_STRING,        exec_exchange},
1897
  {"exec",      EXEC_EXEC|EXEC_SUBST|EXEC_PROCTOO|EXEC_USECALC,    calc_exec},
1898
  {"execute",   EXEC_EXEC|EXEC_SUBST|EXEC_PROCTOO|EXEC_USECALC,    calc_exec},
1899
  {"exit",      EXEC_JUMP,        exec_exit},
1900
  {"fileappend",EXEC_DIR|EXEC_SUBST,    fileappend},
1901
  {"fileexists",EXEC_STRING|EXEC_USECALC, calc_fileexists},
1902
  {"filelist",  EXEC_DIR|EXEC_SUBST|EXEC_USECALC,calc_listfile},
1903
  {"fileout",   EXEC_HREF|EXEC_SUBST,    exec_getfile},
1904
  {"filewrite", EXEC_DIR|EXEC_SUBST,    filewrite},
1905
  {"filexists",EXEC_STRING|EXEC_USECALC, calc_fileexists},
1906
  {"for",       EXEC_FOR,        exec_for},
1907
  {"form",      EXEC_HREF|EXEC_SUBST,    exec_form},
1908
  {"formbar",   EXEC_HREF,        exec_formbar},
1909
  {"formcheckbox",EXEC_HREF,        exec_formcheckbox},
1910
  {"formend",   EXEC_STRING,    exec_formend},
1911
  {"formradio", EXEC_HREF,        exec_formradio},
1912
  {"formradiobar",EXEC_HREF,        exec_formbar},
1913
  {"formselect",EXEC_HREF,        exec_formselect},
1914
  {"getdef",    EXEC_SCORE|EXEC_USECALC,calc_defof},
1915
  {"getfile",   EXEC_HREF|EXEC_SUBST,    exec_getfile},
1916
  {"getscore",  EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscore},
1917
  {"getscorebest",EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscorebest},
1918
  {"getscorelast",EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscorelast},
1919
  {"getscorelevel",EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscorelevel},
1920
  {"getscoremean",EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscoremean},
1921
  {"getscorepercent",EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscorepercent},
1922
  {"getscorequality",EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscoremean},
1923
  {"getscoreremain",EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscoreremain},
1924
  {"getscorerequire",EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscorerequire},
1925
  {"getscoretry",EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscoretry},
1926
  {"getscoreweight",EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscoreweight},
1927
  {"goto",      EXEC_JUMP|EXEC_SUBST,    exec_goto},
1928
  {"header",    EXEC_HREF,        exec_header},
1929
  {"header1",   EXEC_HREF,        exec_header1},
15502 bpr 1930
  {"headmathjax",EXEC_HREF,  exec_headmathjax},
12245 bpr 1931
  {"headmenu",  EXEC_HREF,        exec_headmenu},
1932
  {"hex",       EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_hex},
1933
  {"homeref",   EXEC_HREF,        exec_homeref},
1934
  {"href",      EXEC_HREF,        exec_href},
13757 bpr 1935
  {"html2iso",  EXEC_STRING|EXEC_USECALC|EXEC_SUBST,calc_html2iso},
12245 bpr 1936
  {"htmlbar",   EXEC_HREF,        exec_formbar},
1937
  {"htmlcheckbox",EXEC_HREF,        exec_formcheckbox},
1938
  {"htmlheader",EXEC_HREF,        exec_header},
1939
  {"htmlmath",  EXEC_STRING|EXEC_SUBST|EXEC_USECALC,htmlmath},
1940
  {"htmlradio", EXEC_HREF,        exec_formradio},
1941
  {"htmlradiobar",EXEC_HREF,        exec_formbar},
1942
  {"htmlselect",EXEC_HREF,        exec_formselect},
1943
  {"htmltail",  EXEC_HREF,        exec_tail},
1944
  {"htmltitle", EXEC_HREF,        exec_title},
1945
  {"if",        EXEC_IF,        exec_if},
1946
  {"ifval",     EXEC_IF,        exec_ifval},
1947
  {"ifvalue",   EXEC_IF,        exec_ifval},
1948
  {"imgrename", EXEC_STRING|EXEC_USECALC|EXEC_SUBST,calc_imgrename},
1949
  {"include",   EXEC_READ|EXEC_SUBST,   exec_read},
1950
  {"increase",  EXEC_VAR|EXEC_SUBST,    exec_increase},
1951
  {"input",     EXEC_READ|EXEC_SUBST,    exec_read},
1952
  {"insdraw",   EXEC_INS|EXEC_SUBST,    exec_insdraw},
1953
  {"insmath",   EXEC_INS,        insmath},
1954
  {"inspaint",  EXEC_INS|EXEC_SUBST,    exec_insdraw},
1955
  {"insplot",   EXEC_INS|EXEC_SUBST,    exec_insplot},
1956
  {"insplot3d", EXEC_INS|EXEC_SUBST,    exec_insplot3d},
1957
  {"instex",    EXEC_INS,        exec_instex},
1958
  {"instexst",  EXEC_INS|EXEC_USECALC,    calc_instexst},
1959
  {"instexstatic",EXEC_INS|EXEC_USECALC,    calc_instexst},
1960
  {"item",        EXEC_STRING|EXEC_USECALC,calc_itemof},
1961
  {"items",     EXEC_STRING|EXEC_USECALC,calc_itemof},
1962
  {"items2lines", EXEC_STRING|EXEC_SUBST|EXEC_USECALC,items2lines},
1963
  {"items2words",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,items2words},
1964
  {"itemstolines",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,items2lines},
1965
  {"itemstowords",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,items2words},
1966
  {"let",        EXEC_SET,        exec_set},
1967
  {"leveldata",  EXEC_STRING|EXEC_USECALC,calc_leveldata},
1968
  {"levelpoints",EXEC_STRING|EXEC_USECALC,calc_leveldata},
1969
  {"line",       EXEC_STRING|EXEC_USECALC,calc_lineof},
1970
  {"lines",      EXEC_STRING|EXEC_USECALC,calc_lineof},
1971
  {"lines2items",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,lines2items},
1972
  {"lines2list", EXEC_STRING|EXEC_SUBST|EXEC_USECALC,lines2items},
1973
  {"lines2words",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,lines2words},
1974
  {"linestoitems",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,lines2items},
1975
  {"linestolist",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,lines2items},
1976
  {"linestowords",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,lines2words},
1977
  {"list2lines", EXEC_STRING|EXEC_SUBST|EXEC_USECALC,items2lines},
1978
  {"list2words", EXEC_STRING|EXEC_SUBST|EXEC_USECALC,items2words},
1979
  {"listfile",   EXEC_DIR|EXEC_SUBST|EXEC_USECALC,calc_listfile},
1980
  {"listfiles",  EXEC_DIR|EXEC_SUBST|EXEC_USECALC,calc_listfile},
1981
  {"listintersect",EXEC_STRING|EXEC_USECALC,calc_listintersect},
1982
  {"listintersection", EXEC_STRING|EXEC_USECALC,calc_listintersect},
1983
  {"listtolines",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,items2lines},
1984
  {"listtowords",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,items2words},
1985
  {"listunion",  EXEC_STRING|EXEC_USECALC,calc_listunion},
1986
  {"listuniq",   EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_listuniq},
1987
  {"listunique", EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_listuniq},
1988
  {"listvar",    EXEC_STRING|EXEC_SUBST|EXEC_USECALC,mathvarlist},
1989
  {"lookup",     EXEC_STRING|EXEC_USECALC,    calc_lookup},
1990
  {"lower",      EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_tolower},
1991
  {"lowercase",  EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_tolower},
1992
  {"ls",         EXEC_DIR|EXEC_SUBST|EXEC_USECALC,calc_listfile},
1993
  {"mailto",     EXEC_MAIL|EXEC_SUBST,    exec_mailto},
1994
  {"mailurl",    EXEC_MAIL|EXEC_SUBST|EXEC_USECALC,calc_mailurl},
1995
  {"makelist",   EXEC_STRING|EXEC_USECALC,calc_makelist},
1996
  {"math2html",  EXEC_STRING|EXEC_SUBST|EXEC_USECALC,htmlmath},
1997
  {"math2mathml",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,mathmlmath},
1998
  {"math2tex",   EXEC_STRING|EXEC_SUBST|EXEC_USECALC,texmath},
1999
  {"mathmlmath", EXEC_STRING|EXEC_SUBST|EXEC_USECALC,mathmlmath},
2000
  {"mathsubst",  EXEC_STRING|EXEC_USECALC,calc_mathsubst},
2001
  {"mathsubstit",EXEC_STRING|EXEC_USECALC,calc_mathsubst},
2002
  {"mathsubstitute",EXEC_STRING|EXEC_USECALC,calc_mathsubst},
2003
  {"mexec",     EXEC_EXEC|EXEC_SUBST,    exec_mexec},
2004
  {"module",    EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_module},
2005
  {"msg",       EXEC_EXEC|EXEC_SUBST,exec_msg},
2006
  {"multiply",  EXEC_STRING|EXEC_USECALC,calc_product},
2007
  {"next",      EXEC_FOR,        exec_next},
2008
  {"nocache",   EXEC_READ,        exec_nocache},
2009
  {"non_empty", EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_nonempty},
2010
  {"nonempty",  EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_nonempty},
2011
  {"nospace",   EXEC_STRING|EXEC_SUBST|EXEC_USECALC,nospace},
2012
  {"outfile",   EXEC_HREF|EXEC_SUBST,    exec_getfile},
2013
  {"pedia",     EXEC_PEDIA|EXEC_SUBST|EXEC_USECALC,pedia},
2014
  {"perl",      EXEC_EXEC|EXEC_PROCTOO|EXEC_SUBST,exec_perl},
2015
  {"position",  EXEC_STRING|EXEC_USECALC,calc_pos},
2016
  {"positionof",EXEC_STRING|EXEC_USECALC,calc_pos},
2017
  {"positions", EXEC_STRING|EXEC_USECALC,calc_pos},
2018
  {"prod",      EXEC_STRING|EXEC_USECALC,calc_product},
2019
  {"product",   EXEC_STRING|EXEC_USECALC,calc_product},
2020
  {"rawmath",   EXEC_STRING|EXEC_SUBST|EXEC_USECALC,rawmath},
2021
  {"rawmatrix", EXEC_STRING|EXEC_SUBST|EXEC_USECALC,rawmatrix},
2022
  {"reaccent",  EXEC_STRING|EXEC_USECALC|EXEC_SUBST,reaccent},
2023
  {"read",      EXEC_READ|EXEC_SUBST,    exec_read},
2024
  {"readdef",   EXEC_READ|EXEC_SUBST,    exec_defread},
2025
  {"readproc",  EXEC_READ|EXEC_SUBST,    exec_readproc},
2026
  {"record",    EXEC_STRING|EXEC_USECALC,calc_recordof},
2027
  {"records",   EXEC_STRING|EXEC_USECALC,calc_recordof},
2028
  {"recursion", EXEC_STRING|EXEC_USECALC,calc_recursion},
2029
  {"reinput",   EXEC_STRING|EXEC_USECALC|EXEC_SUBST,calc_reinput},
2030
  {"rem",       EXEC_COMMENT,        exec_comment},
2031
  {"remark",    EXEC_COMMENT,        exec_comment},
2032
  {"replace",   EXEC_STRING|EXEC_USECALC,calc_replace},
2033
  {"reset",     EXEC_SET|EXEC_SUBST,    exec_reset},
2034
  {"restart",   EXEC_JUMP|EXEC_SUBST,    exec_restart},
2035
  {"return",    EXEC_JUMP,        exec_exit},
2036
  {"robotrap",  EXEC_HREF|EXEC_SUBST,    exec_robottrap},
2037
  {"robottrap", EXEC_HREF|EXEC_SUBST,    exec_robottrap},
2038
  {"rootof",    EXEC_STRING|EXEC_USECALC,calc_solve},
2039
  {"row",       EXEC_STRING|EXEC_USECALC,calc_rowof},
2040
  {"rows",      EXEC_STRING|EXEC_USECALC,calc_rowof},
2041
  {"rows2lines",EXEC_STRING|EXEC_USECALC|EXEC_SUBST,calc_rows2lines},
2042
  {"run",       EXEC_EXEC|EXEC_SUBST|EXEC_PROCTOO|EXEC_USECALC,    calc_exec},
2043
  {"select",    EXEC_STRING|EXEC_USECALC,calc_select},
2044
  {"set",       EXEC_SET,        exec_set},
2045
  {"setdef",    EXEC_OTHER,        exec_setdef},
2046
  {"setseed",   EXEC_STRING|EXEC_SUBST,        exec_setseed},
2047
  {"sh",        EXEC_EXEC|EXEC_PROCTOO|EXEC_SUBST,exec_sh},
2048
  {"shortout",  EXEC_JUMP|EXEC_SUBST,    exec_directout},
2049
  {"singlespace",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,singlespace},
2050
  {"solve",     EXEC_STRING|EXEC_USECALC,calc_solve},
2051
  {"sort",      EXEC_STRING|EXEC_USECALC, calc_sort},
7379 bpr 2052
/*      {"sql",     EXEC_SQL|EXEC_SUBST|EXEC_USECALC, calc_sql}, */
12245 bpr 2053
  {"staticinstex",EXEC_INS|EXEC_USECALC,    calc_instexst},
2054
  {"stinstex",  EXEC_INS|EXEC_USECALC,    calc_instexst},
2055
  {"sum",       EXEC_STRING|EXEC_USECALC,calc_sum},
2056
  {"system",    EXEC_EXEC|EXEC_PROCTOO|EXEC_SUBST,exec_sh},
2057
  {"tail",      EXEC_HREF,        exec_tail},
2058
  {"test",      EXEC_DEBUG,        exec_test},
2059
  {"texmath",   EXEC_STRING|EXEC_SUBST|EXEC_USECALC,texmath},
2060
  {"text",      EXEC_STRING|EXEC_USECALC,text},
2061
  {"title",     EXEC_HREF,        exec_title},
2062
  {"tohex",     EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_hex},
2063
  {"tolower",   EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_tolower},
2064
  {"toupper",   EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_toupper},
2065
  {"translate", EXEC_STRING|EXEC_USECALC,calc_translate},
2066
  {"trim",      EXEC_STRING|EXEC_USECALC,calc_trim},
2067
  {"upper",     EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_toupper},
2068
  {"uppercase", EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_toupper},
2069
  {"usererror", EXEC_WARN|EXEC_SUBST,    exec_usererror},
2070
  {"values",    EXEC_STRING|EXEC_USECALC,calc_values},
2071
  {"varlist",   EXEC_STRING|EXEC_SUBST|EXEC_USECALC,mathvarlist},
2072
  {"warn",      EXEC_WARN|EXEC_SUBST,    exec_warn},
2073
  {"warning",   EXEC_WARN|EXEC_SUBST,    exec_warn},
2074
  {"while",     EXEC_WHILE,        exec_while},
2075
  {"whileval",  EXEC_WHILE,        exec_whileval},
2076
  {"whilevalue",EXEC_WHILE,        exec_whileval},
2077
  {"wimsheader",EXEC_HREF,        exec_header},
2078
  {"wimsref",   EXEC_HREF,        exec_homeref},
2079
  {"wimstail",  EXEC_HREF,        exec_tail},
2080
  {"wimstitle", EXEC_HREF,        exec_title},
2081
  {"word",      EXEC_STRING|EXEC_USECALC,calc_wordof},
2082
  {"words",     EXEC_STRING|EXEC_USECALC,calc_wordof},
2083
  {"words2items",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,words2items},
2084
  {"words2lines",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,words2lines},
2085
  {"words2list",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,words2items},
2086
  {"wordstoitems",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,words2items},
2087
  {"wordstolines",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,words2lines},
2088
  {"wordstolist",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,words2items},
2089
  {"writefile", EXEC_DIR|EXEC_SUBST,    filewrite},
10 reyssat 2090
};
8185 bpr 2091
int EXEC_FN_NO=(sizeof(exec_routine)/sizeof(exec_routine[0]));
10 reyssat 2092
 
8155 bpr 2093
/* internal: to skip the content of a false if/while. */
10 reyssat 2094
static void _skip_contents(int isif)
2095
{
12245 bpr 2096
  char buf[MAX_NAMELEN+8], *p1;
2097
  int i,j,loop;
2098
  loop=0;
2099
  while(m_file.linepointer<m_file.linecnt) {
2100
    j=m_file.linepointer;
2101
    if((m_file.lines[j].isstart&2)==0) {
2102
      m_file.linepointer++; continue;
2103
    }
2104
    i=m_file.lines[j].execcode;
2105
    if(i<0) {
2106
      if(wgetline(buf,MAX_NAMELEN+4,&m_file)==EOF) return;
2107
      p1=buf+1; if(*p1!='i' && *p1!='e' && *p1!='w') continue;
2108
      *find_word_end(p1)=0;
2109
      i=search_list(exec_routine,EXEC_FN_NO,sizeof(exec_routine[0]),p1);
2110
      if(i>=0) m_file.lines[j].execcode=i;
2111
    }
2112
    else m_file.linepointer++;
2113
    if(i<0) continue;
2114
    switch(exec_routine[i].tag & 0xffff) {
2115
      case EXEC_WHILE:
2116
        if(!isif) loop++;
2117
        break;
2118
      case EXEC_IF:
2119
        if(isif) loop++;
2120
        break;
2121
      case EXEC_ELSE: {
2122
        if(!isif) break;
2123
        if(loop<=0) return; else break;
7379 bpr 2124
      }
12245 bpr 2125
      case EXEC_ENDIF: {
2126
        if(!isif) break;
2127
        if(loop>0) {
2128
          loop--; break;
2129
        }
2130
        else return;
7379 bpr 2131
      }
12245 bpr 2132
      case EXEC_ENDWHILE: {
2133
        if(isif) break;
2134
        if(loop>0) {
2135
          loop--; break;
7379 bpr 2136
        }
12245 bpr 2137
        else return;
7379 bpr 2138
      }
12245 bpr 2139
      default: break;
10 reyssat 2140
    }
12245 bpr 2141
  }
10 reyssat 2142
}
2143
 
8155 bpr 2144
/* Execute a command defined by !. Returns 0 if OK. */
10 reyssat 2145
void exec_main(char *p)
2146
{
12245 bpr 2147
  int i,j;
2148
  char *pp;
2149
  char tbuf2[MAX_LINELEN+1];
10 reyssat 2150
 
12245 bpr 2151
  pp=find_word_end(p);
2152
  if(*pp!=0) {
2153
    *(pp++)=0; pp=find_word_start(pp);
2154
  }
2155
  i=m_file.lines[m_file.l].execcode;
2156
  if(i<0) {
2157
    i=search_list(exec_routine,EXEC_FN_NO,sizeof(exec_routine[0]),p);
2158
    m_file.lines[m_file.l].execcode=i;
2159
  }
2160
  if(i<0) {
2161
    setvar(error_data_string,p); module_error("bad_cmd");
2162
  }
8155 bpr 2163
/* called from !readdef, no right other than set; bail out */
12245 bpr 2164
  execnt++;
2165
  if((untrust&4)!=0 && (j=(exec_routine[i].tag&0xffff))!=EXEC_SET) {
2166
    tbuf2[0]=0; exec_exit(tbuf2);
2167
  }
2168
  ovlstrcpy(tbuf2,pp); j=exec_routine[i].tag;
2169
  if(j&EXEC_SUBST) substit(tbuf2);
2170
  if(j&EXEC_USECALC) {
2171
    if(!outputing && (j&EXEC_PROCTOO)==0) return;
2172
    exec_routine[i].routine(tbuf2); if(outputing) output0(tbuf2);
2173
  }
2174
  else exec_routine[i].routine(tbuf2);
2175
  return;
10 reyssat 2176
}