Logo Search packages:      
Sourcecode: wims version File versions  Download package

wims.c

/*    Copyright (C) 1998 XIAO, Gang of Universite de Nice - Sophia Antipolis
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/* Web mathematical exerciser */

#define WEBMATH 1
#include "Lib/libwims.h"
#include "wims.h"

#define evalue strevalue
char *robot_session="../robot";
int robot_access=0,human_access=0;
int user_error_nolog=0;
char *good_agent[]={
      "Mozilla","Netscape","Opera","WIMS",
       "Microsoft Internet Explorer","Lynx","Konqueror",
       "Lotus-Notes","Java","NCSA Mosaic", "OmniWeb",
      "Multilingual Mosai", "HtmlViewer", "Dillo"
};
#define good_agent_no (sizeof(good_agent)/sizeof(good_agent[0]))
char *bad_agent[]={
      "HTTrack","MemoWeb","Teleport","Offline","Wget","eCatch",
      "Powermarks","EmailSiphon", "WebCopier", "Teoma"
};
#define bad_agent_no (sizeof(bad_agent)/sizeof(bad_agent[0]))

/* used for debugging */
int debug=0;

00044 typedef struct {
    char *name;
    char *value;
} USER_VARIABLE;

USER_VARIABLE user_variable[MAX_VAR_NUM];
int user_var_no;

      /* Destinated to module error messages */
WORKING_FILE m_file;

      /* whether the user has defined language */
int user_lang=0;

      /* for instex grouping */
int instex_cnt=0, getwimstexsize=1;
char instex_src[MAX_LINELEN+1], instex_fname[MAX_LINELEN+1];
char *instex_processor="tex..gd";

      /* Cookie management */
char cookiegot[256], cookieset[256], cookieheader[64]="WIMSUSER=";

      /* multipart boundary */
char mpboundary[1024];
int  deplen=0; /* length of deposit */

int confset=0; /* set to 1 if setvar for config */

      /* Operating mode: default, popup, raw, etc. */
enum {mode_default, mode_popup, mode_raw} NAME_MODES;
int mode=mode_default;

      /* Switch; notice subroutines wherether we are outputing. */
int outputing;

char *home_module="home"; /* name of home module */
extern char **environ;        /* table of environment variables */
int module_defined=0;

        /* directory prefix buffers */
char session_prefix[MAX_LINELEN+1], module_prefix[MAX_LINELEN+1];

char *stdinbuf;
int executed_gotos; /* number of goto's executed. to check with GOTO_LIMIT. */
int insert_no; /* number of instex, insplot, insPLOT. */
int output_length; /* length of the output. */
int isexam=0;     /* non-zero if request is exam */
int direct_datafile=0;
int exec_is_module=0;
int new_session=0; /* =1 if new session created */
int internal_sql=0; /* for internal sql use */
int direct_exec=0; /* calc routine is exected by exec if 1 */
int print_precision=8; /* precision when printing real numbers */
int session_serial, saved_serial; /* request serial for session control */
int form_access=0;      /* identifies form access, for robot identification */
FILE *lastout_file=NULL;      /* file to hold last output */
char *last_query_string="";   /* last query string saved in var file */
char *instex_style="";        /* "": text "$": math "$$": displaymath */
int instex_usedynamic=0;      /* always dynamic if 1 */
int wrapexec=0;         /* if set to 1, change uid (nobody) to euid (wims).
                   * if set to -1, change euid to uid when exec(). */
int parm_restore=0;     /* Restoring saved parameters? */
int exec_wait=1;  /* whether to wait for fork return */
int manageable=0; /* whether the connection may be site manager
                   * 0: no; 1: maybe; 2: sure */
int ismhelp=0;          /* 1 if session is in mhelp. */
int noout=0;            /* if set to 1 then output is skipped */
char tmp_dir[80]="/var/lib/wims/tmp";     /* temporary directory, default */
char *bin_dir="bin";    /* directory containing executable scripts and programs. */
char cwdbuf[256]; /* store current working directory */
char *tmp_debug="no";
char ins_alt[MAX_LINELEN+1];  /* dynamic insertion alternative text */
int isclassmodule=0;    /* 1 if the module is class module */
int setcookie=0;  /* 1 if need to set cookie */
int killpid=0;          /* pid of process to kill by alarm */
char *mathalign_sup1, *mathalign_sup2;    /* see mathalign_base */
int substnest=0;  /* nesting level of substit() */
int exodepOK=1;
long int startmtime;    /* start time in milliseconds */
int backslash_insmath=0;      /* \(...) substitution? */

struct tm *now, Now;    /* time of request */
time_t nowtime, limtime, limtimex;
char nowstr[32];

      /* Resource limits. Capital names are reserved by system. */
