Browse code

webkernel: basic cookie support

Dario Rodriguez authored on 13/07/2014 19:55:14
Showing 2 changed files
... ...
@@ -64,6 +64,7 @@ typedef struct wk_client {
64 64
         wk_post *post;
65 65
         int pendingpost;
66 66
         int inpostvar;
67
+        int cookiebufid;
67 68
         time_t lastio;
68 69
 } wk_client;
69 70
 
... ...
@@ -401,6 +402,39 @@ wk_service(wk *paramweb)
401 402
         return(0);
402 403
 }
403 404
 
405
+int
406
+wk_serve_cookieadd(wk *paramweb, int connid, char *cookiename, char *value, char *domain, int maxage, char *attributes)
407
+{
408
+        _wk *web=(_wk *)paramweb;
409
+        wk_client *client;
410
+        sbuf *buf;
411
+        char str[1024];
412
+        if(web==NULL || cookiename==NULL || (value==NULL && maxage>0))
413
+                return(-1);
414
+        if((client=wk_clientget(web,connid))==NULL)
415
+                return(-1);
416
+        if(client->cookiebufid==-1) {
417
+                if((client->cookiebufid=wk_sbufacquire((wk *)web))==-1)
418
+                        return(-1); /* insufficient memory */
419
+        }
420
+        if((buf=wk_sbufget((wk *)web,client->cookiebufid))==NULL)
421
+                return(-1); /* internal error */
422
+        if(sbuf_count(buf)==0) {
423
+                sbuf_addstr(buf,"Cache-control: no-cache=\"set-cookie\"\r\n");
424
+                sbuf_addstr(buf,"Expires: Tue, 01 Jan 1980 1:00:00 GMT\r\n");
425
+        }
426
+        snprintf(str,sizeof(str)-1,"Set-Cookie: %s=%s %s%s%s; Max-Age=%i ; Version=1%s%s\r\n",
427
+                cookiename,(value!=NULL)?value:"",
428
+                (domain!=NULL)?"; Domain = ":"",
429
+                (domain!=NULL && *domain!='.')?".":"",
430
+                (domain!=NULL)?domain:"",
431
+                maxage,
432
+                (attributes!=NULL)?"; ":"",(attributes!=NULL)?attributes:"");
433
+        sbuf_addstr(buf,str);
434
+        return(0);
435
+}
436
+
437
+
404 438
 int
405 439
 wk_serve_buffer_as_file(wk *paramweb, int connid, void *data, int datalen, const char *mime)
