scorpius/lib/url.c

177 lines
3.1 KiB
C

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifdef TESTURLLIB
typedef struct _url {
char *scheme;
char *host;
char *port;
char *path;
} Url;
int
main (void)
{
return 0;
}
#endif
Url*
urllib_init (void)
{
Url *url = malloc (sizeof (Url));
url->scheme = NULL;
url->host = NULL;
url->port = NULL;
url->path = NULL;
return url;
}
void
urllib_free (Url *url)
{
free (url->scheme);
free (url->host);
free (url->port);
free (url->path);
free (url);
}
/* check this parser : http://draft.scyphus.co.jp/lang/c/url_parser.html not perfect but could give ideas */
int
urllib_parse (Url *url, const char *url_string)
{
char *cursor = url_string;
char *tmpcursor = NULL;
int len;
/* get scheme */
tmpcursor = strchr (cursor, ':');
if (tmpcursor == NULL)
return 1;//error if not found
len = tmpcursor - cursor;
/* Verify scheme syntax */
if (!isalpha (cursor[0]))
return 1;
for (i = 1; i < len; i++)
if (!(isalnum(cursor[i]) || cursor[i] == '+' || cursor[i] == '-' || cursor[i] == '.'))
return 1;
url->scheme = malloc (sizeof (char) * (len + 1));
if (url->scheme == NULL)
return 1;
strncpy (url->scheme, cursor, len);
url->scheme[len] = '\0';
//Move after first ':'
cursor = tmpcursor + 1;
if (strlen (cursor) <= 2)
return 1;//There must be 2 '/' and an host
if (cursor[0] != '/' || cursor[1] != '/')
return 1;
//parse IPv6, IPv4 or hostname
cursor += 2;
if (cursor[0] == '[') // IPv6
{
tmpcursor = strchr (cursor, ']');
if (tmpcursor == NULL)
return 1;
len = tmpcursor - cursor
for (i = 1; i < len - 1; i++)//verify
if (!isdigit (cursor[i]) && !(tolower(cursor[i]) >= 'a' && tolower(cursor[i]) <= 'f') && !(cursor[i] == ':'))
return 1;
}
else // IPv4 or hostname
{
tmpcursor = strchr (cursor, ':');
if (tmpcursor == NULL)
tmpcursor = strchr (cursor, '/');
if (tmpcursor == NULL)
return 1;
//missing case when no tailing / and no : (only host) (test \0 ?, or len = strlen)
len = tmpcursor - cursor;
for (i = 0, i < len; i++)
if (!isalnum (cursor[i]) && !(cursor[i] == '.'))
return 1;
}
url->host = malloc (sizeof (char) * (len + 1));
if (url->host == NULL)
return 1;
strncpy (url->host, cursor, len);
url->host[len] = '\0';
//parse port (or not)
cursor += len + 1;
if (cursor[0] == ':')
{
tmpcursor = strchr (cursor, '/');
if (tmpcursor == NULL)
len = strlen (cursor);
else
len = tmpcursor - cursor;
for (i = 1; i < len; i++)
if (!isdigit (cursor[i]))
return 1;
url->port = malloc (sizeof (char) * len);
if (url->port == NULL)
return 1;
strncpy (url->port, cursor + 1, len - 1);
cursor += len;
}
//parse path
len = strlen (cursor);
if (len > 0)
{
url->path = malloc (sizeof (char) * (len + 1));
if (url->path == NULL)
return 1;
strncpy (url->path, cursor, len);
}
return 0;
//is there a path ? (test \0)
}
void
urllib_tostring (Url *url, char *dest)
{
if (url->port == NULL)
sprintf (dest, "%s://%s/%s\r\n", url->scheme, url->host, url->path);
else
sprintf (dest, "%s://%s:%s/%s\r\n", url->scheme, url->host, url->port, url->path);
}
void
urllib_join (Url *url, const char *path)
{}