1
0
mirror of https://github.com/lammertb/libhttp.git synced 2026-01-27 08:02:47 +03:00

Code cleanup

This commit is contained in:
Lammert Bies
2016-12-20 23:53:16 +01:00
parent 5ef6904d6b
commit 87cdc3e4c2
13 changed files with 240 additions and 166 deletions

View File

@@ -29,13 +29,18 @@
int XX_httplib_must_hide_file( struct httplib_connection *conn, const char *path ) {
if (conn && conn->ctx) {
const char *pw_pattern = "**" PASSWORDS_FILE_NAME "$";
const char *pattern = conn->ctx->config[HIDE_FILES];
return XX_httplib_match_prefix(pw_pattern, strlen(pw_pattern), path) > 0
|| (pattern != NULL
&& XX_httplib_match_prefix(pattern, strlen(pattern), path) > 0);
}
const char *pw_pattern;
const char *pattern;
if ( conn == NULL || conn->ctx == NULL ) return 0;
pw_pattern = "**" PASSWORDS_FILE_NAME "$";
pattern = conn->ctx->config[HIDE_FILES];
return XX_httplib_match_prefix(pw_pattern, strlen(pw_pattern), path) > 0
|| (pattern != NULL
&& XX_httplib_match_prefix(pattern, strlen(pattern), path) > 0);
return 0;
} /* XX_httplib_must_hide_file */

View File

