~ubuntu-branches/ubuntu/warty/curl/warty

« back to all changes in this revision

Viewing changes to lib/cookie.c

  • Committer: Bazaar Package Importer
  • Author(s): Domenico Andreoli
  • Date: 2002-03-12 19:06:21 UTC
  • Revision ID: james.westby@ubuntu.com-20020312190621-iqx7k9cipo5d0ifr
Tags: upstream-7.9.5
ImportĀ upstreamĀ versionĀ 7.9.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 *                                  _   _ ____  _     
 
3
 *  Project                     ___| | | |  _ \| |    
 
4
 *                             / __| | | | |_) | |    
 
5
 *                            | (__| |_| |  _ <| |___ 
 
6
 *                             \___|\___/|_| \_\_____|
 
7
 *
 
8
 * Copyright (C) 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
 
9
 *
 
10
 * In order to be useful for every potential user, curl and libcurl are
 
11
 * dual-licensed under the MPL and the MIT/X-derivate licenses.
 
12
 *
 
13
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 
14
 * copies of the Software, and permit persons to whom the Software is
 
15
 * furnished to do so, under the terms of the MPL or the MIT/X-derivate
 
16
 * licenses. You may pick one of these licenses.
 
17
 *
 
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 
19
 * KIND, either express or implied.
 
20
 *
 
21
 * $Id: cookie.c,v 1.31 2002/02/27 07:38:04 bagder Exp $
 
22
 *****************************************************************************/
 
23
 
 
24
/***
 
25
 
 
26
 
 
27
RECEIVING COOKIE INFORMATION
 
28
============================
 
29
 
 
30
struct CookieInfo *cookie_init(char *file);
 
31
        
 
32
        Inits a cookie struct to store data in a local file. This is always
 
33
        called before any cookies are set.
 
34
 
 
35
int cookies_set(struct CookieInfo *cookie, char *cookie_line);
 
36
 
 
37
        The 'cookie_line' parameter is a full "Set-cookie:" line as
 
38
        received from a server.
 
39
 
 
40
        The function need to replace previously stored lines that this new
 
41
        line superceeds.
 
42
 
 
43
        It may remove lines that are expired.
 
44
 
 
45
        It should return an indication of success/error.
 
46
 
 
47
 
 
48
SENDING COOKIE INFORMATION
 
49
==========================
 
50
 
 
51
struct Cookies *cookie_getlist(struct CookieInfo *cookie,
 
52
                               char *host, char *path, bool secure);
 
53
 
 
54
        For a given host and path, return a linked list of cookies that
 
55
        the client should send to the server if used now. The secure
 
56
        boolean informs the cookie if a secure connection is achieved or
 
57
        not.
 
58
 
 
59
        It shall only return cookies that haven't expired.
 
60
 
 
61
    
 
62
Example set of cookies:
 
63
    
 
64
    Set-cookie: PRODUCTINFO=webxpress; domain=.fidelity.com; path=/; secure
 
65
    Set-cookie: PERSONALIZE=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
 
66
    domain=.fidelity.com; path=/ftgw; secure
 
67
    Set-cookie: FidHist=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
 
68
    domain=.fidelity.com; path=/; secure
 
69
    Set-cookie: FidOrder=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
 
70
    domain=.fidelity.com; path=/; secure
 
71
    Set-cookie: DisPend=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
 
72
    domain=.fidelity.com; path=/; secure
 
73
    Set-cookie: FidDis=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
 
74
    domain=.fidelity.com; path=/; secure
 
75
    Set-cookie:
 
76
    Session_Key@6791a9e0-901a-11d0-a1c8-9b012c88aa77=none;expires=Monday,
 
77
    13-Jun-1988 03:04:55 GMT; domain=.fidelity.com; path=/; secure
 
78
****/
 
79
 
 
80
#include "setup.h"
 
81
 
 
82
#include <stdlib.h>
 
83
#include <string.h>
 
84
#include <ctype.h>
 
85
 
 
86
#include "cookie.h"
 
87
#include "getdate.h"
 
88
#include "strequal.h"
 
89
#include "strtok.h"
 
90
 
 
91
/* The last #include file should be: */
 
92
#ifdef MALLOCDEBUG
 
93
#include "memdebug.h"
 
94
#endif
 
95
 
 
96
/****************************************************************************
 
97
 *
 
98
 * Curl_cookie_add()
 
99
 *
 
100
 * Add a single cookie line to the cookie keeping object.
 
101
 *
 
102
 ***************************************************************************/
 
103
 
 
104
struct Cookie *
 
105
Curl_cookie_add(struct CookieInfo *c,
 
106
                bool httpheader, /* TRUE if HTTP header-style line */
 
107
                char *lineptr,   /* first non-space of the line */
 
108
                char *domain)    /* default domain */
 
109
{
 
110
  struct Cookie *clist;
 
111
  char what[MAX_COOKIE_LINE];
 
112
  char name[MAX_NAME];
 
113
  char *ptr;
 
114
  char *semiptr;
 
115
  struct Cookie *co;
 
116
  struct Cookie *lastc=NULL;
 
117
  time_t now = time(NULL);
 
118
  bool replace_old = FALSE;
 
119
 
 
120
  /* First, alloc and init a new struct for it */
 
121
  co = (struct Cookie *)malloc(sizeof(struct Cookie));
 
122
  if(!co)
 
123
    return NULL; /* bail out if we're this low on memory */
 
124
 
 
125
  /* clear the whole struct first */
 
126
  memset(co, 0, sizeof(struct Cookie));
 
127
            
 
128
  if(httpheader) {
 
129
    /* This line was read off a HTTP-header */
 
130
    char *sep;
 
131
    semiptr=strchr(lineptr, ';'); /* first, find a semicolon */
 
132
    ptr = lineptr;
 
133
    do {
 
134
      /* we have a <what>=<this> pair or a 'secure' word here */
 
135
      sep = strchr(ptr, '=');
 
136
      if(sep && (!semiptr || (semiptr>sep)) ) {
 
137
        /*
 
138
         * There is a = sign and if there was a semicolon too, which make sure
 
139
         * that the semicolon comes _after_ the equal sign.
 
140
         */
 
141
 
 
142
        name[0]=what[0]=0; /* init the buffers */
 
143
        if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;=]=%"
 
144
                       MAX_COOKIE_LINE_TXT "[^;\r\n]",
 
145
                       name, what)) {
 
146
          /* this is a <name>=<what> pair */
 
147
 
 
148
          /* Strip off trailing whitespace from the 'what' */
 
149
          int len=strlen(what);
 
150
          while(len && isspace((int)what[len-1])) {
 
151
            what[len-1]=0;
 
152
            len--;
 
153
          }
 
154
 
 
155
          if(strequal("path", name)) {
 
156
            co->path=strdup(what);
 
157
          }
 
158
          else if(strequal("domain", name)) {
 
159
            co->domain=strdup(what);
 
160
            co->field1= (what[0]=='.')?2:1;
 
161
          }
 
162
          else if(strequal("version", name)) {
 
163
            co->version=strdup(what);
 
164
          }
 
165
          else if(strequal("max-age", name)) {
 
166
            /* Defined in RFC2109:
 
167
 
 
168
               Optional.  The Max-Age attribute defines the lifetime of the
 
169
               cookie, in seconds.  The delta-seconds value is a decimal non-
 
170
               negative integer.  After delta-seconds seconds elapse, the
 
171
               client should discard the cookie.  A value of zero means the
 
172
               cookie should be discarded immediately.
 
173
 
 
174
             */
 
175
            co->maxage = strdup(what);
 
176
            co->expires =
 
177
              atoi((*co->maxage=='\"')?&co->maxage[1]:&co->maxage[0]) + now;
 
178
          }
 
179
          else if(strequal("expires", name)) {
 
180
            co->expirestr=strdup(what);
 
181
            co->expires = curl_getdate(what, &now);
 
182
          }
 
183
          else if(!co->name) {
 
184
            co->name = strdup(name);
 
185
            co->value = strdup(what);
 
186
          }
 
187
          /*
 
188
            else this is the second (or more) name we don't know
 
189
            about! */
 
190
        }
 
191
        else {
 
192
          /* this is an "illegal" <what>=<this> pair */
 
193
        }
 
194
      }
 
195
      else {
 
196
        if(sscanf(ptr, "%" MAX_COOKIE_LINE_TXT "[^;\r\n]",
 
197
                  what)) {
 
198
          if(strequal("secure", what))
 
199
            co->secure = TRUE;
 
200
          /* else,
 
201
             unsupported keyword without assign! */
 
202
 
 
203
        }
 
204
      }
 
205
      if(!semiptr || !*semiptr) {
 
206
        /* we already know there are no more cookies */
 
207
        semiptr = NULL;
 
208
        continue;
 
209
      }
 
210
 
 
211
      ptr=semiptr+1;
 
212
      while(ptr && *ptr && isspace((int)*ptr))
 
213
        ptr++;
 
214
      semiptr=strchr(ptr, ';'); /* now, find the next semicolon */
 
215
 
 
216
      if(!semiptr && *ptr)
 
217
        /* There are no more semicolons, but there's a final name=value pair
 
218
           coming up */
 
219
        semiptr=strchr(ptr, '\0');
 
220
    } while(semiptr);
 
