uri.cpp revision f6c638878573ea59ed64c4c21efcbef470c9a58b
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * IPRT - Uniform Resource Identifier handling.
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * Copyright (C) 2011 Oracle Corporation
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * available from http://www.virtualbox.org. This file is free software;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * you can redistribute it and/or modify it under the terms of the GNU
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * General Public License (GPL) as published by the Free Software
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * The contents of this file may alternatively be used under the terms
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * of the Common Development and Distribution License Version 1.0
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * VirtualBox OSE distribution, in which case the provisions of the
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * CDDL are applicable instead of those of the GPL.
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * You may elect to license modified versions of this file under the
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * terms and conditions of either the GPL or the CDDL or both.
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync/*******************************************************************************
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync* Header Files *
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync*******************************************************************************/
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync/* General URI format:
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync foo://example.com:8042/over/there?name=ferret#nose
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync \_/ \______________/\_________/ \_________/ \__/
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync scheme authority path query fragment
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync | _____________________|__
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync urn:example:animal:ferret:nose
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync/*******************************************************************************
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync* Private RTUri helper *
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync*******************************************************************************/
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync/* The following defines characters which have to be % escaped:
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync control = 00-1F
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync space = ' '
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync delims = '<' , '>' , '#' , '%' , '"'
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync unwise = '{' , '}' , '|' , '\' , '^' , '[' , ']' , '`'
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncstatic char *rtUriPercentEncodeN(const char *pszString, size_t cchMax)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* The new string can be max 3 times in size of the original string. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrFormatU8(&szNum[0], 3, pszString[iIn++], 16, 2, 2, RTSTR_F_CAPITAL | RTSTR_F_ZEROPAD);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* If the source and target strings have different size, recreate
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * the target string with the correct size. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncstatic char *rtUriPercentDecodeN(const char *pszString, size_t cchMax)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* The new string can only get smaller. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* % encoding means the percent sign and exactly 2 hexadecimal
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * digits describing the ASCII number of the character. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* If the source and target strings have different size, recreate
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * the target string with the correct size. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncstatic bool rtUriFindSchemeEnd(const char *pszUri, size_t iStart, size_t cbLen, size_t *piEnd)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* The scheme has to end with ':'. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return true;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return false;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncstatic bool rtUriCheckAuthorityStart(const char *pszUri, size_t iStart, size_t cbLen, size_t *piStart)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* The authority have to start with '//' */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return true;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return false;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncstatic bool rtUriFindAuthorityEnd(const char *pszUri, size_t iStart, size_t cbLen, size_t *piEnd)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* The authority can end with '/' || '?' || '#'. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return true;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return false;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncstatic bool rtUriCheckPathStart(const char *pszUri, size_t iStart, size_t cbLen, size_t *piStart)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* The path could start with a '/'. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return true;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* '?' || '#' means there is no path. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return false;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* All other values are allowed. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return true;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncstatic bool rtUriFindPathEnd(const char *pszUri, size_t iStart, size_t cbLen, size_t *piEnd)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* The path can end with '?' || '#'. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return true;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return false;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncstatic bool rtUriCheckQueryStart(const char *pszUri, size_t iStart, size_t cbLen, size_t *piStart)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* The query start with a '?'. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return true;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return false;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncstatic bool rtUriFindQueryEnd(const char *pszUri, size_t iStart, size_t cbLen, size_t *piEnd)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* The query can end with '?' || '#'. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return true;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return false;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncstatic bool rtUriCheckFragmentStart(const char *pszUri, size_t iStart, size_t cbLen, size_t *piStart)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* The fragment start with a '#'. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return true;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return false;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync/*******************************************************************************
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync* Public RTUri interface *
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync*******************************************************************************/
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync/*******************************************************************************
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync* Generic Uri methods *
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync*******************************************************************************/
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncRTR3DECL(char *) RTUriCreate(const char *pszScheme, const char *pszAuthority, const char *pszPath, const char *pszQuery, const char *pszFragment)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!pszScheme) /* Scheme is minimum requirement */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Create the percent encoded strings and calculate the necessary uri
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * length. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t cbSize = strlen(pszScheme) + 1 + 1; /* plus zero byte */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszAuthority1 = rtUriPercentEncodeN(pszAuthority, RTSTR_MAX);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszPath1 = rtUriPercentEncodeN(pszPath, RTSTR_MAX);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszQuery1 = rtUriPercentEncodeN(pszQuery, RTSTR_MAX);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszFragment1 = rtUriPercentEncodeN(pszFragment, RTSTR_MAX);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync char *pszTmp = pszResult = (char*)RTMemAllocZ(cbSize);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Compose the target uri string. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }while (0);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Cleanup */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncRTR3DECL(bool) RTUriHasScheme(const char *pszUri, const char *pszScheme)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync bool fRes = false;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync fRes = RTStrNICmp(pszScheme, pszTmp, strlen(pszTmp)) == 0;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the end of the scheme. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the start of the authority. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (rtUriCheckAuthorityStart(pszUri, iPos1, cbLen - iPos1, &iPos2))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the end of the authority. If not found, the rest of the string
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * is used. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync rtUriFindAuthorityEnd(pszUri, iPos2, cbLen - iPos2, &iPos3);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return rtUriPercentDecodeN(&pszUri[iPos2], iPos3 - iPos2);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the end of the scheme. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos3 = iPos1; /* Skip if no authority is found */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the start of the authority. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (rtUriCheckAuthorityStart(pszUri, iPos1, cbLen - iPos1, &iPos2))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the end of the authority. If not found, then there is no path
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * component, cause the authority is the rest of the string. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!rtUriFindAuthorityEnd(pszUri, iPos2, cbLen - iPos2, &iPos3))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the start of the path */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (rtUriCheckPathStart(pszUri, iPos3, cbLen - iPos3, &iPos4))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Search for the end of the scheme. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync rtUriFindPathEnd(pszUri, iPos4, cbLen - iPos4, &iPos5);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return rtUriPercentDecodeN(&pszUri[iPos4], iPos5 - iPos4);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the end of the scheme. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos3 = iPos1; /* Skip if no authority is found */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the start of the authority. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (rtUriCheckAuthorityStart(pszUri, iPos1, cbLen - iPos1, &iPos2))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the end of the authority. If not found, then there is no path
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * component, cause the authority is the rest of the string. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!rtUriFindAuthorityEnd(pszUri, iPos2, cbLen - iPos2, &iPos3))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos5 = iPos3; /* Skip if no path is found */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the start of the path */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (rtUriCheckPathStart(pszUri, iPos3, cbLen - iPos3, &iPos4))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the end of the path. If not found, then there is no query
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * component, cause the path is the rest of the string. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!rtUriFindPathEnd(pszUri, iPos4, cbLen - iPos4, &iPos5))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the start of the query */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (rtUriCheckQueryStart(pszUri, iPos5, cbLen - iPos5, &iPos6))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Search for the end of the query. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync rtUriFindQueryEnd(pszUri, iPos6, cbLen - iPos6, &iPos7);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return rtUriPercentDecodeN(&pszUri[iPos6], iPos7 - iPos6);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the end of the scheme. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos3 = iPos1; /* Skip if no authority is found */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the start of the authority. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (rtUriCheckAuthorityStart(pszUri, iPos1, cbLen - iPos1, &iPos2))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the end of the authority. If not found, then there is no path
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * component, cause the authority is the rest of the string. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!rtUriFindAuthorityEnd(pszUri, iPos2, cbLen - iPos2, &iPos3))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos5 = iPos3; /* Skip if no path is found */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the start of the path */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (rtUriCheckPathStart(pszUri, iPos3, cbLen - iPos3, &iPos4))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the end of the path. If not found, then there is no query
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * component, cause the path is the rest of the string. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!rtUriFindPathEnd(pszUri, iPos4, cbLen - iPos4, &iPos5))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos7 = iPos5; /* Skip if no query is found */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the start of the query */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (rtUriCheckQueryStart(pszUri, iPos5, cbLen - iPos5, &iPos6))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the end of the query If not found, then there is no fragment
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * component, cause the query is the rest of the string. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!rtUriFindQueryEnd(pszUri, iPos6, cbLen - iPos6, &iPos7))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the start of the fragment */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (rtUriCheckFragmentStart(pszUri, iPos7, cbLen - iPos7, &iPos8))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* There could be nothing behind a fragment. So use the rest of the
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * string. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return rtUriPercentDecodeN(&pszUri[iPos8], cbLen - iPos8);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync/*******************************************************************************
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync* File Uri methods *
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync*******************************************************************************/
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncRTR3DECL(char *) RTUriFileCreate(const char *pszPath)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Create the percent encoded strings and calculate the necessary uri
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * length. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszPath1 = rtUriPercentEncodeN(pszPath, RTSTR_MAX);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t cbSize = 7 /* file:// */ + strlen(pszPath1) + 1; /* plus zero byte */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync char *pszTmp = pszResult = (char*)RTMemAllocZ(cbSize);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Compose the target uri string. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }while (0);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Cleanup */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncRTR3DECL(char *) RTUriFilePath(const char *pszUri, uint32_t uFormat)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncRTR3DECL(char *) RTUriFileNPath(const char *pszUri, uint32_t uFormat, size_t cchMax)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the end of the scheme. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Check that this is a file Uri */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos3 = iPos1; /* Skip if no authority is found */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the start of the authority. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (rtUriCheckAuthorityStart(pszUri, iPos1, cbLen - iPos1, &iPos2))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the end of the authority. If not found, then there is no path
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * component, cause the authority is the rest of the string. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!rtUriFindAuthorityEnd(pszUri, iPos2, cbLen - iPos2, &iPos3))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the start of the path */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (rtUriCheckPathStart(pszUri, iPos3, cbLen - iPos3, &iPos4))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Auto is based on the current host OS. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync#else /* RT_OS_WINDOWS */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync#endif /* !RT_OS_WINDOWS */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Search for the end of the scheme. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync rtUriFindPathEnd(pszUri, iPos4, cbLen - iPos4, &iPos5);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync char *pszPath = rtUriPercentDecodeN(&pszUri[iPos4], iPos5 - iPos4);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync AssertMsgFailed(("Unknown uri file format %u", uFIntern));