int rlimit_cpu=20;      /* cpu time in seconds */
int rlimit_fsize=8388608;/* file size */
int rlimit_data=33554432;/* data segment size */
int rlimit_stack=2097152;/* stack size */
int rlimit_core=0;      /* core dump size */
int rlimit_rss=16777216;      /* resident size */
int rlimit_nproc=1024;  /* number of processes */
int rlimit_nofile=512;  /* number of open files */
int rlimit_memlock=2097152;/* locked-in-memory address space */

char *var_str; /* malloc'ed buffer to hold translated query_string */

      /* buffer to hold module's variable definition file, malloc'ed. */
char *var_def_buf;

      /* job_identifier is even a reserved variable name */
char job_identifier[32];

      /* sheet and exercise information */
int wims_sheet=0,wims_exo=0;

      /* Form method: get or post */
char *default_form_method="post";

      /* Je suis maintenant oblige de passer a l'anglais 
       * pour la langue de defaut. */
char lang[16]="en";
char available_lang[MAX_LANGUAGES][4]={"en","fr"};
int available_lang_no=2;
char pre_language[4]="";
char *protocol="http"; /* http or https */

      /* check for coordinate input. This will mean that
       * the request is manual, but not robot. */
int coord_input=0;

      /* These are readonly environment variable names */
      /* special parm used for special cmds (getins, etc). */
char *ro_name[]={
      "cmd" ,
      "lang" ,
      "module" ,
      "session" ,
      "special_parm",
      "special_parm2",
      "useropts" ,
      "wims_session",
      "wims_subsession",
      "wims_window",
      "worksheet"
};
enum {
    ro_cmd, ro_lang, ro_module, ro_session, ro_special_parm, ro_special_parm2,
      ro_useropts, ro_wsession, ro_subsession, ro_win, ro_worksheet
} RO_NAMES;
#define RO_NAME_NO (sizeof(ro_name)/sizeof(ro_name[0]))

int cmd_type;
char *commands[]={
    "intro" , "new" , "renew" , "reply" , "config" , "hint" , "help" ,
      "resume", "getins", "getframe", "getfile", "close"
};
enum {
    cmd_intro, cmd_new, cmd_renew, cmd_reply, cmd_config, cmd_hint, cmd_help,
      cmd_resume, cmd_getins, cmd_getframe, cmd_getfile, cmd_close
}COMMANDS;
#define CMD_NO (sizeof(commands)/sizeof(commands[0]))

struct {
    char *name; int stat;
} internal_name[]={
      {"wims_caller",         1},   /* caller session */
      {"wims_class",          1},
      {"wims_class_limit",    1},
      {"wims_class_quota",    1},
      {"wims_class_regpass",  1},
      {"wims_class_user_limit",     1},
      {"wims_classname",      1},
      {"wims_developer",      1},
      {"wims_doc_quota",      1},
      {"wims_doc_regpass",    1},
      {"wims_email",          1},
      {"wims_exo",            0},   /* exercise number */
      {"wims_exoption",       1},   /* exercise option */
      {"wims_firstname",      1},
      {"wims_forum_limit",    1},
      {"wims_institutionname",      1},
      {"wims_isexam",         0},   /* whether the sheet is an exam sheet */
      {"wims_ismanager",      0},
      {"wims_lastname",       1},
      {"wims_mode",           0},   /* operating mode */
      {"wims_module_start_time",0},
      {"wims_otherclass",     1},   /* Remember other logins */
      {"wims_protocol",       0},   /* http protocol */
      {"wims_rafale",         0},   /* rapidfire request information */
      {"wims_req_time",       0},   /* time of the request */
      {"wims_scorereg",       0},   /* score registration flag */
      {"wims_session_serial", 0},   /* request serial in the session */
      {"wims_session_start_time",0},
      {"wims_sheet",          0},   /* sheet number */
      {"wims_sup_secure",     1},   /* secure level of supervisor */
      {"wims_supervisor",     1},   /* real name of the supervisor */
      {"wims_supervisormail", 1},   /* email of supervisor */
      {"wims_user",           1},   /* user login */
      {"wims_useropts",       1}    /* user options */
};
#define INTERNAL_NAME_NO (sizeof(internal_name)/sizeof(internal_name[0]))

char *httpd_vars[]={
      "HTTP_ACCEPT",
      "HTTP_ACCEPT_CHARSET",
      "HTTP_ACCEPT_LANGUAGE",
      "HTTP_COOKIE",
      "HTTP_HOST",
      "HTTP_USER_AGENT",
      "HTTPS",
      "QUERY_STRING",
      "REMOTE_HOST",
      "REMOTE_ADDR",
      "REMOTE_PORT",
      "REQUEST_METHOD",
      "SCRIPT_NAME",
      "SERVER_NAME",
      "SERVER_SOFTWARE",
      "SERVER_PROTOCOL"
};
#define HTTPD_VAR_NO (sizeof(httpd_vars)/sizeof(httpd_vars[0]))

char *remote_addr="";   /* storing for performance */
char *remote_host="";

char ref_name[MAX_LINELEN+1];
char ref_base[MAX_LINELEN+1];

void put_special_page(char *pname);
void useropts(void);

