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> ");
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