Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Sanitized namespoace handling for 'event start'. Startet attribute input to the 'event start' method. Therefor internal reorganisation, which also makes adding hash tables for larger sets of attribute a bit simpler.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | schema
Files: files | file ages | folders
SHA3-256: 5f6af15f8d366a042262ca9b1a7037d3def7ad920752d1e7c4a1277a8b21983e
User & Date: rolf 2019-10-23 00:27:41
Context
2019-10-24
11:13
Further work on the schema command "event" method. check-in: 644a84f1b9 user: rolf tags: schema
2019-10-23
09:25
Merged from schema. check-in: 3c16fd1ab1 user: rolf tags: wip
00:27
Sanitized namespoace handling for 'event start'. Startet attribute input to the 'event start' method. Therefor internal reorganisation, which also makes adding hash tables for larger sets of attribute a bit simpler. check-in: 5f6af15f8d user: rolf tags: schema
2019-10-19
12:01
Removed more no longer used defines. check-in: 0605e10005 user: rolf tags: schema
Changes

Changes to generic/schema.c.

1380
1381
1382
1383
1384
1385
1386


































1387
1388
1389
1390
1391
1392
1393
1394
1395

1396
1397
1398
1399
1400
1401
1402
....
1408
1409
1410
1411
1412
1413
1414
1415
1416

1417
1418
1419
1420

1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439



1440
1441
1442
1443
1444
1445

1446
1447
1448
1449
1450
1451
1452
....
1462
1463
1464
1465
1466
1467
1468

1469
1470

1471
1472
1473
1474
1475
1476
1477
....
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504

1505
1506
1507
1508
1509
1510
1511
....
1519
1520
1521
1522
1523
1524
1525
1526


1527
1528
1529



1530
1531

1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549

1550
1551
1552
1553
1554
1555
1556
....
1610
1611
1612
1613
1614
1615
1616























































1617
1618
1619
1620
1621
1622
1623
....
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
....
3432
3433
3434
3435
3436
3437
3438

3439
3440
3441

















3442
3443
3444





3445

3446
3447
3448
3449
3450
3451
3452
            Tcl_AppendResult (interp, namespacePtr, ":", NULL);
        }
        Tcl_AppendResult (interp, name, "\" doesn't match", NULL);
    }
    return TCL_ERROR;
}



