221
 
 
222
    if(NULL == co->name) {
 
223
      /* we didn't get a cookie name, this is an illegal line, bail out */
 
224
      if(co->domain)
 
225
        free(co->domain);
 
226
      if(co->path)
 
227
        free(co->path);
 
228
      if(co->name)
 
229
        free(co->name);
 
230
      if(co->value)
 
231
        free(co->value);
 
232
      free(co);
 
233
      return NULL;
 
234
    }
 
235
 
 
236
    if(NULL == co->domain)
 
237
      /* no domain given in the header line, set the default now */
 
238
      co->domain=domain?strdup(domain):NULL;
 
239
  }
 
240
  else {
 
241
    /* This line is NOT a HTTP header style line, we do offer support for
 
242
       reading the odd netscape cookies-file format here */
 
243
    char *firstptr;
 
244
    char *tok_buf;
 
245
    int fields;
 
246
 
 
247
    if(lineptr[0]=='#') {
 
248
      /* don't even try the comments */
 
249
      free(co);
 
250
      return NULL;
 
251
    }
 
252
    /* strip off the possible end-of-line characters */
 
253
    ptr=strchr(lineptr, '\r');
 
254
    if(ptr)
 
255
      *ptr=0; /* clear it */
 
256
    ptr=strchr(lineptr, '\n');
 
257
    if(ptr)
 
258
      *ptr=0; /* clear it */
 
259
 
 
260
    firstptr=strtok_r(lineptr, "\t", &tok_buf); /* first tokenize it on the TAB */
 
261
 
 
262
    /* Here's a quick check to eliminate normal HTTP-headers from this */
 
263
    if(!firstptr || strchr(firstptr, ':')) {
 
264
      free(co);
 
265
      return NULL;
 
266
    }
 
267
 
 
268
    /* Now loop through the fields and init the struct we already have
 
269
       allocated */
 
270
    for(ptr=firstptr, fields=0; ptr; ptr=strtok_r(NULL, "\t", &tok_buf), fields++) {
 
271
      switch(fields) {
 
272
      case 0:
 
273
        co->domain = strdup(ptr);
 
274
        break;
 
275
      case 1:
 
276
        /* This field got its explanation on the 23rd of May 2001 by
 
277
           Andrļæ½s Garcļæ½a:
 
278
 
 
279
           flag: A TRUE/FALSE value indicating if all machines within a given
 
280
           domain can access the variable. This value is set automatically by
 
281
           the browser, depending on the value you set for the domain.
 
282
 
 
283
           As far as I can see, it is set to true when the cookie says
 
284
           .domain.com and to false when the domain is complete www.domain.com
 
285
 
 
286
           We don't currently take advantage of this knowledge.
 
287
        */
 
288
        co->field1=strequal(ptr, "TRUE")+1; /* store information */
 
289
        break;
 
290
      case 2:
 
291
        /* It turns out, that sometimes the file format allows the path
 
292
           field to remain not filled in, we try to detect this and work
 
293
           around it! Andrļæ½s Garcļæ½a made us aware of this... */
 
294
        if (strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) {
 
295
          /* only if the path doesn't look like a boolean option! */
 
296
          co->path = strdup(ptr);
 
297
          break;
 
298
        }
 
299
        /* this doesn't look like a path, make one up! */
 
300
        co->path = strdup("/");
 
301
        fields++; /* add a field and fall down to secure */
 
302
        /* FALLTHROUGH */
 
303
      case 3:
 
304
        co->secure = strequal(ptr, "TRUE");
 
305
        break;
 
306
      case 4:
 
307
        co->expires = atoi(ptr);
 
308
        break;
 
309
      case 5:
 
310
        co->name = strdup(ptr);
 
311
        break;
 
312
      case 6:
 
313
        co->value = strdup(ptr);
 
314
        break;
 
315
      }
 
316
    }
 
317
 
 
318
    if(7 != fields) {
 
319
      /* we did not find the sufficient number of fields to recognize this
 
320
         as a valid line, abort and go home */
 
321
 
 
322
      if(co->domain)
 
323
        free(co->domain);
 
324
      if(co->path)
 
325
        free(co->path);
 
326
      if(co->name)
 
327
        free(co->name);
 
328
      if(co->value)
 
329
        free(co->value);
 
330
 
 
331
      free(co);
 
332
      return NULL;
 
333
    }
 
334
 
 
335
  }
 
