blob: 0d1250ba00667951c816270fb5ac45ad58a58b58 [file] [log] [blame]
/*
* Copyright (c) 2020, The OpenThread Authors.
* 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.
*/
#include "lib/url/url.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "core/common/code_utils.hpp"
namespace ot {
namespace Url {
otError Url::Init(char *aUrl)
{
otError error = OT_ERROR_NONE;
char *url = aUrl;
mEnd = aUrl + strlen(aUrl);
mProtocol = aUrl;
url = strstr(aUrl, "://");
VerifyOrExit(url != nullptr, error = OT_ERROR_PARSE);
*url = '\0';
url += sizeof("://") - 1;
mPath = url;
url = strstr(url, "?");
if (url != nullptr)
{
mQuery = ++url;
for (char *cur = strtok(url, "&"); cur != nullptr; cur = strtok(nullptr, "&"))
{
cur[-1] = '\0';
}
}
else
{
mQuery = mEnd;
}
exit:
return error;
}
const char *Url::GetValue(const char *aName, const char *aLastValue) const
{
const char *rval = nullptr;
const size_t len = strlen(aName);
const char *start;
if (aLastValue == nullptr)
{
start = mQuery;
}
else
{
VerifyOrExit(aLastValue > mQuery && aLastValue < mEnd);
start = aLastValue + strlen(aLastValue) + 1;
}
while (start < mEnd)
{
const char *last = nullptr;
if (!strncmp(aName, start, len))
{
if (start[len] == '=')
{
ExitNow(rval = &start[len + 1]);
}
else if (start[len] == '\0')
{
ExitNow(rval = &start[len]);
}
}
last = start;
start = last + strlen(last) + 1;
}
exit:
return rval;
}
otError Url::ParseUint32(const char *aName, uint32_t &aValue) const
{
otError error = OT_ERROR_NONE;
const char *str;
long long value;
VerifyOrExit((str = GetValue(aName)) != nullptr, error = OT_ERROR_NOT_FOUND);
value = strtoll(str, nullptr, 0);
VerifyOrExit(0 <= value && value <= UINT32_MAX, error = OT_ERROR_INVALID_ARGS);
aValue = static_cast<uint32_t>(value);
exit:
return error;
}
otError Url::ParseUint16(const char *aName, uint16_t &aValue) const
{
otError error = OT_ERROR_NONE;
uint32_t value;
SuccessOrExit(error = ParseUint32(aName, value));
VerifyOrExit(value <= UINT16_MAX, error = OT_ERROR_INVALID_ARGS);
aValue = static_cast<uint16_t>(value);
exit:
return error;
}
otError Url::ParseUint8(const char *aName, uint8_t &aValue) const
{
otError error = OT_ERROR_NONE;
uint32_t value;
SuccessOrExit(error = ParseUint32(aName, value));
VerifyOrExit(value <= UINT8_MAX, error = OT_ERROR_INVALID_ARGS);
aValue = static_cast<uint8_t>(value);
exit:
return error;
}
otError Url::ParseInt32(const char *aName, int32_t &aValue) const
{
otError error = OT_ERROR_NONE;
const char *str;
long long value;
VerifyOrExit((str = GetValue(aName)) != nullptr, error = OT_ERROR_NOT_FOUND);
value = strtoll(str, nullptr, 0);
VerifyOrExit(INT32_MIN <= value && value <= INT32_MAX, error = OT_ERROR_INVALID_ARGS);
aValue = static_cast<int32_t>(value);
exit:
return error;
}
otError Url::ParseInt16(const char *aName, int16_t &aValue) const
{
otError error = OT_ERROR_NONE;
int32_t value;
SuccessOrExit(error = ParseInt32(aName, value));
VerifyOrExit(INT16_MIN <= value && value <= INT16_MAX, error = OT_ERROR_INVALID_ARGS);
aValue = static_cast<int16_t>(value);
exit:
return error;
}
otError Url::ParseInt8(const char *aName, int8_t &aValue) const
{
otError error = OT_ERROR_NONE;
int32_t value;
SuccessOrExit(error = ParseInt32(aName, value));
VerifyOrExit(INT8_MIN <= value && value <= INT8_MAX, error = OT_ERROR_INVALID_ARGS);
aValue = static_cast<int8_t>(value);
exit:
return error;
}
} // namespace Url
} // namespace ot