Coverage Report

Created: 2025-06-22 06:55

/src/libxml2/entities.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * entities.c : implementation for the XML entities handling
3
 *
4
 * See Copyright for the status of this software.
5
 *
6
 * Author: Daniel Veillard
7
 */
8
9
/* To avoid EBCDIC trouble when parsing on zOS */
10
#if defined(__MVS__)
11
#pragma convert("ISO8859-1")
12
#endif
13
14
#define IN_LIBXML
15
#include "libxml.h"
16
17
#include <string.h>
18
#include <stdlib.h>
19
20
#include <libxml/xmlmemory.h>
21
#include <libxml/hash.h>
22
#include <libxml/entities.h>
23
#include <libxml/parser.h>
24
#include <libxml/parserInternals.h>
25
#include <libxml/xmlerror.h>
26
#include <libxml/dict.h>
27
#include <libxml/xmlsave.h>
28
29
#include "private/entities.h"
30
#include "private/error.h"
31
#include "private/io.h"
32
33
#ifndef SIZE_MAX
34
  #define SIZE_MAX ((size_t) -1)
35
#endif
36
37
/*
38
 * The XML predefined entities.
39
 */
40
41
static xmlEntity xmlEntityLt = {
42
    NULL, XML_ENTITY_DECL, BAD_CAST "lt",
43
    NULL, NULL, NULL, NULL, NULL, NULL,
44
    BAD_CAST "<", BAD_CAST "<", 1,
45
    XML_INTERNAL_PREDEFINED_ENTITY,
46
    NULL, NULL, NULL, NULL, 0, 0, 0
47
};
48
static xmlEntity xmlEntityGt = {
49
    NULL, XML_ENTITY_DECL, BAD_CAST "gt",
50
    NULL, NULL, NULL, NULL, NULL, NULL,
51
    BAD_CAST ">", BAD_CAST ">", 1,
52
    XML_INTERNAL_PREDEFINED_ENTITY,
53
    NULL, NULL, NULL, NULL, 0, 0, 0
54
};
55
static xmlEntity xmlEntityAmp = {
56
    NULL, XML_ENTITY_DECL, BAD_CAST "amp",
57
    NULL, NULL, NULL, NULL, NULL, NULL,
58
    BAD_CAST "&", BAD_CAST "&", 1,
59
    XML_INTERNAL_PREDEFINED_ENTITY,
60
    NULL, NULL, NULL, NULL, 0, 0, 0
61
};
62
static xmlEntity xmlEntityQuot = {
63
    NULL, XML_ENTITY_DECL, BAD_CAST "quot",
64
    NULL, NULL, NULL, NULL, NULL, NULL,
65
    BAD_CAST "\"", BAD_CAST "\"", 1,
66
    XML_INTERNAL_PREDEFINED_ENTITY,
67
    NULL, NULL, NULL, NULL, 0, 0, 0
68
};
69
static xmlEntity xmlEntityApos = {
70
    NULL, XML_ENTITY_DECL, BAD_CAST "apos",
71
    NULL, NULL, NULL, NULL, NULL, NULL,
72
    BAD_CAST "'", BAD_CAST "'", 1,
73
    XML_INTERNAL_PREDEFINED_ENTITY,
74
    NULL, NULL, NULL, NULL, 0, 0, 0
75
};
76
77
/**
78
 * Frees the entity.
79
 *
80
 * @param entity  an entity
81
 */
82
void
83
xmlFreeEntity(xmlEntity *entity)
84
9.22k
{
85
9.22k
    xmlDictPtr dict = NULL;
86
87
9.22k
    if (entity == NULL)
88
0
        return;
89
90
9.22k
    if (entity->doc != NULL)
91
9.22k
        dict = entity->doc->dict;
92
93
94
9.22k
    if ((entity->children) &&
95
9.22k
        (entity == (xmlEntityPtr) entity->children->parent))
96
360
        xmlFreeNodeList(entity->children);
97
9.22k
    if ((entity->name != NULL) &&
98
9.22k
        ((dict == NULL) || (!xmlDictOwns(dict, entity->name))))
99
9.22k
        xmlFree((char *) entity->name);
100
9.22k
    if (entity->ExternalID != NULL)
101
971
        xmlFree((char *) entity->ExternalID);
102
9.22k
    if (entity->SystemID != NULL)
103
895
        xmlFree((char *) entity->SystemID);
104
9.22k
    if (entity->URI != NULL)
105
207
        xmlFree((char *) entity->URI);
106
9.22k
    if (entity->content != NULL)
107
7.63k
        xmlFree((char *) entity->content);
108
9.22k
    if (entity->orig != NULL)
109
3.80k
        xmlFree((char *) entity->orig);
110
9.22k
    xmlFree(entity);
111
9.22k
}
112
113
/*
114
 * internal routine doing the entity node structures allocations
115
 */