336
 
 
337
  co->livecookie = c->running;
 
338
 
 
339
  /* now, we have parsed the incoming line, we must now check if this
 
340
     superceeds an already existing cookie, which it may if the previous have
 
341
     the same domain and path as this */
 
342
 
 
343
  clist = c->cookies;
 
344
  replace_old = FALSE;
 
345
  while(clist) {
 
346
    if(strequal(clist->name, co->name)) {
 
347
      /* the names are identical */
 
348
 
 
349
      if(clist->domain && co->domain) {
 
350
        if(strequal(clist->domain, co->domain))
 
351
          replace_old=TRUE;
 
352
      }
 
353
      else if(!clist->domain && !co->domain)
 
354
        replace_old = TRUE;
 
355
 
 
356
      if(replace_old) {
 
357
        /* the domains were identical */
 
358
 
 
359
        if(clist->path && co->path) {
 
360
          if(strequal(clist->path, co->path)) {
 
361
            replace_old = TRUE;
 
362
          }
 
363
          else
 
364
            replace_old = FALSE;
 
365
        }
 
366
        else if(!clist->path && !co->path)
 
367
          replace_old = TRUE;
 
368
        else
 
369
          replace_old = FALSE;
 
370
        
 
371
      }
 
372
 
 
373
      if(replace_old && !co->livecookie && clist->livecookie) {
 
374
        /* Both cookies matched fine, except that the already present
 
375
           cookie is "live", which means it was set from a header, while
 
376
           the new one isn't "live" and thus only read from a file. We let
 
377
           live cookies stay alive */
 
378
 
 
379
        /* Free the newcomer and get out of here! */
 
380
        if(co->domain)
 
381
          free(co->domain);
 
382
        if(co->path)
 
383
          free(co->path);
 
384
        if(co->name)
 
385
          free(co->name);
 
386
        if(co->value)
 
387
          free(co->value);
 
388
 
 
389
        free(co);
 
390
        return NULL;
 
391
      }
 
392
 
 
393
      if(replace_old) {
 
394
        co->next = clist->next; /* get the next-pointer first */
 
395
 
 
396
        /* then free all the old pointers */
 
397
        if(clist->name)
 
398
          free(clist->name);
 
399
        if(clist->value)
 
400
          free(clist->value);
 
401
        if(clist->domain)
 
402
          free(clist->domain);
 
403
        if(clist->path)
 
404
          free(clist->path);
 
405
        if(clist->expirestr)
 
406
          free(clist->expirestr);
 
407
 
 
408
        if(clist->version)
 
409
          free(clist->version);
 
410
        if(clist->maxage)
 
411
          free(clist->maxage);
 
412
 
 
413
        *clist = *co;  /* then store all the new data */
 
414
 
 
415
        free(co);   /* free the newly alloced memory */
 
416
        co = clist; /* point to the previous struct instead */
 
417
 
 
418
        /* We have replaced a cookie, now skip the rest of the list but
 
419
           make sure the 'lastc' pointer is properly set */
 
420
        do {
 
421
          lastc = clist;
 
422
          clist = clist->next;
 
423
        } while(clist);
 
424
        break;
 
425
      }
 
426
    }
 
427
    lastc = clist;
 
428
    clist = clist->next;
 
429
  }
 
