blob: 959524ea931ef0c5711f0c961080073118149915 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*
* XSEC
*
* DSIGTransformC14n := Class that performs C14n canonicalisation
*
* $Id$
*
*/
#include <xsec/dsig/DSIGSignature.hpp>
#include <xsec/dsig/DSIGTransformC14n.hpp>
#include <xsec/framework/XSECEnv.hpp>
#include <xsec/framework/XSECError.hpp>
#include <xsec/framework/XSECException.hpp>
#include <xsec/transformers/TXFMC14n.hpp>
#include <xsec/transformers/TXFMChain.hpp>
#include "../utils/XSECAlgorithmSupport.hpp"
#include "../utils/XSECDOMUtils.hpp"
XERCES_CPP_NAMESPACE_USE
// --------------------------------------------------------------------------------
// Constructors and Destructors
// --------------------------------------------------------------------------------
DSIGTransformC14n::DSIGTransformC14n(const XSECEnv* env, DOMNode* node) :
DSIGTransform(env, node) {
m_cMethod = NULL;
mp_inclNSNode = NULL;
mp_inclNSStr = NULL;
m_exclusive = false;
m_comments = false;
m_onedotone = false;
}
DSIGTransformC14n::DSIGTransformC14n(const XSECEnv* env) :
DSIGTransform(env) {
m_cMethod = NULL;
mp_inclNSNode = NULL;
mp_inclNSStr = NULL;
m_exclusive = false;
m_comments = false;
m_onedotone = false;
}
DSIGTransformC14n::~DSIGTransformC14n() {};
// --------------------------------------------------------------------------------
// Interface Methods
// --------------------------------------------------------------------------------
void DSIGTransformC14n::appendTransformer(TXFMChain* input) {
TXFMC14n* c;
XSECnew(c, TXFMC14n(mp_txfmNode->getOwnerDocument()));
input->appendTxfm(c);
if (m_comments)
c->activateComments();
else
c->stripComments();
// Check for exclusive and 1.1
if (m_exclusive) {
if (mp_inclNSStr == NULL) {
c->setExclusive();
}
else {
safeBuffer incl;
incl << (*(mp_env->getSBFormatter()) << mp_inclNSStr);
c->setExclusive(incl);
}
}
else if (m_onedotone) {
c->setInclusive11();
}
}
DOMElement* DSIGTransformC14n::createBlankTransform(DOMDocument* parentDoc) {
safeBuffer str;
const XMLCh * prefix;
DOMElement *ret;
DOMDocument *doc = mp_env->getParentDocument();
prefix = mp_env->getDSIGNSPrefix();
// Create the transform node
makeQName(str, prefix, "Transform");
ret = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
ret->setAttributeNS(NULL,DSIGConstants::s_unicodeStrAlgorithm, DSIGConstants::s_unicodeStrURIC14N_NOC);
m_cMethod = ret->getAttributeNS(NULL, DSIGConstants::s_unicodeStrAlgorithm);
m_comments = false;
m_exclusive = false;
m_onedotone = false;
mp_txfmNode = ret;
mp_inclNSStr = NULL;
mp_inclNSNode = NULL;
return ret;
}
void DSIGTransformC14n::load() {
DOMNamedNodeMap* atts;
DOMNode* att;
// Read the URI for the type
if (mp_txfmNode == NULL) {
throw XSECException(XSECException::ExpectedDSIGChildNotFound,
"Expected <Transform> Node in DSIGTrasnformC14n::load");
}
atts = mp_txfmNode->getAttributes();
if (atts == NULL ||
((att = atts->getNamedItem(DSIGConstants::s_unicodeStrAlgorithm)) == NULL)) {
throw XSECException(XSECException::ExpectedDSIGChildNotFound,
"Expected to find Algorithm attribute in <Transform> node");
}
m_cMethod = att->getNodeValue();
if (!XSECAlgorithmSupport::evalCanonicalizationMethod(m_cMethod, m_exclusive, m_comments, m_onedotone)) {
throw XSECException(XSECException::TransformError,
"Unexpected URI found in canonicalization <Transform>");
}
// Determine whether there is an InclusiveNamespaces list
if (m_exclusive) {
// Exclusive, so there may be an InclusiveNamespaces node
DOMNode* inclNSNode = mp_txfmNode->getFirstChild();
while (inclNSNode != NULL && (inclNSNode->getNodeType() != DOMNode::ELEMENT_NODE ||
!strEquals(getECLocalName(inclNSNode), "InclusiveNamespaces")))
inclNSNode = inclNSNode->getNextSibling();
if (inclNSNode != 0) {
mp_inclNSNode = static_cast<DOMElement *>(inclNSNode);
// Have a prefix list
atts = mp_inclNSNode->getAttributes();
safeBuffer inSB;
if (atts == 0 || ((att = atts->getNamedItem(MAKE_UNICODE_STRING("PrefixList"))) == NULL)) {
throw XSECException(XSECException::ExpectedDSIGChildNotFound,
"Expected PrefixList in InclusiveNamespaces");
}
mp_inclNSStr = att->getNodeValue();
}
}
}
// --------------------------------------------------------------------------------
// Canonicalization Specific Methods
// --------------------------------------------------------------------------------
void DSIGTransformC14n::setCanonicalizationMethod(const XMLCh* uri) {
bool exclusive;
bool comments;
bool onedotone;
if (mp_txfmNode == NULL || !XSECAlgorithmSupport::evalCanonicalizationMethod(uri, exclusive, comments, onedotone)) {
throw XSECException(XSECException::TransformError,
"Either method unknown or Node not set in setCanonicalizationMethod");
}
// Switching from exclusive to inclusive?
if (!exclusive && m_exclusive) {
if (mp_inclNSNode != 0) {
mp_txfmNode->removeChild(mp_inclNSNode);
mp_inclNSNode->release(); // No longer required
mp_inclNSNode = NULL;
mp_inclNSStr = NULL;
}
}
// Now do the set.
((DOMElement *) mp_txfmNode)->setAttributeNS(NULL, DSIGConstants::s_unicodeStrAlgorithm, uri);
m_cMethod = ((DOMElement *) mp_txfmNode)->getAttributeNS(NULL, DSIGConstants::s_unicodeStrAlgorithm);
m_exclusive = exclusive;
m_comments = comments;
m_onedotone = onedotone;
}
const XMLCh* DSIGTransformC14n::getCanonicalizationMethod() const {
return m_cMethod;
}
void DSIGTransformC14n::createInclusiveNamespaceNode() {
// Creates an empty inclusiveNamespace node. Does _not_ set the prefixlist attribute
if (mp_inclNSNode != NULL)
return; // Already exists
safeBuffer str;
const XMLCh * prefix;
DOMDocument *doc = mp_env->getParentDocument();
// Use the Exclusive Canonicalisation prefix
prefix = mp_env->getECNSPrefix();
// Create the transform node
makeQName(str, prefix, "InclusiveNamespaces");
mp_inclNSNode = doc->createElementNS(DSIGConstants::s_unicodeStrURIEC, str.rawXMLChBuffer());
// Add the node to the owner element
mp_env->doPrettyPrint(mp_txfmNode);
mp_txfmNode->appendChild(mp_inclNSNode);
mp_env->doPrettyPrint(mp_txfmNode);
// Set the namespace attribute
if (prefix[0] == '\0') {
str.sbTranscodeIn("xmlns");
}
else {
str.sbTranscodeIn("xmlns:");
str.sbXMLChCat(prefix);
}
mp_inclNSNode->setAttributeNS(DSIGConstants::s_unicodeStrURIXMLNS,
str.rawXMLChBuffer(),
DSIGConstants::s_unicodeStrURIEC);
}
void DSIGTransformC14n::setInclusiveNamespaces(const XMLCh* ns) {
// Set all the namespaces at once
if (!m_exclusive) {
throw XSECException(XSECException::TransformError,
"Cannot set inclusive namespaces on non Exclusive Canonicalization");
}
if (mp_inclNSNode == NULL) {
// Create the transform node
createInclusiveNamespaceNode();
}
// Now create the prefix list
mp_inclNSNode->setAttributeNS(NULL,MAKE_UNICODE_STRING("PrefixList"), ns);
mp_inclNSStr = mp_inclNSNode->getAttributes()->getNamedItem(MAKE_UNICODE_STRING("PrefixList"))->getNodeValue();
}
void DSIGTransformC14n::addInclusiveNamespace(const char* ns) {
if (!m_exclusive) {
throw XSECException(XSECException::TransformError,
"Cannot set inclusive namespaces on non Exclusive Canonicalization");
}
if (mp_inclNSNode == NULL) {
// Create the transform node
createInclusiveNamespaceNode();
// Now create the prefix list
mp_inclNSNode->setAttributeNS(NULL,MAKE_UNICODE_STRING("PrefixList"), MAKE_UNICODE_STRING(ns));
mp_inclNSStr = mp_inclNSNode->getAttributes()->getNamedItem(MAKE_UNICODE_STRING("PrefixList"))->getNodeValue();
}
else {
// More tricky
safeBuffer str;
str << (*(mp_env->getSBFormatter()) << mp_inclNSStr);
str.sbStrcatIn(" ");
str.sbStrcatIn((char *) ns);
mp_inclNSNode->setAttributeNS(NULL,MAKE_UNICODE_STRING("PrefixList"), str.sbStrToXMLCh());
mp_inclNSStr = mp_inclNSNode->getAttributes()->getNamedItem(MAKE_UNICODE_STRING("PrefixList"))->getNodeValue();
}
}
const XMLCh* DSIGTransformC14n::getPrefixList() const {
return mp_inclNSStr;
}
void DSIGTransformC14n::clearInclusiveNamespaces() {
if (mp_inclNSNode != 0) {
mp_txfmNode->removeChild(mp_inclNSNode);
mp_inclNSNode->release(); // No longer required
mp_inclNSNode = NULL;
mp_inclNSStr = NULL;
}
}