~ubuntu-branches/ubuntu/raring/edbrowse/raring

« back to all changes in this revision

Viewing changes to html.c

  • Committer: Bazaar Package Importer
  • Author(s): Kapil Hari Paranjape
  • Date: 2007-12-05 10:39:04 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20071205103904-zr3kzzu0ym6stg16
Tags: 3.3.1-1
* New upstream version (3.3.1).
  - Messages have been internationalised.
  - Supports LANG environment variable.
  - Includes man page.
* Incorporate upstream man page:
  - debian/rules: Add rule to install upstream man page.
  - debian/edbrowse.1: Not required. Removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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},
241
241
    bool retain:1;
242
242
    bool multiple:1;
243
243
    bool rdonly:1;
 
244
    bool clickable:1;           /* but not an input field */
244
245
    bool secure:1;
245
246
    bool checked:1;
246
247
    bool rchecked:1;            /* for reset */
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;
352
353
                if(currentForm)
356
357
    }
357
358
}                               /* get_js_event */
358
359
 
 
360
static bool strayClick;
 
361
 
359
362
static void
360
363
get_js_events(void)
361
364
{
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"))
377
 
        browseError
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 */
385
387
        else
386
 
            browseError
387
 
               ("warning, onclick code is not associated with a hyperlink or button");
 
388
            strayClick = true;
388
389
    }
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);
392
393
    }
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);
531
532
 
532
533
    htmlName();
533
534
    if(namecheck && !topTag->name)
534
 
        browseError("%s does not have a name", topTag->info->desc);
 
535
        browseError(MSG_FieldNoName, topTag->info->desc);
535
536
 
536
537
    if(fo) {
537
538
        topTag->jv = e =
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);
605
606
        nzFree(a);
606
607
    }
607
608
 
610
611
        if(stringEqualCI(a, "multipart/form-data"))
611
612
            topTag->mime = true;
612
613
        else if(!stringEqualCI(a, "application/x-www-form-urlencoded"))
613
 
            browseError
614
 
               ("unrecognized enctype, plese use multipart/form-data or application/x-www-form-urlencoded");
 
614
            browseError(MSG_Enctype);
615
615
        nzFree(a);
616
616
    }
617
617
 
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);
629
629
        }
630
630
    }
631
631
 
650
650
    memcpy(cw->dw + 3, "<html>\n", 7);
651
651
    side = sideBuffer(0, cw->dw + 10, -1, cw->fileName, true);
652
652
    if(side) {
653
 
        printf("A separate window has been created in buffer %d\n", side);
 
653
        i_printf(MSG_SideBufferX, side);
654
654
    } else {
655
 
        puts
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);
658
657
    }
659
658
    nzFree(cw->dw);
671
670
        caseShift(s, 'l');
672
671
        n = stringInList(inp_types, s);
673
672
        if(n < 0) {
674
 
            browseError("unrecognized input type %s", s);
 
673
            browseError(MSG_InputType, s);
675
674
            n = INP_TEXT;
676
675
        }
677
676
    }
701
700
            }
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);
705
704
                return;
706
705
            }
707
706
            stringAndString(&radioChecked, &radioChecked_l, namebuf + 1);
850
849
            t = locateOptionByName(sel, iopt, &pmc, false);
851
850
        if(!t) {
852
851
            if(n >= 0)
853
 
                setError("%d is out of range", n);
 
852
                setError(MSG_XOutOfRange, n);
854
853
            else
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 */
858
856
            if(setcheck) {
859
 
                runningError
860
 
                   ("error resolving option %s during sync or form submit",
861
 
                   iopt);
 
857
                runningError(MSG_OptionSync, iopt);
862
858
                continue;
863
859
            }
864
860
            goto fail;
944
940
            set_property_bool(eo, "checked", checked);
945
941
            continue;
946
942
        }
947
 
        /* checkable */
 
943
 
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. */
952
948
 
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);
 
951
            if(!t->multiple)
 
952
                value = cloneString( get_property_option(eo));
