diff --git a/TODO b/TODO index 9c72b93..3e316dc 100644 --- a/TODO +++ b/TODO @@ -26,8 +26,6 @@ - add an option to only call device/get_status in configurable intervals - add an option to make file cache size configurable - write man pages - - username and password must be urlencoded in - mfapi/apicalls/user_get_session_token.c - implement truncate (problem: zero byte files are not allowed at the remote) - move uploading of files from release() to flush() because the return value of release is ignored and because the calling close() returns diff --git a/fuse/operations.c b/fuse/operations.c index 8e24f7c..6490419 100644 --- a/fuse/operations.c +++ b/fuse/operations.c @@ -612,7 +612,8 @@ int mediafirefs_release(const char *path, struct fuse_file_info *file_info) // hash exists, so use upload/instant retval = mfconn_api_upload_instant(ctx->conn, NULL, - file_name, hash, size, folder_key); + file_name, hash, size, + folder_key); fclose(fh); free(temp1); @@ -630,7 +631,7 @@ int mediafirefs_release(const char *path, struct fuse_file_info *file_info) // hash does not exist, so do full upload upload_key = NULL; retval = mfconn_api_upload_simple(ctx->conn, folder_key, - fh, file_name, &upload_key); + fh, file_name, &upload_key); fclose(fh); free(temp1); diff --git a/mfapi/apicalls.h b/mfapi/apicalls.h index 2ca4a3b..fb7682b 100644 --- a/mfapi/apicalls.h +++ b/mfapi/apicalls.h @@ -145,11 +145,13 @@ int mfconn_api_device_get_patch(mfconn * conn, mfpatch * patch, int mfconn_api_upload_check(mfconn * conn, const char *filename, const char *hash, uint64_t size, const char *folder_key, - struct mfconn_upload_check_result *result); + struct mfconn_upload_check_result + *result); int mfconn_api_upload_instant(mfconn * conn, const char *quick_key, - const char *filename, const char *hash, - uint64_t size, const char *folder_key); + const char *filename, + const char *hash, uint64_t size, + const char *folder_key); int mfconn_api_upload_simple(mfconn * conn, const char *folderkey, FILE * fh, const char *file_name, diff --git a/mfapi/apicalls/file_update.c b/mfapi/apicalls/file_update.c index 2efb2b3..2699cf0 100644 --- a/mfapi/apicalls/file_update.c +++ b/mfapi/apicalls/file_update.c @@ -32,6 +32,7 @@ int mfconn_api_file_update(mfconn * conn, const char *quickkey, int retval; mfhttp *http; int i; + char *filename_urlenc; if (conn == NULL) return -1; @@ -49,11 +50,17 @@ int mfconn_api_file_update(mfconn * conn, const char *quickkey, return -1; for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { + filename_urlenc = urlencode(filename); + if (filename_urlenc == NULL) { + fprintf(stderr, "urlencode failed\n"); + return -1; + } api_call = mfconn_create_signed_get(conn, 0, "file/update.php", "?quick_key=%s" "&filename=%s" "&response_format=json", quickkey, - filename); + filename_urlenc); + free(filename_urlenc); if (api_call == NULL) { fprintf(stderr, "mfconn_create_signed_get failed\n"); return -1; diff --git a/mfapi/apicalls/folder_create.c b/mfapi/apicalls/folder_create.c index 70526eb..66ee4e2 100644 --- a/mfapi/apicalls/folder_create.c +++ b/mfapi/apicalls/folder_create.c @@ -32,6 +32,7 @@ int mfconn_api_folder_create(mfconn * conn, const char *parent, int retval; mfhttp *http; int i; + char *name_urlenc; if (conn == NULL) return -1; @@ -47,18 +48,24 @@ int mfconn_api_folder_create(mfconn * conn, const char *parent, } for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { + name_urlenc = urlencode(name); + if (name_urlenc == NULL) { + fprintf(stderr, "urlencode failed\n"); + return -1; + } if (parent != NULL) { api_call = mfconn_create_signed_get(conn, 0, "folder/create.php", "?parent_key=%s&foldername=%s" "&response_format=json", parent, - name); + name_urlenc); } else { api_call = mfconn_create_signed_get(conn, 0, "folder/create.php", "?foldername=%s&response_format=json", - name); + name_urlenc); } + free(name_urlenc); if (api_call == NULL) { fprintf(stderr, "mfconn_create_signed_get failed\n"); return -1; diff --git a/mfapi/apicalls/folder_update.c b/mfapi/apicalls/folder_update.c index 591894a..6317f39 100644 --- a/mfapi/apicalls/folder_update.c +++ b/mfapi/apicalls/folder_update.c @@ -32,6 +32,7 @@ int mfconn_api_folder_update(mfconn * conn, const char *folder_key, int retval; mfhttp *http; int i; + char *foldername_urlenc; if (conn == NULL) return -1; @@ -49,11 +50,17 @@ int mfconn_api_folder_update(mfconn * conn, const char *folder_key, return -1; for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { + foldername_urlenc = urlencode(foldername); + if (foldername_urlenc == NULL) { + fprintf(stderr, "urlencode failed\n"); + return -1; + } api_call = mfconn_create_signed_get(conn, 0, "folder/update.php", "?folder_key=%s" "&foldername=%s" "&response_format=json", - folder_key, foldername); + folder_key, foldername_urlenc); + free(foldername_urlenc); if (api_call == NULL) { fprintf(stderr, "mfconn_create_signed_get failed\n"); return -1; diff --git a/mfapi/apicalls/upload_check.c b/mfapi/apicalls/upload_check.c index 86fd024..95091dc 100644 --- a/mfapi/apicalls/upload_check.c +++ b/mfapi/apicalls/upload_check.c @@ -22,22 +22,24 @@ #include #include #include +#include #include "../../utils/http.h" #include "../mfconn.h" -#include "../patch.h" #include "../apicalls.h" // IWYU pragma: keep static int _decode_upload_check(mfhttp * conn, void *data); -int mfconn_api_upload_check(mfconn * conn, const char *filename, const char *hash, - uint64_t size, const char *folder_key, +int mfconn_api_upload_check(mfconn * conn, const char *filename, + const char *hash, uint64_t size, + const char *folder_key, struct mfconn_upload_check_result *result) { const char *api_call; int retval; mfhttp *http; int i; + char *filename_urlenc; if (conn == NULL) return -1; @@ -58,13 +60,19 @@ int mfconn_api_upload_check(mfconn * conn, const char *filename, const char *has } for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { + filename_urlenc = urlencode(filename); + if (filename_urlenc == NULL) { + fprintf(stderr, "urlencode failed\n"); + return -1; + } api_call = mfconn_create_signed_get(conn, 0, "upload/check.php", "?response_format=json" "&filename=%s" "&size=%" PRIu64 "&hash=%s" - "&folder_key=%s", filename, + "&folder_key=%s", filename_urlenc, size, hash, folder_key); + free(filename_urlenc); if (api_call == NULL) { fprintf(stderr, "mfconn_create_signed_get failed\n"); return -1; @@ -98,7 +106,7 @@ int mfconn_api_upload_check(mfconn * conn, const char *filename, const char *has return retval; } -static int _decode_upload_check(mfhttp * conn, void *data) +static int _decode_upload_check(mfhttp * conn, void *data) { json_error_t error; json_t *obj; @@ -160,7 +168,8 @@ static int _decode_upload_check(mfhttp * conn, void *data) return -1; } if (!json_is_string(obj)) { - fprintf(stderr, "response/in_account is not expected type string\n"); + fprintf(stderr, + "response/in_account is not expected type string\n"); json_decref(root); return -1; } @@ -206,7 +215,8 @@ static int _decode_upload_check(mfhttp * conn, void *data) return -1; } if (!json_is_string(obj)) { - fprintf(stderr, "response/different_hash is not expected type string\n"); + fprintf(stderr, + "response/different_hash is not expected type string\n"); json_decref(root); return -1; } diff --git a/mfapi/apicalls/upload_instant.c b/mfapi/apicalls/upload_instant.c index f8b2d09..c63311f 100644 --- a/mfapi/apicalls/upload_instant.c +++ b/mfapi/apicalls/upload_instant.c @@ -18,8 +18,8 @@ #include #include -#include #include +#include #include "../../utils/http.h" #include "../mfconn.h" @@ -33,6 +33,7 @@ int mfconn_api_upload_instant(mfconn * conn, const char *quick_key, int retval; mfhttp *http; int i; + char *filename_urlenc; if (conn == NULL) return -1; @@ -51,17 +52,22 @@ int mfconn_api_upload_instant(mfconn * conn, const char *quick_key, "&hash=%s" "&response_format=json", quick_key, size, hash); - } else if (filename != NULL && filename[0] != '\0' - && folder_key != 0) { + } else if (filename != NULL && filename[0] != '\0' && folder_key != 0) { // upload a new file + filename_urlenc = urlencode(filename); + if (filename_urlenc == NULL) { + fprintf(stderr, "urlencode failed\n"); + return -1; + } api_call = mfconn_create_signed_get(conn, 0, "upload/instant.php", "?folder_key=%s" "&filename=%s" "&size=%" PRIu64 "&hash=%s" "&response_format=json", - folder_key, filename, size, - hash); + folder_key, filename_urlenc, + size, hash); + free(filename_urlenc); } else { fprintf(stderr, "you must either pass a quick_key or a filename " "and folder_key\n"); @@ -75,7 +81,8 @@ int mfconn_api_upload_instant(mfconn * conn, const char *quick_key, http = http_create(); retval = - http_get_buf(http, api_call, mfapi_decode_common, "upload/instant"); + http_get_buf(http, api_call, mfapi_decode_common, + "upload/instant"); http_destroy(http); mfconn_update_secret_key(conn); diff --git a/mfapi/apicalls/user_get_session_token.c b/mfapi/apicalls/user_get_session_token.c index be7c6a7..36571f8 100644 --- a/mfapi/apicalls/user_get_session_token.c +++ b/mfapi/apicalls/user_get_session_token.c @@ -55,6 +55,8 @@ mfconn_api_user_get_session_token(mfconn * conn, const char *server, struct user_get_session_token_response response; mfhttp *http; int i; + char *username_urlenc; + char *password_urlenc; if (conn == NULL) return -1; @@ -81,15 +83,26 @@ mfconn_api_user_get_session_token(mfconn * conn, const char *server, mfconn_create_user_signature(conn, username, password, app_id, app_key); - // FIXME: username and password have to be urlencoded (maybe using - // curl_easy_escape) + username_urlenc = urlencode(username); + if (username_urlenc == NULL) { + fprintf(stderr, "urlencode failed\n"); + return -1; + } + password_urlenc = urlencode(password); + if (password_urlenc == NULL) { + fprintf(stderr, "urlencode failed\n"); + return -1; + } post_args = strdup_printf("email=%s" "&password=%s" "&application_id=%d" "&signature=%s" "&token_version=2" "&response_format=json", - username, password, app_id, user_signature); + username_urlenc, password_urlenc, app_id, + user_signature); + free(username_urlenc); + free(password_urlenc); free((void *)user_signature); http = http_create(); diff --git a/utils/http.c b/utils/http.c index 4f008a7..cb77955 100644 --- a/utils/http.c +++ b/utils/http.c @@ -328,3 +328,39 @@ http_post_file(mfhttp * conn, const char *url, FILE * fh, retval = data_handler(conn, data); return retval; } + +// we roll our own urlencode function because curl_easy_escape requires a curl +// handle +char *urlencode(const char *inp) +{ + char *buf; + char *bufp; + char hex[] = "0123456789abcdef"; + + // allocating three times the length of the input because in the worst + // case each character must be urlencoded and add a byte for the + // terminating zero + bufp = buf = (char *)malloc(strlen(inp) * 3 + 1); + + if (buf == NULL) { + fprintf(stderr, "malloc failed\n"); + return NULL; + } + + while (*inp) { + if ((*inp >= '0' && *inp <= '9') + || (*inp >= 'A' && *inp <= 'Z') + || (*inp >= 'a' && *inp <= 'z') + || *inp == '-' || *inp == '_' || *inp == '.' || *inp == '~') { + *bufp++ = *inp; + } else { + *bufp++ = '%'; + *bufp++ = hex[(*inp >> 4) & 0xf]; + *bufp++ = hex[*inp & 0xf]; + } + inp++; + } + *bufp = '\0'; + + return buf; +} diff --git a/utils/http.h b/utils/http.h index a345098..a2f93de 100644 --- a/utils/http.h +++ b/utils/http.h @@ -46,4 +46,6 @@ int http_post_file(mfhttp * conn, const char *url, FILE * fh, int (*data_handler) (mfhttp * conn, void *data), void *data); +char *urlencode(const char *input); + #endif