int rtPathFromNative(const char **ppszPath, const char *pszNativePath, const char *pszBasePath)
{
    *ppszPath = NULL;

    int rc = RTOnce(&g_OnceInitPathConv, rtPathConvInitOnce, NULL);
    if (RT_SUCCESS(rc))
    {
        if (g_fPassthruUtf8 || !*pszNativePath)
        {
            size_t cCpsIgnored;
            size_t cchNativePath;
            rc = rtUtf8Length(pszNativePath, RTSTR_MAX, &cCpsIgnored, &cchNativePath);
            if (RT_SUCCESS(rc))
            {
                char *pszPath;
                *ppszPath = pszPath = RTStrAlloc(cchNativePath + 1);
                if (pszPath)
                    memcpy(pszPath, pszNativePath, cchNativePath + 1);
                else
                    rc = VERR_NO_STR_MEMORY;
            }
        }
        else
            rc = rtStrConvert(pszNativePath, strlen(pszNativePath), g_szFsCodeset,
                              (char **)ppszPath, 0, "UTF-8",
                              2, g_enmFsToUtf8Idx);
    }
    NOREF(pszBasePath); /* We don't query the FS for codeset preferences. */
    return rc;
}
Esempio n. 2
0
RTR3DECL(int) RTManifestWriteFilesBuf(void **ppvBuf, size_t *pcbSize, RTDIGESTTYPE enmDigestType, PRTMANIFESTTEST paFiles, size_t cFiles)
{
    /* Validate input */
    AssertPtrReturn(ppvBuf, VERR_INVALID_POINTER);
    AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
    AssertPtrReturn(paFiles, VERR_INVALID_POINTER);
    AssertReturn(cFiles > 0, VERR_INVALID_PARAMETER);

    const char *pcszDigestType;
    switch (enmDigestType)
    {
        case RTDIGESTTYPE_CRC32:  pcszDigestType = "CRC32";  break;
        case RTDIGESTTYPE_CRC64:  pcszDigestType = "CRC64";  break;
        case RTDIGESTTYPE_MD5:    pcszDigestType = "MD5";    break;
        case RTDIGESTTYPE_SHA1:   pcszDigestType = "SHA1";   break;
        case RTDIGESTTYPE_SHA256: pcszDigestType = "SHA256"; break;
        default: return VERR_INVALID_PARAMETER;
    }

    /* Calculate the size necessary for the memory buffer. */
    size_t cbSize = 0;
    size_t cbMaxSize = 0;
    for (size_t i = 0; i < cFiles; ++i)
    {
        size_t cbTmp = strlen(RTPathFilename(paFiles[i].pszTestFile))
                     + strlen(paFiles[i].pszTestDigest)
                     + strlen(pcszDigestType)
                     + 6;
        cbMaxSize = RT_MAX(cbMaxSize, cbTmp);
        cbSize += cbTmp;
    }

    /* Create the memory buffer */
    void *pvBuf = RTMemAlloc(cbSize);
    if (!pvBuf)
        return VERR_NO_MEMORY;

    /* Allocate a temporary string buffer. */
    char *pszTmp = RTStrAlloc(cbMaxSize + 1);
    if (!pszTmp)
    {
        RTMemFree(pvBuf);
        return VERR_NO_MEMORY;
    }
    size_t cbPos = 0;

    for (size_t i = 0; i < cFiles; ++i)
    {
        size_t cch = RTStrPrintf(pszTmp, cbMaxSize + 1, "%s (%s)= %s\n", pcszDigestType, RTPathFilename(paFiles[i].pszTestFile), paFiles[i].pszTestDigest);
        memcpy(&((char*)pvBuf)[cbPos], pszTmp, cch);
        cbPos += cch;
    }
    RTStrFree(pszTmp);

    /* Results */
    *ppvBuf = pvBuf;
    *pcbSize = cbSize;

    return VINF_SUCCESS;
}
RTR3DECL(int)   RTProcQueryUsernameA(RTPROCESS hProcess, char **ppszUser)
{
    /*
     * Validation.
     */
    AssertPtrReturn(ppszUser, VERR_INVALID_POINTER);

    int rc = VINF_SUCCESS;
    size_t cbUser = 0;

    rc = RTProcQueryUsername(hProcess, NULL, cbUser, &cbUser);
    if (rc == VERR_BUFFER_OVERFLOW)
    {
        char *pszUser = (char *)RTStrAlloc(cbUser);
        if (pszUser)
        {
            rc = RTProcQueryUsername(hProcess, pszUser, cbUser, NULL);
            Assert(rc != VERR_BUFFER_OVERFLOW);
            if (RT_SUCCESS(rc))
                *ppszUser = pszUser;
            else
                RTStrFree(pszUser);
        }
        else
            rc = VERR_NO_STR_MEMORY;
    }

    return rc;
}
Esempio n. 4
0
/**
 * A variant of Utf8Str::copyFromN that does not throw any exceptions but
 * returns E_OUTOFMEMORY instead.
 *
 * @param   a_pcszSrc   The source string.
 * @param   a_offSrc    Start offset to copy from.
 * @param   a_cchSrc    The source string.
 * @returns S_OK or E_OUTOFMEMORY.
 *
 * @remarks This calls cleanup() first, so the caller doesn't have to. (Saves
 *          code space.)
 */