956
953
        }
957
 
        /* select */
 
954
 
958
955
        if(itype == INP_TA) {
959
956
            if(!value) {
960
957
                set_property_string(eo, "value", 0);
972
969
            nzFree(cxbuf);
973
970
            continue;
974
971
        }
975
 
        /* text area */
 
972
 
976
973
        if(value) {
977
974
            set_property_string(eo, "value", value);
978
975
            nzFree(value);
1007
1004
        if(closing) {
1008
1005
            if(match)
1009
1006
                return t;
1010
 
            browseError("%s is closed inside %s", desc, t->info->desc);
 
1007
            browseError(MSG_TagNest, desc, t->info->desc);
1011
1008
            continue;
1012
1009
        }
1013
1010
        if(!match)
1014
1011
            continue;
1015
1012
        if(!(t->info->nest & 2))
1016
 
            browseError("%s begins in the middle of %s", desc, desc);
 
1013
            browseError(MSG_TagInTag, desc, desc);
1017
1014
        return t;
1018
1015
    }                           /* loop */
1019
1016
 
1020
1017
    if(closing)
1021
 
        browseError("an unexpected closure of %s, which was never opened",
1022
 
           desc);
 
1018
        browseError(MSG_TagClose, desc);
1023
1019
    return NULL;
1024
1020
}                               /* findOpenTag */
1025
1021
 
1040
1036
    t->info = ti;
1041
1037
    t->seqno = ntags++;
1042
1038
    t->balanced = true;
 
1039
    if(stringEqual(name, "a"))
 
1040
        t->clickable = true;
1043
1041
    addToListBack(&htmlStack, t);
1044
1042
    return t;
1045
1043
}                               /* newTag */
1056
1054
    if(!handlerPresent(obj, "onunload"))
1057
1055
        return;
1058
1056
    if(handlerPresent(obj, "onclick")) {
1059
 
        runningError
1060
 
           ("tag cannot have onunload and onclik handlers simultaneously");
 
1057
        runningError(MSG_UnloadClick);
1061
1058
        return;
1062
1059
    }
1063
1060
 
1236
1233
            currentTA = 0;
1237
1234
            if(slash)
1238
1235
                continue;
1239
 
            browseError("a text area begins in the middle of a text area");
 
1236
            browseError(MSG_TextareaNest);
1240
1237
        }
1241
1238
 
1242
1239
        if(!action)
1273
1270
            continue;           /* negated version means nothing */
1274
1271
 
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;
1282
 
            currentA = 0;
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");
 
1277
            if(rc ||
 
1278
               ti->bits & TAG_CLOSEA && (a_text || action <= TAGACT_OPTION)) {
 
1279
                browseError(MSG_InAnchor, ti->desc);
 
1280
              forceCloseAnchor:
 
1281
                stringAndString(&new, &l, "\2000}");
 
1282
                currentA->balanced = true;
 
1283
                currentA = 0;
 
1284
/* if/when the </a> comes along, it will be unbalanced, and we'll ignore it. */
 
1285
            }
1284
1286
        }
1285
1287
 
1286
1288
        retainTag = true;
1291
1293
        if(ti->bits & TAG_INVISIBLE)
1292
1294
            invisible = !slash;
1293
1295
 
 
1296
        strayClick = false;
 
1297
 
1294
1298
/* Are we gathering text to build title or option? */
1295
1299
        if(currentTitle || currentOpt) {
1296
1300
            char **ptr;
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))
1304
1308
                continue;
1305
1309
/* close off the title or option */
1318
1322
                    for(y = a; *y; ++y)
1319
1323
                        if(*y == ',')
1320
1324
                            *y = ' ';
1321
 
                    browseError
1322
 
                       ("option cannot contain a comma when it is part of a multiple select");
 
1325
                    browseError(MSG_OptionComma);
1323
1326
                }
1324
1327
                spaceCrunch(a, true, true);
1325
1328
                *ptr = a;
1331
1334
 
