Coverage Report

Created: 2024-08-17 06:44

/src/libxml2/debugXML.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * debugXML.c : This is a set of routines used for debugging the tree
3
 *              produced by the XML parser.
4
 *
5
 * See Copyright for the status of this software.
6
 *
7
 * Daniel Veillard <daniel@veillard.com>
8
 */
9
10
#define IN_LIBXML
11
#include "libxml.h"
12
#ifdef LIBXML_DEBUG_ENABLED
13
14
#include <string.h>
15
#include <stdlib.h>
16
17
#include <libxml/xmlmemory.h>
18
#include <libxml/tree.h>
19
#include <libxml/parser.h>
20
#include <libxml/parserInternals.h>
21
#include <libxml/valid.h>
22
#include <libxml/debugXML.h>
23
#include <libxml/HTMLtree.h>
24
#include <libxml/HTMLparser.h>
25
#include <libxml/xmlerror.h>
26
#include <libxml/globals.h>
27
#include <libxml/xpathInternals.h>
28
#include <libxml/uri.h>
29
#ifdef LIBXML_SCHEMAS_ENABLED
30
#include <libxml/relaxng.h>
31
#endif
32
33
#include "private/error.h"
34
35
0
#define DUMP_TEXT_TYPE 1
36
37
typedef struct _xmlDebugCtxt xmlDebugCtxt;
38
typedef xmlDebugCtxt *xmlDebugCtxtPtr;
39
struct _xmlDebugCtxt {
40
    FILE *output;               /* the output file */
41
    char shift[101];            /* used for indenting */
42
    int depth;                  /* current depth */
43
    xmlDocPtr doc;              /* current document */
44
    xmlNodePtr node;    /* current node */
45
    xmlDictPtr dict;    /* the doc dictionary */
46
    int check;                  /* do just checkings */
47
    int errors;                 /* number of errors found */
48
    int nodict;     /* if the document has no dictionary */
49
    int options;    /* options */
50
};
51
52
static void xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node);
53
54
static void
55
xmlCtxtDumpInitCtxt(xmlDebugCtxtPtr ctxt)
56
0
{
57
0
    int i;
58
59
0
    ctxt->depth = 0;
60
0
    ctxt->check = 0;
61
0
    ctxt->errors = 0;
62
0
    ctxt->output = stdout;
63
0
    ctxt->doc = NULL;
64
0
    ctxt->node = NULL;
65
0
    ctxt->dict = NULL;
66
0
    ctxt->nodict = 0;
67
0
    ctxt->options = 0;
68
0
    for (i = 0; i < 100; i++)
69
0
        ctxt->shift[i] = ' ';
70
0
    ctxt->shift[100] = 0;
71
0
}
72
73
static void
74
xmlCtxtDumpCleanCtxt(xmlDebugCtxtPtr ctxt ATTRIBUTE_UNUSED)
75
0
{
76
 /* remove the ATTRIBUTE_UNUSED when this is added */
77
0
}
78
79
/**
80
 * xmlNsCheckScope:
81
 * @node: the node
82
 * @ns: the namespace node
83
 *
84
 * Check that a given namespace is in scope on a node.
85
 *
86
 * Returns 1 if in scope, -1 in case of argument error,
87
 *         -2 if the namespace is not in scope, and -3 if not on
88
 *         an ancestor node.
89
 */
90
static int
91
xmlNsCheckScope(xmlNodePtr node, xmlNsPtr ns)
92
0
{
93
0
    xmlNsPtr cur;
94
95
0
    if ((node == NULL) || (ns == NULL))
96
0
        return(-1);
97
98
0
    if ((node->type != XML_ELEMENT_NODE) &&
99
0
  (node->type != XML_ATTRIBUTE_NODE) &&
100
0
  (node->type != XML_DOCUMENT_NODE) &&
101
0
  (node->type != XML_TEXT_NODE) &&
102
0
  (node->type != XML_HTML_DOCUMENT_NODE) &&
103
0
  (node->type != XML_XINCLUDE_START))
104
0
  return(-2);
105
106
0
    while ((node != NULL) &&
107
0
           ((node->type == XML_ELEMENT_NODE) ||
108
0
            (node->type == XML_ATTRIBUTE_NODE) ||
109
0
            (node->type == XML_TEXT_NODE) ||
110
0
      (node->type == XML_XINCLUDE_START))) {
111
0
  if ((node->type == XML_ELEMENT_NODE) ||
112
0
      (node->type == XML_XINCLUDE_START)) {
113
0
      cur = node->nsDef;
114
0
      while (cur != NULL) {
115
0
          if (cur == ns)
116
0
        return(1);
117
0
    if (xmlStrEqual(cur->prefix, ns->prefix))
118
0
        return(-2);
119
0
    cur = cur->next;
120
0
      }
121
0
  }
122
0
  node = node->parent;
123
0
    }
124
    /* the xml namespace may be declared on the document node */
125
0
    if ((node != NULL) &&
126
0
        ((node->type == XML_DOCUMENT_NODE) ||
127
0
   (node->type == XML_HTML_DOCUMENT_NODE))) {
128
0
   xmlNsPtr oldNs = ((xmlDocPtr) node)->oldNs;
129
0
   if (oldNs == ns)
130
0
       return(1);
131
0
    }
132
0
    return(-3);
133
0
}
134
135
static void
136
xmlCtxtDumpSpaces(xmlDebugCtxtPtr ctxt)
137
0
{
138
0
    if (ctxt->check)
139
0
        return;
140
0
    if ((ctxt->output != NULL) && (ctxt->depth > 0)) {
141
0
        if (ctxt->depth < 50)
142
0
            fprintf(ctxt->output, "%s", &ctxt->shift[100 - 2 * ctxt->depth]);
143
0
        else
144
0
            fprintf(ctxt->output, "%s", ctxt->shift);
145
0
    }
146
0
}
147
148
/**
149
 * xmlDebugErr:
150
 * @ctxt:  a debug context
151
 * @error:  the error code
152
 *
153
 * Handle a debug error.
154
 */
155
static void
156
xmlDebugErr(xmlDebugCtxtPtr ctxt, int error, const char *msg)
157
0
{
158
0
    ctxt->errors++;
159
0
    __xmlRaiseError(NULL, NULL, NULL,
160
0
        NULL, ctxt->node, XML_FROM_CHECK,
161
0
        error, XML_ERR_ERROR, NULL, 0,
162
0
        NULL, NULL, NULL, 0, 0,
163
0
        "%s", msg);
164
0
}
165
static void LIBXML_ATTR_FORMAT(3,0)
166
xmlDebugErr2(xmlDebugCtxtPtr ctxt, int error, const char *msg, int extra)
167
0
{
168
0
    ctxt->errors++;
169
0
    __xmlRaiseError(NULL, NULL, NULL,
170
0
        NULL, ctxt->node, XML_FROM_CHECK,
171
0
        error, XML_ERR_ERROR, NULL, 0,
172
0
        NULL, NULL, NULL, 0, 0,
173
0
        msg, extra);
174
0
}
175
static void LIBXML_ATTR_FORMAT(3,0)
176
xmlDebugErr3(xmlDebugCtxtPtr ctxt, int error, const char *msg, const char *extra)
177
0
{
178
0
    ctxt->errors++;
179
0
    __xmlRaiseError(NULL, NULL, NULL,
180
0
        NULL, ctxt->node, XML_FROM_CHECK,
181
0
        error, XML_ERR_ERROR, NULL, 0,
182
0
        NULL, NULL, NULL, 0, 0,
183
0
        msg, extra);
184
0
}
185
186
/**
187
 * xmlCtxtNsCheckScope:
188
 * @ctxt: the debugging context
189
 * @node: the node
190
 * @ns: the namespace node
191
 *
192
 * Report if a given namespace is is not in scope.
193
 */
194
static void
195
xmlCtxtNsCheckScope(xmlDebugCtxtPtr ctxt, xmlNodePtr node, xmlNsPtr ns)
196
0
{
197
0
    int ret;
198
199
0
    ret = xmlNsCheckScope(node, ns);
200
0
    if (ret == -2) {
201
0
        if (ns->prefix == NULL)
202
0
      xmlDebugErr(ctxt, XML_CHECK_NS_SCOPE,
203
0
      "Reference to default namespace not in scope\n");
204
0
  else
205
0
      xmlDebugErr3(ctxt, XML_CHECK_NS_SCOPE,
206
0
       "Reference to namespace '%s' not in scope\n",
207
0
       (char *) ns->prefix);
208
0
    }
209
0
    if (ret == -3) {
210
0
        if (ns->prefix == NULL)
211
0
      xmlDebugErr(ctxt, XML_CHECK_NS_ANCESTOR,
212
0
      "Reference to default namespace not on ancestor\n");
213
0
  else
214
0
      xmlDebugErr3(ctxt, XML_CHECK_NS_ANCESTOR,
215
0
       "Reference to namespace '%s' not on ancestor\n",
216
0
       (char *) ns->prefix);
217
0
    }
218
0
}
219
220
/**
221
 * xmlCtxtCheckString:
222
 * @ctxt: the debug context
223
 * @str: the string
224
 *
225
 * Do debugging on the string, currently it just checks the UTF-8 content
226
 */
227
static void
228
xmlCtxtCheckString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
229
0
{
230
0
    if (str == NULL) return;
231
0
    if (ctxt->check) {
232
0
        if (!xmlCheckUTF8(str)) {
233
0
      xmlDebugErr3(ctxt, XML_CHECK_NOT_UTF8,
234
0
       "String is not UTF-8 %s", (const char *) str);
235
0
  }
236
0
    }
237
0
}
238
239
/**
240
 * xmlCtxtCheckName:
241
 * @ctxt: the debug context
242
 * @name: the name
243
 *
244
 * Do debugging on the name, for example the dictionary status and
245
 * conformance to the Name production.
246
 */
247
static void
248
xmlCtxtCheckName(xmlDebugCtxtPtr ctxt, const xmlChar * name)
249
0
{
250
0
    if (ctxt->check) {
251
0
  if (name == NULL) {
252
0
      xmlDebugErr(ctxt, XML_CHECK_NO_NAME, "Name is NULL");
253
0
      return;
254
0
  }
255
0
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
256
0
        if (xmlValidateName(name, 0)) {
257
0
      xmlDebugErr3(ctxt, XML_CHECK_NOT_NCNAME,
258
0
       "Name is not an NCName '%s'", (const char *) name);
259
0
  }
260
0
#endif
261
0
  if ((ctxt->dict != NULL) &&
262
0
      (!xmlDictOwns(ctxt->dict, name)) &&
263
0
            ((ctxt->doc == NULL) ||
264
0
             ((ctxt->doc->parseFlags & (XML_PARSE_SAX1 | XML_PARSE_NODICT)) == 0))) {
265
0
      xmlDebugErr3(ctxt, XML_CHECK_OUTSIDE_DICT,
266
0
       "Name is not from the document dictionary '%s'",
267
0
       (const char *) name);
268
0
  }
269
0
    }
270
0
}
271
272
static void
273
0
xmlCtxtGenericNodeCheck(xmlDebugCtxtPtr ctxt, xmlNodePtr node) {
274
0
    xmlDocPtr doc;
275
0
    xmlDictPtr dict;
276
277
0
    doc = node->doc;
278
279
0
    if (node->parent == NULL)
280
0
        xmlDebugErr(ctxt, XML_CHECK_NO_PARENT,
281
0
              "Node has no parent\n");
282
0
    if (node->doc == NULL) {
283
0
        xmlDebugErr(ctxt, XML_CHECK_NO_DOC,
284
0
              "Node has no doc\n");
285
0
        dict = NULL;
286
0
    } else {
287
0
  dict = doc->dict;
288
0
  if ((dict == NULL) && (ctxt->nodict == 0)) {
289
#if 0
290
            /* deactivated right now as it raises too many errors */
291
      if (doc->type == XML_DOCUMENT_NODE)
292
    xmlDebugErr(ctxt, XML_CHECK_NO_DICT,
293
          "Document has no dictionary\n");
294
#endif
295
0
      ctxt->nodict = 1;
296
0
  }
297
0
  if (ctxt->doc == NULL)
298
0
      ctxt->doc = doc;
299
300
0
  if (ctxt->dict == NULL) {
301
0
      ctxt->dict = dict;
302
0
  }
303
0
    }
304
0
    if ((node->parent != NULL) && (node->doc != node->parent->doc) &&
305
0
        (!xmlStrEqual(node->name, BAD_CAST "pseudoroot")))
306
0
        xmlDebugErr(ctxt, XML_CHECK_WRONG_DOC,
307
0
              "Node doc differs from parent's one\n");
308
0
    if (node->prev == NULL) {
309
0
        if (node->type == XML_ATTRIBUTE_NODE) {
310
0
      if ((node->parent != NULL) &&
311
0
          (node != (xmlNodePtr) node->parent->properties))
312
0
    xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
313
0
                    "Attr has no prev and not first of attr list\n");
314
315
0
        } else if ((node->parent != NULL) && (node->parent->children != node))
316
0
      xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
317
0
                    "Node has no prev and not first of parent list\n");
318
0
    } else {
319
0
        if (node->prev->next != node)
320
0
      xmlDebugErr(ctxt, XML_CHECK_WRONG_PREV,
321
0
                        "Node prev->next : back link wrong\n");
322
0
    }
323
0
    if (node->next == NULL) {
324
0
  if ((node->parent != NULL) && (node->type != XML_ATTRIBUTE_NODE) &&
325
0
      (node->parent->last != node) &&
326
0
      (node->parent->type == XML_ELEMENT_NODE))
327
0
      xmlDebugErr(ctxt, XML_CHECK_NO_NEXT,
328
0
                    "Node has no next and not last of parent list\n");
329
0
    } else {
330
0
        if (node->next->prev != node)
331
0
      xmlDebugErr(ctxt, XML_CHECK_WRONG_NEXT,
332
0
                    "Node next->prev : forward link wrong\n");
333
0
        if (node->next->parent != node->parent)
334
0
      xmlDebugErr(ctxt, XML_CHECK_WRONG_PARENT,
335
0
                    "Node next->prev : forward link wrong\n");
336
0
    }
337
0
    if (node->type == XML_ELEMENT_NODE) {
338
0
        xmlNsPtr ns;
339
340
0
  ns = node->nsDef;
341
0
  while (ns != NULL) {
342
0
      xmlCtxtNsCheckScope(ctxt, node, ns);
343
0
      ns = ns->next;
344
0
  }
345
0
  if (node->ns != NULL)
346
0
      xmlCtxtNsCheckScope(ctxt, node, node->ns);
347
0
    } else if (node->type == XML_ATTRIBUTE_NODE) {
348
0
  if (node->ns != NULL)
349
0
      xmlCtxtNsCheckScope(ctxt, node, node->ns);
350
0
    }
351
352
0
    if ((node->type != XML_ELEMENT_NODE) &&
353
0
  (node->type != XML_ATTRIBUTE_NODE) &&
354
0
  (node->type != XML_ELEMENT_DECL) &&
355
0
  (node->type != XML_ATTRIBUTE_DECL) &&
356
0
  (node->type != XML_DTD_NODE) &&
357
0
  (node->type != XML_HTML_DOCUMENT_NODE) &&
358
0
  (node->type != XML_DOCUMENT_NODE)) {
359
0
  if (node->content != NULL)
360
0
      xmlCtxtCheckString(ctxt, (const xmlChar *) node->content);
361
0
    }
362
0
    switch (node->type) {
363
0
        case XML_ELEMENT_NODE:
364
0
        case XML_ATTRIBUTE_NODE:
365
0
      xmlCtxtCheckName(ctxt, node->name);
366
0
      break;
367
0
        case XML_TEXT_NODE:
368
0
      if ((node->name == xmlStringText) ||
369
0
          (node->name == xmlStringTextNoenc))
370
0
    break;
371
      /* some case of entity substitution can lead to this */
372
0
      if ((ctxt->dict != NULL) &&
373
0
          (node->name == xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
374
0
                                 7)))
375
0
    break;
376
377
0
      xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME,
378
0
       "Text node has wrong name '%s'",
379
0
       (const char *) node->name);
380
0
      break;
381
0
        case XML_COMMENT_NODE:
382
0
      if (node->name == xmlStringComment)
383
0
    break;
384
0
      xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME,
385
0
       "Comment node has wrong name '%s'",
386
0
       (const char *) node->name);
387
0
      break;
388
0
        case XML_PI_NODE:
389
0
      xmlCtxtCheckName(ctxt, node->name);
390
0
      break;
391
0
        case XML_CDATA_SECTION_NODE:
392
0
      if (node->name == NULL)
393
0
    break;
394
0
      xmlDebugErr3(ctxt, XML_CHECK_NAME_NOT_NULL,
395
0
       "CData section has non NULL name '%s'",
396
0
       (const char *) node->name);
397
0
      break;
398
0
        case XML_ENTITY_REF_NODE:
399
0
        case XML_ENTITY_NODE:
400
0
        case XML_DOCUMENT_TYPE_NODE:
401
0
        case XML_DOCUMENT_FRAG_NODE:
402
0
        case XML_NOTATION_NODE:
403
0
        case XML_DTD_NODE:
404
0
        case XML_ELEMENT_DECL:
405
0
        case XML_ATTRIBUTE_DECL:
406
0
        case XML_ENTITY_DECL:
407
0
        case XML_NAMESPACE_DECL:
408
0
        case XML_XINCLUDE_START:
