|
64 | 64 | #ifndef URI_DOXYGEN
|
65 | 65 | # include <uriparser/Uri.h>
|
66 | 66 | # include "UriCommon.h"
|
| 67 | +# include "UriMemory.h" |
67 | 68 | #endif
|
68 | 69 |
|
69 | 70 |
|
@@ -119,6 +120,225 @@ int URI_FUNC(CompareRange)(
|
119 | 120 |
|
120 | 121 |
|
121 | 122 |
|
| 123 | +UriBool URI_FUNC(CopyRangeEngine)(URI_TYPE(TextRange) * destRange, |
| 124 | + const URI_TYPE(TextRange) * sourceRange, UriMemoryManager * memory) { |
| 125 | + const int lenInChars = (int)(sourceRange->afterLast - sourceRange->first); |
| 126 | + const int lenInBytes = lenInChars * sizeof(URI_CHAR); |
| 127 | + URI_CHAR * dup = memory->malloc(memory, lenInBytes); |
| 128 | + if (dup == NULL) { |
| 129 | + return URI_FALSE; |
| 130 | + } |
| 131 | + memcpy(dup, sourceRange->first, lenInBytes); |
| 132 | + destRange->first = dup; |
| 133 | + destRange->afterLast = dup + lenInChars; |
| 134 | + |
| 135 | + return URI_TRUE; |
| 136 | +} |
| 137 | + |
| 138 | + |
| 139 | + |
| 140 | +UriBool URI_FUNC(CopyRange)(URI_TYPE(TextRange) * destRange, |
| 141 | + const URI_TYPE(TextRange) * sourceRange, UriBool useSafe, UriMemoryManager * memory) { |
| 142 | + if (sourceRange->first == NULL || sourceRange->afterLast == NULL || (sourceRange->first > sourceRange->afterLast && !useSafe)) { |
| 143 | + destRange->first = NULL; |
| 144 | + destRange->afterLast = NULL; |
| 145 | + } else if (sourceRange->first >= sourceRange->afterLast && useSafe) { |
| 146 | + destRange->first = URI_FUNC(SafeToPointTo); |
| 147 | + destRange->afterLast = URI_FUNC(SafeToPointTo); |
| 148 | + } else { |
| 149 | + return URI_FUNC(CopyRangeEngine)(destRange, sourceRange, memory); |
| 150 | + } |
| 151 | + |
| 152 | + return URI_TRUE; |
| 153 | +} |
| 154 | + |
| 155 | + |
| 156 | + |
| 157 | +URI_INLINE void URI_FUNC(PreventLeakage)(URI_TYPE(Uri) * uri, |
| 158 | + unsigned int revertMask, UriMemoryManager * memory) { |
| 159 | + if (revertMask & URI_NORMALIZE_SCHEME) { |
| 160 | + /* NOTE: A scheme cannot be the empty string |
| 161 | + * so no need to compare .first with .afterLast, here. */ |
| 162 | + memory->free(memory, (URI_CHAR *)uri->scheme.first); |
| 163 | + uri->scheme.first = NULL; |
| 164 | + uri->scheme.afterLast = NULL; |
| 165 | + } |
| 166 | + |
| 167 | + if (revertMask & URI_NORMALIZE_USER_INFO) { |
| 168 | + if (uri->userInfo.first != uri->userInfo.afterLast) { |
| 169 | + memory->free(memory, (URI_CHAR *)uri->userInfo.first); |
| 170 | + } |
| 171 | + uri->userInfo.first = NULL; |
| 172 | + uri->userInfo.afterLast = NULL; |
| 173 | + } |
| 174 | + |
| 175 | + if (revertMask & URI_NORMALIZE_HOST) { |
| 176 | + if (uri->hostData.ipFuture.first != NULL) { |
| 177 | + /* IPvFuture */ |
| 178 | + /* NOTE: An IPvFuture address cannot be the empty string |
| 179 | + * so no need to compare .first with .afterLast, here. */ |
| 180 | + memory->free(memory, (URI_CHAR *)uri->hostData.ipFuture.first); |
| 181 | + uri->hostData.ipFuture.first = NULL; |
| 182 | + uri->hostData.ipFuture.afterLast = NULL; |
| 183 | + uri->hostText.first = NULL; |
| 184 | + uri->hostText.afterLast = NULL; |
| 185 | + } else if (uri->hostText.first != NULL) { |
| 186 | + /* Regname */ |
| 187 | + if (uri->hostText.first != uri->hostText.afterLast) { |
| 188 | + memory->free(memory, (URI_CHAR *)uri->hostText.first); |
| 189 | + } |
| 190 | + uri->hostText.first = NULL; |
| 191 | + uri->hostText.afterLast = NULL; |
| 192 | + } |
| 193 | + } |
| 194 | + |
| 195 | + /* NOTE: Port cannot happen! */ |
| 196 | + |
| 197 | + if (revertMask & URI_NORMALIZE_PATH) { |
| 198 | + URI_TYPE(PathSegment) * walker = uri->pathHead; |
| 199 | + while (walker != NULL) { |
| 200 | + URI_TYPE(PathSegment) * const next = walker->next; |
| 201 | + if (walker->text.afterLast > walker->text.first) { |
| 202 | + memory->free(memory, (URI_CHAR *)walker->text.first); |
| 203 | + } |
| 204 | + memory->free(memory, walker); |
| 205 | + walker = next; |
| 206 | + } |
| 207 | + uri->pathHead = NULL; |
| 208 | + uri->pathTail = NULL; |
| 209 | + } |
| 210 | + |
| 211 | + if (revertMask & URI_NORMALIZE_QUERY) { |
| 212 | + if (uri->query.first != uri->query.afterLast) { |
| 213 | + memory->free(memory, (URI_CHAR *)uri->query.first); |
| 214 | + } |
| 215 | + uri->query.first = NULL; |
| 216 | + uri->query.afterLast = NULL; |
| 217 | + } |
| 218 | + |
| 219 | + if (revertMask & URI_NORMALIZE_FRAGMENT) { |
| 220 | + if (uri->fragment.first != uri->fragment.afterLast) { |
| 221 | + memory->free(memory, (URI_CHAR *)uri->fragment.first); |
| 222 | + } |
| 223 | + uri->fragment.first = NULL; |
| 224 | + uri->fragment.afterLast = NULL; |
| 225 | + } |
| 226 | +} |
| 227 | + |
| 228 | + |
| 229 | + |
| 230 | +int URI_FUNC(CopyUriMm)(URI_TYPE(Uri) * destUri, |
| 231 | + const URI_TYPE(Uri) * sourceUri, UriMemoryManager * memory) { |
| 232 | + if (sourceUri == NULL) { |
| 233 | + return URI_ERROR_NULL; |
| 234 | + } |
| 235 | + |
| 236 | + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ |
| 237 | + |
| 238 | + if (URI_FUNC(CopyRange)(&destUri->scheme, &sourceUri->scheme, URI_FALSE, memory) == URI_FALSE) { |
| 239 | + return URI_ERROR_MALLOC; |
| 240 | + } |
| 241 | + |
| 242 | + if (URI_FUNC(CopyRange)(&destUri->userInfo, &sourceUri->userInfo, URI_FALSE, memory) == URI_FALSE) { |
| 243 | + URI_FUNC(PreventLeakage)(destUri, URI_NORMALIZE_SCHEME, memory); |
| 244 | + return URI_ERROR_MALLOC; |
| 245 | + } |
| 246 | + |
| 247 | + if (URI_FUNC(CopyRange)(&destUri->hostText, &sourceUri->hostText, URI_TRUE, memory) == URI_FALSE) { |
| 248 | + URI_FUNC(PreventLeakage)(destUri, URI_NORMALIZE_USER_INFO, memory); |
| 249 | + return URI_ERROR_MALLOC; |
| 250 | + } |
| 251 | + if (sourceUri->hostData.ip4 == NULL) { |
| 252 | + destUri->hostData.ip4 = NULL; |
| 253 | + } else { |
| 254 | + destUri->hostData.ip4 = memory->malloc(memory, sizeof(UriIp4)); |
| 255 | + if (destUri->hostData.ip4 == NULL) { |
| 256 | + URI_FUNC(PreventLeakage)(destUri, URI_NORMALIZE_HOST, memory); |
| 257 | + return URI_ERROR_MALLOC; |
| 258 | + } |
| 259 | + *(destUri->hostData.ip4) = *(sourceUri->hostData.ip4); |
| 260 | + } |
| 261 | + if (sourceUri->hostData.ip6 == NULL) { |
| 262 | + destUri->hostData.ip6 = NULL; |
| 263 | + } else { |
| 264 | + destUri->hostData.ip6 = memory->malloc(memory, sizeof(UriIp6)); |
| 265 | + if (destUri->hostData.ip6 == NULL) { |
| 266 | + URI_FUNC(PreventLeakage)(destUri, URI_NORMALIZE_HOST, memory); |
| 267 | + return URI_ERROR_MALLOC; |
| 268 | + } |
| 269 | + *(destUri->hostData.ip6) = *(sourceUri->hostData.ip6); |
| 270 | + } |
| 271 | + if (URI_FUNC(CopyRange)(&destUri->hostData.ipFuture, &sourceUri->hostData.ipFuture, URI_FALSE, memory) == URI_FALSE) { |
| 272 | + URI_FUNC(PreventLeakage)(destUri, URI_NORMALIZE_HOST, memory); |
| 273 | + return URI_ERROR_MALLOC; |
| 274 | + } |
| 275 | + |
| 276 | + if (URI_FUNC(CopyRange)(&destUri->portText, &sourceUri->portText, URI_FALSE, memory) == URI_FALSE) { |
| 277 | + URI_FUNC(PreventLeakage)(destUri, URI_NORMALIZE_HOST, memory); |
| 278 | + return URI_ERROR_MALLOC; |
| 279 | + } |
| 280 | + |
| 281 | + if (sourceUri->pathHead != NULL && sourceUri->pathTail != NULL) { |
| 282 | + destUri->pathHead = memory->malloc(memory, sizeof(URI_TYPE(PathSegment))); |
| 283 | + if (destUri->pathHead == NULL) { |
| 284 | + URI_FUNC(PreventLeakage)(destUri, URI_NORMALIZE_PATH, memory); |
| 285 | + return URI_ERROR_MALLOC; |
| 286 | + } |
| 287 | + if (URI_FUNC(CopyRange)(&destUri->pathHead->text, &sourceUri->pathHead->text, URI_TRUE, memory) == URI_FALSE) { |
| 288 | + URI_FUNC(PreventLeakage)(destUri, URI_NORMALIZE_PATH, memory); |
| 289 | + return URI_ERROR_MALLOC; |
| 290 | + } |
| 291 | + destUri->pathHead->reserved = NULL; |
| 292 | + |
| 293 | + URI_TYPE(PathSegment) *p = sourceUri->pathHead->next; |
| 294 | + URI_TYPE(PathSegment) *newP = destUri->pathHead; |
| 295 | + while (p != NULL && (p->text.first != p->text.afterLast || p->text.first == URI_FUNC(SafeToPointTo))) { |
| 296 | + newP->next = memory->malloc(memory, sizeof(URI_TYPE(PathSegment))); |
| 297 | + if (newP->next == NULL) { |
| 298 | + URI_FUNC(PreventLeakage)(destUri, URI_NORMALIZE_PATH, memory); |
| 299 | + return URI_ERROR_MALLOC; |
| 300 | + } |
| 301 | + newP = newP->next; |
| 302 | + if (URI_FUNC(CopyRange)(&newP->text, &p->text, URI_TRUE, memory) == URI_FALSE) { |
| 303 | + URI_FUNC(PreventLeakage)(destUri, URI_NORMALIZE_PATH, memory); |
| 304 | + return URI_ERROR_MALLOC; |
| 305 | + } |
| 306 | + newP->reserved = NULL; |
| 307 | + p = p->next; |
| 308 | + } |
| 309 | + newP->next = NULL; |
| 310 | + destUri->pathTail = newP; |
| 311 | + } else { |
| 312 | + destUri->pathHead = NULL; |
| 313 | + destUri->pathTail = NULL; |
| 314 | + } |
| 315 | + |
| 316 | + if (URI_FUNC(CopyRange)(&destUri->query, &sourceUri->query, URI_FALSE, memory) == URI_FALSE) { |
| 317 | + URI_FUNC(PreventLeakage)(destUri, URI_NORMALIZE_PATH, memory); |
| 318 | + return URI_ERROR_MALLOC; |
| 319 | + } |
| 320 | + |
| 321 | + if (URI_FUNC(CopyRange)(&destUri->fragment, &sourceUri->fragment, URI_FALSE, memory) == URI_FALSE) { |
| 322 | + URI_FUNC(PreventLeakage)(destUri, URI_NORMALIZE_QUERY, memory); |
| 323 | + return URI_ERROR_MALLOC; |
| 324 | + } |
| 325 | + |
| 326 | + destUri->absolutePath = sourceUri->absolutePath; |
| 327 | + destUri->owner = URI_TRUE; |
| 328 | + destUri->reserved = NULL; |
| 329 | + |
| 330 | + return URI_SUCCESS; |
| 331 | +} |
| 332 | + |
| 333 | + |
| 334 | + |
| 335 | +int URI_FUNC(CopyUri)(URI_TYPE(Uri) * destUri, |
| 336 | + const URI_TYPE(Uri) * sourceUri) { |
| 337 | + return URI_FUNC(CopyUriMm)(destUri, sourceUri, NULL); |
| 338 | +} |
| 339 | + |
| 340 | + |
| 341 | + |
122 | 342 | UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,
|
123 | 343 | UriBool relative, UriBool pathOwned, UriMemoryManager * memory) {
|
124 | 344 | URI_TYPE(PathSegment) * walker;
|
|
0 commit comments