Back to index

nordugrid-arc-nox  1.1.0~rc6
Public Types | Public Member Functions | Protected Attributes
Arc::XMLSecNode Class Reference

Extends XMLNode class to support XML security operation. More...

#include <XMLSecNode.h>

Inheritance diagram for Arc::XMLSecNode:
Inheritance graph
[legend]
Collaboration diagram for Arc::XMLSecNode:
Collaboration graph
[legend]

List of all members.

Public Types

enum  SignatureMethod { RSA_SHA1, DSA_SHA1 }
enum  SymEncryptionType { TRIPLEDES, AES_128, AES_256, DEFAULT }

Public Member Functions

 XMLSecNode (XMLNode &node)
 Create a object based on an XMLNode instance.
 ~XMLSecNode (void)
void AddSignatureTemplate (const std::string &id_name, const SignatureMethod sign_method, const std::string &incl_namespaces="")
 Add the signature template for later signing.
bool SignNode (const std::string &privkey_file, const std::string &cert_file)
 Sign this node (identified by id_name).
bool VerifyNode (const std::string &id_name, const std::string &ca_file, const std::string &ca_path, bool verify_trusted=true)
 Verify the signature under this node.
bool EncryptNode (const std::string &cert_file, const SymEncryptionType encrpt_type)
 Encrypt this node, after encryption, this node will be replaced by the encrypted node.
bool DecryptNode (const std::string &privkey_file, XMLNode &decrypted_node)
 Decrypt the <xenc:EncryptedData/> under this node, the decrypted node will be output in the second *argument of DecryptNode method.
void New (XMLNode &node) const
 Creates a copy of XML (sub)tree.
void Exchange (XMLNode &node)
 Exchanges XML (sub)trees.
void Move (XMLNode &node)
 Moves content of this XML (sub)tree to node This opeartion is similar to New except that XML (sub)tree to refered by this is destroyed.
void Swap (XMLNode &node)
 Swaps XML (sub)trees to this this and node refer.
 operator bool (void) const
 Returns true if instance points to XML element - valid instance.
bool operator! (void) const
 Returns true if instance does not point to XML element - invalid instance.
bool operator== (const XMLNode &node)
 Returns true if 'node' represents same XML element.
bool operator== (bool val)
 This operator is needed to avoid ambiguity.
bool operator== (const std::string &str)
 This operator is needed to avoid ambiguity.
bool operator== (const char *str)
 This operator is needed to avoid ambiguity.
bool operator!= (const XMLNode &node)
 Returns false if 'node' represents same XML element.
bool operator!= (bool val)
 This operator is needed to avoid ambiguity.
bool operator!= (const std::string &str)
 This operator is needed to avoid ambiguity.
bool operator!= (const char *str)
 This operator is needed to avoid ambiguity.
bool Same (const XMLNode &node)
 Returns true if 'node' represents same XML element - for bindings.
XMLNode Child (int n=0)
 Returns XMLNode instance representing n-th child of XML element.
XMLNode operator[] (const char *name) const
 Returns XMLNode instance representing first child element with specified name.
XMLNode operator[] (const std::string &name) const
 Similar to previous method.
XMLNode operator[] (int n) const
 Returns XMLNode instance representing n-th node in sequence of siblings of same name.
void operator++ (void)
 Convenience operator to switch to next element of same name.
void operator-- (void)
 Convenience operator to switch to previous element of same name.
int Size (void) const
 Returns number of children nodes.
XMLNode Get (const std::string &name) const
 Same as operator[].
std::string Name (void) const
 Returns name of XML node.
void Name (const char *name)
 Assigns new name to XML node.
void Name (const std::string &name)
 Assigns new name to XML node.
std::string Prefix (void) const
 Returns namespace prefix of XML node.
std::string FullName (void) const
 Returns prefix:name of XML node.
std::string Namespace (void) const
 Returns namespace URI of XML node.
void GetXML (std::string &out_xml_str, bool user_friendly=false) const
 Fills argument with this instance XML subtree textual representation.
void GetXML (std::string &out_xml_str, const std::string &encoding, bool user_friendly=false) const
 Fills argument with this instance XML subtree textual representation if the XML subtree is corresponding to the encoding format specified in the argument, e.g.
void GetDoc (std::string &out_xml_str, bool user_friendly=false) const
 Fills argument with whole XML document textual representation.
 operator std::string (void) const
 Returns textual content of node excluding content of children nodes.
void Set (const std::string &content)
 Same as operator=.
XMLNode Attribute (int n=0)
 Returns list of all attributes of node.
XMLNode Attribute (const char *name)
 Returns XMLNode instance representing first attribute of node with specified by name.
XMLNode Attribute (const std::string &name)
 Returns XMLNode instance representing first attribute of node with specified by name.
XMLNode NewAttribute (const char *name)
 Creates new attribute with specified name.
XMLNode NewAttribute (const std::string &name)
 Creates new attribute with specified name.
int AttributesSize (void) const
 Returns number of attributes of node.
void Namespaces (const NS &namespaces, bool keep=false, int recursion=-1)
 Assigns namespaces of XML document at point specified by this instance.
NS Namespaces (void)
 Returns namespaces known at this node.
std::string NamespacePrefix (const char *urn)
 Returns prefix of specified namespace.
XMLNode NewChild (const char *name, int n=-1, bool global_order=false)
 Creates new child XML element at specified position with specified name.
XMLNode NewChild (const std::string &name, int n=-1, bool global_order=false)
 Same as NewChild(const char*,int,bool)
XMLNode NewChild (const char *name, const NS &namespaces, int n=-1, bool global_order=false)
 Creates new child XML element at specified position with specified name and namespaces.
XMLNode NewChild (const std::string &name, const NS &namespaces, int n=-1, bool global_order=false)
 Same as NewChild(const char*,const NS&,int,bool)
XMLNode NewChild (const XMLNode &node, int n=-1, bool global_order=false)
 Link a copy of supplied XML node as child.
void Replace (const XMLNode &node)
 Makes a copy of supplied XML node and makes this instance refere to it.
void Destroy (void)
 Destroys underlying XML element.
XMLNodeList Path (const std::string &path)
 Collects nodes corresponding to specified path.
XMLNodeList XPathLookup (const std::string &xpathExpr, const NS &nsList)
 Uses xPath to look up the whole xml structure, Returns a list of XMLNode points.
XMLNode GetRoot (void)
 Get the root node from any child node of the tree.
XMLNode Parent (void)
 Get the parent node from any child node of the tree.
bool SaveToFile (const std::string &file_name) const
 Save string representation of node to file.
bool SaveToStream (std::ostream &out) const
 Save string representation of node to stream.
bool ReadFromFile (const std::string &file_name)
 Read XML document from file and associate it with this node.
bool ReadFromStream (std::istream &in)
 Read XML document from stream and associate it with this node.
bool Validate (const std::string &schema_file, std::string &err_msg)
 Remove all eye-candy information leaving only informational parts * void Purify(void);.

Protected Attributes

xmlNodePtr node_
bool is_owner_
 If true node is owned by this instance - hence released in destructor.
bool is_temporary_
 This variable is for future.

Detailed Description

Extends XMLNode class to support XML security operation.

All XMLNode methods are exposed by inheriting from XMLNode. XMLSecNode itself does not own node, instead it uses the node from the base class XMLNode.

Definition at line 12 of file XMLSecNode.h.


Member Enumeration Documentation

Enumerator:
RSA_SHA1 
DSA_SHA1 

Definition at line 14 of file XMLSecNode.h.

Enumerator:
TRIPLEDES 
AES_128 
AES_256 
DEFAULT 

Definition at line 18 of file XMLSecNode.h.


Constructor & Destructor Documentation

Create a object based on an XMLNode instance.

Definition at line 43 of file XMLSecNode.cpp.

                                   :XMLNode(node) {
  if(!node_) return;
  if(node_->type != XML_ELEMENT_NODE) { node_=NULL; return; };
}

Definition at line 48 of file XMLSecNode.cpp.

                            {
}

Member Function Documentation

void Arc::XMLSecNode::AddSignatureTemplate ( const std::string &  id_name,
const SignatureMethod  sign_method,
const std::string &  incl_namespaces = "" 
)

Add the signature template for later signing.

Parameters:
id_nameThe identifier name under this node which will be used for the <Signature> to refer to.
sign_methodThe sign method for signing. Two options now, RSA_SHA1, DSA_SHA1

