ib_status_t ib_util_decode_url_ex(uint8_t *data_in, size_t dlen_in, size_t *dlen_out, ib_flags_t *result) { IB_FTRACE_INIT(); assert(data_in != NULL); assert(dlen_out != NULL); assert(result != NULL); uint8_t *out = data_in; uint8_t *in = data_in; uint8_t *end = data_in + dlen_in; bool modified = false; while (in < end) { if (*in == '%') { /* Character is a percent sign. */ /* Are there enough bytes available? */ if (in + 2 < end) { char c1 = *(in + 1); char c2 = *(in + 2); if (IS_HEX_CHAR(c1) && IS_HEX_CHAR(c2)) { /* Valid encoding - decode it. */ *out++ = x2c(in + 1); in += 3; modified = true; } else { /* Not a valid encoding, skip this % */ if (in == out) { ++out; ++in; } else { *out++ = *in++; modified = true; } } } else { /* Not enough bytes available, copy the raw bytes. */ if (in == out) { ++out; ++in; } else { *out++ = *in++; modified = true; } } } else { /* Character is not a percent sign. */ if (*in == '+') { *out++ = ' '; modified = true; } else if (out != in) { *out++ = *in; modified = true; } else { ++out; } ++in; } } *dlen_out = (out - data_in); *result = ( (modified == true) ? (IB_STRFLAG_ALIAS | IB_STRFLAG_MODIFIED) : IB_STRFLAG_ALIAS ); IB_FTRACE_RET_STATUS(IB_OK); }
char *urldecode(const char *src, const int src_len, char *dest, int *dest_len) { #define IS_HEX_CHAR(ch) \ ((ch >= '0' && ch <= '9') || \ (ch >= 'a' && ch <= 'f') || \ (ch >= 'A' && ch <= 'F')) #define HEX_VALUE(ch, value) \ if (ch >= '0' && ch <= '9') \ { \ value = ch - '0'; \ } \ else if (ch >= 'a' && ch <= 'f') \ { \ value = ch - 'a' + 10; \ } \ else \ { \ value = ch - 'A' + 10; \ } const unsigned char *pSrc; const unsigned char *pEnd; char *pDest; unsigned char cHigh; unsigned char cLow; int valHigh; int valLow; pDest = dest; pSrc = (unsigned char *)src; pEnd = (unsigned char *)src + src_len; while (pSrc < pEnd) { if (*pSrc == '%' && pSrc + 2 < pEnd) { cHigh = *(pSrc + 1); cLow = *(pSrc + 2); if (IS_HEX_CHAR(cHigh) && IS_HEX_CHAR(cLow)) { HEX_VALUE(cHigh, valHigh) HEX_VALUE(cLow, valLow) *pDest++ = (valHigh << 4) | valLow; pSrc += 3; } else { *pDest++ = *pSrc; pSrc++; } } else if (*pSrc == '+') { *pDest++ = ' '; pSrc++; } else { *pDest++ = *pSrc; pSrc++; } } *pDest = '\0'; *dest_len = pDest - dest; return dest; }
ib_status_t ib_util_decode_url_cow_ex(ib_mpool_t *mp, const uint8_t *data_in, size_t dlen_in, uint8_t **data_out, size_t *dlen_out, ib_flags_t *result) { IB_FTRACE_INIT(); assert(mp != NULL); assert(data_in != NULL); assert(data_out != NULL); assert(dlen_out != NULL); assert(result != NULL); uint8_t *out = NULL; const uint8_t *in = data_in; const uint8_t *end = data_in + dlen_in; *data_out = NULL; while (in < end) { if (*in == '%') { /* Character is a percent sign. */ /* Are there enough bytes available? */ if (in + 2 < end) { char c1 = *(in + 1); char c2 = *(in + 2); if (IS_HEX_CHAR(c1) && IS_HEX_CHAR(c2)) { /* Valid encoding - decode it. */ out = ib_util_copy_on_write(mp, data_in, in, dlen_in, out, data_out, NULL); if (out == NULL) { IB_FTRACE_RET_STATUS(IB_EALLOC); } *out++ = x2c(in + 1); in += 3; } else { /* Not a valid encoding, skip this % */ if (out == NULL) { ++in; } else { *out++ = *in++; } } } else { /* Not enough bytes available, copy the raw bytes. */ if (out == NULL) { ++in; } else { *out++ = *in++; } } } else { /* Character is not a percent sign. */ if (*in == '+') { out = ib_util_copy_on_write(mp, data_in, in, dlen_in, out, data_out, NULL); if (out == NULL) { IB_FTRACE_RET_STATUS(IB_EALLOC); } *out++ = ' '; } else if (out != NULL) { *out++ = *in; } ++in; } } if (out == NULL) { *result = IB_STRFLAG_ALIAS; *data_out = (uint8_t *)data_in; *dlen_out = dlen_in; } else { *result = IB_STRFLAG_NEWBUF | IB_STRFLAG_MODIFIED; *dlen_out = out - *data_out; } IB_FTRACE_RET_STATUS(IB_OK); }