430
 
 
431
  if(!replace_old) {
 
432
    /* then make the last item point on this new one */
 
433
    if(lastc)
 
434
      lastc->next = co;
 
435
    else
 
436
      c->cookies = co;
 
437
  }
 
438
 
 
439
  c->numcookies++; /* one more cookie in the jar */
 
440
 
 
441
  return co;
 
442
}
 
443
 
 
444
/*****************************************************************************
 
445
 *
 
446
 * Curl_cookie_init()
 
447
 *
 
448
 * Inits a cookie struct to read data from a local file. This is always
 
449
 * called before any cookies are set. File may be NULL.
 
450
 *
 
451
 ****************************************************************************/
 
452
struct CookieInfo *Curl_cookie_init(char *file, struct CookieInfo *inc)
 
453
{
 
454
  char line[MAX_COOKIE_LINE];
 
455
  struct CookieInfo *c;
 
456
  FILE *fp;
 
457
  bool fromfile=TRUE;
 
458
  
 
459
  if(NULL == inc) {
 
460
    /* we didn't get a struct, create one */
 
461
    c = (struct CookieInfo *)malloc(sizeof(struct CookieInfo));
 
462
    if(!c)
 
463
      return NULL; /* failed to get memory */
 
464
    memset(c, 0, sizeof(struct CookieInfo));
 
465
    c->filename = strdup(file?file:"none"); /* copy the name just in case */
 
466
  }
 
467
  else {
 
468
    /* we got an already existing one, use that */
 
469
    c = inc;
 
470
  }
 
471
  c->running = FALSE; /* this is not running, this is init */
 
472
 
 
473
  if(file && strequal(file, "-")) {
 
474
    fp = stdin;
 
475
    fromfile=FALSE;
 
476
  }
 
477
  else
 
478
    fp = file?fopen(file, "r"):NULL;
 
479
 
 
480
  if(fp) {
 
481
    char *lineptr;
 
482
    bool headerline;
 
483
    while(fgets(line, MAX_COOKIE_LINE, fp)) {
 
484
      if(strnequal("Set-Cookie:", line, 11)) {
 
485
        /* This is a cookie line, get it! */
 
486
        lineptr=&line[11];
 
487
        headerline=TRUE;
 
488
      }
 
489
      else {
 
490
        lineptr=line;
 
491
        headerline=FALSE;
 
492
      }
 
493
      while(*lineptr && isspace((int)*lineptr))
 
494
        lineptr++;
 
495
 
 
496
      Curl_cookie_add(c, headerline, lineptr, NULL);
 
497
    }
 
498
    if(fromfile)
 
499
      fclose(fp);
 
500
  }
 
501
 
 
502
  c->running = TRUE; /* now, we're running */
 
503
 
 
504
  return c;
 
505
}
 