1332
1335
                if(currentOpt) {
1333
1336
                    if(!*a) {
1334
 
                        browseError("empty option");
 
1337
                        browseError(MSG_OptionEmpty);
1335
1338
                    } else {
1336
1339
                        if(!v->value)
1337
1340
                            v->value = cloneString(a);
1392
1395
            if(slash)
1393
1396
                continue;
1394
1397
            if(cw->ft)
1395
 
                browseError("multiple titles");
 
1398
                browseError(MSG_ManyTitles);
1396
1399
            offset = l;
1397
1400
            currentTitle = t;
1398
1401
            continue;
1410
1413
                   domLink("Anchor", topTag->name, topTag->id, "href",
1411
1414
                   topTag->href, "links", jdoc, false);
1412
1415
                get_js_events();
1413
 
                if(t->href)
 
1416
                if(t->href) {
1414
1417
                    a_href = true;
 
1418
                    topTag->clickable = true;
 
1419
                }
1415
1420
                a_text = false;
1416
1421
            }
1417
1422
            if(a_href) {
1485
1490
                }
1486
1491
            }
1487
1492
            if(j < 0)
1488
 
                browseError("%s is not inside a list", ti->desc);
 
1493
                browseError(MSG_NotInList, ti->desc);
1489
1494
            if(!retainTag)
1490
1495
                continue;
1491
1496
            hnum[0] = '\r';
1508
1513
                break;
1509
1514
        }
1510
1515
            if(v == (struct htmlTag *)&htmlStack)
1511
 
                browseError("%s is not inside a list", ti->desc);
 
1516
                browseError(MSG_NotInList, ti->desc);
1512
1517
            goto nop;
1513
1518
 
1514
1519
        case TAGACT_TABLE:
1530
1535
 
1531
1536
        case TAGACT_TR:
1532
1537
            if(!intable) {
1533
 
                browseError("%s is not inside a table", ti->desc);
 
1538
                browseError(MSG_NotInTable, ti->desc);
1534
1539
                continue;
1535
1540
            }
1536
 
/* This really doesn't work for tables inside tables */
1537
1541
            if(slash)
1538
1542
                --inrow;
1539
1543
            else
1540
1544
                ++inrow;
1541
1545
            tdfirst = true;
1542
 
            if((!slash) && (open = findOpenTag("table")) && (to = open->jv)) {
 
1546
            if((!slash) && (open = findOpenTag("table")) && open->jv) {
1543
1547
                htmlName();
1544
 
                topTag->jv =
 
1548
                topTag->jv = to =
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");
1548
1553
            }
1549
1554
            goto nop;
1550
1555
 
1551
1556
        case TAGACT_TD:
1552
1557
            if(!inrow) {
1553
 
                browseError("%s is not inside a table row", ti->desc);
 
1558
                browseError(MSG_NotInRow, ti->desc);
1554
1559
                continue;
1555
1560
            }
1556
1561
            if(slash)
1563
1568
                new[l] = 0;
1564
1569
                stringAndChar(&new, &l, '|');
1565
1570
            }
 
1571
            if((open = findOpenTag("tr")) && open->jv) {
 
1572
                htmlName();
 
1573
                topTag->jv = to =
 
1574
                   domLink("Cell", topTag->name, topTag->id, 0, 0,
 
1575
                   "cells", open->jv, false);
 
1576
                get_js_events();
 
1577
            }
1566
1578
            goto endtag;
1567
1579
 
1568
1580
        case TAGACT_DIV:
1599
1611
            else
1600
1612
                j &= 3;
1601
1613
            if(!j)
1602
 
                continue;
 
1614
                goto endtag;
1603
1615
            c = '\f';
