Commits

Anonymous committed 7b8f1a0

Modified Files:
LibXML.xs
+ name testing, so in default mode a user gets reported if nodes with
invalid names are created
+ addNewChild()
creates a new child element on an existing element.
(this avoids creating of extra nodes, namespace overlaps, node adding)
+ createRawElement(), createRawElementNS(), createRawAttribute(),
createRawAttributeNS()
avoid name testing creation functions().

t/03doc.t t/04node.t t/06elements.t t/19encoding.t
more tests

  • Participants
  • Parent commits cfae452

Comments (0)

Files changed (5)

 
 }
 
+
+int 
+LibXML_test_node_name( xmlChar * name ) 
+{
+    xmlChar * cur = name;
+    xmlChar * tc;
+    int t = 0;
+    if ( cur == NULL || *cur == 0 ) {
+        return(0);
+    }
+
+    tc = cur+UTF8SKIP(cur);
+    while (cur != tc) {
+        t = (t << 8) + *cur++;
+    }
+
+    if ( !( IS_LETTER( t ) || (t == '_') || (t == ':')) ) {
+        return(0);
+    }
+    t = 0;
+
+    while (*cur!=0 ) {
+        tc = cur+UTF8SKIP(cur);
+        while (cur != tc) {
+            t = (t << 8) + *cur++;
+        }
+
+        if (!(IS_LETTER(t) || IS_DIGIT(t) || (t == '_') || (t == '-') ||
+             (t == ':') || (t == '.') || IS_COMBINING(t) || IS_EXTENDER(t)) ) {
+            return(0);
+        }
+        t = 0;
+    }
+    
+    return(1);
+}
+
 /* ****************************************************************
  * general parse functions 
  * **************************************************************** */
         xmlNodePtr newNode;
         xmlChar * elname = NULL;
         ProxyNodePtr docfrag = NULL;
-        STRLEN len;
     CODE:
         elname = nodeSv2C( name , (xmlNodePtr) self);
