#![allow(non_snake_case)]
#![allow(unused_variables)]
#![allow(clippy::missing_safety_doc)]
#![allow(clippy::not_unsafe_ptr_arg_deref)]
use core::ffi::c_void;
use core::ptr;
use std::os::raw::{c_char, c_int};
use crate::abi::allocator::{xmlFreeImpl, xmlMallocImpl};
use crate::abi::exports_hash::xmlDictReference;
use crate::abi::exports_string::xmlStrstr;
use crate::abi::exports_tree::xmlNodeGetBase;
use crate::abi::exports_uri::xmlBuildURI;
use crate::abi::exports_xml2::*;
use crate::abi::structs::*;
use crate::abi::types::xmlElementType::*;
use crate::abi::types::*;
use crate::xml::xpath::exports::xmlXPathNewString;
const XSLT_NAMESPACE: &[u8] = b"http://www.w3.org/1999/XSL/Transform";
const XSLT_PARSE_OPTIONS: c_int = (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4);
const XSLT_LOAD_STYLESHEET: c_int = 1;
const XSLT_FUNC_DOCUMENT: c_int = 17;
const XSLT_FUNC_EXTENSION: c_int = 22;
const XSLT_VAR_PARAM: c_int = 1 << 1;
const XSLT_SECPREF_READ_FILE: c_int = 1;
const XSLT_SECPREF_READ_NETWORK: c_int = 4;
const XSLT_MAX_NESTING: c_int = 40;
static XSLT_EXT_MARKER: [u8; 18] = *b"Extension Element\0";
pub type xsltTransformFunction = unsafe extern "C" fn(
ctxt: *mut _xsltTransformContext,
node: *mut _xmlNode,
inst: *mut _xmlNode,
comp: *mut c_void,
);
pub type xsltElemPreCompDeallocator = unsafe extern "C" fn(comp: *mut c_void);
pub type xsltPreComputeFunction = unsafe extern "C" fn(
style: *mut _xsltStylesheet,
inst: *mut _xmlNode,
function: Option<xsltTransformFunction>,
) -> *mut c_void;
#[repr(C)]
pub struct _xsltElemPreComp {
pub next: *mut _xsltElemPreComp,
pub type_: c_int, pub func: Option<xsltTransformFunction>,
pub inst: *mut _xmlNode,
pub free: Option<xsltElemPreCompDeallocator>,
}
#[repr(C)]
struct _xsltStylePreComp {
pub base: _xsltElemPreComp,
pub ver11: c_int,
pub filename: *const xmlChar,
pub has_filename: c_int,
}
#[repr(C)]
struct _xsltExtElementEntry {
pub next: *mut _xsltExtElementEntry,
pub name: *mut xmlChar,
pub URI: *mut xmlChar,
pub precomp: Option<xsltPreComputeFunction>,
pub transform: Option<xsltTransformFunction>,
}
static mut XSLT_ELEMENTS_REGISTRY: *mut _xsltExtElementEntry = ptr::null_mut();
#[repr(C)]
struct _xsltExtModuleEntry {
pub next: *mut _xsltExtModuleEntry,
pub URI: *mut xmlChar,
pub shutdownFunc: Option<unsafe extern "C" fn(*mut c_void, *const xmlChar, *mut c_void)>,
}
static mut XSLT_MODULES_REGISTRY: *mut _xsltExtModuleEntry = ptr::null_mut();
static mut XSLT_GLOBALS_INITIALIZED: c_int = 0;
unsafe fn is_xslt_elem(n: *mut _xmlNode) -> bool {
if n.is_null() || (*n).type_ != XML_ELEMENT_NODE as c_int || (*n).ns.is_null() {
return false;
}
xmlStrEqual((*(*n).ns).href, XSLT_NAMESPACE.as_ptr() as *const xmlChar) != 0
}
unsafe fn is_xslt_name(n: *mut _xmlNode, val: &[u8]) -> bool {
if n.is_null() || (*n).name.is_null() {
return false;
}
let len = libc::strlen((*n).name as *const libc::c_char) as usize;
len == val.len() && core::slice::from_raw_parts((*n).name, len) == val
}
unsafe fn is_blank_str(str: *const xmlChar) -> bool {
if str.is_null() {
return true;
}
let mut cur = str;
while *cur != 0 {
if *cur != b' ' && *cur != b'\t' && *cur != b'\n' && *cur != b'\r' {
return false;
}
cur = cur.add(1);
}
true
}
unsafe fn cbytes(p: *const u8) -> &'static [u8] {
if p.is_null() {
return b"";
}
core::ffi::CStr::from_ptr(p as *const c_char).to_bytes()
}
unsafe fn report_error(style: *mut _xsltStylesheet, inst: *mut _xmlNode, msg: &[u8]) {
let mut m = msg.to_vec();
m.push(0);
crate::xslt::errors::xsltTransformError(
ptr::null_mut(),
style,
inst,
m.as_ptr() as *const c_char,
);
}
#[allow(dead_code)]
unsafe fn xslt_free_ext_def(entry: *mut c_void) {
let _ = entry;
}
unsafe fn ext_element_lookup(
name: *const xmlChar,
uri: *const xmlChar,
) -> *mut _xsltExtElementEntry {
if name.is_null() || uri.is_null() {
return ptr::null_mut();
}
let mut cur = XSLT_ELEMENTS_REGISTRY;
while !cur.is_null() {
if !(*cur).name.is_null()
&& !(*cur).URI.is_null()
&& xmlStrEqual((*cur).name, name) != 0
&& xmlStrEqual((*cur).URI, uri) != 0
{
return cur;
}
cur = (*cur).next;
}
ptr::null_mut()
}
unsafe fn dup_str(s: *const xmlChar) -> *mut xmlChar {
if s.is_null() {
return ptr::null_mut();
}
let len = libc::strlen(s as *const libc::c_char);
let copy = xmlMallocImpl(len + 1) as *mut xmlChar;
if copy.is_null() {
return ptr::null_mut();
}
core::ptr::copy_nonoverlapping(s, copy, len);
*copy.add(len) = 0;
copy
}
unsafe fn xslt_check_read(
sec: *mut c_void,
ctxt: *mut _xsltTransformContext,
url: *const xmlChar,
) -> c_int {
if sec.is_null() {
return 1;
}
let is_network = !xmlStrstr(url, b"://\0".as_ptr() as *const xmlChar).is_null();
let option = if is_network {
XSLT_SECPREF_READ_NETWORK
} else {
XSLT_SECPREF_READ_FILE
};
let check = crate::xslt::security::xsltGetSecurityPrefs(sec, option);
if let Some(check_fn) = check {
let ret = check_fn(sec, ctxt as *mut c_void, url as *const c_char);
if ret == 0 {
if is_network {
report_error(ptr::null_mut(), ptr::null_mut(), b"Network access for ");
} else {
report_error(ptr::null_mut(), ptr::null_mut(), b"Local file read for ");
}
report_error(ptr::null_mut(), ptr::null_mut(), cbytes(url as *const u8));
report_error(ptr::null_mut(), ptr::null_mut(), b" refused\n");
return 0;
}
return ret;
}
1
}
unsafe fn xslt_doc_default_loader(
uri: *const xmlChar,
_dict: *mut c_void,
options: c_int,
ctxt: *mut c_void,
_type: c_int,
) -> *mut _xmlDoc {
let loader = crate::xslt::documents::xsltGetLoaderFunc();
if let Some(loader_fn) = loader {
let input = loader_fn(
ctxt,
ptr::null(), uri as *const c_char,
ptr::null(), 0, );
if !input.is_null() {
crate::xml::parser::helpers::free_parser_input(input);
}
}
xmlReadFile(uri as *const c_char, ptr::null(), options)
}
unsafe fn xslt_new_decimal_format(
nsUri: *const xmlChar,
name: *mut xmlChar,
) -> *mut _xsltDecimalFormat {
let self_ = xmlMallocImpl(core::mem::size_of::<_xsltDecimalFormat>()) as *mut _xsltDecimalFormat;
if !self_.is_null() {
ptr::write_bytes(
self_ as *mut u8,
0,
core::mem::size_of::<_xsltDecimalFormat>(),
);
(*self_).nsUri = nsUri;
(*self_).name = name;
(*self_).digit = xmlStrdup(b"#\0".as_ptr() as *const xmlChar);
(*self_).patternSeparator = xmlStrdup(b";\0".as_ptr() as *const xmlChar);
(*self_).decimalPoint = xmlStrdup(b".\0".as_ptr() as *const xmlChar);
(*self_).grouping = xmlStrdup(b",\0".as_ptr() as *const xmlChar);
(*self_).percent = xmlStrdup(b"%\0".as_ptr() as *const xmlChar);
(*self_).permille = xmlStrdup("\u{2030}\0".as_ptr() as *const xmlChar);
(*self_).zeroDigit = xmlStrdup(b"0\0".as_ptr() as *const xmlChar);
(*self_).minusSign = xmlStrdup(b"-\0".as_ptr() as *const xmlChar);
(*self_).infinity = xmlStrdup(b"Infinity\0".as_ptr() as *const xmlChar);
(*self_).noNumber = xmlStrdup(b"NaN\0".as_ptr() as *const xmlChar);
}
self_
}
unsafe fn xslt_new_stylesheet_internal(parent: *mut _xsltStylesheet) -> *mut _xsltStylesheet {
let ret = xmlMallocImpl(core::mem::size_of::<_xsltStylesheet>()) as *mut _xsltStylesheet;
if ret.is_null() {
report_error(
ptr::null_mut(),
ptr::null_mut(),
b"xsltNewStylesheet : malloc failed\n",
);
return ptr::null_mut();
}
ptr::write_bytes(ret as *mut u8, 0, core::mem::size_of::<_xsltStylesheet>());
(*ret).parent = parent;
(*ret).omitXmlDeclaration = -1;
(*ret).standalone = -1;
(*ret).decimalFormat = xslt_new_decimal_format(ptr::null(), ptr::null_mut());
(*ret).indent = -1;
(*ret).errors = 0;
(*ret).warnings = 0;
(*ret).exclPrefixNr = 0;
(*ret).exclPrefixMax = 0;
(*ret).exclPrefixTab = ptr::null_mut();
(*ret).extInfos = ptr::null_mut();
(*ret).extrasNr = 0;
(*ret).internalized = 1;
(*ret).literal_result = 0;
(*ret).forwards_compatible = 0;
(*ret).dict = xmlDictCreate();
if parent.is_null() {
(*ret).principal = ret;
(*ret).xpathCtxt = xmlXPathNewContext(ptr::null_mut());
if (*ret).xpathCtxt.is_null() {
report_error(
ptr::null_mut(),
ptr::null_mut(),
b"xsltNewStylesheet: xmlXPathNewContext failed\n",
);
crate::xslt::stylesheet::xsltFreeStylesheet(ret);
return ptr::null_mut();
}
if crate::xml::xpath::exports::xmlXPathContextSetCache((*ret).xpathCtxt, 1, -1, 0) == -1 {
crate::xslt::stylesheet::xsltFreeStylesheet(ret);
return ptr::null_mut();
}
} else {
(*ret).principal = (*parent).principal;
}
crate::abi::exports_xslt::xsltInit();
ret
}
#[no_mangle]
pub unsafe extern "C" fn xsltNewStylesheet() -> *mut _xsltStylesheet {
xslt_new_stylesheet_internal(ptr::null_mut())
}
#[no_mangle]
pub unsafe extern "C" fn xsltParseStylesheetProcess(
style: *mut _xsltStylesheet,
doc: *mut _xmlDoc,
) -> *mut _xsltStylesheet {
xsltInitGlobals();
if doc.is_null() {
return ptr::null_mut();
}
if style.is_null() {
return style;
}
let root = crate::xml::tree::doc_get_root_element(doc);
if root.is_null() {
report_error(
style,
doc as *mut _xmlNode,
b"xsltParseStylesheetProcess : empty stylesheet\n",
);
return ptr::null_mut();
}
let ret = crate::xslt::compiler::compile(style, doc);
if ret != 0 {
return ptr::null_mut();
}
style
}
#[no_mangle]
pub unsafe extern "C" fn xsltParseStylesheetUser(
style: *mut _xsltStylesheet,
doc: *mut _xmlDoc,
) -> c_int {
if style.is_null() || doc.is_null() {
return -1;
}
if !(*doc).dict.is_null() {
xmlDictFree((*style).dict);
(*style).dict = (*doc).dict;
xmlDictReference((*style).dict);
}
(*style).doc = doc;
if xsltParseStylesheetProcess(style, doc).is_null() {
(*style).doc = ptr::null_mut();
return -1;
}
if (*style).parent.is_null() {
crate::abi::exports_xslt_apply::xsltResolveStylesheetAttributeSet(style);
}
if (*style).errors != 0 {
(*style).doc = ptr::null_mut();
return -1;
}
0
}
#[no_mangle]
pub unsafe extern "C" fn xsltParseStylesheetImportedDoc(
doc: *mut _xmlDoc,
parentStyle: *mut _xsltStylesheet,
) -> *mut _xsltStylesheet {
if doc.is_null() {
return ptr::null_mut();
}
let retStyle = xslt_new_stylesheet_internal(parentStyle);
if retStyle.is_null() {
return ptr::null_mut();
}
if xsltParseStylesheetUser(retStyle, doc) != 0 {
crate::xslt::stylesheet::xsltFreeStylesheet(retStyle);
return ptr::null_mut();
}
retStyle
}
unsafe fn xslt_fix_imported_comp_steps(master: *mut _xsltStylesheet, style: *mut _xsltStylesheet) {
(*master).extrasNr += (*style).extrasNr;
let mut res = (*style).imports;
while !res.is_null() {
xslt_fix_imported_comp_steps(master, res);
res = (*res).next;
}
}
unsafe fn xslt_check_cycle(
style: *mut _xsltStylesheet,
cur: *mut _xmlNode,
uri: *const xmlChar,
) -> c_int {
let mut depth: c_int = 0;
let mut ancestor = style;
while !ancestor.is_null() {
depth += 1;
if depth >= XSLT_MAX_NESTING {
report_error(style, cur, b"maximum nesting depth exceeded: ");
report_error(style, cur, cbytes(uri as *const u8));
report_error(style, cur, b"\n");
return -1;
}
if !(*ancestor).doc.is_null()
&& !(*(*ancestor).doc).URL.is_null()
&& xmlStrEqual((*(*ancestor).doc).URL, uri) != 0
{
report_error(style, cur, b"recursion detected on imported URL ");
report_error(style, cur, cbytes(uri as *const u8));
report_error(style, cur, b"\n");
return -1;
}
let mut docptr = (*ancestor).includes;
while !docptr.is_null() {
depth += 1;
if depth >= XSLT_MAX_NESTING {
report_error(style, cur, b"maximum nesting depth exceeded: ");
report_error(style, cur, cbytes(uri as *const u8));
report_error(style, cur, b"\n");
return -1;
}
if !(*docptr).doc.is_null()
&& !(*(*docptr).doc).URL.is_null()
&& xmlStrEqual((*(*docptr).doc).URL, uri) != 0
{
report_error(style, cur, b"recursion detected on included URL ");
report_error(style, cur, cbytes(uri as *const u8));
report_error(style, cur, b"\n");
return -1;
}
docptr = (*docptr).includes;
}
ancestor = (*ancestor).parent;
}
0
}
#[no_mangle]
pub unsafe extern "C" fn xsltParseStylesheetImport(
style: *mut _xsltStylesheet,
cur: *mut _xmlNode,
) -> c_int {
let mut ret: c_int = -1;
let mut uriRef: *mut xmlChar = ptr::null_mut();
let mut base: *mut xmlChar = ptr::null_mut();
let mut uri: *mut xmlChar = ptr::null_mut();
if cur.is_null() || style.is_null() {
return ret;
}
uriRef = xmlGetNsProp(cur, b"href\0".as_ptr() as *const xmlChar, ptr::null());
if uriRef.is_null() {
report_error(style, cur, b"xsl:import : missing href attribute\n");
if !uriRef.is_null() {
xmlFreeImpl(uriRef as *mut c_void);
}
if !base.is_null() {
xmlFreeImpl(base as *mut c_void);
}
if !uri.is_null() {
xmlFreeImpl(uri as *mut c_void);
}
return ret;
}
base = xmlNodeGetBase((*style).doc, cur);
uri = xmlBuildURI(uriRef as *const c_char, base as *const c_char);
if uri.is_null() {
report_error(style, cur, b"xsl:import : invalid URI reference ");
report_error(style, cur, cbytes(uriRef as *const u8));
report_error(style, cur, b"\n");
if !uriRef.is_null() {
xmlFreeImpl(uriRef as *mut c_void);
}
if !base.is_null() {
xmlFreeImpl(base as *mut c_void);
}
if !uri.is_null() {
xmlFreeImpl(uri as *mut c_void);
}
return ret;
}
if xslt_check_cycle(style, cur, uri) < 0 {
if !uriRef.is_null() {
xmlFreeImpl(uriRef as *mut c_void);
}
if !base.is_null() {
xmlFreeImpl(base as *mut c_void);
}
if !uri.is_null() {
xmlFreeImpl(uri as *mut c_void);
}
return ret;
}
let sec = crate::xslt::security::xsltGetDefaultSecurityPrefs();
if !sec.is_null() {
let secres = xslt_check_read(sec, ptr::null_mut(), uri);
if secres <= 0 {
if secres == 0 {
report_error(
ptr::null_mut(),
ptr::null_mut(),
b"xsl:import: read rights for ",
);
report_error(ptr::null_mut(), ptr::null_mut(), cbytes(uri as *const u8));
report_error(ptr::null_mut(), ptr::null_mut(), b" denied\n");
}
if !uriRef.is_null() {
xmlFreeImpl(uriRef as *mut c_void);
}
if !base.is_null() {
xmlFreeImpl(base as *mut c_void);
}
if !uri.is_null() {
xmlFreeImpl(uri as *mut c_void);
}
return ret;
}
}
let import = xslt_doc_default_loader(
uri,
(*style).dict,
XSLT_PARSE_OPTIONS,
style as *mut c_void,
XSLT_LOAD_STYLESHEET,
);
if import.is_null() {
report_error(style, cur, b"xsl:import : unable to load ");
report_error(style, cur, cbytes(uri as *const u8));
report_error(style, cur, b"\n");
if !uriRef.is_null() {
xmlFreeImpl(uriRef as *mut c_void);
}
if !base.is_null() {
xmlFreeImpl(base as *mut c_void);
}
if !uri.is_null() {
xmlFreeImpl(uri as *mut c_void);
}
return ret;
}
let res = xsltParseStylesheetImportedDoc(import, style);
if !res.is_null() {
(*res).next = (*style).imports;
(*style).imports = res;
if (*style).parent.is_null() {
xslt_fix_imported_comp_steps(style, res);
}
ret = 0;
} else {
crate::xml::tree::free_doc(import);
}
if !uriRef.is_null() {
xmlFreeImpl(uriRef as *mut c_void);
}
if !base.is_null() {
xmlFreeImpl(base as *mut c_void);
}
if !uri.is_null() {
xmlFreeImpl(uri as *mut c_void);
}
ret
}
#[no_mangle]
pub unsafe extern "C" fn xsltParseStylesheetInclude(
style: *mut _xsltStylesheet,
cur: *mut _xmlNode,
) -> c_int {
let mut ret: c_int = -1;
let mut uriRef: *mut xmlChar = ptr::null_mut();
let mut base: *mut xmlChar = ptr::null_mut();
let mut uri: *mut xmlChar = ptr::null_mut();
if cur.is_null() || style.is_null() {
return ret;
}
uriRef = xmlGetNsProp(cur, b"href\0".as_ptr() as *const xmlChar, ptr::null());
if uriRef.is_null() {
report_error(style, cur, b"xsl:include : missing href attribute\n");
if !uriRef.is_null() {
xmlFreeImpl(uriRef as *mut c_void);
}
if !base.is_null() {
xmlFreeImpl(base as *mut c_void);
}
if !uri.is_null() {
xmlFreeImpl(uri as *mut c_void);
}
return ret;
}
base = xmlNodeGetBase((*style).doc, cur);
uri = xmlBuildURI(uriRef as *const c_char, base as *const c_char);
if uri.is_null() {
report_error(style, cur, b"xsl:include : invalid URI reference ");
report_error(style, cur, cbytes(uriRef as *const u8));
report_error(style, cur, b"\n");
if !uriRef.is_null() {
xmlFreeImpl(uriRef as *mut c_void);
}
if !base.is_null() {
xmlFreeImpl(base as *mut c_void);
}
if !uri.is_null() {
xmlFreeImpl(uri as *mut c_void);
}
return ret;
}
if xslt_check_cycle(style, cur, uri) < 0 {
if !uriRef.is_null() {
xmlFreeImpl(uriRef as *mut c_void);
}
if !base.is_null() {
xmlFreeImpl(base as *mut c_void);
}
if !uri.is_null() {
xmlFreeImpl(uri as *mut c_void);
}
return ret;
}
let include = xsltLoadStyleDocument(style, uri);
if include.is_null() {
report_error(style, cur, b"xsl:include : unable to load ");
report_error(style, cur, cbytes(uri as *const u8));
report_error(style, cur, b"\n");
if !uriRef.is_null() {
xmlFreeImpl(uriRef as *mut c_void);
}
if !base.is_null() {
xmlFreeImpl(base as *mut c_void);
}
if !uri.is_null() {
xmlFreeImpl(uri as *mut c_void);
}
return ret;
}
let oldDoc = (*style).doc;
(*style).doc = (*include).doc;
(*include).includes = (*style).includes;
(*style).includes = include;
let oldNopreproc = (*style).nopreproc;
(*style).nopreproc = (*include).preproc;
let result = xsltParseStylesheetProcess(style, (*include).doc);
(*style).nopreproc = oldNopreproc;
(*include).preproc = 1;
(*style).includes = (*include).includes;
(*style).doc = oldDoc;
if result.is_null() {
ret = -1;
if !uriRef.is_null() {
xmlFreeImpl(uriRef as *mut c_void);
}
if !base.is_null() {
xmlFreeImpl(base as *mut c_void);
}
if !uri.is_null() {
xmlFreeImpl(uri as *mut c_void);
}
return ret;
}
ret = 0;
if !uriRef.is_null() {
xmlFreeImpl(uriRef as *mut c_void);
}
if !base.is_null() {
xmlFreeImpl(base as *mut c_void);
}
if !uri.is_null() {
xmlFreeImpl(uri as *mut c_void);
}
return ret;
}
unsafe fn xslt_parse_content_error(style: *mut _xsltStylesheet, node: *mut _xmlNode) {
if style.is_null() || node.is_null() {
return;
}
if is_xslt_elem(node) {
report_error(
style,
node,
b"The XSLT-element is not allowed at this position.\n",
);
} else {
report_error(
style,
node,
b"The element is not allowed at this position.\n",
);
}
(*style).errors += 1;
}
#[no_mangle]
pub unsafe extern "C" fn xsltParseStylesheetOutput(
style: *mut _xsltStylesheet,
cur: *mut _xmlNode,
) {
if cur.is_null() || style.is_null() || (*cur).type_ != XML_ELEMENT_NODE as c_int {
return;
}
let mut prop = xmlGetNsProp(cur, b"version\0".as_ptr() as *const xmlChar, ptr::null());
if !prop.is_null() {
if !(*style).version.is_null() {
xmlFreeImpl((*style).version as *mut c_void);
}
(*style).version = prop;
prop = ptr::null_mut();
}
prop = xmlGetNsProp(cur, b"encoding\0".as_ptr() as *const xmlChar, ptr::null());
if !prop.is_null() {
if !(*style).encoding.is_null() {
xmlFreeImpl((*style).encoding as *mut c_void);
}
(*style).encoding = prop;
prop = ptr::null_mut();
}
prop = xmlGetNsProp(cur, b"method\0".as_ptr() as *const xmlChar, ptr::null());
if !prop.is_null() {
if !(*style).method.is_null() {
xmlFreeImpl((*style).method as *mut c_void);
}
(*style).method = ptr::null_mut();
if !(*style).methodURI.is_null() {
xmlFreeImpl((*style).methodURI as *mut c_void);
}
(*style).methodURI = ptr::null_mut();
let mut method = prop;
let uri = crate::abi::exports_xslt_avt::xsltGetQNameURI(cur, &mut method);
if method.is_null() {
if !style.is_null() {
(*style).errors += 1;
}
} else if uri.is_null() {
if xmlStrEqual(method, b"xml\0".as_ptr() as *const xmlChar) != 0
|| xmlStrEqual(method, b"html\0".as_ptr() as *const xmlChar) != 0
|| xmlStrEqual(method, b"text\0".as_ptr() as *const xmlChar) != 0
{
(*style).method = method;
} else {
report_error(style, cur, b"invalid value for method: ");
report_error(style, cur, cbytes(method as *const u8));
report_error(style, cur, b"\n");
if !style.is_null() {
(*style).warnings += 1;
}
xmlFreeImpl(method as *mut c_void);
}
} else {
(*style).method = method;
(*style).methodURI = xmlStrdup(uri);
}
prop = ptr::null_mut();
}
prop = xmlGetNsProp(
cur,
b"doctype-system\0".as_ptr() as *const xmlChar,
ptr::null(),
);
if !prop.is_null() {
if !(*style).doctypeSystem.is_null() {
xmlFreeImpl((*style).doctypeSystem as *mut c_void);
}
(*style).doctypeSystem = prop;
prop = ptr::null_mut();
}
prop = xmlGetNsProp(
cur,
b"doctype-public\0".as_ptr() as *const xmlChar,
ptr::null(),
);
if !prop.is_null() {
if !(*style).doctypePublic.is_null() {
xmlFreeImpl((*style).doctypePublic as *mut c_void);
}
(*style).doctypePublic = prop;
prop = ptr::null_mut();
}
prop = xmlGetNsProp(cur, b"standalone\0".as_ptr() as *const xmlChar, ptr::null());
if !prop.is_null() {
if xmlStrEqual(prop, b"yes\0".as_ptr() as *const xmlChar) != 0 {
(*style).standalone = 1;
} else if xmlStrEqual(prop, b"no\0".as_ptr() as *const xmlChar) != 0 {
(*style).standalone = 0;
} else {
report_error(style, cur, b"invalid value for standalone\n");
(*style).errors += 1;
}
xmlFreeImpl(prop as *mut c_void);
}
prop = xmlGetNsProp(cur, b"indent\0".as_ptr() as *const xmlChar, ptr::null());
if !prop.is_null() {
if xmlStrEqual(prop, b"yes\0".as_ptr() as *const xmlChar) != 0 {
(*style).indent = 1;
} else if xmlStrEqual(prop, b"no\0".as_ptr() as *const xmlChar) != 0 {
(*style).indent = 0;
} else {
report_error(style, cur, b"invalid value for indent\n");
(*style).errors += 1;
}
xmlFreeImpl(prop as *mut c_void);
}
prop = xmlGetNsProp(
cur,
b"omit-xml-declaration\0".as_ptr() as *const xmlChar,
ptr::null(),
);
if !prop.is_null() {
if xmlStrEqual(prop, b"yes\0".as_ptr() as *const xmlChar) != 0 {
(*style).omitXmlDeclaration = 1;
} else if xmlStrEqual(prop, b"no\0".as_ptr() as *const xmlChar) != 0 {
(*style).omitXmlDeclaration = 0;
} else {
report_error(style, cur, b"invalid value for omit-xml-declaration\n");
(*style).errors += 1;
}
xmlFreeImpl(prop as *mut c_void);
}
let elements = xmlGetNsProp(
cur,
b"cdata-section-elements\0".as_ptr() as *const xmlChar,
ptr::null(),
);
if !elements.is_null() {
if (*style).cdataSection.is_null() {
(*style).cdataSection = crate::xml::hash::hash_create(10) as *mut c_void;
}
if (*style).cdataSection.is_null() {
xmlFreeImpl(elements as *mut c_void);
return;
}
let mut element: *mut xmlChar = elements;
while *element != 0 {
while matches!(*element, b' ' | b'\t' | b'\n' | b'\r') {
element = element.add(1);
}
if *element == 0 {
break;
}
let mut end = element;
while *end != 0 && !matches!(*end, b' ' | b'\t' | b'\n' | b'\r') {
end = end.add(1);
}
let len = end.offset_from(element) as usize;
let token = xmlMallocImpl(len + 1) as *mut xmlChar;
if !token.is_null() {
core::ptr::copy_nonoverlapping(element, token, len);
*token.add(len) = 0;
if xmlValidateQName(token, 0) != 0 {
report_error(
style,
cur,
b"Attribute 'cdata-section-elements': The value is not a valid QName.\n",
);
xmlFreeImpl(token as *mut c_void);
(*style).errors += 1;
} else {
let mut qname = token;
let quri = crate::abi::exports_xslt_avt::xsltGetQNameURI(cur, &mut qname);
if qname.is_null() {
report_error(
style,
cur,
b"Attribute 'cdata-section-elements': Not a valid QName.\n",
);
(*style).errors += 1;
} else {
let mut uri = quri;
if uri.is_null() {
let ns = xmlSearchNs((*style).doc, cur, ptr::null());
if !ns.is_null() {
uri = (*ns).href;
}
}
crate::xml::hash::hash_add_entry2(
(*style).cdataSection as *mut crate::xml::hash::HashTable,
qname,
uri,
b"cdata\0".as_ptr() as *const c_void as *mut c_void,
);
xmlFreeImpl(qname as *mut c_void);
}
}
}
element = end;
}
xmlFreeImpl(elements as *mut c_void);
}
prop = xmlGetNsProp(cur, b"media-type\0".as_ptr() as *const xmlChar, ptr::null());
if !prop.is_null() {
if !(*style).mediaType.is_null() {
xmlFreeImpl((*style).mediaType as *mut c_void);
}
(*style).mediaType = prop;
prop = ptr::null_mut();
}
if !(*cur).children.is_null() {
xslt_parse_content_error(style, (*cur).children);
}
}
#[no_mangle]
pub unsafe extern "C" fn xsltParseStylesheetAttributeSet(
style: *mut _xsltStylesheet,
cur: *mut _xmlNode,
) {
if cur.is_null() || style.is_null() || (*cur).type_ != XML_ELEMENT_NODE as c_int {
return;
}
let value = xmlGetNsProp(cur, b"name\0".as_ptr() as *const xmlChar, ptr::null());
if value.is_null() || *value == 0 {
if !value.is_null() {
xmlFreeImpl(value as *mut c_void);
}
return;
}
if xmlValidateQName(value, 0) != 0 {
report_error(
style,
cur,
b"xsl:attribute-set : The name is not a valid QName.\n",
);
(*style).errors += 1;
xmlFreeImpl(value as *mut c_void);
return;
}
xmlFreeImpl(value as *mut c_void);
crate::xslt::attributes::xsltCompileAttrSet(style, cur);
}
#[no_mangle]
pub unsafe extern "C" fn xsltParseGlobalVariable(style: *mut _xsltStylesheet, cur: *mut _xmlNode) {
if cur.is_null() || style.is_null() || (*cur).type_ != XML_ELEMENT_NODE as c_int {
return;
}
let name = xmlGetNsProp(cur, b"name\0".as_ptr() as *const xmlChar, ptr::null());
if name.is_null() {
report_error(style, cur, b"xsl:variable : missing name attribute\n");
return;
}
let mut tmp = (*style).variables;
while !tmp.is_null() {
if ((*tmp).flags & XSLT_VAR_PARAM) == 0
&& !(*tmp).name.is_null()
&& xmlStrEqual((*tmp).name, name) != 0
{
report_error(style, cur, b"redefinition of global variable ");
report_error(style, cur, cbytes(name as *const u8));
report_error(style, cur, b"\n");
(*style).errors += 1;
break;
}
tmp = (*tmp).next;
}
xmlFreeImpl(name as *mut c_void);
if !(*cur).children.is_null() {
xsltParseTemplateContent(style, cur);
}
crate::xslt::compiler::compile_variable(style, cur, 0, 0);
}
#[no_mangle]
pub unsafe extern "C" fn xsltParseGlobalParam(style: *mut _xsltStylesheet, cur: *mut _xmlNode) {
if cur.is_null() || style.is_null() || (*cur).type_ != XML_ELEMENT_NODE as c_int {
return;
}
let name = xmlGetNsProp(cur, b"name\0".as_ptr() as *const xmlChar, ptr::null());
if name.is_null() {
report_error(style, cur, b"xsl:param : missing name attribute\n");
return;
}
xmlFreeImpl(name as *mut c_void);
if !(*cur).children.is_null() {
xsltParseTemplateContent(style, cur);
}
crate::xslt::compiler::compile_variable(style, cur, 0, 1);
}
#[no_mangle]
pub unsafe extern "C" fn xsltParseTemplateContent(
style: *mut _xsltStylesheet,
templ: *mut _xmlNode,
) {
if style.is_null() || templ.is_null() || (*templ).type_ == XML_NAMESPACE_DECL as c_int {
return;
}
let mut cur = (*templ).children;
while !cur.is_null() {
if !(*style).principal.is_null() {
(*(*style).principal).opCount += 1;
}
if is_xslt_elem(cur) {
xsltStylePreCompute(style, cur);
} else if !(*cur).ns.is_null() && !ext_ns_registered((*(*cur).ns).href) {
} else if !(*cur).ns.is_null() && ext_ns_registered((*(*cur).ns).href) {
xsltStylePreCompute(style, cur);
} else if (*cur).type_ == XML_ELEMENT_NODE as c_int {
if (*cur).ns.is_null() && !(*style).defaultAlias.is_null() {
(*cur).ns = xmlSearchNsByHref((*cur).doc, cur, (*style).defaultAlias);
}
if !(*cur).properties.is_null() {
let mut attr = (*cur).properties;
while !attr.is_null() {
xsltCompileAttr(style, attr);
attr = (*attr).next;
}
}
}
if !(*cur).children.is_null() {
if (*(*cur).children).type_ != XML_ENTITY_DECL as c_int {
cur = (*cur).children;
continue;
}
}
if !(*cur).next.is_null() {
cur = (*cur).next;
continue;
}
loop {
cur = (*cur).parent;
if cur.is_null() {
break;
}
if cur == templ {
cur = ptr::null_mut();
break;
}
if !(*cur).next.is_null() {
cur = (*cur).next;
break;
}
}
}
let mut cur = (*templ).children;
while !cur.is_null() {
if is_xslt_elem(cur) && !is_xslt_name(cur, b"param") {
break;
}
cur = (*cur).next;
}
while !cur.is_null() {
if is_xslt_elem(cur) && is_xslt_name(cur, b"param") {
let param = cur;
report_error(
style,
cur,
b"xsltParseTemplateContent: ignoring misplaced param element\n",
);
if !style.is_null() {
(*style).warnings += 1;
}
cur = (*cur).next;
crate::xml::tree::unlink_node(param);
crate::xml::tree::free_node(param);
} else {
break;
}
}
}
unsafe fn ext_ns_registered(uri: *const xmlChar) -> bool {
if uri.is_null() {
return false;
}
let mut cur = XSLT_ELEMENTS_REGISTRY;
while !cur.is_null() {
if !(*cur).URI.is_null() && xmlStrEqual((*cur).URI, uri) != 0 {
return true;
}
cur = (*cur).next;
}
false
}
#[no_mangle]
pub unsafe extern "C" fn xsltCompileAttr(style: *mut _xsltStylesheet, attr: *mut _xmlAttr) {
if style.is_null() || attr.is_null() || (*attr).children.is_null() {
return;
}
if (*(*attr).children).type_ != XML_TEXT_NODE as c_int || !(*(*attr).children).next.is_null() {
report_error(
style,
(*attr).parent,
b"Attribute ': The content is expected to be a single text node when compiling an AVT.\n",
);
(*style).errors += 1;
return;
}
let str_ = (*(*attr).children).content;
if xmlStrchr(str_, b'{' as xmlChar).is_null() && xmlStrchr(str_, b'}' as xmlChar).is_null() {
return;
}
if !(*attr).psvi.is_null() {
return;
}
let mut cur = str_;
while *cur != 0 {
if *cur == b'{' {
if !cur.add(1).is_null() && *cur.add(1) == b'{' {
cur = cur.add(2);
continue;
}
if !cur.add(1).is_null() && *cur.add(1) == b'}' {
cur = cur.add(2);
continue;
}
let mut p = cur.add(1);
while *p != 0 && *p != b'}' {
if *p == b'\'' || *p == b'"' {
let delim = *p;
p = p.add(1);
while *p != 0 && *p != delim {
p = p.add(1);
}
if *p != 0 {
p = p.add(1);
}
} else {
p = p.add(1);
}
}
if *p == 0 {
report_error(
style,
(*attr).parent,
b"Attribute ': The AVT has an unmatched '{'.\n",
);
(*style).errors += 1;
return;
}
cur = p.add(1);
} else if *cur == b'}' {
if !cur.add(1).is_null() && *cur.add(1) == b'}' {
cur = cur.add(2);
continue;
}
report_error(
style,
(*attr).parent,
b"Attribute ': The AVT has an unmatched '}'.\n",
);
return;
} else {
cur = cur.add(1);
}
}
}
unsafe fn xslt_free_style_pre_comp(comp: *mut c_void) {
if comp.is_null() {
return;
}
xmlFreeImpl(comp);
}
unsafe extern "C" fn xslt_free_elem_pre_comp(comp: *mut c_void) {
xmlFreeImpl(comp);
}
unsafe fn xslt_new_style_pre_comp(
style: *mut _xsltStylesheet,
type_: c_int,
) -> *mut _xsltStylePreComp {
if style.is_null() {
return ptr::null_mut();
}
let cur = xmlMallocImpl(core::mem::size_of::<_xsltStylePreComp>()) as *mut _xsltStylePreComp;
if cur.is_null() {
report_error(
style,
ptr::null_mut(),
b"xsltNewStylePreComp : malloc failed\n",
);
(*style).errors += 1;
return ptr::null_mut();
}
ptr::write_bytes(cur as *mut u8, 0, core::mem::size_of::<_xsltStylePreComp>());
(*cur).base.type_ = type_;
(*cur).base.next = (*style).preComps as *mut _xsltElemPreComp;
(*style).preComps = cur as *mut c_void;
cur
}
#[no_mangle]
pub unsafe extern "C" fn xsltDocumentComp(
style: *mut _xsltStylesheet,
inst: *mut _xmlNode,
_function: Option<xsltTransformFunction>,
) -> *mut _xsltElemPreComp {
if style.is_null() || inst.is_null() || (*inst).type_ != XML_ELEMENT_NODE as c_int {
return ptr::null_mut();
}
let comp = xslt_new_style_pre_comp(style, XSLT_FUNC_DOCUMENT);
if comp.is_null() {
return ptr::null_mut();
}
(*comp).base.inst = inst;
(*comp).ver11 = 0;
let mut filename: *const xmlChar = ptr::null();
if is_xslt_name(inst, b"output") {
filename = crate::abi::exports_xslt_avt::xsltEvalStaticAttrValueTemplate(
style,
inst,
b"file\0".as_ptr() as *const xmlChar,
ptr::null(),
&mut (*comp).has_filename,
);
} else if is_xslt_name(inst, b"write") {
} else if is_xslt_name(inst, b"document") {
if !(*inst).ns.is_null() {
if xmlStrEqual(
(*(*inst).ns).href,
XSLT_NAMESPACE.as_ptr() as *const xmlChar,
) != 0
{
(*comp).ver11 = 1;
}
}
filename = crate::abi::exports_xslt_avt::xsltEvalStaticAttrValueTemplate(
style,
inst,
b"href\0".as_ptr() as *const xmlChar,
ptr::null(),
&mut (*comp).has_filename,
);
}
if (*comp).has_filename != 0 {
(*comp).filename = filename;
}
&mut (*comp).base as *mut _xsltElemPreComp
}
unsafe fn xslt_init_elem_pre_comp(
comp: *mut _xsltElemPreComp,
style: *mut _xsltStylesheet,
inst: *mut _xmlNode,
function: Option<xsltTransformFunction>,
free_func: Option<xsltElemPreCompDeallocator>,
) {
(*comp).type_ = XSLT_FUNC_EXTENSION;
(*comp).func = function;
(*comp).inst = inst;
(*comp).free = free_func;
(*comp).next = (*style).preComps as *mut _xsltElemPreComp;
(*style).preComps = comp as *mut c_void;
}
unsafe fn xslt_new_elem_pre_comp(
style: *mut _xsltStylesheet,
inst: *mut _xmlNode,
function: Option<xsltTransformFunction>,
) -> *mut _xsltElemPreComp {
let cur = xmlMallocImpl(core::mem::size_of::<_xsltElemPreComp>()) as *mut _xsltElemPreComp;
if cur.is_null() {
report_error(
style,
ptr::null_mut(),
b"xsltNewExtElement : malloc failed\n",
);
return ptr::null_mut();
}
ptr::write_bytes(cur as *mut u8, 0, core::mem::size_of::<_xsltElemPreComp>());
xslt_init_elem_pre_comp(cur, style, inst, function, Some(xslt_free_elem_pre_comp));
cur
}
#[no_mangle]
pub unsafe extern "C" fn xsltPreComputeExtModuleElement(
style: *mut _xsltStylesheet,
inst: *mut _xmlNode,
) -> *mut _xsltElemPreComp {
if style.is_null()
|| inst.is_null()
|| (*inst).type_ != XML_ELEMENT_NODE as c_int
|| (*inst).ns.is_null()
{
return ptr::null_mut();
}
let ext = ext_element_lookup((*inst).name, (*(*inst).ns).href);
if ext.is_null() {
return ptr::null_mut();
}
let mut comp: *mut _xsltElemPreComp = ptr::null_mut();
if let Some(precomp) = (*ext).precomp {
comp = precomp(style, inst, (*ext).transform) as *mut _xsltElemPreComp;
}
if comp.is_null() {
comp = xslt_new_elem_pre_comp(style, inst, (*ext).transform);
}
comp
}
#[no_mangle]
pub unsafe extern "C" fn xsltFreeStylePreComps(style: *mut _xsltStylesheet) {
if style.is_null() {
return;
}
let mut cur = (*style).preComps as *mut _xsltElemPreComp;
(*style).preComps = ptr::null_mut();
while !cur.is_null() {
let next = (*cur).next;
if (*cur).type_ == XSLT_FUNC_EXTENSION {
if let Some(free_func) = (*cur).free {
free_func(cur as *mut c_void);
} else {
xslt_free_style_pre_comp(cur as *mut c_void);
}
} else {
xslt_free_style_pre_comp(cur as *mut c_void);
}
cur = next;
}
}
#[no_mangle]
pub unsafe extern "C" fn xsltStylePreCompute(style: *mut _xsltStylesheet, inst: *mut _xmlNode) {
if inst.is_null() || (*inst).type_ != XML_ELEMENT_NODE as c_int || !(*inst).psvi.is_null() {
return;
}
if is_xslt_elem(inst) {
if is_xslt_name(inst, b"apply-templates") {
xslt_check_instruction_element(style, inst);
} else if is_xslt_name(inst, b"with-param") {
xslt_check_parent_element(style, inst, b"apply-templates", b"call-template\0".as_ptr() as *const u8);
} else if is_xslt_name(inst, b"value-of") {
xslt_check_instruction_element(style, inst);
} else if is_xslt_name(inst, b"copy") {
xslt_check_instruction_element(style, inst);
} else if is_xslt_name(inst, b"copy-of") {
xslt_check_instruction_element(style, inst);
} else if is_xslt_name(inst, b"if") {
xslt_check_instruction_element(style, inst);
} else if is_xslt_name(inst, b"when") {
xslt_check_parent_element(style, inst, b"choose", ptr::null());
} else if is_xslt_name(inst, b"choose") {
xslt_check_instruction_element(style, inst);
} else if is_xslt_name(inst, b"for-each") {
xslt_check_instruction_element(style, inst);
} else if is_xslt_name(inst, b"apply-imports") {
xslt_check_instruction_element(style, inst);
} else if is_xslt_name(inst, b"attribute") {
let parent = (*inst).parent;
let is_in_attr_set = !parent.is_null()
&& (*parent).type_ == XML_ELEMENT_NODE as c_int
&& !(*parent).ns.is_null()
&& xmlStrEqual(
(*(*parent).ns).href,
XSLT_NAMESPACE.as_ptr() as *const xmlChar,
) != 0
&& is_xslt_name(parent, b"attribute-set");
if !is_in_attr_set {
xslt_check_instruction_element(style, inst);
}
} else if is_xslt_name(inst, b"element") {
xslt_check_instruction_element(style, inst);
} else if is_xslt_name(inst, b"text") {
xslt_check_instruction_element(style, inst);
} else if is_xslt_name(inst, b"sort") {
xslt_check_parent_element(style, inst, b"apply-templates", b"for-each\0".as_ptr() as *const u8);
} else if is_xslt_name(inst, b"comment") {
xslt_check_instruction_element(style, inst);
} else if is_xslt_name(inst, b"number") {
xslt_check_instruction_element(style, inst);
} else if is_xslt_name(inst, b"processing-instruction") {
xslt_check_instruction_element(style, inst);
} else if is_xslt_name(inst, b"call-template") {
xslt_check_instruction_element(style, inst);
} else if is_xslt_name(inst, b"param") {
if xslt_check_top_level_element(style, inst, 0) == 0 {
xslt_check_instruction_element(style, inst);
}
} else if is_xslt_name(inst, b"variable") {
if xslt_check_top_level_element(style, inst, 0) == 0 {
xslt_check_instruction_element(style, inst);
}
} else if is_xslt_name(inst, b"otherwise") {
xslt_check_parent_element(style, inst, b"choose", ptr::null());
xslt_check_instruction_element(style, inst);
return;
} else if is_xslt_name(inst, b"template") {
xslt_check_top_level_element(style, inst, 1);
return;
} else if is_xslt_name(inst, b"output") {
xslt_check_top_level_element(style, inst, 1);
return;
} else if is_xslt_name(inst, b"preserve-space") {
xslt_check_top_level_element(style, inst, 1);
return;
} else if is_xslt_name(inst, b"strip-space") {
xslt_check_top_level_element(style, inst, 1);
return;
} else if is_xslt_name(inst, b"stylesheet") || is_xslt_name(inst, b"transform") {
let parent = (*inst).parent;
if parent.is_null() || (*parent).type_ != XML_DOCUMENT_NODE as c_int {
report_error(style, inst, b"element only allowed only as root element\n");
(*style).errors += 1;
}
return;
} else if is_xslt_name(inst, b"key") {
xslt_check_top_level_element(style, inst, 1);
return;
} else if is_xslt_name(inst, b"message") {
xslt_check_instruction_element(style, inst);
return;
} else if is_xslt_name(inst, b"attribute-set") {
xslt_check_top_level_element(style, inst, 1);
return;
} else if is_xslt_name(inst, b"namespace-alias") {
xslt_check_top_level_element(style, inst, 1);
return;
} else if is_xslt_name(inst, b"include") {
xslt_check_top_level_element(style, inst, 1);
return;
} else if is_xslt_name(inst, b"import") {
xslt_check_top_level_element(style, inst, 1);
return;
} else if is_xslt_name(inst, b"decimal-format") {
xslt_check_top_level_element(style, inst, 1);
return;
} else if is_xslt_name(inst, b"fallback") {
xslt_check_instruction_element(style, inst);
return;
} else if is_xslt_name(inst, b"document") {
xslt_check_instruction_element(style, inst);
(*inst).psvi = xsltDocumentComp(style, inst, None) as *mut c_void;
} else if style.is_null() || (*style).forwards_compatible == 0 {
report_error(
style,
inst,
b"xsltStylePreCompute: unknown xsl: instruction\n",
);
if !style.is_null() {
(*style).warnings += 1;
}
}
} else {
(*inst).psvi = xsltPreComputeExtModuleElement(style, inst) as *mut c_void;
if (*inst).psvi.is_null() {
(*inst).psvi = XSLT_EXT_MARKER.as_ptr() as *mut c_void;
}
}
}
unsafe fn xslt_check_top_level_element(
style: *mut _xsltStylesheet,
inst: *mut _xmlNode,
err: c_int,
) -> c_int {
if style.is_null() || inst.is_null() || (*inst).ns.is_null() {
return -1;
}
let parent = (*inst).parent;
if parent.is_null() {
if err != 0 {
report_error(style, inst, b"internal problem: element has no parent\n");
(*style).errors += 1;
}
return 0;
}
if (*parent).ns.is_null()
|| (*parent).type_ != XML_ELEMENT_NODE as c_int
|| (xmlStrEqual((*(*parent).ns).href, (*(*inst).ns).href) == 0)
|| (!is_xslt_name(parent, b"stylesheet") && !is_xslt_name(parent, b"transform"))
{
if err != 0 {
report_error(
style,
inst,
b"element only allowed as child of stylesheet\n",
);
(*style).errors += 1;
}
return 0;
}
1
}
unsafe fn xslt_check_instruction_element(style: *mut _xsltStylesheet, inst: *mut _xmlNode) {
if style.is_null() || inst.is_null() || (*inst).ns.is_null() || (*style).literal_result != 0 {
return;
}
let has_ext = !(*style).extInfos.is_null() || !ext_ns_registered(ptr::null());
let mut parent = (*inst).parent;
if parent.is_null() {
report_error(style, inst, b"internal problem: element has no parent\n");
(*style).errors += 1;
return;
}
while !parent.is_null() && (*parent).type_ != XML_DOCUMENT_NODE as c_int {
if ((*parent).ns == (*inst).ns
|| (!(*parent).ns.is_null()
&& xmlStrEqual((*(*parent).ns).href, (*(*inst).ns).href) != 0))
&& (is_xslt_name(parent, b"template")
|| is_xslt_name(parent, b"param")
|| is_xslt_name(parent, b"attribute")
|| is_xslt_name(parent, b"variable"))
{
return;
}
if has_ext && !(*parent).ns.is_null() && ext_ns_registered((*(*parent).ns).href) {
return;
}
parent = (*parent).parent;
}
report_error(
style,
inst,
b"element only allowed within a template, variable or param\n",
);
(*style).errors += 1;
}
unsafe fn xslt_check_parent_element(
style: *mut _xsltStylesheet,
inst: *mut _xmlNode,
allow1: &[u8],
allow2: *const u8,
) {
if style.is_null() || inst.is_null() || (*inst).ns.is_null() || (*style).literal_result != 0 {
return;
}
let parent = (*inst).parent;
if parent.is_null() {
report_error(style, inst, b"internal problem: element has no parent\n");
(*style).errors += 1;
return;
}
let allow2_bytes: &[u8] = if allow2.is_null() {
b""
} else {
core::slice::from_raw_parts(allow2, libc::strlen(allow2 as *const libc::c_char) as usize)
};
if ((*parent).ns == (*inst).ns
|| (!(*parent).ns.is_null() && xmlStrEqual((*(*parent).ns).href, (*(*inst).ns).href) != 0))
&& (is_xslt_name(parent, allow1)
|| (!allow2_bytes.is_empty() && is_xslt_name(parent, allow2_bytes)))
{
return;
}
if !ext_ns_registered(ptr::null()) {
let mut p = parent;
while !p.is_null() && (*p).type_ != XML_DOCUMENT_NODE as c_int {
if !(*p).ns.is_null() && ext_ns_registered((*(*p).ns).href) {
return;
}
p = (*p).parent;
}
}
report_error(style, inst, b"element is not allowed within that context\n");
(*style).errors += 1;
}
#[no_mangle]
pub unsafe extern "C" fn xsltNormalizeCompSteps(
payload: *mut c_void,
data: *mut c_void,
_name: *const xmlChar,
) {
let _ = (payload, data);
}
#[no_mangle]
pub unsafe extern "C" fn xsltNewStyleDocument(
style: *mut _xsltStylesheet,
doc: *mut _xmlDoc,
) -> *mut _xsltDocument {
let cur = xmlMallocImpl(core::mem::size_of::<_xsltDocument>()) as *mut _xsltDocument;
if cur.is_null() {
report_error(
style,
doc as *mut _xmlNode,
b"xsltNewStyleDocument : malloc failed\n",
);
return ptr::null_mut();
}
ptr::write_bytes(cur as *mut u8, 0, core::mem::size_of::<_xsltDocument>());
(*cur).doc = doc;
if !style.is_null() {
(*cur).next = (*style).docList;
(*style).docList = cur;
}
cur
}
#[no_mangle]
pub unsafe extern "C" fn xsltLoadStyleDocument(
style: *mut _xsltStylesheet,
uri: *const xmlChar,
) -> *mut _xsltDocument {
if style.is_null() || uri.is_null() {
return ptr::null_mut();
}
let sec = crate::xslt::security::xsltGetDefaultSecurityPrefs();
if !sec.is_null() {
let res = xslt_check_read(sec, ptr::null_mut(), uri);
if res <= 0 {
if res == 0 {
report_error(
ptr::null_mut(),
ptr::null_mut(),
b"xsltLoadStyleDocument: read rights for ",
);
report_error(ptr::null_mut(), ptr::null_mut(), cbytes(uri as *const u8));
report_error(ptr::null_mut(), ptr::null_mut(), b" denied\n");
}
return ptr::null_mut();
}
}
let mut ret = (*style).docList;
while !ret.is_null() {
if !(*ret).doc.is_null()
&& !(*(*ret).doc).URL.is_null()
&& xmlStrEqual((*(*ret).doc).URL, uri) != 0
{
return ret;
}
ret = (*ret).next;
}
let doc = xslt_doc_default_loader(
uri,
(*style).dict,
XSLT_PARSE_OPTIONS,
style as *mut c_void,
XSLT_LOAD_STYLESHEET,
);
if doc.is_null() {
return ptr::null_mut();
}
let ret = xsltNewStyleDocument(style, doc);
if ret.is_null() {
crate::xml::tree::free_doc(doc);
}
ret
}
#[no_mangle]
pub unsafe extern "C" fn xsltFreeStyleDocuments(style: *mut _xsltStylesheet) {
if style.is_null() {
return;
}
let mut cur = (*style).docList;
(*style).docList = ptr::null_mut();
while !cur.is_null() {
let doc = cur;
cur = (*cur).next;
if (*doc).main == 0 && !(*doc).doc.is_null() {
crate::xml::tree::free_doc((*doc).doc);
}
xmlFreeImpl(doc as *mut c_void);
}
}
#[no_mangle]
pub unsafe extern "C" fn xsltInitGlobals() {
if XSLT_GLOBALS_INITIALIZED == 0 {
XSLT_GLOBALS_INITIALIZED = 1;
}
}
#[no_mangle]
pub unsafe extern "C" fn xsltUninit() {
XSLT_GLOBALS_INITIALIZED = 0;
}
#[no_mangle]
pub unsafe extern "C" fn xsltFreeExts(style: *mut _xsltStylesheet) {
if style.is_null() {
return;
}
}
#[no_mangle]
pub unsafe extern "C" fn xsltShutdownExts(style: *mut _xsltStylesheet) {
if style.is_null() {
return;
}
if (*style).extInfos.is_null() {
return;
}
crate::xml::hash::hash_free((*style).extInfos as *mut crate::xml::hash::HashTable, None);
(*style).extInfos = ptr::null_mut();
}
#[no_mangle]
pub unsafe extern "C" fn xsltDebugDumpExtensions(output: *mut libc::FILE) {
let out = if output.is_null() {
libc::fdopen(1, b"w\0".as_ptr() as *const c_char)
} else {
output
};
if out.is_null() {
return;
}
libc::fprintf(
out,
b"Registered XSLT Extensions\n--------------------------\n\0".as_ptr() as *const c_char,
);
libc::fprintf(
out,
b"No registered extension functions\n\0".as_ptr() as *const c_char,
);
libc::fprintf(
out,
b"\nNo registered top-level extension elements\n\0".as_ptr() as *const c_char,
);
if XSLT_ELEMENTS_REGISTRY.is_null() {
libc::fprintf(
out,
b"\nNo registered instruction extension elements\n\0".as_ptr() as *const c_char,
);
} else {
libc::fprintf(
out,
b"\nRegistered instruction extension elements:\n\0".as_ptr() as *const c_char,
);
let mut cur = XSLT_ELEMENTS_REGISTRY;
while !cur.is_null() {
if !(*cur).URI.is_null() && !(*cur).name.is_null() {
libc::fprintf(
out,
b"{%s}%s\n\0".as_ptr() as *const c_char,
(*cur).URI as *const c_char,
(*cur).name as *const c_char,
);
}
cur = (*cur).next;
}
}
if XSLT_MODULES_REGISTRY.is_null() {
libc::fprintf(
out,
b"\nNo registered extension modules\n\0".as_ptr() as *const c_char,
);
} else {
libc::fprintf(
out,
b"\nRegistered extension modules:\n\0".as_ptr() as *const c_char,
);
let mut cur = XSLT_MODULES_REGISTRY;
while !cur.is_null() {
if !(*cur).URI.is_null() {
libc::fprintf(
out,
b"%s\n\0".as_ptr() as *const c_char,
(*cur).URI as *const c_char,
);
}
cur = (*cur).next;
}
}
}