1604
1616
            if(j == 1) {
1605
1617
                c = '\r';
1609
1621
            if(currentA)
1610
1622
                c = ' ';
1611
1623
            stringAndChar(&new, &l, c);
1612
 
            continue;
 
1624
            goto endtag;
1613
1625
 
1614
1626
        case TAGACT_FORM:
1615
1627
            htmlForm();
1664
1676
            if(slash)
1665
1677
                continue;
1666
1678
            if(!currentSel) {
1667
 
                browseError("option appears outside a select statement");
 
1679
                browseError(MSG_NotInSelect);
1668
1680
                continue;
1669
1681
            }
1670
1682
            currentOpt = t;
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);
1678
1690
                else
1679
1691
                    t->checked = t->rchecked = true, ++currentSel->lic;
1680
1692
            }
1738
1750
                   domLink("Area", topTag->name, topTag->id, "href",
1739
1751
                   topTag->href, "areas", jdoc, false);
1740
1752
            }
 
1753
            topTag->clickable = true;
1741
1754
            get_js_events();
1742
1755
            if(!retainTag)
1743
1756
                continue;
1824
1837
/* I'm not going to process an open ended script. */
1825
1838
            if(!rc) {
1826
1839
                nzFree(javatext);
1827
 
                runningError
1828
 
                   ("script is not closed at eof, suspending javascript");
 
1840
                runningError(MSG_ScriptNotClosed);
1829
1841
                cw->jsdead = true;
1830
1842
                continue;
1831
1843
            }
1846
1858
                        if(browseLocal && !isURL(t->href)) {
1847
1859
                            if(!fileIntoMemory(t->href, &serverData,
1848
1860
                               &serverDataLen)) {
1849
 
                                runningError
1850
 
                                   ("could not fetch local javascript, %s",
1851
 
                                   errorMsg);
 
1861
                                runningError(MSG_GetLocalJS, errorMsg);
1852
1862
                            } else {
1853
1863
                                javatext = serverData;
1854
1864
                                prepareForBrowse(javatext, serverDataLen);
1859
1869
                                prepareForBrowse(javatext, serverDataLen);
1860
1870
                            } else {
1861
1871
                                nzFree(serverData);
1862
 
                                runningError
1863
 
                                   ("could not fetch javascript from %s, code %d",
1864
 
                                   t->href, hcode);
 
1872
                                runningError(MSG_GetJS, t->href, hcode);
1865
1873
                            }
1866
1874
                        } else {
1867
 
                            runningError("could not fetch javascript, %s",
1868
 
                               errorMsg);
 
1875
                            runningError(MSG_GetJS2, errorMsg);
1869
1876
                        }
1870
1877
                        js_line = 1;
1871
1878
                        js_file = t->href;
1872
1879
                    }
1873
1880
                }               /* fetch from the net */
1874
1881
                if(javatext) {
1875
 
                    char *w = strrchr(js_file, '/');
 
1882
                    char *w = 0;
 
1883
                    if(js_file)
 
1884
                        w = strrchr(js_file, '/');
1876
1885
                    if(w) {
1877
1886
/* Trailing slash doesn't count */
1878
1887
                        if(w[1] == 0 && w > js_file)
1925
1934
            continue;
1926
1935
 
1927
1936
        default:
1928
 
            browseError("unprocessed tag action %d", action);
 
1937
            browseError(MSG_BadTag, action);
1929
1938
            continue;
1930
1939
        }                       /* switch */
1931
1940
 
1942
1951
        stringAndString(&new, &l, hnum);
1943
1952
      endtag:
1944
1953
        lastact = action;
 
1954
        if(strayClick) {
 
1955
            topTag->clickable = true;
 
1956
            a_text = false;
 
1957
            topTag->href = cloneString("#");
 
1958
            currentA = topTag;
 
1959
            sprintf(hnum, "%c%d{", InternalCodeChar, topTag->seqno);
 
1960
            stringAndString(&new, &l, hnum);
 
1961
        }
1945
1962
    }                           /* loop over html string */
1946
1963
 
