/* * uriparser - RFC 3986 URI parsing library * * Copyright (C) 2025, 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: * * 1. Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * 2. 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. * * 3. Neither the name of the copyright holder 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 HOLDER 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 "UriSetScheme.c" # undef URI_PASS_ANSI # endif # ifdef URI_ENABLE_UNICODE # define URI_PASS_UNICODE 1 # include "UriSetScheme.c" # undef URI_PASS_UNICODE # endif #else # ifdef URI_PASS_ANSI # include # else # include # include # endif # ifndef URI_DOXYGEN # include # include "UriCommon.h" # include "UriMemory.h" # include "UriSets.h" # endif # include UriBool URI_FUNC(IsWellFormedScheme)(const URI_CHAR * first, const URI_CHAR * afterLast) { if ((first == NULL) || (afterLast == NULL)) { return URI_FALSE; } /* The related part of the grammar in RFC 3986 reads: * * scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */ if (first >= afterLast) { return URI_FALSE; } switch (first[0]) { case URI_SET_ALPHA(_UT): break; default: return URI_FALSE; } first++; while (first < afterLast) { switch (first[0]) { case URI_SET_ALPHA(_UT): case URI_SET_DIGIT(_UT): case _UT('+'): case _UT('-'): case _UT('.'): break; default: return URI_FALSE; } first++; } return URI_TRUE; } int URI_FUNC(SetSchemeMm)(URI_TYPE(Uri) * uri, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory) { /* Input validation (before making any changes) */ if ((uri == NULL) || ((first == NULL) != (afterLast == NULL))) { return URI_ERROR_NULL; } URI_CHECK_MEMORY_MANAGER(memory); /* may return */ if ((first != NULL) && (URI_FUNC(IsWellFormedScheme)(first, afterLast) == URI_FALSE)) { return URI_ERROR_SYNTAX; } /* Clear old value */ if ((uri->owner == URI_TRUE) && (uri->scheme.first != uri->scheme.afterLast)) { memory->free(memory, (URI_CHAR *)uri->scheme.first); } uri->scheme.first = NULL; uri->scheme.afterLast = NULL; /* Already done setting? */ if (first == NULL) { /* Yes, but disambiguate as needed */ const UriBool success = URI_FUNC(FixPathNoScheme)(uri, memory); return (success == URI_TRUE) ? URI_SUCCESS : URI_ERROR_MALLOC; } assert(first != NULL); /* Ensure owned */ if (uri->owner == URI_FALSE) { const int res = URI_FUNC(MakeOwnerMm)(uri, memory); if (res != URI_SUCCESS) { return res; } } assert(uri->owner == URI_TRUE); /* Apply new value */ URI_TYPE(TextRange) sourceRange; sourceRange.first = first; sourceRange.afterLast = afterLast; if (URI_FUNC(CopyRangeAsNeeded)(&uri->scheme, &sourceRange, memory) == URI_FALSE) { return URI_ERROR_MALLOC; } return URI_SUCCESS; } int URI_FUNC(SetScheme)(URI_TYPE(Uri) * uri, const URI_CHAR * first, const URI_CHAR * afterLast) { return URI_FUNC(SetSchemeMm)(uri, first, afterLast, NULL); } #endif