/
singlwolf
/
Radiola-2S3
Обзор
Документация
Войти
/
singlwolf
/
Radiola-2S3
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
lib/url_parser/url_parser.cpp
202 строки
5 KB
SinglWolf
Public access
27 мар 2026, 07:00
27 мар 2026, 07:00
642fcfc
Код
Авторство
О чём код?
/* * url_parser.c * * This is a wrapper around http_parser_url to simplify usage. * * Created on: 29.03.2017 * Author: michaelboeckling */ #include <stdlib.h> #include <stdint.h> #include <string.h> #include <stdio.h> #include "esp_log.h" #include "http_parser.h" #include "url_parser.h" #define TAG "url_parser" static char *url_get_nested(const char *path) { if (path == NULL) return NULL; const char *sep = strstr(path, "://"); if (sep == NULL) return NULL; const char *start = strstr(path, "http"); if (start && start < sep) { return strdup(start); } return NULL; } static char *url_get_extension(struct http_parser_url *url, const char *uri) { if (!(url->field_set & (1 << UF_PATH))) return NULL; const char *last_dot = NULL; const char *last_slash = NULL; for (size_t i = 0; i < url->field_data[UF_PATH].len; i++) { if (uri[url->field_data[UF_PATH].off + i] == '/') last_slash = &uri[url->field_data[UF_PATH].off + i]; if (uri[url->field_data[UF_PATH].off + i] == '.') last_dot = &uri[url->field_data[UF_PATH].off + i]; } if (last_dot && (!last_slash || last_dot > last_slash)) { size_t ext_len = (uri + url->field_data[UF_PATH].off + url->field_data[UF_PATH].len) - last_dot - 1; if (ext_len > 0 && ext_len < 6) return strndup(last_dot + 1, ext_len); } return NULL; } static char *url_get_scheme(struct http_parser_url *url, const char *uri) { return strndup(&uri[url->field_data[UF_SCHEMA].off], url->field_data[UF_SCHEMA].len); } static char *url_get_host(struct http_parser_url *url, const char *uri) { return strndup(&uri[url->field_data[UF_HOST].off], url->field_data[UF_HOST].len); } static uint16_t url_get_port(struct http_parser_url *url) { uint16_t port; if (url->field_set & (1 << UF_PORT)) { port = url->port; } else { // assume: 4 = http, 5 = https port = (url->field_data[UF_SCHEMA].len == 5) ? 443 : 80; } return port; } static char *url_get_authority(struct http_parser_url *url, const char *uri) { char *authority; /* MAX 5 digits (max 65535) + 1 ':' + 1 NULL (because of snprintf) */ size_t extra = 7; uint16_t authoritylen = url->field_data[UF_HOST].len; authority = (char *)calloc(authoritylen + extra, sizeof(char)); memcpy(authority, &uri[url->field_data[UF_HOST].off], url->field_data[UF_HOST].len); /* maybe add port */ if (url->field_set & (1 << UF_PORT)) { authoritylen += (size_t)snprintf(authority + authoritylen, extra, ":%u", url->port); } authority[authoritylen] = '\0'; return authority; } static char *url_get_path(struct http_parser_url *url, const char *uri) { /* path */ char *path; /* If we don't have path in URI, we use "/" as path. */ uint16_t pathlen = 1; if (url->field_set & (1 << UF_PATH)) { pathlen = url->field_data[UF_PATH].len; } if (url->field_set & (1 << UF_QUERY)) { /* +1 for '?' character */ pathlen += (size_t)(url->field_data[UF_QUERY].len + 1); } /* +1 for \0 */ path = (char *)malloc(pathlen + 1); if (url->field_set & (1 << UF_PATH)) { memcpy(path, &uri[url->field_data[UF_PATH].off], url->field_data[UF_PATH].len); } else { path[0] = '/'; } if (url->field_set & (1 << UF_QUERY)) { path[pathlen - url->field_data[UF_QUERY].len - 1] = '?'; memcpy( path + pathlen - url->field_data[UF_QUERY].len, &uri[url->field_data[UF_QUERY].off], url->field_data[UF_QUERY].len); } path[pathlen] = '\0'; return path; } url_t *url_parse(const char *uri) { struct http_parser_url *url_parser = (struct http_parser_url *)calloc(1, sizeof(struct http_parser_url)); if (url_parser == NULL) { ESP_LOGE(TAG, "could not allocate http_parser_url"); return NULL; } int ret = http_parser_parse_url(uri, strlen(uri), 0, url_parser); if (ret != 0) { ESP_LOGE(TAG, "Could not parse URI %s", uri); free(url_parser); return NULL; } url_t *url = (url_t *)calloc(1, sizeof(url_t)); if (url == NULL) { ESP_LOGE(TAG, "could not allocate url_t"); free(url_parser); return NULL; } url->scheme = url_get_scheme(url_parser, uri); url->host = url_get_host(url_parser, uri); url->port = url_get_port(url_parser); url->authority = url_get_authority(url_parser, uri); url->path = url_get_path(url_parser, uri); url->extension = url_get_extension(url_parser, uri); url->redirect_url = url_get_nested(url->path); free(url_parser); return url; } void url_free(url_t *url) { if (url == NULL) return; if (url->scheme != NULL) free(url->scheme); if (url->host != NULL) free(url->host); if (url->authority != NULL) free(url->authority); if (url->path != NULL) free(url->path); if (url->extension != NULL) free(url->extension); if (url->redirect_url != NULL) free(url->redirect_url); free(url); }