/***************************************************************************
*
* Copyright 2001,2011,2013 by Sean Conner.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, see .
*
* Comments, questions and criticisms can be sent to: sean@conman.org
*
*************************************************************************/
#ifdef __GNUC__
# define _GNU_SOURCE
#endif
#include
#include
#include
#include
#include
#include "../url.h"
/**********************************************************************/
static int http_new (url__t *restrict,char const *restrict);
static int http_compare (url__t const *const restrict,url__t const *const restrict);
static size_t http_makestring (url__t const *const restrict,char *restrict,size_t);
static void http_free (url__t *);
/***********************************************************************/
struct urlvector const g_httpvec =
{
http_new,
http_compare,
http_makestring,
http_free
};
/********************************************************************/
static int http_new(url__t *restrict url,char const *surl)
{
urlhttp__t *hurl = &url->http;
char tmpbuf[BUFSIZ];
size_t tmpsz;
assert(url != NULL);
assert(surl != NULL);
/*-----------------------------------------------------------------
; at this point, durl->protocol is set, and url points just past the
; ':' in the url spec
;
; durl->vector is also set.
;
; The spec (RFC-1808) is
; http:[//host.domain.top[:port]][/path/file[;parms][?query][#fragment]]
;
; technically, everything but the scheme may be absent, but for now,
; we're hacking it up a bit ...
;
; we're also ignoring the parms portion for now.
;-----------------------------------------------------------------*/
/*------------------------------------------------
; host portion, if any
;-------------------------------------------------*/
UrlGetHost(tmpbuf,BUFSIZ,&surl);
hurl->host = strdup(tmpbuf);
/*-------------------------------------------------------
; optional port number
;------------------------------------------------------*/
tmpsz = UrlGetPort(tmpbuf,BUFSIZ,&surl);
if (tmpsz)
{
long lport;
errno = 0;
lport = strtol(tmpbuf,NULL,10);
if ((errno == ERANGE) && ((lport == LONG_MAX) || (lport == LONG_MIN)))
return(ERANGE);
if ((lport < 0) || (lport > PORTMAX))
return(EDOM);
hurl->port = lport;
}
else
{
if (hurl->scheme == URL_HTTP)
hurl->port = 80;
else
hurl->port = 443;
}
/*------------------------------------------------------------------
; parse the file part
;-----------------------------------------------------------------*/
tmpsz = UrlGetFile(tmpbuf,BUFSIZ,&surl);
if (tmpsz)
hurl->path = strdup(tmpbuf);
else
hurl->path = strdup("/");
/*------------------------------------------------------
; params, query and fragment parts
;-------------------------------------------------------*/
if (*surl == '?') /* query part */
{
surl++;
tmpsz = UrlGetFile(tmpbuf,BUFSIZ,&surl);
if (tmpsz)
hurl->query = strdup(tmpbuf);
else
hurl->query = strdup("");
}
else
hurl->query = strdup("");
/*---------------------------------------------------------------
; fragment part (of file) if any
;----------------------------------------------------------------*/
if (*surl == '#')
hurl->fragment = strdup(++surl);
else
hurl->fragment = strdup("");
return(0);
}
/**********************************************************************/
static int http_compare(
url__t const *const restrict durl,
url__t const *const restrict surl
)
{
int rc;
assert(durl != NULL);
assert((durl->scheme == URL_HTTP) || (durl->scheme == URL_HTTPS));
assert(surl != NULL);
assert(surl->scheme < URL_max);
rc = durl->scheme - surl->scheme;
if (rc != 0) return rc;
rc = strcmp(durl->http.host,surl->http.host);
if (rc != 0) return rc;
rc = durl->http.port - surl->http.port;
if (rc != 0) return rc;
rc = strcmp(durl->http.path,surl->http.path);
if (rc != 0) return rc;
rc = strcmp(durl->http.query,surl->http.query);
if (rc != 0) return rc;
return strcmp(durl->http.fragment,surl->http.fragment);
}
/**********************************************************************/
static size_t http_makestring(
url__t const *const restrict url,
char *restrict d,
size_t sd
)
{
char port[7];
assert(url != NULL);
assert((url->scheme == URL_HTTP) || (url->scheme == URL_HTTPS));;
assert(url->http.host != NULL);
assert(url->http.port >= 0);
assert(url->http.port <= PORTMAX);
assert(url->http.path != NULL);
assert(url->http.query != NULL);
assert(url->http.fragment != NULL);
assert(d != NULL);
assert(sd > 0);
if (url->http.port == 80)
port[0] = '\0';
else
snprintf(port,sizeof(port),":%d",url->http.port);
return snprintf(
d,
sd, /* h N p ? q # f */
"http://%s%s%s%s%s%s%s",
url->http.host,
port,
url->http.path,
(*url->http.query != '\0') ? "?" : "",
url->http.query,
(*url->http.fragment != '\0') ? "#" : "",
url->http.fragment
);
}
/***********************************************************************/
static void http_free(url__t *url)
{
assert(url != NULL);
assert((url->scheme == URL_HTTP) || (url->scheme == URL_HTTPS));
free(url->http.host);
free(url->http.path);
free(url->http.query);
free(url->http.fragment);
free(url);
}
/*************************************************************************/
.