#include "lines.c"
#include "var.c"
#include "config.c"
#include "cleaning.c"
#include "files.c"
#include "pedia.c"
#include "evalue.c"
#include "compare.c"
#include "html.c"
#include "rawmath.c"
#include "texmath.c"
#include "insmath.c"
#include "matrix.c"
#include "score.c"
#include "test.c"
#include "calc.c"
#include "exec.c"
#include "auth.c"
#include "variables.c"
#include "exam.c"
#include "log.c"

      /* Make certain httpd variables readable by modules */
void take_httpd_vars(void)
{
    int i;
    char *p, *p2, buf[1024];
    for(i=0;i<HTTPD_VAR_NO;i++) {
      snprintf(buf,sizeof(buf),"httpd_%s",httpd_vars[i]);
      if((p=getenv(httpd_vars[i]))!=NULL) setvar(buf,p);
    }
    
    p2=getenv("SERVER_ADDR");
    if(p2!=NULL && strlen(p2)<32) {
      strcat(cookieheader,p2); strcat(cookieheader,"/");
    }
    p=getenv("HTTP_COOKIE"); cookiegot[0]=0;
    if(p!=NULL && (p2=strstr(p,cookieheader))!=NULL) {
      snprintf(cookiegot,sizeof(cookiegot),"%s",
             find_word_start(p+strlen(cookieheader)));
      *find_word_end(cookiegot)=0;
    }
}

void cookie2session(void)
{
    char cksession[64], psession[32], *ckey, *p;
    char nbuf[1024], vbuf[MAX_LINELEN+1];

    if(mode==mode_popup) return;
    if(cookiegot[0]==0 || ro_cmd==cmd_close) {
      ckset: cookiegot[0]=0; setcookie=1; return;
    }
    p=getvar("special_parm");
    if(p!=NULL && strcmp(p,"ignorecookie")==0) return;
    snprintf(cksession,sizeof(cksession),"%s",cookiegot);
    ckey=strchr(cksession,'-');
    if(ckey==NULL) goto ckset; else *ckey++=0;
    p=getvar("wims_session"); if(p==NULL) p="";
    if(strstr(p,"new")!=NULL) goto ckset;
    snprintf(psession,sizeof(psession),"%s",p);
    p=strchr(psession,'_'); if(p!=NULL) *p=0;
    if(psession[0]!=0) {
      if(strcmp(psession,cksession)==0) return;
      if(session_exists(psession)) goto ckset;
      if(session_exists(cksession)) goto change;
    }
    else {
      if(!session_exists(cksession)) return;
      change:
      p=getenv("HTTPS");
      if(p!=NULL && strcasecmp(p,"on")==0) goto ckset;
      snprintf(nbuf,sizeof(nbuf),"%s/%s/var",session_dir,cksession);
      getdef(nbuf,"w_wims_ismanager",vbuf);
      if(vbuf[0]!=0 && vbuf[0]!='0') goto ckset;
      getdef(nbuf,"w_wims_protocol",vbuf);
      if(strcasecmp(vbuf,"https")==0) goto ckset;
      snprintf(nbuf,sizeof(nbuf),"%s/%s/var.stat",session_dir,cksession);
      getdef(nbuf,"wims_user",vbuf);
      if(vbuf[0]!=0) goto ckset;
      force_setvar(ro_name[ro_session],cksession);
      force_setvar("wims_session",cksession);
      force_setvar("wims_subsession","");
      session_serial=0;
    }
}

void determine_font(char *l)
{
    int i;
    
    if(l==NULL || *l==0) return;
    for(i=0;i<charname_no && memcmp(charname[i].name,l,2);i++);
    if(i<charname_no) setvar("wims_main_font",charname[i].font);
}

void predetermine_language(void)
{
    char *p;
    int i,n;

    if(pre_language[0]!=0) p=pre_language;
    else p=getenv("HTTP_ACCEPT_LANGUAGE");
    if(p!=NULL && strlen(p)>=2) {
      for(i=0;i<available_lang_no && memcmp(p,available_lang[i],2)!=0;i++);
      if(i<available_lang_no) goto lend;
    }
    p=getenv("HTTP_USER_AGENT");
    if(p!=NULL && strlen(p)>=5) {
      char *q;
      if((q=strchr(p,'['))!=NULL && islower(*(q+1)) && islower(*(q+2)) && *(q+3)==']') {
          char bb[4];
          bb[0]=*(q+1);bb[1]=*(q+2);bb[2]=0;
          for(i=0;i<available_lang_no && memcmp(bb,available_lang[i],2)!=0;i++);
          if(i<available_lang_no) {
            memmove(lang,bb,2); lang[2]=0;
            goto lend2;
          }
      }
    }
    p=getenv("HTTP_HOST"); if(p==NULL) goto lend2;
    n=strlen(p); if(n<=3 || *(p+n-3)!='.') goto lend2;
    p=p+n-2;
    for(i=0;i<available_lang_no && memcmp(p,available_lang[i],2)!=0;i++);
    if(i<available_lang_no) {
      lend: memmove(lang,p,2); lang[2]=0;
      lend2:      determine_font(lang);
    }
}

      /* print a special page */