506
 
 
507
/*****************************************************************************
 
508
 *
 
509
 * Curl_cookie_getlist()
 
510
 *
 
511
 * For a given host and path, return a linked list of cookies that the
 
512
 * client should send to the server if used now. The secure boolean informs
 
513
 * the cookie if a secure connection is achieved or not.
 
514
 *
 
515
 * It shall only return cookies that haven't expired.
 
516
 *
 
517
 ****************************************************************************/
 
518
 
 
519
struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
 
520
                                   char *host, char *path, bool secure)
 
521
{
 
522
   struct Cookie *newco;
 
523
   struct Cookie *co;
 
524
   time_t now = time(NULL);
 
525
   int hostlen=strlen(host);
 
526
   int domlen;
 
527
 
 
528
   struct Cookie *mainco=NULL;
 
529
 
 
530
   if(!c || !c->cookies)
 
531
      return NULL; /* no cookie struct or no cookies in the struct */
 
532
 
 
533
   co = c->cookies;
 
534
 
 
535
   while(co) {
 
536
      /* only process this cookie if it is not expired or had no expire
 
537
         date AND that if the cookie requires we're secure we must only
 
538
         continue if we are! */
 
539
     if( (co->expires<=0 || (co->expires> now)) &&
 
540
         (co->secure?secure:TRUE) ) {
 
541
 
 
542
         /* now check if the domain is correct */
 
543
         domlen=co->domain?strlen(co->domain):0;
 
544
         if(!co->domain ||
 
545
            ((domlen<=hostlen) &&
 
546
             strequal(host+(hostlen-domlen), co->domain)) ) {
 
547
            /* the right part of the host matches the domain stuff in the
 
548
               cookie data */
 
549
 
 
550
            /* now check the left part of the path with the cookies path
 
551
               requirement */
 
552
            if(!co->path ||
 
553
               strnequal(path, co->path, strlen(co->path))) {
 
554
 
 
555
               /* and now, we know this is a match and we should create an
 
556
                  entry for the return-linked-list */
 
557
 
 
558
               newco = (struct Cookie *)malloc(sizeof(struct Cookie));
 
559
               if(newco) {
 
560
                  /* first, copy the whole source cookie: */
 
561
                  memcpy(newco, co, sizeof(struct Cookie));
 
562
 
 
563
                  /* then modify our next */
 
564
                  newco->next = mainco;
 
565
 
 
566
                  /* point the main to us */
 
567
                  mainco = newco;
 
568
               }
 
569
            }
 
570
         }
 
571
      }
 
572
      co = co->next;
 
573
   }
 
574
 
 
575
   return mainco; /* return the new list */
 
576
}
 