Definition at line 51 of file XMLSecNode.cpp.

                                    {
  xmlNodePtr signature = NULL;
  xmlNodePtr reference = NULL;
  if(sign_method == RSA_SHA1)
    signature = xmlSecTmplSignatureCreate(NULL, xmlSecTransformExclC14NId, xmlSecTransformRsaSha1Id, NULL);
  else
    signature = xmlSecTmplSignatureCreate(NULL, xmlSecTransformExclC14NId, xmlSecTransformDsaSha1Id, NULL);
 
  //Add signature to the node
  xmlNodePtr nd = this->node_;
  xmlAddChild(nd, signature);

  //Add reference for signature
  xmlDocPtr docPtr = nd->doc;
  xmlChar* id = NULL;
  id =  xmlGetProp(nd, (xmlChar *)(id_name.c_str()));
  if(!id) { std::cerr<<"There is not "<<id_name<<" attribute in xml node"<<std::endl; return; }

  std::string uri; uri.append("#"); uri.append((char*)id);

  reference = xmlSecTmplSignatureAddReference(signature, xmlSecTransformSha1Id,
                                              NULL, (xmlChar *)(uri.c_str()), NULL);
  xmlSecTmplReferenceAddTransform(reference, xmlSecTransformEnvelopedId);
  xmlNodePtr transform = NULL;
  transform = xmlSecTmplReferenceAddTransform(reference, xmlSecTransformExclC14NId);
  if(!incl_namespaces.empty())
    xmlSecTmplTransformAddC14NInclNamespaces(transform, (const xmlChar*)(incl_namespaces.c_str()));

  xmlAttrPtr id_attr = xmlHasProp(nd, (xmlChar *)(id_name.c_str()));
  xmlAddID(NULL, docPtr, (xmlChar *)id, id_attr);
  xmlFree(id);
  
  xmlNodePtr key_info = xmlSecTmplSignatureEnsureKeyInfo(signature, NULL);
  xmlSecTmplKeyInfoAddX509Data(key_info);
}

Here is the caller graph for this function:

XMLNode Arc::XMLNode::Attribute ( int  n = 0) [inherited]

Returns list of all attributes of node.

Returns XMLNode instance reresenting n-th attribute of node.

Definition at line 413 of file XMLNode.cpp.

                                  {
    if (!node_)
      return XMLNode();
    if (node_->type != XML_ELEMENT_NODE)
      return XMLNode();
    xmlAttrPtr p = n < 0 ? NULL : node_->properties;
    for (; p; p = p->next) {
      if (p->type != XML_ATTRIBUTE_NODE)
        continue;
      if ((--n) < 0)
        break;
    }
    return XMLNode((xmlNodePtr)p);
  }

Here is the call graph for this function:

XMLNode Arc::XMLNode::Attribute ( const char *  name) [inherited]

Returns XMLNode instance representing first attribute of node with specified by name.

Definition at line 428 of file XMLNode.cpp.

                                             {
    if (!node_)
      return XMLNode();
    if (node_->type != XML_ELEMENT_NODE)
      return XMLNode();
    xmlNodePtr p = (xmlNodePtr)(node_->properties);
    for (; p; p = p->next) {
      if (p->type != XML_ATTRIBUTE_NODE)
        continue;
      if (MatchXMLName(p, name))
        break;
    }
    if (p)
      return XMLNode(p);
    // New temporary node
    return XMLNode(p);
  }

Here is the call graph for this function:

XMLNode Arc::XMLNode::Attribute ( const std::string &  name) [inline, inherited]

Returns XMLNode instance representing first attribute of node with specified by name.

Definition at line 273 of file XMLNode.h.

                                             {
      return Attribute(name.c_str());
    }

Here is the call graph for this function:

int Arc::XMLNode::AttributesSize ( void  ) const [inherited]

Returns number of attributes of node.

Definition at line 398 of file XMLNode.cpp.

                                        {
    if (!node_)
      return 0;
    if (node_->type != XML_ELEMENT_NODE)
      return 0;
    int n = 0;
    xmlAttrPtr p = node_->properties;
    for (; p; p = p->next) {
      if (p->type != XML_ATTRIBUTE_NODE)
        continue;
      ++n;
    }
    return n;
  }
XMLNode Arc::XMLNode::Child ( int  n = 0) [inherited]

Returns XMLNode instance representing n-th child of XML element.

If such does not exist invalid XMLNode instance is returned

Definition at line 503 of file XMLNode.cpp.

                              {
    if (!node_)
      return XMLNode();
    if (node_->type != XML_ELEMENT_NODE)
      return XMLNode();
    xmlNodePtr p = n < 0 ? NULL : node_->children;
    for (; p; p = p->next) {
      if (p->type != XML_ELEMENT_NODE)
        continue;
      if ((--n) < 0)
        break;
    }
    return XMLNode(p);
  }

Here is the call graph for this function:

bool Arc::XMLSecNode::DecryptNode ( const std::string &  privkey_file,
XMLNode decrypted_node 
)

Decrypt the <xenc:EncryptedData/> under this node, the decrypted node will be output in the second *argument of DecryptNode method.

And the <xenc:EncryptedData/> under this node will be removed after *decryption.

Parameters:
privkey_fileThe private key file, which is used for decrypting
decrypted_nodeOutput the decrypted node