void put_special_page(char *pname)
{
    char buf[64];
    determine_font(lang);
    snprintf(buf,sizeof(buf),"%s.phtml.%s",pname,lang);
    phtml_put_base(buf);
    write_logs();free(var_str);
}

      /* check whether the connection is a site manager. */
void manager_check(void)
{
    char *p, *pp, buf[16];
    
    manageable=0;
    if(robot_access || *manager_site==0 || checkhost(manager_site)<1)
      goto mend;
    if(manager_https) {
      p=getenv("HTTPS");
      if(p==NULL || strcmp(p,"on")!=0) goto mend;
    }
    if(strcmp(remote_addr,"127.0.0.1")==0) {
      int port, port2;
      char buf[MAX_LINELEN+1], tester[256];
      p=getenv("REMOTE_PORT"); if(p==NULL) goto mend;
      port=atoi(p); if(port<1024 || port>65535) goto mend;
      p=getenv("SERVER_PORT"); if(p==NULL) goto mend;
      port2=atoi(p); if(port2>=10000 || port2<=0) goto mend;
            /* this is very non-portable */
      manageable=1;
      accessfile(buf,"r","/proc/net/tcp");
      snprintf(tester,sizeof(tester)," 0100007F:%04X 0100007F:%04X ",
             port,port2);
      p=strstr(buf,tester); 
      if(p!=NULL) {
          pp=strchr(p,'\n'); if(pp!=NULL) *pp=0;
          if(strlen(p)>=75) {
            p=find_word_start(p+70); *find_word_end(p)=0;
            if(atoi(p)==geteuid()) manageable=2;
          }
      }
    }
    else manageable=1;
    if(manageable>0 && (confstat.st_mode&(S_IRWXO|S_IRWXG))!=0) manageable=-1;
    if(manageable>0 && !trusted_module()) manageable=0;
    if(manageable==1) {
      char fbuf[MAX_LINELEN+1];
      fbuf[0]=0;
      accessfile(fbuf,"r","%s/.manager",session_prefix);
      if(strstr(fbuf,"yes")!=NULL) manageable=2;
    }
    if(manageable==1) {
      p=getvar(ro_name[ro_module]);
      if(p!=NULL && strncmp(p,"adm/manage",strlen("adm/manage"))==0) {
          struct stat pstat;
          if(stat("../.wimspass",&pstat)==0) {
            if((S_IFMT&pstat.st_mode)!=S_IFREG || 
               ((S_IRWXO|S_IRWXG)&pstat.st_mode)!=0)
              manageable=-2;
          }
      }
    }
    mend:
    snprintf(buf,sizeof(buf),"%d",manageable);
    force_setvar("wims_ismanager",buf);
    if(manageable>=2) {
      struct rlimit rlim;
      rlimit_cpu*=10;
      rlim.rlim_cur=rlim.rlim_max=rlimit_cpu;
      setrlimit(RLIMIT_CPU,&rlim);
      snprintf(buf,sizeof(buf),"%u",rlimit_cpu);
      setvar("wims_cpu_limit",buf);
    }
}

      /* check for robot access */
void robot_check(void)
{
    char *ua, *ses, *c, *mod;
    int i;

    if(human_access) return;
    mod=getvar(ro_name[ro_module]);
    if(mod!=NULL && strcmp(mod,"adm/raw")==0) return;
    ua=getenv("HTTP_USER_AGENT");
    if(ua!=NULL) {
      for(i=0;i<bad_agent_no 
          && strstr(ua,bad_agent[i])==NULL;i++);
      if(i<bad_agent_no) user_error("trapped");
      for(i=0;i<good_agent_no 
          && strncasecmp(ua,good_agent[i],strlen(good_agent[i]));i++);
      if(i<good_agent_no) return;
    }
      /* requests with referers are OK. */
/*    ua=getenv("HTTP_REFERER");
    if(ua!=NULL && *ua!=0 && strstr(ua,"wims.cgi")==NULL) return;
*/    ses=getvar(ro_name[ro_session]);
      /* user has valid session; OK */
    if(ses!=NULL && strncmp(ses,robot_session,strlen(robot_session))!=0) {
      set_session_prefix(); if(check_session()!=-1) return;
    }
    force_setvar(ro_name[ro_session],robot_session);
    force_setvar("wims_session",robot_session);
    c=getvar(ro_name[ro_cmd]);
    robot_access=1;
    if(c!=NULL && strcmp(c,"new") && strcmp(c,"intro")) {
      put_special_page("robot");
      exit(0);
    }
}

      /* type=0: ordinary; type=1: multipart/form-data */
