1 /*
2 * Copyright (c) 2020, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "lib/url/url.hpp"
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include "core/common/code_utils.hpp"
36
37 namespace ot {
38 namespace Url {
39
Url(void)40 Url::Url(void)
41 {
42 mProtocol = nullptr;
43 mPath = nullptr;
44 mQuery = nullptr;
45 mEnd = nullptr;
46 }
47
Init(char * aUrl)48 otError Url::Init(char *aUrl)
49 {
50 otError error = OT_ERROR_NONE;
51 char *url = aUrl;
52
53 mEnd = aUrl + strlen(aUrl);
54 mProtocol = aUrl;
55
56 url = strstr(aUrl, "://");
57 VerifyOrExit(url != nullptr, error = OT_ERROR_PARSE);
58 *url = '\0';
59 url += sizeof("://") - 1;
60 mPath = url;
61
62 url = strstr(url, "?");
63
64 if (url != nullptr)
65 {
66 mQuery = ++url;
67
68 for (char *cur = strtok(url, "&"); cur != nullptr; cur = strtok(nullptr, "&"))
69 {
70 cur[-1] = '\0';
71 }
72 }
73 else
74 {
75 mQuery = mEnd;
76 }
77
78 exit:
79 return error;
80 }
81
GetValue(const char * aName,const char * aLastValue) const82 const char *Url::GetValue(const char *aName, const char *aLastValue) const
83 {
84 const char *rval = nullptr;
85 const size_t len = strlen(aName);
86 const char *start;
87
88 if (aLastValue == nullptr)
89 {
90 start = mQuery;
91 }
92 else
93 {
94 VerifyOrExit(aLastValue > mQuery && aLastValue < mEnd);
95 start = aLastValue + strlen(aLastValue) + 1;
96 }
97
98 while (start < mEnd)
99 {
100 const char *last = nullptr;
101
102 if (!strncmp(aName, start, len))
103 {
104 if (start[len] == '=')
105 {
106 ExitNow(rval = &start[len + 1]);
107 }
108 else if (start[len] == '\0')
109 {
110 ExitNow(rval = &start[len]);
111 }
112 }
113 last = start;
114 start = last + strlen(last) + 1;
115 }
116
117 exit:
118 return rval;
119 }
120
ParseUint32(const char * aName,uint32_t & aValue) const121 otError Url::ParseUint32(const char *aName, uint32_t &aValue) const
122 {
123 otError error = OT_ERROR_NONE;
124 const char *str;
125 long long value;
126
127 VerifyOrExit((str = GetValue(aName)) != nullptr, error = OT_ERROR_NOT_FOUND);
128
129 value = strtoll(str, nullptr, 0);
130 VerifyOrExit(0 <= value && value <= UINT32_MAX, error = OT_ERROR_INVALID_ARGS);
131 aValue = static_cast<uint32_t>(value);
132
133 exit:
134 return error;
135 }
136
ParseUint16(const char * aName,uint16_t & aValue) const137 otError Url::ParseUint16(const char *aName, uint16_t &aValue) const
138 {
139 otError error = OT_ERROR_NONE;
140 uint32_t value;
141
142 SuccessOrExit(error = ParseUint32(aName, value));
143 VerifyOrExit(value <= UINT16_MAX, error = OT_ERROR_INVALID_ARGS);
144 aValue = static_cast<uint16_t>(value);
145
146 exit:
147 return error;
148 }
149
ParseUint8(const char * aName,uint8_t & aValue) const150 otError Url::ParseUint8(const char *aName, uint8_t &aValue) const
151 {
152 otError error = OT_ERROR_NONE;
153 uint32_t value;
154
155 SuccessOrExit(error = ParseUint32(aName, value));
156 VerifyOrExit(value <= UINT8_MAX, error = OT_ERROR_INVALID_ARGS);
157 aValue = static_cast<uint8_t>(value);
158
159 exit:
160 return error;
161 }
162
ParseInt32(const char * aName,int32_t & aValue) const163 otError Url::ParseInt32(const char *aName, int32_t &aValue) const
164 {
165 otError error = OT_ERROR_NONE;
166 const char *str;
167 long long value;
168
169 VerifyOrExit((str = GetValue(aName)) != nullptr, error = OT_ERROR_NOT_FOUND);
170
171 value = strtoll(str, nullptr, 0);
172 VerifyOrExit(INT32_MIN <= value && value <= INT32_MAX, error = OT_ERROR_INVALID_ARGS);
173 aValue = static_cast<int32_t>(value);
174
175 exit:
176 return error;
177 }
178
ParseInt16(const char * aName,int16_t & aValue) const179 otError Url::ParseInt16(const char *aName, int16_t &aValue) const
180 {
181 otError error = OT_ERROR_NONE;
182 int32_t value;
183
184 SuccessOrExit(error = ParseInt32(aName, value));
185 VerifyOrExit(INT16_MIN <= value && value <= INT16_MAX, error = OT_ERROR_INVALID_ARGS);
186 aValue = static_cast<int16_t>(value);
187
188 exit:
189 return error;
190 }
191
ParseInt8(const char * aName,int8_t & aValue) const192 otError Url::ParseInt8(const char *aName, int8_t &aValue) const
193 {
194 otError error = OT_ERROR_NONE;
195 int32_t value;
196
197 SuccessOrExit(error = ParseInt32(aName, value));
198 VerifyOrExit(INT8_MIN <= value && value <= INT8_MAX, error = OT_ERROR_INVALID_ARGS);
199 aValue = static_cast<int8_t>(value);
200
201 exit:
202 return error;
203 }
204
205 } // namespace Url
206 } // namespace ot
207