-/*
- * Copyright 2001-2007 Internet2
+/**
+ * Licensed to the University Corporation for Advanced Internet
+ * Development, Inc. (UCAID) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
*
- * Licensed 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
+ * UCAID 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
+ * 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.
+ * 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.
*/
/**
* ddf.cpp
- *
+ *
* C++ DDF abstraction for interpretive RPC
*/
#include <xercesc/util/XMLUniDefs.hpp>
#include <xmltooling/XMLToolingConfig.h>
#include <xmltooling/util/ParserPool.h>
+#include <xmltooling/util/URLEncoder.h>
#include <xmltooling/util/XMLHelper.h>
using namespace shibsp;
char* ddf_strdup(const char* s)
{
- return (s && *s) ? strdup(s) : NULL;
+ return (s && *s) ? strdup(s) : nullptr;
}
#define MAX_NAME_LEN 255
The name buffer is returned from the function. */
char* ddf_token(const char** path, char* name)
{
- const char* temp=NULL;
-
- *name='\0';
- if (*path==NULL || **path=='\0')
+ *name=0;
+ if (*path==nullptr || **path==0)
return name;
- temp=strchr(*path,'.');
- if (temp==NULL)
- {
- strcpy(name,*path);
- *path=NULL;
+ const char* temp=strchr(*path,'.');
+ if (temp==nullptr) {
+ strncpy(name,*path,MAX_NAME_LEN);
+ name[MAX_NAME_LEN]=0;
+ *path=nullptr;
}
- else if (temp>*path)
- {
+ else if (temp>*path) {
strncpy(name,*path,temp-*path);
- name[temp-*path]='\0';
+ name[temp-*path]=0;
*path=temp+1;
}
else
// body implementation
struct shibsp::ddf_body_t {
- ddf_body_t() : name(NULL), parent(NULL), next(NULL), prev(NULL), type(DDF_EMPTY) {}
+ ddf_body_t() : name(nullptr), parent(nullptr), next(nullptr), prev(nullptr), type(DDF_EMPTY) {}
char* name; // name of node
ddf_body_t* parent; // parent node, if any
DDF_FLOAT,
DDF_STRUCT,
DDF_LIST,
- DDF_POINTER
+ DDF_POINTER,
+ DDF_STRING_UNSAFE
} type; // data type of node
union {
// library implementation
+DDF::DDF() : m_handle(nullptr)
+{
+}
+
DDF::DDF(const char* n)
{
m_handle=new(nothrow) ddf_body_t;
name(n);
}
-DDF::DDF(const char* n, const char* val)
+DDF::DDF(const char* n, const char* val, bool safe)
{
m_handle=new(nothrow) ddf_body_t;
name(n);
- string(val);
+ string(const_cast<char*>(val), true, safe);
}
DDF::DDF(const char* n, long val)
DDF& DDF::destroy()
{
- remove().empty().name(NULL);
+ remove().empty().name(nullptr);
delete m_handle;
- m_handle=NULL;
+ m_handle=nullptr;
return *this;
}
DDF DDF::copy() const
{
- if (m_handle==NULL)
+ if (m_handle==nullptr)
return DDF();
switch (m_handle->type) {
case ddf_body_t::DDF_EMPTY:
return DDF(m_handle->name);
case ddf_body_t::DDF_STRING:
- return DDF(m_handle->name,m_handle->value.string);
+ case ddf_body_t::DDF_STRING_UNSAFE:
+ return DDF(m_handle->name,m_handle->value.string,(m_handle->type==ddf_body_t::DDF_STRING));
case ddf_body_t::DDF_INT:
return DDF(m_handle->name,m_handle->value.integer);
case ddf_body_t::DDF_FLOAT:
temp.m_handle=child;
DDF temp2=temp.copy();
copy.add(temp2);
- if (copy.m_handle==NULL)
+ if (copy.m_handle==nullptr)
return copy;
if (m_handle->value.children.current==child)
copy.m_handle->value.children.current=copy.m_handle->value.children.last;
const char* DDF::name() const
{
- return (m_handle) ? m_handle->name : NULL;
+ return (m_handle) ? m_handle->name : nullptr;
}
DDF& DDF::name(const char* name)
destroy();
}
else
- m_handle->name=NULL;
+ m_handle->name=nullptr;
}
return *this;
}
bool DDF::isstring() const
{
- return m_handle ? (m_handle->type==ddf_body_t::DDF_STRING) : false;
+ return m_handle ? (m_handle->type==ddf_body_t::DDF_STRING || m_handle->type==ddf_body_t::DDF_STRING_UNSAFE) : false;
}
bool DDF::isint() const
const char* DDF::string() const
{
- return isstring() ? m_handle->value.string : NULL;
+ return isstring() ? m_handle->value.string : nullptr;
}
long DDF::integer() const
case ddf_body_t::DDF_FLOAT:
return static_cast<long>(m_handle->value.floating);
case ddf_body_t::DDF_STRING:
+ case ddf_body_t::DDF_STRING_UNSAFE:
return m_handle->value.string ? atol(m_handle->value.string) : 0;
case ddf_body_t::DDF_STRUCT:
case ddf_body_t::DDF_LIST:
case ddf_body_t::DDF_FLOAT:
return m_handle->value.floating;
case ddf_body_t::DDF_STRING:
+ case ddf_body_t::DDF_STRING_UNSAFE:
return m_handle->value.string ? atof(m_handle->value.string) : 0;
case ddf_body_t::DDF_STRUCT:
case ddf_body_t::DDF_LIST:
void* DDF::pointer() const
{
- return ispointer() ? m_handle->value.pointer : NULL;
+ return ispointer() ? m_handle->value.pointer : nullptr;
}
size_t DDF::strlen() const
bool DDF::operator==(const char* s) const
{
- if (string()==NULL || s==NULL)
- return (string()==NULL && s==NULL);
+ if (string()==nullptr || s==nullptr)
+ return (string()==nullptr && s==nullptr);
else
return (::strcmp(string(),s)==0);
}
if (m_handle) {
switch (m_handle->type) {
case ddf_body_t::DDF_STRING:
+ case ddf_body_t::DDF_STRING_UNSAFE:
if (m_handle->value.string)
free(m_handle->value.string);
break;
return *this;
}
-DDF& DDF::string(const char* val)
+DDF& DDF::string(char* val, bool copyit, bool safe)
{
if (empty().m_handle) {
- m_handle->value.string=ddf_strdup(val);
+ m_handle->value.string = copyit ? ddf_strdup(val) : val;
if (!m_handle->value.string && val && *val)
return destroy();
- m_handle->type=ddf_body_t::DDF_STRING;
+ m_handle->type=(safe ? ddf_body_t::DDF_STRING : ddf_body_t::DDF_STRING_UNSAFE);
}
return *this;
}
+DDF& DDF::string(const char* val)
+{
+ return string(const_cast<char*>(val), true);
+}
+
+DDF& DDF::unsafe_string(const char* val)
+{
+ return string(const_cast<char*>(val), true, false);
+}
+
DDF& DDF::string(long val)
{
char buf[20];
{
if (empty().m_handle) {
m_handle->type=ddf_body_t::DDF_STRUCT;
- m_handle->value.children.first=NULL;
- m_handle->value.children.last=NULL;
- m_handle->value.children.current=NULL;
+ m_handle->value.children.first=nullptr;
+ m_handle->value.children.last=nullptr;
+ m_handle->value.children.current=nullptr;
m_handle->value.children.count=0;
}
return *this;
{
if (empty().m_handle) {
m_handle->type=ddf_body_t::DDF_LIST;
- m_handle->value.children.first=NULL;
- m_handle->value.children.last=NULL;
- m_handle->value.children.current=NULL;
+ m_handle->value.children.first=nullptr;
+ m_handle->value.children.last=nullptr;
+ m_handle->value.children.current=nullptr;
m_handle->value.children.count=0;
}
return *this;
m_handle->parent->value.children.current=m_handle->prev;
m_handle->parent->value.children.count--;
- m_handle->parent=NULL;
- m_handle->next=NULL;
- m_handle->prev=NULL;
+ m_handle->parent=nullptr;
+ m_handle->next=nullptr;
+ m_handle->prev=nullptr;
return *this;
}
{
DDF p;
- p.m_handle=(m_handle ? m_handle->parent : NULL);
+ p.m_handle=(m_handle ? m_handle->parent : nullptr);
return p;
}
return p;
}
+DDF DDF::operator[](const char* path) const
+{
+ return getmember(path);
+}
+
DDF DDF::operator[](unsigned long index) const
{
DDF d;
{
char name[MAX_NAME_LEN+1];
const char* path_ptr=path;
-
+
if (m_handle && ddf_strlen(ddf_token(&path_ptr,name))>0) {
if (!isstruct())
structure();
DDF DDF::getmember(const char* path) const
{
+ DDF current;
char name[MAX_NAME_LEN+1];
const char* path_ptr=path;
- DDF current;
- if (isstruct() && ddf_strlen(ddf_token(&path_ptr,name))>0) {
- current.m_handle=m_handle->value.children.first;
- while (current.m_handle && strcmp(current.m_handle->name,name)!=0)
- current.m_handle=current.m_handle->next;
-
- if (current.m_handle && ddf_strlen(path_ptr)>0)
- current=current.getmember(path_ptr);
+ ddf_token(&path_ptr, name);
+ if (*name == 0)
+ return current;
+ else if (*name == '[') {
+ unsigned long i = strtoul(name+1, nullptr, 10);
+ if (islist() && i < m_handle->value.children.count)
+ current=operator[](i);
+ else if (i == 0)
+ current = *this;
+ }
+ else if (isstruct()) {
+ current.m_handle = m_handle->value.children.first;
+ while (current.m_handle && strcmp(current.m_handle->name,name) != 0)
+ current.m_handle = current.m_handle->next;
}
+ else if (islist()) {
+ current.m_handle = m_handle->value.children.first;
+ return current.getmember(path);
+ }
+
+ if (current.m_handle && path_ptr && *path_ptr)
+ current = current.getmember(path_ptr);
return current;
}
ddf_print_indent(f,indent);
if (m_handle) {
switch (m_handle->type) {
-
+
case ddf_body_t::DDF_EMPTY:
fprintf(f,"empty");
if (m_handle->name)
break;
case ddf_body_t::DDF_STRING:
+ case ddf_body_t::DDF_STRING_UNSAFE:
if (m_handle->name)
fprintf(f,"char* %s = ",m_handle->name);
else
putc('"',f);
}
else
- fprintf(f,"NULL");
+ fprintf(f,"nullptr");
break;
case ddf_body_t::DDF_INT:
if (m_handle->value.pointer)
fprintf(f,"%p",m_handle->value.pointer);
else
- fprintf(f,"NULL");
+ fprintf(f,"nullptr");
break;
default:
}
}
else
- fprintf(f,"NULL");
+ fprintf(f,"nullptr");
fprintf(f,";\n");
}
void xml_encode(ostream& os, const char* start)
{
+ size_t pos;
while (start && *start) {
- switch (*start) {
- case '"': os << """; break;
- case '<': os << "<"; break;
- case '>': os << ">"; break;
- case '&': os << "&"; break;
- default: os << *start;
+ pos = strcspn(start, "\"<>&");
+ if (pos > 0) {
+ os.write(start,pos);
+ start += pos;
+ }
+ else {
+ switch (*start) {
+ case '"': os << """; break;
+ case '<': os << "<"; break;
+ case '>': os << ">"; break;
+ case '&': os << "&"; break;
+ default: os << *start;
+ }
+ start++;
}
- start++;
}
}
{
if (p) {
switch (p->type) {
-
+
case ddf_body_t::DDF_STRING:
+ case ddf_body_t::DDF_STRING_UNSAFE:
os << "<string";
if (name_attr && p->name) {
os << " name=\"";
os << '"';
}
if (p->value.string) {
- os << '>';
- xml_encode(os,p->value.string);
+ if (p->type == ddf_body_t::DDF_STRING) {
+ os << '>';
+ xml_encode(os,p->value.string);
+ }
+ else {
+ os << " unsafe=\"1\">";
+ xml_encode(os,XMLToolingConfig::getConfig().getURLEncoder()->encode(p->value.string).c_str());
+ }
os << "</string>";
}
else
static const XMLCh _array[] = UNICODE_LITERAL_5(a,r,r,a,y);
static const XMLCh _struct[] = UNICODE_LITERAL_6(s,t,r,u,c,t);
static const XMLCh _lowercase[] = UNICODE_LITERAL_9(l,o,w,e,r,c,a,s,e);
+static const XMLCh _unsafe[] = UNICODE_LITERAL_6(u,n,s,a,f,e);
DDF deserialize(DOMElement* root, bool lowercase)
{
- DDF obj(NULL);
- auto_ptr_char name_val(root->getAttribute(_name));
+ DDF obj(nullptr);
+ auto_ptr_char name_val(root->getAttributeNS(nullptr, _name));
if (name_val.get() && *name_val.get()) {
if (lowercase)
for (char* pch=const_cast<char*>(name_val.get()); *pch=tolower(*pch); pch++);
}
const XMLCh* tag=root->getTagName();
- if (!XMLString::compareString(tag,_var)) {
+ if (XMLString::equals(tag,_var)) {
root=XMLHelper::getFirstChildElement(root);
tag=(root ? root->getTagName() : &chNull);
}
- if (!XMLString::compareString(tag,_string)) {
+ if (XMLString::equals(tag,_string)) {
DOMNode* child=root->getFirstChild();
if (child && child->getNodeType()==DOMNode::TEXT_NODE) {
- char* val = toUTF8(child->getNodeValue());
- if (val) {
- obj.string(val);
- delete[] val;
+ const XMLCh* unsafe = root->getAttributeNS(nullptr, _unsafe);
+ if (unsafe && *unsafe==chDigit_1) {
+ // If it's unsafe, it's not UTF-8 data, so we have to convert to ASCII and decode it.
+ char* encoded = XMLString::transcode(child->getNodeValue());
+ XMLToolingConfig::getConfig().getURLEncoder()->decode(encoded);
+ obj.string(encoded, true, false); // re-copy into free-able buffer, plus mark unsafe
+ XMLString::release(&encoded);
+ }
+ else {
+ char* val = toUTF8(child->getNodeValue(), true); // use malloc
+ obj.string(val, false); // don't re-copy the string
}
}
}
- else if (!XMLString::compareString(tag,_number)) {
+ else if (XMLString::equals(tag,_number)) {
DOMNode* child=root->getFirstChild();
if (child && child->getNodeType()==DOMNode::TEXT_NODE) {
auto_ptr_char val(child->getNodeValue());
obj.integer(val.get());
}
}
- else if (!XMLString::compareString(tag,_array)) {
+ else if (XMLString::equals(tag,_array)) {
obj.list();
DOMNodeList* children=root->getChildNodes();
for (unsigned int i=0; children && i<children->getLength(); i++)
obj.add(temp);
}
}
- else if (!XMLString::compareString(tag,_struct)) {
+ else if (XMLString::equals(tag,_struct)) {
obj.structure();
DOMNodeList* children=root->getChildNodes();
for (unsigned int i=0; children && i<children->getLength(); i++)