1#![allow(non_snake_case)]
44#![allow(unused_variables)]
45#![allow(clippy::missing_safety_doc)]
46#![allow(clippy::not_unsafe_ptr_arg_deref)]
47
48use core::ffi::c_void;
49use core::ptr;
50use std::os::raw::{c_char, c_int};
51
52use crate::abi::allocator::{xmlFreeImpl, xmlMallocImpl};
53use crate::abi::exports_hash::xmlDictReference;
54use crate::abi::exports_string::xmlStrstr;
55use crate::abi::exports_tree::xmlNodeGetBase;
56use crate::abi::exports_uri::xmlBuildURI;
57use crate::abi::exports_xml2::*;
58use crate::abi::structs::*;
59use crate::abi::types::xmlElementType::*;
60use crate::abi::types::*;
61use crate::xml::xpath::exports::xmlXPathNewString;
62
63const XSLT_NAMESPACE: &[u8] = b"http://www.w3.org/1999/XSL/Transform";
65
66const XSLT_PARSE_OPTIONS: c_int = (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4);
68
69const XSLT_LOAD_STYLESHEET: c_int = 1;
71
72const XSLT_FUNC_DOCUMENT: c_int = 17;
74const XSLT_FUNC_EXTENSION: c_int = 22;
75
76const XSLT_VAR_PARAM: c_int = 1 << 1;
79
80const XSLT_SECPREF_READ_FILE: c_int = 1;
82const XSLT_SECPREF_READ_NETWORK: c_int = 4;
83
84const XSLT_MAX_NESTING: c_int = 40;
86
87static XSLT_EXT_MARKER: [u8; 18] = *b"Extension Element\0";
96
97pub type xsltTransformFunction = unsafe extern "C" fn(
104 ctxt: *mut _xsltTransformContext,
105 node: *mut _xmlNode,
106 inst: *mut _xmlNode,
107 comp: *mut c_void,
108);
109
110pub type xsltElemPreCompDeallocator = unsafe extern "C" fn(comp: *mut c_void);
112
113pub type xsltPreComputeFunction = unsafe extern "C" fn(
116 style: *mut _xsltStylesheet,
117 inst: *mut _xmlNode,
118 function: Option<xsltTransformFunction>,
119) -> *mut c_void;
120
121#[repr(C)]
136pub struct _xsltElemPreComp {
137 pub next: *mut _xsltElemPreComp,
138 pub type_: c_int, pub func: Option<xsltTransformFunction>,
140 pub inst: *mut _xmlNode,
141 pub free: Option<xsltElemPreCompDeallocator>,
142}
143
144#[repr(C)]
152struct _xsltStylePreComp {
153 pub base: _xsltElemPreComp,
154 pub ver11: c_int,
155 pub filename: *const xmlChar,
156 pub has_filename: c_int,
157}
158
159#[repr(C)]
162struct _xsltExtElementEntry {
163 pub next: *mut _xsltExtElementEntry,
164 pub name: *mut xmlChar,
165 pub URI: *mut xmlChar,
166 pub precomp: Option<xsltPreComputeFunction>,
167 pub transform: Option<xsltTransformFunction>,
168}
169
170static mut XSLT_ELEMENTS_REGISTRY: *mut _xsltExtElementEntry = ptr::null_mut();
176
177#[repr(C)]
181struct _xsltExtModuleEntry {
182 pub next: *mut _xsltExtModuleEntry,
183 pub URI: *mut xmlChar,
184 pub shutdownFunc: Option<unsafe extern "C" fn(*mut c_void, *const xmlChar, *mut c_void)>,
185}
186
187static mut XSLT_MODULES_REGISTRY: *mut _xsltExtModuleEntry = ptr::null_mut();
188
189static mut XSLT_GLOBALS_INITIALIZED: c_int = 0;
192
193unsafe fn is_xslt_elem(n: *mut _xmlNode) -> bool {
199 if n.is_null() || (*n).type_ != XML_ELEMENT_NODE as c_int || (*n).ns.is_null() {
200 return false;
201 }
202 xmlStrEqual((*(*n).ns).href, XSLT_NAMESPACE.as_ptr() as *const xmlChar) != 0
203}
204
205unsafe fn is_xslt_name(n: *mut _xmlNode, val: &[u8]) -> bool {
207 if n.is_null() || (*n).name.is_null() {
208 return false;
209 }
210 let len = libc::strlen((*n).name as *const libc::c_char) as usize;
211 len == val.len() && core::slice::from_raw_parts((*n).name, len) == val
212}
213
214unsafe fn is_blank_str(str: *const xmlChar) -> bool {
216 if str.is_null() {
217 return true;
218 }
219 let mut cur = str;
220 while *cur != 0 {
221 if *cur != b' ' && *cur != b'\t' && *cur != b'\n' && *cur != b'\r' {
222 return false;
223 }
224 cur = cur.add(1);
225 }
226 true
227}
228
229unsafe fn cbytes(p: *const u8) -> &'static [u8] {
233 if p.is_null() {
234 return b"";
235 }
236 core::ffi::CStr::from_ptr(p as *const c_char).to_bytes()
237}
238
239unsafe fn report_error(style: *mut _xsltStylesheet, inst: *mut _xmlNode, msg: &[u8]) {
240 let mut m = msg.to_vec();
241 m.push(0);
242 crate::xslt::errors::xsltTransformError(
243 ptr::null_mut(),
244 style,
245 inst,
246 m.as_ptr() as *const c_char,
247 );
248}
249
250#[allow(dead_code)]
255unsafe fn xslt_free_ext_def(entry: *mut c_void) {
256 let _ = entry;
259}
260
261unsafe fn ext_element_lookup(
263 name: *const xmlChar,
264 uri: *const xmlChar,
265) -> *mut _xsltExtElementEntry {
266 if name.is_null() || uri.is_null() {
267 return ptr::null_mut();
268 }
269 let mut cur = XSLT_ELEMENTS_REGISTRY;
270 while !cur.is_null() {
271 if !(*cur).name.is_null()
272 && !(*cur).URI.is_null()
273 && xmlStrEqual((*cur).name, name) != 0
274 && xmlStrEqual((*cur).URI, uri) != 0
275 {
276 return cur;
277 }
278 cur = (*cur).next;
279 }
280 ptr::null_mut()
281}
282
283unsafe fn dup_str(s: *const xmlChar) -> *mut xmlChar {
285 if s.is_null() {
286 return ptr::null_mut();
287 }
288 let len = libc::strlen(s as *const libc::c_char);
289 let copy = xmlMallocImpl(len + 1) as *mut xmlChar;
290 if copy.is_null() {
291 return ptr::null_mut();
292 }
293 core::ptr::copy_nonoverlapping(s, copy, len);
294 *copy.add(len) = 0;
295 copy
296}
297
298unsafe fn xslt_check_read(
305 sec: *mut c_void,
306 ctxt: *mut _xsltTransformContext,
307 url: *const xmlChar,
308) -> c_int {
309 if sec.is_null() {
310 return 1;
311 }
312 let is_network = !xmlStrstr(url, b"://\0".as_ptr() as *const xmlChar).is_null();
313 let option = if is_network {
314 XSLT_SECPREF_READ_NETWORK
315 } else {
316 XSLT_SECPREF_READ_FILE
317 };
318 let check = crate::xslt::security::xsltGetSecurityPrefs(sec, option);
319 if let Some(check_fn) = check {
320 let ret = check_fn(sec, ctxt as *mut c_void, url as *const c_char);
321 if ret == 0 {
322 if is_network {
323 report_error(ptr::null_mut(), ptr::null_mut(), b"Network access for ");
324 } else {
325 report_error(ptr::null_mut(), ptr::null_mut(), b"Local file read for ");
326 }
327 report_error(ptr::null_mut(), ptr::null_mut(), cbytes(url as *const u8));
328 report_error(ptr::null_mut(), ptr::null_mut(), b" refused\n");
329 return 0;
330 }
331 return ret;
332 }
333 1
334}
335
336unsafe fn xslt_doc_default_loader(
342 uri: *const xmlChar,
343 _dict: *mut c_void,
344 options: c_int,
345 ctxt: *mut c_void,
346 _type: c_int,
347) -> *mut _xmlDoc {
348 let loader = crate::xslt::documents::xsltGetLoaderFunc();
349 if let Some(loader_fn) = loader {
350 let input = loader_fn(
351 ctxt,
352 ptr::null(), uri as *const c_char,
354 ptr::null(), 0, );
357 if !input.is_null() {
358 crate::xml::parser::helpers::free_parser_input(input);
359 }
360 }
361 xmlReadFile(uri as *const c_char, ptr::null(), options)
362}
363
364unsafe fn xslt_new_decimal_format(
367 nsUri: *const xmlChar,
368 name: *mut xmlChar,
369) -> *mut _xsltDecimalFormat {
370 let self_ = xmlMallocImpl(core::mem::size_of::<_xsltDecimalFormat>()) as *mut _xsltDecimalFormat;
371 if !self_.is_null() {
372 ptr::write_bytes(
373 self_ as *mut u8,
374 0,
375 core::mem::size_of::<_xsltDecimalFormat>(),
376 );
377 (*self_).nsUri = nsUri;
378 (*self_).name = name;
379 (*self_).digit = xmlStrdup(b"#\0".as_ptr() as *const xmlChar);
381 (*self_).patternSeparator = xmlStrdup(b";\0".as_ptr() as *const xmlChar);
382 (*self_).decimalPoint = xmlStrdup(b".\0".as_ptr() as *const xmlChar);
383 (*self_).grouping = xmlStrdup(b",\0".as_ptr() as *const xmlChar);
384 (*self_).percent = xmlStrdup(b"%\0".as_ptr() as *const xmlChar);
385 (*self_).permille = xmlStrdup("\u{2030}\0".as_ptr() as *const xmlChar);
386 (*self_).zeroDigit = xmlStrdup(b"0\0".as_ptr() as *const xmlChar);
387 (*self_).minusSign = xmlStrdup(b"-\0".as_ptr() as *const xmlChar);
388 (*self_).infinity = xmlStrdup(b"Infinity\0".as_ptr() as *const xmlChar);
389 (*self_).noNumber = xmlStrdup(b"NaN\0".as_ptr() as *const xmlChar);
390 }
391 self_
392}
393
394unsafe fn xslt_new_stylesheet_internal(parent: *mut _xsltStylesheet) -> *mut _xsltStylesheet {
396 let ret = xmlMallocImpl(core::mem::size_of::<_xsltStylesheet>()) as *mut _xsltStylesheet;
397 if ret.is_null() {
398 report_error(
399 ptr::null_mut(),
400 ptr::null_mut(),
401 b"xsltNewStylesheet : malloc failed\n",
402 );
403 return ptr::null_mut();
404 }
405 ptr::write_bytes(ret as *mut u8, 0, core::mem::size_of::<_xsltStylesheet>());
406
407 (*ret).parent = parent;
408 (*ret).omitXmlDeclaration = -1;
409 (*ret).standalone = -1;
410 (*ret).decimalFormat = xslt_new_decimal_format(ptr::null(), ptr::null_mut());
411 (*ret).indent = -1;
412 (*ret).errors = 0;
413 (*ret).warnings = 0;
414 (*ret).exclPrefixNr = 0;
415 (*ret).exclPrefixMax = 0;
416 (*ret).exclPrefixTab = ptr::null_mut();
417 (*ret).extInfos = ptr::null_mut();
418 (*ret).extrasNr = 0;
419 (*ret).internalized = 1;
420 (*ret).literal_result = 0;
421 (*ret).forwards_compatible = 0;
422 (*ret).dict = xmlDictCreate();
423
424 if parent.is_null() {
425 (*ret).principal = ret;
426 (*ret).xpathCtxt = xmlXPathNewContext(ptr::null_mut());
427 if (*ret).xpathCtxt.is_null() {
428 report_error(
429 ptr::null_mut(),
430 ptr::null_mut(),
431 b"xsltNewStylesheet: xmlXPathNewContext failed\n",
432 );
433 crate::xslt::stylesheet::xsltFreeStylesheet(ret);
434 return ptr::null_mut();
435 }
436 if crate::xml::xpath::exports::xmlXPathContextSetCache((*ret).xpathCtxt, 1, -1, 0) == -1 {
437 crate::xslt::stylesheet::xsltFreeStylesheet(ret);
438 return ptr::null_mut();
439 }
440 } else {
441 (*ret).principal = (*parent).principal;
442 }
443
444 crate::abi::exports_xslt::xsltInit();
448
449 ret
450}
451
452#[no_mangle]
478pub unsafe extern "C" fn xsltNewStylesheet() -> *mut _xsltStylesheet {
479 xslt_new_stylesheet_internal(ptr::null_mut())
480}
481
482#[no_mangle]
509pub unsafe extern "C" fn xsltParseStylesheetProcess(
510 style: *mut _xsltStylesheet,
511 doc: *mut _xmlDoc,
512) -> *mut _xsltStylesheet {
513 xsltInitGlobals();
514
515 if doc.is_null() {
516 return ptr::null_mut();
517 }
518 if style.is_null() {
519 return style;
520 }
521
522 let root = crate::xml::tree::doc_get_root_element(doc);
523 if root.is_null() {
524 report_error(
525 style,
526 doc as *mut _xmlNode,
527 b"xsltParseStylesheetProcess : empty stylesheet\n",
528 );
529 return ptr::null_mut();
530 }
531
532 let ret = crate::xslt::compiler::compile(style, doc);
533 if ret != 0 {
534 return ptr::null_mut();
535 }
536 style
537}
538
539#[no_mangle]
581pub unsafe extern "C" fn xsltParseStylesheetUser(
582 style: *mut _xsltStylesheet,
583 doc: *mut _xmlDoc,
584) -> c_int {
585 if style.is_null() || doc.is_null() {
586 return -1;
587 }
588
589 if !(*doc).dict.is_null() {
591 xmlDictFree((*style).dict);
592 (*style).dict = (*doc).dict;
593 xmlDictReference((*style).dict);
594 }
595
596 (*style).doc = doc;
600 if xsltParseStylesheetProcess(style, doc).is_null() {
601 (*style).doc = ptr::null_mut();
602 return -1;
603 }
604
605 if (*style).parent.is_null() {
606 crate::abi::exports_xslt_apply::xsltResolveStylesheetAttributeSet(style);
607 }
608
609 if (*style).errors != 0 {
610 (*style).doc = ptr::null_mut();
613 return -1;
614 }
615
616 0
617}
618
619#[no_mangle]
645pub unsafe extern "C" fn xsltParseStylesheetImportedDoc(
646 doc: *mut _xmlDoc,
647 parentStyle: *mut _xsltStylesheet,
648) -> *mut _xsltStylesheet {
649 if doc.is_null() {
650 return ptr::null_mut();
651 }
652
653 let retStyle = xslt_new_stylesheet_internal(parentStyle);
654 if retStyle.is_null() {
655 return ptr::null_mut();
656 }
657
658 if xsltParseStylesheetUser(retStyle, doc) != 0 {
659 crate::xslt::stylesheet::xsltFreeStylesheet(retStyle);
660 return ptr::null_mut();
661 }
662
663 retStyle
664}
665
666unsafe fn xslt_fix_imported_comp_steps(master: *mut _xsltStylesheet, style: *mut _xsltStylesheet) {
680 (*master).extrasNr += (*style).extrasNr;
681 let mut res = (*style).imports;
682 while !res.is_null() {
683 xslt_fix_imported_comp_steps(master, res);
684 res = (*res).next;
685 }
686}
687
688unsafe fn xslt_check_cycle(
690 style: *mut _xsltStylesheet,
691 cur: *mut _xmlNode,
692 uri: *const xmlChar,
693) -> c_int {
694 let mut depth: c_int = 0;
695 let mut ancestor = style;
696 while !ancestor.is_null() {
697 depth += 1;
698 if depth >= XSLT_MAX_NESTING {
699 report_error(style, cur, b"maximum nesting depth exceeded: ");
700 report_error(style, cur, cbytes(uri as *const u8));
701 report_error(style, cur, b"\n");
702 return -1;
703 }
704 if !(*ancestor).doc.is_null()
705 && !(*(*ancestor).doc).URL.is_null()
706 && xmlStrEqual((*(*ancestor).doc).URL, uri) != 0
707 {
708 report_error(style, cur, b"recursion detected on imported URL ");
709 report_error(style, cur, cbytes(uri as *const u8));
710 report_error(style, cur, b"\n");
711 return -1;
712 }
713
714 let mut docptr = (*ancestor).includes;
716 while !docptr.is_null() {
717 depth += 1;
718 if depth >= XSLT_MAX_NESTING {
719 report_error(style, cur, b"maximum nesting depth exceeded: ");
720 report_error(style, cur, cbytes(uri as *const u8));
721 report_error(style, cur, b"\n");
722 return -1;
723 }
724 if !(*docptr).doc.is_null()
725 && !(*(*docptr).doc).URL.is_null()
726 && xmlStrEqual((*(*docptr).doc).URL, uri) != 0
727 {
728 report_error(style, cur, b"recursion detected on included URL ");
729 report_error(style, cur, cbytes(uri as *const u8));
730 report_error(style, cur, b"\n");
731 return -1;
732 }
733 docptr = (*docptr).includes;
734 }
735
736 ancestor = (*ancestor).parent;
737 }
738
739 0
740}
741
742#[no_mangle]
763pub unsafe extern "C" fn xsltParseStylesheetImport(
764 style: *mut _xsltStylesheet,
765 cur: *mut _xmlNode,
766) -> c_int {
767 let mut ret: c_int = -1;
768 let mut uriRef: *mut xmlChar = ptr::null_mut();
769 let mut base: *mut xmlChar = ptr::null_mut();
770 let mut uri: *mut xmlChar = ptr::null_mut();
771
772 if cur.is_null() || style.is_null() {
773 return ret;
774 }
775
776 uriRef = xmlGetNsProp(cur, b"href\0".as_ptr() as *const xmlChar, ptr::null());
777 if uriRef.is_null() {
778 report_error(style, cur, b"xsl:import : missing href attribute\n");
779 if !uriRef.is_null() {
780 xmlFreeImpl(uriRef as *mut c_void);
781 }
782 if !base.is_null() {
783 xmlFreeImpl(base as *mut c_void);
784 }
785 if !uri.is_null() {
786 xmlFreeImpl(uri as *mut c_void);
787 }
788 return ret;
789 }
790
791 base = xmlNodeGetBase((*style).doc, cur);
792 uri = xmlBuildURI(uriRef as *const c_char, base as *const c_char);
793 if uri.is_null() {
794 report_error(style, cur, b"xsl:import : invalid URI reference ");
795 report_error(style, cur, cbytes(uriRef as *const u8));
796 report_error(style, cur, b"\n");
797 if !uriRef.is_null() {
798 xmlFreeImpl(uriRef as *mut c_void);
799 }
800 if !base.is_null() {
801 xmlFreeImpl(base as *mut c_void);
802 }
803 if !uri.is_null() {
804 xmlFreeImpl(uri as *mut c_void);
805 }
806 return ret;
807 }
808
809 if xslt_check_cycle(style, cur, uri) < 0 {
810 if !uriRef.is_null() {
811 xmlFreeImpl(uriRef as *mut c_void);
812 }
813 if !base.is_null() {
814 xmlFreeImpl(base as *mut c_void);
815 }
816 if !uri.is_null() {
817 xmlFreeImpl(uri as *mut c_void);
818 }
819 return ret;
820 }
821
822 let sec = crate::xslt::security::xsltGetDefaultSecurityPrefs();
824 if !sec.is_null() {
825 let secres = xslt_check_read(sec, ptr::null_mut(), uri);
826 if secres <= 0 {
827 if secres == 0 {
828 report_error(
829 ptr::null_mut(),
830 ptr::null_mut(),
831 b"xsl:import: read rights for ",
832 );
833 report_error(ptr::null_mut(), ptr::null_mut(), cbytes(uri as *const u8));
834 report_error(ptr::null_mut(), ptr::null_mut(), b" denied\n");
835 }
836 if !uriRef.is_null() {
837 xmlFreeImpl(uriRef as *mut c_void);
838 }
839 if !base.is_null() {
840 xmlFreeImpl(base as *mut c_void);
841 }
842 if !uri.is_null() {
843 xmlFreeImpl(uri as *mut c_void);
844 }
845 return ret;
846 }
847 }
848
849 let import = xslt_doc_default_loader(
850 uri,
851 (*style).dict,
852 XSLT_PARSE_OPTIONS,
853 style as *mut c_void,
854 XSLT_LOAD_STYLESHEET,
855 );
856 if import.is_null() {
857 report_error(style, cur, b"xsl:import : unable to load ");
858 report_error(style, cur, cbytes(uri as *const u8));
859 report_error(style, cur, b"\n");
860 if !uriRef.is_null() {
861 xmlFreeImpl(uriRef as *mut c_void);
862 }
863 if !base.is_null() {
864 xmlFreeImpl(base as *mut c_void);
865 }
866 if !uri.is_null() {
867 xmlFreeImpl(uri as *mut c_void);
868 }
869 return ret;
870 }
871
872 let res = xsltParseStylesheetImportedDoc(import, style);
873 if !res.is_null() {
874 (*res).next = (*style).imports;
875 (*style).imports = res;
876 if (*style).parent.is_null() {
877 xslt_fix_imported_comp_steps(style, res);
878 }
879 ret = 0;
880 } else {
881 crate::xml::tree::free_doc(import);
882 }
883
884 if !uriRef.is_null() {
885 xmlFreeImpl(uriRef as *mut c_void);
886 }
887 if !base.is_null() {
888 xmlFreeImpl(base as *mut c_void);
889 }
890 if !uri.is_null() {
891 xmlFreeImpl(uri as *mut c_void);
892 }
893
894 ret
895}
896
897#[no_mangle]
927pub unsafe extern "C" fn xsltParseStylesheetInclude(
928 style: *mut _xsltStylesheet,
929 cur: *mut _xmlNode,
930) -> c_int {
931 let mut ret: c_int = -1;
932 let mut uriRef: *mut xmlChar = ptr::null_mut();
933 let mut base: *mut xmlChar = ptr::null_mut();
934 let mut uri: *mut xmlChar = ptr::null_mut();
935
936 if cur.is_null() || style.is_null() {
937 return ret;
938 }
939
940 uriRef = xmlGetNsProp(cur, b"href\0".as_ptr() as *const xmlChar, ptr::null());
941 if uriRef.is_null() {
942 report_error(style, cur, b"xsl:include : missing href attribute\n");
943 if !uriRef.is_null() {
944 xmlFreeImpl(uriRef as *mut c_void);
945 }
946 if !base.is_null() {
947 xmlFreeImpl(base as *mut c_void);
948 }
949 if !uri.is_null() {
950 xmlFreeImpl(uri as *mut c_void);
951 }
952 return ret;
953 }
954
955 base = xmlNodeGetBase((*style).doc, cur);
956 uri = xmlBuildURI(uriRef as *const c_char, base as *const c_char);
957 if uri.is_null() {
958 report_error(style, cur, b"xsl:include : invalid URI reference ");
959 report_error(style, cur, cbytes(uriRef as *const u8));
960 report_error(style, cur, b"\n");
961 if !uriRef.is_null() {
962 xmlFreeImpl(uriRef as *mut c_void);
963 }
964 if !base.is_null() {
965 xmlFreeImpl(base as *mut c_void);
966 }
967 if !uri.is_null() {
968 xmlFreeImpl(uri as *mut c_void);
969 }
970 return ret;
971 }
972
973 if xslt_check_cycle(style, cur, uri) < 0 {
974 if !uriRef.is_null() {
975 xmlFreeImpl(uriRef as *mut c_void);
976 }
977 if !base.is_null() {
978 xmlFreeImpl(base as *mut c_void);
979 }
980 if !uri.is_null() {
981 xmlFreeImpl(uri as *mut c_void);
982 }
983 return ret;
984 }
985
986 let include = xsltLoadStyleDocument(style, uri);
987 if include.is_null() {
988 report_error(style, cur, b"xsl:include : unable to load ");
989 report_error(style, cur, cbytes(uri as *const u8));
990 report_error(style, cur, b"\n");
991 if !uriRef.is_null() {
992 xmlFreeImpl(uriRef as *mut c_void);
993 }
994 if !base.is_null() {
995 xmlFreeImpl(base as *mut c_void);
996 }
997 if !uri.is_null() {
998 xmlFreeImpl(uri as *mut c_void);
999 }
1000 return ret;
1001 }
1002
1003 let oldDoc = (*style).doc;
1004 (*style).doc = (*include).doc;
1005 (*include).includes = (*style).includes;
1007 (*style).includes = include;
1008 let oldNopreproc = (*style).nopreproc;
1009 (*style).nopreproc = (*include).preproc;
1010 let result = xsltParseStylesheetProcess(style, (*include).doc);
1016 (*style).nopreproc = oldNopreproc;
1017 (*include).preproc = 1;
1018 (*style).includes = (*include).includes;
1019 (*style).doc = oldDoc;
1020 if result.is_null() {
1021 ret = -1;
1022 if !uriRef.is_null() {
1023 xmlFreeImpl(uriRef as *mut c_void);
1024 }
1025 if !base.is_null() {
1026 xmlFreeImpl(base as *mut c_void);
1027 }
1028 if !uri.is_null() {
1029 xmlFreeImpl(uri as *mut c_void);
1030 }
1031 return ret;
1032 }
1033 ret = 0;
1034
1035 if !uriRef.is_null() {
1036 xmlFreeImpl(uriRef as *mut c_void);
1037 }
1038 if !base.is_null() {
1039 xmlFreeImpl(base as *mut c_void);
1040 }
1041 if !uri.is_null() {
1042 xmlFreeImpl(uri as *mut c_void);
1043 }
1044 return ret;
1045}
1046
1047unsafe fn xslt_parse_content_error(style: *mut _xsltStylesheet, node: *mut _xmlNode) {
1053 if style.is_null() || node.is_null() {
1054 return;
1055 }
1056 if is_xslt_elem(node) {
1057 report_error(
1058 style,
1059 node,
1060 b"The XSLT-element is not allowed at this position.\n",
1061 );
1062 } else {
1063 report_error(
1064 style,
1065 node,
1066 b"The element is not allowed at this position.\n",
1067 );
1068 }
1069 (*style).errors += 1;
1070}
1071
1072#[no_mangle]
1093pub unsafe extern "C" fn xsltParseStylesheetOutput(
1094 style: *mut _xsltStylesheet,
1095 cur: *mut _xmlNode,
1096) {
1097 if cur.is_null() || style.is_null() || (*cur).type_ != XML_ELEMENT_NODE as c_int {
1098 return;
1099 }
1100
1101 let mut prop = xmlGetNsProp(cur, b"version\0".as_ptr() as *const xmlChar, ptr::null());
1103 if !prop.is_null() {
1104 if !(*style).version.is_null() {
1105 xmlFreeImpl((*style).version as *mut c_void);
1106 }
1107 (*style).version = prop;
1108 prop = ptr::null_mut();
1109 }
1110
1111 prop = xmlGetNsProp(cur, b"encoding\0".as_ptr() as *const xmlChar, ptr::null());
1113 if !prop.is_null() {
1114 if !(*style).encoding.is_null() {
1115 xmlFreeImpl((*style).encoding as *mut c_void);
1116 }
1117 (*style).encoding = prop;
1118 prop = ptr::null_mut();
1119 }
1120
1121 prop = xmlGetNsProp(cur, b"method\0".as_ptr() as *const xmlChar, ptr::null());
1123 if !prop.is_null() {
1124 if !(*style).method.is_null() {
1125 xmlFreeImpl((*style).method as *mut c_void);
1126 }
1127 (*style).method = ptr::null_mut();
1128 if !(*style).methodURI.is_null() {
1129 xmlFreeImpl((*style).methodURI as *mut c_void);
1130 }
1131 (*style).methodURI = ptr::null_mut();
1132
1133 let mut method = prop;
1134 let uri = crate::abi::exports_xslt_avt::xsltGetQNameURI(cur, &mut method);
1135 if method.is_null() {
1136 if !style.is_null() {
1137 (*style).errors += 1;
1138 }
1139 } else if uri.is_null() {
1140 if xmlStrEqual(method, b"xml\0".as_ptr() as *const xmlChar) != 0
1141 || xmlStrEqual(method, b"html\0".as_ptr() as *const xmlChar) != 0
1142 || xmlStrEqual(method, b"text\0".as_ptr() as *const xmlChar) != 0
1143 {
1144 (*style).method = method;
1145 } else {
1146 report_error(style, cur, b"invalid value for method: ");
1147 report_error(style, cur, cbytes(method as *const u8));
1148 report_error(style, cur, b"\n");
1149 if !style.is_null() {
1150 (*style).warnings += 1;
1151 }
1152 xmlFreeImpl(method as *mut c_void);
1153 }
1154 } else {
1155 (*style).method = method;
1156 (*style).methodURI = xmlStrdup(uri);
1157 }
1158 prop = ptr::null_mut();
1159 }
1160
1161 prop = xmlGetNsProp(
1163 cur,
1164 b"doctype-system\0".as_ptr() as *const xmlChar,
1165 ptr::null(),
1166 );
1167 if !prop.is_null() {
1168 if !(*style).doctypeSystem.is_null() {
1169 xmlFreeImpl((*style).doctypeSystem as *mut c_void);
1170 }
1171 (*style).doctypeSystem = prop;
1172 prop = ptr::null_mut();
1173 }
1174
1175 prop = xmlGetNsProp(
1177 cur,
1178 b"doctype-public\0".as_ptr() as *const xmlChar,
1179 ptr::null(),
1180 );
1181 if !prop.is_null() {
1182 if !(*style).doctypePublic.is_null() {
1183 xmlFreeImpl((*style).doctypePublic as *mut c_void);
1184 }
1185 (*style).doctypePublic = prop;
1186 prop = ptr::null_mut();
1187 }
1188
1189 prop = xmlGetNsProp(cur, b"standalone\0".as_ptr() as *const xmlChar, ptr::null());
1191 if !prop.is_null() {
1192 if xmlStrEqual(prop, b"yes\0".as_ptr() as *const xmlChar) != 0 {
1193 (*style).standalone = 1;
1194 } else if xmlStrEqual(prop, b"no\0".as_ptr() as *const xmlChar) != 0 {
1195 (*style).standalone = 0;
1196 } else {
1197 report_error(style, cur, b"invalid value for standalone\n");
1198 (*style).errors += 1;
1199 }
1200 xmlFreeImpl(prop as *mut c_void);
1201 }
1202
1203 prop = xmlGetNsProp(cur, b"indent\0".as_ptr() as *const xmlChar, ptr::null());
1205 if !prop.is_null() {
1206 if xmlStrEqual(prop, b"yes\0".as_ptr() as *const xmlChar) != 0 {
1207 (*style).indent = 1;
1208 } else if xmlStrEqual(prop, b"no\0".as_ptr() as *const xmlChar) != 0 {
1209 (*style).indent = 0;
1210 } else {
1211 report_error(style, cur, b"invalid value for indent\n");
1212 (*style).errors += 1;
1213 }
1214 xmlFreeImpl(prop as *mut c_void);
1215 }
1216
1217 prop = xmlGetNsProp(
1219 cur,
1220 b"omit-xml-declaration\0".as_ptr() as *const xmlChar,
1221 ptr::null(),
1222 );
1223 if !prop.is_null() {
1224 if xmlStrEqual(prop, b"yes\0".as_ptr() as *const xmlChar) != 0 {
1225 (*style).omitXmlDeclaration = 1;
1226 } else if xmlStrEqual(prop, b"no\0".as_ptr() as *const xmlChar) != 0 {
1227 (*style).omitXmlDeclaration = 0;
1228 } else {
1229 report_error(style, cur, b"invalid value for omit-xml-declaration\n");
1230 (*style).errors += 1;
1231 }
1232 xmlFreeImpl(prop as *mut c_void);
1233 }
1234
1235 let elements = xmlGetNsProp(
1237 cur,
1238 b"cdata-section-elements\0".as_ptr() as *const xmlChar,
1239 ptr::null(),
1240 );
1241 if !elements.is_null() {
1242 if (*style).cdataSection.is_null() {
1243 (*style).cdataSection = crate::xml::hash::hash_create(10) as *mut c_void;
1244 }
1245 if (*style).cdataSection.is_null() {
1246 xmlFreeImpl(elements as *mut c_void);
1247 return;
1248 }
1249
1250 let mut element: *mut xmlChar = elements;
1251 while *element != 0 {
1252 while matches!(*element, b' ' | b'\t' | b'\n' | b'\r') {
1253 element = element.add(1);
1254 }
1255 if *element == 0 {
1256 break;
1257 }
1258 let mut end = element;
1259 while *end != 0 && !matches!(*end, b' ' | b'\t' | b'\n' | b'\r') {
1260 end = end.add(1);
1261 }
1262 let len = end.offset_from(element) as usize;
1263 let token = xmlMallocImpl(len + 1) as *mut xmlChar;
1264 if !token.is_null() {
1265 core::ptr::copy_nonoverlapping(element, token, len);
1266 *token.add(len) = 0;
1267 if xmlValidateQName(token, 0) != 0 {
1268 report_error(
1269 style,
1270 cur,
1271 b"Attribute 'cdata-section-elements': The value is not a valid QName.\n",
1272 );
1273 xmlFreeImpl(token as *mut c_void);
1274 (*style).errors += 1;
1275 } else {
1276 let mut qname = token;
1277 let quri = crate::abi::exports_xslt_avt::xsltGetQNameURI(cur, &mut qname);
1278 if qname.is_null() {
1279 report_error(
1280 style,
1281 cur,
1282 b"Attribute 'cdata-section-elements': Not a valid QName.\n",
1283 );
1284 (*style).errors += 1;
1285 } else {
1286 let mut uri = quri;
1287 if uri.is_null() {
1290 let ns = xmlSearchNs((*style).doc, cur, ptr::null());
1291 if !ns.is_null() {
1292 uri = (*ns).href;
1293 }
1294 }
1295 crate::xml::hash::hash_add_entry2(
1296 (*style).cdataSection as *mut crate::xml::hash::HashTable,
1297 qname,
1298 uri,
1299 b"cdata\0".as_ptr() as *const c_void as *mut c_void,
1300 );
1301 xmlFreeImpl(qname as *mut c_void);
1302 }
1303 }
1304 }
1305 element = end;
1306 }
1307 xmlFreeImpl(elements as *mut c_void);
1308 }
1309
1310 prop = xmlGetNsProp(cur, b"media-type\0".as_ptr() as *const xmlChar, ptr::null());
1312 if !prop.is_null() {
1313 if !(*style).mediaType.is_null() {
1314 xmlFreeImpl((*style).mediaType as *mut c_void);
1315 }
1316 (*style).mediaType = prop;
1317 prop = ptr::null_mut();
1318 }
1319
1320 if !(*cur).children.is_null() {
1323 xslt_parse_content_error(style, (*cur).children);
1324 }
1325}
1326
1327#[no_mangle]
1349pub unsafe extern "C" fn xsltParseStylesheetAttributeSet(
1350 style: *mut _xsltStylesheet,
1351 cur: *mut _xmlNode,
1352) {
1353 if cur.is_null() || style.is_null() || (*cur).type_ != XML_ELEMENT_NODE as c_int {
1354 return;
1355 }
1356
1357 let value = xmlGetNsProp(cur, b"name\0".as_ptr() as *const xmlChar, ptr::null());
1358 if value.is_null() || *value == 0 {
1359 if !value.is_null() {
1360 xmlFreeImpl(value as *mut c_void);
1361 }
1362 return;
1363 }
1364 if xmlValidateQName(value, 0) != 0 {
1365 report_error(
1366 style,
1367 cur,
1368 b"xsl:attribute-set : The name is not a valid QName.\n",
1369 );
1370 (*style).errors += 1;
1371 xmlFreeImpl(value as *mut c_void);
1372 return;
1373 }
1374 xmlFreeImpl(value as *mut c_void);
1375
1376 crate::xslt::attributes::xsltCompileAttrSet(style, cur);
1377}
1378
1379#[no_mangle]
1404pub unsafe extern "C" fn xsltParseGlobalVariable(style: *mut _xsltStylesheet, cur: *mut _xmlNode) {
1405 if cur.is_null() || style.is_null() || (*cur).type_ != XML_ELEMENT_NODE as c_int {
1406 return;
1407 }
1408
1409 let name = xmlGetNsProp(cur, b"name\0".as_ptr() as *const xmlChar, ptr::null());
1410 if name.is_null() {
1411 report_error(style, cur, b"xsl:variable : missing name attribute\n");
1412 return;
1413 }
1414
1415 let mut tmp = (*style).variables;
1418 while !tmp.is_null() {
1419 if ((*tmp).flags & XSLT_VAR_PARAM) == 0
1420 && !(*tmp).name.is_null()
1421 && xmlStrEqual((*tmp).name, name) != 0
1422 {
1423 report_error(style, cur, b"redefinition of global variable ");
1424 report_error(style, cur, cbytes(name as *const u8));
1425 report_error(style, cur, b"\n");
1426 (*style).errors += 1;
1427 break;
1428 }
1429 tmp = (*tmp).next;
1430 }
1431 xmlFreeImpl(name as *mut c_void);
1432
1433 if !(*cur).children.is_null() {
1435 xsltParseTemplateContent(style, cur);
1436 }
1437
1438 crate::xslt::compiler::compile_variable(style, cur, 0, 0);
1439}
1440
1441#[no_mangle]
1461pub unsafe extern "C" fn xsltParseGlobalParam(style: *mut _xsltStylesheet, cur: *mut _xmlNode) {
1462 if cur.is_null() || style.is_null() || (*cur).type_ != XML_ELEMENT_NODE as c_int {
1463 return;
1464 }
1465
1466 let name = xmlGetNsProp(cur, b"name\0".as_ptr() as *const xmlChar, ptr::null());
1467 if name.is_null() {
1468 report_error(style, cur, b"xsl:param : missing name attribute\n");
1469 return;
1470 }
1471 xmlFreeImpl(name as *mut c_void);
1472
1473 if !(*cur).children.is_null() {
1475 xsltParseTemplateContent(style, cur);
1476 }
1477
1478 crate::xslt::compiler::compile_variable(style, cur, 0, 1);
1479}
1480
1481#[no_mangle]
1514pub unsafe extern "C" fn xsltParseTemplateContent(
1515 style: *mut _xsltStylesheet,
1516 templ: *mut _xmlNode,
1517) {
1518 if style.is_null() || templ.is_null() || (*templ).type_ == XML_NAMESPACE_DECL as c_int {
1519 return;
1520 }
1521
1522 let mut cur = (*templ).children;
1523 while !cur.is_null() {
1524 if !(*style).principal.is_null() {
1525 (*(*style).principal).opCount += 1;
1526 }
1527
1528 if is_xslt_elem(cur) {
1529 xsltStylePreCompute(style, cur);
1530 } else if !(*cur).ns.is_null() && !ext_ns_registered((*(*cur).ns).href) {
1533 } else if !(*cur).ns.is_null() && ext_ns_registered((*(*cur).ns).href) {
1536 xsltStylePreCompute(style, cur);
1538 } else if (*cur).type_ == XML_ELEMENT_NODE as c_int {
1539 if (*cur).ns.is_null() && !(*style).defaultAlias.is_null() {
1542 (*cur).ns = xmlSearchNsByHref((*cur).doc, cur, (*style).defaultAlias);
1543 }
1544 if !(*cur).properties.is_null() {
1545 let mut attr = (*cur).properties;
1546 while !attr.is_null() {
1547 xsltCompileAttr(style, attr);
1548 attr = (*attr).next;
1549 }
1550 }
1551 }
1552
1553 if !(*cur).children.is_null() {
1556 if (*(*cur).children).type_ != XML_ENTITY_DECL as c_int {
1557 cur = (*cur).children;
1558 continue;
1559 }
1560 }
1561 if !(*cur).next.is_null() {
1562 cur = (*cur).next;
1563 continue;
1564 }
1565 loop {
1566 cur = (*cur).parent;
1567 if cur.is_null() {
1568 break;
1569 }
1570 if cur == templ {
1571 cur = ptr::null_mut();
1572 break;
1573 }
1574 if !(*cur).next.is_null() {
1575 cur = (*cur).next;
1576 break;
1577 }
1578 }
1579 }
1580
1581 let mut cur = (*templ).children;
1583 while !cur.is_null() {
1584 if is_xslt_elem(cur) && !is_xslt_name(cur, b"param") {
1585 break;
1586 }
1587 cur = (*cur).next;
1588 }
1589
1590 while !cur.is_null() {
1592 if is_xslt_elem(cur) && is_xslt_name(cur, b"param") {
1593 let param = cur;
1594 report_error(
1595 style,
1596 cur,
1597 b"xsltParseTemplateContent: ignoring misplaced param element\n",
1598 );
1599 if !style.is_null() {
1600 (*style).warnings += 1;
1601 }
1602 cur = (*cur).next;
1603 crate::xml::tree::unlink_node(param);
1604 crate::xml::tree::free_node(param);
1605 } else {
1606 break;
1607 }
1608 }
1609}
1610
1611unsafe fn ext_ns_registered(uri: *const xmlChar) -> bool {
1614 if uri.is_null() {
1615 return false;
1616 }
1617 let mut cur = XSLT_ELEMENTS_REGISTRY;
1618 while !cur.is_null() {
1619 if !(*cur).URI.is_null() && xmlStrEqual((*cur).URI, uri) != 0 {
1620 return true;
1621 }
1622 cur = (*cur).next;
1623 }
1624 false
1625}
1626
1627#[no_mangle]
1652pub unsafe extern "C" fn xsltCompileAttr(style: *mut _xsltStylesheet, attr: *mut _xmlAttr) {
1653 if style.is_null() || attr.is_null() || (*attr).children.is_null() {
1654 return;
1655 }
1656 if (*(*attr).children).type_ != XML_TEXT_NODE as c_int || !(*(*attr).children).next.is_null() {
1657 report_error(
1658 style,
1659 (*attr).parent,
1660 b"Attribute ': The content is expected to be a single text node when compiling an AVT.\n",
1661 );
1662 (*style).errors += 1;
1663 return;
1664 }
1665
1666 let str_ = (*(*attr).children).content;
1667 if xmlStrchr(str_, b'{' as xmlChar).is_null() && xmlStrchr(str_, b'}' as xmlChar).is_null() {
1668 return;
1669 }
1670 if !(*attr).psvi.is_null() {
1671 return;
1673 }
1674
1675 let mut cur = str_;
1678 while *cur != 0 {
1679 if *cur == b'{' {
1680 if !cur.add(1).is_null() && *cur.add(1) == b'{' {
1681 cur = cur.add(2);
1683 continue;
1684 }
1685 if !cur.add(1).is_null() && *cur.add(1) == b'}' {
1686 cur = cur.add(2);
1688 continue;
1689 }
1690 let mut p = cur.add(1);
1693 while *p != 0 && *p != b'}' {
1694 if *p == b'\'' || *p == b'"' {
1695 let delim = *p;
1696 p = p.add(1);
1697 while *p != 0 && *p != delim {
1698 p = p.add(1);
1699 }
1700 if *p != 0 {
1701 p = p.add(1);
1702 }
1703 } else {
1704 p = p.add(1);
1705 }
1706 }
1707 if *p == 0 {
1708 report_error(
1709 style,
1710 (*attr).parent,
1711 b"Attribute ': The AVT has an unmatched '{'.\n",
1712 );
1713 (*style).errors += 1;
1714 return;
1715 }
1716 cur = p.add(1);
1717 } else if *cur == b'}' {
1718 if !cur.add(1).is_null() && *cur.add(1) == b'}' {
1719 cur = cur.add(2);
1721 continue;
1722 }
1723 report_error(
1724 style,
1725 (*attr).parent,
1726 b"Attribute ': The AVT has an unmatched '}'.\n",
1727 );
1728 return;
1729 } else {
1730 cur = cur.add(1);
1731 }
1732 }
1733}
1734
1735unsafe fn xslt_free_style_pre_comp(comp: *mut c_void) {
1744 if comp.is_null() {
1745 return;
1746 }
1747 xmlFreeImpl(comp);
1748}
1749
1750unsafe extern "C" fn xslt_free_elem_pre_comp(comp: *mut c_void) {
1752 xmlFreeImpl(comp);
1753}
1754
1755unsafe fn xslt_new_style_pre_comp(
1766 style: *mut _xsltStylesheet,
1767 type_: c_int,
1768) -> *mut _xsltStylePreComp {
1769 if style.is_null() {
1770 return ptr::null_mut();
1771 }
1772 let cur = xmlMallocImpl(core::mem::size_of::<_xsltStylePreComp>()) as *mut _xsltStylePreComp;
1773 if cur.is_null() {
1774 report_error(
1775 style,
1776 ptr::null_mut(),
1777 b"xsltNewStylePreComp : malloc failed\n",
1778 );
1779 (*style).errors += 1;
1780 return ptr::null_mut();
1781 }
1782 ptr::write_bytes(cur as *mut u8, 0, core::mem::size_of::<_xsltStylePreComp>());
1783
1784 (*cur).base.type_ = type_;
1785 (*cur).base.next = (*style).preComps as *mut _xsltElemPreComp;
1786 (*style).preComps = cur as *mut c_void;
1787
1788 cur
1789}
1790
1791#[no_mangle]
1811pub unsafe extern "C" fn xsltDocumentComp(
1812 style: *mut _xsltStylesheet,
1813 inst: *mut _xmlNode,
1814 _function: Option<xsltTransformFunction>,
1815) -> *mut _xsltElemPreComp {
1816 if style.is_null() || inst.is_null() || (*inst).type_ != XML_ELEMENT_NODE as c_int {
1817 return ptr::null_mut();
1818 }
1819
1820 let comp = xslt_new_style_pre_comp(style, XSLT_FUNC_DOCUMENT);
1821 if comp.is_null() {
1822 return ptr::null_mut();
1823 }
1824 (*comp).base.inst = inst;
1825 (*comp).ver11 = 0;
1826 let mut filename: *const xmlChar = ptr::null();
1827
1828 if is_xslt_name(inst, b"output") {
1829 filename = crate::abi::exports_xslt_avt::xsltEvalStaticAttrValueTemplate(
1831 style,
1832 inst,
1833 b"file\0".as_ptr() as *const xmlChar,
1834 ptr::null(),
1835 &mut (*comp).has_filename,
1836 );
1837 } else if is_xslt_name(inst, b"write") {
1838 } else if is_xslt_name(inst, b"document") {
1840 if !(*inst).ns.is_null() {
1841 if xmlStrEqual(
1842 (*(*inst).ns).href,
1843 XSLT_NAMESPACE.as_ptr() as *const xmlChar,
1844 ) != 0
1845 {
1846 (*comp).ver11 = 1;
1848 }
1849 }
1851 filename = crate::abi::exports_xslt_avt::xsltEvalStaticAttrValueTemplate(
1852 style,
1853 inst,
1854 b"href\0".as_ptr() as *const xmlChar,
1855 ptr::null(),
1856 &mut (*comp).has_filename,
1857 );
1858 }
1859 if (*comp).has_filename != 0 {
1860 (*comp).filename = filename;
1861 }
1862
1863 &mut (*comp).base as *mut _xsltElemPreComp
1864}
1865
1866unsafe fn xslt_init_elem_pre_comp(
1877 comp: *mut _xsltElemPreComp,
1878 style: *mut _xsltStylesheet,
1879 inst: *mut _xmlNode,
1880 function: Option<xsltTransformFunction>,
1881 free_func: Option<xsltElemPreCompDeallocator>,
1882) {
1883 (*comp).type_ = XSLT_FUNC_EXTENSION;
1884 (*comp).func = function;
1885 (*comp).inst = inst;
1886 (*comp).free = free_func;
1887
1888 (*comp).next = (*style).preComps as *mut _xsltElemPreComp;
1889 (*style).preComps = comp as *mut c_void;
1890}
1891
1892unsafe fn xslt_new_elem_pre_comp(
1900 style: *mut _xsltStylesheet,
1901 inst: *mut _xmlNode,
1902 function: Option<xsltTransformFunction>,
1903) -> *mut _xsltElemPreComp {
1904 let cur = xmlMallocImpl(core::mem::size_of::<_xsltElemPreComp>()) as *mut _xsltElemPreComp;
1905 if cur.is_null() {
1906 report_error(
1907 style,
1908 ptr::null_mut(),
1909 b"xsltNewExtElement : malloc failed\n",
1910 );
1911 return ptr::null_mut();
1912 }
1913 ptr::write_bytes(cur as *mut u8, 0, core::mem::size_of::<_xsltElemPreComp>());
1914
1915 xslt_init_elem_pre_comp(cur, style, inst, function, Some(xslt_free_elem_pre_comp));
1916
1917 cur
1918}
1919
1920#[no_mangle]
1949pub unsafe extern "C" fn xsltPreComputeExtModuleElement(
1950 style: *mut _xsltStylesheet,
1951 inst: *mut _xmlNode,
1952) -> *mut _xsltElemPreComp {
1953 if style.is_null()
1954 || inst.is_null()
1955 || (*inst).type_ != XML_ELEMENT_NODE as c_int
1956 || (*inst).ns.is_null()
1957 {
1958 return ptr::null_mut();
1959 }
1960
1961 let ext = ext_element_lookup((*inst).name, (*(*inst).ns).href);
1962 if ext.is_null() {
1963 return ptr::null_mut();
1964 }
1965
1966 let mut comp: *mut _xsltElemPreComp = ptr::null_mut();
1967 if let Some(precomp) = (*ext).precomp {
1968 comp = precomp(style, inst, (*ext).transform) as *mut _xsltElemPreComp;
1969 }
1970 if comp.is_null() {
1971 comp = xslt_new_elem_pre_comp(style, inst, (*ext).transform);
1973 }
1974
1975 comp
1976}
1977
1978#[no_mangle]
1996pub unsafe extern "C" fn xsltFreeStylePreComps(style: *mut _xsltStylesheet) {
1997 if style.is_null() {
1998 return;
1999 }
2000
2001 let mut cur = (*style).preComps as *mut _xsltElemPreComp;
2002 (*style).preComps = ptr::null_mut();
2003 while !cur.is_null() {
2004 let next = (*cur).next;
2005 if (*cur).type_ == XSLT_FUNC_EXTENSION {
2006 if let Some(free_func) = (*cur).free {
2007 free_func(cur as *mut c_void);
2008 } else {
2009 xslt_free_style_pre_comp(cur as *mut c_void);
2010 }
2011 } else {
2012 xslt_free_style_pre_comp(cur as *mut c_void);
2013 }
2014 cur = next;
2015 }
2016}
2017
2018#[no_mangle]
2046pub unsafe extern "C" fn xsltStylePreCompute(style: *mut _xsltStylesheet, inst: *mut _xmlNode) {
2047 if inst.is_null() || (*inst).type_ != XML_ELEMENT_NODE as c_int || !(*inst).psvi.is_null() {
2048 return;
2049 }
2050
2051 if is_xslt_elem(inst) {
2052 if is_xslt_name(inst, b"apply-templates") {
2053 xslt_check_instruction_element(style, inst);
2054 } else if is_xslt_name(inst, b"with-param") {
2056 xslt_check_parent_element(style, inst, b"apply-templates", b"call-template\0".as_ptr() as *const u8);
2057 } else if is_xslt_name(inst, b"value-of") {
2059 xslt_check_instruction_element(style, inst);
2060 } else if is_xslt_name(inst, b"copy") {
2061 xslt_check_instruction_element(style, inst);
2062 } else if is_xslt_name(inst, b"copy-of") {
2063 xslt_check_instruction_element(style, inst);
2064 } else if is_xslt_name(inst, b"if") {
2065 xslt_check_instruction_element(style, inst);
2066 } else if is_xslt_name(inst, b"when") {
2067 xslt_check_parent_element(style, inst, b"choose", ptr::null());
2068 } else if is_xslt_name(inst, b"choose") {
2069 xslt_check_instruction_element(style, inst);
2070 } else if is_xslt_name(inst, b"for-each") {
2071 xslt_check_instruction_element(style, inst);
2072 } else if is_xslt_name(inst, b"apply-imports") {
2073 xslt_check_instruction_element(style, inst);
2074 } else if is_xslt_name(inst, b"attribute") {
2075 let parent = (*inst).parent;
2076 let is_in_attr_set = !parent.is_null()
2077 && (*parent).type_ == XML_ELEMENT_NODE as c_int
2078 && !(*parent).ns.is_null()
2079 && xmlStrEqual(
2080 (*(*parent).ns).href,
2081 XSLT_NAMESPACE.as_ptr() as *const xmlChar,
2082 ) != 0
2083 && is_xslt_name(parent, b"attribute-set");
2084 if !is_in_attr_set {
2085 xslt_check_instruction_element(style, inst);
2086 }
2087 } else if is_xslt_name(inst, b"element") {
2089 xslt_check_instruction_element(style, inst);
2090 } else if is_xslt_name(inst, b"text") {
2091 xslt_check_instruction_element(style, inst);
2092 } else if is_xslt_name(inst, b"sort") {
2093 xslt_check_parent_element(style, inst, b"apply-templates", b"for-each\0".as_ptr() as *const u8);
2094 } else if is_xslt_name(inst, b"comment") {
2095 xslt_check_instruction_element(style, inst);
2096 } else if is_xslt_name(inst, b"number") {
2097 xslt_check_instruction_element(style, inst);
2098 } else if is_xslt_name(inst, b"processing-instruction") {
2099 xslt_check_instruction_element(style, inst);
2100 } else if is_xslt_name(inst, b"call-template") {
2101 xslt_check_instruction_element(style, inst);
2102 } else if is_xslt_name(inst, b"param") {
2103 if xslt_check_top_level_element(style, inst, 0) == 0 {
2104 xslt_check_instruction_element(style, inst);
2105 }
2106 } else if is_xslt_name(inst, b"variable") {
2108 if xslt_check_top_level_element(style, inst, 0) == 0 {
2109 xslt_check_instruction_element(style, inst);
2110 }
2111 } else if is_xslt_name(inst, b"otherwise") {
2113 xslt_check_parent_element(style, inst, b"choose", ptr::null());
2114 xslt_check_instruction_element(style, inst);
2115 return;
2116 } else if is_xslt_name(inst, b"template") {
2117 xslt_check_top_level_element(style, inst, 1);
2118 return;
2119 } else if is_xslt_name(inst, b"output") {
2120 xslt_check_top_level_element(style, inst, 1);
2121 return;
2122 } else if is_xslt_name(inst, b"preserve-space") {
2123 xslt_check_top_level_element(style, inst, 1);
2124 return;
2125 } else if is_xslt_name(inst, b"strip-space") {
2126 xslt_check_top_level_element(style, inst, 1);
2127 return;
2128 } else if is_xslt_name(inst, b"stylesheet") || is_xslt_name(inst, b"transform") {
2129 let parent = (*inst).parent;
2130 if parent.is_null() || (*parent).type_ != XML_DOCUMENT_NODE as c_int {
2131 report_error(style, inst, b"element only allowed only as root element\n");
2132 (*style).errors += 1;
2133 }
2134 return;
2135 } else if is_xslt_name(inst, b"key") {
2136 xslt_check_top_level_element(style, inst, 1);
2137 return;
2138 } else if is_xslt_name(inst, b"message") {
2139 xslt_check_instruction_element(style, inst);
2140 return;
2141 } else if is_xslt_name(inst, b"attribute-set") {
2142 xslt_check_top_level_element(style, inst, 1);
2143 return;
2144 } else if is_xslt_name(inst, b"namespace-alias") {
2145 xslt_check_top_level_element(style, inst, 1);
2146 return;
2147 } else if is_xslt_name(inst, b"include") {
2148 xslt_check_top_level_element(style, inst, 1);
2149 return;
2150 } else if is_xslt_name(inst, b"import") {
2151 xslt_check_top_level_element(style, inst, 1);
2152 return;
2153 } else if is_xslt_name(inst, b"decimal-format") {
2154 xslt_check_top_level_element(style, inst, 1);
2155 return;
2156 } else if is_xslt_name(inst, b"fallback") {
2157 xslt_check_instruction_element(style, inst);
2158 return;
2159 } else if is_xslt_name(inst, b"document") {
2160 xslt_check_instruction_element(style, inst);
2161 (*inst).psvi = xsltDocumentComp(style, inst, None) as *mut c_void;
2162 } else if style.is_null() || (*style).forwards_compatible == 0 {
2163 report_error(
2164 style,
2165 inst,
2166 b"xsltStylePreCompute: unknown xsl: instruction\n",
2167 );
2168 if !style.is_null() {
2169 (*style).warnings += 1;
2170 }
2171 }
2172 } else {
2173 (*inst).psvi = xsltPreComputeExtModuleElement(style, inst) as *mut c_void;
2176 if (*inst).psvi.is_null() {
2177 (*inst).psvi = XSLT_EXT_MARKER.as_ptr() as *mut c_void;
2178 }
2179 }
2180}
2181
2182unsafe fn xslt_check_top_level_element(
2187 style: *mut _xsltStylesheet,
2188 inst: *mut _xmlNode,
2189 err: c_int,
2190) -> c_int {
2191 if style.is_null() || inst.is_null() || (*inst).ns.is_null() {
2192 return -1;
2193 }
2194
2195 let parent = (*inst).parent;
2196 if parent.is_null() {
2197 if err != 0 {
2198 report_error(style, inst, b"internal problem: element has no parent\n");
2199 (*style).errors += 1;
2200 }
2201 return 0;
2202 }
2203 if (*parent).ns.is_null()
2204 || (*parent).type_ != XML_ELEMENT_NODE as c_int
2205 || (xmlStrEqual((*(*parent).ns).href, (*(*inst).ns).href) == 0)
2206 || (!is_xslt_name(parent, b"stylesheet") && !is_xslt_name(parent, b"transform"))
2207 {
2208 if err != 0 {
2209 report_error(
2210 style,
2211 inst,
2212 b"element only allowed as child of stylesheet\n",
2213 );
2214 (*style).errors += 1;
2215 }
2216 return 0;
2217 }
2218 1
2219}
2220
2221unsafe fn xslt_check_instruction_element(style: *mut _xsltStylesheet, inst: *mut _xmlNode) {
2224 if style.is_null() || inst.is_null() || (*inst).ns.is_null() || (*style).literal_result != 0 {
2225 return;
2226 }
2227
2228 let has_ext = !(*style).extInfos.is_null() || !ext_ns_registered(ptr::null());
2229
2230 let mut parent = (*inst).parent;
2231 if parent.is_null() {
2232 report_error(style, inst, b"internal problem: element has no parent\n");
2233 (*style).errors += 1;
2234 return;
2235 }
2236 while !parent.is_null() && (*parent).type_ != XML_DOCUMENT_NODE as c_int {
2237 if ((*parent).ns == (*inst).ns
2238 || (!(*parent).ns.is_null()
2239 && xmlStrEqual((*(*parent).ns).href, (*(*inst).ns).href) != 0))
2240 && (is_xslt_name(parent, b"template")
2241 || is_xslt_name(parent, b"param")
2242 || is_xslt_name(parent, b"attribute")
2243 || is_xslt_name(parent, b"variable"))
2244 {
2245 return;
2246 }
2247
2248 if has_ext && !(*parent).ns.is_null() && ext_ns_registered((*(*parent).ns).href) {
2251 return;
2252 }
2253
2254 parent = (*parent).parent;
2255 }
2256 report_error(
2257 style,
2258 inst,
2259 b"element only allowed within a template, variable or param\n",
2260 );
2261 (*style).errors += 1;
2262}
2263
2264unsafe fn xslt_check_parent_element(
2267 style: *mut _xsltStylesheet,
2268 inst: *mut _xmlNode,
2269 allow1: &[u8],
2270 allow2: *const u8,
2271) {
2272 if style.is_null() || inst.is_null() || (*inst).ns.is_null() || (*style).literal_result != 0 {
2273 return;
2274 }
2275
2276 let parent = (*inst).parent;
2277 if parent.is_null() {
2278 report_error(style, inst, b"internal problem: element has no parent\n");
2279 (*style).errors += 1;
2280 return;
2281 }
2282 let allow2_bytes: &[u8] = if allow2.is_null() {
2283 b""
2284 } else {
2285 core::slice::from_raw_parts(allow2, libc::strlen(allow2 as *const libc::c_char) as usize)
2286 };
2287 if ((*parent).ns == (*inst).ns
2288 || (!(*parent).ns.is_null() && xmlStrEqual((*(*parent).ns).href, (*(*inst).ns).href) != 0))
2289 && (is_xslt_name(parent, allow1)
2290 || (!allow2_bytes.is_empty() && is_xslt_name(parent, allow2_bytes)))
2291 {
2292 return;
2293 }
2294
2295 if !ext_ns_registered(ptr::null()) {
2296 let mut p = parent;
2297 while !p.is_null() && (*p).type_ != XML_DOCUMENT_NODE as c_int {
2298 if !(*p).ns.is_null() && ext_ns_registered((*(*p).ns).href) {
2299 return;
2300 }
2301 p = (*p).parent;
2302 }
2303 }
2304 report_error(style, inst, b"element is not allowed within that context\n");
2305 (*style).errors += 1;
2306}
2307
2308#[no_mangle]
2338pub unsafe extern "C" fn xsltNormalizeCompSteps(
2339 payload: *mut c_void,
2340 data: *mut c_void,
2341 _name: *const xmlChar,
2342) {
2343 let _ = (payload, data);
2344}
2345
2346#[no_mangle]
2377pub unsafe extern "C" fn xsltNewStyleDocument(
2378 style: *mut _xsltStylesheet,
2379 doc: *mut _xmlDoc,
2380) -> *mut _xsltDocument {
2381 let cur = xmlMallocImpl(core::mem::size_of::<_xsltDocument>()) as *mut _xsltDocument;
2382 if cur.is_null() {
2383 report_error(
2384 style,
2385 doc as *mut _xmlNode,
2386 b"xsltNewStyleDocument : malloc failed\n",
2387 );
2388 return ptr::null_mut();
2389 }
2390 ptr::write_bytes(cur as *mut u8, 0, core::mem::size_of::<_xsltDocument>());
2391 (*cur).doc = doc;
2392 if !style.is_null() {
2393 (*cur).next = (*style).docList;
2394 (*style).docList = cur;
2395 }
2396 cur
2397}
2398
2399#[no_mangle]
2421pub unsafe extern "C" fn xsltLoadStyleDocument(
2422 style: *mut _xsltStylesheet,
2423 uri: *const xmlChar,
2424) -> *mut _xsltDocument {
2425 if style.is_null() || uri.is_null() {
2426 return ptr::null_mut();
2427 }
2428
2429 let sec = crate::xslt::security::xsltGetDefaultSecurityPrefs();
2431 if !sec.is_null() {
2432 let res = xslt_check_read(sec, ptr::null_mut(), uri);
2433 if res <= 0 {
2434 if res == 0 {
2435 report_error(
2436 ptr::null_mut(),
2437 ptr::null_mut(),
2438 b"xsltLoadStyleDocument: read rights for ",
2439 );
2440 report_error(ptr::null_mut(), ptr::null_mut(), cbytes(uri as *const u8));
2441 report_error(ptr::null_mut(), ptr::null_mut(), b" denied\n");
2442 }
2443 return ptr::null_mut();
2444 }
2445 }
2446
2447 let mut ret = (*style).docList;
2449 while !ret.is_null() {
2450 if !(*ret).doc.is_null()
2451 && !(*(*ret).doc).URL.is_null()
2452 && xmlStrEqual((*(*ret).doc).URL, uri) != 0
2453 {
2454 return ret;
2455 }
2456 ret = (*ret).next;
2457 }
2458
2459 let doc = xslt_doc_default_loader(
2460 uri,
2461 (*style).dict,
2462 XSLT_PARSE_OPTIONS,
2463 style as *mut c_void,
2464 XSLT_LOAD_STYLESHEET,
2465 );
2466 if doc.is_null() {
2467 return ptr::null_mut();
2468 }
2469
2470 let ret = xsltNewStyleDocument(style, doc);
2471 if ret.is_null() {
2472 crate::xml::tree::free_doc(doc);
2473 }
2474 ret
2475}
2476
2477#[no_mangle]
2507pub unsafe extern "C" fn xsltFreeStyleDocuments(style: *mut _xsltStylesheet) {
2508 if style.is_null() {
2509 return;
2510 }
2511
2512 let mut cur = (*style).docList;
2513 (*style).docList = ptr::null_mut();
2514 while !cur.is_null() {
2515 let doc = cur;
2516 cur = (*cur).next;
2517 if (*doc).main == 0 && !(*doc).doc.is_null() {
2518 crate::xml::tree::free_doc((*doc).doc);
2519 }
2520 xmlFreeImpl(doc as *mut c_void);
2521 }
2522}
2523
2524#[no_mangle]
2548pub unsafe extern "C" fn xsltInitGlobals() {
2549 if XSLT_GLOBALS_INITIALIZED == 0 {
2550 XSLT_GLOBALS_INITIALIZED = 1;
2551 }
2552}
2553
2554#[no_mangle]
2575pub unsafe extern "C" fn xsltUninit() {
2576 XSLT_GLOBALS_INITIALIZED = 0;
2577}
2578
2579#[no_mangle]
2605pub unsafe extern "C" fn xsltFreeExts(style: *mut _xsltStylesheet) {
2606 if style.is_null() {
2607 return;
2608 }
2609 }
2611
2612#[no_mangle]
2641pub unsafe extern "C" fn xsltShutdownExts(style: *mut _xsltStylesheet) {
2642 if style.is_null() {
2643 return;
2644 }
2645 if (*style).extInfos.is_null() {
2646 return;
2647 }
2648 crate::xml::hash::hash_free((*style).extInfos as *mut crate::xml::hash::HashTable, None);
2652 (*style).extInfos = ptr::null_mut();
2653}
2654
2655#[no_mangle]
2674pub unsafe extern "C" fn xsltDebugDumpExtensions(output: *mut libc::FILE) {
2675 let out = if output.is_null() {
2676 libc::fdopen(1, b"w\0".as_ptr() as *const c_char)
2677 } else {
2678 output
2679 };
2680
2681 if out.is_null() {
2682 return;
2683 }
2684
2685 libc::fprintf(
2686 out,
2687 b"Registered XSLT Extensions\n--------------------------\n\0".as_ptr() as *const c_char,
2688 );
2689 libc::fprintf(
2690 out,
2691 b"No registered extension functions\n\0".as_ptr() as *const c_char,
2692 );
2693 libc::fprintf(
2694 out,
2695 b"\nNo registered top-level extension elements\n\0".as_ptr() as *const c_char,
2696 );
2697
2698 if XSLT_ELEMENTS_REGISTRY.is_null() {
2699 libc::fprintf(
2700 out,
2701 b"\nNo registered instruction extension elements\n\0".as_ptr() as *const c_char,
2702 );
2703 } else {
2704 libc::fprintf(
2705 out,
2706 b"\nRegistered instruction extension elements:\n\0".as_ptr() as *const c_char,
2707 );
2708 let mut cur = XSLT_ELEMENTS_REGISTRY;
2709 while !cur.is_null() {
2710 if !(*cur).URI.is_null() && !(*cur).name.is_null() {
2711 libc::fprintf(
2712 out,
2713 b"{%s}%s\n\0".as_ptr() as *const c_char,
2714 (*cur).URI as *const c_char,
2715 (*cur).name as *const c_char,
2716 );
2717 }
2718 cur = (*cur).next;
2719 }
2720 }
2721
2722 if XSLT_MODULES_REGISTRY.is_null() {
2723 libc::fprintf(
2724 out,
2725 b"\nNo registered extension modules\n\0".as_ptr() as *const c_char,
2726 );
2727 } else {
2728 libc::fprintf(
2729 out,
2730 b"\nRegistered extension modules:\n\0".as_ptr() as *const c_char,
2731 );
2732 let mut cur = XSLT_MODULES_REGISTRY;
2733 while !cur.is_null() {
2734 if !(*cur).URI.is_null() {
2735 libc::fprintf(
2736 out,
2737 b"%s\n\0".as_ptr() as *const c_char,
2738 (*cur).URI as *const c_char,
2739 );
2740 }
2741 cur = (*cur).next;
2742 }
2743 }
2744}