577
 
 
578
 
 
579
/*****************************************************************************
 
580
 *
 
581
 * Curl_cookie_freelist()
 
582
 *
 
583
 * Free a list of cookies previously returned by Curl_cookie_getlist();
 
584
 *
 
585
 ****************************************************************************/
 
586
 
 
587
void Curl_cookie_freelist(struct Cookie *co)
 
588
{
 
589
   struct Cookie *next;
 
590
   if(co) {
 
591
      while(co) {
 
592
         next = co->next;
 
593
         free(co); /* we only free the struct since the "members" are all
 
594
                      just copied! */
 
595
         co = next;
 
596
      }
 
597
   }
 
598
}
 
599
 
 
600
/*****************************************************************************
 
601
 *
 
602
 * Curl_cookie_cleanup()
 
603
 *
 
604
 * Free a "cookie object" previous created with cookie_init().
 
605
 *
 
606
 ****************************************************************************/
 
607
void Curl_cookie_cleanup(struct CookieInfo *c)
 
608
{
 
609
   struct Cookie *co;
 
610
   struct Cookie *next;
 
611
   if(c) {
 
612
      if(c->filename)
 
613
         free(c->filename);
 
614
      co = c->cookies;
 
615
 
 
616
      while(co) {
 
617
         if(co->name)
 
618
            free(co->name);
 
619
         if(co->value)
 
620
            free(co->value);
 
621
         if(co->domain)
 
622
            free(co->domain);
 
623
         if(co->path)
 
624
            free(co->path);
 
625
         if(co->expirestr)
 
626
            free(co->expirestr);
 
627
 
 
628
         if(co->version)
 
629
            free(co->version);
 
630
         if(co->maxage)
 
631
            free(co->maxage);
 
632
 
 
633
         next = co->next;
 
634
         free(co);
 
635
         co = next;
 
636
      }
 
637
      free(c); /* free the base struct as well */
 
638
   }
 
639
}
 