HRESULT Utf8Str::copyFromExNComRC(const char *a_pcszSrc, size_t a_offSrc, size_t a_cchSrc)
{
    cleanup();
    if (a_cchSrc)
    {
        m_psz = RTStrAlloc(a_cchSrc + 1);
        if (RT_LIKELY(m_psz))
        {
            m_cch = a_cchSrc;
            m_cbAllocated = a_cchSrc + 1;
            memcpy(m_psz, a_pcszSrc + a_offSrc, a_cchSrc);
            m_psz[a_cchSrc] = '\0';
        }
        else
        {
            m_cch = 0;
            m_cbAllocated = 0;
            return E_OUTOFMEMORY;
        }
    }
    else
    {
        m_cch = 0;
        m_cbAllocated = 0;
        m_psz = NULL;
    }
    return S_OK;
}
Esempio n. 5
0
static char *rtUriPercentEncodeN(const char *pszString, size_t cchMax)
{
    if (!pszString)
        return NULL;

    int rc = VINF_SUCCESS;

    size_t cbLen = RT_MIN(strlen(pszString), cchMax);
    /* The new string can be max 3 times in size of the original string. */
    char *pszNew = RTStrAlloc(cbLen * 3 + 1);
    if (!pszNew)
        return NULL;

    char *pszRes = NULL;
    size_t iIn = 0;
    size_t iOut = 0;
    while (iIn < cbLen)
    {
        if (URI_EXCLUDED(pszString[iIn]))
        {
            char szNum[3] = { 0, 0, 0 };
            RTStrFormatU8(&szNum[0], 3, pszString[iIn++], 16, 2, 2, RTSTR_F_CAPITAL | RTSTR_F_ZEROPAD);
            pszNew[iOut++] = '%';
            pszNew[iOut++] = szNum[0];
            pszNew[iOut++] = szNum[1];
        }
        else
            pszNew[iOut++] = pszString[iIn++];
    }
    if (RT_SUCCESS(rc))
    {
        pszNew[iOut] = '\0';
        if (iOut != iIn)
        {
            /* If the source and target strings have different size, recreate
             * the target string with the correct size. */
            pszRes = RTStrDupN(pszNew, iOut);
            RTStrFree(pszNew);
        }
        else
            pszRes = pszNew;
    }
    else
        RTStrFree(pszNew);

    return pszRes;
}
Esempio n. 6
0
RTR3DECL(int) RTManifestWriteFilesBuf(void **ppvBuf, size_t *pcbSize, PRTMANIFESTTEST paFiles, size_t cFiles)
{
    /* Validate input */
    AssertPtrReturn(ppvBuf, VERR_INVALID_POINTER);
    AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
    AssertPtrReturn(paFiles, VERR_INVALID_POINTER);
    AssertReturn(cFiles > 0, VERR_INVALID_PARAMETER);

    /* Calculate the size necessary for the memory buffer. */
    size_t cbSize = 0;
    size_t cbMaxSize = 0;
    for (size_t i = 0; i < cFiles; ++i)
    {
        size_t cbTmp = strlen(RTPathFilename(paFiles[i].pszTestFile)) + strlen(paFiles[i].pszTestDigest) + 10;
        cbMaxSize = RT_MAX(cbMaxSize, cbTmp);
        cbSize += cbTmp;
    }

    /* Create the memory buffer */
    void *pvBuf = RTMemAlloc(cbSize);
    if (!pvBuf)
        return VERR_NO_MEMORY;

    /* Allocate a temporary string buffer. */
    char * pszTmp = RTStrAlloc(cbMaxSize + 1);
    size_t cbPos = 0;
    for (size_t i = 0; i < cFiles; ++i)
    {
        size_t cch = RTStrPrintf(pszTmp, cbMaxSize + 1, "SHA1 (%s)= %s\n", RTPathFilename(paFiles[i].pszTestFile), paFiles[i].pszTestDigest);
        memcpy(&((char*)pvBuf)[cbPos], pszTmp, cch);
        cbPos += cch;
    }
    RTStrFree(pszTmp);

    /* Results */
    *ppvBuf = pvBuf;
    *pcbSize = cbSize;

    return VINF_SUCCESS;
}
Esempio n. 7
0
/**
 * Basic API checks.
 * We'll return if any of these fails.
 */