409
0
        case XML_XINCLUDE_END:
410
0
        case XML_DOCUMENT_NODE:
411
0
        case XML_HTML_DOCUMENT_NODE:
412
0
      break;
413
0
    }
414
0
}
415
416
static void
417
xmlCtxtDumpString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
418
0
{
419
0
    int i;
420
421
0
    if (ctxt->check) {
422
0
        return;
423
0
    }
424
    /* TODO: check UTF8 content of the string */
425
0
    if (str == NULL) {
426
0
        fprintf(ctxt->output, "(NULL)");
427
0
        return;
428
0
    }
429
0
    for (i = 0; i < 40; i++)
430
0
        if (str[i] == 0)
431
0
            return;
432
0
        else if (IS_BLANK_CH(str[i]))
433
0
            fputc(' ', ctxt->output);
434
0
        else if (str[i] >= 0x80)
435
0
            fprintf(ctxt->output, "#%X", str[i]);
436
0
        else
437
0
            fputc(str[i], ctxt->output);
438
0
    fprintf(ctxt->output, "...");
439
0
}
440
441
static void
442
xmlCtxtDumpDtdNode(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
443
0
{
444
0
    xmlCtxtDumpSpaces(ctxt);
445
446
0
    if (dtd == NULL) {
447
0
        if (!ctxt->check)
448
0
            fprintf(ctxt->output, "DTD node is NULL\n");
449
0
        return;
450
0
    }
451
452
0
    if (dtd->type != XML_DTD_NODE) {
453
0
  xmlDebugErr(ctxt, XML_CHECK_NOT_DTD,
454
0
              "Node is not a DTD");
455
0
        return;
456
0
    }
457
0
    if (!ctxt->check) {
458
0
        if (dtd->name != NULL)
459
0
            fprintf(ctxt->output, "DTD(%s)", (char *) dtd->name);
460
0
        else
461
0
            fprintf(ctxt->output, "DTD");
462
0
        if (dtd->ExternalID != NULL)
463
0
            fprintf(ctxt->output, ", PUBLIC %s", (char *) dtd->ExternalID);
464
0
        if (dtd->SystemID != NULL)
465
0
            fprintf(ctxt->output, ", SYSTEM %s", (char *) dtd->SystemID);
466
0
        fprintf(ctxt->output, "\n");
467
0
    }
468
    /*
469
     * Do a bit of checking
470
     */
471
0
    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) dtd);
472
0
}
473
474
static void
475
xmlCtxtDumpAttrDecl(xmlDebugCtxtPtr ctxt, xmlAttributePtr attr)
476
0
{
477
0
    xmlCtxtDumpSpaces(ctxt);
478
479
0
    if (attr == NULL) {
480
0
        if (!ctxt->check)
481
0
            fprintf(ctxt->output, "Attribute declaration is NULL\n");
482
0
        return;
483
0
    }
484
0
    if (attr->type != XML_ATTRIBUTE_DECL) {
485
0
  xmlDebugErr(ctxt, XML_CHECK_NOT_ATTR_DECL,
486
0
              "Node is not an attribute declaration");
487
0
        return;
488
0
    }
489
0
    if (attr->name != NULL) {
490
0
        if (!ctxt->check)
491
0
            fprintf(ctxt->output, "ATTRDECL(%s)", (char *) attr->name);
492
0
    } else
493
0
  xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
494
0
              "Node attribute declaration has no name");
495
0
    if (attr->elem != NULL) {
496
0
        if (!ctxt->check)
497
0
            fprintf(ctxt->output, " for %s", (char *) attr->elem);
498
0
    } else
499
0
  xmlDebugErr(ctxt, XML_CHECK_NO_ELEM,
500
0
              "Node attribute declaration has no element name");
501
0
    if (!ctxt->check) {
502
0
        switch (attr->atype) {
503
0
            case XML_ATTRIBUTE_CDATA:
504
0
                fprintf(ctxt->output, " CDATA");
505
0
                break;
506
0
            case XML_ATTRIBUTE_ID:
507
0
                fprintf(ctxt->output, " ID");
508
0
                break;
509
0
            case XML_ATTRIBUTE_IDREF:
510
0
                fprintf(ctxt->output, " IDREF");
511
0
                break;
512
0
            case XML_ATTRIBUTE_IDREFS:
513
0
                fprintf(ctxt->output, " IDREFS");
514
0
                break;
515
0
            case XML_ATTRIBUTE_ENTITY:
516
0
                fprintf(ctxt->output, " ENTITY");
517
0
                break;
518
0
            case XML_ATTRIBUTE_ENTITIES:
519
0
                fprintf(ctxt->output, " ENTITIES");
520
0
                break;
521
0
            case XML_ATTRIBUTE_NMTOKEN:
522
0
                fprintf(ctxt->output, " NMTOKEN");
523
0
                break;
524
0
            case XML_ATTRIBUTE_NMTOKENS:
525
0
                fprintf(ctxt->output, " NMTOKENS");
526
0
                break;
527
0
            case XML_ATTRIBUTE_ENUMERATION:
528
0
                fprintf(ctxt->output, " ENUMERATION");
529
0
                break;
530
0
            case XML_ATTRIBUTE_NOTATION:
531
0
                fprintf(ctxt->output, " NOTATION ");
532
0
                break;
533
0
        }
534
0
        if (attr->tree != NULL) {
535
0
            int indx;
536
0
            xmlEnumerationPtr cur = attr->tree;
537
538
0
            for (indx = 0; indx < 5; indx++) {
539
0
                if (indx != 0)
540
0
                    fprintf(ctxt->output, "|%s", (char *) cur->name);
541
0
                else
542
0
                    fprintf(ctxt->output, " (%s", (char *) cur->name);
543
0
                cur = cur->next;
544
0
                if (cur == NULL)
545
0
                    break;
546
0
            }
547
0
            if (cur == NULL)
548
0
                fprintf(ctxt->output, ")");
549
0
            else
550
0
                fprintf(ctxt->output, "...)");
551
0
        }
552
0
        switch (attr->def) {
553
0
            case XML_ATTRIBUTE_NONE:
554
0
                break;
555
0
            case XML_ATTRIBUTE_REQUIRED:
556
0
                fprintf(ctxt->output, " REQUIRED");
557
0
                break;
558
0
            case XML_ATTRIBUTE_IMPLIED:
559
0
                fprintf(ctxt->output, " IMPLIED");
560
0
                break;
561
0
            case XML_ATTRIBUTE_FIXED:
562
0
                fprintf(ctxt->output, " FIXED");
563
0
                break;
564
0
        }
565
0
        if (attr->defaultValue != NULL) {
566
0
            fprintf(ctxt->output, "\"");
567
0
            xmlCtxtDumpString(ctxt, attr->defaultValue);
568
0
            fprintf(ctxt->output, "\"");
569
0
        }
570
0
        fprintf(ctxt->output, "\n");
571
0
    }
572
573
    /*
574
     * Do a bit of checking
575
     */
576
0
    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
577
0
}
578
579
static void
580
xmlCtxtDumpElemDecl(xmlDebugCtxtPtr ctxt, xmlElementPtr elem)
581
0
{
582
0
    xmlCtxtDumpSpaces(ctxt);
583
584
0
    if (elem == NULL) {
585
0
        if (!ctxt->check)
586
0
            fprintf(ctxt->output, "Element declaration is NULL\n");
587
0
        return;
588
0
    }
589
0
    if (elem->type != XML_ELEMENT_DECL) {
590
0
  xmlDebugErr(ctxt, XML_CHECK_NOT_ELEM_DECL,
591
0
              "Node is not an element declaration");
592
0
        return;
593
0
    }
594
0
    if (elem->name != NULL) {
595
0
        if (!ctxt->check) {
596
0
            fprintf(ctxt->output, "ELEMDECL(");
597
0
            xmlCtxtDumpString(ctxt, elem->name);
598
0
            fprintf(ctxt->output, ")");
599
0
        }
600
0
    } else
601
0
  xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
602
0
              "Element declaration has no name");
603
0
    if (!ctxt->check) {
604
0
        switch (elem->etype) {
605
0
            case XML_ELEMENT_TYPE_UNDEFINED:
606
0
                fprintf(ctxt->output, ", UNDEFINED");
607
0
                break;
608
0
            case XML_ELEMENT_TYPE_EMPTY:
609
0
                fprintf(ctxt->output, ", EMPTY");
610
0
                break;
611
0
            case XML_ELEMENT_TYPE_ANY:
612
0
                fprintf(ctxt->output, ", ANY");
613
0
                break;
614
0
            case XML_ELEMENT_TYPE_MIXED:
615
0
                fprintf(ctxt->output, ", MIXED ");
616
0
                break;
617
0
            case XML_ELEMENT_TYPE_ELEMENT:
618
0
                fprintf(ctxt->output, ", MIXED ");
619
0
                break;
620
0
        }
621
0
        if ((elem->type != XML_ELEMENT_NODE) && (elem->content != NULL)) {
622
0
            char buf[5001];
623
624
0
            buf[0] = 0;
625
0
            xmlSnprintfElementContent(buf, 5000, elem->content, 1);
626
0
            buf[5000] = 0;
627
0
            fprintf(ctxt->output, "%s", buf);
628
0
        }
629
0
        fprintf(ctxt->output, "\n");
630
0
    }
631
632
    /*
633
     * Do a bit of checking
634
     */
635
0
    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) elem);
636
0
}
637
638
static void
639
xmlCtxtDumpEntityDecl(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent)
640
0
{
641
0
    xmlCtxtDumpSpaces(ctxt);
642
643
0
    if (ent == NULL) {
644
0
        if (!ctxt->check)
645
0
            fprintf(ctxt->output, "Entity declaration is NULL\n");
646
0
        return;
647
0
    }
648
0
    if (ent->type != XML_ENTITY_DECL) {
649
0
  xmlDebugErr(ctxt, XML_CHECK_NOT_ENTITY_DECL,
650
0
              "Node is not an entity declaration");
651
0
        return;
652
0
    }
653
0
    if (ent->name != NULL) {
654
0
        if (!ctxt->check) {
655
0
            fprintf(ctxt->output, "ENTITYDECL(");
656
0
            xmlCtxtDumpString(ctxt, ent->name);
657
0
            fprintf(ctxt->output, ")");
658
0
        }
659
0
    } else
660
0
  xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
661
0
              "Entity declaration has no name");
662
0
    if (!ctxt->check) {
663
0
        switch (ent->etype) {
664
0
            case XML_INTERNAL_GENERAL_ENTITY:
665
0
                fprintf(ctxt->output, ", internal\n");
666
0
                break;
667
0
            case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
668
0
                fprintf(ctxt->output, ", external parsed\n");
669
0
                break;
670
0
            case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
671
0
                fprintf(ctxt->output, ", unparsed\n");
672
0
                break;
673
0
            case XML_INTERNAL_PARAMETER_ENTITY:
674
0
                fprintf(ctxt->output, ", parameter\n");
675
0
                break;
676
0
            case XML_EXTERNAL_PARAMETER_ENTITY:
677
0
                fprintf(ctxt->output, ", external parameter\n");
678
0
                break;
679
0
            case XML_INTERNAL_PREDEFINED_ENTITY:
680
0
                fprintf(ctxt->output, ", predefined\n");
681
0
                break;
682
0
        }
683
0
        if (ent->ExternalID) {
684
0
            xmlCtxtDumpSpaces(ctxt);
685
0
            fprintf(ctxt->output, " ExternalID=%s\n",
686
0
                    (char *) ent->ExternalID);
687
0
        }
688
0
        if (ent->SystemID) {
689
0
            xmlCtxtDumpSpaces(ctxt);
690
0
            fprintf(ctxt->output, " SystemID=%s\n",
691
0
                    (char *) ent->SystemID);
692
0
        }
693
0
        if (ent->URI != NULL) {
694
0
            xmlCtxtDumpSpaces(ctxt);
695
0
            fprintf(ctxt->output, " URI=%s\n", (char *) ent->URI);
696
0
        }
697
0
        if (ent->content) {
698
0
            xmlCtxtDumpSpaces(ctxt);
699
0
            fprintf(ctxt->output, " content=");
700
0
            xmlCtxtDumpString(ctxt, ent->content);
701
0
            fprintf(ctxt->output, "\n");
702
0
        }
703
0
    }
704
705
    /*
706
     * Do a bit of checking
707
     */
708
0
    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) ent);
