gcs6.c

0000/********************************************
0001 gcs6.c Cookie
0002********************************************/
0003
0004#include <stdio.h>
0005#include <stdlib.h>
0006#include <time.h>
0007#include <string.h>
0008#include <ctype.h>
0009
0010#include "gcs6.h"
0011
0012struct {
0013 int ncol;
0014 int nrow;
0015 int *cols;    // column attributes
0016               // 0 : int (byte storage)
0017               // 1 : int (short storage)
0018               // 2 : int (int storage)
0019               // 3 : time_t (unsigned int)
0020               // 4 : int (int) with initial and increment specified
0021               // 5 : time_t with initial and increment specified
0022               // 6 : string
0023               // 7 : double (float storage)
0024               // 8 : double (double storage)
0025 void **coldata;
0026               // data storage area
0027               // cols=0,1,2 : nrow ints
0028               // cols=3     : nrow unsigned ints
0029               // cols=4     : 2 ints (initial and increment)
0030               // cols=5     : 2 unsigned ints (initial and increment)
0031               // cols=6     : offset to strings
0032               // cols=7,8   : nrow doubles
0033 int pte;      // past-the-end index of str
0034 char *str;    // string buffer
0035 int pack;     // 0 : combination of icol, irow, defined data are packed
0036               // 1 : all data in column major order are packed (default)
0037} table;
0038
0039extern int outbyte(int num,const char *buf);
0040extern int outstr(const char *buf); /* for zero-terminated string */
0041extern int flush();
0042
0043int occupied=0;
0044
0045char cookieval[3921];     /* base-64 encoded value data (2940*43+1) */
0046unsigned char cdata[2941]; /* cookie value data (2940+terminating 0)*/
0047int ncdata;
0048
0049/********************************************************
0050 inittab
0051   initialize the table giving column and row size
0052********************************************************/
0053int inittab(int ncol,int nrow)
0054{
0055 int i;
0056 if(occupied){
0057  for(i=0;i<table.ncol;i++) free(table.coldata[i]);
0058  free(table.str);
0059  free(table.coldata);
0060  free(table.cols);
0061 }
0062 table.ncol=ncol;
0063 table.nrow=nrow;
0064 table.cols=(int *)calloc(ncol,sizeof(int));
0065 table.coldata=(void **)calloc(ncol,sizeof(void *));
0066 table.str=(char *)malloc(7000*sizeof(char));
0067 table.pte=0;
0068 table.pack=1; /* default */
0069 occupied=1;
0070}
0071
0072/********************************************************
0073 initcol
0074   initialize a column type
0075********************************************************/
0076int initcol(int col,int icols)
0077{
0078 int i;
0079 table.cols[col]=icols;
0080 switch(icols){
0081  case 0:
0082  case 1:
0083  case 2:
0084  case 3:
0085   table.coldata[col]=(void *)calloc(table.nrow,sizeof(int));
0086   break;
0087  case 4:
0088  case 5:
0089   table.coldata[col]=(void *)malloc(2*sizeof(int));
0090   break;
0091  case 6:
0092   table.coldata[col]=(void *)malloc(table.nrow*sizeof(int));
0093   for(i=0;i<table.nrow;i++) *((int *)table.coldata[col]+i)=-1; /* vacant */
0094   break;
0095  case 7:
0096  case 8:
0097   table.coldata[col]=(void *)calloc(table.nrow,sizeof(double));
0098   break;
0099 }
0100}
0101
0102/********************************************************
0103 putinist
0104   define data in a column by init and step
0105********************************************************/
0106int putinist(int col,int init,int step)
0107{
0108 int i,j;
0109 i=table.cols[col];
0110 if(i==4){
0111  *(int *)table.coldata[col]=init;
0112  *((int *)table.coldata[col]+1)=step;
0113 }
0114 else if(i==5){
0115  j=init;
0116  *(time_t *)table.coldata[col]=*(time_t *)&j;
0117  *((time_t *)table.coldata[col]+1)=step;
0118 }
0119 else return 1;
0120}
0121
0122/********************************************************
0123 putint
0124   define data in a cell
0125********************************************************/
0126int putint(int col,int row,int data)
0127{
0128 int i,j;
0129 i=table.cols[col];
0130 if(i<3) *((int *)table.coldata[col]+row)=data;
0131 else if(i==3){
0132  j=data;
0133  *((time_t *)table.coldata[col]+row)=*(time_t *)&j;
0134 }
0135 else return 1;
0136}
0137
0138/********************************************************
0139 putstr
0140   define data in a cell - previous str data deleted
0141********************************************************/
0142int putstr(int col,int row,char *s)
0143{
0144 int i,j,k;
0145 i=table.cols[col];
0146 if(i!=6) return 1;
0147 if(*((int *)table.coldata[col]+row)!=-1){  /* delete the previous entry */
0148  i=*((int *)table.coldata[col]+row);       /* offset of the string */
0149  j=strlen(&table.str[i])+1;                /* length of the string and terminator */
0150  for(k=0;k<table.nrow;k++)
0151   if(*((int *)table.coldata[col]+k)>i) *((int *)table.coldata[col]+k)-=j;
0152  memmove(&table.str[i],&table.str[i+j],table.pte-i-j);
0153  table.pte-=j;
0154 }
0155 if(s[0]=='\0') *((int *)table.coldata[col]+row)=-1;
0156 else{
0157  strcpy(&table.str[table.pte],s);
0158  *((int *)table.coldata[col]+row)=table.pte;
0159  table.pte+=(strlen(s)+1);
0160 }
0161}
0162
0163/********************************************************
0164 putdbl
0165   define data in a cell
0166********************************************************/
0167int putdbl(int col,int row,double data)
0168{
0169 int i;
0170 i=table.cols[col];
0171 if(i!=7&&i!=8) return 1;
0172 *((double *)table.coldata[col]+row)=data;
0173}
0174
0175/********************************************************
0176 getrow
0177********************************************************/
0178int getrow()
0179{
0180 return table.nrow;
0181}
0182
0183/********************************************************
0184 getint
0185   fetch data from a cell
0186********************************************************/
0187int getint(int col,int row)
0188{
0189 int i,j;
0190 time_t k;
0191 i=table.cols[col];
0192 if(i<4) j=*((int *)table.coldata[col]+row);
0193 else if(i==4){
0194  j=*(int *)table.coldata[col]+row**((int *)table.coldata[col]+1);
0195 }
0196 else if(i==5){
0197  k=*(time_t *)table.coldata[col]+row**((time_t *)table.coldata[col]+1);
0198  j=*(int *)&k;
0199 }
0200 else return 0;
0201 return j;
0202}
0203
0204/********************************************************
0205 getstr
0206   fetch data from a cell
0207********************************************************/
0208int getstr(int col,int row,char *s)
0209{
0210 if(*((int *)table.coldata[col]+row)==-1) s[0]='\0';
0211 else strcpy(s,&table.str[*((int *)table.coldata[col]+row)]);
0212}
0213
0214/********************************************************
0215 getdbl
0216   fetch data from a cell
0217********************************************************/
0218double getdbl(int col,int row)
0219{
0220 return *((double *)table.coldata[col]+row);
0221}
0222
0223/********************************************************
0224 movstr
0225   move data from a cell to a cell
0226********************************************************/
0227int movstr(int cs,int rs,int cd,int rd)
0228{
0229 *((int *)table.coldata[cd]+rd)=*((int *)table.coldata[cs]+rs);
0230 *((int *)table.coldata[cs]+rs)=-1;
0231}
0232
0233/********************************************************
0234 sendcookie
0235  hours : hours to expire
0236
0237  base-64 encode cdata[ncdata] to cookieval[]
0238  get key from 
0239********************************************************/
0240int sendcookie(int hours)
0241{
0242 int i,j,k;
0243 unsigned char c;
0244 short sh;
0245 time_t t;
0246 int ncdat;
0247 unsigned char *cdat;
0248
0249 cdat=(unsigned char *)malloc(10000*sizeof(char));
0250
0251/******** move table data to cdata ************/
0252 ncdat=0;
0253 cdat[ncdat++]=table.ncol;
0254 cdat[ncdat++]=table.nrow;
0255 for(i=0;i<table.ncol;i++) cdat[ncdat++]=table.cols[i];
0256 for(i=0;i<table.ncol;i++){
0257  switch(table.cols[i]){
0258   case 0 :  /* int (byte) */
0259    for(j=0;j<table.nrow;j++){
0260     c=*((int *)table.coldata[i]+j);
0261     cdat[ncdat++]=c;
0262    }
0263    break;
0264   case 1 :  /* int (short) */
0265    for(j=0;j<table.nrow;j++){
0266     sh=*((int *)table.coldata[i]+j);
0267     *(short *)&cdat[ncdat]=sh;
0268     ncdat+=2;
0269    }
0270    break;
0271   case 2 :  /* int (int) */
0272    for(j=0;j<table.nrow;j++){
0273     k=*((int *)table.coldata[i]+j);
0274     *(int *)&cdat[ncdat]=k;
0275     ncdat+=4;
0276    }
0277    break;
0278   case 3 :  /* time_t (unsigned int) */
0279    for(j=0;j<table.nrow;j++){
0280     t=*((time_t *)table.coldata[i]+j);
0281     *(time_t *)&cdat[ncdat]=t;
0282     ncdat+=4;
0283    }
0284    break;
0285   case 4 :  /* int (int) with initial and increment specified */
0286    for(j=0;2;j++){
0287     k=*((int *)table.coldata[i]+j);
0288     *(int *)&cdat[ncdat]=k;
0289     ncdat+=4;
0290    }
0291    break;
0292   case 5 :  /* unsigned int with initial and increment specified */
0293    for(j=0;j<2;j++){
0294     t=*((time_t *)table.coldata[i]+j);
0295     *(time_t *)&cdat[ncdat]=t;
0296     ncdat+=4;
0297    }
0298    break;
0299   case 6 :  /* string */
0300    for(j=0;j<table.nrow;j++){
0301     sh=*((int *)table.coldata[i]+j);
0302     *(short *)&cdat[ncdat]=sh;
0303     ncdat+=2;
0304    }
0305    break;
0306   case 7 :  /* double (float)*/
0307    for(j=0;j<table.nrow;j++){
0308     *(float *)&cdat[ncdat]=*((double *)table.coldata[i]+j);
0309     ncdat+=4;
0310    }
0311    break;
0312   case 8 :  /* double (double)*/
0313    for(j=0;j<table.nrow;j++){
0314     *(double *)&cdat[ncdat]=*((double *)table.coldata[i]+j);
0315     ncdat+=8;
0316    }
0317    break;
0318  }
0319 }
0320 *(short *)&cdat[ncdat]=table.pte;
0321 ncdat+=2;
0322 for(i=0;i<table.pte;i++) cdat[ncdat++]=table.str[i];
0323 cdat[ncdat++]='\0';
0324 i=sendc(cdat,ncdat,hours);
0325 free(cdat);
0326 return i;
0327}
0328
0329/********************************************************
0330 sendc
0331
0332  sends cdat[ncdat] 
0333********************************************************/
0334int sendc(unsigned char *cdat,int ncdat,int hours)
0335{
0336 int i,j,k,l;
0337 char *s1=getenv("REQUEST_URI");
0338 char *s2=getenv("HTTP_HOST");
0339 time_t expires;
0340 char s[200];
0341 unsigned char c;
0342
0343 if(s1==NULL||s2==NULL) return 1;
0344 k=0;
0345 for(l=0;l<ncdat;l+=2940){
0346  outstr("Set-Cookie: ");
0347  outstr(&s1[9]);
0348  sprintf(s,"%02i",k);
0349  outstr(s);
0350  outstr("=");
0351  ncdata=(ncdat-l>2940)? 2940:ncdat-l;
0352  for(i=0;i<ncdata;i++) cdata[i]=cdat[l+i];
0353  cdata[ncdata]='\0';
0354  b64encode();
0355  outstr(cookieval);
0356  expires = time(NULL) + 3600*hours;
0357  strftime(s, 200, "%a,  %d-%b-%Y  %H:%M:%S  %Z",
0358                            gmtime(&expires));
0359  outstr("; expires=");
0360  outstr(s);
0361  outstr("; domain=");
0362  outstr(s2);
0363  outstr("; path=");
0364  outstr(s1);
0365  outstr("\n");
0366  flush();
0367  k++;
0368 }
0369// sprintf(s,"ncdat=%i k=%i\n",ncdat,k);
0370// outstr(s);
0371// outstr("\n");
0372// flush();
0373 return 0;
0374}
0375
0376/********************************************************
0377 recvc
0378
0379  cookiev[] to cdat[ncdat] 
0380********************************************************/
0381int recvc(unsigned char *cdat,int *ncdat)
0382{
0383 int i,j,k,l,m,n;
0384 int moff[20],mnum[20];
0385 char *cookiev;
0386 char *s1=getenv("REQUEST_URI");
0387 char c;
0388
0389 cookiev=getenv("HTTP_COOKIE");
0390 if(cookiev==NULL) return 1;
0391 if(s1[9]!=cookiev[0]||s1[10]!=cookiev[1]) return 1;
0392 n=strlen(cookiev);
0393 m=0; /* number of key-value pairs */
0394 moff[m++]=0;
0395 for(i=0;i<n;i++) if(cookiev[i]==';') moff[m++]=i;
0396 for(j=0;j<m;j++){
0397  for(i=moff[j];cookiev[i]!='=';i++);
0398  moff[j]=i+1;  /* offset of a value */
0399  c=cookiev[i-2];
0400  if(c!='0'&&c!='1') return 1;
0401  mnum[j]=10*(c-'0');
0402  c=cookiev[i-1];
0403  if(c<'0'||c>'9') return 1;
0404  mnum[j]+=c-'0'; /* sequencial number */
0405 }
0406 for(j=0;j<m;j++){
0407  for(i=0;i<m;i++) if(mnum[i]==j) break;
0408  if(i==m) return 1;
0409 }
0410 l=0;
0411 for(j=0;j<m;j++){
0412  for(i=0;i<m;i++) if(mnum[i]==j) break;
0413  for(k=0;;k++){
0414   c=cookiev[moff[i]+k];
0415   if(c==';'||c=='\0') break;
0416   cookieval[k]=c;
0417  }
0418  cookieval[k]='\0';
0419  b64decode();
0420  for(k=0;k<ncdata;k++) cdat[l+k]=cdata[k];
0421  l+=ncdata;
0422 }
0423 *ncdat=l;
0424 return 0;
0425}
0426 
0427/********************************************************
0428 recvcookie
0429
0430  base-64 decode cookieval[] to cdata[ncdata]
0431
0432 return value
0433  -1 : cookie not received
0434********************************************************/
0435int recvcookie()
0436{
0437 int i,j;
0438 int ncdat;
0439 unsigned char *cdat;
0440
0441 cdat=(unsigned char *)malloc(10000*sizeof(char));
0442 if(recvc(cdat,&ncdat)!=0) return -1;
0443
0444 
0445/******** move cdata to table data ************/
0446 ncdat=0;
0447 i=cdat[ncdat++];
0448 j=cdat[ncdat++];
0449 inittab(i,j);
0450 for(i=0;i<table.ncol;i++) initcol(i,cdat[ncdat++]);
0451 for(i=0;i<table.ncol;i++){
0452  switch(table.cols[i]){
0453   case 0 :  /* int (byte) */
0454    for(j=0;j<table.nrow;j++){
0455     *((int *)table.coldata[i]+j)=cdat[ncdat++];
0456    }
0457    break;
0458   case 1 :  /* int (short) */
0459    for(j=0;j<table.nrow;j++){
0460     *((int *)table.coldata[i]+j)=*(short *)&cdat[ncdat];
0461     ncdat+=2;
0462    }
0463    break;
0464   case 2 :  /* int (int) */
0465    for(j=0;j<table.nrow;j++){
0466     *((int *)table.coldata[i]+j)=*(int *)&cdat[ncdat];
0467     ncdat+=4;
0468    }
0469    break;
0470   case 3 :  /* time_t (unsigned int) */
0471    for(j=0;j<table.nrow;j++){
0472     *((time_t *)table.coldata[i]+j)=*(time_t *)&cdat[ncdat];
0473     ncdat+=4;
0474    }
0475    break;
0476   case 4 :  /* int (int) with initial and increment specified */
0477    for(j=0;2;j++){
0478     *((int *)table.coldata[i]+j)=*(int *)&cdat[ncdat];
0479     ncdat+=4;
0480    }
0481    break;
0482   case 5 :  /* unsigned int with initial and increment specified */
0483    for(j=0;j<2;j++){
0484     *((time_t *)table.coldata[i]+j)=*(time_t *)&cdat[ncdat];
0485     ncdat+=4;
0486    }
0487    break;
0488   case 6 :  /* string */
0489    for(j=0;j<table.nrow;j++){
0490     *((int *)table.coldata[i]+j)=*(short *)&cdat[ncdat];
0491     ncdat+=2;
0492    }
0493    break;
0494   case 7 :  /* double (float)*/
0495    for(j=0;j<table.nrow;j++){
0496     *((double *)table.coldata[i]+j)=*(float *)&cdat[ncdat];
0497     ncdat+=4;
0498    }
0499    break;
0500   case 8 :  /* double (double)*/
0501    for(j=0;j<table.nrow;j++){
0502     *((double *)table.coldata[i]+j)=*(double *)&cdat[ncdat];
0503     ncdat+=8;
0504    }
0505    break;
0506  }
0507 }
0508 table.pte=*(short *)&cdat[ncdat];
0509 ncdat+=2;
0510 for(i=0;i<table.pte;i++) table.str[i]=cdat[ncdat++];
0511 table.str[i]='\0';
0512 return 0;
0513}
0514
0515/********************************************************
0516 htmltable
0517
0518********************************************************/
0519int htmltable(char *caption)
0520{
0521 int col,row;
0522 char s[100];
0523 time_t t;
0524 outstr("<table border>\n<caption>");
0525 outstr(caption);
0526 outstr("</caption>\n");
0527 outstr("<tr>\n<th>&nbsp;");
0528 for(col=0;col<table.ncol;col++){
0529  sprintf(s,"<th>%i\n",col);
0530  outstr(s);
0531 }
0532 flush();
0533 for(row=0;row<table.nrow;row++){
0534  sprintf(s,"<tr>\n<td>%i\n",row);
0535  outstr(s);
0536  for(col=0;col<table.ncol;col++){
0537   switch(table.cols[col]){
0538    case 0 :  // int (byte)
0539    case 1 :  // int (short)
0540    case 2 :  // int (int)
0541     sprintf(s,"<td align=right>%i\n",*((int *)table.coldata[col]+row));
0542     outstr(s);
0543     outstr("\n");
0544     break;
0545    case 3 :  // time_t (unsigned int)
0546     strftime(s, 100, "%a,  %d-%b-%Y  %H:%M:%S  %Z",gmtime((time_t *)table.coldata[col]+row));
0547     outstr("<td>");
0548     outstr(s);
0549     outstr("\n");
0550     break;
0551    case 4 :  // int (int) with initial and increment specified
0552     sprintf(s,"<td align=right>%i\n",*(int *)table.coldata[col]+row**((int *)table.coldata[col]+1));
0553     outstr(s);
0554     outstr("\n");
0555     break;
0556    case 5 :  // unsigned int with initial and increment specified
0557     t=*(time_t *)table.coldata[col]+row**((time_t *)table.coldata[col]+1);
0558     strftime(s, 100, "%a,  %d-%b-%Y  %H:%M:%S  %Z",gmtime(&t));
0559     outstr("<td>");
0560     outstr(s);
0561     outstr("\n");
0562     break;
0563    case 6 :  // string
0564     outstr("<td>");
0565     outstr(&table.str[*((int *)table.coldata[col]+row)]);
0566     outstr("\n");
0567     break;
0568    case 7 :  // double (float)
0569    case 8 :  // double (double)
0570     sprintf(s,"<td align=right>%f\n",*((double *)table.coldata[col]+row));
0571     outstr(s);
0572     outstr("\n");
0573     break;
0574   }
0575  }
0576  flush();
0577 }
0578 outstr("</table>\n");
0579 flush();
0580}
0581
0582/********************************************************
0583 b64encode
0584  base-64 encode cdata[ncdata] to cookieval[].
0585  cdata[0]-cdata[ncdata-1] contain actual data.
0586  cdata[ncdata] contains 0.
0587
0588  cookieval will be 0 terminated.
0589  length of cookieval without the terminating 0
0590  is multiple of 4.
0591  the last 0, 1 or 2 chars of cookieval may be =.
0592********************************************************/
0593int b64encode()
0594{
0595 static char b64enc[] =
0596     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
0597 unsigned char *s;
0598 unsigned char *t, *te;
0599 size_t nt,nc;
0600 unsigned char c;
0601 int ns;
0602
0603 s=cdata;
0604 ns=ncdata;
0605 if (s == NULL) return 1;
0606
0607
0608 if (ns == 0) ns = strlen(s);
0609 nt = ((ns + 2) / 3) * 4;
0610 t = te = cookieval;
0611 
0612 while (ns) {
0613  c = *s++;
0614  *te++ = b64enc[ (c >> 2) ];
0615  *te++ = b64enc[ ((c & 0x3) << 4) | (*s >> 4) ];
0616  if (--ns <= 0) {
0617   *te++ = '=';
0618   *te++ = '=';
0619   continue;
0620  }
0621  c = *s++;
0622  *te++ = b64enc[ ((c & 0xf) << 2) | (*s >> 6) ];
0623  if (--ns <= 0) {
0624   *te++ = '=';
0625   continue;
0626  }
0627  *te++ = b64enc[ (int)(*s & 0x3f) ];
0628  s++;
0629  --ns;
0630 }
0631 *te = '\0';
0632 return 0;
0633}
0634
0635/********************************************************
0636 b64decode
0637  base-64 decode  cookieval[] to cdata[ncdata].
0638  cookieval will be 0 terminated.
0639  length of cookieval without the terminating 0
0640  is multiple of 4.
0641  the last 0, 1 or 2 chars of cookieval may be =.
0642
0643  cdata[0]-cdata[ncdata-1] contain actual data.
0644  cdata[ncdata] contains 0.
0645********************************************************/
0646int b64decode()
0647{
0648 char *s;
0649 char b64dec[255];
0650 unsigned char *t, *te;
0651 size_t ns, nt;
0652 unsigned char a, b, c, d;
0653
0654 s=cookieval;
0655 ns = strlen(s);
0656 if (ns & 0x3) return 2;
0657
0658 memset(b64dec, 0x80, 255);
0659 for (c = 'A'; c <= 'Z'; c++)
0660     b64dec[ c ] = 0 + (c - 'A');
0661 for (c = 'a'; c <= 'z'; c++)
0662     b64dec[ c ] = 26 + (c - 'a');
0663 for (c = '0'; c <= '9'; c++)
0664     b64dec[ c ] = 52 + (c - '0');
0665 b64dec[(unsigned)'+'] = 62;
0666 b64dec[(unsigned)'/'] = 63;
0667 b64dec[(unsigned)'='] = 0;
0668     
0669 nt = (ns / 4) * 3;
0670 t = te = cdata;
0671 
0672 while (ns > 0) {
0673  if ((a = b64dec[ (unsigned)*s++ ]) == 0x80)
0674   break;
0675  if ((b = b64dec[ (unsigned)*s++ ]) == 0x80)
0676   break;
0677  if ((c = b64dec[ (unsigned)*s++ ]) == 0x80)
0678   break;
0679  if ((d = b64dec[ (unsigned)*s++ ]) == 0x80)
0680   break;
0681  ns -= 4;
0682  *te++ = (a << 2) | (b >> 4);
0683  if (s[-2] == '=') break;
0684  *te++ = (b << 4) | (c >> 2);
0685  if (s[-1] == '=') break;
0686  *te++ = (c << 6) | d;
0687 }
0688 if (ns > 0)  return 3;
0689 ncdata = (te - t);
0690 cdata[ncdata]='\0';
0691 return 0;
0692}
0693
0694