1947
1964
    if(currentA) {
1989
2006
        foreach(t, htmlStack) {
1990
2007
            browseLine = t->ln;
1991
2008
            if(t->info->nest && !t->slash && !t->balanced) {
1992
 
                browseError("%s is not closed at eof", t->info->desc);
 
2009
                browseError(MSG_TagNotClosed, t->info->desc);
1993
2010
                break;
1994
2011
            }
1995
2012
 
2013
2030
                    break;
2014
2031
            }
2015
2032
            if(v == (struct htmlTag *)&htmlStack) {     /* end of list */
2016
 
                browseError("label %s not found", a);
 
2033
                browseError(MSG_NoLable2, a);
2017
2034
                break;
2018
2035
            }
2019
2036
        }                       /* loop over all tags */
2044
2061
{
2045
2062
    const struct htmlTag *t;
2046
2063
    if(!parsePage)
2047
 
        errorPrint("@calling preFormatTag without parsePage");
 
2064
        i_printfExit(MSG_ErrCallPreFormat);
2048
2065
    *pretag = *slash = false;
2049
2066
    if(tagno >= 0 && tagno < ntags) {
2050
2067
        t = tagArray[tagno];
2059
2076
    char *newbuf;
2060
2077
 
2061
2078
    if(parsePage)
2062
 
        errorPrint("@htmlParse() is not reentrant.");
 
2079
        i_printfExit(MSG_HtmlNotreentrant);
2063
2080
    parsePage = true;
2064
2081
    if(remote >= 0)
2065
2082
        browseLocal = !remote;
2356
2373
        ++s;
2357
2374
    printf("%s", s);
2358
2375
    if(t->multiple)
2359
 
        printf(" many");
 
2376
        i_printf(MSG_Many);
2360
2377
    if(t->itype >= INP_TEXT && t->itype <= INP_NUMBER && t->lic)
2361
2378
        printf("[%d]", t->lic);
2362
2379
    if(t->itype == INP_TA) {
2366
2383
        if(rows && cols) {
2367
2384
            printf("[%sx%s", rows, cols);
2368
2385
            if(wrap && stringEqualCI(wrap, "virtual"))
2369
 
                printf(" recommended");
2370
 
            printf("]");
 
2386
                i_printf(MSG_Recommended);
 
2387
            i_printf(MSG_Close);
2371
2388
        }
2372
2389
        nzFree(rows);
2373
2390
        nzFree(cols);
2375
2392
    }                           /* text area */
2376
2393
    if(t->name)
2377
2394
        printf(" %s", t->name);
2378
 
    printf("\n");
 
2395
    nl();
2379
2396
    if(t->itype != INP_SELECT)
2380
2397
        return;
2381
2398
 
2396
2413
    }
2397
2414
    if(!show) {
2398
2415
        if(!search)
2399
 
            puts("no options");
 
2416
            i_puts(MSG_NoOptions);
2400
2417
        else
2401
 
            printf("no options contain the string %s\n", search);
 
2418
            i_printf(MSG_NoOptionsMatch, search);
2402
2419
    }
2403
2420
}                               /* infShow */
2404
2421
 
2415
2432
 
2416
2433
/* sanity checks on the input */
2417
2434
    if(itype <= INP_SUBMIT) {
2418
 
        char *b = "";
 
2435
        int b = MSG_IsButton;
2419
2436
        if(itype == INP_SUBMIT || itype == INP_IMAGE)
2420
 
            b = "submit ";
 
2437
            b = MSG_SubmitButton;
2421
2438
        if(itype == INP_RESET)
2422
 
            b = "reset ";
2423
 
        setError("this is a %sbutton; use i* to push the button", b);
 
2439
            b = MSG_ResetButton;
 
2440
        setError(b);
2424
2441
        return false;
2425
2442
    }
2426
2443
 
2427
2444
    if(itype == INP_TA) {
2428
 
        setError("this is a textarea, you must edit it from session %d",
2429
 
           t->lic);
 
2445
        setError(MSG_Textarea, t->lic);
2430
2446
        return false;
2431
2447
    }
2432
2448
 
