@ -38,6 +38,7 @@
# include "multipart_parser.h"
# define READ_BLOCK 4096
# define POST_LIMIT 131072
enum part {
PART_UNKNOWN ,
@ -223,55 +224,86 @@ urldecode(char *buf)
return true ;
}
static bool
static char *
postdecode ( char * * fields , int n_fields )
{
char * p ;
const char * var ;
static char buf [ 1024 ] ;
int i , len , field , found = 0 ;
char * p , * postbuf ;
int i , field , found = 0 ;
ssize_t len = 0 , rlen = 0 , content_length = 0 ;
var = getenv ( " CONTENT_TYPE " ) ;
if ( ! var | | strncmp ( var , " application/x-www-form-urlencoded " , 33 ) )
return false ;
return NULL ;
var = getenv ( " CONTENT_LENGTH " ) ;
if ( ! var )
return NULL ;
content_length = strtol ( var , & p , 10 ) ;
if ( p = = var | | content_length < = 0 | | content_length > = POST_LIMIT )
return NULL ;
postbuf = calloc ( 1 , content_length + 1 ) ;
if ( postbuf = = NULL )
return NULL ;
for ( len = 0 ; len < content_length ; )
{
rlen = read ( 0 , postbuf + len , content_length - len ) ;
if ( rlen < = 0 )
break ;
memset ( buf , 0 , sizeof ( buf ) ) ;
len + = rlen ;
}
if ( ( len = read ( 0 , buf , sizeof ( buf ) - 1 ) ) > 0 )
if ( len < content_length )
{
for ( p = buf , i = 0 ; i < = len ; i + + )
free ( postbuf ) ;
return NULL ;
}
for ( p = postbuf , i = 0 ; i < = len ; i + + )
{
if ( postbuf [ i ] = = ' = ' )
{
if ( buf [ i ] = = ' = ' )
{
buf [ i ] = 0 ;
postbuf [ i ] = 0 ;
for ( field = 0 ; field < ( n_fields * 2 ) ; field + = 2 )
for ( field = 0 ; field < ( n_fields * 2 ) ; field + = 2 )
{
if ( ! strcmp ( p , fields [ field ] ) )
{
if ( ! strcmp ( p , fields [ field ] ) )
{
fields [ field + 1 ] = buf + i + 1 ;
found + + ;
}
fields [ field + 1 ] = postbuf + i + 1 ;
found + + ;
}
}
else if ( buf [ i ] = = ' & ' | | buf [ i ] = = ' \0 ' )
{
buf [ i ] = 0 ;
}
else if ( postbuf [ i ] = = ' & ' | | postbuf [ i ] = = ' \0 ' )
{
postbuf [ i ] = 0 ;
if ( found > = n_fields )
break ;
if ( found > = n_fields )
break ;
p = buf + i + 1 ;
}
p = postbuf + i + 1 ;
}
}
for ( field = 0 ; field < ( n_fields * 2 ) ; field + = 2 )
{
if ( ! urldecode ( fields [ field + 1 ] ) )
return false ;
{
free ( postbuf ) ;
return NULL ;
}
}
return ( found > = n_fields ) ;
return postbuf ;
}
static char *
@ -658,6 +690,14 @@ main_upload(int argc, char *argv[])
return 0 ;
}
static void
free_charp ( char * * ptr )
{
free ( * ptr ) ;
}
# define autochar __attribute__((__cleanup__(free_charp))) char
static int
main_download ( int argc , char * * argv )
{
@ -668,7 +708,7 @@ main_download(int argc, char **argv)
struct stat s ;
int rfd ;
postdecode ( fields , 4 ) ;
autochar * post = postdecode ( fields , 4 ) ;
if ( ! fields [ 1 ] | | ! session_access ( fields [ 1 ] , " cgi-io " , " download " , " read " ) )
return failure ( 403 , 0 , " Download permission denied " ) ;
@ -706,29 +746,39 @@ main_download(int argc, char **argv)
if ( fields [ 5 ] )
printf ( " Content-Disposition: attachment; filename= \" %s \" \r \n " , fields [ 5 ] ) ;
printf ( " Content-Length: %llu \r \n \r \n " , size ) ;
fflush ( stdout ) ;
if ( size > 0 ) {
printf ( " Content-Length: %llu \r \n \r \n " , size ) ;
fflush ( stdout ) ;
while ( size > 0 ) {
len = sendfile ( 1 , rfd , NULL , size ) ;
while ( size > 0 ) {
len = sendfile ( 1 , rfd , NULL , size ) ;
if ( len = = - 1 ) {
if ( errno = = ENOSYS | | errno = = EINVAL ) {
while ( ( len = read ( rfd , buf , sizeof ( buf ) ) ) > 0 )
fwrite ( buf , len , 1 , stdout ) ;
if ( len = = - 1 ) {
if ( errno = = ENOSYS | | errno = = EINVAL ) {
while ( ( len = read ( rfd , buf , sizeof ( buf ) ) ) > 0 )
fwrite ( buf , len , 1 , stdout ) ;
fflush ( stdout ) ;
break ;
fflush ( stdout ) ;
break ;
}
if ( errno = = EINTR | | errno = = EAGAIN )
continue ;
}
if ( errno = = EINTR | | errno = = EAGAIN )
continue ;
if ( len < = 0 )
break ;
size - = len ;
}
}
else {
printf ( " \r \n " ) ;
if ( len < = 0 )
break ;
while ( ( len = read ( rfd , buf , sizeof ( buf ) ) ) > 0 )
fwrite ( buf , len , 1 , stdout ) ;
size - = len ;
fflush ( stdout ) ;
}
close ( rfd ) ;
@ -749,7 +799,9 @@ main_backup(int argc, char **argv)
char hostname [ 64 ] = { 0 } ;
char * fields [ ] = { " sessionid " , NULL } ;
if ( ! postdecode ( fields , 1 ) | | ! session_access ( fields [ 1 ] , " cgi-io " , " backup " , " read " ) )
autochar * post = postdecode ( fields , 1 ) ;
if ( ! fields [ 1 ] | | ! session_access ( fields [ 1 ] , " cgi-io " , " backup " , " read " ) )
return failure ( 403 , 0 , " Backup permission denied " ) ;
if ( pipe ( fds ) )
@ -929,7 +981,7 @@ main_exec(int argc, char **argv)
char * p , * * args ;
pid_t pid ;
postdecode ( fields , 4 ) ;
autochar * post = postdecode ( fields , 4 ) ;
if ( ! fields [ 1 ] | | ! session_access ( fields [ 1 ] , " cgi-io " , " exec " , " read " ) )
return failure ( 403 , 0 , " Exec permission denied " ) ;