void parse_query_string(int len, int type)
{
    int i,j,l,v,cmd_defined;
    int parenth=-1, ll, lb, dlen;
    char *start, *p, *p1, *pt, *b1="";
    
    cmd_defined=0;
    setvar("wims_subsession","");
    ll=lb=0;
    if(type) {
      ll=strlen(mpboundary);
      start=strstr(var_str,mpboundary);
      if(start==NULL) start=var_str+strlen(var_str);
      if(strstr(var_str,"\r\n\r\n")!=NULL) b1="\r\n\r\n";
      else b1="\n\n";
      lb=strlen(b1);
    }
    else start=var_str;
    for(v=0, p1=start;p1<var_str+len;p1+=l) {
      if(type) {
          char *p2, *p3, *p4, *p5;
          p2=p1+ll; p3=memstr(p2,mpboundary,var_str+len-p2); l=p3-p1;
          p=memstr(p2,b1,var_str+len-p2); if(p>=p3) continue;
          p+=lb; if(p3<var_str+len) {
            while(*p3!='\n' && p3>p2) p3--; *p3=0;
            p3--; if(*p3=='\r') *p3=0;
          }
          dlen=p3-p;
          p2=memstr(p2,"name=",p3-p2); if(p2>=p3) continue;
          p2+=strlen("name="); if(*p2=='"') p2++;
          for(p3=p2; isalnum(*p3) || strchr("._",*p3)!=NULL; p3++);
          if(p3==p2) continue;
          if(p3-p2==strlen("wims_deposit") &&
             strncmp(p2,"wims_deposit",p3-p2)==0) {
            p4=memstr(p1,"filename=",p-p1); if(p4<p) {
                p4+=strlen("filename="); if(*p4=='"') {
                  p4++; p5=strchr(p4,'"');
                  if(p5==NULL || p5-p4>256) goto emptyquote;
                }
                else {
                  emptyquote: 
                  for(p5=p4; p5<p && !isspace(*p5) &&
                      strchr(";\"~#*?=,'",*p5)==NULL; p5++);
                }
                if(p5>p4) {
                  *p5=0;
                  for(p5--;
                      p5>=p4 && !isspace(*p5) && strchr("/\\:",*p5)==NULL;
                      p5--);
                  if(p5>=p4) p4=p5+1; if(*p4==0) goto noname;
                  if(strstr(p4,"..")!=NULL || *p4=='.')
                    p4="noname.file";
                  setvar("wims_deposit",p4);
                }
                else {
                  noname: setvar("wims_deposit","noname.file");
                }
            }
            deplen=dlen;
          }
          *p3=0; l-=p2-p1; p1=p2;
      }
      else {
          p1=find_word_start(p1);
          l=strlen(p1)+1; p=strchr(p1,'='); 
          if(p==NULL) p=p1+strlen(p1);
          if(*p==0 && l>1) {
            user_variable[v].name="no_name";
            user_variable[v].value=p1;
            coord_input=1;
            goto nnext;
          }
          *p++=0;
      }
            /* empty name or empty value: ignore */
        if(*p1==0 || *p==0) continue;
            /* We do not treat names containing '.' */
      for(pt=p1; *pt; pt++) if(*pt=='.') *pt='_';
            /* Restrictions on variable names */
      for(pt=p1; isalnum(*pt) || *pt=='_'; pt++);
      if(*pt) continue;
            /* This is a restriction:
             * Every parameter must have matching parentheses. */
      if(parenth==-1 && strcmp(p1,"wims_deposit")!=0
         && check_parentheses(p,1)) parenth=v;
      if(strcmp(p1,"special_parm")==0 && strcmp(p,"wims")==0)
        human_access=1;
      j=search_list(ro_name,RO_NAME_NO,sizeof(ro_name[0]),p1);
      if(j>=0) {
          if(j==ro_session) {
            if(strcmp(p,robot_session)==0) p="";
            if(strcasecmp(p,"popup")==0) {
                mode=mode_popup;
                force_setvar("wims_mode","popup");
                force_setvar("session","");
                continue;
            }
          }
          if(j==ro_module) module_defined=1;
          if(j==ro_cmd) cmd_defined=1;
          if(j==ro_lang) {
            if(strlen(p)!=2) continue;
            for(i=0;i<available_lang_no && strcmp(available_lang[i],p)!=0;i++);
            if(i<available_lang_no) {user_lang=1; strcpy(lang,p);}
            else continue;
          }
          /* strip leading and trailing '/'s in module name */
          if(j==ro_module) {
            while(*p=='/') p++;
            while(*p!=0 && *(p+strlen(p)-1)=='/') *(p+strlen(p)-1)=0;
          }
          setvar(p1,p);
          if(j==ro_session && mode!=mode_popup) {
            char *pp, *pr;
            char buf[1024];
            strncpy(buf,p,1023); buf[1023]=0;
            if((pp=strchr(buf,'.'))!=NULL) {
                *pp++=0; session_serial=atoi(pp);
                if(pp<0) pp=0;
            }
            else session_serial=0;
            pp=strchr(buf,'_');
            if(pp!=NULL && (pr=strstr(pp,"_mhelp"))!=NULL) {
                *pr=0; ismhelp=1; lastout_file=NULL;
                setvar("wims_inssub","mh");
            }
            force_setvar("wims_session",buf);
            if(pp!=NULL) force_setvar("wims_subsession",pp);
          }
          continue;
      }
      user_variable[v].name=p1;
      user_variable[v].value=p;
nnext:      v++; if(v>=MAX_VAR_NUM) user_error("too_many_variables");
    }
    user_var_no=v;
    if(parenth>=0) {
      char buf[256];
      snprintf(buf,sizeof(buf),"%d",user_var_no);
      setvar("user_var_no",buf);
      for(i=0;i<user_var_no;i++) {
          snprintf(buf,sizeof(buf),"name%d",i);
          setvar(buf,user_variable[i].name);
          snprintf(buf,sizeof(buf),"value%d",i);
          setvar(buf,user_variable[i].value);
      }
      snprintf(buf,sizeof(buf),"%d",parenth);
      setvar("bad_parentheses",buf);
      user_error("unmatched_parentheses");
    }
    p=getenv("SCRIPT_NAME"); 
    if(p!=NULL && (p=strstr(p,"/getfile/"))!=NULL) {
      p+=strlen("/getfile/");
      force_setvar(ro_name[ro_cmd],commands[cmd_getfile]);
      force_setvar("special_parm",p);
      cmd_defined=1;
    }
    if(module_defined && !cmd_defined) setvar(ro_name[ro_cmd],commands[cmd_intro]);
    robot_check(); cookie2session();
}

      /* parse special commands */
