mirror of
https://github.com/tursodatabase/libsql.git
synced 2025-03-08 23:41:50 +00:00
A common complain with libSQL is how to run extensions. The main mechanism, with a .so, has a lot of issues around how those .so are distributed. The most common extensions are the ones in the sqlean package. We can improve this experience by bundling them in our sqlite build. Not all SQLean extensions are kosher: some of them, like fileio, use the vfs. Others, are deemed too complex. The extensions included here are a subset that we deem important enough, and low risk enough, to just be a part of the main bundle.
83 lines
2.0 KiB
C
83 lines
2.0 KiB
C
// Originally by Fränz Friederes, MIT License
|
|
// https://github.com/cryptii/cryptii/blob/main/src/Encoder/URL.js
|
|
|
|
// Modified by Anton Zhiyanov, MIT License
|
|
// https://github.com/nalgeon/sqlean/
|
|
|
|
// URL-escape encoding/decoding
|
|
|
|
#include <ctype.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
const char* url_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~";
|
|
|
|
uint8_t hex_to_ascii(char c) {
|
|
if (isdigit(c)) {
|
|
return c - '0';
|
|
} else {
|
|
return tolower(c) - 'a' + 10;
|
|
}
|
|
}
|
|
|
|
uint8_t* url_encode(const uint8_t* src, size_t len, size_t* out_len) {
|
|
size_t encoded_len = 0;
|
|
for (size_t i = 0; i < len; i++) {
|
|
if (strchr(url_chars, src[i]) == NULL) {
|
|
encoded_len += 3;
|
|
} else {
|
|
encoded_len += 1;
|
|
}
|
|
}
|
|
|
|
uint8_t* encoded = malloc(encoded_len + 1);
|
|
if (encoded == NULL) {
|
|
*out_len = 0;
|
|
return NULL;
|
|
}
|
|
|
|
size_t pos = 0;
|
|
for (size_t i = 0; i < len; i++) {
|
|
if (strchr(url_chars, src[i]) == NULL) {
|
|
encoded[pos++] = '%';
|
|
encoded[pos++] = "0123456789ABCDEF"[src[i] >> 4];
|
|
encoded[pos++] = "0123456789ABCDEF"[src[i] & 0x0F];
|
|
} else {
|
|
encoded[pos++] = src[i];
|
|
}
|
|
}
|
|
encoded[pos] = '\0';
|
|
|
|
*out_len = pos;
|
|
return encoded;
|
|
}
|
|
|
|
uint8_t* url_decode(const uint8_t* src, size_t len, size_t* out_len) {
|
|
uint8_t* decoded = malloc(len);
|
|
if (decoded == NULL) {
|
|
*out_len = 0;
|
|
return NULL;
|
|
}
|
|
|
|
size_t pos = 0;
|
|
for (size_t i = 0; i < len; i++) {
|
|
if (src[i] == '%') {
|
|
if (i + 2 >= len || !isxdigit(src[i + 1]) || !isxdigit(src[i + 2])) {
|
|
free(decoded);
|
|
return NULL;
|
|
}
|
|
decoded[pos++] = (hex_to_ascii(src[i + 1]) << 4) | hex_to_ascii(src[i + 2]);
|
|
i += 2;
|
|
} else if (src[i] == '+') {
|
|
decoded[pos++] = ' ';
|
|
} else {
|
|
decoded[pos++] = src[i];
|
|
}
|
|
}
|
|
|
|
*out_len = pos;
|
|
return decoded;
|
|
}
|