709
0
}
710
711
static void
712
xmlCtxtDumpNamespace(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
713
0
{
714
0
    xmlCtxtDumpSpaces(ctxt);
715
716
0
    if (ns == NULL) {
717
0
        if (!ctxt->check)
718
0
            fprintf(ctxt->output, "namespace node is NULL\n");
719
0
        return;
720
0
    }
721
0
    if (ns->type != XML_NAMESPACE_DECL) {
722
0
  xmlDebugErr(ctxt, XML_CHECK_NOT_NS_DECL,
723
0
              "Node is not a namespace declaration");
724
0
        return;
725
0
    }
726
0
    if (ns->href == NULL) {
727
0
        if (ns->prefix != NULL)
728
0
      xmlDebugErr3(ctxt, XML_CHECK_NO_HREF,
729
0
                    "Incomplete namespace %s href=NULL\n",
730
0
                    (char *) ns->prefix);
731
0
        else
732
0
      xmlDebugErr(ctxt, XML_CHECK_NO_HREF,
733
0
                    "Incomplete default namespace href=NULL\n");
734
0
    } else {
735
0
        if (!ctxt->check) {
736
0
            if (ns->prefix != NULL)
737
0
                fprintf(ctxt->output, "namespace %s href=",
738
0
                        (char *) ns->prefix);
739
0
            else
740
0
                fprintf(ctxt->output, "default namespace href=");
741
742
0
            xmlCtxtDumpString(ctxt, ns->href);
743
0
            fprintf(ctxt->output, "\n");
744
0
        }
745
0
    }
746
0
}
747
748
static void
749
xmlCtxtDumpNamespaceList(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
750
0
{
751
0
    while (ns != NULL) {
752
0
        xmlCtxtDumpNamespace(ctxt, ns);
753
0
        ns = ns->next;
754
0
    }
755
0
}
756
757
static void
758
xmlCtxtDumpEntity(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent)
759
0
{
760
0
    xmlCtxtDumpSpaces(ctxt);
761
762
0
    if (ent == NULL) {
763
0
        if (!ctxt->check)
764
0
            fprintf(ctxt->output, "Entity is NULL\n");
765
0
        return;
766
0
    }
767
0
    if (!ctxt->check) {
768
0
        switch (ent->etype) {
769
0
            case XML_INTERNAL_GENERAL_ENTITY:
770
0
                fprintf(ctxt->output, "INTERNAL_GENERAL_ENTITY ");
771
0
                break;
772
0
            case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
773
0
                fprintf(ctxt->output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
774
0
                break;
775
0
            case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
776
0
                fprintf(ctxt->output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
777
0
                break;
778
0
            case XML_INTERNAL_PARAMETER_ENTITY:
779
0
                fprintf(ctxt->output, "INTERNAL_PARAMETER_ENTITY ");
780
0
                break;
781
0
            case XML_EXTERNAL_PARAMETER_ENTITY:
782
0
                fprintf(ctxt->output, "EXTERNAL_PARAMETER_ENTITY ");
783
0
                break;
784
0
            default:
785
0
                fprintf(ctxt->output, "ENTITY_%d ! ", (int) ent->etype);
786
0
        }
787
0
        fprintf(ctxt->output, "%s\n", ent->name);
788
0
        if (ent->ExternalID) {
789
0
            xmlCtxtDumpSpaces(ctxt);
790
0
            fprintf(ctxt->output, "ExternalID=%s\n",
791
0
                    (char *) ent->ExternalID);
792
0
        }
793
0
        if (ent->SystemID) {
794
0
            xmlCtxtDumpSpaces(ctxt);
795
0
            fprintf(ctxt->output, "SystemID=%s\n", (char *) ent->SystemID);
796
0
        }
797
0
        if (ent->URI) {
798
0
            xmlCtxtDumpSpaces(ctxt);
799
0
            fprintf(ctxt->output, "URI=%s\n", (char *) ent->URI);
800
0
        }
801
0
        if (ent->content) {
802
0
            xmlCtxtDumpSpaces(ctxt);
803
0
            fprintf(ctxt->output, "content=");
804
0
            xmlCtxtDumpString(ctxt, ent->content);
805
0
            fprintf(ctxt->output, "\n");
806
0
        }
807
0
    }
808
0
}
809
810
/**
811
 * xmlCtxtDumpAttr:
812
 * @output:  the FILE * for the output
813
 * @attr:  the attribute
814
 * @depth:  the indentation level.
815
 *
816
 * Dumps debug information for the attribute
817
 */
818
static void
819
xmlCtxtDumpAttr(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr)
820
0
{
821
0
    xmlCtxtDumpSpaces(ctxt);
822
823
0
    if (attr == NULL) {
824
0
        if (!ctxt->check)
825
0
            fprintf(ctxt->output, "Attr is NULL");
826
0
        return;
827
0
    }
828
0
    if (!ctxt->check) {
829
0
        fprintf(ctxt->output, "ATTRIBUTE ");
830
0
  xmlCtxtDumpString(ctxt, attr->name);
831
0
        fprintf(ctxt->output, "\n");
832
0
        if (attr->children != NULL) {
833
0
            ctxt->depth++;
834
0
            xmlCtxtDumpNodeList(ctxt, attr->children);
835
0
            ctxt->depth--;
836
0
        }
837
0
    }
838
0
    if (attr->name == NULL)
839
0
  xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
840
0
              "Attribute has no name");
841
842
    /*
843
     * Do a bit of checking
844
     */
845
0
    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
846
0
}
847
848
/**
849
 * xmlCtxtDumpAttrList:
850
 * @output:  the FILE * for the output
851
 * @attr:  the attribute list
852
 * @depth:  the indentation level.
853
 *
854
 * Dumps debug information for the attribute list
855
 */
856
static void
857
xmlCtxtDumpAttrList(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr)
858
0
{
859
0
    while (attr != NULL) {
860
0
        xmlCtxtDumpAttr(ctxt, attr);
861
0
        attr = attr->next;
862
0
    }
863
0
}
864
865
/**
866
 * xmlCtxtDumpOneNode:
867
 * @output:  the FILE * for the output
868
 * @node:  the node
869
 * @depth:  the indentation level.
870
 *
871
 * Dumps debug information for the element node, it is not recursive
872
 */
873
static void
874
xmlCtxtDumpOneNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
875
0
{
876
0
    if (node == NULL) {
877
0
        if (!ctxt->check) {
878
0
            xmlCtxtDumpSpaces(ctxt);
879
0
            fprintf(ctxt->output, "node is NULL\n");
880
0
        }
881
0
        return;
882
0
    }
883
0
    ctxt->node = node;
884
885
0
    switch (node->type) {
886
0
        case XML_ELEMENT_NODE:
887
0
            if (!ctxt->check) {
888
0
                xmlCtxtDumpSpaces(ctxt);
889
0
                fprintf(ctxt->output, "ELEMENT ");
890
0
                if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
891
0
                    xmlCtxtDumpString(ctxt, node->ns->prefix);
892
0
                    fprintf(ctxt->output, ":");
893
0
                }
894
0
                xmlCtxtDumpString(ctxt, node->name);
895
0
                fprintf(ctxt->output, "\n");
896
0
            }
897
0
            break;
898
0
        case XML_ATTRIBUTE_NODE:
899
0
            if (!ctxt->check)
900
0
                xmlCtxtDumpSpaces(ctxt);
901
0
            fprintf(ctxt->output, "Error, ATTRIBUTE found here\n");
902
0
            xmlCtxtGenericNodeCheck(ctxt, node);
903
0
            return;
904
0
        case XML_TEXT_NODE:
905
0
            if (!ctxt->check) {
906
0
                xmlCtxtDumpSpaces(ctxt);
907
0
                if (node->name == (const xmlChar *) xmlStringTextNoenc)
908
0
                    fprintf(ctxt->output, "TEXT no enc");
909
0
                else
910
0
                    fprintf(ctxt->output, "TEXT");
911
0
    if (ctxt->options & DUMP_TEXT_TYPE) {
912
0
        if (node->content == (xmlChar *) &(node->properties))
913
0
      fprintf(ctxt->output, " compact\n");
914
0
        else if (xmlDictOwns(ctxt->dict, node->content) == 1)
915
0
      fprintf(ctxt->output, " interned\n");
916
0
        else
917
0
      fprintf(ctxt->output, "\n");
918
0
    } else
919
0
        fprintf(ctxt->output, "\n");
920
0
            }
921
0
            break;
922
0
        case XML_CDATA_SECTION_NODE:
923
0
            if (!ctxt->check) {
924
0
                xmlCtxtDumpSpaces(ctxt);
925
0
                fprintf(ctxt->output, "CDATA_SECTION\n");
926
0
            }
927
0
            break;
928
0
        case XML_ENTITY_REF_NODE:
929
0
            if (!ctxt->check) {
930
0
                xmlCtxtDumpSpaces(ctxt);
931
0
                fprintf(ctxt->output, "ENTITY_REF(%s)\n",
932
0
                        (char *) node->name);
933
0
            }
934
0
            break;
935
0
        case XML_ENTITY_NODE:
936
0
            if (!ctxt->check) {
937
0
                xmlCtxtDumpSpaces(ctxt);
938
0
                fprintf(ctxt->output, "ENTITY\n");
939
0
            }
940
0
            break;
941
0
        case XML_PI_NODE:
942
0
            if (!ctxt->check) {
943
0
                xmlCtxtDumpSpaces(ctxt);
944
0
                fprintf(ctxt->output, "PI %s\n", (char *) node->name);
945
0
            }
946
0
            break;
947
0
        case XML_COMMENT_NODE:
948
0
            if (!ctxt->check) {
949
0
                xmlCtxtDumpSpaces(ctxt);
950
0
                fprintf(ctxt->output, "COMMENT\n");
951
0
            }
952
0
            break;
953
0
        case XML_DOCUMENT_NODE:
954
0
        case XML_HTML_DOCUMENT_NODE:
955
0
            if (!ctxt->check) {
956
0
                xmlCtxtDumpSpaces(ctxt);
957
0
            }
958
0
            fprintf(ctxt->output, "Error, DOCUMENT found here\n");
959
0
            xmlCtxtGenericNodeCheck(ctxt, node);
960
0
            return;
961
0
        case XML_DOCUMENT_TYPE_NODE:
962
0
            if (!ctxt->check) {
963
0
                xmlCtxtDumpSpaces(ctxt);
964
0
                fprintf(ctxt->output, "DOCUMENT_TYPE\n");
965
0
            }
966
0
            break;
967
0
        case XML_DOCUMENT_FRAG_NODE:
968
0
            if (!ctxt->check) {
969
0
                xmlCtxtDumpSpaces(ctxt);
970
0
                fprintf(ctxt->output, "DOCUMENT_FRAG\n");
971
0
            }
972
0
            break;
973
0
        case XML_NOTATION_NODE:
974
0
            if (!ctxt->check) {
975
0
                xmlCtxtDumpSpaces(ctxt);
976
0
                fprintf(ctxt->output, "NOTATION\n");
977
0
            }
978
0
            break;
979
0
        case XML_DTD_NODE:
980
0
            xmlCtxtDumpDtdNode(ctxt, (xmlDtdPtr) node);
981
0
            return;
982
0
        case XML_ELEMENT_DECL:
983
0
            xmlCtxtDumpElemDecl(ctxt, (xmlElementPtr) node);
984
0
            return;
985
0
        case XML_ATTRIBUTE_DECL:
986
0
            xmlCtxtDumpAttrDecl(ctxt, (xmlAttributePtr) node);
987
0
            return;
988
0
        case XML_ENTITY_DECL:
989
0
            xmlCtxtDumpEntityDecl(ctxt, (xmlEntityPtr) node);
990
0
            return;
991
0
        case XML_NAMESPACE_DECL:
992
0
            xmlCtxtDumpNamespace(ctxt, (xmlNsPtr) node);
993
0
            return;
994
0
        case XML_XINCLUDE_START:
995
0
            if (!ctxt->check) {
996
0
                xmlCtxtDumpSpaces(ctxt);
997
0
                fprintf(ctxt->output, "INCLUDE START\n");
998
0
            }
999
0
            return;
1000
0
        case XML_XINCLUDE_END:
1001
0
            if (!ctxt->check) {
1002
0
                xmlCtxtDumpSpaces(ctxt);
1003
0
                fprintf(ctxt->output, "INCLUDE END\n");
1004
0
            }
1005
0
            return;
1006
0
        default:
1007
0
            if (!ctxt->check)
1008
0
                xmlCtxtDumpSpaces(ctxt);
1009
0
      xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
1010
0
                  "Unknown node type %d\n", node->type);
1011
0
            return;
1012
0
    }
1013
0
    if (node->doc == NULL) {
1014
0
        if (!ctxt->check) {
1015
0
            xmlCtxtDumpSpaces(ctxt);
1016
0
        }
1017
0
        fprintf(ctxt->output, "PBM: doc == NULL !!!\n");
1018
0
    }
1019
0
    ctxt->depth++;
1020
0
    if ((node->type == XML_ELEMENT_NODE) && (node->nsDef != NULL))
1021
0
        xmlCtxtDumpNamespaceList(ctxt, node->nsDef);
1022
0
    if ((node->type == XML_ELEMENT_NODE) && (node->properties != NULL))
1023
0
        xmlCtxtDumpAttrList(ctxt, node->properties);
1024
0
    if (node->type != XML_ENTITY_REF_NODE) {
1025
0
        if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
1026
0
            if (!ctxt->check) {
1027
0
                xmlCtxtDumpSpaces(ctxt);
1028
0
                fprintf(ctxt->output, "content=");
1029
0
                xmlCtxtDumpString(ctxt, node->content);
1030
0
                fprintf(ctxt->output, "\n");
1031
0
            }
1032
0
        }
1033
0
    } else {
1034
0
        xmlEntityPtr ent;
1035
1036
0
        ent = xmlGetDocEntity(node->doc, node->name);
1037
0
        if (ent != NULL)
1038
0
            xmlCtxtDumpEntity(ctxt, ent);
1039
0
    }
1040
0
    ctxt->depth--;
1041
1042
    /*
1043
     * Do a bit of checking
1044
     */
1045
0
    xmlCtxtGenericNodeCheck(ctxt, node);
1046
0
}
1047
1048
/**
1049
 * xmlCtxtDumpNode:
1050
 * @output:  the FILE * for the output
1051
 * @node:  the node
1052
 * @depth:  the indentation level.
1053
 *
1054
 * Dumps debug information for the element node, it is recursive
1055
 */
1056
static void
1057
xmlCtxtDumpNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
1058
0
{
1059
0
    if (node == NULL) {
1060
0
        if (!ctxt->check) {
1061
0
            xmlCtxtDumpSpaces(ctxt);
1062
0
            fprintf(ctxt->output, "node is NULL\n");
1063
0
        }
1064
0
        return;
1065
0
    }
1066
0
    xmlCtxtDumpOneNode(ctxt, node);
1067
0
    if ((node->type != XML_NAMESPACE_DECL) &&
1068
0
        (node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
1069
0
        ctxt->depth++;
1070
0
        xmlCtxtDumpNodeList(ctxt, node->children);
1071
0
        ctxt->depth--;
1072
0
    }
1073
0
}
1074
1075
/**
1076
 * xmlCtxtDumpNodeList:
1077
 * @output:  the FILE * for the output
1078
 * @node:  the node list
1079
 * @depth:  the indentation level.
1080
 *
1081
 * Dumps debug information for the list of element node, it is recursive
1082
 */
1083
static void
1084
xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
1085
0
{
1086
0
    while (node != NULL) {
1087
0
        xmlCtxtDumpNode(ctxt, node);
1088
0
        node = node->next;
1089
0
    }
1090
0
}
1091
1092
static void
1093
xmlCtxtDumpDocHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1094
0
{
1095
0
    if (doc == NULL) {
1096
0
        if (!ctxt->check)
1097
0
            fprintf(ctxt->output, "DOCUMENT == NULL !\n");
1098
0
        return;
1099
0
    }
1100
0
    ctxt->node = (xmlNodePtr) doc;
1101
1102
0
    switch (doc->type) {
1103
0
        case XML_ELEMENT_NODE:
1104
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_ELEMENT,
1105
0
                  "Misplaced ELEMENT node\n");
1106
0
            break;
1107
0
        case XML_ATTRIBUTE_NODE:
1108
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_ATTRIBUTE,
1109
0
                  "Misplaced ATTRIBUTE node\n");
1110
0
            break;
1111
0
        case XML_TEXT_NODE:
1112
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_TEXT,
1113
0
                  "Misplaced TEXT node\n");
1114
0
            break;
1115
0
        case XML_CDATA_SECTION_NODE:
1116
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_CDATA,
1117
0
                  "Misplaced CDATA node\n");
1118
0
            break;
1119
0
        case XML_ENTITY_REF_NODE:
1120
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITYREF,
1121
0
                  "Misplaced ENTITYREF node\n");
1122
0
            break;
1123
0
        case XML_ENTITY_NODE:
1124
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITY,
1125
0
                  "Misplaced ENTITY node\n");
1126
0
            break;
1127
0
        case XML_PI_NODE:
1128
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_PI,
1129
0
                  "Misplaced PI node\n");
1130
0
            break;
1131
0
        case XML_COMMENT_NODE:
1132
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_COMMENT,
1133
0
                  "Misplaced COMMENT node\n");
1134
0
            break;
1135
0
        case XML_DOCUMENT_NODE:
1136
0
      if (!ctxt->check)
1137
0
    fprintf(ctxt->output, "DOCUMENT\n");
1138
0
            break;
1139
0
        case XML_HTML_DOCUMENT_NODE:
1140
0
      if (!ctxt->check)
1141
0
    fprintf(ctxt->output, "HTML DOCUMENT\n");
1142
0
            break;
1143
0
        case XML_DOCUMENT_TYPE_NODE:
1144
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_DOCTYPE,
1145
0
                  "Misplaced DOCTYPE node\n");
1146
0
            break;
1147
0
        case XML_DOCUMENT_FRAG_NODE:
1148
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_FRAGMENT,
1149
0
                  "Misplaced FRAGMENT node\n");
1150
0
            break;
1151
0
        case XML_NOTATION_NODE:
1152
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_NOTATION,
1153
0
                  "Misplaced NOTATION node\n");
1154
0
            break;
1155
0
        default:
1156
0
      xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
1157
0
                  "Unknown node type %d\n", doc->type);
1158
0
    }
1159
0
}
1160
1161
/**
1162
 * xmlCtxtDumpDocumentHead:
1163
 * @output:  the FILE * for the output
1164
 * @doc:  the document
1165
 *
1166
 * Dumps debug information concerning the document, not recursive
1167
 */
1168
static void
1169
xmlCtxtDumpDocumentHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1170
0
{
1171
0
    if (doc == NULL) return;
1172
0
    xmlCtxtDumpDocHead(ctxt, doc);
1173
0
    if (!ctxt->check) {
1174
0
        if (doc->name != NULL) {
1175
0
            fprintf(ctxt->output, "name=");
1176
0
            xmlCtxtDumpString(ctxt, BAD_CAST doc->name);
1177
0
            fprintf(ctxt->output, "\n");
1178
0
        }
1179
0
        if (doc->version != NULL) {
1180
0
            fprintf(ctxt->output, "version=");
1181
0
            xmlCtxtDumpString(ctxt, doc->version);
1182
0
            fprintf(ctxt->output, "\n");
1183
0
        }
1184
0
        if (doc->encoding != NULL) {
1185
0
            fprintf(ctxt->output, "encoding=");
1186
0
            xmlCtxtDumpString(ctxt, doc->encoding);
1187
0
            fprintf(ctxt->output, "\n");
1188
0
        }
1189
0
        if (doc->URL != NULL) {
1190
0
            fprintf(ctxt->output, "URL=");
1191
0
            xmlCtxtDumpString(ctxt, doc->URL);
1192
0
            fprintf(ctxt->output, "\n");
1193
0
        }
1194
0
        if (doc->standalone)
1195
0
            fprintf(ctxt->output, "standalone=true\n");
1196
0
    }
1197
0
    if (doc->oldNs != NULL)
1198
0
        xmlCtxtDumpNamespaceList(ctxt, doc->oldNs);
1199
0
}
1200
1201
/**
1202
 * xmlCtxtDumpDocument:
1203
 * @output:  the FILE * for the output
1204
 * @doc:  the document
1205
 *
1206
 * Dumps debug information for the document, it's recursive
1207
 */
1208
static void
1209
xmlCtxtDumpDocument(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1210
0
{
1211
0
    if (doc == NULL) {
1212
0
        if (!ctxt->check)
1213
0
            fprintf(ctxt->output, "DOCUMENT == NULL !\n");
1214
0
        return;
1215
0
    }
1216
0
    xmlCtxtDumpDocumentHead(ctxt, doc);
1217
0
    if (((doc->type == XML_DOCUMENT_NODE) ||
1218
0
         (doc->type == XML_HTML_DOCUMENT_NODE))
1219
0
        && (doc->children != NULL)) {
1220
0
        ctxt->depth++;
1221
0
        xmlCtxtDumpNodeList(ctxt, doc->children);
1222
0
        ctxt->depth--;
1223
0
    }
1224
0
}
1225
1226
static void
1227
xmlCtxtDumpEntityCallback(void *payload, void *data,
1228
                          const xmlChar *name ATTRIBUTE_UNUSED)
1229
0
{
1230
0
    xmlEntityPtr cur = (xmlEntityPtr) payload;
1231
0
    xmlDebugCtxtPtr ctxt = (xmlDebugCtxtPtr) data;
1232
0
    if (cur == NULL) {
1233
0
        if (!ctxt->check)
1234
0
            fprintf(ctxt->output, "Entity is NULL");
1235
0
        return;
1236
0
    }
1237
0
    if (!ctxt->check) {
1238
0
        fprintf(ctxt->output, "%s : ", (char *) cur->name);
1239
0
        switch (cur->etype) {
1240
0
            case XML_INTERNAL_GENERAL_ENTITY:
1241
0
                fprintf(ctxt->output, "INTERNAL GENERAL, ");
1242
0
                break;
1243
0
            case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1244
0
                fprintf(ctxt->output, "EXTERNAL PARSED, ");
1245
0
                break;
1246
0
            case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1247
0
                fprintf(ctxt->output, "EXTERNAL UNPARSED, ");
1248
0
                break;
1249
0
            case XML_INTERNAL_PARAMETER_ENTITY:
1250
0
                fprintf(ctxt->output, "INTERNAL PARAMETER, ");
1251
0
                break;
1252
0
            case XML_EXTERNAL_PARAMETER_ENTITY:
1253
0
                fprintf(ctxt->output, "EXTERNAL PARAMETER, ");
1254
0
                break;
1255
0
            default:
1256
0
    xmlDebugErr2(ctxt, XML_CHECK_ENTITY_TYPE,
1257
0
           "Unknown entity type %d\n", cur->etype);
1258
0
        }
1259
0
        if (cur->ExternalID != NULL)
1260
0
            fprintf(ctxt->output, "ID \"%s\"", (char *) cur->ExternalID);
1261
0
        if (cur->SystemID != NULL)
1262
0
            fprintf(ctxt->output, "SYSTEM \"%s\"", (char *) cur->SystemID);
1263
0
        if (cur->orig != NULL)
1264
0
            fprintf(ctxt->output, "\n orig \"%s\"", (char *) cur->orig);
1265
0
        if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL))
1266
0
            fprintf(ctxt->output, "\n content \"%s\"",
1267
0
                    (char *) cur->content);
1268
0
        fprintf(ctxt->output, "\n");
1269
0
    }
