diff --git a/CMakeLists.txt b/CMakeLists.txt index d939bc1..90f1da1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ add_library(mfapi SHARED mfapi/file.c mfapi/folder.c mfapi/patch.c + mfapi/apicalls.c mfapi/apicalls/file_get_info.c mfapi/apicalls/user_get_info.c mfapi/apicalls/file_get_links.c diff --git a/mfapi/apicalls.c b/mfapi/apicalls.c new file mode 100644 index 0000000..c16232d --- /dev/null +++ b/mfapi/apicalls.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2014 Johannes Schauer + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2, as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include + +#include "../utils/http.h" +#include "../utils/json.h" + +int mfapi_check_response(json_t * response, const char *apicall) +{ + json_t *j_obj; + int error_code; + + j_obj = json_object_get(response, "result"); + if (j_obj == NULL || strcmp(json_string_value(j_obj), "Success") != 0) { + // an error occurred + j_obj = json_object_get(response, "message"); + if (j_obj == NULL) { + fprintf(stderr, "no error message\n"); + } else { + fprintf(stderr, "error message: %s\n", json_string_value(j_obj)); + } + j_obj = json_object_get(response, "error"); + if (j_obj == NULL) { + fprintf(stderr, "unknown error code\n"); + error_code = -1; + } else { + fprintf(stderr, "error code: %s\n", json_string_value(j_obj)); + error_code = atol(json_string_value(j_obj)); + if (error_code == 0) + error_code = -1; + } + return error_code; + } + + j_obj = json_object_get(response, "action"); + if (j_obj == NULL) { + fprintf(stderr, "no value for action\n"); + return -1; + } + + if (strcmp(json_string_value(j_obj), apicall) != 0) { + fprintf(stderr, "expected action %s but got %s", apicall, + json_string_value(j_obj)); + return -1; + } + + return 0; +} + +int mfapi_decode_common(mfhttp * conn, void *user_ptr) +{ + json_t *root; + json_t *node; + json_error_t error; + int retval; + char *apicall; + + if (user_ptr == NULL) { + fprintf(stderr, "user_ptr must not be null\n"); + return -1; + } + + apicall = (char *)user_ptr; + + root = http_parse_buf_json(conn, 0, &error); + + if (root == NULL) { + fprintf(stderr, "http_parse_buf_json failed at line %d\n", error.line); + fprintf(stderr, "error message: %s\n", error.text); + return -1; + } + + node = json_object_by_path(root, "response"); + + retval = mfapi_check_response(node, apicall); + if (retval != 0) { + fprintf(stderr, "invalid response\n"); + json_decref(root); + return retval; + } + + json_decref(root); + + return 0; +} diff --git a/mfapi/apicalls.h b/mfapi/apicalls.h index 383c6bd..8aa7bf9 100644 --- a/mfapi/apicalls.h +++ b/mfapi/apicalls.h @@ -20,6 +20,7 @@ #ifndef _MFAPI_APICALLS_H_ #define _MFAPI_APICALLS_H_ +#include #include #include @@ -27,6 +28,7 @@ #include "folder.h" #include "patch.h" #include "mfconn.h" +#include "../utils/http.h" #define MFAPI_MAX_LEN_KEY 15 #define MFAPI_MAX_LEN_NAME 255 @@ -46,6 +48,10 @@ struct mfconn_device_change { char parent[16]; }; +int mfapi_check_response(json_t * response, const char *apicall); + +int mfapi_decode_common(mfhttp * conn, void *user_ptr); + int mfconn_api_file_get_info(mfconn * conn, mffile * file, const char *quickkey); diff --git a/mfapi/apicalls/device_get_changes.c b/mfapi/apicalls/device_get_changes.c index 45f1e1d..baa2d12 100644 --- a/mfapi/apicalls/device_get_changes.c +++ b/mfapi/apicalls/device_get_changes.c @@ -103,6 +103,7 @@ static int _decode_device_get_changes(mfhttp * conn, void *user_ptr) json_t *parent; json_t *revision; json_t *device_revision; + int retval; int array_sz; int i = 0; @@ -116,12 +117,26 @@ static int _decode_device_get_changes(mfhttp * conn, void *user_ptr) root = http_parse_buf_json(conn, 0, &error); + if (root == NULL) { + fprintf(stderr, "http_parse_buf_json failed at line %d\n", error.line); + fprintf(stderr, "error message: %s\n", error.text); + return -1; + } + node = json_object_by_path(root, "response"); + retval = mfapi_check_response(node, "device/get_changes"); + if (retval != 0) { + fprintf(stderr, "invalid response\n"); + json_decref(root); + return retval; + } + device_revision = json_object_get(node, "device_revision"); if (device_revision == NULL) { fprintf(stderr, "response/device_revision is not part of the result\n"); + json_decref(root); return -1; } @@ -204,8 +219,7 @@ static int _decode_device_get_changes(mfhttp * conn, void *user_ptr) (*changes)[len_changes - 1].revision = atoll(json_string_value(device_revision)); - if (root != NULL) - json_decref(root); + json_decref(root); return 0; } diff --git a/mfapi/apicalls/device_get_patch.c b/mfapi/apicalls/device_get_patch.c index 2c15a19..71c9c6f 100644 --- a/mfapi/apicalls/device_get_patch.c +++ b/mfapi/apicalls/device_get_patch.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "../../utils/http.h" #include "../../utils/json.h" @@ -77,6 +78,7 @@ static int _decode_device_get_patch(mfhttp * conn, void *data) mfpatch *patch; json_t *root; json_t *node; + int retval; if (data == NULL) return -1; @@ -85,8 +87,21 @@ static int _decode_device_get_patch(mfhttp * conn, void *data) root = http_parse_buf_json(conn, 0, &error); + if (root == NULL) { + fprintf(stderr, "http_parse_buf_json failed at line %d\n", error.line); + fprintf(stderr, "error message: %s\n", error.text); + return -1; + } + node = json_object_by_path(root, "response"); + retval = mfapi_check_response(node, "device/get_patch"); + if (retval != 0) { + fprintf(stderr, "invalid response\n"); + json_decref(root); + return retval; + } + obj = json_object_get(node, "patch_hash"); if (obj != NULL) patch_set_hash(patch, json_string_value(obj)); @@ -95,8 +110,7 @@ static int _decode_device_get_patch(mfhttp * conn, void *data) if (obj != NULL) patch_set_link(patch, json_string_value(obj)); - if (root != NULL) - json_decref(root); + json_decref(root); return 0; } diff --git a/mfapi/apicalls/device_get_status.c b/mfapi/apicalls/device_get_status.c index f2d13dd..3c9896c 100644 --- a/mfapi/apicalls/device_get_status.c +++ b/mfapi/apicalls/device_get_status.c @@ -61,6 +61,7 @@ static int _decode_device_get_status(mfhttp * conn, void *data) json_t *node; json_t *device_revision; uint64_t *revision; + int retval; revision = (uint64_t *) data; if (data == NULL) @@ -68,8 +69,21 @@ static int _decode_device_get_status(mfhttp * conn, void *data) root = http_parse_buf_json(conn, 0, &error); + if (root == NULL) { + fprintf(stderr, "http_parse_buf_json failed at line %d\n", error.line); + fprintf(stderr, "error message: %s\n", error.text); + return -1; + } + node = json_object_by_path(root, "response"); + retval = mfapi_check_response(node, "device/get_status"); + if (retval != 0) { + fprintf(stderr, "invalid response\n"); + json_decref(root); + return retval; + } + device_revision = json_object_get(node, "device_revision"); if (device_revision != NULL) { fprintf(stderr, "device_revision: %s\n", @@ -77,8 +91,7 @@ static int _decode_device_get_status(mfhttp * conn, void *data) *revision = atoll(json_string_value(device_revision)); } - if (root != NULL) - json_decref(root); + json_decref(root); return 0; } diff --git a/mfapi/apicalls/device_get_updates.c b/mfapi/apicalls/device_get_updates.c index 90f17a8..548deff 100644 --- a/mfapi/apicalls/device_get_updates.c +++ b/mfapi/apicalls/device_get_updates.c @@ -95,6 +95,7 @@ static int _decode_device_get_updates(mfhttp * conn, void *user_ptr) int array_sz; int i; + int retval; mfpatch ***patches; mfpatch *tmp_patch; @@ -107,8 +108,21 @@ static int _decode_device_get_updates(mfhttp * conn, void *user_ptr) root = http_parse_buf_json(conn, 0, &error); + if (root == NULL) { + fprintf(stderr, "http_parse_buf_json failed at line %d\n", error.line); + fprintf(stderr, "error message: %s\n", error.text); + return -1; + } + node = json_object_by_path(root, "response"); + retval = mfapi_check_response(node, "device/get_updates"); + if (retval != 0) { + fprintf(stderr, "invalid response\n"); + json_decref(root); + return retval; + } + len_patches = 0; obj_array = json_object_get(node, "updates"); if (json_is_array(obj_array)) { @@ -149,8 +163,7 @@ static int _decode_device_get_updates(mfhttp * conn, void *user_ptr) // write an empty last element (*patches)[len_patches - 1] = NULL; - if (root != NULL) - json_decref(root); + json_decref(root); return 0; } diff --git a/mfapi/apicalls/file_delete.c b/mfapi/apicalls/file_delete.c index 091b497..dcca305 100644 --- a/mfapi/apicalls/file_delete.c +++ b/mfapi/apicalls/file_delete.c @@ -45,7 +45,7 @@ int mfconn_api_file_delete(mfconn * conn, const char *quickkey) quickkey); http = http_create(); - retval = http_get_buf(http, api_call, NULL, NULL); + retval = http_get_buf(http, api_call, mfapi_decode_common, "file/delete"); http_destroy(http); free((void *)api_call); diff --git a/mfapi/apicalls/file_get_info.c b/mfapi/apicalls/file_get_info.c index a48f0aa..742f391 100644 --- a/mfapi/apicalls/file_get_info.c +++ b/mfapi/apicalls/file_get_info.c @@ -86,8 +86,21 @@ static int _decode_file_get_info(mfhttp * conn, void *data) root = http_parse_buf_json(conn, 0, &error); + if (root == NULL) { + fprintf(stderr, "http_parse_buf_json failed at line %d\n", error.line); + fprintf(stderr, "error message: %s\n", error.text); + return -1; + } + node = json_object_by_path(root, "response/file_info"); + retval = mfapi_check_response(node, "file/get_info"); + if (retval != 0) { + fprintf(stderr, "invalid response\n"); + json_decref(root); + return retval; + } + quickkey = json_object_get(node, "quickkey"); if (quickkey != NULL) file_set_key(file, json_string_value(quickkey)); @@ -133,8 +146,7 @@ static int _decode_file_get_info(mfhttp * conn, void *data) if (quickkey == NULL) retval = -1; - if (root != NULL) - json_decref(root); + json_decref(root); return retval; } diff --git a/mfapi/apicalls/file_get_links.c b/mfapi/apicalls/file_get_links.c index 196e877..3bf8547 100644 --- a/mfapi/apicalls/file_get_links.c +++ b/mfapi/apicalls/file_get_links.c @@ -85,8 +85,21 @@ static int _decode_file_get_links(mfhttp * conn, void *data) root = http_parse_buf_json(conn, 0, &error); + if (root == NULL) { + fprintf(stderr, "http_parse_buf_json failed at line %d\n", error.line); + fprintf(stderr, "error message: %s\n", error.text); + return -1; + } + node = json_object_by_path(root, "response"); + retval = mfapi_check_response(node, "file/get_links"); + if (retval != 0) { + fprintf(stderr, "invalid response\n"); + json_decref(root); + return retval; + } + links_array = json_object_get(node, "links"); if (!json_is_array(links_array)) { json_decref(root); @@ -116,8 +129,7 @@ static int _decode_file_get_links(mfhttp * conn, void *data) if (share_link == NULL) retval = -1; - if (root != NULL) - json_decref(root); + json_decref(root); return retval; } diff --git a/mfapi/apicalls/folder_create.c b/mfapi/apicalls/folder_create.c index 7609510..743ca69 100644 --- a/mfapi/apicalls/folder_create.c +++ b/mfapi/apicalls/folder_create.c @@ -58,7 +58,8 @@ int mfconn_api_folder_create(mfconn * conn, const char *parent, } http = http_create(); - retval = http_get_buf(http, api_call, NULL, NULL); + retval = http_get_buf(http, api_call, mfapi_decode_common, + "folder/create"); http_destroy(http); free((void *)api_call); diff --git a/mfapi/apicalls/folder_delete.c b/mfapi/apicalls/folder_delete.c index 4a29eb4..83cddcf 100644 --- a/mfapi/apicalls/folder_delete.c +++ b/mfapi/apicalls/folder_delete.c @@ -45,7 +45,8 @@ int mfconn_api_folder_delete(mfconn * conn, const char *folderkey) folderkey); http = http_create(); - retval = http_get_buf(http, api_call, NULL, NULL); + retval = http_get_buf(http, api_call, mfapi_decode_common, + "folder/delete"); http_destroy(http); free((void *)api_call); diff --git a/mfapi/apicalls/folder_get_content.c b/mfapi/apicalls/folder_get_content.c index 8e7d54e..888ff94 100644 --- a/mfapi/apicalls/folder_get_content.c +++ b/mfapi/apicalls/folder_get_content.c @@ -109,6 +109,7 @@ static int _decode_folder_get_content_folders(mfhttp * conn, void *user_ptr) char *ret; struct tm tm; + int retval; int array_sz; int i = 0; @@ -123,6 +124,21 @@ static int _decode_folder_get_content_folders(mfhttp * conn, void *user_ptr) root = http_parse_buf_json(conn, 0, &error); + if (root == NULL) { + fprintf(stderr, "http_parse_buf_json failed at line %d\n", error.line); + fprintf(stderr, "error message: %s\n", error.text); + return -1; + } + + node = json_object_by_path(root, "response"); + + retval = mfapi_check_response(node, "folder/get_content"); + if (retval != 0) { + fprintf(stderr, "invalid response\n"); + json_decref(root); + return retval; + } + /*json_t *result = json_object_by_path(root, "response/action"); fprintf(stderr, "response/action: %s\n", (char*)json_string_value(result)); */ @@ -206,6 +222,7 @@ static int _decode_folder_get_content_files(mfhttp * conn, void *user_ptr) json_t *quickkey; json_t *file_name; json_t *j_obj; + int retval; char *ret; struct tm tm; @@ -223,6 +240,21 @@ static int _decode_folder_get_content_files(mfhttp * conn, void *user_ptr) root = http_parse_buf_json(conn, 0, &error); + if (root == NULL) { + fprintf(stderr, "http_parse_buf_json failed at line %d\n", error.line); + fprintf(stderr, "error message: %s\n", error.text); + return -1; + } + + node = json_object_by_path(root, "response"); + + retval = mfapi_check_response(node, "folder/get_content"); + if (retval != 0) { + fprintf(stderr, "invalid response\n"); + json_decref(root); + return retval; + } + node = json_object_by_path(root, "response/folder_content"); files_array = json_object_get(node, "files"); @@ -290,8 +322,7 @@ static int _decode_folder_get_content_files(mfhttp * conn, void *user_ptr) // write an empty last element (*mffile_result)[len_mffile_result - 1] = NULL; - if (root != NULL) - json_decref(root); + json_decref(root); return 0; } diff --git a/mfapi/apicalls/folder_get_info.c b/mfapi/apicalls/folder_get_info.c index 73c22ee..453e18f 100644 --- a/mfapi/apicalls/folder_get_info.c +++ b/mfapi/apicalls/folder_get_info.c @@ -92,6 +92,21 @@ static int _decode_folder_get_info(mfhttp * conn, void *data) root = http_parse_buf_json(conn, 0, &error); + if (root == NULL) { + fprintf(stderr, "http_parse_buf_json failed at line %d\n", error.line); + fprintf(stderr, "error message: %s\n", error.text); + return -1; + } + + node = json_object_by_path(root, "response"); + + retval = mfapi_check_response(node, "folder/get_info"); + if (retval != 0) { + fprintf(stderr, "invalid response\n"); + json_decref(root); + return retval; + } + node = json_object_by_path(root, "response/folder_info"); folderkey = json_object_get(node, "folderkey"); @@ -129,8 +144,7 @@ static int _decode_folder_get_info(mfhttp * conn, void *data) if (folderkey == NULL) retval = -1; - if (root != NULL) - json_decref(root); + json_decref(root); return retval; } diff --git a/mfapi/apicalls/upload_poll_upload.c b/mfapi/apicalls/upload_poll_upload.c index c624724..78ac10f 100644 --- a/mfapi/apicalls/upload_poll_upload.c +++ b/mfapi/apicalls/upload_poll_upload.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "../../utils/http.h" #include "../../utils/json.h" @@ -74,6 +75,7 @@ static int _decode_upload_poll_upload(mfhttp * conn, void *user_ptr) json_t *root; json_t *node; json_t *j_obj; + int retval; struct upload_poll_upload_response *response; @@ -86,6 +88,21 @@ static int _decode_upload_poll_upload(mfhttp * conn, void *user_ptr) root = http_parse_buf_json(conn, 0, &error); + if (root == NULL) { + fprintf(stderr, "http_parse_buf_json failed at line %d\n", error.line); + fprintf(stderr, "error message: %s\n", error.text); + return -1; + } + + node = json_object_by_path(root, "response"); + + retval = mfapi_check_response(node, "upload/poll_upload"); + if (retval != 0) { + fprintf(stderr, "invalid response\n"); + json_decref(root); + return retval; + } + node = json_object_by_path(root, "response/doupload"); // make sure that the result code is zero (success) @@ -105,8 +122,7 @@ static int _decode_upload_poll_upload(mfhttp * conn, void *user_ptr) response->fileerror = atol(json_string_value(j_obj)); } - if (root != NULL) - json_decref(root); + json_decref(root); return 0; } diff --git a/mfapi/apicalls/upload_simple.c b/mfapi/apicalls/upload_simple.c index f990aaa..969e66a 100644 --- a/mfapi/apicalls/upload_simple.c +++ b/mfapi/apicalls/upload_simple.c @@ -97,6 +97,7 @@ static int _decode_upload_simple(mfhttp * conn, void *user_ptr) json_t *root; json_t *node; json_t *j_obj; + int retval; char **upload_key; @@ -106,6 +107,21 @@ static int _decode_upload_simple(mfhttp * conn, void *user_ptr) root = http_parse_buf_json(conn, 0, &error); + if (root == NULL) { + fprintf(stderr, "http_parse_buf_json failed at line %d\n", error.line); + fprintf(stderr, "error message: %s\n", error.text); + return -1; + } + + node = json_object_by_path(root, "response"); + + retval = mfapi_check_response(node, "upload/simple"); + if (retval != 0) { + fprintf(stderr, "invalid response\n"); + json_decref(root); + return retval; + } + node = json_object_by_path(root, "response/doupload"); j_obj = json_object_get(node, "key"); @@ -119,8 +135,7 @@ static int _decode_upload_simple(mfhttp * conn, void *user_ptr) *upload_key = NULL; } - if (root != NULL) - json_decref(root); + json_decref(root); return 0; } diff --git a/mfapi/apicalls/user_get_info.c b/mfapi/apicalls/user_get_info.c index 4925135..5d398f2 100644 --- a/mfapi/apicalls/user_get_info.c +++ b/mfapi/apicalls/user_get_info.c @@ -59,12 +59,28 @@ static int _decode_user_get_info(mfhttp * conn, void *data) json_t *email; json_t *first_name; json_t *last_name; + int retval; if (data != NULL) return -1; root = http_parse_buf_json(conn, 0, &error); + if (root == NULL) { + fprintf(stderr, "http_parse_buf_json failed at line %d\n", error.line); + fprintf(stderr, "error message: %s\n", error.text); + return -1; + } + + node = json_object_by_path(root, "response"); + + retval = mfapi_check_response(node, "user/get_info"); + if (retval != 0) { + fprintf(stderr, "invalid response\n"); + json_decref(root); + return retval; + } + node = json_object_by_path(root, "response/user_info"); email = json_object_get(node, "email"); @@ -81,8 +97,7 @@ static int _decode_user_get_info(mfhttp * conn, void *data) printf("\n\r"); - if (root != NULL) - json_decref(root); + json_decref(root); return 0; } diff --git a/mfapi/apicalls/user_session.c b/mfapi/apicalls/user_session.c index 46a5f7e..fb2a79d 100644 --- a/mfapi/apicalls/user_session.c +++ b/mfapi/apicalls/user_session.c @@ -96,11 +96,12 @@ static int _decode_get_session_token(mfhttp * conn, void *user_ptr) { json_error_t error; json_t *root = NULL; - json_t *data; + json_t *node; json_t *session_token; json_t *secret_key; json_t *secret_time; struct user_get_session_token_response *response; + int retval; if (user_ptr == NULL) return -1; @@ -109,13 +110,22 @@ static int _decode_get_session_token(mfhttp * conn, void *user_ptr) root = http_parse_buf_json(conn, 0, &error); - data = json_object_by_path(root, "response"); - if (data == NULL) { - fprintf(stderr, "json: no /response content\n"); + if (root == NULL) { + fprintf(stderr, "http_parse_buf_json failed at line %d\n", error.line); + fprintf(stderr, "error message: %s\n", error.text); return -1; } - session_token = json_object_get(data, "session_token"); + node = json_object_by_path(root, "response"); + + retval = mfapi_check_response(node, "user/get_session_token"); + if (retval != 0) { + fprintf(stderr, "invalid response\n"); + json_decref(root); + return retval; + } + + session_token = json_object_get(node, "session_token"); if (session_token == NULL) { json_decref(root); fprintf(stderr, "json: no /session_token content\n"); @@ -124,7 +134,7 @@ static int _decode_get_session_token(mfhttp * conn, void *user_ptr) response->session_token = strdup(json_string_value(session_token)); - secret_key = json_object_get(data, "secret_key"); + secret_key = json_object_get(node, "secret_key"); if (secret_key != NULL) response->secret_key = atoll(json_string_value(secret_key)); @@ -132,7 +142,7 @@ static int _decode_get_session_token(mfhttp * conn, void *user_ptr) time looks like a float but we must store it as a string to remain congruent with the server on decimal place presentation. */ - secret_time = json_object_get(data, "time"); + secret_time = json_object_get(node, "time"); if (secret_time != NULL) response->secret_time = strdup(json_string_value(secret_time));