2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync/* $Id$ */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync/** @file
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * IPRT - Uniform Resource Identifier handling.
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync/*
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * Copyright (C) 2011 Oracle Corporation
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync *
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 *
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 *
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
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync/*******************************************************************************
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync* Header Files *
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync*******************************************************************************/
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync#include <iprt/uri.h>
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync#include <iprt/string.h>
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync#include <iprt/mem.h>
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync#include <iprt/path.h>
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync#include <iprt/stream.h>
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync/* General URI format:
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync foo://example.com:8042/over/there?name=ferret#nose
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync \_/ \______________/\_________/ \_________/ \__/
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync | | | | |
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync scheme authority path query fragment
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync | _____________________|__
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync / \ / \
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync urn:example:animal:ferret:nose
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync*/
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync/*******************************************************************************
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync* Private RTUri helper *
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync*******************************************************************************/
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync/* The following defines characters which have to be % escaped:
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync control = 00-1F
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync space = ' '
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync delims = '<' , '>' , '#' , '%' , '"'
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync unwise = '{' , '}' , '|' , '\' , '^' , '[' , ']' , '`'
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync*/
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync#define URI_EXCLUDED(a) \
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync ((a) >= 0x0 && (a) <= 0x20) \
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync || ((a) >= 0x5B && (a) <= 0x5E) \
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync || ((a) >= 0x7B && (a) <= 0x7D) \
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync || (a) == '<' || (a) == '>' || (a) == '#' \
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync || (a) == '%' || (a) == '"' || (a) == '`'
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncstatic char *rtUriPercentEncodeN(const char *pszString, size_t cchMax)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync{
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!pszString)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return NULL;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync int rc = VINF_SUCCESS;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t cbLen = RT_MIN(strlen(pszString), cchMax);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* The new string can be max 3 times in size of the original string. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync char *pszNew = (char*)RTMemAlloc(cbLen * 3 + 1);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!pszNew)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return NULL;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync char *pszRes = NULL;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iIn = 0;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iOut = 0;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync while(iIn < cbLen)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (URI_EXCLUDED(pszString[iIn]))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync char szNum[3] = { 0, 0, 0 };
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrFormatU8(&szNum[0], 3, pszString[iIn++], 16, 2, 2, RTSTR_F_CAPITAL | RTSTR_F_ZEROPAD);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszNew[iOut++] = '%';
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszNew[iOut++] = szNum[0];
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszNew[iOut++] = szNum[1];
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync else
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszNew[iOut++] = pszString[iIn++];
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (RT_SUCCESS(rc))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszNew[iOut] = '\0';
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (iOut != iIn)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* If the source and target strings have different size, recreate
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * the target string with the correct size. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszRes = RTStrDupN(pszNew, iOut);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrFree(pszNew);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync else
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszRes = pszNew;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync else
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrFree(pszNew);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return pszRes;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync}
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncstatic char *rtUriPercentDecodeN(const char *pszString, size_t cchMax)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync{
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!pszString)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return NULL;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync int rc = VINF_SUCCESS;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t cbLen = RT_MIN(strlen(pszString), cchMax);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* The new string can only get smaller. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync char *pszNew = (char*)RTMemAlloc(cbLen + 1);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!pszNew)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return NULL;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync char *pszRes = NULL;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iIn = 0;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iOut = 0;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync while(iIn < cbLen)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (pszString[iIn] == '%')
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* % encoding means the percent sign and exactly 2 hexadecimal
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * digits describing the ASCII number of the character. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync ++iIn;
f6c638878573ea59ed64c4c21efcbef470c9a58bvboxsync char szNum[3];
f6c638878573ea59ed64c4c21efcbef470c9a58bvboxsync szNum[0] = pszString[iIn++];
f6c638878573ea59ed64c4c21efcbef470c9a58bvboxsync szNum[1] = pszString[iIn++];
f6c638878573ea59ed64c4c21efcbef470c9a58bvboxsync szNum[2] = '\0';
7b4c4bb29760b28b5727231ad446462a5b0cc01avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync uint8_t u8;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync rc = RTStrToUInt8Ex(szNum, NULL, 16, &u8);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (RT_FAILURE(rc))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync break;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszNew[iOut] = u8;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync else
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszNew[iOut] = pszString[iIn++];
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync ++iOut;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (RT_SUCCESS(rc))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszNew[iOut] = '\0';
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (iOut != iIn)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* If the source and target strings have different size, recreate
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * the target string with the correct size. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszRes = RTStrDupN(pszNew, iOut);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrFree(pszNew);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync else
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszRes = pszNew;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync else
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrFree(pszNew);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return pszRes;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync}
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncstatic bool rtUriFindSchemeEnd(const char *pszUri, size_t iStart, size_t cbLen, size_t *piEnd)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync{
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t i = iStart;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* The scheme has to end with ':'. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync while(i < iStart + cbLen)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (pszUri[i] == ':')
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync *piEnd = i;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return true;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync ++i;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return false;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync}
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncstatic bool rtUriCheckAuthorityStart(const char *pszUri, size_t iStart, size_t cbLen, size_t *piStart)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync{
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* The authority have to start with '//' */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if ( cbLen >= 2
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync && pszUri[iStart ] == '/'
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync && pszUri[iStart + 1] == '/')
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync *piStart = iStart + 2;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return true;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return false;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync}
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncstatic bool rtUriFindAuthorityEnd(const char *pszUri, size_t iStart, size_t cbLen, size_t *piEnd)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync{
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t i = iStart;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* The authority can end with '/' || '?' || '#'. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync while(i < iStart + cbLen)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if ( pszUri[i] == '/'
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync || pszUri[i] == '?'
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync || pszUri[i] == '#')
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync *piEnd = i;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return true;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync ++i;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return false;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync}
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncstatic bool rtUriCheckPathStart(const char *pszUri, size_t iStart, size_t cbLen, size_t *piStart)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync{
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* The path could start with a '/'. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if ( cbLen >= 1
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync && pszUri[iStart] == '/')
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync *piStart = iStart; /* Including '/' */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return true;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* '?' || '#' means there is no path. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if ( cbLen >= 1
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync && ( pszUri[iStart] == '?'
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync || pszUri[iStart] == '#'))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return false;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* All other values are allowed. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync *piStart = iStart;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return true;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync}
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncstatic bool rtUriFindPathEnd(const char *pszUri, size_t iStart, size_t cbLen, size_t *piEnd)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync{
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t i = iStart;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* The path can end with '?' || '#'. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync while(i < iStart + cbLen)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if ( pszUri[i] == '?'
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync || pszUri[i] == '#')
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync *piEnd = i;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return true;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync ++i;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return false;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync}
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncstatic bool rtUriCheckQueryStart(const char *pszUri, size_t iStart, size_t cbLen, size_t *piStart)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync{
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* The query start with a '?'. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if ( cbLen >= 1
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync && pszUri[iStart] == '?')
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync *piStart = iStart + 1; /* Excluding '?' */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return true;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return false;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync}
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncstatic bool rtUriFindQueryEnd(const char *pszUri, size_t iStart, size_t cbLen, size_t *piEnd)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync{
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t i = iStart;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* The query can end with '?' || '#'. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync while(i < iStart + cbLen)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (pszUri[i] == '#')
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync *piEnd = i;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return true;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync ++i;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return false;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync}
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncstatic bool rtUriCheckFragmentStart(const char *pszUri, size_t iStart, size_t cbLen, size_t *piStart)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync{
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* The fragment start with a '#'. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if ( cbLen >= 1
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync && pszUri[iStart] == '#')
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync *piStart = iStart + 1; /* Excluding '#' */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return true;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return false;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync}
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync/*******************************************************************************
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync* Public RTUri interface *
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync*******************************************************************************/
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync/*******************************************************************************
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync* Generic Uri methods *
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync*******************************************************************************/
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncRTR3DECL(char *) RTUriCreate(const char *pszScheme, const char *pszAuthority, const char *pszPath, const char *pszQuery, const char *pszFragment)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync{
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!pszScheme) /* Scheme is minimum requirement */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return NULL;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync char *pszResult = 0;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync char *pszAuthority1 = 0;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync char *pszPath1 = 0;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync char *pszQuery1 = 0;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync char *pszFragment1 = 0;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync do
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
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 if (pszAuthority)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszAuthority1 = rtUriPercentEncodeN(pszAuthority, RTSTR_MAX);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!pszAuthority1)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync break;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync cbSize += strlen(pszAuthority1) + 2;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (pszPath)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszPath1 = rtUriPercentEncodeN(pszPath, RTSTR_MAX);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!pszPath1)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync break;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync cbSize += strlen(pszPath1);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (pszQuery)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszQuery1 = rtUriPercentEncodeN(pszQuery, RTSTR_MAX);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!pszQuery1)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync break;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync cbSize += strlen(pszQuery1) + 1;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (pszFragment)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszFragment1 = rtUriPercentEncodeN(pszFragment, RTSTR_MAX);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!pszFragment1)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync break;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync cbSize += strlen(pszFragment1) + 1;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync char *pszTmp = pszResult = (char*)RTMemAllocZ(cbSize);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!pszResult)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync break;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Compose the target uri string. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrCatP(&pszTmp, &cbSize, pszScheme);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrCatP(&pszTmp, &cbSize, ":");
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (pszAuthority1)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrCatP(&pszTmp, &cbSize, "//");
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrCatP(&pszTmp, &cbSize, pszAuthority1);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (pszPath1)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrCatP(&pszTmp, &cbSize, pszPath1);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (pszQuery1)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrCatP(&pszTmp, &cbSize, "?");
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrCatP(&pszTmp, &cbSize, pszQuery1);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (pszFragment1)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrCatP(&pszTmp, &cbSize, "#");
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrCatP(&pszTmp, &cbSize, pszFragment1);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }while (0);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Cleanup */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (pszAuthority1)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrFree(pszAuthority1);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (pszPath1)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrFree(pszPath1);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (pszQuery1)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrFree(pszQuery1);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (pszFragment1)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrFree(pszFragment1);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return pszResult;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync}
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncRTR3DECL(bool) RTUriHasScheme(const char *pszUri, const char *pszScheme)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync{
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync bool fRes = false;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync char *pszTmp = RTUriScheme(pszUri);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (pszTmp)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync fRes = RTStrNICmp(pszScheme, pszTmp, strlen(pszTmp)) == 0;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrFree(pszTmp);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return fRes;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync}
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncRTR3DECL(char *) RTUriScheme(const char *pszUri)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync{
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync AssertPtrReturn(pszUri, NULL);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos1;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t cbLen = strlen(pszUri);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (rtUriFindSchemeEnd(pszUri, 0, cbLen, &iPos1))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return rtUriPercentDecodeN(pszUri, iPos1);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return NULL;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync}
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncRTR3DECL(char *) RTUriAuthority(const char *pszUri)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync{
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync AssertPtrReturn(pszUri, NULL);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos1;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t cbLen = strlen(pszUri);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the end of the scheme. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!rtUriFindSchemeEnd(pszUri, 0, cbLen, &iPos1))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return NULL; /* no URI */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync else
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync ++iPos1; /* Skip ':' */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos2;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the start of the authority. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (rtUriCheckAuthorityStart(pszUri, iPos1, cbLen - iPos1, &iPos2))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos3 = cbLen;
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 if (iPos3 > iPos2) /* Length check */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return rtUriPercentDecodeN(&pszUri[iPos2], iPos3 - iPos2);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync else
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return NULL;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return NULL;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync}
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncRTR3DECL(char *) RTUriPath(const char *pszUri)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync{
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync AssertPtrReturn(pszUri, NULL);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos1;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t cbLen = strlen(pszUri);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the end of the scheme. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!rtUriFindSchemeEnd(pszUri, 0, cbLen, &iPos1))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return NULL; /* no URI */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync else
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync ++iPos1; /* Skip ':' */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos2;
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 {
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 return NULL; /* no path! */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos4;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the start of the path */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (rtUriCheckPathStart(pszUri, iPos3, cbLen - iPos3, &iPos4))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Search for the end of the scheme. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos5 = cbLen;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync rtUriFindPathEnd(pszUri, iPos4, cbLen - iPos4, &iPos5);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (iPos5 > iPos4) /* Length check */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return rtUriPercentDecodeN(&pszUri[iPos4], iPos5 - iPos4);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return NULL;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync}
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncRTR3DECL(char *) RTUriQuery(const char *pszUri)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync{
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync AssertPtrReturn(pszUri, NULL);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos1;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t cbLen = strlen(pszUri);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the end of the scheme. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!rtUriFindSchemeEnd(pszUri, 0, cbLen, &iPos1))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return NULL; /* no URI */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync else
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync ++iPos1; /* Skip ':' */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos2;
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 {
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 return NULL; /* no path! */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos4;
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 {
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 return NULL; /* no query! */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos6;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the start of the query */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (rtUriCheckQueryStart(pszUri, iPos5, cbLen - iPos5, &iPos6))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Search for the end of the query. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos7 = cbLen;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync rtUriFindQueryEnd(pszUri, iPos6, cbLen - iPos6, &iPos7);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (iPos7 > iPos6) /* Length check */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return rtUriPercentDecodeN(&pszUri[iPos6], iPos7 - iPos6);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return NULL;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync}
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncRTR3DECL(char *) RTUriFragment(const char *pszUri)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync{
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync AssertPtrReturn(pszUri, NULL);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos1;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t cbLen = strlen(pszUri);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the end of the scheme. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!rtUriFindSchemeEnd(pszUri, 0, cbLen, &iPos1))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return NULL; /* no URI */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync else
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync ++iPos1; /* Skip ':' */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos2;
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 {
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 return NULL; /* no path! */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos4;
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 {
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 return NULL; /* no query! */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos6;
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 {
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 return NULL; /* no query! */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos8;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the start of the fragment */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (rtUriCheckFragmentStart(pszUri, iPos7, cbLen - iPos7, &iPos8))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* There could be nothing behind a fragment. So use the rest of the
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * string. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (cbLen > iPos8) /* Length check */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return rtUriPercentDecodeN(&pszUri[iPos8], cbLen - iPos8);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return NULL;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync}
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync/*******************************************************************************
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync* File Uri methods *
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync*******************************************************************************/
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncRTR3DECL(char *) RTUriFileCreate(const char *pszPath)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync{
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!pszPath)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return NULL;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync char *pszResult = 0;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync char *pszPath1 = 0;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync do
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Create the percent encoded strings and calculate the necessary uri
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync * length. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync pszPath1 = rtUriPercentEncodeN(pszPath, RTSTR_MAX);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!pszPath1)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync break;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t cbSize = 7 /* file:// */ + strlen(pszPath1) + 1; /* plus zero byte */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (pszPath1[0] != '/')
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync ++cbSize;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync char *pszTmp = pszResult = (char*)RTMemAllocZ(cbSize);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!pszResult)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync break;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Compose the target uri string. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrCatP(&pszTmp, &cbSize, "file://");
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (pszPath1[0] != '/')
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrCatP(&pszTmp, &cbSize, "/");
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrCatP(&pszTmp, &cbSize, pszPath1);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }while (0);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Cleanup */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (pszPath1)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrFree(pszPath1);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return pszResult;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync}
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncRTR3DECL(char *) RTUriFilePath(const char *pszUri, uint32_t uFormat)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync{
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return RTUriFileNPath(pszUri, uFormat, RTSTR_MAX);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync}
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsyncRTR3DECL(char *) RTUriFileNPath(const char *pszUri, uint32_t uFormat, size_t cchMax)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync{
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync AssertPtrReturn(pszUri, NULL);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos1;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t cbLen = RT_MIN(strlen(pszUri), cchMax);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the end of the scheme. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (!rtUriFindSchemeEnd(pszUri, 0, cbLen, &iPos1))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return NULL; /* no URI */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync else
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync ++iPos1; /* Skip ':' */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Check that this is a file Uri */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (RTStrNICmp(pszUri, "file:", iPos1) != 0)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return NULL;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos2;
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 {
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 return NULL; /* no path! */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos4;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Find the start of the path */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (rtUriCheckPathStart(pszUri, iPos3, cbLen - iPos3, &iPos4))
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync uint32_t uFIntern = uFormat;
7b4c4bb29760b28b5727231ad446462a5b0cc01avboxsync /* Auto is based on the current OS. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (uFormat == URI_FILE_FORMAT_AUTO)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync#ifdef RT_OS_WINDOWS
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync uFIntern = URI_FILE_FORMAT_WIN;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync#else /* RT_OS_WINDOWS */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync uFIntern = URI_FILE_FORMAT_UNIX;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync#endif /* !RT_OS_WINDOWS */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if ( uFIntern != URI_FILE_FORMAT_UNIX
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync && pszUri[iPos4] == '/')
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync ++iPos4;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync /* Search for the end of the scheme. */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync size_t iPos5 = cbLen;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync rtUriFindPathEnd(pszUri, iPos4, cbLen - iPos4, &iPos5);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (iPos5 > iPos4) /* Length check */
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync char *pszPath = rtUriPercentDecodeN(&pszUri[iPos4], iPos5 - iPos4);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync if (uFIntern == URI_FILE_FORMAT_UNIX)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return RTPathChangeToUnixSlashes(pszPath, true);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync else if (uFIntern == URI_FILE_FORMAT_WIN)
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return RTPathChangeToDosSlashes(pszPath, true);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync else
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync {
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync RTStrFree(pszPath);
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync AssertMsgFailed(("Unknown uri file format %u", uFIntern));
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return NULL;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync }
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync return NULL;
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync}
2eca2a2fb6e205bccf07ee440e48881cffb8959avboxsync