void special_cmds(void)
{
    char *c, *p;
    int i;
    long int l=-1;
    
    c=getvar(ro_name[ro_cmd]);
    if(c==NULL || *c==0) {  /* no module name nor command */
      setvar(ro_name[ro_module],home_module);
      setvar(ro_name[ro_cmd],commands[cmd_new]);
      return;
    }
    for(i=0;i<CMD_NO && strcmp(commands[i],c)!=0; i++);
    switch(i) {
      case cmd_intro: {
          struct stat istat;
          char ifname[1024];
          set_module_prefix();
          default_form_method="get";
          snprintf(ifname,sizeof(ifname),"%s/%s",module_prefix,intro_file);
          if(stat(ifname,&istat)!=0) {
            force_setvar(ro_name[ro_cmd],commands[cmd_new]);
            return;
          }
          p=getvar("wims_session");
          if(p!=NULL && *p!=0) {
            if(set_session_prefix()==0) check_session();
            else trap_check(p);
          }
          determine_font(lang);
          main_phtml_put(intro_file);
          write_logs();free(var_str);
          delete_pid(); exit(0);
      }
      case cmd_getins: {
          c=getvar(ro_name[ro_special_parm]);
          if(c==NULL || *c==0) {
            user_error_nolog=1; user_error("no_insnum");
          }
          if(*c=='/' || strstr(c,"..")!=NULL) goto badins;
          set_session_prefix();
          l=filelength("%s/%s",session_prefix,c);
          if(l<0) {
            badins: user_error_nolog=1; user_error("bad_insnum");
          }
          {
            char *fmt;
            fmt=strchr(c,'.');
            if(fmt==NULL) {
                user_error_nolog=1; user_error("bad_insnum");
            }
            else fmt++;
            
/* insert format problem; bricolage */
            printf("Content-type: image/%s\n\
Content-length: %ld\n\n",fmt,l);
            catfile(stdout,"%s/%s",session_prefix,c); exit(0);
          }
      }
      case cmd_getfile: {
          c=getvar(ro_name[ro_special_parm]);
          if(c==NULL || *c==0) {
            user_error_nolog=1; user_error("no_insnum");
          }
          if(*c=='/' || strstr(c,"..")!=NULL) goto badfile;
          set_session_prefix();
          l=filelength("%s/getfile/%s",session_prefix,c);
          if(l<0) {
            badfile: user_error_nolog=1; user_error("bad_insnum");
          }
          {
            char *p1;
            char mime[MAX_LINELEN+1];
            for(p1=c+strlen(c);p1>c && isalpha(*(p1-1)); p1--);
            strcpy(mime,"application/octet-stream");
            if(p1>c && *(p1-1)=='.') {
                setvar("translator_unknown",mime);
                setvar("dictionary","bases/sys/mime");
                snprintf(mime,sizeof(mime),"translator %s",p1);
                calc_exec(mime);
            }
            printf("Content-type: %s\n\
Content-length: %ld\n\n",mime,l);
            catfile(stdout,"%s/getfile/%s",session_prefix,c); exit(0);
          }
      }
      case cmd_close: {
          char *p, b2[32]; int w;
          char nbuf[256],vbuf[MAX_LINELEN+1];
          p=getvar(ro_name[ro_session]);
          if(p==NULL || strlen(p)<10 ||
             strchr(p,'/')!=NULL) return;
          snprintf(b2,sizeof(b2),"%s",p);
          p=strchr(b2,'.'); if(p!=NULL) *p=0;
          snprintf(nbuf,sizeof(nbuf),"%s/%s/var.stat",session_dir,b2);
          getdef(nbuf,"wims_caller",vbuf);
          if(vbuf[0]!=0) force_setvar(ro_name[ro_session],vbuf);
          w=wrapexec; wrapexec=1;
          call_sh("rm -Rf %s/%s* &>/dev/null",session_dir,b2);
          wrapexec=w; cookiegot[0]=0;
          force_setvar(ro_name[ro_cmd],"new");
      }
      default: return;
    }
}

      /* This is run only when manually invoking the program.
       * Verifies the orderedness of various list tables. */
