~ubuntu-branches/ubuntu/vivid/edbrowse/vivid

« back to all changes in this revision

Viewing changes to src/cookies.c

  • Committer: Bazaar Package Importer
  • Author(s): Kapil Hari Paranjape
  • Date: 2009-03-01 16:55:12 UTC
  • mfrom: (1.1.5 upstream) (3.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090301165512-97yhte20cy3c4q2w
Tags: 3.4.1-1
* New upstream version (3.4.1).
* debian/rules:
  - add "touch build-stamp" to build-stamp target.
  - modify clean target to use clean target in src/makefile.
  - remove debian/edbrowse.1 in clean target.
  - added "-lcurl" to linker flags.
* debian/control:
  - added libcurl4-openssl-dev to Build-Depends
  - Standards Version 3.8.0. No changes required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
 * This file is part of the Links project, released under GPL
5
5
 *
6
6
 * Modified by Karl Dahlke for integration with edbrowse.
 
7
 * Modified by Chris Brannon to allow cooperation with libcurl.
7
8
 */
8
9
 
9
10
#include "eb.h"
18
19
    bool secure;
19
20
};
20
21
 
 
22
static int
 
23
count_tabs(const char *the_string)
 
24
{
 
25
    int str_index = 0, num_tabs = 0;
 
26
    for(str_index = 0; the_string[str_index] != '\0'; str_index++)
 
27
        if(the_string[str_index] == '\t')
 
28
            num_tabs++;
 
29
    return num_tabs;
 
30
}                               /* count_tabs */
 
31
 
 
32
#define FIELDS_PER_COOKIE_LINE 7
 
33
 
 
34
static struct cookie *
 
35
cookie_from_netscape_line(char *cookie_line)
 
36
{
 
37
    struct cookie *new_cookie = NULL;
 
38
    if(cookie_line && cookie_line[0]) {
 
39
/* Only parse the line if it is not a comment and it has the requisite number
 
40
 * of tabs.  Comment lines begin with a leading # symbol.
 
41
 * Syntax checking is rudimentary, because these lines are
 
42
 * machine-generated. */
 
43
        if(cookie_line[0] != '#' &&
 
44
           count_tabs(cookie_line) == FIELDS_PER_COOKIE_LINE - 1) {
 
45
            new_cookie = allocZeroMem(sizeof (struct cookie));
 
46
            char *start = cookie_line;
 
47
            char *end = strchr(cookie_line, '\t');
 
48
            new_cookie->domain = pullString1(start, end);
 
49
            start = end + 1;
 
50
/* Ignore the second field of the line. */
 
51
            while(*start != '\t')
 
52
                start++;
 
53
            start++;            /* skip tab */
 
54
            end = strchr(start, '\t');
 
55
            new_cookie->path = pullString1(start, end);
 
56
            start = end + 1;
 
57
            if(*start == 'T' || *start == 't')
 
58
                new_cookie->secure = true;
 
59
            else
 
60
                new_cookie->secure = false;
 
61
            start = strchr(start, '\t') + 1;
 
62
            new_cookie->expires = strtol(start, &end, 10);
 
63
/* Now end points to the tab following the expiration time. */
 
64
            start = end + 1;
 
65
            end = strchr(start, '\t');
 
66
            new_cookie->name = pullString1(start, end);
 
67
            start = end + 1;
 
68
/* strcspn gives count of non-newline characters in string, which is the
 
69
 * length of the final field.  Either CR or LF is considered a newline. */
 
70
            new_cookie->value = pullString(start, strcspn(start, "\r\n"));
 
71
        }
 
72
    }
 
73
 
 
74
    return new_cookie;
 
75
}                               /* cookie_from_netscape_line */
 
76
 
21
77
static void
22
78
freeCookie(struct cookie *c)
23
79
{
49
105
    addToListBack(&cookies, c);
50
106
}                               /* acceptCookie */
51
107
 
52
 
static void
53
 
cookieIntoJar(const struct cookie *c)
 
