204 lines
4.2 KiB
C
204 lines
4.2 KiB
C
|
#include "../include/error.h"
|
||
|
#include "../include/util.h"
|
||
|
#include "../include/url.h"
|
||
|
#include <assert.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
char valid_path[] = "-._~:/?#[]@!$&'()*+,;%=";
|
||
|
|
||
|
typedef enum lm_state {
|
||
|
URL_PROTOCOL_0 = 0,
|
||
|
URL_SPLIT_1 = 1,
|
||
|
URL_HOST_2 = 2,
|
||
|
URL_PATH_3 = 3,
|
||
|
} lm_state_t;
|
||
|
|
||
|
uint16_t lm_url_default(char *protocol){
|
||
|
if(eq(protocol, "ftp"))
|
||
|
return 21;
|
||
|
else if(eq(protocol, "ftps"))
|
||
|
return 990;
|
||
|
else if(eq(protocol, "http"))
|
||
|
return 80;
|
||
|
else if(eq(protocol, "https"))
|
||
|
return 443;
|
||
|
else if(eq(protocol, "mptp"))
|
||
|
return 5858;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
bool lm_url_parse(lm_url_t *url, char *str){
|
||
|
// clear out every variable
|
||
|
bzero(url->protocol, sizeof(url->protocol));
|
||
|
url->host = NULL;
|
||
|
url->path = NULL;
|
||
|
url->port = 0;
|
||
|
|
||
|
// stores the string size
|
||
|
size_t strl = 0, index = 0, pos = 0;
|
||
|
|
||
|
// make sure the URL string size is not too large
|
||
|
// extra 4 for "://" and ":"
|
||
|
if((strl = strlen(str)) > URL_PROTOCOL_MAX+URL_PATH_MAX+URL_HOST_MAX+4){
|
||
|
lm_error_set(LM_ERR_URLTooLarge);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
lm_state_t state = URL_PROTOCOL_0;
|
||
|
char buffer[strl+1]; // temporary buffer
|
||
|
bool ret = false; // return value
|
||
|
|
||
|
// clear out the temporary buffer
|
||
|
bzero(buffer, strl+1);
|
||
|
|
||
|
while ((buffer[index] = *(str+pos)) != 0) {
|
||
|
switch (state) {
|
||
|
case URL_PROTOCOL_0:
|
||
|
if(index > URL_PROTOCOL_MAX){
|
||
|
lm_error_set(LM_ERR_URLBadProtocol);
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
if (!is_letter(buffer[index]) && !is_digit(buffer[index]) && buffer[index] != ':'){
|
||
|
lm_error_set(LM_ERR_URLBadChar);
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
if(buffer[index] != ':')
|
||
|
break;
|
||
|
|
||
|
if(0 == index){
|
||
|
lm_error_set(LM_ERR_URLBadProtocol);
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
buffer[index] = 0;
|
||
|
memcpy(url->protocol, buffer, index+1);
|
||
|
goto next;
|
||
|
|
||
|
case URL_SPLIT_1:
|
||
|
if(index > 1){
|
||
|
lm_error_set(LM_ERR_URLBadProtocol);
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
if (buffer[index] != '/'){
|
||
|
lm_error_set(LM_ERR_URLBadChar);
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
if(index != 1)
|
||
|
break;
|
||
|
|
||
|
if(buffer[index-1] != '/' || buffer[index] != '/'){
|
||
|
lm_error_set(LM_ERR_URLBadProtocol);
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
goto next;
|
||
|
|
||
|
case URL_HOST_2:
|
||
|
if(index > URL_HOST_MAX){
|
||
|
lm_error_set(LM_ERR_URLHostLarge);
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
if (!is_letter(buffer[index]) && !is_digit(buffer[index]) && buffer[index] != '.' && buffer[index] != ':' && buffer[index] != '/'){
|
||
|
lm_error_set(LM_ERR_URLBadChar);
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
if(buffer[index] != '/')
|
||
|
break;
|
||
|
|
||
|
if(index == 0){
|
||
|
lm_error_set(LM_ERR_URLBadHost);
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
buffer[index] = 0;
|
||
|
url->host = malloc((index+1)*sizeof(char));
|
||
|
memcpy(url->host, buffer, index+1);
|
||
|
goto next;
|
||
|
|
||
|
case URL_PATH_3:
|
||
|
if(index > URL_PATH_MAX){
|
||
|
lm_error_set(LM_ERR_URLPathLarge);
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
if (!is_letter(buffer[index]) && !is_digit(buffer[index]) && !contains(valid_path, buffer[index])){
|
||
|
lm_error_set(LM_ERR_URLBadChar);
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
assert(false);
|
||
|
}
|
||
|
|
||
|
index++;
|
||
|
pos++;
|
||
|
continue;
|
||
|
|
||
|
next:
|
||
|
bzero(buffer, strl+1);
|
||
|
state++;
|
||
|
index = 0;
|
||
|
pos++;
|
||
|
}
|
||
|
|
||
|
switch (state) {
|
||
|
case URL_HOST_2:
|
||
|
if(index == 0){
|
||
|
lm_error_set(LM_ERR_URLBadHost);
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
if(index > URL_HOST_MAX){
|
||
|
lm_error_set(LM_ERR_URLHostLarge);
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
url->host = malloc((index+1)*sizeof(char));
|
||
|
memcpy(url->host, buffer, index+1);
|
||
|
|
||
|
url->path = malloc(2*sizeof(char));
|
||
|
url->path[0] = '/';
|
||
|
url->path[1] = 0;
|
||
|
break;
|
||
|
|
||
|
case URL_PATH_3:
|
||
|
url->path = malloc((index+2)*sizeof(char));
|
||
|
url->path[0] = '/';
|
||
|
memcpy(url->path+1, buffer, index+1);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
lm_error_set(LM_ERR_URLEnd);
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
ret = true;
|
||
|
|
||
|
end:
|
||
|
if(!ret && NULL != url->host)
|
||
|
free(url->host);
|
||
|
|
||
|
if(!ret && NULL != url->path)
|
||
|
free(url->path);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void lm_url_free(lm_url_t *url){
|
||
|
if(NULL != url->host)
|
||
|
free(url->host);
|
||
|
|
||
|
if(NULL != url->path)
|
||
|
free(url->path);
|
||
|
}
|