| 482 | } |
| 483 | |
| 484 | void fxDecodeURI(txMachine* the, txString theSet) |
| 485 | { |
| 486 | txString src; |
| 487 | txInteger length; |
| 488 | txInteger c, d; |
| 489 | const txUTF8Sequence *sequence; |
| 490 | txInteger size; |
| 491 | txString dst; |
| 492 | |
| 493 | src = fxToString(the, mxArgv(0)); |
| 494 | length = 0; |
| 495 | while ((c = c_read8(src++))) { |
| 496 | if (c == '%') { |
| 497 | if (!fxParseHexEscape(&src, &d)) |
| 498 | mxURIError("invalid URI"); |
| 499 | if ((d < 128) && c_read8(theSet + d)) |
| 500 | length += 3; |
| 501 | else { |
| 502 | for (sequence = gxUTF8Sequences; sequence->size; sequence++) { |
| 503 | if ((d & sequence->cmask) == sequence->cval) |
| 504 | break; |
| 505 | } |
| 506 | if (!sequence->size) |
| 507 | mxURIError("invalid URI"); |
| 508 | size = sequence->size - 1; |
| 509 | while (size > 0) { |
| 510 | c = c_read8(src++); |
| 511 | if (c != '%') |
| 512 | mxURIError("invalid URI"); |
| 513 | if (!fxParseHexEscape(&src, &c)) |
| 514 | mxURIError("invalid URI"); |
| 515 | if ((c & 0xC0) != 0x80) |
| 516 | mxURIError("invalid URI"); |
| 517 | d = (d << 6) | (c & 0x3F); |
| 518 | size--; |
| 519 | } |
| 520 | d &= sequence->lmask; |
| 521 | if (sequence != gxUTF8Sequences) { |
| 522 | if ((sequence[-1].lmask >= (txU4)d) || ((d >= 0xD800) & (d <= 0xDFFF)) || (d >= 0x110000)) |
| 523 | mxURIError("invalid URI"); |
| 524 | } |
| 525 | |
| 526 | length += mxStringByteLength(d); |
| 527 | } |
| 528 | } |
| 529 | else |
| 530 | length += 1; |
| 531 | } |
| 532 | length += 1; |
| 533 | if (length == (src - mxArgv(0)->value.string)) { |
| 534 | mxResult->value.string = mxArgv(0)->value.string; |
| 535 | mxResult->kind = mxArgv(0)->kind; |
| 536 | return; |
| 537 | } |
| 538 | mxResult->value.string = fxNewChunk(the, length); |
| 539 | mxResult->kind = XS_STRING_KIND; |
| 540 | src = mxArgv(0)->value.string; |
| 541 | dst = mxResult->value.string; |
no test coverage detected