108
 
 
109
/* Tell libcurl about a new cookie.  Called when setting cookies from
 
110
 * JavaScript.
 
111
 * The function is pretty simple.  Construct a line of the form used by
 
112
 * the Netscape cookie file format, and pass that to libcurl. */
 
113
static CURLcode
 
114
cookieForLibcurl(const struct cookie *c)
54
115
{
55
 
    FILE *f;
56
 
    if(!cookieFile) {
57
 
        static bool warn = false;
58
 
        if(warn)
59
 
            return;
60
 
        i_puts(MSG_NoJar);
61
 
        warn = true;
62
 
        return;
63
 
    }
64
 
    if(c->expires <= time(0))
65
 
        return;                 /* not persistent, or out of date */
66
 
    f = fopen(cookieFile, "a");
67
 
    if(!f)
68
 
        return;
69
116
/* Netscape format */
70
117
/* I have no clue what the second argument is suppose to be, */
71
118
/* I'm always calling it false. */
72
 
    fprintf(f, "%s\tFALSE\t%s\t%s\t%u\t%s\t%s\n",
73
 
       c->domain, c->path,
 
119
    char *cookLine =
 
120
       allocMem(strlen(c->path) + strlen(c->domain) + strlen(c->name) +
 
121
       strlen(c->value) + 48);
 
122
    sprintf(cookLine, "%s\tFALSE\t%s\t%s\t%u\t%s\t%s\n", c->domain, c->path,
74
123
       c->secure ? "TRUE" : "FALSE", (unsigned)c->expires, c->name, c->value);
75
 
    fclose(f);
76
 
    debugPrint(3, "into jar");
77
 
}                               /* cookieIntoJar */
 
124
    debugPrint(3, "cookie for libcurl");
 
125
    curl_easy_setopt(curl_handle, CURLOPT_COOKIELIST, cookLine);
 
126
}                               /* cookieForLibcurl */
78
127
 
79
128
/* Should this server really specify this domain in a cookie? */
80
129
/* Domain must be the trailing substring of server. */
179
228
        nzFree(s);
180
229
    }
181
230
 
182
 
    acceptCookie(c);
183
 
    cookieIntoJar(c);
 
231
    cookieForLibcurl(c);
 
232
    freeCookie(c);
 
233
    nzFree(c);
184
234
    return true;
185
235
}                               /* receiveCookie */
186
236
 
194
244
    char *cbuf, *s, *t;
195
245
    FILE *f;
196
246
    int n, cnt, expired, displaced;
 
247
    char *cbuf_end;
197
248
    time_t now;
198
249
    struct cookie *c;
199
250
 
202
253
    if(!fileIntoMemory(cookieFile, &cbuf, &n))
203
254
        showErrorAbort();
204
255
    cbuf[n] = 0;
 
256
    cbuf_end = cbuf + n;
205
257
    time(&now);
206
258
 
207
259
    cnt = expired = displaced = 0;
208
260
    s = cbuf;