2433
2449
    if(t->rdonly) {
2434
 
        setError("readonly field");
 
2450
        setError(MSG_Readonly);
2435
2451
        return false;
2436
2452
    }
2437
2453
 
2438
2454
    if(strchr(newtext, '\n')) {
2439
 
        setError("input field cannot contain a newline character");
 
2455
        setError(MSG_InputNewline);
2440
2456
        return false;
2441
2457
    }
2442
2458
 
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);
2445
2461
        return false;
2446
2462
    }
2447
2463
 
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);
2451
2467
            return false;
2452
2468
        }
2453
2469
        if(itype == INP_RADIO && newtext[0] == '-') {
2454
 
            setError
2455
 
               ("you cannot clear a radio button; you must set another one");
 
2470
            setError(MSG_ClearRadio);
2456
2471
            return false;
2457
2472
        }
2458
2473
    }
2475
2490
        if(!envFile(newtext, &newtext))
2476
2491
            return false;
2477
2492
        if(newtext[0] && access(newtext, 4)) {
2478
 
            setError("%s is not an accessible file", newtext);
 
2493
            setError(MSG_FileAccess, newtext);
2479
2494
            return false;
2480
2495
        }
2481
2496
    }
2482
2497
 
2483
2498
    if(itype == INP_NUMBER) {
2484
2499
        if(*newtext && stringIsNum(newtext) < 0) {
2485
 
            setError("number expected");
 
2500
            setError(MSG_NumberExpected);
2486
2501
            return false;
2487
2502
        }
2488
2503
    }
2509
2524
 
2510
2525
    if(itype >= INP_RADIO && tagHandler(t->seqno, "onclick")) {
2511
2526
        if(cw->jsdead)
2512
 
            runningError("javascript disabled, skipping the onclick code");
 
2527
            runningError(MSG_NJNoOnclick);
2513
2528
        else {
2514
2529
            jSyncup();
2515
2530
            handlerGo(t->jv, "onclick");
2522
2537
    if(itype >= INP_TEXT && itype <= INP_SELECT &&
2523
2538
       tagHandler(t->seqno, "onchange")) {
2524
2539
        if(cw->jsdead)
2525
 
            runningError("javascript disabled, skipping the onchange code");
 
2540
            runningError(MSG_NJNoOnchange);
2526
2541
        else {
2527
2542
            jSyncup();
2528
2543
            handlerGo(t->jv, "onchange");
2622
2637
            set_property_number(t->jv, "selectedIndex", -1);
2623
2638
    }                           /* loop over tags */
2624
2639
 
2625
 
    puts("form has been reset");
 
2640
    i_puts(MSG_FormReset);
2626
2641
}                               /* formReset */
2627
2642
 
2628
2643
/* Fetch a field value (from a form) to post. */
2672
2687
    if(fsep == '-') {
2673
2688
        stringAndString(post, l, "--");
2674
2689
        stringAndString(post, l, boundary);
 
2690
        stringAndChar(post, l, '\r');
2675
2691
        fsep = '\n';
2676
2692
    }
2677
2693
    stringAndChar(post, l, fsep);
2702
2718
            break;
2703
2719
        case '\n':
2704
2720
            stringAndString(post, l, name);
2705
 
            stringAndString(post, l, "=\n");
 
2721
            stringAndString(post, l, "=\r\n");
2706
2722
            break;
2707
2723
        case '-':
2708
2724
            stringAndString(post, l, "Content-Disposition: form-data; name=\"");
2727
2743
        break;
2728
2744
    case '\n':
2729
2745
        stringAndString(post, l, val);
2730
 
        stringAndChar(post, l, '\n');
 
2746
        stringAndString(post, l, eol);
2731
2747
        break;
2732
2748
    case '-':
2733
2749
        if(isfile) {
2751
2767
                    break;
2752
2768
                }
2753
2769
        }
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);
2761
2777
        if(isfile)
2762
2778
            nzFree(enc);
2763
2779
        break;
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);
2790
2806
    }
2791
2807
 
