mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-07-30 22:43:14 +03:00
html: Handle numeric character references directly
This commit is contained in:
201
HTMLparser.c
201
HTMLparser.c
@ -2452,84 +2452,19 @@ static const short htmlC1Remap[32] = {
|
|||||||
0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x009D, 0x017E, 0x0178
|
0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x009D, 0x017E, 0x0178
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
|
||||||
htmlParseNCR(const xmlChar *string, size_t slen, int *dlen) {
|
|
||||||
const xmlChar *in = string;
|
|
||||||
const xmlChar *end = string + slen;
|
|
||||||
unsigned val = 0;
|
|
||||||
|
|
||||||
while (in < end) {
|
|
||||||
int c = *in;
|
|
||||||
|
|
||||||
if ((c < '0') || (c > '9'))
|
|
||||||
break;
|
|
||||||
val = val * 10 + (c - '0');
|
|
||||||
if (val >= 0x110000)
|
|
||||||
val = 0x110000;
|
|
||||||
|
|
||||||
in += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*in == ';')
|
|
||||||
in += 1;
|
|
||||||
|
|
||||||
if ((val >= 0x80) && (val < 0xA0)) {
|
|
||||||
val = htmlC1Remap[val - 0x80];
|
|
||||||
} else if ((val <= 0) ||
|
|
||||||
((val >= 0xD800) && (val < 0xE000)) ||
|
|
||||||
(val > 0x10FFFF)) {
|
|
||||||
val = 0xFFFD;
|
|
||||||
}
|
|
||||||
|
|
||||||
*dlen = in - string;
|
|
||||||
|
|
||||||
return(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
htmlParseNCRHex(const xmlChar *string, size_t slen, int *dlen) {
|
|
||||||
const xmlChar *in = string;
|
|
||||||
const xmlChar *end = string + slen;
|
|
||||||
unsigned val = 0;
|
|
||||||
|
|
||||||
while (in < end) {
|
|
||||||
int c = *in | 0x20;
|
|
||||||
|
|
||||||
if ((c >= '0') && (c <= '9')) {
|
|
||||||
c -= '0';
|
|
||||||
} else if ((c >= 'a') && (c <= 'f')) {
|
|
||||||
c = (c - 'a') + 10;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
val = val * 16 + c;
|
|
||||||
if (val >= 0x110000)
|
|
||||||
val = 0x110000;
|
|
||||||
|
|
||||||
in += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*in == ';')
|
|
||||||
in += 1;
|
|
||||||
|
|
||||||
if ((val >= 0x80) && (val < 0xA0)) {
|
|
||||||
val = htmlC1Remap[val - 0x80];
|
|
||||||
} else if ((val <= 0) ||
|
|
||||||
((val >= 0xD800) && (val < 0xE000)) ||
|
|
||||||
(val > 0x10FFFF)) {
|
|
||||||
val = 0xFFFD;
|
|
||||||
}
|
|
||||||
|
|
||||||
*dlen = in - string;
|
|
||||||
|
|
||||||
return(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const xmlChar *
|
static const xmlChar *
|
||||||
htmlCodePointToUtf8(int c, xmlChar *out, int *osize) {
|
htmlCodePointToUtf8(int c, xmlChar *out, int *osize) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int bits, hi;
|
int bits, hi;
|
||||||
|
|
||||||
|
if ((c >= 0x80) && (c < 0xA0)) {
|
||||||
|
c = htmlC1Remap[c - 0x80];
|
||||||
|
} else if ((c <= 0) ||
|
||||||
|
((c >= 0xD800) && (c < 0xE000)) ||
|
||||||
|
(c > 0x10FFFF)) {
|
||||||
|
c = 0xFFFD;
|
||||||
|
}
|
||||||
|
|
||||||
if (c < 0x80) { bits = 0; hi = 0x00; }
|
if (c < 0x80) { bits = 0; hi = 0x00; }
|
||||||
else if (c < 0x800) { bits = 6; hi = 0xC0; }
|
else if (c < 0x800) { bits = 6; hi = 0xC0; }
|
||||||
else if (c < 0x10000) { bits = 12; hi = 0xE0; }
|
else if (c < 0x10000) { bits = 12; hi = 0xE0; }
|
||||||
@ -2656,7 +2591,7 @@ htmlFindEntityPrefix(const xmlChar *string, size_t slen, int isAttr,
|
|||||||
* @refs: true if references are allowed
|
* @refs: true if references are allowed
|
||||||
* @maxLength: maximum output length
|
* @maxLength: maximum output length
|
||||||
*
|
*
|
||||||
* Parse data until callback signals to stop.
|
* Parse data until terminator is reached.
|
||||||
*
|
*
|
||||||
* Returns the parsed string or NULL in case of errors.
|
* Returns the parsed string or NULL in case of errors.
|
||||||
*/
|
*/
|
||||||
@ -2694,6 +2629,9 @@ htmlParseData(htmlParserCtxtPtr ctxt, htmlAsciiMask mask,
|
|||||||
size_t avail, chunkSize, extraSize;
|
size_t avail, chunkSize, extraSize;
|
||||||
int replSize;
|
int replSize;
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
|
int ncr = 0;
|
||||||
|
int ncrSize = 0;
|
||||||
|
int cp = 0;
|
||||||
|
|
||||||
chunk = input->cur;
|
chunk = input->cur;
|
||||||
avail = input->end - chunk;
|
avail = input->end - chunk;
|
||||||
@ -2704,7 +2642,7 @@ htmlParseData(htmlParserCtxtPtr ctxt, htmlAsciiMask mask,
|
|||||||
|
|
||||||
while (!PARSER_STOPPED(ctxt)) {
|
while (!PARSER_STOPPED(ctxt)) {
|
||||||
size_t j;
|
size_t j;
|
||||||
int cur, size, cp;
|
int cur, size;
|
||||||
|
|
||||||
if ((!eof) && (avail <= 64)) {
|
if ((!eof) && (avail <= 64)) {
|
||||||
size_t oldAvail = avail;
|
size_t oldAvail = avail;
|
||||||
@ -2757,12 +2695,37 @@ htmlParseData(htmlParserCtxtPtr ctxt, htmlAsciiMask mask,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ncr) {
|
||||||
|
int lc = cur | 0x20;
|
||||||
|
int digit;
|
||||||
|
|
||||||
|
if ((cur >= '0') && (cur <= '9')) {
|
||||||
|
digit = cur - '0';
|
||||||
|
} else if ((ncr == 16) && (lc >= 'a') && (lc <= 'f')) {
|
||||||
|
digit = (lc - 'a') + 10;
|
||||||
|
} else {
|
||||||
|
if (cur == ';') {
|
||||||
|
in += 1;
|
||||||
|
size += 1;
|
||||||
|
ncrSize += 1;
|
||||||
|
}
|
||||||
|
goto next_chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
cp = cp * ncr + digit;
|
||||||
|
if (cp >= 0x110000)
|
||||||
|
cp = 0x110000;
|
||||||
|
|
||||||
|
ncrSize += 1;
|
||||||
|
|
||||||
|
goto next_char;
|
||||||
|
}
|
||||||
|
|
||||||
switch (cur) {
|
switch (cur) {
|
||||||
case '&':
|
case '&':
|
||||||
if (!refs)
|
if (!refs)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
cp = 0;
|
|
||||||
j = 1;
|
j = 1;
|
||||||
|
|
||||||
if ((j < avail) && (in[j] == '#')) {
|
if ((j < avail) && (in[j] == '#')) {
|
||||||
@ -2771,21 +2734,18 @@ htmlParseData(htmlParserCtxtPtr ctxt, htmlAsciiMask mask,
|
|||||||
if ((in[j] | 0x20) == 'x') {
|
if ((in[j] | 0x20) == 'x') {
|
||||||
j += 1;
|
j += 1;
|
||||||
if ((j < avail) && (IS_HEX_DIGIT(in[j]))) {
|
if ((j < avail) && (IS_HEX_DIGIT(in[j]))) {
|
||||||
cp = htmlParseNCRHex(in + j, avail - j, &skip);
|
ncr = 16;
|
||||||
skip += 3;
|
size = 3;
|
||||||
|
ncrSize = 3;
|
||||||
|
cp = 0;
|
||||||
}
|
}
|
||||||
} else if (IS_ASCII_DIGIT(in[j])) {
|
} else if (IS_ASCII_DIGIT(in[j])) {
|
||||||
cp = htmlParseNCR(in + j, avail - j, &skip);
|
ncr = 10;
|
||||||
skip += 2;
|
size = 2;
|
||||||
|
ncrSize = 2;
|
||||||
|
cp = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cp > 0) {
|
|
||||||
repl = htmlCodePointToUtf8(cp, utf8Char, &replSize);
|
|
||||||
goto next_chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
skip = 0;
|
|
||||||
} else {
|
} else {
|
||||||
repl = htmlFindEntityPrefix(in + j,
|
repl = htmlFindEntityPrefix(in + j,
|
||||||
avail - j,
|
avail - j,
|
||||||
@ -2851,11 +2811,19 @@ htmlParseData(htmlParserCtxtPtr ctxt, htmlAsciiMask mask,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
next_char:
|
||||||
in += size;
|
in += size;
|
||||||
avail -= size;
|
avail -= size;
|
||||||
}
|
}
|
||||||
|
|
||||||
next_chunk:
|
next_chunk:
|
||||||
|
if (ncrSize > 0) {
|
||||||
|
skip = ncrSize;
|
||||||
|
in -= ncrSize;
|
||||||
|
|
||||||
|
repl = htmlCodePointToUtf8(cp, utf8Char, &replSize);
|
||||||
|
}
|
||||||
|
|
||||||
chunkSize = in - chunk;
|
chunkSize = in - chunk;
|
||||||
extraSize = chunkSize + replSize;
|
extraSize = chunkSize + replSize;
|
||||||
|
|
||||||
@ -3028,6 +2996,9 @@ htmlParseCharData(htmlParserCtxtPtr ctxt) {
|
|||||||
size_t avail;
|
size_t avail;
|
||||||
int replSize;
|
int replSize;
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
|
int ncr = 0;
|
||||||
|
int ncrSize = 0;
|
||||||
|
int cp = 0;
|
||||||
|
|
||||||
chunk = input->cur;
|
chunk = input->cur;
|
||||||
avail = input->end - chunk;
|
avail = input->end - chunk;
|
||||||
@ -3038,7 +3009,7 @@ htmlParseCharData(htmlParserCtxtPtr ctxt) {
|
|||||||
|
|
||||||
while (!PARSER_STOPPED(ctxt)) {
|
while (!PARSER_STOPPED(ctxt)) {
|
||||||
size_t j;
|
size_t j;
|
||||||
int cur, size, cp;
|
int cur, size;
|
||||||
|
|
||||||
if (avail <= 64) {
|
if (avail <= 64) {
|
||||||
if (!eof) {
|
if (!eof) {
|
||||||
@ -3068,6 +3039,32 @@ htmlParseCharData(htmlParserCtxtPtr ctxt) {
|
|||||||
size = 1;
|
size = 1;
|
||||||
col += 1;
|
col += 1;
|
||||||
|
|
||||||
|
if (ncr) {
|
||||||
|
int lc = cur | 0x20;
|
||||||
|
int digit;
|
||||||
|
|
||||||
|
if ((cur >= '0') && (cur <= '9')) {
|
||||||
|
digit = cur - '0';
|
||||||
|
} else if ((ncr == 16) && (lc >= 'a') && (lc <= 'f')) {
|
||||||
|
digit = (lc - 'a') + 10;
|
||||||
|
} else {
|
||||||
|
if (cur == ';') {
|
||||||
|
in += 1;
|
||||||
|
size += 1;
|
||||||
|
ncrSize += 1;
|
||||||
|
}
|
||||||
|
goto next_chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
cp = cp * ncr + digit;
|
||||||
|
if (cp >= 0x110000)
|
||||||
|
cp = 0x110000;
|
||||||
|
|
||||||
|
ncrSize += 1;
|
||||||
|
|
||||||
|
goto next_char;
|
||||||
|
}
|
||||||
|
|
||||||
switch (cur) {
|
switch (cur) {
|
||||||
case '<':
|
case '<':
|
||||||
if (mode == 0) {
|
if (mode == 0) {
|
||||||
@ -3155,7 +3152,6 @@ htmlParseCharData(htmlParserCtxtPtr ctxt) {
|
|||||||
if ((mode != 0) && (mode != DATA_RCDATA))
|
if ((mode != 0) && (mode != DATA_RCDATA))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
cp = 0;
|
|
||||||
j = 1;
|
j = 1;
|
||||||
|
|
||||||
if ((j < avail) && (in[j] == '#')) {
|
if ((j < avail) && (in[j] == '#')) {
|
||||||
@ -3164,21 +3160,18 @@ htmlParseCharData(htmlParserCtxtPtr ctxt) {
|
|||||||
if ((in[j] | 0x20) == 'x') {
|
if ((in[j] | 0x20) == 'x') {
|
||||||
j += 1;
|
j += 1;
|
||||||
if ((j < avail) && (IS_HEX_DIGIT(in[j]))) {
|
if ((j < avail) && (IS_HEX_DIGIT(in[j]))) {
|
||||||
cp = htmlParseNCRHex(in + j, avail - j, &skip);
|
ncr = 16;
|
||||||
skip += 3;
|
size = 3;
|
||||||
|
ncrSize = 3;
|
||||||
|
cp = 0;
|
||||||
}
|
}
|
||||||
} else if (IS_ASCII_DIGIT(in[j])) {
|
} else if (IS_ASCII_DIGIT(in[j])) {
|
||||||
cp = htmlParseNCR(in + j, avail - j, &skip);
|
ncr = 10;
|
||||||
skip += 2;
|
size = 2;
|
||||||
|
ncrSize = 2;
|
||||||
|
cp = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cp > 0) {
|
|
||||||
repl = htmlCodePointToUtf8(cp, utf8Char, &replSize);
|
|
||||||
goto next_chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
skip = 0;
|
|
||||||
} else {
|
} else {
|
||||||
repl = htmlFindEntityPrefix(in + j,
|
repl = htmlFindEntityPrefix(in + j,
|
||||||
avail - j,
|
avail - j,
|
||||||
@ -3244,11 +3237,19 @@ htmlParseCharData(htmlParserCtxtPtr ctxt) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
next_char:
|
||||||
in += size;
|
in += size;
|
||||||
avail -= size;
|
avail -= size;
|
||||||
}
|
}
|
||||||
|
|
||||||
next_chunk:
|
next_chunk:
|
||||||
|
if (ncrSize > 0) {
|
||||||
|
skip = ncrSize;
|
||||||
|
in -= ncrSize;
|
||||||
|
|
||||||
|
repl = htmlCodePointToUtf8(cp, utf8Char, &replSize);
|
||||||
|
}
|
||||||
|
|
||||||
if (in > chunk) {
|
if (in > chunk) {
|
||||||
input->cur += in - chunk;
|
input->cur += in - chunk;
|
||||||
htmlCharDataSAXCallback(ctxt, chunk, in - chunk, mode);
|
htmlCharDataSAXCallback(ctxt, chunk, in - chunk, mode);
|
||||||
|
Reference in New Issue
Block a user