114 lines
3.5 KiB
C
114 lines
3.5 KiB
C
#include "maze32_provisioning_protocol.h"
|
|
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
|
|
static const char *skip_space(const char *cursor, const char *end)
|
|
{
|
|
while (cursor < end && isspace((unsigned char)*cursor)) {
|
|
++cursor;
|
|
}
|
|
return cursor;
|
|
}
|
|
|
|
static int parse_json_string(const char **cursor_pointer,
|
|
const char *end,
|
|
char *output,
|
|
size_t capacity)
|
|
{
|
|
const char *cursor = *cursor_pointer;
|
|
size_t length = 0U;
|
|
if (cursor >= end || *cursor++ != '"') {
|
|
return 0;
|
|
}
|
|
while (cursor < end && *cursor != '"') {
|
|
unsigned char value = (unsigned char)*cursor++;
|
|
if (value == '\\') {
|
|
if (cursor >= end) {
|
|
return 0;
|
|
}
|
|
char escaped = *cursor++;
|
|
if (escaped == '"' || escaped == '\\' || escaped == '/') {
|
|
value = (unsigned char)escaped;
|
|
} else if (escaped == 'b') {
|
|
value = '\b';
|
|
} else if (escaped == 'f') {
|
|
value = '\f';
|
|
} else if (escaped == 'n') {
|
|
value = '\n';
|
|
} else if (escaped == 'r') {
|
|
value = '\r';
|
|
} else if (escaped == 't') {
|
|
value = '\t';
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
if (value < 0x20U || length + 1U >= capacity) {
|
|
return 0;
|
|
}
|
|
output[length++] = (char)value;
|
|
}
|
|
if (cursor >= end || *cursor++ != '"') {
|
|
return 0;
|
|
}
|
|
output[length] = '\0';
|
|
*cursor_pointer = cursor;
|
|
return 1;
|
|
}
|
|
|
|
int maze32_provisioning_parse_credentials(const char *body,
|
|
size_t length,
|
|
maze32_wifi_credentials_t *credentials)
|
|
{
|
|
if (body == NULL || credentials == NULL) {
|
|
return 0;
|
|
}
|
|
const char *cursor = body;
|
|
const char *end = body + length;
|
|
int have_ssid = 0;
|
|
int have_password = 0;
|
|
memset(credentials, 0, sizeof(*credentials));
|
|
cursor = skip_space(cursor, end);
|
|
if (cursor >= end || *cursor++ != '{') {
|
|
return 0;
|
|
}
|
|
for (int field_index = 0; field_index < 2; ++field_index) {
|
|
char key[12];
|
|
char value[MAZE32_WIFI_PASSWORD_MAX_BYTES + 1U];
|
|
cursor = skip_space(cursor, end);
|
|
if (!parse_json_string(&cursor, end, key, sizeof(key))) {
|
|
return 0;
|
|
}
|
|
cursor = skip_space(cursor, end);
|
|
if (cursor >= end || *cursor++ != ':') {
|
|
return 0;
|
|
}
|
|
cursor = skip_space(cursor, end);
|
|
if (!parse_json_string(&cursor, end, value, sizeof(value))) {
|
|
return 0;
|
|
}
|
|
if (strcmp(key, "ssid") == 0 && !have_ssid &&
|
|
strlen(value) <= MAZE32_WIFI_SSID_MAX_BYTES) {
|
|
memcpy(credentials->ssid, value, strlen(value) + 1U);
|
|
have_ssid = 1;
|
|
} else if (strcmp(key, "password") == 0 && !have_password) {
|
|
memcpy(credentials->password, value, strlen(value) + 1U);
|
|
have_password = 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
cursor = skip_space(cursor, end);
|
|
if (field_index == 0 && (cursor >= end || *cursor++ != ',')) {
|
|
return 0;
|
|
}
|
|
}
|
|
cursor = skip_space(cursor, end);
|
|
if (cursor >= end || *cursor++ != '}') {
|
|
return 0;
|
|
}
|
|
cursor = skip_space(cursor, end);
|
|
return cursor == end && have_ssid && have_password &&
|
|
maze32_wifi_credentials_validate(credentials) == MAZE32_WIFI_CONFIG_VALID;
|
|
}
|