116
static xmlEntityPtr
117
xmlCreateEntity(xmlDocPtr doc, const xmlChar *name, int type,
118
          const xmlChar *publicId, const xmlChar *systemId,
119
9.22k
          const xmlChar *content) {
120
9.22k
    xmlEntityPtr ret;
121
122
9.22k
    ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
123
9.22k
    if (ret == NULL)
124
0
  return(NULL);
125
9.22k
    memset(ret, 0, sizeof(xmlEntity));
126
9.22k
    ret->doc = doc;
127
9.22k
    ret->type = XML_ENTITY_DECL;
128
129
    /*
130
     * fill the structure.
131
     */
132
9.22k
    ret->etype = (xmlEntityType) type;
133
9.22k
    if ((doc == NULL) || (doc->dict == NULL))
134
9.22k
  ret->name = xmlStrdup(name);
135
0
    else
136
0
        ret->name = xmlDictLookup(doc->dict, name, -1);
137
9.22k
    if (ret->name == NULL)
138
0
        goto error;
139
9.22k
    if (publicId != NULL) {
140
971
        ret->ExternalID = xmlStrdup(publicId);
141
971
        if (ret->ExternalID == NULL)
142
0
            goto error;
143
971
    }
144
9.22k
    if (systemId != NULL) {
145
895
        ret->SystemID = xmlStrdup(systemId);
146
895
        if (ret->SystemID == NULL)
147
0
            goto error;
148
895
    }
149
9.22k
    if (content != NULL) {
150
7.63k
        ret->length = xmlStrlen(content);
151
7.63k
  ret->content = xmlStrndup(content, ret->length);
152
7.63k
        if (ret->content == NULL)
153
0
            goto error;
154
7.63k
     } else {
155
1.59k
        ret->length = 0;
156
1.59k
        ret->content = NULL;
157
1.59k
    }
158
9.22k
    ret->URI = NULL; /* to be computed by the layer knowing
159
      the defining entity */
160
9.22k
    ret->orig = NULL;
161
162
9.22k
    return(ret);
163
164
0
error:
165
0
    xmlFreeEntity(ret);
166
0
    return(NULL);
167
9.22k
}
168
169
/**
170
 * Register a new entity for this document.
171
 *
172
 * @since 2.13.0
173
 *
174
 * @param doc  the document
175
 * @param extSubset  add to the external or internal subset
176
 * @param name  the entity name
177
 * @param type  an xmlEntityType value
178
 * @param publicId  the publid identifier (optional)
179
 * @param systemId  the system identifier (URL) (optional)
180
 * @param content  the entity content
181
 * @param out  pointer to resulting entity (optional)
182
 * @returns an xmlParserErrors error code.
183
 */
184
int
185
xmlAddEntity(xmlDoc *doc, int extSubset, const xmlChar *name, int type,
186
    const xmlChar *publicId, const xmlChar *systemId,
187
14.7k
    const xmlChar *content, xmlEntity **out) {
188
14.7k
    xmlDtdPtr dtd;
189
14.7k
    xmlDictPtr dict = NULL;
190
14.7k
    xmlEntitiesTablePtr table = NULL;
191
14.7k
    xmlEntityPtr ret, predef;
192
14.7k
    int res;
193
194
14.7k
    if (out != NULL)
195
14.7k
        *out = NULL;
196
14.7k
    if ((doc == NULL) || (name == NULL))
197
0
  return(XML_ERR_ARGUMENT);
198
14.7k
    dict = doc->dict;
199
200
14.7k
    if (extSubset)
201
0
        dtd = doc->extSubset;
202
14.7k
    else
203
14.7k
        dtd = doc->intSubset;
204
14.7k
    if (dtd == NULL)
205
0
        return(XML_DTD_NO_DTD);
206
207
14.7k
    switch (type) {
208
11.5k
        case XML_INTERNAL_GENERAL_ENTITY:
209
13.0k
        case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
210
13.0k
        case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
211
13.0k
            predef = xmlGetPredefinedEntity(name);
212
13.0k
            if (predef != NULL) {
213
8.32k
                int valid = 0;
214
215
                /* 4.6 Predefined Entities */
216
8.32k
                if ((type == XML_INTERNAL_GENERAL_ENTITY) &&
217
8.32k
                    (content != NULL)) {
218
8.23k
                    int c = predef->content[0];
219
220
8.23k
                    if (((content[0] == c) && (content[1] == 0)) &&
221
8.23k
                        ((c == '>') || (c == '\'') || (c == '"'))) {
222
59
                        valid = 1;
223
8.17k
                    } else if ((content[0] == '&') && (content[1] == '#')) {
224
5.19k
                        if (content[2] == 'x') {
225
2.28k
                            xmlChar *hex = BAD_CAST "0123456789ABCDEF";
226
2.28k
                            xmlChar ref[] = "00;";
227
228
2.28k
                            ref[0] = hex[c / 16 % 16];
229
2.28k
                            ref[1] = hex[c % 16];
230
2.28k
                            if (xmlStrcasecmp(&content[3], ref) == 0)
231
663
                                valid = 1;
232
2.91k
                        } else {
233
2.91k
                            xmlChar ref[] = "00;";
234
235
2.91k
                            ref[0] = '0' + c / 10 % 10;
236
2.91k
                            ref[1] = '0' + c % 10;
237
2.91k
                            if (xmlStrEqual(&content[2], ref))
238
2.10k
                                valid = 1;
239
2.91k
                        }
240
5.19k
                    }
241
8.23k
                }
242
8.32k
                if (!valid)
243
5.49k
                    return(XML_ERR_REDECL_PREDEF_ENTITY);
244
8.32k
            }
245
7.59k
      if (dtd->entities == NULL) {
246
1.85k
    dtd->entities = xmlHashCreateDict(0, dict);
247
1.85k
                if (dtd->entities == NULL)
248
0
                    return(XML_ERR_NO_MEMORY);
249
1.85k
            }
250
7.59k
      table = dtd->entities;
251
7.59k
      break;
252
1.44k
        case XML_INTERNAL_PARAMETER_ENTITY:
253
1.63k
        case XML_EXTERNAL_PARAMETER_ENTITY:
254
1.63k
      if (dtd->pentities == NULL) {
255
1.19k
    dtd->pentities = xmlHashCreateDict(0, dict);
256
1.19k
                if (dtd->pentities == NULL)
257
0
                    return(XML_ERR_NO_MEMORY);
258
1.19k
            }
259
1.63k
      table = dtd->pentities;
260
1.63k
      break;
261
0
        default:
262
0
      return(XML_ERR_ARGUMENT);
263
14.7k
    }
264
9.22k
    ret = xmlCreateEntity(dtd->doc, name, type, publicId, systemId, content);
265
9.22k
    if (ret == NULL)
266
0
        return(XML_ERR_NO_MEMORY);
267
268
9.22k
    res = xmlHashAdd(table, name, ret);
269
9.22k
    if (res < 0) {
270
0
        xmlFreeEntity(ret);
271
0
        return(XML_ERR_NO_MEMORY);
272
9.22k
    } else if (res == 0) {
273
  /*
274
   * entity was already defined at another level.
275
   */
276
5.07k
        xmlFreeEntity(ret);
277
5.07k
  return(XML_WAR_ENTITY_REDEFINED);
278
5.07k
    }
279
280
    /*
281
     * Link it to the DTD
282
     */
283
4.15k
    ret->parent = dtd;
284
4.15k
    ret->doc = dtd->doc;
285
4.15k
    if (dtd->last == NULL) {
286
2.97k
  dtd->children = dtd->last = (xmlNodePtr) ret;
287
2.97k
    } else {
288
1.18k
  dtd->last->next = (xmlNodePtr) ret;
289
1.18k
  ret->prev = dtd->last;
290
1.18k
  dtd->last = (xmlNodePtr) ret;
291
1.18k
    }
292
293
4.15k
    if (out != NULL)
294
4.15k
        *out = ret;
295
4.15k
    return(0);
296
9.22k
}
297
298
/**
299
 * Look up a predefined entity.
300
 *
301
 * @param name  the entity name
302
 * @returns the entity, or NULL if not found.
303
 */
304
xmlEntity *
305
848k
xmlGetPredefinedEntity(const xmlChar *name) {
306
848k
    if (name == NULL) return(NULL);
307
848k
    switch (name[0]) {
308
116k
        case 'l':
309
116k
      if (xmlStrEqual(name, BAD_CAST "lt"))
310
82.7k
          return(&xmlEntityLt);
311
33.6k
      break;
312
33.6k
        case 'g':
313
2.80k
      if (xmlStrEqual(name, BAD_CAST "gt"))
314
396
          return(&xmlEntityGt);
315
2.40k
      break;
316
359k
        case 'a':
317
359k
      if (xmlStrEqual(name, BAD_CAST "amp"))
318
3.13k
          return(&xmlEntityAmp);
319
355k
      if (xmlStrEqual(name, BAD_CAST "apos"))
320
319
          return(&xmlEntityApos);
321
355k
      break;
322
355k
        case 'q':
323
279k
      if (xmlStrEqual(name, BAD_CAST "quot"))
324
308
          return(&xmlEntityQuot);
325
279k
      break;
326
279k
  default:
327
91.1k
      break;
328
848k
    }
329
762k
    return(NULL);
330
848k
}
331
332
/**
333
 * Add a new entity to the document's external subset.
334
 *
335
 * #xmlAddEntity offers better error handling.
336
 *
337
 * @param doc  the document
338
 * @param name  the entity name
339
 * @param type  an xmlEntityType value
340
 * @param publicId  the publid identifier (optional)
341
 * @param systemId  the system identifier (URL) (optional)
342
 * @param content  the entity content
343
 * @returns a pointer to the entity or NULL in case of error
344
 */
345
xmlEntity *
346
xmlAddDtdEntity(xmlDoc *doc, const xmlChar *name, int type,
347
          const xmlChar *publicId, const xmlChar *systemId,
348
0
    const xmlChar *content) {
349
0
    xmlEntityPtr ret;
350
351
0
    xmlAddEntity(doc, 1, name, type, publicId, systemId, content, &ret);
352
0
    return(ret);
353
0
}
354
355
/**
356
 * Add a new entity to the document's internal subset.
357
 *
358
 * #xmlAddEntity offers better error handling.
359
 *
360
 * @param doc  the document
361
 * @param name  the entity name
362
 * @param type  an xmlEntityType value
363
 * @param publicId  the publid identifier (optional)
364
 * @param systemId  the system identifier (URL) (optional)
365
 * @param content  the entity content
366
 * @returns a pointer to the entity or NULL in case of error
367
 */
368
xmlEntity *
369
xmlAddDocEntity(xmlDoc *doc, const xmlChar *name, int type,
370
          const xmlChar *publicId, const xmlChar *systemId,
371
0
          const xmlChar *content) {
372
0
    xmlEntityPtr ret;
373
374
0
    xmlAddEntity(doc, 0, name, type, publicId, systemId, content, &ret);
375
0
    return(ret);
376
0
}
377
378
/**
379
 * Create a new entity.
380
 *
381
 * Like #xmlAddDocEntity, but if `doc` is NULL or has no internal
382
 * subset defined, an unlinked entity will be returned. It is then
383
 * the responsibility of the caller to link it to the document later
384
 * or free it when not needed anymore.
385
 *
386
 * @param doc  the document (optional)
387
 * @param name  the entity name
388
 * @param type  an xmlEntityType value
389
 * @param publicId  the publid identifier (optional)
390
 * @param systemId  the system identifier (URL) (optional)
391
 * @param content  the entity content
392
 * @returns a pointer to the entity or NULL in case of error
393
 */
394
xmlEntity *
395
xmlNewEntity(xmlDoc *doc, const xmlChar *name, int type,
396
       const xmlChar *publicId, const xmlChar *systemId,
397
0
       const xmlChar *content) {
398
0
    if ((doc != NULL) && (doc->intSubset != NULL)) {
399
0
  return(xmlAddDocEntity(doc, name, type, publicId, systemId, content));
400
0
    }
401
0
    if (name == NULL)
402
0
        return(NULL);
403
0
    return(xmlCreateEntity(doc, name, type, publicId, systemId, content));
404
0
}
405
406
/**
407
 * Look up an entity in a table.
408
 *
409
 * @param table  an entity table
410
 * @param name  the entity name
411
 * @returns a pointer to the entity or NULL if not found.
412
 */
413
static xmlEntityPtr
414
337k
xmlGetEntityFromTable(xmlEntitiesTablePtr table, const xmlChar *name) {
415
337k
    return((xmlEntityPtr) xmlHashLookup(table, name));
416
337k
}
417
418
/**
419
 * Look up a paramater entity in the internal and external subset
420
 * of `doc`.
421
 *
422
 * @param doc  the document
423
 * @param name  the entity name
424
 * @returns a pointer to the entity or NULL if not found.
425
 */
426
xmlEntity *
427
39.0k
xmlGetParameterEntity(xmlDoc *doc, const xmlChar *name) {
428
39.0k
    xmlEntitiesTablePtr table;
429
39.0k
    xmlEntityPtr ret;
430
431
39.0k
    if (doc == NULL)
432
860
  return(NULL);
433
38.1k
    if ((doc->intSubset != NULL) && (doc->intSubset->pentities != NULL)) {
434
35.1k
  table = (xmlEntitiesTablePtr) doc->intSubset->pentities;
435
35.1k
  ret = xmlGetEntityFromTable(table, name);
436
35.1k
  if (ret != NULL)
437
31.6k
      return(ret);
438
35.1k
    }
439
6.51k
    if ((doc->extSubset != NULL) && (doc->extSubset->pentities != NULL)) {
440
0
  table = (xmlEntitiesTablePtr) doc->extSubset->pentities;
441
0
  return(xmlGetEntityFromTable(table, name));
442
0
    }
443
6.51k
    return(NULL);
444
6.51k
}
445
446
/**
447
 * Look up a general entity in the external subset of `doc`.
448
 *
449
 * @param doc  the document
450
 * @param name  the entity name
451
 * @returns a pointer to the entity or NULL if not found.
452
 */
453
xmlEntity *
454
0
xmlGetDtdEntity(xmlDoc *doc, const xmlChar *name) {
455
0
    xmlEntitiesTablePtr table;
456
457
0
    if (doc == NULL)
458
0
  return(NULL);
459
0
    if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
460
0
  table = (xmlEntitiesTablePtr) doc->extSubset->entities;
461
0
  return(xmlGetEntityFromTable(table, name));
462
0
    }
463
0
    return(NULL);
464
0
}
465
466
/**
467
 * Look up a general entity in the internal and external subset
468
 * of `doc`. Also checks for predefined entities.
469
 *
470
 * @param doc  the document referencing the entity
471
 * @param name  the entity name
472
 * @returns a pointer to the entity or NULL if not found.
473
 */
474
xmlEntity *
475
355k
xmlGetDocEntity(const xmlDoc *doc, const xmlChar *name) {
476
355k
    xmlEntityPtr cur;
477
355k
    xmlEntitiesTablePtr table;
478
479
355k
    if (doc != NULL) {
480
342k
  if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
481
277k
      table = (xmlEntitiesTablePtr) doc->intSubset->entities;
482
277k
      cur = xmlGetEntityFromTable(table, name);
483
277k
      if (cur != NULL)
484
247k
    return(cur);
485
277k
  }
486
94.7k
  if (doc->standalone != 1) {
487
94.4k
      if ((doc->extSubset != NULL) &&
488
94.4k
    (doc->extSubset->entities != NULL)) {
489
24.8k
    table = (xmlEntitiesTablePtr) doc->extSubset->entities;
490
24.8k
    cur = xmlGetEntityFromTable(table, name);
491
24.8k
    if (cur != NULL)
492
0
        return(cur);
493
24.8k
      }
494
94.4k
  }
495
94.7k
    }
496
107k
    return(xmlGetPredefinedEntity(name));
497
355k
}
498
499
/**
500
 * Replace special characters with predefined entities or numeric
501
 * character references.
502
 *
503
 * If `doc` is NULL or an XML document, replaces `<`, `>` and `&`
504
 * with predefined entities. Carriage return is replaced with
505
 * `&#13;`. If `doc` or its encoding are NULL, non-ASCII
506
 * characters are replaced with a hexadecimal character reference.
507
 *
508
 * If `doc` is an HTML document, follows the HTML serialization
509
 * rules.
510
 *
511
 * Silently removes some invalid characters like ASCII control
512
 * codes.
513
 *
514
 * See #xmlEncodeSpecialChars for an alternative.
515
 *
516
 * @param doc  the document containing the string (optional)
517
 * @param input  A string to convert to XML.
518
 * @returns a newly allocated string with substitutions.
519
 */
520
xmlChar *
521
0
xmlEncodeEntitiesReentrant(xmlDoc *doc, const xmlChar *input) {
522
0
    int flags = 0;
523
524
0
    if (input == NULL)
525
0
        return(NULL);
526
527
0
    if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE))
528
0
        flags |= XML_ESCAPE_HTML;
529
0
    else if ((doc == NULL) || (doc->encoding == NULL))
530
0
        flags |= XML_ESCAPE_NON_ASCII;
531
532
0
    return(xmlEscapeText(input, flags));
533
0
}
534
535
/**
536
 * Replace special characters with predefined entities or numeric
537
 * character references.
538
 *
539
 * Replaces `<`, `>`, `&` and `"` with predefined entities. Carriage
540
 * return is replaced with `&#13;`.
541
 *
542
 * @param doc  unused
543
 * @param input  A string to convert to XML.
544
 * @returns a newly allocated string with substitutions.
545
 */
546
xmlChar *
547
xmlEncodeSpecialChars(const xmlDoc *doc ATTRIBUTE_UNUSED,
548
0
                      const xmlChar *input) {
549
0
    if (input == NULL)
550
0
        return(NULL);
551
552
0
    return(xmlEscapeText(input, XML_ESCAPE_QUOT));
553
0
}
554
555
/**
556
 * Create and initialize an empty entities hash table.
557
 *
558
 * @deprecated Internal function, don't use.
559
 *
560
 * @returns the xmlEntitiesTable just created or NULL in case of error.
561
 */
562
xmlEntitiesTable *
563
0
xmlCreateEntitiesTable(void) {
564
0
    return((xmlEntitiesTablePtr) xmlHashCreate(0));
565
0
}
566
567
/**
568
 * Deallocate the memory used by an entities in the hash table.
569
 *
570
 * @param entity  An entity
571
 * @param name  its name
572
 */
573
static void
574
4.15k
xmlFreeEntityWrapper(void *entity, const xmlChar *name ATTRIBUTE_UNUSED) {
575
4.15k
    if (entity != NULL)
576
4.15k
  xmlFreeEntity((xmlEntityPtr) entity);
577
4.15k
}
578
579
/**
580
 * Deallocate the memory used by an entities hash table.
581
 *
582
 * @deprecated Internal function, don't use.
583
 *
584
 * @param table  An entity table
585
 */
586
void
587
3.05k
xmlFreeEntitiesTable(xmlEntitiesTable *table) {
588
3.05k
    xmlHashFree(table, xmlFreeEntityWrapper);
589
3.05k
}
590
591
/**
592
 * Build a copy of an entity
593
 *
594
 * @param payload  An entity
595
 * @param name  unused
596
 * @returns the new xmlEntities or NULL in case of error.
597
 */
598
static void *
599
0
xmlCopyEntity(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
600
0
    xmlEntityPtr ent = (xmlEntityPtr) payload;
601
0
    xmlEntityPtr cur;
602
603
0
    cur = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
604
0
    if (cur == NULL)
605
0
  return(NULL);
606
0
    memset(cur, 0, sizeof(xmlEntity));
607
0
    cur->type = XML_ENTITY_DECL;
608
609
0
    cur->etype = ent->etype;
610
0
    if (ent->name != NULL) {
611
0
  cur->name = xmlStrdup(ent->name);
612
0
        if (cur->name == NULL)
613
0
            goto error;
614
0
    }
615
0
    if (ent->ExternalID != NULL) {
616
0
  cur->ExternalID = xmlStrdup(ent->ExternalID);
617
0
        if (cur->ExternalID == NULL)
618
0
            goto error;
619
0
    }
620
0
    if (ent->SystemID != NULL) {
621
0
  cur->SystemID = xmlStrdup(ent->SystemID);
622
0
        if (cur->SystemID == NULL)
623
0
            goto error;
624
0
    }
625
0
    if (ent->content != NULL) {
626
0
  cur->content = xmlStrdup(ent->content);
627
0
        if (cur->content == NULL)
628
0
            goto error;
629
0
    }
630
0
    if (ent->orig != NULL) {
631
0
  cur->orig = xmlStrdup(ent->orig);
632
0
        if (cur->orig == NULL)
633
0
            goto error;
634
0
    }
635
0
    if (ent->URI != NULL) {
636
0
  cur->URI = xmlStrdup(ent->URI);
637
0
        if (cur->URI == NULL)
638
0
            goto error;
639
0
    }
640
0
    return(cur);
641
642
0
error:
643
0
    xmlFreeEntity(cur);
644
0
    return(NULL);
645
0
}
646
647
/**
648
 * Build a copy of an entity table.
649
 *
650
 * @deprecated Internal function, don't use.
651
 *
652
 * @param table  An entity table
653
 * @returns the new xmlEntitiesTable or NULL in case of error.
654
 */
655
xmlEntitiesTable *
656
0
xmlCopyEntitiesTable(xmlEntitiesTable *table) {
657
0
    return(xmlHashCopySafe(table, xmlCopyEntity, xmlFreeEntityWrapper));
658
0
}
659
660
#ifdef LIBXML_OUTPUT_ENABLED
661
662
/**
663
 * This will dump the content of the entity table as an XML DTD
664
 * definition.
665
 *
666
 * @deprecated Internal function, don't use.
667
 *
668
 * @param buf  An XML buffer.
669
 * @param ent  An entity table
670
 */
671
void
672
0
xmlDumpEntityDecl(xmlBuffer *buf, xmlEntity *ent) {
673
0
    xmlSaveCtxtPtr save;
674
675
0
    if ((buf == NULL) || (ent == NULL))
676
0
        return;
677
678
0
    save = xmlSaveToBuffer(buf, NULL, 0);
679
0
    xmlSaveTree(save, (xmlNodePtr) ent);
680
0
    if (xmlSaveFinish(save) != XML_ERR_OK)
681
0
        xmlFree(xmlBufferDetach(buf));
682
0
}
683
684
/**
685
 * When using the hash table scan function, arguments need to be
686
 * reversed.
687
 *
688
 * @param ent  an entity table
689
 * @param save  a save context
690
 * @param name  unused
691
 */
692
static void
693
xmlDumpEntityDeclScan(void *ent, void *save,
694
0
                      const xmlChar *name ATTRIBUTE_UNUSED) {
695
0
    xmlSaveTree(save, ent);
696
0
}
697
698
/**
699
 * This will dump the content of the entity table as an XML DTD
700
 * definition.
701
 *
702
 * @deprecated Internal function, don't use.
703
 *
704
 * @param buf  An XML buffer.
705
 * @param table  An entity table
706
 */
707
void
708
0
xmlDumpEntitiesTable(xmlBuffer *buf, xmlEntitiesTable *table) {
709
0
    xmlSaveCtxtPtr save;
710
711
0
    if ((buf == NULL) || (table == NULL))
712
0
        return;
713
714
0
    save = xmlSaveToBuffer(buf, NULL, 0);
715
0
    xmlHashScan(table, xmlDumpEntityDeclScan, save);
716
0
    if (xmlSaveFinish(save) != XML_ERR_OK)
717
0
        xmlFree(xmlBufferDetach(buf));
718
0
}
719
#endif /* LIBXML_OUTPUT_ENABLED */