Definition at line 299 of file XMLSecNode.cpp.

                                                                                   {
  XMLNode encrypted_data = (*this)["xenc:EncryptedData"];
  XMLNode enc_method1 = encrypted_data["xenc:EncryptionMethod"];
  std::string algorithm = (std::string)(enc_method1.Attribute("Algorithm"));
  if(algorithm.empty()) { std::cerr<<"No EncryptionMethod"<<std::endl; return false; }
  xmlSecKeyDataId key_type;
  if(algorithm.find("#aes")!=std::string::npos) { key_type = xmlSecKeyDataAesId;}
  else if(algorithm.find("#des")!=std::string::npos) { key_type = xmlSecKeyDataDesId;}
  else { std::cerr<<"Unknown EncryptionMethod"<<std::endl; return false; }  

  xmlNodePtr todecrypt_data_nd = ((XMLSecNode*)(&encrypted_data))->node_;

  XMLNode encrypted_key = encrypted_data["KeyInfo"]["EncryptedKey"]; 
  //Copy the encrypted key, because it will be replaced by decrypted node after
  //decryption, and then it will affect the decryption if encrypted data
  xmlNodePtr todecrypt_key_nd = xmlCopyNode(((XMLSecNode*)(&encrypted_key))->node_, 1);

  xmlDocPtr doc_key_nd = NULL;
  doc_key_nd = xmlNewDoc((xmlChar*)"1.0");
  xmlDocSetRootElement(doc_key_nd, todecrypt_key_nd);

  xmlSecKeyPtr private_key = get_key_from_keyfile(privkey_file.c_str());

  xmlSecEncCtxPtr encCtx = NULL;
  xmlSecKeyPtr symmetric_key = NULL;
  xmlSecBufferPtr key_buffer; 
  encCtx = xmlSecEncCtxCreate(NULL);
  if (encCtx == NULL) { std::cerr<<"Failed to create encryption context"<<std::endl; xmlFreeDoc(doc_key_nd); return false; }
  encCtx->encKey = private_key;
  encCtx->mode = xmlEncCtxModeEncryptedKey;
  key_buffer = xmlSecEncCtxDecryptToBuffer(encCtx, todecrypt_key_nd);
  if (key_buffer == NULL) { 
    std::cerr<<"Failed to decrypt EncryptedKey"<<std::endl;  
    xmlSecEncCtxDestroy(encCtx);  xmlFreeDoc(doc_key_nd); return false;
  }
  symmetric_key = xmlSecKeyReadBuffer(key_type, key_buffer);
  if (symmetric_key == NULL) { 
    std::cerr<<"Failed to decrypt EncryptedKey"<<std::endl; 
    xmlSecEncCtxDestroy(encCtx);  xmlFreeDoc(doc_key_nd); return false;
  }
  xmlSecEncCtxDestroy(encCtx);

  xmlDocPtr doc_data_nd = NULL;
  doc_data_nd = xmlNewDoc((xmlChar*)"1.0");
  xmlDocSetRootElement(doc_data_nd, todecrypt_data_nd);
  encCtx = xmlSecEncCtxCreate(NULL);
  if (encCtx == NULL) { std::cerr<<"Failed to create encryption context"<<std::endl; xmlFreeDoc(doc_key_nd); xmlFreeDoc(doc_data_nd); return false; }
  encCtx->encKey = symmetric_key;
  encCtx->mode = xmlEncCtxModeEncryptedData;
  xmlSecBufferPtr decrypted_buf;
  decrypted_buf = xmlSecEncCtxDecryptToBuffer(encCtx, todecrypt_data_nd);
  if(decrypted_buf == NULL) {
    std::cerr<<"Failed to decrypt EncryptedData"<<std::endl;
    xmlSecEncCtxDestroy(encCtx); xmlFreeDoc(doc_key_nd);  xmlFreeDoc(doc_data_nd); return false;
  }

  std::string decrypted_str((const char*)decrypted_buf->data);
  //std::cout<<"Decrypted node: "<<decrypted_str<<std::endl;

  // TODO: less copies
  XMLNode decrypted_data(decrypted_str);
  decrypted_data.New(decrypted_node);

  xmlSecEncCtxDestroy(encCtx);
  xmlFreeDoc(doc_key_nd);
  xmlFreeDoc(doc_data_nd);

  return true;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void Arc::XMLNode::Destroy ( void  ) [inherited]

Destroys underlying XML element.

XML element is unlinked from XML tree and destroyed. After this operation XMLNode instance becomes invalid

Definition at line 771 of file XMLNode.cpp.

                            {
    if (node_ == NULL)
      return;
    if (is_owner_) {
      xmlFreeDoc(node_->doc);
      node_ = NULL;
      is_owner_ = false;
      return;
    }
    if (node_->type == XML_ELEMENT_NODE) {
      xmlUnlinkNode(node_);
      xmlFreeNode(node_);
      node_ = NULL;
      return;
    }
    if (node_->type == XML_ATTRIBUTE_NODE) {
      xmlRemoveProp((xmlAttrPtr)node_);
      node_ = NULL;
      return;
    }
  }

Here is the caller graph for this function:

bool Arc::XMLSecNode::EncryptNode ( const std::string &  cert_file,
const SymEncryptionType  encrpt_type 
)

Encrypt this node, after encryption, this node will be replaced by the encrypted node.

Parameters:
cert_fileThe certificate file, the public key parsed from this certificate is used to encrypted the symmetric key, and then the symmetric key is used to encrypted the node
encrpt_typeThe encryption type when encrypting the node, four option in SymEncryptionType
verify_trustedVerify trusted certificates or not. If set to false, then only the signature will be checked (by using the public key from KeyInfo).

Definition at line 194 of file XMLSecNode.cpp.

                                                                                            {
  xmlNodePtr data_nd = this->node_;
  xmlDocPtr doc_nd = data_nd->doc;

  xmlNodePtr encDataNode = NULL;
  xmlNodePtr keyInfoNode = NULL;
  xmlNodePtr encKeyNode = NULL;
  xmlNodePtr keyInfoNode2 = NULL;
  xmlSecEncCtxPtr encCtx = NULL;

  xmlSecTransformId encryption_sym_key_type;
  switch (encrpt_type) {
    case AES_256:
      encryption_sym_key_type = xmlSecTransformAes256CbcId;
      break;
    case TRIPLEDES:
      encryption_sym_key_type = xmlSecTransformDes3CbcId;
      break;
    case AES_128:
    default:
      encryption_sym_key_type = xmlSecTransformAes128CbcId;
      break;
  }
  //Create encryption template for a specific symetric key type
  encDataNode = xmlSecTmplEncDataCreate(doc_nd , encryption_sym_key_type,
                      NULL, xmlSecTypeEncElement, NULL, NULL);
  if(encDataNode == NULL) { std::cerr<<"Failed to create encryption template"<<std::endl; return false; }

  // Put encrypted data in the <enc:CipherValue/> node
  if(xmlSecTmplEncDataEnsureCipherValue(encDataNode) == NULL){
    std::cerr<<"Failed to add CipherValue node"<<std::endl;
    if(encDataNode != NULL) xmlFreeNode(encDataNode); return false;
  }
  // Add <dsig:KeyInfo/>
  keyInfoNode = xmlSecTmplEncDataEnsureKeyInfo(encDataNode, NULL);
  if(keyInfoNode == NULL) {
    std::cerr<<"Failed to add key info"<<std::endl;
    if(encDataNode != NULL) xmlFreeNode(encDataNode); return false;
  }

  // Add <enc:EncryptedKey/> to store the encrypted session key
  encKeyNode = xmlSecTmplKeyInfoAddEncryptedKey(keyInfoNode, xmlSecTransformRsaPkcs1Id, NULL, NULL, NULL);
  if(encKeyNode == NULL) {
    std::cerr<<"Failed to add key info"<<std::endl;
    if(encDataNode != NULL) xmlFreeNode(encDataNode); return false;
  }

  // Put encrypted key in the <enc:CipherValue/> node
  if(xmlSecTmplEncDataEnsureCipherValue(encKeyNode) == NULL) {
    std::cerr<<"Error: failed to add CipherValue node"<<std::endl;
    if(encDataNode != NULL) xmlFreeNode(encDataNode); return false;
  }

  // Add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to <enc:EncryptedKey/>
  keyInfoNode2 = xmlSecTmplEncDataEnsureKeyInfo(encKeyNode, NULL);
  if(keyInfoNode2 == NULL){
    std::cerr<<"Failed to add key info"<<std::endl;
    if(encDataNode != NULL) xmlFreeNode(encDataNode); return false;
  }

  //Create encryption context
  xmlSecKeysMngr* keys_mngr = NULL;
  keys_mngr = load_key_from_certfile(&keys_mngr, cert_file.c_str());
  encCtx = xmlSecEncCtxCreate(keys_mngr);
  if(encCtx == NULL) {
    std::cerr<<"Failed to create encryption context"<<std::endl;
    if(encDataNode != NULL) xmlFreeNode(encDataNode); return false;
  }
  
  //Generate a symmetric key
  switch (encrpt_type) {
    case AES_256:
       encCtx->encKey = xmlSecKeyGenerate(xmlSecKeyDataAesId, 256, xmlSecKeyDataTypeSession);
      break;
    case TRIPLEDES:
       encCtx->encKey = xmlSecKeyGenerate(xmlSecKeyDataDesId, 192, xmlSecKeyDataTypeSession);
      break;
    case AES_128:
    default:
       encCtx->encKey = xmlSecKeyGenerate(xmlSecKeyDataAesId, 128, xmlSecKeyDataTypeSession);
      break;
  }
  if(encCtx->encKey == NULL) {
    std::cerr<<"Failed to generate session des key"<<std::endl;
    if(encCtx != NULL) xmlSecEncCtxDestroy(encCtx);
    if(encDataNode != NULL) xmlFreeNode(encDataNode);
    return false;
  }
  //Encrypt the node  
  if(xmlSecEncCtxXmlEncrypt(encCtx, encDataNode, data_nd) < 0) {
    std::cerr<<"Encryption failed"<<std::endl;
    if(encCtx != NULL) xmlSecEncCtxDestroy(encCtx);
    if(encDataNode != NULL) xmlFreeNode(encDataNode);
    return false;
  }

    //The template has been inserted in the doc
  this->node_ = (data_nd=encDataNode);
  encDataNode = NULL;

  if(encCtx != NULL) xmlSecEncCtxDestroy(encCtx);
  if(keys_mngr != NULL)xmlSecKeysMngrDestroy(keys_mngr);
  return true;
}

Here is the call graph for this function:

void Arc::XMLNode::Exchange ( XMLNode node) [inherited]

Exchanges XML (sub)trees.

Following conbinations are possible

If either this ir node are refering owned XML tree (top level node) then references are simply excanged. This opearationis fast. If both this and node are refering to XML (sub)tree of different documents then (sub)trees are exchahed between documments. If both this and node are refering to XML (sub)tree of same document then (sub)trees are moved inside document. The main reason for this method is to provide effective way to insert one XML document inside another. One should take into account that if any of exchanged nodes is top level it must be also owner of document. Otherwise method will fail. If both nodes are top level owners and/or invlaid nodes then this method is identical to Swap().

Definition at line 693 of file XMLNode.cpp.

                                      {
    if(((node_ == NULL) || is_owner_) &&
       ((node.node_ == NULL) || node.is_owner_)) {
      Swap(node); // ?
      return;
    }
    xmlNodePtr node1 = node_;
    xmlNodePtr node2 = node.node_;
    if(node1 && (node1->type != XML_ELEMENT_NODE)) return;
    if(node2 && (node2->type != XML_ELEMENT_NODE)) return;
    node_ = NULL; node.node_ = NULL;
    xmlNodePtr neighb1 = node1?(node1->next):NULL;
    xmlNodePtr neighb2 = node2?(node2->next):NULL;
    xmlNodePtr parent1 = node1?(node1->parent):NULL;
    xmlNodePtr parent2 = node2?(node2->parent):NULL;
    xmlDocPtr doc1 = node1?(node1->doc):NULL;
    xmlDocPtr doc2 = node2?(node2->doc):NULL;
    // In current implementation it is dangerous to move
    // top level element if node is not owning document
    if((parent1 == NULL) && (!is_owner_)) return;
    if((parent2 == NULL) && (!node.is_owner_)) return;
    xmlUnlinkNode(node1);
    xmlUnlinkNode(node2);
    if(parent1) {
      if(neighb1) {
        xmlAddPrevSibling(neighb1,node2);
      } else {
        xmlAddChild(parent1,node2);
      }
    } else if(doc1) {
      xmlDocSetRootElement(doc1,node2);
    } else {
      // Should not happen
      xmlFreeNode(node2); node2 = NULL;
    }
    if(parent2) {
      if(neighb2) {
        xmlAddPrevSibling(neighb2,node1);
      } else {
        xmlAddChild(parent2,node1);
      }
    } else if(doc2) {
      xmlDocSetRootElement(doc2,node1);
    } else {
      // Should not happen
      xmlFreeNode(node1); node1 = NULL;
    }
    node_ = node2;
    node.node_ = node1;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

std::string Arc::XMLNode::FullName ( void  ) const [inline, inherited]

Returns prefix:name of XML node.

Definition at line 231 of file XMLNode.h.

                                   {
      return Prefix() + ":" + Name();
    }

Here is the call graph for this function:

Here is the caller graph for this function:

XMLNode Arc::XMLNode::Get ( const std::string &  name) const [inline, inherited]

Same as operator[].

Definition at line 223 of file XMLNode.h.

                                             {
      return operator[](name.c_str());
    }

Here is the call graph for this function:

Here is the caller graph for this function:

void Arc::XMLNode::GetDoc ( std::string &  out_xml_str,
bool  user_friendly = false 
) const [inherited]

Fills argument with whole XML document textual representation.

Definition at line 909 of file XMLNode.cpp.

                                                                       {
    out_xml_str.resize(0);
    if (!node_)
      return;
    xmlDocPtr doc = node_->doc;
    if (doc == NULL)
      return;
    xmlOutputBufferPtr buf =
     xmlOutputBufferCreateIO(&write_to_string,&close_string,&out_xml_str,NULL);
    if(buf == NULL)
      return;
/*
    xmlChar *buf = NULL;
    int bufsize = 0;
    if (user_friendly)
      xmlDocDumpFormatMemory(doc, &buf, &bufsize, 1);
    else
      xmlDocDumpMemory(doc, &buf, &bufsize);
    if (buf) {
      out_xml_str = (char*)buf;
      xmlFree(buf);
    }
*/
    // Note xmlSaveFormatFileTo/xmlSaveFileTo call xmlOutputBufferClose
    if (user_friendly)
      xmlSaveFormatFileTo(buf, doc, (const char*)(doc->encoding), 1);
    else
      xmlSaveFileTo(buf, doc, (const char*)(doc->encoding));
  }

Here is the call graph for this function:

Here is the caller graph for this function:

XMLNode Arc::XMLNode::GetRoot ( void  ) [inherited]

Get the root node from any child node of the tree.

Definition at line 864 of file XMLNode.cpp.

                               {
    if (node_ == NULL)
      return XMLNode();
    xmlDocPtr doc = node_->doc;
    if (doc == NULL)
      return XMLNode();
    return XMLNode(doc->children);
  }

Here is the call graph for this function:

Here is the caller graph for this function:

void Arc::XMLNode::GetXML ( std::string &  out_xml_str,
bool  user_friendly = false 
) const [inherited]

Fills argument with this instance XML subtree textual representation.

Definition at line 939 of file XMLNode.cpp.

                                                                       {
    out_xml_str.resize(0);
    if (!node_)
      return;
    if (node_->type != XML_ELEMENT_NODE)
      return;
    xmlDocPtr doc = node_->doc;
    if (doc == NULL)
      return;
/*
    xmlBufferPtr buf = xmlBufferCreate();
    xmlNodeDump(buf, doc, node_, 0, user_friendly ? 1 : 0);
    out_xml_str = (char*)(buf->content);
    xmlBufferFree(buf);
*/
    xmlOutputBufferPtr buf =
     xmlOutputBufferCreateIO(&write_to_string,&close_string,&out_xml_str,NULL);
    if(buf == NULL)
      return;
    xmlNodeDumpOutput(buf, doc, node_, 0, user_friendly ? 1 : 0, (const char*)(doc->encoding));
    xmlOutputBufferClose(buf);
  }

Here is the call graph for this function:

void Arc::XMLNode::GetXML ( std::string &  out_xml_str,
const std::string &  encoding,
bool  user_friendly = false 
) const [inherited]

Fills argument with this instance XML subtree textual representation if the XML subtree is corresponding to the encoding format specified in the argument, e.g.

utf-8

Definition at line 962 of file XMLNode.cpp.

                                                                                                  {
    out_xml_str.resize(0);
    if (!node_)
      return;
    if (node_->type != XML_ELEMENT_NODE)
      return;
    xmlDocPtr doc = node_->doc;
    if (doc == NULL)
      return;
    xmlCharEncodingHandlerPtr handler = NULL;
    handler = xmlFindCharEncodingHandler(encoding.c_str());
    if (handler == NULL)
      return;
    //xmlOutputBufferPtr buf = xmlAllocOutputBuffer(handler);
    xmlOutputBufferPtr buf =
     xmlOutputBufferCreateIO(&write_to_string,&close_string,&out_xml_str,NULL);
    if(buf == NULL)
      return;
    xmlNodeDumpOutput(buf, doc, node_, 0, user_friendly ? 1 : 0, encoding.c_str());
    xmlOutputBufferFlush(buf);
    //out_xml_str = (char*)(buf->conv ? buf->conv->content : buf->buffer->content);
    xmlOutputBufferClose(buf);
  }

Here is the call graph for this function:

void Arc::XMLNode::Move ( XMLNode node) [inherited]

Moves content of this XML (sub)tree to node This opeartion is similar to New except that XML (sub)tree to refered by this is destroyed.

This method is more effective than combination of New() and Destroy() because internally it is optimized not to copy data if not needed. The main purpose of this is to effectively extract part of XML document.

Definition at line 655 of file XMLNode.cpp.

                                  {
    if (node.is_owner_ && node.node_)
      xmlFreeDoc(node.node_->doc);
    node.is_owner_ = false;
    node.node_ = NULL;
    if (node_ == NULL)
      return;
    // TODO: Copy attribute node too
    if (node_->type != XML_ELEMENT_NODE) {
      return;
    }
    if(is_owner_) {
      // Owner also means top level. So just copy and clean.
      node.node_=node_;
      node.is_owner_=true;
      node_=NULL; is_owner_=false;
      return;
    }
    // Otherwise unlink this node and make a new document of it
    // New(node); Destroy();
    xmlDocPtr doc = xmlNewDoc((const xmlChar*)"1.0");
    if (doc == NULL) return;
    xmlUnlinkNode(node_);
    node.node_ = node_; node_ = NULL;
    xmlDocSetRootElement(doc, node.node_);
    node.is_owner_ = true;
    return;
  }

Here is the caller graph for this function:

std::string Arc::XMLNode::Name ( void  ) const [inherited]

Returns name of XML node.

Definition at line 393 of file XMLNode.cpp.

                                    {
    const char *name = (node_) ? ((node_->name) ? (char*)(node_->name) : "") : "";
    return std::string(name);
  }

Here is the call graph for this function:

void Arc::XMLNode::Name ( const char *  name) [inherited]

Assigns new name to XML node.

Definition at line 485 of file XMLNode.cpp.

                                     {
    if (!node_)
      return;
    const char *name_ = strchr(name, ':');
    xmlNsPtr ns = NULL;
    if (name_ != NULL) {
      std::string ns_(name, name_ - name);
      // ns element is located at same place in Node and Attr elements
      ns = xmlSearchNs(node_->doc, node_, (const xmlChar*)(ns_.c_str()));
      ++name_;
    }
    else
      name_ = name;
    xmlNodeSetName(node_, (const xmlChar*)name_);
    if (ns)
      node_->ns = ns;
  }
void Arc::XMLNode::Name ( const std::string &  name) [inline, inherited]

Assigns new name to XML node.

Definition at line 239 of file XMLNode.h.

                                     {
      Name(name.c_str());
    }

Here is the call graph for this function:

std::string Arc::XMLNode::Namespace ( void  ) const [inherited]

Returns namespace URI of XML node.

Definition at line 474 of file XMLNode.cpp.

                                         {
    if (!node_)
      return "";
    xmlNsPtr ns = GetNamespace(node_);
    if (!ns)
      return "";
    if (!(ns->href))
      return "";
    return (const char*)(ns->href);
  }

Here is the call graph for this function:

Here is the caller graph for this function:

std::string Arc::XMLNode::NamespacePrefix ( const char *  urn) [inherited]

Returns prefix of specified namespace.

Empty string if no such namespace.

Definition at line 762 of file XMLNode.cpp.

                                                    {
    if (node_ == NULL)
      return "";
    xmlNsPtr ns_ = xmlSearchNsByHref(node_->doc, node_, (const xmlChar*)urn);
    if (!ns_)
      return "";
    return (char*)(ns_->prefix);
  }

Here is the caller graph for this function:

void Arc::XMLNode::Namespaces ( const NS namespaces,
bool  keep = false,
int  recursion = -1 
) [inherited]

Assigns namespaces of XML document at point specified by this instance.

If namespace already exists it gets new prefix. New namespaces are added. It is useful to apply this method to XML being processed in order to refer to it's elements by known prefix. If keep is set to false existing namespace definition residing at this instance and below are removed (default beavior). If recursion is set to positive number then depth of prefix replacement is limited by this number (0 limits it to this node only). For unlimted recursion use -1. If recursion is limited then value of keep is ignored and existing namespaces are always kept.

Definition at line 744 of file XMLNode.cpp.

                                                                         {
    if (node_ == NULL)
      return;
    if (node_->type != XML_ELEMENT_NODE)
      return;
    SetNamespaces(namespaces, node_, keep, recursion);
  }

Here is the call graph for this function:

Here is the caller graph for this function:

NS Arc::XMLNode::Namespaces ( void  ) [inherited]

Returns namespaces known at this node.

Definition at line 752 of file XMLNode.cpp.

                             {
    NS namespaces;
    if (node_ == NULL)
      return namespaces;
    if (node_->type != XML_ELEMENT_NODE)
      return namespaces;
    GetNamespaces(namespaces, node_);
    return namespaces;
  }

Here is the call graph for this function:

void Arc::XMLNode::New ( XMLNode node) const [inherited]

Creates a copy of XML (sub)tree.

If object does not represent whole document - top level document is created. 'new_node' becomes a pointer owning new XML document.

Definition at line 634 of file XMLNode.cpp.

                                           {
    if (new_node.is_owner_ && new_node.node_)
      xmlFreeDoc(new_node.node_->doc);
    new_node.is_owner_ = false;
    new_node.node_ = NULL;
    if (node_ == NULL)
      return;
    // TODO: Copy attribute node too
    if (node_->type != XML_ELEMENT_NODE)
      return;
    xmlDocPtr doc = xmlNewDoc((const xmlChar*)"1.0");
    if (doc == NULL)
      return;
    new_node.node_ = xmlDocCopyNode(node_, doc, 1);
    if (new_node.node_ == NULL)
      return;
    xmlDocSetRootElement(doc, new_node.node_);
    new_node.is_owner_ = true;
    return;
  }
XMLNode Arc::XMLNode::NewAttribute ( const char *  name) [inherited]

Creates new attribute with specified name.

Definition at line 446 of file XMLNode.cpp.

                                                {
    if (!node_)
      return XMLNode();
    if (node_->type != XML_ELEMENT_NODE)
      return XMLNode();
    const char *name_ = strchr(name, ':');
    xmlNsPtr ns = NULL;
    if (name_ != NULL) {
      std::string ns_(name, name_ - name);
      ns = xmlSearchNs(node_->doc, node_, (const xmlChar*)(ns_.c_str()));
      ++name_;
    }
    else
      name_ = name;
    return XMLNode((xmlNodePtr)xmlNewNsProp(node_, ns, (const xmlChar*)name_, NULL));
  }

Here is the call graph for this function:

XMLNode Arc::XMLNode::NewAttribute ( const std::string &  name) [inline, inherited]

Creates new attribute with specified name.

Definition at line 279 of file XMLNode.h.

                                                {
      return NewAttribute(name.c_str());
    }

Here is the call graph for this function:

XMLNode Arc::XMLNode::NewChild ( const char *  name,
int  n = -1,
bool  global_order = false 
) [inherited]

Creates new child XML element at specified position with specified name.

Default is to put it at end of list. If global order is true position applies to whole set of children, otherwise only to children of same name. Returns created node.

Definition at line 555 of file XMLNode.cpp.

                                                                      {
    if (node_ == NULL)
      return XMLNode();
    if (node_->type != XML_ELEMENT_NODE)
      return XMLNode();
    const char *name_ = strchr(name, ':');
    xmlNsPtr ns = NULL;
    if (name_ != NULL) {
      std::string ns_(name, name_ - name);
      ns = xmlSearchNs(node_->doc, node_, (const xmlChar*)(ns_.c_str()));
      ++name_;
    }
    else
      name_ = name;
    xmlNodePtr new_node = xmlNewNode(ns, (const xmlChar*)name_);
    if (new_node == NULL)
      return XMLNode();
    if (n < 0)
      return XMLNode(xmlAddChild(node_, new_node));
    XMLNode old_node = global_order ? Child(n) : operator[](name)[n];
    if (!old_node)
      // TODO: find last old_node
      return XMLNode(xmlAddChild(node_, new_node));
    if (old_node)
      return XMLNode(xmlAddPrevSibling(old_node.node_, new_node));
    return XMLNode(xmlAddChild(node_, new_node));
  }

Here is the call graph for this function:

XMLNode Arc::XMLNode::NewChild ( const std::string &  name,
int  n = -1,
bool  global_order = false 
) [inline, inherited]

Same as NewChild(const char*,int,bool)

Definition at line 306 of file XMLNode.h.

                                                                                   {
      return NewChild(name.c_str(), n, global_order);
    }

Here is the call graph for this function:

XMLNode Arc::XMLNode::NewChild ( const char *  name,
const NS namespaces,
int  n = -1,
bool  global_order = false 
) [inherited]

Creates new child XML element at specified position with specified name and namespaces.

For more information look at NewChild(const char*,int,bool)

Definition at line 548 of file XMLNode.cpp.

                                                                                            {
    XMLNode x = NewChild("", n, global_order); // placeholder
    x.Namespaces(namespaces);
    x.Name(name);
    return x;
  }

Here is the call graph for this function:

XMLNode Arc::XMLNode::NewChild ( const std::string &  name,
const NS namespaces,
int  n = -1,
bool  global_order = false 
) [inline, inherited]

Same as NewChild(const char*,const NS&,int,bool)

Definition at line 313 of file XMLNode.h.

                                                                                                         {
      return NewChild(name.c_str(), namespaces, n, global_order);
    }

Here is the call graph for this function:

XMLNode Arc::XMLNode::NewChild ( const XMLNode node,
int  n = -1,
bool  global_order = false 
) [inherited]

Link a copy of supplied XML node as child.

Returns instance refering to new child. XML element is a copy of supplied one but not owned by returned instance

Definition at line 583 of file XMLNode.cpp.

                                                                         {
    if (node_ == NULL)
      return XMLNode();
    if (node.node_ == NULL)
      return XMLNode();
    if (node_->type != XML_ELEMENT_NODE)
      return XMLNode();
    // TODO: Add new attribute if 'node' is attribute
    if (node.node_->type != XML_ELEMENT_NODE)
      return XMLNode();
    xmlNodePtr new_node = xmlDocCopyNode(node.node_, node_->doc, 1);
    if (new_node == NULL)
      return XMLNode();
    if (n < 0)
      return XMLNode(xmlAddChild(node_, new_node));
    std::string name;
    xmlNsPtr ns = GetNamespace(new_node);
    if (ns != NULL) {
      if (ns->prefix != NULL)
        name = (char*)ns->prefix;
      name += ":";
    }
    if (new_node->name)
      name += (char*)(new_node->name);
    XMLNode old_node = global_order ? Child(n) : operator[](name)[n];
    if (!old_node)
      // TODO: find last old_node
      return XMLNode(xmlAddChild(node_, new_node));
    if (old_node)
      return XMLNode(xmlAddPrevSibling(old_node.node_, new_node));
    return XMLNode(xmlAddChild(node_, new_node));
  }

Here is the call graph for this function:

Arc::XMLNode::operator bool ( void  ) const [inline, inherited]

Returns true if instance points to XML element - valid instance.

Definition at line 143 of file XMLNode.h.

                              {
      return ((node_ != NULL) && (!is_temporary_));
    }
Arc::XMLNode::operator std::string ( void  ) const [inherited]

Returns textual content of node excluding content of children nodes.

Definition at line 518 of file XMLNode.cpp.

                                        {
    std::string content;
    if (!node_)
      return content;
    for (xmlNodePtr p = node_->children; p; p = p->next) {
      if (p->type != XML_TEXT_NODE)
        continue;
      xmlChar *buf = xmlNodeGetContent(p);
      if (!buf)
        continue;
      content += (char*)buf;
      xmlFree(buf);
    }
    return content;
  }
bool Arc::XMLNode::operator! ( void  ) const [inline, inherited]

Returns true if instance does not point to XML element - invalid instance.

Definition at line 147 of file XMLNode.h.

                               {
      return ((node_ == NULL) || is_temporary_);
    }
bool Arc::XMLNode::operator!= ( const XMLNode node) [inline, inherited]

Returns false if 'node' represents same XML element.

Definition at line 155 of file XMLNode.h.

                                         {
      return ((node_ != node.node_) || (node_ == NULL));
    }
bool Arc::XMLNode::operator!= ( bool  val) [inline, inherited]

This operator is needed to avoid ambiguity.

Definition at line 167 of file XMLNode.h.

                              {
      return ((bool)(*this) != val);
    }
bool Arc::XMLNode::operator!= ( const std::string &  str) [inline, inherited]

This operator is needed to avoid ambiguity.

Definition at line 175 of file XMLNode.h.

                                          {
      return ((std::string)(*this) != str);
    }
bool Arc::XMLNode::operator!= ( const char *  str) [inline, inherited]

This operator is needed to avoid ambiguity.

Definition at line 183 of file XMLNode.h.

                                     {
      return ((std::string)(*this) != str);
    }
void Arc::XMLNode::operator++ ( void  ) [inherited]

Convenience operator to switch to next element of same name.

If there is no such node this object becomes invalid.

Definition at line 332 of file XMLNode.cpp.

                               {
    if (!node_)
      return;
    if (is_owner_) { // top node has no siblings
      xmlFreeDoc(node_->doc);
      node_ = NULL;
      is_owner_ = false;
      return;
    }
    xmlNodePtr p = node_->next;
    for (; p; p = p->next) {
      if (node_->type != p->type)
        continue;
      if (node_->name) {
        if (!(p->name))
          continue;
        if (!MatchXMLName(node_, p))
          continue;
      }
      break;
    }
    node_ = p;
  }
void Arc::XMLNode::operator-- ( void  ) [inherited]

Convenience operator to switch to previous element of same name.

If there is no such node this object becomes invalid.

Definition at line 356 of file XMLNode.cpp.

                               {
    if (!node_)
      return;
    if (is_owner_) { // top node has no siblings
      xmlFreeDoc(node_->doc);
      node_ = NULL;
      is_owner_ = false;
      return;
    }
    xmlNodePtr p = node_->prev;
    for (; p; p = p->prev) {
      if (node_->type != p->type)
        continue;
      if (node_->name) {
        if (!(p->name))
          continue;
        if (!MatchXMLName(node_, p))
          continue;
      }
      break;
    }
    node_ = p;
  }
bool Arc::XMLNode::operator== ( const XMLNode node) [inline, inherited]

Returns true if 'node' represents same XML element.

Definition at line 151 of file XMLNode.h.

                                         {
      return ((node_ == node.node_) && (node_ != NULL));
    }

Here is the caller graph for this function:

bool Arc::XMLNode::operator== ( bool  val) [inline, inherited]

This operator is needed to avoid ambiguity.

Definition at line 163 of file XMLNode.h.

                              {
      return ((bool)(*this) == val);
    }
bool Arc::XMLNode::operator== ( const std::string &  str) [inline, inherited]

This operator is needed to avoid ambiguity.

Definition at line 171 of file XMLNode.h.

                                          {
      return ((std::string)(*this) == str);
    }
bool Arc::XMLNode::operator== ( const char *  str) [inline, inherited]

This operator is needed to avoid ambiguity.

Definition at line 179 of file XMLNode.h.

                                     {
      return ((std::string)(*this) == str);
    }
XMLNode Arc::XMLNode::operator[] ( const char *  name) const [inherited]

Returns XMLNode instance representing first child element with specified name.

Name may be "namespace_prefix:name" or simply "name". In last case namespace is ignored. If such node does not exist invalid XMLNode instance is returned. This method should not be marked const because obtaining unrestricted XMLNode of child element allows modification of underlying XML tree. But in order to keep const in other places non-const-handling is passed to programmer. Otherwise C++ compiler goes nuts.

Definition at line 315 of file XMLNode.cpp.

                                                    {
    if (!node_)
      return XMLNode();
    if ((node_->type != XML_ELEMENT_NODE) &&
        (node_->type != XML_ATTRIBUTE_NODE))
      return XMLNode();
    xmlNodePtr p = node_->children;
    for (; p; p = p->next) {
      if ((p->type != XML_ELEMENT_NODE) &&
          (p->type != XML_ATTRIBUTE_NODE))
        continue;
      if (MatchXMLName(p, name))
        break;
    }
    return XMLNode(p);
  }

Here is the call graph for this function:

Here is the caller graph for this function:

XMLNode Arc::XMLNode::operator[] ( const std::string &  name) const [inline, inherited]

Similar to previous method.

Definition at line 201 of file XMLNode.h.

                                                    {
      return operator[](name.c_str());
    }

Here is the call graph for this function:

XMLNode Arc::XMLNode::operator[] ( int  n) const [inherited]

Returns XMLNode instance representing n-th node in sequence of siblings of same name.

It's main purpose is to be used to retrieve element in array of children of same name like node["name"][5]. This method should not be marked const because obtaining unrestricted XMLNode of child element allows modification of underlying XML tree. But in order to keep const in other places non-const-handling is passed to programmer. Otherwise C++ compiler goes nuts.

Definition at line 295 of file XMLNode.cpp.

                                         {
    if (!node_)
      return XMLNode();
    xmlNodePtr p = n < 0 ? NULL : node_;
    for (; p; p = p->next) {
      if ((p->type != XML_ELEMENT_NODE) &&
          (p->type != XML_ATTRIBUTE_NODE))
        continue;
      if (node_->name) {
        if (!(p->name))
          continue;
        if (!MatchXMLName(node_, p))
          continue;
      }
      if ((--n) < 0)
        break;
    }
    return XMLNode(p);
  }

Here is the call graph for this function:

XMLNode Arc::XMLNode::Parent ( void  ) [inherited]

Get the parent node from any child node of the tree.

Definition at line 873 of file XMLNode.cpp.

                              {
    if (node_ == NULL)
      return XMLNode();
    if (node_->type == XML_ELEMENT_NODE)
      return XMLNode(node_->parent);
    if (node_->type == XML_ATTRIBUTE_NODE)
      return XMLNode(((xmlAttrPtr)node_)->parent);
    return XMLNode();
  }

Here is the call graph for this function:

Here is the caller graph for this function:

XMLNodeList Arc::XMLNode::Path ( const std::string &  path) [inherited]

Collects nodes corresponding to specified path.

This is a convenience function to cover common use of XPath but without performance hit. Path is made of node_name[/node_name[...]] and is relative to current node. node_names are treated in same way as in operator[]. Returns all nodes which are represented by path.

Definition at line 793 of file XMLNode.cpp.

                                                 {
    XMLNodeList res;
    std::string::size_type name_s = 0;
    std::string::size_type name_e = path.find('/', name_s);
    if (name_e == std::string::npos)
      name_e = path.length();
    res.push_back(*this);
    for (;;) {
      if (res.size() <= 0)
        return res;
      XMLNodeList::iterator node = res.begin();
      std::string node_name = path.substr(name_s, name_e - name_s);
      int nodes_num = res.size();
      for (int n = 0; n < nodes_num; ++n) {
        for (int cn = 0;; ++cn) {
          XMLNode cnode = (*node).Child(cn);
          if (!cnode)
            break;
          if (MatchXMLName(cnode, node_name))
            res.push_back(cnode);
        }
        ++node;
      }
      res.erase(res.begin(), node);
      if (name_e >= path.length())
        break;
      name_s = name_e + 1;
      name_e = path.find('/', name_s);
      if (name_e == std::string::npos)
        name_e = path.length();
    }
    return res;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

std::string Arc::XMLNode::Prefix ( void  ) const [inherited]

Returns namespace prefix of XML node.

Definition at line 463 of file XMLNode.cpp.

                                      {
    if (!node_)
      return "";
    xmlNsPtr ns = GetNamespace(node_);
    if (!ns)
      return "";
    if (!(ns->prefix))
      return "";
    return (const char*)(ns->prefix);
  }

Here is the call graph for this function:

Here is the caller graph for this function:

bool Arc::XMLNode::ReadFromFile ( const std::string &  file_name) [inherited]

Read XML document from file and associate it with this node.

Definition at line 1035 of file XMLNode.cpp.

                                                       {
    std::ifstream in(file_name.c_str(), std::ios::in);
    if (!in)
      return false;
    bool r = ReadFromStream(in);
    in.close();
    return r;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

bool Arc::XMLNode::ReadFromStream ( std::istream &  in) [inherited]

Read XML document from stream and associate it with this node.

Definition at line 1008 of file XMLNode.cpp.

                                             {
    std::string s;
    std::getline<char>(in, s, 0);
    if (!in)
      return false;
    xmlDocPtr doc = xmlParseMemory((char*)(s.c_str()), s.length());
    if (doc == NULL)
      return false;
    xmlNodePtr p = doc->children;
    for (; p; p = p->next)
      if (p->type == XML_ELEMENT_NODE) break;
    if (!p) {
      xmlFreeDoc(doc);
      return false;
    }
    if (node_ != NULL)
      if (is_owner_) {
        xmlFreeDoc(node_->doc);
        node_ = NULL;
        is_owner_ = false;
      }
    node_ = p;
    if (node_)
      is_owner_ = true;
    return true;
  }

Here is the caller graph for this function:

void Arc::XMLNode::Replace ( const XMLNode node) [inherited]

Makes a copy of supplied XML node and makes this instance refere to it.

Definition at line 616 of file XMLNode.cpp.

                                           {
    if (node_ == NULL)
      return;
    if (node.node_ == NULL)
      return;
    if (node_->type != XML_ELEMENT_NODE)
      return;
    if (node.node_->type != XML_ELEMENT_NODE)
      return;
    xmlNodePtr new_node = xmlDocCopyNode(node.node_, node_->doc, 1);
    if (new_node == NULL)
      return;
    xmlReplaceNode(node_, new_node);
    xmlFreeNode(node_);
    node_ = new_node;
    return;
  }

Here is the caller graph for this function:

bool Arc::XMLNode::Same ( const XMLNode node) [inline, inherited]

Returns true if 'node' represents same XML element - for bindings.

Definition at line 159 of file XMLNode.h.

                                   {
      return operator==(node);
    }

Here is the call graph for this function:

bool Arc::XMLNode::SaveToFile ( const std::string &  file_name) const [inherited]

Save string representation of node to file.

Definition at line 994 of file XMLNode.cpp.

                                                           {
    std::ofstream out(file_name.c_str(), std::ios::out);
    if (!out)
      return false;
    bool r = SaveToStream(out);
    out.close();
    return r;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

bool Arc::XMLNode::SaveToStream ( std::ostream &  out) const [inherited]

Save string representation of node to stream.

Definition at line 986 of file XMLNode.cpp.

                                                  {
    std::string s;
    GetXML(s);
    out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << std::endl;
    out << s;
    return (bool)out;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

void Arc::XMLNode::Set ( const std::string &  content) [inline, inherited]

Same as operator=.

Used for bindings.

Definition at line 259 of file XMLNode.h.

                                       {
      operator=(content.c_str());
    }

Here is the call graph for this function:

Here is the caller graph for this function:

bool Arc::XMLSecNode::SignNode ( const std::string &  privkey_file,
const std::string &  cert_file 
)

Sign this node (identified by id_name).

Parameters:
privkey_fileThe private key file. The private key is used for signing
cert_fileThe certificate file. The certificate is used as the <KeyInfo> part of the <Signature>; <KeyInfo> will be used for the other end to verify this <Signature>
incl_namespacesInclusiveNamespaces for Tranform in Signature

Definition at line 88 of file XMLSecNode.cpp.

                                                                                   {
  //Generate signature according to the information inside signature template;
  XMLNode signature = (*this)["Signature"];
  xmlNodePtr signatureptr = ((XMLSecNode*)(&signature))->node_;
  xmlSecDSigCtx *dsigCtx = xmlSecDSigCtxCreate(NULL);
  //load private key, assuming there is no need for passphrase
  dsigCtx->signKey = xmlSecCryptoAppKeyLoad(privkey_file.c_str(), xmlSecKeyDataFormatPem, NULL, NULL, NULL);
  if(dsigCtx->signKey == NULL) {
    xmlSecDSigCtxDestroy(dsigCtx);
    std::cerr<<"Can not load key"<<std::endl; return false;
  }
  if(xmlSecCryptoAppKeyCertLoad(dsigCtx->signKey, cert_file.c_str(), xmlSecKeyDataFormatPem) < 0) {
    xmlSecDSigCtxDestroy(dsigCtx);
    std::cerr<<"Can not load certificate"<<std::endl; return false;
  }
  if (xmlSecDSigCtxSign(dsigCtx, signatureptr) < 0) {
    xmlSecDSigCtxDestroy(dsigCtx);
    std::cerr<<"Can not sign node"<<std::endl; return false;
  }
  if(dsigCtx != NULL)xmlSecDSigCtxDestroy(dsigCtx);
  return true;
}

Here is the caller graph for this function:

int Arc::XMLNode::Size ( void  ) const [inherited]

Returns number of children nodes.

Definition at line 380 of file XMLNode.cpp.

                              {
    if (!node_)
      return 0;
    int n = 0;
    xmlNodePtr p = node_->children;
    for (; p; p = p->next) {
      if (p->type != XML_ELEMENT_NODE)
        continue;
      ++n;
    }
    return n;
  }

Here is the caller graph for this function:

void Arc::XMLNode::Swap ( XMLNode node) [inherited]

Swaps XML (sub)trees to this this and node refer.

For XML subtrees this method is not anyhow different then using combinaiion XMLNode tmp=*this; *this=node; node=tmp; But in case of either this or node owning XML document ownership is swapped too. And this is a main purpose of Swap() method.

Definition at line 684 of file XMLNode.cpp.

                                  {
    xmlNodePtr tmp_node_ = node.node_;
    bool tmp_is_owner_ = node.is_owner_;
    node.node_ = node_;
    node.is_owner_ = is_owner_;
    node_ = tmp_node_;
    is_owner_ = tmp_is_owner_;
  }

Here is the caller graph for this function:

bool Arc::XMLNode::Validate ( const std::string &  schema_file,
std::string &  err_msg 
) [inherited]

Remove all eye-candy information leaving only informational parts * void Purify(void);.

XML schema validation against the schema file defined as argument

Definition at line 1049 of file XMLNode.cpp.

                                                                              {
    // create parser ctxt for schema accessible on schemaPath
    xmlSchemaParserCtxtPtr schemaParser = xmlSchemaNewParserCtxt(schema_file_name.c_str());
    if (!schemaParser) {
        err_msg = "Cannot load schema";
        return false;
    }
    // parse schema
    xmlSchemaPtr schema = xmlSchemaParse(schemaParser);
    if (!schema) {
        xmlSchemaFreeParserCtxt(schemaParser);
        err_msg = "Cannot parse schmea";
        return false;
    }
    xmlSchemaFreeParserCtxt(schemaParser);

    // create schema validation context
    xmlSchemaValidCtxtPtr validityCtx = xmlSchemaNewValidCtxt(schema);
    if (!validityCtx) {
        xmlSchemaFree(schema);
        err_msg = "Cannot create validation context";
        return false;
    }

    // Set contect collectoors
    xmlSchemaSetValidErrors(validityCtx,
                            (xmlSchemaValidityErrorFunc) fprintf,
                            (xmlSchemaValidityWarningFunc) fprintf,
                            stderr);
    // validate against schema
    bool result = (xmlSchemaValidateDoc(validityCtx, node_->doc) == 0);

    // free resources and return result
    xmlSchemaFreeValidCtxt(validityCtx);
    xmlSchemaFree(schema);

    return result;
  }

Here is the caller graph for this function:

bool Arc::XMLSecNode::VerifyNode ( const std::string &  id_name,
const std::string &  ca_file,
const std::string &  ca_path,
bool  verify_trusted = true 
)

Verify the signature under this node.

Parameters:
id_nameThe id of this node, which is used for identifying the node
ca_fileThe CA file which used as trused certificate when verify the certificate in the <KeyInfo> part of <Signature>
ca_pathThe CA directory; either ca_file or ca_path should be set.

Definition at line 111 of file XMLSecNode.cpp.

                                                                                                                             {
  xmlNodePtr node = this->node_;
  xmlDocPtr docPtr = node->doc;
  xmlChar* id = xmlGetProp(node, (xmlChar *)(id_name.c_str()));
  xmlAttrPtr id_attr = xmlHasProp(node, (xmlChar *)(id_name.c_str()));
  xmlAddID(NULL, docPtr, (xmlChar *)id, id_attr);
  xmlFree(id);
 
  XMLNode signature = (*this)["Signature"];
  if(!signature) { std::cerr<<"No signature node under this node"<<std::endl; return false; }
  xmlNodePtr signatureptr = ((XMLSecNode*)(&signature))->node_;
  XMLNode keyinfo = signature["KeyInfo"];
  XMLNode x509data = signature["KeyInfo"]["X509Data"];

  xmlSecKeysMngr* keys_manager = NULL;
  xmlSecDSigCtx *dsigCtx;
  
  if(verify_trusted) {
    //Verify the signature under the signature node (this node) 
    if((bool)x509data && (!ca_file.empty() || !ca_path.empty())) {
      keys_manager = load_trusted_certs(&keys_manager, ca_file.c_str(), ca_path.c_str());
      if(keys_manager == NULL) { std::cerr<<"Can not load trusted certificates"<<std::endl; return false; }
    } 
    else if((bool)x509data)
      { std::cerr<<"No trusted certificates exists"<<std::endl; return false;}
    if(keys_manager == NULL){ std::cerr<<"No <X509Data/> exists, or no trusted certificates configured"<<std::endl; return false;}
    dsigCtx = xmlSecDSigCtxCreate(keys_manager);
  }
  else {
    dsigCtx = xmlSecDSigCtxCreate(NULL);
    if((bool)x509data) {
      //Since xmlsec automatically needs to check trusted certificates
      //if the KeyInfo is composed by X509Data, here we manualy extract 
      //the public key from X509Data
      XMLNode x509cert = x509data["X509Certificate"];
      std::string certstr = (std::string)x509cert;
      xmlSecKey* pubkey = get_key_from_certstr(certstr);
      if (pubkey == NULL){
        xmlSecDSigCtxDestroy(dsigCtx);
        std::cerr<<"Can not load public key"<<std::endl; return false;
      }
      dsigCtx->signKey = pubkey;
    }
    else {
      //Use xmlSecKeyInfoNodeRead to extract public key
      dsigCtx->flags |= XMLSEC_DSIG_FLAGS_STORE_SIGNEDINFO_REFERENCES;
      dsigCtx->signKey = xmlSecKeyCreate();
      if(!keyinfo) {  
        std::cerr<<"No KeyInfo node exists"<<std::endl;         
        xmlSecDSigCtxDestroy(dsigCtx); return false;
      }
      xmlNodePtr keyinfoptr = ((XMLSecNode*)(&keyinfo))->node_;
      xmlSecKeyInfoCtxPtr keyInfo;
      keyInfo = xmlSecKeyInfoCtxCreate(NULL);
      if(!keyInfo) { xmlSecDSigCtxDestroy(dsigCtx); return false; }
      xmlSecKeyInfoNodeRead(keyinfoptr, dsigCtx->signKey,keyInfo);
      xmlSecKeyInfoCtxDestroy(keyInfo);
    }
  }


#if 0
if(//(xmlSecDSigCtxEnableReferenceTransform(dsigCtx, xmlSecTransformInclC14NId) < 0) ||
                        (xmlSecDSigCtxEnableReferenceTransform(dsigCtx, xmlSecTransformExclC14NId) < 0) ||
                        (xmlSecDSigCtxEnableReferenceTransform(dsigCtx, xmlSecTransformSha1Id) < 0) || 
                        (xmlSecDSigCtxEnableReferenceTransform(dsigCtx, xmlSecTransformEnvelopedId) < 0)
                        )
#endif
    
  if (xmlSecDSigCtxVerify(dsigCtx, signatureptr) < 0) {
    xmlSecDSigCtxDestroy(dsigCtx);
    if (keys_manager) xmlSecKeysMngrDestroy(keys_manager);
    std::cerr<<"Signature verification failed"<<std::endl;
    return false;
  } 
  if(keys_manager != NULL)xmlSecKeysMngrDestroy(keys_manager);
  if(dsigCtx->status == xmlSecDSigStatusSucceeded) {
    std::cout<<"Succeed to verify the signature under this node"<<std::endl;
    xmlSecDSigCtxDestroy(dsigCtx); return true;
  } 
  else { std::cerr<<"Invalid signature in this node"<<std::endl; xmlSecDSigCtxDestroy(dsigCtx); return false; }
}

Here is the call graph for this function:

Here is the caller graph for this function:

XMLNodeList Arc::XMLNode::XPathLookup ( const std::string &  xpathExpr,
const NS nsList 
) [inherited]

Uses xPath to look up the whole xml structure, Returns a list of XMLNode points.

The xpathExpr should be like "//xx:child1/" which indicates the namespace and node that you would like to find; The nsList is the namespace the result should belong to (e.g. xx="uri:test"). Query is run on whole XML document but only the elements belonging to this XML subtree are returned.

Definition at line 827 of file XMLNode.cpp.

                                                                               {
    std::list<XMLNode> retlist;
    if (node_ == NULL)
      return retlist;
    if (node_->type != XML_ELEMENT_NODE)
      return retlist;
    xmlDocPtr doc = node_->doc;
    if (doc == NULL)
      return retlist;
    xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);

    for (NS::const_iterator ns = nsList.begin(); ns != nsList.end(); ++ns)
      xmlXPathRegisterNs(xpathCtx, (xmlChar*)ns->first.c_str(), (xmlChar*)ns->second.c_str());

    xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression((const xmlChar*)(xpathExpr.c_str()), xpathCtx);

    if (xpathObj && xpathObj->nodesetval && xpathObj->nodesetval->nodeNr) {
      xmlNodeSetPtr nodes = xpathObj->nodesetval;
      int size = nodes->nodeNr;
      for (int i = 0; i < size; ++i)
        if (nodes->nodeTab[i]->type == XML_ELEMENT_NODE) {
          xmlNodePtr cur = nodes->nodeTab[i];
          xmlNodePtr parent = cur;
          for (; parent; parent = parent->parent)
            if (parent == node_)
              break;
          if (parent)
            retlist.push_back(XMLNode(cur));
        }
    }

    xmlXPathFreeObject(xpathObj);
    xmlXPathFreeContext(xpathCtx);

    return retlist;
  }

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

bool Arc::XMLNode::is_owner_ [protected, inherited]

If true node is owned by this instance - hence released in destructor.

Normally that may be true only for top level node of XML document.

Definition at line 68 of file XMLNode.h.

bool Arc::XMLNode::is_temporary_ [protected, inherited]

This variable is for future.

Definition at line 70 of file XMLNode.h.

xmlNodePtr Arc::XMLNode::node_ [protected, inherited]

Definition at line 64 of file XMLNode.h.


The documentation for this class was generated from the following files: