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
364pub(crate) unsafe fn xslt_new_decimal_format(
367 nsUri: *const xmlChar,
368 name: *mut xmlChar,
369) -> *mut _xsltDecimalFormat {
370 let self_ =
371 xmlMallocImpl(core::mem::size_of::<_xsltDecimalFormat>()) as *mut _xsltDecimalFormat;
372 if !self_.is_null() {
373 ptr::write_bytes(
374 self_ as *mut u8,
375 0,
376 core::mem::size_of::<_xsltDecimalFormat>(),
377 );
378 (*self_).nsUri = nsUri;
379 (*self_).name = name;
380 (*self_).digit = xmlStrdup(b"#\0".as_ptr() as *const xmlChar);
382 (*self_).patternSeparator = xmlStrdup(b";\0".as_ptr() as *const xmlChar);
383 (*self_).decimalPoint = xmlStrdup(b".\0".as_ptr() as *const xmlChar);
384 (*self_).grouping = xmlStrdup(b",\0".as_ptr() as *const xmlChar);
385 (*self_).percent = xmlStrdup(b"%\0".as_ptr() as *const xmlChar);
386 (*self_).permille = xmlStrdup("\u{2030}\0".as_ptr() as *const xmlChar);
387 (*self_).zeroDigit = xmlStrdup(b"0\0".as_ptr() as *const xmlChar);
388 (*self_).minusSign = xmlStrdup(b"-\0".as_ptr() as *const xmlChar);
389 (*self_).infinity = xmlStrdup(b"Infinity\0".as_ptr() as *const xmlChar);
390 (*self_).noNumber = xmlStrdup(b"NaN\0".as_ptr() as *const xmlChar);
391 }
392 self_
393}
394
395unsafe fn xslt_new_stylesheet_internal(parent: *mut _xsltStylesheet) -> *mut _xsltStylesheet {
397 let ret = xmlMallocImpl(core::mem::size_of::<_xsltStylesheet>()) as *mut _xsltStylesheet;
398 if ret.is_null() {
399 report_error(
400 ptr::null_mut(),
401 ptr::null_mut(),
402 b"xsltNewStylesheet : malloc failed\n",
403 );
404 return ptr::null_mut();
405 }
406 ptr::write_bytes(ret as *mut u8, 0, core::mem::size_of::<_xsltStylesheet>());
407
408 (*ret).parent = parent;
409 (*ret).omitXmlDeclaration = -1;
410 (*ret).standalone = -1;
411 (*ret).decimalFormat = xslt_new_decimal_format(ptr::null(), ptr::null_mut());
412 (*ret).indent = -1;
413 (*ret).errors = 0;
414 (*ret).warnings = 0;
415 (*ret).exclPrefixNr = 0;
416 (*ret).exclPrefixMax = 0;
417 (*ret).exclPrefixTab = ptr::null_mut();
418 (*ret).extInfos = ptr::null_mut();
419 (*ret).extrasNr = 0;
420 (*ret).internalized = 1;
421 (*ret).literal_result = 0;
422 (*ret).forwards_compatible = 0;
423 (*ret).dict = xmlDictCreate();
424
425 if parent.is_null() {
426 (*ret).principal = ret;
427 (*ret).xpathCtxt = xmlXPathNewContext(ptr::null_mut());
428 if (*ret).xpathCtxt.is_null() {
429 report_error(
430 ptr::null_mut(),
431 ptr::null_mut(),
432 b"xsltNewStylesheet: xmlXPathNewContext failed\n",
433 );
434 crate::xslt::stylesheet::xsltFreeStylesheet(ret);
435 return ptr::null_mut();
436 }
437 if crate::xml::xpath::exports::xmlXPathContextSetCache((*ret).xpathCtxt, 1, -1, 0) == -1 {
438 crate::xslt::stylesheet::xsltFreeStylesheet(ret);
439 return ptr::null_mut();
440 }
441 } else {
442 (*ret).principal = (*parent).principal;
443 }
444
445 crate::abi::exports_xslt::xsltInit();
449
450 ret
451}
452
453#[no_mangle]
479pub unsafe extern "C" fn xsltNewStylesheet() -> *mut _xsltStylesheet {
480 xslt_new_stylesheet_internal(ptr::null_mut())
481}
482
483#[no_mangle]
510pub unsafe extern "C" fn xsltParseStylesheetProcess(
511 style: *mut _xsltStylesheet,
512 doc: *mut _xmlDoc,
513) -> *mut _xsltStylesheet {
514 xsltInitGlobals();
515
516 if doc.is_null() {
517 return ptr::null_mut();
518 }
519 if style.is_null() {
520 return style;
521 }
522
523 let root = crate::xml::tree::doc_get_root_element(doc);
524 if root.is_null() {
525 report_error(
526 style,
527 doc as *mut _xmlNode,
528 b"xsltParseStylesheetProcess : empty stylesheet\n",
529 );
530 return ptr::null_mut();
531 }
532
533 let ret = crate::xslt::compiler::compile(style, doc);
534 if ret != 0 {
535 return ptr::null_mut();
536 }
537 style
538}
539
540#[no_mangle]
582pub unsafe extern "C" fn xsltParseStylesheetUser(
583 style: *mut _xsltStylesheet,
584 doc: *mut _xmlDoc,
585) -> c_int {
586 if style.is_null() || doc.is_null() {
587 return -1;
588 }
589
590 if !(*doc).dict.is_null() {
592 xmlDictFree((*style).dict);
593 (*style).dict = (*doc).dict;
594 xmlDictReference((*style).dict);
595 }
596
597 (*style).doc = doc;
601 if xsltParseStylesheetProcess(style, doc).is_null() {
602 (*style).doc = ptr::null_mut();
603 return -1;
604 }
605
606 if (*style).parent.is_null() {
607 crate::abi::exports_xslt_apply::xsltResolveStylesheetAttributeSet(style);
608 }
609
610 if (*style).errors != 0 {
611 (*style).doc = ptr::null_mut();
614 return -1;
615 }
616
617 0
618}
619
620#[no_mangle]
646pub unsafe extern "C" fn xsltParseStylesheetImportedDoc(
647 doc: *mut _xmlDoc,
648 parentStyle: *mut _xsltStylesheet,
649) -> *mut _xsltStylesheet {
650 if doc.is_null() {
651 return ptr::null_mut();
652 }
653
654 let retStyle = xslt_new_stylesheet_internal(parentStyle);
655 if retStyle.is_null() {
656 return ptr::null_mut();
657 }
658
659 if xsltParseStylesheetUser(retStyle, doc) != 0 {
660 crate::xslt::stylesheet::xsltFreeStylesheet(retStyle);
661 return ptr::null_mut();
662 }
663
664 retStyle
665}
666
667unsafe fn xslt_fix_imported_comp_steps(master: *mut _xsltStylesheet, style: *mut _xsltStylesheet) {
681 (*master).extrasNr += (*style).extrasNr;
682 let mut res = (*style).imports;
683 while !res.is_null() {
684 xslt_fix_imported_comp_steps(master, res);
685 res = (*res).next;
686 }
687}
688
689unsafe fn xslt_check_cycle(
691 style: *mut _xsltStylesheet,
692 cur: *mut _xmlNode,
693 uri: *const xmlChar,
694) -> c_int {
695 let mut depth: c_int = 0;
696 let mut ancestor = style;
697 while !ancestor.is_null() {
698 depth += 1;
699 if depth >= XSLT_MAX_NESTING {
700 report_error(style, cur, b"maximum nesting depth exceeded: ");
701 report_error(style, cur, cbytes(uri as *const u8));
702 report_error(style, cur, b"\n");
703 return -1;
704 }
705 if !(*ancestor).doc.is_null()
706 && !(*(*ancestor).doc).URL.is_null()
707 && xmlStrEqual((*(*ancestor).doc).URL, uri) != 0
708 {
709 report_error(style, cur, b"recursion detected on imported URL ");
710 report_error(style, cur, cbytes(uri as *const u8));
711 report_error(style, cur, b"\n");
712 return -1;
713 }
714
715 let mut docptr = (*ancestor).includes;
717 while !docptr.is_null() {
718 depth += 1;
719 if depth >= XSLT_MAX_NESTING {
720 report_error(style, cur, b"maximum nesting depth exceeded: ");
721 report_error(style, cur, cbytes(uri as *const u8));
722 report_error(style, cur, b"\n");
723 return -1;
724 }
725 if !(*docptr).doc.is_null()
726 && !(*(*docptr).doc).URL.is_null()
727 && xmlStrEqual((*(*docptr).doc).URL, uri) != 0
728 {
729 report_error(style, cur, b"recursion detected on included URL ");
730 report_error(style, cur, cbytes(uri as *const u8));
731 report_error(style, cur, b"\n");
732 return -1;
733 }
734 docptr = (*docptr).includes;
735 }
736
737 ancestor = (*ancestor).parent;
738 }
739
740 0
741}
742
743#[no_mangle]
764pub unsafe extern "C" fn xsltParseStylesheetImport(
765 style: *mut _xsltStylesheet,
766 cur: *mut _xmlNode,
767) -> c_int {
768 let mut ret: c_int = -1;
769 let mut uriRef: *mut xmlChar = ptr::null_mut();
770 let mut base: *mut xmlChar = ptr::null_mut();
771 let mut uri: *mut xmlChar = ptr::null_mut();
772
773 if cur.is_null() || style.is_null() {
774 return ret;
775 }
776
777 uriRef = xmlGetNsProp(cur, b"href\0".as_ptr() as *const xmlChar, ptr::null());
778 if uriRef.is_null() {
779 report_error(style, cur, b"xsl:import : missing href attribute\n");
780 if !uriRef.is_null() {
781 xmlFreeImpl(uriRef as *mut c_void);
782 }
783 if !base.is_null() {
784 xmlFreeImpl(base as *mut c_void);
785 }
786 if !uri.is_null() {
787 xmlFreeImpl(uri as *mut c_void);
788 }
789 return ret;
790 }
791
792 base = xmlNodeGetBase((*style).doc, cur);
793 uri = xmlBuildURI(uriRef as *const c_char, base as *const c_char);
794 if uri.is_null() {
795 report_error(style, cur, b"xsl:import : invalid URI reference ");
796 report_error(style, cur, cbytes(uriRef as *const u8));
797 report_error(style, cur, b"\n");
798 if !uriRef.is_null() {
799 xmlFreeImpl(uriRef as *mut c_void);
800 }
801 if !base.is_null() {
802 xmlFreeImpl(base as *mut c_void);
803 }
804 if !uri.is_null() {
805 xmlFreeImpl(uri as *mut c_void);
806 }
807 return ret;
808 }
809
810 if xslt_check_cycle(style, cur, uri) < 0 {
811 if !uriRef.is_null() {
812 xmlFreeImpl(uriRef as *mut c_void);
813 }
814 if !base.is_null() {
815 xmlFreeImpl(base as *mut c_void);
816 }
817 if !uri.is_null() {
818 xmlFreeImpl(uri as *mut c_void);
819 }
820 return ret;
821 }
822
823 let sec = crate::xslt::security::xsltGetDefaultSecurityPrefs();
825 if !sec.is_null() {
826 let secres = xslt_check_read(sec, ptr::null_mut(), uri);
827 if secres <= 0 {
828 if secres == 0 {
829 report_error(
830 ptr::null_mut(),
831 ptr::null_mut(),
832 b"xsl:import: read rights for ",
833 );
834 report_error(ptr::null_mut(), ptr::null_mut(), cbytes(uri as *const u8));
835 report_error(ptr::null_mut(), ptr::null_mut(), b" denied\n");
836 }
837 if !uriRef.is_null() {
838 xmlFreeImpl(uriRef as *mut c_void);
839 }
840 if !base.is_null() {
841 xmlFreeImpl(base as *mut c_void);
842 }
843 if !uri.is_null() {
844 xmlFreeImpl(uri as *mut c_void);
845 }
846 return ret;
847 }
848 }
849
850 let import = xslt_doc_default_loader(
851 uri,
852 (*style).dict,
853 XSLT_PARSE_OPTIONS,
854 style as *mut c_void,
855 XSLT_LOAD_STYLESHEET,
856 );
857 if import.is_null() {
858 report_error(style, cur, b"xsl:import : unable to load ");
859 report_error(style, cur, cbytes(uri as *const u8));
860 report_error(style, cur, b"\n");
861 if !uriRef.is_null() {
862 xmlFreeImpl(uriRef as *mut c_void);
863 }
864 if !base.is_null() {
865 xmlFreeImpl(base as *mut c_void);
866 }
867 if !uri.is_null() {
868 xmlFreeImpl(uri as *mut c_void);
869 }
870 return ret;
871 }
872
873 let res = xsltParseStylesheetImportedDoc(import, style);
874 if !res.is_null() {
875 (*res).next = (*style).imports;
876 (*style).imports = res;
877 if (*style).parent.is_null() {
878 xslt_fix_imported_comp_steps(style, res);
879 }
880 ret = 0;
881 } else {
882 crate::xml::tree::free_doc(import);
883 }
884
885 if !uriRef.is_null() {
886 xmlFreeImpl(uriRef as *mut c_void);
887 }
888 if !base.is_null() {
889 xmlFreeImpl(base as *mut c_void);
890 }
891 if !uri.is_null() {
892 xmlFreeImpl(uri as *mut c_void);
893 }
894
895 ret
896}
897
898#[no_mangle]
928pub unsafe extern "C" fn xsltParseStylesheetInclude(
929 style: *mut _xsltStylesheet,
930 cur: *mut _xmlNode,
931) -> c_int {
932 let mut ret: c_int = -1;
933 let mut uriRef: *mut xmlChar = ptr::null_mut();
934 let mut base: *mut xmlChar = ptr::null_mut();
935 let mut uri: *mut xmlChar = ptr::null_mut();
936
937 if cur.is_null() || style.is_null() {
938 return ret;
939 }
940
941 uriRef = xmlGetNsProp(cur, b"href\0".as_ptr() as *const xmlChar, ptr::null());
942 if uriRef.is_null() {
943 report_error(style, cur, b"xsl:include : missing href attribute\n");
944 if !uriRef.is_null() {
945 xmlFreeImpl(uriRef as *mut c_void);
946 }
947 if !base.is_null() {
948 xmlFreeImpl(base as *mut c_void);
949 }
950 if !uri.is_null() {
951 xmlFreeImpl(uri as *mut c_void);
952 }
953 return ret;
954 }
955
956 base = xmlNodeGetBase((*style).doc, cur);
957 uri = xmlBuildURI(uriRef as *const c_char, base as *const c_char);
958 if uri.is_null() {
959 report_error(style, cur, b"xsl:include : invalid URI reference ");
960 report_error(style, cur, cbytes(uriRef as *const u8));
961 report_error(style, cur, b"\n");
962 if !uriRef.is_null() {
963 xmlFreeImpl(uriRef as *mut c_void);
964 }
965 if !base.is_null() {
966 xmlFreeImpl(base as *mut c_void);
967 }
968 if !uri.is_null() {
969 xmlFreeImpl(uri as *mut c_void);
970 }
971 return ret;
972 }
973
974 if xslt_check_cycle(style, cur, uri) < 0 {
975 if !uriRef.is_null() {
976 xmlFreeImpl(uriRef as *mut c_void);
977 }
978 if !base.is_null() {
979 xmlFreeImpl(base as *mut c_void);
980 }
981 if !uri.is_null() {
982 xmlFreeImpl(uri as *mut c_void);
983 }
984 return ret;
985 }
986
987 let include = xsltLoadStyleDocument(style, uri);
988 if include.is_null() {
989 report_error(style, cur, b"xsl:include : unable to load ");
990 report_error(style, cur, cbytes(uri as *const u8));
991 report_error(style, cur, b"\n");
992 if !uriRef.is_null() {
993 xmlFreeImpl(uriRef as *mut c_void);
994 }
995 if !base.is_null() {
996 xmlFreeImpl(base as *mut c_void);
997 }
998 if !uri.is_null() {
999 xmlFreeImpl(uri as *mut c_void);
1000 }
1001 return ret;
1002 }
1003
1004 let oldDoc = (*style).doc;
1005 (*style).doc = (*include).doc;
1006 (*include).includes = (*style).includes;
1008 (*style).includes = include;
1009 let oldNopreproc = (*style).nopreproc;
1010 (*style).nopreproc = (*include).preproc;
1011 let result = xsltParseStylesheetProcess(style, (*include).doc);
1017 (*style).nopreproc = oldNopreproc;
1018 (*include).preproc = 1;
1019 (*style).includes = (*include).includes;
1020 (*style).doc = oldDoc;
1021 if result.is_null() {
1022 ret = -1;
1023 if !uriRef.is_null() {
1024 xmlFreeImpl(uriRef as *mut c_void);
1025 }
1026 if !base.is_null() {
1027 xmlFreeImpl(base as *mut c_void);
1028 }
1029 if !uri.is_null() {
1030 xmlFreeImpl(uri as *mut c_void);
1031 }
1032 return ret;
1033 }
1034 ret = 0;
1035
1036 if !uriRef.is_null() {
1037 xmlFreeImpl(uriRef as *mut c_void);
1038 }
1039 if !base.is_null() {
1040 xmlFreeImpl(base as *mut c_void);
1041 }
1042 if !uri.is_null() {
1043 xmlFreeImpl(uri as *mut c_void);
1044 }
1045 return ret;
1046}
1047
1048unsafe fn xslt_parse_content_error(style: *mut _xsltStylesheet, node: *mut _xmlNode) {
1054 if style.is_null() || node.is_null() {
1055 return;
1056 }
1057 if is_xslt_elem(node) {
1058 report_error(
1059 style,
1060 node,
1061 b"The XSLT-element is not allowed at this position.\n",
1062 );
1063 } else {
1064 report_error(
1065 style,
1066 node,
1067 b"The element is not allowed at this position.\n",
1068 );
1069 }
1070 (*style).errors += 1;
1071}
1072
1073#[no_mangle]
1094pub unsafe extern "C" fn xsltParseStylesheetOutput(
1095 style: *mut _xsltStylesheet,
1096 cur: *mut _xmlNode,
1097) {
1098 if cur.is_null() || style.is_null() || (*cur).type_ != XML_ELEMENT_NODE as c_int {
1099 return;
1100 }
1101
1102 let mut prop = xmlGetNsProp(cur, b"version\0".as_ptr() as *const xmlChar, ptr::null());
1104 if !prop.is_null() {
1105 if !(*style).version.is_null() {
1106 xmlFreeImpl((*style).version as *mut c_void);
1107 }
1108 (*style).version = prop;
1109 prop = ptr::null_mut();
1110 }
1111
1112 prop = xmlGetNsProp(cur, b"encoding\0".as_ptr() as *const xmlChar, ptr::null());
1114 if !prop.is_null() {
1115 if !(*style).encoding.is_null() {
1116 xmlFreeImpl((*style).encoding as *mut c_void);
1117 }
1118 (*style).encoding = prop;
1119 prop = ptr::null_mut();
1120 }
1121
1122 prop = xmlGetNsProp(cur, b"method\0".as_ptr() as *const xmlChar, ptr::null());
1124 if !prop.is_null() {
1125 if !(*style).method.is_null() {
1126 xmlFreeImpl((*style).method as *mut c_void);
1127 }
1128 (*style).method = ptr::null_mut();
1129 if !(*style).methodURI.is_null() {
1130 xmlFreeImpl((*style).methodURI as *mut c_void);
1131 }
1132 (*style).methodURI = ptr::null_mut();
1133
1134 let mut method = prop;
1135 let uri = crate::abi::exports_xslt_avt::xsltGetQNameURI(cur, &mut method);
1136 if method.is_null() {
1137 if !style.is_null() {
1138 (*style).errors += 1;
1139 }
1140 } else if uri.is_null() {
1141 if xmlStrEqual(method, b"xml\0".as_ptr() as *const xmlChar) != 0
1142 || xmlStrEqual(method, b"html\0".as_ptr() as *const xmlChar) != 0
1143 || xmlStrEqual(method, b"text\0".as_ptr() as *const xmlChar) != 0
1144 {
1145 (*style).method = method;
1146 } else {
1147 report_error(style, cur, b"invalid value for method: ");
1148 report_error(style, cur, cbytes(method as *const u8));
1149 report_error(style, cur, b"\n");
1150 if !style.is_null() {
1151 (*style).warnings += 1;
1152 }
1153 xmlFreeImpl(method as *mut c_void);
1154 }
1155 } else {
1156 (*style).method = method;
1157 (*style).methodURI = xmlStrdup(uri);
1158 }
1159 prop = ptr::null_mut();
1160 }
1161
1162 prop = xmlGetNsProp(
1164 cur,
1165 b"doctype-system\0".as_ptr() as *const xmlChar,
1166 ptr::null(),
1167 );
1168 if !prop.is_null() {
1169 if !(*style).doctypeSystem.is_null() {
1170 xmlFreeImpl((*style).doctypeSystem as *mut c_void);
1171 }
1172 (*style).doctypeSystem = prop;
1173 prop = ptr::null_mut();
1174 }
1175
1176 prop = xmlGetNsProp(
1178 cur,
1179 b"doctype-public\0".as_ptr() as *const xmlChar,
1180 ptr::null(),
1181 );
1182 if !prop.is_null() {
1183 if !(*style).doctypePublic.is_null() {
1184 xmlFreeImpl((*style).doctypePublic as *mut c_void);
1185 }
1186 (*style).doctypePublic = prop;
1187 prop = ptr::null_mut();
1188 }
1189
1190 prop = xmlGetNsProp(cur, b"standalone\0".as_ptr() as *const xmlChar, ptr::null());
1192 if !prop.is_null() {
1193 if xmlStrEqual(prop, b"yes\0".as_ptr() as *const xmlChar) != 0 {
1194 (*style).standalone = 1;
1195 } else if xmlStrEqual(prop, b"no\0".as_ptr() as *const xmlChar) != 0 {
1196 (*style).standalone = 0;
1197 } else {
1198 report_error(style, cur, b"invalid value for standalone\n");
1199 (*style).errors += 1;
1200 }
1201 xmlFreeImpl(prop as *mut c_void);
1202 }
1203
1204 prop = xmlGetNsProp(cur, b"indent\0".as_ptr() as *const xmlChar, ptr::null());
1206 if !prop.is_null() {
1207 if xmlStrEqual(prop, b"yes\0".as_ptr() as *const xmlChar) != 0 {
1208 (*style).indent = 1;
1209 } else if xmlStrEqual(prop, b"no\0".as_ptr() as *const xmlChar) != 0 {
1210 (*style).indent = 0;
1211 } else {
1212 report_error(style, cur, b"invalid value for indent\n");
1213 (*style).errors += 1;
1214 }
1215 xmlFreeImpl(prop as *mut c_void);
1216 }
1217
1218 prop = xmlGetNsProp(
1220 cur,
1221 b"omit-xml-declaration\0".as_ptr() as *const xmlChar,
1222 ptr::null(),
1223 );
1224 if !prop.is_null() {
1225 if xmlStrEqual(prop, b"yes\0".as_ptr() as *const xmlChar) != 0 {
1226 (*style).omitXmlDeclaration = 1;
1227 } else if xmlStrEqual(prop, b"no\0".as_ptr() as *const xmlChar) != 0 {
1228 (*style).omitXmlDeclaration = 0;
1229 } else {
1230 report_error(style, cur, b"invalid value for omit-xml-declaration\n");
1231 (*style).errors += 1;
1232 }
1233 xmlFreeImpl(prop as *mut c_void);
1234 }
1235
1236 let elements = xmlGetNsProp(
1238 cur,
1239 b"cdata-section-elements\0".as_ptr() as *const xmlChar,
1240 ptr::null(),
1241 );
1242 if !elements.is_null() {
1243 if (*style).cdataSection.is_null() {
1244 (*style).cdataSection = crate::xml::hash::hash_create(10) as *mut c_void;
1245 }
1246 if (*style).cdataSection.is_null() {
1247 xmlFreeImpl(elements as *mut c_void);
1248 return;
1249 }
1250
1251 let mut element: *mut xmlChar = elements;
1252 while *element != 0 {
1253 while matches!(*element, b' ' | b'\t' | b'\n' | b'\r') {
1254 element = element.add(1);
1255 }
1256 if *element == 0 {
1257 break;
1258 }
1259 let mut end = element;
1260 while *end != 0 && !matches!(*end, b' ' | b'\t' | b'\n' | b'\r') {
1261 end = end.add(1);
1262 }
1263 let len = end.offset_from(element) as usize;
1264 let token = xmlMallocImpl(len + 1) as *mut xmlChar;
1265 if !token.is_null() {
1266 core::ptr::copy_nonoverlapping(element, token, len);
1267 *token.add(len) = 0;
1268 if xmlValidateQName(token, 0) != 0 {
1269 report_error(
1270 style,
1271 cur,
1272 b"Attribute 'cdata-section-elements': The value is not a valid QName.\n",
1273 );
1274 xmlFreeImpl(token as *mut c_void);
1275 (*style).errors += 1;
1276 } else {
1277 let mut qname = token;
1278 let quri = crate::abi::exports_xslt_avt::xsltGetQNameURI(cur, &mut qname);
1279 if qname.is_null() {
1280 report_error(
1281 style,
1282 cur,
1283 b"Attribute 'cdata-section-elements': Not a valid QName.\n",
1284 );
1285 (*style).errors += 1;
1286 } else {
1287 let mut uri = quri;
1288 if uri.is_null() {
1291 let ns = xmlSearchNs((*style).doc, cur, ptr::null());
1292 if !ns.is_null() {
1293 uri = (*ns).href;
1294 }
1295 }
1296 crate::xml::hash::hash_add_entry2(
1297 (*style).cdataSection as *mut crate::xml::hash::HashTable,
1298 qname,
1299 uri,
1300 b"cdata\0".as_ptr() as *const c_void as *mut c_void,
1301 );
1302 xmlFreeImpl(qname as *mut c_void);
1303 }
1304 }
1305 }
1306 element = end;
1307 }
1308 xmlFreeImpl(elements as *mut c_void);
1309 }
1310
1311 prop = xmlGetNsProp(cur, b"media-type\0".as_ptr() as *const xmlChar, ptr::null());
1313 if !prop.is_null() {
1314 if !(*style).mediaType.is_null() {
1315 xmlFreeImpl((*style).mediaType as *mut c_void);
1316 }
1317 (*style).mediaType = prop;
1318 prop = ptr::null_mut();
1319 }
1320
1321 if !(*cur).children.is_null() {
1324 xslt_parse_content_error(style, (*cur).children);
1325 }
1326}
1327
1328#[no_mangle]
1350pub unsafe extern "C" fn xsltParseStylesheetAttributeSet(
1351 style: *mut _xsltStylesheet,
1352 cur: *mut _xmlNode,
1353) {
1354 if cur.is_null() || style.is_null() || (*cur).type_ != XML_ELEMENT_NODE as c_int {
1355 return;
1356 }
1357
1358 let value = xmlGetNsProp(cur, b"name\0".as_ptr() as *const xmlChar, ptr::null());
1359 if value.is_null() || *value == 0 {
1360 if !value.is_null() {
1361 xmlFreeImpl(value as *mut c_void);
1362 }
1363 return;
1364 }
1365 if xmlValidateQName(value, 0) != 0 {
1366 report_error(
1367 style,
1368 cur,
1369 b"xsl:attribute-set : The name is not a valid QName.\n",
1370 );
1371 (*style).errors += 1;
1372 xmlFreeImpl(value as *mut c_void);
1373 return;
1374 }
1375 xmlFreeImpl(value as *mut c_void);
1376
1377 crate::xslt::attributes::xsltCompileAttrSet(style, cur);
1378}
1379
1380#[no_mangle]
1405pub unsafe extern "C" fn xsltParseGlobalVariable(style: *mut _xsltStylesheet, cur: *mut _xmlNode) {
1406 if cur.is_null() || style.is_null() || (*cur).type_ != XML_ELEMENT_NODE as c_int {
1407 return;
1408 }
1409
1410 let name = xmlGetNsProp(cur, b"name\0".as_ptr() as *const xmlChar, ptr::null());
1411 if name.is_null() {
1412 report_error(style, cur, b"xsl:variable : missing name attribute\n");
1413 return;
1414 }
1415
1416 let mut tmp = (*style).variables;
1419 while !tmp.is_null() {
1420 if ((*tmp).flags & XSLT_VAR_PARAM) == 0
1421 && !(*tmp).name.is_null()
1422 && xmlStrEqual((*tmp).name, name) != 0
1423 {
1424 report_error(style, cur, b"redefinition of global variable ");
1425 report_error(style, cur, cbytes(name as *const u8));
1426 report_error(style, cur, b"\n");
1427 (*style).errors += 1;
1428 break;
1429 }
1430 tmp = (*tmp).next;
1431 }
1432 xmlFreeImpl(name as *mut c_void);
1433
1434 if !(*cur).children.is_null() {
1436 xsltParseTemplateContent(style, cur);
1437 }
1438
1439 crate::xslt::compiler::compile_variable(style, cur, 0, 0);
1440}
1441
1442#[no_mangle]
1462pub unsafe extern "C" fn xsltParseGlobalParam(style: *mut _xsltStylesheet, cur: *mut _xmlNode) {
1463 if cur.is_null() || style.is_null() || (*cur).type_ != XML_ELEMENT_NODE as c_int {
1464 return;
1465 }
1466
1467 let name = xmlGetNsProp(cur, b"name\0".as_ptr() as *const xmlChar, ptr::null());
1468 if name.is_null() {
1469 report_error(style, cur, b"xsl:param : missing name attribute\n");
1470 return;
1471 }
1472 xmlFreeImpl(name as *mut c_void);
1473
1474 if !(*cur).children.is_null() {
1476 xsltParseTemplateContent(style, cur);
1477 }
1478
1479 crate::xslt::compiler::compile_variable(style, cur, 0, 1);
1480}
1481
1482#[no_mangle]
1515pub unsafe extern "C" fn xsltParseTemplateContent(
1516 style: *mut _xsltStylesheet,
1517 templ: *mut _xmlNode,
1518) {
1519 if style.is_null() || templ.is_null() || (*templ).type_ == XML_NAMESPACE_DECL as c_int {
1520 return;
1521 }
1522
1523 let mut cur = (*templ).children;
1524 while !cur.is_null() {
1525 if !(*style).principal.is_null() {
1526 (*(*style).principal).opCount += 1;
1527 }
1528
1529 if is_xslt_elem(cur) {
1530 xsltStylePreCompute(style, cur);
1531 } else if !(*cur).ns.is_null() && !ext_ns_registered((*(*cur).ns).href) {
1534 } else if !(*cur).ns.is_null() && ext_ns_registered((*(*cur).ns).href) {
1537 xsltStylePreCompute(style, cur);
1539 } else if (*cur).type_ == XML_ELEMENT_NODE as c_int {
1540 if (*cur).ns.is_null() && !(*style).defaultAlias.is_null() {
1543 (*cur).ns = xmlSearchNsByHref((*cur).doc, cur, (*style).defaultAlias);
1544 }
1545 if !(*cur).properties.is_null() {
1546 let mut attr = (*cur).properties;
1547 while !attr.is_null() {
1548 xsltCompileAttr(style, attr);
1549 attr = (*attr).next;
1550 }
1551 }
1552 }
1553
1554 if !(*cur).children.is_null() {
1557 if (*(*cur).children).type_ != XML_ENTITY_DECL as c_int {
1558 cur = (*cur).children;
1559 continue;
1560 }
1561 }
1562 if !(*cur).next.is_null() {
1563 cur = (*cur).next;
1564 continue;
1565 }
1566 loop {
1567 cur = (*cur).parent;
1568 if cur.is_null() {
1569 break;
1570 }
1571 if cur == templ {
1572 cur = ptr::null_mut();
1573 break;
1574 }
1575 if !(*cur).next.is_null() {
1576 cur = (*cur).next;
1577 break;
1578 }
1579 }
1580 }
1581
1582 let mut cur = (*templ).children;
1584 while !cur.is_null() {
1585 if is_xslt_elem(cur) && !is_xslt_name(cur, b"param") {
1586 break;
1587 }
1588 cur = (*cur).next;
1589 }
1590
1591 while !cur.is_null() {
1593 if is_xslt_elem(cur) && is_xslt_name(cur, b"param") {
1594 let param = cur;
1595 report_error(
1596 style,
1597 cur,
1598 b"xsltParseTemplateContent: ignoring misplaced param element\n",
1599 );
1600 if !style.is_null() {
1601 (*style).warnings += 1;
1602 }
1603 cur = (*cur).next;
1604 crate::xml::tree::unlink_node(param);
1605 crate::xml::tree::free_node(param);
1606 } else {
1607 break;
1608 }
1609 }
1610}
1611
1612unsafe fn ext_ns_registered(uri: *const xmlChar) -> bool {
1615 if uri.is_null() {
1616 return false;
1617 }
1618 let mut cur = XSLT_ELEMENTS_REGISTRY;
1619 while !cur.is_null() {
1620 if !(*cur).URI.is_null() && xmlStrEqual((*cur).URI, uri) != 0 {
1621 return true;
1622 }
1623 cur = (*cur).next;
1624 }
1625 false
1626}
1627
1628#[no_mangle]
1653pub unsafe extern "C" fn xsltCompileAttr(style: *mut _xsltStylesheet, attr: *mut _xmlAttr) {
1654 if style.is_null() || attr.is_null() || (*attr).children.is_null() {
1655 return;
1656 }
1657 if (*(*attr).children).type_ != XML_TEXT_NODE as c_int || !(*(*attr).children).next.is_null() {
1658 report_error(
1659 style,
1660 (*attr).parent,
1661 b"Attribute ': The content is expected to be a single text node when compiling an AVT.\n",
1662 );
1663 (*style).errors += 1;
1664 return;
1665 }
1666
1667 let str_ = (*(*attr).children).content;
1668 if xmlStrchr(str_, b'{' as xmlChar).is_null() && xmlStrchr(str_, b'}' as xmlChar).is_null() {
1669 return;
1670 }
1671 if !(*attr).psvi.is_null() {
1672 return;
1674 }
1675
1676 let mut cur = str_;
1679 while *cur != 0 {
1680 if *cur == b'{' {
1681 if !cur.add(1).is_null() && *cur.add(1) == b'{' {
1682 cur = cur.add(2);
1684 continue;
1685 }
1686 if !cur.add(1).is_null() && *cur.add(1) == b'}' {
1687 cur = cur.add(2);
1689 continue;
1690 }
1691 let mut p = cur.add(1);
1694 while *p != 0 && *p != b'}' {
1695 if *p == b'\'' || *p == b'"' {
1696 let delim = *p;
1697 p = p.add(1);
1698 while *p != 0 && *p != delim {
1699 p = p.add(1);
1700 }
1701 if *p != 0 {
1702 p = p.add(1);
1703 }
1704 } else {
1705 p = p.add(1);
1706 }
1707 }
1708 if *p == 0 {
1709 report_error(
1710 style,
1711 (*attr).parent,
1712 b"Attribute ': The AVT has an unmatched '{'.\n",
1713 );
1714 (*style).errors += 1;
1715 return;
1716 }
1717 cur = p.add(1);
1718 } else if *cur == b'}' {
1719 if !cur.add(1).is_null() && *cur.add(1) == b'}' {
1720 cur = cur.add(2);
1722 continue;
1723 }
1724 report_error(
1725 style,
1726 (*attr).parent,
1727 b"Attribute ': The AVT has an unmatched '}'.\n",
1728 );
1729 return;
1730 } else {
1731 cur = cur.add(1);
1732 }
1733 }
1734}
1735
1736unsafe fn xslt_free_style_pre_comp(comp: *mut c_void) {
1745 if comp.is_null() {
1746 return;
1747 }
1748 xmlFreeImpl(comp);
1749}
1750
1751unsafe extern "C" fn xslt_free_elem_pre_comp(comp: *mut c_void) {
1753 xmlFreeImpl(comp);
1754}
1755
1756unsafe fn xslt_new_style_pre_comp(
1767 style: *mut _xsltStylesheet,
1768 type_: c_int,
1769) -> *mut _xsltStylePreComp {
1770 if style.is_null() {
1771 return ptr::null_mut();
1772 }
1773 let cur = xmlMallocImpl(core::mem::size_of::<_xsltStylePreComp>()) as *mut _xsltStylePreComp;
1774 if cur.is_null() {
1775 report_error(
1776 style,
1777 ptr::null_mut(),
1778 b"xsltNewStylePreComp : malloc failed\n",
1779 );
1780 (*style).errors += 1;
1781 return ptr::null_mut();
1782 }
1783 ptr::write_bytes(cur as *mut u8, 0, core::mem::size_of::<_xsltStylePreComp>());
1784
1785 (*cur).base.type_ = type_;
1786 (*cur).base.next = (*style).preComps as *mut _xsltElemPreComp;
1787 (*style).preComps = cur as *mut c_void;
1788
1789 cur
1790}
1791
1792#[no_mangle]
1812pub unsafe extern "C" fn xsltDocumentComp(
1813 style: *mut _xsltStylesheet,
1814 inst: *mut _xmlNode,
1815 _function: Option<xsltTransformFunction>,
1816) -> *mut _xsltElemPreComp {
1817 if style.is_null() || inst.is_null() || (*inst).type_ != XML_ELEMENT_NODE as c_int {
1818 return ptr::null_mut();
1819 }
1820
1821 let comp = xslt_new_style_pre_comp(style, XSLT_FUNC_DOCUMENT);
1822 if comp.is_null() {
1823 return ptr::null_mut();
1824 }
1825 (*comp).base.inst = inst;
1826 (*comp).ver11 = 0;
1827 let mut filename: *const xmlChar = ptr::null();
1828
1829 if is_xslt_name(inst, b"output") {
1830 filename = crate::abi::exports_xslt_avt::xsltEvalStaticAttrValueTemplate(
1832 style,
1833 inst,
1834 b"file\0".as_ptr() as *const xmlChar,
1835 ptr::null(),
1836 &mut (*comp).has_filename,
1837 );
1838 } else if is_xslt_name(inst, b"write") {
1839 } else if is_xslt_name(inst, b"document") {
1841 if !(*inst).ns.is_null() {
1842 if xmlStrEqual(
1843 (*(*inst).ns).href,
1844 XSLT_NAMESPACE.as_ptr() as *const xmlChar,
1845 ) != 0
1846 {
1847 (*comp).ver11 = 1;
1849 }
1850 }
1852 filename = crate::abi::exports_xslt_avt::xsltEvalStaticAttrValueTemplate(
1853 style,
1854 inst,
1855 b"href\0".as_ptr() as *const xmlChar,
1856 ptr::null(),
1857 &mut (*comp).has_filename,
1858 );
1859 }
1860 if (*comp).has_filename != 0 {
1861 (*comp).filename = filename;
1862 }
1863
1864 &mut (*comp).base as *mut _xsltElemPreComp
1865}
1866
1867unsafe fn xslt_init_elem_pre_comp(
1878 comp: *mut _xsltElemPreComp,
1879 style: *mut _xsltStylesheet,
1880 inst: *mut _xmlNode,
1881 function: Option<xsltTransformFunction>,
1882 free_func: Option<xsltElemPreCompDeallocator>,
1883) {
1884 (*comp).type_ = XSLT_FUNC_EXTENSION;
1885 (*comp).func = function;
1886 (*comp).inst = inst;
1887 (*comp).free = free_func;
1888
1889 (*comp).next = (*style).preComps as *mut _xsltElemPreComp;
1890 (*style).preComps = comp as *mut c_void;
1891}
1892
1893unsafe fn xslt_new_elem_pre_comp(
1901 style: *mut _xsltStylesheet,
1902 inst: *mut _xmlNode,
1903 function: Option<xsltTransformFunction>,
1904) -> *mut _xsltElemPreComp {
1905 let cur = xmlMallocImpl(core::mem::size_of::<_xsltElemPreComp>()) as *mut _xsltElemPreComp;
1906 if cur.is_null() {
1907 report_error(
1908 style,
1909 ptr::null_mut(),
1910 b"xsltNewExtElement : malloc failed\n",
1911 );
1912 return ptr::null_mut();
1913 }
1914 ptr::write_bytes(cur as *mut u8, 0, core::mem::size_of::<_xsltElemPreComp>());
1915
1916 xslt_init_elem_pre_comp(cur, style, inst, function, Some(xslt_free_elem_pre_comp));
1917
1918 cur
1919}
1920
1921#[no_mangle]
1950pub unsafe extern "C" fn xsltPreComputeExtModuleElement(
1951 style: *mut _xsltStylesheet,
1952 inst: *mut _xmlNode,
1953) -> *mut _xsltElemPreComp {
1954 if style.is_null()
1955 || inst.is_null()
1956 || (*inst).type_ != XML_ELEMENT_NODE as c_int
1957 || (*inst).ns.is_null()
1958 {
1959 return ptr::null_mut();
1960 }
1961
1962 let ext = ext_element_lookup((*inst).name, (*(*inst).ns).href);
1963 if ext.is_null() {
1964 return ptr::null_mut();
1965 }
1966
1967 let mut comp: *mut _xsltElemPreComp = ptr::null_mut();
1968 if let Some(precomp) = (*ext).precomp {
1969 comp = precomp(style, inst, (*ext).transform) as *mut _xsltElemPreComp;
1970 }
1971 if comp.is_null() {
1972 comp = xslt_new_elem_pre_comp(style, inst, (*ext).transform);
1974 }
1975
1976 comp
1977}
1978
1979#[no_mangle]
1997pub unsafe extern "C" fn xsltFreeStylePreComps(style: *mut _xsltStylesheet) {
1998 if style.is_null() {
1999 return;
2000 }
2001
2002 let mut cur = (*style).preComps as *mut _xsltElemPreComp;
2003 (*style).preComps = ptr::null_mut();
2004 while !cur.is_null() {
2005 let next = (*cur).next;
2006 if (*cur).type_ == XSLT_FUNC_EXTENSION {
2007 if let Some(free_func) = (*cur).free {
2008 free_func(cur as *mut c_void);
2009 } else {
2010 xslt_free_style_pre_comp(cur as *mut c_void);
2011 }
2012 } else {
2013 xslt_free_style_pre_comp(cur as *mut c_void);
2014 }
2015 cur = next;
2016 }
2017}
2018
2019#[no_mangle]
2047pub unsafe extern "C" fn xsltStylePreCompute(style: *mut _xsltStylesheet, inst: *mut _xmlNode) {
2048 if inst.is_null() || (*inst).type_ != XML_ELEMENT_NODE as c_int || !(*inst).psvi.is_null() {
2049 return;
2050 }
2051
2052 if is_xslt_elem(inst) {
2053 if is_xslt_name(inst, b"apply-templates") {
2054 xslt_check_instruction_element(style, inst);
2055 } else if is_xslt_name(inst, b"with-param") {
2057 xslt_check_parent_element(
2058 style,
2059 inst,
2060 b"apply-templates",
2061 b"call-template\0".as_ptr() as *const u8,
2062 );
2063 } else if is_xslt_name(inst, b"value-of") {
2065 xslt_check_instruction_element(style, inst);
2066 } else if is_xslt_name(inst, b"copy") {
2067 xslt_check_instruction_element(style, inst);
2068 } else if is_xslt_name(inst, b"copy-of") {
2069 xslt_check_instruction_element(style, inst);
2070 } else if is_xslt_name(inst, b"if") {
2071 xslt_check_instruction_element(style, inst);
2072 } else if is_xslt_name(inst, b"when") {
2073 xslt_check_parent_element(style, inst, b"choose", ptr::null());
2074 } else if is_xslt_name(inst, b"choose") {
2075 xslt_check_instruction_element(style, inst);
2076 } else if is_xslt_name(inst, b"for-each") {
2077 xslt_check_instruction_element(style, inst);
2078 } else if is_xslt_name(inst, b"apply-imports") {
2079 xslt_check_instruction_element(style, inst);
2080 } else if is_xslt_name(inst, b"attribute") {
2081 let parent = (*inst).parent;
2082 let is_in_attr_set = !parent.is_null()
2083 && (*parent).type_ == XML_ELEMENT_NODE as c_int
2084 && !(*parent).ns.is_null()
2085 && xmlStrEqual(
2086 (*(*parent).ns).href,
2087 XSLT_NAMESPACE.as_ptr() as *const xmlChar,
2088 ) != 0
2089 && is_xslt_name(parent, b"attribute-set");
2090 if !is_in_attr_set {
2091 xslt_check_instruction_element(style, inst);
2092 }
2093 } else if is_xslt_name(inst, b"element") {
2095 xslt_check_instruction_element(style, inst);
2096 } else if is_xslt_name(inst, b"text") {
2097 xslt_check_instruction_element(style, inst);
2098 } else if is_xslt_name(inst, b"sort") {
2099 xslt_check_parent_element(
2100 style,
2101 inst,
2102 b"apply-templates",
2103 b"for-each\0".as_ptr() as *const u8,
2104 );
2105 } else if is_xslt_name(inst, b"comment") {
2106 xslt_check_instruction_element(style, inst);
2107 } else if is_xslt_name(inst, b"number") {
2108 xslt_check_instruction_element(style, inst);
2109 } else if is_xslt_name(inst, b"processing-instruction") {
2110 xslt_check_instruction_element(style, inst);
2111 } else if is_xslt_name(inst, b"call-template") {
2112 xslt_check_instruction_element(style, inst);
2113 } else if is_xslt_name(inst, b"param") {
2114 if xslt_check_top_level_element(style, inst, 0) == 0 {
2115 xslt_check_instruction_element(style, inst);
2116 }
2117 } else if is_xslt_name(inst, b"variable") {
2119 if xslt_check_top_level_element(style, inst, 0) == 0 {
2120 xslt_check_instruction_element(style, inst);
2121 }
2122 } else if is_xslt_name(inst, b"otherwise") {
2124 xslt_check_parent_element(style, inst, b"choose", ptr::null());
2125 xslt_check_instruction_element(style, inst);
2126 return;
2127 } else if is_xslt_name(inst, b"template") {
2128 xslt_check_top_level_element(style, inst, 1);
2129 return;
2130 } else if is_xslt_name(inst, b"output") {
2131 xslt_check_top_level_element(style, inst, 1);
2132 return;
2133 } else if is_xslt_name(inst, b"preserve-space") {
2134 xslt_check_top_level_element(style, inst, 1);
2135 return;
2136 } else if is_xslt_name(inst, b"strip-space") {
2137 xslt_check_top_level_element(style, inst, 1);
2138 return;
2139 } else if is_xslt_name(inst, b"stylesheet") || is_xslt_name(inst, b"transform") {
2140 let parent = (*inst).parent;
2141 if parent.is_null() || (*parent).type_ != XML_DOCUMENT_NODE as c_int {
2142 report_error(style, inst, b"element only allowed only as root element\n");
2143 (*style).errors += 1;
2144 }
2145 return;
2146 } else if is_xslt_name(inst, b"key") {
2147 xslt_check_top_level_element(style, inst, 1);
2148 return;
2149 } else if is_xslt_name(inst, b"message") {
2150 xslt_check_instruction_element(style, inst);
2151 return;
2152 } else if is_xslt_name(inst, b"attribute-set") {
2153 xslt_check_top_level_element(style, inst, 1);
2154 return;
2155 } else if is_xslt_name(inst, b"namespace-alias") {
2156 xslt_check_top_level_element(style, inst, 1);
2157 return;
2158 } else if is_xslt_name(inst, b"include") {
2159 xslt_check_top_level_element(style, inst, 1);
2160 return;
2161 } else if is_xslt_name(inst, b"import") {
2162 xslt_check_top_level_element(style, inst, 1);
2163 return;
2164 } else if is_xslt_name(inst, b"decimal-format") {
2165 xslt_check_top_level_element(style, inst, 1);
2166 return;
2167 } else if is_xslt_name(inst, b"fallback") {
2168 xslt_check_instruction_element(style, inst);
2169 return;
2170 } else if is_xslt_name(inst, b"document") {
2171 xslt_check_instruction_element(style, inst);
2172 (*inst).psvi = xsltDocumentComp(style, inst, None) as *mut c_void;
2173 } else if style.is_null() || (*style).forwards_compatible == 0 {
2174 report_error(
2175 style,
2176 inst,
2177 b"xsltStylePreCompute: unknown xsl: instruction\n",
2178 );
2179 if !style.is_null() {
2180 (*style).warnings += 1;
2181 }
2182 }
2183 } else {
2184 (*inst).psvi = xsltPreComputeExtModuleElement(style, inst) as *mut c_void;
2187 if (*inst).psvi.is_null() {
2188 (*inst).psvi = XSLT_EXT_MARKER.as_ptr() as *mut c_void;
2189 }
2190 }
2191}
2192
2193unsafe fn xslt_check_top_level_element(
2198 style: *mut _xsltStylesheet,
2199 inst: *mut _xmlNode,
2200 err: c_int,
2201) -> c_int {
2202 if style.is_null() || inst.is_null() || (*inst).ns.is_null() {
2203 return -1;
2204 }
2205
2206 let parent = (*inst).parent;
2207 if parent.is_null() {
2208 if err != 0 {
2209 report_error(style, inst, b"internal problem: element has no parent\n");
2210 (*style).errors += 1;
2211 }
2212 return 0;
2213 }
2214 if (*parent).ns.is_null()
2215 || (*parent).type_ != XML_ELEMENT_NODE as c_int
2216 || (xmlStrEqual((*(*parent).ns).href, (*(*inst).ns).href) == 0)
2217 || (!is_xslt_name(parent, b"stylesheet") && !is_xslt_name(parent, b"transform"))
2218 {
2219 if err != 0 {
2220 report_error(
2221 style,
2222 inst,
2223 b"element only allowed as child of stylesheet\n",
2224 );
2225 (*style).errors += 1;
2226 }
2227 return 0;
2228 }
2229 1
2230}
2231
2232unsafe fn xslt_check_instruction_element(style: *mut _xsltStylesheet, inst: *mut _xmlNode) {
2235 if style.is_null() || inst.is_null() || (*inst).ns.is_null() || (*style).literal_result != 0 {
2236 return;
2237 }
2238
2239 let has_ext = !(*style).extInfos.is_null() || !ext_ns_registered(ptr::null());
2240
2241 let mut parent = (*inst).parent;
2242 if parent.is_null() {
2243 report_error(style, inst, b"internal problem: element has no parent\n");
2244 (*style).errors += 1;
2245 return;
2246 }
2247 while !parent.is_null() && (*parent).type_ != XML_DOCUMENT_NODE as c_int {
2248 if ((*parent).ns == (*inst).ns
2249 || (!(*parent).ns.is_null()
2250 && xmlStrEqual((*(*parent).ns).href, (*(*inst).ns).href) != 0))
2251 && (is_xslt_name(parent, b"template")
2252 || is_xslt_name(parent, b"param")
2253 || is_xslt_name(parent, b"attribute")
2254 || is_xslt_name(parent, b"variable"))
2255 {
2256 return;
2257 }
2258
2259 if has_ext && !(*parent).ns.is_null() && ext_ns_registered((*(*parent).ns).href) {
2262 return;
2263 }
2264
2265 parent = (*parent).parent;
2266 }
2267 report_error(
2268 style,
2269 inst,
2270 b"element only allowed within a template, variable or param\n",
2271 );
2272 (*style).errors += 1;
2273}
2274
2275unsafe fn xslt_check_parent_element(
2278 style: *mut _xsltStylesheet,
2279 inst: *mut _xmlNode,
2280 allow1: &[u8],
2281 allow2: *const u8,
2282) {
2283 if style.is_null() || inst.is_null() || (*inst).ns.is_null() || (*style).literal_result != 0 {
2284 return;
2285 }
2286
2287 let parent = (*inst).parent;
2288 if parent.is_null() {
2289 report_error(style, inst, b"internal problem: element has no parent\n");
2290 (*style).errors += 1;
2291 return;
2292 }
2293 let allow2_bytes: &[u8] = if allow2.is_null() {
2294 b""
2295 } else {
2296 core::slice::from_raw_parts(allow2, libc::strlen(allow2 as *const libc::c_char) as usize)
2297 };
2298 if ((*parent).ns == (*inst).ns
2299 || (!(*parent).ns.is_null() && xmlStrEqual((*(*parent).ns).href, (*(*inst).ns).href) != 0))
2300 && (is_xslt_name(parent, allow1)
2301 || (!allow2_bytes.is_empty() && is_xslt_name(parent, allow2_bytes)))
2302 {
2303 return;
2304 }
2305
2306 if !ext_ns_registered(ptr::null()) {
2307 let mut p = parent;
2308 while !p.is_null() && (*p).type_ != XML_DOCUMENT_NODE as c_int {
2309 if !(*p).ns.is_null() && ext_ns_registered((*(*p).ns).href) {
2310 return;
2311 }
2312 p = (*p).parent;
2313 }
2314 }
2315 report_error(style, inst, b"element is not allowed within that context\n");
2316 (*style).errors += 1;
2317}
2318
2319#[no_mangle]
2349pub unsafe extern "C" fn xsltNormalizeCompSteps(
2350 payload: *mut c_void,
2351 data: *mut c_void,
2352 _name: *const xmlChar,
2353) {
2354 let _ = (payload, data);
2355}
2356
2357#[no_mangle]
2388pub unsafe extern "C" fn xsltNewStyleDocument(
2389 style: *mut _xsltStylesheet,
2390 doc: *mut _xmlDoc,
2391) -> *mut _xsltDocument {
2392 let cur = xmlMallocImpl(core::mem::size_of::<_xsltDocument>()) as *mut _xsltDocument;
2393 if cur.is_null() {
2394 report_error(
2395 style,
2396 doc as *mut _xmlNode,
2397 b"xsltNewStyleDocument : malloc failed\n",
2398 );
2399 return ptr::null_mut();
2400 }
2401 ptr::write_bytes(cur as *mut u8, 0, core::mem::size_of::<_xsltDocument>());
2402 (*cur).doc = doc;
2403 if !style.is_null() {
2404 (*cur).next = (*style).docList;
2405 (*style).docList = cur;
2406 }
2407 cur
2408}
2409
2410#[no_mangle]
2432pub unsafe extern "C" fn xsltLoadStyleDocument(
2433 style: *mut _xsltStylesheet,
2434 uri: *const xmlChar,
2435) -> *mut _xsltDocument {
2436 if style.is_null() || uri.is_null() {
2437 return ptr::null_mut();
2438 }
2439
2440 let sec = crate::xslt::security::xsltGetDefaultSecurityPrefs();
2442 if !sec.is_null() {
2443 let res = xslt_check_read(sec, ptr::null_mut(), uri);
2444 if res <= 0 {
2445 if res == 0 {
2446 report_error(
2447 ptr::null_mut(),
2448 ptr::null_mut(),
2449 b"xsltLoadStyleDocument: read rights for ",
2450 );
2451 report_error(ptr::null_mut(), ptr::null_mut(), cbytes(uri as *const u8));
2452 report_error(ptr::null_mut(), ptr::null_mut(), b" denied\n");
2453 }
2454 return ptr::null_mut();
2455 }
2456 }
2457
2458 let mut ret = (*style).docList;
2460 while !ret.is_null() {
2461 if !(*ret).doc.is_null()
2462 && !(*(*ret).doc).URL.is_null()
2463 && xmlStrEqual((*(*ret).doc).URL, uri) != 0
2464 {
2465 return ret;
2466 }
2467 ret = (*ret).next;
2468 }
2469
2470 let doc = xslt_doc_default_loader(
2471 uri,
2472 (*style).dict,
2473 XSLT_PARSE_OPTIONS,
2474 style as *mut c_void,
2475 XSLT_LOAD_STYLESHEET,
2476 );
2477 if doc.is_null() {
2478 return ptr::null_mut();
2479 }
2480
2481 let ret = xsltNewStyleDocument(style, doc);
2482 if ret.is_null() {
2483 crate::xml::tree::free_doc(doc);
2484 }
2485 ret
2486}
2487
2488#[no_mangle]
2518pub unsafe extern "C" fn xsltFreeStyleDocuments(style: *mut _xsltStylesheet) {
2519 if style.is_null() {
2520 return;
2521 }
2522
2523 let mut cur = (*style).docList;
2524 (*style).docList = ptr::null_mut();
2525 while !cur.is_null() {
2526 let doc = cur;
2527 cur = (*cur).next;
2528 if (*doc).main == 0 && !(*doc).doc.is_null() {
2529 crate::xml::tree::free_doc((*doc).doc);
2530 }
2531 xmlFreeImpl(doc as *mut c_void);
2532 }
2533}
2534
2535#[no_mangle]
2559pub unsafe extern "C" fn xsltInitGlobals() {
2560 if XSLT_GLOBALS_INITIALIZED == 0 {
2561 XSLT_GLOBALS_INITIALIZED = 1;
2562 }
2563}
2564
2565#[no_mangle]
2586pub unsafe extern "C" fn xsltUninit() {
2587 XSLT_GLOBALS_INITIALIZED = 0;
2588}
2589
2590#[no_mangle]
2616pub unsafe extern "C" fn xsltFreeExts(style: *mut _xsltStylesheet) {
2617 if style.is_null() {
2618 return;
2619 }
2620 }
2622
2623#[no_mangle]
2652pub unsafe extern "C" fn xsltShutdownExts(style: *mut _xsltStylesheet) {
2653 if style.is_null() {
2654 return;
2655 }
2656 if (*style).extInfos.is_null() {
2657 return;
2658 }
2659 crate::xml::hash::hash_free((*style).extInfos as *mut crate::xml::hash::HashTable, None);
2663 (*style).extInfos = ptr::null_mut();
2664}
2665
2666#[no_mangle]
2685pub unsafe extern "C" fn xsltDebugDumpExtensions(output: *mut libc::FILE) {
2686 let out = if output.is_null() {
2687 libc::fdopen(1, b"w\0".as_ptr() as *const c_char)
2688 } else {
2689 output
2690 };
2691
2692 if out.is_null() {
2693 return;
2694 }
2695
2696 libc::fprintf(
2697 out,
2698 b"Registered XSLT Extensions\n--------------------------\n\0".as_ptr() as *const c_char,
2699 );
2700 libc::fprintf(
2701 out,
2702 b"No registered extension functions\n\0".as_ptr() as *const c_char,
2703 );
2704 libc::fprintf(
2705 out,
2706 b"\nNo registered top-level extension elements\n\0".as_ptr() as *const c_char,
2707 );
2708
2709 if XSLT_ELEMENTS_REGISTRY.is_null() {
2710 libc::fprintf(
2711 out,
2712 b"\nNo registered instruction extension elements\n\0".as_ptr() as *const c_char,
2713 );
2714 } else {
2715 libc::fprintf(
2716 out,
2717 b"\nRegistered instruction extension elements:\n\0".as_ptr() as *const c_char,
2718 );
2719 let mut cur = XSLT_ELEMENTS_REGISTRY;
2720 while !cur.is_null() {
2721 if !(*cur).URI.is_null() && !(*cur).name.is_null() {
2722 libc::fprintf(
2723 out,
2724 b"{%s}%s\n\0".as_ptr() as *const c_char,
2725 (*cur).URI as *const c_char,
2726 (*cur).name as *const c_char,
2727 );
2728 }
2729 cur = (*cur).next;
2730 }
2731 }
2732
2733 if XSLT_MODULES_REGISTRY.is_null() {
2734 libc::fprintf(
2735 out,
2736 b"\nNo registered extension modules\n\0".as_ptr() as *const c_char,
2737 );
2738 } else {
2739 libc::fprintf(
2740 out,
2741 b"\nRegistered extension modules:\n\0".as_ptr() as *const c_char,
2742 );
2743 let mut cur = XSLT_MODULES_REGISTRY;
2744 while !cur.is_null() {
2745 if !(*cur).URI.is_null() {
2746 libc::fprintf(
2747 out,
2748 b"%s\n\0".as_ptr() as *const c_char,
2749 (*cur).URI as *const c_char,
2750 );
2751 }
2752 cur = (*cur).next;
2753 }
2754 }
2755}