/* This file is part of the Trinity Desktop Environment project * Copyright © 2026, Alexander Golubev (Fat-Zer) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License version 2 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * This file incorporates work extracted from libxml2-2.13.8, which is covered * by the following copyright and permission notice: * * Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to permit * persons to whom the Software is fur- nished to do so, subject to the * following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FIT- NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #if (LIBXML_VERSION >= 21400) /* * This file provides compatibility wigh Shell libxml function which were * removed from newer libxml. */ #ifdef LIBXML_DEBUG_ENABLED #include #include #include #include #include #include #include #include #include #include #include #include #ifdef LIBXML_SCHEMAS_ENABLED #include #endif #include "debugXML_compat.h" #define DUMP_TEXT_TYPE 1 /* * Attributes */ #ifndef ATTRIBUTE_UNUSED #if __GNUC__ * 100 + __GNUC_MINOR__ >= 207 || defined(__clang__) #define ATTRIBUTE_UNUSED __attribute__((unused)) #else #define ATTRIBUTE_UNUSED #endif #endif /** * xmlLsCountNode: * @node: the node to count * * Count the children of @node. * * Returns the number of children of @node. */ int xmlLsCountNode(xmlNodePtr node) { int ret = 0; xmlNodePtr list = NULL; if (node == NULL) return(0); switch (node->type) { case XML_ELEMENT_NODE: list = node->children; break; case XML_DOCUMENT_NODE: case XML_HTML_DOCUMENT_NODE: list = ((xmlDocPtr) node)->children; break; case XML_ATTRIBUTE_NODE: list = ((xmlAttrPtr) node)->children; break; case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: case XML_PI_NODE: case XML_COMMENT_NODE: if (node->content != NULL) { ret = xmlStrlen(node->content); } break; case XML_ENTITY_REF_NODE: case XML_DOCUMENT_TYPE_NODE: case XML_ENTITY_NODE: case XML_DOCUMENT_FRAG_NODE: case XML_NOTATION_NODE: case XML_DTD_NODE: case XML_ELEMENT_DECL: case XML_ATTRIBUTE_DECL: case XML_ENTITY_DECL: case XML_NAMESPACE_DECL: case XML_XINCLUDE_START: case XML_XINCLUDE_END: ret = 1; break; } for (;list != NULL;ret++) list = list->next; return(ret); } /** * xmlLsOneNode: * @output: the FILE * for the output * @node: the node to dump * * Dump to @output the type and name of @node. */ void xmlLsOneNode(FILE *output, xmlNodePtr node) { if (output == NULL) return; if (node == NULL) { fprintf(output, "NULL\n"); return; } switch (node->type) { case XML_ELEMENT_NODE: fprintf(output, "-"); break; case XML_ATTRIBUTE_NODE: fprintf(output, "a"); break; case XML_TEXT_NODE: fprintf(output, "t"); break; case XML_CDATA_SECTION_NODE: fprintf(output, "C"); break; case XML_ENTITY_REF_NODE: fprintf(output, "e"); break; case XML_ENTITY_NODE: fprintf(output, "E"); break; case XML_PI_NODE: fprintf(output, "p"); break; case XML_COMMENT_NODE: fprintf(output, "c"); break; case XML_DOCUMENT_NODE: fprintf(output, "d"); break; case XML_HTML_DOCUMENT_NODE: fprintf(output, "h"); break; case XML_DOCUMENT_TYPE_NODE: fprintf(output, "T"); break; case XML_DOCUMENT_FRAG_NODE: fprintf(output, "F"); break; case XML_NOTATION_NODE: fprintf(output, "N"); break; case XML_NAMESPACE_DECL: fprintf(output, "n"); break; default: fprintf(output, "?"); } if (node->type != XML_NAMESPACE_DECL) { if (node->properties != NULL) fprintf(output, "a"); else fprintf(output, "-"); if (node->nsDef != NULL) fprintf(output, "n"); else fprintf(output, "-"); } fprintf(output, " %8d ", xmlLsCountNode(node)); switch (node->type) { case XML_ELEMENT_NODE: if (node->name != NULL) { if ((node->ns != NULL) && (node->ns->prefix != NULL)) fprintf(output, "%s:", node->ns->prefix); fprintf(output, "%s", (const char *) node->name); } break; case XML_ATTRIBUTE_NODE: if (node->name != NULL) fprintf(output, "%s", (const char *) node->name); break; case XML_TEXT_NODE: if (node->content != NULL) { xmlDebugDumpString(output, node->content); } break; case XML_CDATA_SECTION_NODE: break; case XML_ENTITY_REF_NODE: if (node->name != NULL) fprintf(output, "%s", (const char *) node->name); break; case XML_ENTITY_NODE: if (node->name != NULL) fprintf(output, "%s", (const char *) node->name); break; case XML_PI_NODE: if (node->name != NULL) fprintf(output, "%s", (const char *) node->name); break; case XML_COMMENT_NODE: break; case XML_DOCUMENT_NODE: break; case XML_HTML_DOCUMENT_NODE: break; case XML_DOCUMENT_TYPE_NODE: break; case XML_DOCUMENT_FRAG_NODE: break; case XML_NOTATION_NODE: break; case XML_NAMESPACE_DECL: { xmlNsPtr ns = (xmlNsPtr) node; if (ns->prefix == NULL) fprintf(output, "default -> %s", (char *)ns->href); else fprintf(output, "%s -> %s", (char *)ns->prefix, (char *)ns->href); break; } default: if (node->name != NULL) fprintf(output, "%s", (const char *) node->name); } fprintf(output, "\n"); } /** * xmlBoolToText: * @boolval: a bool to turn into text * * Convenient way to turn bool into text * * Returns a pointer to either "True" or "False" */ const char * xmlBoolToText(int boolval) { if (boolval) return("True"); else return("False"); } #ifdef LIBXML_XPATH_ENABLED /**************************************************************** * * * The XML shell related functions * * * ****************************************************************/ /* * TODO: Improvement/cleanups for the XML shell * - allow to shell out an editor on a subpart * - cleanup function registrations (with help) and calling * - provide registration routines */ /** * xmlShellPrintXPathError: * @errorType: valid xpath error id * @arg: the argument that cause xpath to fail * * Print the xpath error to libxml default error channel */ void xmlShellPrintXPathError(int errorType, const char *arg) { const char *default_arg = "Result"; if (!arg) arg = default_arg; switch (errorType) { case XPATH_UNDEFINED: fprintf(stderr, "%s: no such node\n", arg); break; case XPATH_BOOLEAN: fprintf(stderr, "%s is a Boolean\n", arg); break; case XPATH_NUMBER: fprintf(stderr, "%s is a number\n", arg); break; case XPATH_STRING: fprintf(stderr, "%s is a string\n", arg); break; #ifdef LIBXML_XPTR_LOCS_ENABLED case XPATH_POINT: fprintf(stderr, "%s is a point\n", arg); break; case XPATH_RANGE: fprintf(stderr, "%s is a range\n", arg); break; case XPATH_LOCATIONSET: fprintf(stderr, "%s is a range\n", arg); break; #endif /* LIBXML_XPTR_LOCS_ENABLED */ case XPATH_USERS: fprintf(stderr, "%s is user-defined\n", arg); break; case XPATH_XSLT_TREE: fprintf(stderr, "%s is an XSLT value tree\n", arg); break; } #if 0 fprintf(stderr, "Try casting the result string function (xpath builtin)\n", arg); #endif } /** * xmlShellList: * @ctxt: the shell context * @arg: unused * @node: a node * @node2: unused * * Implements the XML shell function "ls" * Does an Unix like listing of the given node (like a directory) * * Returns 0 */ int xmlShellList(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED) { xmlNodePtr cur; if (!ctxt) return (0); if (node == NULL) { fprintf(ctxt->output, "NULL\n"); return (0); } if ((node->type == XML_DOCUMENT_NODE) || (node->type == XML_HTML_DOCUMENT_NODE)) { cur = ((xmlDocPtr) node)->children; } else if (node->type == XML_NAMESPACE_DECL) { xmlLsOneNode(ctxt->output, node); return (0); } else if (node->children != NULL) { cur = node->children; } else { xmlLsOneNode(ctxt->output, node); return (0); } while (cur != NULL) { xmlLsOneNode(ctxt->output, cur); cur = cur->next; } return (0); } /** * xmlShellBase: * @ctxt: the shell context * @arg: unused * @node: a node * @node2: unused * * Implements the XML shell function "base" * dumps the current XML base of the node * * Returns 0 */ int xmlShellBase(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED) { xmlChar *base; if (!ctxt) return 0; if (node == NULL) { fprintf(ctxt->output, "NULL\n"); return (0); } base = xmlNodeGetBase(node->doc, node); if (base == NULL) { fprintf(ctxt->output, " No base found !!!\n"); } else { fprintf(ctxt->output, "%s\n", base); xmlFree(base); } return (0); } /** * xmlShellDir: * @ctxt: the shell context * @arg: unused * @node: a node * @node2: unused * * Implements the XML shell function "dir" * dumps information about the node (namespace, attributes, content). * * Returns 0 */ int xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED) { if (!ctxt) return (0); if (node == NULL) { fprintf(ctxt->output, "NULL\n"); return (0); } if ((node->type == XML_DOCUMENT_NODE) || (node->type == XML_HTML_DOCUMENT_NODE)) { xmlDebugDumpDocumentHead(ctxt->output, (xmlDocPtr) node); } else if (node->type == XML_ATTRIBUTE_NODE) { xmlDebugDumpAttr(ctxt->output, (xmlAttrPtr) node, 0); } else { xmlDebugDumpOneNode(ctxt->output, node, 0); } return (0); } /** * xmlShellDu: * @ctxt: the shell context * @arg: unused * @tree: a node defining a subtree * @node2: unused * * Implements the XML shell function "du" * show the structure of the subtree under node @tree * If @tree is null, the command works on the current node. * * Returns 0 or -1 in case of error */ int xmlShellDu(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree, xmlNodePtr node2 ATTRIBUTE_UNUSED) { xmlNodePtr node; int indent = 0, i; if (!ctxt) return (-1); if (tree == NULL) return (-1); node = tree; while (node != NULL) { if ((node->type == XML_DOCUMENT_NODE) || (node->type == XML_HTML_DOCUMENT_NODE)) { fprintf(ctxt->output, "/\n"); } else if (node->type == XML_ELEMENT_NODE) { for (i = 0; i < indent; i++) fprintf(ctxt->output, " "); if ((node->ns) && (node->ns->prefix)) fprintf(ctxt->output, "%s:", node->ns->prefix); fprintf(ctxt->output, "%s\n", node->name); } else { } /* * Browse the full subtree, deep first */ if ((node->type == XML_DOCUMENT_NODE) || (node->type == XML_HTML_DOCUMENT_NODE)) { node = ((xmlDocPtr) node)->children; } else if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) { /* deep first */ node = node->children; indent++; } else if ((node != tree) && (node->next != NULL)) { /* then siblings */ node = node->next; } else if (node != tree) { /* go up to parents->next if needed */ while (node != tree) { if (node->parent != NULL) { node = node->parent; indent--; } if ((node != tree) && (node->next != NULL)) { node = node->next; break; } if (node->parent == NULL) { node = NULL; break; } if (node == tree) { node = NULL; break; } } /* exit condition */ if (node == tree) node = NULL; } else node = NULL; } return (0); } /** * xmlShellPwd: * @ctxt: the shell context * @buffer: the output buffer * @node: a node * @node2: unused * * Implements the XML shell function "pwd" * Show the full path from the root to the node, if needed building * thumblers when similar elements exists at a given ancestor level. * The output is compatible with XPath commands. * * Returns 0 or -1 in case of error */ int xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED) { xmlChar *path; if ((node == NULL) || (buffer == NULL)) return (-1); path = xmlGetNodePath(node); if (path == NULL) return (-1); /* * This test prevents buffer overflow, because this routine * is only called by xmlShell, in which the second argument is * 500 chars long. * It is a dirty hack before a cleaner solution is found. * Documentation should mention that the second argument must * be at least 500 chars long, and could be stripped if too long. */ snprintf(buffer, 499, "%s", path); buffer[499] = '0'; xmlFree(path); return (0); } #endif /* LIBXML_XPATH_ENABLED */ #endif /* LIBXML_DEBUG_ENABLED */ #endif /* LIBXML_VERSION >= 21400 */