STATUS uriDecodeString()

in src/source/Common/AwsV4Signer.c [912:971]


STATUS uriDecodeString(PCHAR pSrc, UINT32 srcLen, PCHAR pDst, PUINT32 pDstLen)
{
    STATUS retStatus = STATUS_SUCCESS;
    UINT32 decodedLen = 0, strLen, remaining, size, decLen = ARRAY_SIZE(URI_ENCODED_FORWARD_SLASH) - 1;
    PCHAR pCurPtr = pSrc, pDec = pDst;
    CHAR ch;

    // Set the source length to max if not specified
    strLen = (srcLen == 0) ? MAX_UINT32 : srcLen;

    // Set the remaining length
    remaining = (pDst == NULL) ? MAX_UINT32 : *pDstLen;

    CHK(pSrc != NULL && pDstLen != NULL, STATUS_NULL_ARG);

    while (((UINT32)(pCurPtr - pSrc) < strLen) && ((ch = *pCurPtr) != '\0')) {
        if (ch == '%') {
            CHK((UINT32)(pCurPtr - pSrc) + decLen <= strLen && *(pCurPtr + 1) != '\0' && *(pCurPtr + 2) != '\0', STATUS_INVALID_ARG);
            if (pDec != NULL) {
                size = remaining;
                CHK_STATUS(hexDecode(pCurPtr + 1, 2, (PBYTE) pDec, &size));
                CHK(size == 1, STATUS_INVALID_ARG);
            }

            size = decLen;
        } else {
            if (pDec != NULL) {
                CHK(remaining > 0, STATUS_NOT_ENOUGH_MEMORY);
                *pDec = ch;
            }

            size = 1;
        }

        pCurPtr += size;
        decodedLen++;
        remaining--;

        if (pDec != NULL) {
            pDec++;
        }
    }

    // Account for the null terminator
    decodedLen++;

    if (pDec != NULL) {
        CHK(remaining > 0, STATUS_NOT_ENOUGH_MEMORY);
        *pDec++ = '\0';
        remaining--;
    }

CleanUp:

    if (pDstLen != NULL) {
        *pDstLen = decodedLen;
    }

    return retStatus;
}