168
168
{"IMAGE", "an image", TAGACT_IMAGE, 0, 0, 4},
169
169
{"BR", "a line break", TAGACT_BR, 0, 1, 4},
170
170
{"P", "a paragraph", TAGACT_NOP, 0, 2, 5},
171
{"DIV", "a divided section", TAGACT_DIV, 1, 5, 0},
171
{"DIV", "a divided section", TAGACT_DIV, 3, 5, 0},
172
172
{"HTML", "html", TAGACT_NOP, 0, 0, 0},
173
173
{"BLOCKQUOTE", "a quoted paragraph", TAGACT_NOP, 1, 10, 1},
174
174
{"H1", "a level 1 header", TAGACT_NOP, 1, 10, 1},
346
347
if(stringEqual(name, "onchange")) {
347
348
if(action == TAGACT_INPUT || action == TAGACT_SELECT) {
348
349
if(itype == INP_TA)
349
runningError("onchange handler does not work with textarea");
350
runningError(MSG_OnchangeText);
350
351
else if(itype > INP_HIDDEN && itype <= INP_SELECT) {
351
352
topTag->handler = true;
374
377
/* Some warnings about some handlers that we just don't "handle" */
375
378
if(handlerPresent(ev, "onkeypress") ||
376
379
handlerPresent(ev, "onkeyup") || handlerPresent(ev, "onkeydown"))
378
("warning, javascript cannot be invoked through keystroke events");
380
browseError(MSG_JSKeystroke);
379
381
if(handlerPresent(ev, "onfocus") || handlerPresent(ev, "onblur"))
380
browseError("javascript cannot be invoked through focus or blur");
382
browseError(MSG_JSFocus);
381
383
if(handlerPresent(ev, "ondblclick"))
382
runningError("warning, javascript cannot be invoked by a double click");
384
runningError(MSG_Doubleclick);
383
385
if(handlerPresent(ev, "onclick")) {
384
386
if((action == TAGACT_A || action == TAGACT_AREA || action == TAGACT_FRAME) && topTag->href || action == TAGACT_INPUT && (itype <= INP_SUBMIT || itype >= INP_RADIO)) ; /* ok */
387
("warning, onclick code is not associated with a hyperlink or button");
389
390
if(handlerPresent(ev, "onchange")) {
390
391
if(action != TAGACT_INPUT && action != TAGACT_SELECT || itype == INP_TA)
391
browseError("onchange handler is not accessible");
392
browseError(MSG_StrayOnchange);
393
394
/* Other warnings might be appropriate, but I'm going to assume this
394
395
* is valid javascript, and you won't put an onsubmit function on <P> etc */
527
528
topTag->controller = currentForm;
528
529
fo = currentForm->jv;
529
530
} else if(itype != INP_BUTTON)
530
browseError("%s is not part of a fill-out form", topTag->info->desc);
531
browseError(MSG_NotInForm2, topTag->info->desc);
533
534
if(namecheck && !topTag->name)
534
browseError("%s does not have a name", topTag->info->desc);
535
browseError(MSG_FieldNoName, topTag->info->desc);
601
602
if(stringEqualCI(a, "post"))
602
603
topTag->post = true;
603
604
else if(!stringEqualCI(a, "get"))
604
browseError("unrecognized method, plese use GET or POST");
605
browseError(MSG_GetPost);
610
611
if(stringEqualCI(a, "multipart/form-data"))
611
612
topTag->mime = true;
612
613
else if(!stringEqualCI(a, "application/x-www-form-urlencoded"))
614
("unrecognized enctype, plese use multipart/form-data or application/x-www-form-urlencoded");
614
browseError(MSG_Enctype);
625
625
else if(stringEqualCI(prot, "https"))
626
626
topTag->secure = true;
627
627
else if(!stringEqualCI(prot, "http"))
628
browseError("form cannot submit using protocol %s", prot);
628
browseError(MSG_FormProtBad, prot);
650
650
memcpy(cw->dw + 3, "<html>\n", 7);
651
651
side = sideBuffer(0, cw->dw + 10, -1, cw->fileName, true);
653
printf("A separate window has been created in buffer %d\n", side);
653
i_printf(MSG_SideBufferX, side);
656
("The following has been sent to your browser, but there is no buffer to contain it.");
655
i_puts(MSG_NoSideBuffer);
657
656
printf("%s\n", cw->dw + 10);
671
670
caseShift(s, 'l');
672
671
n = stringInList(inp_types, s);
674
browseError("unrecognized input type %s", s);
673
browseError(MSG_InputType, s);
702
701
sprintf(namebuf, "|%s|", topTag->name);
703
702
if(strstr(radioChecked, namebuf)) {
704
browseError("multiple radio buttons have been selected");
703
browseError(MSG_RadioMany);
707
706
stringAndString(&radioChecked, &radioChecked_l, namebuf + 1);
850
849
t = locateOptionByName(sel, iopt, &pmc, false);
853
setError("%d is out of range", n);
852
setError(MSG_XOutOfRange, n);
855
setError("%s options contain the string %s",
856
(pmc ? "multiple" : "no"), iopt);
854
setError(pmc + MSG_OptMatchNone, iopt);
857
855
/* This should never happen when we're doing a set check */
860
("error resolving option %s during sync or form submit",
857
runningError(MSG_OptionSync, iopt);
944
940
set_property_bool(eo, "checked", checked);
948
944
value = getFieldFromBuffer(t->seqno);
949
945
/* If that line has been deleted from the user's buffer,
950
946
* indicated by value = 0,
951
947
* revert back to the original (reset) value. */
953
949
if(itype == INP_SELECT) {
954
/* should value be replaced here, or do we know it's ok? */
955
950
locateOptions(t, (value ? value : t->value), 0, 0, true);
952
value = cloneString( get_property_option(eo));
958
955
if(itype == INP_TA) {
960
957
set_property_string(eo, "value", 0);
1010
browseError("%s is closed inside %s", desc, t->info->desc);
1007
browseError(MSG_TagNest, desc, t->info->desc);
1015
1012
if(!(t->info->nest & 2))
1016
browseError("%s begins in the middle of %s", desc, desc);
1013
browseError(MSG_TagInTag, desc, desc);
1021
browseError("an unexpected closure of %s, which was never opened",
1018
browseError(MSG_TagClose, desc);
1024
1020
} /* findOpenTag */
1056
1054
if(!handlerPresent(obj, "onunload"))
1058
1056
if(handlerPresent(obj, "onclick")) {
1060
("tag cannot have onunload and onclik handlers simultaneously");
1057
runningError(MSG_UnloadClick);
1273
1270
continue; /* negated version means nothing */
1275
1272
/* Does this tag force the closure of an anchor? */
1276
if(ti->bits & TAG_CLOSEA && currentA &&
1277
(action != TAGACT_A || !slash) &&
1278
(a_text || action <= TAGACT_OPTION)) {
1279
browseError("%s appears inside an anchor", ti->desc);
1280
stringAndString(&new, &l, "\2000}");
1281
currentA->balanced = true;
1283
/* when the </a> comes along, it will be unbalanced, and we'll ignore it. */
1273
if(currentA && (action != TAGACT_A || !slash)) {
1274
if(open && open->clickable)
1275
goto forceCloseAnchor;
1276
rc = htmlAttrPresent(topAttrib, "onclick");
1278
ti->bits & TAG_CLOSEA && (a_text || action <= TAGACT_OPTION)) {
1279
browseError(MSG_InAnchor, ti->desc);
1281
stringAndString(&new, &l, "\2000}");
1282
currentA->balanced = true;
1284
/* if/when the </a> comes along, it will be unbalanced, and we'll ignore it. */
1286
1288
retainTag = true;
1299
1303
if(v->action != action &&
1300
1304
!(v->action == TAGACT_OPTION && action == TAGACT_SELECT) ||
1301
1305
action != TAGACT_OPTION && !slash)
1302
browseError("%s contains html tags", v->info->desc);
1306
browseError(MSG_HasTags, v->info->desc);
1303
1307
if(!(ti->bits & TAG_CLOSEA))
1305
1309
/* close off the title or option */
1410
1413
domLink("Anchor", topTag->name, topTag->id, "href",
1411
1414
topTag->href, "links", jdoc, false);
1412
1415
get_js_events();
1418
topTag->clickable = true;
1415
1420
a_text = false;
1531
1536
case TAGACT_TR:
1533
browseError("%s is not inside a table", ti->desc);
1538
browseError(MSG_NotInTable, ti->desc);
1536
/* This really doesn't work for tables inside tables */
1541
1545
tdfirst = true;
1542
if((!slash) && (open = findOpenTag("table")) && (to = open->jv)) {
1546
if((!slash) && (open = findOpenTag("table")) && open->jv) {
1545
1549
domLink("Trow", topTag->name, topTag->id, 0, 0,
1546
1550
"rows", open->jv, false);
1547
1551
get_js_events();
1552
establish_property_array(to, "cells");
1551
1556
case TAGACT_TD:
1553
browseError("%s is not inside a table row", ti->desc);
1558
browseError(MSG_NotInRow, ti->desc);
1564
1569
stringAndChar(&new, &l, '|');
1571
if((open = findOpenTag("tr")) && open->jv) {
1574
domLink("Cell", topTag->name, topTag->id, 0, 0,
1575
"cells", open->jv, false);
1568
1580
case TAGACT_DIV:
1674
1686
t->value = htmlAttrVal(topAttrib, "value");
1675
1687
if(htmlAttrPresent(topAttrib, "selected")) {
1676
1688
if(currentSel->lic && !currentSel->multiple)
1677
browseError("multiple options are selected");
1689
browseError(MSG_ManyOptSelected);
1679
1691
t->checked = t->rchecked = true, ++currentSel->lic;
1738
1750
domLink("Area", topTag->name, topTag->id, "href",
1739
1751
topTag->href, "areas", jdoc, false);
1753
topTag->clickable = true;
1741
1754
get_js_events();
1846
1858
if(browseLocal && !isURL(t->href)) {
1847
1859
if(!fileIntoMemory(t->href, &serverData,
1848
1860
&serverDataLen)) {
1850
("could not fetch local javascript, %s",
1861
runningError(MSG_GetLocalJS, errorMsg);
1853
1863
javatext = serverData;
1854
1864
prepareForBrowse(javatext, serverDataLen);
1859
1869
prepareForBrowse(javatext, serverDataLen);
1861
1871
nzFree(serverData);
1863
("could not fetch javascript from %s, code %d",
1872
runningError(MSG_GetJS, t->href, hcode);
1867
runningError("could not fetch javascript, %s",
1875
runningError(MSG_GetJS2, errorMsg);
1871
1878
js_file = t->href;
1873
1880
} /* fetch from the net */
1875
char *w = strrchr(js_file, '/');
1884
w = strrchr(js_file, '/');
1877
1886
/* Trailing slash doesn't count */
1878
1887
if(w[1] == 0 && w > js_file)
1942
1951
stringAndString(&new, &l, hnum);
1944
1953
lastact = action;
1955
topTag->clickable = true;
1957
topTag->href = cloneString("#");
1959
sprintf(hnum, "%c%d{", InternalCodeChar, topTag->seqno);
1960
stringAndString(&new, &l, hnum);
1945
1962
} /* loop over html string */
2015
2032
if(v == (struct htmlTag *)&htmlStack) { /* end of list */
2016
browseError("label %s not found", a);
2033
browseError(MSG_NoLable2, a);
2019
2036
} /* loop over all tags */
2416
2433
/* sanity checks on the input */
2417
2434
if(itype <= INP_SUBMIT) {
2435
int b = MSG_IsButton;
2419
2436
if(itype == INP_SUBMIT || itype == INP_IMAGE)
2437
b = MSG_SubmitButton;
2421
2438
if(itype == INP_RESET)
2423
setError("this is a %sbutton; use i* to push the button", b);
2439
b = MSG_ResetButton;
2427
2444
if(itype == INP_TA) {
2428
setError("this is a textarea, you must edit it from session %d",
2445
setError(MSG_Textarea, t->lic);
2433
2449
if(t->rdonly) {
2434
setError("readonly field");
2450
setError(MSG_Readonly);
2438
2454
if(strchr(newtext, '\n')) {
2439
setError("input field cannot contain a newline character");
2455
setError(MSG_InputNewline);
2443
2459
if(itype >= INP_TEXT && itype <= INP_NUMBER && t->lic && newlen > t->lic) {
2444
setError("input too long, limit %d", t->lic);
2460
setError(MSG_InputLong, t->lic);
2448
2464
if(itype >= INP_RADIO) {
2449
2465
if(newtext[0] != '+' && newtext[0] != '-' || newtext[1]) {
2450
setError("field must be set to + or -");
2466
setError(MSG_InputRadio);
2453
2469
if(itype == INP_RADIO && newtext[0] == '-') {
2455
("you cannot clear a radio button; you must set another one");
2470
setError(MSG_ClearRadio);
2475
2490
if(!envFile(newtext, &newtext))
2477
2492
if(newtext[0] && access(newtext, 4)) {
2478
setError("%s is not an accessible file", newtext);
2493
setError(MSG_FileAccess, newtext);
2483
2498
if(itype == INP_NUMBER) {
2484
2499
if(*newtext && stringIsNum(newtext) < 0) {
2485
setError("number expected");
2500
setError(MSG_NumberExpected);
2510
2525
if(itype >= INP_RADIO && tagHandler(t->seqno, "onclick")) {
2512
runningError("javascript disabled, skipping the onclick code");
2527
runningError(MSG_NJNoOnclick);
2515
2530
handlerGo(t->jv, "onclick");
2522
2537
if(itype >= INP_TEXT && itype <= INP_SELECT &&
2523
2538
tagHandler(t->seqno, "onchange")) {
2525
runningError("javascript disabled, skipping the onchange code");
2540
runningError(MSG_NJNoOnchange);
2528
2543
handlerGo(t->jv, "onchange");
2672
2687
if(fsep == '-') {
2673
2688
stringAndString(post, l, "--");
2674
2689
stringAndString(post, l, boundary);
2690
stringAndChar(post, l, '\r');
2677
2693
stringAndChar(post, l, fsep);
2704
2720
stringAndString(post, l, name);
2705
stringAndString(post, l, "=\n");
2721
stringAndString(post, l, "=\r\n");
2708
2724
stringAndString(post, l, "Content-Disposition: form-data; name=\"");
2729
2745
stringAndString(post, l, val);
2730
stringAndChar(post, l, '\n');
2746
stringAndString(post, l, eol);
2754
stringAndString(post, l, "\nContent-Type: ");
2770
stringAndString(post, l, "\r\nContent-Type: ");
2755
2771
stringAndString(post, l, ct);
2756
stringAndString(post, l, "\nContent-Transfer-Encoding: ");
2772
stringAndString(post, l, "\r\nContent-Transfer-Encoding: ");
2757
2773
stringAndString(post, l, ce);
2758
stringAndString(post, l, "\n\n");
2774
stringAndString(post, l, "\r\n\r\n");
2759
2775
stringAndString(post, l, val);
2760
stringAndChar(post, l, '\n');
2776
stringAndString(post, l, eol);
2786
2802
boundary = makeBoundary();
2787
2803
stringAndString(post, l, "`mfd~");
2788
2804
stringAndString(post, l, boundary);
2789
stringAndChar(post, l, '\n');
2805
stringAndString(post, l, eol);
2792
2808
while(t = *list++) {
2949
errorPrint("@unexpected input type in submitForm()");
2964
i_printfExit(MSG_UnexSubmitForm);
2952
2967
postNameVal(name, value, fsep, false, boundary, post, l);
2955
2970
if(form->mime) { /* the last boundary */
2956
2971
stringAndString(post, l, "--");
2957
2972
stringAndString(post, l, boundary);
2958
stringAndString(post, l, "--\n");
2973
stringAndString(post, l, "--\r\n");
2962
debugPrint(0, "warning: fields without names will not be transmitted");
2963
puts("submitting form");
2977
i_puts(MSG_UnnamedFields);
2978
i_puts(MSG_FormSubmit);
3006
3021
if(itype > INP_SUBMIT) {
3007
setError("this is an input field, not a button");
3022
setError(MSG_NoButton);
3011
3026
if(!form && itype != INP_BUTTON) {
3012
setError("this button is not part of a form");
3027
setError(MSG_NotInForm);
3016
3031
if(t && tagHandler(t->seqno, "onclick")) {
3018
runningError("javascript disabled, %s",
3020
INP_BUTTON ? "no action taken" : "skipping the onclick code");
3033
runningError(itype ==
3034
INP_BUTTON ? MSG_NJNoAction : MSG_NJNoOnclick);
3022
3036
rc = handlerGo(t->jv, "onclick");
3031
3045
if(itype == INP_BUTTON) {
3032
3046
if(!handlerPresent(t->jv, "onclick")) {
3033
setError("no javascript associated with this button");
3047
setError(MSG_ButtonNoJS);
3040
3054
/* Before we reset, run the onreset code */
3041
3055
if(t && tagHandler(form->seqno, "onreset")) {
3043
runningError("javascript disabled, skipping the onreset code");
3057
runningError(MSG_NJNoReset);
3045
3059
rc = handlerGo(form->jv, "onreset");
3057
3071
/* Before we submit, run the onsubmit code */
3058
3072
if(t && tagHandler(form->seqno, "onsubmit")) {
3060
runningError("javascript disabled, skipping the onsubmit code");
3074
runningError(MSG_NJNoSubmit);
3062
3076
rc = handlerGo(form->jv, "onsubmit");
3095
3109
prot = getProtURL(action);
3097
setError("the action of the form is not a url");
3111
setError(MSG_FormBadURL);
3101
3115
if(stringEqualCI(prot, "javascript")) {
3102
3116
if(cw->jsdead) {
3103
setError("javascript is disabled, cannot activate this form");
3117
setError(MSG_NJNoForm);
3106
3120
javaParseExecute(form->jv, action, 0, 0);
3115
3129
form->bymail = true;
3116
3130
} else if(stringEqualCI(prot, "http")) {
3117
3131
if(form->secure) {
3119
("This form has changed from https to http, and is now insecure");
3132
setError(MSG_BecameInsecure);
3122
3135
} else if(!stringEqualCI(prot, "https")) {
3123
setError("cannot submit using protocol %s", prot);
3136
setError(MSG_SubmitProtBad, prot);
3128
3141
stringAndString(&post, &l, action);
3129
3142
section = strchr(post, '#');
3132
"warning: form url specifies a section %s, which will be ignored",
3144
i_printf(MSG_SectionIgnored, section);
3135
3146
l = strlen(post);
3137
3148
section = strpbrk(post, "?\1");
3139
3150
if(*section == '\1' || !(form->bymail | form->post)) {
3141
"warning: the url already specifies some data, which will be overwritten by the data in this form");
3152
"the url already specifies some data, which will be overwritten by the data in this form");
3143
3154
l = strlen(post);
3178
3189
sprintf(q, "subject:html form(%s)\n", name ? name : "?");
3179
3190
strcpy(q + strlen(q), post + actlen);
3181
printf("sending mail to %s\n", addr);
3192
i_printf(MSG_MailSending, addr);
3183
3194
rc = sendMail(localAccount, tolist, q, -1, atlist, 0, false);
3186
("Your information has been sent; watch for a reply via return mail.\n");
3196
i_puts(MSG_MailSent);
3202
3212
struct htmlTag **list = cw->tags;
3203
3213
struct htmlTag *t;
3205
errorPrint("@list = 0 in tagFromJavaVar()");
3215
i_printfExit(MSG_NullListInform);
3206
3216
while(t = *list++)
3211
("could not find the html tag associated with the javascript variable being modified");
3220
runningError(MSG_LostTag);
3213
3222
} /* tagFromJavaVar */
3228
3237
if(t->itype == INP_TA) {
3230
("javascript modified a textarea, and that isn't implemented yet");
3238
runningError(MSG_JSTextarea);
3233
3241
updateFieldInBuffer(t->seqno, val, parsePage ? 0 : 2, false);
3293
3301
javaSetsTimeout(int n, const char *jsrc, void *to, bool isInterval)
3295
struct htmlTag *t = newTag("A");
3303
struct htmlTag *t = newTag("a");
3296
3304
char timedesc[48];