209
 
    while(*s) {
210
 
        ++cnt;
211
 
        c = allocZeroMem(sizeof (struct cookie));
212
 
        t = strchr(s, '\t');
213
 
        *t = 0;
214
 
        c->domain = cloneString(s);
215
 
        s = t + 1;
216
 
        t = strchr(s, '\t');
217
 
        s = t + 1;
218
 
        t = strchr(s, '\t');
219
 
        *t = 0;
220
 
        c->path = cloneString(s);
221
 
        s = t + 1;
222
 
        t = strchr(s, '\t');
223
 
        c->secure = (*s == 'T');
224
 
        s = t + 1;
225
 
        t = strchr(s, '\t');
226
 
        *t = 0;
227
 
        c->expires = (time_t) atol(s);
228
 
        s = t + 1;
229
 
        t = strchr(s, '\t');
230
 
        *t = 0;
231
 
        c->name = cloneString(s);
232
 
        s = t + 1;
233
 
        t = strchr(s, '\n');
234
 
        *t = 0;
235
 
        c->value = cloneString(s);
236
 
        s = t + 1;
237
 
 
238
 
        if(c->expires < now) {
239
 
            freeCookie(c);
240
 
            nzFree(c);
241
 
            ++expired;
242
 
        } else {
243
 
            acceptCookie(c);
244
 
            displaced += displacedCookie;
 
261
 
 
262
    while(s < cbuf_end) {
 
263
        t = s + strcspn(s, "\r\n");
 
264
/* t points to the first newline past s.  If there is no newline in s,
 
265
 * then it points to the NUL byte at end of s. */
 
266
        *t = '\0';
 
267
        c = cookie_from_netscape_line(s);
 
268
 
 
269
        if(c) {                 /* Got a valid cookie line. */
 
270
            cnt++;
 
271
            if(c->expires < now) {
 
272
                freeCookie(c);
 
273
                nzFree(c);
 
274
                ++expired;
 
275
            } else {
 
276
                acceptCookie(c);
 
277
                displaced += displacedCookie;
 
278
            }
245
279
        }
 
280
 
 
281
        s = t + 1;              /* Get ready to read more lines. */
 
282
/* Skip over blank lines, if necessary.  */
 
283
        while(s < cbuf_end && (*s == '\r' || *s == '\n'))
 
284
            s++;
246
285
    }
247
286
 
248
287
    debugPrint(3, "%d persistent cookies, %d expired, %d displaced",
287
326
    return !memcmp(d, s, dl);
288
327
}                               /* isPathPrefix */
289
328
 
 
329
 
 
330
 
290
331
void
291
332
sendCookies(char **s, int *l, const char *url, bool issecure)
292
333
{
293
334
    const char *server = getHostURL(url);
294
335
    const char *data = getDataURL(url);
295
336
    int nc = 0;                 /* new cookie */
296
 
    struct cookie *c, *d;
 
337
    struct cookie *c = NULL;
297
338
    time_t now;
 
339
    struct curl_slist *known_cookies = NULL;
 
340
    struct curl_slist *cursor = NULL;
 
341
    curl_easy_getinfo(curl_handle, CURLINFO_COOKIELIST, &known_cookies);
298
342
 
299
343
    if(!url || !server || !data)
300
344
        return;
305
349
        data = "/";
306
350
    time(&now);
307
351
 
308
 
    foreach(c, cookies) {
 
352
/* Can't use foreach here, since known_cookies is just a pointer. */
 
353
    cursor = known_cookies;
 
354
 
 
355
/* The code at the top of the loop guards against a memory leak.
 
356
 * Otherwise, structs could become inaccessible after continue statements. */
 
357
    while(cursor != NULL) {
 
358
        if(c != NULL) {         /* discard un-freed cookie structs */
 
359
            freeCookie(c);
 
360
            nzFree(c);
 
361
        }
 
362
        c = cookie_from_netscape_line(cursor->data);
 
363
        cursor = cursor->next;
 
364
        if(c == NULL)           /* didn't read a cookie line. */
 
365
            continue;
309
366
        if(!isInDomain(c->domain, server))
310
367
            continue;
311
368
        if(!isPathPrefix(c->path, data))
312
369
            continue;
313
 
        if(c->expires && c->expires < now) {
314
 
            d = c;
315
 
            c = c->prev;
316
 
            delFromList(d);
317
 
            freeCookie(d);
318
 
            nzFree(d);
 
370
        if(c->expires && c->expires < now)
319
371
            continue;
320
 
        }
321
372
        if(c->secure && !issecure)
322
373
            continue;
323
374
/* We're good to go. */
331
382
        debugPrint(3, "send cookie %s=%s", c->name, c->value);
332
383
    }
333
384
 
 
385
    if(c != NULL) {
 
386
        freeCookie(c);
 
387
        nzFree(c);
 
388
    }
 
389
 
 
390
    if(known_cookies != NULL)
 
391
        curl_slist_free_all(known_cookies);
334
392
    if(nc)
335
393
        stringAndString(s, l, eol);
336
394
}                               /* sendCookies */