-        if ( elname != NULL || xmlStrlen(elname) > 0 ) {
-            newNode = xmlNewNode(NULL , elname);
-            xmlFree(elname);
-            if ( newNode != NULL ) {        
-                docfrag = PmmNewFragment( self );
-                newNode->doc = self;
-                xmlAddChild(PmmNODE(docfrag), newNode);
-                RETVAL = PmmNodeToSv(newNode,docfrag);
-            }
-            else {
-                xs_warn( "no node created!" );
-                XSRETURN_UNDEF;
-            }
+        if ( !LibXML_test_node_name( elname ) ) {
+            xmlFree( elname );
+            croak( "bad name" );
+        }
+
+        newNode = xmlNewNode(NULL , elname);
+        xmlFree(elname);
+        if ( newNode != NULL ) {        
+            docfrag = PmmNewFragment( self );
+            newNode->doc = self;
+            xmlAddChild(PmmNODE(docfrag), newNode);
+            RETVAL = PmmNodeToSv(newNode,docfrag);
         }
         else {
+            xs_warn( "no node created!" );
             XSRETURN_UNDEF;
         }
     OUTPUT:
         RETVAL
 
 SV*
+createRawElement( self, name )
+        xmlDocPtr self
+        SV* name
+    PREINIT:
+        xmlNodePtr newNode;
+        xmlChar * elname = NULL;
+        ProxyNodePtr docfrag = NULL;
+    CODE:
+        elname = nodeSv2C( name , (xmlNodePtr) self);
+        if ( !elname || xmlStrlen(elname) <= 0 ) {
+            xmlFree( elname );
+            croak( "bad name" );
+        }
+
+        newNode = xmlNewDocNode(self,NULL , elname, NULL);
+        xmlFree(elname);
+        if ( newNode != NULL ) {        
+            docfrag = PmmNewFragment( self );
+            xmlAddChild(PmmNODE(docfrag), newNode);
+            RETVAL = PmmNodeToSv(newNode,docfrag);
+        }
+        else {
+            xs_warn( "no node created!" );
+            XSRETURN_UNDEF;
+        }
+    OUTPUT:
+        RETVAL
+
+
+SV*
 createElementNS( self, nsURI, name )
         xmlDocPtr self
         SV * nsURI
         xmlNsPtr ns            = NULL;
         ProxyNodePtr docfrag   = NULL;
         xmlNodePtr newNode     = NULL;
+        int err                = 0;
+        xmlChar * cur          = NULL;
     CODE:
         ename = nodeSv2C( name , (xmlNodePtr) self );
+        if ( !LibXML_test_node_name( ename ) ) {
+            xmlFree( ename );
+            croak( "bad name" );
+        }
+        
         eURI  = Sv2C( nsURI , NULL );
 
         if ( eURI != NULL && xmlStrlen(eURI)!=0 ){
     OUTPUT:
         RETVAL
 
+
+SV*
+createRawElementNS( self, nsURI, name )
+        xmlDocPtr self
+        SV * nsURI
+        SV * name
+    PREINIT:
+        xmlChar * ename        = NULL;
+        xmlChar * prefix       = NULL;
+        xmlChar * localname    = NULL;
+        xmlChar * eURI         = NULL;
+        const xmlChar * pchar  = NULL;
+        xmlNsPtr ns            = NULL;
+        ProxyNodePtr docfrag   = NULL;
+        xmlNodePtr newNode     = NULL;
+        int err                = 0;
+        xmlChar * cur          = NULL;
+    CODE:
+        ename = nodeSv2C( name , (xmlNodePtr) self );
+        if ( !LibXML_test_node_name( ename ) ) {
+            xmlFree( ename );
+            croak( "bad name" );
+        }
+        
+        eURI  = Sv2C( nsURI , NULL );
+
+        if ( eURI != NULL && xmlStrlen(eURI)!=0 ){
+            localname = xmlSplitQName2(ename, &prefix);
+            if ( localname == NULL ) {
+                localname = xmlStrdup( ename );
+            }
+
+            newNode = xmlNewDocNode( self,NULL , localname, NULL );
+            
+            ns = xmlSearchNsByHref( self, newNode, eURI );
+            if ( ns == NULL ) { 
+                /* create a new NS if the NS does not already exists */
+                ns = xmlNewNs(newNode, eURI , prefix );
+            }
+
+            if ( ns == NULL ) {
+                xmlFreeNode( newNode );
+                xmlFree(eURI);
+                xmlFree(localname);
+                if ( prefix != NULL ) {
+                    xmlFree(prefix);
+                }
+                xmlFree(ename);
+                XSRETURN_UNDEF;
+            }
+
+            xmlFree(localname);
+        }
+        else {
+            xs_warn( " ordinary element " );    
+            /* ordinary element */
+            localname = ename;
+        
+            newNode = xmlNewDocNode( self, NULL , localname, NULL );
+        }
+        
+        xmlSetNs(newNode, ns);
+        docfrag = PmmNewFragment( self );
+        xmlAddChild(PmmNODE(docfrag), newNode);
+        RETVAL = PmmNodeToSv(newNode, docfrag);
+    
+        if ( prefix != NULL ) {
+            xmlFree(prefix);
+        }
+        if ( eURI != NULL ) {
+            xmlFree(eURI);
+        }
+        xmlFree(ename);
+    OUTPUT:
+        RETVAL
+
 SV *
 createTextNode( self, content )
         xmlDocPtr self
         xmlChar * name = NULL;
         xmlChar * value = NULL;
         xmlAttrPtr newAttr = NULL;
+        xmlChar * cur  = NULL;
+        int err = 0;
     CODE:
         name = nodeSv2C( pname , (xmlNodePtr) self );
-        if ( name == NULL ) {
+        if ( !LibXML_test_node_name( name ) ) {
+            xmlFree(name);
             XSRETURN_UNDEF;
         }
+
         value = nodeSv2C( pvalue , (xmlNodePtr) self );
         newAttr = xmlNewDocProp( self, name, value );
         RETVAL = PmmNodeToSv((xmlNodePtr)newAttr, NULL); 
         xmlChar * nsURI = NULL;
         xmlAttrPtr newAttr = NULL;
         xmlNsPtr ns = NULL;
+        xmlChar * cur  = NULL;
+        int err = 0;
     CODE:
-        name  = nodeSv2C( pname , (xmlNodePtr) self );
-        if( name == NULL ) {
+        name = nodeSv2C( pname , (xmlNodePtr) self );
+        if ( !LibXML_test_node_name( name ) ) {
+            xmlFree(name);
             XSRETURN_UNDEF;
         }
 
         xmlChar* prefix;
     CODE:
         string = nodeSv2C( value , self );
+        if ( !LibXML_test_node_name( string ) ) {
+            xmlFree(string);
+            croak( "bad name" );
+        }
         if( self->ns ){
             localname = xmlSplitQName2(string, &prefix);
             xmlNodeSetName(self, localname );
         }
         xmlFree(string);
 
+void
+setRawName( self, value ) 
+        xmlNodePtr self
+        SV * value
+    PREINIT:
+        xmlChar* string;
+        xmlChar* localname;
+        xmlChar* prefix;
+    CODE:
+        string = nodeSv2C( value , self );
+        if ( !string || xmlStrlen( string) <= 0 ) {
+            xmlFree(string);
+            XSRETURN_UNDEF;
+        }
+        if( self->ns ){
+            localname = xmlSplitQName2(string, &prefix);
+            xmlNodeSetName(self, localname );
+            xmlFree(localname);
+            xmlFree(prefix);
+        }
+        else {
+            xmlNodeSetName(self, string );
+        }
+        xmlFree(string);
+
+
 SV*
 nodeValue( self, useDomEncoding = &PL_sv_undef ) 
         xmlNodePtr self 
         SV * attr_name
         SV * attr_value
     PREINIT:
-        xmlChar * name;
+        xmlChar * name  = NULL;
         xmlChar * value = NULL;
+        xmlChar * cur   = NULL;
+        int err = 0;
     CODE:
         name  = nodeSv2C(attr_name, self );
-        if ( !name ) {
-            XSRETURN_UNDEF;
+
+        if ( !LibXML_test_node_name(name) ) {
+            xmlFree(name);
+            croak( "bad name" );
         }
         value = nodeSv2C(attr_value, self );
        
         xmlChar * prefix    = NULL;
     INIT:
         name  = nodeSv2C( attr_name, self );        
+
+        if ( !LibXML_test_node_name(name) ) {
+            xmlFree(name);
+            croak( "bad name" );
+        }
+
         nsURI = nodeSv2C( namespaceURI, self );
-        if ( !name && !xmlStrlen( name ) ) {
-            if ( nsURI ) {
-                xmlFree( nsURI);
-            }
-            croak( "no name" );
-            XSRETURN_UNDEF;
-        }
         localname = xmlSplitQName2(name, &prefix); 
         if ( localname ) {
             xmlFree( name ); 
             xmlFree(encstr);
         xmlFree(name);
 
+SV *
+addNewChild( self, namespaceURI, nodename ) 
+        xmlNodePtr self
+        SV * namespaceURI
+        SV * nodename
+    ALIAS:
+        XML::LibXML::DocumentFragment::newRawChild = 1
+    PREINIT:
+        xmlChar * nsURI = NULL;
+        xmlChar * name  = NULL;
+        xmlChar * localname  = NULL;
+        xmlChar * prefix     = NULL;
+        xmlNodePtr newNode = NULL;
+        xmlNsPtr ns = NULL;
+    CODE:
+        name = nodeSv2C(nodename, self);
+        if ( name &&  xmlStrlen( name ) == 0 ) {
+            xmlFree(name);
+            XSRETURN_UNDEF;
+        }
+ 
+        nsURI = nodeSv2C(namespaceURI, self);
+        if ( nsURI &&  xmlStrlen( nsURI ) == 0 ) {
+            xmlFree(nsURI);
+            nsURI=NULL;
+        }
+
+        if ( nsURI != NULL ) {
+            localname = xmlSplitQName2(name, &prefix); 
+            ns = xmlSearchNsByHref(self->doc, self, nsURI);
+            if ( ns == NULL )  {
+                newNode = xmlNewChild( self, ns, 
+                                       localname?localname:name, NULL );
+                ns = xmlNewNs(newNode, nsURI, prefix);
+                newNode->ns = ns;
+            }     
+            else {
+                newNode = xmlNewChild( self, ns, 
+                                       localname?localname:name, NULL );
+            }           
+
+            xmlFree(localname);
+            xmlFree(prefix);
+            xmlFree(nsURI);
+        }
+        else {
+            newNode = xmlNewChild( self, NULL, name, NULL );
+        }
+     	RETVAL = PmmNodeToSv(newNode, PmmOWNERPO(PmmPROXYNODE(self)) );
+   
+        xmlFree(name);        
+    OUTPUT:
+        RETVAL
 
 MODULE = XML::LibXML         PACKAGE = XML::LibXML::Text
 
 use Test;
 use strict;
 
-BEGIN { plan tests => 84 };
+BEGIN { plan tests => 101 };
 use XML::LibXML;
 use XML::LibXML::Common qw(:libxml);
 
     my $doc2 = XML::LibXML::Document->createDocument("1.1", "iso-8859-2");
     ok( $doc2->encoding, "iso-8859-2" );
     ok( $doc2->version,  "1.1" );
+    ok( $doc2->standalone,  -1 );
 }
 
 {
     }
 
     {
+        print "# bad element creation\n";
+        my @badnames = ( ";", "&", "<><", "/", "1A");
+
+        foreach my $name ( @badnames ) {
+            my $node = eval {$doc->createElement( $name );};
+            ok( not defined $node );
+        }
+
+    }
+
+    {
         my $node = $doc->createTextNode( "foo" );
         ok($node);
         ok($node->nodeType, XML_TEXT_NODE );
         ok($attr->hasChildNodes, 0);
         my $content = $attr->firstChild;
         ok( $content );
+        ok( $content->nodeType, XML_TEXT_NODE );
     }
+    {
+        print "# bad attribute creation\n";
+        my @badnames = ( ";", "&", "<><", "/", "1A");
+
+        foreach my $name ( @badnames ) {
+            my $node = eval {$doc->createAttribute( $name, "bar" );};
+            ok( not defined $node );
+        }
+
+    }
+
 
     {
         eval {
         ok($attr->value, "bar" );
         
     }
+    {
+        print "# bad attribute creation\n";
+        my @badnames = ( ";", "&", "<><", "/", "1A");
+
+        foreach my $name ( @badnames ) {
+            my $node = eval {$doc->createAttributeNS( undef, $name, "bar" );};
+            ok( not defined $node );
+        }
+
+    }
 
     print "# 2.2 Create PIs\n";
     {
         ok($pi->nodeName, "foo");
         ok( $pi->textContent, undef);
     }
-
 }
 
 {
 
 {
     my $doc = XML::LibXML::Document->new();
-    my $URI = "http://kungfoo";
+    my $URI ="http://kungfoo";
     my $pre = "foo";
     my $name= "bar";
 
         my $docB = XML::LibXML::Document->new;
         my $e1   = $docB->createElement( "A" );
         my $e2   = $docB->createElement( "B" );
-        my $e3   = $docB->createElementNS( "C:D","http://kungfoo" );
+        my $e3   = $docB->createElementNS( "http://kungfoo", "C:D" );
         $e1->appendChild( $e2 );
         $e1->appendChild( $e3 );
 

File t/06elements.t

 
 use Test;
 
-BEGIN { plan tests => 58 };
+BEGIN { plan tests => 70 };
 use XML::LibXML;
 
 my $foo       = "foo";
 my $attvalue2 = "b";
 my $attname3  = "C";
 
+my @badnames= ("1A", "<><", "&", "-:");
+
 print "# 1. bound node\n";
 {
     my $doc = XML::LibXML::Document->new();
     ok($elem);
     ok($elem->tagName, $foo);
     
+    {
+        foreach my $name ( @badnames ) {
+            eval { $elem->setNodeName( $name ); };
+            ok( $@ );
+        }
+    }
+    
     $elem->setAttribute( $attname1, $attvalue1 );
     ok( $elem->hasAttribute($attname1) );
     ok( $elem->getAttribute($attname1), $attvalue1);
     ok($elem->hasAttribute($attname3) );
     ok($elem->getAttribute($attname3), "");
 
+    {
+        foreach my $name ( @badnames ) {
+            eval {$elem->setAttribute( $name, "X" );};
+            ok( $@ );
+        }
+
+    }
+
+
     print "# 1.1 Namespaced Attributes\n";
 
     $elem->setAttributeNS( $nsURI, $prefix . ":". $foo, $attvalue2 );
     ok( $elem->hasAttribute($attname1) );
     ok( $elem->hasAttributeNS($nsURI,$attname1) );
     # warn $elem->toString;
+
+    {
+        foreach my $name ( @badnames ) {
+            eval {$elem->setAttributeNS( undef, $name, "X" );};
+            ok( $@ );
+        }
+    }
 } 
 
 print "# 2. unbound node\n";

File t/19encoding.t

 BEGIN { 
     my $tests        = 0;
     my $basics       = 0;
-    my $magic        = 6;    
+    my $magic        = 7;    
 
     if ( $] >= 5.008 ) {
         print "# Skipping test on this platform\n";
             elsif ( $ENV{TEST_LANGUAGES} eq "EUC-JP"
                     or $ENV{TEST_LANGUAGES} eq "KIO8-R" ) {
                 $tests += $basics;  
-                $tests += $magic if $] >= 5.006;
+                $tests += $magic-1 if $] >= 5.006;
             }
         }
     }
         "<$tstr_iso_latin1/>");
     ok( $elemlat1->toString(0,1), "<$tstr_iso_latin1/>");
 
+    my $elemlat2   = $dom_latin1->createElement( "�l" );
+    ok( $elemlat2->toString(0,1), "<�l/>");
+
     $elemlat1->appendText( $tstr_iso_latin1 );
 
     ok( decodeFromUTF8( 'iso-8859-1' ,$elemlat1->string_value()),