#![allow(non_snake_case)]
#![allow(unused_variables)]
#![allow(clippy::missing_safety_doc)]
#![allow(clippy::not_unsafe_ptr_arg_deref)]
#![allow(clippy::comparison_chain)]
#![allow(unused_assignments)]
use core::ffi::c_void;
use core::ptr;
use std::os::raw::{c_char, c_int};
use crate::abi::allocator::*;
use crate::abi::exports_hash::xmlDictOwns;
use crate::abi::exports_tree::{xmlNewDocProp, xmlNewNsProp, xmlNewTextLen};
use crate::abi::exports_treedump::xmlNodeListGetString;
use crate::abi::exports_xml2::*;
use crate::abi::structs::*;
use crate::abi::types::xmlElementType::*;
use crate::abi::types::*;
const XSLT_NAMESPACE: &[u8] = b"http://www.w3.org/1999/XSL/Transform\0";
const XSLT_OUTPUT_XML: c_int = 0;
const UNDEFINED_DEFAULT_NS: *const xmlChar = -1isize as *const xmlChar;
const UNDEFINED_DEFAULT_NS_MARKER: &[u8] = &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
unsafe fn alloc_str(bytes: &[u8]) -> *mut xmlChar {
let p = xmlMalloc(bytes.len() + 1) as *mut xmlChar;
if p.is_null() {
return ptr::null_mut();
}
ptr::copy_nonoverlapping(bytes.as_ptr(), p, bytes.len());
*p.add(bytes.len()) = 0;
p
}
unsafe fn ns_uri_is_undefined(uri: *const xmlChar) -> bool {
if uri == UNDEFINED_DEFAULT_NS {
return true;
}
if uri.is_null() {
return false;
}
let len = libc::strlen(uri as *const c_char);
len == UNDEFINED_DEFAULT_NS_MARKER.len() as libc::size_t
&& core::slice::from_raw_parts(uri, UNDEFINED_DEFAULT_NS_MARKER.len())
== UNDEFINED_DEFAULT_NS_MARKER
}
unsafe fn lookup_ns_alias(style: *mut _xsltStylesheet, href: *const xmlChar) -> *const xmlChar {
if style.is_null() || href.is_null() {
return ptr::null();
}
let mut cur = (*style).nsAliases as *mut _xsltNsAlias;
while !cur.is_null() {
if !(*cur).styleNs.is_null()
&& libc::strcmp((*cur).styleNs as *const c_char, href as *const c_char) == 0
{
return (*cur).resultNs;
}
cur = (*cur).next;
}
ptr::null()
}
unsafe fn xslt_next_import(cur: *mut _xsltStylesheet) -> *mut _xsltStylesheet {
if cur.is_null() {
return ptr::null_mut();
}
if !(*cur).imports.is_null() {
return (*cur).imports;
}
if !(*cur).next.is_null() {
return (*cur).next;
}
let mut c = cur;
loop {
c = (*c).parent;
if c.is_null() {
break;
}
if !(*c).next.is_null() {
return (*c).next;
}
}
c
}
unsafe fn dict_empty(dict: *mut c_void) -> *const xmlChar {
let e = xmlDictLookup(dict, b"\0".as_ptr() as *const xmlChar, 0);
if e.is_null() {
b"\0".as_ptr() as *const xmlChar
} else {
e
}
}
unsafe fn new_attr_text_node(attr: *mut _xmlAttr, content: *mut xmlChar) -> *mut _xmlNode {
let text = crate::xml::tree::new_text(ptr::null());
if text.is_null() {
return ptr::null_mut();
}
if !(*text).content.is_null() {
xmlFree((*text).content as *mut c_void);
}
(*text).content = content;
(*attr).last = text;
(*attr).children = text;
(*text).parent = attr as *mut _xmlNode;
(*text).doc = (*attr).doc;
text
}
#[no_mangle]
pub unsafe extern "C" fn xsltAttrListTemplateProcess(
ctxt: *mut _xsltTransformContext,
target: *mut _xmlNode,
attrs: *mut _xmlAttr,
) -> *mut _xmlAttr {
if ctxt.is_null() || target.is_null() || attrs.is_null() {
return ptr::null_mut();
}
if (*target).type_ != XML_ELEMENT_NODE as c_int {
return ptr::null_mut();
}
let old_insert = (*ctxt).insert;
(*ctxt).insert = target;
let mut attr = attrs;
loop {
if !(*attr).ns.is_null()
&& xmlStrEqual(
(*attr).name,
b"use-attribute-sets\0".as_ptr() as *const xmlChar,
) != 0
&& xmlStrEqual(
(*(*attr).ns).href,
XSLT_NAMESPACE.as_ptr() as *const xmlChar,
) != 0
{
let value = crate::xml::tree::node_get_content((*attr).children);
if !value.is_null() {
crate::xslt::attributes::xsltApplyAttrSets(ctxt, target, value);
xmlFree(value as *mut c_void);
}
}
attr = (*attr).next;
if attr.is_null() {
break;
}
}
let mut has_attr = 0;
if !(*target).properties.is_null() {
has_attr = 1;
}
let mut attr = attrs;
let mut last: *mut _xmlAttr = ptr::null_mut();
let mut orig_ns: *mut _xmlNs = ptr::null_mut();
let mut copy_ns: *mut _xmlNs = ptr::null_mut();
loop {
if !(*attr).ns.is_null()
&& xmlStrEqual(
(*(*attr).ns).href,
XSLT_NAMESPACE.as_ptr() as *const xmlChar,
) != 0
{
attr = (*attr).next;
if attr.is_null() {
break;
}
continue;
}
let value: *const xmlChar;
if !(*attr).children.is_null() {
if (*(*attr).children).type_ != XML_TEXT_NODE as c_int
|| !(*(*attr).children).next.is_null()
{
crate::xslt::errors::xsltTransformError(
ctxt,
ptr::null_mut(),
(*attr).parent,
b"Internal error: The children of an attribute node of a literal result element are not in the expected form.\n\0"
.as_ptr() as *const c_char,
);
(*ctxt).insert = old_insert;
return ptr::null_mut();
}
let c = (*(*attr).children).content;
if c.is_null() {
value = dict_empty((*ctxt).dict);
} else {
value = c;
}
} else {
value = dict_empty((*ctxt).dict);
}
if (*attr).ns != orig_ns {
orig_ns = (*attr).ns;
if !(*attr).ns.is_null() {
copy_ns = xsltGetNamespace(ctxt, (*attr).parent, (*attr).ns, target);
if copy_ns.is_null() {
(*ctxt).insert = old_insert;
return ptr::null_mut();
}
} else {
copy_ns = ptr::null_mut();
}
}
let copy: *mut _xmlAttr;
if has_attr != 0 {
copy = xmlSetNsProp(target, copy_ns, (*attr).name, ptr::null());
} else {
copy = xmlNewDocProp((*target).doc, (*attr).name, ptr::null());
if !copy.is_null() {
(*copy).ns = copy_ns;
(*copy).parent = target;
if last.is_null() {
(*target).properties = copy;
last = copy;
} else {
(*last).next = copy;
(*copy).prev = last;
last = copy;
}
}
}
if copy.is_null() {
crate::xslt::errors::xsltTransformError(
ctxt,
ptr::null_mut(),
(*attr).parent,
b"Internal error: Failed to create attribute.\n\0".as_ptr() as *const c_char,
);
(*ctxt).insert = old_insert;
return ptr::null_mut();
}
let text: *mut _xmlNode;
if (*attr).psvi.is_null() {
let content: *mut xmlChar;
if (*ctxt).internalized != 0
&& !(*target).doc.is_null()
&& (*(*target).doc).dict == (*ctxt).dict
&& !(*ctxt).dict.is_null()
&& xmlDictOwns((*ctxt).dict, value) != 0
{
content = value as *mut xmlChar;
} else {
content = xmlStrdup(value);
}
text = new_attr_text_node(copy, content);
} else {
let value_avt = xsltEvalAVT(ctxt, (*attr).psvi, (*attr).parent);
let content: *mut xmlChar = if value_avt.is_null() {
xmlStrdup(b"\0".as_ptr() as *const xmlChar)
} else {
value_avt
};
text = new_attr_text_node(copy, content);
}
if !text.is_null() && xmlIsID((*copy).doc, (*copy).parent, copy) != 0 {
xmlAddID(ptr::null_mut(), (*copy).doc, (*text).content, copy);
}
attr = (*attr).next;
if attr.is_null() {
break;
}
}
(*ctxt).insert = old_insert;
(*target).properties
}
#[no_mangle]
pub unsafe extern "C" fn xsltAttrTemplateProcess(
ctxt: *mut _xsltTransformContext,
target: *mut _xmlNode,
attr: *mut _xmlAttr,
) -> *mut _xmlAttr {
if ctxt.is_null() || attr.is_null() || target.is_null() {
return ptr::null_mut();
}
if (*target).type_ != XML_ELEMENT_NODE as c_int {
return ptr::null_mut();
}
if (*attr).type_ != XML_ATTRIBUTE_NODE as c_int {
return ptr::null_mut();
}
if !(*attr).ns.is_null()
&& xmlStrEqual(
(*(*attr).ns).href,
XSLT_NAMESPACE.as_ptr() as *const xmlChar,
) != 0
{
return ptr::null_mut();
}
let value: *const xmlChar;
if !(*attr).children.is_null() {
if (*(*attr).children).type_ != XML_TEXT_NODE as c_int
|| !(*(*attr).children).next.is_null()
{
crate::xslt::errors::xsltTransformError(
ctxt,
ptr::null_mut(),
(*attr).parent,
b"Internal error: The children of an attribute node of a literal result element are not in the expected form.\n\0"
.as_ptr() as *const c_char,
);
return ptr::null_mut();
}
let c = (*(*attr).children).content;
if c.is_null() {
value = dict_empty((*ctxt).dict);
} else {
value = c;
}
} else {
value = dict_empty((*ctxt).dict);
}
let mut ret = (*target).properties;
while !ret.is_null() {
let same_ns = ((*attr).ns.is_null() && (*ret).ns.is_null())
|| (!(*attr).ns.is_null() && !(*ret).ns.is_null());
if same_ns
&& xmlStrEqual((*ret).name, (*attr).name) != 0
&& ((*attr).ns.is_null() || xmlStrEqual((*(*attr).ns).href, (*(*ret).ns).href) != 0)
{
break;
}
ret = (*ret).next;
}
if !ret.is_null() {
if !(*ret).children.is_null() {
crate::xml::tree::free_node_list((*ret).children);
}
(*ret).children = ptr::null_mut();
(*ret).last = ptr::null_mut();
if !(*ret).ns.is_null() && xmlStrEqual((*(*ret).ns).prefix, (*(*attr).ns).prefix) == 0 {
(*ret).ns = xsltGetNamespace(ctxt, (*attr).parent, (*attr).ns, target);
}
} else {
if !(*attr).ns.is_null() {
ret = xmlNewNsProp(
target,
xsltGetNamespace(ctxt, (*attr).parent, (*attr).ns, target),
(*attr).name,
ptr::null(),
);
} else {
ret = xmlNewNsProp(target, ptr::null_mut(), (*attr).name, ptr::null());
}
}
if !ret.is_null() {
if (*attr).psvi.is_null() {
let content: *mut xmlChar;
if (*ctxt).internalized != 0
&& !target.is_null()
&& !(*target).doc.is_null()
&& (*(*target).doc).dict == (*ctxt).dict
&& !(*ctxt).dict.is_null()
&& xmlDictOwns((*ctxt).dict, value) != 0
{
content = value as *mut xmlChar;
} else {
content = xmlStrdup(value);
}
let text = new_attr_text_node(ret, content);
let _ = text;
} else {
let val = xsltEvalAVT(ctxt, (*attr).psvi, (*attr).parent);
let content: *mut xmlChar = if val.is_null() {
xmlStrdup(b"\0".as_ptr() as *const xmlChar)
} else {
val
};
let text = new_attr_text_node(ret, content);
let _ = text;
}
}
ret
}
#[no_mangle]
pub unsafe extern "C" fn xsltAttrTemplateValueProcessNode(
ctxt: *mut _xsltTransformContext,
str: *const xmlChar,
inst: *mut _xmlNode,
) -> *mut xmlChar {
if ctxt.is_null() {
return ptr::null_mut();
}
if str.is_null() {
return ptr::null_mut();
}
if *str == 0 {
return crate::xml::string::bytes_to_xmlstr(&[]);
}
if inst.is_null() {
return crate::xslt::transform::eval_avt(ctxt, str);
}
let saved_node = (*ctxt).node;
let saved_inst = (*ctxt).inst;
(*ctxt).node = inst;
(*ctxt).inst = inst;
let ret = crate::xslt::transform::eval_avt(ctxt, str);
(*ctxt).node = saved_node;
(*ctxt).inst = saved_inst;
ret
}
#[no_mangle]
pub unsafe extern "C" fn xsltAttrTemplateValueProcess(
ctxt: *mut _xsltTransformContext,
str: *const xmlChar,
) -> *mut xmlChar {
xsltAttrTemplateValueProcessNode(ctxt, str, ptr::null_mut())
}
#[no_mangle]
pub unsafe extern "C" fn xsltEvalAVT(
ctxt: *mut _xsltTransformContext,
avt: *mut c_void,
node: *mut _xmlNode,
) -> *mut xmlChar {
if ctxt.is_null() || avt.is_null() || node.is_null() {
return ptr::null_mut();
}
crate::xslt::transform::eval_avt(ctxt, avt as *const xmlChar)
}
#[no_mangle]
pub unsafe extern "C" fn xsltEvalAttrValueTemplate(
ctxt: *mut _xsltTransformContext,
inst: *mut _xmlNode,
name: *const xmlChar,
ns: *const xmlChar,
) -> *mut xmlChar {
if ctxt.is_null() || inst.is_null() || name.is_null() {
return ptr::null_mut();
}
if (*inst).type_ != XML_ELEMENT_NODE as c_int {
return ptr::null_mut();
}
let expr = xsltGetNsProp(inst, name, ns);
if expr.is_null() {
return ptr::null_mut();
}
let ret = xsltAttrTemplateValueProcessNode(ctxt, expr, inst);
xmlFree(expr as *mut c_void);
ret
}
#[no_mangle]
pub unsafe extern "C" fn xsltEvalStaticAttrValueTemplate(
style: *mut _xsltStylesheet,
inst: *mut _xmlNode,
name: *const xmlChar,
ns: *const xmlChar,
found: *mut c_int,
) -> *const xmlChar {
if style.is_null() || inst.is_null() || name.is_null() {
return ptr::null();
}
if (*inst).type_ != XML_ELEMENT_NODE as c_int {
return ptr::null();
}
let expr = xsltGetNsProp(inst, name, ns);
if expr.is_null() {
if !found.is_null() {
*found = 0;
}
return ptr::null();
}
if !found.is_null() {
*found = 1;
}
if !xmlStrchr(expr, b'{' as xmlChar).is_null() {
xmlFree(expr as *mut c_void);
return ptr::null();
}
let mut ret = xmlDictLookup((*style).dict, expr, -1);
if ret.is_null() {
ret = b"\0".as_ptr() as *const xmlChar;
}
xmlFree(expr as *mut c_void);
ret
}
#[no_mangle]
pub unsafe extern "C" fn xsltEvalTemplateString(
ctxt: *mut _xsltTransformContext,
contextNode: *mut _xmlNode,
inst: *mut _xmlNode,
) -> *mut xmlChar {
if ctxt.is_null() || contextNode.is_null() || inst.is_null() {
return ptr::null_mut();
}
if (*inst).type_ != XML_ELEMENT_NODE as c_int {
return ptr::null_mut();
}
if (*inst).children.is_null() {
return ptr::null_mut();
}
let insert = crate::xml::tree::new_node(ptr::null_mut(), b"fake\0".as_ptr() as *const xmlChar);
if insert.is_null() {
crate::xslt::errors::xsltTransformError(
ctxt,
ptr::null_mut(),
inst,
b"Failed to create temporary node\n\0".as_ptr() as *const c_char,
);
return ptr::null_mut();
}
(*insert).doc = (*ctxt).output;
let old_insert = (*ctxt).insert;
let old_node = (*ctxt).node;
let old_inst = (*ctxt).inst;
let old_lasttext = (*ctxt).lasttext;
let old_lasttsize = (*ctxt).lasttsize;
let old_lasttuse = (*ctxt).lasttuse;
(*ctxt).insert = insert;
(*ctxt).node = contextNode;
(*ctxt).inst = inst;
crate::xslt::transform::execute_content(ctxt, (*inst).children);
(*ctxt).insert = old_insert;
(*ctxt).node = old_node;
(*ctxt).inst = old_inst;
(*ctxt).lasttext = old_lasttext;
(*ctxt).lasttsize = old_lasttsize;
(*ctxt).lasttuse = old_lasttuse;
let ret = crate::xml::tree::node_get_content(insert);
crate::xml::tree::free_node_list(insert);
ret
}
#[no_mangle]
pub unsafe extern "C" fn xsltFreeAVTList(_avt: *mut c_void) {}
#[no_mangle]
pub unsafe extern "C" fn xsltGetCNsProp(
style: *mut _xsltStylesheet,
node: *mut _xmlNode,
name: *const xmlChar,
nameSpace: *const xmlChar,
) -> *const xmlChar {
if node.is_null() || style.is_null() || (*style).dict.is_null() {
return ptr::null();
}
if nameSpace.is_null() {
return xmlGetProp(node, name);
}
if (*node).type_ == XML_NAMESPACE_DECL as c_int {
return ptr::null();
}
let mut prop = if (*node).type_ == XML_ELEMENT_NODE as c_int {
(*node).properties
} else {
ptr::null_mut()
};
while !prop.is_null() {
let prop_ns = (*prop).ns;
let matches = (prop_ns.is_null()
&& !(*node).ns.is_null()
&& xmlStrEqual((*(*node).ns).href, nameSpace) != 0)
|| (!prop_ns.is_null() && xmlStrEqual((*prop_ns).href, nameSpace) != 0);
if xmlStrEqual((*prop).name, name) != 0 && matches {
let tmp = xmlNodeListGetString((*node).doc, (*prop).children, 1);
let ret;
if tmp.is_null() {
ret = dict_empty((*style).dict);
} else {
ret = xmlDictLookup((*style).dict, tmp, -1);
xmlFree(tmp as *mut c_void);
}
return ret;
}
prop = (*prop).next;
}
let doc = (*node).doc;
if !doc.is_null() {
if !(*doc).intSubset.is_null() {
let mut attr_decl = xmlGetDtdAttrDesc((*doc).intSubset, (*node).name, name);
if attr_decl.is_null() && !(*doc).extSubset.is_null() {
attr_decl = xmlGetDtdAttrDesc((*doc).extSubset, (*node).name, name);
}
if !attr_decl.is_null() && !(*attr_decl).prefix.is_null() {
let ns = xmlSearchNs(doc, node, (*attr_decl).prefix);
if !ns.is_null() && xmlStrEqual((*ns).href, nameSpace) != 0 {
return xmlDictLookup((*style).dict, (*attr_decl).defaultValue, -1);
}
}
}
}
ptr::null()
}
#[no_mangle]
pub unsafe extern "C" fn xsltGetNsProp(
node: *mut _xmlNode,
name: *const xmlChar,
nameSpace: *const xmlChar,
) -> *mut xmlChar {
if node.is_null() {
return ptr::null_mut();
}
if nameSpace.is_null() {
return xmlGetProp(node, name);
}
if (*node).type_ == XML_NAMESPACE_DECL as c_int {
return ptr::null_mut();
}
let mut prop = if (*node).type_ == XML_ELEMENT_NODE as c_int {
(*node).properties
} else {
ptr::null_mut()
};
while !prop.is_null() {
let prop_ns = (*prop).ns;
let matches = (prop_ns.is_null()
&& !(*node).ns.is_null()
&& xmlStrEqual((*(*node).ns).href, nameSpace) != 0)
|| (!prop_ns.is_null() && xmlStrEqual((*prop_ns).href, nameSpace) != 0);
if xmlStrEqual((*prop).name, name) != 0 && matches {
let ret = xmlNodeListGetString((*node).doc, (*prop).children, 1);
if ret.is_null() {
return xmlStrdup(b"\0".as_ptr() as *const xmlChar);
}
return ret;
}
prop = (*prop).next;
}
let doc = (*node).doc;
if !doc.is_null() {
if !(*doc).intSubset.is_null() {
let mut attr_decl = xmlGetDtdAttrDesc((*doc).intSubset, (*node).name, name);
if attr_decl.is_null() && !(*doc).extSubset.is_null() {
attr_decl = xmlGetDtdAttrDesc((*doc).extSubset, (*node).name, name);
}
if !attr_decl.is_null() && !(*attr_decl).prefix.is_null() {
let ns = xmlSearchNs(doc, node, (*attr_decl).prefix);
if !ns.is_null() && xmlStrEqual((*ns).href, nameSpace) != 0 {
return xmlStrdup((*attr_decl).defaultValue);
}
}
}
}
ptr::null_mut()
}
#[no_mangle]
pub unsafe extern "C" fn xsltGetNamespace(
ctxt: *mut _xsltTransformContext,
cur: *mut _xmlNode,
ns: *mut _xmlNs,
out: *mut _xmlNode,
) -> *mut _xmlNs {
if ns.is_null() {
return ptr::null_mut();
}
if ctxt.is_null() || cur.is_null() || out.is_null() {
return ptr::null_mut();
}
let mut style = (*ctxt).style;
let mut uri: *const xmlChar = ptr::null();
while !style.is_null() {
if !(*ns).href.is_null() && !(*style).nsAliases.is_null() {
uri = lookup_ns_alias(style, (*ns).href);
}
if !uri.is_null() {
break;
}
style = xslt_next_import(style);
}
if ns_uri_is_undefined(uri) {
return xsltGetSpecialNamespace(ctxt, cur, ptr::null(), ptr::null(), out);
}
if uri.is_null() {
uri = (*ns).href;
}
xsltGetSpecialNamespace(ctxt, cur, uri, (*ns).prefix, out)
}
#[no_mangle]
pub unsafe extern "C" fn xsltGetPlainNamespace(
ctxt: *mut _xsltTransformContext,
cur: *mut _xmlNode,
ns: *mut _xmlNs,
out: *mut _xmlNode,
) -> *mut _xmlNs {
xsltGetNamespace(ctxt, cur, ns, out)
}
#[no_mangle]
pub unsafe extern "C" fn xsltGetSpecialNamespace(
ctxt: *mut _xsltTransformContext,
invocNode: *mut _xmlNode,
nsName: *const xmlChar,
nsPrefix: *const xmlChar,
target: *mut _xmlNode,
) -> *mut _xmlNs {
if ctxt.is_null() || target.is_null() {
return ptr::null_mut();
}
if (*target).type_ != XML_ELEMENT_NODE as c_int {
return ptr::null_mut();
}
if nsPrefix.is_null() && (nsName.is_null() || *nsName == 0) {
if !(*target).nsDef.is_null() {
let mut ns = (*target).nsDef;
loop {
if (*ns).prefix.is_null() {
if !(*ns).href.is_null() && *(*ns).href != 0 {
crate::xslt::errors::xsltTransformError(
ctxt,
ptr::null_mut(),
invocNode,
b"Namespace normalization error: Cannot undeclare the default namespace, since the default namespace is already declared on the result element.\n\0"
.as_ptr() as *const c_char,
);
return ptr::null_mut();
} else {
return ptr::null_mut();
}
}
ns = (*ns).next;
if ns.is_null() {
break;
}
}
}
if !(*target).parent.is_null() && (*(*target).parent).type_ == XML_ELEMENT_NODE as c_int {
if (*(*target).parent).ns.is_null() {
return ptr::null_mut();
}
let ns = xmlSearchNs((*target).doc, (*target).parent, ptr::null());
if ns.is_null() || (*ns).href.is_null() || *(*ns).href == 0 {
return ptr::null_mut();
}
xmlNewNs(target, b"\0".as_ptr() as *const xmlChar, ptr::null());
return ptr::null_mut();
}
return ptr::null_mut();
}
if !nsPrefix.is_null() {
let plen = libc::strlen(nsPrefix as *const c_char);
if plen == 3 && core::slice::from_raw_parts(nsPrefix, 3) == b"xml" {
return xmlSearchNs((*target).doc, target, nsPrefix);
}
}
let mut prefix_occupied = 0;
let mut ns: *mut _xmlNs = ptr::null_mut();
if !(*target).nsDef.is_null() {
ns = (*target).nsDef;
loop {
let ns_prefix = (*ns).prefix;
if (ns_prefix.is_null()) == (nsPrefix.is_null()) {
if ns_prefix == nsPrefix {
if xmlStrEqual((*ns).href, nsName) != 0 {
return ns;
}
prefix_occupied = 1;
break;
} else if xmlStrEqual(ns_prefix, nsPrefix) != 0 {
if xmlStrEqual((*ns).href, nsName) != 0 {
return ns;
}
prefix_occupied = 1;
break;
}
}
ns = (*ns).next;
if ns.is_null() {
break;
}
}
}
if prefix_occupied != 0 {
ns = xmlSearchNsByHref((*target).doc, target, nsName);
if !ns.is_null() {
return ns;
}
} else if !(*target).parent.is_null() && (*(*target).parent).type_ == XML_ELEMENT_NODE as c_int
{
let parent_ns = (*(*target).parent).ns;
if !parent_ns.is_null() && ((*parent_ns).prefix.is_null()) == (nsPrefix.is_null()) {
if nsPrefix.is_null() {
if xmlStrEqual((*parent_ns).href, nsName) != 0 {
return parent_ns;
}
} else if xmlStrEqual((*parent_ns).prefix, nsPrefix) != 0
&& xmlStrEqual((*parent_ns).href, nsName) != 0
{
return parent_ns;
}
}
ns = xmlSearchNs((*target).doc, (*target).parent, nsPrefix);
if !ns.is_null() {
if xmlStrEqual((*ns).href, nsName) != 0 {
return ns;
}
if !(*target).properties.is_null() {
let mut attr = (*target).properties;
loop {
if !(*attr).ns.is_null() && xmlStrEqual((*(*attr).ns).prefix, nsPrefix) != 0 {
ns = xmlSearchNsByHref((*target).doc, target, nsName);
if !ns.is_null() {
return ns;
}
return xslt_declare_new_prefix(ctxt, invocNode, nsName, nsPrefix, target);
}
attr = (*attr).next;
if attr.is_null() {
break;
}
}
}
}
ns = xmlNewNs(target, nsName, nsPrefix);
return ns;
} else {
ns = xmlNewNs(target, nsName, nsPrefix);
return ns;
}
xslt_declare_new_prefix(ctxt, invocNode, nsName, nsPrefix, target)
}
unsafe fn xslt_declare_new_prefix(
ctxt: *mut _xsltTransformContext,
invocNode: *mut _xmlNode,
nsName: *const xmlChar,
nsPrefix: *const xmlChar,
target: *mut _xmlNode,
) -> *mut _xmlNs {
let base: *const xmlChar = if nsPrefix.is_null() {
b"ns\0".as_ptr() as *const xmlChar
} else {
nsPrefix
};
let base_str = String::from_utf8_lossy(core::slice::from_raw_parts(
base,
libc::strlen(base as *const c_char) as usize,
))
.into_owned();
let mut counter: c_int = 1;
loop {
let pref = format!("{}_{}", base_str, counter);
counter += 1;
let pref_c = crate::xml::string::bytes_to_xmlstr(pref.as_bytes());
if pref_c.is_null() {
return ptr::null_mut();
}
let ns = xmlSearchNs((*target).doc, target, pref_c);
xmlFree(pref_c as *mut c_void);
if counter > 1000 {
crate::xslt::errors::xsltTransformError(
ctxt,
ptr::null_mut(),
invocNode,
b"Internal error in xsltAcquireResultInScopeNs(): Failed to compute a unique ns-prefix for the generated element\0"
.as_ptr() as *const c_char,
);
return ptr::null_mut();
}
if ns.is_null() {
let pref_c = crate::xml::string::bytes_to_xmlstr(pref.as_bytes());
return xmlNewNs(target, nsName, pref_c);
}
}
}
#[no_mangle]
pub unsafe extern "C" fn xsltCopyNamespace(
_ctxt: *mut _xsltTransformContext,
elem: *mut _xmlNode,
ns: *mut _xmlNs,
) -> *mut _xmlNs {
if ns.is_null() || (*ns).type_ != XML_NAMESPACE_DECL as c_int {
return ptr::null_mut();
}
if !elem.is_null() && (*elem).type_ != XML_ELEMENT_NODE as c_int {
return xmlNewNs(ptr::null_mut(), (*ns).href, (*ns).prefix);
}
xmlNewNs(elem, (*ns).href, (*ns).prefix)
}
#[no_mangle]
pub unsafe extern "C" fn xsltCopyNamespaceList(
ctxt: *mut _xsltTransformContext,
node: *mut _xmlNode,
cur: *mut _xmlNs,
) -> *mut _xmlNs {
if cur.is_null() {
return ptr::null_mut();
}
if (*cur).type_ != XML_NAMESPACE_DECL as c_int {
return ptr::null_mut();
}
let mut node = node;
if !node.is_null() && (*node).type_ != XML_ELEMENT_NODE as c_int {
node = ptr::null_mut();
}
let mut ret: *mut _xmlNs = ptr::null_mut();
let mut p: *mut _xmlNs = ptr::null_mut();
let mut cur = cur;
while !cur.is_null() {
if (*cur).type_ != XML_NAMESPACE_DECL as c_int {
break;
}
if !node.is_null() {
if !(*node).ns.is_null()
&& xmlStrEqual((*(*node).ns).prefix, (*cur).prefix) != 0
&& xmlStrEqual((*(*node).ns).href, (*cur).href) != 0
{
cur = (*cur).next;
continue;
}
let tmp = xmlSearchNs((*node).doc, node, (*cur).prefix);
if !tmp.is_null() && xmlStrEqual((*tmp).href, (*cur).href) != 0 {
cur = (*cur).next;
continue;
}
}
if xmlStrEqual((*cur).href, XSLT_NAMESPACE.as_ptr() as *const xmlChar) == 0 {
let style = if ctxt.is_null() {
ptr::null_mut()
} else {
(*ctxt).style
};
let uri = if !style.is_null() {
lookup_ns_alias(style, (*cur).href)
} else {
ptr::null()
};
if ns_uri_is_undefined(uri) {
cur = (*cur).next;
continue;
}
let q: *mut _xmlNs = if !uri.is_null() {
xmlNewNs(node, uri, (*cur).prefix)
} else {
xmlNewNs(node, (*cur).href, (*cur).prefix)
};
if p.is_null() {
ret = q;
p = q;
} else {
(*p).next = q;
p = q;
}
}
cur = (*cur).next;
}
ret
}
#[no_mangle]
pub unsafe extern "C" fn xsltNamespaceAlias(style: *mut _xsltStylesheet, node: *mut _xmlNode) {
if style.is_null() || node.is_null() {
return;
}
let style_prefix = xmlGetProp(node, b"stylesheet-prefix\0".as_ptr() as *const xmlChar);
if style_prefix.is_null() {
crate::xslt::errors::xsltTransformError(
ptr::null_mut(),
style,
node,
b"namespace-alias: stylesheet-prefix attribute missing\n\0".as_ptr() as *const c_char,
);
return;
}
let result_prefix = xmlGetProp(node, b"result-prefix\0".as_ptr() as *const xmlChar);
if result_prefix.is_null() {
crate::xslt::errors::xsltTransformError(
ptr::null_mut(),
style,
node,
b"namespace-alias: result-prefix attribute missing\n\0".as_ptr() as *const c_char,
);
xmlFree(style_prefix as *mut c_void);
return;
}
let literal_ns: *mut _xmlNs;
let literal_ns_name: *const xmlChar;
if xmlStrEqual(style_prefix, b"#default\0".as_ptr() as *const xmlChar) != 0 {
literal_ns = xmlSearchNs((*node).doc, node, ptr::null());
if literal_ns.is_null() {
literal_ns_name = ptr::null();
} else {
literal_ns_name = (*literal_ns).href;
}
} else {
literal_ns = xmlSearchNs((*node).doc, node, style_prefix);
if literal_ns.is_null() || (*literal_ns).href.is_null() {
crate::xslt::errors::xsltTransformError(
ptr::null_mut(),
style,
node,
b"namespace-alias: prefix not bound to any namespace\n\0".as_ptr() as *const c_char,
);
xmlFree(style_prefix as *mut c_void);
xmlFree(result_prefix as *mut c_void);
return;
}
literal_ns_name = (*literal_ns).href;
}
let target_ns: *mut _xmlNs;
let target_ns_name: *const xmlChar;
if xmlStrEqual(result_prefix, b"#default\0".as_ptr() as *const xmlChar) != 0 {
target_ns = xmlSearchNs((*node).doc, node, ptr::null());
if target_ns.is_null() {
target_ns_name = UNDEFINED_DEFAULT_NS;
} else {
target_ns_name = (*target_ns).href;
}
} else {
target_ns = xmlSearchNs((*node).doc, node, result_prefix);
if target_ns.is_null() || (*target_ns).href.is_null() {
crate::xslt::errors::xsltTransformError(
ptr::null_mut(),
style,
node,
b"namespace-alias: prefix not bound to any namespace\n\0".as_ptr() as *const c_char,
);
xmlFree(style_prefix as *mut c_void);
xmlFree(result_prefix as *mut c_void);
return;
}
target_ns_name = (*target_ns).href;
}
if literal_ns_name.is_null() {
if !target_ns.is_null() {
(*style).defaultAlias = (*target_ns).href;
}
} else {
let result_stored: *const xmlChar = if ns_uri_is_undefined(target_ns_name) {
alloc_str(UNDEFINED_DEFAULT_NS_MARKER)
} else {
alloc_str(core::slice::from_raw_parts(
target_ns_name,
libc::strlen(target_ns_name as *const c_char) as usize,
))
};
let style_stored = alloc_str(core::slice::from_raw_parts(
literal_ns_name,
libc::strlen(literal_ns_name as *const c_char) as usize,
));
if result_stored.is_null() || style_stored.is_null() {
if !result_stored.is_null() {
xmlFree(result_stored as *mut c_void);
}
if !style_stored.is_null() {
xmlFree(style_stored as *mut c_void);
}
} else {
let alias = libc::calloc(1, core::mem::size_of::<_xsltNsAlias>()) as *mut _xsltNsAlias;
if alias.is_null() {
xmlFree(result_stored as *mut c_void);
xmlFree(style_stored as *mut c_void);
} else {
(*alias).styleNs = style_stored;
(*alias).resultNs = result_stored;
(*alias).next = (*style).nsAliases as *mut _xsltNsAlias;
(*style).nsAliases = alias as *mut c_void;
}
}
}
xmlFree(style_prefix as *mut c_void);
xmlFree(result_prefix as *mut c_void);
}
#[no_mangle]
pub unsafe extern "C" fn xsltFreeNamespaceAliasHashes(style: *mut _xsltStylesheet) {
if style.is_null() {
return;
}
crate::xslt::namespace_alias::xsltFreeNsAliases(style);
}
#[no_mangle]
pub unsafe extern "C" fn xsltCopyTextString(
ctxt: *mut _xsltTransformContext,
target: *mut _xmlNode,
string: *const xmlChar,
noescape: c_int,
) -> *mut _xmlNode {
if string.is_null() {
return ptr::null_mut();
}
if ctxt.is_null() {
return ptr::null_mut();
}
if target.is_null() || (*target).children.is_null() {
(*ctxt).lasttext = ptr::null();
}
let len = xmlStrlen(string);
let cdata_section = (*ctxt).type_ == XSLT_OUTPUT_XML
&& !(*ctxt).style.is_null()
&& !(*(*ctxt).style).cdataSection.is_null()
&& !target.is_null()
&& (*target).type_ == XML_ELEMENT_NODE as c_int
&& (((*target).ns.is_null()
&& !xmlHashLookup2((*(*ctxt).style).cdataSection, (*target).name, ptr::null())
.is_null())
|| (!(*target).ns.is_null()
&& !xmlHashLookup2(
(*(*ctxt).style).cdataSection,
(*target).name,
(*(*target).ns).href,
)
.is_null()));
let copy: *mut _xmlNode;
if cdata_section {
if !target.is_null()
&& !(*target).last.is_null()
&& (*(*target).last).type_ == XML_CDATA_SECTION_NODE as c_int
{
return xslt_add_text_string(ctxt, (*target).last, string, len);
}
copy = xmlNewCDataBlock((*ctxt).output, string, len);
} else if noescape != 0 {
if !target.is_null()
&& !(*target).last.is_null()
&& (*(*target).last).type_ == XML_TEXT_NODE as c_int
&& node_name_eq((*(*target).last).name, b"textnoenc")
{
return xslt_add_text_string(ctxt, (*target).last, string, len);
}
copy = xmlNewTextLen(string, len);
if !copy.is_null() {
let name = alloc_str(b"textnoenc");
if !name.is_null() {
xmlFree((*copy).name as *mut c_void);
(*copy).name = name;
}
}
} else {
if !target.is_null()
&& !(*target).last.is_null()
&& (*(*target).last).type_ == XML_TEXT_NODE as c_int
&& node_name_eq((*(*target).last).name, b"text")
{
return xslt_add_text_string(ctxt, (*target).last, string, len);
}
copy = xmlNewTextLen(string, len);
}
let copy = if !copy.is_null() && !target.is_null() {
xmlAddChild(target, copy)
} else {
copy
};
if !copy.is_null() {
(*ctxt).lasttext = (*copy).content;
(*ctxt).lasttsize = len;
(*ctxt).lasttuse = len;
} else {
crate::xslt::errors::xsltTransformError(
ctxt,
ptr::null_mut(),
target,
b"xsltCopyTextString: text copy failed\n\0".as_ptr() as *const c_char,
);
(*ctxt).lasttext = ptr::null();
}
copy
}
unsafe fn node_name_eq(s: *const xmlChar, b: &[u8]) -> bool {
if s.is_null() {
return false;
}
let len = libc::strlen(s as *const c_char) as usize;
len == b.len() && core::slice::from_raw_parts(s, len) == b
}
unsafe fn xslt_add_text_string(
ctxt: *mut _xsltTransformContext,
target: *mut _xmlNode,
string: *const xmlChar,
len: c_int,
) -> *mut _xmlNode {
if len <= 0 || string.is_null() || target.is_null() {
return target;
}
if ctxt.is_null() {
crate::xml::tree::text_concat(target, string, len);
return target;
}
if (*ctxt).lasttext == (*target).content {
if len >= c_int::MAX - (*ctxt).lasttuse {
crate::xslt::errors::xsltTransformError(
ctxt,
ptr::null_mut(),
target,
b"xsltCopyText: text allocation failed\n\0".as_ptr() as *const c_char,
);
return ptr::null_mut();
}
let min_size = (*ctxt).lasttuse + len + 1;
if (*ctxt).lasttsize < min_size {
let extra = if min_size < 100 { 100 } else { min_size };
let size = if extra > c_int::MAX - (*ctxt).lasttsize {
c_int::MAX
} else {
(*ctxt).lasttsize + extra
};
let newbuf =
xmlRealloc((*target).content as *mut c_void, size as usize) as *mut xmlChar;
if newbuf.is_null() {
crate::xslt::errors::xsltTransformError(
ctxt,
ptr::null_mut(),
target,
b"xsltCopyText: text allocation failed\n\0".as_ptr() as *const c_char,
);
return ptr::null_mut();
}
(*ctxt).lasttsize = size;
(*ctxt).lasttext = newbuf;
(*target).content = newbuf;
}
libc::memcpy(
(*target).content.add((*ctxt).lasttuse as usize) as *mut libc::c_void,
string as *const libc::c_void,
len as usize,
);
(*ctxt).lasttuse += len;
*(*target).content.add((*ctxt).lasttuse as usize) = 0;
} else {
crate::xml::tree::text_concat(target, string, len);
(*ctxt).lasttext = (*target).content;
let l = xmlStrlen((*target).content);
(*ctxt).lasttsize = l;
(*ctxt).lasttuse = l;
}
target
}
#[no_mangle]
pub unsafe extern "C" fn xsltIsBlank(str: *mut xmlChar) -> c_int {
if str.is_null() {
return 1;
}
let mut cur = str;
while *cur != 0 {
if *cur != b' ' && *cur != b'\t' && *cur != b'\n' && *cur != b'\r' {
return 0;
}
cur = cur.add(1);
}
1
}
#[no_mangle]
pub unsafe extern "C" fn xsltSplitQName(
dict: *mut c_void,
name: *const xmlChar,
prefix: *mut *const xmlChar,
) -> *const xmlChar {
if !prefix.is_null() {
*prefix = ptr::null();
}
if name.is_null() || dict.is_null() {
return ptr::null();
}
if *name == b':' as xmlChar {
return xmlDictLookup(dict, name, -1);
}
let mut len: usize = 0;
while *name.add(len) != 0 && *name.add(len) != b':' as xmlChar {
len += 1;
}
if *name.add(len) == 0 {
return xmlDictLookup(dict, name, -1);
}
if !prefix.is_null() {
*prefix = xmlDictLookup(dict, name, len as c_int);
}
xmlDictLookup(dict, name.add(len + 1), -1)
}
#[no_mangle]
pub unsafe extern "C" fn xsltGetQNameURI(
node: *mut _xmlNode,
name: *mut *mut xmlChar,
) -> *const xmlChar {
if name.is_null() {
return ptr::null();
}
let qname = *name;
if qname.is_null() || *qname == 0 {
return ptr::null();
}
if node.is_null() {
xmlFree(qname as *mut c_void);
*name = ptr::null_mut();
return ptr::null();
}
if *qname == b':' as xmlChar {
return ptr::null();
}
let qlen = libc::strlen(qname as *const c_char) as usize;
let mut len: usize = 0;
while len < qlen && *qname.add(len) != b':' as xmlChar {
len += 1;
}
if len == qlen {
return ptr::null();
}
if len >= 4 && core::slice::from_raw_parts(qname, 4) == b"xml:" {
if qlen == 4 {
return ptr::null();
}
*name = xmlStrdup(qname.add(4));
xmlFree(qname as *mut c_void);
return crate::abi::constants::XML_XML_NAMESPACE.as_ptr() as *const xmlChar;
}
*qname.add(len) = 0;
let ns = xmlSearchNs((*node).doc, node, qname);
if ns.is_null() {
*name = ptr::null_mut();
xmlFree(qname as *mut c_void);
return ptr::null();
}
*name = xmlStrdup(qname.add(len + 1));
xmlFree(qname as *mut c_void);
(*ns).href
}
#[no_mangle]
pub unsafe extern "C" fn xsltGetQNameURI2(
style: *mut _xsltStylesheet,
node: *mut _xmlNode,
name: *mut *const xmlChar,
) -> *const xmlChar {
if name.is_null() {
return ptr::null();
}
let qname = *name;
if qname.is_null() || *qname == 0 {
return ptr::null();
}
if node.is_null() {
*name = ptr::null();
return ptr::null();
}
let qlen = libc::strlen(qname as *const c_char) as usize;
let mut len: usize = 0;
while len < qlen && *qname.add(len) != b':' as xmlChar {
len += 1;
}
if len == qlen {
return ptr::null();
}
if len >= 4 && core::slice::from_raw_parts(qname, 4) == b"xml:" {
if qlen == 4 {
return ptr::null();
}
if !style.is_null() {
*name = xmlDictLookup((*style).dict, qname.add(4), -1);
} else {
*name = ptr::null();
}
return crate::abi::constants::XML_XML_NAMESPACE.as_ptr() as *const xmlChar;
}
let qname_prefix = xmlStrndup(qname, len as c_int);
let ns = xmlSearchNs((*node).doc, node, qname_prefix);
if ns.is_null() {
if !style.is_null() {
crate::xslt::errors::xsltTransformError(
ptr::null_mut(),
style,
node,
b"No namespace bound to prefix.\n\0".as_ptr() as *const c_char,
);
(*style).errors += 1;
}
*name = ptr::null();
if !qname_prefix.is_null() {
xmlFree(qname_prefix as *mut c_void);
}
return ptr::null();
}
if !style.is_null() {
*name = xmlDictLookup((*style).dict, qname.add(len + 1), -1);
} else {
*name = ptr::null();
}
if !qname_prefix.is_null() {
xmlFree(qname_prefix as *mut c_void);
}
(*ns).href
}
#[no_mangle]
pub unsafe extern "C" fn xsltGetUTF8Char(utf: *const u8, len: *mut c_int) -> c_int {
let mut c: u32;
if utf.is_null() {
return error_utf8(len);
}
if len.is_null() {
return error_utf8(len);
}
if *len < 1 {
return error_utf8(len);
}
c = *utf as u32;
if c & 0x80 != 0 {
if *len < 2 {
return error_utf8(len);
}
if *utf.add(1) & 0xc0 != 0x80 {
return error_utf8(len);
}
if c & 0xe0 == 0xe0 {
if *len < 3 {
return error_utf8(len);
}
if *utf.add(2) & 0xc0 != 0x80 {
return error_utf8(len);
}
if c & 0xf0 == 0xf0 {
if *len < 4 {
return error_utf8(len);
}
if c & 0xf8 != 0xf0 || *utf.add(3) & 0xc0 != 0x80 {
return error_utf8(len);
}
*len = 4;
c = ((*utf & 0x7) as u32) << 18;
c |= ((*utf.add(1) & 0x3f) as u32) << 12;
c |= ((*utf.add(2) & 0x3f) as u32) << 6;
c |= (*utf.add(3) & 0x3f) as u32;
} else {
*len = 3;
c = ((*utf & 0xf) as u32) << 12;
c |= ((*utf.add(1) & 0x3f) as u32) << 6;
c |= (*utf.add(2) & 0x3f) as u32;
}
} else {
*len = 2;
c = ((*utf & 0x1f) as u32) << 6;
c |= (*utf.add(1) & 0x3f) as u32;
}
} else {
*len = 1;
}
c as c_int
}
unsafe fn error_utf8(len: *mut c_int) -> c_int {
if !len.is_null() {
*len = 0;
}
-1
}
#[cfg(test)]
mod tests {
use super::*;
use crate::xml::string::xml_strdup;
use crate::xml::tree::*;
fn cstr(s: &[u8]) -> *const xmlChar {
let mut v = s.to_vec();
v.push(0);
let leaked: &'static [u8] = Box::leak(v.into_boxed_slice());
leaked.as_ptr() as *const xmlChar
}
fn cstr_mut(s: &[u8]) -> *mut xmlChar {
cstr(s) as *mut xmlChar
}
fn free_str(s: *mut xmlChar) {
if !s.is_null() {
unsafe { xmlFree(s as *mut c_void) };
}
}
unsafe fn make_ctxt(doc: *mut _xmlDoc, node: *mut _xmlNode) -> *mut _xsltTransformContext {
let ctxt = libc::calloc(1, core::mem::size_of::<_xsltTransformContext>())
as *mut _xsltTransformContext;
assert!(!ctxt.is_null());
(*ctxt).xpathCtxt = xmlXPathNewContext(doc);
assert!(!(*ctxt).xpathCtxt.is_null());
(*ctxt).node = node;
if !doc.is_null() {
let docu = libc::calloc(1, core::mem::size_of::<_xsltDocument>()) as *mut _xsltDocument;
(*docu).doc = doc;
(*docu).main = 1;
(*ctxt).document = docu;
}
ctxt
}
unsafe fn free_ctxt(ctxt: *mut _xsltTransformContext) {
if !(*ctxt).document.is_null() {
(*(*ctxt).document).doc = ptr::null_mut();
libc::free((*ctxt).document as *mut libc::c_void);
}
if !(*ctxt).xpathCtxt.is_null() {
xmlXPathFreeContext((*ctxt).xpathCtxt);
}
libc::free(ctxt as *mut libc::c_void);
}
#[test]
fn test_is_blank() {
unsafe {
assert_eq!(xsltIsBlank(ptr::null_mut()), 1);
assert_eq!(xsltIsBlank(cstr_mut(b"")), 1);
assert_eq!(xsltIsBlank(cstr_mut(b" \t\r\n ")), 1);
assert_eq!(xsltIsBlank(cstr_mut(b" a")), 0);
}
}
#[test]
fn test_get_utf8_char() {
unsafe {
let mut len: c_int = 1;
assert_eq!(xsltGetUTF8Char(b"A".as_ptr(), &mut len), 0x41);
assert_eq!(len, 1);
let two = [0xC3u8, 0xA9];
len = 2;
assert_eq!(xsltGetUTF8Char(two.as_ptr(), &mut len), 0xE9);
assert_eq!(len, 2);
let three = [0xE2u8, 0x82, 0xAC];
len = 3;
assert_eq!(xsltGetUTF8Char(three.as_ptr(), &mut len), 0x20AC);
assert_eq!(len, 3);
let four = [0xF0u8, 0x9F, 0x98, 0x80];
len = 4;
assert_eq!(xsltGetUTF8Char(four.as_ptr(), &mut len), 0x1F600);
assert_eq!(len, 4);
let bad = [0xC3u8];
len = 1;
assert_eq!(xsltGetUTF8Char(bad.as_ptr(), &mut len), -1);
assert_eq!(len, 0);
let bad2 = [0xC3u8, 0x41];
len = 2;
assert_eq!(xsltGetUTF8Char(bad2.as_ptr(), &mut len), -1);
assert_eq!(len, 0);
assert_eq!(xsltGetUTF8Char(ptr::null(), ptr::null_mut()), -1);
}
}
#[test]
fn test_split_qname() {
unsafe {
let dict = xmlDictCreate();
assert!(!dict.is_null());
let mut prefix: *const xmlChar = ptr::null();
let local = xsltSplitQName(dict, cstr(b"p:local"), &mut prefix);
assert!(!local.is_null());
assert!(!prefix.is_null());
assert_eq!(
libc::strcmp(local as *const c_char, b"local\0".as_ptr() as *const c_char),
0
);
assert_eq!(
libc::strcmp(prefix as *const c_char, b"p\0".as_ptr() as *const c_char),
0
);
prefix = cstr(b"x");
let local2 = xsltSplitQName(dict, cstr(b"plain"), &mut prefix);
assert!(!local2.is_null());
assert!(prefix.is_null());
assert!(xsltSplitQName(dict, ptr::null(), &mut prefix).is_null());
assert!(xsltSplitQName(ptr::null_mut(), cstr(b"a:b"), &mut prefix).is_null());
xmlDictFree(dict);
}
}
#[test]
fn test_attr_template_value_process() {
unsafe {
let doc = new_doc(ptr::null());
let root = new_node(ptr::null_mut(), cstr(b"root"));
add_child(doc as *mut _xmlNode, root);
let item = new_node(ptr::null_mut(), cstr(b"item"));
add_child(root, item);
set_prop(item, cstr(b"n"), cstr(b"7"));
let ctxt = make_ctxt(doc, item);
let r1 = xsltAttrTemplateValueProcess(ctxt, cstr(b"hello"));
assert!(!r1.is_null());
assert_eq!(
libc::strcmp(r1 as *const c_char, b"hello\0".as_ptr() as *const c_char),
0
);
free_str(r1);
let r2 = xsltAttrTemplateValueProcess(ctxt, cstr(b"item-{@n}"));
assert!(!r2.is_null());
assert_eq!(
libc::strcmp(r2 as *const c_char, b"item-7\0".as_ptr() as *const c_char),
0
);
free_str(r2);
let r3 = xsltAttrTemplateValueProcess(ctxt, cstr(b"{{x}}y}}z"));
assert!(!r3.is_null());
assert_eq!(
libc::strcmp(r3 as *const c_char, b"{x}y}z\0".as_ptr() as *const c_char),
0
);
free_str(r3);
let r4 = xsltAttrTemplateValueProcess(ctxt, cstr(b""));
assert!(!r4.is_null());
assert_eq!(*r4, 0);
free_str(r4);
assert!(xsltAttrTemplateValueProcess(ctxt, ptr::null()).is_null());
free_ctxt(ctxt);
free_doc(doc);
}
}
#[test]
fn test_get_ns_prop() {
unsafe {
let doc = new_doc(ptr::null());
let root = new_node(ptr::null_mut(), cstr(b"root"));
add_child(doc as *mut _xmlNode, root);
let ns = new_ns(root, cstr(b"urn:test"), cstr(b"t"));
(*root).ns = ns;
set_ns_prop(root, ns, cstr(b"attr"), cstr(b"v"));
let v = xsltGetNsProp(root, cstr(b"attr"), cstr(b"urn:test"));
assert!(!v.is_null());
assert_eq!(
libc::strcmp(v as *const c_char, b"v\0".as_ptr() as *const c_char),
0
);
free_str(v);
assert!(xsltGetNsProp(root, cstr(b"attr"), cstr(b"urn:other")).is_null());
let v2 = xsltGetNsProp(root, cstr(b"attr"), ptr::null());
assert!(!v2.is_null());
free_str(v2);
free_doc(doc);
}
}
#[test]
fn test_eval_static_attr_value_template() {
unsafe {
let style =
libc::calloc(1, core::mem::size_of::<_xsltStylesheet>()) as *mut _xsltStylesheet;
(*style).dict = xmlDictCreate();
let inst = new_node(ptr::null_mut(), cstr(b"elem"));
set_prop(inst, cstr(b"a"), cstr(b"static"));
set_prop(inst, cstr(b"b"), cstr(b"dyn-{x}"));
let mut found: c_int = -1;
let r1 =
xsltEvalStaticAttrValueTemplate(style, inst, cstr(b"a"), ptr::null(), &mut found);
assert_eq!(found, 1);
assert!(!r1.is_null());
assert_eq!(
libc::strcmp(r1 as *const c_char, b"static\0".as_ptr() as *const c_char),
0
);
let r2 =
xsltEvalStaticAttrValueTemplate(style, inst, cstr(b"b"), ptr::null(), &mut found);
assert_eq!(found, 1);
assert!(r2.is_null());
let r3 =
xsltEvalStaticAttrValueTemplate(style, inst, cstr(b"zzz"), ptr::null(), &mut found);
assert_eq!(found, 0);
assert!(r3.is_null());
xmlDictFree((*style).dict);
crate::xml::tree::free_node_list(inst);
libc::free(style as *mut libc::c_void);
}
}
#[test]
fn test_get_qname_uri() {
unsafe {
let doc = new_doc(ptr::null());
let root = new_node(ptr::null_mut(), cstr(b"root"));
add_child(doc as *mut _xmlNode, root);
let ns = new_ns(root, cstr(b"urn:q"), cstr(b"p"));
(*root).ns = ns;
let name = xml_strdup(cstr(b"p:local"));
let mut name_ptr = name;
let uri = xsltGetQNameURI(root, &mut name_ptr);
assert!(!uri.is_null());
assert_eq!(
libc::strcmp(uri as *const c_char, b"urn:q\0".as_ptr() as *const c_char),
0
);
free_doc(doc);
}
}
#[test]
fn test_copy_namespace_and_text() {
unsafe {
let elem = new_node(ptr::null_mut(), cstr(b"out"));
let ns = new_ns(ptr::null_mut(), cstr(b"urn:copy"), cstr(b"c"));
let copy = xsltCopyNamespace(ptr::null_mut(), elem, ns);
assert!(!copy.is_null());
assert_eq!((*copy).context as *mut _xmlNode, elem);
assert_eq!(
libc::strcmp(
(*copy).href as *const c_char,
b"urn:copy\0".as_ptr() as *const c_char
),
0
);
assert!(xsltCopyNamespace(ptr::null_mut(), elem, ptr::null_mut()).is_null());
let ctxt = libc::calloc(1, core::mem::size_of::<_xsltTransformContext>())
as *mut _xsltTransformContext;
let text = xsltCopyTextString(ctxt, elem, cstr(b"text!"), 0);
assert!(!text.is_null());
assert_eq!((*text).type_, XML_TEXT_NODE as c_int);
assert_eq!(
libc::strcmp(
(*text).content as *const c_char,
b"text!\0".as_ptr() as *const c_char
),
0
);
assert_eq!((*elem).last, text);
let noenc = xsltCopyTextString(ctxt, elem, cstr(b"<raw>"), 1);
assert!(!noenc.is_null());
assert!(node_name_eq((*noenc).name, b"textnoenc"));
assert_eq!(
libc::strcmp(
(*noenc).content as *const c_char,
b"<raw>\0".as_ptr() as *const c_char
),
0
);
assert!(xsltCopyTextString(ctxt, elem, ptr::null(), 0).is_null());
libc::free(ctxt as *mut libc::c_void);
crate::xml::tree::free_node_list(elem);
crate::xml::tree::free_node(ns as *mut _xmlNode);
}
}
}