diff --git a/include/dirlisting.h b/include/dirlisting.h index 4b499b2..ea4c9cf 100644 --- a/include/dirlisting.h +++ b/include/dirlisting.h @@ -11,6 +11,6 @@ #ifndef DIRLISTING_H #define DIRLISTING_H -char* create_dirlisting(const char *url, const char *localpath); +char* create_dirlisting(const char *url, const char *localpath, int uploadEnabled); #endif // DIRLISTING_H diff --git a/include/main.h b/include/main.h index b330962..129493d 100644 --- a/include/main.h +++ b/include/main.h @@ -20,6 +20,8 @@ struct ConnectionState { char localFileName[PATH_MAX]; struct stat targetStat; + uint8_t uploadRequest; + FILE *upload_fd; enum ResultCode result; diff --git a/include/templates.h b/include/templates.h index e15e6de..ec3782f 100644 --- a/include/templates.h +++ b/include/templates.h @@ -87,4 +87,18 @@ " " \ FOOTER +#define UPLOAD_FORM \ + HEADER1 \ + " Upload" \ + HEADER2 \ + "

Upload

" \ + "

You can upload a file to the current directory here.

" \ + "

" \ + "

" \ + " " \ + " " \ + "
" \ + "

" \ + FOOTER + #endif // TEMPLATES_H diff --git a/src/dirlisting.c b/src/dirlisting.c index 6583a09..a5117a3 100644 --- a/src/dirlisting.c +++ b/src/dirlisting.c @@ -63,7 +63,7 @@ static int compare_entries(const void *sp1,const void *sp2 ) { return( strcasecmp(e1->name, e2->name) ); } -char* gen_html(const char *url, struct Entry *entries, size_t numentries) { +char* gen_html(const char *url, struct Entry *entries, size_t numentries, int uploadEnabled) { char *result; size_t allocated; size_t i; @@ -198,12 +198,18 @@ char* gen_html(const char *url, struct Entry *entries, size_t numentries) { } strcat(result, ""); + + if(uploadEnabled) { + strcat(result, "

Upload

"); + strcat(result, "

Upload a file to this directory

"); + } + strcat(result, FOOTER); return result; } -char* create_dirlisting(const char *url, const char *localpath) { +char* create_dirlisting(const char *url, const char *localpath, int uploadEnabled) { char *result; struct Entry *entries; @@ -288,7 +294,7 @@ char* create_dirlisting(const char *url, const char *localpath) { qsort(entries, numentries, sizeof(struct Entry), compare_entries); - result = gen_html(url, entries, numentries); + result = gen_html(url, entries, numentries, uploadEnabled); for(i = 0; i < numentries; i++) { if(entries[i].flags & FLG_USED) free(entries[i].name); diff --git a/src/main.c b/src/main.c index ae8f64c..cb2172b 100644 --- a/src/main.c +++ b/src/main.c @@ -55,6 +55,7 @@ magic_t magicCookie; #endif int running = 1; +int uploadEnabled = 1; void request_completed(void *cls, struct MHD_Connection * connection, @@ -208,7 +209,7 @@ int serv_directory(struct MHD_Connection *connection, struct ConnectionState *co LOG(LVL_DEBUG, "Generating directory listing for %s.", connstate->localFileName); - char *result = create_dirlisting(connstate->cleanedURL, connstate->localFileName); + char *result = create_dirlisting(connstate->cleanedURL, connstate->localFileName, uploadEnabled); if(!result) { LOG(LVL_ERR, "Failed to generate dirlisting for %s.", connstate->localFileName); return MHD_queue_response(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, error500Response); @@ -259,7 +260,13 @@ int serv_result_page(struct MHD_Connection *connection, struct ConnectionState * char *buffer = malloc(strlen(HEADER1 HEADER2 FOOTER) + 1024); - sprintf(buffer, HEADER1 "%s" HEADER2 "

%s

%s

" FOOTER, + sprintf(buffer, + HEADER1 + "%s" + HEADER2 + "

%s

%s

" + "

Back to the directory listing.

" + FOOTER, title, title, message); response = MHD_create_response_from_buffer( @@ -333,6 +340,24 @@ static int post_processor(void *cls, return MHD_NO; } +int key_value_iterator(void *cls, + enum MHD_ValueKind kind, + const char *key, const char *value) { + struct ConnectionState *connstate = (struct ConnectionState*)cls; + + if(kind == MHD_GET_ARGUMENT_KIND) { + if(strcmp(key, "upload") == 0) { + connstate->uploadRequest = 1; + return MHD_NO; // this is the only argument we search for + } + + return MHD_YES; + } else { + return MHD_NO; + } +} + + static int connection_handler(void * cls, struct MHD_Connection *connection, const char *url, @@ -351,6 +376,7 @@ static int connection_handler(void * cls, connstate->result = RC_OK; connstate->upload_fd = NULL; + connstate->uploadRequest = 0; // set the local file name strncpy(connstate->localFileName, shareRoot, PATH_MAX); @@ -366,6 +392,9 @@ static int connection_handler(void * cls, method, url, connstate->localFileName); if (0 == strcmp(method, "GET") || 0 == strcmp(method, "HEAD")) { + // process GET arguments + MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, key_value_iterator, connstate); + connstate->postProcessor = NULL; connstate->requestType = GET; } else if(0 == strcmp(method, "POST")) { @@ -413,7 +442,11 @@ static int connection_handler(void * cls, if(S_ISREG(connstate->targetStat.st_mode)) { return serv_regular_file(connection, connstate); } else if(S_ISDIR(connstate->targetStat.st_mode)) { - return serv_directory(connection, connstate); + if(connstate->uploadRequest) { + return MHD_queue_response(connection, MHD_HTTP_OK, uploadFormResponse); + } else { + return serv_directory(connection, connstate); + } } else { LOG(LVL_WARN, "%s is neither a directory nor a regular file. Don't allow the access.",