@@ -27,56 +27,58 @@
#include "httplib_main.h"
/* A helper function for traversing a comma separated list of values.
/*
* A helper function for traversing a comma separated list of values.
* It returns a list pointer shifted to the next value, or NULL if the end
* of the list found.
* Value is stored in val vector. If value has form "x=y", then eq_val
* vector is initialized to point to the "y" part, and val vector length
* is adjusted to point only to "x". */
* is adjusted to point only to "x".
*/
const char *XX_httplib_next_option( const char *list, struct vec *val, struct vec *eq_val ) {
int end;
reparse:
if (val == NULL || list == NULL || *list == '\0') {
/* End of the list */
list = NULL;
} else {
/* Skip over leading LWS */
while (*list == ' ' || *list == '\t') list++;
if ( val == NULL || list == NULL || *list == '\0' ) return NULL;
/* Skip over leading LWS */
while ( *list == ' ' || *list == '\t' ) list++;
val->ptr = list;
if ((list = strchr(val->ptr, ',')) != NULL) {
/* Comma found. Store length and shift the list ptr */
val->len = ((size_t)(list - val->ptr));
list++;
} else {
/* This value is the last one */
list = val->ptr + strlen(val->ptr);
val->len = ((size_t)(list - val->ptr));
}
val->ptr = list;
if ((list = strchr(val->ptr, ',')) != NULL) {
/* Comma found. Store length and shift the list ptr */
val->len = ((size_t)(list - val->ptr));
list++;
}
else {
/* This value is the last one */
list = val->ptr + strlen(val->ptr);
val->len = ((size_t)(list - val->ptr));
}
/* Adjust length for trailing LWS */
end = (int)val->len - 1;
while (end >= 0 && (val->ptr[end] == ' ' || val->ptr[end] == '\t'))
end--;
val->len = (size_t)(end + 1);
/* Adjust length for trailing LWS */
end = (int)val->len - 1;
while ( end >= 0 && ( val->ptr[end] == ' ' || val->ptr[end] == '\t' ) ) end--;
if (val->len == 0) {
/* Ignore any empty entries. */
goto reparse;
}
val->len = (size_t)(end + 1);
if (eq_val != NULL) {
/* Value has form "x=y", adjust pointers and lengths
* so that val points to "x", and eq_val points to "y". */
eq_val->len = 0;
eq_val->ptr = (const char *)memchr(val->ptr, '=', val->len);
if (eq_val->ptr != NULL) {
eq_val->ptr++; /* Skip over '=' character */
eq_val->len = ((size_t)(val->ptr - eq_val->ptr)) + val->len;
val->len = ((size_t)(eq_val->ptr - val->ptr)) - 1;
}
if (val->len == 0) {
/* Ignore any empty entries. */
goto reparse;
}
if (eq_val != NULL) {
/* Value has form "x=y", adjust pointers and lengths
* so that val points to "x", and eq_val points to "y". */
eq_val->len = 0;
eq_val->ptr = (const char *)memchr(val->ptr, '=', val->len);
if (eq_val->ptr != NULL) {
eq_val->ptr++; /* Skip over '=' character */
eq_val->len = ((size_t)(val->ptr - eq_val->ptr)) + val->len;
val->len = ((size_t)(eq_val->ptr - val->ptr)) - 1;
}
}

View File

@@ -22,7 +22,7 @@
* THE SOFTWARE.
*
* ============
* Release: 1.8
* Release: 2.0
*/
#include "httplib_main.h"
@@ -32,43 +32,61 @@
* or search for .htpasswd in the requested directory. */
void XX_httplib_open_auth_file( struct httplib_connection *conn, const char *path, struct file *filep ) {
if ( conn == NULL || conn->ctx == NULL ) return;
char name[PATH_MAX];
const char *p;
const char *e;
const char *gpass = conn->ctx->config[GLOBAL_PASSWORDS_FILE];
const char *gpass;
struct file file = STRUCT_FILE_INITIALIZER;
int truncated;
if (gpass != NULL) {
/* Use global passwords file */
if (!XX_httplib_fopen(conn, gpass, "r", filep)) {
#ifdef DEBUG
httplib_cry(conn, "fopen(%s): %s", gpass, strerror(ERRNO));
#endif
}
/* Important: using local struct file to test path for is_directory
* flag. If filep is used, XX_httplib_stat() makes it appear as if auth file
* was opened. */
} else if (XX_httplib_stat(conn, path, &file) && file.is_directory) {
XX_httplib_snprintf(conn, &truncated, name, sizeof(name), "%s/%s", path, PASSWORDS_FILE_NAME);
if ( conn == NULL || conn->ctx == NULL ) return;
if (truncated || !XX_httplib_fopen(conn, name, "r", filep)) {
gpass = conn->ctx->config[GLOBAL_PASSWORDS_FILE];
if ( gpass != NULL ) {
/*
* Use global passwords file
*/
if ( ! XX_httplib_fopen( conn, gpass, "r", filep ) ) {
#ifdef DEBUG
httplib_cry(conn, "fopen(%s): %s", name, strerror(ERRNO));
httplib_cry( conn, "fopen(%s): %s", gpass, strerror(ERRNO) );
#endif
}
} else {
/* Try to find .htpasswd in requested directory. */
/*
* Important: using local struct file to test path for is_directory
* flag. If filep is used, XX_httplib_stat() makes it appear as if auth file
* was opened.
*/
}
else if ( XX_httplib_stat( conn, path, &file ) && file.is_directory ) {
XX_httplib_snprintf( conn, &truncated, name, sizeof(name), "%s/%s", path, PASSWORDS_FILE_NAME );
if ( truncated || ! XX_httplib_fopen( conn, name, "r", filep ) ) {
#ifdef DEBUG
httplib_cry( conn, "fopen(%s): %s", name, strerror(ERRNO) );
#endif
}
}
else {
/*
* Try to find .htpasswd in requested directory.
*/
for (p = path, e = p + strlen(p) - 1; e > p; e--) {
if (e[0] == '/') break;
}
XX_httplib_snprintf(conn, &truncated, name, sizeof(name), "%.*s/%s", (int)(e - p), p, PASSWORDS_FILE_NAME);
if (truncated || !XX_httplib_fopen(conn, name, "r", filep)) {
XX_httplib_snprintf( conn, &truncated, name, sizeof(name), "%.*s/%s", (int)(e - p), p, PASSWORDS_FILE_NAME );
if ( truncated || ! XX_httplib_fopen( conn, name, "r", filep ) ) {
#ifdef DEBUG
httplib_cry(conn, "fopen(%s): %s", name, strerror(ERRNO));
httplib_cry( conn, "fopen(%s): %s", name, strerror(ERRNO) );
#endif
}
}

View File

@@ -22,7 +22,7 @@
* THE SOFTWARE.
*
* ============
* Release: 1.8
* Release: 2.0
*/
#include "httplib_main.h"
@@ -35,12 +35,13 @@ static const char *month_names[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "
#if !defined(NO_CACHING)
/* Convert month to the month number. Return -1 on error, or month number */
static int get_month_index(const char *s) {
static int get_month_index( const char *s ) {
size_t i;
for (i = 0; i < ARRAY_SIZE(month_names); i++) {
if (!strcmp(s, month_names[i])) return (int)i;
if ( ! strcmp( s, month_names[i] ) ) return (int)i;
}
return -1;
@@ -65,16 +66,19 @@ time_t XX_httplib_parse_date_string( const char *datetime ) {
( sscanf(datetime, "%*3s, %d %3s %d %d:%d:%d", &day, month_str, &year, &hour, &minute, &second ) == 6 ) ||
( sscanf(datetime, "%d-%3s-%d %d:%d:%d", &day, month_str, &year, &hour, &minute, &second ) == 6 ) ) {
month = get_month_index(month_str);
if ((month >= 0) && (year >= 1970)) {
memset(&tm, 0, sizeof(tm));
month = get_month_index( month_str );
if ( month >= 0 && year >= 1970 ) {
memset( &tm, 0, sizeof(tm) );
tm.tm_year = year - 1900;
tm.tm_mon = month;
tm.tm_mon = month;
tm.tm_mday = day;
tm.tm_hour = hour;
tm.tm_min = minute;
tm.tm_sec = second;
result = timegm(&tm);
tm.tm_min = minute;
tm.tm_sec = second;
result = timegm( & tm );
}
}

View File

@@ -22,7 +22,7 @@
* THE SOFTWARE.
*
* ============
* Release: 1.8
* Release: 2.0
*/
#include "httplib_main.h"
@@ -43,16 +43,19 @@ int XX_httplib_parse_net( const char *spec, uint32_t *net, uint32_t *mask ) {
int b;
int c;
int d;
int slash = 32;
int len = 0;
int slash;
int len;
if ((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5
|| sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4) && isbyte(a)
&& isbyte(b) && isbyte(c) && isbyte(d) && slash >= 0
&& slash < 33) {
len = n;
*net = ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8) | (uint32_t)d;
*mask = slash ? (0xffffffffU << (32 - slash)) : 0;
slash = 32;
len = 0;
if ( ( sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5 ||
sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4 ) &&
isbyte(a) && isbyte(b) && isbyte(c) && isbyte(d) && slash >= 0 && slash < 33 ) {
len = n;
*net = ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8) | (uint32_t)d;
*mask = (slash) ? (0xffffffffU << (32 - slash)) : 0;
}
return len;

View File

@@ -36,24 +36,34 @@ void XX_httplib_send_file_data( struct httplib_connection *conn, struct file *fi
int num_written;
int64_t size;
if (!filep || !conn) return;
if ( filep == NULL || conn == NULL ) return;
/* Sanity check the offset */
size = (filep->size > INT64_MAX) ? INT64_MAX : (int64_t)(filep->size);
size = (filep->size > INT64_MAX) ? INT64_MAX : (int64_t)(filep->size);
offset = (offset < 0) ? 0 : ((offset > size) ? size : offset);
if (len > 0 && filep->membuf != NULL && size > 0) {
/* file stored in memory */
if (len > size - offset) {
len = size - offset;
}
httplib_write(conn, filep->membuf + offset, (size_t)len);
} else if (len > 0 && filep->fp != NULL) {
if ( len > 0 && filep->membuf != NULL && size > 0 ) {
/*
* file stored in memory
*/
if (len > size - offset) len = size - offset;
httplib_write( conn, filep->membuf + offset, (size_t)len );
}
else if ( len > 0 && filep->fp != NULL ) {
/* file stored on disk */
#if defined(__linux__)
/* sendfile is only available for Linux */
if ((conn->ssl == 0) && (conn->throttle == 0)
&& (!httplib_strcasecmp(conn->ctx->config[ALLOW_SENDFILE_CALL], "yes"))) {
/*
* sendfile is only available for Linux
*/
if ( conn->ssl == 0 && conn->throttle == 0 && ! httplib_strcasecmp( conn->ctx->config[ALLOW_SENDFILE_CALL], "yes" ) ) {
off_t sf_offs = (off_t)offset;
ssize_t sf_sent;
int sf_file = fileno(filep->fp);
@@ -62,15 +72,18 @@ void XX_httplib_send_file_data( struct httplib_connection *conn, struct file *fi
do {
/* 2147479552 (0x7FFFF000) is a limit found by experiment on
* 64 bit Linux (2^31 minus one memory page of 4k?). */
size_t sf_tosend =
(size_t)((len < 0x7FFFF000) ? len : 0x7FFFF000);
sf_sent =
sendfile(conn->client.sock, sf_file, &sf_offs, sf_tosend);
if (sf_sent > 0) {
size_t sf_tosend = (size_t)((len < 0x7FFFF000) ? len : 0x7FFFF000);
sf_sent = sendfile(conn->client.sock, sf_file, &sf_offs, sf_tosend);
if ( sf_sent > 0 ) {
conn->num_bytes_sent += sf_sent;
len -= sf_sent;
offset += sf_sent;
} else if (loop_cnt == 0) {
len -= sf_sent;
offset += sf_sent;
}
else if (loop_cnt == 0) {
/* This file can not be sent using sendfile.
* This might be the case for pseudo-files in the
* /sys/ and /proc/ file system.
@@ -101,9 +114,7 @@ void XX_httplib_send_file_data( struct httplib_connection *conn, struct file *fi
while (len > 0) {
/* Calculate how much to read from the file in the buffer */
to_read = sizeof(buf);
if ((int64_t)to_read > len) {
to_read = (int)len;
}
if ((int64_t)to_read > len) to_read = (int)len;
/* Read from file, exit the loop on error */
if ((num_read = (int)fread(buf, 1, (size_t)to_read, filep->fp)) <= 0) break;

View File

@@ -22,18 +22,21 @@
* THE SOFTWARE.
*
* ============
* Release: 1.8
* Release: 2.0
*/
#include "httplib_main.h"
int XX_httplib_send_no_cache_header( struct httplib_connection *conn ) {
/* Send all current and obsolete cache opt-out directives. */
return httplib_printf(conn,
/*
* Send all current and obsolete cache opt-out directives.
*/
return httplib_printf( conn,
"Cache-Control: no-cache, no-store, "
"must-revalidate, private, max-age=0\r\n"
"Pragma: no-cache\r\n"
"Expires: 0\r\n");
"Expires: 0\r\n" );
} /* XX_httplib_send_no_cache_header */

View File

@@ -34,8 +34,6 @@
static int hexdump2string( void *mem, int memlen, char *buf, int buflen );
/*
* void XX_httplib_ssl_get_client_cert_info( struct httplib_connection *conn );
*
@@ -62,7 +60,7 @@ void XX_httplib_ssl_get_client_cert_info( struct httplib_connection *conn ) {
/* Get Subject and issuer */
X509_NAME *subj = X509_get_subject_name(cert);
X509_NAME *iss = X509_get_issuer_name(cert);
X509_NAME *iss = X509_get_issuer_name(cert);
/* Get serial number */
ASN1_INTEGER *serial = X509_get_serialNumber(cert);

View File

@@ -22,7 +22,7 @@
* THE SOFTWARE.
*
* ============
* Release: 1.8
* Release: 2.0
*/
#include "httplib_main.h"
@@ -45,31 +45,41 @@ int XX_httplib_sslize( struct httplib_connection *conn, SSL_CTX *s, int (*func)(
if ( conn == NULL ) return 0;
short_trust = (conn->ctx->config[SSL_SHORT_TRUST] != NULL) && (httplib_strcasecmp(conn->ctx->config[SSL_SHORT_TRUST], "yes") == 0);
short_trust = ( conn->ctx->config[SSL_SHORT_TRUST] != NULL && ! httplib_strcasecmp( conn->ctx->config[SSL_SHORT_TRUST], "yes" ) );
if (short_trust) {
int trust_ret = XX_httplib_refresh_trust(conn);
if (!trust_ret) return trust_ret;
if ( short_trust ) {
int trust_ret = XX_httplib_refresh_trust( conn );
if ( ! trust_ret ) return trust_ret;
}
conn->ssl = SSL_new(s);
if (conn->ssl == NULL) return 0;
conn->ssl = SSL_new( s );
if ( conn->ssl == NULL ) return 0;
ret = SSL_set_fd(conn->ssl, conn->client.sock);
if (ret != 1) {
err = SSL_get_error(conn->ssl, ret);
ret = SSL_set_fd( conn->ssl, conn->client.sock );
if ( ret != 1 ) {
err = SSL_get_error( conn->ssl, ret );
(void)err; /* TODO: set some error message */
SSL_free(conn->ssl);
SSL_free( conn->ssl );
conn->ssl = NULL;
/* Avoid CRYPTO_cleanup_all_ex_data(); See discussion:
* https://wiki.openssl.org/index.php/Talk:Library_Initialization */
ERR_remove_state(0);
/*
* Avoid CRYPTO_cleanup_all_ex_data(); See discussion:
* https://wiki.openssl.org/index.php/Talk:Library_Initialization
*/
ERR_remove_state( 0 );
return 0;
}
/* SSL functions may fail and require to be called again:
/*
* SSL functions may fail and require to be called again:
* see https://www.openssl.org/docs/manmaster/ssl/SSL_get_error.html
* Here "func" could be SSL_connect or SSL_accept. */
* Here "func" could be SSL_connect or SSL_accept.
*/
for (i = 0; i <= 16; i *= 2) {
ret = func(conn->ssl);
if (ret != 1) {
@@ -85,12 +95,17 @@ int XX_httplib_sslize( struct httplib_connection *conn, SSL_CTX *s, int (*func)(
else break; /* Success */
}
if (ret != 1) {
SSL_free(conn->ssl);
if ( ret != 1 ) {
SSL_free( conn->ssl );
conn->ssl = NULL;
/* Avoid CRYPTO_cleanup_all_ex_data(); See discussion:
* https://wiki.openssl.org/index.php/Talk:Library_Initialization */
ERR_remove_state(0);
/*
* Avoid CRYPTO_cleanup_all_ex_data(); See discussion:
* https://wiki.openssl.org/index.php/Talk:Library_Initialization
*/
ERR_remove_state( 0 );
return 0;
}

View File

@@ -103,16 +103,19 @@ int XX_httplib_stat( struct httplib_connection *conn, const char *path, struct f
int XX_httplib_stat( struct httplib_connection *conn, const char *path, struct file *filep ) {
struct stat st;
if (!filep) return 0;
memset(filep, 0, sizeof(*filep));
if ( filep == NULL ) return 0;
if (conn && XX_httplib_is_file_in_memory(conn, path, filep)) return 1;
memset( filep, 0, sizeof(*filep) );
if (0 == stat(path, &st)) {
filep->size = (uint64_t)(st.st_size);
if ( conn != NULL && XX_httplib_is_file_in_memory( conn, path, filep ) ) return 1;
if ( stat( path, &st ) == 0 ) {
filep->size = (uint64_t)(st.st_size);
filep->last_modified = st.st_mtime;
filep->is_directory = S_ISDIR(st.st_mode);
filep->is_directory = S_ISDIR(st.st_mode);
return 1;
}

View File

@@ -50,12 +50,13 @@ int64_t httplib_store_body( struct httplib_connection *conn, const char *path )
}
ret = XX_httplib_put_dir( conn, path );
if (ret < 0) {
if ( ret < 0 ) {
/* -1 for path too long,
* -2 for path can not be created. */
return ret;
}
if (ret != 1) {
if ( ret != 1 ) {
/* Return 0 means, path itself is a directory. */
return 0;
}
@@ -64,7 +65,7 @@ int64_t httplib_store_body( struct httplib_connection *conn, const char *path )
ret = httplib_read( conn, buf, sizeof(buf) );
while ( ret > 0) {
while ( ret > 0 ) {
n = (int)fwrite( buf, 1, (size_t)ret, fi.fp );
if ( n != ret ) {
@@ -76,8 +77,11 @@ int64_t httplib_store_body( struct httplib_connection *conn, const char *path )
ret = httplib_read( conn, buf, sizeof(buf) );
}
/* TODO: XX_httplib_fclose should return an error,
* and every caller should check and handle it. */
/*
* TODO: XX_httplib_fclose should return an error,
* and every caller should check and handle it.
*/
if ( fclose(fi.fp) != 0 ) {
XX_httplib_remove_bad_file( conn, path );

View File

@@ -22,7 +22,7 @@
* THE SOFTWARE.
*
* ============
* Release: 1.8
* Release: 2.0
*/
#include "httplib_main.h"
@@ -39,33 +39,36 @@
*/
#if !defined(NO_SSL)
void XX_httplib_uninitialize_ssl( struct httplib_context *ctx ) {
UNUSED_PARAMETER(ctx);
int i;
if (httplib_atomic_dec(&XX_httplib_cryptolib_users) == 0) {
if ( httplib_atomic_dec( & XX_httplib_cryptolib_users ) == 0 ) {
/* Shutdown according to
/*
* Shutdown according to
* https://wiki.openssl.org/index.php/Library_Initialization#Cleanup
* http://stackoverflow.com/questions/29845527/how-to-properly-uninitialize-openssl
*/
CRYPTO_set_locking_callback(NULL);
CRYPTO_set_id_callback(NULL);
CRYPTO_set_locking_callback( NULL );
CRYPTO_set_id_callback( NULL );
ENGINE_cleanup();
CONF_modules_unload(1);
CONF_modules_unload( 1 );
ERR_free_strings();
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
ERR_remove_state(0);
ERR_remove_state( 0 );
for (i=0; i<CRYPTO_num_locks(); i++) httplib_pthread_mutex_destroy( & XX_httplib_ssl_mutexes[i] );
for (i = 0; i < CRYPTO_num_locks(); i++) {
httplib_pthread_mutex_destroy( & XX_httplib_ssl_mutexes[i] );
}
httplib_free( XX_httplib_ssl_mutexes );
XX_httplib_ssl_mutexes = NULL;
}
} /* XX_httplib_unitialize_ssl */
#endif /* !NO_SSL */

View File

@@ -28,14 +28,17 @@
#include "httplib_main.h"
#include "httplib_string.h"
/* Return null terminated string of given maximum length.
* Report errors if length is exceeded. */
/*
* Return null terminated string of given maximum length.
* Report errors if length is exceeded.
*/
void XX_httplib_vsnprintf( const struct httplib_connection *conn, int *truncated, char *buf, size_t buflen, const char *fmt, va_list ap ) {
int n;
int ok;
if (buflen == 0) return;
if ( buf == NULL || buflen < 1 ) return;
#ifdef __clang__
#pragma clang diagnostic push
@@ -44,7 +47,7 @@ void XX_httplib_vsnprintf( const struct httplib_connection *conn, int *truncated
* indirectly by XX_httplib_snprintf */
#endif
n = (int)vsnprintf_impl(buf, buflen, fmt, ap);
n = (int)vsnprintf_impl( buf, buflen, fmt, ap );
ok = (n >= 0) && ((size_t)n < buflen);
#ifdef __clang__
@@ -52,9 +55,11 @@ void XX_httplib_vsnprintf( const struct httplib_connection *conn, int *truncated
#endif
if (ok) {
if (truncated) *truncated = 0;
} else {
if (truncated) *truncated = 1;
if ( truncated != NULL ) *truncated = 0;
}
else {
if ( truncated != NULL ) *truncated = 1;
httplib_cry(conn, "truncating vsnprintf buffer: [%.*s]", (int)((buflen > 200) ? 200 : (buflen - 1)), buf);
n = (int)buflen - 1;
}