doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
cookie.c
Go to the documentation of this file.
1 /***************************************************************************
2  * _ _ ____ _
3  * Project ___| | | | _ \| |
4  * / __| | | | |_) | |
5  * | (__| |_| | _ <| |___
6  * \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at http://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
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.52 2004/03/10 09:41:37 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 
81 #include "setup.h"
82 
83 #ifndef CURL_DISABLE_HTTP
84 
85 #include <stdlib.h>
86 #include <string.h>
87 #include <ctype.h>
88 
89 #include "urldata.h"
90 #include "cookie.h"
91 #include "getdate.h"
92 #include "strequal.h"
93 #include "strtok.h"
94 #include "sendf.h"
95 
96 /* The last #include file should be: */
97 #ifdef CURLDEBUG
98 #include "memdebug.h"
99 #endif
100 
101 static void
102 free_cookiemess(struct Cookie *co)
103 {
104  if(co->domain)
105  free(co->domain);
106  if(co->path)
107  free(co->path);
108  if(co->name)
109  free(co->name);
110  if(co->value)
111  free(co->value);
112 
113  free(co);
114 }
115 
116 static bool tailmatch(const char *little, const char *bigone)
117 {
118  size_t littlelen = strlen(little);
119  size_t biglen = strlen(bigone);
120 
121  if(littlelen > biglen)
122  return FALSE;
123 
124  return (bool)strequal(little, bigone+biglen-littlelen);
125 }
126 
127 /****************************************************************************
128  *
129  * Curl_cookie_add()
130  *
131  * Add a single cookie line to the cookie keeping object.
132  *
133  ***************************************************************************/
134 
135 struct Cookie *
137  /* The 'data' pointer here may be NULL at times, and thus
138  must only be used very carefully for things that can deal
139  with data being NULL. Such as infof() and similar */
140 
141  struct CookieInfo *c,
142  bool httpheader, /* TRUE if HTTP header-style line */
143  char *lineptr, /* first character of the line */
144  char *domain, /* default domain */
145  char *path) /* full path used when this cookie is set,
146  used to get default path for the cookie
147  unless set */
148 {
149  struct Cookie *clist;
150  char what[MAX_COOKIE_LINE];
151  char name[MAX_NAME];
152  char *ptr;
153  char *semiptr;
154  struct Cookie *co;
155  struct Cookie *lastc=NULL;
156  time_t now = time(NULL);
157  bool replace_old = FALSE;
158  bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
159 
160  /* First, alloc and init a new struct for it */
161  co = (struct Cookie *)calloc(sizeof(struct Cookie), 1);
162  if(!co)
163  return NULL; /* bail out if we're this low on memory */
164 
165  if(httpheader) {
166  /* This line was read off a HTTP-header */
167  char *sep;
168  semiptr=strchr(lineptr, ';'); /* first, find a semicolon */
169 
170  while(*lineptr && isspace((int)*lineptr))
171  lineptr++;
172 
173  ptr = lineptr;
174  do {
175  /* we have a <what>=<this> pair or a 'secure' word here */
176  sep = strchr(ptr, '=');
177  if(sep && (!semiptr || (semiptr>sep)) ) {
178  /*
179  * There is a = sign and if there was a semicolon too, which make sure
180  * that the semicolon comes _after_ the equal sign.
181  */
182 
183  name[0]=what[0]=0; /* init the buffers */
184  if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;=]=%"
185  MAX_COOKIE_LINE_TXT "[^;\r\n]",
186  name, what)) {
187  /* this is a <name>=<what> pair */
188 
189  char *whatptr;
190 
191  /* Strip off trailing whitespace from the 'what' */
192  size_t len=strlen(what);
193  while(len && isspace((int)what[len-1])) {
194  what[len-1]=0;
195  len--;
196  }
197 
198  /* Skip leading whitespace from the 'what' */
199  whatptr=what;
200  while(isspace((int)*whatptr)) {
201  whatptr++;
202  }
203 
204  if(strequal("path", name)) {
205  co->path=strdup(whatptr);
206  }
207  else if(strequal("domain", name)) {
208  /* note that this name may or may not have a preceeding dot, but
209  we don't care about that, we treat the names the same anyway */
210 
211  const char *domptr=whatptr;
212  int dotcount=1;
213  unsigned int i;
214 
215  static const char *seventhree[]= {
216  "com", "edu", "net", "org", "gov", "mil", "int"
217  };
218 
219  /* Count the dots, we need to make sure that there are THREE dots
220  in the normal domains, or TWO in the seventhree-domains. */
221 
222  if('.' == whatptr[0])
223  /* don't count the initial dot, assume it */
224  domptr++;
225 
226  do {
227  domptr = strchr(domptr, '.');
228  if(domptr) {
229  domptr++;
230  dotcount++;
231  }
232  } while(domptr);
233 
234  for(i=0;
235  i<sizeof(seventhree)/sizeof(seventhree[0]); i++) {
236  if(tailmatch(seventhree[i], whatptr)) {
237  dotcount++; /* we allow one dot less for these */
238  break;
239  }
240  }
241  /* The original Netscape cookie spec defined that this domain name
242  MUST have three dots (or two if one of the seven holy TLDs),
243  but it seems that these kinds of cookies are in use "out there"
244  so we cannot be that strict. I've therefore lowered the check
245  to not allow less than two dots. */
246 
247  if(dotcount < 2) {
248  /* Received and skipped a cookie with a domain using too few
249  dots. */
250  badcookie=TRUE; /* mark this as a bad cookie */
251  infof(data, "skipped cookie with illegal dotcount domain: %s",
252  whatptr);
253  }
254  else {
255  /* Now, we make sure that our host is within the given domain,
256  or the given domain is not valid and thus cannot be set. */
257 
258  if(!domain || tailmatch(whatptr, domain)) {
259  const char *tailptr=whatptr;
260  if(tailptr[0] == '.')
261  tailptr++;
262  co->domain=strdup(tailptr); /* don't prefix w/dots internally */
263  co->tailmatch=TRUE; /* we always do that if the domain name was
264  given */
265  }
266  else {
267  /* we did not get a tailmatch and then the attempted set domain
268  is not a domain to which the current host belongs. Mark as
269  bad. */
270  badcookie=TRUE;
271  infof(data, "skipped cookie with bad tailmatch domain: %s",
272  whatptr);
273  }
274  }
275  }
276  else if(strequal("version", name)) {
277  co->version=strdup(whatptr);
278  }
279  else if(strequal("max-age", name)) {
280  /* Defined in RFC2109:
281 
282  Optional. The Max-Age attribute defines the lifetime of the
283  cookie, in seconds. The delta-seconds value is a decimal non-
284  negative integer. After delta-seconds seconds elapse, the
285  client should discard the cookie. A value of zero means the
286  cookie should be discarded immediately.
287 
288  */
289  co->maxage = strdup(whatptr);
290  co->expires =
291  atoi((*co->maxage=='\"')?&co->maxage[1]:&co->maxage[0]) + now;
292  }
293  else if(strequal("expires", name)) {
294  co->expirestr=strdup(whatptr);
295  co->expires = curl_getdate(what, &now);
296  }
297  else if(!co->name) {
298  co->name = strdup(name);
299  co->value = strdup(whatptr);
300  }
301  /*
302  else this is the second (or more) name we don't know
303  about! */
304  }
305  else {
306  /* this is an "illegal" <what>=<this> pair */
307  }
308  }
309  else {
310  if(sscanf(ptr, "%" MAX_COOKIE_LINE_TXT "[^;\r\n]",
311  what)) {
312  if(strequal("secure", what))
313  co->secure = TRUE;
314  /* else,
315  unsupported keyword without assign! */
316 
317  }
318  }
319  if(!semiptr || !*semiptr) {
320  /* we already know there are no more cookies */
321  semiptr = NULL;
322  continue;
323  }
324 
325  ptr=semiptr+1;
326  while(ptr && *ptr && isspace((int)*ptr))
327  ptr++;
328  semiptr=strchr(ptr, ';'); /* now, find the next semicolon */
329 
330  if(!semiptr && *ptr)
331  /* There are no more semicolons, but there's a final name=value pair
332  coming up */
333  semiptr=strchr(ptr, '\0');
334  } while(semiptr);
335 
336  if(badcookie || (NULL == co->name)) {
337  /* we didn't get a cookie name or a bad one,
338  this is an illegal line, bail out */
339  if(co->expirestr)
340  free(co->expirestr);
341  if(co->domain)
342  free(co->domain);
343  if(co->path)
344  free(co->path);
345  if(co->name)
346  free(co->name);
347  if(co->value)
348  free(co->value);
349  free(co);
350  return NULL;
351  }
352 
353  if(NULL == co->domain)
354  /* no domain was given in the header line, set the default now */
355  co->domain=domain?strdup(domain):NULL;
356  if((NULL == co->path) && path) {
357  /* no path was given in the header line, set the default now */
358  char *endslash = strrchr(path, '/');
359  if(endslash) {
360  size_t pathlen = endslash-path+1; /* include the ending slash */
361  co->path=malloc(pathlen+1); /* one extra for the zero byte */
362  if(co->path) {
363  memcpy(co->path, path, pathlen);
364  co->path[pathlen]=0; /* zero terminate */
365  }
366  }
367  }
368  }
369  else {
370  /* This line is NOT a HTTP header style line, we do offer support for
371  reading the odd netscape cookies-file format here */
372  char *firstptr;
373  char *tok_buf;
374  int fields;
375 
376  if(lineptr[0]=='#') {
377  /* don't even try the comments */
378  free(co);
379  return NULL;
380  }
381  /* strip off the possible end-of-line characters */
382  ptr=strchr(lineptr, '\r');
383  if(ptr)
384  *ptr=0; /* clear it */
385  ptr=strchr(lineptr, '\n');
386  if(ptr)
387  *ptr=0; /* clear it */
388 
389  firstptr=strtok_r(lineptr, "\t", &tok_buf); /* first tokenize it on the TAB */
390 
391  /* Here's a quick check to eliminate normal HTTP-headers from this */
392  if(!firstptr || strchr(firstptr, ':')) {
393  free(co);
394  return NULL;
395  }
396 
397  /* Now loop through the fields and init the struct we already have
398  allocated */
399  for(ptr=firstptr, fields=0; ptr;
400  ptr=strtok_r(NULL, "\t", &tok_buf), fields++) {
401  switch(fields) {
402  case 0:
403  if(ptr[0]=='.') /* skip preceeding dots */
404  ptr++;
405  co->domain = strdup(ptr);
406  break;
407  case 1:
408  /* This field got its explanation on the 23rd of May 2001 by
409  Andrés García:
410 
411  flag: A TRUE/FALSE value indicating if all machines within a given
412  domain can access the variable. This value is set automatically by
413  the browser, depending on the value you set for the domain.
414 
415  As far as I can see, it is set to true when the cookie says
416  .domain.com and to false when the domain is complete www.domain.com
417  */
418  co->tailmatch=(bool)strequal(ptr, "TRUE"); /* store information */
419  break;
420  case 2:
421  /* It turns out, that sometimes the file format allows the path
422  field to remain not filled in, we try to detect this and work
423  around it! Andrés García made us aware of this... */
424  if (strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) {
425  /* only if the path doesn't look like a boolean option! */
426  co->path = strdup(ptr);
427  break;
428  }
429  /* this doesn't look like a path, make one up! */
430  co->path = strdup("/");
431  fields++; /* add a field and fall down to secure */
432  /* FALLTHROUGH */
433  case 3:
434  co->secure = (bool)strequal(ptr, "TRUE");
435  break;
436  case 4:
437  co->expires = atoi(ptr);
438  break;
439  case 5:
440  co->name = strdup(ptr);
441  break;
442  case 6:
443  co->value = strdup(ptr);
444  break;
445  }
446  }
447 
448  if(6 == fields) {
449  /* we got a cookie with blank contents, fix it */
450  co->value = strdup("");
451  }
452  else if(7 != fields) {
453  /* we did not find the sufficient number of fields to recognize this
454  as a valid line, abort and go home */
455  free_cookiemess(co);
456  return NULL;
457  }
458  }
459 
460  if(!c->running && /* read from a file */
461  c->newsession && /* clean session cookies */
462  !co->expires) { /* this is a session cookie since it doesn't expire! */
463  free_cookiemess(co);
464  return NULL;
465  }
466 
467  co->livecookie = c->running;
468 
469  /* now, we have parsed the incoming line, we must now check if this
470  superceeds an already existing cookie, which it may if the previous have
471  the same domain and path as this */
472 
473  clist = c->cookies;
474  replace_old = FALSE;
475  while(clist) {
476  if(strequal(clist->name, co->name)) {
477  /* the names are identical */
478 
479  if(clist->domain && co->domain) {
480  if(strequal(clist->domain, co->domain))
481  /* The domains are identical */
482  replace_old=TRUE;
483  }
484  else if(!clist->domain && !co->domain)
485  replace_old = TRUE;
486 
487  if(replace_old) {
488  /* the domains were identical */
489 
490  if(clist->path && co->path) {
491  if(strequal(clist->path, co->path)) {
492  replace_old = TRUE;
493  }
494  else
495  replace_old = FALSE;
496  }
497  else if(!clist->path && !co->path)
498  replace_old = TRUE;
499  else
500  replace_old = FALSE;
501 
502  }
503 
504  if(replace_old && !co->livecookie && clist->livecookie) {
505  /* Both cookies matched fine, except that the already present
506  cookie is "live", which means it was set from a header, while
507  the new one isn't "live" and thus only read from a file. We let
508  live cookies stay alive */
509 
510  /* Free the newcomer and get out of here! */
511  if(co->domain)
512  free(co->domain);
513  if(co->path)
514  free(co->path);
515  if(co->name)
516  free(co->name);
517  if(co->value)
518  free(co->value);
519 
520  free(co);
521  return NULL;
522  }
523 
524  if(replace_old) {
525  co->next = clist->next; /* get the next-pointer first */
526 
527  /* then free all the old pointers */
528  if(clist->name)
529  free(clist->name);
530  if(clist->value)
531  free(clist->value);
532  if(clist->domain)
533  free(clist->domain);
534  if(clist->path)
535  free(clist->path);
536  if(clist->expirestr)
537  free(clist->expirestr);
538 
539  if(clist->version)
540  free(clist->version);
541  if(clist->maxage)
542  free(clist->maxage);
543 
544  *clist = *co; /* then store all the new data */
545 
546  free(co); /* free the newly alloced memory */
547  co = clist; /* point to the previous struct instead */
548 
549  /* We have replaced a cookie, now skip the rest of the list but
550  make sure the 'lastc' pointer is properly set */
551  do {
552  lastc = clist;
553  clist = clist->next;
554  } while(clist);
555  break;
556  }
557  }
558  lastc = clist;
559  clist = clist->next;
560  }
561 
562  if(c->running)
563  /* Only show this when NOT reading the cookies from a file */
564  infof(data, "%s cookie %s=\"%s\" for domain %s, path %s, expire %d\n",
565  replace_old?"Replaced":"Added", co->name, co->value,
566  co->domain, co->path, co->expires);
567 
568  if(!replace_old) {
569  /* then make the last item point on this new one */
570  if(lastc)
571  lastc->next = co;
572  else
573  c->cookies = co;
574  }
575 
576  c->numcookies++; /* one more cookie in the jar */
577  return co;
578 }
579 
580 /*****************************************************************************
581  *
582  * Curl_cookie_init()
583  *
584  * Inits a cookie struct to read data from a local file. This is always
585  * called before any cookies are set. File may be NULL.
586  *
587  * If 'newsession' is TRUE, discard all "session cookies" on read from file.
588  *
589  ****************************************************************************/
591  char *file,
592  struct CookieInfo *inc,
593  bool newsession)
594 {
595  char line[MAX_COOKIE_LINE];
596  struct CookieInfo *c;
597  FILE *fp;
598  bool fromfile=TRUE;
599 
600  if(NULL == inc) {
601  /* we didn't get a struct, create one */
602  c = (struct CookieInfo *)malloc(sizeof(struct CookieInfo));
603  if(!c)
604  return NULL; /* failed to get memory */
605  memset(c, 0, sizeof(struct CookieInfo));
606  c->filename = strdup(file?file:"none"); /* copy the name just in case */
607  }
608  else {
609  /* we got an already existing one, use that */
610  c = inc;
611  }
612  c->running = FALSE; /* this is not running, this is init */
613 
614  if(file && strequal(file, "-")) {
615  fp = stdin;
616  fromfile=FALSE;
617  }
618  else
619  fp = file?fopen(file, "r"):NULL;
620 
621  c->newsession = newsession; /* new session? */
622 
623  if(fp) {
624  char *lineptr;
625  bool headerline;
626  while(fgets(line, MAX_COOKIE_LINE, fp)) {
627  if(checkprefix("Set-Cookie:", line)) {
628  /* This is a cookie line, get it! */
629  lineptr=&line[11];
630  headerline=TRUE;
631  }
632  else {
633  lineptr=line;
634  headerline=FALSE;
635  }
636  while(*lineptr && isspace((int)*lineptr))
637  lineptr++;
638 
639  Curl_cookie_add(data, c, headerline, lineptr, NULL, NULL);
640  }
641  if(fromfile)
642  fclose(fp);
643  }
644 
645  c->running = TRUE; /* now, we're running */
646 
647  return c;
648 }
649 
650 /*****************************************************************************
651  *
652  * Curl_cookie_getlist()
653  *
654  * For a given host and path, return a linked list of cookies that the
655  * client should send to the server if used now. The secure boolean informs
656  * the cookie if a secure connection is achieved or not.
657  *
658  * It shall only return cookies that haven't expired.
659  *
660  ****************************************************************************/
661 
663  char *host, char *path, bool secure)
664 {
665  struct Cookie *newco;
666  struct Cookie *co;
667  time_t now = time(NULL);
668  struct Cookie *mainco=NULL;
669 
670  if(!c || !c->cookies)
671  return NULL; /* no cookie struct or no cookies in the struct */
672 
673  co = c->cookies;
674 
675  while(co) {
676  /* only process this cookie if it is not expired or had no expire
677  date AND that if the cookie requires we're secure we must only
678  continue if we are! */
679  if( (co->expires<=0 || (co->expires> now)) &&
680  (co->secure?secure:TRUE) ) {
681 
682  /* now check if the domain is correct */
683  if(!co->domain ||
684  (co->tailmatch && tailmatch(co->domain, host)) ||
685  (!co->tailmatch && strequal(host, co->domain)) ) {
686  /* the right part of the host matches the domain stuff in the
687  cookie data */
688 
689  /* now check the left part of the path with the cookies path
690  requirement */
691  if(!co->path ||
692  checkprefix(co->path, path) ) {
693 
694  /* and now, we know this is a match and we should create an
695  entry for the return-linked-list */
696 
697  newco = (struct Cookie *)malloc(sizeof(struct Cookie));
698  if(newco) {
699  /* first, copy the whole source cookie: */
700  memcpy(newco, co, sizeof(struct Cookie));
701 
702  /* then modify our next */
703  newco->next = mainco;
704 
705  /* point the main to us */
706  mainco = newco;
707  }
708  }
709  }
710  }
711  co = co->next;
712  }
713 
714  return mainco; /* return the new list */
715 }
716 
717 
718 /*****************************************************************************
719  *
720  * Curl_cookie_freelist()
721  *
722  * Free a list of cookies previously returned by Curl_cookie_getlist();
723  *
724  ****************************************************************************/
725 
726 void Curl_cookie_freelist(struct Cookie *co)
727 {
728  struct Cookie *next;
729  if(co) {
730  while(co) {
731  next = co->next;
732  free(co); /* we only free the struct since the "members" are all
733  just copied! */
734  co = next;
735  }
736  }
737 }
738 
739 /*****************************************************************************
740  *
741  * Curl_cookie_cleanup()
742  *
743  * Free a "cookie object" previous created with cookie_init().
744  *
745  ****************************************************************************/
747 {
748  struct Cookie *co;
749  struct Cookie *next;
750  if(c) {
751  if(c->filename)
752  free(c->filename);
753  co = c->cookies;
754 
755  while(co) {
756  if(co->name)
757  free(co->name);
758  if(co->value)
759  free(co->value);
760  if(co->domain)
761  free(co->domain);
762  if(co->path)
763  free(co->path);
764  if(co->expirestr)
765  free(co->expirestr);
766 
767  if(co->version)
768  free(co->version);
769  if(co->maxage)
770  free(co->maxage);
771 
772  next = co->next;
773  free(co);
774  co = next;
775  }
776  free(c); /* free the base struct as well */
777  }
778 }
779 
780 /*
781  * Curl_cookie_output()
782  *
783  * Writes all internally known cookies to the specified file. Specify
784  * "-" as file name to write to stdout.
785  *
786  * The function returns non-zero on write failure.
787  */
788 int Curl_cookie_output(struct CookieInfo *c, char *dumphere)
789 {
790  struct Cookie *co;
791  FILE *out;
792  bool use_stdout=FALSE;
793 
794  if((NULL == c) || (0 == c->numcookies))
795  /* If there are no known cookies, we don't write or even create any
796  destination file */
797  return 0;
798 
799  if(strequal("-", dumphere)) {
800  /* use stdout */
801  out = stdout;
802  use_stdout=TRUE;
803  }
804  else {
805  out = fopen(dumphere, "w");
806  if(!out)
807  return 1; /* failure */
808  }
809 
810  if(c) {
811  fputs("# Netscape HTTP Cookie File\n"
812  "# http://www.netscape.com/newsref/std/cookie_spec.html\n"
813  "# This file was generated by libcurl! Edit at your own risk.\n\n",
814  out);
815  co = c->cookies;
816 
817  while(co) {
818  fprintf(out,
819  "%s%s\t" /* domain */
820  "%s\t" /* tailmatch */
821  "%s\t" /* path */
822  "%s\t" /* secure */
823  "%u\t" /* expires */
824  "%s\t" /* name */
825  "%s\n", /* value */
826 
827  /* Make sure all domains are prefixed with a dot if they allow
828  tailmatching. This is Mozilla-style. */
829  (co->tailmatch && co->domain && co->domain[0] != '.')? ".":"",
830  co->domain?co->domain:"unknown",
831  co->tailmatch?"TRUE":"FALSE",
832  co->path?co->path:"/",
833  co->secure?"TRUE":"FALSE",
834  (unsigned int)co->expires,
835  co->name,
836  co->value?co->value:"");
837 
838  co=co->next;
839  }
840  }
841 
842  if(!use_stdout)
843  fclose(out);
844 
845  return 0;
846 }
847 
848 #endif /* CURL_DISABLE_HTTP */
#define strcmp
Definition: Str.h:41
#define strequal(a, b)
Definition: strequal.h:32
time_t curl_getdate(const char *p, const time_t *now)
Definition: getdate.c:1991
GLenum GLsizei len
Definition: glext.h:3472
int i
Definition: process.py:33
const GLubyte * c
Definition: glext.h:4677
#define NULL
Definition: Lib.h:88
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:2853
const char * path
Definition: sws.c:117
#define checkprefix(a, b)
Definition: strequal.h:37
char * strdup(char *s1)
Definition: main.c:183
#define strtok_r
Definition: strtok.h:32
const GLcharARB * name
Definition: glext.h:3629
#define infof
Definition: sendf.h:31
#define FALSE
Definition: mprintf.c:70
unsigned char bool
Definition: setup.h:74
#define TRUE
Definition: mprintf.c:69