1270
0
}
1271
1272
/**
1273
 * xmlCtxtDumpEntities:
1274
 * @output:  the FILE * for the output
1275
 * @doc:  the document
1276
 *
1277
 * Dumps debug information for all the entities in use by the document
1278
 */
1279
static void
1280
xmlCtxtDumpEntities(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1281
0
{
1282
0
    if (doc == NULL) return;
1283
0
    xmlCtxtDumpDocHead(ctxt, doc);
1284
0
    if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
1285
0
        xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1286
0
            doc->intSubset->entities;
1287
1288
0
        if (!ctxt->check)
1289
0
            fprintf(ctxt->output, "Entities in internal subset\n");
1290
0
        xmlHashScan(table, xmlCtxtDumpEntityCallback, ctxt);
1291
0
    } else
1292
0
        fprintf(ctxt->output, "No entities in internal subset\n");
1293
0
    if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
1294
0
        xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1295
0
            doc->extSubset->entities;
1296
1297
0
        if (!ctxt->check)
1298
0
            fprintf(ctxt->output, "Entities in external subset\n");
1299
0
        xmlHashScan(table, xmlCtxtDumpEntityCallback, ctxt);
1300
0
    } else if (!ctxt->check)
1301
0
        fprintf(ctxt->output, "No entities in external subset\n");
1302
0
}
1303
1304
/**
1305
 * xmlCtxtDumpDTD:
1306
 * @output:  the FILE * for the output
1307
 * @dtd:  the DTD
1308
 *
1309
 * Dumps debug information for the DTD
1310
 */
1311
static void
1312
xmlCtxtDumpDTD(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
1313
0
{
1314
0
    if (dtd == NULL) {
1315
0
        if (!ctxt->check)
1316
0
            fprintf(ctxt->output, "DTD is NULL\n");
1317
0
        return;
1318
0
    }
1319
0
    xmlCtxtDumpDtdNode(ctxt, dtd);
1320
0
    if (dtd->children == NULL)
1321
0
        fprintf(ctxt->output, "    DTD is empty\n");
1322
0
    else {
1323
0
        ctxt->depth++;
1324
0
        xmlCtxtDumpNodeList(ctxt, dtd->children);
1325
0
        ctxt->depth--;
1326
0
    }
1327
0
}
1328
1329
/************************************************************************
1330
 *                  *
1331
 *      Public entry points for dump      *
1332
 *                  *
1333
 ************************************************************************/
1334
1335
/**
1336
 * xmlDebugDumpString:
1337
 * @output:  the FILE * for the output
1338
 * @str:  the string
1339
 *
1340
 * Dumps information about the string, shorten it if necessary
1341
 */
1342
void
1343
xmlDebugDumpString(FILE * output, const xmlChar * str)
1344
0
{
1345
0
    int i;
1346
1347
0
    if (output == NULL)
1348
0
  output = stdout;
1349
0
    if (str == NULL) {
1350
0
        fprintf(output, "(NULL)");
1351
0
        return;
1352
0
    }
1353
0
    for (i = 0; i < 40; i++)
1354
0
        if (str[i] == 0)
1355
0
            return;
1356
0
        else if (IS_BLANK_CH(str[i]))
1357
0
            fputc(' ', output);
1358
0
        else if (str[i] >= 0x80)
1359
0
            fprintf(output, "#%X", str[i]);
1360
0
        else
1361
0
            fputc(str[i], output);
1362
0
    fprintf(output, "...");
1363
0
}
1364
1365
/**
1366
 * xmlDebugDumpAttr:
1367
 * @output:  the FILE * for the output
1368
 * @attr:  the attribute
1369
 * @depth:  the indentation level.
1370
 *
1371
 * Dumps debug information for the attribute
1372
 */
1373
void
1374
0
xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
1375
0
    xmlDebugCtxt ctxt;
1376
1377
0
    if (output == NULL) return;
1378
0
    xmlCtxtDumpInitCtxt(&ctxt);
1379
0
    ctxt.output = output;
1380
0
    ctxt.depth = depth;
1381
0
    xmlCtxtDumpAttr(&ctxt, attr);
1382
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1383
0
}
1384
1385
1386
/**
1387
 * xmlDebugDumpEntities:
1388
 * @output:  the FILE * for the output
1389
 * @doc:  the document
1390
 *
1391
 * Dumps debug information for all the entities in use by the document
1392
 */
1393
void
1394
xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
1395
0
{
1396
0
    xmlDebugCtxt ctxt;
1397
1398
0
    if (output == NULL) return;
1399
0
    xmlCtxtDumpInitCtxt(&ctxt);
1400
0
    ctxt.output = output;
1401
0
    xmlCtxtDumpEntities(&ctxt, doc);
1402
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1403
0
}
1404
1405
/**
1406
 * xmlDebugDumpAttrList:
1407
 * @output:  the FILE * for the output
1408
 * @attr:  the attribute list
1409
 * @depth:  the indentation level.
1410
 *
1411
 * Dumps debug information for the attribute list
1412
 */
1413
void
1414
xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
1415
0
{
1416
0
    xmlDebugCtxt ctxt;
1417
1418
0
    if (output == NULL) return;
1419
0
    xmlCtxtDumpInitCtxt(&ctxt);
1420
0
    ctxt.output = output;
1421
0
    ctxt.depth = depth;
1422
0
    xmlCtxtDumpAttrList(&ctxt, attr);
1423
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1424
0
}
1425
1426
/**
1427
 * xmlDebugDumpOneNode:
1428
 * @output:  the FILE * for the output
1429
 * @node:  the node
1430
 * @depth:  the indentation level.
1431
 *
1432
 * Dumps debug information for the element node, it is not recursive
1433
 */
1434
void
1435
xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
1436
0
{
1437
0
    xmlDebugCtxt ctxt;
1438
1439
0
    if (output == NULL) return;
1440
0
    xmlCtxtDumpInitCtxt(&ctxt);
1441
0
    ctxt.output = output;
1442
0
    ctxt.depth = depth;
1443
0
    xmlCtxtDumpOneNode(&ctxt, node);
1444
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1445
0
}
1446
1447
/**
1448
 * xmlDebugDumpNode:
1449
 * @output:  the FILE * for the output
1450
 * @node:  the node
1451
 * @depth:  the indentation level.
1452
 *
1453
 * Dumps debug information for the element node, it is recursive
1454
 */
1455
void
1456
xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
1457
0
{
1458
0
    xmlDebugCtxt ctxt;
1459
1460
0
    if (output == NULL)
1461
0
  output = stdout;
1462
0
    xmlCtxtDumpInitCtxt(&ctxt);
1463
0
    ctxt.output = output;
1464
0
    ctxt.depth = depth;
1465
0
    xmlCtxtDumpNode(&ctxt, node);
1466
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1467
0
}
1468
1469
/**
1470
 * xmlDebugDumpNodeList:
1471
 * @output:  the FILE * for the output
1472
 * @node:  the node list
1473
 * @depth:  the indentation level.
1474
 *
1475
 * Dumps debug information for the list of element node, it is recursive
1476
 */
1477
void
1478
xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
1479
0
{
1480
0
    xmlDebugCtxt ctxt;
1481
1482
0
    if (output == NULL)
1483
0
  output = stdout;
1484
0
    xmlCtxtDumpInitCtxt(&ctxt);
1485
0
    ctxt.output = output;
1486
0
    ctxt.depth = depth;
1487
0
    xmlCtxtDumpNodeList(&ctxt, node);
1488
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1489
0
}
1490
1491
/**
1492
 * xmlDebugDumpDocumentHead:
1493
 * @output:  the FILE * for the output
1494
 * @doc:  the document
1495
 *
1496
 * Dumps debug information concerning the document, not recursive
1497
 */
1498
void
1499
xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
1500
0
{
1501
0
    xmlDebugCtxt ctxt;
1502
1503
0
    if (output == NULL)
1504
0
  output = stdout;
1505
0
    xmlCtxtDumpInitCtxt(&ctxt);
1506
0
    ctxt.options |= DUMP_TEXT_TYPE;
1507
0
    ctxt.output = output;
1508
0
    xmlCtxtDumpDocumentHead(&ctxt, doc);
1509
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1510
0
}
1511
1512
/**
1513
 * xmlDebugDumpDocument:
1514
 * @output:  the FILE * for the output
1515
 * @doc:  the document
1516
 *
1517
 * Dumps debug information for the document, it's recursive
1518
 */
1519
void
1520
xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
1521
0
{
1522
0
    xmlDebugCtxt ctxt;
1523
1524
0
    if (output == NULL)
1525
0
  output = stdout;
1526
0
    xmlCtxtDumpInitCtxt(&ctxt);
1527
0
    ctxt.options |= DUMP_TEXT_TYPE;
1528
0
    ctxt.output = output;
1529
0
    xmlCtxtDumpDocument(&ctxt, doc);
1530
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1531
0
}
1532
1533
/**
1534
 * xmlDebugDumpDTD:
1535
 * @output:  the FILE * for the output
1536
 * @dtd:  the DTD
1537
 *
1538
 * Dumps debug information for the DTD
1539
 */
1540
void
1541
xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
1542
0
{
1543
0
    xmlDebugCtxt ctxt;
1544
1545
0
    if (output == NULL)
1546
0
  output = stdout;
1547
0
    xmlCtxtDumpInitCtxt(&ctxt);
1548
0
    ctxt.options |= DUMP_TEXT_TYPE;
1549
0
    ctxt.output = output;
1550
0
    xmlCtxtDumpDTD(&ctxt, dtd);
1551
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1552
0
}
1553
1554
/************************************************************************
1555
 *                  *
1556
 *      Public entry points for checkings   *
1557
 *                  *
1558
 ************************************************************************/
1559
1560
/**
1561
 * xmlDebugCheckDocument:
1562
 * @output:  the FILE * for the output
1563
 * @doc:  the document
1564
 *
1565
 * Check the document for potential content problems, and output
1566
 * the errors to @output
1567
 *
1568
 * Returns the number of errors found
1569
 */
1570
int
1571
xmlDebugCheckDocument(FILE * output, xmlDocPtr doc)
1572
0
{
1573
0
    xmlDebugCtxt ctxt;
1574
1575
0
    if (output == NULL)
1576
0
  output = stdout;
1577
0
    xmlCtxtDumpInitCtxt(&ctxt);
1578
0
    ctxt.output = output;
1579
0
    ctxt.check = 1;
1580
0
    xmlCtxtDumpDocument(&ctxt, doc);
1581
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1582
0
    return(ctxt.errors);
1583
0
}
1584
1585
/************************************************************************
1586
 *                  *
1587
 *      Helpers for Shell       *
1588
 *                  *
1589
 ************************************************************************/
1590
1591
/**
1592
 * xmlLsCountNode:
1593
 * @node:  the node to count
1594
 *
1595
 * Count the children of @node.
1596
 *
1597
 * Returns the number of children of @node.
1598
 */
1599
int
1600
0
xmlLsCountNode(xmlNodePtr node) {
1601
0
    int ret = 0;
1602
0
    xmlNodePtr list = NULL;
1603
1604
0
    if (node == NULL)
1605
0
  return(0);
1606
1607
0
    switch (node->type) {
1608
0
  case XML_ELEMENT_NODE:
1609
0
      list = node->children;
1610
0
      break;
1611
0
  case XML_DOCUMENT_NODE:
1612
0
  case XML_HTML_DOCUMENT_NODE:
1613
0
      list = ((xmlDocPtr) node)->children;
1614
0
      break;
1615
0
  case XML_ATTRIBUTE_NODE:
1616
0
      list = ((xmlAttrPtr) node)->children;
1617
0
      break;
1618
0
  case XML_TEXT_NODE:
1619
0
  case XML_CDATA_SECTION_NODE:
1620
0
  case XML_PI_NODE:
1621
0
  case XML_COMMENT_NODE:
1622
0
      if (node->content != NULL) {
1623
0
    ret = xmlStrlen(node->content);
1624
0
            }
1625
0
      break;
1626
0
  case XML_ENTITY_REF_NODE:
1627
0
  case XML_DOCUMENT_TYPE_NODE:
1628
0
  case XML_ENTITY_NODE:
1629
0
  case XML_DOCUMENT_FRAG_NODE:
1630
0
  case XML_NOTATION_NODE:
1631
0
  case XML_DTD_NODE:
1632
0
        case XML_ELEMENT_DECL:
1633
0
        case XML_ATTRIBUTE_DECL:
1634
0
        case XML_ENTITY_DECL:
1635
0
  case XML_NAMESPACE_DECL:
1636
0
  case XML_XINCLUDE_START:
1637
0
  case XML_XINCLUDE_END:
1638
0
      ret = 1;
1639
0
      break;
1640
0
    }
1641
0
    for (;list != NULL;ret++)
1642
0
        list = list->next;
1643
0
    return(ret);
1644
0
}
1645
1646
/**
1647
 * xmlLsOneNode:
1648
 * @output:  the FILE * for the output
1649
 * @node:  the node to dump
1650
 *
1651
 * Dump to @output the type and name of @node.
1652
 */
1653
void
1654
0
xmlLsOneNode(FILE *output, xmlNodePtr node) {
1655
0
    if (output == NULL) return;
1656
0
    if (node == NULL) {
1657
0
  fprintf(output, "NULL\n");
1658
0
  return;
1659
0
    }
1660
0
    switch (node->type) {
1661
0
  case XML_ELEMENT_NODE:
1662
0
      fprintf(output, "-");
1663
0
      break;
1664
0
  case XML_ATTRIBUTE_NODE:
1665
0
      fprintf(output, "a");
1666
0
      break;
1667
0
  case XML_TEXT_NODE:
1668
0
      fprintf(output, "t");
1669
0
      break;
1670
0
  case XML_CDATA_SECTION_NODE:
1671
0
      fprintf(output, "C");
1672
0
      break;
1673
0
  case XML_ENTITY_REF_NODE:
1674
0
      fprintf(output, "e");
1675
0
      break;
1676
0
  case XML_ENTITY_NODE:
1677
0
      fprintf(output, "E");
1678
0
      break;
1679
0
  case XML_PI_NODE:
1680
0
      fprintf(output, "p");
1681
0
      break;
1682
0
  case XML_COMMENT_NODE:
1683
0
      fprintf(output, "c");
1684
0
      break;
1685
0
  case XML_DOCUMENT_NODE:
1686
0
      fprintf(output, "d");
1687
0
      break;
1688
0
  case XML_HTML_DOCUMENT_NODE:
1689
0
      fprintf(output, "h");
1690
0
      break;
1691
0
  case XML_DOCUMENT_TYPE_NODE:
1692
0
      fprintf(output, "T");
1693
0
      break;
1694
0
  case XML_DOCUMENT_FRAG_NODE:
1695
0
      fprintf(output, "F");
1696
0
      break;
1697
0
  case XML_NOTATION_NODE:
1698
0
      fprintf(output, "N");
1699
0
      break;
1700
0
  case XML_NAMESPACE_DECL:
1701
0
      fprintf(output, "n");
1702
0
      break;
1703
0
  default:
1704
0
      fprintf(output, "?");
1705
0
    }
1706
0
    if (node->type != XML_NAMESPACE_DECL) {
1707
0
  if (node->properties != NULL)
1708
0
      fprintf(output, "a");
1709
0
  else
1710
0
      fprintf(output, "-");
1711
0
  if (node->nsDef != NULL)
1712
0
      fprintf(output, "n");
1713
0
  else
1714
0
      fprintf(output, "-");
1715
0
    }
1716
1717
0
    fprintf(output, " %8d ", xmlLsCountNode(node));
1718
1719
0
    switch (node->type) {
1720
0
  case XML_ELEMENT_NODE:
1721
0
      if (node->name != NULL) {
1722
0
                if ((node->ns != NULL) && (node->ns->prefix != NULL))
1723
0
                    fprintf(output, "%s:", node->ns->prefix);
1724
0
    fprintf(output, "%s", (const char *) node->name);
1725
0
            }
1726
0
      break;
1727
0
  case XML_ATTRIBUTE_NODE:
1728
0
      if (node->name != NULL)
1729
0
    fprintf(output, "%s", (const char *) node->name);
1730
0
      break;
1731
0
  case XML_TEXT_NODE:
1732
0
      if (node->content != NULL) {
1733
0
    xmlDebugDumpString(output, node->content);
1734
0
            }
1735
0
      break;
1736
0
  case XML_CDATA_SECTION_NODE:
1737
0
      break;
1738
0
  case XML_ENTITY_REF_NODE:
1739
0
      if (node->name != NULL)
1740
0
    fprintf(output, "%s", (const char *) node->name);
1741
0
      break;
1742
0
  case XML_ENTITY_NODE:
1743
0
      if (node->name != NULL)
1744
0
    fprintf(output, "%s", (const char *) node->name);
1745
0
      break;
1746
0
  case XML_PI_NODE:
1747
0
      if (node->name != NULL)
1748
0
    fprintf(output, "%s", (const char *) node->name);
1749
0
      break;
1750
0
  case XML_COMMENT_NODE:
1751
0
      break;
1752
0
  case XML_DOCUMENT_NODE:
1753
0
      break;
1754
0
  case XML_HTML_DOCUMENT_NODE:
1755
0
      break;
1756
0
  case XML_DOCUMENT_TYPE_NODE:
1757
0
      break;
1758
0
  case XML_DOCUMENT_FRAG_NODE:
1759
0
      break;
1760
0
  case XML_NOTATION_NODE:
1761
0
      break;
1762
0
  case XML_NAMESPACE_DECL: {
1763
0
      xmlNsPtr ns = (xmlNsPtr) node;
1764
1765
0
      if (ns->prefix == NULL)
1766
0
    fprintf(output, "default -> %s", (char *)ns->href);
1767
0
      else
1768
0
    fprintf(output, "%s -> %s", (char *)ns->prefix,
1769
0
      (char *)ns->href);
1770
0
      break;
1771
0
  }
1772
0
  default:
1773
0
      if (node->name != NULL)
1774
0
    fprintf(output, "%s", (const char *) node->name);
1775
0
    }
1776
0
    fprintf(output, "\n");
1777
0
}
1778
1779
/**
1780
 * xmlBoolToText:
1781
 * @boolval: a bool to turn into text
1782
 *
1783
 * Convenient way to turn bool into text
1784
 *
1785
 * Returns a pointer to either "True" or "False"
1786
 */