static void tst1(void)
{
    RTTestISub("Basics");
    char *psz;
    int rc = VINF_SUCCESS;

    /* RTStrAlloc */
    RTTESTI_CHECK(psz = RTStrAlloc(0));
    RTTESTI_CHECK(psz && !*psz);
    RTStrFree(psz);

    RTTESTI_CHECK(psz = RTStrAlloc(1));
    RTTESTI_CHECK(psz && !*psz);
    RTStrFree(psz);

    RTTESTI_CHECK(psz = RTStrAlloc(128));
    RTTESTI_CHECK(psz && !*psz);
    RTStrFree(psz);

    /* RTStrAllocEx */
    psz = (char*)"asdfasdf";
    RTTESTI_CHECK_RC(RTStrAllocEx(&psz, 0), VINF_SUCCESS);
    RTTESTI_CHECK(psz && !*psz);
    RTStrFree(psz);

    RTTESTI_CHECK_RC(RTStrAllocEx(&psz, 1), VINF_SUCCESS);
    RTTESTI_CHECK(psz && !*psz);
    RTStrFree(psz);

    RTTESTI_CHECK_RC(RTStrAllocEx(&psz, 128), VINF_SUCCESS);
    RTTESTI_CHECK(psz && !*psz);
    RTStrFree(psz);

    /* RTStrRealloc */
    psz = NULL;
    RTTESTI_CHECK_RC(RTStrRealloc(&psz, 10), VINF_SUCCESS);
    RTTESTI_CHECK(psz && !psz[0]);
    RTTESTI_CHECK(psz && !psz[9]);
    RTStrFree(psz);

    psz = NULL;
    RTTESTI_CHECK_RC(RTStrRealloc(&psz, 0), VINF_SUCCESS);
    RTTESTI_CHECK(!psz);

    psz = NULL;
    RTTESTI_CHECK_RC(RTStrRealloc(&psz, 128), VINF_SUCCESS);
    RTTESTI_CHECK(psz && !psz[0]);
    RTTESTI_CHECK(psz && !psz[127]);
    if (psz)
    {
        memset(psz, 'a', 127);
        RTTESTI_CHECK_RC(rc = RTStrRealloc(&psz, 160), VINF_SUCCESS);
        if (RT_SUCCESS(rc) && psz)
        {
            RTTESTI_CHECK(!psz[127]);
            RTTESTI_CHECK(!psz[159]);
            RTTESTI_CHECK(ASMMemIsAll8(psz, 127, 'a') == NULL);
            memset(psz, 'b', 159);

            RTTESTI_CHECK_RC(rc = RTStrRealloc(&psz, 79), VINF_SUCCESS);
            if (RT_SUCCESS(rc))
            {
                RTTESTI_CHECK(!psz[78]);
                RTTESTI_CHECK(ASMMemIsAll8(psz, 78, 'b') == NULL);

                RTTESTI_CHECK_RC(rc = RTStrRealloc(&psz, 0), VINF_SUCCESS);
                RTTESTI_CHECK(!psz);
            }
        }
    }
    RTStrFree(psz);

    /* RTStrDup */
    RTTESTI_CHECK(psz = RTStrDup(""));
    RTTESTI_CHECK(psz && *psz == '\0');
    RTStrFree(psz);

    RTTESTI_CHECK(psz = RTStrDup("abcdefghijklmnop"));
    RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnop"));
    RTStrFree(psz);

    /* RTStrDupEx */
    psz = NULL;
    RTTESTI_CHECK_RC(RTStrDupEx(&psz, ""), VINF_SUCCESS);
    RTTESTI_CHECK(RT_FAILURE(rc) || *psz == '\0');
    if (RT_SUCCESS(rc))
        RTStrFree(psz);

    psz = (char*)"asdfasdfasdfasdf";
    RTTESTI_CHECK_RC(rc = RTStrDupEx(&psz, "abcdefghijklmnop"), VINF_SUCCESS);
    RTTESTI_CHECK(RT_FAILURE(rc) || !RTStrCmp(psz, "abcdefghijklmnop"));
    if (RT_SUCCESS(rc))
        RTStrFree(psz);

    /* RTStrDupN */
    RTTESTI_CHECK(psz = RTStrDupN("abcdefg", 3));
    RTTESTI_CHECK(!RTStrCmp(psz, "abc"));
    RTStrFree(psz);

    RTTESTI_CHECK(psz = RTStrDupN("abc", 100000));
    RTTESTI_CHECK(!RTStrCmp(psz, "abc"));
    RTStrFree(psz);

    RTTESTI_CHECK(psz = RTStrDupN("abc", 0));
    RTTESTI_CHECK(psz && *psz == '\0');
    RTStrFree(psz);

    /* RTStrAAppend */
    RTTESTI_CHECK(psz = RTStrDup("abc"));
    RTTESTI_CHECK_RC(RTStrAAppend(&psz, "def"), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abcdef"));
    RTStrFree(psz);

    RTTESTI_CHECK(psz = RTStrDup("abc"));
    RTTESTI_CHECK_RC(RTStrAAppend(&psz, ""), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abc"));
    RTTESTI_CHECK_RC(RTStrAAppend(&psz, NULL), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abc"));
    RTStrFree(psz);

    psz = NULL;
    RTTESTI_CHECK_RC(RTStrAAppend(&psz, "xyz"), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "xyz"));
    RTStrFree(psz);

    /* RTStrAAppendN */
    RTTESTI_CHECK(psz = RTStrDup("abc"));
    RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "def", 1), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abcd"));
    RTStrFree(psz);

    RTTESTI_CHECK(psz = RTStrDup("abc"));
    RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "", 0), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abc"));
    RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "", RTSTR_MAX), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abc"));
    RTTESTI_CHECK_RC(RTStrAAppendN(&psz, NULL, 0), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abc"));
    RTStrFree(psz);

    psz = NULL;
    RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "abc", 2), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "ab"));
    RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "cdefghijklm", 1), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abc"));
    RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "defghijklm", RTSTR_MAX), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklm"));
    RTStrFree(psz);

    /* RTStrAAppendExN / RTStrAAppendExNV */
    psz = NULL;
    RTTESTI_CHECK_RC(RTStrAAppendExN(&psz, 5, "a", (size_t)1, "bc", (size_t)1, "cdefg", RTSTR_MAX, "hijkl", (size_t)2, "jklmnopqrstuvwxyz", RTSTR_MAX), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnopqrstuvwxyz"));
    RTTESTI_CHECK_RC(RTStrAAppendExN(&psz, 0), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnopqrstuvwxyz"));
    RTTESTI_CHECK_RC(RTStrAAppendExN(&psz, 2, NULL, (size_t)0, "", (size_t)0), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnopqrstuvwxyz"));
    RTTESTI_CHECK_RC(RTStrAAppendExN(&psz, 1, "-", (size_t)1), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnopqrstuvwxyz-"));
    RTStrFree(psz);

    /* RTStrATruncate */
    psz = NULL;
    RTTESTI_CHECK_RC(RTStrATruncate(&psz, 0), VINF_SUCCESS);
    RTTESTI_CHECK(!psz);

    RTTESTI_CHECK(psz = RTStrDup(""));
    RTTESTI_CHECK_RC(RTStrATruncate(&psz, 0), VINF_SUCCESS);
    RTStrFree(psz);

    RTTESTI_CHECK(psz = RTStrDup("1234567890"));
    RTTESTI_CHECK_RC(RTStrATruncate(&psz, 5), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "12345"));
    RTStrFree(psz);

    psz = NULL;
    for (uint32_t i = 0; i < 128; i++)
        RTTESTI_CHECK_RC_RETV(RTStrAAppend(&psz, "abcdefghijklmnopqrstuvwxyz"), VINF_SUCCESS);
    RTTESTI_CHECK_RC(RTStrATruncate(&psz, sizeof("abcdefghijklmnopqrstuvwxyz") - 1), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnopqrstuvwxyz"));
    RTTESTI_CHECK_RC(RTStrATruncate(&psz, 6), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "abcdef"));
    RTTESTI_CHECK_RC(RTStrATruncate(&psz, 1), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, "a"));
    RTTESTI_CHECK_RC(RTStrATruncate(&psz, 0), VINF_SUCCESS);
    RTTESTI_CHECK(!RTStrCmp(psz, ""));
    RTStrFree(psz);

}
Esempio n. 8
0
RTDECL(int) RTGetOptArgvToString(char **ppszCmdLine, const char * const *papszArgv, uint32_t fFlags)
{
    AssertReturn(!(fFlags & ~RTGETOPTARGV_CNV_QUOTE_MASK), VERR_INVALID_PARAMETER);

#define PUT_CH(ch) \
        if (RT_UNLIKELY(off + 1 >= cbCmdLineAlloc)) { \
            rc = rtGetOptArgvToStringGrow(&pszCmdLine, &cbCmdLineAlloc, 1); \
            if (RT_FAILURE(rc)) \
                break; \
        } \
        pszCmdLine[off++] = (ch)

#define PUT_PSZ(psz, cch) \
        if (RT_UNLIKELY(off + (cch) >= cbCmdLineAlloc)) { \
            rc = rtGetOptArgvToStringGrow(&pszCmdLine, &cbCmdLineAlloc, (cch)); \
            if (RT_FAILURE(rc)) \
                break; \
        } \
        memcpy(&pszCmdLine[off], (psz), (cch)); \
        off += (cch);
#define PUT_SZ(sz)  PUT_PSZ(sz, sizeof(sz) - 1)

    /*
     * Take the realloc approach, it requires less code and is probably more
     * efficient than figuring out the size first.
     */
    int     rc              = VINF_SUCCESS;
    size_t  off             = 0;
    size_t  cbCmdLineAlloc  = 256;
    char   *pszCmdLine      = RTStrAlloc(256);
    if (!pszCmdLine)
        return VERR_NO_STR_MEMORY;

    for (size_t i = 0; papszArgv[i]; i++)
    {
        if (i > 0)
        {
            PUT_CH(' ');
        }

        /* does it need quoting? */
        const char *pszArg = papszArgv[i];
        size_t      cchArg;
        if (!rtGetOpArgvRequiresQuoting(pszArg, fFlags, &cchArg))
        {
            /* No quoting needed, just append the argument. */
            PUT_PSZ(pszArg, cchArg);
        }
        else if ((fFlags & RTGETOPTARGV_CNV_QUOTE_MASK) == RTGETOPTARGV_CNV_QUOTE_MS_CRT)
        {
            /*
             * Microsoft CRT quoting.  Quote the whole argument in double
             * quotes to make it easier to read and code.
             */
            PUT_CH('"');
            char ch;
            while ((ch = *pszArg++))
            {
                if (   ch == '\\'
                        && rtGetOptArgvMsCrtIsSlashQuote(pszArg))
                {
                    PUT_SZ("\\\\");
                }
                else if (ch == '"')
                {
                    PUT_SZ("\\\"");
                }
                else
                {
                    PUT_CH(ch);
                }
            }
            PUT_CH('"');
        }
        else
        {
            /*
             * Bourne Shell quoting.  Quote the whole thing in single quotes
             * and use double quotes for any single quote chars.
             */
            PUT_CH('\'');
            char ch;
            while ((ch = *pszArg++))
            {
                if (ch == '\'')
                {
                    PUT_SZ("'\"'\"'");
                }
                else
                {
                    PUT_CH(ch);
                }
            }
            PUT_CH('\'');
        }
    }

    /* Set return value / cleanup. */
    if (RT_SUCCESS(rc))
    {
        pszCmdLine[off] = '\0';
        *ppszCmdLine    = pszCmdLine;
    }
    else
        RTStrFree(pszCmdLine);
#undef PUT_SZ
#undef PUT_PSZ
#undef PUT_CH
    return rc;
}
Esempio n. 9
0
RTDECL(int) RTUriFilePathEx(const char *pszUri, uint32_t fPathStyle, char **ppszPath, size_t cbPath, size_t *pcchPath)
{
    /*
     * Validate and adjust input.
     */
    if (pcchPath)
    {
        AssertPtrReturn(pcchPath, VERR_INVALID_POINTER);
        *pcchPath = ~(size_t)0;
    }
    AssertPtrReturn(ppszPath, VERR_INVALID_POINTER);
    AssertReturn(!(fPathStyle & ~RTPATH_STR_F_STYLE_MASK) && fPathStyle != RTPATH_STR_F_STYLE_RESERVED, VERR_INVALID_FLAGS);
    if (fPathStyle == RTPATH_STR_F_STYLE_HOST)
        fPathStyle = RTPATH_STYLE;
    AssertPtrReturn(pszUri, VERR_INVALID_POINTER);

    /*
     * Check that this is a file URI.
     */
    if (RTStrNICmp(pszUri, RT_STR_TUPLE("file:")) == 0)
    { /* likely */ }
    else
        return VERR_URI_NOT_FILE_SCHEME;

    /*
     * We may have a number of variations here, mostly thanks to
     * various windows software.  First the canonical variations:
     *     - file:///C:/Windows/System32/kernel32.dll
     *     - file:///C|/Windows/System32/kernel32.dll
     *     - file:///C:%5CWindows%5CSystem32%5Ckernel32.dll
     *     - file://localhost/C:%5CWindows%5CSystem32%5Ckernel32.dll
     *     - file://cifsserver.dev/systemshare%5CWindows%5CSystem32%5Ckernel32.dll
     *     - file://cifsserver.dev:139/systemshare%5CWindows%5CSystem32%5Ckernel32.dll  (not quite sure here, but whatever)
     *
     * Legacy variant without any slashes after the schema:
     *     - file:C:/Windows/System32/kernel32.dll
     *     - file:C|/Windows/System32%5Ckernel32.dll
     *     - file:~/.bashrc
     *            \--path-/
     *
     * Legacy variant with exactly one slashes after the schema:
     *     - file:/C:/Windows/System32%5Ckernel32.dll
     *     - file:/C|/Windows/System32/kernel32.dll
     *     - file:/usr/bin/env
     *            \---path---/
     *
     * Legacy variant with two slashes after the schema and an unescaped DOS path:
     *     - file://C:/Windows/System32\kernel32.dll (**)
     *     - file://C|/Windows/System32\kernel32.dll
     *                \---path---------------------/
     *              -- authority, with ':' as non-working port separator
     *
     * Legacy variant with exactly four slashes after the schema and an unescaped DOS path.
     *     - file:////C:/Windows\System32\user32.dll
     *
     * Legacy variant with four or more slashes after the schema and an unescaped UNC path:
     *     - file:////cifsserver.dev/systemshare/System32%\kernel32.dll
     *     - file://///cifsserver.dev/systemshare/System32\kernel32.dll
     *              \---path--------------------------------------------/
     *
     * The the two unescaped variants shouldn't be handed to rtUriParse, which
     * is good as we cannot actually handle the one marked by (**).  So, handle
     * those two special when parsing.
     */
    RTURIPARSED Parsed;
    int         rc;
    size_t      cSlashes = 0;
    while (pszUri[5 + cSlashes] == '/')
        cSlashes++;
    if (   (cSlashes == 2 || cSlashes == 4)
        && RT_C_IS_ALPHA(pszUri[5 + cSlashes])
        && (pszUri[5 + cSlashes + 1] == ':' || pszUri[5 + cSlashes + 1] == '|'))
    {
        RT_ZERO(Parsed); /* RTURIPARSED_F_CONTAINS_ESCAPED_CHARS is now clear. */
        Parsed.offPath = 5 + cSlashes;
        Parsed.cchPath = strlen(&pszUri[Parsed.offPath]);
        rc = RTStrValidateEncoding(&pszUri[Parsed.offPath]);
    }
    else if (cSlashes >= 4)
    {
        RT_ZERO(Parsed);
        Parsed.fFlags  = cSlashes > 4 ? RTURIPARSED_F_CONTAINS_ESCAPED_CHARS : 0;
        Parsed.offPath = 5 + cSlashes - 2;
        Parsed.cchPath = strlen(&pszUri[Parsed.offPath]);
        rc = RTStrValidateEncoding(&pszUri[Parsed.offPath]);
    }
    else
        rc = rtUriParse(pszUri, &Parsed);
    if (RT_SUCCESS(rc))
    {
        /*
         * Ignore localhost as hostname (it's implicit).
         */
        static char const s_szLocalhost[] = "localhost";
        if (    Parsed.cchAuthorityHost == sizeof(s_szLocalhost) - 1U
            &&  RTStrNICmp(&pszUri[Parsed.offAuthorityHost], RT_STR_TUPLE(s_szLocalhost)) == 0)
        {
            Parsed.cchAuthorityHost = 0;
            Parsed.cchAuthority     = 0;
        }

        /*
         * Ignore leading path slash/separator if we detect a DOS drive letter
         * and we don't have a host name.
         */
        if (   Parsed.cchPath >= 3
            && Parsed.cchAuthorityHost    == 0
            && pszUri[Parsed.offPath]     == '/'           /* Leading path slash/separator. */
            && (   pszUri[Parsed.offPath + 2] == ':'       /* Colon after drive letter. */
                || pszUri[Parsed.offPath + 2] == '|')      /* Colon alternative. */
            && RT_C_IS_ALPHA(pszUri[Parsed.offPath + 1]) ) /* Drive letter. */
        {
            Parsed.offPath++;
            Parsed.cchPath--;
        }

        /*
         * Calculate the size of the encoded result.
         *
         * Since we're happily returning "C:/Windows/System32/kernel.dll"
         * style paths when the caller requested UNIX style paths, we will
         * return straight UNC paths too ("//cifsserver/share/dir/file").
         */
        size_t cchDecodedHost = 0;
        size_t cbResult;
        if (Parsed.fFlags & RTURIPARSED_F_CONTAINS_ESCAPED_CHARS)
        {
            cchDecodedHost = rtUriCalcDecodedLength(&pszUri[Parsed.offAuthorityHost], Parsed.cchAuthorityHost);
            cbResult = cchDecodedHost + rtUriCalcDecodedLength(&pszUri[Parsed.offPath], Parsed.cchPath) + 1;
        }
        else
        {
            cchDecodedHost = 0;
            cbResult = Parsed.cchAuthorityHost + Parsed.cchPath + 1;
        }
        if (pcchPath)
            *pcchPath = cbResult - 1;
        if (cbResult > 1)
        {
            /*
             * Prepare the necessary buffer space for the result.
             */
            char  *pszDst;
            char  *pszFreeMe = NULL;
            if (!cbPath || *ppszPath == NULL)
            {
                cbPath = RT_MAX(cbPath, cbResult);
                *ppszPath = pszFreeMe = pszDst = RTStrAlloc(cbPath);
                AssertReturn(pszDst, VERR_NO_STR_MEMORY);
            }
            else if (cbResult <= cbPath)
                pszDst = *ppszPath;
            else
                return VERR_BUFFER_OVERFLOW;

            /*
             * Compose the result.
             */
            if (Parsed.fFlags & RTURIPARSED_F_CONTAINS_ESCAPED_CHARS)
            {
                rc = rtUriDecodeIntoBuffer(&pszUri[Parsed.offAuthorityHost],Parsed.cchAuthorityHost,
                                           pszDst, cchDecodedHost + 1);
                Assert(RT_SUCCESS(rc) && strlen(pszDst) == cchDecodedHost);
                if (RT_SUCCESS(rc))
                    rc = rtUriDecodeIntoBuffer(&pszUri[Parsed.offPath], Parsed.cchPath,
                                               &pszDst[cchDecodedHost], cbResult - cchDecodedHost);
                Assert(RT_SUCCESS(rc) && strlen(pszDst) == cbResult - 1);
            }
            else
            {
                memcpy(pszDst, &pszUri[Parsed.offAuthorityHost], Parsed.cchAuthorityHost);
                memcpy(&pszDst[Parsed.cchAuthorityHost], &pszUri[Parsed.offPath], Parsed.cchPath);
                pszDst[cbResult - 1] = '\0';
            }
            if (RT_SUCCESS(rc))
            {
                /*
                 * Convert colon DOS driver letter colon alternative.
                 * We do this regardless of the desired path style.
                 */
                if (   RT_C_IS_ALPHA(pszDst[0])
                    && pszDst[1] == '|')
                    pszDst[1] = ':';

                /*
                 * Fix slashes.
                 */
                if (fPathStyle == RTPATH_STR_F_STYLE_DOS)
                    RTPathChangeToDosSlashes(pszDst, true);
                else if (fPathStyle == RTPATH_STR_F_STYLE_UNIX)
                    RTPathChangeToUnixSlashes(pszDst, true); /** @todo not quite sure how this actually makes sense... */
                else
                    AssertFailed();
                return rc;
            }

            /* bail out */
            RTStrFree(pszFreeMe);
        }
        else
            rc = VERR_PATH_ZERO_LENGTH;
    }
    return rc;
}
Esempio n. 10
0
RTDECL(int) RTUriFileCreateEx(const char *pszPath, uint32_t fPathStyle, char **ppszUri, size_t cbUri, size_t *pcchUri)
{
    /*
     * Validate and adjust input. (RTPathParse check pszPath out for us)
     */
    if (pcchUri)
    {
        AssertPtrReturn(pcchUri, VERR_INVALID_POINTER);
        *pcchUri = ~(size_t)0;
    }
    AssertPtrReturn(ppszUri, VERR_INVALID_POINTER);
    AssertReturn(!(fPathStyle & ~RTPATH_STR_F_STYLE_MASK) && fPathStyle != RTPATH_STR_F_STYLE_RESERVED, VERR_INVALID_FLAGS);
    if (fPathStyle == RTPATH_STR_F_STYLE_HOST)
        fPathStyle = RTPATH_STYLE;

    /*
     * Let the RTPath code parse the stuff (no reason to duplicate path parsing
     * and get it slightly wrong here).
     */
    RTPATHPARSED ParsedPath;
    int rc = RTPathParse(pszPath, &ParsedPath, sizeof(ParsedPath), fPathStyle);
    if (RT_SUCCESS(rc) || rc == VERR_BUFFER_OVERFLOW)
    {
        /* Skip leading slashes. */
        if (ParsedPath.fProps & RTPATH_PROP_ROOT_SLASH)
        {
            if (fPathStyle == RTPATH_STR_F_STYLE_DOS)
                while (pszPath[0] == '/' || pszPath[0] == '\\')
                    pszPath++;
            else
                while (pszPath[0] == '/')
                    pszPath++;
        }
        const size_t cchPath = strlen(pszPath);

        /*
         * Calculate the encoded length and figure destination buffering.
         */
        static const char s_szPrefix[] = "file:///";
        size_t const      cchPrefix    = sizeof(s_szPrefix) - (ParsedPath.fProps & RTPATH_PROP_UNC ? 2 : 1);
        size_t cchEncoded = rtUriCalcEncodedLength(pszPath, cchPath, fPathStyle != RTPATH_STR_F_STYLE_DOS);

        if (pcchUri)
            *pcchUri = cchEncoded;

        char  *pszDst;
        char  *pszFreeMe = NULL;
        if (!cbUri || *ppszUri == NULL)
        {
            cbUri = RT_MAX(cbUri, cchPrefix + cchEncoded + 1);
            *ppszUri = pszFreeMe = pszDst = RTStrAlloc(cbUri);
            AssertReturn(pszDst, VERR_NO_STR_MEMORY);
        }
        else if (cchEncoded < cbUri)
            pszDst = *ppszUri;
        else
            return VERR_BUFFER_OVERFLOW;

        /*
         * Construct the URI.
         */
        memcpy(pszDst, s_szPrefix, cchPrefix);
        pszDst[cchPrefix] = '\0';
        rc = rtUriEncodeIntoBuffer(pszPath, cchPath, fPathStyle != RTPATH_STR_F_STYLE_DOS, &pszDst[cchPrefix], cbUri - cchPrefix);
        if (RT_SUCCESS(rc))
        {
            Assert(strlen(pszDst) == cbUri - 1);
            if (fPathStyle == RTPATH_STR_F_STYLE_DOS)
                RTPathChangeToUnixSlashes(pszDst, true /*fForce*/);
            return VINF_SUCCESS;
        }

        AssertRC(rc); /* Impossible! rtUriCalcEncodedLength or something above is busted! */
        if (pszFreeMe)
            RTStrFree(pszFreeMe);
    }
    return rc;
}
Esempio n. 11
0
RTDECL(char *) RTUriCreate(const char *pszScheme, const char *pszAuthority, const char *pszPath, const char *pszQuery,
                           const char *pszFragment)
{
    if (!pszScheme) /* Scheme is minimum requirement */
        return NULL;

    char *pszResult = 0;
    char *pszAuthority1 = 0;
    char *pszPath1 = 0;
    char *pszQuery1 = 0;
    char *pszFragment1 = 0;

    do
    {
        /* Create the percent encoded strings and calculate the necessary uri
         * length. */
        size_t cbSize = strlen(pszScheme) + 1 + 1; /* plus zero byte */
        if (pszAuthority)
        {
            pszAuthority1 = rtUriPercentEncodeN(pszAuthority, RTSTR_MAX);
            if (!pszAuthority1)
                break;
            cbSize += strlen(pszAuthority1) + 2;
        }
        if (pszPath)
        {
            pszPath1 = rtUriPercentEncodeN(pszPath, RTSTR_MAX);
            if (!pszPath1)
                break;
            cbSize += strlen(pszPath1);
        }
        if (pszQuery)
        {
            pszQuery1 = rtUriPercentEncodeN(pszQuery, RTSTR_MAX);
            if (!pszQuery1)
                break;
            cbSize += strlen(pszQuery1) + 1;
        }
        if (pszFragment)
        {
            pszFragment1 = rtUriPercentEncodeN(pszFragment, RTSTR_MAX);
            if (!pszFragment1)
                break;
            cbSize += strlen(pszFragment1) + 1;
        }

        char *pszTmp = pszResult = (char *)RTStrAlloc(cbSize);
        if (!pszResult)
            break;
        RT_BZERO(pszTmp, cbSize);

        /* Compose the target uri string. */
        RTStrCatP(&pszTmp, &cbSize, pszScheme);
        RTStrCatP(&pszTmp, &cbSize, ":");
        if (pszAuthority1)
        {
            RTStrCatP(&pszTmp, &cbSize, "//");
            RTStrCatP(&pszTmp, &cbSize, pszAuthority1);
        }
        if (pszPath1)
        {
            RTStrCatP(&pszTmp, &cbSize, pszPath1);
        }
        if (pszQuery1)
        {
            RTStrCatP(&pszTmp, &cbSize, "?");
            RTStrCatP(&pszTmp, &cbSize, pszQuery1);
        }
        if (pszFragment1)
        {
            RTStrCatP(&pszTmp, &cbSize, "#");
            RTStrCatP(&pszTmp, &cbSize, pszFragment1);
        }
    } while (0);

    /* Cleanup */
    if (pszAuthority1)
        RTStrFree(pszAuthority1);
    if (pszPath1)
        RTStrFree(pszPath1);
    if (pszQuery1)
        RTStrFree(pszQuery1);
    if (pszFragment1)
        RTStrFree(pszFragment1);

    return pszResult;
}
Esempio n. 12
0
static char *rtUriPercentDecodeN(const char *pszString, size_t cchString)
{
    AssertPtrReturn(pszString, NULL);
    AssertReturn(memchr(pszString, '\0', cchString) == NULL, NULL);

    /*
     * The new string can only get smaller, so use the input length as a
     * staring buffer size.
     */
    char *pszDecoded = RTStrAlloc(cchString + 1);
    if (pszDecoded)
    {
        /*
         * Knowing that the pszString itself is valid UTF-8, we only have to
         * validate the escape sequences.
         */
        size_t      cchLeft = cchString;
        char const *pchSrc  = pszString;
        char       *pchDst  = pszDecoded;
        while (cchLeft > 0)
        {
            const char *pchPct = (const char *)memchr(pchSrc, '%', cchLeft);
            if (pchPct)
            {
                size_t cchBefore = pchPct - pchSrc;
                if (cchBefore)
                {
                    memcpy(pchDst, pchSrc, cchBefore);
                    pchDst  += cchBefore;
                    pchSrc  += cchBefore;
                    cchLeft -= cchBefore;
                }

                char chHigh, chLow;
                if (   cchLeft >= 3
                    && RT_C_IS_XDIGIT(chHigh = pchSrc[1])
                    && RT_C_IS_XDIGIT(chLow  = pchSrc[2]))
                {
                    uint8_t b = RT_C_IS_DIGIT(chHigh) ? chHigh - '0' : (chHigh & ~0x20) - 'A' + 10;
                    b <<= 4;
                    b |= RT_C_IS_DIGIT(chLow) ? chLow - '0' : (chLow & ~0x20) - 'A' + 10;
                    *pchDst++ = (char)b;
                    pchSrc  += 3;
                    cchLeft -= 3;
                }
                else
                {
                    AssertFailed();
                    *pchDst++ = *pchSrc++;
                    cchLeft--;
                }
            }
            else
            {
                memcpy(pchDst, pchSrc, cchLeft);
                pchDst += cchLeft;
                pchSrc += cchLeft;
                cchLeft = 0;
                break;
            }
        }

        *pchDst = '\0';

        /*
         * If we've got lof space room in the result string, reallocate it.
         */
        size_t cchDecoded = pchDst - pszDecoded;
        Assert(cchDecoded <= cchString);
        if (cchString - cchDecoded > 64)
            RTStrRealloc(&pszDecoded, cchDecoded + 1);
    }
    return pszDecoded;
}