int probeAttributes (
    Tcl_Interp *interp,
    SchemaData *sdata,
    const char **attr
    )
{
    char   **atPtr, *ln, *namespace;
    int i, j, found, nsatt, reqAttr = 0;
    SchemaCP *cp;


    cp = sdata->stack->pattern;
    for (atPtr = (char **) attr; atPtr[0] && atPtr[1]; atPtr += 2) {
        found = 0;
        ln = atPtr[0];
        j = 0;
        while (*ln && *ln != '\xFF') {
................................................................................
            ln++;
            nsatt = 1;
        } else {
            namespace = NULL;
            ln = atPtr[0];
            nsatt = 0;
        }
        for (i = 0; i < cp->numAttr; i++) {
            if (nsatt) {

                if (!cp->attrs[i]->namespace
                    || (strcmp (cp->attrs[i]->namespace, namespace) != 0))
                    continue;
            }

            if (strcmp (ln, cp->attrs[i]->name) == 0) {
                found = 1;
                if (cp->attrs[i]->cp) {
                    if (!checkText (interp, cp->attrs[i]->cp,
                                    (char *) atPtr[1])) {
                        if (!recover (interp, sdata,
                                      S("WRONG_ATTRIBUTE_VALUE"), 0, 0)) {
                            if (nsatt) namespace[j] = '\xFF';
                            SetResult3 ("Attribute value doesn't match for "
                                        "attribute '", atPtr[0], "'");
                            return TCL_ERROR;
                        }
                    }
                }
                if (cp->attrs[i]->required) reqAttr++;
                break;
            }
        }
        if (nsatt) namespace[j] = '\xFF';



        if (!found) {
            if (!recover (interp, sdata, S("UNKNOWN_ATTRIBUTE"), 0, 0)) {
                SetResult3 ("Unknown attribute \"", atPtr[0], "\"");
                return TCL_ERROR;
            }
        }

    }
    if (reqAttr != cp->numReqAttr) {
        /* Lookup the missing attribute(s) */
        SetResult ("Missing mandatory attribute(s):");
        for (i = 0; i < cp->numAttr; i++) {
            if (!cp->attrs[i]->required) continue;
            found = 0;
................................................................................
                        namespace[j] = '\0';
                        ln++;
                        nsatt = 1;
                    } else {
                        continue;
                    }
                    if (strcmp (cp->attrs[i]->namespace, namespace) != 0) {

                        continue;
                    }

                }
                if (strcmp (atPtr[0], cp->attrs[i]->name) == 0) {
                    found = 1;
                    break;
                }
            }
            if (!found) {
................................................................................
int probeDomAttributes (
    Tcl_Interp *interp,
    SchemaData *sdata,
    domAttrNode *attr
    )
{
    domAttrNode *atPtr;
    int i, found, reqAttr = 0;
    const char *ns, *ln;
    SchemaCP *cp;


    cp = sdata->stack->pattern;
    atPtr = attr;
    while (atPtr) {
        if (atPtr->nodeFlags & IS_NS_NODE) goto nextAttr;
        found = 0;
        if (atPtr->namespace) {
................................................................................
                }
                ln++;
            }
        } else {
            ns = NULL;
            ln = atPtr->nodeName;
        }
        for (i = 0; i < cp->numAttr; i++) {


            if (ns) {
                if (!cp->attrs[i]->namespace) continue;
                if (strcmp (ns, cp->attrs[i]->namespace) != 0) continue;



            } else {
                if (cp->attrs[i]->namespace) continue;

            }
            if (strcmp (ln, cp->attrs[i]->name) == 0) {
                if (cp->attrs[i]->cp) {
                    if (!checkText (interp, cp->attrs[i]->cp,
                                    (char *) atPtr->nodeValue)) {
                        if (!recover (interp, sdata,
                                      S("WRONG_ATTRIBUTE_VALUE"), 0, 0)) {
                            SetResult3 ("Attribute value doesn't match for "
                                        "attribute '", ln, "'");
                            return TCL_ERROR;
                        }
                    }
                }
                found = 1;
                if (cp->attrs[i]->required) reqAttr++;
                break;
            }
        }

        if (!found) {
            if (!recover (interp, sdata, S("UNKNOWN_ATTRIBUTE"), 0, 0)) {
                if (ns) {
                    SetResult ("Unknown attribute \"");
                    Tcl_AppendResult (interp, ns, ":", atPtr->nodeName,
                                      "\"");
                } else {
................................................................................
        }
        if (!sdata->reportCmd) {
            sdata->validationState = VALIDATION_ERROR;
            return TCL_ERROR;
        }
    }
    return TCL_OK;























































}

static int checkElementEnd (
    Tcl_Interp *interp,
    SchemaData *sdata
    )
{
................................................................................
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[]
    )
{
    int            methodIndex, keywordIndex, hnew, patternIndex;
    int            result = TCL_OK, forwardDef = 0, i = 0, j;
    int            savedDefineToplevel, type, len;
    unsigned int   savedNumPatternList;
    SchemaData    *savedsdata = NULL, *sdata = (SchemaData *) clientData;
    Tcl_HashTable *hashTable;
    Tcl_HashEntry *h, *h1;
    SchemaCP      *pattern, *current = NULL;
    void          *namespacePtr, *savedNamespacePtr;
    char          *xmlstr, *errMsg;
................................................................................
        case k_elementstart:
            if (objc < 4 && objc > 6) {
                Tcl_WrongNumArgs (interp, 3, objv, "<elementname>"
                    "?<attInfo>? ?<namespace>?");
                return TCL_ERROR;
            }
            namespacePtr = NULL;

            if (objc == 6) {
                namespacePtr = getNamespacePtr (sdata,
                                                Tcl_GetString (objv[5]));

















            }
            result = probeElement (interp, sdata, Tcl_GetString (objv[3]),
                                   namespacePtr);





            break;

        case k_elementend:
            if (objc != 3) {
                Tcl_WrongNumArgs (interp, 3, objv, "No arguments expected.");
                return TCL_ERROR;
            }
            result = probeElementEnd (interp, sdata);
            break;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|
|

>







 







|
|
>
|
|
<
<
>
|
|
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
>
>
>






>







 







>


>







 







|


>







 







|
>
>
|
<
<
>
>
>
|
<
>
|
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



>
>
>
>
>

>







1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
....
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454


1455
1456
1457
1458








1459







1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
....
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
....
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
....
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556


1557
1558
1559
1560

1561
1562



1563
1564












1565
1566
1567
1568
1569
1570
1571
1572
....
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
....
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
....
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
            Tcl_AppendResult (interp, namespacePtr, ":", NULL);
        }
        Tcl_AppendResult (interp, name, "\" doesn't match", NULL);
    }
    return TCL_ERROR;
}