1787
const char *
1788
xmlBoolToText(int boolval)
1789
0
{
1790
0
    if (boolval)
1791
0
        return("True");
1792
0
    else
1793
0
        return("False");
1794
0
}
1795
1796
#ifdef LIBXML_XPATH_ENABLED
1797
/****************************************************************
1798
 *                *
1799
 *    The XML shell related functions     *
1800
 *                *
1801
 ****************************************************************/
1802
1803
1804
1805
/*
1806
 * TODO: Improvement/cleanups for the XML shell
1807
 *     - allow to shell out an editor on a subpart
1808
 *     - cleanup function registrations (with help) and calling
1809
 *     - provide registration routines
1810
 */
1811
1812
/**
1813
 * xmlShellPrintXPathError:
1814
 * @errorType: valid xpath error id
1815
 * @arg: the argument that cause xpath to fail
1816
 *
1817
 * Print the xpath error to libxml default error channel
1818
 */
1819
void
1820
xmlShellPrintXPathError(int errorType, const char *arg)
1821
0
{
1822
0
    const char *default_arg = "Result";
1823
1824
0
    if (!arg)
1825
0
        arg = default_arg;
1826
1827
0
    switch (errorType) {
1828
0
        case XPATH_UNDEFINED:
1829
0
            xmlGenericError(xmlGenericErrorContext,
1830
0
                            "%s: no such node\n", arg);
1831
0
            break;
1832
1833
0
        case XPATH_BOOLEAN:
1834
0
            xmlGenericError(xmlGenericErrorContext,
1835
0
                            "%s is a Boolean\n", arg);
1836
0
            break;
1837
0
        case XPATH_NUMBER:
1838
0
            xmlGenericError(xmlGenericErrorContext,
1839
0
                            "%s is a number\n", arg);
1840
0
            break;
1841
0
        case XPATH_STRING:
1842
0
            xmlGenericError(xmlGenericErrorContext,
1843
0
                            "%s is a string\n", arg);
1844
0
            break;
1845
#ifdef LIBXML_XPTR_LOCS_ENABLED
1846
        case XPATH_POINT:
1847
            xmlGenericError(xmlGenericErrorContext,
1848
                            "%s is a point\n", arg);
1849
            break;
1850
        case XPATH_RANGE:
1851
            xmlGenericError(xmlGenericErrorContext,
1852
                            "%s is a range\n", arg);
1853
            break;
1854
        case XPATH_LOCATIONSET:
1855
            xmlGenericError(xmlGenericErrorContext,
1856
                            "%s is a range\n", arg);
1857
            break;
1858
#endif /* LIBXML_XPTR_LOCS_ENABLED */
1859
0
        case XPATH_USERS:
1860
0
            xmlGenericError(xmlGenericErrorContext,
1861
0
                            "%s is user-defined\n", arg);
1862
0
            break;
1863
0
        case XPATH_XSLT_TREE:
1864
0
            xmlGenericError(xmlGenericErrorContext,
1865
0
                            "%s is an XSLT value tree\n", arg);
1866
0
            break;
1867
0
    }
1868
#if 0
1869
    xmlGenericError(xmlGenericErrorContext,
1870
                    "Try casting the result string function (xpath builtin)\n",
1871
                    arg);
1872
#endif
1873
0
}
1874
1875
1876
#ifdef LIBXML_OUTPUT_ENABLED
1877
/**
1878
 * xmlShellPrintNodeCtxt:
1879
 * @ctxt : a non-null shell context
1880
 * @node : a non-null node to print to the output FILE
1881
 *
1882
 * Print node to the output FILE
1883
 */
1884
static void
1885
xmlShellPrintNodeCtxt(xmlShellCtxtPtr ctxt,xmlNodePtr node)
1886
0
{
1887
0
    FILE *fp;
1888
1889
0
    if (!node)
1890
0
        return;
1891
0
    if (ctxt == NULL)
1892
0
  fp = stdout;
1893
0
    else
1894
0
  fp = ctxt->output;
1895
1896
0
    if (node->type == XML_DOCUMENT_NODE)
1897
0
        xmlDocDump(fp, (xmlDocPtr) node);
1898
0
    else if (node->type == XML_ATTRIBUTE_NODE)
1899
0
        xmlDebugDumpAttrList(fp, (xmlAttrPtr) node, 0);
1900
0
    else
1901
0
        xmlElemDump(fp, node->doc, node);
1902
1903
0
    fprintf(fp, "\n");
1904
0
}
1905
1906
/**
1907
 * xmlShellPrintNode:
1908
 * @node : a non-null node to print to the output FILE
1909
 *
1910
 * Print node to the output FILE
1911
 */
1912
void
1913
xmlShellPrintNode(xmlNodePtr node)
1914
0
{
1915
0
    xmlShellPrintNodeCtxt(NULL, node);
1916
0
}
1917
#endif /* LIBXML_OUTPUT_ENABLED */
1918
1919
/**
1920
 * xmlShellPrintXPathResultCtxt:
1921
 * @ctxt: a valid shell context
1922
 * @list: a valid result generated by an xpath evaluation
1923
 *
1924
 * Prints result to the output FILE
1925
 */
1926
static void
1927
xmlShellPrintXPathResultCtxt(xmlShellCtxtPtr ctxt,xmlXPathObjectPtr list)
1928
0
{
1929
0
    if (!ctxt)
1930
0
       return;
1931
1932
0
    if (list != NULL) {
1933
0
        switch (list->type) {
1934
0
            case XPATH_NODESET:{
1935
0
#ifdef LIBXML_OUTPUT_ENABLED
1936
0
                    int indx;
1937
1938
0
                    if (list->nodesetval) {
1939
0
                        for (indx = 0; indx < list->nodesetval->nodeNr;
1940
0
                             indx++) {
1941
0
                            xmlShellPrintNodeCtxt(ctxt,
1942
0
            list->nodesetval->nodeTab[indx]);
1943
0
                        }
1944
0
                    } else {
1945
0
                        xmlGenericError(xmlGenericErrorContext,
1946
0
                                        "Empty node set\n");
1947
0
                    }
1948
0
                    break;
1949
#else
1950
        xmlGenericError(xmlGenericErrorContext,
1951
            "Node set\n");
1952
#endif /* LIBXML_OUTPUT_ENABLED */
1953
0
                }
1954
0
            case XPATH_BOOLEAN:
1955
0
                xmlGenericError(xmlGenericErrorContext,
1956
0
                                "Is a Boolean:%s\n",
1957
0
                                xmlBoolToText(list->boolval));
1958
0
                break;
1959
0
            case XPATH_NUMBER:
1960
0
                xmlGenericError(xmlGenericErrorContext,
1961
0
                                "Is a number:%0g\n", list->floatval);
1962
0
                break;
1963
0
            case XPATH_STRING:
1964
0
                xmlGenericError(xmlGenericErrorContext,
1965
0
                                "Is a string:%s\n", list->stringval);
1966
0
                break;
1967
1968
0
            default:
1969
0
                xmlShellPrintXPathError(list->type, NULL);
1970
0
        }
1971
0
    }
1972
0
}
1973
1974
/**
1975
 * xmlShellPrintXPathResult:
1976
 * @list: a valid result generated by an xpath evaluation
1977
 *
1978
 * Prints result to the output FILE
1979
 */
1980
void
1981
xmlShellPrintXPathResult(xmlXPathObjectPtr list)
1982
0
{
1983
0
    xmlShellPrintXPathResultCtxt(NULL, list);
1984
0
}
1985
1986
/**
1987
 * xmlShellList:
1988
 * @ctxt:  the shell context
1989
 * @arg:  unused
1990
 * @node:  a node
1991
 * @node2:  unused
1992
 *
1993
 * Implements the XML shell function "ls"
1994
 * Does an Unix like listing of the given node (like a directory)
1995
 *
1996
 * Returns 0
1997
 */
1998
int
1999
xmlShellList(xmlShellCtxtPtr ctxt,
2000
             char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
2001
             xmlNodePtr node2 ATTRIBUTE_UNUSED)
2002
0
{
2003
0
    xmlNodePtr cur;
2004
0
    if (!ctxt)
2005
0
        return (0);
2006
0
    if (node == NULL) {
2007
0
  fprintf(ctxt->output, "NULL\n");
2008
0
  return (0);
2009
0
    }
2010
0
    if ((node->type == XML_DOCUMENT_NODE) ||
2011
0
        (node->type == XML_HTML_DOCUMENT_NODE)) {
2012
0
        cur = ((xmlDocPtr) node)->children;
2013
0
    } else if (node->type == XML_NAMESPACE_DECL) {
2014
0
        xmlLsOneNode(ctxt->output, node);
2015
0
        return (0);
2016
0
    } else if (node->children != NULL) {
2017
0
        cur = node->children;
2018
0
    } else {
2019
0
        xmlLsOneNode(ctxt->output, node);
2020
0
        return (0);
2021
0
    }
2022
0
    while (cur != NULL) {
2023
0
        xmlLsOneNode(ctxt->output, cur);
2024
0
        cur = cur->next;
2025
0
    }
2026
0
    return (0);
2027
0
}
2028
2029
/**
2030
 * xmlShellBase:
2031
 * @ctxt:  the shell context
2032
 * @arg:  unused
2033
 * @node:  a node
2034
 * @node2:  unused
2035
 *
2036
 * Implements the XML shell function "base"
2037
 * dumps the current XML base of the node
2038
 *
2039
 * Returns 0
2040
 */
2041
int
2042
xmlShellBase(xmlShellCtxtPtr ctxt,
2043
             char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
2044
             xmlNodePtr node2 ATTRIBUTE_UNUSED)
2045
0
{
2046
0
    xmlChar *base;
2047
0
    if (!ctxt)
2048
0
        return 0;
2049
0
    if (node == NULL) {
2050
0
  fprintf(ctxt->output, "NULL\n");
2051
0
  return (0);
2052
0
    }
2053
2054
0
    base = xmlNodeGetBase(node->doc, node);
2055
2056
0
    if (base == NULL) {
2057
0
        fprintf(ctxt->output, " No base found !!!\n");
2058
0
    } else {
2059
0
        fprintf(ctxt->output, "%s\n", base);
2060
0
        xmlFree(base);
2061
0
    }
2062
0
    return (0);
2063
0
}
2064
2065
#ifdef LIBXML_TREE_ENABLED
2066
/**
2067
 * xmlShellSetBase:
2068
 * @ctxt:  the shell context
2069
 * @arg:  the new base
2070
 * @node:  a node
2071
 * @node2:  unused
2072
 *
2073
 * Implements the XML shell function "setbase"
2074
 * change the current XML base of the node
2075
 *
2076
 * Returns 0
2077
 */
2078
static int
2079
xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2080
             char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
2081
             xmlNodePtr node2 ATTRIBUTE_UNUSED)
2082
0
{
2083
0
    xmlNodeSetBase(node, (xmlChar*) arg);
2084
0
    return (0);
2085
0
}
2086
#endif
2087
2088
#ifdef LIBXML_XPATH_ENABLED
2089
/**
2090
 * xmlShellRegisterNamespace:
2091
 * @ctxt:  the shell context
2092
 * @arg:  a string in prefix=nsuri format
2093
 * @node:  unused
2094
 * @node2:  unused
2095
 *
2096
 * Implements the XML shell function "setns"
2097
 * register/unregister a prefix=namespace pair
2098
 * on the XPath context
2099
 *
2100
 * Returns 0 on success and a negative value otherwise.
2101
 */
