/* * uriparser - RFC 3986 URI parsing library * * Copyright (C) 2007, Weijia Song * Copyright (C) 2007, Sebastian Pipping * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the nor the names of its * contributors may be used to endorse or promote products * derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ /* What encodings are enabled? */ #include #if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) /* Include SELF twice */ # ifdef URI_ENABLE_ANSI # define URI_PASS_ANSI 1 # include "UriFile.c" # undef URI_PASS_ANSI # endif # ifdef URI_ENABLE_UNICODE # define URI_PASS_UNICODE 1 # include "UriFile.c" # undef URI_PASS_UNICODE # endif #else # ifdef URI_PASS_ANSI # include # else # include # include # endif #ifndef URI_DOXYGEN # include #endif static URI_INLINE int URI_FUNC(FilenameToUriString)(const URI_CHAR * filename, URI_CHAR * uriString, UriBool fromUnix) { const URI_CHAR * input = filename; const URI_CHAR * lastSep = input - 1; UriBool firstSegment = URI_TRUE; URI_CHAR * output = uriString; const UriBool absolute = (filename != NULL) && ((fromUnix && (filename[0] == _UT('/'))) || (!fromUnix && (filename[0] != _UT('\0')) && (filename[1] == _UT(':')))); if ((filename == NULL) || (uriString == NULL)) { return URI_ERROR_NULL; } if (absolute) { const URI_CHAR * const prefix = fromUnix ? _UT("file://") : _UT("file:///"); const int prefixLen = fromUnix ? 7 : 8; /* Copy prefix */ memcpy(uriString, prefix, prefixLen * sizeof(URI_CHAR)); output += prefixLen; } /* Copy and escape on the fly */ for (;;) { if ((input[0] == _UT('\0')) || (fromUnix && input[0] == _UT('/')) || (!fromUnix && input[0] == _UT('\\'))) { /* Copy text after last seperator */ if (lastSep + 1 < input) { if (!fromUnix && absolute && (firstSegment == URI_TRUE)) { /* Quick hack to not convert "C:" to "C%3A" */ const int charsToCopy = (int)(input - (lastSep + 1)); memcpy(output, lastSep + 1, charsToCopy * sizeof(URI_CHAR)); output += charsToCopy; } else { output = URI_FUNC(EscapeEx)(lastSep + 1, input, output, URI_FALSE, URI_FALSE); } } firstSegment = URI_FALSE; } if (input[0] == _UT('\0')) { output[0] = _UT('\0'); break; } else if (fromUnix && (input[0] == _UT('/'))) { /* Copy separators unmodified */ output[0] = _UT('/'); output++; lastSep = input; } else if (!fromUnix && (input[0] == _UT('\\'))) { /* Convert backslashes to forward slashes */ output[0] = _UT('/'); output++; lastSep = input; } input++; } return URI_SUCCESS; } static URI_INLINE int URI_FUNC(UriStringToFilename)(const URI_CHAR * uriString, URI_CHAR * filename, UriBool toUnix) { const URI_CHAR * const prefix = toUnix ? _UT("file://") : _UT("file:///"); const int prefixLen = toUnix ? 7 : 8; URI_CHAR * walker = filename; size_t charsToCopy; const UriBool absolute = (URI_STRNCMP(uriString, prefix, prefixLen) == 0); const int charsToSkip = (absolute ? prefixLen : 0); charsToCopy = URI_STRLEN(uriString + charsToSkip) + 1; memcpy(filename, uriString + charsToSkip, charsToCopy * sizeof(URI_CHAR)); URI_FUNC(UnescapeInPlaceEx)(filename, URI_FALSE, URI_BR_DONT_TOUCH); /* Convert forward slashes to backslashes */ if (!toUnix) { while (walker[0] != _UT('\0')) { if (walker[0] == _UT('/')) { walker[0] = _UT('\\'); } walker++; } } return URI_SUCCESS; } int URI_FUNC(UnixFilenameToUriString)(const URI_CHAR * filename, URI_CHAR * uriString) { return URI_FUNC(FilenameToUriString)(filename, uriString, URI_TRUE); } int URI_FUNC(WindowsFilenameToUriString)(const URI_CHAR * filename, URI_CHAR * uriString) { return URI_FUNC(FilenameToUriString)(filename, uriString, URI_FALSE); } int URI_FUNC(UriStringToUnixFilename)(const URI_CHAR * uriString, URI_CHAR * filename) { return URI_FUNC(UriStringToFilename)(uriString, filename, URI_TRUE); } int URI_FUNC(UriStringToWindowsFilename)(const URI_CHAR * uriString, URI_CHAR * filename) { return URI_FUNC(UriStringToFilename)(uriString, filename, URI_FALSE); } #endif