mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-09 12:54:23 +01:00
Simplified http.c.
This commit is contained in:
parent
5b40b56647
commit
be622bd268
@ -1,3 +1,17 @@
|
|||||||
|
2010-08-05 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* estream.h (es_asprintf, es_vasprintf): Add lost prototyps.
|
||||||
|
|
||||||
|
* http.c: Require estream and make HTTP_USE_ESTREAM obsolete. It
|
||||||
|
make the code unreadable and we require estream anyway for GnuPG.
|
||||||
|
(http_wait_response): Get use of cookies right.
|
||||||
|
(send_request): s/xtryasprintf/es_asprintf/ to allow standalone
|
||||||
|
use of the code.
|
||||||
|
(insert_escapes, connect_server): s/sprintf/snprintf/.
|
||||||
|
(parse_response): s/my_read_line/es_read_line/.
|
||||||
|
(my_read_line): Remove.
|
||||||
|
(write_server): Use pth_write.
|
||||||
|
|
||||||
2010-07-26 Werner Koch <wk@g10code.com>
|
2010-07-26 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* estream.c (es_func_fp_write) [W32]: Write smaller chunks.
|
* estream.c (es_func_fp_write) [W32]: Write smaller chunks.
|
||||||
|
@ -352,6 +352,11 @@ int es_vfprintf_unlocked (estream_t ES__RESTRICT stream,
|
|||||||
const char *ES__RESTRICT format, va_list ap)
|
const char *ES__RESTRICT format, va_list ap)
|
||||||
_ESTREAM_GCC_A_PRINTF(2,0);
|
_ESTREAM_GCC_A_PRINTF(2,0);
|
||||||
|
|
||||||
|
char *es_asprintf (const char *ES__RESTRICT format, ...)
|
||||||
|
_ESTREAM_GCC_A_PRINTF(1,2);
|
||||||
|
char *es_vasprintf (const char *ES__RESTRICT format, va_list ap)
|
||||||
|
_ESTREAM_GCC_A_PRINTF(1,0);
|
||||||
|
|
||||||
int es_setvbuf (estream_t ES__RESTRICT stream,
|
int es_setvbuf (estream_t ES__RESTRICT stream,
|
||||||
char *ES__RESTRICT buf, int mode, size_t size);
|
char *ES__RESTRICT buf, int mode, size_t size);
|
||||||
void es_setbuf (estream_t ES__RESTRICT stream, char *ES__RESTRICT buf);
|
void es_setbuf (estream_t ES__RESTRICT stream, char *ES__RESTRICT buf);
|
||||||
|
268
common/http.c
268
common/http.c
@ -21,11 +21,13 @@
|
|||||||
/* Simple HTTP client implementation. We try to keep the code as
|
/* Simple HTTP client implementation. We try to keep the code as
|
||||||
self-contained as possible. There are some contraints however:
|
self-contained as possible. There are some contraints however:
|
||||||
|
|
||||||
|
- estream is required. We now require estream because it provides a
|
||||||
|
very useful and portable asprintf implementation and the fopencookie
|
||||||
|
function.
|
||||||
- stpcpy is required
|
- stpcpy is required
|
||||||
- fixme: list other requirements.
|
- fixme: list other requirements.
|
||||||
|
|
||||||
|
|
||||||
- With HTTP_USE_ESTREAM defined, all I/O is done through estream.
|
|
||||||
- With HTTP_USE_GNUTLS support for https is provided (this also
|
- With HTTP_USE_GNUTLS support for https is provided (this also
|
||||||
requires estream).
|
requires estream).
|
||||||
- With HTTP_NO_WSASTARTUP the socket initialization is not done
|
- With HTTP_NO_WSASTARTUP the socket initialization is not done
|
||||||
@ -129,18 +131,13 @@ typedef unsigned long longcounter_t;
|
|||||||
# define counter_strtoul(a) strtoul ((a), NULL, 10)
|
# define counter_strtoul(a) strtoul ((a), NULL, 10)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Define a prefix to map stream functions to the estream library. */
|
#if defined(HTTP_USE_ESTREAM) && defined (__GNUC__)
|
||||||
#ifdef HTTP_USE_ESTREAM
|
# warning HTTP_USE_ESTREAM is an obsolete macro
|
||||||
#define P_ES(a) es_ ## a
|
|
||||||
#else
|
|
||||||
#define P_ES(a) a
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HTTP_USE_GNUTLS
|
#ifndef HTTP_USE_GNUTLS
|
||||||
typedef void * gnutls_session_t;
|
typedef void * gnutls_session_t;
|
||||||
#endif
|
#endif
|
||||||
#if defined(HTTP_USE_GNUTLS) && !defined(HTTP_USE_ESTREAM)
|
|
||||||
#error Use of GNUTLS also requires support for Estream
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static gpg_error_t do_parse_uri (parsed_uri_t uri, int only_local_part);
|
static gpg_error_t do_parse_uri (parsed_uri_t uri, int only_local_part);
|
||||||
static int remove_escapes (char *string);
|
static int remove_escapes (char *string);
|
||||||
@ -156,7 +153,6 @@ static int connect_server (const char *server, unsigned short port,
|
|||||||
unsigned int flags, const char *srvtag);
|
unsigned int flags, const char *srvtag);
|
||||||
static gpg_error_t write_server (int sock, const char *data, size_t length);
|
static gpg_error_t write_server (int sock, const char *data, size_t length);
|
||||||
|
|
||||||
#ifdef HTTP_USE_ESTREAM
|
|
||||||
static ssize_t cookie_read (void *cookie, void *buffer, size_t size);
|
static ssize_t cookie_read (void *cookie, void *buffer, size_t size);
|
||||||
static ssize_t cookie_write (void *cookie, const void *buffer, size_t size);
|
static ssize_t cookie_write (void *cookie, const void *buffer, size_t size);
|
||||||
static int cookie_close (void *cookie);
|
static int cookie_close (void *cookie);
|
||||||
@ -187,8 +183,6 @@ struct cookie_s
|
|||||||
};
|
};
|
||||||
typedef struct cookie_s *cookie_t;
|
typedef struct cookie_s *cookie_t;
|
||||||
|
|
||||||
#endif /*HTTP_USE_ESTREAM*/
|
|
||||||
|
|
||||||
#ifdef HTTP_USE_GNUTLS
|
#ifdef HTTP_USE_GNUTLS
|
||||||
static gpg_error_t (*tls_callback) (http_t, gnutls_session_t, int);
|
static gpg_error_t (*tls_callback) (http_t, gnutls_session_t, int);
|
||||||
#endif /*HTTP_USE_GNUTLS*/
|
#endif /*HTTP_USE_GNUTLS*/
|
||||||
@ -211,15 +205,10 @@ struct http_context_s
|
|||||||
int sock;
|
int sock;
|
||||||
unsigned int in_data:1;
|
unsigned int in_data:1;
|
||||||
unsigned int is_http_0_9:1;
|
unsigned int is_http_0_9:1;
|
||||||
#ifdef HTTP_USE_ESTREAM
|
|
||||||
estream_t fp_read;
|
estream_t fp_read;
|
||||||
estream_t fp_write;
|
estream_t fp_write;
|
||||||
void *write_cookie;
|
void *write_cookie;
|
||||||
void *read_cookie;
|
void *read_cookie;
|
||||||
#else /*!HTTP_USE_ESTREAM*/
|
|
||||||
FILE *fp_read;
|
|
||||||
FILE *fp_write;
|
|
||||||
#endif /*!HTTP_USE_ESTREAM*/
|
|
||||||
void *tls_context;
|
void *tls_context;
|
||||||
parsed_uri_t uri;
|
parsed_uri_t uri;
|
||||||
http_req_t req_type;
|
http_req_t req_type;
|
||||||
@ -375,9 +364,9 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url,
|
|||||||
if (!hd->fp_read && !hd->fp_write && hd->sock != -1)
|
if (!hd->fp_read && !hd->fp_write && hd->sock != -1)
|
||||||
sock_close (hd->sock);
|
sock_close (hd->sock);
|
||||||
if (hd->fp_read)
|
if (hd->fp_read)
|
||||||
P_ES(fclose) (hd->fp_read);
|
es_fclose (hd->fp_read);
|
||||||
if (hd->fp_write)
|
if (hd->fp_write)
|
||||||
P_ES(fclose) (hd->fp_write);
|
es_fclose (hd->fp_write);
|
||||||
http_release_parsed_uri (hd->uri);
|
http_release_parsed_uri (hd->uri);
|
||||||
xfree (hd);
|
xfree (hd);
|
||||||
}
|
}
|
||||||
@ -392,17 +381,12 @@ http_start_data (http_t hd)
|
|||||||
{
|
{
|
||||||
if (!hd->in_data)
|
if (!hd->in_data)
|
||||||
{
|
{
|
||||||
#ifdef HTTP_USE_ESTREAM
|
|
||||||
es_fputs ("\r\n", hd->fp_write);
|
es_fputs ("\r\n", hd->fp_write);
|
||||||
es_fflush (hd->fp_write);
|
es_fflush (hd->fp_write);
|
||||||
#else
|
|
||||||
fflush (hd->fp_write);
|
|
||||||
write_server (hd->sock, "\r\n", 2);
|
|
||||||
#endif
|
|
||||||
hd->in_data = 1;
|
hd->in_data = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
P_ES(fflush) (hd->fp_write);
|
es_fflush (hd->fp_write);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -410,42 +394,21 @@ gpg_error_t
|
|||||||
http_wait_response (http_t hd)
|
http_wait_response (http_t hd)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
|
cookie_t cookie;
|
||||||
|
|
||||||
/* Make sure that we are in the data. */
|
/* Make sure that we are in the data. */
|
||||||
http_start_data (hd);
|
http_start_data (hd);
|
||||||
|
|
||||||
/* We dup the socket, to cope with the fact that fclose closes the
|
/* Close the write stream but keep the socket open. */
|
||||||
underlying socket. In TLS mode we don't do that because we can't
|
cookie = hd->write_cookie;
|
||||||
close the socket gnutls is working on; instead we make sure that
|
if (!cookie)
|
||||||
the fclose won't close the socket in this case. */
|
return gpg_error (GPG_ERR_INTERNAL);
|
||||||
#ifdef HTTP_USE_ESTREAM
|
|
||||||
if (hd->write_cookie)
|
|
||||||
{
|
|
||||||
/* The write cookie is only set in the TLS case. */
|
|
||||||
cookie_t cookie = hd->write_cookie;
|
|
||||||
cookie->keep_socket = 1;
|
cookie->keep_socket = 1;
|
||||||
}
|
es_fclose (hd->fp_write);
|
||||||
else
|
|
||||||
#endif /*HTTP_USE_ESTREAM*/
|
|
||||||
{
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
HANDLE handle = (HANDLE)hd->sock;
|
|
||||||
if (!DuplicateHandle (GetCurrentProcess(), handle,
|
|
||||||
GetCurrentProcess(), &handle, 0,
|
|
||||||
TRUE, DUPLICATE_SAME_ACCESS ))
|
|
||||||
return gpg_error_from_syserror ();
|
|
||||||
hd->sock = (int)handle;
|
|
||||||
#else
|
|
||||||
hd->sock = dup (hd->sock);
|
|
||||||
#endif
|
|
||||||
if (hd->sock == -1)
|
|
||||||
return gpg_error_from_syserror ();
|
|
||||||
}
|
|
||||||
P_ES(fclose) (hd->fp_write);
|
|
||||||
hd->fp_write = NULL;
|
hd->fp_write = NULL;
|
||||||
#ifdef HTTP_USE_ESTREAM
|
/* The close has released the cookie and thus we better set it to NULL. */
|
||||||
hd->write_cookie = NULL;
|
hd->write_cookie = NULL;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Shutdown one end of the socket is desired. As per HTTP/1.0 this
|
/* Shutdown one end of the socket is desired. As per HTTP/1.0 this
|
||||||
is not required but some very old servers (e.g. the original pksd
|
is not required but some very old servers (e.g. the original pksd
|
||||||
@ -454,10 +417,7 @@ http_wait_response (http_t hd)
|
|||||||
shutdown (hd->sock, 1);
|
shutdown (hd->sock, 1);
|
||||||
hd->in_data = 0;
|
hd->in_data = 0;
|
||||||
|
|
||||||
#ifdef HTTP_USE_ESTREAM
|
/* Create a new cookie and a stream for reading. */
|
||||||
{
|
|
||||||
cookie_t cookie;
|
|
||||||
|
|
||||||
cookie = xtrycalloc (1, sizeof *cookie);
|
cookie = xtrycalloc (1, sizeof *cookie);
|
||||||
if (!cookie)
|
if (!cookie)
|
||||||
return gpg_error_from_syserror ();
|
return gpg_error_from_syserror ();
|
||||||
@ -465,18 +425,14 @@ http_wait_response (http_t hd)
|
|||||||
if (hd->uri->use_tls)
|
if (hd->uri->use_tls)
|
||||||
cookie->tls_session = hd->tls_context;
|
cookie->tls_session = hd->tls_context;
|
||||||
|
|
||||||
|
hd->read_cookie = cookie;
|
||||||
hd->fp_read = es_fopencookie (cookie, "r", cookie_functions);
|
hd->fp_read = es_fopencookie (cookie, "r", cookie_functions);
|
||||||
if (!hd->fp_read)
|
if (!hd->fp_read)
|
||||||
{
|
{
|
||||||
xfree (cookie);
|
xfree (cookie);
|
||||||
|
hd->read_cookie = NULL;
|
||||||
return gpg_error_from_syserror ();
|
return gpg_error_from_syserror ();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#else /*!HTTP_USE_ESTREAM*/
|
|
||||||
hd->fp_read = fdopen (hd->sock, "r");
|
|
||||||
if (!hd->fp_read)
|
|
||||||
return gpg_error_from_syserror ();
|
|
||||||
#endif /*!HTTP_USE_ESTREAM*/
|
|
||||||
|
|
||||||
err = parse_response (hd);
|
err = parse_response (hd);
|
||||||
return err;
|
return err;
|
||||||
@ -515,9 +471,9 @@ http_close (http_t hd, int keep_read_stream)
|
|||||||
if (!hd->fp_read && !hd->fp_write && hd->sock != -1)
|
if (!hd->fp_read && !hd->fp_write && hd->sock != -1)
|
||||||
sock_close (hd->sock);
|
sock_close (hd->sock);
|
||||||
if (hd->fp_read && !keep_read_stream)
|
if (hd->fp_read && !keep_read_stream)
|
||||||
P_ES(fclose) (hd->fp_read);
|
es_fclose (hd->fp_read);
|
||||||
if (hd->fp_write)
|
if (hd->fp_write)
|
||||||
P_ES(fclose) (hd->fp_write);
|
es_fclose (hd->fp_write);
|
||||||
http_release_parsed_uri (hd->uri);
|
http_release_parsed_uri (hd->uri);
|
||||||
while (hd->headers)
|
while (hd->headers)
|
||||||
{
|
{
|
||||||
@ -531,29 +487,18 @@ http_close (http_t hd, int keep_read_stream)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef HTTP_USE_ESTREAM
|
|
||||||
estream_t
|
estream_t
|
||||||
http_get_read_ptr (http_t hd)
|
http_get_read_ptr (http_t hd)
|
||||||
{
|
{
|
||||||
return hd?hd->fp_read:NULL;
|
return hd?hd->fp_read:NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
estream_t
|
estream_t
|
||||||
http_get_write_ptr (http_t hd)
|
http_get_write_ptr (http_t hd)
|
||||||
{
|
{
|
||||||
return hd?hd->fp_write:NULL;
|
return hd?hd->fp_write:NULL;
|
||||||
}
|
}
|
||||||
#else /*!HTTP_USE_ESTREAM*/
|
|
||||||
FILE *
|
|
||||||
http_get_read_ptr (http_t hd)
|
|
||||||
{
|
|
||||||
return hd?hd->fp_read:NULL;
|
|
||||||
}
|
|
||||||
FILE *
|
|
||||||
http_get_write_ptr (http_t hd)
|
|
||||||
{
|
|
||||||
return hd?hd->fp_write:NULL;
|
|
||||||
}
|
|
||||||
#endif /*!HTTP_USE_ESTREAM*/
|
|
||||||
unsigned int
|
unsigned int
|
||||||
http_get_status_code (http_t hd)
|
http_get_status_code (http_t hd)
|
||||||
{
|
{
|
||||||
@ -794,7 +739,7 @@ insert_escapes (char *buffer, const char *string,
|
|||||||
{
|
{
|
||||||
if (buffer)
|
if (buffer)
|
||||||
{
|
{
|
||||||
sprintf (buffer, "%%%02X", *s);
|
snprintf (buffer, 4, "%%%02X", *s);
|
||||||
buffer += 3;
|
buffer += 3;
|
||||||
}
|
}
|
||||||
n += 3;
|
n += 3;
|
||||||
@ -1017,7 +962,7 @@ send_request (http_t hd, const char *auth,
|
|||||||
|
|
||||||
if (http_proxy && *http_proxy)
|
if (http_proxy && *http_proxy)
|
||||||
{
|
{
|
||||||
request = xtryasprintf
|
request = es_asprintf
|
||||||
("%s http://%s:%hu%s%s HTTP/1.0\r\n%s%s",
|
("%s http://%s:%hu%s%s HTTP/1.0\r\n%s%s",
|
||||||
hd->req_type == HTTP_REQ_GET ? "GET" :
|
hd->req_type == HTTP_REQ_GET ? "GET" :
|
||||||
hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
|
hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
|
||||||
@ -1035,7 +980,7 @@ send_request (http_t hd, const char *auth,
|
|||||||
else
|
else
|
||||||
snprintf (portstr, sizeof portstr, ":%u", port);
|
snprintf (portstr, sizeof portstr, ":%u", port);
|
||||||
|
|
||||||
request = xtryasprintf
|
request = es_asprintf
|
||||||
("%s %s%s HTTP/1.0\r\nHost: %s%s\r\n%s",
|
("%s %s%s HTTP/1.0\r\nHost: %s%s\r\n%s",
|
||||||
hd->req_type == HTTP_REQ_GET ? "GET" :
|
hd->req_type == HTTP_REQ_GET ? "GET" :
|
||||||
hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
|
hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
|
||||||
@ -1053,7 +998,6 @@ send_request (http_t hd, const char *auth,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef HTTP_USE_ESTREAM
|
|
||||||
/* First setup estream so that we can write even the first line
|
/* First setup estream so that we can write even the first line
|
||||||
using estream. This is also required for the sake of gnutls. */
|
using estream. This is also required for the sake of gnutls. */
|
||||||
{
|
{
|
||||||
@ -1066,16 +1010,15 @@ send_request (http_t hd, const char *auth,
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
cookie->fd = hd->sock;
|
cookie->fd = hd->sock;
|
||||||
if (hd->uri->use_tls)
|
|
||||||
{
|
|
||||||
cookie->tls_session = tls_session;
|
|
||||||
hd->write_cookie = cookie;
|
hd->write_cookie = cookie;
|
||||||
}
|
if (hd->uri->use_tls)
|
||||||
|
cookie->tls_session = tls_session;
|
||||||
|
|
||||||
hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
|
hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
|
||||||
if (!hd->fp_write)
|
if (!hd->fp_write)
|
||||||
{
|
{
|
||||||
xfree (cookie);
|
xfree (cookie);
|
||||||
|
hd->write_cookie = NULL;
|
||||||
err = gpg_error_from_syserror ();
|
err = gpg_error_from_syserror ();
|
||||||
}
|
}
|
||||||
else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write))
|
else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write))
|
||||||
@ -1083,8 +1026,9 @@ send_request (http_t hd, const char *auth,
|
|||||||
else
|
else
|
||||||
err = 0;
|
err = 0;
|
||||||
|
|
||||||
if(err==0)
|
if (!err)
|
||||||
for(;headers;headers=headers->next)
|
{
|
||||||
|
for (;headers; headers=headers->next)
|
||||||
{
|
{
|
||||||
if ((es_fputs (headers->d, hd->fp_write) || es_fflush (hd->fp_write))
|
if ((es_fputs (headers->d, hd->fp_write) || es_fflush (hd->fp_write))
|
||||||
|| (es_fputs("\r\n",hd->fp_write) || es_fflush(hd->fp_write)))
|
|| (es_fputs("\r\n",hd->fp_write) || es_fflush(hd->fp_write)))
|
||||||
@ -1094,34 +1038,10 @@ send_request (http_t hd, const char *auth,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
|
es_free (request);
|
||||||
#else /*!HTTP_USE_ESTREAM*/
|
|
||||||
/* We send out the start of the request through our own send
|
|
||||||
function and only then assign a stdio stream. This allows for
|
|
||||||
better error reporting that through standard stdio means. */
|
|
||||||
err = write_server (hd->sock, request, strlen (request));
|
|
||||||
if (!err)
|
|
||||||
for (;headers;headers=headers->next)
|
|
||||||
{
|
|
||||||
err = write_server (hd->sock, headers->d, strlen(headers->d));
|
|
||||||
if (err)
|
|
||||||
break;
|
|
||||||
err = write_server (hd->sock, "\r\n", 2);
|
|
||||||
if (err)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!err)
|
|
||||||
{
|
|
||||||
hd->fp_write = fdopen (hd->sock, "w");
|
|
||||||
if (!hd->fp_write)
|
|
||||||
err = gpg_error_from_syserror ();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /*!HTTP_USE_ESTREAM*/
|
|
||||||
|
|
||||||
xfree (request);
|
|
||||||
xfree (authstr);
|
xfree (authstr);
|
||||||
xfree (proxy_authstr);
|
xfree (proxy_authstr);
|
||||||
|
|
||||||
@ -1181,97 +1101,6 @@ build_rel_path (parsed_uri_t uri)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Same as fgets() but if the buffer is too short a larger one will be
|
|
||||||
allocated up to some limit *MAX_LENGTH. A line is considered a
|
|
||||||
byte stream ending in a LF. Returns the length of the line. EOF is
|
|
||||||
indicated by a line of length zero. The last LF may be missing due
|
|
||||||
to an EOF. If MAX_LENGTH is zero on return, the line has been
|
|
||||||
truncated. If the returned buffer is NULL, not enough memory was
|
|
||||||
enable to increase it, the return value will also be 0 and some
|
|
||||||
bytes might have been lost which should be no problem becuase
|
|
||||||
out-of-memory is pretty fatal for most applications.
|
|
||||||
|
|
||||||
If a line has been truncated, the file pointer is internally moved
|
|
||||||
forward to the end of the line.
|
|
||||||
|
|
||||||
Note: The returned buffer is allocated with enough extra space to
|
|
||||||
append a CR,LF,Nul
|
|
||||||
*/
|
|
||||||
static size_t
|
|
||||||
my_read_line (
|
|
||||||
#ifdef HTTP_USE_ESTREAM
|
|
||||||
estream_t fp,
|
|
||||||
#else
|
|
||||||
FILE *fp,
|
|
||||||
#endif
|
|
||||||
char **addr_of_buffer,
|
|
||||||
size_t *length_of_buffer, size_t *max_length)
|
|
||||||
{
|
|
||||||
int c;
|
|
||||||
char *buffer = *addr_of_buffer;
|
|
||||||
size_t length = *length_of_buffer;
|
|
||||||
size_t nbytes = 0;
|
|
||||||
size_t maxlen = *max_length;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
if (!buffer) /* Must allocate a new buffer. */
|
|
||||||
{
|
|
||||||
length = 256;
|
|
||||||
buffer = xtrymalloc (length);
|
|
||||||
*addr_of_buffer = buffer;
|
|
||||||
if (!buffer)
|
|
||||||
{
|
|
||||||
*length_of_buffer = *max_length = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*length_of_buffer = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
length -= 3; /* Reserve 3 bytes (cr,lf,eol). */
|
|
||||||
p = buffer;
|
|
||||||
while ((c = P_ES(getc) (fp)) != EOF)
|
|
||||||
{
|
|
||||||
if (nbytes == length) /* Increase the buffer. */
|
|
||||||
{
|
|
||||||
if (length > maxlen) /* Limit reached. */
|
|
||||||
{
|
|
||||||
/* Skip the rest of the line. */
|
|
||||||
while (c != '\n' && (c = P_ES(getc) (fp)) != EOF)
|
|
||||||
;
|
|
||||||
*p++ = '\n'; /* Always append a LF (we reserved some space). */
|
|
||||||
nbytes++;
|
|
||||||
*max_length = 0; /* Indicate truncation */
|
|
||||||
break; /*(the while loop)*/
|
|
||||||
}
|
|
||||||
length += 3; /* Adjust for the reserved bytes. */
|
|
||||||
length += length < 1024 ? 256 : 1024;
|
|
||||||
*addr_of_buffer = xtryrealloc (buffer, length);
|
|
||||||
if (!*addr_of_buffer)
|
|
||||||
{
|
|
||||||
int save_errno = errno;
|
|
||||||
xfree (buffer);
|
|
||||||
*length_of_buffer = *max_length = 0;
|
|
||||||
gpg_err_set_errno (save_errno);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
buffer = *addr_of_buffer;
|
|
||||||
*length_of_buffer = length;
|
|
||||||
length -= 3; /* And re-adjust for the reservation. */
|
|
||||||
p = buffer + nbytes;
|
|
||||||
}
|
|
||||||
*p++ = c;
|
|
||||||
nbytes++;
|
|
||||||
if (c == '\n')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*p = 0; /* Make sure the line is a string. */
|
|
||||||
|
|
||||||
return nbytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Transform a header name into a standard capitalized format; e.g.
|
/* Transform a header name into a standard capitalized format; e.g.
|
||||||
"Content-Type". Conversion stops at the colon. As usual we don't
|
"Content-Type". Conversion stops at the colon. As usual we don't
|
||||||
use the localized versions of ctype.h. */
|
use the localized versions of ctype.h. */
|
||||||
@ -1418,7 +1247,7 @@ parse_response (http_t hd)
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
maxlen = MAX_LINELEN;
|
maxlen = MAX_LINELEN;
|
||||||
len = my_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
|
len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
|
||||||
line = hd->buffer;
|
line = hd->buffer;
|
||||||
if (!line)
|
if (!line)
|
||||||
return gpg_error_from_syserror (); /* Out of core. */
|
return gpg_error_from_syserror (); /* Out of core. */
|
||||||
@ -1462,7 +1291,7 @@ parse_response (http_t hd)
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
maxlen = MAX_LINELEN;
|
maxlen = MAX_LINELEN;
|
||||||
len = my_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
|
len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
|
||||||
line = hd->buffer;
|
line = hd->buffer;
|
||||||
if (!line)
|
if (!line)
|
||||||
return gpg_error_from_syserror (); /* Out of core. */
|
return gpg_error_from_syserror (); /* Out of core. */
|
||||||
@ -1664,7 +1493,7 @@ connect_server (const char *server, unsigned short port,
|
|||||||
struct addrinfo hints, *res, *ai;
|
struct addrinfo hints, *res, *ai;
|
||||||
char portstr[35];
|
char portstr[35];
|
||||||
|
|
||||||
sprintf (portstr, "%hu", port);
|
snprintf (portstr, sizeof portstr, "%hu", port);
|
||||||
memset (&hints, 0, sizeof (hints));
|
memset (&hints, 0, sizeof (hints));
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
if (getaddrinfo (serverlist[srv].target, portstr, &hints, &res))
|
if (getaddrinfo (serverlist[srv].target, portstr, &hints, &res))
|
||||||
@ -1778,22 +1607,25 @@ static gpg_error_t
|
|||||||
write_server (int sock, const char *data, size_t length)
|
write_server (int sock, const char *data, size_t length)
|
||||||
{
|
{
|
||||||
int nleft;
|
int nleft;
|
||||||
|
int nwritten;
|
||||||
|
|
||||||
/* FIXME: We would better use pth I/O functions. */
|
/* FIXME: We would better use pth I/O functions. */
|
||||||
nleft = length;
|
nleft = length;
|
||||||
while (nleft > 0)
|
while (nleft > 0)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#if defined(HAVE_W32_SYSTEM) && !defined(HAVE_PTH)
|
||||||
int nwritten;
|
|
||||||
|
|
||||||
nwritten = send (sock, data, nleft, 0);
|
nwritten = send (sock, data, nleft, 0);
|
||||||
if ( nwritten == SOCKET_ERROR )
|
if ( nwritten == SOCKET_ERROR )
|
||||||
{
|
{
|
||||||
log_info ("network write failed: ec=%d\n", (int)WSAGetLastError ());
|
log_info ("network write failed: ec=%d\n", (int)WSAGetLastError ());
|
||||||
return gpg_error (GPG_ERR_NETWORK);
|
return gpg_error (GPG_ERR_NETWORK);
|
||||||
}
|
}
|
||||||
#else /*!HAVE_W32_SYSTEM*/
|
#else /*!HAVE_W32_SYSTEM || HAVE_PTH*/
|
||||||
int nwritten = write (sock, data, nleft);
|
# ifdef HAVE_PTH
|
||||||
|
nwritten = pth_write (sock, data, nleft);
|
||||||
|
# else
|
||||||
|
nwritten = write (sock, data, nleft);
|
||||||
|
# endif
|
||||||
if (nwritten == -1)
|
if (nwritten == -1)
|
||||||
{
|
{
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
@ -1810,7 +1642,7 @@ write_server (int sock, const char *data, size_t length)
|
|||||||
log_info ("network write failed: %s\n", strerror (errno));
|
log_info ("network write failed: %s\n", strerror (errno));
|
||||||
return gpg_error_from_syserror ();
|
return gpg_error_from_syserror ();
|
||||||
}
|
}
|
||||||
#endif /*!HAVE_W32_SYSTEM*/
|
#endif /*!HAVE_W32_SYSTEM || HAVE_PTH*/
|
||||||
nleft -= nwritten;
|
nleft -= nwritten;
|
||||||
data += nwritten;
|
data += nwritten;
|
||||||
}
|
}
|
||||||
@ -1820,7 +1652,6 @@ write_server (int sock, const char *data, size_t length)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HTTP_USE_ESTREAM
|
|
||||||
/* Read handler for estream. */
|
/* Read handler for estream. */
|
||||||
static ssize_t
|
static ssize_t
|
||||||
cookie_read (void *cookie, void *buffer, size_t size)
|
cookie_read (void *cookie, void *buffer, size_t size)
|
||||||
@ -1961,7 +1792,6 @@ cookie_close (void *cookie)
|
|||||||
xfree (c);
|
xfree (c);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /*HTTP_USE_ESTREAM*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1999,9 +1829,7 @@ main (int argc, char **argv)
|
|||||||
#endif /*HTTP_USE_GNUTLS*/
|
#endif /*HTTP_USE_GNUTLS*/
|
||||||
header_t hdr;
|
header_t hdr;
|
||||||
|
|
||||||
#ifdef HTTP_USE_ESTREAM
|
|
||||||
es_init ();
|
es_init ();
|
||||||
#endif
|
|
||||||
log_set_prefix ("http-test", 1 | 4);
|
log_set_prefix ("http-test", 1 | 4);
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
{
|
{
|
||||||
@ -2100,7 +1928,7 @@ main (int argc, char **argv)
|
|||||||
switch (http_get_status_code (hd))
|
switch (http_get_status_code (hd))
|
||||||
{
|
{
|
||||||
case 200:
|
case 200:
|
||||||
while ((c = P_ES(getc) (http_get_read_ptr (hd))) != EOF)
|
while ((c = es_getc (http_get_read_ptr (hd))) != EOF)
|
||||||
putchar (c);
|
putchar (c);
|
||||||
break;
|
break;
|
||||||
case 301:
|
case 301:
|
||||||
|
@ -21,9 +21,7 @@
|
|||||||
#define GNUPG_COMMON_HTTP_H
|
#define GNUPG_COMMON_HTTP_H
|
||||||
|
|
||||||
#include <gpg-error.h>
|
#include <gpg-error.h>
|
||||||
#ifdef HTTP_USE_ESTREAM
|
|
||||||
#include "../common/estream.h"
|
#include "../common/estream.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
struct uri_tuple_s {
|
struct uri_tuple_s {
|
||||||
struct uri_tuple_s *next;
|
struct uri_tuple_s *next;
|
||||||
@ -100,13 +98,8 @@ gpg_error_t http_open_document (http_t *r_hd,
|
|||||||
const char *srvtag,
|
const char *srvtag,
|
||||||
strlist_t headers);
|
strlist_t headers);
|
||||||
|
|
||||||
#ifdef HTTP_USE_ESTREAM
|
|
||||||
estream_t http_get_read_ptr (http_t hd);
|
estream_t http_get_read_ptr (http_t hd);
|
||||||
estream_t http_get_write_ptr (http_t hd);
|
estream_t http_get_write_ptr (http_t hd);
|
||||||
#else /*!HTTP_USE_ESTREAM*/
|
|
||||||
FILE *http_get_read_ptr (http_t hd);
|
|
||||||
FILE *http_get_write_ptr (http_t hd);
|
|
||||||
#endif /*!HTTP_USE_ESTREAM*/
|
|
||||||
unsigned int http_get_status_code (http_t hd);
|
unsigned int http_get_status_code (http_t hd);
|
||||||
const char *http_get_header (http_t hd, const char *name);
|
const char *http_get_header (http_t hd, const char *name);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user