admin.c

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /* cgi_admin.c © Copyright 2000-2004 by Raosoft Inc. All Rights Reserved.     */
00003 /*                                                                            */
00004 /* You may use and modify this file for your own use, but may not distribute  */
00005 /* it or derivative works without the prior written consent of Raosoft, Inc.  */
00006 /*                                                                            */
00007 /* This software is provided "as is," and Raosoft makes no warranty, express  */
00008 /* or implied, of fitness for a articular application. Every measure has been */
00009 /* taken to anticipate risks inherent to computer networks, but we cannot     */
00010 /* guarantee safety or reliability of this program in every situation.        */
00011 /*                                                                            */
00012 /******************************************************************************/
00013 
00014 #include "cgi.h"
00015 #include <dirent.h>
00074 static char* systemFields =  "DIRECTORY,PAGE,NAME,SECTION";
00075 
00076 typedef struct
00077 {
00078   char* argv0;
00079   CGINameValue* Config;
00080   CGINameValue* Params;
00081   STREAM htmlout;
00082 } AdminInfo;
00083 
00084 int WriteINIFileSection(char* fname,char* section, CGINameValue* ini)
00085 {
00086   int size = FileSize(fname);
00087   char* c;
00088   char *d, *e;
00089   char* lastname="";
00090   char* start;
00091   size_t i;
00092   FILE * f = fopen(fname,"rt");
00093   if (!f) return 0;
00094 
00095   start = strdup3("[",section,"]");
00096   c  = CGIMALLOC(size + 2);
00097   size = fread(c,1,size,f);
00098   c[size]=0;
00099   fclose(f);
00100 
00101   d = stristr(c,start);
00102   if (d) e = stristr(d+1,"\n[");
00103   else e = 0;
00104 
00105   f = fopen(fname,"wt");
00106   if (!f)
00107   {
00108    CGIFREE(c);
00109    return 0;
00110   }
00111 
00112   fwrite(c,1,d ? (d-c) : size,f);
00113   fprintf(f,"%s",start);
00114 
00115   for (i=0; ini[i].name; i++)
00116   {
00117    if (!ini[i].name[0]) continue;
00118    if (!strcmp(ini[i].name,lastname))
00119     fprintf(f,",%s",ini[i].value);
00120    else
00121     fprintf(f,"\n%s=%s",ini[i].name,ini[i].value);
00122    lastname = ini[i].name;
00123   }
00124   fwrite("\n",1,1,f);
00125 
00126   if (e)
00127    fwrite(e,1,strlen(e),f);
00128 
00129   fclose(f);
00130   CGIFREE(c)
00131   CGIFREE(start);
00132   return 1;
00133 }
00134 
00135 void DoSetValue(CGINameValue* Variables, char*name, char* value)
00136 {
00137  if (!SetFieldValue(Variables,name,value))
00138  {
00139   ExtendNVP(Variables,128);
00140   SetFieldValue(Variables,name,value);
00141   /* add to the list of 'shadow variables' that won't get saved */
00142  }
00143 }
00144 
00145 int GetRespcount(char* argv0, char* dbname)
00146 {
00147   char filename[MAXPATH];
00148   int i = 0;
00149   FILE * f;
00150 
00151   ExpandLocalPath(argv0,filename,dbname,".respcount");
00152   f = CGIFOPEN(filename,"rb");
00153   if (f)
00154   {
00155    fread(&i,sizeof(i),1,f);
00156    fclose(f);
00157   }
00158   return i;
00159 }
00160 
00161 int SetRespcount(char* argv0, char* dbname, int i)
00162 {
00163   char filename[MAXPATH];
00164 
00165   FILE * f;
00166   ExpandLocalPath(argv0,filename,dbname,".respcount");
00167   f = CGIFOPEN(filename,"wb");
00168   if (f)
00169   {
00170    fwrite(&i,sizeof(i),1,f);
00171    fclose(f);
00172    return 1;
00173   }
00174   return 0;
00175 }
00176 
00177 FILE* OpenPage(char* argv0,char* page)
00178 {
00179  char fname[MAXPATH];
00180  FILE* f=0;
00181  if (!page) return 0;
00182  if (!*page) return 0;
00183  ExpandLocalPath(argv0,fname,"admin" SLASH,page);
00184  f = fopen(fname,"rt");
00185  return f;
00186 }
00187 
00188 void Login(AdminInfo* self)
00189 {
00190  FILE* source = OpenPage(self->argv0,"login.html");
00191  if (source)
00192  {
00193   RunReport(self->argv0,self->htmlout,source,self->Params,0,0,1,0);
00194   fclose(source);
00195  }
00196 }
00197 
00198 
00251 int VerifyPassword(AdminInfo* self,char* directory, char* password)
00252 {
00253   char fname[MAXPATH];
00254   CGINameValue* ini;
00255   int ret;
00256   char* c;
00257   if (!*directory) directory = "."; /*root dir*/
00258   ExpandLocalPath(self->argv0,fname,directory,SLASH "cgi.ini");
00259   ini = ReadINIFileSection(fname,"admin",0);
00260   c = GetFieldValue(ini,"PASSWORD");
00261   ret = *c && HasToken(password,c,0);
00262   DeleteNVP(ini);
00263   return ret;
00264 }
00265 
00266 int VerifyUser(AdminInfo* self,char* directory, char* username, char* session, char* password)
00267 {
00268   char * verify;
00269   char fname[MAXPATH];
00270   CGINameValue* ini;
00271   int ret;
00272   ret = strcspn(username,"\\/.");
00273   if (username[ret]) return 0; /* invalid name */
00274   if (ret > 32) return 0; /* too long */
00275   ExpandLocalPath(self->argv0,fname,"admin" SLASH, username);
00276   strcat(fname,".ini");
00277   ini = ReadINIFileSection(fname,"USER",1); /* leave room for a SESSION entry */
00278   if (!ini) return 0;
00279 
00280   ret = atoi(GetFieldValue(ini,"ACTIVE"));
00281   if (ret)
00282   {
00283    /* check the password */
00284    if (*password && !strcmp(password,GetFieldValue(ini,"PASSWORD")))
00285    {
00286     ret = 1;
00287     /* update the session */
00288     SetFieldValue(ini,"SESSION",session);
00289     WriteINIFileSection(fname,"USER",ini);
00290    }
00291    /* or the session */
00292    else if (*session && atoi(session) && !strcmp(session,GetFieldValue(ini,"SESSION")))
00293     ret = 1;
00294    else
00295     ret = 0;
00296 
00297    if (ret)
00298    {
00299     char* home = GetFieldValue(ini,"HOME");
00300     if (!*home && !*directory)
00301      ret = 1;
00302     else if (*home && !*directory)
00303     {
00304      SetFieldValue(self->Params,"DIRECTORY",home);
00305      ret = 2;
00306     }
00307     else
00308     {
00309      ret = HasTokenI(GetFieldValue(ini,"SPACES"),directory,0);
00310      if (!ret) /* administrators can always get in */
00311       ret = HasTokenI(GetFieldValue(ini,"SPACES"),"admin",0);
00312     }
00313     /* always can read the home directory */
00314    }
00315 
00316   }
00317 
00318   DeleteNVP(ini);
00319   return ret;
00320 }
00321 
00323 int Authenticate(AdminInfo* self,char* directory, char** cookie)
00324 {
00325  CGINameValue *clist=0;
00326 
00327  int ret = 0;
00328  char * password = GetFieldValue(self->Params,"AUTHENTICATION");
00329  char * username = GetFieldValue(self->Params,"USER");
00330 
00331  int authUser = atoi(GetFieldValue(self->Config,"AUTHUSER"));
00332  int authSpace = atoi(GetFieldValue(self->Config,"AUTHSPACE"));
00333 
00334  if (cookie)
00335  {
00336   if (*cookie)
00337    clist = ReadPairedString(*cookie,';',0);
00338 
00339   *cookie = 0;
00340  }
00341 
00342  if (!strcmp(directory,".")) directory = "";
00343 
00344  if (*username && authUser)
00345  {/* logging in to a user account. generate a new session */
00346    char s[32];
00347    int i = time(0) ^ 0x5a5a5a5a;
00348    /* invert the bit order and use decimal notation */
00349    i = (i&0x00ffff00) | ((i & 0xff000000) >> 24) | ((i & 0x000000ff) << 24);
00350    sprintf(s,"%u",i);
00351    /* username limited to 32 bytes */
00352    ret = VerifyUser(self,directory, username, s, password);
00353    if (ret && cookie)
00354    {/* erase old workspace passwords. new cookie: user=username; session=s; */
00355     char x[128];
00356     sprintf(x,"Set-Cookie: USER=%s;\nSet-Cookie: SESSION=%s;\nSet-Cookie: PASSWORD=;",username,s);
00357     *cookie = strdup(x);
00358    }
00359  }
00360 
00361  if (!ret && *password && authSpace)
00362  {
00363   ret = VerifyPassword(self, directory, password);
00364   if (ret && cookie)
00365   {
00366    char x[128], *y, *z;
00367    /* preserve existing username/session */
00368    sprintf(x,"Set-Cookie: USER=%s;\nSet-Cookie: SESSION=%s;\nSet-Cookie: PASSWORD=",
00369              GetFieldValue(clist,"USER"),
00370              GetFieldValue(clist,"SESSION"));
00371    y = strdup3(x,password,",");
00372    z = GetFieldValue(clist,"PASSWORD");
00373    if (HasToken(z,password,0))
00374    {
00375     *cookie = y;
00376    }
00377    else
00378    {
00379     z = strdup3(y,z,"");
00380     *cookie = z;
00381    }
00382    free(y);
00383   }
00384  }
00385 
00386  RenameField(self->Params, "AUTHENTICATION",0);
00387  if (ret) return ret;
00388 
00389  if (clist)
00390  {
00391   if (authUser)
00392   {
00393    ret = VerifyUser(self, directory, GetFieldValue(clist,"USER"), GetFieldValue(clist,"SESSION"), "");
00394    if (ret && !*username)
00395     SetFieldValue(self->Params,"USER",GetFieldValue(clist,"USER"));
00396   }
00397   if (!ret && authSpace)
00398     ret = VerifyPassword(self, directory, GetFieldValue(clist,"PASSWORD"));
00399  }
00400 
00401  DeleteNVP(clist);
00402  return ret;
00403 }
00404 
00405 char* RelativeName(char* directory,char* name)
00406 {
00407   if (*directory)
00408     return strdup3(directory,"/",name);
00409   else
00410     return strdup(name);
00411 }
00412 
00413 void ProjectUpdate(AdminInfo *self,char* directory,char* project)
00414 {
00415  CGINameValue* ini, *Params = self->Params;
00416  char iniName[MAXPATH+5];
00417  char* name=RelativeName(directory,project);
00418  char* section=GetSetting(self->Params,"SECTION","DATABASE");
00419 
00420  ExpandLocalPath(self->argv0,iniName,name,".ini");
00421  ini = ReadINIFileSection(iniName,section,ListLength(Params));
00422  if (ini)
00423  {
00424   size_t x;
00425   for (x=0; Params[x].name; x++)
00426   {
00427    if (Params[x].name)
00428     if (!HasTokenI(systemFields,Params[x].name,0))
00429      SetFieldValue(ini,Params[x].name,Params[x].value);
00430   }
00431  }
00432 
00433  WriteINIFileSection(iniName,section,ini);
00434 
00435  CGIFREE(name);
00436  DeleteNVP(ini);
00437 }
00438 
00439 void RecurseDirectories(char* directory,STREAM htmlout,char* format, char* replace)
00440 {
00441  DIR* d;
00442  struct stat info;
00443  char* name, *c;
00444 
00445  name = directory;
00446  if (!*name) name = ".";
00447  d = opendir(name);
00448  while (d)
00449  {
00450   struct dirent* f = readdir(d);
00451   if (!f) break;
00452   if (f->d_name[0] == '.') continue; /* hidden or system file */
00453   name = RelativeName(directory,f->d_name);
00454 
00455   if (stat(name,&info))
00456   {
00457    free(name);
00458    continue;
00459   }
00460 
00461   if (info.st_mode & S_IFREG)
00462   {
00463    free(name);
00464    continue;
00465   }
00466 
00467   c = strdup3(name,SLASH,"cgi.ini");
00468   if (stat(c,&info))
00469   {
00470    free(c);
00471    continue;
00472   }
00473   free(c);
00474   c = format;
00475   while (c)
00476   {
00477    char* d = (char*)stristr(c,replace);
00478    if (d)
00479    {
00480     HTMLWriteL(htmlout,c,(d-c));
00481     HTMLWrite(htmlout,name);
00482     d += strlen(replace);
00483    }
00484    else
00485    {
00486     HTMLWrite(htmlout,c);
00487     d=0;
00488    }
00489 
00490    c=d;
00491   }
00492   RecurseDirectories(name,htmlout,format,replace);
00493   free(name);
00494  }
00495 
00496  if (d) closedir(d);
00497 }
00498 
00500 static char* JSListWorkspaces(ScriptEnvironment* Env, char* cmd, int argc, char** argv, CGINameValue* Params)
00501 {
00502  char* f ="$";
00503  char* g ="$";
00504  if (argc) f = argv[0];
00505  if (argc > 2) g = argv[1];
00506  RecurseDirectories("",Env->htmlout,f,g);
00507  return 0;
00508 }
00509 
00511 static char* JSSendMail(ScriptEnvironment* Env, char* cmd, int argc, char** argv, CGINameValue* Params)
00512 {
00513  if (!Env->config) return 0;
00514  if (argc < 3) return 0;
00515  {
00516    char* server   = GetSetting(Env->config,"EMAILSERVER","");
00517    char* profile  = GetSetting(Env->config,"EMAILPROFILE","Windows Messaging Settings");
00518    char* name     = GetSetting(Env->config,"EMAILNAME","");
00519    char* password = GetSetting(Env->config,"EMAILPWD","");
00520 
00521    SendMail(argv[0],argv[1],argv[2], server, profile, name, password);
00522  }
00523  return 0;
00524 }
00525 
00526 
00527 static ScriptFunction AdminFunctions[] =
00528    {
00529     {"listDirectories",2,(ScriptFunctionCall)*JSListWorkspaces},
00530     {0,0,0}
00531    };
00532 
00533 void AdminPrintPage(AdminInfo* self,char* iniName,FILE* source)
00534 {
00535   char section[MAXPATH];
00536   CGINameValue* ini=0;
00537 
00538   while (!feof(source))
00539   {
00540    *section = 0;
00541 
00542    if (ini)
00543      RunReportF(self->argv0,self->htmlout,source,ini,self->Params,0,1,"%load",section,AdminFunctions);
00544    else
00545      RunReportF(self->argv0,self->htmlout,source,self->Params,0,0,1,"%load",section,AdminFunctions);
00546 
00547    if (ini) DeleteNVP(ini);
00548 
00549    swapchars(section,'%',0);
00550 
00551    if (*section)
00552       ini = ReadINIFileSection(iniName,section,0);
00553    else
00554       ini = 0;
00555   }
00556 }
00557 
00558 int AdminRunScript(AdminInfo *self,CGINameValue* data,char* page)
00559 {
00560  if (page)
00561   if (*page)
00562  {
00563  int ret;
00564  FILE* script = OpenPage(self->argv0,page);
00565  ScriptFunction Functions[] =
00566  {
00567   {"print",10,(ScriptFunctionCall)*JSPrint},
00568   {"write",10,(ScriptFunctionCall)*JSPrint},
00569   {"eval",1,(ScriptFunctionCall)*JSEval},
00570   {"tofixed",2,(ScriptFunctionCall)*JStoFixed},
00571   {"sendmail",3,(ScriptFunctionCall)*JSSendMail},
00572   {"runReport",8,(ScriptFunctionCall)*JSReport},
00573   {"number",1,(ScriptFunctionCall)*JSToNumber},
00574   {"toNumber",1,(ScriptFunctionCall)*JSToNumber},
00575   {"random",1,(ScriptFunctionCall)*JSRandom},
00576   {"subStr",3,(ScriptFunctionCall)*JSsubstr},
00577   {"indexOf",4,(ScriptFunctionCall)*JSIndexOf},
00578   {"length",1,(ScriptFunctionCall)*JSstrlen},
00579   {"listDirectories",2,(ScriptFunctionCall)*JSListWorkspaces},
00580  {0,0,0}};
00581 
00582  ScriptEnvironment Global;
00583  memset(&Global,0,sizeof(Global));
00584  Global.htmlout   = self->htmlout;
00585  Global.Functions = Functions;
00586  Global.argv0     = self->argv0;
00587  Global.config    = self->Config;
00588  if (script == NULL) return 1; /* OK */
00589 
00590  ret = RunScript(&Global,script,data?data:self->Config);
00591 
00592  CGIFCLOSE(script);
00593  return ret;
00594  }
00595  return 0;
00596 }
00597 
00598 int UserAdd(AdminInfo* self,char* user)
00599 {
00600  FILE *f;
00601  char fname[MAXPATH];
00602  CGINameValue* ini;
00603  struct stat info;
00604 
00605  ExpandLocalPath(self->argv0,fname,"admin" "/", user);
00606  strcat(fname,".ini");
00607  if (!stat(fname,&info))
00608    return 0; /* already exists */
00609 
00610  f = fopen(fname,"wt");
00611  if (f)
00612  {
00613   fwrite("[USER]\nACTIVE=0\n",1,7,f);
00614   fclose(f);
00615   return 1;
00616  }
00617  return 0;
00618 }
00619 
00620 void UserUpdate(AdminInfo* self,char* user,char * fields,char* page)
00621 {
00622  FILE *f;
00623  char fname[MAXPATH];
00624  CGINameValue* ini;
00625  size_t x;
00626 
00627  ExpandLocalPath(self->argv0,fname,"admin" "/", user);
00628  strcat(fname,".ini");
00629  ini = ReadINIFileSection(fname,"USER",16);
00630 
00631  if (!ini) /* new user */
00632   return;
00633 
00634  for (x=0; self->Params[x].name; x++)
00635   {
00636    if (!*self->Params[x].name)
00637     continue;
00638 
00639    if (HasTokenI(systemFields,self->Params[x].name,0))
00640     continue;
00641 
00642    if (fields)
00643     if (!HasTokenI(fields,self->Params[x].name,0))
00644      continue;
00645 
00646    SetFieldValue(ini,self->Params[x].name,self->Params[x].value);
00647   }
00648 
00649  AdminRunScript(self,ini,page);
00650  if (!atoi(GetFieldValue(self->Params,"ERROR")))
00651  {
00652    WriteINIFileSection(fname,"USER",ini);
00653  }
00654 
00655  DeleteNVP(ini);
00656 }
00657 
00658 void UserAddSpace(AdminInfo* self,char* user,char * directory)
00659 {
00660  FILE *f;
00661  char fname[MAXPATH];
00662  CGINameValue* ini;
00663  char* x;
00664  ExpandLocalPath(self->argv0,fname,"admin" "/", user);
00665  strcat(fname,".ini");
00666  ini = ReadINIFileSection(fname,"USER",16);
00667 
00668  if (!ini) /* new user */
00669   return;
00670 
00671  x = GetFieldValue(ini,"SPACES");
00672  x = strdup3(x,",",directory);
00673  SetFieldValue(ini,"SPACES",x);
00674  free(x);
00675 
00676  WriteINIFileSection(fname,"USER",ini);
00677  DeleteNVP(ini);
00678 }
00679 void User(AdminInfo* self,char* user, char* page)
00680 {
00681   char fname[MAXPATH];
00682   CGINameValue* ini;
00683   FILE* source = OpenPage(self->argv0,page);
00684   if (!source) return;
00685 
00686   ExpandLocalPath(self->argv0,fname,"admin" "/", user);
00687   strcat(fname,".ini");
00688   AdminPrintPage(self,fname,source);
00689 
00690 /*  RunReportF(self->argv0,self->htmlout,source,self->Params,0,0,1,"admin",AdminFunctions);
00691 
00692   ini = ReadINIFileSection(fname,"USER",0);
00693 
00694   if (ini && source)
00695   {
00696    RunReportF(self->argv0,self->htmlout,source,ini,self->Params,0,1,0,AdminFunctions);
00697    fclose(source);
00698   }
00699 
00700   DeleteNVP(ini);
00701 */
00702 }
00703 
00704 int SpaceAdd(AdminInfo* self,char* directory, char* name, char* page)
00705 {
00706  FILE *f;
00707  char fname[MAXPATH];
00708  CGINameValue* ini;
00709  struct stat info;
00710  int ret = 0;
00711  char* pwd = GetFieldValue(self->Params,"PASSWORD");
00712  if (!*pwd)
00713   {
00714    FILE* source = OpenPage(self->argv0,page);
00715    if (source)
00716    {
00717     RunReportF(self->argv0,self->htmlout,source,self->Params,0,0,1,0,0,AdminFunctions);
00718     fclose(source);
00719    }
00720    return 2;
00721   }
00722 
00723  directory = RelativeName(directory,name);
00724  ExpandLocalPath(self->argv0,fname,directory,"/" "cgi.ini");
00725 
00726  if (stat(fname,&info))
00727  {
00728    mkdir(directory);
00729    f = fopen(fname,"wt");
00730    if (f)
00731    {
00732     fwrite("[admin]\nLOGLEVEL=0\nPASSWORD=\n",1,29,f);
00733     fclose(f);
00734     ret = 1;
00735    }
00736  }
00737  free(directory);
00738  return ret;
00739 }
00740 
00741 void Space(AdminInfo* self,char* directory,char* page)
00742 {
00743   char fname[MAXPATH];
00744   FILE* source = OpenPage(self->argv0,page);
00745   if (!source) return;
00746 
00747   if (!*directory) directory=".";
00748   ExpandLocalPath(self->argv0,fname,directory, "/" "cgi.ini");
00749 
00750   AdminPrintPage(self,fname,source);
00751 /*  RunReportF(self->argv0,self->htmlout,source,ini,self->Params,0,1,0,AdminFunctions); */
00752   fclose(source);
00753 }
00754 
00755 void SpaceUpdate(AdminInfo* self,char* directory,char * fields,char* page)
00756 {
00757  FILE *f;
00758  char fname[MAXPATH];
00759  CGINameValue* ini;
00760  char* pwd;
00761  size_t x;
00762  char* section=GetSetting(self->Params,"SECTION","admin");
00763 
00764 
00765  if (!*directory) directory=".";
00766  ExpandLocalPath(self->argv0,fname,directory, "/" "cgi.ini");
00767  ini = ReadINIFileSection(fname,section,16); /* leave room for new entries */
00768 
00769  if (!ini) /* new user */
00770   return;
00771 
00772  for (x=0; self->Params[x].name; x++)
00773   {
00774    if (!*self->Params[x].name)
00775     continue;
00776 
00777    if (HasTokenI(systemFields,self->Params[x].name,0))
00778     continue;
00779 
00780    if (fields)
00781     if (!HasTokenI(fields,self->Params[x].name,0))
00782      continue;
00783 
00784    SetFieldValue(ini,self->Params[x].name,self->Params[x].value);
00785   }
00786 
00787  AdminRunScript(self,ini,page);
00788  if (!atoi(GetFieldValue(self->Params,"ERROR")))
00789  {
00790    WriteINIFileSection(fname,section,ini);
00791  }
00792 
00793  DeleteNVP(ini);
00794 }
00795 
00796 void Project(AdminInfo *self,char* directory,char* project)
00797 {
00798  char fname[MAXPATH+5];
00799  FILE* source = OpenPage(self->argv0,"project.html");
00800  char* name;
00801  if (!source) return;
00802 
00803  name=RelativeName(directory,project);
00804  ExpandLocalPath(self->argv0,fname,name,".ini");
00805  free(name);
00806 
00807  AdminPrintPage(self,fname,source);
00808  /*
00809  RunReportF(self->argv0,self->htmlout,source,self->Params,0,0,1,"database",AdminFunctions);
00810 
00811  ini = ReadINIFileSection(iniName,"DATABASE",0);
00812  RunReportF(self->argv0,self->htmlout,source,ini,self->Params,0,1,"access",AdminFunctions);
00813  DeleteNVP(ini);
00814  ini = ReadINIFileSection(iniName,"ACCESS",0);
00815  RunReportF(self->argv0,self->htmlout,source,ini,self->Params,0,1,0,AdminFunctions);
00816  DeleteNVP(ini);*/
00817  fclose(source);
00818 }
00819 
00820 int GetProjectExtra(AdminInfo* self,char* name)
00821 {
00822  char rName[MAXPATH];
00823  struct stat info;
00824  char* dbname = strdup(name);
00825  char* c = (char*)stristr(dbname,".ini");
00826  if (c)
00827  {
00828   char temp[32];
00829   *c =0;
00830   ExpandLocalPath(self->argv0,rName,dbname,".respcount");
00831   if (!stat(rName,&info)) /* response count file */
00832     DoSetValue(self->Params,"LASTSAVEDATE",ctime(&info.st_mtime));
00833   sprintf(temp,"%d",GetRespcount(self->argv0,dbname));
00834   DoSetValue(self->Params,"RESPONSES",temp);
00835  }
00836  free(dbname);
00837  return (c != NULL);
00838 }
00839 
00840 void Index(AdminInfo *self,char* directory)
00841 {
00842  DIR* d;
00843  struct stat info;
00844  char* name;
00845  CGINameValue* ini;
00846  char iniName[MAXPATH];
00847  int dirstart=-1,filestart=-1,footerstart=0;
00848 
00849  FILE* source = OpenPage(self->argv0,"projects.html");
00850  if (!source) return;
00851 
00852  RunReportF(self->argv0,self->htmlout,source,self->Params,0,0,1,"directory",0,AdminFunctions);
00853  dirstart = ftell(source);
00854  ReadUntilWordS(source,0,"<file>");
00855  filestart= ftell(source);
00856  ReadUntilWordS(source,0,"</file>");
00857  footerstart = ftell(source);
00858 
00859  name = directory;
00860  if (!name || !*name) name = ".";
00861  d = opendir(name);
00862 
00863  while (d)
00864  {
00865   struct dirent* f = readdir(d);
00866   if (!f) break;
00867   if (f->d_name[0] == '.') continue; /* hidden or system file */
00868 
00869   name = RelativeName(directory,f->d_name);
00870 
00871   ExpandLocalPath(self->argv0,iniName,name,0);
00872   if (!stat(iniName,&info))
00873   {
00874    if (!(info.st_mode & S_IFREG) && dirstart > 0)
00875    {/* directory */
00876     ExpandLocalPath(self->argv0,iniName,name,"/" "cgi.ini");
00877     ini = ReadINIFileSection(iniName,"admin",0);
00878     if (ini)
00879     {
00880      DoSetValue(self->Params, "NAME", name);
00881      fseek(source,dirstart,0);
00882      RunReportF(self->argv0,self->htmlout,source,ini,self->Params,0,1,"/directory",0,AdminFunctions);
00883      DeleteNVP(ini);
00884     }
00885    }
00886    else if (stristr(f->d_name,".ini") && filestart > 0)
00887    {/* file */
00888     ExpandLocalPath(self->argv0,iniName,name,0);
00889 
00890     if (info.st_ctime)
00891      DoSetValue(self->Params,"CREATIONDATE",ctime(&info.st_ctime));
00892 
00893     ini = ReadINIFileSection(iniName,"DATABASE",0);
00894     if (ini)
00895     {
00896      fseek(source,filestart,0);
00897      GetProjectExtra(self,name);
00898      name=strdup(f->d_name);
00899      *stristr(name,".ini") = 0;
00900      DoSetValue(self->Params, "NAME", name);
00901      RunReportF(self->argv0,self->htmlout,source,ini,self->Params,0,1,"/file",0,AdminFunctions);
00902      DeleteNVP(ini);
00903     }
00904    }
00905   }
00906   free(name);
00907  }
00908 
00909  fseek(source,footerstart,0);
00910  RunReportF(self->argv0,self->htmlout,source,self->Params,0,0,0,0,0,AdminFunctions);
00911  fclose(source);
00912 
00913  if (d) closedir(d);
00914 }
00915 
00916 void UserList(AdminInfo *self)
00917 {
00918  DIR* d;
00919  struct stat info;
00920  char* name=0, *c;
00921  CGINameValue* ini;
00922  char iniName[MAXPATH];
00923  int pos;
00924 
00925  FILE* source = OpenPage(self->argv0,"users.html");
00926 
00927  if (!source)
00928   return;
00929 
00930  RunReportF(self->argv0,self->htmlout,source,self->Params,0,0,1,"user",0,AdminFunctions);
00931  pos = ftell(source);
00932  d = opendir("admin");
00933  // look for all .ini files in admin, and report on [USER] sections
00934  while (d)
00935  {
00936   struct dirent* f = readdir(d);
00937   if (!f) break;
00938   if (f->d_name[0] == '.') continue; /* hidden or system file */
00939 
00940   if (stristr(f->d_name,".ini"))
00941   {
00942 
00943     ExpandLocalPath(self->argv0,iniName,"admin" "/",f->d_name);
00944     ini = ReadINIFileSection(iniName,"USER",16);
00945     if (ini)
00946     {
00947      name = strdup(f->d_name);
00948      *stristr(name,".ini") = 0;
00949      DoSetValue(self->Params, "NAME", name);
00950 
00951      if (!stat(iniName,&info))
00952      {
00953       if (info.st_ctime)
00954        DoSetValue(self->Params,"CREATIONDATE",ctime(&info.st_ctime));
00955       if (info.st_mtime)
00956        DoSetValue(self->Params,"LASTSAVEDATE",ctime(&info.st_mtime));
00957      }
00958 
00959      RunReportF(self->argv0,self->htmlout,source,ini,self->Params,0,1,"/user",0,AdminFunctions);
00960      fseek(source,pos,0);
00961      DeleteNVP(ini);
00962      free(name);
00963     }
00964 
00965   }
00966  }
00967  if (source)
00968  {
00969   ReadUntilWordS(source,0,"</user>");
00970   RunReportF(self->argv0,self->htmlout,source,self->Params,0,0,1,0,0,AdminFunctions);
00971   fclose(source);
00972  }
00973  if (d) closedir(d);
00974 }
00975 
00976 int SendImage(AdminInfo *self,char* image)
00977 {
00978  char fname[MAXPATH];
00979  char header[1024];
00980  if (image[strcspn(image,"\\/")] || strstr(image,".."))
00981   return 0; /* invalid name */
00982 
00983  ExpandLocalPath(self->argv0,fname,"admin" "/",image);
00984 
00985  if (stristr(image,".png"))
00986   SendCGIHeader(self->htmlout,"Content-Type: image/png\n\n");
00987  else if (stristr(image,".gif"))
00988   SendCGIHeader(self->htmlout,"Content-Type: image/gif\n\n");
00989  else if (stristr(image,".ico"))
00990   SendCGIHeader(self->htmlout,"Content-Type: image/x-icon\n\n");
00991  else
00992   return 0;
00993 
00994  return HTMLWriteFile(self->htmlout,fname);
00995 }
00996 
00997 int ShowAdmin(AdminInfo *self,char*name,char*page)
00998 {
00999 /* log in as administrator */
01000  if (!strnicmp(page,"USER",4))
01001  {
01002   int i = strcspn(name,"\\/.");
01003   if (name[i] || i > 32)
01004     return 4; /* too long or invalid character */
01005  }
01006 
01007  if (!stricmp(page,"USER") && *name)
01008   {
01009    User(self,name,"user.html");
01010    return 3;
01011   }
01012 
01013  if (!stricmp(page,"USERADD"))
01014   {
01015    if (UserAdd(self,name))
01016    {
01017     UserUpdate(self,name,0,0);
01018     User(self,name,"user.html");
01019     return 3;
01020    }
01021   }
01022  else if (!stricmp(page,"USERUPDATE"))
01023   {
01024    UserUpdate(self,name,0,"user.js");
01025    return 2;
01026   }
01027 
01028  return 0;
01029 }
01030 
01031 
01038 int ShowPage(AdminInfo *self,char*directory,char*name,char*page)
01039 {
01040  char * user = GetFieldValue(self->Params,"USER"); /* current user name */
01041  int i = strcspn(user,"\\/.");
01042  if (user[i] || i > 32)
01043    return 4; /* too long or invalid character */
01044 
01045  if (!strnicmp(page,"PASSWORD",8)) /* log in as admin or as yourself */
01046  {
01047   if (!*user)
01048     return 4; /* not logged in */
01049 
01050   if (!stricmp(page,"PASSWORD")) /* change my password or info*/
01051   {
01052    User(self,user,"password.html");
01053    return 3;
01054   }
01055   else if (!stricmp(page,"PASSWORDUPDATE")) /* change my password */
01056   {
01057    UserUpdate(self,user,"DISPLAY,PASSWORD,EMAIL","user.js");
01058    SetFieldValue(self->Params,"DIRECTORY",0);
01059    return 1;
01060   }
01061  }
01062 
01063  if (!stricmp(page,"PROJECT") && *name)
01064  {
01065   Project(self,directory,name);
01066   return 3;
01067  }
01068  else if (!stricmp(page,"PROJECTUPDATE")&& *name)
01069  {
01070   ProjectUpdate(self,directory,name);
01071   return 1;
01072  }
01073  else if (!stricmp(page,"SPACE"))
01074  {
01075   Space(self,directory,"space.html");
01076   return 3;
01077  }
01078  else if (!stricmp(page,"SPACEADD"))
01079  {
01080   if (!strnicmp(directory,"admin",5))
01081    return 4; /* can't create directories in the admin section */
01082 
01083   switch (SpaceAdd(self,directory,name,"spaceadd.html"))
01084   {
01085    case 1:
01086    {
01087     char * c = RelativeName(directory,name);
01088     SetFieldValue(self->Params,"DIRECTORY",c);
01089     SpaceUpdate(self,c,"LOGLEVEL,PASSWORD,DISPLAY","space.js");
01090     Space(self,c,"space.html");
01091     if (*user) /* add myself to the new directory */
01092       UserAddSpace(self,user,c);
01093     else
01094       SetFieldValue(self->Params,"AUTHENTICATION",GetFieldValue(self->Params,"PASSWORD"));
01095     free(c);
01096    }
01097    case 2: return 3;
01098   }
01099  }
01100  else if (!stricmp(page,"SPACEUPDATE"))
01101  {
01102   SpaceUpdate(self,directory,"LOGLEVEL,PASSWORD,DISPLAY","space.js");
01103   return 1;
01104  }
01105 
01106 
01107  return 0;
01108 }
01109 
01110 void Error(AdminInfo* self)
01111 {
01112  HTMLWrite(self->htmlout,"<HTML><body><h1>Error</h1><hr><pre>");
01113  DebugShowNVP(self->htmlout,self->Params);
01114 }
01115 
01116 int CGImain(char * argv0,CGINameValue* Params,STREAM htmlout)
01117 {
01118  char * directory = GetFieldValue(Params,"DIRECTORY");
01119  char * name      = GetFieldValue(Params,"NAME");
01120  char * page      = GetFieldValue(Params,"PAGE");
01121  char * image     = GetFieldValue(Params,"IMAGE");
01122  char * cookie    = GetEnvironment(htmlout,"HTTP_COOKIE");//"USER=newuser; SESSION=; PASSWORD=5678," ; //
01123  char fname[MAXPATH];
01124  int ret, r2;
01125  AdminInfo Self;
01126  Self.argv0 = argv0;
01127  Self.Config = 0;
01128  Self.Params = Params;
01129  Self.htmlout= htmlout;
01130 
01131  if (strchr(name,'/') || strchr(name,'\\')
01132      || stristr(name,".ini") ||
01133      !stricmp(page,"LOGOUT"))
01134  {/* access error -- kick 'em out! */
01135     SendCGIHeader(htmlout,"Set-Cookie: USER=;\nSet-Cookie: SESSION=;\nSet-Cookie: PASSWORD=;\n" CGI_DEFAULT_HEADER);
01136     Self.Params = 0;
01137     Login(&Self);
01138     return 0;
01139  }
01140 
01141  if (!strnicmp(page,"USER",4) && !*directory)
01142   directory = "admin";
01143 
01144  if (*image)
01145  {
01146   SendImage(&Self,image);
01147   return 0;
01148  }
01149 
01150  ExpandLocalPath(argv0,fname,"admin",SLASH "cgi.ini");
01151  Self.Config= ReadINIFileSection(fname,"admin",0);
01152 
01153  ret = Authenticate(&Self,directory,&cookie);
01154  if (ret == 2 && !*page && !*directory) /* new login, go to the home directory */
01155    directory = GetFieldValue(Params,"DIRECTORY");
01156 
01157  if (ret) /* login valid, maybe write a new cookie */
01158  {
01159   if (cookie)
01160   {
01161    char* header = strdup3(cookie, "\n", CGI_DEFAULT_HEADER);
01162    SendCGIHeader(htmlout,header);
01163    free(header);
01164    free(cookie);
01165   }
01166   else
01167      SendCGIHeader(htmlout,0);
01168  }
01169  else
01170  {
01171   if (*directory) SetFieldValue(Self.Params,"DIRECTORY",directory);
01172   SendCGIHeader(htmlout,0);
01173   Login(&Self);
01174   goto atexit;
01175  }
01176  /* must be logged in! */
01177 
01178  ret = 0;
01179  r2 = 0;
01180  if (!stricmp(directory,"admin"))
01181  {
01182   ret = ShowAdmin(&Self,name,page);
01183   r2 = 2;
01184  }
01185 
01186  if (!ret)
01187  {
01188   ret =ShowPage(&Self,directory,name,page);
01189   if (!ret) ret = r2;
01190  }
01191 
01192  switch (ret)
01193  {
01194   case 0:
01195   case 1: Index(&Self,directory); break;
01196   case 2: UserList(&Self);
01197   case 3: break;
01198   default: Error(&Self);
01199  }
01200 
01201  atexit:
01202  DeleteNVP(Self.Config);
01203  return 0;
01204 }
01205 
01206 
01207 


Raosoft, Inc.
Raosoft EZReport, EZSurvey, InterForm, RapidReport, Raosoft, and SurveyWin are registered trademarks of Raosoft, Inc. Page contents © 1996-2007 by Raosoft, Inc. You may use and modify this file for your own use, but may not distribute it or derivative works without the prior written consent of Raosoft, Inc. This software is provided "as is," and Raosoft makes no warranty, express or implied, of fitness for a particular application. Every measure has been taken to anticipate risks inherent to computer networks, but we cannot guarantee safety or reliability of this program in every situation.
Tel: 206-525-4025 (US) Email: raosoft@raosoft.com
http://www.raosoft.com/