/* * File: DropBoxProvider.cc * Author: jgaebler * * Created on April 26, 2012, 3:27 PM */ #include "DropBoxProvider.h" #include "Dispatcher.h" #include "common/container/PeerIDList.h" #include "common/time/GenericTime.h" #include "mob/sync/cloud/transfer/TransferContainer.h" #include "mob/sync/cloud/transfer/TransferMessage.h" #include "mob/sync/cloud/transfer/TransferSerializer.h" #include "common/util/StringUtil.h" #include "common/container/StringList.h" #if OMNETPP #include "../../opt/json-c-0.10/include/json/json.h" #include #include #endif #include "Moversight.h" #include #include #undef DEBUG #define DEBUG(msg) if (module.isPrintDebugDIS()) MOV_DEBUG << "DBP@" << dispatcher.getMembershipService().getLocalID()<< " "< 0) { //std::cerr<< "upload - file name " << fileName< (&uploadData[0]); char * reply; reply = oauth_post_data(url.c_str(), postData, uploadData.size(), "Content-Type: application/json"); //@TODO check reply for errors and propaged it //std::cout << "reply: " << reply << std::endl; if (reply) free(reply); }//End if #endif } /** * @brief Creates the url for the file upload to dropbox * @param id The id of the peer which has created the first folder in the dropbox. * @param fileName The name of the file to store * @return The build url. */ std::string DropBoxProvider::buildUploadUrl(PeerID id, std::string fileName) { std::string s_time = StringUtil::int2String(std::time(NULL)); std::string folder = StringUtil::int2String(id); #if OMNETPP char * nonce = oauth_gen_nonce(); // Building Upload url std::string url = "https://api-content.dropbox.com/1/files_put/sandbox/" + folder; url += "/" + fileName + "." + FILE_TYPE; std::string a(url); a += "?oauth_nonce=" + std::string(nonce) + "?overwrite=false"; a += "&oauth_timestamp=" + s_time + "&oauth_consumer_key=" + APP_KEY; a += "&oauth_signature_method=PLAINTEXT&oauth_version=1.0&oauth_token=" + OAUTH_TOKEN; a += "&oauth_signature=" + APP_SECRET + "%26" + OAUTH_TOKEN_SECRET; // + "&overwrite=False"; if (nonce) free(nonce); //char* signedUrl = oauth_sign_url2(url.c_str(), //request url // NULL, //post arguments // OA_HMAC, //oauth method OA_HMAC // NULL, //http method (GET or POST), if NULL - auto detection // APP_KEY.c_str(), //c_key // APP_SECRET.c_str(), //c_secret // OAUTH_TOKEN.c_str(), // t_key // OAUTH_TOKEN_SECRET.c_str()); //t_secret //std::cout << "UPLOAD URL: " << url << std::endl; //std::cout << "SIGNED URL: " << signedUrl << std::endl; //std::cout << "EXPECTED URL: "<< a < 0) { ByteArray loadedFile(ms.memory, ms.memory + ms.size); TransferContainer tc; tc.setPeerID(id); if (TransferSerializer::deserialize(loadedFile, tc)) { tcl.add(tc); }//End if else { DEBUG("downloadMessagesFromPeer - error: de-serialize retrieved data failed."); }//End else //clean up free(ms.memory); }//End if else { DEBUG("downloadMessagesFromPeer - error: download failed."); }//End else }//End for }//End if metaReply #endif return tcl; } /** * @brief Determine the peers, which have stored messages in the cloud. * @return The list of peers that have stored messages in the cloud. */ PeerIDList DropBoxProvider::determineStoringPeers() { // the dropbox api response with an json array // the array is parsed with the json parser // create the url for the metadata download std::string mdurl = buildMetaDataUrl(); PeerIDList idList; #if OMNETPP char * reply = oauth_http_get(mdurl.c_str(), NULL); if (reply != NULL) { //list of peers which have stored messages in the cloud, filled by the json parser StringList peerList; std::string pathKey("path"); json_object * jobj = json_tokener_parse(reply); //false jsonParse(jobj, true, peerList, pathKey.c_str()); //have a peer messages stored in the cloud? for (size_t i = 0; i < peerList.size(); i++) { //we have at least one peer, which have stored messages in the cloud //load the string of the peer ID std::string client = peerList.get(i); if (client != "") { //convert the ID and store it in the list idList.add(PeerID(atoi(client.c_str()))); }//End if }//end while free(jobj); free(reply); }//End if #endif return idList; } /* * @brief The json array parser * @note See joysofprogramming.com/json-c-libjson-tutorial/ for the * source of the original code */ void DropBoxProvider::jsonParseArray(json_object *jobj, char *key, bool parse, StringList & list, const char * param /* = "path" */) { #if OMNETPP enum json_type type; //Simply get the array json_object *jarray = jobj; if (key) { //Getting the array if it is a key value pair jarray = json_object_object_get(jobj, key); } //Getting the length of the array int arraylen = json_object_array_length(jarray); int i; json_object * jvalue; for (i = 0; i < arraylen; i++) { //Getting the array element at position i jvalue = json_object_array_get_idx(jarray, i); type = json_object_get_type(jvalue); if (type == json_type_array) { jsonParseArray(jvalue, NULL, false, list, param); } else { jsonParse(jvalue, parse, list, param); } } #endif } /* * @brief The json object parser * @note base on joysofprogramming.com/json-c-libjson-tutorial/ * * @param jobj The object to parse * @param parse Enable parsing * @param param The parameter to parse * @param list The list of the resulting tokens, with match to the key * "path" within the JSON response */ void DropBoxProvider::jsonParse(json_object * jobj, bool /* parse */, StringList & list, const char * param /* = "path" */) { #if OMNETPP enum json_type type; //Passing through every array element json_object_object_foreach(jobj, key, val) { type = json_object_get_type(val); switch (type) { case json_type_string: if (strcmp(key, param) == 0) { std::string client = json_object_get_string(val); list.add(client.substr(1)); } break; case json_type_array: if (strcmp(key, "contents") == 0) { jsonParseArray(jobj, key, true, list, param); } break; case json_type_int: if (strcmp(key, param) == 0) { int intVal = json_object_get_int(val); list.add(StringUtil::int2String(intVal)); } default: { //‘json_type_boolean’ //‘json_type_double’ //‘json_type_object’ } } } #endif } /* * @brief Creates the url for requesting the meta data for the path "path" * @return The build url. */ std::string DropBoxProvider::buildMetaDataUrl() { return buildMetaDataUrl(UNDEFINED_PEER_ID); } /* * @brief Creates the url for requesting the meta data for the given peer * ID. If the id equals to UNDEFINED_PEER_ID, the path is set to empty; * @param id The id of the uploading peer. * @return The build url. */ std::string DropBoxProvider::buildMetaDataUrl(PeerID id) { std::string path; if (id != UNDEFINED_PEER_ID) { path = path + StringUtil::int2String(id) + "/"; } return buildMetaDataUrl(path); } /* * @brief Creates the url for requesting the meta data for the path. * @param path The path to set * @return The build url. */ std::string DropBoxProvider::buildMetaDataUrl(std::string path) { #if OMNETPP char * nonce = oauth_gen_nonce(); std::string url = "https://api.dropbox.com/1/metadata/sandbox/" + path + "?oauth_nonce=" + std::string(nonce) + "&oauth_timestamp=" + StringUtil::int2String(std::time(NULL)) + "&file_limit=10000&list=true" + "&oauth_consumer_key=" + APP_KEY + "&oauth_signature_method=PLAINTEXT&include_deleted=False&oauth_version=1.0&" + "&oauth_token=" + OAUTH_TOKEN + "&oauth_signature=" + APP_SECRET + "%26" + OAUTH_TOKEN_SECRET; free(nonce); return url; #else return "https://no.url.com"; #endif } /** * @brief Creates the url for the file download from the dropbox. * @param path The path to the file to download. * @return The build url. */ std::string DropBoxProvider::buildDownloadUrl(std::string path) { int random = (rand() % 99999999 + 1) + 10000000; std::string url = "https://api-content.dropbox.com/1/files/sandbox/" + path + "?oauth_nonce=" + StringUtil::int2String(random) + "&oauth_timestamp=" + StringUtil::int2String(std::time(NULL)) + "&oauth_consumer_key=" + APP_KEY + "&oauth_signature_method=PLAINTEXT&oauth_version=1.0&" + "&oauth_token=" + OAUTH_TOKEN + "&oauth_signature=" + APP_SECRET + "%26" + OAUTH_TOKEN_SECRET; return url; } /** * @brief Retrieves a curl fetch operation and returns a chunk of memory, * which stores the retrieved file. * @param url The url of the message to fetch * @return The memory struct, which stores the retrieved file content. * @note The memory of the MemoryStruct chunk have to be cleaned by the caller * @see http://curl.haxx.se/libcurl/c/getinmemory.html */ struct MemoryStruct DropBoxProvider::performCurlDownload(std::string url) { //init the memory area to store the meta data MemoryStruct chunk; chunk.memory = (char*) malloc(1); chunk.size = 0; #if OMNETPP //build the curl request for the metadata upload //and perform the request CURL* curl_handle; curl_global_init(CURL_GLOBAL_ALL); curl_handle = curl_easy_init(); curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writeMemoryCallback); curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &chunk); curl_easy_perform(curl_handle); curl_easy_cleanup(curl_handle); curl_global_cleanup(); #endif return chunk; } /** * @brief Callback for the curl library downloads * @param contents The content to store * @param size the size of the fetched content * @param nmemb the size of the allocated memory * @param userp the destination to store * @return the value of the allocated memory * @see http://curl.haxx.se/libcurl/c/getinmemory.html */ size_t DropBoxProvider::writeMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) { size_t realsize = size * nmemb; MemoryStruct *mem = (MemoryStruct *) userp; mem->memory = (char*) realloc(mem->memory, mem->size + realsize + 1); if (mem->memory == NULL) { // out of memory! std::cerr << "not enough memory (realloc returned NULL)" << std::endl; exit(EXIT_FAILURE); } memcpy(&(mem->memory[mem->size]), contents, realsize); mem->size += realsize; mem->memory[mem->size] = 0; return realsize; } } }