int probeAttribute (
    Tcl_Interp *interp,
    SchemaData *sdata,
    const char *name,
    const char *ns,
    char *value,
    int *isrequiered
    )
{
    int i;
    SchemaCP *cp;
    
    cp = sdata->stack->pattern;
    *isrequiered = 0;
    for (i = 0; i < cp->numAttr; i++) {
        if (cp->attrs[i]->namespace == ns
            && cp->attrs[i]->name == name) {
            if (cp->attrs[i]->cp) {
                if (!checkText (interp, cp->attrs[i]->cp, value)) {
                    if (!recover (interp, sdata,
                                  S("WRONG_ATTRIBUTE_VALUE"), 0, 0)) {
                        SetResult3 ("Attribute value doesn't match for "
                                    "attribute '", name , "'");
                        return 0;
                    }
                }
            }
            if (cp->attrs[i]->required) *isrequiered = 1;
            return 1;
        }
    }
    return 0;
}
    
int probeAttributes (
    Tcl_Interp *interp,
    SchemaData *sdata,
    const char **attr
    )
{
    char   **atPtr, *ln, *namespace, *ns;
    int i, j, found, nsatt, req, reqAttr = 0;
    SchemaCP *cp;
    Tcl_HashEntry *h;

    cp = sdata->stack->pattern;
    for (atPtr = (char **) attr; atPtr[0] && atPtr[1]; atPtr += 2) {
        found = 0;
        ln = atPtr[0];
        j = 0;
        while (*ln && *ln != '\xFF') {
................................................................................
            ln++;
            nsatt = 1;
        } else {
            namespace = NULL;
            ln = atPtr[0];
            nsatt = 0;
        }
        h = Tcl_FindHashEntry (&sdata->attrNames, ln);
        if (!h) goto unknowncleanup;
        ln = Tcl_GetHashKey (&sdata->attrNames, h);
        if (namespace) {
            h = Tcl_FindHashEntry (&sdata->namespace, namespace);


            if (!h) goto unknowncleanup;
            ns = Tcl_GetHashKey (&sdata->namespace, h);
        } else {
            ns = NULL;








        }







        found = probeAttribute (interp, sdata, ln, ns, atPtr[1], &req);
        reqAttr += req;
    unknowncleanup:
        if (!found) {
            if (!recover (interp, sdata, S("UNKNOWN_ATTRIBUTE"), 0, 0)) {
                SetResult3 ("Unknown attribute \"", atPtr[0], "\"");
                return TCL_ERROR;
            }
        }
        if (nsatt) namespace[j] = '\xFF';
    }
    if (reqAttr != cp->numReqAttr) {
        /* Lookup the missing attribute(s) */
        SetResult ("Missing mandatory attribute(s):");
        for (i = 0; i < cp->numAttr; i++) {
            if (!cp->attrs[i]->required) continue;
            found = 0;
................................................................................
                        namespace[j] = '\0';
                        ln++;
                        nsatt = 1;
                    } else {
                        continue;
                    }
                    if (strcmp (cp->attrs[i]->namespace, namespace) != 0) {
                        if (nsatt) namespace[j] = '\xFF';
                        continue;
                    }
                    if (nsatt) namespace[j] = '\xFF';
                }
                if (strcmp (atPtr[0], cp->attrs[i]->name) == 0) {
                    found = 1;
                    break;
                }
            }
            if (!found) {
................................................................................
int probeDomAttributes (
    Tcl_Interp *interp,
    SchemaData *sdata,
    domAttrNode *attr
    )
{
    domAttrNode *atPtr;
    int i, found, req, reqAttr = 0;
    const char *ns, *ln;
    SchemaCP *cp;
    Tcl_HashEntry *h;

    cp = sdata->stack->pattern;
    atPtr = attr;
    while (atPtr) {
        if (atPtr->nodeFlags & IS_NS_NODE) goto nextAttr;
        found = 0;
        if (atPtr->namespace) {
................................................................................
                }
                ln++;
            }
        } else {
            ns = NULL;
            ln = atPtr->nodeName;
        }
        h = Tcl_FindHashEntry (&sdata->attrNames, ln);
        if (!h) goto unknown;
        ln = Tcl_GetHashKey (&sdata->attrNames, h);
        if (ns) {


            h = Tcl_FindHashEntry (&sdata->namespace, ns);
            if (!h) goto unknown;
            ns = Tcl_GetHashKey (&sdata->namespace, h);
        } else {

            ns = NULL;
        }



        found = probeAttribute (interp, sdata, ln, ns, atPtr->nodeValue, &req);
        reqAttr += req;












    unknown:
        if (!found) {
            if (!recover (interp, sdata, S("UNKNOWN_ATTRIBUTE"), 0, 0)) {
                if (ns) {
                    SetResult ("Unknown attribute \"");
                    Tcl_AppendResult (interp, ns, ":", atPtr->nodeName,
                                      "\"");
                } else {
................................................................................
        }
        if (!sdata->reportCmd) {
            sdata->validationState = VALIDATION_ERROR;
            return TCL_ERROR;
        }
    }
    return TCL_OK;
}
int probeEventAttribute (
    Tcl_Interp *interp,
    SchemaData *sdata,
    Tcl_Obj *attr,
    int len
    )
{
    int i, found, req, reqAttr = 0;
    char *name, *ns;
    SchemaCP *cp;
    Tcl_HashEntry *h;
    Tcl_Obj *attname, *attns, *attvalue;

    cp = sdata->stack->pattern;
    for (i = 0; i < len; i += 2) {
        Tcl_ListObjIndex (interp, attr, i, &attname);
        Tcl_ListObjIndex (interp, attr, i+1, &attvalue);
        if (Tcl_ListObjLength (interp, attname, &len) == TCL_OK) {
            if (len == 2) {
                Tcl_ListObjIndex (interp, attname, 1, &attns);
                Tcl_ListObjIndex (interp, attname, 1, &attname);
            }
        }
        h = Tcl_FindHashEntry (&sdata->attrNames, Tcl_GetString (attname));
        if (!h) goto unknown;
        name = Tcl_GetHashKey (&sdata->attrNames, h);
        if (attns) {
            h = Tcl_FindHashEntry (&sdata->namespace, Tcl_GetString (attns));
            if (!h) goto unknown;
            ns = Tcl_GetHashKey (&sdata->namespace, h);
        }
        found = probeAttribute (interp, sdata, name, ns,
                                Tcl_GetString (attvalue), &req);
        reqAttr += req;
    unknown:
        if (!found) {
            if (!recover (interp, sdata, S("UNKNOWN_ATTRIBUTE"), 0, 0)) {
                if (ns) {
                    SetResult ("Unknown attribute \"");
                    Tcl_AppendResult (interp, ns, ":", ns,
                                      "\"");
                } else {
                    SetResult3 ("Unknown attribute \"", name, "\"");
                }
                sdata->validationState = VALIDATION_ERROR;
                return TCL_ERROR;
            }
        }
    }
    if (reqAttr != cp->numReqAttr) {
        SetResult ("Missing mandatory attribute(s)");
        return TCL_ERROR;
    }
    return TCL_OK;
}

static int checkElementEnd (
    Tcl_Interp *interp,
    SchemaData *sdata
    )
{
................................................................................
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[]
    )
{
    int            methodIndex, keywordIndex, hnew, patternIndex;
    int            result = TCL_OK, forwardDef = 0, i = 0, j;
    int            savedDefineToplevel, type, len, checkAttr;
    unsigned int   savedNumPatternList;
    SchemaData    *savedsdata = NULL, *sdata = (SchemaData *) clientData;
    Tcl_HashTable *hashTable;
    Tcl_HashEntry *h, *h1;
    SchemaCP      *pattern, *current = NULL;
    void          *namespacePtr, *savedNamespacePtr;
    char          *xmlstr, *errMsg;
................................................................................
        case k_elementstart:
            if (objc < 4 && objc > 6) {
                Tcl_WrongNumArgs (interp, 3, objv, "<elementname>"
                    "?<attInfo>? ?<namespace>?");
                return TCL_ERROR;
            }
            namespacePtr = NULL;
            checkAttr = 0;
            if (objc == 6) {
                namespacePtr = getNamespacePtr (sdata,
                                                Tcl_GetString (objv[5]));
            }
            if (objc >= 5) {
                if (Tcl_ListObjLength (interp, objv[4], &len) != TCL_OK) {
                    namespacePtr = getNamespacePtr (sdata,
                                                    Tcl_GetString (objv[4]));
                } else {
                    if (len == 1) {
                        namespacePtr = getNamespacePtr (
                            sdata, Tcl_GetString (objv[4])
                            );
                    } else if (len % 2 != 0) {
                        SetResult ("Invalid attribute information");
                        return TCL_ERROR;
                    } else {
                        checkAttr = 1;
                    }
                }
            }
            result = probeElement (interp, sdata, Tcl_GetString (objv[3]),
                                   namespacePtr);
            if (result == TCL_OK && checkAttr) {
                if (!probeEventAttribute (interp, sdata, objv[4], len)) {
                    return TCL_ERROR;
                }
            }
            break;
            
        case k_elementend:
            if (objc != 3) {
                Tcl_WrongNumArgs (interp, 3, objv, "No arguments expected.");
                return TCL_ERROR;
            }
            result = probeElementEnd (interp, sdata);
            break;

Changes to tests/schema.test.

924
925
926
927
928
929
930














931
932
933
934
935
936
937
    } {
        lappend result [s validate $xml errMsg]
        lappend result $errMsg
    }
    s delete
    set result
} {0 {error "This method is not allowed in nested evaluation" at line 1 character 6} 0 {error "This method is not allowed in nested evaluation" at line 1 character 15} 0 {error "This method is not allowed in nested evaluation" at line 1 character 13}}















test schema-5.1 {dom parse -validateCmd} {
    set result [catch {
        [dom parse -validateCmd tdom::schema <doc/>]
    }]
} 1








>
>
>
>
>
>
>
>
>
>
>
>
>
>







924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
    } {
        lappend result [s validate $xml errMsg]
        lappend result $errMsg
    }
    s delete
    set result
} {0 {error "This method is not allowed in nested evaluation" at line 1 character 6} 0 {error "This method is not allowed in nested evaluation" at line 1 character 15} 0 {error "This method is not allowed in nested evaluation" at line 1 character 13}}

test schema-4.6 {event start with namespace} {
    tdom::schema s
    s defelement doc http://tdom.org/test {
        element a 1 {
            attribute att1
        }
    }
    s event start doc http://tdom.org/test
    s event start a http://tdom.org/test
    s event end
    s event end
    s delete
} {}

test schema-5.1 {dom parse -validateCmd} {
    set result [catch {
        [dom parse -validateCmd tdom::schema <doc/>]
    }]
} 1