406 440
 {
... ...
@@ -408,11 +442,18 @@ wk_serve_buffer_as_file(wk *paramweb, int connid, void *data, int datalen, const
408 442
         _wk *web=(_wk *)paramweb;
409 443
         wk_client *client;
410 444
         char buf[256];
445
+        sbuf *cookiebuf;
411 446
         if(web==NULL)
412 447
                 return(-1);
413 448
         if((client=wk_clientget(web,connid))==NULL)
414 449
                 return(-1);
415 450
         wk_writestr((wk *)web,connid,"HTTP/1.0 200 OK\r\n");
451
+        if(client->cookiebufid!=-1 && (cookiebuf=wk_sbufget((wk *)web,client->cookiebufid))!=NULL) {
452
+                if(wk_write((wk *)web,connid,sbuf_getbytes(cookiebuf,sbuf_count(cookiebuf)),sbuf_count(cookiebuf))==-1 ||
453
+                  sbuf_count(cookiebuf)!=0)
454
+                        return(-1); /* insufficient memory */
455
+                wk_sbufrelease((wk *)web,client->cookiebufid),client->cookiebufid=-1;
456
+        }
416 457
         sprintf(buf,"Content-Length: %i\r\n",datalen);
417 458
         wk_writestr((wk *)web,connid,buf);
418 459
         if(mime!=NULL && strlen(mime)<(sizeof(buf)-sizeof(strcontenttype)-3))
... ...
@@ -433,6 +474,7 @@ wk_serve_file(wk *paramweb, int connid, char *filename, const char *mime)
433 474
         _wk *web=(_wk *)paramweb;
434 475
         wk_client *client;
435 476
         char buf[256];
477
+        sbuf *cookiebuf;
436 478
         struct stat st;
437 479
         if(web==NULL || filename==NULL)
438 480
                 return(-1);
... ...
@@ -445,6 +487,12 @@ wk_serve_file(wk *paramweb, int connid, char *filename, const char *mime)
445 487
                 return(-1);
446 488
         }
447 489
         wk_writestr((wk *)web,connid,"HTTP/1.1 200 OK\r\n");
490
+        if(client->cookiebufid!=-1 && (cookiebuf=wk_sbufget((wk *)web,client->cookiebufid))!=NULL) {
491
+                if(wk_write((wk *)web,connid,sbuf_getbytes(cookiebuf,sbuf_count(cookiebuf)),sbuf_count(cookiebuf))==-1 ||
492
+                  sbuf_count(cookiebuf)!=0)
493
+                        return(-1); /* insufficient memory */
494
+                wk_sbufrelease((wk *)web,client->cookiebufid),client->cookiebufid=-1;
495
+        }
448 496
         if(fstat(client->fdtoserve,&st)==0) {
449 497
                 sprintf(buf,"Content-Length: %lld\r\n",(long long)st.st_size);
450 498
                 wk_writestr((wk *)web,connid,buf);
... ...
@@ -675,6 +723,65 @@ wk_uri_copyvar(wk_uri *uri, char *varname, char *dest, int destlen)
675 723
         return(dest);
676 724
 }
677 725
 
726
+char *
727
+wk_uri_getcookie(wk_uri *uri, char *cookiename, int *len)
728
+{
729
+        int n;
730
+        char *header;
731
+        int namelen;
732
+        char *ptr;
733
+        char *sep;
734
+        char *end;
735
+        char *next;
736
+        if(uri==NULL || uri->headers==NULL || cookiename==NULL || len==NULL)
737
+                return(NULL);
738
+        namelen=strlen(cookiename);
739
+        for(n=0,header=uri->headers;*header!='\0';header++,n++) {
740
+                if(memcmp(header,"Cookie: ",8)!=0 && memcmp(header,"cookie: ",8)!=0)
741
+                        continue;
742
+                for(ptr=header+8;*ptr!='\0';ptr=((*next!='\0')?next+1:next)) {
743
+                        /* cookies are separated by ',' or ';' */
744
+                        next=strchr(ptr,';');
745
+                        if(next==NULL)
746
+                                next=ptr+strlen(ptr);
747
+                        if((sep=strchr(ptr,','))!=NULL && sep<next)
748
+                                next=sep;
749
+                        /* trim cookie name */
750
+                        while(*ptr==' ')
751
+                                ptr++;
752
+                        /* check for our cookie and search for the value pos */
753
+                        if(memcmp(ptr,cookiename,namelen)!=0)
754
+                                continue; /* not our cookie */
755
+                        for(sep=ptr+namelen;*sep==' ';sep++)
756
+                                ;
757
+                        if(*sep!='=')
758
+                                continue; /* was partial match or unrecognized cookie format */
759
+                        /* skip '=' and trim value */
760
+                        sep++;
761
+                        while(*sep==' ')
762
+                                sep++;
763
+                        for(end=next;end>sep && end[-1]==' ';)
764
+                                end--;
765
+                        /* cookie found, return it */
766
+                        *len=end-sep;
767
+                        return(ptr);
768
+                }
769
+        }
770
+        return(NULL);
771
+}
772
+
773
+char *
774
+wk_uri_copycookie(wk_uri *uri, char *cookiename, char *dest, int destlen)
775
+{
776
+        char *value;
777
+        int len;
778
+        if(dest==NULL || destlen<1 || (value=wk_uri_getcookie(uri,cookiename,&len))==NULL)
779
+                return(NULL);
780
+        memcpy(dest,value,(len<(destlen-1))?len:destlen-1);
781
+        dest[(len<(destlen-1))?len:destlen-1]='\0';
782
+        return(dest);
783
+}
784
+
678 785
 
679 786
 int
680 787
 wk_post_addvalid(wk *paramweb, int connid, char *varname, char *tofile)
... ...
@@ -937,6 +1044,7 @@ wk_clientacquire(_wk *web)
937 1044
         client->usedoutbufids=1;
938 1045
         client->fdtoserve=-1;
939 1046
         client->headerbufid=-1;
1047
+        client->cookiebufid=-1;
940 1048
         return(client);
941 1049
 }
942 1050
 
... ...
@@ -959,6 +1067,8 @@ wk_clientrelease(_wk *web, int connid)
959 1067
                 wk_sbufrelease((wk *)web,client->outbufids[w]),client->outbufids[w]=-1;
960 1068
         if(client->headerbufid!=-1)
961 1069
                 wk_sbufrelease((wk *)web,client->headerbufid),client->headerbufid=-1;
1070
+        if(client->cookiebufid!=-1)
1071
+                wk_sbufrelease((wk *)web,client->cookiebufid),client->cookiebufid=-1;
962 1072
         wk_postfree(web,client);
963 1073
         memset(client,0,sizeof(wk_client));
964 1074
         return(0);
... ...
@@ -51,6 +51,7 @@ wk_uri *wk_geturi(wk *web, int connid); /* for use in callback_event() when wke_
51 51
 
52 52
 int wk_service(wk *web); /* To be called after sselelect_wait() but before sselect_getXXX() */
53 53
 
54
+int wk_serve_cookieadd(wk *web, int connid, char *cookiename, char *value, char *domain, int maxage, char *attributes);
54 55
 int wk_serve_buffer_as_file(wk *web, int connid, void *data, int datalen, const char *mime);
55 56
 int wk_serve_file(wk *web, int connid, char *filename, const char *mime);
56 57
 int wk_serve_error(wk *web, int connid, wk_error wkerror);
... ...
@@ -64,6 +65,8 @@ char *wk_uri_getheaderbynum(wk_uri *wkuri, int num);
64 65
 
65 66
 char *wk_uri_getvar(wk_uri *wkuri, char *varname, int *len);
66 67
 char *wk_uri_copyvar(wk_uri *uri, char *varname, char *dest, int destlen);
68
+char *wk_uri_getcookie(wk_uri *uri, char *cookiename, int *len);
69
+char *wk_uri_copycookie(wk_uri *uri, char *cookiename, char *dest, int destlen);
67 70
 
68 71
 int wk_post_addvalid(wk *web, int connid, char *varname, char *tofile);
69 72
 char *wk_post_get(wk *web, int connid, char *varname, int *isfile);