1#![allow(
31 missing_docs,
32 non_snake_case,
33 non_camel_case_types,
34 non_upper_case_globals
35)]
36#![allow(clippy::missing_safety_doc)]
37#![allow(clippy::not_unsafe_ptr_arg_deref)]
38#![allow(clippy::comparison_chain)]
39#![allow(clippy::needless_range_loop)]
40#![allow(clippy::manual_swap)]
41#![allow(unused_assignments)]
44#![allow(missing_debug_implementations)]
45
46use core::ffi::c_void;
47use core::ptr;
48use std::os::raw::{c_char, c_int};
49use std::sync::atomic::{AtomicI32, Ordering};
50
51use crate::abi::allocator::{xmlFreeImpl, xmlMallocImpl, xmlMallocZero, xmlReallocImpl};
52use crate::abi::constants::*;
53use crate::abi::structs::*;
54use crate::abi::types::xmlElementType::*;
55use crate::abi::types::*;
56use crate::xml::entities;
57use crate::xml::hash;
58use crate::xml::tree;
59
60unsafe fn dup_str(s: *const xmlChar) -> *mut xmlChar {
66 unsafe { crate::abi::exports_xml2::xmlStrdup(s) }
67}
68
69unsafe fn str_len(s: *const xmlChar) -> c_int {
71 unsafe { crate::abi::exports_xml2::xmlStrlen(s) }
72}
73
74unsafe fn str_prefix(name: *const xmlChar, max: usize) -> Vec<u8> {
77 if name.is_null() {
78 return vec![0];
79 }
80 let mut v = Vec::new();
81 let mut i = 0usize;
82 while i < max {
83 let c = unsafe { *name.add(i) };
84 if c == 0 {
85 break;
86 }
87 v.push(c);
88 i += 1;
89 }
90 v.push(0);
91 v
92}
93
94unsafe fn str_eq_or_ptr(a: *const xmlChar, b: *const xmlChar) -> bool {
96 if a == b {
97 return true;
98 }
99 unsafe { crate::abi::exports_xml2::xmlStrEqual(a, b) != 0 }
100}
101
102unsafe fn strcasecmp_eq(a: *const xmlChar, lit: &[u8]) -> bool {
104 if a.is_null() {
105 return false;
106 }
107 let mut i = 0usize;
108 loop {
109 let ca = unsafe { *a.add(i) };
110 if i >= lit.len() {
111 return ca == 0;
112 }
113 let cb = lit[i];
114 if ca == 0 || ca.to_ascii_lowercase() != cb.to_ascii_lowercase() {
115 return false;
116 }
117 i += 1;
118 }
119}
120
121unsafe fn is_str_xml(s: *const xmlChar) -> bool {
123 unsafe { crate::abi::exports_xml2::xmlStrEqual(s, b"xml\0".as_ptr() as *const xmlChar) != 0 }
124}
125
126const TEXT_NAME: &[u8] = b"text\0";
128
129unsafe fn copy_char_multibyte(mut out: *mut xmlChar, val: c_int) -> c_int {
131 if out.is_null() || val < 0 {
132 return 0;
133 }
134 if val >= 0x80 {
135 let saved = out;
136 let bits: c_int;
137 if val < 0x800 {
138 *out = ((val >> 6) | 0xC0) as u8;
139 out = out.add(1);
140 bits = 0;
141 } else if val < 0x10000 {
142 *out = ((val >> 12) | 0xE0) as u8;
143 out = out.add(1);
144 bits = 6;
145 } else if val < 0x110000 {
146 *out = ((val >> 18) | 0xF0) as u8;
147 out = out.add(1);
148 bits = 12;
149 } else {
150 return 0;
151 }
152 let mut b = bits;
153 loop {
154 *out = (((val >> b) & 0x3F) | 0x80) as u8;
155 out = out.add(1);
156 if b == 0 {
157 break;
158 }
159 b -= 6;
160 }
161 return unsafe { out.offset_from(saved) } as c_int;
162 }
163 *out = val as u8;
164 1
165}
166
167unsafe fn vec_to_c_string(v: &[u8]) -> *mut xmlChar {
169 let buf = unsafe { xmlMallocImpl(v.len() + 1) } as *mut xmlChar;
170 if buf.is_null() {
171 return ptr::null_mut();
172 }
173 unsafe {
174 ptr::copy_nonoverlapping(v.as_ptr(), buf, v.len());
175 *buf.add(v.len()) = 0;
176 }
177 buf
178}
179
180unsafe fn text_set_content(text: *mut _xmlNode, content: *mut xmlChar) {
182 if !(*text).content.is_null() {
183 let inline_addr = core::ptr::addr_of_mut!((*text).properties) as *const c_void;
184 if (*text).content as *const c_void != inline_addr {
185 unsafe { xmlFreeImpl((*text).content as *mut c_void) };
186 }
187 }
188 (*text).content = content;
189 (*text).properties = ptr::null_mut();
190}
191
192unsafe fn text_add_content(text: *mut _xmlNode, content: *const xmlChar, len: c_int) -> c_int {
195 if content.is_null() {
196 return 0;
197 }
198 let l = if len < 0 {
199 unsafe { str_len(content) }
200 } else {
201 len
202 };
203 let merged = unsafe { crate::abi::exports_xml2::xmlStrncatNew((*text).content, content, l) };
204 if merged.is_null() {
205 return -1;
206 }
207 unsafe { text_set_content(text, merged) };
208 0
209}
210
211unsafe fn new_doc_text(doc: *mut _xmlDoc, content: *const xmlChar) -> *mut _xmlNode {
213 let n = unsafe { tree::new_text(content) };
214 if !n.is_null() {
215 (*n).doc = doc;
216 }
217 n
218}
219
220unsafe fn new_doc_text_len(
222 doc: *mut _xmlDoc,
223 content: *const xmlChar,
224 len: c_int,
225) -> *mut _xmlNode {
226 let node = unsafe { xmlMallocZero(size_of::<_xmlNode>()) } as *mut _xmlNode;
227 if node.is_null() {
228 return ptr::null_mut();
229 }
230 (*node).type_ = XML_TEXT_NODE as c_int;
231 (*node).name = unsafe { dup_str(TEXT_NAME.as_ptr() as *const xmlChar) };
232 (*node).doc = doc;
233 if !content.is_null() {
234 (*node).content = unsafe { crate::abi::exports_xml2::xmlStrndup(content, len) };
235 if (*node).content.is_null() {
236 unsafe { tree::free_node(node) };
237 return ptr::null_mut();
238 }
239 }
240 node
241}
242
243unsafe fn new_entity_ref(doc: *mut _xmlDoc, name: *mut xmlChar) -> *mut _xmlNode {
246 let cur = unsafe { xmlMallocZero(size_of::<_xmlNode>()) } as *mut _xmlNode;
247 if cur.is_null() {
248 unsafe { xmlFreeImpl(name as *mut c_void) };
249 return ptr::null_mut();
250 }
251 (*cur).type_ = XML_ENTITY_REF_NODE as c_int;
252 (*cur).doc = doc;
253 (*cur).name = name;
254 cur
255}
256
257unsafe fn predefined_entity_content(name: *const xmlChar) -> *const xmlChar {
259 if name.is_null() {
260 return ptr::null();
261 }
262 let c = unsafe { *name };
263 let n1 = unsafe { *name.add(1) };
264 let n2 = unsafe { *name.add(2) };
265 match c {
266 b'l' if n1 == b't' && n2 == 0 => b"<\0".as_ptr() as *const xmlChar,
267 b'g' if n1 == b't' && n2 == 0 => b">\0".as_ptr() as *const xmlChar,
268 b'a' if n1 == b'm' && n2 == b'p' && unsafe { *name.add(3) } == 0 => {
269 b"&\0".as_ptr() as *const xmlChar
270 }
271 b'q' if n1 == b'u'
272 && n2 == b'o'
273 && unsafe { *name.add(3) } == b't'
274 && unsafe { *name.add(4) } == 0 =>
275 {
276 b"\"\0".as_ptr() as *const xmlChar
277 }
278 b'a' if n1 == b'p'
279 && n2 == b'o'
280 && unsafe { *name.add(3) } == b's'
281 && unsafe { *name.add(4) } == 0 =>
282 {
283 b"'\0".as_ptr() as *const xmlChar
284 }
285 _ => ptr::null(),
286 }
287}
288
289unsafe fn list_append(head: *mut *mut _xmlNode, last: *mut *mut _xmlNode, node: *mut _xmlNode) {
292 if (*head).is_null() {
293 *head = node;
294 } else {
295 (**last).next = node;
296 (*node).prev = *last;
297 }
298 *last = node;
299}
300
301unsafe fn node_parse_att_value(
305 doc: *mut _xmlDoc,
306 attr: *mut _xmlNode,
307 value: *const xmlChar,
308 len: usize,
309) -> c_int {
310 let mut head: *mut _xmlNode = ptr::null_mut();
311 let mut last: *mut _xmlNode = ptr::null_mut();
312 let mut remaining = len;
313
314 if !value.is_null() && *value != 0 {
315 let mut cur = value;
316 let mut q = cur;
317 let mut buf: Vec<u8> = Vec::new();
318 let mut failed = false;
319 while remaining > 0 && *cur != 0 {
320 if *cur == b'&' {
321 let mut charval: c_int = 0;
322 if cur != q {
323 buf.extend_from_slice(core::slice::from_raw_parts(
324 q,
325 cur.offset_from(q) as usize,
326 ));
327 q = cur;
328 }
329 if remaining > 2 && *cur.add(1) == b'#' && *cur.add(2) == b'x' {
330 cur = cur.add(3);
331 remaining -= 3;
332 while remaining > 0 {
333 let tmp = *cur;
334 if tmp == b';' {
335 break;
336 }
337 charval = match tmp {
338 b'0'..=b'9' => charval * 16 + (tmp - b'0') as c_int,
339 b'a'..=b'f' => charval * 16 + (tmp - b'a') as c_int + 10,
340 b'A'..=b'F' => charval * 16 + (tmp - b'A') as c_int + 10,
341 _ => {
342 charval = 0;
343 break;
344 }
345 };
346 if charval > 0x110000 {
347 charval = 0x110000;
348 }
349 cur = cur.add(1);
350 remaining -= 1;
351 }
352 if *cur == b';' {
353 cur = cur.add(1);
354 remaining -= 1;
355 }
356 q = cur;
357 } else if remaining > 1 && *cur.add(1) == b'#' {
358 cur = cur.add(2);
359 remaining -= 2;
360 while remaining > 0 {
361 let tmp = *cur;
362 if tmp == b';' {
363 break;
364 }
365 charval = match tmp {
366 b'0'..=b'9' => charval * 10 + (tmp - b'0') as c_int,
367 _ => {
368 charval = 0;
369 break;
370 }
371 };
372 if charval > 0x110000 {
373 charval = 0x110000;
374 }
375 cur = cur.add(1);
376 remaining -= 1;
377 }
378 if *cur == b';' {
379 cur = cur.add(1);
380 remaining -= 1;
381 }
382 q = cur;
383 } else {
384 cur = cur.add(1);
385 remaining -= 1;
386 q = cur;
387 while remaining > 0 && *cur != 0 && *cur != b';' {
388 cur = cur.add(1);
389 remaining -= 1;
390 }
391 if remaining <= 0 || *cur == 0 {
392 failed = true;
393 break;
394 }
395 if cur != q {
396 let mut val = unsafe {
397 crate::abi::exports_xml2::xmlStrndup(q, (cur.offset_from(q)) as c_int)
398 };
399 if val.is_null() {
400 failed = true;
401 break;
402 }
403 let ent = unsafe { tree::get_doc_entity(doc, val) };
404 let is_predef = unsafe { predefined_entity_content(val) };
405 if !is_predef.is_null() {
406 let p = is_predef;
408 let mut i = 0usize;
409 while unsafe { *p.add(i) } != 0 {
410 buf.push(unsafe { *p.add(i) });
411 i += 1;
412 }
413 } else {
414 if !buf.is_empty() {
416 let node = unsafe { new_doc_text(doc, ptr::null()) };
417 if node.is_null() {
418 unsafe { xmlFreeImpl(val as *mut c_void) };
419 failed = true;
420 break;
421 }
422 (*node).content = unsafe { vec_to_c_string(&buf) };
423 if (*node).content.is_null() {
424 unsafe { tree::free_node(node) };
425 unsafe { xmlFreeImpl(val as *mut c_void) };
426 failed = true;
427 break;
428 }
429 buf.clear();
430 (*node).parent = attr;
431 unsafe { list_append(&mut head, &mut last, node) };
432 }
433 let node = unsafe { new_entity_ref(doc, val) };
435 val = ptr::null_mut();
436 if node.is_null() {
437 failed = true;
438 break;
439 }
440 (*node).parent = attr;
441 (*node).last = ent as *mut _xmlNode;
442 if !ent.is_null() {
443 (*node).children = ent as *mut _xmlNode;
444 (*node).content = (*ent).content;
445 }
446 unsafe { list_append(&mut head, &mut last, node) };
447 }
448 if !val.is_null() {
449 unsafe { xmlFreeImpl(val as *mut c_void) };
450 }
451 }
452 cur = cur.add(1);
453 remaining -= 1;
454 q = cur;
455 }
456 if charval != 0 && !failed {
457 if charval >= 0x110000 {
458 charval = 0xFFFD; }
460 let mut buffer = [0u8; 8];
461 let l = unsafe { copy_char_multibyte(buffer.as_mut_ptr(), charval) };
462 if l > 0 {
463 buf.extend_from_slice(&buffer[..l as usize]);
464 }
465 }
466 if failed {
467 break;
468 }
469 } else {
470 cur = cur.add(1);
471 remaining -= 1;
472 }
473 }
474 if !failed && cur != q {
475 buf.extend_from_slice(core::slice::from_raw_parts(q, cur.offset_from(q) as usize));
476 }
477 if !failed {
478 if !buf.is_empty() {
479 let node = unsafe { new_doc_text(doc, ptr::null()) };
480 if node.is_null() {
481 failed = true;
482 } else {
483 (*node).content = unsafe { vec_to_c_string(&buf) };
484 if (*node).content.is_null() {
485 unsafe { tree::free_node(node) };
486 failed = true;
487 } else {
488 (*node).parent = attr;
489 unsafe { list_append(&mut head, &mut last, node) };
490 }
491 }
492 } else if head.is_null() {
493 let node = unsafe { new_doc_text(doc, b"\0".as_ptr() as *const xmlChar) };
494 if node.is_null() {
495 failed = true;
496 } else {
497 (*node).parent = attr;
498 head = node;
499 last = node;
500 }
501 }
502 }
503 if failed {
504 if !head.is_null() {
505 unsafe { tree::free_node_list(head) };
506 }
507 return -1;
508 }
509 }
510
511 if !attr.is_null() {
512 if !(*attr).children.is_null() {
513 unsafe { tree::free_node_list((*attr).children) };
514 }
515 (*attr).children = head;
516 (*attr).last = last;
517 }
518 0
519}
520
521unsafe fn ensure_xml_decl(doc: *mut _xmlDoc) -> *mut _xmlNs {
527 if doc.is_null() {
528 return ptr::null_mut();
529 }
530 if !(*doc).oldNs.is_null() {
531 return (*doc).oldNs;
532 }
533 let ns = unsafe {
534 tree::new_ns(
535 ptr::null_mut(),
536 XML_XML_NAMESPACE.as_ptr() as *const xmlChar,
537 b"xml\0".as_ptr() as *const xmlChar,
538 )
539 };
540 if ns.is_null() {
541 return ptr::null_mut();
542 }
543 (*doc).oldNs = ns;
544 ns
545}
546
547unsafe fn ns_list_lookup_by_prefix(ns_list: *mut _xmlNs, prefix: *const xmlChar) -> *mut _xmlNs {
549 if ns_list.is_null() {
550 return ptr::null_mut();
551 }
552 let mut ns = ns_list;
553 loop {
554 if unsafe { str_eq_or_ptr(prefix, (*ns).prefix) } {
555 return ns;
556 }
557 if (*ns).next.is_null() {
558 break;
559 }
560 ns = (*ns).next;
561 }
562 ptr::null_mut()
563}
564
565unsafe fn free_prop_impl(cur: *mut _xmlAttr) {
571 if cur.is_null() {
572 return;
573 }
574 if !(*cur).children.is_null() {
575 unsafe { tree::free_node_list((*cur).children) };
576 }
577 if !(*cur).name.is_null() {
578 unsafe { xmlFreeImpl((*cur).name as *mut c_void) };
579 }
580 unsafe { xmlFreeImpl(cur as *mut c_void) };
581}
582
583unsafe fn free_ns_impl(cur: *mut _xmlNs) {
585 if cur.is_null() {
586 return;
587 }
588 if !(*cur).href.is_null() {
589 unsafe { xmlFreeImpl((*cur).href as *mut c_void) };
590 }
591 if !(*cur).prefix.is_null() {
592 unsafe { xmlFreeImpl((*cur).prefix as *mut c_void) };
593 }
594 unsafe { xmlFreeImpl(cur as *mut c_void) };
595}
596
597unsafe fn find_prop_node_internal(
599 node: *mut _xmlNode,
600 name: *const xmlChar,
601 ns_href: *const xmlChar,
602 _use_dtd: c_int,
603) -> *mut _xmlAttr {
604 if node.is_null() || (*node).type_ != XML_ELEMENT_NODE as c_int || name.is_null() {
605 return ptr::null_mut();
606 }
607 if !(*node).properties.is_null() {
608 let mut prop = (*node).properties;
609 if ns_href.is_null() {
610 loop {
611 if (*prop).ns.is_null()
612 && !(*prop).name.is_null()
613 && unsafe { crate::abi::exports_xml2::xmlStrEqual((*prop).name, name) != 0 }
614 {
615 return prop;
616 }
617 if (*prop).next.is_null() {
618 break;
619 }
620 prop = (*prop).next;
621 }
622 } else {
623 loop {
624 if !(*prop).ns.is_null()
625 && !(*prop).name.is_null()
626 && unsafe { crate::abi::exports_xml2::xmlStrEqual((*prop).name, name) != 0 }
627 && !(*(*prop).ns).href.is_null()
628 && unsafe {
629 crate::abi::exports_xml2::xmlStrEqual((*(*prop).ns).href, ns_href) != 0
630 }
631 {
632 return prop;
633 }
634 if (*prop).next.is_null() {
635 break;
636 }
637 prop = (*prop).next;
638 }
639 }
640 }
641 ptr::null_mut()
642}
643
644unsafe fn get_prop_node_value_internal(prop: *mut _xmlAttr) -> *mut xmlChar {
646 if (*prop).children.is_null() {
647 return unsafe { dup_str(b"\0".as_ptr() as *const xmlChar) };
648 }
649 let text = (*prop).children;
650 if (*text).type_ == XML_TEXT_NODE as c_int {
651 if (*text).content.is_null() {
652 return unsafe { dup_str(b"\0".as_ptr() as *const xmlChar) };
653 }
654 return unsafe { dup_str((*text).content) };
655 }
656 unsafe { tree::node_get_content(prop as *mut _xmlNode) }
658}
659
660unsafe fn get_attr_value(
663 node: *mut _xmlNode,
664 name: *const xmlChar,
665 ns_uri: *const xmlChar,
666) -> *mut xmlChar {
667 let prop = unsafe { find_prop_node_internal(node, name, ns_uri, 0) };
668 if prop.is_null() {
669 return ptr::null_mut();
670 }
671 unsafe { get_prop_node_value_internal(prop) }
672}
673
674unsafe fn set_ns_prop_impl(
676 node: *mut _xmlNode,
677 ns: *mut _xmlNs,
678 name: *const xmlChar,
679 value: *const xmlChar,
680) -> *mut _xmlAttr {
681 if node.is_null() || name.is_null() {
682 return ptr::null_mut();
683 }
684 let ns_href = if ns.is_null() {
685 ptr::null()
686 } else {
687 (*ns).href
688 };
689 let existing = unsafe { find_prop_node_internal(node, name, ns_href, 0) };
690 if !existing.is_null() {
691 if !(*existing).children.is_null() {
692 unsafe { tree::free_node_list((*existing).children) };
693 (*existing).children = ptr::null_mut();
694 (*existing).last = ptr::null_mut();
695 }
696 if !value.is_null() {
697 let text = unsafe { new_doc_text((*node).doc, value) };
698 if !text.is_null() {
699 (*existing).children = text;
700 (*existing).last = text;
701 (*text).parent = existing as *mut _xmlNode;
702 (*text).doc = (*node).doc;
703 }
704 }
705 return existing;
706 }
707 unsafe { new_prop_internal(node, ns, name, value, 0) }
708}
709
710unsafe fn new_prop_internal(
712 node: *mut _xmlNode,
713 ns: *mut _xmlNs,
714 name: *const xmlChar,
715 value: *const xmlChar,
716 eatname: c_int,
717) -> *mut _xmlAttr {
718 let doc: *mut _xmlDoc;
719 if !node.is_null() && (*node).type_ != XML_ELEMENT_NODE as c_int {
720 if eatname == 1 {
721 unsafe { xmlFreeImpl(name as *mut c_void) };
722 }
723 return ptr::null_mut();
724 }
725 let cur = unsafe { xmlMallocZero(size_of::<_xmlAttr>()) } as *mut _xmlAttr;
726 if cur.is_null() {
727 if eatname == 1 {
728 unsafe { xmlFreeImpl(name as *mut c_void) };
729 }
730 return ptr::null_mut();
731 }
732 (*cur).type_ = XML_ATTRIBUTE_NODE as c_int;
733 (*cur).parent = node;
734 if !node.is_null() {
735 doc = (*node).doc;
736 (*cur).doc = doc;
737 } else {
738 doc = ptr::null_mut();
739 }
740 (*cur).ns = ns;
741
742 if eatname == 0 {
743 (*cur).name = unsafe { dup_str(name) };
744 if (*cur).name.is_null() {
745 unsafe { free_prop_impl(cur) };
746 return ptr::null_mut();
747 }
748 } else {
749 (*cur).name = name;
750 }
751
752 if !value.is_null() {
753 let text = unsafe { new_doc_text(doc, value) };
754 if text.is_null() {
755 unsafe { free_prop_impl(cur) };
756 return ptr::null_mut();
757 }
758 (*cur).children = text;
759 (*cur).last = ptr::null_mut();
760 let mut tmp = text;
761 while !tmp.is_null() {
762 (*tmp).parent = cur as *mut _xmlNode;
763 if (*tmp).next.is_null() {
764 (*cur).last = tmp;
765 }
766 tmp = (*tmp).next;
767 }
768 }
769
770 if !node.is_null() {
771 if (*node).properties.is_null() {
772 (*node).properties = cur;
773 } else {
774 let mut prev = (*node).properties;
775 while !(*prev).next.is_null() {
776 prev = (*prev).next;
777 }
778 (*prev).next = cur;
779 (*cur).prev = prev;
780 }
781 }
782 cur
783}
784
785unsafe fn remove_prop_impl(cur: *mut _xmlAttr) -> c_int {
787 if cur.is_null() {
788 return -1;
789 }
790 if (*cur).parent.is_null() {
791 return -1;
792 }
793 let mut tmp = (*(*cur).parent).properties;
794 if tmp == cur {
795 (*(*cur).parent).properties = (*cur).next;
796 if !(*cur).next.is_null() {
797 (*(*cur).next).prev = ptr::null_mut();
798 }
799 unsafe { free_prop_impl(cur) };
800 return 0;
801 }
802 while !tmp.is_null() {
803 if (*tmp).next == cur {
804 (*tmp).next = (*cur).next;
805 if !(*tmp).next.is_null() {
806 (*(*tmp).next).prev = tmp;
807 }
808 unsafe { free_prop_impl(cur) };
809 return 0;
810 }
811 tmp = (*tmp).next;
812 }
813 -1
814}
815
816unsafe fn node_set_doc_impl(node: *mut _xmlNode, doc: *mut _xmlDoc) -> c_int {
822 let ret = 0;
823 match (*node).type_ as u32 {
824 t if t == XML_ENTITY_REF_NODE as u32 => {
825 (*node).children = ptr::null_mut();
826 (*node).last = ptr::null_mut();
827 (*node).content = ptr::null_mut();
828 if !doc.is_null() && (!(*doc).intSubset.is_null() || !(*doc).extSubset.is_null()) {
829 let ent = unsafe { tree::get_doc_entity(doc, (*node).name) };
830 if !ent.is_null() {
831 (*node).children = ent as *mut _xmlNode;
832 (*node).last = ent as *mut _xmlNode;
833 (*node).content = (*ent).content;
834 }
835 }
836 }
837 t if t == XML_DTD_NODE as u32 => {
838 if !(*node).doc.is_null() {
839 if (*(*node).doc).intSubset == node as *mut _xmlDtd {
840 (*(*node).doc).intSubset = ptr::null_mut();
841 }
842 if (*(*node).doc).extSubset == node as *mut _xmlDtd {
843 (*(*node).doc).extSubset = ptr::null_mut();
844 }
845 }
846 }
847 _ => {}
848 }
849 (*node).doc = doc;
850 ret
851}
852
853unsafe fn set_list_doc_impl(list: *mut _xmlNode, doc: *mut _xmlDoc) -> c_int {
855 let mut ret = 0;
856 if list.is_null() || (*list).type_ == XML_NAMESPACE_DECL as c_int {
857 return 0;
858 }
859 let mut cur = list;
860 while !cur.is_null() {
861 if (*cur).doc != doc {
862 if unsafe { set_tree_doc_impl(cur, doc) } < 0 {
863 ret = -1;
864 }
865 }
866 cur = (*cur).next;
867 }
868 ret
869}
870
871unsafe fn set_tree_doc_impl(tree: *mut _xmlNode, doc: *mut _xmlDoc) -> c_int {
873 let mut ret = 0;
874 if tree.is_null() || (*tree).type_ == XML_NAMESPACE_DECL as c_int {
875 return 0;
876 }
877 if (*tree).doc == doc {
878 return 0;
879 }
880 if (*tree).type_ == XML_ELEMENT_NODE as c_int {
881 let mut prop = (*tree).properties;
882 while !prop.is_null() {
883 if !(*prop).children.is_null() {
884 if unsafe { set_list_doc_impl((*prop).children, doc) } < 0 {
885 ret = -1;
886 }
887 }
888 if unsafe { node_set_doc_impl(prop as *mut _xmlNode, doc) } < 0 {
889 ret = -1;
890 }
891 prop = (*prop).next;
892 }
893 }
894 if !(*tree).children.is_null() && (*tree).type_ != XML_ENTITY_REF_NODE as c_int {
895 if unsafe { set_list_doc_impl((*tree).children, doc) } < 0 {
896 ret = -1;
897 }
898 }
899 if unsafe { node_set_doc_impl(tree, doc) } < 0 {
900 ret = -1;
901 }
902 ret
903}
904
905unsafe fn insert_prop(
908 doc: *mut _xmlDoc,
909 cur: *mut _xmlNode,
910 parent: *mut _xmlNode,
911 prev: *mut _xmlNode,
912 next: *mut _xmlNode,
913) -> *mut _xmlNode {
914 if (!prev.is_null() && (*prev).type_ != XML_ATTRIBUTE_NODE as c_int)
915 || (!next.is_null() && (*next).type_ != XML_ATTRIBUTE_NODE as c_int)
916 {
917 return ptr::null_mut();
918 }
919 let ns_href = if (*cur).ns.is_null() {
920 ptr::null()
921 } else {
922 (*(*cur).ns).href
923 };
924 let attr = unsafe { find_prop_node_internal(parent, (*cur).name, ns_href, 0) };
925
926 unsafe { tree::unlink_node(cur) };
927
928 if (*cur).doc != doc {
929 if unsafe { set_tree_doc_impl(cur, doc) } < 0 {
930 return ptr::null_mut();
931 }
932 }
933 (*cur).parent = parent;
934 (*cur).prev = prev;
935 (*cur).next = next;
936
937 if prev.is_null() {
938 if !parent.is_null() {
939 (*parent).properties = cur as *mut _xmlAttr;
940 }
941 } else {
942 (*prev).next = cur;
943 }
944 if !next.is_null() {
945 (*next).prev = cur;
946 }
947
948 if !attr.is_null() && attr != cur as *mut _xmlAttr {
949 unsafe { remove_prop_impl(attr) };
951 }
952 cur
953}
954
955unsafe fn insert_node(
958 doc: *mut _xmlDoc,
959 cur: *mut _xmlNode,
960 parent: *mut _xmlNode,
961 prev: *mut _xmlNode,
962 next: *mut _xmlNode,
963 coalesce: c_int,
964) -> *mut _xmlNode {
965 if (*cur).type_ == XML_ATTRIBUTE_NODE as c_int {
966 return unsafe { insert_prop(doc, cur, parent, prev, next) };
967 }
968
969 if coalesce != 0 && (*cur).type_ == XML_TEXT_NODE as c_int {
970 if !prev.is_null()
971 && (*prev).type_ == XML_TEXT_NODE as c_int
972 && unsafe { str_eq_or_ptr((*prev).name, (*cur).name) }
973 {
974 if unsafe { text_add_content(prev, (*cur).content, -1) } < 0 {
975 return ptr::null_mut();
976 }
977 unsafe { tree::unlink_node(cur) };
978 unsafe { tree::free_node(cur) };
979 return prev;
980 }
981 if !next.is_null()
982 && (*next).type_ == XML_TEXT_NODE as c_int
983 && unsafe { str_eq_or_ptr((*next).name, (*cur).name) }
984 {
985 if !(*cur).content.is_null() {
986 let l = unsafe { str_len((*next).content) };
987 let merged = unsafe {
988 crate::abi::exports_xml2::xmlStrncatNew((*cur).content, (*next).content, l)
989 };
990 if merged.is_null() {
991 return ptr::null_mut();
992 }
993 unsafe { text_set_content(next, merged) };
994 }
995 unsafe { tree::unlink_node(cur) };
996 unsafe { tree::free_node(cur) };
997 return next;
998 }
999 }
1000
1001 let old_parent = (*cur).parent;
1002 if !old_parent.is_null() {
1003 if (*old_parent).children == cur {
1004 (*old_parent).children = (*cur).next;
1005 }
1006 if (*old_parent).last == cur {
1007 (*old_parent).last = (*cur).prev;
1008 }
1009 }
1010 if !(*cur).next.is_null() {
1011 (*(*cur).next).prev = (*cur).prev;
1012 }
1013 if !(*cur).prev.is_null() {
1014 (*(*cur).prev).next = (*cur).next;
1015 }
1016
1017 if (*cur).doc != doc {
1018 if unsafe { set_tree_doc_impl(cur, doc) } < 0 {
1019 (*cur).parent = ptr::null_mut();
1020 (*cur).prev = ptr::null_mut();
1021 (*cur).next = ptr::null_mut();
1022 return ptr::null_mut();
1023 }
1024 }
1025
1026 (*cur).parent = parent;
1027 (*cur).prev = prev;
1028 (*cur).next = next;
1029
1030 if prev.is_null() {
1031 if !parent.is_null() {
1032 (*parent).children = cur;
1033 }
1034 } else {
1035 (*prev).next = cur;
1036 }
1037 if next.is_null() {
1038 if !parent.is_null() {
1039 (*parent).last = cur;
1040 }
1041 } else {
1042 (*next).prev = cur;
1043 }
1044 cur
1045}
1046
1047unsafe fn add_child_coalesce(parent: *mut _xmlNode, cur: *mut _xmlNode) -> *mut _xmlNode {
1049 if parent.is_null()
1050 || (*parent).type_ == XML_NAMESPACE_DECL as c_int
1051 || cur.is_null()
1052 || (*cur).type_ == XML_NAMESPACE_DECL as c_int
1053 || parent == cur
1054 {
1055 return ptr::null_mut();
1056 }
1057 if (*parent).type_ == XML_TEXT_NODE as c_int {
1059 if unsafe { text_add_content(parent, (*cur).content, -1) } < 0 {
1060 return ptr::null_mut();
1061 }
1062 unsafe { tree::unlink_node(cur) };
1063 unsafe { tree::free_node(cur) };
1064 return parent;
1065 }
1066 let prev: *mut _xmlNode = if (*cur).type_ == XML_ATTRIBUTE_NODE as c_int {
1067 let mut p = (*parent).properties;
1068 if !p.is_null() {
1069 while !(*p).next.is_null() {
1070 p = (*p).next;
1071 }
1072 }
1073 p as *mut _xmlNode
1074 } else {
1075 (*parent).last
1076 };
1077 if cur == prev {
1078 return cur;
1079 }
1080 unsafe { insert_node((*parent).doc, cur, parent, prev, ptr::null_mut(), 1) }
1081}
1082
1083unsafe fn new_elem(
1085 doc: *mut _xmlDoc,
1086 ns: *mut _xmlNs,
1087 name: *const xmlChar,
1088 content: *const xmlChar,
1089) -> *mut _xmlNode {
1090 let cur = unsafe { xmlMallocZero(size_of::<_xmlNode>()) } as *mut _xmlNode;
1091 if cur.is_null() {
1092 return ptr::null_mut();
1093 }
1094 (*cur).type_ = XML_ELEMENT_NODE as c_int;
1095 (*cur).doc = doc;
1096 (*cur).name = name;
1097 (*cur).ns = ns;
1098 if !content.is_null() {
1099 if unsafe { node_parse_att_value(doc, cur, content, usize::MAX) } < 0 {
1100 unsafe { xmlFreeImpl(cur as *mut c_void) };
1102 return ptr::null_mut();
1103 }
1104 }
1105 cur
1106}
1107
1108unsafe fn new_doc_node(
1110 doc: *mut _xmlDoc,
1111 ns: *mut _xmlNs,
1112 name: *const xmlChar,
1113 content: *const xmlChar,
1114) -> *mut _xmlNode {
1115 if name.is_null() {
1116 return ptr::null_mut();
1117 }
1118 let copy = unsafe { dup_str(name) };
1119 if copy.is_null() {
1120 return ptr::null_mut();
1121 }
1122 let cur = unsafe { new_elem(doc, ns, copy, content) };
1123 if cur.is_null() {
1124 unsafe { xmlFreeImpl(copy as *mut c_void) };
1125 return ptr::null_mut();
1126 }
1127 cur
1128}
1129
1130unsafe fn new_doc_node_eat_name(
1132 doc: *mut _xmlDoc,
1133 ns: *mut _xmlNs,
1134 name: *mut xmlChar,
1135 content: *const xmlChar,
1136) -> *mut _xmlNode {
1137 if name.is_null() {
1138 return ptr::null_mut();
1139 }
1140 let cur = unsafe { new_elem(doc, ns, name, content) };
1141 if cur.is_null() {
1142 unsafe { xmlFreeImpl(name as *mut c_void) };
1143 return ptr::null_mut();
1144 }
1145 cur
1146}
1147
1148unsafe fn new_doc_raw_node(
1150 doc: *mut _xmlDoc,
1151 ns: *mut _xmlNs,
1152 name: *const xmlChar,
1153 content: *const xmlChar,
1154) -> *mut _xmlNode {
1155 let cur = unsafe { new_doc_node(doc, ns, name, ptr::null()) };
1156 if cur.is_null() {
1157 return ptr::null_mut();
1158 }
1159 (*cur).doc = doc;
1160 if !content.is_null() {
1161 let text = unsafe { new_doc_text(doc, content) };
1162 if text.is_null() {
1163 unsafe { tree::free_node(cur) };
1164 return ptr::null_mut();
1165 }
1166 (*cur).children = text;
1167 (*cur).last = text;
1168 (*text).parent = cur;
1169 }
1170 cur
1171}
1172
1173pub type xmlDOMWrapAcquireNsFunction = unsafe extern "C" fn(
1179 ctxt: *mut _xmlDOMWrapCtxt,
1180 node: *mut _xmlNode,
1181 nsName: *const xmlChar,
1182 nsPrefix: *const xmlChar,
1183) -> *mut _xmlNs;
1184
1185#[repr(C)]
1187pub struct _xmlDOMWrapCtxt {
1188 pub _private: *mut c_void,
1189 pub type_: c_int,
1190 pub namespaceMap: *mut c_void,
1191 pub getNsForNodeFunc: Option<xmlDOMWrapAcquireNsFunction>,
1192}
1193
1194const XML_TREE_NSMAP_PARENT: c_int = -1;
1195const XML_TREE_NSMAP_DOC: c_int = -3;
1196const XML_TREE_NSMAP_CUSTOM: c_int = -4;
1197
1198const XML_DOM_RECONNS_REMOVEREDUND: c_int = 1 << 0;
1199
1200#[repr(C)]
1202struct NsMapItem {
1203 next: *mut NsMapItem,
1204 prev: *mut NsMapItem,
1205 oldNs: *mut _xmlNs,
1206 newNs: *mut _xmlNs,
1207 shadowDepth: c_int,
1208 depth: c_int,
1209}
1210
1211#[repr(C)]
1213struct NsMap {
1214 first: *mut NsMapItem,
1215 last: *mut NsMapItem,
1216 pool: *mut NsMapItem,
1217}
1218
1219unsafe fn ns_map_not_empty(m: *mut NsMap) -> bool {
1220 !m.is_null() && !(*m).first.is_null()
1221}
1222
1223unsafe fn ns_map_free(nsmap: *mut NsMap) {
1225 if nsmap.is_null() {
1226 return;
1227 }
1228 let mut cur = (*nsmap).pool;
1229 while !cur.is_null() {
1230 let next = (*cur).next;
1231 unsafe { xmlFreeImpl(cur as *mut c_void) };
1232 cur = next;
1233 }
1234 cur = (*nsmap).first;
1235 while !cur.is_null() {
1236 let next = (*cur).next;
1237 unsafe { xmlFreeImpl(cur as *mut c_void) };
1238 cur = next;
1239 }
1240 unsafe { xmlFreeImpl(nsmap as *mut c_void) };
1241}
1242
1243unsafe fn ns_map_add_item(
1245 nsmap: *mut *mut NsMap,
1246 position: c_int,
1247 oldNs: *mut _xmlNs,
1248 newNs: *mut _xmlNs,
1249 depth: c_int,
1250) -> *mut NsMapItem {
1251 if nsmap.is_null() {
1252 return ptr::null_mut();
1253 }
1254 if position != -1 && position != 0 {
1255 return ptr::null_mut();
1256 }
1257 let mut map = *nsmap;
1258 if map.is_null() {
1259 map = unsafe { xmlMallocZero(size_of::<NsMap>()) } as *mut NsMap;
1260 if map.is_null() {
1261 return ptr::null_mut();
1262 }
1263 *nsmap = map;
1264 }
1265 let ret = unsafe { xmlMallocZero(size_of::<NsMapItem>()) } as *mut NsMapItem;
1266 if ret.is_null() {
1267 return ptr::null_mut();
1268 }
1269 if (*map).first.is_null() {
1270 (*map).first = ret;
1271 (*map).last = ret;
1272 } else if position == -1 {
1273 (*ret).prev = (*map).last;
1274 (*(*map).last).next = ret;
1275 (*map).last = ret;
1276 } else {
1277 (*(*map).first).prev = ret;
1278 (*ret).next = (*map).first;
1279 (*map).first = ret;
1280 }
1281 (*ret).oldNs = oldNs;
1282 (*ret).newNs = newNs;
1283 (*ret).shadowDepth = -1;
1284 (*ret).depth = depth;
1285 ret
1286}
1287
1288unsafe fn ns_map_pop(map: *mut NsMap) -> *mut NsMapItem {
1290 let i = (*map).last;
1291 (*map).last = (*i).prev;
1292 if (*map).last.is_null() {
1293 (*map).first = ptr::null_mut();
1294 } else {
1295 (*(*map).last).next = ptr::null_mut();
1296 }
1297 (*i).prev = ptr::null_mut();
1298 (*i).next = (*map).pool;
1299 (*map).pool = i;
1300 i
1301}
1302
1303unsafe fn store_ns(
1305 doc: *mut _xmlDoc,
1306 ns_name: *const xmlChar,
1307 prefix: *const xmlChar,
1308) -> *mut _xmlNs {
1309 if doc.is_null() {
1310 return ptr::null_mut();
1311 }
1312 let mut ns = unsafe { ensure_xml_decl(doc) };
1313 if ns.is_null() {
1314 return ptr::null_mut();
1315 }
1316 if !(*ns).next.is_null() {
1317 ns = (*ns).next;
1318 loop {
1319 if unsafe { str_eq_or_ptr((*ns).prefix, prefix) }
1320 && !(*ns).href.is_null()
1321 && !ns_name.is_null()
1322 && unsafe { crate::abi::exports_xml2::xmlStrEqual((*ns).href, ns_name) != 0 }
1323 {
1324 return ns;
1325 }
1326 if (*ns).next.is_null() {
1327 break;
1328 }
1329 ns = (*ns).next;
1330 }
1331 }
1332 if !ns.is_null() {
1333 let n = unsafe { tree::new_ns(ptr::null_mut(), ns_name, prefix) };
1334 if n.is_null() {
1335 return ptr::null_mut();
1336 }
1337 (*ns).next = n;
1338 return n;
1339 }
1340 ptr::null_mut()
1341}
1342
1343unsafe fn gather_in_scope_ns(map: *mut *mut NsMap, node: *mut _xmlNode) -> c_int {
1345 if map.is_null() || !(*map).is_null() {
1346 return -1;
1347 }
1348 if node.is_null() || (*node).type_ == XML_NAMESPACE_DECL as c_int {
1349 return -1;
1350 }
1351 let mut cur = node;
1352 while !cur.is_null() && cur != (*cur).doc as *mut _xmlNode {
1353 if (*cur).type_ == XML_ELEMENT_NODE as c_int && !(*cur).nsDef.is_null() {
1354 let mut ns = (*cur).nsDef;
1355 loop {
1356 let mut shadowed = 0;
1357 if unsafe { ns_map_not_empty(*map) } {
1358 let mut mi = (*(*map)).first;
1359 while !mi.is_null() {
1360 if !(*mi).newNs.is_null()
1361 && unsafe { str_eq_or_ptr((*ns).prefix, (*(*mi).newNs).prefix) }
1362 {
1363 shadowed = 1;
1364 break;
1365 }
1366 mi = (*mi).next;
1367 }
1368 }
1369 let mi =
1370 unsafe { ns_map_add_item(map, 0, ptr::null_mut(), ns, XML_TREE_NSMAP_PARENT) };
1371 if mi.is_null() {
1372 return -1;
1373 }
1374 if shadowed != 0 {
1375 (*mi).shadowDepth = 0;
1376 }
1377 if (*ns).next.is_null() {
1378 break;
1379 }
1380 ns = (*ns).next;
1381 }
1382 }
1383 cur = (*cur).parent;
1384 }
1385 0
1386}
1387
1388unsafe fn ns_norm_add_ns_map_item2(
1390 list: *mut *mut *mut _xmlNs,
1391 size: *mut c_int,
1392 number: *mut c_int,
1393 old_ns: *mut _xmlNs,
1394 new_ns: *mut _xmlNs,
1395) -> c_int {
1396 if *number >= *size {
1397 let new_size = if *size <= 0 { 6 } else { (*size) * 2 };
1398 let tmp = unsafe {
1399 xmlReallocImpl(
1400 *list as *mut c_void,
1401 (new_size as usize) * 2 * size_of::<*mut _xmlNs>(),
1402 )
1403 } as *mut *mut _xmlNs;
1404 if tmp.is_null() {
1405 return -1;
1406 }
1407 *list = tmp;
1408 *size = new_size;
1409 }
1410 let arr = *list;
1411 unsafe {
1412 arr.add((2 * *number) as usize).write(old_ns);
1413 arr.add((2 * *number + 1) as usize).write(new_ns);
1414 }
1415 *number += 1;
1416 0
1417}
1418
1419unsafe fn search_ns_by_prefix_strict(
1421 doc: *mut _xmlDoc,
1422 node: *mut _xmlNode,
1423 prefix: *const xmlChar,
1424 ret_ns: *mut *mut _xmlNs,
1425) -> c_int {
1426 if doc.is_null() || node.is_null() || (*node).type_ == XML_NAMESPACE_DECL as c_int {
1427 return -1;
1428 }
1429 if !ret_ns.is_null() {
1430 *ret_ns = ptr::null_mut();
1431 }
1432 if unsafe { is_str_xml(prefix) } {
1433 if !ret_ns.is_null() {
1434 let ns = unsafe { ensure_xml_decl(doc) };
1435 if ns.is_null() {
1436 return -1;
1437 }
1438 *ret_ns = ns;
1439 }
1440 return 1;
1441 }
1442 let mut cur = node;
1443 loop {
1444 if (*cur).type_ == XML_ELEMENT_NODE as c_int {
1445 if !(*cur).nsDef.is_null() {
1446 let mut ns = (*cur).nsDef;
1447 loop {
1448 if unsafe { str_eq_or_ptr(prefix, (*ns).prefix) } {
1449 if (*ns).href.is_null() {
1451 return 0;
1452 }
1453 if !ret_ns.is_null() {
1454 *ret_ns = ns;
1455 }
1456 return 1;
1457 }
1458 if (*ns).next.is_null() {
1459 break;
1460 }
1461 ns = (*ns).next;
1462 }
1463 }
1464 } else if (*cur).type_ == XML_ENTITY_DECL as c_int {
1465 return 0;
1466 }
1467 cur = (*cur).parent;
1468 if cur.is_null() || (*cur).doc == cur as *mut _xmlDoc {
1469 break;
1470 }
1471 }
1472 0
1473}
1474
1475unsafe fn search_ns_by_namespace_strict(
1477 doc: *mut _xmlDoc,
1478 node: *mut _xmlNode,
1479 ns_name: *const xmlChar,
1480 ret_ns: *mut *mut _xmlNs,
1481 prefixed: c_int,
1482) -> c_int {
1483 if doc.is_null() || ns_name.is_null() || ret_ns.is_null() {
1484 return -1;
1485 }
1486 if node.is_null() || (*node).type_ == XML_NAMESPACE_DECL as c_int {
1487 return -1;
1488 }
1489 *ret_ns = ptr::null_mut();
1490 if unsafe {
1491 crate::abi::exports_xml2::xmlStrEqual(ns_name, XML_XML_NAMESPACE.as_ptr() as *const xmlChar)
1492 != 0
1493 } {
1494 let ns = unsafe { ensure_xml_decl(doc) };
1495 if ns.is_null() {
1496 return -1;
1497 }
1498 *ret_ns = ns;
1499 return 1;
1500 }
1501 let mut cur = node;
1502 let mut prev: *mut _xmlNode = ptr::null_mut();
1503 let mut out: *mut _xmlNode = ptr::null_mut();
1504 loop {
1505 if (*cur).type_ == XML_ELEMENT_NODE as c_int {
1506 if !(*cur).nsDef.is_null() {
1507 let mut ns = (*cur).nsDef;
1508 loop {
1509 if prefixed != 0 && (*ns).prefix.is_null() {
1510 if (*ns).next.is_null() {
1511 break;
1512 }
1513 ns = (*ns).next;
1514 continue;
1515 }
1516 if !prev.is_null() {
1517 let mut prevns = (*prev).nsDef;
1519 let mut shadowed: *mut _xmlNs = ptr::null_mut();
1520 while !prevns.is_null() {
1521 if unsafe { str_eq_or_ptr((*prevns).prefix, (*ns).prefix) } {
1522 shadowed = prevns;
1523 break;
1524 }
1525 prevns = (*prevns).next;
1526 }
1527 if !shadowed.is_null() {
1528 if (*ns).next.is_null() {
1529 break;
1530 }
1531 ns = (*ns).next;
1532 continue;
1533 }
1534 }
1535 if unsafe { crate::abi::exports_xml2::xmlStrEqual(ns_name, (*ns).href) != 0 } {
1536 if !out.is_null() {
1537 if unsafe {
1539 search_ns_by_prefix_strict(doc, node, (*ns).prefix, ptr::null_mut())
1540 } == 0
1541 {
1542 if (*ns).next.is_null() {
1543 break;
1544 }
1545 ns = (*ns).next;
1546 continue;
1547 }
1548 }
1549 *ret_ns = ns;
1550 return 1;
1551 }
1552 if (*ns).next.is_null() {
1553 break;
1554 }
1555 ns = (*ns).next;
1556 }
1557 out = prev;
1558 prev = cur;
1559 }
1560 } else if (*cur).type_ == XML_ENTITY_DECL as c_int {
1561 return 0;
1562 }
1563 cur = (*cur).parent;
1564 if cur.is_null() || (*cur).doc == cur as *mut _xmlDoc {
1565 break;
1566 }
1567 }
1568 0
1569}
1570
1571unsafe fn declare_ns_forced(
1573 doc: *mut _xmlDoc,
1574 elem: *mut _xmlNode,
1575 ns_name: *const xmlChar,
1576 prefix: *const xmlChar,
1577 check_shadow: c_int,
1578) -> *mut _xmlNs {
1579 if doc.is_null() || elem.is_null() || (*elem).type_ != XML_ELEMENT_NODE as c_int {
1580 return ptr::null_mut();
1581 }
1582 let mut counter: c_int = 0;
1583 let mut buf: Vec<u8> = Vec::new();
1584 let mut cur_prefix: *const xmlChar = prefix;
1585 loop {
1586 let mut used = false;
1587 if !(*elem).nsDef.is_null()
1588 && !unsafe { ns_list_lookup_by_prefix((*elem).nsDef, cur_prefix) }.is_null()
1589 {
1590 used = true;
1591 }
1592 if !used && check_shadow != 0 && !(*elem).parent.is_null() {
1593 if unsafe {
1594 search_ns_by_prefix_strict(doc, (*elem).parent, cur_prefix, ptr::null_mut())
1595 } == 1
1596 {
1597 used = true;
1598 }
1599 }
1600 if !used {
1601 let ret = unsafe { tree::new_ns(ptr::null_mut(), ns_name, cur_prefix) };
1602 if ret.is_null() {
1603 return ptr::null_mut();
1604 }
1605 if (*elem).nsDef.is_null() {
1606 (*elem).nsDef = ret;
1607 } else {
1608 let mut ns2 = (*elem).nsDef;
1609 while !(*ns2).next.is_null() {
1610 ns2 = (*ns2).next;
1611 }
1612 (*ns2).next = ret;
1613 }
1614 return ret;
1615 }
1616 counter += 1;
1617 if counter > 1000 {
1618 return ptr::null_mut();
1619 }
1620 if prefix.is_null() {
1621 let s = format!("ns_{}", counter);
1622 buf = s.into_bytes();
1623 buf.push(0);
1624 } else {
1625 let p = unsafe { str_prefix(prefix, 30) };
1626 let p_str = String::from_utf8_lossy(&p[..p.len().saturating_sub(1)]);
1627 let s = format!("{}_{}", p_str, counter);
1628 buf = s.into_bytes();
1629 buf.push(0);
1630 }
1631 cur_prefix = buf.as_ptr() as *const xmlChar;
1632 }
1633}
1634
1635unsafe fn acquire_normalized_ns(
1637 doc: *mut _xmlDoc,
1638 elem: *mut _xmlNode,
1639 ns: *mut _xmlNs,
1640 ret_ns: *mut *mut _xmlNs,
1641 ns_map: *mut *mut NsMap,
1642 depth: c_int,
1643 ancestors_only: c_int,
1644 prefixed: c_int,
1645) -> c_int {
1646 if doc.is_null() || ns.is_null() || ret_ns.is_null() || ns_map.is_null() {
1647 return -1;
1648 }
1649 *ret_ns = ptr::null_mut();
1650 if unsafe { is_str_xml((*ns).prefix) } {
1651 let xml_ns = unsafe { ensure_xml_decl(doc) };
1652 if xml_ns.is_null() {
1653 return -1;
1654 }
1655 *ret_ns = xml_ns;
1656 return 0;
1657 }
1658 if unsafe { ns_map_not_empty(*ns_map) } && !(ancestors_only != 0 && elem.is_null()) {
1659 let mut mi = (*(*ns_map)).first;
1660 while !mi.is_null() {
1661 if (*mi).depth >= XML_TREE_NSMAP_PARENT
1662 && ((ancestors_only == 0) || (*mi).depth == XML_TREE_NSMAP_PARENT)
1663 && (*mi).shadowDepth == -1
1664 && !(*mi).newNs.is_null()
1665 && !(*(*mi).newNs).href.is_null()
1666 && *(*(*mi).newNs).href != 0
1667 && ((prefixed == 0) || !(*(*mi).newNs).prefix.is_null())
1668 && ((*ns).href == (*(*mi).newNs).href
1669 || unsafe {
1670 crate::abi::exports_xml2::xmlStrEqual((*ns).href, (*(*mi).newNs).href) != 0
1671 })
1672 {
1673 (*mi).oldNs = ns;
1674 *ret_ns = (*mi).newNs;
1675 return 0;
1676 }
1677 mi = (*mi).next;
1678 }
1679 }
1680 if elem.is_null() {
1681 let tmpns = unsafe { store_ns(doc, (*ns).href, (*ns).prefix) };
1682 if tmpns.is_null() {
1683 return -1;
1684 }
1685 if unsafe { ns_map_add_item(ns_map, -1, ns, tmpns, XML_TREE_NSMAP_DOC) }.is_null() {
1686 return -1;
1687 }
1688 *ret_ns = tmpns;
1689 } else {
1690 let tmpns = unsafe { declare_ns_forced(doc, elem, (*ns).href, (*ns).prefix, 0) };
1691 if tmpns.is_null() {
1692 return -1;
1693 }
1694 if unsafe { ns_map_not_empty(*ns_map) } {
1695 let mut mi = (*(*ns_map)).first;
1696 while !mi.is_null() {
1697 if (*mi).depth < depth
1698 && (*mi).shadowDepth == -1
1699 && !(*mi).newNs.is_null()
1700 && unsafe { str_eq_or_ptr((*ns).prefix, (*(*mi).newNs).prefix) }
1701 {
1702 (*mi).shadowDepth = depth;
1703 break;
1704 }
1705 mi = (*mi).next;
1706 }
1707 }
1708 if unsafe { ns_map_add_item(ns_map, -1, ns, tmpns, depth) }.is_null() {
1709 return -1;
1710 }
1711 *ret_ns = tmpns;
1712 }
1713 0
1714}
1715
1716unsafe fn ns_map_pop_depth(ns_map: *mut NsMap, depth: c_int) {
1720 if ns_map.is_null() {
1721 return;
1722 }
1723 if unsafe { ns_map_not_empty(ns_map) } {
1724 while !(*ns_map).last.is_null() && (*(*ns_map).last).depth >= depth {
1725 unsafe { ns_map_pop(ns_map) };
1726 }
1727 let mut mi = (*ns_map).first;
1728 while !mi.is_null() {
1729 if (*mi).shadowDepth >= depth {
1730 (*mi).shadowDepth = -1;
1731 }
1732 mi = (*mi).next;
1733 }
1734 }
1735}
1736
1737#[no_mangle]
1753pub unsafe extern "C" fn xmlFreeNs(cur: *mut _xmlNs) {
1754 unsafe { free_ns_impl(cur) };
1755}
1756
1757#[no_mangle]
1769pub unsafe extern "C" fn xmlFreeNsList(cur: *mut _xmlNs) {
1770 let mut c = cur;
1771 while !c.is_null() {
1772 let next = (*c).next;
1773 unsafe { free_ns_impl(c) };
1774 c = next;
1775 }
1776}
1777
1778#[no_mangle]
1794pub unsafe extern "C" fn xmlFreeProp(cur: *mut _xmlAttr) {
1795 unsafe { free_prop_impl(cur) };
1796}
1797
1798#[no_mangle]
1810pub unsafe extern "C" fn xmlFreePropList(cur: *mut _xmlAttr) {
1811 let mut c = cur;
1812 while !c.is_null() {
1813 let next = (*c).next;
1814 unsafe { free_prop_impl(c) };
1815 c = next;
1816 }
1817}
1818
1819#[no_mangle]
1839pub unsafe extern "C" fn xmlNewNodeEatName(ns: *mut _xmlNs, name: *mut xmlChar) -> *mut _xmlNode {
1840 unsafe { new_doc_node_eat_name(ptr::null_mut(), ns, name, ptr::null()) }
1841}
1842
1843#[no_mangle]
1860pub unsafe extern "C" fn xmlNewDocNode(
1861 doc: *mut _xmlDoc,
1862 ns: *mut _xmlNs,
1863 name: *const xmlChar,
1864 content: *const xmlChar,
1865) -> *mut _xmlNode {
1866 unsafe { new_doc_node(doc, ns, name, content) }
1867}
1868
1869#[no_mangle]
1882pub unsafe extern "C" fn xmlNewDocNodeEatName(
1883 doc: *mut _xmlDoc,
1884 ns: *mut _xmlNs,
1885 name: *mut xmlChar,
1886 content: *const xmlChar,
1887) -> *mut _xmlNode {
1888 unsafe { new_doc_node_eat_name(doc, ns, name, content) }
1889}
1890
1891#[no_mangle]
1904pub unsafe extern "C" fn xmlNewDocRawNode(
1905 doc: *mut _xmlDoc,
1906 ns: *mut _xmlNs,
1907 name: *const xmlChar,
1908 content: *const xmlChar,
1909) -> *mut _xmlNode {
1910 unsafe { new_doc_raw_node(doc, ns, name, content) }
1911}
1912
1913#[no_mangle]
1925pub unsafe extern "C" fn xmlNewDocFragment(doc: *mut _xmlDoc) -> *mut _xmlNode {
1926 let cur = unsafe { xmlMallocZero(size_of::<_xmlNode>()) } as *mut _xmlNode;
1927 if cur.is_null() {
1928 return ptr::null_mut();
1929 }
1930 (*cur).type_ = XML_DOCUMENT_FRAG_NODE as c_int;
1931 (*cur).doc = doc;
1932 cur
1933}
1934
1935#[no_mangle]
1947pub unsafe extern "C" fn xmlNewProp(
1948 node: *mut _xmlNode,
1949 name: *const xmlChar,
1950 value: *const xmlChar,
1951) -> *mut _xmlAttr {
1952 if name.is_null() {
1953 return ptr::null_mut();
1954 }
1955 unsafe { new_prop_internal(node, ptr::null_mut(), name, value, 0) }
1956}
1957
1958#[no_mangle]
1971pub unsafe extern "C" fn xmlNewNsProp(
1972 node: *mut _xmlNode,
1973 ns: *mut _xmlNs,
1974 name: *const xmlChar,
1975 value: *const xmlChar,
1976) -> *mut _xmlAttr {
1977 if name.is_null() {
1978 return ptr::null_mut();
1979 }
1980 unsafe { new_prop_internal(node, ns, name, value, 0) }
1981}
1982
1983#[no_mangle]
1996pub unsafe extern "C" fn xmlNewNsPropEatName(
1997 node: *mut _xmlNode,
1998 ns: *mut _xmlNs,
1999 name: *mut xmlChar,
2000 value: *const xmlChar,
2001) -> *mut _xmlAttr {
2002 if name.is_null() {
2003 return ptr::null_mut();
2004 }
2005 unsafe { new_prop_internal(node, ns, name, value, 1) }
2006}
2007
2008#[no_mangle]
2021pub unsafe extern "C" fn xmlNewDocProp(
2022 doc: *mut _xmlDoc,
2023 name: *const xmlChar,
2024 value: *const xmlChar,
2025) -> *mut _xmlAttr {
2026 if name.is_null() {
2027 return ptr::null_mut();
2028 }
2029 let cur = unsafe { xmlMallocZero(size_of::<_xmlAttr>()) } as *mut _xmlAttr;
2030 if cur.is_null() {
2031 return ptr::null_mut();
2032 }
2033 (*cur).type_ = XML_ATTRIBUTE_NODE as c_int;
2034 (*cur).name = unsafe { dup_str(name) };
2035 if (*cur).name.is_null() {
2036 unsafe { xmlFreeImpl(cur as *mut c_void) };
2037 return ptr::null_mut();
2038 }
2039 (*cur).doc = doc;
2040 if !value.is_null() {
2041 if unsafe { node_parse_att_value(doc, cur as *mut _xmlNode, value, usize::MAX) } < 0 {
2042 unsafe { free_prop_impl(cur) };
2043 return ptr::null_mut();
2044 }
2045 }
2046 cur
2047}
2048
2049#[no_mangle]
2064pub unsafe extern "C" fn xmlNewReference(
2065 doc: *const _xmlDoc,
2066 name: *const xmlChar,
2067) -> *mut _xmlNode {
2068 if name.is_null() {
2069 return ptr::null_mut();
2070 }
2071 let cur = unsafe { xmlMallocZero(size_of::<_xmlNode>()) } as *mut _xmlNode;
2072 if cur.is_null() {
2073 return ptr::null_mut();
2074 }
2075 (*cur).type_ = XML_ENTITY_REF_NODE as c_int;
2076 (*cur).doc = doc as *mut _xmlDoc;
2077 let mut nm = name;
2078 if *nm == b'&' {
2079 nm = nm.add(1);
2080 let len = unsafe { str_len(nm) } as usize;
2081 (*cur).name = if len > 0 && unsafe { *nm.add(len - 1) } == b';' {
2082 unsafe { crate::abi::exports_xml2::xmlStrndup(nm, (len - 1) as c_int) }
2083 } else {
2084 unsafe { crate::abi::exports_xml2::xmlStrndup(nm, len as c_int) }
2085 };
2086 } else {
2087 (*cur).name = unsafe { dup_str(nm) };
2088 }
2089 if (*cur).name.is_null() {
2090 unsafe { tree::free_node(cur) };
2091 return ptr::null_mut();
2092 }
2093 let ent = unsafe { tree::get_doc_entity(doc as *mut _xmlDoc, (*cur).name) };
2094 if !ent.is_null() {
2095 (*cur).content = (*ent).content;
2096 (*cur).children = ent as *mut _xmlNode;
2097 (*cur).last = ent as *mut _xmlNode;
2098 }
2099 cur
2100}
2101
2102#[no_mangle]
2120pub unsafe extern "C" fn xmlNewTextChild(
2121 parent: *mut _xmlNode,
2122 ns: *mut _xmlNs,
2123 name: *const xmlChar,
2124 content: *const xmlChar,
2125) -> *mut _xmlNode {
2126 if parent.is_null() || name.is_null() {
2127 return ptr::null_mut();
2128 }
2129 let mut ns = ns;
2130 match (*parent).type_ as u32 {
2131 t if t == XML_DOCUMENT_NODE as u32
2132 || t == XML_HTML_DOCUMENT_NODE as u32
2133 || t == XML_DOCUMENT_FRAG_NODE as u32 => {}
2134 t if t == XML_ELEMENT_NODE as u32 => {
2135 if ns.is_null() {
2136 ns = (*parent).ns;
2137 }
2138 }
2139 _ => return ptr::null_mut(),
2140 }
2141 let cur = unsafe { new_doc_raw_node((*parent).doc, ns, name, content) };
2142 if cur.is_null() {
2143 return ptr::null_mut();
2144 }
2145 (*cur).parent = parent;
2146 if (*parent).children.is_null() {
2147 (*parent).children = cur;
2148 (*parent).last = cur;
2149 } else {
2150 let prev = (*parent).last;
2151 (*prev).next = cur;
2152 (*cur).prev = prev;
2153 (*parent).last = cur;
2154 }
2155 cur
2156}
2157
2158#[no_mangle]
2170pub unsafe extern "C" fn xmlNewTextLen(content: *const xmlChar, len: c_int) -> *mut _xmlNode {
2171 let cur = unsafe { xmlMallocZero(size_of::<_xmlNode>()) } as *mut _xmlNode;
2172 if cur.is_null() {
2173 return ptr::null_mut();
2174 }
2175 (*cur).type_ = XML_TEXT_NODE as c_int;
2176 (*cur).name = unsafe { dup_str(TEXT_NAME.as_ptr() as *const xmlChar) };
2177 if !content.is_null() {
2178 (*cur).content = unsafe { crate::abi::exports_xml2::xmlStrndup(content, len) };
2179 if (*cur).content.is_null() {
2180 unsafe { tree::free_node(cur) };
2181 return ptr::null_mut();
2182 }
2183 }
2184 cur
2185}
2186
2187#[no_mangle]
2203pub unsafe extern "C" fn xmlNodeSetContent(cur: *mut _xmlNode, content: *const xmlChar) -> c_int {
2204 unsafe { node_set_content_internal(cur, content, -1) }
2205}
2206
2207#[no_mangle]
2219pub unsafe extern "C" fn xmlNodeSetContentLen(
2220 cur: *mut _xmlNode,
2221 content: *const xmlChar,
2222 len: c_int,
2223) -> c_int {
2224 unsafe { node_set_content_internal(cur, content, len) }
2225}
2226
2227unsafe fn node_set_content_internal(
2229 cur: *mut _xmlNode,
2230 content: *const xmlChar,
2231 len: c_int,
2232) -> c_int {
2233 if cur.is_null() {
2234 return 1;
2235 }
2236 match (*cur).type_ as u32 {
2237 t if t == XML_DOCUMENT_FRAG_NODE as u32
2238 || t == XML_ELEMENT_NODE as u32
2239 || t == XML_ATTRIBUTE_NODE as u32 =>
2240 {
2241 let max_size = if len < 0 { usize::MAX } else { len as usize };
2242 if unsafe { node_parse_att_value((*cur).doc, cur, content, max_size) } < 0 {
2243 return -1;
2244 }
2245 }
2246 t if t == XML_TEXT_NODE as u32
2247 || t == XML_CDATA_SECTION_NODE as u32
2248 || t == XML_PI_NODE as u32
2249 || t == XML_COMMENT_NODE as u32 =>
2250 {
2251 let mut copy: *mut xmlChar = ptr::null_mut();
2252 if !content.is_null() {
2253 copy = if len < 0 {
2254 unsafe { dup_str(content) }
2255 } else {
2256 unsafe { crate::abi::exports_xml2::xmlStrndup(content, len) }
2257 };
2258 if copy.is_null() {
2259 return -1;
2260 }
2261 }
2262 unsafe { text_set_content(cur, copy) };
2263 }
2264 _ => {}
2265 }
2266 0
2267}
2268
2269#[no_mangle]
2284pub unsafe extern "C" fn xmlNodeAddContent(cur: *mut _xmlNode, content: *const xmlChar) -> c_int {
2285 let len = unsafe { str_len(content) };
2286 unsafe { xmlNodeAddContentLen(cur, content, len) }
2287}
2288
2289#[no_mangle]
2301pub unsafe extern "C" fn xmlNodeAddContentLen(
2302 cur: *mut _xmlNode,
2303 content: *const xmlChar,
2304 len: c_int,
2305) -> c_int {
2306 if cur.is_null() {
2307 return 1;
2308 }
2309 if content.is_null() || len <= 0 {
2310 return 0;
2311 }
2312 match (*cur).type_ as u32 {
2313 t if t == XML_DOCUMENT_FRAG_NODE as u32
2314 || t == XML_ELEMENT_NODE as u32
2315 || t == XML_ATTRIBUTE_NODE as u32 =>
2316 {
2317 let new_node = unsafe { new_doc_text_len((*cur).doc, content, len) };
2318 if new_node.is_null() {
2319 return -1;
2320 }
2321 let tmp = unsafe { add_child_coalesce(cur, new_node) };
2322 if tmp.is_null() {
2323 unsafe { tree::free_node(new_node) };
2324 return -1;
2325 }
2326 }
2327 t if t == XML_TEXT_NODE as u32
2328 || t == XML_CDATA_SECTION_NODE as u32
2329 || t == XML_PI_NODE as u32
2330 || t == XML_COMMENT_NODE as u32 =>
2331 {
2332 return unsafe { text_add_content(cur, content, len) };
2333 }
2334 _ => {}
2335 }
2336 0
2337}
2338
2339#[no_mangle]
2351pub unsafe extern "C" fn xmlNodeGetContent(cur: *const _xmlNode) -> *mut xmlChar {
2352 unsafe { tree::node_get_content(cur as *mut _xmlNode) }
2353}
2354
2355#[no_mangle]
2371pub unsafe extern "C" fn xmlNodeSetLang(cur: *mut _xmlNode, lang: *const xmlChar) -> c_int {
2372 if cur.is_null() || (*cur).type_ != XML_ELEMENT_NODE as c_int {
2373 return 1;
2374 }
2375 let ns = unsafe { ensure_xml_decl((*cur).doc) };
2376 if ns.is_null() {
2377 return -1;
2378 }
2379 let attr = unsafe { set_ns_prop_impl(cur, ns, b"lang\0".as_ptr() as *const xmlChar, lang) };
2380 if attr.is_null() {
2381 return -1;
2382 }
2383 0
2384}
2385
2386#[no_mangle]
2398pub unsafe extern "C" fn xmlNodeGetLang(cur: *const _xmlNode) -> *mut xmlChar {
2399 if cur.is_null() || (*cur).type_ == XML_NAMESPACE_DECL as c_int {
2400 return ptr::null_mut();
2401 }
2402 let mut c = cur;
2403 while !c.is_null() {
2404 let lang = unsafe {
2405 get_attr_value(
2406 c as *mut _xmlNode,
2407 b"lang\0".as_ptr() as *const xmlChar,
2408 XML_XML_NAMESPACE.as_ptr() as *const xmlChar,
2409 )
2410 };
2411 if !lang.is_null() {
2412 return lang;
2413 }
2414 c = (*c).parent;
2415 }
2416 ptr::null_mut()
2417}
2418
2419#[no_mangle]
2431pub unsafe extern "C" fn xmlNodeSetSpacePreserve(cur: *mut _xmlNode, val: c_int) -> c_int {
2432 if cur.is_null() || (*cur).type_ != XML_ELEMENT_NODE as c_int {
2433 return 1;
2434 }
2435 let ns = unsafe { ensure_xml_decl((*cur).doc) };
2436 if ns.is_null() {
2437 return -1;
2438 }
2439 let string: &[u8] = if val == 0 {
2440 b"default\0"
2441 } else {
2442 b"preserve\0"
2443 };
2444 let attr = unsafe {
2445 set_ns_prop_impl(
2446 cur,
2447 ns,
2448 b"space\0".as_ptr() as *const xmlChar,
2449 string.as_ptr() as *const xmlChar,
2450 )
2451 };
2452 if attr.is_null() {
2453 return -1;
2454 }
2455 0
2456}
2457
2458#[no_mangle]
2470pub unsafe extern "C" fn xmlNodeGetSpacePreserve(cur: *const _xmlNode) -> c_int {
2471 if cur.is_null() || (*cur).type_ != XML_ELEMENT_NODE as c_int {
2472 return -1;
2473 }
2474 let mut c = cur;
2475 while !c.is_null() {
2476 let space = unsafe {
2477 get_attr_value(
2478 c as *mut _xmlNode,
2479 b"space\0".as_ptr() as *const xmlChar,
2480 XML_XML_NAMESPACE.as_ptr() as *const xmlChar,
2481 )
2482 };
2483 if !space.is_null() {
2484 if unsafe {
2485 crate::abi::exports_xml2::xmlStrEqual(
2486 space,
2487 b"preserve\0".as_ptr() as *const xmlChar,
2488 ) != 0
2489 } {
2490 unsafe { xmlFreeImpl(space as *mut c_void) };
2491 return 1;
2492 }
2493 if unsafe {
2494 crate::abi::exports_xml2::xmlStrEqual(
2495 space,
2496 b"default\0".as_ptr() as *const xmlChar,
2497 ) != 0
2498 } {
2499 unsafe { xmlFreeImpl(space as *mut c_void) };
2500 return 0;
2501 }
2502 unsafe { xmlFreeImpl(space as *mut c_void) };
2503 }
2504 c = (*c).parent;
2505 }
2506 -1
2507}
2508
2509#[no_mangle]
2521pub unsafe extern "C" fn xmlNodeSetName(cur: *mut _xmlNode, name: *const xmlChar) {
2522 if cur.is_null() || name.is_null() {
2523 return;
2524 }
2525 match (*cur).type_ as u32 {
2526 t if t == XML_ELEMENT_NODE as u32
2527 || t == XML_ATTRIBUTE_NODE as u32
2528 || t == XML_PI_NODE as u32
2529 || t == XML_ENTITY_REF_NODE as u32 => {}
2530 _ => return,
2531 }
2532 let copy = unsafe { dup_str(name) };
2533 if copy.is_null() {
2534 return;
2535 }
2536 let old = (*cur).name;
2537 (*cur).name = copy;
2538 if !old.is_null() {
2539 unsafe { xmlFreeImpl(old as *mut c_void) };
2540 }
2541}
2542
2543#[no_mangle]
2556pub unsafe extern "C" fn xmlNodeSetBase(cur: *mut _xmlNode, uri: *const xmlChar) -> c_int {
2557 if cur.is_null() {
2558 return -1;
2559 }
2560 match (*cur).type_ as u32 {
2561 t if t == XML_ELEMENT_NODE as u32 || t == XML_ATTRIBUTE_NODE as u32 => {}
2562 t if t == XML_DOCUMENT_NODE as u32 || t == XML_HTML_DOCUMENT_NODE as u32 => {
2563 let doc = cur as *mut _xmlDoc;
2564 if !(*doc).URL.is_null() {
2565 unsafe { xmlFreeImpl((*doc).URL as *mut c_void) };
2566 }
2567 if uri.is_null() {
2568 (*doc).URL = ptr::null_mut();
2569 } else {
2570 (*doc).URL = unsafe { crate::abi::exports_uri::xmlPathToURI(uri as *const c_char) };
2571 if (*doc).URL.is_null() {
2572 return -1;
2573 }
2574 }
2575 return 0;
2576 }
2577 _ => return -1,
2578 }
2579 let ns = unsafe { ensure_xml_decl((*cur).doc) };
2580 if ns.is_null() {
2581 return -1;
2582 }
2583 let fixed = unsafe { crate::abi::exports_uri::xmlPathToURI(uri as *const c_char) };
2584 if fixed.is_null() {
2585 return -1;
2586 }
2587 let attr = unsafe { set_ns_prop_impl(cur, ns, b"base\0".as_ptr() as *const xmlChar, fixed) };
2588 if attr.is_null() {
2589 unsafe { xmlFreeImpl(fixed as *mut c_void) };
2590 return -1;
2591 }
2592 unsafe { xmlFreeImpl(fixed as *mut c_void) };
2593 0
2594}
2595
2596#[no_mangle]
2608pub unsafe extern "C" fn xmlNodeGetBaseSafe(
2609 doc: *const _xmlDoc,
2610 cur: *const _xmlNode,
2611 baseOut: *mut *mut xmlChar,
2612) -> c_int {
2613 if baseOut.is_null() {
2614 return 1;
2615 }
2616 *baseOut = ptr::null_mut();
2617 if cur.is_null() && doc.is_null() {
2618 return 1;
2619 }
2620 if !cur.is_null() && (*cur).type_ == XML_NAMESPACE_DECL as c_int {
2621 return 1;
2622 }
2623 let mut doc = doc;
2624 if doc.is_null() {
2625 doc = (*cur).doc;
2626 }
2627 let mut ret: *mut xmlChar = ptr::null_mut();
2628
2629 if !doc.is_null() && (*doc).type_ == XML_HTML_DOCUMENT_NODE as c_int {
2630 let mut c = (*doc).children;
2631 while !c.is_null() {
2632 if (*c).type_ != XML_ELEMENT_NODE as c_int {
2633 c = (*c).next;
2634 continue;
2635 }
2636 if unsafe { strcasecmp_eq((*c).name, b"html") } {
2637 c = (*c).children;
2638 continue;
2639 }
2640 if unsafe { strcasecmp_eq((*c).name, b"head") } {
2641 c = (*c).children;
2642 continue;
2643 }
2644 if unsafe { strcasecmp_eq((*c).name, b"base") } {
2645 ret =
2646 unsafe { get_attr_value(c, b"href\0".as_ptr() as *const xmlChar, ptr::null()) };
2647 if ret.is_null() {
2648 return 1;
2649 }
2650 *baseOut = ret;
2651 return 0;
2652 }
2653 c = (*c).next;
2654 }
2655 return 0;
2656 }
2657
2658 let mut c = cur;
2659 while !c.is_null() {
2660 if (*c).type_ == XML_ENTITY_DECL as c_int {
2661 let ent = c as *const _xmlEntity as *mut _xmlEntity;
2662 if (*ent).URI.is_null() {
2663 break;
2664 }
2665 if !ret.is_null() {
2666 unsafe { xmlFreeImpl(ret as *mut c_void) };
2667 }
2668 ret = unsafe { dup_str((*ent).URI) };
2669 if ret.is_null() {
2670 return -1;
2671 }
2672 *baseOut = ret;
2673 return 0;
2674 }
2675 if (*c).type_ == XML_ELEMENT_NODE as c_int {
2676 let base = unsafe {
2677 get_attr_value(
2678 c as *mut _xmlNode,
2679 b"base\0".as_ptr() as *const xmlChar,
2680 XML_XML_NAMESPACE.as_ptr() as *const xmlChar,
2681 )
2682 };
2683 if !base.is_null() {
2684 if !ret.is_null() {
2685 let mut newbase: *mut xmlChar = ptr::null_mut();
2686 let res = unsafe {
2687 crate::abi::exports_uri::xmlBuildURISafe(
2688 ret as *const c_char,
2689 base as *const c_char,
2690 &mut newbase,
2691 )
2692 };
2693 unsafe { xmlFreeImpl(ret as *mut c_void) };
2694 unsafe { xmlFreeImpl(base as *mut c_void) };
2695 if res != 0 {
2696 return res;
2697 }
2698 ret = newbase;
2699 } else {
2700 ret = base;
2701 }
2702 if !ret.is_null()
2703 && (unsafe { *ret } == b'h'
2704 || unsafe { *ret } == b'f'
2705 || unsafe { *ret } == b'u')
2706 {
2707 if unsafe {
2708 crate::abi::exports_xml2::xmlStrncmp(
2709 ret,
2710 b"http://\0".as_ptr() as *const xmlChar,
2711 7,
2712 ) == 0
2713 } || unsafe {
2714 crate::abi::exports_xml2::xmlStrncmp(
2715 ret,
2716 b"ftp://\0".as_ptr() as *const xmlChar,
2717 6,
2718 ) == 0
2719 } || unsafe {
2720 crate::abi::exports_xml2::xmlStrncmp(
2721 ret,
2722 b"urn:\0".as_ptr() as *const xmlChar,
2723 4,
2724 ) == 0
2725 } {
2726 *baseOut = ret;
2727 return 0;
2728 }
2729 }
2730 }
2731 }
2732 c = (*c).parent;
2733 }
2734
2735 if !doc.is_null() && !(*doc).URL.is_null() {
2736 if ret.is_null() {
2737 ret = unsafe { dup_str((*doc).URL) };
2738 if ret.is_null() {
2739 return -1;
2740 }
2741 } else {
2742 let mut newbase: *mut xmlChar = ptr::null_mut();
2743 let res = unsafe {
2744 crate::abi::exports_uri::xmlBuildURISafe(
2745 ret as *const c_char,
2746 (*doc).URL as *const c_char,
2747 &mut newbase,
2748 )
2749 };
2750 unsafe { xmlFreeImpl(ret as *mut c_void) };
2751 if res != 0 {
2752 return res;
2753 }
2754 ret = newbase;
2755 }
2756 }
2757 *baseOut = ret;
2758 0
2759}
2760
2761#[no_mangle]
2774pub unsafe extern "C" fn xmlNodeGetBase(doc: *const _xmlDoc, cur: *const _xmlNode) -> *mut xmlChar {
2775 let mut base: *mut xmlChar = ptr::null_mut();
2776 unsafe { xmlNodeGetBaseSafe(doc, cur, &mut base) };
2777 base
2778}
2779
2780#[no_mangle]
2792pub unsafe extern "C" fn xmlNodeIsText(node: *const _xmlNode) -> c_int {
2793 if node.is_null() {
2794 return 0;
2795 }
2796 if (*node).type_ == XML_TEXT_NODE as c_int {
2797 1
2798 } else {
2799 0
2800 }
2801}
2802
2803#[no_mangle]
2820pub unsafe extern "C" fn xmlSetTreeDoc(tree: *mut _xmlNode, doc: *mut _xmlDoc) -> c_int {
2821 unsafe { set_tree_doc_impl(tree, doc) }
2822}
2823
2824#[no_mangle]
2838pub unsafe extern "C" fn xmlAddNextSibling(
2839 prev: *mut _xmlNode,
2840 cur: *mut _xmlNode,
2841) -> *mut _xmlNode {
2842 if prev.is_null()
2843 || (*prev).type_ == XML_NAMESPACE_DECL as c_int
2844 || cur.is_null()
2845 || (*cur).type_ == XML_NAMESPACE_DECL as c_int
2846 || cur == prev
2847 {
2848 return ptr::null_mut();
2849 }
2850 if cur == (*prev).next {
2851 return cur;
2852 }
2853 unsafe { insert_node((*prev).doc, cur, (*prev).parent, prev, (*prev).next, 0) }
2854}
2855
2856#[no_mangle]
2870pub unsafe extern "C" fn xmlAddPrevSibling(
2871 next: *mut _xmlNode,
2872 cur: *mut _xmlNode,
2873) -> *mut _xmlNode {
2874 if next.is_null()
2875 || (*next).type_ == XML_NAMESPACE_DECL as c_int
2876 || cur.is_null()
2877 || (*cur).type_ == XML_NAMESPACE_DECL as c_int
2878 || cur == next
2879 {
2880 return ptr::null_mut();
2881 }
2882 if cur == (*next).prev {
2883 return cur;
2884 }
2885 unsafe { insert_node((*next).doc, cur, (*next).parent, (*next).prev, next, 0) }
2886}
2887
2888#[no_mangle]
2900pub unsafe extern "C" fn xmlAddChildList(
2901 parent: *mut _xmlNode,
2902 cur: *mut _xmlNode,
2903) -> *mut _xmlNode {
2904 if parent.is_null() || (*parent).type_ == XML_NAMESPACE_DECL as c_int {
2905 return ptr::null_mut();
2906 }
2907 if cur.is_null() || (*cur).type_ == XML_NAMESPACE_DECL as c_int {
2908 return ptr::null_mut();
2909 }
2910
2911 let mut oom = 0;
2912 let mut iter = cur;
2913 while !iter.is_null() {
2914 if (*iter).doc != (*parent).doc {
2915 if unsafe { set_tree_doc_impl(iter, (*parent).doc) } < 0 {
2916 oom = 1;
2917 }
2918 }
2919 iter = (*iter).next;
2920 }
2921 if oom != 0 {
2922 return ptr::null_mut();
2923 }
2924
2925 let mut cur = cur;
2926 if (*parent).children.is_null() {
2927 (*parent).children = cur;
2928 } else {
2929 let prev = (*parent).last;
2930 if (*cur).type_ == XML_TEXT_NODE as c_int
2931 && (*prev).type_ == XML_TEXT_NODE as c_int
2932 && unsafe { str_eq_or_ptr((*cur).name, (*prev).name) }
2933 {
2934 if unsafe { text_add_content(prev, (*cur).content, -1) } < 0 {
2935 return ptr::null_mut();
2936 }
2937 let next = (*cur).next;
2938 unsafe { tree::free_node(cur) };
2939 if next.is_null() {
2940 return prev;
2941 }
2942 cur = next;
2943 }
2944 (*prev).next = cur;
2945 (*cur).prev = prev;
2946 }
2947 while !(*cur).next.is_null() {
2948 (*cur).parent = parent;
2949 cur = (*cur).next;
2950 }
2951 (*cur).parent = parent;
2952 (*parent).last = cur;
2953 cur
2954}
2955
2956#[no_mangle]
2969pub unsafe extern "C" fn xmlReplaceNode(old: *mut _xmlNode, cur: *mut _xmlNode) -> *mut _xmlNode {
2970 if old == cur {
2971 return ptr::null_mut();
2972 }
2973 if old.is_null() || (*old).type_ == XML_NAMESPACE_DECL as c_int || (*old).parent.is_null() {
2974 return ptr::null_mut();
2975 }
2976 if cur.is_null() || (*cur).type_ == XML_NAMESPACE_DECL as c_int {
2977 unsafe { tree::unlink_node(old) };
2979 return old;
2980 }
2981 if (*old).type_ == XML_ATTRIBUTE_NODE as c_int && (*cur).type_ != XML_ATTRIBUTE_NODE as c_int {
2982 return old;
2983 }
2984 if (*cur).type_ == XML_ATTRIBUTE_NODE as c_int && (*old).type_ != XML_ATTRIBUTE_NODE as c_int {
2985 return old;
2986 }
2987 unsafe { tree::unlink_node(cur) };
2988 if unsafe { set_tree_doc_impl(cur, (*old).doc) } < 0 {
2989 return ptr::null_mut();
2990 }
2991 (*cur).parent = (*old).parent;
2992 (*cur).next = (*old).next;
2993 if !(*cur).next.is_null() {
2994 (*(*cur).next).prev = cur;
2995 }
2996 (*cur).prev = (*old).prev;
2997 if !(*cur).prev.is_null() {
2998 (*(*cur).prev).next = cur;
2999 }
3000 if !(*cur).parent.is_null() {
3001 if (*cur).type_ == XML_ATTRIBUTE_NODE as c_int {
3002 if (*(*cur).parent).properties == old as *mut _xmlAttr {
3003 (*(*cur).parent).properties = cur as *mut _xmlAttr;
3004 }
3005 } else {
3006 if (*(*cur).parent).children == old {
3007 (*(*cur).parent).children = cur;
3008 }
3009 if (*(*cur).parent).last == old {
3010 (*(*cur).parent).last = cur;
3011 }
3012 }
3013 }
3014 (*old).next = ptr::null_mut();
3015 (*old).prev = ptr::null_mut();
3016 (*old).parent = ptr::null_mut();
3017 old
3018}
3019
3020#[no_mangle]
3038pub unsafe extern "C" fn xmlGetNsListSafe(
3039 doc: *const _xmlDoc,
3040 node: *const _xmlNode,
3041 out: *mut *mut *mut _xmlNs,
3042) -> c_int {
3043 let _ = doc;
3044 if out.is_null() {
3045 return 1;
3046 }
3047 *out = ptr::null_mut();
3048 if node.is_null() || (*node).type_ == XML_NAMESPACE_DECL as c_int {
3049 return 1;
3050 }
3051 let mut namespaces: *mut *mut _xmlNs = ptr::null_mut();
3052 let mut nbns: c_int = 0;
3053 let mut maxns: c_int = 0;
3054
3055 let mut n = node;
3056 while !n.is_null() {
3057 if (*n).type_ == XML_ELEMENT_NODE as c_int {
3058 let mut cur = (*n).nsDef;
3059 while !cur.is_null() {
3060 let mut i = 0;
3061 let mut found = false;
3062 while i < nbns {
3063 if unsafe {
3064 str_eq_or_ptr((*cur).prefix, (*(*namespaces).add(i as usize)).prefix)
3065 } {
3066 found = true;
3067 break;
3068 }
3069 i += 1;
3070 }
3071 if !found {
3072 if nbns >= maxns {
3073 let new_size = if maxns <= 0 { 10 } else { maxns * 2 };
3074 let tmp = unsafe {
3075 xmlReallocImpl(
3076 namespaces as *mut c_void,
3077 ((new_size + 1) as usize) * size_of::<*mut _xmlNs>(),
3078 )
3079 } as *mut *mut _xmlNs;
3080 if tmp.is_null() {
3081 unsafe { xmlFreeImpl(namespaces as *mut c_void) };
3082 return -1;
3083 }
3084 namespaces = tmp;
3085 maxns = new_size;
3086 }
3087 *namespaces.add(nbns as usize) = cur;
3088 nbns += 1;
3089 *namespaces.add(nbns as usize) = ptr::null_mut();
3090 }
3091 cur = (*cur).next;
3092 }
3093 }
3094 n = (*n).parent;
3095 }
3096
3097 *out = namespaces;
3098 if namespaces.is_null() {
3099 1
3100 } else {
3101 0
3102 }
3103}
3104
3105unsafe fn new_reconciled_ns(tree: *mut _xmlNode, ns: *mut _xmlNs) -> *mut _xmlNs {
3109 if tree.is_null() || (*tree).type_ != XML_ELEMENT_NODE as c_int {
3110 return ptr::null_mut();
3111 }
3112 if ns.is_null() || (*ns).type_ != XML_NAMESPACE_DECL as c_int {
3113 return ptr::null_mut();
3114 }
3115 let def = unsafe { tree::search_ns_by_href(ptr::null_mut(), tree, (*ns).href) };
3117 if !def.is_null() {
3118 return def;
3119 }
3120 let prefix_base: Vec<u8> = if (*ns).prefix.is_null() {
3122 b"default\0".to_vec()
3123 } else {
3124 unsafe { str_prefix((*ns).prefix, 20) }
3125 };
3126 let mut counter: c_int = 1;
3127 let mut buf: Vec<u8> = prefix_base.clone();
3128 loop {
3129 let res = unsafe { tree::search_ns(ptr::null_mut(), tree, buf.as_ptr() as *const xmlChar) };
3130 if res.is_null() {
3131 break;
3132 }
3133 if counter > 1000 {
3134 return ptr::null_mut();
3135 }
3136 let base = &prefix_base[..prefix_base.len().saturating_sub(1)];
3137 let s = format!("{}{}", String::from_utf8_lossy(base), counter);
3138 buf = s.into_bytes();
3139 buf.push(0);
3140 counter += 1;
3141 }
3142 unsafe { tree::new_ns(tree, (*ns).href, buf.as_ptr() as *const xmlChar) }
3143}
3144
3145#[no_mangle]
3158pub unsafe extern "C" fn xmlReconciliateNs(doc: *mut _xmlDoc, tree: *mut _xmlNode) -> c_int {
3159 let mut cache: Vec<(*mut _xmlNs, *mut _xmlNs)> = Vec::new();
3160 let mut ret = 0;
3161
3162 if tree.is_null() || (*tree).type_ != XML_ELEMENT_NODE as c_int {
3163 return -1;
3164 }
3165 if (*tree).doc != doc {
3166 return -1;
3167 }
3168 let mut node = tree;
3169 loop {
3170 if !(*node).ns.is_null() {
3172 let mut i = 0;
3173 let mut found = false;
3174 while i < cache.len() {
3175 if cache[i].0 == (*node).ns {
3176 (*node).ns = cache[i].1;
3177 found = true;
3178 break;
3179 }
3180 i += 1;
3181 }
3182 if !found {
3183 let n = unsafe { new_reconciled_ns(tree, (*node).ns) };
3184 if n.is_null() {
3185 ret = -1;
3186 } else {
3187 cache.push(((*node).ns, n));
3188 }
3189 (*node).ns = n;
3190 }
3191 }
3192 if (*node).type_ == XML_ELEMENT_NODE as c_int {
3194 let mut attr = (*node).properties;
3195 while !attr.is_null() {
3196 if !(*attr).ns.is_null() {
3197 let mut i = 0;
3198 let mut found = false;
3199 while i < cache.len() {
3200 if cache[i].0 == (*attr).ns {
3201 (*attr).ns = cache[i].1;
3202 found = true;
3203 break;
3204 }
3205 i += 1;
3206 }
3207 if !found {
3208 let n = unsafe { new_reconciled_ns(tree, (*attr).ns) };
3209 if n.is_null() {
3210 ret = -1;
3211 } else {
3212 cache.push(((*attr).ns, n));
3213 }
3214 (*attr).ns = n;
3215 }
3216 }
3217 attr = (*attr).next;
3218 }
3219 }
3220 if !(*node).children.is_null() && (*node).type_ != XML_ENTITY_REF_NODE as c_int {
3222 node = (*node).children;
3223 } else if node != tree && !(*node).next.is_null() {
3224 node = (*node).next;
3225 } else if node != tree {
3226 loop {
3229 if node == tree {
3230 break;
3231 }
3232 if !(*node).parent.is_null() {
3233 node = (*node).parent;
3234 }
3235 if node != tree && !(*node).next.is_null() {
3236 node = (*node).next;
3237 break;
3238 }
3239 if (*node).parent.is_null() {
3240 node = ptr::null_mut();
3241 break;
3242 }
3243 }
3244 if node == tree {
3245 node = ptr::null_mut();
3246 }
3247 } else {
3248 break;
3249 }
3250 if node.is_null() {
3251 break;
3252 }
3253 }
3254 ret
3255}
3256
3257static XML_COMPRESS_MODE: AtomicI32 = AtomicI32::new(0);
3262
3263#[no_mangle]
3271pub unsafe extern "C" fn xmlGetCompressMode() -> c_int {
3272 XML_COMPRESS_MODE.load(Ordering::Relaxed)
3273}
3274
3275#[no_mangle]
3285pub unsafe extern "C" fn xmlSetCompressMode(mode: c_int) {
3286 let m = if mode < 0 {
3287 0
3288 } else if mode > 9 {
3289 9
3290 } else {
3291 mode
3292 };
3293 XML_COMPRESS_MODE.store(m, Ordering::Relaxed);
3294}
3295
3296#[no_mangle]
3308pub unsafe extern "C" fn xmlDOMWrapNewCtxt() -> *mut _xmlDOMWrapCtxt {
3309 unsafe { xmlMallocZero(size_of::<_xmlDOMWrapCtxt>()) as *mut _xmlDOMWrapCtxt }
3310}
3311
3312#[no_mangle]
3324pub unsafe extern "C" fn xmlDOMWrapFreeCtxt(ctxt: *mut _xmlDOMWrapCtxt) {
3325 if ctxt.is_null() {
3326 return;
3327 }
3328 if !(*ctxt).namespaceMap.is_null() {
3329 unsafe { ns_map_free((*ctxt).namespaceMap as *mut NsMap) };
3330 }
3331 unsafe { xmlFreeImpl(ctxt as *mut c_void) };
3332}
3333
3334#[no_mangle]
3348pub unsafe extern "C" fn xmlDOMWrapRemoveNode(
3349 ctxt: *mut _xmlDOMWrapCtxt,
3350 doc: *mut _xmlDoc,
3351 node: *mut _xmlNode,
3352 options: c_int,
3353) -> c_int {
3354 let _ = options;
3355 let mut list: *mut *mut _xmlNs = ptr::null_mut();
3356 let mut size_list: c_int = 0;
3357 let mut nb_list: c_int = 0;
3358 let mut ret = 0;
3359
3360 if node.is_null() || doc.is_null() || (*node).doc != doc {
3361 return -1;
3362 }
3363 if (*node).parent.is_null() {
3364 return 0;
3365 }
3366 match (*node).type_ as u32 {
3367 t if t == XML_TEXT_NODE as u32
3368 || t == XML_CDATA_SECTION_NODE as u32
3369 || t == XML_ENTITY_REF_NODE as u32
3370 || t == XML_PI_NODE as u32
3371 || t == XML_COMMENT_NODE as u32 =>
3372 {
3373 unsafe { tree::unlink_node(node) };
3374 return 0;
3375 }
3376 t if t == XML_ELEMENT_NODE as u32 || t == XML_ATTRIBUTE_NODE as u32 => {}
3377 _ => return 1,
3378 }
3379 unsafe { tree::unlink_node(node) };
3380
3381 let mut cur = node;
3382 'outer: loop {
3383 let node_type = (*cur).type_;
3384 match node_type as u32 {
3385 t if t == XML_ELEMENT_NODE as u32 => {
3386 if ctxt.is_null() && !(*cur).nsDef.is_null() {
3387 let mut ns = (*cur).nsDef;
3388 loop {
3389 if unsafe {
3390 ns_norm_add_ns_map_item2(
3391 &mut list,
3392 &mut size_list,
3393 &mut nb_list,
3394 ns,
3395 ns,
3396 )
3397 } == -1
3398 {
3399 ret = -1;
3400 }
3401 if (*ns).next.is_null() {
3402 break;
3403 }
3404 ns = (*ns).next;
3405 }
3406 }
3407 if !(*cur).ns.is_null() {
3408 let mut mapped = false;
3409 if !list.is_null() {
3410 let mut i = 0;
3411 let mut j = 0;
3412 while i < nb_list {
3413 if (*cur).ns == *list.add(j as usize) {
3414 (*cur).ns = *list.add((j + 1) as usize);
3415 mapped = true;
3416 break;
3417 }
3418 i += 1;
3419 j += 2;
3420 }
3421 }
3422 if !mapped {
3423 let mut ns: *mut _xmlNs = ptr::null_mut();
3424 if ctxt.is_null() {
3425 ns = unsafe { store_ns(doc, (*(*cur).ns).href, (*(*cur).ns).prefix) };
3426 if ns.is_null() {
3427 ret = -1;
3428 }
3429 }
3430 if !ns.is_null() {
3431 if unsafe {
3432 ns_norm_add_ns_map_item2(
3433 &mut list,
3434 &mut size_list,
3435 &mut nb_list,
3436 (*cur).ns,
3437 ns,
3438 )
3439 } == -1
3440 {
3441 ret = -1;
3442 }
3443 }
3444 (*cur).ns = ns;
3445 }
3446 }
3447 if !(*cur).properties.is_null() {
3448 cur = (*cur).properties as *mut _xmlNode;
3449 continue 'outer;
3450 }
3451 }
3452 t if t == XML_ATTRIBUTE_NODE as u32 => {
3453 if !(*cur).ns.is_null() {
3454 let mut mapped = false;
3455 if !list.is_null() {
3456 let mut i = 0;
3457 let mut j = 0;
3458 while i < nb_list {
3459 if (*cur).ns == *list.add(j as usize) {
3460 (*cur).ns = *list.add((j + 1) as usize);
3461 mapped = true;
3462 break;
3463 }
3464 i += 1;
3465 j += 2;
3466 }
3467 }
3468 if !mapped {
3469 let mut ns: *mut _xmlNs = ptr::null_mut();
3470 if ctxt.is_null() {
3471 ns = unsafe { store_ns(doc, (*(*cur).ns).href, (*(*cur).ns).prefix) };
3472 if ns.is_null() {
3473 ret = -1;
3474 }
3475 }
3476 if !ns.is_null() {
3477 if unsafe {
3478 ns_norm_add_ns_map_item2(
3479 &mut list,
3480 &mut size_list,
3481 &mut nb_list,
3482 (*cur).ns,
3483 ns,
3484 )
3485 } == -1
3486 {
3487 ret = -1;
3488 }
3489 }
3490 (*cur).ns = ns;
3491 }
3492 }
3493 }
3494 _ => {}
3495 }
3496 if node_type == XML_ELEMENT_NODE as c_int && !(*cur).children.is_null() {
3498 cur = (*cur).children;
3499 continue 'outer;
3500 }
3501 loop {
3503 if cur.is_null() {
3504 break 'outer;
3505 }
3506 if !(*cur).next.is_null() {
3507 cur = (*cur).next;
3508 break;
3509 }
3510 let t = (*cur).type_;
3511 cur = (*cur).parent;
3512 if t == XML_ATTRIBUTE_NODE as c_int && !cur.is_null() && !(*cur).children.is_null() {
3513 cur = (*cur).children;
3514 break;
3515 }
3516 if cur.is_null() {
3518 break 'outer;
3519 }
3520 }
3521 }
3522
3523 if !list.is_null() {
3524 unsafe { xmlFreeImpl(list as *mut c_void) };
3525 }
3526 ret
3527}
3528
3529#[no_mangle]
3542pub unsafe extern "C" fn xmlDOMWrapReconcileNamespaces(
3543 ctxt: *mut _xmlDOMWrapCtxt,
3544 elem: *mut _xmlNode,
3545 options: c_int,
3546) -> c_int {
3547 let _ = ctxt;
3548 let mut depth: c_int = -1;
3549 let mut adoptns: c_int = 0;
3550 let mut parnsdone: c_int = 0;
3551 let mut ns_map: *mut NsMap = ptr::null_mut();
3552 let ancestors_only: c_int = 0;
3553 let opt_remove_redundant = (options & XML_DOM_RECONNS_REMOVEREDUND) != 0;
3554 let mut list_redund: *mut *mut _xmlNs = ptr::null_mut();
3555 let mut size_redund: c_int = 0;
3556 let mut nb_redund: c_int = 0;
3557 let mut ret = 0;
3558
3559 if elem.is_null() || (*elem).doc.is_null() || (*elem).type_ != XML_ELEMENT_NODE as c_int {
3560 return -1;
3561 }
3562 let doc = (*elem).doc;
3563 let mut cur = elem;
3564 let mut cur_elem: *mut _xmlNode = ptr::null_mut();
3565
3566 'outer: loop {
3567 match (*cur).type_ as u32 {
3568 t if t == XML_ELEMENT_NODE as u32 => {
3569 adoptns = 1;
3570 cur_elem = cur;
3571 depth += 1;
3572 if !(*cur).nsDef.is_null() {
3573 let mut prevns: *mut _xmlNs = ptr::null_mut();
3574 let mut ns = (*cur).nsDef;
3575 loop {
3576 if parnsdone == 0 {
3577 if !(*elem).parent.is_null()
3578 && (*elem).parent != (*(*elem).parent).doc as *mut _xmlNode
3579 {
3580 if unsafe { gather_in_scope_ns(&mut ns_map, (*elem).parent) } == -1
3581 {
3582 ret = -1;
3583 }
3584 }
3585 parnsdone = 1;
3586 }
3587 if opt_remove_redundant && unsafe { ns_map_not_empty(ns_map) } {
3589 let mut mi = (*ns_map).first;
3590 let mut removed = false;
3591 while !mi.is_null() {
3592 if (*mi).depth >= XML_TREE_NSMAP_PARENT
3593 && (*mi).shadowDepth == -1
3594 && !(*mi).newNs.is_null()
3595 && unsafe { str_eq_or_ptr((*ns).prefix, (*(*mi).newNs).prefix) }
3596 && unsafe { str_eq_or_ptr((*ns).href, (*(*mi).newNs).href) }
3597 {
3598 if unsafe {
3599 ns_norm_add_ns_map_item2(
3600 &mut list_redund,
3601 &mut size_redund,
3602 &mut nb_redund,
3603 ns,
3604 (*mi).newNs,
3605 )
3606 } == -1
3607 {
3608 ret = -1;
3609 } else {
3610 let next_ns = (*ns).next;
3611 if !prevns.is_null() {
3612 (*prevns).next = next_ns;
3613 } else {
3614 (*cur).nsDef = next_ns;
3615 }
3616 ns = next_ns;
3617 removed = true;
3618 break;
3619 }
3620 }
3621 mi = (*mi).next;
3622 }
3623 if removed {
3624 if ns.is_null() {
3625 break;
3626 }
3627 continue;
3628 }
3629 }
3630 if !(*cur).ns.is_null() && adoptns != 0 && (*cur).ns == ns {
3633 adoptns = 0;
3634 }
3635 if unsafe { ns_map_not_empty(ns_map) } {
3637 let mut mi = (*ns_map).first;
3638 while !mi.is_null() {
3639 if (*mi).depth >= XML_TREE_NSMAP_PARENT
3640 && (*mi).shadowDepth == -1
3641 && !(*mi).newNs.is_null()
3642 && unsafe { str_eq_or_ptr((*ns).prefix, (*(*mi).newNs).prefix) }
3643 {
3644 (*mi).shadowDepth = depth;
3645 }
3646 mi = (*mi).next;
3647 }
3648 }
3649 if unsafe { ns_map_add_item(&mut ns_map, -1, ns, ns, depth) }.is_null() {
3651 ret = -1;
3652 }
3653 prevns = ns;
3654 if (*ns).next.is_null() {
3655 break;
3656 }
3657 ns = (*ns).next;
3658 }
3659 }
3660 if adoptns == 0 {
3661 } else {
3663 let _ = unsafe {
3665 reconcile_ns_reference(
3666 doc,
3667 elem,
3668 cur,
3669 cur_elem,
3670 &mut ns_map,
3671 depth,
3672 ancestors_only,
3673 &mut ret,
3674 &mut parnsdone,
3675 &mut list_redund,
3676 &mut size_redund,
3677 &mut nb_redund,
3678 )
3679 };
3680 }
3681 if (*cur).type_ == XML_ELEMENT_NODE as c_int && !(*cur).properties.is_null() {
3683 cur = (*cur).properties as *mut _xmlNode;
3684 continue 'outer;
3685 }
3686 }
3687 t if t == XML_ATTRIBUTE_NODE as u32 => {
3688 let _ = unsafe {
3689 reconcile_ns_reference(
3690 doc,
3691 elem,
3692 cur,
3693 cur_elem,
3694 &mut ns_map,
3695 depth,
3696 ancestors_only,
3697 &mut ret,
3698 &mut parnsdone,
3699 &mut list_redund,
3700 &mut size_redund,
3701 &mut nb_redund,
3702 )
3703 };
3704 }
3705 _ => {
3706 }
3708 }
3709 if (*cur).type_ == XML_ELEMENT_NODE as c_int && !(*cur).children.is_null() {
3711 cur = (*cur).children;
3712 continue 'outer;
3713 }
3714 if cur == elem {
3716 break;
3717 }
3718 if (*cur).type_ == XML_ELEMENT_NODE as c_int {
3719 unsafe { ns_map_pop_depth(ns_map, depth) };
3720 depth -= 1;
3721 }
3722 if !(*cur).next.is_null() {
3723 cur = (*cur).next;
3724 } else {
3725 if (*cur).type_ == XML_ATTRIBUTE_NODE as c_int {
3726 cur = (*cur).parent;
3727 if (*cur).type_ == XML_ELEMENT_NODE as c_int && !(*cur).children.is_null() {
3729 cur = (*cur).children;
3730 continue 'outer;
3731 }
3732 if cur == elem {
3734 break;
3735 }
3736 if (*cur).type_ == XML_ELEMENT_NODE as c_int {
3737 unsafe { ns_map_pop_depth(ns_map, depth) };
3738 depth -= 1;
3739 }
3740 if !(*cur).next.is_null() {
3741 cur = (*cur).next;
3742 } else {
3743 cur = (*cur).parent;
3744 if cur.is_null() {
3745 break;
3746 }
3747 }
3748 continue 'outer;
3749 }
3750 cur = (*cur).parent;
3751 if cur.is_null() {
3752 break;
3753 }
3754 }
3756 }
3757
3758 if !list_redund.is_null() {
3759 let mut i = 0;
3760 let mut j = 0;
3761 while i < nb_redund {
3762 unsafe { free_ns_impl(*list_redund.add(j as usize)) };
3763 i += 1;
3764 j += 2;
3765 }
3766 unsafe { xmlFreeImpl(list_redund as *mut c_void) };
3767 }
3768 if !ns_map.is_null() {
3769 unsafe { ns_map_free(ns_map) };
3770 }
3771 ret
3772}
3773
3774unsafe fn reconcile_ns_reference(
3777 doc: *mut _xmlDoc,
3778 elem: *mut _xmlNode,
3779 cur: *mut _xmlNode,
3780 cur_elem: *mut _xmlNode,
3781 ns_map: *mut *mut NsMap,
3782 depth: c_int,
3783 ancestors_only: c_int,
3784 ret: &mut c_int,
3785 parnsdone: &mut c_int,
3786 list_redund: *mut *mut *mut _xmlNs,
3787 _size_redund: *mut c_int,
3788 nb_redund: *mut c_int,
3789) -> c_int {
3790 if (*cur).ns.is_null() {
3791 return 0;
3792 }
3793 if *parnsdone == 0 {
3794 if !elem.is_null()
3795 && !(*elem).parent.is_null()
3796 && (*elem).parent != (*(*elem).parent).doc as *mut _xmlNode
3797 {
3798 if unsafe { gather_in_scope_ns(ns_map, (*elem).parent) } == -1 {
3799 *ret = -1;
3800 }
3801 }
3802 *parnsdone = 1;
3803 }
3804 if !list_redund.is_null() && !(*list_redund).is_null() && *nb_redund > 0 {
3806 let list = *list_redund;
3807 let mut i = 0;
3808 let mut j = 0;
3809 while i < *nb_redund {
3810 if (*cur).ns == *list.add(j as usize) {
3811 (*cur).ns = *list.add((j + 1) as usize);
3812 return 0;
3813 }
3814 i += 1;
3815 j += 2;
3816 }
3817 }
3818 if unsafe { ns_map_not_empty(*ns_map) } {
3820 let mut mi = (*(*ns_map)).first;
3821 while !mi.is_null() {
3822 if (*mi).shadowDepth == -1 && (*cur).ns == (*mi).oldNs {
3823 (*cur).ns = (*mi).newNs;
3824 return 0;
3825 }
3826 mi = (*mi).next;
3827 }
3828 }
3829 let mut ns: *mut _xmlNs = ptr::null_mut();
3831 if unsafe {
3832 acquire_normalized_ns(
3833 doc,
3834 cur_elem,
3835 (*cur).ns,
3836 &mut ns,
3837 ns_map,
3838 depth,
3839 ancestors_only,
3840 if (*cur).type_ == XML_ATTRIBUTE_NODE as c_int {
3841 1
3842 } else {
3843 0
3844 },
3845 )
3846 } == -1
3847 {
3848 *ret = -1;
3849 }
3850 (*cur).ns = ns;
3851 0
3852}
3853
3854unsafe fn domwrap_adopt_branch(
3857 ctxt: *mut _xmlDOMWrapCtxt,
3858 node: *mut _xmlNode,
3859 dest_doc: *mut _xmlDoc,
3860 dest_parent: *mut _xmlNode,
3861) -> c_int {
3862 let mut ret = 0;
3863 let mut cur = node;
3864 let mut cur_elem: *mut _xmlNode = ptr::null_mut();
3865 let mut ns_map: *mut NsMap = ptr::null_mut();
3866 let mut ns: *mut _xmlNs = ptr::null_mut();
3867 let mut depth: c_int = -1;
3868 let mut parnsdone: c_int;
3869 let ancestors_only: c_int = 0;
3870 let mut leave = false;
3871
3872 if !ctxt.is_null() {
3873 ns_map = (*ctxt).namespaceMap as *mut NsMap;
3874 }
3875 if dest_parent.is_null() || (!ctxt.is_null() && (*ctxt).getNsForNodeFunc.is_some()) {
3878 parnsdone = 1;
3879 } else {
3880 parnsdone = 0;
3881 }
3882
3883 'outer: loop {
3884 if !leave {
3885 if (*cur).doc != dest_doc {
3886 if unsafe { node_set_doc_impl(cur, dest_doc) } < 0 {
3887 ret = -1;
3888 }
3889 }
3890 match (*cur).type_ as u32 {
3891 t if t == XML_XINCLUDE_START as u32 || t == XML_XINCLUDE_END as u32 => {
3892 ret = -1;
3893 leave = true;
3894 }
3895 t if t == XML_ELEMENT_NODE as u32 => {
3896 cur_elem = cur;
3897 depth += 1;
3898 if !(*cur).nsDef.is_null()
3899 && (ctxt.is_null() || (*ctxt).getNsForNodeFunc.is_none())
3900 {
3901 if parnsdone == 0 {
3902 if unsafe { gather_in_scope_ns(&mut ns_map, dest_parent) } == -1 {
3903 ret = -1;
3904 }
3905 parnsdone = 1;
3906 }
3907 let mut ns2 = (*cur).nsDef;
3908 loop {
3909 if unsafe { ns_map_not_empty(ns_map) } {
3910 let mut mi = (*ns_map).first;
3911 while !mi.is_null() {
3912 if (*mi).depth >= XML_TREE_NSMAP_PARENT
3913 && (*mi).shadowDepth == -1
3914 && !(*mi).newNs.is_null()
3915 && unsafe {
3916 str_eq_or_ptr((*ns2).prefix, (*(*mi).newNs).prefix)
3917 }
3918 {
3919 (*mi).shadowDepth = depth;
3920 }
3921 mi = (*mi).next;
3922 }
3923 }
3924 if unsafe { ns_map_add_item(&mut ns_map, -1, ns2, ns2, depth) }
3925 .is_null()
3926 {
3927 ret = -1;
3928 }
3929 if (*ns2).next.is_null() {
3930 break;
3931 }
3932 ns2 = (*ns2).next;
3933 }
3934 }
3935 if !(*cur).ns.is_null() {
3936 if parnsdone == 0 {
3937 if unsafe { gather_in_scope_ns(&mut ns_map, dest_parent) } == -1 {
3938 ret = -1;
3939 }
3940 parnsdone = 1;
3941 }
3942 let mut mapped = false;
3943 if unsafe { ns_map_not_empty(ns_map) } {
3944 let mut mi = (*ns_map).first;
3945 while !mi.is_null() {
3946 if (*mi).shadowDepth == -1 && (*cur).ns == (*mi).oldNs {
3947 (*cur).ns = (*mi).newNs;
3948 mapped = true;
3949 break;
3950 }
3951 mi = (*mi).next;
3952 }
3953 }
3954 if !mapped {
3955 if !ctxt.is_null() && (*ctxt).getNsForNodeFunc.is_some() {
3956 let f = (*ctxt).getNsForNodeFunc.unwrap();
3957 ns =
3958 unsafe { f(ctxt, cur, (*(*cur).ns).href, (*(*cur).ns).prefix) };
3959 unsafe {
3960 ns_map_add_item(
3961 &mut ns_map,
3962 -1,
3963 (*cur).ns,
3964 ns,
3965 XML_TREE_NSMAP_CUSTOM,
3966 )
3967 };
3968 (*cur).ns = ns;
3969 } else {
3970 if unsafe {
3971 acquire_normalized_ns(
3972 dest_doc,
3973 if dest_parent.is_null() {
3974 ptr::null_mut()
3975 } else {
3976 cur_elem
3977 },
3978 (*cur).ns,
3979 &mut ns,
3980 &mut ns_map,
3981 depth,
3982 ancestors_only,
3983 0,
3984 )
3985 } == -1
3986 {
3987 ret = -1;
3988 }
3989 (*cur).ns = ns;
3990 }
3991 }
3992 }
3993 (*cur).psvi = ptr::null_mut();
3994 (*cur).line = 0;
3995 (*cur).extra = 0;
3996 if !(*cur).properties.is_null() {
3997 cur = (*cur).properties as *mut _xmlNode;
3998 continue 'outer;
3999 }
4000 }
4001 t if t == XML_ATTRIBUTE_NODE as u32 => {
4002 if !(*cur).ns.is_null() {
4003 if parnsdone == 0 {
4004 if unsafe { gather_in_scope_ns(&mut ns_map, dest_parent) } == -1 {
4005 ret = -1;
4006 }
4007 parnsdone = 1;
4008 }
4009 let mut mapped = false;
4010 if unsafe { ns_map_not_empty(ns_map) } {
4011 let mut mi = (*ns_map).first;
4012 while !mi.is_null() {
4013 if (*mi).shadowDepth == -1 && (*cur).ns == (*mi).oldNs {
4014 (*cur).ns = (*mi).newNs;
4015 mapped = true;
4016 break;
4017 }
4018 mi = (*mi).next;
4019 }
4020 }
4021 if !mapped {
4022 if !ctxt.is_null() && (*ctxt).getNsForNodeFunc.is_some() {
4023 let f = (*ctxt).getNsForNodeFunc.unwrap();
4024 ns =
4025 unsafe { f(ctxt, cur, (*(*cur).ns).href, (*(*cur).ns).prefix) };
4026 unsafe {
4027 ns_map_add_item(
4028 &mut ns_map,
4029 -1,
4030 (*cur).ns,
4031 ns,
4032 XML_TREE_NSMAP_CUSTOM,
4033 )
4034 };
4035 (*cur).ns = ns;
4036 } else {
4037 if unsafe {
4038 acquire_normalized_ns(
4039 dest_doc,
4040 if dest_parent.is_null() {
4041 ptr::null_mut()
4042 } else {
4043 cur_elem
4044 },
4045 (*cur).ns,
4046 &mut ns,
4047 &mut ns_map,
4048 depth,
4049 ancestors_only,
4050 1,
4051 )
4052 } == -1
4053 {
4054 ret = -1;
4055 }
4056 (*cur).ns = ns;
4057 }
4058 }
4059 }
4060 }
4061 t if t == XML_TEXT_NODE as u32
4062 || t == XML_CDATA_SECTION_NODE as u32
4063 || t == XML_PI_NODE as u32
4064 || t == XML_COMMENT_NODE as u32
4065 || t == XML_ENTITY_REF_NODE as u32 =>
4066 {
4067 leave = true;
4068 }
4069 _ => {
4070 ret = -1;
4071 leave = true;
4072 }
4073 }
4074 if !leave {
4075 if !(*cur).children.is_null() {
4076 cur = (*cur).children;
4077 continue 'outer;
4078 }
4079 leave = true;
4080 }
4081 }
4082 leave = false;
4084 if cur == node {
4085 break;
4086 }
4087 if (*cur).type_ == XML_ELEMENT_NODE as c_int
4088 || (*cur).type_ == XML_XINCLUDE_START as c_int
4089 || (*cur).type_ == XML_XINCLUDE_END as c_int
4090 {
4091 unsafe { ns_map_pop_depth(ns_map, depth) };
4092 depth -= 1;
4093 }
4094 if !(*cur).next.is_null() {
4095 cur = (*cur).next;
4096 } else if (*cur).type_ == XML_ATTRIBUTE_NODE as c_int
4097 && !(*cur).parent.is_null()
4098 && !(*(*cur).parent).children.is_null()
4099 {
4100 cur = (*(*cur).parent).children;
4101 } else {
4102 cur = (*cur).parent;
4103 if cur.is_null() {
4104 break;
4105 }
4106 leave = true;
4108 }
4109 }
4110
4111 if !ns_map.is_null() {
4112 if !ctxt.is_null() && (*ctxt).namespaceMap == ns_map as *mut c_void {
4113 if !(*ns_map).first.is_null() {
4115 if !(*ns_map).pool.is_null() {
4116 (*(*ns_map).last).next = (*ns_map).pool;
4117 }
4118 (*ns_map).pool = (*ns_map).first;
4119 (*ns_map).first = ptr::null_mut();
4120 }
4121 } else {
4122 unsafe { ns_map_free(ns_map) };
4123 }
4124 }
4125 ret
4126}
4127
4128unsafe fn domwrap_adopt_attr(
4130 ctxt: *mut _xmlDOMWrapCtxt,
4131 attr: *mut _xmlAttr,
4132 dest_doc: *mut _xmlDoc,
4133 dest_parent: *mut _xmlNode,
4134) -> c_int {
4135 let _ = ctxt;
4136 let mut ret = 0;
4137 if attr.is_null() || dest_doc.is_null() {
4138 return -1;
4139 }
4140 if (*attr).doc != dest_doc {
4141 if unsafe { set_tree_doc_impl(attr as *mut _xmlNode, dest_doc) } < 0 {
4142 ret = -1;
4143 }
4144 }
4145 if !(*attr).ns.is_null() {
4146 let mut ns: *mut _xmlNs = ptr::null_mut();
4147 if unsafe { is_str_xml((*(*attr).ns).prefix) } {
4148 ns = unsafe { ensure_xml_decl(dest_doc) };
4149 } else if dest_parent.is_null() {
4150 ns = unsafe { store_ns(dest_doc, (*(*attr).ns).href, (*(*attr).ns).prefix) };
4151 } else {
4152 if unsafe {
4153 search_ns_by_namespace_strict(dest_doc, dest_parent, (*(*attr).ns).href, &mut ns, 1)
4154 } == -1
4155 {
4156 ret = -1;
4157 }
4158 if ns.is_null() {
4159 ns = unsafe {
4160 declare_ns_forced(
4161 dest_doc,
4162 dest_parent,
4163 (*(*attr).ns).href,
4164 (*(*attr).ns).prefix,
4165 1,
4166 )
4167 };
4168 }
4169 }
4170 if ns.is_null() {
4171 ret = -1;
4172 }
4173 (*attr).ns = ns;
4174 }
4175 ret
4176}
4177
4178#[no_mangle]
4192pub unsafe extern "C" fn xmlDOMWrapAdoptNode(
4193 ctxt: *mut _xmlDOMWrapCtxt,
4194 sourceDoc: *mut _xmlDoc,
4195 node: *mut _xmlNode,
4196 destDoc: *mut _xmlDoc,
4197 destParent: *mut _xmlNode,
4198 options: c_int,
4199) -> c_int {
4200 let _ = options;
4201 let mut ret = 0;
4202 if node.is_null()
4203 || (*node).type_ == XML_NAMESPACE_DECL as c_int
4204 || destDoc.is_null()
4205 || (!destParent.is_null() && (*destParent).doc != destDoc)
4206 {
4207 return -1;
4208 }
4209 let mut sourceDoc = sourceDoc;
4210 if sourceDoc.is_null() {
4211 sourceDoc = (*node).doc;
4212 } else if (*node).doc != sourceDoc {
4213 return -1;
4214 }
4215 if sourceDoc == destDoc {
4216 return -1;
4217 }
4218 match (*node).type_ as u32 {
4219 t if t == XML_ELEMENT_NODE as u32
4220 || t == XML_ATTRIBUTE_NODE as u32
4221 || t == XML_TEXT_NODE as u32
4222 || t == XML_CDATA_SECTION_NODE as u32
4223 || t == XML_ENTITY_REF_NODE as u32
4224 || t == XML_PI_NODE as u32
4225 || t == XML_COMMENT_NODE as u32 => {}
4226 t if t == XML_DOCUMENT_FRAG_NODE as u32 => return 2,
4227 _ => return 1,
4228 }
4229 if !(*node).parent.is_null() && destParent != (*node).parent {
4231 unsafe { tree::unlink_node(node) };
4232 }
4233 if (*node).type_ == XML_ELEMENT_NODE as c_int {
4234 return unsafe { domwrap_adopt_branch(ctxt, node, destDoc, destParent) };
4235 } else if (*node).type_ == XML_ATTRIBUTE_NODE as c_int {
4236 return unsafe { domwrap_adopt_attr(ctxt, node as *mut _xmlAttr, destDoc, destParent) };
4237 } else {
4238 if (*node).doc != destDoc {
4239 if unsafe { node_set_doc_impl(node, destDoc) } < 0 {
4240 ret = -1;
4241 }
4242 }
4243 }
4244 ret
4245}
4246
4247#[no_mangle]
4262pub unsafe extern "C" fn xmlDOMWrapCloneNode(
4263 ctxt: *mut _xmlDOMWrapCtxt,
4264 sourceDoc: *mut _xmlDoc,
4265 node: *mut _xmlNode,
4266 resNode: *mut *mut _xmlNode,
4267 destDoc: *mut _xmlDoc,
4268 destParent: *mut _xmlNode,
4269 deep: c_int,
4270 options: c_int,
4271) -> c_int {
4272 let _ = options;
4273 const ST_NORMAL: u8 = 0;
4274 const ST_INTO_CONTENT: u8 = 1;
4275 const ST_LEAVE: u8 = 2;
4276 let mut ret = 0;
4277 let mut cur = node;
4278 let mut clone_elem: *mut _xmlNode = ptr::null_mut();
4279 let mut ns_map: *mut NsMap = ptr::null_mut();
4280 let mut depth: c_int = -1;
4281 let mut parnsdone: c_int = 0;
4282 let ancestors_only: c_int = 0;
4283 let mut result_clone: *mut _xmlNode = ptr::null_mut();
4284 let mut clone: *mut _xmlNode = ptr::null_mut();
4285 let mut parent_clone: *mut _xmlNode = ptr::null_mut();
4286 let mut prev_clone: *mut _xmlNode = ptr::null_mut();
4287 let mut clone_ns: *mut _xmlNs = ptr::null_mut();
4288 let mut clone_ns_def_slot: *mut *mut _xmlNs = ptr::null_mut();
4289 let mut state: u8 = ST_NORMAL;
4290
4291 if node.is_null()
4292 || resNode.is_null()
4293 || destDoc.is_null()
4294 || (!destParent.is_null() && (*destParent).doc != destDoc)
4295 {
4296 return -1;
4297 }
4298 if (*node).type_ != XML_ELEMENT_NODE as c_int {
4299 return 1;
4300 }
4301 if !(*node).doc.is_null() && !sourceDoc.is_null() && (*node).doc != sourceDoc {
4302 return -1;
4303 }
4304 let mut sourceDoc = sourceDoc;
4305 if sourceDoc.is_null() {
4306 sourceDoc = (*node).doc;
4307 }
4308 if sourceDoc.is_null() {
4309 return -1;
4310 }
4311 if !ctxt.is_null() {
4312 ns_map = (*ctxt).namespaceMap as *mut NsMap;
4313 }
4314 *resNode = ptr::null_mut();
4315
4316 'outer: loop {
4317 if state == ST_NORMAL {
4318 if (*cur).doc != sourceDoc {
4319 ret = -1;
4321 break;
4322 }
4323 let cur_type = (*cur).type_;
4324 match cur_type as u32 {
4325 t if t == XML_XINCLUDE_START as u32 || t == XML_XINCLUDE_END as u32 => {
4326 ret = -1;
4327 break;
4328 }
4329 t if t == XML_ELEMENT_NODE as u32
4330 || t == XML_TEXT_NODE as u32
4331 || t == XML_CDATA_SECTION_NODE as u32
4332 || t == XML_COMMENT_NODE as u32
4333 || t == XML_PI_NODE as u32
4334 || t == XML_DOCUMENT_FRAG_NODE as u32
4335 || t == XML_ENTITY_REF_NODE as u32 =>
4336 {
4337 clone = unsafe { xmlMallocZero(size_of::<_xmlNode>()) } as *mut _xmlNode;
4338 if clone.is_null() {
4339 ret = -1;
4340 break;
4341 }
4342 if !result_clone.is_null() {
4343 (*clone).parent = parent_clone;
4344 if !prev_clone.is_null() {
4345 (*prev_clone).next = clone;
4346 (*clone).prev = prev_clone;
4347 } else {
4348 (*parent_clone).children = clone;
4349 }
4350 (*parent_clone).last = clone;
4351 } else {
4352 result_clone = clone;
4353 }
4354 }
4355 t if t == XML_ATTRIBUTE_NODE as u32 => {
4356 clone = unsafe { xmlMallocZero(size_of::<_xmlAttr>()) } as *mut _xmlNode;
4357 if clone.is_null() {
4358 ret = -1;
4359 break;
4360 }
4361 if !result_clone.is_null() {
4362 (*clone).parent = parent_clone;
4363 if !prev_clone.is_null() {
4364 (*prev_clone).next = clone;
4365 (*clone).prev = prev_clone;
4366 } else {
4367 (*parent_clone).properties = clone as *mut _xmlAttr;
4368 }
4369 } else {
4370 result_clone = clone;
4371 }
4372 }
4373 _ => {
4374 ret = -1;
4375 break;
4376 }
4377 }
4378 if ret == -1 {
4379 break;
4380 }
4381 (*clone).type_ = cur_type;
4382 (*clone).doc = destDoc;
4383 if !(*cur).name.is_null() {
4385 (*clone).name = unsafe { dup_str((*cur).name) };
4386 if (*clone).name.is_null() {
4387 ret = -1;
4388 break;
4389 }
4390 }
4391 match cur_type as u32 {
4392 t if t == XML_ELEMENT_NODE as u32 => {
4393 clone_elem = clone;
4394 depth += 1;
4395 if !(*cur).nsDef.is_null() {
4396 if parnsdone == 0 {
4397 if !destParent.is_null() && ctxt.is_null() {
4398 if unsafe { gather_in_scope_ns(&mut ns_map, destParent) } == -1 {
4399 ret = -1;
4400 break;
4401 }
4402 }
4403 parnsdone = 1;
4404 }
4405 clone_ns_def_slot = core::ptr::addr_of_mut!((*clone).nsDef);
4407 let mut ns = (*cur).nsDef;
4408 loop {
4409 clone_ns = unsafe { xmlMallocZero(size_of::<_xmlNs>()) } as *mut _xmlNs;
4410 if clone_ns.is_null() {
4411 ret = -1;
4412 break;
4413 }
4414 (*clone_ns).type_ = XML_LOCAL_NAMESPACE as c_int;
4415 if !(*ns).href.is_null() {
4416 (*clone_ns).href = unsafe { dup_str((*ns).href) };
4417 if (*clone_ns).href.is_null() {
4418 unsafe { free_ns_impl(clone_ns) };
4419 ret = -1;
4420 break;
4421 }
4422 }
4423 if !(*ns).prefix.is_null() {
4424 (*clone_ns).prefix = unsafe { dup_str((*ns).prefix) };
4425 if (*clone_ns).prefix.is_null() {
4426 unsafe { free_ns_impl(clone_ns) };
4427 ret = -1;
4428 break;
4429 }
4430 }
4431 *clone_ns_def_slot = clone_ns;
4432 clone_ns_def_slot = core::ptr::addr_of_mut!((*clone_ns).next);
4433 if ctxt.is_null() || (*ctxt).getNsForNodeFunc.is_none() {
4434 if unsafe { ns_map_not_empty(ns_map) } {
4435 let mut mi = (*ns_map).first;
4436 while !mi.is_null() {
4437 if (*mi).depth >= XML_TREE_NSMAP_PARENT
4438 && (*mi).shadowDepth == -1
4439 && !(*mi).newNs.is_null()
4440 && unsafe {
4441 str_eq_or_ptr((*ns).prefix, (*(*mi).newNs).prefix)
4442 }
4443 {
4444 (*mi).shadowDepth = depth;
4445 }
4446 mi = (*mi).next;
4447 }
4448 }
4449 if unsafe { ns_map_add_item(&mut ns_map, -1, ns, clone_ns, depth) }
4450 .is_null()
4451 {
4452 ret = -1;
4453 break;
4454 }
4455 }
4456 if (*ns).next.is_null() {
4457 break;
4458 }
4459 ns = (*ns).next;
4460 }
4461 if ret == -1 {
4462 break;
4463 }
4464 }
4465 }
4466 t if t == XML_PI_NODE as u32
4467 || t == XML_COMMENT_NODE as u32
4468 || t == XML_TEXT_NODE as u32
4469 || t == XML_CDATA_SECTION_NODE as u32 =>
4470 {
4471 if !(*cur).content.is_null() {
4472 (*clone).content = unsafe { dup_str((*cur).content) };
4473 if (*clone).content.is_null() {
4474 ret = -1;
4475 break;
4476 }
4477 }
4478 state = ST_LEAVE;
4479 continue 'outer;
4480 }
4481 t if t == XML_ENTITY_REF_NODE as u32 => {
4482 if sourceDoc != destDoc {
4483 if !(*destDoc).intSubset.is_null() || !(*destDoc).extSubset.is_null() {
4484 let ent = unsafe { tree::get_doc_entity(destDoc, (*cur).name) };
4485 if !ent.is_null() {
4486 (*clone).content = (*ent).content;
4487 (*clone).children = ent as *mut _xmlNode;
4488 (*clone).last = ent as *mut _xmlNode;
4489 }
4490 }
4491 } else {
4492 (*clone).content = (*cur).content;
4493 (*clone).children = (*cur).children;
4494 (*clone).last = (*cur).last;
4495 }
4496 state = ST_LEAVE;
4497 continue 'outer;
4498 }
4499 _ => {
4500 ret = -1;
4501 break;
4502 }
4503 }
4504 if ret == -1 {
4505 break;
4506 }
4507 if !(*cur).ns.is_null() {
4509 if parnsdone == 0 {
4510 if !destParent.is_null() && ctxt.is_null() {
4511 if unsafe { gather_in_scope_ns(&mut ns_map, destParent) } == -1 {
4512 ret = -1;
4513 break;
4514 }
4515 }
4516 parnsdone = 1;
4517 }
4518 let mut mapped = false;
4519 if unsafe { ns_map_not_empty(ns_map) } {
4520 let mut mi = (*ns_map).first;
4521 while !mi.is_null() {
4522 if (*mi).shadowDepth == -1 && (*cur).ns == (*mi).oldNs {
4523 (*clone).ns = (*mi).newNs;
4524 mapped = true;
4525 break;
4526 }
4527 mi = (*mi).next;
4528 }
4529 }
4530 if !mapped {
4531 if !ctxt.is_null() && (*ctxt).getNsForNodeFunc.is_some() {
4532 let f = (*ctxt).getNsForNodeFunc.unwrap();
4533 let ns = unsafe { f(ctxt, cur, (*(*cur).ns).href, (*(*cur).ns).prefix) };
4534 unsafe {
4535 ns_map_add_item(&mut ns_map, -1, (*cur).ns, ns, XML_TREE_NSMAP_CUSTOM)
4536 };
4537 (*clone).ns = ns;
4538 } else {
4539 let mut ns: *mut _xmlNs = ptr::null_mut();
4540 if unsafe {
4541 acquire_normalized_ns(
4542 destDoc,
4543 if destParent.is_null() {
4544 ptr::null_mut()
4545 } else {
4546 clone_elem
4547 },
4548 (*cur).ns,
4549 &mut ns,
4550 &mut ns_map,
4551 depth,
4552 ancestors_only,
4553 if (*cur).type_ == XML_ATTRIBUTE_NODE as c_int {
4554 1
4555 } else {
4556 0
4557 },
4558 )
4559 } == -1
4560 {
4561 ret = -1;
4562 break;
4563 }
4564 (*clone).ns = ns;
4565 }
4566 }
4567 }
4568 if (*cur).type_ == XML_ELEMENT_NODE as c_int && !(*cur).properties.is_null() {
4570 prev_clone = ptr::null_mut();
4571 parent_clone = clone;
4572 cur = (*cur).properties as *mut _xmlNode;
4573 continue 'outer; }
4575 state = ST_INTO_CONTENT;
4576 continue 'outer;
4577 } else if state == ST_INTO_CONTENT {
4578 if !(*cur).children.is_null() {
4579 if deep != 0 || (*cur).type_ == XML_ATTRIBUTE_NODE as c_int {
4580 prev_clone = ptr::null_mut();
4581 parent_clone = clone;
4582 cur = (*cur).children;
4583 state = ST_NORMAL;
4584 continue 'outer;
4585 }
4586 }
4587 state = ST_LEAVE;
4588 }
4589 if cur == node {
4591 break;
4592 }
4593 if (*cur).type_ == XML_ELEMENT_NODE as c_int
4594 || (*cur).type_ == XML_XINCLUDE_START as c_int
4595 || (*cur).type_ == XML_XINCLUDE_END as c_int
4596 {
4597 unsafe { ns_map_pop_depth(ns_map, depth) };
4598 depth -= 1;
4599 }
4600 if !(*cur).next.is_null() {
4601 prev_clone = clone;
4602 cur = (*cur).next;
4603 state = ST_NORMAL;
4604 } else if (*cur).type_ != XML_ATTRIBUTE_NODE as c_int {
4605 clone = (*clone).parent;
4606 if !clone.is_null() {
4607 parent_clone = (*clone).parent;
4608 }
4609 cur = (*cur).parent;
4610 if cur.is_null() {
4611 break;
4612 }
4613 state = ST_LEAVE;
4615 } else {
4616 clone = (*clone).parent;
4618 parent_clone = (*clone).parent;
4619 cur = (*cur).parent;
4620 if cur.is_null() {
4621 break;
4622 }
4623 state = ST_INTO_CONTENT;
4625 }
4626 }
4627
4628 if !ns_map.is_null() {
4630 if !ctxt.is_null() && (*ctxt).namespaceMap == ns_map as *mut c_void {
4631 if !(*ns_map).first.is_null() {
4633 if !(*ns_map).pool.is_null() {
4634 (*(*ns_map).last).next = (*ns_map).pool;
4635 }
4636 (*ns_map).pool = (*ns_map).first;
4637 (*ns_map).first = ptr::null_mut();
4638 }
4639 } else {
4640 unsafe { ns_map_free(ns_map) };
4641 }
4642 }
4643 *resNode = result_clone;
4644 ret
4645}
4646
4647#[no_mangle]
4659pub unsafe extern "C" fn xmlCreateEntitiesTable() -> *mut c_void {
4660 hash::hash_create(0) as *mut c_void
4661}
4662
4663unsafe extern "C" fn free_entity_wrapper(payload: *mut c_void, _name: *mut xmlChar) {
4664 if !payload.is_null() {
4665 unsafe { entities::free_entity(payload as *mut _xmlEntity) };
4666 }
4667}
4668
4669#[no_mangle]
4681pub unsafe extern "C" fn xmlFreeEntitiesTable(table: *mut c_void) {
4682 unsafe { hash::hash_free(table as *mut hash::HashTable, Some(free_entity_wrapper)) };
4683}
4684
4685#[no_mangle]
4697pub unsafe extern "C" fn xmlNewEntityInputStream(
4698 ctxt: *mut _xmlParserCtxt,
4699 entity: *mut _xmlEntity,
4700) -> *mut _xmlParserInput {
4701 if ctxt.is_null() || entity.is_null() {
4702 return ptr::null_mut();
4703 }
4704 if !(*entity).content.is_null() {
4705 let input = unsafe { xmlMallocZero(size_of::<_xmlParserInput>()) } as *mut _xmlParserInput;
4706 if input.is_null() {
4707 return ptr::null_mut();
4708 }
4709 let len = unsafe { str_len((*entity).content) } as usize;
4710 (*input).line = 1;
4711 (*input).col = 1;
4712 (*input).base = (*entity).content;
4713 (*input).cur = (*entity).content;
4714 (*input).end = (*entity).content.add(len);
4715 (*input).length = len as c_int;
4716 (*input).entity = entity;
4717 (*input).buf = ptr::null_mut();
4718 return input;
4719 }
4720 if !(*entity).URI.is_null() {
4724 return ptr::null_mut();
4725 }
4726 ptr::null_mut()
4727}
4728
4729#[no_mangle]
4745pub unsafe extern "C" fn xmlCreateEnumeration(name: *const xmlChar) -> *mut _xmlEnumeration {
4746 let ret = unsafe { xmlMallocZero(size_of::<_xmlEnumeration>()) } as *mut _xmlEnumeration;
4747 if ret.is_null() {
4748 return ptr::null_mut();
4749 }
4750 if !name.is_null() {
4751 (*ret).name = unsafe { dup_str(name) };
4752 if (*ret).name.is_null() {
4753 unsafe { xmlFreeImpl(ret as *mut c_void) };
4754 return ptr::null_mut();
4755 }
4756 }
4757 ret
4758}
4759
4760#[no_mangle]
4772pub unsafe extern "C" fn xmlFreeEnumeration(cur: *mut _xmlEnumeration) {
4773 let mut c = cur;
4774 while !c.is_null() {
4775 let next = (*c).next;
4776 if !(*c).name.is_null() {
4777 unsafe { xmlFreeImpl((*c).name as *mut c_void) };
4778 }
4779 unsafe { xmlFreeImpl(c as *mut c_void) };
4780 c = next;
4781 }
4782}
4783
4784unsafe fn free_elem_content_internal(cur: *mut _xmlElementContent) {
4786 if cur.is_null() {
4787 return;
4788 }
4789 let mut depth: usize = 0;
4790 let mut cur = cur;
4791 loop {
4792 while !(*cur).c1.is_null() || !(*cur).c2.is_null() {
4793 cur = if !(*cur).c1.is_null() {
4794 (*cur).c1
4795 } else {
4796 (*cur).c2
4797 };
4798 depth += 1;
4799 }
4800 if !(*cur).name.is_null() {
4801 unsafe { xmlFreeImpl((*cur).name as *mut c_void) };
4802 }
4803 if !(*cur).prefix.is_null() {
4804 unsafe { xmlFreeImpl((*cur).prefix as *mut c_void) };
4805 }
4806 let parent = (*cur).parent;
4807 if depth == 0 || parent.is_null() {
4808 unsafe { xmlFreeImpl(cur as *mut c_void) };
4809 break;
4810 }
4811 if cur == (*parent).c1 {
4812 (*parent).c1 = ptr::null_mut();
4813 } else {
4814 (*parent).c2 = ptr::null_mut();
4815 }
4816 unsafe { xmlFreeImpl(cur as *mut c_void) };
4817 if !(*parent).c2.is_null() {
4818 cur = (*parent).c2;
4819 } else {
4820 depth -= 1;
4821 cur = parent;
4822 }
4823 }
4824}
4825
4826#[no_mangle]
4838pub unsafe extern "C" fn xmlFreeDocElementContent(doc: *mut _xmlDoc, cur: *mut _xmlElementContent) {
4839 let _ = doc;
4840 unsafe { free_elem_content_internal(cur) };
4841}
4842
4843unsafe extern "C" fn free_attribute_table_entry(payload: *mut c_void, _name: *mut xmlChar) {
4848 if !payload.is_null() {
4849 unsafe { crate::xml::dtd::free_attribute(payload as *mut _xmlAttribute) };
4850 }
4851}
4852
4853#[no_mangle]
4865pub unsafe extern "C" fn xmlFreeAttributeTable(table: *mut c_void) {
4866 unsafe {
4867 hash::hash_free(
4868 table as *mut hash::HashTable,
4869 Some(free_attribute_table_entry),
4870 )
4871 };
4872}
4873
4874unsafe extern "C" fn free_element_table_entry(payload: *mut c_void, _name: *mut xmlChar) {
4875 if !payload.is_null() {
4876 unsafe { crate::xml::dtd::free_element(payload as *mut _xmlElement) };
4877 }
4878}
4879
4880#[no_mangle]
4892pub unsafe extern "C" fn xmlFreeElementTable(table: *mut c_void) {
4893 unsafe {
4894 hash::hash_free(
4895 table as *mut hash::HashTable,
4896 Some(free_element_table_entry),
4897 )
4898 };
4899}
4900
4901unsafe extern "C" fn free_notation_table_entry(payload: *mut c_void, _name: *mut xmlChar) {
4902 if !payload.is_null() {
4903 unsafe { crate::xml::dtd::free_notation(payload as *mut _xmlNotation) };
4904 }
4905}
4906
4907#[no_mangle]
4919pub unsafe extern "C" fn xmlFreeNotationTable(table: *mut c_void) {
4920 unsafe {
4921 hash::hash_free(
4922 table as *mut hash::HashTable,
4923 Some(free_notation_table_entry),
4924 )
4925 };
4926}
4927
4928unsafe extern "C" fn writer_push_write_cb(
4933 ctx: *mut c_void,
4934 buffer: *const c_char,
4935 len: c_int,
4936) -> c_int {
4937 let ctxt = ctx as *mut _xmlParserCtxt;
4938 if ctxt.is_null() || buffer.is_null() {
4939 return -1;
4940 }
4941 let rc = unsafe { crate::abi::exports_xml2::xmlParseChunk(ctxt, buffer, len, 0) };
4942 if rc != 0 {
4943 return -1;
4944 }
4945 len
4946}
4947
4948unsafe extern "C" fn writer_push_close_cb(ctx: *mut c_void) -> c_int {
4949 let ctxt = ctx as *mut _xmlParserCtxt;
4950 if ctxt.is_null() {
4951 return -1;
4952 }
4953 let rc = unsafe { crate::abi::exports_xml2::xmlParseChunk(ctxt, ptr::null(), 0, 1) };
4954 if rc != 0 {
4955 return -1;
4956 }
4957 0
4958}
4959
4960#[no_mangle]
4975pub unsafe extern "C" fn xmlNewTextWriterPushParser(
4976 ctxt: *mut _xmlParserCtxt,
4977 compression: c_int,
4978) -> *mut crate::xml::writer::XmlTextWriter {
4979 let _ = compression;
4980 if ctxt.is_null() {
4981 return ptr::null_mut();
4982 }
4983 let out = crate::xml::io::output_buffer_create_io(
4984 Some(writer_push_write_cb),
4985 Some(writer_push_close_cb),
4986 ctxt as *mut c_void,
4987 ptr::null_mut(),
4988 );
4989 if out.is_null() {
4990 return ptr::null_mut();
4991 }
4992 let ret = crate::xml::writer::xmlNewTextWriter(out);
4993 if ret.is_null() {
4994 crate::xml::io::output_buffer_close(out);
4995 return ptr::null_mut();
4996 }
4997 ret
4998}
4999
5000#[no_mangle]
5018pub unsafe extern "C" fn xmlNewGlobalNs(
5019 _doc: *mut _xmlDoc,
5020 _href: *const xmlChar,
5021 _prefix: *const xmlChar,
5022) -> *mut _xmlNs {
5023 ptr::null_mut()
5024}