2102
static int
2103
xmlShellRegisterNamespace(xmlShellCtxtPtr ctxt, char *arg,
2104
      xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2105
0
{
2106
0
    xmlChar* nsListDup;
2107
0
    xmlChar* prefix;
2108
0
    xmlChar* href;
2109
0
    xmlChar* next;
2110
2111
0
    nsListDup = xmlStrdup((xmlChar *) arg);
2112
0
    next = nsListDup;
2113
0
    while(next != NULL) {
2114
  /* skip spaces */
2115
  /*while((*next) == ' ') next++;*/
2116
0
  if((*next) == '\0') break;
2117
2118
  /* find prefix */
2119
0
  prefix = next;
2120
0
  next = (xmlChar*)xmlStrchr(next, '=');
2121
0
  if(next == NULL) {
2122
0
      fprintf(ctxt->output, "setns: prefix=[nsuri] required\n");
2123
0
      xmlFree(nsListDup);
2124
0
      return(-1);
2125
0
  }
2126
0
  *(next++) = '\0';
2127
2128
  /* find href */
2129
0
  href = next;
2130
0
  next = (xmlChar*)xmlStrchr(next, ' ');
2131
0
  if(next != NULL) {
2132
0
      *(next++) = '\0';
2133
0
  }
2134
2135
  /* do register namespace */
2136
0
  if(xmlXPathRegisterNs(ctxt->pctxt, prefix, href) != 0) {
2137
0
      fprintf(ctxt->output,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", prefix, href);
2138
0
      xmlFree(nsListDup);
2139
0
      return(-1);
2140
0
  }
2141
0
    }
2142
2143
0
    xmlFree(nsListDup);
2144
0
    return(0);
2145
0
}
2146
/**
2147
 * xmlShellRegisterRootNamespaces:
2148
 * @ctxt:  the shell context
2149
 * @arg:  unused
2150
 * @node:  the root element
2151
 * @node2:  unused
2152
 *
2153
 * Implements the XML shell function "setrootns"
2154
 * which registers all namespaces declarations found on the root element.
2155
 *
2156
 * Returns 0 on success and a negative value otherwise.
2157
 */
2158
static int
2159
xmlShellRegisterRootNamespaces(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
2160
      xmlNodePtr root, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2161
0
{
2162
0
    xmlNsPtr ns;
2163
2164
0
    if ((root == NULL) || (root->type != XML_ELEMENT_NODE) ||
2165
0
        (root->nsDef == NULL) || (ctxt == NULL) || (ctxt->pctxt == NULL))
2166
0
  return(-1);
2167
0
    ns = root->nsDef;
2168
0
    while (ns != NULL) {
2169
0
        if (ns->prefix == NULL)
2170
0
      xmlXPathRegisterNs(ctxt->pctxt, BAD_CAST "defaultns", ns->href);
2171
0
  else
2172
0
      xmlXPathRegisterNs(ctxt->pctxt, ns->prefix, ns->href);
2173
0
        ns = ns->next;
2174
0
    }
2175
0
    return(0);
2176
0
}
2177
#endif
2178
2179
/**
2180
 * xmlShellGrep:
2181
 * @ctxt:  the shell context
2182
 * @arg:  the string or regular expression to find
2183
 * @node:  a node
2184
 * @node2:  unused
2185
 *
2186
 * Implements the XML shell function "grep"
2187
 * dumps information about the node (namespace, attributes, content).
2188
 *
2189
 * Returns 0
2190
 */
2191
static int
2192
xmlShellGrep(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2193
            char *arg, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2194
0
{
2195
0
    if (!ctxt)
2196
0
        return (0);
2197
0
    if (node == NULL)
2198
0
  return (0);
2199
0
    if (arg == NULL)
2200
0
  return (0);
2201
#ifdef LIBXML_REGEXP_ENABLED
2202
    if ((xmlStrchr((xmlChar *) arg, '?')) ||
2203
  (xmlStrchr((xmlChar *) arg, '*')) ||
2204
  (xmlStrchr((xmlChar *) arg, '.')) ||
2205
  (xmlStrchr((xmlChar *) arg, '['))) {
2206
    }
2207
#endif
2208
0
    while (node != NULL) {
2209
0
        if (node->type == XML_COMMENT_NODE) {
2210
0
      if (xmlStrstr(node->content, (xmlChar *) arg)) {
2211
2212
0
    fprintf(ctxt->output, "%s : ", xmlGetNodePath(node));
2213
0
                xmlShellList(ctxt, NULL, node, NULL);
2214
0
      }
2215
0
        } else if (node->type == XML_TEXT_NODE) {
2216
0
      if (xmlStrstr(node->content, (xmlChar *) arg)) {
2217
2218
0
    fprintf(ctxt->output, "%s : ", xmlGetNodePath(node->parent));
2219
0
                xmlShellList(ctxt, NULL, node->parent, NULL);
2220
0
      }
2221
0
        }
2222
2223
        /*
2224
         * Browse the full subtree, deep first
2225
         */
2226
2227
0
        if ((node->type == XML_DOCUMENT_NODE) ||
2228
0
            (node->type == XML_HTML_DOCUMENT_NODE)) {
2229
0
            node = ((xmlDocPtr) node)->children;
2230
0
        } else if ((node->children != NULL)
2231
0
                   && (node->type != XML_ENTITY_REF_NODE)) {
2232
            /* deep first */
2233
0
            node = node->children;
2234
0
        } else if (node->next != NULL) {
2235
            /* then siblings */
2236
0
            node = node->next;
2237
0
        } else {
2238
            /* go up to parents->next if needed */
2239
0
            while (node != NULL) {
2240
0
                if (node->parent != NULL) {
2241
0
                    node = node->parent;
2242
0
                }
2243
0
                if (node->next != NULL) {
2244
0
                    node = node->next;
2245
0
                    break;
2246
0
                }
2247
0
                if (node->parent == NULL) {
2248
0
                    node = NULL;
2249
0
                    break;
2250
0
                }
2251
0
            }
2252
0
  }
2253
0
    }
2254
0
    return (0);
2255
0
}
2256
2257
/**
2258
 * xmlShellDir:
2259
 * @ctxt:  the shell context
2260
 * @arg:  unused
2261
 * @node:  a node
2262
 * @node2:  unused
2263
 *
2264
 * Implements the XML shell function "dir"
2265
 * dumps information about the node (namespace, attributes, content).
2266
 *
2267
 * Returns 0
2268
 */
2269
int
2270
xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2271
            char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
2272
            xmlNodePtr node2 ATTRIBUTE_UNUSED)
2273
0
{
2274
0
    if (!ctxt)
2275
0
        return (0);
2276
0
    if (node == NULL) {
2277
0
  fprintf(ctxt->output, "NULL\n");
2278
0
  return (0);
2279
0
    }
2280
0
    if ((node->type == XML_DOCUMENT_NODE) ||
2281
0
        (node->type == XML_HTML_DOCUMENT_NODE)) {
2282
0
        xmlDebugDumpDocumentHead(ctxt->output, (xmlDocPtr) node);
2283
0
    } else if (node->type == XML_ATTRIBUTE_NODE) {
2284
0
        xmlDebugDumpAttr(ctxt->output, (xmlAttrPtr) node, 0);
2285
0
    } else {
2286
0
        xmlDebugDumpOneNode(ctxt->output, node, 0);
2287
0
    }
2288
0
    return (0);
2289
0
}
2290
2291
/**
2292
 * xmlShellSetContent:
2293
 * @ctxt:  the shell context
2294
 * @value:  the content as a string
2295
 * @node:  a node
2296
 * @node2:  unused
2297
 *
2298
 * Implements the XML shell function "dir"
2299
 * dumps information about the node (namespace, attributes, content).
2300
 *
2301
 * Returns 0
2302
 */
2303
static int
2304
xmlShellSetContent(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2305
            char *value, xmlNodePtr node,
2306
            xmlNodePtr node2 ATTRIBUTE_UNUSED)
2307
0
{
2308
0
    xmlNodePtr results;
2309
0
    xmlParserErrors ret;
2310
2311
0
    if (!ctxt)
2312
0
        return (0);
2313
0
    if (node == NULL) {
2314
0
  fprintf(ctxt->output, "NULL\n");
2315
0
  return (0);
2316
0
    }
2317
0
    if (value == NULL) {
2318
0
        fprintf(ctxt->output, "NULL\n");
2319
0
  return (0);
2320
0
    }
2321
2322
0
    ret = xmlParseInNodeContext(node, value, strlen(value), 0, &results);
2323
0
    if (ret == XML_ERR_OK) {
2324
0
  if (node->children != NULL) {
2325
0
      xmlFreeNodeList(node->children);
2326
0
      node->children = NULL;
2327
0
      node->last = NULL;
2328
0
  }
2329
0
  xmlAddChildList(node, results);
2330
0
    } else {
2331
0
        fprintf(ctxt->output, "failed to parse content\n");
2332
0
    }
2333
0
    return (0);
2334
0
}
2335
2336
#ifdef LIBXML_SCHEMAS_ENABLED
2337
/**
2338
 * xmlShellRNGValidate:
2339
 * @ctxt:  the shell context
2340
 * @schemas:  the path to the Relax-NG schemas
2341
 * @node:  a node
2342
 * @node2:  unused
2343
 *
2344
 * Implements the XML shell function "relaxng"
2345
 * validating the instance against a Relax-NG schemas
2346
 *
2347
 * Returns 0
2348
 */
2349
static int
2350
xmlShellRNGValidate(xmlShellCtxtPtr sctxt, char *schemas,
2351
            xmlNodePtr node ATTRIBUTE_UNUSED,
2352
      xmlNodePtr node2 ATTRIBUTE_UNUSED)
2353
{
2354
    xmlRelaxNGPtr relaxngschemas;
2355
    xmlRelaxNGParserCtxtPtr ctxt;
2356
    xmlRelaxNGValidCtxtPtr vctxt;
2357
    int ret;
2358
2359
    ctxt = xmlRelaxNGNewParserCtxt(schemas);
2360
    xmlRelaxNGSetParserErrors(ctxt, xmlGenericError, xmlGenericError, NULL);
2361
    relaxngschemas = xmlRelaxNGParse(ctxt);
2362
    xmlRelaxNGFreeParserCtxt(ctxt);
2363
    if (relaxngschemas == NULL) {
2364
  xmlGenericError(xmlGenericErrorContext,
2365
    "Relax-NG schema %s failed to compile\n", schemas);
2366
  return(-1);
2367
    }
2368
    vctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
2369
    xmlRelaxNGSetValidErrors(vctxt, xmlGenericError, xmlGenericError, NULL);
2370
    ret = xmlRelaxNGValidateDoc(vctxt, sctxt->doc);
2371
    if (ret == 0) {
2372
  fprintf(stderr, "%s validates\n", sctxt->filename);
2373
    } else if (ret > 0) {
2374
  fprintf(stderr, "%s fails to validate\n", sctxt->filename);
2375
    } else {
2376
  fprintf(stderr, "%s validation generated an internal error\n",
2377
         sctxt->filename);
2378
    }
2379
    xmlRelaxNGFreeValidCtxt(vctxt);
2380
    if (relaxngschemas != NULL)
2381
  xmlRelaxNGFree(relaxngschemas);
2382
    return(0);
2383
}
2384
#endif
2385
2386
#ifdef LIBXML_OUTPUT_ENABLED
2387
/**
2388
 * xmlShellCat:
2389
 * @ctxt:  the shell context
2390
 * @arg:  unused
2391
 * @node:  a node
2392
 * @node2:  unused
2393
 *
2394
 * Implements the XML shell function "cat"
2395
 * dumps the serialization node content (XML or HTML).
2396
 *
2397
 * Returns 0
2398
 */
2399
int
2400
xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
2401
            xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2402
0
{
2403
0
    if (!ctxt)
2404
0
        return (0);
2405
0
    if (node == NULL) {
2406
0
  fprintf(ctxt->output, "NULL\n");
2407
0
  return (0);
2408
0
    }
2409
0
    if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
2410
0
#ifdef LIBXML_HTML_ENABLED
2411
0
        if (node->type == XML_HTML_DOCUMENT_NODE)
2412
0
            htmlDocDump(ctxt->output, (htmlDocPtr) node);
2413
0
        else
2414
0
            htmlNodeDumpFile(ctxt->output, ctxt->doc, node);
2415
#else
2416
        if (node->type == XML_DOCUMENT_NODE)
2417
            xmlDocDump(ctxt->output, (xmlDocPtr) node);
2418
        else
2419
            xmlElemDump(ctxt->output, ctxt->doc, node);
2420
#endif /* LIBXML_HTML_ENABLED */
2421
0
    } else {
2422
0
        if (node->type == XML_DOCUMENT_NODE)
2423
0
            xmlDocDump(ctxt->output, (xmlDocPtr) node);
2424
0
        else
2425
0
            xmlElemDump(ctxt->output, ctxt->doc, node);
2426
0
    }
2427
0
    fprintf(ctxt->output, "\n");
2428
0
    return (0);
2429
0
}
2430
#endif /* LIBXML_OUTPUT_ENABLED */
2431
2432
/**
2433
 * xmlShellLoad:
2434
 * @ctxt:  the shell context
2435
 * @filename:  the file name
2436
 * @node:  unused
2437
 * @node2:  unused
2438
 *
2439
 * Implements the XML shell function "load"
2440
 * loads a new document specified by the filename
2441
 *
2442
 * Returns 0 or -1 if loading failed
2443
 */
2444
int
2445
xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
2446
             xmlNodePtr node ATTRIBUTE_UNUSED,
2447
             xmlNodePtr node2 ATTRIBUTE_UNUSED)
2448
0
{
2449
0
    xmlDocPtr doc;
2450
0
    int html = 0;
2451
2452
0
    if ((ctxt == NULL) || (filename == NULL)) return(-1);
2453
0
    if (ctxt->doc != NULL)
2454
0
        html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
2455
2456
0
    if (html) {
2457
0
#ifdef LIBXML_HTML_ENABLED
2458
0
        doc = htmlParseFile(filename, NULL);
2459
#else
2460
        fprintf(ctxt->output, "HTML support not compiled in\n");
2461
        doc = NULL;
2462
#endif /* LIBXML_HTML_ENABLED */
2463
0
    } else {
2464
0
        doc = xmlReadFile(filename,NULL,0);
2465
0
    }
2466
0
    if (doc != NULL) {
2467
0
        if (ctxt->loaded == 1) {
2468
0
            xmlFreeDoc(ctxt->doc);
2469
0
        }
2470
0
        ctxt->loaded = 1;
2471
0
#ifdef LIBXML_XPATH_ENABLED
2472
0
        xmlXPathFreeContext(ctxt->pctxt);
2473
0
#endif /* LIBXML_XPATH_ENABLED */
2474
0
        xmlFree(ctxt->filename);
2475
0
        ctxt->doc = doc;
2476
0
        ctxt->node = (xmlNodePtr) doc;
2477
0
#ifdef LIBXML_XPATH_ENABLED
2478
0
        ctxt->pctxt = xmlXPathNewContext(doc);
2479
0
#endif /* LIBXML_XPATH_ENABLED */
2480
0
        ctxt->filename = (char *) xmlCanonicPath((xmlChar *) filename);
2481
0
    } else
2482
0
        return (-1);
2483
0
    return (0);
2484
0
}
2485
2486
#ifdef LIBXML_OUTPUT_ENABLED
2487
/**
2488
 * xmlShellWrite:
2489
 * @ctxt:  the shell context
2490
 * @filename:  the file name
2491
 * @node:  a node in the tree
2492
 * @node2:  unused
2493
 *
2494
 * Implements the XML shell function "write"
2495
 * Write the current node to the filename, it saves the serialization
2496
 * of the subtree under the @node specified
2497
 *
2498
 * Returns 0 or -1 in case of error
2499
 */
2500
int
2501
xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
2502
              xmlNodePtr node2 ATTRIBUTE_UNUSED)
2503
0
{
2504
0
    if (node == NULL)
2505
0
        return (-1);
2506
0
    if ((filename == NULL) || (filename[0] == 0)) {
2507
0
        return (-1);
2508
0
    }
2509
#ifdef W_OK
2510
    if (access((char *) filename, W_OK)) {
2511
        xmlGenericError(xmlGenericErrorContext,
2512
                        "Cannot write to %s\n", filename);
2513
        return (-1);
2514
    }
2515
#endif
2516
0
    switch (node->type) {
2517
0
        case XML_DOCUMENT_NODE:
2518
0
            if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
2519
0
                xmlGenericError(xmlGenericErrorContext,
2520
0
                                "Failed to write to %s\n", filename);
2521
0
                return (-1);
2522
0
            }
2523
0
            break;
2524
0
        case XML_HTML_DOCUMENT_NODE:
2525
0
#ifdef LIBXML_HTML_ENABLED
2526
0
            if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
2527
0
                xmlGenericError(xmlGenericErrorContext,
2528
0
                                "Failed to write to %s\n", filename);
2529
0
                return (-1);
2530
0
            }
2531
#else
2532
            if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
2533
                xmlGenericError(xmlGenericErrorContext,
2534
                                "Failed to write to %s\n", filename);
2535
                return (-1);
2536
            }
2537
#endif /* LIBXML_HTML_ENABLED */
2538
0
            break;
2539
0
        default:{
2540
0
                FILE *f;
2541
2542
0
                f = fopen((char *) filename, "w");
2543
0
                if (f == NULL) {
2544
0
                    xmlGenericError(xmlGenericErrorContext,
2545
0
                                    "Failed to write to %s\n", filename);
2546
0
                    return (-1);
2547
0
                }
2548
0
                xmlElemDump(f, ctxt->doc, node);
2549
0
                fclose(f);
2550
0
            }
2551
0
    }
2552
0
    return (0);
2553
0
}
2554
2555
/**
2556
 * xmlShellSave:
2557
 * @ctxt:  the shell context
2558
 * @filename:  the file name (optional)
2559
 * @node:  unused
2560
 * @node2:  unused
2561
 *
2562
 * Implements the XML shell function "save"
2563
 * Write the current document to the filename, or it's original name
2564
 *
2565
 * Returns 0 or -1 in case of error
2566
 */
2567
int
2568
xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
2569
             xmlNodePtr node ATTRIBUTE_UNUSED,
2570
             xmlNodePtr node2 ATTRIBUTE_UNUSED)
2571
0
{
2572
0
    if ((ctxt == NULL) || (ctxt->doc == NULL))
2573
0
        return (-1);
2574
0
    if ((filename == NULL) || (filename[0] == 0))
2575
0
        filename = ctxt->filename;
2576
0
    if (filename == NULL)
2577
0
        return (-1);
2578
#ifdef W_OK
2579
    if (access((char *) filename, W_OK)) {
2580
        xmlGenericError(xmlGenericErrorContext,
2581
                        "Cannot save to %s\n", filename);
2582
        return (-1);
2583
    }
2584
#endif
2585
0
    switch (ctxt->doc->type) {
2586
0
        case XML_DOCUMENT_NODE:
2587
0
            if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
2588
0
                xmlGenericError(xmlGenericErrorContext,
2589
0
                                "Failed to save to %s\n", filename);
2590
0
            }
2591
0
            break;
2592
0
        case XML_HTML_DOCUMENT_NODE:
2593
0
#ifdef LIBXML_HTML_ENABLED
2594
0
            if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
2595
0
                xmlGenericError(xmlGenericErrorContext,
2596
0
                                "Failed to save to %s\n", filename);
2597
0
            }
2598
#else
2599
            if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
2600
                xmlGenericError(xmlGenericErrorContext,
2601
                                "Failed to save to %s\n", filename);
2602
            }
2603
#endif /* LIBXML_HTML_ENABLED */
2604
0
            break;
2605
0
        default:
2606
0
            xmlGenericError(xmlGenericErrorContext,
2607
0
      "To save to subparts of a document use the 'write' command\n");
2608
0
            return (-1);
2609
2610
0
    }
2611
0
    return (0);
2612
0
}
2613
#endif /* LIBXML_OUTPUT_ENABLED */
2614
2615
#ifdef LIBXML_VALID_ENABLED
2616
/**
2617
 * xmlShellValidate:
2618
 * @ctxt:  the shell context
2619
 * @dtd:  the DTD URI (optional)
2620
 * @node:  unused
2621
 * @node2:  unused
2622
 *
2623
 * Implements the XML shell function "validate"
2624
 * Validate the document, if a DTD path is provided, then the validation
2625
 * is done against the given DTD.
2626
 *
2627
 * Returns 0 or -1 in case of error
2628
 */
2629
int
2630
xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
2631
                 xmlNodePtr node ATTRIBUTE_UNUSED,
2632
                 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2633
{
2634
    xmlValidCtxt vctxt;
2635
    int res = -1;
2636
2637
    if ((ctxt == NULL) || (ctxt->doc == NULL)) return(-1);
2638
    memset(&vctxt, 0, sizeof(vctxt));
2639
    vctxt.error = xmlGenericError;
2640
    vctxt.warning = xmlGenericError;
2641
2642
    if ((dtd == NULL) || (dtd[0] == 0)) {
2643
        res = xmlValidateDocument(&vctxt, ctxt->doc);
2644
    } else {
2645
        xmlDtdPtr subset;
2646
2647
        subset = xmlParseDTD(NULL, (xmlChar *) dtd);
2648
        if (subset != NULL) {
2649
            res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
2650
2651
            xmlFreeDtd(subset);
2652
        }
2653
    }
2654
    return (res);
2655
}
2656
#endif /* LIBXML_VALID_ENABLED */
2657
2658
/**
2659
 * xmlShellDu:
2660
 * @ctxt:  the shell context
2661
 * @arg:  unused
2662
 * @tree:  a node defining a subtree
2663
 * @node2:  unused
2664
 *
2665
 * Implements the XML shell function "du"
2666
 * show the structure of the subtree under node @tree
2667
 * If @tree is null, the command works on the current node.
2668
 *
2669
 * Returns 0 or -1 in case of error
2670
 */
