cgi_data.c

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /* cgi_data.c © Copyright 1998-2005 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 /* If you choose to share your modifications with Raosoft, Inc. the company   */
00008 /* will attempt to incorporate them into future versions of this file.        */
00009 /*                                                                            */
00010 /* This software is provided "as is," and Raosoft makes no warranty, express  */
00011 /* or implied, of fitness for a particular application. Every measure has been*/
00012 /* taken to anticipate risks inherent to computer networks, but we cannot     */
00013 /* guarantee safety or reliability of this program in every situation.        */
00014 /*                                                                            */
00015 /******************************************************************************/
00016 
00017 #include "cgi.h"
00018 
00019 #ifndef XP_WIN
00020 #ifndef AIX3
00021 #include <sys/file.h>
00022 #endif
00023 
00024 #endif
00025 
00026 int SkipLines(FILE * in, size_t lines)
00027 {
00028  char c;
00029  int skipped =0;
00030  while (lines && fread(&c,1,1,in)>0 )
00031  {
00032   if (c == '\n') {lines--; skipped++;}
00033  }
00034  if (lines) return 0;
00035  return skipped;
00036 }
00037 
00042 int DoesFileMatchForm(CGINameValue * data, CGINameValue* hdr)
00043 {
00044  int x;
00045  if (hdr == NULL) return 0;
00046  for (x=0; (data[x].name != NULL); x++)
00047   {
00048    if (data[x].name[0] == 0) continue;
00049    if (data[x].name[0] == '_') continue;
00050 
00051    if (HasTokenI("HOST,DATE,TIME",data[x].name,0)) continue;
00052    if (data[x].value == 0) continue;
00053    if (data[x].value[0] == 0) continue;
00054 
00055    /* don't require fields that we add to save */
00056    if (GetField(hdr, data[x].name) == NULL)
00057    {
00058     LogError("\nCGI_DATA: data file missing the field: ");
00059     LogError(data[x].name);
00060     return 0;
00061    }
00062   }
00063  return 1;
00064 }
00065 
00069 CGINameValue* _loaddbheader(DATABASE *f,int extra)
00070 {
00071  char name[MAXBUF];
00072  int c;
00073  size_t x;
00074  size_t fieldcount = 0;
00075  CGINameValue*v, *i;
00076 
00077    do {
00078      c = ReadUntilChar(f,name,MAXBUF,"\t\n",'\r');
00079      fieldcount++;
00080 
00081      if (c == EOF) /* the header needs to be LF terminated! */
00082        {
00083         CGIFCLOSE(f);
00084         return 0;
00085        }
00086    } while (c != '\r' && c != '\n');
00087 
00088  if (fieldcount == 1 && *name == 0) return 0;
00089 
00090 /* create a structure to hold the values  */
00091  v = NewNVP(fieldcount+extra);
00092  i = v;
00093 
00094  for (x = fieldcount; x < fieldcount + extra; x++)
00095  {v[x].name = strdup(""); v[x].value = strdup(""); }
00096 
00097 /* reopen the file at the beginning       */
00098 #ifdef __WINCE__
00099  fseek(f,0,SEEK_SET);
00100 #else
00101  rewind(f);
00102 #endif
00103 
00104 /* read the fieldnames into the structure */
00105   do {
00106      char * d;
00107      c = ReadUntilChar(f,name,MAXBUF,"\t\n",'\r');
00108      d = strchr(name,'\r');
00109      if (d) *d = 0; /* just in case we opened it in binary mode */
00110 
00111      i->name = strdup((name[0] == '#') ? name+1 : name);
00112 
00113      i++;
00114      fieldcount --;
00115      if (c == EOF)
00116        {
00117         CGIFCLOSE(f);
00118         DeleteNVP(v);
00119         return 0;
00120        }
00121    } while (c != '\r' && c != '\n' && fieldcount);
00122 
00123  return v;
00124 }
00125 
00126 
00127 void WriteXML(FILE* f,CGINameValue* data)
00128 {
00129  int i;
00130  char * currentchild = NULL;
00131  int currentitem = -1;
00132 
00133  fprintf(f,"<TRANSACTION>");
00134 
00135  for(i=0;data[i].name;i++) /* skip host, date, time */
00136   {
00137    char * c;
00138    int inchild = 0;
00139    char* name;
00140    if (!data[i].name[0]) continue;
00141    if (data[i].name[0] == '_') continue;
00142 
00143    name = data[i].name;
00144    c = strchr(name,'_');
00145 
00146    if (c)
00147     if (strchr(c+2,'_'))
00148      if (strchr("1234567890",c[1])) /* item_1_name */
00149       {
00150        int thisitem;
00151        int newobj = 0;
00152        char* newchild = strdup(name);
00153 
00154        inchild = 1;
00155        c = strchr(newchild,'_');
00156 
00157        thisitem = atoi(c+1);
00158 
00159        name = strchr(c+2,'_');
00160        if (name) name++;
00161 
00162        c[0] = 0;
00163 
00164        if (thisitem != currentitem || stricmp(currentchild,newchild))
00165        {
00166         newobj = 1;
00167         currentitem = thisitem;
00168        }
00169 
00170        if (newobj && currentchild) fprintf(f,"</%s>\n",currentchild);
00171 
00172        if (name)
00173     {
00174      if (currentchild) CGIFREE(currentchild);
00175          currentchild = newchild;
00176          if (newobj) fprintf(f,"<%s id=%d>\n",currentchild,thisitem);
00177         }
00178        else name=data[1].name;
00179       }
00180 
00181    if (inchild == 0 && currentchild)
00182      {
00183        fprintf(f,"</%s>\n",currentchild);
00184        if (currentchild) CGIFREE(currentchild);
00185        currentchild = NULL;
00186 
00187      }
00188 
00189    fprintf(f,"<%s>%s</%s>\n",name,data[i].value,name);
00190 
00191   }
00192 
00193  if (currentchild) printf("</%s>\n",currentchild);
00194  if (currentchild) CGIFREE(currentchild);
00195  fprintf(f,"</TRANSACTION>\n");
00196 }
00197 
00198 int SaveDataToXML(CGINameValue* data,char* filename,int*pos)
00199 {
00200  FILE* f = NULL;
00201 #ifndef __WINCE__
00202  int fh;
00203 #endif
00204 #ifdef XP_POSIX
00205  static struct flock myLock ;
00206 #endif
00207 #if defined(XP_WIN) && !defined(VPWSCGI)
00208  HANDLE Mutex;
00209  char Mutex_name[MAXPATH+1];
00210 #endif
00211 
00212 /*
00213 #ifndef __WINCE__
00214  if (access(filename,2)) return 6;
00215 #endif
00216 */
00217 
00218 #if defined(XP_WIN) && !defined(VPWSCGI)
00219  strncpy(Mutex_name,filename,MAXPATH);
00220  Mutex_name[MAXPATH] = 0;
00221  swapchars(Mutex_name, '\\', '/');
00222 
00223  Mutex = CreateMutex(0,FALSE,Mutex_name);
00224 
00225  /* wait up to 20 seconds */
00226  if (Mutex) if (WaitForSingleObject(Mutex,20000) == WAIT_TIMEOUT)
00227   {
00228    CloseHandle(Mutex);
00229    return 23;
00230   }
00231 #endif
00232 
00233 #ifdef __WINCE__
00234  f = CGIFOPEN(filename,"ab");
00235 #else
00236  fh = open(filename,O_WRONLY|O_APPEND);
00237  if (fh != -1)
00238   {
00239    f = fdopen(fh,"ab");
00240   }
00241 #endif
00242 
00243  if (!f) return 8;
00244 
00245 /* Wait for a file lock to become available */
00246 #ifdef XP_POSIX
00247     myLock.l_type = F_WRLCK ;
00248     myLock.l_start = 0 ;
00249     myLock.l_whence = SEEK_END ;
00250     myLock.l_len = 0 ;
00251     myLock.l_pid = getpid() ;
00252  fcntl(fh, F_SETLKW, &myLock);
00253 #endif
00254 
00255 
00256  if (pos) *pos = ftell(f);
00257  WriteXML(f,data);
00258 
00259 #ifdef XP_POSIX
00260  myLock.l_type = F_UNLCK;
00261  fcntl(fh, F_SETLKW, &myLock);
00262 #endif
00263 
00264 #if defined(XP_WIN) && !defined(VPWSCGI)
00265 if (Mutex)
00266 {
00267  ReleaseMutex(Mutex);
00268  CloseHandle(Mutex);
00269  }
00270 #endif
00271 
00272  CGIFCLOSE(f);
00273  return 0;
00274 }
00275 
00276 #if 0
00277 CGINameValue* LoadDatabaseHeader(char * filename)
00278 {
00279  FILE * f;
00280  CGINameValue* ret;
00281 /* first, count the number of records */
00282  #ifdef __BORLANDC__
00283  f = CGIFOPEN(filename,"rb+"); /* buffered read */
00284  #else
00285  f = CGIFOPEN(filename,"rb"); /* buffered read, no write */
00286  #endif
00287  if (!f) return 0;
00288  ret = _loaddbheader(f,0);
00289  if (ret) CGIFCLOSE(f);
00290  return ret;
00291 }
00292 #endif
00293 
00294 int DatabaseOpen(char * filename, DATABASE * *database, CGINameValue * *header, int extra, int rw)
00295 {
00296  /*char newname[MAXPATH]; */
00297  DATABASE * file;
00298  int ret;
00299 #ifdef __BORLANDC__
00300  file  = CGIFOPEN(filename,"rb+"); /* open a buffered file in text mode*/
00301 #else
00302  file  = CGIFOPEN(filename,rw ? "rb+" : "rb"); /* open a buffered file in text mode*/
00303 #endif
00304 
00305  if (database) { *database = file; }
00306 
00307  if (file == NULL)
00308   {
00309    if (header) *header = 0;
00310    ret = 0;
00311   }
00312  else
00313   {
00314    CGINameValue * v = _loaddbheader(file,extra);
00315    if (header) *header = v;
00316    ret = v ? 1 : 0;
00317    if (database == NULL) CGIFCLOSE(file);
00318  }
00319  return ret;
00320 }
00321 
00322 int DatabaseReset(DATABASE * database)
00323 {
00324 #ifdef __WINCE__
00325  fseek(database,0,SEEK_SET);
00326 #else
00327  rewind(database);
00328 #endif
00329  return SkipLines(database,1);
00330 }
00331 
00332 int DatabaseFFD(DATABASE * database,int skiprecords)
00333 {
00334  if (skiprecords < 0) return DatabaseReset(database);
00335  if (skiprecords == 0) return 0;
00336  return SkipLines(database,skiprecords);
00337 }
00338 
00339 void ResetList(CGINameValue* v)
00340 {
00341  for (; v->name; v++)
00342   {
00343 #ifdef CGIFREE
00344     CGIFREE(v->value);
00345 #else
00346     if (v->value != NULL)
00347      {
00348       CGIFREE(v->value);
00349       v->value = NULL;
00350      }
00351 #endif
00352   }
00353 }
00354 
00355 int DatabaseDeleteRecord(char * database, int record)
00356 {/* can't use CGIFOPEN for writing, since it would truncate the data */
00357  char c;
00358  int count = 0;
00359 #ifdef __WINCE__
00360  FILE* f = CGIFOPEN(database,"r+");
00361 
00362  if (f == NULL) return 7;
00363 
00364  while (count < record)
00365   {
00366    if (fread(&c,1,1,f) != 1) {CGIFCLOSE(f); return 15;}
00367    if (c == '\n') count ++;
00368   }
00369 
00370  fread(&c,1,1,f);
00371  if (c == '\n') return 0; /* can't delete an empty row, sorry */
00372 
00373  fseek(f,-1,SEEK_CUR);
00374  if (fwrite("#",1,1,f) != 1) {CGIFCLOSE(f); return 15;}
00375  CGIFCLOSE(f);
00376 #else
00377  int f = open(database,O_RDWR);
00378 
00379  if (f < 0) return 7;
00380 
00381  while (count < record)
00382   {
00383    if (read(f,&c,1) != 1) {close(f); return 15;}
00384    if (c == '\n') count ++;
00385   }
00386 
00387  read(f,&c,1);
00388  if (c == '\n') return 0; /* can't delete an empty row, sorry */
00389 
00390  lseek(f,-1,SEEK_CUR);
00391  if (write(f,"#",1) != 1) { close(f);return 15;}
00392  close(f);
00393 #endif
00394  /* deletes a row from the database. Minor data loss. */
00395  /* if the first row is named STATUS, everything will work great! */
00396 
00397  return 0;
00398 }
00399 
00400 void UnfixQuotes(char * c)
00401 {
00402  char * d = c;
00403 
00404  if (!strcmp(c,"\"\""))
00405   {
00406    c[0] = 0;
00407    return;
00408   }
00409 
00410  while (*c)
00411  {
00412   if (c[0] == '\"') c++;
00413   *d = *c;
00414   d++;
00415   if (*c) c++;
00416  }
00417 
00418 }
00419 
00420 
00421 void FixQuotes(CGINameValue* v)
00422 {
00423  int x;
00424  for (x=0; v[x].name; x++)
00425   {
00426    if (v[x].value == NULL) continue;
00427    if (v[x].value[0] == '\"')
00428      {
00429       int a=1,b=0;
00430       while (v[x].value[a])
00431        {
00432         v[x].value[b] = v[x].value[a];
00433         if (v[x].value[a] == '\"')
00434          {
00435           if (v[x].value[a+1] == '\"') a++;
00436           else break;
00437          }
00438 
00439         a++; b++;
00440        }
00441       v[x].value[b] = 0;
00442      }
00443   }
00444 }
00445 
00449 int DatabaseReadRecord(DATABASE * database, CGINameValue * v, int * flags)
00450 {
00451  int c = 0;
00452  char*d = 0;
00453  char *data = 0;
00454  int any = 0;
00455 
00456  data = CGIMALLOC(MAXDATA);
00457 
00458  if (flags) *flags = 0;
00459  if (data == NULL) return 0;
00460 
00461  ResetList(v); /* clear the record, just to be sure */
00462 
00463  do {
00464     if (v->name == NULL) /* end of header, but not end of line? */
00465      { /* finish off the line and continue */
00466        ReadUntilChar(database,0,0,"\n",0);
00467       break;
00468      }
00469     c = ReadUntilChar(database,data,MAXDATA,"\t\n",'\r');
00470 
00471     d = strchr(data,'\r');
00472     if (d != NULL) *d = 0; /* just in case we opened it in binary mode */
00473 
00474     if (any == 0 && flags != NULL)
00475      {
00476       switch (data[0])
00477       { case 0 :  *flags = 2; if (*data) if (strstr(data+1,"\"\t")) data[0]='\"'; break;
00478         case '#': *flags = 1; if (*data) if (strstr(data+1,"\"\t")) data[0]='\"'; break;
00479         default:   *flags = 0;
00480       }
00481      }
00482 
00483     if (*data)
00484      {
00485       v->value = strdup(data);
00486       if (v->value[0] == '\"')
00487        UnfixQuotes(v->value);
00488       any = 1;
00489      }
00490 
00491     v++;
00492 
00493     if (c == EOF ) /* premature end of file */
00494       {
00495        CGIFREE(data);
00496        if (any) FixQuotes(v);
00497        return any;
00498       }
00499    } while (c != '\n');
00500 
00501  CGIFREE(data);
00502  if (any) FixQuotes(v);
00503  return any;
00504 }
00505 
00507 #ifdef XP_WIN
00508 void WriteValue( HANDLE file,char* c)
00509 {
00510  size_t len;
00511  DWORD written=0;
00512  while (*c)
00513   {
00514    if (*c == '\"') WriteFile(file,"\"",1,&written,0);
00515 
00516    if (*c != '\n' && *c != '\r')
00517    {
00518       len = strcspn(c+1,"\"");
00519       WriteFile(file,c,1+len,&written,0);
00520       c += len;
00521    }
00522 
00523    c++;
00524   }
00525 }
00526 
00527 #else
00528 /*void WriteValue( int file,char* c)
00529 {
00530  while (*c)
00531   {
00532    if (*c == '\"') write(file,"\"",1);
00533 
00534    if (*c != '\n' && *c != '\r')
00535    {
00536       size_t len = strcspn(c+1,"\"");
00537       write(file,c,1+len);
00538       c += len;
00539    }
00540 
00541    c++;
00542   }
00543 }
00544 */
00545 void WriteValue( TextBuffer* file,char* c)
00546 {
00547  while (*c)
00548   {
00549    if (*c == '\"') BufferWriteL(file,"\"",1);
00550 
00551    if (*c != '\n' && *c != '\r')
00552    {
00553       size_t len = strcspn(c+1,"\"");
00554       BufferWriteL(file,c,1+len);
00555       c += len;
00556    }
00557 
00558    c++;
00559   }
00560 }
00561 
00562 #endif
00563 
00564 #ifdef __WINCE__
00565  int ToWideChar(char*in,size_t l1,wchar_t*out,size_t l2);
00566 #endif
00567 
00568 int DatabaseSaveIndex(char * indexfile, CGINameValue * Params,int pos)
00569 {
00570     FILE * indexdb;
00571     CGINameValue * indexheader;
00572     int ret = 0;
00573 
00574     if (DatabaseOpen(indexfile,&indexdb,&indexheader,0,0))
00575     {
00576       FILE* ndx;
00577 
00578       DatabaseClose(indexdb,NULL);
00579       ndx = CGIFOPEN(indexfile,"ab");
00580       if (ndx)
00581       {
00582        size_t i;
00583        for ( i=0; indexheader[i].name; i++)
00584        {
00585         if (!strcmp(indexheader[i].name,"_POS"))
00586          { fprintf(ndx,"%d",pos); }
00587         else
00588          { fprintf(ndx,"\"%s\"\t",GetFieldValue(Params,indexheader[i].name)); }
00589        }
00590        fprintf(ndx,"\n");
00591        fclose(ndx);
00592       }
00593       else
00594        ret = 9;
00595 
00596       DatabaseClose(NULL,indexheader);
00597     }
00598     return ret;
00599  }
00600 
00605 int DatabaseSaveNewRecord(char * filename, CGINameValue * v,int* pos)
00606 {
00607  int x,y;
00608  CGINameValue * header;
00609  char *c, * lastfieldname;
00610  int ret = 0, writecomma;
00611 #ifdef XP_WIN
00612  HANDLE fh;
00613  DWORD written=0;
00614 #ifndef VPWSCGI
00615  HANDLE Mutex;
00616 #endif
00617 #else
00618  TextBuffer * buf;
00619  int fh;
00620  static struct flock myLock ;
00621 #endif
00622 
00623  if (!DatabaseOpen(filename,0,&header,0,0))
00624  {
00625   /*LogError("\nTried to read a data file, failed: ");
00626   LogError(filename);*/
00627   return 2;
00628  }
00629 
00630 /* do this early to minimize the time the file is open
00631  if (!DoesFileMatchForm(v, header)) ret = 5;
00632 */
00633 
00634 
00635 /* personal web server is single-threaded, no need for file locks */
00636 #if defined(XP_WIN) && !defined(VPWSCGI)
00637  {
00638 #ifdef UNICODE
00639  wchar_t Mutex_name[MAXPATH+1];
00640  ToWideChar(_filename,strlen(_filename),Mutex_name,MAXPATH);
00641 #else
00642  char Mutex_name[MAXPATH+1];
00643  strncpy(Mutex_name,filename,MAXPATH);
00644 #endif
00645  Mutex_name[MAXPATH] = 0;
00646  for (x=0; Mutex_name[x]; x++) if (Mutex_name[x] == '\\') Mutex_name[x] = '/';
00647  Mutex = CreateMutex(0,FALSE,Mutex_name);
00648 
00649  /* wait up to 20 seconds */
00650  if(Mutex) if ( WaitForSingleObject(Mutex,20000) == WAIT_TIMEOUT)
00651   {
00652    CloseHandle(Mutex);
00653    DatabaseClose(0,header);
00654    return 23;
00655   }
00656  }
00657 #endif
00658 
00659 #ifdef XP_WIN /* binary mode, direct write */
00660 
00661 #ifdef __WINCE__
00662  {
00663    wchar_t fn[MAXPATH+1];
00664    ToWideChar(filename,strlen(filename),fn,MAXPATH+1);
00665    fh = CreateFileW(fn,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
00666  }
00667 #else
00668  fh = CreateFileA(filename,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,0);
00669 #endif
00670 
00671  if (fh == INVALID_HANDLE_VALUE)
00672  {
00673 #if !defined(VPWSCGI)
00674    if (Mutex) CloseHandle(Mutex);
00675 #endif
00676      x = GetLastError();
00677     return 6;
00678  }
00679  x = SetFilePointer(fh,0,0,FILE_END);
00680 #else
00681  fh = open(filename,O_WRONLY|O_APPEND);
00682 
00683  if (fh == -1)
00684  {
00685   return 6;
00686  }
00687 #endif
00688 
00689 
00690 /* Wait for a file lock to become available */
00691 #ifdef XP_POSIX
00692     myLock.l_type = F_WRLCK ;
00693     myLock.l_start = 0 ;
00694     myLock.l_whence = SEEK_END ;
00695     myLock.l_len = 0 ;
00696     myLock.l_pid = getpid() ;
00697  fcntl(fh, F_SETLKW, &myLock);
00698 #endif
00699 
00700  if (pos)
00701  {
00702 #ifdef XP_WIN
00703   *pos = x;
00704 #else
00705   *pos = lseek(fh,0,SEEK_END);
00706 #endif
00707  }
00708 
00709 #ifndef XP_WIN
00710  buf = NewBuffer(16384);
00711 #endif
00712 
00713  for(x=0; header[x].name; x++)
00714    {
00715     /* if two consecutive questions have the same fieldname, append their data together */
00716     if (!header[x].name[0]) continue;
00717     /*don't write empty fieldnames */
00718 
00719 #ifdef XP_WIN
00720         WriteFile(fh,"\"",1,&written,0);
00721 #else
00722       BufferWriteL(buf,"\"",1);
00723 /*      write(fh,"\"",1); */
00724 #endif
00725     y = 0;
00726     lastfieldname = NULLSTR;
00727     writecomma = 0;
00728     while (v[y].name)
00729     {
00730      if (v[y].name[0] && stricmp(header[x].name,v[y].name)==0)
00731      {/*write this entry*/
00732        c = v[y].value;
00733        if ( c && *c )
00734         {
00735          if (*lastfieldname && writecomma)
00736 #ifdef XP_WIN
00737                 WriteFile(fh,",",1,&written,0);
00738          WriteValue(fh,c);
00739 #else
00740                 BufferWriteL(buf,",",1);
00741          WriteValue(buf,c);
00742             /* write(fh,",",1); WriteValue(fh,c); */
00743 #endif
00744          if (*c) writecomma = 1;
00745         }
00746       lastfieldname=header[x].name;
00747      }
00748      y++;
00749     }
00750 #ifdef XP_WIN
00751         WriteFile(fh,"\"\t",2,&written,0);
00752 #else
00753       BufferWriteL(buf,"\"\t",2);
00754         /*write(fh,"\"\t",2); */
00755 #endif
00756   }
00757 
00758 #ifdef XP_WIN
00759         WriteFile(fh,"\r\n",2,&written,0);
00760 #else
00761       BufferWriteL(buf,"\r\n",2);
00762         /*write(fh,"\r\n",2);*/
00763 #endif
00764 
00765 #if defined(XP_WIN) && !defined(VPWSCGI)
00766 if (Mutex)
00767 {
00768  ReleaseMutex(Mutex);
00769  CloseHandle(Mutex);
00770 }
00771 #endif
00772 
00773 #ifndef XP_WIN
00774  c = CopyBuffer(buf);
00775  x = lseek(fh,0,SEEK_END);
00776  if (pos) *pos = x;
00777  write(fh,c,BufferSize(buf));
00778  free(c);
00779  DeleteBuffer(buf);
00780 #endif
00781 
00782 #ifdef XP_POSIX
00783  myLock.l_type = F_UNLCK;
00784  fcntl(fh, F_SETLKW, &myLock);
00785 #endif
00786 
00787 #ifdef XP_WIN
00788  CloseHandle(fh);
00789 #else
00790  close(fh);
00791 #endif
00792 
00793  DatabaseClose(0,header);
00794  return ret;
00795 }
00796 
00797 #if 0
00798 int DatabaseSaveNewRecord(char * filename, CGINameValue * v,int* pos)
00799 {
00800  int x,y;
00801  CGINameValue * header;
00802  DATABASE* file=NULL;
00803  char *c, * lastfieldname;
00804  int ret = 0, writecomma;
00805 #ifndef __WINCE__
00806  int fh;
00807 #endif
00808 
00809 #if defined(XP_WIN) && !defined(VPWSCGI)
00810  HANDLE Mutex;
00811  char Mutex_name[MAXPATH+1];
00812  strncpy(Mutex_name,filename,MAXPATH);
00813  Mutex_name[MAXPATH] = 0;
00814  swapchars(Mutex_name, '\\', '/');
00815 #endif
00816 
00817  if (!DatabaseOpen(filename,0,&header,0))
00818  {
00819   /*LogError("\nTried to read a data file, failed: ");
00820   LogError(filename);*/
00821   return 2;
00822  }
00823 
00824 #ifdef __WINCE__ /* open in text mode */
00825  file = CGIFOPEN(filename,"ab");
00826 #else
00827  fh = open(filename,O_WRONLY|O_APPEND );
00828  if (fh != -1)
00829   {
00830    file = fdopen(fh,"ab");
00831   }
00832 #endif
00833 
00834  if (file == NULL)
00835  {
00836   /*LogError("\nTried to append to a data file, failed: ");
00837   LogError(filename);*/
00838   return 6;
00839  }
00840 
00841  if (!DoesFileMatchForm(v, header)) ret = 5;
00842 
00843 #if defined(XP_WIN) && !defined(VPWSCGI)
00844 
00845  Mutex = CreateMutex(0,FALSE,Mutex_name);
00846 
00847 
00848  /* wait up to 20 seconds */
00849  if ( WaitForSingleObject(Mutex,20000) == WAIT_TIMEOUT)
00850   {
00851    CloseHandle(Mutex);
00852    return 23;
00853   }
00854 #endif
00855 
00856 #ifdef USE_FLOCK
00857  flock(fh,LOCK_EX);
00858 #endif
00859 
00860  if (pos)
00861  {
00862   fseek(file,0,2);
00863   *pos = ftell(file);
00864  }
00865 
00866  for(x=0; header[x].name; x++)
00867    {
00868     /* if two consecutive questions have the same fieldname, append their data together */
00869     if (!header[x].name[0]) continue;
00870     /*don't write empty fieldnames */
00871 
00872     fwrite("\"",1,1,file);
00873 
00874     y = 0;
00875     lastfieldname = NULLSTR;
00876     writecomma = 0;
00877     while (v[y].name)
00878     {
00879      if (v[y].name[0] && stricmp(header[x].name,v[y].name)==0)
00880      {/*write this entry*/
00881        c = v[y].value;
00882        if ( c && *c )
00883         {
00884          if (*lastfieldname && writecomma) fwrite(",",1,1,file);
00885          WriteValue(file,c);
00886          if (strlen(c)) writecomma = 1;
00887         }
00888       lastfieldname=header[x].name;
00889      }
00890      y++;
00891     }
00892    fwrite("\"\t",2,1,file);
00893   }
00894 
00895  fwrite("\r\n",2,1,file);
00896 #if defined(XP_WIN) && !defined(VPWSCGI)
00897  ReleaseMutex(Mutex);
00898  CloseHandle(Mutex);
00899 #endif
00900 
00901 #ifdef USE_FLOCK
00902  flock(fh,LOCK_UN);
00903 #endif
00904 
00905  CGIFCLOSE(file);
00906  DatabaseClose(0,header);
00907  return ret ? ret : 0;
00908 }
00909 #endif
00910 
00911 void DatabaseClose(DATABASE * database, CGINameValue * header)
00912 {
00913  if (database) CGIFCLOSE(database);
00914  if (header) DeleteNVP(header);
00915 }
00916 
00917 char * FindEndChar(char * text,char start,char finish);
00918 
00919 
00920 /********************* CGI Database macros **************************/
00921 
00922 int CreateDatabase(CGINameValue * data,char * filename)
00923 {
00924  char * lastfieldname=NULLSTR;
00925  register int x ;
00926  FILE* handle;
00927  char * c;
00928 
00929 /*File does not exist, so we save fieldnames. Appends to the data file*/
00930   handle=CGIFOPEN(filename,"ab+");
00931   if (handle ==0)
00932     {
00933      return 4;
00934     }
00935 
00936   for(x=0; data[x].name ; x++)
00937    {
00938     c = data[x].name;
00939     if (!*c) continue;
00940     if (stricmp(lastfieldname,c))
00941        {
00942         if (*lastfieldname) fwrite("\t",1,1,handle);
00943         fwrite(c,1,strlen(c),handle);
00944        }
00945     lastfieldname=c;
00946    }
00947   fwrite("\r\n",2,1,handle);
00948   CGIFCLOSE(handle); /* done! */
00949 return 0; /* success */
00950 }
00951 
00952 int SaveDataToASC(CGINameValue *data,char * filename,int* pos)
00953 {
00954 #if 0
00955  int x;
00956  FILE* handle;
00957 
00958  /* Check to see if file exists*/
00959 
00960  handle=CGIFOPEN(filename,"rb");
00961  if ( handle == 0 )
00962   {
00963    x = CreateDatabase(data,filename);
00964    if (x) return x;
00965    /* that should ensure that the file exists, now open it in append mode*/
00966   }
00967  else
00968   {
00969    CGIFCLOSE(handle);
00970   }
00971 #endif
00972  return DatabaseSaveNewRecord(filename,data,pos);
00973 }
00974 
00975 


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/