~ubuntu-branches/ubuntu/jaunty/edbrowse/jaunty-security

« back to all changes in this revision

Viewing changes to src/jsloc.c

  • Committer: Bazaar Package Importer
  • Author(s): Kapil Hari Paranjape
  • Date: 2008-04-09 18:55:23 UTC
  • mfrom: (1.1.4 upstream) (3.1.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080409185523-dqokcloumyn1ibn4
Tags: 3.3.4-1
* New upstream version (3.3.4).
 - Convert between iso8859-1 and utf-8 on the fly.
 - Support reading of pdf using pdftohtml.
 - French translation of html documentation.
 - Old html documentation renamed to usersguide.
 - Additional documentation on philosophy.
* debian/control:
 - Changed homepage to sourcefource site.
 - Moved homepage from description to its own field.
 - Added "poppler-utils | xpdf-utils" to Recommends.
 - Added "www-browser", "mail-reader" and "editor" to Provides. 
 - Removed "XS-" from Vcs-Svn tag.
 - Standards-Version: 3.7.3
* debian/docs: Added new documentation files
  from "doc/" subdirectory.
* debian/watch: Updated to use sourceforge site.
* debian/edbrowse.doc-base:
  - Changed name of upstream provided html documentation from
    "ebdoc.html" to "usersguide.html".
  - Changed section from "net" to "Network/Web Browsing".
* debian/install: Compiled binary is now in "src/".

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* jsloc.c
 
2
* Javascript support, the URL class and the location object.
 
3
 * The cookie string, and other things with get/set side effects.
 
4
* Copyright (c) Karl Dahlke, 2008
 
5
* This file is part of the edbrowse project, released under GPL.
 
6
*/
 
7
 
 
8
#include "eb.h"
 
9
 
 
10
#include "jsapi.h"
 
11
/* jsprf.h is not publically visible on some systems,
 
12
so I can't #include it here.
 
13
Instead, I'll declare the needed prototype myself, and hope it is consistent
 
14
with whatever smjs you are using. */
 
15
extern
 
16
JS_PUBLIC_API(char *)
 
17
JS_smprintf(const char *fmt, ...);
 
18
 
 
19
#define PROP_FIXED (JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT)
 
20
 
 
21
 
 
22
/*********************************************************************
 
23
The URL class, and the associated window.location object, is tricky,
 
24
with lots of interacting properties and setter functions.
 
25
*********************************************************************/
 
26
 
 
27
static const char *emptyParms[] = { 0 };
 
28
static jsval emptyArgs[] = { 0 };
 
29
 
 
30
static void
 
31
url_initialize(const char *url, bool readonly, bool exclude_href);
 
32
 
 
33
const char *
 
34
stringize(long v)
 
35
{
 
36
    static char buf[24];
 
37
    int n;
 
38
    jsdouble d;
 
39
    if(JSVAL_IS_STRING(v)) {
 
40
        return JS_GetStringBytes(JSVAL_TO_STRING(v));
 
41
    }
 
42
    if(JSVAL_IS_INT(v)) {
 
43
        n = JSVAL_TO_INT(v);
 
44
        sprintf(buf, "%d", n);
 
45
        return buf;
 
46
    }
 
47
    if(JSVAL_IS_DOUBLE(v)) {
 
48
        d = *JSVAL_TO_DOUBLE(v);
 
49
        n = d;
 
50
        if(n == d)
 
51
            sprintf(buf, "%d", n);
 
52
        else
 
53
            sprintf(buf, "%lf", d);
 
54
        return buf;
 
55
    }
 
56
/* Sorry, I don't look for object.toString() */
 
57
    return 0;                   /* failed */
 
58
}                               /* stringize */
 
59
 
 
60
static JSClass url_class = {
 
61
    "URL",
 
62
    JSCLASS_HAS_PRIVATE,
 
63
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
64
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
65
};
 
66
 
 
67
/* To builld path names, host names, etc. */
 
68
static char urlbuffer[512];
 
69
static JSObject *uo;            /* the url object */
 
70
static char *uo_href;
 
71
static bool setter_suspend;
 
72
 
 
73
/* Are we modifying window.location? */
 
74
/*Return false if we are, because that will put a stop to javascript. */
 
75
static bool
 
76
isWinLoc(void)
 
77
{
 
78
    if(uo != jwloc && uo != jdloc) {
 
79
        nzFree(uo_href);
 
80
        uo_href = 0;
 
81
        return true;
 
82
    }
 
83
/* This call frees t, or takes it over, so you should not free it here. */
 
84
    gotoLocation(uo_href, 0, true);
 
85
    uo_href = 0;
 
86
    return false;
 
87
}                               /* isWinLoc */
 
88
 
 
89
/* Converting to a string just pulls out the href property */
 
90
static JSBool
 
91
loc_toString(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
 
92
   jsval * rval)
 
93
{
 
94
    JS_GetProperty(jcx, obj, "href", rval);
 
95
    return JS_TRUE;
 
96
}                               /* loc_toString */
 
97
 
 
98
static JSBool
 
99
loc_reload(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
 
100
   jsval * rval)
 
101
{
 
102
    const char *s = firstURL();
 
103
    if(s && isURL(s))
 
104
        gotoLocation(cloneString(s), 0, true);
 
105
    else
 
106
        JS_ReportError(jcx, "location.reload() cannot find a url to refresh");
 
107
    return JS_FALSE;
 
108
}                               /* loc_reload */
 
109
 
 
110
static JSBool
 
111
loc_replace(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
 
112
   jsval * rval)
 
113
{
 
114
    const char *s;
 
115
    char *ss, *t;
 
116
    if(argc > 0 && JSVAL_IS_STRING(argv[0])) {
 
117
        s = stringize(argv[0]);
 
118
/* I have to copy the string, just so I can run unpercent */
 
119
        ss = cloneString(s);
 
120
        unpercentURL(ss);
 
121
        t = resolveURL(cw->fileName, ss);
 
122
        nzFree(ss);
 
123
/* This call frees t, or takes it over, so you should not free it here. */
 
124
        gotoLocation(t, 0, true);
 
125
        return JS_FALSE;
 
126
    }
 
127
    JS_ReportError(jcx,
 
128
       "argument to location.replace() does not look like a url");
 
129
    return JS_FALSE;
 
130
}                               /* loc_replace */
 
131
 
 
132
/* Put a url together from its pieces, after something has changed. */
 
133
static void
 
134
build_url(int exception, const char *e)
 
135
{
 
136
    jsval v;
 
137
    const char *prot, *slashes, *host, *pathname, *pathslash, *search, *hash;
 
138
    char *new_url;
 
139
    static const char *const noslashes[] = {
 
140
        "mailto", "telnet", "javascript", 0
 
141
    };
 
142
    setter_suspend = true;
 
143
/* I'm a little worried about the first one being freed while I'm
 
144
 * getting the next one.
 
145
 * I just don't know that much about the js heap. */
 
146
    if(exception == 1)
 
147
        prot = e;
 
148
    else {
 
149
        JS_GetProperty(jcx, uo, "protocol", &v);
 
150
        prot = stringize(v);
 
151
    }
 
152
    slashes = EMPTYSTRING;
 
153
    if(stringInListCI(noslashes, prot) < 0)
 
154
        slashes = "//";
 
155
    if(exception == 2)
 
156
        host = e;
 
157
    else {
 
158
        JS_GetProperty(jcx, uo, "host", &v);
 
159
        host = stringize(v);
 
160
    }
 
161
    if(exception == 3)
 
162
        pathname = e;
 
163
    else {
 
164
        JS_GetProperty(jcx, uo, "pathname", &v);
 
165
        pathname = stringize(v);
 
166
    }
 
167
    pathslash = EMPTYSTRING;
 
168
    if(pathname[0] != '/')
 
169
        pathslash = "/";
 
170
    if(exception == 4)
 
171
        search = e;
 
172
    else {
 
173
        JS_GetProperty(jcx, uo, "search", &v);
 
174
        search = stringize(v);
 
175
    }
 
176
    if(exception == 5)
 
177
        hash = e;
 
178
    else {
 
179
        JS_GetProperty(jcx, uo, "hash", &v);
 
180
        hash = stringize(v);
 
181
    }
 
182
    new_url =
 
183
       JS_smprintf("%s%s%s%s%s%s%s", prot, slashes, host, pathslash, pathname,
 
184
       search, hash);
 
185
    v = STRING_TO_JSVAL(JS_NewStringCopyZ(jcx, new_url));
 
186
    JS_SetProperty(jcx, uo, "href", &v);
 
187
/* I want control over this string */
 
188
    uo_href = cloneString(new_url);
 
189
    JS_smprintf_free(new_url);
 
190
    setter_suspend = false;
 
191
}                               /* build_url */
 
192
 
 
193
/* Rebuild host, because hostname or port changed. */
 
194
static void
 
195
build_host(int exception, const char *hostname, int port)
 
196
{
 
197
    jsval v;
 
198
    const char *oldhost;
 
199
    setter_suspend = true;
 
200
    if(exception == 1) {
 
201
        JS_GetProperty(jcx, uo, "port", &v);
 
202
        port = JSVAL_TO_INT(v);
 
203
    } else {
 
204
        JS_GetProperty(jcx, uo, "hostname", &v);
 
205
        hostname = stringize(v);
 
206
    }
 
207
    JS_GetProperty(jcx, uo, "host", &v);
 
208
    oldhost = stringize(v);
 
209
    if(exception == 2 || strchr(oldhost, ':'))
 
210
        sprintf(urlbuffer, "%s:%d", hostname, port);
 
211
    else
 
212
        strcpy(urlbuffer, hostname);
 
213
    if(strlen(urlbuffer) >= sizeof (urlbuffer))
 
214
        i_printfExit(MSG_PortTooLong);
 
215
    v = STRING_TO_JSVAL(JS_NewStringCopyZ(jcx, urlbuffer));
 
216
    JS_SetProperty(jcx, uo, "host", &v);
 
217
    setter_suspend = false;
 
218
}                               /* build_host */
 
219
 
 
220
/* define or set a local property */
 
221
static void
 
222
loc_def_set(const char *name, const char *s,
 
223
   JSBool(*setter) (JSContext *, JSObject *, jsval, jsval *), jsuint attr)
 
224
{
 
225
    JSBool found;
 
226
    jsval vv;
 
227
    if(s)
 
228
        vv = STRING_TO_JSVAL(JS_NewStringCopyZ(jcx, s));
 
229
    else
 
230
        vv = JS_GetEmptyStringValue(jcx);
 
231
    JS_HasProperty(jcx, uo, name, &found);
 
232
    if(found)
 
233
        JS_SetProperty(jcx, uo, name, &vv);
 
234
    else
 
235
        JS_DefineProperty(jcx, uo, name, vv, NULL, setter, attr);
 
236
}                               /* loc_def_set */
 
237
 
 
238
/* Like the above, but using an integer, this is for port only. */
 
239
static void
 
240
loc_def_set_n(const char *name, int port,
 
241
   JSBool(*setter) (JSContext *, JSObject *, jsval, jsval *), jsuint attr)
 
242
{
 
243
    JSBool found;
 
244
    jsval vv = INT_TO_JSVAL(port);
 
245
    JS_HasProperty(jcx, uo, name, &found);
 
246
    if(found)
 
247
        JS_SetProperty(jcx, uo, name, &vv);
 
248
    else
 
249
        JS_DefineProperty(jcx, uo, name, vv, NULL, setter, attr);
 
250
}                               /* loc_def_set_n */
 
251
 
 
252
static void
 
253
loc_def_set_part(const char *name, const char *s, int n,
 
254
   JSBool(*setter) (JSContext *, JSObject *, jsval, jsval *), jsuint attr)
 
255
{
 
256
    JSBool found;
 
257
    jsval vv;
 
258
    if(s)
 
259
        vv = STRING_TO_JSVAL(JS_NewStringCopyN(jcx, s, n));
 
260
    else
 
261
        vv = JS_GetEmptyStringValue(jcx);
 
262
    JS_HasProperty(jcx, uo, name, &found);
 
263
    if(found)
 
264
        JS_SetProperty(jcx, uo, name, &vv);
 
265
    else
 
266
        JS_DefineProperty(jcx, uo, name, vv, NULL, setter, attr);
 
267
}                               /* loc_def_set_part */
 
268
 
 
269
static JSBool
 
270
setter_loc(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
 
271
{
 
272
    const char *s = stringize(*vp);
 
273
    if(!s) {
 
274
        JS_ReportError(jcx,
 
275
           "window.location is assigned something that I don't understand");
 
276
    } else {
 
277
        char *t;
 
278
/* I have to copy the string, just so I can run unpercent */
 
279
        char *ss = cloneString(s);
 
280
        unpercentURL(ss);
 
281
        t = resolveURL(cw->fileName, ss);
 
282
        nzFree(ss);
 
283
/* This call frees t, or takes it over, so you should not free it here. */
 
284
        gotoLocation(t, 0, true);
 
285
    }
 
286
/* Return false to stop javascript. */
 
287
/* After all, we're trying to move to a new web page. */
 
288
    return JS_FALSE;
 
289
}                               /* setter_loc */
 
290
 
 
291
static JSBool
 
292
setter_loc_href(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
 
293
{
 
294
    const char *url = 0;
 
295
    if(setter_suspend)
 
296
        return JS_TRUE;
 
297
    url = stringize(*vp);
 
298
    if(!url)
 
299
        return JS_TRUE;
 
300
    uo = obj;
 
301
    url_initialize(url, false, true);
 
302
    uo_href = cloneString(url);
 
303
    if(uo == jwloc || uo == jdloc) {
 
304
        char *t;
 
305
        unpercentURL(uo_href);
 
306
        t = resolveURL(cw->fileName, uo_href);
 
307
        nzFree(uo_href);
 
308
        uo_href = t;
 
309
    }
 
310
    return isWinLoc();
 
311
}                               /* setter_loc_href */
 
312
 
 
313
static JSBool
 
314
setter_loc_hash(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
 
315
{
 
316
    const char *e;
 
317
    if(setter_suspend)
 
318
        return JS_TRUE;
 
319
    e = stringize(*vp);
 
320
    uo = obj;
 
321
    build_url(5, e);
 
322
    return isWinLoc();
 
323
}                               /* setter_loc_hash */
 
324
 
 
325
static JSBool
 
326
setter_loc_search(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
 
327
{
 
328
    const char *e;
 
329
    if(setter_suspend)
 
330
        return JS_TRUE;
 
331
    e = stringize(*vp);
 
332
    uo = obj;
 
333
    build_url(4, e);
 
334
    return isWinLoc();
 
335
}                               /* setter_loc_search */
 
336
 
 
337
static JSBool
 
338
setter_loc_prot(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
 
339
{
 
340
    const char *e;
 
341
    if(setter_suspend)
 
342
        return JS_TRUE;
 
343
    e = stringize(*vp);
 
344
    uo = obj;
 
345
    build_url(1, e);
 
346
    return isWinLoc();
 
347
}                               /* setter_loc_prot */
 
348
 
 
349
static JSBool
 
350
setter_loc_pathname(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
 
351
{
 
352
    const char *e;
 
353
    if(setter_suspend)
 
354
        return JS_TRUE;
 
355
    e = stringize(*vp);
 
356
    uo = obj;
 
357
    build_url(3, e);
 
358
    return isWinLoc();
 
359
}                               /* setter_loc_pathname */
 
360
 
 
361
static JSBool
 
362
setter_loc_hostname(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
 
363
{
 
364
    const char *e;
 
365
    if(setter_suspend)
 
366
        return JS_TRUE;
 
367
    e = stringize(*vp);
 
368
    uo = obj;
 
369
    build_host(1, e, 0);
 
370
    build_url(0, 0);
 
371
    return isWinLoc();
 
372
}                               /* setter_loc_hostname */
 
373
 
 
374
static JSBool
 
375
setter_loc_port(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
 
376
{
 
377
    int port;
 
378
    if(setter_suspend)
 
379
        return JS_TRUE;
 
380
    port = JSVAL_TO_INT(*vp);
 
381
    uo = obj;
 
382
    build_host(2, 0, port);
 
383
    build_url(0, 0);
 
384
    return isWinLoc();
 
385
}                               /* setter_loc_port */
 
386
 
 
387
static JSBool
 
388
setter_loc_host(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
 
389
{
 
390
    const char *e, *s;
 
391
    int n;
 
392
    jsval v;
 
393
    if(setter_suspend)
 
394
        return JS_TRUE;
 
395
    e = stringize(*vp);
 
396
    uo = obj;
 
397
    build_url(2, e);
 
398
/* and we have to update hostname and port */
 
399
    setter_suspend = true;
 
400
    s = strchr(e, ':');
 
401
    if(s)
 
402
        n = s - e;
 
403
    else
 
404
        n = strlen(e);
 
405
    v = STRING_TO_JSVAL(JS_NewStringCopyN(jcx, e, n));
 
406
    JS_SetProperty(jcx, uo, "hostname", &v);
 
407
    if(s) {
 
408
        v = INT_TO_JSVAL(atoi(s + 1));
 
409
        JS_SetProperty(jcx, uo, "port", &v);
 
410
    }
 
411
    setter_suspend = false;
 
412
    return isWinLoc();
 
413
}                               /* setter_loc_pathname */
 
414
 
 
415
static void
 
416
url_initialize(const char *url, bool readonly, bool exclude_href)
 
417
{
 
418
    int n, port;
 
419
    const char *data;
 
420
    const char *s;
 
421
    const char *pl;
 
422
    jsuint attr = JSPROP_ENUMERATE | JSPROP_PERMANENT;
 
423
    if(readonly)
 
424
        attr |= JSPROP_READONLY;
 
425
 
 
426
    setter_suspend = true;
 
427
 
 
428
/* Store the url in location.href */
 
429
    if(!exclude_href) {
 
430
        loc_def_set("href", url, setter_loc_href, attr);
 
431
    }
 
432
 
 
433
/* Now make a property for each piece of the url. */
 
434
    if(s = getProtURL(url)) {
 
435
        sprintf(urlbuffer, "%s:", s);
 
436
        if(strlen(urlbuffer) >= sizeof (urlbuffer))
 
437
            i_printfExit(MSG_ProtTooLong);
 
438
        s = urlbuffer;
 
439
    }
 
440
    loc_def_set("protocol", s, setter_loc_prot, attr);
 
441
 
 
442
    data = getDataURL(url);
 
443
    s = 0;
 
444
    if(data)
 
445
        s = strchr(data, '#');
 
446
    loc_def_set("hash", s, setter_loc_hash, attr);
 
447
 
 
448
    s = getHostURL(url);
 
449
    if(s && !*s)
 
450
        s = 0;
 
451
    loc_def_set("hostname", s, setter_loc_hostname, attr);
 
452
 
 
453
    getPortLocURL(url, &pl, &port);
 
454
    loc_def_set_n("port", port, setter_loc_port, attr);
 
455
 
 
456
    if(s) {                     /* this was hostname */
 
457
        strcpy(urlbuffer, s);
 
458
        if(pl)
 
459
            sprintf(urlbuffer + strlen(urlbuffer), ":%d", port);
 
460
        if(strlen(urlbuffer) >= sizeof (urlbuffer))
 
461
            i_printfExit(MSG_PortTooLong);
 
462
        s = urlbuffer;
 
463
    }
 
464
    loc_def_set("host", s, setter_loc_host, attr);
 
465
 
 
466
    s = 0;
 
467
    n = 0;
 
468
    getDirURL(url, &s, &pl);
 
469
    if(s) {
 
470
        pl = strpbrk(s, "?\1#");
 
471
        n = pl ? pl - s : strlen(s);
 
472
        if(!n)
 
473
            s = "/", n = 1;
 
474
    }
 
475
    loc_def_set_part("pathname", s, n, setter_loc_pathname, attr);
 
476
 
 
477
    s = 0;
 
478
    if(data && (s = strpbrk(data, "?\1")) &&
 
479
       (!(pl = strchr(data, '#')) || pl > s)) {
 
480
        if(pl)
 
481
            n = pl - s;
 
482
        else
 
483
            n = strlen(s);
 
484
    }
 
485
    loc_def_set_part("search", s, n, setter_loc_search, attr);
 
486
 
 
487
    setter_suspend = false;
 
488
}                               /* url_initialize */
 
489
 
 
490
static JSBool
 
491
url_ctor(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
 
492
{
 
493
    const char *url = 0;
 
494
    const char *s;
 
495
    if(argc && JSVAL_IS_STRING(*argv)) {
 
496
        s = stringize(argv[0]);
 
497
        if(strlen(s))
 
498
            url = s;
 
499
    }                           /* string argument */
 
500
    uo = obj;
 
501
    url_initialize(url, false, false);
 
502
    return JS_TRUE;
 
503
}                               /* url_ctor */
 
504
 
 
505
static JSFunctionSpec url_methods[] = {
 
506
    {"toString", loc_toString, 0, 0, 0},
 
507
    {0}
 
508
};
 
509
 
 
510
void
 
511
initLocationClass(void)
 
512
{
 
513
    JS_InitClass(jcx, jwin, 0, &url_class, url_ctor, 1,
 
514
       NULL, url_methods, NULL, NULL);
 
515
}                               /* initLocationClass */
 
516
 
 
517
 
 
518
/*********************************************************************
 
519
If js changes the value of an input field in a form,
 
520
this fact has to make it back to the text you are reading, in edbrowse,
 
521
after js returns.
 
522
That requires a special setter function to pass the new value back to the text.
 
523
*********************************************************************/
 
524
 
 
525
static JSBool
 
526
setter_value(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
 
527
{
 
528
    const char *val;
 
529
    if(setter_suspend)
 
530
        return JS_TRUE;
 
531
    val = stringize(*vp);
 
532
    if(!val) {
 
533
        JS_ReportError(jcx,
 
534
           "input.value is assigned something other than a string; this can cause problems when you submit the form.");
 
535
    } else {
 
536
        javaSetsTagVar(obj, val);
 
537
    }
 
538
    return JS_TRUE;
 
539
}                               /* setter_value */
 
540
 
 
541
static JSBool
 
542
setter_checked(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
 
543
{
 
544
    JSBool b;
 
545
    if(setter_suspend)
 
546
        return JS_TRUE;
 
547
    b = JSVAL_TO_BOOLEAN(*vp);
 
548
    return JS_TRUE;
 
549
}                               /* setter_checked */
 
550
 
 
551
static JSBool
 
552
setter_selected(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
 
553
{
 
554
    JSBool b;
 
555
    if(setter_suspend)
 
556
        return JS_TRUE;
 
557
    b = JSVAL_TO_BOOLEAN(*vp);
 
558
    return JS_TRUE;
 
559
}                               /* setter_selected */
 
560
 
 
561
static JSBool
 
562
setter_selidx(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
 
563
{
 
564
    int n;
 
565
    if(setter_suspend)
 
566
        return JS_TRUE;
 
567
    n = JSVAL_TO_INT(*vp);
 
568
    return JS_TRUE;
 
569
}                               /* setter_selidx */
 
570
 
 
571
static JSBool
 
572
getter_cookie(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
 
573
{
 
574
    int cook_l;
 
575
    char *cook = initString(&cook_l);
 
576
    const char *url = cw->fileName;
 
577
    bool secure = false;
 
578
    const char *proto;
 
579
    char *s;
 
580
 
 
581
    if(url) {
 
582
        proto = getProtURL(url);
 
583
        if(proto && stringEqualCI(proto, "https"))
 
584
            secure = true;
 
585
        sendCookies(&cook, &cook_l, url, secure);
 
586
        if(memEqualCI(cook, "cookie: ", 8)) {   /* should often happen */
 
587
            strcpy(cook, cook + 8);
 
588
        }
 
589
        if(s = strstr(cook, "\r\n"))
 
590
            *s = 0;
 
591
    }
 
592
 
 
593
    *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(jcx, cook));
 
594
    nzFree(cook);
 
595
    return JS_TRUE;
 
596
}                               /* getter_cookie */
 
597
 
 
598
static JSBool
 
599
setter_cookie(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
 
600
{
 
601
    const char *host = getHostURL(cw->fileName);
 
602
    if(!host) {
 
603
        JS_ReportError(jcx, "cannot set cookie, ill-defined domain");
 
604
    } else {
 
605
        const char *s = stringize(*vp);
 
606
        if(!receiveCookie(cw->fileName, s))
 
607
            JS_ReportError(jcx, "unable to set cookie %s", s);
 
608
    }
 
609
    return JS_TRUE;
 
610
}                               /* setter_cookie */
 
611
 
 
612
static JSBool
 
613
setter_domain(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
 
614
{
 
615
    const char *hostname = getHostURL(cw->fileName);
 
616
    const char *dom = 0;
 
617
    if(!hostname)
 
618
        goto out;               /* local file, don't care */
 
619
    dom = stringize(*vp);
 
620
    if(dom && strlen(dom) && domainSecurityCheck(hostname, dom))
 
621
        goto out;
 
622
    if(!dom)
 
623
        dom = EMPTYSTRING;
 
624
    JS_ReportError(jcx,
 
625
       "document.domain is being set to an insecure string <%s>", dom);
 
626
  out:
 
627
    return JS_TRUE;
 
628
}                               /* setter_domain */
 
629
 
 
630
 
 
631
/*********************************************************************
 
632
Convenient set property routines that can be invoked from edbrowse,
 
633
requiring no knowledge of smjs.
 
634
*********************************************************************/
 
635
 
 
636
static JSBool(*my_getter) (JSContext *, JSObject *, jsval, jsval *);
 
637
static JSBool(*my_setter) (JSContext *, JSObject *, jsval, jsval *);
 
638
 
 
639
void
 
640
establish_property_string(void *jv, const char *name, const char *value,
 
641
   bool readonly)
 
642
{
 
643
    jsuint attr = JSPROP_ENUMERATE | JSPROP_PERMANENT;
 
644
    if(readonly)
 
645
        attr |= JSPROP_READONLY;
 
646
    JSObject *obj = jv;
 
647
    my_getter = my_setter = 0;
 
648
    if(stringEqual(name, "value"))
 
649
        my_setter = setter_value;
 
650
    if(stringEqual(name, "domain"))
 
651
        my_setter = setter_domain;
 
652
    if(stringEqual(name, "cookie")) {
 
653
        my_getter = getter_cookie;
 
654
        my_setter = setter_cookie;
 
655
    }
 
656
    JS_DefineProperty(jcx, obj, name,
 
657
       ((value && *value) ? STRING_TO_JSVAL(JS_NewStringCopyZ(jcx, value))
 
658
       : JS_GetEmptyStringValue(jcx)), my_getter, my_setter, attr);
 
659
}                               /* establish_property_string */
 
660
 
 
661
void
 
662
establish_property_number(void *jv, const char *name, int value, bool readonly)
 
663
{
 
664
    jsuint attr = JSPROP_ENUMERATE | JSPROP_PERMANENT;
 
665
    if(readonly)
 
666
        attr |= JSPROP_READONLY;
 
667
    JSObject *obj = jv;
 
668
    my_setter = 0;
 
669
    if(stringEqual(name, "selectedIndex"))
 
670
        my_setter = setter_selidx;
 
671
    JS_DefineProperty(jcx, obj, name,
 
672
       INT_TO_JSVAL(value), NULL, my_setter, attr);
 
673
}                               /* establish_property_number */
 
674
 
 
675
void
 
676
establish_property_bool(void *jv, const char *name, bool value, bool readonly)
 
677
{
 
678
    jsuint attr = JSPROP_ENUMERATE | JSPROP_PERMANENT;
 
679
    if(readonly)
 
680
        attr |= JSPROP_READONLY;
 
681
    JSObject *obj = jv;
 
682
    my_setter = 0;
 
683
    if(stringEqual(name, "checked"))
 
684
        my_setter = setter_checked;
 
685
    if(stringEqual(name, "selected"))
 
686
        my_setter = setter_selected;
 
687
    JS_DefineProperty(jcx, obj, name,
 
688
       (value ? JSVAL_TRUE : JSVAL_FALSE), NULL, my_setter, attr);
 
689
}                               /* establish_property_bool */
 
690
 
 
691
void *
 
692
establish_property_array(void *jv, const char *name)
 
693
{
 
694
    JSObject *obj = jv;
 
695
    JSObject *a = JS_NewArrayObject(jcx, 0, NULL);
 
696
    establish_property_object(obj, name, a);
 
697
    return a;
 
698
}                               /* establish_property_array */
 
699
 
 
700
void
 
701
establish_property_object(void *parent, const char *name, void *child)
 
702
{
 
703
    JS_DefineProperty(jcx, parent, name,
 
704
       OBJECT_TO_JSVAL(((JSObject *) child)), 0, 0, PROP_FIXED);
 
705
}                               /* establish_property_object */
 
706
 
 
707
void
 
708
establish_property_url(void *jv, const char *name,
 
709
   const char *url, bool readonly)
 
710
{
 
711
    JSObject *obj = jv;
 
712
    jsuint attr = JSPROP_ENUMERATE | JSPROP_PERMANENT;
 
713
    if(readonly)
 
714
        attr |= JSPROP_READONLY;
 
715
 
 
716
/* window.location, and document.location, has a special setter */
 
717
    my_setter = 0;
 
718
    if(stringEqual(name, "location"))
 
719
        my_setter = setter_loc;
 
720
    uo = JS_NewObject(jcx, &url_class, NULL, obj);
 
721
    JS_DefineProperty(jcx, obj, name,
 
722
       OBJECT_TO_JSVAL(uo), NULL, my_setter, attr);
 
723
    if(!url)
 
724
        url = EMPTYSTRING;
 
725
    url_initialize(url, readonly, false);
 
726
    if(my_setter == setter_loc) {
 
727
        if(obj == jwin)
 
728
            jwloc = uo;
 
729
        else
 
730
            jdloc = uo;
 
731
        JS_DefineFunction(jcx, uo, "reload", loc_reload, 0, PROP_FIXED);
 
732
        JS_DefineFunction(jcx, uo, "replace", loc_replace, 1, PROP_FIXED);
 
733
    }                           /* location object */
 
734
}                               /* establish_property_url */
 
735
 
 
736
void
 
737
set_property_string(void *jv, const char *name, const char *value)
 
738
{
 
739
    JSObject *obj = jv;
 
740
    jsval vv;
 
741
    setter_suspend = true;
 
742
    vv = ((value && *value) ? STRING_TO_JSVAL(JS_NewStringCopyZ(jcx, value))
 
743
       : JS_GetEmptyStringValue(jcx));
 
744
    JS_SetProperty(jcx, obj, name, &vv);
 
745
    setter_suspend = false;
 
746
}                               /* set_property_string */
 
747
 
 
748
void
 
749
set_property_number(void *jv, const char *name, int value)
 
750
{
 
751
    JSObject *obj = jv;
 
752
    jsval vv;
 
753
    setter_suspend = true;
 
754
    vv = INT_TO_JSVAL(value);
 
755
    JS_SetProperty(jcx, obj, name, &vv);
 
756
    setter_suspend = false;
 
757
}                               /* set_property_number */
 
758
 
 
759
void
 
760
set_property_bool(void *jv, const char *name, int value)
 
761
{
 
762
    JSObject *obj = jv;
 
763
    jsval vv;
 
764
    setter_suspend = true;
 
765
    vv = (value ? JSVAL_TRUE : JSVAL_FALSE);
 
766
    JS_SetProperty(jcx, obj, name, &vv);
 
767
    setter_suspend = false;
 
768
}                               /* set_property_bool */
 
769
 
 
770
/* These get routines assume the property exists, and of the right type. */
 
771
const char *
 
772
get_property_url(void *jv, bool doaction)
 
773
{
 
774
    JSObject *obj = jv;
 
775
    JSObject *lo;               /* location object */
 
776
    jsval v;
 
777
    const char *s;
 
778
    JSBool found = false;
 
779
    if(!obj)
 
780
        return 0;
 
781
    if(!doaction) {
 
782
        JS_HasProperty(jcx, obj, "href", &found);
 
783
        if(found)
 
784
            JS_GetProperty(jcx, obj, "href", &v);
 
785
        if(!found) {
 
786
            JS_HasProperty(jcx, obj, "src", &found);
 
787
            if(found)
 
788
                JS_GetProperty(jcx, obj, "src", &v);
 
789
        }
 
790
    } else {
 
791
        JS_HasProperty(jcx, obj, "action", &found);
 
792
        if(found)
 
793
            JS_GetProperty(jcx, obj, "action", &v);
 
794
    }
 
795
    if(!found)
 
796
        return 0;
 
797
    if(!JSVAL_IS_STRING(v)) {
 
798
        if(!JSVAL_IS_OBJECT(v)) {
 
799
          badobj:
 
800
            JS_ReportError(jcx,
 
801
               "url object is assigned something that I don't understand; I may not be able to fetch the next web page.");
 
802
            return 0;
 
803
        }
 
804
        lo = JSVAL_TO_OBJECT(v);
 
805
        JS_HasProperty(jcx, lo, "actioncrash", &found);
 
806
        if(found)
 
807
            return 0;
 
808
        if(!JS_InstanceOf(jcx, lo, &url_class, emptyArgs))
 
809
            goto badobj;
 
810
        JS_GetProperty(jcx, lo, "href", &v);
 
811
    }
 
812
    s = stringize(v);
 
813
    return s;
 
814
}                               /* get_property_url */
 
815
 
 
816
const char *
 
817
get_property_string(void *jv, const char *name)
 
818
{
 
819
    JSObject *obj = jv;
 
820
    jsval v;
 
821
    if(!obj)
 
822
        return 0;
 
823
    JS_GetProperty(jcx, obj, name, &v);
 
824
    return stringize(v);
 
825
}                               /* get_property_string */
 
826
 
 
827
bool
 
828
get_property_bool(void *jv, const char *name)
 
829
{
 
830
    JSObject *obj = jv;
 
831
    jsval v;
 
832
    if(!obj)
 
833
        return false;
 
834
    JS_GetProperty(jcx, obj, name, &v);
 
835
    return JSVAL_TO_BOOLEAN(v);
 
836
}                               /* get_property_bool */
 
837
 
 
838
const char *
 
839
get_property_option(void *jv)
 
840
{
 
841
    JSObject *obj = jv;
 
842
    jsval v;
 
843
    JSObject *oa;               /* option array */
 
844
    JSObject *oo;               /* option object */
 
845
    int n;
 
846
 
 
847
    if(!obj)
 
848
        return 0;
 
849
    JS_GetProperty(jcx, obj, "selectedIndex", &v);
 
850
    n = JSVAL_TO_INT(v);
 
851
    if(n < 0)
 
852
        return 0;
 
853
    JS_GetProperty(jcx, obj, "options", &v);
 
854
    oa = JSVAL_TO_OBJECT(v);
 
855
    JS_GetElement(jcx, oa, n, &v);
 
856
    oo = JSVAL_TO_OBJECT(v);
 
857
    return get_property_string(oo, "value");
 
858
}                               /* get_property_option */
 
859
 
 
860
 
 
861
/*********************************************************************
 
862
Manage the array of options under an html select.
 
863
This will explode into a lot of code, if we ever implement
 
864
dynamic option lists under js control.
 
865
*********************************************************************/
 
866
 
 
867
static JSClass option_class = {
 
868
    "Option",
 
869
    JSCLASS_HAS_PRIVATE,
 
870
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
871
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
872
};
 
873
void *
 
874
establish_js_option(void *ev, int idx)
 
875
{
 
876
    JSObject *so = ev;          /* select object */
 
877
    jsval vv;
 
878
    JSObject *oa;               /* option array */
 
879
    JSObject *oo;               /* option object */
 
880
    JS_GetProperty(jcx, so, "options", &vv);
 
881
    oa = JSVAL_TO_OBJECT(vv);
 
882
    oo = JS_NewObject(jcx, &option_class, NULL, so);
 
883
    vv = OBJECT_TO_JSVAL(oo);
 
884
    JS_DefineElement(jcx, oa, idx, vv, NULL, NULL, JSPROP_ENUMERATE);
 
885
/* option.form = select.form */
 
886
    JS_GetProperty(jcx, so, "form", &vv);
 
887
    JS_SetProperty(jcx, oo, "form", &vv);
 
888
    return oo;
 
889
}                               /* establish_js_option */
 
890
 
 
891
 
 
892
/*********************************************************************
 
893
Compile and call event handlers.
 
894
*********************************************************************/
 
895
 
 
896
bool
 
897
handlerGo(void *obj, const char *name)
 
898
{
 
899
    jsval v, rval;
 
900
    bool rc;
 
901
    JSObject *fo;               /* function object */
 
902
    JSFunction *f;
 
903
    JSBool found;
 
904
    JS_HasProperty(jcx, obj, name, &found);
 
905
    if(!found)
 
906
        return false;
 
907
    JS_GetProperty(jcx, obj, name, &v);
 
908
    if(!JSVAL_IS_OBJECT(v))
 
909
        return false;
 
910
    fo = JSVAL_TO_OBJECT(v);
 
911
    if(!JS_ObjectIsFunction(jcx, fo))
 
912
        return false;
 
913
    f = JS_ValueToFunction(jcx, v);
 
914
    JS_CallFunction(jcx, obj, f, 0, emptyArgs, &rval);
 
915
    rc = true;
 
916
    if(JSVAL_IS_BOOLEAN(rval))
 
917
        rc = JSVAL_TO_BOOLEAN(rval);
 
918
    JS_GC(jcx);
 
919
    return rc;
 
920
}                               /* handlerGo */
 
921
 
 
922
void
 
923
handlerSet(void *ev, const char *name, const char *code)
 
924
{
 
925
    JSObject *obj = ev;
 
926
    char *newcode;
 
927
    JSBool found;
 
928
    if(!obj)
 
929
        return;
 
930
    newcode = allocMem(strlen(code) + 60);
 
931
    strcpy(newcode, "with(document) { ");
 
932
    JS_HasProperty(jcx, obj, "form", &found);
 
933
    if(found)
 
934
        strcat(newcode, "with(this.form) { ");
 
935
    strcat(newcode, code);
 
936
    if(found)
 
937
        strcat(newcode, " }");
 
938
    strcat(newcode, " }");
 
939
    JS_CompileFunction(jcx, obj, name, 0, emptyParms,   /* no named parameters */
 
940
       newcode, strlen(newcode), name, 1);
 
941
    nzFree(newcode);
 
942
}                               /* handlerSet */
 
943
 
 
944
void
 
945
link_onunload_onclick(void *jv)
 
946
{
 
947
    JSObject *obj = jv;
 
948
    jsval v;
 
949
    JS_GetProperty(jcx, obj, "onunload", &v);
 
950
    JS_DefineProperty(jcx, obj, "onclick", v, 0, 0, PROP_FIXED);
 
951
}                               /* link_onunload_onclick */
 
952
 
 
953
bool
 
954
handlerPresent(void *ev, const char *name)
 
955
{
 
956
    JSObject *obj = ev;
 
957
    JSBool found = JS_FALSE;
 
958
    if(!obj)
 
959
        return false;
 
960
    JS_HasProperty(jcx, obj, name, &found);
 
961
    return found;
 
962
}                               /* handlerPresent */