2671
int
2672
xmlShellDu(xmlShellCtxtPtr ctxt,
2673
           char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
2674
           xmlNodePtr node2 ATTRIBUTE_UNUSED)
2675
0
{
2676
0
    xmlNodePtr node;
2677
0
    int indent = 0, i;
2678
2679
0
    if (!ctxt)
2680
0
  return (-1);
2681
2682
0
    if (tree == NULL)
2683
0
        return (-1);
2684
0
    node = tree;
2685
0
    while (node != NULL) {
2686
0
        if ((node->type == XML_DOCUMENT_NODE) ||
2687
0
            (node->type == XML_HTML_DOCUMENT_NODE)) {
2688
0
            fprintf(ctxt->output, "/\n");
2689
0
        } else if (node->type == XML_ELEMENT_NODE) {
2690
0
            for (i = 0; i < indent; i++)
2691
0
                fprintf(ctxt->output, "  ");
2692
0
            if ((node->ns) && (node->ns->prefix))
2693
0
                fprintf(ctxt->output, "%s:", node->ns->prefix);
2694
0
            fprintf(ctxt->output, "%s\n", node->name);
2695
0
        } else {
2696
0
        }
2697
2698
        /*
2699
         * Browse the full subtree, deep first
2700
         */
2701
2702
0
        if ((node->type == XML_DOCUMENT_NODE) ||
2703
0
            (node->type == XML_HTML_DOCUMENT_NODE)) {
2704
0
            node = ((xmlDocPtr) node)->children;
2705
0
        } else if ((node->children != NULL)
2706
0
                   && (node->type != XML_ENTITY_REF_NODE)) {
2707
            /* deep first */
2708
0
            node = node->children;
2709
0
            indent++;
2710
0
        } else if ((node != tree) && (node->next != NULL)) {
2711
            /* then siblings */
2712
0
            node = node->next;
2713
0
        } else if (node != tree) {
2714
            /* go up to parents->next if needed */
2715
0
            while (node != tree) {
2716
0
                if (node->parent != NULL) {
2717
0
                    node = node->parent;
2718
0
                    indent--;
2719
0
                }
2720
0
                if ((node != tree) && (node->next != NULL)) {
2721
0
                    node = node->next;
2722
0
                    break;
2723
0
                }
2724
0
                if (node->parent == NULL) {
2725
0
                    node = NULL;
2726
0
                    break;
2727
0
                }
2728
0
                if (node == tree) {
2729
0
                    node = NULL;
2730
0
                    break;
2731
0
                }
2732
0
            }
2733
            /* exit condition */
2734
0
            if (node == tree)
2735
0
                node = NULL;
2736
0
        } else
2737
0
            node = NULL;
2738
0
    }
2739
0
    return (0);
2740
0
}
2741
2742
/**
2743
 * xmlShellPwd:
2744
 * @ctxt:  the shell context
2745
 * @buffer:  the output buffer
2746
 * @node:  a node
2747
 * @node2:  unused
2748
 *
2749
 * Implements the XML shell function "pwd"
2750
 * Show the full path from the root to the node, if needed building
2751
 * thumblers when similar elements exists at a given ancestor level.
2752
 * The output is compatible with XPath commands.
2753
 *
2754
 * Returns 0 or -1 in case of error
2755
 */
2756
int
2757
xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
2758
            xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2759
0
{
2760
0
    xmlChar *path;
2761
2762
0
    if ((node == NULL) || (buffer == NULL))
2763
0
        return (-1);
2764
2765
0
    path = xmlGetNodePath(node);
2766
0
    if (path == NULL)
2767
0
  return (-1);
2768
2769
    /*
2770
     * This test prevents buffer overflow, because this routine
2771
     * is only called by xmlShell, in which the second argument is
2772
     * 500 chars long.
2773
     * It is a dirty hack before a cleaner solution is found.
2774
     * Documentation should mention that the second argument must
2775
     * be at least 500 chars long, and could be stripped if too long.
2776
     */
2777
0
    snprintf(buffer, 499, "%s", path);
2778
0
    buffer[499] = '0';
2779
0
    xmlFree(path);
2780
2781
0
    return (0);
2782
0
}
2783
2784
/**
2785
 * xmlShell:
2786
 * @doc:  the initial document
2787
 * @filename:  the output buffer
2788
 * @input:  the line reading function
2789
 * @output:  the output FILE*, defaults to stdout if NULL
2790
 *
2791
 * Implements the XML shell
2792
 * This allow to load, validate, view, modify and save a document
2793
 * using a environment similar to a UNIX commandline.
2794
 */
2795
void
2796
xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
2797
         FILE * output)
