blob: 1f5eff4be2a886c6f67d50609777269049257541 [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.
*/
/*
* $Id$
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <cstdio>
#include <xercesc/util/OutOfMemoryException.hpp>
#include <xercesc/util/XMLUTF8Transcoder.hpp>
#include <xercesc/framework/XMLBuffer.hpp>
#include <xercesc/validators/datatype/AnyURIDatatypeValidator.hpp>
#include <xercesc/validators/datatype/InvalidDatatypeFacetException.hpp>
#include <xercesc/validators/datatype/InvalidDatatypeValueException.hpp>
XERCES_CPP_NAMESPACE_BEGIN
// ---------------------------------------------------------------------------
// Constructors and Destructor
// ---------------------------------------------------------------------------
AnyURIDatatypeValidator::AnyURIDatatypeValidator(MemoryManager* const manager)
:AbstractStringValidator(0, 0, 0, DatatypeValidator::AnyURI, manager)
{}
AnyURIDatatypeValidator::~AnyURIDatatypeValidator()
{
}
AnyURIDatatypeValidator::AnyURIDatatypeValidator(
DatatypeValidator* const baseValidator
, RefHashTableOf<KVStringPair>* const facets
, RefArrayVectorOf<XMLCh>* const enums
, const int finalSet
, MemoryManager* const manager)
:AbstractStringValidator(baseValidator, facets, finalSet, DatatypeValidator::AnyURI, manager)
{
init(enums, manager);
}
DatatypeValidator* AnyURIDatatypeValidator::newInstance(
RefHashTableOf<KVStringPair>* const facets
, RefArrayVectorOf<XMLCh>* const enums
, const int finalSet
, MemoryManager* const manager)
{
return (DatatypeValidator*) new (manager) AnyURIDatatypeValidator(this, facets, enums, finalSet, manager);
}
// ---------------------------------------------------------------------------
// Utilities
// ---------------------------------------------------------------------------
void AnyURIDatatypeValidator::checkValueSpace(const XMLCh* const content
, MemoryManager* const manager)
{
bool validURI = true;
// check 3.2.17.c0 must: URI (rfc 2396/2723)
try
{
// Support for relative URLs
// According to Java 1.1: URLs may also be specified with a
// String and the URL object that it is related to.
//
XMLSize_t len = XMLString::stringLen(content);
if (len)
{
// Encode special characters using XLink 5.4 algorithm
XMLBuffer encoded((len*3)+1, manager);
encode(content, len, encoded, manager);
validURI = XMLUri::isValidURI(true, encoded.getRawBuffer(), true);
}
}
catch(const OutOfMemoryException&)
{
throw;
}
catch (...)
{
ThrowXMLwithMemMgr1(InvalidDatatypeValueException
, XMLExcepts::VALUE_URI_Malformed
, content
, manager);
}
if (!validURI) {
ThrowXMLwithMemMgr1(InvalidDatatypeValueException
, XMLExcepts::VALUE_URI_Malformed
, content
, manager);
}
}
/***
* To encode special characters in anyURI, by using %HH to represent
* special ASCII characters: 0x00~0x1F, 0x7F, ' ', '<', '>', etc.
* and non-ASCII characters (whose value >= 128).
***/
void AnyURIDatatypeValidator::encode(const XMLCh* const content, const XMLSize_t len, XMLBuffer& encoded, MemoryManager* const manager)
{
static const bool needEscapeMap[] = {
true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , /* 0x00 to 0x0F need escape */
true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , /* 0x10 to 0x1F need escape */
true , false, true , false, false, false, false, false, false, false, false, false, false, false, false, false, /* 0x20:' ', 0x22:'"' */
false, false, false, false, false, false, false, false, false, false, false, false, true , false, true , false, /* 0x3C:'<', 0x3E:'>' */
false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false, false, true , false, true , false, /* 0x5C:'\\', 0x5E:'^' */
true , false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, /* 0x60:'`' */
false, false, false, false, false, false, false, false, false, false, false, true , true , true , true , true /* 0x7B:'{', 0x7C:'|', 0x7D:'}', 0x7E:'~', 0x7F:DEL */
};
// For each character in content
XMLSize_t i;
for (i = 0; i < len; i++)
{
int ch = (int)content[i];
// If it's not an ASCII character, break here, and use UTF-8 encoding
if (ch >= 128)
break;
if (needEscapeMap[ch])
{
char tempStr[3] = "\0";
sprintf(tempStr, "%02X", ch);
encoded.append('%');
encoded.append((XMLCh)tempStr[0]);
encoded.append((XMLCh)tempStr[1]);
}
else
{
encoded.append((XMLCh)ch);
}
}
// we saw some non-ascii character
if (i < len) {
// get UTF-8 bytes for the remaining sub-string
const XMLCh* remContent = (XMLCh*)&content[i];
const XMLSize_t remContentLen = len - i;
XMLByte* UTF8Byte = (XMLByte*)manager->allocate((remContentLen*4+1) * sizeof(XMLByte));
XMLSize_t charsEaten;
XMLUTF8Transcoder transcoder(XMLUni::fgUTF8EncodingString, remContentLen*4+1, manager);
XMLSize_t utf8Len = transcoder.transcodeTo(remContent, remContentLen, UTF8Byte, remContentLen*4, charsEaten, XMLTranscoder::UnRep_RepChar);
assert(charsEaten == remContentLen);
XMLSize_t j;
for (j = 0; j < utf8Len; j++) {
XMLByte b = UTF8Byte[j];
if (b >= 128 || needEscapeMap[b])
{
char tempStr[3] = "\0";
sprintf(tempStr, "%02X", b);
encoded.append('%');
encoded.append((XMLCh)tempStr[0]);
encoded.append((XMLCh)tempStr[1]);
}
else
{
encoded.append((XMLCh)b);
}
}
manager->deallocate(UTF8Byte);
}
}
/***
* Support for Serialization/De-serialization
***/
IMPL_XSERIALIZABLE_TOCREATE(AnyURIDatatypeValidator)
void AnyURIDatatypeValidator::serialize(XSerializeEngine& serEng)
{
AbstractStringValidator::serialize(serEng);
}
XERCES_CPP_NAMESPACE_END
/**
* End of file AnyURIDatatypeValidator.cpp
*/