Annotation of libwww/Library/src/HTCookie.c, revision 2.1

2.1     ! frystyk     1: /*
        !             2: **     SIMPLE HTTP COOKIE FILTER HANDLER
        !             3: **
        !             4: **     (c) COPYRIGHT MIT 1999.
        !             5: **     Please first read the full copyright statement in the file COPYRIGH.
        !             6: **     @(#) $Id: HTCache.c,v 2.66 1999/03/14 02:01:08 frystyk Exp $
        !             7: **
        !             8: **     Written based on Jim Raven's code sent to the <www-lib@w3.org> list
        !             9: **
        !            10: **      History:
        !            11: **         JR:  Sent code to the list
        !            12: **         HFN: Made a libwww module
        !            13: **
        !            14: */
        !            15: 
        !            16: /* Library include files */
        !            17: #include "wwwsys.h"
        !            18: #include "WWWUtil.h"
        !            19: #include "WWWCore.h"
        !            20: #include "WWWHTTP.h"
        !            21: #include "WWWMIME.h"
        !            22: #include "HTCookie.h"                                   /* Implemented here */
        !            23: 
        !            24: /* Interface to persistent cookie jar */
        !            25: PRIVATE HTCookieSetCallback *  SetCookie = NULL;
        !            26: PRIVATE void *         SetCookieContext = NULL;
        !            27: 
        !            28: PRIVATE HTCookieFindCallback * FindCookie = NULL;
        !            29: PRIVATE void * FindCookieContext = NULL;
        !            30: 
        !            31: /* Are cookies enabled */
        !            32: PRIVATE BOOL baking_cookies = NO;
        !            33: 
        !            34: /* Our cookies */
        !            35: struct _HTCookie {
        !            36:     char *             name;
        !            37:     char *             value;
        !            38:     char *             domain;
        !            39:     char *             path;
        !            40:     time_t             expiration;
        !            41:     BOOL               secure;
        !            42: };
        !            43: 
        !            44: /* Hold all cookies found for a single request */
        !            45: typedef struct _HTCookieHolder {
        !            46:     HTRequest *                request;
        !            47:     HTList *           cookies;
        !            48: } HTCookieHolder;
        !            49: 
        !            50: /* List of current cookie holders */
        !            51: PRIVATE HTList *       cookie_holder = NULL;
        !            52: 
        !            53: /* What should we do with cookies? */
        !            54: PRIVATE HTCookieMode   CookieMode = HT_COOKIE_PROMPT;
        !            55: 
        !            56: /* ------------------------------------------------------------------------- */
        !            57: 
        !            58: PRIVATE HTCookie * HTCookie_new (void)
        !            59: {
        !            60:     HTCookie * me = NULL;
        !            61:     if ((me = (HTCookie *) HT_CALLOC(1, sizeof(HTCookie))) == NULL)
        !            62:         HT_OUTOFMEM("HTCookie_new");
        !            63:     return me;
        !            64: } 
        !            65: 
        !            66: PRIVATE BOOL HTCookie_delete (HTCookie * me)
        !            67: {
        !            68:     if (me) {
        !            69:        HT_FREE(me->name);
        !            70:        HT_FREE(me->value);
        !            71:        HT_FREE(me->domain);
        !            72:        HT_FREE(me->path);
        !            73:        HT_FREE(me);
        !            74:        return YES;
        !            75:     }
        !            76:     return NO;
        !            77: }
        !            78: 
        !            79: PUBLIC BOOL HTCookie_setName (HTCookie * me, const char * name)
        !            80: {
        !            81:     if (me && name) {
        !            82:        me->name = StrAllocCopy(me->name, name);
        !            83:        return YES;
        !            84:     }
        !            85:     return NO;
        !            86: }
        !            87: 
        !            88: PUBLIC char * HTCookie_name (HTCookie * me)
        !            89: {
        !            90:     return me ? me->name : NULL;
        !            91: }
        !            92: 
        !            93: PUBLIC BOOL HTCookie_setValue (HTCookie * me, const char * value)
        !            94: {
        !            95:     if (me && value) {
        !            96:        me->value = StrAllocCopy(me->value, value);
        !            97:        return YES;
        !            98:     }
        !            99:     return NO;
        !           100: }
        !           101: 
        !           102: PUBLIC char * HTCookie_value (HTCookie * me)
        !           103: {
        !           104:     return me ? me->value : NULL;
        !           105: }
        !           106: 
        !           107: PUBLIC BOOL HTCookie_setDomain (HTCookie * me, const char * domain)
        !           108: {
        !           109:     if (me && domain) {
        !           110:        me->domain = StrAllocCopy(me->domain, domain);
        !           111:        return YES;
        !           112:     }
        !           113:     return NO;
        !           114: }
        !           115: 
        !           116: PUBLIC char * HTCookie_domain (HTCookie * me)
        !           117: {
        !           118:     return me ? me->domain : NULL;
        !           119: }
        !           120: 
        !           121: PUBLIC BOOL HTCookie_setPath (HTCookie * me, const char * path)
        !           122: {
        !           123:     if (me && path) {
        !           124:        me->path = StrAllocCopy(me->path, path);
        !           125:        return YES;
        !           126:     }
        !           127:     return NO;
        !           128: }
        !           129: 
        !           130: PUBLIC char * HTCookie_path (HTCookie * me)
        !           131: {
        !           132:     return me ? me->path : NULL;
        !           133: }
        !           134: 
        !           135: PUBLIC time_t HTCookie_setExpiration (HTCookie * me, time_t expiration)
        !           136: {
        !           137:     if (me) {
        !           138:        me->expiration = expiration;
        !           139:        return YES;
        !           140:     }
        !           141:     return NO;
        !           142: }
        !           143: 
        !           144: PUBLIC time_t HTCookie_expiration (HTCookie * me)
        !           145: {
        !           146:     return me ? me->expiration : -1;
        !           147: }
        !           148: 
        !           149: PUBLIC time_t HTCookie_setSecure (HTCookie * me, BOOL secure)
        !           150: {
        !           151:     if (me) {
        !           152:        me->secure = secure;
        !           153:        return YES;
        !           154:     }
        !           155:     return NO;
        !           156: }
        !           157: 
        !           158: PUBLIC BOOL HTCookie_isSecure (HTCookie * me)
        !           159: {
        !           160:     return me ? me->secure : NO;
        !           161: }
        !           162: 
        !           163: /* ------------------------------------------------------------------------- */
        !           164: 
        !           165: PRIVATE BOOL HTCookieHolder_addCookie (HTRequest * request, HTCookie * cookie)
        !           166: {
        !           167:     if (request && cookie) {
        !           168:        HTList * cur = cookie_holder;
        !           169:        HTCookieHolder * pres = NULL;
        !           170: 
        !           171:        /* Make sure that we have a cookie holder list */
        !           172:        if (!cookie_holder) cookie_holder = HTList_new();
        !           173: 
        !           174:        /* See if we already have a cookie holder for this request */
        !           175:        while ((pres = (HTCookieHolder *) HTList_nextObject(cur))) {
        !           176:            if (pres->request == request) break;
        !           177:        }
        !           178: 
        !           179:        /* If found then use existing cookie holder, otherwise create new one */
        !           180:        if (!pres) {
        !           181:            if ((pres = (HTCookieHolder *) HT_CALLOC(1, sizeof(HTCookieHolder))) == NULL)
        !           182:                HT_OUTOFMEM("HTCookieHolder_newCookie");
        !           183:            pres->request = request;
        !           184:            pres->cookies = HTList_new();
        !           185: 
        !           186:            /* Add to cookie holder list */
        !           187:            HTList_addObject(cookie_holder, pres);
        !           188:        }
        !           189: 
        !           190:        /* Now add the cookie */
        !           191:        HTList_addObject(pres->cookies, cookie);
        !           192: 
        !           193:        return YES;
        !           194:     }
        !           195:     return NO;
        !           196: }
        !           197: 
        !           198: PRIVATE HTCookieHolder * HTCookieHolder_find (HTRequest * request)
        !           199: {
        !           200:     if (request) {
        !           201:        HTList * cur = cookie_holder;
        !           202:        HTCookieHolder * pres = NULL;
        !           203:        while ((pres = (HTCookieHolder *) HTList_nextObject(cur))) {
        !           204:            if (pres->request == request) return pres;
        !           205:        }
        !           206:     }
        !           207:     return NULL;
        !           208: }
        !           209: 
        !           210: PRIVATE BOOL HTCookieHolder_delete (HTCookieHolder * me)
        !           211: {
        !           212:     if (me) {
        !           213:        if (me->cookies) {
        !           214:            HTList * cookies = me->cookies;
        !           215:            HTCookie * cookie;
        !           216:            while ((cookie = (HTCookie *) HTList_nextObject(cookies)))
        !           217:                HTCookie_delete(cookie);                    
        !           218:        }
        !           219:        HTList_removeObject(cookie_holder, me);
        !           220:        HT_FREE(me);
        !           221:        return YES;
        !           222:     }
        !           223:     return NO;
        !           224: }
        !           225: 
        !           226: PRIVATE BOOL HTCookieHolder_deleteAll (void)
        !           227: {
        !           228:     if (cookie_holder) {
        !           229:        HTList * cur = cookie_holder;
        !           230:        HTCookieHolder * pres = NULL;
        !           231:        while ((pres = (HTCookieHolder *) HTList_nextObject(cur))) {
        !           232:            HTCookieHolder_delete(pres);
        !           233:        }
        !           234:        HTList_delete(cookie_holder);
        !           235:        cookie_holder = NULL;
        !           236:        return YES;
        !           237:     }
        !           238:     return NO;
        !           239: }
        !           240: 
        !           241: /* ------------------------------------------------------------------------- */
        !           242: 
        !           243: /*
        !           244: **  MIME header parser for the Set-Cookie header field. We parse the cookies
        !           245: **  and create HTCookie objects and store them in the cookie holder so that
        !           246: **  the cookie after filter can deal with them accordingly.
        !           247: */
        !           248: PRIVATE int HTCookie_parseSetCookie (HTRequest * request, HTResponse * response,
        !           249:                                     char * token, char * value)
        !           250: 
        !           251: {
        !           252:     char * cookie_name = HTNextField(&value);
        !           253:     char * cookie_value = HTNextField(&value);
        !           254:     if (cookie_name && *cookie_name && cookie_value) {
        !           255:        HTCookie * cookie = HTCookie_new();
        !           256:        char * param_pair;
        !           257: 
        !           258:        HTCookie_setName(cookie, cookie_name);
        !           259:        HTCookie_setValue(cookie, cookie_value);
        !           260:        
        !           261:        /* Add the cookie to our holder */
        !           262:        HTCookieHolder_addCookie(request, cookie);
        !           263: 
        !           264:        /* Parse cookie parameters */
        !           265:        while ((param_pair = HTNextParam(&value))) {
        !           266:            char * tok = HTNextField(&param_pair);
        !           267:            char * val = param_pair;
        !           268:            if (tok) {
        !           269:                if (!strcasecomp(tok, "expires") && val && *val) {
        !           270:                    HTTRACE(STREAM_TRACE, "Cookie...... Expires `%s\'\n" _ val);
        !           271:                    HTCookie_setExpiration(cookie, HTParseTime(val, NULL, YES));
        !           272:                } else if (!strcasecomp(tok, "domain") && val && *val) {
        !           273:                    HTTRACE(STREAM_TRACE, "Cookie...... Domain `%s\'\n" _ val);
        !           274:                    HTCookie_setDomain(cookie, val);
        !           275:                } else if (!strcasecomp(tok, "path") && val && *val) {
        !           276:                    HTTRACE(STREAM_TRACE, "Cookie...... Path `%s\'\n" _ val);
        !           277:                    HTCookie_setPath(cookie, val);
        !           278:                } else if (!strcasecomp(tok, "secure")) {
        !           279:                    HTTRACE(STREAM_TRACE, "Cookie...... Secure `%s\'\n" _ val);
        !           280:                    HTCookie_setSecure(cookie, YES);
        !           281:                } else
        !           282:                    HTTRACE(STREAM_TRACE, "Cookie...... Unknown `%s\' with value `%s\'\n" _ 
        !           283:                            tok _ val ? val : "<null>");
        !           284:            }
        !           285:        }
        !           286:     }
        !           287:     return HT_OK;
        !           288: }
        !           289: 
        !           290: /*
        !           291: **  Check whether the application provides us with a cookie or more.
        !           292: */
        !           293: PRIVATE int HTCookie_beforeFilter (HTRequest * request, void * param, int mode)
        !           294: {
        !           295:     if (CookieMode!=HT_COOKIE_TOSS && FindCookie) {
        !           296:        HTAssocList * cookies = (*FindCookie)(request, FindCookieContext);
        !           297:        if (cookies) {      
        !           298:            HTChunk * cookie_header = HTChunk_new(64);
        !           299:            HTAssoc * pres;
        !           300:            BOOL first=YES;
        !           301:            while ((pres = (HTAssoc *) HTAssocList_nextObject(cookies))) {              
        !           302:                if (!first) HTChunk_putc(cookie_header, ',');
        !           303:                HTChunk_puts(cookie_header, HTAssoc_name(pres));
        !           304:                HTChunk_putc(cookie_header, '=');
        !           305:                HTChunk_puts(cookie_header, HTAssoc_value(pres));
        !           306:                first = NO;
        !           307:            }
        !           308:            HTRequest_addExtraHeader(request, "Cookie", HTChunk_data(cookie_header));
        !           309:            HTChunk_delete(cookie_header);
        !           310: 
        !           311:            /* Also delete the association list */
        !           312:            HTAssocList_delete(cookies);
        !           313:        }
        !           314:     }
        !           315:     return HT_OK;
        !           316: }
        !           317: 
        !           318: /*
        !           319: **  Check the response to see if we got a cookie or more.
        !           320: **  If so then figure out what to do with it (prompt user, store, etc.)
        !           321: */
        !           322: PRIVATE int HTCookie_afterFilter (HTRequest * request, HTResponse * response,
        !           323:                                  void * param, int status)
        !           324: {
        !           325:     if (CookieMode!=HT_COOKIE_TOSS && SetCookie) {
        !           326:        HTCookieHolder * holder = HTCookieHolder_find(request);
        !           327:        if (holder) {
        !           328:            HTList * cookies = holder->cookies;
        !           329:            HTCookie * pres;
        !           330:            while ((pres = (HTCookie *) HTAssocList_nextObject(cookies))) {
        !           331: 
        !           332:                /* check to see if we should prompt user here */
        !           333: 
        !           334:                (*SetCookie)(request, pres, SetCookieContext);
        !           335:            }
        !           336:            
        !           337:            /* Delete cookie holder */
        !           338:            HTCookieHolder_delete(holder);
        !           339:        }
        !           340:     }
        !           341:     return HT_OK;
        !           342: }
        !           343: 
        !           344: /* ------------------------------------------------------------------------- */
        !           345: 
        !           346: /*
        !           347: **  Start and stop the cookie engine
        !           348: */
        !           349: PUBLIC BOOL HTCookie_init (void)
        !           350: {
        !           351:     if (!baking_cookies) {
        !           352: 
        !           353:        /* Register the SetCookie header parser */
        !           354:        HTHeader_addParser("Set-Cookie", NO, HTCookie_parseSetCookie);
        !           355: 
        !           356:        /* Register the cookie before and after filters */
        !           357:        HTNet_addBefore(HTCookie_beforeFilter, "http://*", NULL, HT_FILTER_MIDDLE);
        !           358:        HTNet_addAfter(HTCookie_afterFilter, "http://*", NULL, HT_ALL, HT_FILTER_MIDDLE);
        !           359: 
        !           360:        baking_cookies = YES;
        !           361:        return YES;
        !           362:     }
        !           363:     return NO;
        !           364: }
        !           365: 
        !           366: PUBLIC BOOL HTCookie_terminate (void)
        !           367: {
        !           368:     /* Unregister Set-Cookie header parser */
        !           369:     HTHeader_deleteParser("Set-Cookie");
        !           370: 
        !           371:     /* Unregister the cookie before and after filters */
        !           372:     HTNet_deleteBefore(HTCookie_beforeFilter);
        !           373:     HTNet_deleteAfter(HTCookie_afterFilter);
        !           374: 
        !           375:     /* Delete all pending cookies */
        !           376:     HTCookieHolder_deleteAll();
        !           377:     return YES;
        !           378: }
        !           379: 
        !           380: PUBLIC BOOL HTCookie_setCookieMode (HTCookieMode mode)
        !           381: {
        !           382:     CookieMode = mode;
        !           383:     return YES;
        !           384: }
        !           385: 
        !           386: /*
        !           387: **  Callbacks can be used by the application to set and retrieve cookies
        !           388: **  from a persistent cookie jar as libwww doesn't provide a persistent
        !           389: **  storage for this kind of thing and they probably should be secured
        !           390: **  anyway.
        !           391: */
        !           392: PUBLIC BOOL HTCookie_setCallbacks (HTCookieSetCallback *       setCookie,
        !           393:                                   void *                       setCookieContext,
        !           394:                                   HTCookieFindCallback *       findCookie,
        !           395:                                   void *                       findCookieContext)
        !           396: {
        !           397:     if (setCookie && findCookie) {
        !           398:        HTTRACE(APP_TRACE, "Cookie...... Registering cookie callbacks\n");
        !           399:        SetCookie = setCookie;
        !           400:        SetCookieContext = setCookieContext;
        !           401: 
        !           402:        FindCookie = findCookie;
        !           403:        FindCookieContext = findCookieContext;
        !           404:        return YES;
        !           405:     }
        !           406:     return NO;
        !           407: }
        !           408: 
        !           409: PUBLIC BOOL HTCookie_deleteCallbacks (void)
        !           410: {
        !           411:     HTTRACE(APP_TRACE, "Cookie...... Unregistering cookie callbacks\n");
        !           412:     SetCookie = NULL;
        !           413:     SetCookieContext = NULL;
        !           414:     FindCookie = NULL;
        !           415:     FindCookieContext = NULL;
        !           416:     return YES;
        !           417: }

Webmaster