int verify_tables(void)
{
    if(verify_order(calc_routine,CALC_FN_NO,sizeof(calc_routine[0]))) return -1;
    if(verify_order(exec_routine,EXEC_FN_NO,sizeof(exec_routine[0]))) return -1;
    if(verify_order(main_config,MAIN_CONFIG_NO,sizeof(main_config[0]))) return -1;
    if(verify_order(mathname,mathname_no,sizeof(mathname[0]))) return -1;
    if(verify_order(hmname,hmname_no,sizeof(hmname[0]))) return -1;
    if(verify_order(ro_name,RO_NAME_NO,sizeof(ro_name[0]))) return -1;
    if(verify_order(distr_cmd,distr_cmd_no,sizeof(distr_cmd[0]))) return -1;
    if(verify_order(internal_name,INTERNAL_NAME_NO,
                sizeof(internal_name[0]))) return -1;
    if(verify_order(tmathfn,tmathfn_no,sizeof(tmathfn[0]))) return -1;
    if(verify_order(tmathvar,tmathvar_no,sizeof(tmathvar[0]))) return -1;
    if(evaltab_verify()) return -1;
    if(textab_verify()) return -1;
    return 0;
}

void config_defaults(void)
{
    int i, *pi;
    char **ps;
    
    for(i=0;i<MAIN_CONFIG_NO;i++) {
      pi=main_config[i].address; ps=main_config[i].address;
      if((1&main_config[i].is_integer)==1) 
        printf("DF_%s=%d\n",main_config[i].name, *pi);
      else
        printf("DF_%s=%s\n",main_config[i].name,*ps);
    }
}

      /* get and set useroptions */
void useropts(void)
{
    char *p;
    setvar("lang",lang);
    p=getvar("useropts");
    if(p==NULL || *p==0) p=getvar("wims_useropts");
    if(p!=NULL && *p!=0) {
      if(p[0]!=0) {
          usertexsize=p[0]-'0';
          if(usertexsize>9) usertexsize=9;
          if(usertexsize<1) usertexsize=1;
      }
    }
    if(mathalign_base) {
      mathalign_sup1="<SUP>"; mathalign_sup2="</SUP>";
    }
    else mathalign_sup1=mathalign_sup2="";
}

      /* popup module help */
void mhelp(void)
{
    char *p, buf[MAX_LINELEN+1];
    main_phtml_put("");
    if(cmd_type!=cmd_help) {
      phtml_put_base("closemhelp.phtml");
    }
    else {
      phtml_put_base("mhelpheader.phtml");
      p=getvar("special_parm");
      if(p!=NULL && strcmp(p,"about")==0) 
        phtml_put("about.phtml");
      else phtml_put("help.phtml");
      exec_tail(buf);
    }
}

      /* input: p=QUERY_STRING. output: parameter length. */
      /* Netscape puts form content into /tmp. */
int formdata(char *p)
{
    char *pp;
    int i, inlen;
    char *ctype;
    inlen=0; ctype=getenv("CONTENT_TYPE");
    if(ctype==NULL || strstr(ctype,"multipart/form-data")==NULL
       || (p=strstr(ctype,"boundary="))==NULL) {
      bad: stdinbuf=""; return 0;
    }
    pp=getenv("CONTENT_LENGTH");
    if(pp==NULL) goto bad;
    inlen=atoi(pp); if(inlen<=10) goto bad;
    if(inlen>=MAX_DEPOSITLEN) user_error("parm_too_long");
    stdinbuf=xmalloc(inlen+1);
    i=fread(stdinbuf,1,inlen,stdin); if(i!=inlen) goto bad;
    stdinbuf[i]=0;
    p+=strlen("boundary=");
    for(pp=p;isalnum(*pp) || *pp=='-'; pp++);
    if(pp-p<sizeof(mpboundary)-2) {
      memmove(mpboundary,p,pp-p); mpboundary[pp-p]=0;
    }
            /* empty data */
    if(strstr(stdinbuf,mpboundary)==NULL || strstr(stdinbuf,"name=")==NULL) {
      free(stdinbuf); goto bad;
    }
    form_access=1; post_log();
    return inlen;
}

