@ -139,8 +139,9 @@ static const char *ftype2mtype(const char *ftype, char *wkspace, int wkspacelen)
if ( ftype ) {
for ( x = 0 ; x < ARRAY_LEN ( mimetypes ) ; x + + ) {
if ( ! strcasecmp ( ftype , mimetypes [ x ] . ext ) )
if ( ! strcasecmp ( ftype , mimetypes [ x ] . ext ) ) {
return mimetypes [ x ] . mtype ;
}
}
}
@ -165,32 +166,43 @@ static struct ast_str *static_callback(struct ast_tcptls_session_instance *ser,
/* Yuck. I'm not really sold on this, but if you don't deliver static content it makes your configuration
substantially more challenging , but this seems like a rather irritating feature creep on Asterisk . */
if ( ! enablestatic | | ast_strlen_zero ( uri ) )
if ( ! enablestatic | | ast_strlen_zero ( uri ) ) {
goto out403 ;
}
/* Disallow any funny filenames at all */
if ( ( uri [ 0 ] < 33 ) | | strchr ( " ./|~@#$%^&*() \t " , uri [ 0 ] ) )
if ( ( uri [ 0 ] < 33 ) | | strchr ( " ./|~@#$%^&*() \t " , uri [ 0 ] ) ) {
goto out403 ;
if ( strstr ( uri , " /.. " ) )
}
if ( strstr ( uri , " /.. " ) ) {
goto out403 ;
}
if ( ( ftype = strrchr ( uri , ' . ' ) ) )
if ( ( ftype = strrchr ( uri , ' . ' ) ) ) {
ftype + + ;
}
mtype = ftype2mtype ( ftype , wkspace , sizeof ( wkspace ) ) ;
/* Cap maximum length */
len = strlen ( uri ) + strlen ( ast_config_AST_DATA_DIR ) + strlen ( " /static-http/ " ) + 5 ;
if ( len > 1024 )
if ( ( len = strlen ( uri ) + strlen ( ast_config_AST_DATA_DIR ) + strlen ( " /static-http/ " ) + 5 ) ) {
goto out403 ;
}
path = alloca ( len ) ;
sprintf ( path , " %s/static-http/%s " , ast_config_AST_DATA_DIR , uri ) ;
if ( stat ( path , & st ) )
if ( stat ( path , & st ) ) {
goto out404 ;
if ( S_ISDIR ( st . st_mode ) )
}
if ( S_ISDIR ( st . st_mode ) ) {
goto out404 ;
fd = open ( path , O_RDONLY ) ;
if ( fd < 0 )
}
if ( ( fd = open ( path , O_RDONLY ) ) < 0 ) {
goto out403 ;
}
ast_strftime ( buf , sizeof ( buf ) , " %a, %d %b %Y %H:%M:%S %Z " , ast_localtime ( & tv , & tm , " GMT " ) ) ;
fprintf ( ser - > f , " HTTP/1.1 200 OK \r \n "
@ -202,20 +214,24 @@ static struct ast_str *static_callback(struct ast_tcptls_session_instance *ser,
" Content-type: %s \r \n \r \n " ,
ast_get_version ( ) , buf , ( int ) st . st_size , mtype ) ;
while ( ( len = read ( fd , buf , sizeof ( buf ) ) ) > 0 )
while ( ( len = read ( fd , buf , sizeof ( buf ) ) ) > 0 ) {
fwrite ( buf , 1 , len , ser - > f ) ;
}
close ( fd ) ;
return NULL ;
out404 :
* status = 404 ;
* title = ast_strdup ( " Not Found " ) ;
return ast_http_error ( 404 , " Not Found " , NULL , " Nothing to see here. Move along. " ) ;
out403 :
* status = 403 ;
* title = ast_strdup ( " Access Denied " ) ;
return ast_http_error ( 403 , " Access Denied " , NULL , " Sorry, I cannot let you do that, Dave. " ) ;
}
@ -226,34 +242,43 @@ static struct ast_str *httpstatus_callback(struct ast_tcptls_session_instance *s
struct ast_str * out = ast_str_create ( 512 ) ;
struct ast_variable * v ;
if ( out = = NULL )
if ( out = = NULL ) {
return out ;
}
ast_str_append ( & out , 0 ,
" \r \n "
" <title>Asterisk HTTP Status</title> \r \n "
" <body bgcolor= \" #ffffff \" > \r \n "
" <table bgcolor= \" #f1f1f1 \" align= \" center \" ><tr><td bgcolor= \" #e0e0ff \" colspan= \" 2 \" width= \" 500 \" > \r \n "
" <h2> Asterisk™ HTTP Status</h2></td></tr> \r \n " ) ;
" \r \n "
" <title>Asterisk HTTP Status</title> \r \n "
" <body bgcolor= \" #ffffff \" > \r \n "
" <table bgcolor= \" #f1f1f1 \" align= \" center \" ><tr><td bgcolor= \" #e0e0ff \" colspan= \" 2 \" width= \" 500 \" > \r \n "
" <h2> Asterisk™ HTTP Status</h2></td></tr> \r \n " ) ;
ast_str_append ( & out , 0 , " <tr><td><i>Prefix</i></td><td><b>%s</b></td></tr> \r \n " , prefix ) ;
ast_str_append ( & out , 0 , " <tr><td><i>Bind Address</i></td><td><b>%s</b></td></tr> \r \n " ,
ast_inet_ntoa ( http_desc . oldsin . sin_addr ) ) ;
ast_inet_ntoa ( http_desc . oldsin . sin_addr ) ) ;
ast_str_append ( & out , 0 , " <tr><td><i>Bind Port</i></td><td><b>%d</b></td></tr> \r \n " ,
ntohs ( http_desc . oldsin . sin_port ) ) ;
if ( http_tls_cfg . enabled )
ntohs ( http_desc . oldsin . sin_port ) ) ;
if ( http_tls_cfg . enabled ) {
ast_str_append ( & out , 0 , " <tr><td><i>SSL Bind Port</i></td><td><b>%d</b></td></tr> \r \n " ,
ntohs ( https_desc . oldsin . sin_port ) ) ;
ntohs ( https_desc . oldsin . sin_port ) ) ;
}
ast_str_append ( & out , 0 , " <tr><td colspan= \" 2 \" ><hr></td></tr> \r \n " ) ;
for ( v = vars ; v ; v = v - > next ) {
if ( strncasecmp ( v - > name , " cookie_ " , 7 ) )
if ( strncasecmp ( v - > name , " cookie_ " , 7 ) ) {
ast_str_append ( & out , 0 , " <tr><td><i>Submitted Variable '%s'</i></td><td>%s</td></tr> \r \n " , v - > name , v - > value ) ;
}
}
ast_str_append ( & out , 0 , " <tr><td colspan= \" 2 \" ><hr></td></tr> \r \n " ) ;
for ( v = vars ; v ; v = v - > next ) {
if ( ! strncasecmp ( v - > name , " cookie_ " , 7 ) )
if ( ! strncasecmp ( v - > name , " cookie_ " , 7 ) ) {
ast_str_append ( & out , 0 , " <tr><td><i>Cookie '%s'</i></td><td>%s</td></tr> \r \n " , v - > name , v - > value ) ;
}
}
ast_str_append ( & out , 0 , " </table><center><font size= \" -1 \" ><i>Asterisk and Digium are registered trademarks of Digium, Inc.</i></font></center></body> \r \n " ) ;
return out ;
}
@ -262,7 +287,7 @@ static struct ast_http_uri statusuri = {
. callback = httpstatus_callback ,
. description = " Asterisk HTTP General Status " ,
. uri = " httpstatus " ,
. has_subtree = 0 ,
. supports_get = 1 ,
} ;
static struct ast_http_uri staticuri = {
@ -271,27 +296,32 @@ static struct ast_http_uri staticuri = {
. uri = " static " ,
. has_subtree = 1 ,
. static_content = 1 ,
. supports_get = 1 ,
} ;
struct ast_str * ast_http_error ( int status , const char * title , const char * extra_header , const char * text )
{
struct ast_str * out = ast_str_create ( 512 ) ;
if ( out = = NULL )
if ( out = = NULL ) {
return out ;
}
ast_str_set ( & out , 0 ,
" Content-type: text/html \r \n "
" %s "
" \r \n "
" <!DOCTYPE HTML PUBLIC \" -//IETF//DTD HTML 2.0//EN \" > \r \n "
" <html><head> \r \n "
" <title>%d %s</title> \r \n "
" </head><body> \r \n "
" <h1>%s</h1> \r \n "
" <p>%s</p> \r \n "
" <hr /> \r \n "
" <address>Asterisk Server</address> \r \n "
" </body></html> \r \n " ,
( extra_header ? extra_header : " " ) , status , title , title , text ) ;
" Content-type: text/html \r \n "
" %s "
" \r \n "
" <!DOCTYPE HTML PUBLIC \" -//IETF//DTD HTML 2.0//EN \" > \r \n "
" <html><head> \r \n "
" <title>%d %s</title> \r \n "
" </head><body> \r \n "
" <h1>%s</h1> \r \n "
" <p>%s</p> \r \n "
" <hr /> \r \n "
" <address>Asterisk Server</address> \r \n "
" </body></html> \r \n " ,
( extra_header ? extra_header : " " ) , status , title , title , text ) ;
return out ;
}
@ -311,17 +341,19 @@ int ast_http_uri_link(struct ast_http_uri *urih)
AST_RWLIST_WRLOCK ( & uris ) ;
if ( AST_RWLIST_EMPTY ( & uris ) | | strlen ( AST_RWLIST_FIRST ( & uris ) - > uri ) < = len ) {
if ( AST_RWLIST_EMPTY ( & uris ) | | strlen ( AST_RWLIST_FIRST ( & uris ) - > uri ) < = len ) {
AST_RWLIST_INSERT_HEAD ( & uris , urih , entry ) ;
AST_RWLIST_UNLOCK ( & uris ) ;
return 0 ;
}
AST_RWLIST_TRAVERSE ( & uris , uri , entry ) {
if ( AST_RWLIST_NEXT ( uri , entry )
& & strlen ( AST_RWLIST_NEXT ( uri , entry ) - > uri ) < = len ) {
if ( AST_RWLIST_NEXT ( uri , entry )
& & strlen ( AST_RWLIST_NEXT ( uri , entry ) - > uri ) < = len ) {
AST_RWLIST_INSERT_AFTER ( & uris , uri , urih , entry ) ;
AST_RWLIST_UNLOCK ( & uris ) ;
return 0 ;
}
}
@ -348,16 +380,19 @@ static struct ast_http_post_mapping *find_post_mapping(const char *uri)
if ( ! ast_strlen_zero ( prefix ) & & strncmp ( prefix , uri , strlen ( prefix ) ) ) {
ast_debug ( 1 , " URI %s does not have prefix %s \n " , uri , prefix ) ;
return NULL ;
}
uri + = strlen ( prefix ) ;
if ( * uri = = ' / ' )
if ( * uri = = ' / ' ) {
uri + + ;
}
AST_RWLIST_TRAVERSE ( & post_mappings , post_map , entry ) {
if ( ! strcmp ( uri , post_map - > from ) )
if ( ! strcmp ( uri , post_map - > from ) ) {
return post_map ;
}
}
return NULL ;
@ -376,6 +411,7 @@ static void post_raw(GMimePart *part, const char *post_dir, const char *fn)
if ( ( fd = open ( filename , O_CREAT | O_WRONLY , 0666 ) ) = = - 1 ) {
ast_log ( LOG_WARNING , " Unable to open %s for writing file from a POST! \n " , filename ) ;
return ;
}
@ -426,7 +462,7 @@ static void process_message_callback(GMimeObject *part, gpointer user_data)
GList * l ;
ast_log ( LOG_WARNING , " Got unexpected GMIME_IS_MULTIPART, trying to process subparts \n " ) ;
l = GMIME_MULTIPART ( part ) - > subparts ;
l = GMIME_MULTIPART ( part ) - > subparts ;
while ( l ) {
process_message_callback ( l - > data , cbinfo ) ;
l = l - > next ;
@ -434,7 +470,6 @@ static void process_message_callback(GMimeObject *part, gpointer user_data)
} else if ( GMIME_IS_PART ( part ) ) {
const char * filename ;
ast_debug ( 3 , " Got mime part \n " ) ;
if ( ast_strlen_zero ( filename = g_mime_part_get_filename ( GMIME_PART ( part ) ) ) ) {
ast_debug ( 1 , " Skipping part with no filename \n " ) ;
return ;
@ -459,8 +494,8 @@ static int process_message(GMimeMessage *message, const char *post_dir)
}
static struct ast_str * handle_post ( struct ast_tcptls_session_instance * ser , char * uri ,
int * status , char * * title , int * contentlength , struct ast_variable * headers ,
struct ast_variable * cookies )
int * status , char * * title , int * contentlength , struct ast_variable * headers ,
struct ast_variable * cookies )
{
char buf [ 4096 ] ;
FILE * f ;
@ -474,18 +509,21 @@ static struct ast_str *handle_post(struct ast_tcptls_session_instance *ser, char
int message_count = 0 ;
for ( var = cookies ; var ; var = var - > next ) {
if ( strcasecmp ( var - > name , " mansession_id " ) )
if ( strcasecmp ( var - > name , " mansession_id " ) ) {
continue ;
}
if ( sscanf ( var - > value , " %lx " , & ident ) ! = 1 ) {
* status = 400 ;
* title = ast_strdup ( " Bad Request " ) ;
return ast_http_error ( 400 , " Bad Request " , NULL , " The was an error parsing the request. " ) ;
}
if ( ! astman_verify_session_writepermissions ( ident , EVENT_FLAG_CONFIG ) ) {
* status = 401 ;
* title = ast_strdup ( " Unauthorized " ) ;
return ast_http_error ( 401 , " Unauthorized " , NULL , " You are not authorized to make this request. " ) ;
}
@ -494,27 +532,32 @@ static struct ast_str *handle_post(struct ast_tcptls_session_instance *ser, char
if ( ! var ) {
* status = 401 ;
* title = ast_strdup ( " Unauthorized " ) ;
return ast_http_error ( 401 , " Unauthorized " , NULL , " You are not authorized to make this request. " ) ;
}
if ( ! ( f = tmpfile ( ) ) )
if ( ! ( f = tmpfile ( ) ) ) {
return NULL ;
}
for ( var = headers ; var ; var = var - > next ) {
if ( ! strcasecmp ( var - > name , " Content-Length " ) ) {
if ( ( sscanf ( var - > value , " %u " , & content_len ) ) ! = 1 ) {
ast_log ( LOG_ERROR , " Invalid Content-Length in POST request! \n " ) ;
fclose ( f ) ;
return NULL ;
}
ast_debug ( 1 , " Got a Content-Length of %d \n " , content_len ) ;
} else if ( ! strcasecmp ( var - > name , " Content-Type " ) )
} else if ( ! strcasecmp ( var - > name , " Content-Type " ) ) {
fprintf ( f , " Content-Type: %s \r \n \r \n " , var - > value ) ;
}
}
for ( res = sizeof ( buf ) ; content_len ; content_len - = res ) {
if ( content_len < res )
for ( res = sizeof ( buf ) ; content_len ; content_len - = res ) {
if ( content_len < res ) {
res = content_len ;
}
fread ( buf , 1 , res , ser - > f ) ;
fwrite ( buf , 1 , res , f ) ;
}
@ -522,6 +565,7 @@ static struct ast_str *handle_post(struct ast_tcptls_session_instance *ser, char
if ( fseek ( f , SEEK_SET , 0 ) ) {
ast_debug ( 1 , " Failed to seek temp file back to beginning. \n " ) ;
fclose ( f ) ;
return NULL ;
}
@ -531,8 +575,10 @@ static struct ast_str *handle_post(struct ast_tcptls_session_instance *ser, char
AST_RWLIST_UNLOCK ( & post_mappings ) ;
* status = 404 ;
* title = ast_strdup ( " Not Found " ) ;
return ast_http_error ( 404 , " Not Found " , NULL , " The requested URL was not found on this server. " ) ;
}
post_dir = ast_strdupa ( post_map - > to ) ;
post_map = NULL ;
AST_RWLIST_UNLOCK ( & post_mappings ) ;
@ -545,6 +591,7 @@ static struct ast_str *handle_post(struct ast_tcptls_session_instance *ser, char
ast_log ( LOG_ERROR , " Error parsing MIME data \n " ) ;
* status = 400 ;
* title = ast_strdup ( " Bad Request " ) ;
return ast_http_error ( 400 , " Bad Request " , NULL , " The was an error parsing the request. " ) ;
}
@ -552,18 +599,20 @@ static struct ast_str *handle_post(struct ast_tcptls_session_instance *ser, char
ast_log ( LOG_ERROR , " Invalid MIME data, found no parts! \n " ) ;
* status = 400 ;
* title = ast_strdup ( " Bad Request " ) ;
return ast_http_error ( 400 , " Bad Request " , NULL , " The was an error parsing the request. " ) ;
}
* status = 200 ;
* title = ast_strdup ( " OK " ) ;
return ast_http_error ( 200 , " OK " , NULL , " File successfully uploaded. " ) ;
}
# endif /* ENABLE_UPLOADS */
static struct ast_str * handle_uri ( struct ast_tcptls_session_instance * ser , char * uri , int * status ,
char * * title , int * contentlength , struct ast_variable * * cookies ,
unsigned int * static_content )
char * * title , int * contentlength , struct ast_variable * * cookies ,
unsigned int * static_content )
{
char * c ;
struct ast_str * out = NULL ;
@ -574,22 +623,25 @@ static struct ast_str *handle_uri(struct ast_tcptls_session_instance *ser, char
struct http_uri_redirect * redirect ;
strsep ( & params , " ? " ) ;
/* Extract arguments from the request and store them in variables. */
if ( params ) {
char * var , * val ;
while ( ( val = strsep ( & params , " & " ) ) ) {
var = strsep ( & val , " = " ) ;
if ( val )
if ( val ) {
ast_uri_decode ( val ) ;
else
} else {
val = " " ;
}
ast_uri_decode ( var ) ;
if ( ( v = ast_variable_new ( var , val , " " ) ) ) {
if ( vars )
if ( vars ) {
prev - > next = v ;
else
} else {
vars = v ;
}
prev = v ;
}
}
@ -599,54 +651,65 @@ static struct ast_str *handle_uri(struct ast_tcptls_session_instance *ser, char
* at the end is to avoid another pass of the cookies list to find
* the tail ) .
*/
if ( prev )
if ( prev ) {
prev - > next = * cookies ;
else
} else {
vars = * cookies ;
}
* cookies = NULL ;
ast_uri_decode ( uri ) ;
AST_RWLIST_RDLOCK ( & uri_redirects ) ;
AST_RWLIST_TRAVERSE ( & uri_redirects , redirect , entry ) {
if ( ! strcasecmp ( uri , redirect - > target ) ) {
char buf [ 512 ] ;
snprintf ( buf , sizeof ( buf ) , " Location: %s \r \n " , redirect - > dest ) ;
out = ast_http_error ( 302 , " Moved Temporarily " , buf ,
" There is no spoon... " ) ;
" There is no spoon... " ) ;
* status = 302 ;
* title = ast_strdup ( " Moved Temporarily " ) ;
break ;
}
}
AST_RWLIST_UNLOCK ( & uri_redirects ) ;
if ( redirect )
if ( redirect ) {
goto cleanup ;
}
/* We want requests to start with the prefix and '/' */
l = strlen ( prefix ) ;
if ( l & & ! strncasecmp ( uri , prefix , l ) & & uri [ l ] = = ' / ' ) {
if ( ( l = strlen ( prefix ) ) & & ! strncasecmp ( uri , prefix , l ) & & uri [ l ] = = ' / ' ) {
uri + = l + 1 ;
/* scan registered uris to see if we match one. */
AST_RWLIST_RDLOCK ( & uris ) ;
AST_RWLIST_TRAVERSE ( & uris , urih , entry ) {
l = strlen ( urih - > uri ) ;
c = uri + l ; /* candidate */
if ( strncasecmp ( urih - > uri , uri , l ) /* no match */
| | ( * c & & * c ! = ' / ' ) ) /* substring */
| | ( * c & & * c ! = ' / ' ) ) { /* substring */
continue ;
if ( * c = = ' / ' )
}
if ( * c = = ' / ' ) {
c + + ;
}
if ( ! * c | | urih - > has_subtree ) {
uri = c ;
break ;
}
}
if ( ! urih )
if ( ! urih ) {
AST_RWLIST_UNLOCK ( & uris ) ;
}
}
if ( urih ) {
if ( urih - > static_content )
* static_content = 1 ;
* static_content = urih - > static_content ;
out = urih - > callback ( ser , uri , AST_HTTP_GET , vars , status , title , contentlength ) ;
AST_RWLIST_UNLOCK ( & uris ) ;
} else {
@ -658,6 +721,7 @@ static struct ast_str *handle_uri(struct ast_tcptls_session_instance *ser, char
cleanup :
ast_variables_destroy ( vars ) ;
return out ;
}
@ -669,6 +733,7 @@ cleanup:
# define HOOK_T ssize_t
# define LEN_T size_t
# endif
/*!
* replacement read / write functions for SSL support .
* We use wrappers rather than SSL_read / SSL_write directly so
@ -716,19 +781,23 @@ static void *httpd_helper_thread(void *data)
struct ast_str * out = NULL ;
unsigned int static_content = 0 ;
if ( ! fgets ( buf , sizeof ( buf ) , ser - > f ) )
if ( ! fgets ( buf , sizeof ( buf ) , ser - > f ) ) {
goto done ;
}
uri = ast_skip_nonblanks ( buf ) ; /* Skip method */
if ( * uri )
if ( * uri ) {
* uri + + = ' \0 ' ;
}
uri = ast_skip_blanks ( uri ) ; /* Skip white space */
if ( * uri ) { /* terminate at the first blank */
char * c = ast_skip_nonblanks ( uri ) ;
if ( * c )
if ( * c ) {
* c = ' \0 ' ;
}
}
/* process "Cookie: " lines */
@ -738,23 +807,28 @@ static void *httpd_helper_thread(void *data)
/* Trim trailing characters */
ast_trim_blanks ( cookie ) ;
if ( ast_strlen_zero ( cookie ) )
if ( ast_strlen_zero ( cookie ) ) {
break ;
}
if ( strncasecmp ( cookie , " Cookie: " , 8 ) ) {
char * name , * value ;
value = ast_strdupa ( cookie ) ;
name = strsep ( & value , " : " ) ;
if ( ! value )
if ( ! value ) {
continue ;
}
value = ast_skip_blanks ( value ) ;
if ( ast_strlen_zero ( value ) )
if ( ast_strlen_zero ( value ) ) {
continue ;
}
var = ast_variable_new ( name , value , " " ) ;
if ( ! var )
if ( ! var ) {
continue ;
}
var - > next = headers ;
headers = var ;
continue ;
}
@ -777,21 +851,23 @@ static void *httpd_helper_thread(void *data)
past the version to get to the name */
if ( * vname = = ' $ ' ) {
strsep ( & vname , " ; " ) ;
if ( ! vname ) /* no name ? */
if ( ! vname ) { /* no name ? */
continue ;
}
vname = ast_skip_blanks ( vname ) ;
}
vval = strchr ( vname , ' = ' ) ;
if ( ! vval )
if ( ! ( vval = strchr ( vname , ' = ' ) ) ) {
continue ;
}
/* Ditch the = and the quotes */
* vval + + = ' \0 ' ;
if ( * vval )
if ( * vval ) {
vval + + ;
if ( ( l = strlen ( vval ) ) )
}
if ( ( l = strlen ( vval ) ) ) {
vval [ l - 1 ] = ' \0 ' ; /* trim trailing quote */
var = ast_variable_new ( vname , vval , " " ) ;
if ( var ) {
}
if ( ( var = ast_variable_new ( vname , vval , " " ) ) ) {
if ( prev )
prev - > next = var ;
else
@ -817,11 +893,13 @@ static void *httpd_helper_thread(void *data)
}
/* If they aren't mopped up already, clean up the cookies */
if ( vars )
if ( vars ) {
ast_variables_destroy ( vars ) ;
}
/* Clean up all the header information pulled as well */
if ( headers )
if ( headers ) {
ast_variables_destroy ( headers ) ;
}
if ( out ) {
struct timeval tv = ast_tvnow ( ) ;
@ -829,11 +907,12 @@ static void *httpd_helper_thread(void *data)
struct ast_tm tm ;
ast_strftime ( timebuf , sizeof ( timebuf ) , " %a, %d %b %Y %H:%M:%S %Z " , ast_localtime ( & tv , & tm , " GMT " ) ) ;
fprintf ( ser - > f , " HTTP/1.1 %d %s \r \n "
" Server: Asterisk/%s \r \n "
" Date: %s \r \n "
" Connection: close \r \n "
" %s " ,
fprintf ( ser - > f ,
" HTTP/1.1 %d %s \r \n "
" Server: Asterisk/%s \r \n "
" Date: %s \r \n "
" Connection: close \r \n "
" %s " ,
status , title ? title : " OK " , ast_get_version ( ) , timebuf ,
static_content ? " " : " Cache-Control: no-cache, no-store \r \n " ) ;
/* We set the no-cache headers only for dynamic content.
@ -854,12 +933,15 @@ static void *httpd_helper_thread(void *data)
}
ast_free ( out ) ;
}
if ( title )
if ( title ) {
ast_free ( title ) ;
}
done :
fclose ( ser - > f ) ;
ser = ast_tcptls_session_instance_destroy ( ser ) ;
return NULL ;
}
@ -889,8 +971,9 @@ static void add_redirect(const char *value)
target_len = strlen ( target ) + 1 ;
total_len = sizeof ( * redirect ) + target_len + strlen ( dest ) + 1 ;
if ( ! ( redirect = ast_calloc ( 1 , total_len ) ) )
if ( ! ( redirect = ast_calloc ( 1 , total_len ) ) ) {
return ;
}
redirect - > dest = redirect - > target + target_len ;
strcpy ( redirect - > target , target ) ;
@ -899,18 +982,20 @@ static void add_redirect(const char *value)
AST_RWLIST_WRLOCK ( & uri_redirects ) ;
target_len - - ; /* So we can compare directly with strlen() */
if ( AST_RWLIST_EMPTY ( & uri_redirects )
| | strlen ( AST_RWLIST_FIRST ( & uri_redirects ) - > target ) < = target_len ) {
if ( AST_RWLIST_EMPTY ( & uri_redirects )
| | strlen ( AST_RWLIST_FIRST ( & uri_redirects ) - > target ) < = target_len ) {
AST_RWLIST_INSERT_HEAD ( & uri_redirects , redirect , entry ) ;
AST_RWLIST_UNLOCK ( & uri_redirects ) ;
return ;
}
AST_RWLIST_TRAVERSE ( & uri_redirects , cur , entry ) {
if ( AST_RWLIST_NEXT ( cur , entry )
& & strlen ( AST_RWLIST_NEXT ( cur , entry ) - > target ) < = target_len ) {
if ( AST_RWLIST_NEXT ( cur , entry )
& & strlen ( AST_RWLIST_NEXT ( cur , entry ) - > target ) < = target_len ) {
AST_RWLIST_INSERT_AFTER ( & uri_redirects , cur , redirect , entry ) ;
AST_RWLIST_UNLOCK ( & uri_redirects ) ;
return ;
}
}
@ -923,10 +1008,12 @@ static void add_redirect(const char *value)
# ifdef ENABLE_UPLOADS
static void destroy_post_mapping ( struct ast_http_post_mapping * post_map )
{
if ( post_map - > from )
if ( post_map - > from ) {
ast_free ( post_map - > from ) ;
if ( post_map - > to )
}
if ( post_map - > to ) {
ast_free ( post_map - > to ) ;
}
ast_free ( post_map ) ;
}
@ -935,8 +1022,9 @@ static void destroy_post_mappings(void)
struct ast_http_post_mapping * post_map ;
AST_RWLIST_WRLOCK ( & post_mappings ) ;
while ( ( post_map = AST_RWLIST_REMOVE_HEAD ( & post_mappings , entry ) ) )
while ( ( post_map = AST_RWLIST_REMOVE_HEAD ( & post_mappings , entry ) ) ) {
destroy_post_mapping ( post_map ) ;
}
AST_RWLIST_UNLOCK ( & post_mappings ) ;
}
@ -944,16 +1032,19 @@ static void add_post_mapping(const char *from, const char *to)
{
struct ast_http_post_mapping * post_map ;
if ( ! ( post_map = ast_calloc ( 1 , sizeof ( * post_map ) ) ) )
if ( ! ( post_map = ast_calloc ( 1 , sizeof ( * post_map ) ) ) ) {
return ;
}
if ( ! ( post_map - > from = ast_strdup ( from ) ) ) {
destroy_post_mapping ( post_map ) ;
return ;
}
if ( ! ( post_map - > to = ast_strdup ( to ) ) ) {
destroy_post_mapping ( post_map ) ;
return ;
}
@ -976,8 +1067,9 @@ static int __ast_http_load(int reload)
struct http_uri_redirect * redirect ;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 } ;
if ( ( cfg = ast_config_load ( " http.conf " , config_flags ) ) = = CONFIG_STATUS_FILEUNCHANGED )
if ( ( cfg = ast_config_load ( " http.conf " , config_flags ) ) = = CONFIG_STATUS_FILEUNCHANGED ) {
return 0 ;
}
/* default values */
memset ( & http_desc . sin , 0 , sizeof ( http_desc . sin ) ) ;
@ -987,16 +1079,19 @@ static int __ast_http_load(int reload)
https_desc . sin . sin_port = htons ( 8089 ) ;
http_tls_cfg . enabled = 0 ;
if ( http_tls_cfg . certfile )
if ( http_tls_cfg . certfile ) {
ast_free ( http_tls_cfg . certfile ) ;
}
http_tls_cfg . certfile = ast_strdup ( AST_CERTFILE ) ;
if ( http_tls_cfg . cipher )
if ( http_tls_cfg . cipher ) {
ast_free ( http_tls_cfg . cipher ) ;
}
http_tls_cfg . cipher = ast_strdup ( " " ) ;
AST_RWLIST_WRLOCK ( & uri_redirects ) ;
while ( ( redirect = AST_RWLIST_REMOVE_HEAD ( & uri_redirects , entry ) ) )
while ( ( redirect = AST_RWLIST_REMOVE_HEAD ( & uri_redirects , entry ) ) ) {
ast_free ( redirect ) ;
}
AST_RWLIST_UNLOCK ( & uri_redirects ) ;
# ifdef ENABLE_UPLOADS
@ -1006,24 +1101,23 @@ static int __ast_http_load(int reload)
if ( cfg ) {
v = ast_variable_browse ( cfg , " general " ) ;
for ( ; v ; v = v - > next ) {
if ( ! strcasecmp ( v - > name , " enabled " ) )
if ( ! strcasecmp ( v - > name , " enabled " ) ) {
enabled = ast_true ( v - > value ) ;
else if ( ! strcasecmp ( v - > name , " sslenable " ) )
} else if ( ! strcasecmp ( v - > name , " sslenable " ) ) {
http_tls_cfg . enabled = ast_true ( v - > value ) ;
else if ( ! strcasecmp ( v - > name , " sslbindport " ) )
} else if ( ! strcasecmp ( v - > name , " sslbindport " ) ) {
https_desc . sin . sin_port = htons ( atoi ( v - > value ) ) ;
else if ( ! strcasecmp ( v - > name , " sslcert " ) ) {
} else if ( ! strcasecmp ( v - > name , " sslcert " ) ) {
ast_free ( http_tls_cfg . certfile ) ;
http_tls_cfg . certfile = ast_strdup ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " sslcipher " ) ) {
ast_free ( http_tls_cfg . cipher ) ;
http_tls_cfg . cipher = ast_strdup ( v - > value ) ;
}
else if ( ! strcasecmp ( v - > name , " enablestatic " ) )
} else if ( ! strcasecmp ( v - > name , " enablestatic " ) ) {
newenablestatic = ast_true ( v - > value ) ;
else if ( ! strcasecmp ( v - > name , " bindport " ) )
} else if ( ! strcasecmp ( v - > name , " bindport " ) ) {
http_desc . sin . sin_port = htons ( atoi ( v - > value ) ) ;
else if ( ! strcasecmp ( v - > name , " sslbindaddr " ) ) {
} else if ( ! strcasecmp ( v - > name , " sslbindaddr " ) ) {
if ( ( hp = ast_gethostbyname ( v - > value , & ahp ) ) ) {
memcpy ( & https_desc . sin . sin_addr , hp - > h_addr , sizeof ( https_desc . sin . sin_addr ) ) ;
have_sslbindaddr = 1 ;
@ -1051,22 +1145,28 @@ static int __ast_http_load(int reload)
}
# ifdef ENABLE_UPLOADS
for ( v = ast_variable_browse ( cfg , " post_mappings " ) ; v ; v = v - > next )
for ( v = ast_variable_browse ( cfg , " post_mappings " ) ; v ; v = v - > next ) {
add_post_mapping ( v - > name , v - > value ) ;
}
# endif /* ENABLE_UPLOADS */
ast_config_destroy ( cfg ) ;
}
if ( ! have_sslbindaddr )
if ( ! have_sslbindaddr ) {
https_desc . sin . sin_addr = http_desc . sin . sin_addr ;
if ( enabled )
}
if ( enabled ) {
http_desc . sin . sin_family = https_desc . sin . sin_family = AF_INET ;
if ( strcmp ( prefix , newprefix ) )
}
if ( strcmp ( prefix , newprefix ) ) {
ast_copy_string ( prefix , newprefix , sizeof ( prefix ) ) ;
}
enablestatic = newenablestatic ;
ast_tcptls_server_start ( & http_desc ) ;
if ( ast_ssl_setup ( https_desc . tls_cfg ) )
if ( ast_ssl_setup ( https_desc . tls_cfg ) ) {
ast_tcptls_server_start ( & https_desc ) ;
}
return 0 ;
}
@ -1091,20 +1191,22 @@ static char *handle_show_http(struct ast_cli_entry *e, int cmd, struct ast_cli_a
return NULL ;
}
if ( a - > argc ! = 3 )
if ( a - > argc ! = 3 ) {
return CLI_SHOWUSAGE ;
}
ast_cli ( a - > fd , " HTTP Server Status: \n " ) ;
ast_cli ( a - > fd , " Prefix: %s \n " , prefix ) ;
if ( ! http_desc . oldsin . sin_family )
if ( ! http_desc . oldsin . sin_family ) {
ast_cli ( a - > fd , " Server Disabled \n \n " ) ;
else {
} else {
ast_cli ( a - > fd , " Server Enabled and Bound to %s:%d \n \n " ,
ast_inet_ntoa ( http_desc . oldsin . sin_addr ) ,
ntohs ( http_desc . oldsin . sin_port ) ) ;
if ( http_tls_cfg . enabled )
if ( http_tls_cfg . enabled ) {
ast_cli ( a - > fd , " HTTPS Server Enabled and Bound to %s:%d \n \n " ,
ast_inet_ntoa ( https_desc . oldsin . sin_addr ) ,
ntohs ( https_desc . oldsin . sin_port ) ) ;
}
}
ast_cli ( a - > fd , " Enabled URI's: \n " ) ;
@ -1112,17 +1214,20 @@ static char *handle_show_http(struct ast_cli_entry *e, int cmd, struct ast_cli_a
if ( AST_RWLIST_EMPTY ( & uris ) ) {
ast_cli ( a - > fd , " None. \n " ) ;
} else {
AST_RWLIST_TRAVERSE ( & uris , urih , entry )
ast_cli ( a - > fd , " %s/%s%s => %s \n " , prefix , urih - > uri , ( urih - > has_subtree ? " /... " : " " ) , urih - > description ) ;
AST_RWLIST_TRAVERSE ( & uris , urih , entry ) {
ast_cli ( a - > fd , " %s/%s%s => %s \n " , prefix , urih - > uri , ( urih - > has_subtree ? " /... " : " " ) , urih - > description ) ;
}
}
AST_RWLIST_UNLOCK ( & uris ) ;
ast_cli ( a - > fd , " \n Enabled Redirects: \n " ) ;
AST_RWLIST_RDLOCK ( & uri_redirects ) ;
AST_RWLIST_TRAVERSE ( & uri_redirects , redirect , entry )
AST_RWLIST_TRAVERSE ( & uri_redirects , redirect , entry ) {
ast_cli ( a - > fd , " %s => %s \n " , redirect - > target , redirect - > dest ) ;
if ( AST_RWLIST_EMPTY ( & uri_redirects ) )
}
if ( AST_RWLIST_EMPTY ( & uri_redirects ) ) {
ast_cli ( a - > fd , " None. \n " ) ;
}
AST_RWLIST_UNLOCK ( & uri_redirects ) ;