2798
0
{
2799
0
    char prompt[500] = "/ > ";
2800
0
    char *cmdline = NULL, *cur;
2801
0
    char command[100];
2802
0
    char arg[400];
2803
0
    int i;
2804
0
    xmlShellCtxtPtr ctxt;
2805
0
    xmlXPathObjectPtr list;
2806
2807
0
    if (doc == NULL)
2808
0
        return;
2809
0
    if (filename == NULL)
2810
0
        return;
2811
0
    if (input == NULL)
2812
0
        return;
2813
0
    if (output == NULL)
2814
0
        output = stdout;
2815
0
    ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
2816
0
    if (ctxt == NULL)
2817
0
        return;
2818
0
    ctxt->loaded = 0;
2819
0
    ctxt->doc = doc;
2820
0
    ctxt->input = input;
2821
0
    ctxt->output = output;
2822
0
    ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
2823
0
    ctxt->node = (xmlNodePtr) ctxt->doc;
2824
2825
0
#ifdef LIBXML_XPATH_ENABLED
2826
0
    ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
2827
0
    if (ctxt->pctxt == NULL) {
2828
0
        xmlFree(ctxt);
2829
0
        return;
2830
0
    }
2831
0
#endif /* LIBXML_XPATH_ENABLED */
2832
0
    while (1) {
2833
0
        if (ctxt->node == (xmlNodePtr) ctxt->doc)
2834
0
            snprintf(prompt, sizeof(prompt), "%s > ", "/");
2835
0
        else if ((ctxt->node != NULL) && (ctxt->node->name) &&
2836
0
                 (ctxt->node->ns) && (ctxt->node->ns->prefix))
2837
0
            snprintf(prompt, sizeof(prompt), "%s:%s > ",
2838
0
                     (ctxt->node->ns->prefix), ctxt->node->name);
2839
0
        else if ((ctxt->node != NULL) && (ctxt->node->name))
2840
0
            snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
2841
0
        else
2842
0
            snprintf(prompt, sizeof(prompt), "? > ");
2843
0
        prompt[sizeof(prompt) - 1] = 0;
2844
2845
        /*
2846
         * Get a new command line
2847
         */
2848
0
        cmdline = ctxt->input(prompt);
2849
0
        if (cmdline == NULL)
2850
0
            break;
2851
2852
        /*
2853
         * Parse the command itself
2854
         */
2855
0
        cur = cmdline;
2856
0
        while ((*cur == ' ') || (*cur == '\t'))
2857
0
            cur++;
2858
0
        i = 0;
2859
0
        while ((*cur != ' ') && (*cur != '\t') &&
2860
0
               (*cur != '\n') && (*cur != '\r')) {
2861
0
            if (*cur == 0)
2862
0
                break;
2863
0
            command[i++] = *cur++;
2864
0
        }
2865
0
        command[i] = 0;
2866
0
        if (i == 0)
2867
0
            continue;
2868
2869
        /*
2870
         * Parse the argument
2871
         */
2872
0
        while ((*cur == ' ') || (*cur == '\t'))
2873
0
            cur++;
2874
0
        i = 0;
2875
0
        while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
2876
0
            if (*cur == 0)
2877
0
                break;
2878
0
            arg[i++] = *cur++;
2879
0
        }
2880
0
        arg[i] = 0;
2881
2882
        /*
2883
         * start interpreting the command
2884
         */
2885
0
        if (!strcmp(command, "exit"))
2886
0
            break;
2887
0
        if (!strcmp(command, "quit"))
2888
0
            break;
2889
0
        if (!strcmp(command, "bye"))
2890
0
            break;
2891
0
    if (!strcmp(command, "help")) {
2892
0
      fprintf(ctxt->output, "\tbase         display XML base of the node\n");
2893
0
      fprintf(ctxt->output, "\tsetbase URI  change the XML base of the node\n");
2894
0
      fprintf(ctxt->output, "\tbye          leave shell\n");
2895
0
      fprintf(ctxt->output, "\tcat [node]   display node or current node\n");
2896
0
      fprintf(ctxt->output, "\tcd [path]    change directory to path or to root\n");
2897
0
      fprintf(ctxt->output, "\tdir [path]   dumps information about the node (namespace, attributes, content)\n");
2898
0
      fprintf(ctxt->output, "\tdu [path]    show the structure of the subtree under path or the current node\n");
2899
0
      fprintf(ctxt->output, "\texit         leave shell\n");
2900
0
      fprintf(ctxt->output, "\thelp         display this help\n");
2901
0
      fprintf(ctxt->output, "\tfree         display memory usage\n");
2902
0
      fprintf(ctxt->output, "\tload [name]  load a new document with name\n");
2903
0
      fprintf(ctxt->output, "\tls [path]    list contents of path or the current directory\n");
2904
0
      fprintf(ctxt->output, "\tset xml_fragment replace the current node content with the fragment parsed in context\n");
2905
0
#ifdef LIBXML_XPATH_ENABLED
2906
0
      fprintf(ctxt->output, "\txpath expr   evaluate the XPath expression in that context and print the result\n");
2907
0
      fprintf(ctxt->output, "\tsetns nsreg  register a namespace to a prefix in the XPath evaluation context\n");
2908
0
      fprintf(ctxt->output, "\t             format for nsreg is: prefix=[nsuri] (i.e. prefix= unsets a prefix)\n");
2909
0
      fprintf(ctxt->output, "\tsetrootns    register all namespace found on the root element\n");
2910
0
      fprintf(ctxt->output, "\t             the default namespace if any uses 'defaultns' prefix\n");
2911
0
#endif /* LIBXML_XPATH_ENABLED */
2912
0
      fprintf(ctxt->output, "\tpwd          display current working directory\n");
2913
0
      fprintf(ctxt->output, "\twhereis      display absolute path of [path] or current working directory\n");
2914
0
      fprintf(ctxt->output, "\tquit         leave shell\n");
2915
0
#ifdef LIBXML_OUTPUT_ENABLED
2916
0
      fprintf(ctxt->output, "\tsave [name]  save this document to name or the original name\n");
2917
0
      fprintf(ctxt->output, "\twrite [name] write the current node to the filename\n");
2918
0
#endif /* LIBXML_OUTPUT_ENABLED */
2919
#ifdef LIBXML_VALID_ENABLED
2920
      fprintf(ctxt->output, "\tvalidate     check the document for errors\n");
2921
#endif /* LIBXML_VALID_ENABLED */
2922
#ifdef LIBXML_SCHEMAS_ENABLED
2923
      fprintf(ctxt->output, "\trelaxng rng  validate the document against the Relax-NG schemas\n");
2924
#endif
2925
0
      fprintf(ctxt->output, "\tgrep string  search for a string in the subtree\n");
2926
#ifdef LIBXML_VALID_ENABLED
2927
        } else if (!strcmp(command, "validate")) {
2928
            xmlShellValidate(ctxt, arg, NULL, NULL);
2929
#endif /* LIBXML_VALID_ENABLED */
2930
0
        } else if (!strcmp(command, "load")) {
2931
0
            xmlShellLoad(ctxt, arg, NULL, NULL);
2932
#ifdef LIBXML_SCHEMAS_ENABLED
2933
        } else if (!strcmp(command, "relaxng")) {
2934
            xmlShellRNGValidate(ctxt, arg, NULL, NULL);
2935
#endif
2936
0
#ifdef LIBXML_OUTPUT_ENABLED
2937
0
        } else if (!strcmp(command, "save")) {
2938
0
            xmlShellSave(ctxt, arg, NULL, NULL);
2939
0
        } else if (!strcmp(command, "write")) {
2940
0
      if (arg[0] == 0)
2941
0
    xmlGenericError(xmlGenericErrorContext,
2942
0
                        "Write command requires a filename argument\n");
2943
0
      else
2944
0
    xmlShellWrite(ctxt, arg, ctxt->node, NULL);
2945
0
#endif /* LIBXML_OUTPUT_ENABLED */
2946
0
        } else if (!strcmp(command, "grep")) {
2947
0
            xmlShellGrep(ctxt, arg, ctxt->node, NULL);
2948
0
        } else if (!strcmp(command, "free")) {
2949
0
            if (arg[0] == 0) {
2950
0
                xmlMemShow(ctxt->output, 0);
2951
0
            } else {
2952
0
                int len = 0;
2953
2954
0
                sscanf(arg, "%d", &len);
2955
0
                xmlMemShow(ctxt->output, len);
2956
0
            }
2957
0
        } else if (!strcmp(command, "pwd")) {
2958
0
            char dir[500];
2959
2960
0
            if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
2961
0
                fprintf(ctxt->output, "%s\n", dir);
2962
0
        } else if (!strcmp(command, "du")) {
2963
0
            if (arg[0] == 0) {
2964
0
                xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2965
0
            } else {
2966
0
                ctxt->pctxt->node = ctxt->node;
2967
0
#ifdef LIBXML_XPATH_ENABLED
2968
0
                ctxt->pctxt->node = ctxt->node;
2969
0
                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2970
#else
2971
                list = NULL;
2972
#endif /* LIBXML_XPATH_ENABLED */
2973
0
                if (list != NULL) {
2974
0
                    switch (list->type) {
2975
0
                        case XPATH_UNDEFINED:
2976
0
                            xmlGenericError(xmlGenericErrorContext,
2977
0
                                            "%s: no such node\n", arg);
2978
0
                            break;
2979
0
                        case XPATH_NODESET:{
2980
0
                            int indx;
2981
2982
0
                            if (list->nodesetval == NULL)
2983
0
                                break;
2984
2985
0
                            for (indx = 0;
2986
0
                                 indx < list->nodesetval->nodeNr;
2987
0
                                 indx++)
2988
0
                                xmlShellDu(ctxt, NULL,
2989
0
                                           list->nodesetval->
2990
0
                                           nodeTab[indx], NULL);
2991
0
                            break;
2992
0
                        }
2993
0
                        case XPATH_BOOLEAN:
2994
0
                            xmlGenericError(xmlGenericErrorContext,
2995
0
                                            "%s is a Boolean\n", arg);
2996
0
                            break;
2997
0
                        case XPATH_NUMBER:
2998
0
                            xmlGenericError(xmlGenericErrorContext,
2999
0
                                            "%s is a number\n", arg);
3000
0
                            break;
3001
0
                        case XPATH_STRING:
3002
0
                            xmlGenericError(xmlGenericErrorContext,
3003
0
                                            "%s is a string\n", arg);
3004
0
                            break;
3005
#ifdef LIBXML_XPTR_LOCS_ENABLED
3006
                        case XPATH_POINT:
3007
                            xmlGenericError(xmlGenericErrorContext,
3008
                                            "%s is a point\n", arg);
3009
                            break;
3010
                        case XPATH_RANGE:
3011
                            xmlGenericError(xmlGenericErrorContext,
3012
                                            "%s is a range\n", arg);
3013
                            break;
3014
                        case XPATH_LOCATIONSET:
3015
                            xmlGenericError(xmlGenericErrorContext,
3016
                                            "%s is a range\n", arg);
3017
                            break;
3018
#endif /* LIBXML_XPTR_LOCS_ENABLED */
3019
0
                        case XPATH_USERS:
3020
0
                            xmlGenericError(xmlGenericErrorContext,
3021
0
                                            "%s is user-defined\n", arg);
3022
0
                            break;
3023
0
                        case XPATH_XSLT_TREE:
3024
0
                            xmlGenericError(xmlGenericErrorContext,
3025
0
                                            "%s is an XSLT value tree\n",
3026
0
                                            arg);
3027
0
                            break;
3028
0
                    }
3029
0
#ifdef LIBXML_XPATH_ENABLED
3030
0
                    xmlXPathFreeObject(list);
3031
0
#endif
3032
0
                } else {
3033
0
                    xmlGenericError(xmlGenericErrorContext,
3034
0
                                    "%s: no such node\n", arg);
3035
0
                }
3036
0
                ctxt->pctxt->node = NULL;
3037
0
            }
3038
0
        } else if (!strcmp(command, "base")) {
3039
0
            xmlShellBase(ctxt, NULL, ctxt->node, NULL);
3040
0
        } else if (!strcmp(command, "set")) {
3041
0
      xmlShellSetContent(ctxt, arg, ctxt->node, NULL);
3042
0
#ifdef LIBXML_XPATH_ENABLED
3043
0
        } else if (!strcmp(command, "setns")) {
3044
0
            if (arg[0] == 0) {
3045
0
    xmlGenericError(xmlGenericErrorContext,
3046
0
        "setns: prefix=[nsuri] required\n");
3047
0
            } else {
3048
0
                xmlShellRegisterNamespace(ctxt, arg, NULL, NULL);
3049
0
            }
3050
0
        } else if (!strcmp(command, "setrootns")) {
3051
0
      xmlNodePtr root;
3052
3053
0
      root = xmlDocGetRootElement(ctxt->doc);
3054
0
      xmlShellRegisterRootNamespaces(ctxt, NULL, root, NULL);
3055
0
        } else if (!strcmp(command, "xpath")) {
3056
0
            if (arg[0] == 0) {
3057
0
    xmlGenericError(xmlGenericErrorContext,
3058
0
        "xpath: expression required\n");
3059
0
      } else {
3060
0
                ctxt->pctxt->node = ctxt->node;
3061
0
                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3062
0
    xmlXPathDebugDumpObject(ctxt->output, list, 0);
3063
0
    xmlXPathFreeObject(list);
3064
0
      }
3065
0
#endif /* LIBXML_XPATH_ENABLED */
3066
0
#ifdef LIBXML_TREE_ENABLED
3067
0
        } else if (!strcmp(command, "setbase")) {
3068
0
            xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
3069
0
#endif
3070
0
        } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
3071
0
            int dir = (!strcmp(command, "dir"));
3072
3073
0
            if (arg[0] == 0) {
3074
0
                if (dir)
3075
0
                    xmlShellDir(ctxt, NULL, ctxt->node, NULL);
3076
0
                else
3077
0
                    xmlShellList(ctxt, NULL, ctxt->node, NULL);
3078
0
            } else {
3079
0
                ctxt->pctxt->node = ctxt->node;
3080
0
#ifdef LIBXML_XPATH_ENABLED
3081
0
                ctxt->pctxt->node = ctxt->node;
3082
0
                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3083
#else
3084
                list = NULL;
3085
#endif /* LIBXML_XPATH_ENABLED */
3086
0
                if (list != NULL) {
3087
0
                    switch (list->type) {
3088
0
                        case XPATH_UNDEFINED:
3089
0
                            xmlGenericError(xmlGenericErrorContext,
3090
0
                                            "%s: no such node\n", arg);
3091
0
                            break;
3092
0
                        case XPATH_NODESET:{
3093
0
                                int indx;
3094
3095
0
        if (list->nodesetval == NULL)
3096
0
            break;
3097
3098
0
                                for (indx = 0;
3099
0
                                     indx < list->nodesetval->nodeNr;
3100
0
                                     indx++) {
3101
0
                                    if (dir)
3102
0
                                        xmlShellDir(ctxt, NULL,
3103
0
                                                    list->nodesetval->
3104
0
                                                    nodeTab[indx], NULL);
3105
0
                                    else
3106
0
                                        xmlShellList(ctxt, NULL,
3107
0
                                                     list->nodesetval->
3108
0
                                                     nodeTab[indx], NULL);
3109
0
                                }
3110
0
                                break;
3111
0
                            }
3112
0
                        case XPATH_BOOLEAN:
3113
0
                            xmlGenericError(xmlGenericErrorContext,
3114
0
                                            "%s is a Boolean\n", arg);
3115
0
                            break;
3116
0
                        case XPATH_NUMBER:
3117
0
                            xmlGenericError(xmlGenericErrorContext,
3118
0
                                            "%s is a number\n", arg);
3119
0
                            break;
3120
0
                        case XPATH_STRING:
3121
0
                            xmlGenericError(xmlGenericErrorContext,
3122
0
                                            "%s is a string\n", arg);
3123
0
                            break;
3124
#ifdef LIBXML_XPTR_LOCS_ENABLED
3125
                        case XPATH_POINT:
3126
                            xmlGenericError(xmlGenericErrorContext,
3127
                                            "%s is a point\n", arg);
3128
                            break;
3129
                        case XPATH_RANGE:
3130
                            xmlGenericError(xmlGenericErrorContext,
3131
                                            "%s is a range\n", arg);
3132
                            break;
3133
                        case XPATH_LOCATIONSET:
3134
                            xmlGenericError(xmlGenericErrorContext,
3135
                                            "%s is a range\n", arg);
3136
                            break;
3137
#endif /* LIBXML_XPTR_LOCS_ENABLED */
3138
0
                        case XPATH_USERS:
3139
0
                            xmlGenericError(xmlGenericErrorContext,
3140
0
                                            "%s is user-defined\n", arg);
3141
0
                            break;
3142
0
                        case XPATH_XSLT_TREE:
3143
0
                            xmlGenericError(xmlGenericErrorContext,
3144
0
                                            "%s is an XSLT value tree\n",
3145
0
                                            arg);
3146
0
                            break;
3147
0
                    }
3148
0
#ifdef LIBXML_XPATH_ENABLED
3149
0
                    xmlXPathFreeObject(list);
3150
0
#endif
3151
0
                } else {
3152
0
                    xmlGenericError(xmlGenericErrorContext,
3153
0
                                    "%s: no such node\n", arg);
3154
0
                }
3155
0
                ctxt->pctxt->node = NULL;
3156
0
            }
3157
0
        } else if (!strcmp(command, "whereis")) {
3158
0
            char dir[500];
3159
3160
0
            if (arg[0] == 0) {
3161
0
                if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
3162
0
                    fprintf(ctxt->output, "%s\n", dir);
3163
0
            } else {
3164
0
                ctxt->pctxt->node = ctxt->node;
3165
0
#ifdef LIBXML_XPATH_ENABLED
3166
0
                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3167
#else
3168
                list = NULL;
3169
#endif /* LIBXML_XPATH_ENABLED */
3170
0
                if (list != NULL) {
3171
0
                    switch (list->type) {
3172
0
                        case XPATH_UNDEFINED:
3173
0
                            xmlGenericError(xmlGenericErrorContext,
3174
0
                                            "%s: no such node\n", arg);
3175
0
                            break;
3176
0
                        case XPATH_NODESET:{
3177
0
                                int indx;
3178
3179
0
        if (list->nodesetval == NULL)
3180
0
            break;
3181
3182
0
                                for (indx = 0;
3183
0
                                     indx < list->nodesetval->nodeNr;
3184
0
                                     indx++) {
3185
0
                                    if (!xmlShellPwd(ctxt, dir, list->nodesetval->
3186
0
                                                     nodeTab[indx], NULL))
3187
0
                                        fprintf(ctxt->output, "%s\n", dir);
3188
0
                                }
3189
0
                                break;
3190
0
                            }
3191
0
                        case XPATH_BOOLEAN:
3192
0
                            xmlGenericError(xmlGenericErrorContext,
3193
0
                                            "%s is a Boolean\n", arg);
3194
0
                            break;
3195
0
                        case XPATH_NUMBER:
3196
0
                            xmlGenericError(xmlGenericErrorContext,
3197
0
                                            "%s is a number\n", arg);
3198
0
                            break;
3199
0
                        case XPATH_STRING:
3200
0
                            xmlGenericError(xmlGenericErrorContext,
3201
0
                                            "%s is a string\n", arg);
3202
0
                            break;
3203
#ifdef LIBXML_XPTR_LOCS_ENABLED
3204
                        case XPATH_POINT:
3205
                            xmlGenericError(xmlGenericErrorContext,
3206
                                            "%s is a point\n", arg);
3207
                            break;
3208
                        case XPATH_RANGE:
3209
                            xmlGenericError(xmlGenericErrorContext,
3210
                                            "%s is a range\n", arg);
3211
                            break;
3212
                        case XPATH_LOCATIONSET:
3213
                            xmlGenericError(xmlGenericErrorContext,
3214
                                            "%s is a range\n", arg);
3215
                            break;
3216
#endif /* LIBXML_XPTR_LOCS_ENABLED */
3217
0
                        case XPATH_USERS:
3218
0
                            xmlGenericError(xmlGenericErrorContext,
3219
0
                                            "%s is user-defined\n", arg);
3220
0
                            break;
3221
0
                        case XPATH_XSLT_TREE:
3222
0
                            xmlGenericError(xmlGenericErrorContext,
3223
0
                                            "%s is an XSLT value tree\n",
3224
0
                                            arg);
3225
0
                            break;
3226
0
                    }
3227
0
#ifdef LIBXML_XPATH_ENABLED
3228
0
                    xmlXPathFreeObject(list);
3229
0
#endif
3230
0
                } else {
3231
0
                    xmlGenericError(xmlGenericErrorContext,
3232
0
                                    "%s: no such node\n", arg);
3233
0
                }
3234
0
                ctxt->pctxt->node = NULL;
3235
0
            }
3236
0
        } else if (!strcmp(command, "cd")) {
3237
0
            if (arg[0] == 0) {
3238
0
                ctxt->node = (xmlNodePtr) ctxt->doc;
3239
0
            } else {
3240
0
#ifdef LIBXML_XPATH_ENABLED
3241
0
                int l;
3242
3243
0
                ctxt->pctxt->node = ctxt->node;
3244
0
    l = strlen(arg);
3245
0
    if ((l >= 2) && (arg[l - 1] == '/'))
3246
0
        arg[l - 1] = 0;
3247
0
                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3248
#else
3249
                list = NULL;
3250
#endif /* LIBXML_XPATH_ENABLED */
3251
0
                if (list != NULL) {
3252
0
                    switch (list->type) {
3253
0
                        case XPATH_UNDEFINED:
3254
0
                            xmlGenericError(xmlGenericErrorContext,
3255
0
                                            "%s: no such node\n", arg);
3256
0
                            break;
3257
0
                        case XPATH_NODESET:
3258
0
                            if (list->nodesetval != NULL) {
3259
0
        if (list->nodesetval->nodeNr == 1) {
3260
0
            ctxt->node = list->nodesetval->nodeTab[0];
3261
0
            if ((ctxt->node != NULL) &&
3262
0
                (ctxt->node->type ==
3263
0
           XML_NAMESPACE_DECL)) {
3264
0
          xmlGenericError(xmlGenericErrorContext,
3265
0
                "cannot cd to namespace\n");
3266
0
          ctxt->node = NULL;
3267
0
            }
3268
0
        } else
3269
0
            xmlGenericError(xmlGenericErrorContext,
3270
0
                "%s is a %d Node Set\n",
3271
0
                arg,
3272
0
                list->nodesetval->nodeNr);
3273
0
                            } else
3274
0
                                xmlGenericError(xmlGenericErrorContext,
3275
0
                                                "%s is an empty Node Set\n",
3276
0
                                                arg);
3277
0
                            break;
3278
0
                        case XPATH_BOOLEAN:
3279
0
                            xmlGenericError(xmlGenericErrorContext,
3280
0
                                            "%s is a Boolean\n", arg);
3281
0
                            break;
3282
0
                        case XPATH_NUMBER:
3283
0
                            xmlGenericError(xmlGenericErrorContext,
3284
0
                                            "%s is a number\n", arg);
3285
0
                            break;
3286
0
                        case XPATH_STRING:
3287
0
                            xmlGenericError(xmlGenericErrorContext,
3288
0
                                            "%s is a string\n", arg);
3289
0
                            break;
3290
#ifdef LIBXML_XPTR_LOCS_ENABLED
3291
                        case XPATH_POINT:
3292
                            xmlGenericError(xmlGenericErrorContext,
3293
                                            "%s is a point\n", arg);
3294
                            break;
3295
                        case XPATH_RANGE:
3296
                            xmlGenericError(xmlGenericErrorContext,
3297
                                            "%s is a range\n", arg);
3298
                            break;
3299
                        case XPATH_LOCATIONSET:
3300
                            xmlGenericError(xmlGenericErrorContext,
3301
                                            "%s is a range\n", arg);
3302
                            break;
3303
#endif /* LIBXML_XPTR_LOCS_ENABLED */
3304
0
                        case XPATH_USERS:
3305
0
                            xmlGenericError(xmlGenericErrorContext,
3306
0
                                            "%s is user-defined\n", arg);
3307
0
                            break;
3308
0
                        case XPATH_XSLT_TREE:
3309
0
                            xmlGenericError(xmlGenericErrorContext,
3310
0
                                            "%s is an XSLT value tree\n",
3311
0
                                            arg);
3312
0
                            break;
3313
0
                    }
3314
0
#ifdef LIBXML_XPATH_ENABLED
3315
0
                    xmlXPathFreeObject(list);
3316
0
#endif
3317
0
                } else {
3318
0
                    xmlGenericError(xmlGenericErrorContext,
3319
0
                                    "%s: no such node\n", arg);
3320
0
                }
3321
0
                ctxt->pctxt->node = NULL;
3322
0
            }
3323
0
#ifdef LIBXML_OUTPUT_ENABLED
3324
0
        } else if (!strcmp(command, "cat")) {
3325
0
            if (arg[0] == 0) {
3326
0
                xmlShellCat(ctxt, NULL, ctxt->node, NULL);
3327
0
            } else {
3328
0
                ctxt->pctxt->node = ctxt->node;
3329
0
#ifdef LIBXML_XPATH_ENABLED
3330
0
                ctxt->pctxt->node = ctxt->node;
3331
0
                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3332
#else
3333
                list = NULL;
3334
#endif /* LIBXML_XPATH_ENABLED */
3335
0
                if (list != NULL) {
3336
0
                    switch (list->type) {
3337
0
                        case XPATH_UNDEFINED:
3338
0
                            xmlGenericError(xmlGenericErrorContext,
3339
0
                                            "%s: no such node\n", arg);
3340
0
                            break;
3341
0
                        case XPATH_NODESET:{
3342
0
                                int indx;
3343
3344
0
        if (list->nodesetval == NULL)
3345
0
            break;
3346
3347
0
                                for (indx = 0;
3348
0
                                     indx < list->nodesetval->nodeNr;
3349
0
                                     indx++) {
3350
0
                                    if (i > 0)
3351
0
                                        fprintf(ctxt->output, " -------\n");
3352
0
                                    xmlShellCat(ctxt, NULL,
3353
0
                                                list->nodesetval->
3354
0
                                                nodeTab[indx], NULL);
3355
0
                                }
3356
0
                                break;
3357
0
                            }
3358
0
                        case XPATH_BOOLEAN:
3359
0
                            xmlGenericError(xmlGenericErrorContext,
3360
0
                                            "%s is a Boolean\n", arg);
3361
0
                            break;
3362
0
                        case XPATH_NUMBER:
3363
0
                            xmlGenericError(xmlGenericErrorContext,
3364
0
                                            "%s is a number\n", arg);
3365
0
                            break;
3366
0
                        case XPATH_STRING:
3367
0
                            xmlGenericError(xmlGenericErrorContext,
3368
0
                                            "%s is a string\n", arg);
3369
0
                            break;
3370
#ifdef LIBXML_XPTR_LOCS_ENABLED
3371
                        case XPATH_POINT:
3372
                            xmlGenericError(xmlGenericErrorContext,
3373
                                            "%s is a point\n", arg);
3374
                            break;
3375
                        case XPATH_RANGE:
3376
                            xmlGenericError(xmlGenericErrorContext,
3377
                                            "%s is a range\n", arg);
3378
                            break;
3379
                        case XPATH_LOCATIONSET:
3380
                            xmlGenericError(xmlGenericErrorContext,
3381
                                            "%s is a range\n", arg);
3382
                            break;
3383
#endif /* LIBXML_XPTR_LOCS_ENABLED */
3384
0
                        case XPATH_USERS:
3385
0
                            xmlGenericError(xmlGenericErrorContext,
3386
0
                                            "%s is user-defined\n", arg);
3387
0
                            break;
3388
0
                        case XPATH_XSLT_TREE:
3389
0
                            xmlGenericError(xmlGenericErrorContext,
3390
0
                                            "%s is an XSLT value tree\n",
3391
0
                                            arg);
3392
0
                            break;
3393
0
                    }
3394
0
#ifdef LIBXML_XPATH_ENABLED
3395
0
                    xmlXPathFreeObject(list);
3396
0
#endif
3397
0
                } else {
3398
0
                    xmlGenericError(xmlGenericErrorContext,
3399
0
                                    "%s: no such node\n", arg);
3400
0
                }
3401
0
                ctxt->pctxt->node = NULL;
3402
0
            }
3403
0
#endif /* LIBXML_OUTPUT_ENABLED */
3404
0
        } else {
3405
0
            xmlGenericError(xmlGenericErrorContext,
3406
0
                            "Unknown command %s\n", command);
3407
0
        }
3408
0
        free(cmdline);          /* not xmlFree here ! */
3409
0
  cmdline = NULL;
3410
0
    }
3411
0
#ifdef LIBXML_XPATH_ENABLED
3412
0
    xmlXPathFreeContext(ctxt->pctxt);
3413
0
#endif /* LIBXML_XPATH_ENABLED */
3414
0
    if (ctxt->loaded) {
3415
0
        xmlFreeDoc(ctxt->doc);
3416
0
    }
3417
0
    if (ctxt->filename != NULL)
3418
0
        xmlFree(ctxt->filename);
3419
0
    xmlFree(ctxt);
3420
0
    if (cmdline != NULL)
3421
0
        free(cmdline);          /* not xmlFree here ! */
3422
0
}
3423
3424
#endif /* LIBXML_XPATH_ENABLED */
3425
3426
#endif /* LIBXML_DEBUG_ENABLED */