void buffer_init(void)
{
    struct timeval tv;
    mpboundary[0]=cookiegot[0]=cookieset[0]=cwdbuf[0]=0;
    instex_src[0]=instex_fname[0]=0;
    stdinbuf=NULL;
    if(gettimeofday(&tv,NULL)) startmtime=0;
    else startmtime=((tv.tv_sec%10000)*1000+tv.tv_usec/1000);
}

int main(int argc, char *argv[], char *envp[])
{
    char *p, homebuf[1024], lbuf[1024];
    int inlen=0;

    error1=user_error; error2=module_error; error3=internal_error;
    substitute=substit; buffer_init();
    nowtime=time(0); now=localtime(&nowtime);
    initalarm(); var_init(); umask(022);
    memmove(&Now, now, sizeof(Now)); now=&Now;
    snprintf(nowstr,sizeof(nowstr),"%04d%02d%02d.%02d:%02d",
           (now->tm_year)+1900,(now->tm_mon)+1,now->tm_mday,
           now->tm_hour,now->tm_min);
    p=getenv("QUERY_STRING");
    if(argc>1 && p==NULL) {
      if(strcasecmp(argv[1],"table")==0) {
          if(verify_tables()) internal_error("Table disorder.");
          else printf("Table orders OK.\n");
          return 0;
      }
      if(strcasecmp(argv[1],"cleansessions")==0) {
          int i;
          if(argc<3) internal_error("Clean: idle time not given.");
          i=atoi(argv[2]);
          if(i<=0) internal_error("Clean: non-positive idle time.");
          idle_time=i; cleaning(); return 0;
      }
      if(strcasecmp(argv[1],"version")==0) printf("%s",wims_version);
      if(strcasecmp(argv[1],"defaults")==0) config_defaults();
      return 0;
    }
    if(p==NULL || *p==0) {
      int i;
      stdinbuf=xmalloc(QUERY_STRING_LIMIT+1);
      i=fread(stdinbuf,1,QUERY_STRING_LIMIT,stdin); inlen=i;
      if(i<0 || i>=QUERY_STRING_LIMIT) user_error("parm_too_long");
      stdinbuf[i]=0;
      if(i>0) {
          setenv("QUERY_STRING",stdinbuf,1);
          form_access=1; post_log();
      }
    }
    else if(strncmp(p,"form-data",9)==0) inlen=formdata(p);
    executed_gotos=insert_no=output_length=0; ins_alt[0]=0;
    setvar("wims_version",wims_version);
    setvar("wims_version_date",wims_version_date);
    setvar("wims_main_font","iso-8859-1");
    take_httpd_vars();
    main_configure();
    predetermine_language();
    set_rlimits();
    init_random();
    module_configure();
    set_job_ident();
    m_file.name[0]=0;m_file.linecnt=m_file.linepointer=0;
    p=getenv("QUERY_STRING");
    if(p==NULL || strlen(p)==0) {
      setvar("lang",lang);
      snprintf(homebuf,sizeof(homebuf),"module=%s",home_module);
      p=homebuf;
    }
    if(strlen(p)>=QUERY_STRING_LIMIT) user_error("parm_too_long");
    if(mpboundary[0]==0) {
      var_str=xmalloc(strlen(p)+2);
      parse_query_string(http2env(var_str,p),0);
    }
    else {
      var_str=stdinbuf;
      parse_query_string(inlen,1);
    }
    if(ismhelp) {
      p=getvar(ro_name[ro_cmd]);
      if(p==NULL || (strcmp(p,"help")!=0 && strcmp(p,"getins")!=0)) {
          mhelp(); goto outgo;
      }
    }
    check_exam();
    useropts();
    special_cmds();
    cleaning(); /* housekeeping. */
    parse_ro_names();
    manager_check();
    set_variables();
    determine_font(getvar("module_language"));
    if(!robot_access && session_prefix[0]!=0 && cmd_type!=cmd_help) {
      snprintf(lbuf,sizeof(lbuf),"%s/%s",session_prefix,lastout);
      if(!ismhelp) lastout_file=fopen(lbuf,"w");
    }
    p=getvar("module_category");
    if(p==NULL || strstr(p,"tool")==NULL) default_form_method="get";
    if(noout) {
      save_session_vars();write_logs();
      goto outgo;
    }
    if(ismhelp) {
      mhelp();
    }
    else {
      main_phtml_put(html_file);
      if(lastout_file!=NULL) {
          fclose(lastout_file); putlastout();
      }
      save_session_vars();write_logs();
      if(new_session && mode!=mode_popup) housekeep();
    }
    outgo:
    if(var_str!=stdinbuf) free(var_str);
    delete_pid();
    if(mode!=mode_popup && trusted_module()) {
      p=getvar("wims_mode");
      if(p!=NULL && strcmp(p,"popup")==0) mode=mode_popup;
    }
    if(mode==mode_popup && insert_no==0) {
      p=getvar("wims_mode");
      if(p!=NULL && strcmp(p,"popup")==0) remove_tree(session_prefix);
    }
    return 0;
}


Generated by  Doxygen 1.6.0   Back to index