2792
2808
    while(t = *list++) {
2868
2884
                    goto fail;
2869
2885
                for(j = 0; j < cxlen; ++j)
2870
2886
                    if(cxbuf[j] == 0) {
2871
 
                        setError("session %d contains nulls", cx);
 
2887
                        setError(MSG_SessionNull, cx);
2872
2888
                        nzFree(cxbuf);
2873
2889
                        goto fail;
2874
2890
                    }
2934
2950
            if(!*value)
2935
2951
                continue;
2936
2952
            if(!(form->post & form->mime)) {
2937
 
                setError
2938
 
                   ("sending a file requires method=post and enctype=multipart/form-data");
 
2953
                setError(MSG_FilePost);
2939
2954
                nzFree(value);
2940
2955
                goto fail;
2941
2956
            }
2946
2961
            goto fail;
2947
2962
        }
2948
2963
        /* file */
2949
 
        errorPrint("@unexpected input type in submitForm()");
 
2964
        i_printfExit(MSG_UnexSubmitForm);
2950
2965
 
2951
2966
      success:
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");
2959
2974
    }
2960
2975
 
2961
2976
    if(noname)
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);
2964
2979
    return true;
2965
2980
 
2966
2981
  fail:
3004
3019
    }
3005
3020
 
3006
3021
    if(itype > INP_SUBMIT) {
3007
 
        setError("this is an input field, not a button");
 
3022
        setError(MSG_NoButton);
3008
3023
        return false;
3009
3024
    }
3010
3025
 
3011
3026
    if(!form && itype != INP_BUTTON) {
3012
 
        setError("this button is not part of a form");
 
3027
        setError(MSG_NotInForm);
3013
3028
        return false;
3014
3029
    }
3015
3030
 
3016
3031
    if(t && tagHandler(t->seqno, "onclick")) {
3017
3032
        if(cw->jsdead)
3018
 
            runningError("javascript disabled, %s",
3019
 
               itype ==
3020
 
               INP_BUTTON ? "no action taken" : "skipping the onclick code");
 
3033
            runningError(itype ==
 
3034
               INP_BUTTON ? MSG_NJNoAction : MSG_NJNoOnclick);
3021
3035
        else {
3022
3036
            rc = handlerGo(t->jv, "onclick");
3023
3037
            jsdw();
3030
3044
 
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);
3034
3048
            return false;
3035
3049
        }
3036
3050
        return true;