640
 
 
641
/*
 
642
 * Curl_cookie_output()
 
643
 *
 
644
 * Writes all internally known cookies to the specified file. Specify
 
645
 * "-" as file name to write to stdout.
 
646
 *
 
647
 * The function returns non-zero on write failure.
 
648
 */
 
649
int Curl_cookie_output(struct CookieInfo *c, char *dumphere)
 
650
{
 
651
  struct Cookie *co;
 
652
  FILE *out;
 
653
  bool use_stdout=FALSE;
 
654
 
 
655
  if((NULL == c) || (0 == c->numcookies))
 
656
    /* If there are no known cookies, we don't write or even create any
 
657
       destination file */
 
658
    return 0;
 
659
 
 
660
  if(strequal("-", dumphere)) {
 
661
    /* use stdout */
 
662
    out = stdout;
 
663
    use_stdout=TRUE;
 
664
  }
 
665
  else {
 
666
    out = fopen(dumphere, "w");
 
667
    if(!out)
 
668
      return 1; /* failure */
 
669
  }
 
670
 
 
671
  if(c) {
 
672
    fputs("# Netscape HTTP Cookie File\n"
 
673
          "# http://www.netscape.com/newsref/std/cookie_spec.html\n"
 
674
          "# This file was generated by libcurl! Edit at your own risk.\n\n",
 
675
          out);
 
676
    co = c->cookies;
 
677
     
 
678
    while(co) {
 
679
      fprintf(out,
 
680
              "%s\t" /* domain */
 
681
              "%s\t" /* field1 */
 
682
              "%s\t" /* path */
 
683
              "%s\t" /* secure */
 
684
              "%u\t" /* expires */
 
685
              "%s\t" /* name */
 
686
              "%s\n", /* value */
 
687
              co->domain?co->domain:"unknown",
 
688
              co->field1==2?"TRUE":"FALSE",
 
689
              co->path?co->path:"/",
 
690
              co->secure?"TRUE":"FALSE",
 
691
              (unsigned int)co->expires,
 
692
              co->name,
 
693
              co->value?co->value:"");
 
694
 
 
695
      co=co->next;
 
696
    }
 
697
  }
 
698
 
 
699
  if(!use_stdout)
 
700
    fclose(out);
 
701
 
 
702
  return 0;
 
703
}
 
704
 
 
705
#ifdef CURL_COOKIE_DEBUG
 
706
 
 
707
/*
 
708
 * On my Solaris box, this command line builds this test program:
 
709
 *
 
710
 * gcc -g -o cooktest -DCURL_COOKIE_DEBUG -DHAVE_CONFIG_H -I.. -I../include cookie.c strequal.o getdate.o memdebug.o mprintf.o strtok.o -lnsl -lsocket
 
711
 *
 
712
 */
 
713
 
 
714
int main(int argc, char **argv)
 
715
{
 
716
  struct CookieInfo *c=NULL;
 
717
  if(argc>1) {
 
718
    c = Curl_cookie_init(argv[1], c);
 
719
    Curl_cookie_add(c, TRUE, "PERSONALIZE=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=.fidelity.com; path=/ftgw; secure");
 
720
    Curl_cookie_add(c, TRUE, "foobar=yes; domain=.haxx.se; path=/looser;");
 
721
    c = Curl_cookie_init(argv[1], c);
 
722
 
 
723
    Curl_cookie_output(c);
 
724
    Curl_cookie_cleanup(c);
 
725
    return 0;
 
726
  }
 
727
  return 1;
 
728
}
 
729
 
 
730
#endif
 
731
 
 
732
/*
 
733
 * local variables:
 
734
 * eval: (load-file "../curl-mode.el")
 
735
 * end:
 
736
 * vim600: fdm=marker
 
737
 * vim: et sw=2 ts=2 sts=2 tw=78
 
738
 */