From d0e1305ac88996a4394793dff73b69cb92505da4 Mon Sep 17 00:00:00 2001 From: Jean-Marie Verdun Date: Tue, 15 Oct 2019 23:03:20 +0200 Subject: [PATCH] Add Content-MD% into the header as to be able to retrieve it from the ETag answer of the server --- src/Mod/Cloud/App/AppCloud.cpp | 50 +++++++++++++++++++++++++++++----- src/Mod/Cloud/App/AppCloud.h | 4 ++- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/Mod/Cloud/App/AppCloud.cpp b/src/Mod/Cloud/App/AppCloud.cpp index b6f8c596e0..48cd7f06d9 100644 --- a/src/Mod/Cloud/App/AppCloud.cpp +++ b/src/Mod/Cloud/App/AppCloud.cpp @@ -28,6 +28,8 @@ #include #include +#include + #include #include @@ -201,7 +203,7 @@ void Cloud::CloudWriter::createBucket() char path[1024]; sprintf(path, "/%s/", this->Bucket); - RequestData = Cloud::ComputeDigestAmzS3v2("PUT", "application/xml", path, this->SecretKey); + RequestData = Cloud::ComputeDigestAmzS3v2("PUT", "application/xml", path, this->SecretKey, NULL, 0); // Let's build the Header and call to curl curl_global_init(CURL_GLOBAL_ALL); @@ -245,7 +247,7 @@ void Cloud::CloudWriter::createBucket() } } -struct Cloud::AmzData *Cloud::ComputeDigestAmzS3v2(char *operation, char *data_type, const char *target, const char *Secret) +struct Cloud::AmzData *Cloud::ComputeDigestAmzS3v2(char *operation, char *data_type, const char *target, const char *Secret, const char *ptr, long size) { struct AmzData *returnData; struct timeval tv; @@ -275,7 +277,19 @@ struct Cloud::AmzData *Cloud::ComputeDigestAmzS3v2(char *operation, char *data_t tm = localtime(&tv.tv_sec); strftime(date_formatted,256,"%a, %d %b %Y %T %z", tm); #endif - sprintf(StringToSign,"%s\n\n%s\n%s\n%s", operation, data_type, date_formatted, target); + returnData->MD5=NULL; + if ( strcmp(operation,"PUT") == 0 ) + { + if ( ptr != NULL ) + { + returnData->MD5=Cloud::MD5Sum(ptr,size); + sprintf(StringToSign,"%s\n%s\n%s\n%s\n%s", operation, returnData->MD5, data_type, date_formatted, target); + } + else + sprintf(StringToSign,"%s\n\n%s\n%s\n%s", operation, data_type, date_formatted, target); + } + else + sprintf(StringToSign,"%s\n\n%s\n%s\n%s", operation, data_type, date_formatted, target); // We have to use HMAC encoding and SHA1 digest=HMAC(EVP_sha1(),Secret,strlen(Secret), (const unsigned char *)&StringToSign,strlen(StringToSign),NULL,NULL); @@ -285,6 +299,18 @@ struct Cloud::AmzData *Cloud::ComputeDigestAmzS3v2(char *operation, char *data_t } +char *Cloud::MD5Sum(const char *ptr, long size) +{ + char *output; + std::string local; + unsigned char result[MD5_DIGEST_LENGTH]; + output=(char *)malloc(2*MD5_DIGEST_LENGTH*sizeof(char)+1); + MD5((unsigned char*) ptr, size, result); + local= Base::base64_encode(result,MD5_DIGEST_LENGTH); + strcpy(output,local.c_str()); + return(output); +} + struct curl_slist *Cloud::BuildHeaderAmzS3v2(const char *Url, const char *TcpPort, const char *PublicKey, struct Cloud::AmzData *Data) { char header_data[1024]; @@ -305,6 +331,16 @@ struct curl_slist *Cloud::BuildHeaderAmzS3v2(const char *Url, const char *TcpPor sprintf(header_data,"Content-Type:%s", Data->ContentType); chunk = curl_slist_append(chunk, header_data); + // If ptr is not null we must compute the MD5-Sum as to validate later the ETag + // and add the MD5-Content: entry to the header + if ( Data->MD5 != NULL ) + { + sprintf(header_data,"Content-MD5: %s", Data->MD5); + chunk = curl_slist_append(chunk, header_data); + // We don't need it anymore we can free it + free((void *)Data->MD5); + } + // build the Auth entry sprintf(header_data,"Authorization: AWS %s:%s", PublicKey, @@ -330,7 +366,7 @@ Cloud::CloudWriter::CloudWriter(const char* Url, const char* AccessKey, const ch this->FileName=""; char path[1024]; sprintf(path,"/%s/", this->Bucket); - RequestData = Cloud::ComputeDigestAmzS3v2("GET", "application/xml", path, this->SecretKey); + RequestData = Cloud::ComputeDigestAmzS3v2("GET", "application/xml", path, this->SecretKey, NULL, 0); // Let's build the Header and call to curl curl_global_init(CURL_GLOBAL_ALL); curl = curl_easy_init(); @@ -491,7 +527,7 @@ Cloud::CloudReader::CloudReader(const char* Url, const char* AccessKey, const ch char path[1024]; sprintf(path,"/%s/", this->Bucket); - RequestData = Cloud::ComputeDigestAmzS3v2("GET", "application/xml", path, this->SecretKey); + RequestData = Cloud::ComputeDigestAmzS3v2("GET", "application/xml", path, this->SecretKey, NULL, 0); // Let's build the Header and call to curl @@ -561,7 +597,7 @@ void Cloud::CloudReader::DownloadFile(Cloud::CloudReader::FileEntry *entry) // We must get the directory content char path[1024]; sprintf(path, "/%s/%s", this->Bucket, entry->FileName); - RequestData = Cloud::ComputeDigestAmzS3v2("GET", "application/octet-stream", path, this->SecretKey); + RequestData = Cloud::ComputeDigestAmzS3v2("GET", "application/octet-stream", path, this->SecretKey, NULL, 0); // Let's build the Header and call to curl curl_global_init(CURL_GLOBAL_ALL); @@ -670,7 +706,7 @@ void Cloud::CloudWriter::pushCloud(const char *FileName, const char *data, long char path[1024]; sprintf(path, "/%s/%s", this->Bucket, FileName); - RequestData = Cloud::ComputeDigestAmzS3v2("PUT", "application/octet-stream", path, this->SecretKey); + RequestData = Cloud::ComputeDigestAmzS3v2("PUT", "application/octet-stream", path, this->SecretKey, data, size); // Let's build the Header and call to curl curl_global_init(CURL_GLOBAL_ALL); diff --git a/src/Mod/Cloud/App/AppCloud.h b/src/Mod/Cloud/App/AppCloud.h index 9ba2a55e57..b95dc6c136 100644 --- a/src/Mod/Cloud/App/AppCloud.h +++ b/src/Mod/Cloud/App/AppCloud.h @@ -52,12 +52,14 @@ struct AmzData { char dateFormatted[256]; char ContentType[256]; char Host[256]; + char *MD5; }; void eraseSubStr(std::string & Str, const std::string & toErase); size_t CurlWrite_CallbackFunc_StdString(void *contents, size_t size, size_t nmemb, std::string *s); -struct AmzData *ComputeDigestAmzS3v2(char *operation, char *data_type, const char *target, const char *Secret); +struct AmzData *ComputeDigestAmzS3v2(char *operation, char *data_type, const char *target, const char *Secret, const char *ptr, long size); struct curl_slist *BuildHeaderAmzS3v2(const char *Url, const char *TcpPort, const char *PublicKey, struct AmzData *Data); +char *MD5Sum(const char *ptr, long size); class CloudAppExport CloudReader {