3040
3054
/* Before we reset, run the onreset code */
3041
3055
        if(t && tagHandler(form->seqno, "onreset")) {
3042
3056
            if(cw->jsdead)
3043
 
                runningError("javascript disabled, skipping the onreset code");
 
3057
                runningError(MSG_NJNoReset);
3044
3058
            else {
3045
3059
                rc = handlerGo(form->jv, "onreset");
3046
3060
                jsdw();
3057
3071
    /* Before we submit, run the onsubmit code */
3058
3072
    if(t && tagHandler(form->seqno, "onsubmit")) {
3059
3073
        if(cw->jsdead)
3060
 
            runningError("javascript disabled, skipping the onsubmit code");
 
3074
            runningError(MSG_NJNoSubmit);
3061
3075
        else {
3062
3076
            rc = handlerGo(form->jv, "onsubmit");
3063
3077
            jsdw();
3086
3100
    }
3087
3101
 
3088
3102
    if(!action) {
3089
 
        setError("form does not include a destination url");
 
3103
        setError(MSG_FormNoURL);
3090
3104
        return false;
3091
3105
    }
3092
3106
 
3094
3108
 
3095
3109
    prot = getProtURL(action);
3096
3110
    if(!prot) {
3097
 
        setError("the action of the form is not a url");
 
3111
        setError(MSG_FormBadURL);
3098
3112
        return false;
3099
3113
    }
3100
3114
 
3101
3115
    if(stringEqualCI(prot, "javascript")) {
3102
3116
        if(cw->jsdead) {
3103
 
            setError("javascript is disabled, cannot activate this form");
 
3117
            setError(MSG_NJNoForm);
3104
3118
            return false;
3105
3119
        }
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) {
3118
 
            setError
3119
 
               ("This form has changed from https to http, and is now insecure");
 
3132
            setError(MSG_BecameInsecure);
3120
3133
            return false;
3121
3134
        }
3122
3135
    } else if(!stringEqualCI(prot, "https")) {
3123
 
        setError("cannot submit using protocol %s", prot);
 
3136
        setError(MSG_SubmitProtBad, prot);
3124
3137
        return false;
3125
3138
    }
3126
3139
 
3128
3141
    stringAndString(&post, &l, action);
3129
3142
    section = strchr(post, '#');
3130
3143
    if(section) {
3131
 
        debugPrint(0,
3132
 
           "warning: form url specifies a section %s, which will be ignored",
3133
 
           section);
 
3144
        i_printf(MSG_SectionIgnored, section);
3134
3145
        *section = 0;
3135
3146
        l = strlen(post);
3136
3147
    }
3137
3148
    section = strpbrk(post, "?\1");
3138
3149
    if(section) {
3139
3150
        if(*section == '\1' || !(form->bymail | form->post)) {
3140
 
            debugPrint(0,
3141
 
               "warning: the url already specifies some data, which will be overwritten by the data in this form");
 
3151
            debugPrint(3,
 
3152
               "the url already specifies some data, which will be overwritten by the data in this form");
3142
3153
            *section = 0;
3143
3154
            l = strlen(post);
3144
3155
        }
3178
3189
            sprintf(q, "subject:html form(%s)\n", name ? name : "?");
3179
3190
        strcpy(q + strlen(q), post + actlen);
3180
3191
        nzFree(post);
3181
 
        printf("sending mail to %s\n", addr);
 
3192
        i_printf(MSG_MailSending, addr);
3182
3193
        sleep(1);
3183
3194
        rc = sendMail(localAccount, tolist, q, -1, atlist, 0, false);
3184
3195
        if(rc)
3185
 
            printf
3186
 
               ("Your information has been sent; watch for a reply via return mail.\n");
 
3196
            i_puts(MSG_MailSent);
3187
3197
        nzFree(addr);
3188
3198
        nzFree(subj);
3189
3199
        nzFree(q);
3202
3212
    struct htmlTag **list = cw->tags;
3203
3213
    struct htmlTag *t;
3204
3214
    if(!list)
3205
 
        errorPrint("@list = 0 in tagFromJavaVar()");
 
3215
        i_printfExit(MSG_NullListInform);
3206
3216
    while(t = *list++)
3207
3217
        if(t->jv == v)
3208
3218
            break;
3209
3219
    if(!t)
3210
 
        runningError
3211
 
           ("could not find the html tag associated with the javascript variable being modified");
 
3220
        runningError(MSG_LostTag);
3212
3221
    return t;
3213
3222
}                               /* tagFromJavaVar */
3214
3223
 
3226
3235
        return;
3227
3236
    }
3228
3237
    if(t->itype == INP_TA) {
3229
 
        runningError
3230
 
           ("javascript modified a textarea, and that isn't implemented yet");
 
3238
        runningError(MSG_JSTextarea);
3231
3239
        return;
3232
3240
    }
3233
3241
    updateFieldInBuffer(t->seqno, val, parsePage ? 0 : 2, false);
3267
3275
    const char *a;
3268
3276
 
3269
3277
    if(!href || !*href) {
3270
 
        browseError("java is opening a blank window");
 
3278
        browseError(MSG_JSBlankWindow);
3271
3279
        return;
3272
3280
    }
3273
3281
 
3292
3300
void
3293
3301
javaSetsTimeout(int n, const char *jsrc, void *to, bool isInterval)
3294
3302
{
3295
 
    struct htmlTag *t = newTag("A");
 
3303
    struct htmlTag *t = newTag("a");
3296
3304
    char timedesc[48];
3297
3305
    int l;
3298
3306