diff --git a/src/Mod/Cloud/App/AppCloud.cpp b/src/Mod/Cloud/App/AppCloud.cpp index d0a417406e..7457ea710c 100644 --- a/src/Mod/Cloud/App/AppCloud.cpp +++ b/src/Mod/Cloud/App/AppCloud.cpp @@ -129,7 +129,7 @@ Py::Object Cloud::Module::sCloudRestore(const Py::Tuple& args) Py::Object Cloud::Module::sCloudProtocolVersion(const Py::Tuple& args) { char *ProtocolVersion; - if (!PyArg_ParseTuple(args.ptr(), "et","utf-8", &TCPPort)) // convert args: Python->C + if (!PyArg_ParseTuple(args.ptr(), "et","utf-8", &ProtocolVersion)) // convert args: Python->C return Py::None(); if (this->ProtocolVersion.getStrValue() != ProtocolVersion) { this->ProtocolVersion.setValue(ProtocolVersion); @@ -137,6 +137,17 @@ Py::Object Cloud::Module::sCloudProtocolVersion(const Py::Tuple& args) return Py::None(); } +Py::Object Cloud::Module::sCloudRegion(const Py::Tuple& args) +{ + char *Region; + if (!PyArg_ParseTuple(args.ptr(), "et","utf-8", &Region)) // convert args: Python->C + return Py::None(); + if (this->Region.getStrValue() != Region) { + this->Region.setValue(Region); + } + return Py::None(); +} + struct data_buffer { const char *ptr; @@ -212,6 +223,7 @@ void Cloud::CloudWriter::checkText(DOMText* text) { void Cloud::CloudWriter::createBucket() { struct Cloud::AmzData *RequestData; + struct Cloud::AmzDatav4 *RequestDatav4; CURL *curl; CURLcode res; @@ -219,7 +231,14 @@ void Cloud::CloudWriter::createBucket() char path[1024]; sprintf(path, "/%s/", this->Bucket); - RequestData = Cloud::ComputeDigestAmzS3v2("PUT", "application/xml", path, this->TokenSecret, NULL, 0); + std::string strURL(this->URL); + eraseSubStr(strURL,"http://"); + eraseSubStr(strURL,"https://"); + + if ( this->ProtocolVersion == "2" ) + RequestData = Cloud::ComputeDigestAmzS3v2("PUT", "application/xml", path, this->TokenSecret, NULL, 0); + else + RequestDatav4 = Cloud::ComputeDigestAmzS3v4("PUT", strURL.c_str(), "application/xml", path, this->TokenSecret, NULL, 0, NULL, this->Region); // Let's build the Header and call to curl curl_global_init(CURL_GLOBAL_ALL); @@ -237,9 +256,16 @@ void Cloud::CloudWriter::createBucket() std::string strURL(this->URL); eraseSubStr(strURL,"http://"); eraseSubStr(strURL,"https://"); - - chunk = Cloud::BuildHeaderAmzS3v2( strURL.c_str(), this->TCPPort, this->TokenAuth, RequestData); - delete RequestData; + if ( this->ProtocolVersion == "2" ) + { + chunk = Cloud::BuildHeaderAmzS3v2( strURL.c_str(), this->TCPPort, this->TokenAuth, RequestData); + delete RequestData; + } + else + { + chunk = Cloud::BuildHeaderAmzS3v4( strURL.c_str(), this->TCPPort, this->TokenAuth, RequestDatav4); + delete RequestDatav4; + } curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk); @@ -286,15 +312,12 @@ void Cloud::CloudWriter::createBucket() //} //#endif -struct Cloud::AmzDatav4 *Cloud::ComputeDigestAmzS3v4(char *operation, const char *server, char *data_type, const char *target, const char *Secret, const char *ptr, long size) +struct Cloud::AmzDatav4 *Cloud::ComputeDigestAmzS3v4(char *operation, const char *server, char *data_type, const char *target, const char *Secret, const char *ptr, long size, char *parameters, std::string Region) { struct AmzDatav4 *returnData; - char StringToSign[1024]; returnData = new Cloud::AmzDatav4; struct tm *tm; - char date_formatted[256]; char *canonical_request; - char *digest; char *canonicalRequestHash; char *stringToSign; @@ -321,27 +344,38 @@ struct Cloud::AmzDatav4 *Cloud::ComputeDigestAmzS3v4(char *operation, const char strcpy(canonical_request,operation); strcat(canonical_request,"\n"); strcat(canonical_request,target); - strcat(canonical_request,"\n\n"); + strcat(canonical_request,"\n"); + if ( parameters == NULL ) + strcat(canonical_request,"\n"); + else + { + strcat(canonical_request,parameters); + strcat(canonical_request,"\n"); + } strcat(canonical_request,"host:"); strcat(canonical_request,server); strcat(canonical_request, "\n"); - strcat(canonical_request, "x-maz-date:"); + strcat(canonical_request, "x-amz-date:"); strcat(canonical_request, returnData->dateFormattedS); strcat(canonical_request, "\n\n"); strcat(canonical_request, "host;x-amz-date\n"); // We must add there the file SHA256 Hash - puts("====================================================="); + returnData->SHA256Sum=NULL; if ( strcmp(operation,"PUT") == 0 ) { if ( ptr != NULL ) { - returnData->SHA256=Cloud::SHA256Sum(ptr,size); - strcat(canonical_request, returnData->SHA256); + returnData->SHA256Sum=Cloud::SHA256Sum(ptr,size); + strcat(canonical_request, returnData->SHA256Sum); } + else + strcat(canonical_request,"UNSIGNED-PAYLOAD"); + } + else + { + strcat(canonical_request,"UNSIGNED-PAYLOAD"); } - puts(canonical_request); canonicalRequestHash = Cloud::SHA256Sum(canonical_request, strlen(canonical_request)); - puts(canonicalRequestHash); // returnData->digest = string(digest); @@ -349,7 +383,7 @@ struct Cloud::AmzDatav4 *Cloud::ComputeDigestAmzS3v4(char *operation, const char // The format is as follow // ${authType} // ${dateValueL} - // ${dateValueS}/${region}/${service}/aws4_request + // ${dateValueS}/${Region}/${service}/aws4_request // ${canonicalRequestHash}" stringToSign = (char *)malloc(4096*sizeof(char)); @@ -365,12 +399,64 @@ struct Cloud::AmzDatav4 *Cloud::ComputeDigestAmzS3v4(char *operation, const char // We must now compute the signature // Everything starts with the secret key and an SHA256 HMAC encryption + char kSecret[256]; + unsigned char *kDate, *kRegion, *kService, *kSigned, *kSigning; + + strcpy(kSecret,"AWS4"); + strcat(kSecret,Secret); + unsigned int HMACLength; + + std::string temporary; + + kDate = HMAC(EVP_sha256(),kSecret,strlen(kSecret), + (const unsigned char *)returnData->dateFormattedD,strlen(returnData->dateFormattedD),NULL,&HMACLength); + + temporary = getHexValue(kDate,HMACLength); + temporary = getHexValue(kDate,HMACLength); + + // We can now compute the remaining parts + kRegion = HMAC(EVP_sha256(),kDate,HMACLength, + (const unsigned char *)Region.c_str(),strlen(Region.c_str()),NULL,&HMACLength); + + temporary = getHexValue(kRegion,HMACLength); + + kService = HMAC(EVP_sha256(),kRegion,HMACLength, + (const unsigned char *)"s3",strlen("s3"),NULL,&HMACLength); + + temporary = getHexValue(kService,HMACLength); + + kSigning = HMAC(EVP_sha256(),kService,HMACLength, + (const unsigned char *)"aws4_request",strlen("aws4_request"),NULL,&HMACLength); + + temporary = getHexValue(kService,HMACLength); + kSigned = HMAC(EVP_sha256(),kSigning,HMACLength, + (const unsigned char *)stringToSign,strlen(stringToSign),NULL,&HMACLength); + + temporary = getHexValue(kSigned,HMACLength); + + returnData->digest=string(temporary); + returnData->Region = Region; free(canonical_request); return(returnData); } +std::string Cloud::getHexValue(unsigned char *input, unsigned int HMACLength) +{ + char *Hex; + unsigned char *ptr = input; + std::string resultReadable; + Hex = (char *)malloc(HMACLength*2*sizeof(char)+1); + for ( unsigned int i = 0 ; i < HMACLength ; i++ ) { + sprintf(Hex,"%02x", *ptr); + ptr++; + Hex[2]='\0'; + resultReadable+= Hex; + } + return resultReadable; +} + struct Cloud::AmzData *Cloud::ComputeDigestAmzS3v2(char *operation, char *data_type, const char *target, const char *Secret, const char *ptr, long size) { struct AmzData *returnData; @@ -405,8 +491,6 @@ struct Cloud::AmzData *Cloud::ComputeDigestAmzS3v2(char *operation, char *data_t if ( ptr != NULL ) { returnData->MD5=Cloud::MD5Sum(ptr,size); - printf("Target: %s\n",target); - printf("SHA256: %s\n", Cloud::SHA256Sum(ptr,size)); sprintf(StringToSign,"%s\n%s\n%s\n%s\n%s", operation, returnData->MD5, data_type, date_formatted, target); } else @@ -433,13 +517,9 @@ char *Cloud::SHA256Sum(const char *ptr, long size) output=(char *)malloc(2*SHA256_DIGEST_LENGTH*sizeof(char)+1); Hex = (char *)malloc(2*sizeof(char)+1); SHA256((unsigned char*) ptr, size, result); - for ( int i = 0 ; i < SHA256_DIGEST_LENGTH ; i++ ) { - // snprintf((char *)(&Hex[0]),2,"%02x", result[i]); - sprintf(Hex,"%02x", result[i]); - Hex[2]='\0'; - resultReadable+= Hex; - } - strcpy(output,resultReadable.c_str()); + + strcpy(output,getHexValue(result, SHA256_DIGEST_LENGTH).c_str()); + return(output); } @@ -457,7 +537,52 @@ char *Cloud::MD5Sum(const char *ptr, long size) struct curl_slist *Cloud::BuildHeaderAmzS3v4(const char *URL, const char *TCPPort, const char *PublicKey, struct Cloud::AmzDatav4 *Data) { - return NULL; + char header_data[1024]; + struct curl_slist *chunk = NULL; + + // Build the Host: entry + // sprintf(header_data,"Host: %s:%s", URL, TCPPort); + sprintf(header_data,"Host: %s", URL); + chunk = curl_slist_append(chunk, header_data); + + // Build the Date entry + + sprintf(header_data,"X-Amz-Date: %s", Data->dateFormattedS); + chunk = curl_slist_append(chunk, header_data); + + // Build the Content-Type entry + + 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); + } + + if ( Data->SHA256Sum != NULL ) + { + sprintf(header_data,"x-amz-content-sha256: %s", Data->SHA256Sum); + chunk = curl_slist_append(chunk, header_data); + // We don't need it anymore we can free it + free((void *)Data->SHA256Sum); + } + else + { + chunk = curl_slist_append(chunk, "x-amz-content-sha256: UNSIGNED-PAYLOAD"); + } + + // build the Auth entry + sprintf(header_data,"Authorization: AWS4-HMAC-SHA256 Credential=%s/%s/%s/%s/aws4_request, SignedHeaders=%s, Signature=%s", PublicKey, Data->dateFormattedD,"us","s3","host;x-amz-date", + Data->digest.c_str()); + chunk = curl_slist_append(chunk, header_data); + + return chunk; } struct curl_slist *Cloud::BuildHeaderAmzS3v2(const char *URL, const char *TCPPort, const char *PublicKey, struct Cloud::AmzData *Data) @@ -499,9 +624,10 @@ struct curl_slist *Cloud::BuildHeaderAmzS3v2(const char *URL, const char *TCPPor return chunk; } -Cloud::CloudWriter::CloudWriter(const char* URL, const char* TokenAuth, const char* TokenSecret, const char* TCPPort, const char* Bucket) +Cloud::CloudWriter::CloudWriter(const char* URL, const char* TokenAuth, const char* TokenSecret, const char* TCPPort, const char* Bucket, std::string ProtocolVersion, std::string Region) { struct Cloud::AmzData *RequestData; + struct Cloud::AmzDatav4 *RequestDatav4; CURL *curl; CURLcode res; @@ -512,10 +638,21 @@ Cloud::CloudWriter::CloudWriter(const char* URL, const char* TokenAuth, const ch this->TokenSecret=TokenSecret; this->TCPPort=TCPPort; this->Bucket=Bucket; + if ( !ProtocolVersion.empty() ) + this->ProtocolVersion=ProtocolVersion; + else + this->ProtocolVersion="2"; + this->Region=Region; this->FileName=""; char path[1024]; sprintf(path,"/%s/", this->Bucket); - RequestData = Cloud::ComputeDigestAmzS3v2("GET", "application/xml", path, this->TokenSecret, NULL, 0); + std::string strURL(this->URL); + eraseSubStr(strURL,"http://"); + eraseSubStr(strURL,"https://"); + if ( this->ProtocolVersion == "2" ) + RequestData = Cloud::ComputeDigestAmzS3v2("GET", "application/xml", path, this->TokenSecret, NULL, 0); + else + RequestDatav4 = Cloud::ComputeDigestAmzS3v4("GET", strURL.c_str(), "application/xml", path, this->TokenSecret, NULL, 0, NULL, this->Region); // Let's build the Header and call to curl curl_global_init(CURL_GLOBAL_ALL); curl = curl_easy_init(); @@ -531,9 +668,16 @@ Cloud::CloudWriter::CloudWriter(const char* URL, const char* TokenAuth, const ch std::string strURL(this->URL); eraseSubStr(strURL,"http://"); eraseSubStr(strURL,"https://"); - - chunk = Cloud::BuildHeaderAmzS3v2( strURL.c_str(), this->TCPPort, this->TokenAuth, RequestData); - delete RequestData; + if ( this->ProtocolVersion == "2") + { + chunk = Cloud::BuildHeaderAmzS3v2( strURL.c_str(), this->TCPPort, this->TokenAuth, RequestData); + delete RequestData; + } + else + { + chunk = Cloud::BuildHeaderAmzS3v4( strURL.c_str(), this->TCPPort, this->TokenAuth, RequestDatav4); + delete RequestDatav4; + } curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk); @@ -551,8 +695,8 @@ Cloud::CloudWriter::CloudWriter(const char* URL, const char* TokenAuth, const ch fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); curl_easy_cleanup(curl); + createBucket(); // Lets dump temporarily for debug purposes of s3v4 implementation - std::stringstream input(s); try { XMLPlatformUtils::Initialize(); } @@ -681,12 +825,15 @@ Cloud::CloudReader::~CloudReader() { } -Cloud::CloudReader::CloudReader(const char* URL, const char* TokenAuth, const char* TokenSecret, const char* TCPPort, const char* Bucket) +Cloud::CloudReader::CloudReader(const char* URL, const char* TokenAuth, const char* TokenSecret, const char* TCPPort, const char* Bucket, std::string ProtocolVersion, std::string Region) { struct Cloud::AmzData *RequestData; + struct Cloud::AmzDatav4 *RequestDatav4; CURL *curl; CURLcode res; bool GetBucketContentList=true; + struct curl_slist *chunk = NULL; + char parameters[1024]; this->URL=URL; @@ -694,6 +841,11 @@ Cloud::CloudReader::CloudReader(const char* URL, const char* TokenAuth, const ch this->TokenSecret=TokenSecret; this->TCPPort=TCPPort; this->Bucket=Bucket; + if ( !ProtocolVersion.empty() ) + this->ProtocolVersion=ProtocolVersion; + else + this->ProtocolVersion="2"; + this->Region=Region; char path[1024]; sprintf(path,"/%s/", this->Bucket); @@ -708,7 +860,6 @@ Cloud::CloudReader::CloudReader(const char* URL, const char* TokenAuth, const ch while ( GetBucketContentList ) { std::string s; - RequestData = Cloud::ComputeDigestAmzS3v2("GET", "application/xml", path, this->TokenSecret, NULL, 0); curl = curl_easy_init(); #ifdef ALLOW_SELF_SIGNED_CERTIFICATE curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); @@ -717,24 +868,35 @@ Cloud::CloudReader::CloudReader(const char* URL, const char* TokenAuth, const ch if ( curl ) { // Let's build our own header - struct curl_slist *chunk = NULL; char URL[256]; - std::string strURL(this->URL); + std::string strURL(this->URL); eraseSubStr(strURL,"http://"); eraseSubStr(strURL,"https://"); - - chunk = Cloud::BuildHeaderAmzS3v2( strURL.c_str(), this->TCPPort, this->TokenAuth, RequestData); - delete RequestData; - - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk); if ( strlen(NextFileName) == 0 ) - sprintf(URL,"%s:%s/%s/?list-type=2", this->URL,this->TCPPort, - this->Bucket); + { + sprintf(parameters,"list-type=2"); + } else - sprintf(URL,"%s:%s/%s/?list-type=2&continuation-token=%s", this->URL,this->TCPPort, - this->Bucket, NextFileName); + { + sprintf(parameters,"list-type=2&continuation-token=%s", NextFileName); + } + sprintf(URL,"%s:%s/%s/?%s", this->URL,this->TCPPort, + this->Bucket, parameters); curl_easy_setopt(curl, CURLOPT_URL, URL); + if ( this->ProtocolVersion == "2" ) + { + RequestData = Cloud::ComputeDigestAmzS3v2("GET", "application/xml", path, this->TokenSecret, NULL, 0); + chunk = Cloud::BuildHeaderAmzS3v2(strURL.c_str(), this->TCPPort, this->TokenAuth, RequestData); + delete RequestData; + } + else + { + RequestDatav4 = Cloud::ComputeDigestAmzS3v4("GET", strURL.c_str(),"application/xml", path, this->TokenSecret, NULL, 0, (char *)¶meters[0], this->Region); + chunk = Cloud::BuildHeaderAmzS3v4( strURL.c_str(), this->TCPPort, this->TokenAuth, RequestDatav4); + delete RequestDatav4; + } + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s); @@ -748,6 +910,8 @@ Cloud::CloudReader::CloudReader(const char* URL, const char* TokenAuth, const ch fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); curl_easy_cleanup(curl); + + std::stringstream input(s); try { XMLPlatformUtils::Initialize(); } @@ -785,6 +949,7 @@ Cloud::CloudReader::CloudReader(const char* URL, const char* TokenAuth, const ch void Cloud::CloudReader::DownloadFile(Cloud::CloudReader::FileEntry *entry) { struct Cloud::AmzData *RequestData; + struct Cloud::AmzDatav4 *RequestDatav4; CURL *curl; CURLcode res; @@ -793,7 +958,13 @@ 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->TokenSecret, NULL, 0); + std::string strURL(this->URL); + eraseSubStr(strURL,"http://"); + eraseSubStr(strURL,"https://"); + if ( this->ProtocolVersion == "2" ) + RequestData = Cloud::ComputeDigestAmzS3v2("GET", "application/octet-stream", path, this->TokenSecret, NULL, 0); + else + RequestDatav4 = Cloud::ComputeDigestAmzS3v4("GET", strURL.c_str(), "application/octet-stream", path, this->TokenSecret, NULL, 0, NULL, this->Region); // Let's build the Header and call to curl curl_global_init(CURL_GLOBAL_ALL); @@ -810,9 +981,16 @@ void Cloud::CloudReader::DownloadFile(Cloud::CloudReader::FileEntry *entry) std::string strURL(this->URL); eraseSubStr(strURL,"http://"); eraseSubStr(strURL,"https://"); - - chunk = Cloud::BuildHeaderAmzS3v2( strURL.c_str(), this->TCPPort, this->TokenAuth, RequestData); - delete RequestData; + if ( this->ProtocolVersion == "2" ) + { + chunk = Cloud::BuildHeaderAmzS3v2( strURL.c_str(), this->TCPPort, this->TokenAuth, RequestData); + delete RequestData; + } + else + { + chunk = Cloud::BuildHeaderAmzS3v4( strURL.c_str(), this->TCPPort, this->TokenAuth, RequestDatav4); + delete RequestDatav4; + } curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk); @@ -820,7 +998,6 @@ void Cloud::CloudReader::DownloadFile(Cloud::CloudReader::FileEntry *entry) this->Bucket, entry->FileName); curl_easy_setopt(curl, CURLOPT_URL, URL); -// curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s); // curl read a file not a memory buffer (it shall be able to do it) @@ -901,7 +1078,6 @@ bool Cloud::CloudWriter::shouldWrite(const std::string& , const Base::Persistenc void Cloud::CloudWriter::pushCloud(const char *FileName, const char *data, long size) { struct Cloud::AmzData *RequestData; -// vejmarie struct Cloud::AmzDatav4 *RequestDatav4; CURL *curl; CURLcode res; @@ -909,7 +1085,14 @@ 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->TokenSecret, data, size); + + std::string strURL(this->URL); + eraseSubStr(strURL,"http://"); + eraseSubStr(strURL,"https://"); + if ( this->ProtocolVersion == "2" ) + RequestData = Cloud::ComputeDigestAmzS3v2("PUT", "application/octet-stream", path, this->TokenSecret, data, size); + else + RequestDatav4 = Cloud::ComputeDigestAmzS3v4("PUT", strURL.c_str(), "application/octet-stream", path, this->TokenSecret, data, size, NULL, this->Region); // Let's build the Header and call to curl curl_global_init(CURL_GLOBAL_ALL); @@ -926,10 +1109,16 @@ void Cloud::CloudWriter::pushCloud(const char *FileName, const char *data, long std::string strURL(this->URL); eraseSubStr(strURL,"http://"); eraseSubStr(strURL,"https://"); - RequestDatav4 = Cloud::ComputeDigestAmzS3v4("PUT", strURL.c_str(), "application/octet-stream", path, this->TokenSecret, data, size); - delete RequestDatav4; - chunk = Cloud::BuildHeaderAmzS3v2( strURL.c_str(), this->TCPPort, this->TokenAuth, RequestData); - delete RequestData; + if ( this->ProtocolVersion == "2" ) + { + chunk = Cloud::BuildHeaderAmzS3v2( strURL.c_str(), this->TCPPort, this->TokenAuth, RequestData); + delete RequestData; + } + else + { + chunk = Cloud::BuildHeaderAmzS3v4( strURL.c_str(), this->TCPPort, this->TokenAuth, RequestDatav4); + delete RequestDatav4; + } curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk); @@ -940,8 +1129,6 @@ void Cloud::CloudWriter::pushCloud(const char *FileName, const char *data, long curl_easy_setopt(curl, CURLOPT_URL, URL); -// curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); - curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); curl_easy_setopt(curl, CURLOPT_PUT, 1L); // curl read a file not a memory buffer (it shall be able to do it) @@ -1028,7 +1215,9 @@ bool Cloud::Module::cloudSave(const char *BucketName) (const char*)this->TokenAuth.getStrValue().c_str(), (const char*)this->TokenSecret.getStrValue().c_str(), (const char*)this->TCPPort.getStrValue().c_str(), - BucketName); + BucketName, + (const char*)this->ProtocolVersion.getStrValue().c_str(), + this->Region.getStrValue()); mywriter.putNextEntry("Document.xml"); @@ -1102,7 +1291,8 @@ bool Cloud::Module::cloudRestore (const char *BucketName) (const char*)this->TokenAuth.getStrValue().c_str(), (const char*)this->TokenSecret.getStrValue().c_str(), (const char*)this->TCPPort.getStrValue().c_str(), - BucketName); + BucketName, (const char*)this->ProtocolVersion.getStrValue().c_str(), + this->Region.getStrValue()); // we shall pass there the initial Document.xml file diff --git a/src/Mod/Cloud/App/AppCloud.h b/src/Mod/Cloud/App/AppCloud.h index 9f893093ee..2be1237b83 100644 --- a/src/Mod/Cloud/App/AppCloud.h +++ b/src/Mod/Cloud/App/AppCloud.h @@ -61,15 +61,16 @@ struct AmzDatav4 { char dateFormattedD[256]; char ContentType[256]; char Host[256]; + std::string Region; char *MD5; - char *SHA256; + char *SHA256Sum; }; - +std::string getHexValue(unsigned char *input, unsigned int HMACLength); 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, const char *ptr, long size); -struct AmzDatav4 *ComputeDigestAmzS3v4(char *operation, const char *server, char *data_type, const char *target, const char *Secret, const char *ptr, long size); +struct AmzDatav4 *ComputeDigestAmzS3v4(char *operation, const char *server, char *data_type, const char *target, const char *Secret, const char *ptr, long size, char *paramters, std::string Region); struct curl_slist *BuildHeaderAmzS3v2(const char *URL, const char *TCPPort, const char *PublicKey, struct AmzData *Data); struct curl_slist *BuildHeaderAmzS3v4(const char *URL, const char *TCPPort, const char *PublicKey, struct AmzDatav4 *Data); char *MD5Sum(const char *ptr, long size); @@ -78,7 +79,7 @@ char *SHA256Sum(const char *ptr, long size); class CloudAppExport CloudReader { public: - CloudReader(const char* URL, const char* AccessKey, const char* SecretKey, const char* TCPPort, const char* Bucket); + CloudReader(const char* URL, const char* AccessKey, const char* SecretKey, const char* TCPPort, const char* Bucket,std::string ProtocolVersion, std::string Region); virtual ~CloudReader(); int file=0; int continuation=0; @@ -105,6 +106,8 @@ protected: const char* TokenAuth; const char* TokenSecret; const char* Bucket; + std::string ProtocolVersion; + std::string Region; }; class Module : public Py::ExtensionModule @@ -139,6 +142,9 @@ public: add_varargs_method("ProtocolVersion",&Module::sCloudProtocolVersion, "ProtocolVersion(string) -- Specify Amazon s3 protocol version (2 or 4)" ); + add_varargs_method("Region",&Module::sCloudRegion, + "Region(string) -- Specify Amazon s3 Region" + ); initialize("This module is the Cloud module."); // register with Python } @@ -150,6 +156,7 @@ public: App::PropertyString TokenAuth; App::PropertyString TokenSecret; App::PropertyString ProtocolVersion; + App::PropertyString Region; bool cloudSave(const char* BucketName); bool cloudRestore(const char* BucketName); @@ -161,6 +168,7 @@ private: Py::Object sCloudSave (const Py::Tuple& args); Py::Object sCloudRestore (const Py::Tuple& args); Py::Object sCloudProtocolVersion (const Py::Tuple& args); + Py::Object sCloudRegion (const Py::Tuple& args); }; @@ -178,7 +186,7 @@ class CloudAppExport CloudWriter : public Base::Writer public: int print=0; char errorCode[1024]=""; - CloudWriter(const char* URL, const char* TokenAuth, const char* TokenSecret, const char* TCPPort, const char* Bucket); + CloudWriter(const char* URL, const char* TokenAuth, const char* TokenSecret, const char* TCPPort, const char* Bucket, std::string ProtocolVersion, std::string Region); virtual ~CloudWriter(); void pushCloud(const char *FileName, const char *data, long size); void putNextEntry(const char* file); @@ -198,7 +206,8 @@ protected: const char* TokenAuth; const char* TokenSecret; const char* Bucket; - const char* ProtocolVersion; + std::string ProtocolVersion; + std::string Region; std::stringstream FileStream; };