diff --git a/src/App/Document.h b/src/App/Document.h index e8bb032437..24f91f7a68 100644 --- a/src/App/Document.h +++ b/src/App/Document.h @@ -179,6 +179,7 @@ public: boost::signals2::signal signalFinishRestoreObject; boost::signals2::signal signalChangePropertyEditor; //@} + boost::signals2::signal signalLinkXsetValue; void clearDocument(); diff --git a/src/App/PropertyLinks.cpp b/src/App/PropertyLinks.cpp index 5b2005bb71..ac6bef20a4 100644 --- a/src/App/PropertyLinks.cpp +++ b/src/App/PropertyLinks.cpp @@ -2463,6 +2463,19 @@ public: const char *filename, App::Document *pDoc, bool relative, QString *fullPath = 0) { bool absolute; + // The path could be an URI, in that case + // TODO: build a far much more resilient approach to test for an URI + std::string prefix("https://"); + std::string FileName(filename); + auto res = std::mismatch(prefix.begin(), prefix.end(), FileName.begin()); + if ( res.first == prefix.end() ) + { + // We do have an URI + QString path = QString::fromUtf8(filename); + if ( fullPath ) + *fullPath = path; + return std::string(filename); + } // make sure the filename is aboluste path QString path = QDir::cleanPath(QString::fromUtf8(filename)); if((absolute=QFileInfo(path).isAbsolute())) { @@ -2534,12 +2547,28 @@ public: } static QString getFullPath(const char *p) { - if(!p) return QString(); - return QFileInfo(QString::fromUtf8(p)).canonicalFilePath(); - } + QString path = QString::fromUtf8(p);; + std::string prefix("https://"); + std::string Path(path.toStdString()); + auto res = std::mismatch(prefix.begin(), prefix.end(), Path.begin()); + if ( res.first == prefix.end() ) + return(path); + else + { + if(!p) return QString(); + return QFileInfo(QString::fromUtf8(p)).canonicalFilePath(); + } + } QString getFullPath() const { - return QFileInfo(myPos->first).canonicalFilePath(); + QString path = myPos->first; + std::string prefix("https://"); + std::string Path(path.toStdString()); + auto res = std::mismatch(prefix.begin(), prefix.end(), Path.begin()); + if ( res.first == prefix.end() ) + return(path); + else + return QFileInfo(myPos->first).canonicalFilePath(); } const char *filePath() const { @@ -2984,6 +3013,7 @@ void PropertyXLink::setValue(std::string &&filename, std::string &&name, DocumentObject *pObject=0; DocInfoPtr info; if(filename.size()) { + owner->getDocument()->signalLinkXsetValue(filename); info = DocInfo::get(filename.c_str(),owner->getDocument(),this,name.c_str()); if(info->pcDoc) pObject = info->pcDoc->getObject(name.c_str()); diff --git a/src/App/PropertyLinks.h b/src/App/PropertyLinks.h index cec3a2d488..c291abf9d1 100644 --- a/src/App/PropertyLinks.h +++ b/src/App/PropertyLinks.h @@ -25,7 +25,7 @@ #define APP_PROPERTYLINKS_H // Std. configurations - +#include #include #include diff --git a/src/Mod/Cloud/App/AppCloud.cpp b/src/Mod/Cloud/App/AppCloud.cpp index 5709a9d48e..a8b680e48b 100644 --- a/src/Mod/Cloud/App/AppCloud.cpp +++ b/src/Mod/Cloud/App/AppCloud.cpp @@ -263,7 +263,7 @@ void Cloud::CloudWriter::createBucket() } else { - chunk = Cloud::BuildHeaderAmzS3v4( strURL.c_str(), this->TCPPort, this->TokenAuth, RequestDatav4); + chunk = Cloud::BuildHeaderAmzS3v4( strURL.c_str(), this->TokenAuth, RequestDatav4); delete RequestDatav4; } @@ -533,7 +533,7 @@ char *Cloud::MD5Sum(const char *ptr, long size) return(output); } -struct curl_slist *Cloud::BuildHeaderAmzS3v4(const char *URL, const char *TCPPort, const char *PublicKey, struct Cloud::AmzDatav4 *Data) +struct curl_slist *Cloud::BuildHeaderAmzS3v4(const char *URL, const char *PublicKey, struct Cloud::AmzDatav4 *Data) { char header_data[1024]; struct curl_slist *chunk = NULL; @@ -671,7 +671,7 @@ Cloud::CloudWriter::CloudWriter(const char* URL, const char* TokenAuth, const ch } else { - chunk = Cloud::BuildHeaderAmzS3v4( strURL.c_str(), this->TCPPort, this->TokenAuth, RequestDatav4); + chunk = Cloud::BuildHeaderAmzS3v4( strURL.c_str(), this->TokenAuth, RequestDatav4); delete RequestDatav4; } @@ -887,7 +887,7 @@ Cloud::CloudReader::CloudReader(const char* URL, const char* TokenAuth, const ch 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); + chunk = Cloud::BuildHeaderAmzS3v4( strURL.c_str(), this->TokenAuth, RequestDatav4); delete RequestDatav4; } curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk); @@ -982,7 +982,7 @@ void Cloud::CloudReader::DownloadFile(Cloud::CloudReader::FileEntry *entry) } else { - chunk = Cloud::BuildHeaderAmzS3v4( strURL.c_str(), this->TCPPort, this->TokenAuth, RequestDatav4); + chunk = Cloud::BuildHeaderAmzS3v4( strURL.c_str(), this->TokenAuth, RequestDatav4); delete RequestDatav4; } @@ -1110,7 +1110,7 @@ void Cloud::CloudWriter::pushCloud(const char *FileName, const char *data, long } else { - chunk = Cloud::BuildHeaderAmzS3v4( strURL.c_str(), this->TCPPort, this->TokenAuth, RequestDatav4); + chunk = Cloud::BuildHeaderAmzS3v4( strURL.c_str(), this->TokenAuth, RequestDatav4); delete RequestDatav4; } @@ -1265,6 +1265,40 @@ void readFiles(Cloud::CloudReader reader, Base::XMLReader *xmlreader) } } +void Cloud::Module::LinkXSetValue(std::string filename) +{ + // Need to check if the document exist + // if not we have to create a new one + // and Restore the associated Document + // + std::vector Documents; + Documents = App::GetApplication().getDocuments(); + for (std::vector::iterator it = Documents.begin() ; it != Documents.end(); it++) + { + if ( (*it)->FileName.getValue() == filename ) + { + // The document exist + // we can exit + return; + } + } + + size_t header = filename.find_first_of(":"); + string protocol=filename.substr(0,header); + string url_new=filename.substr(header+3); //url_new is the url excluding the http part + size_t part2 = url_new.find_first_of("/"); + string path =url_new.substr(part2+1); + // Starting from here the Document doesn't exist we must create it + // and make it the active Document before Restoring + App::Document* newDoc; + string newName; + Document* currentDoc = GetApplication().getActiveDocument(); + newName = GetApplication().getUniqueDocumentName("unnamed"); + newDoc = GetApplication().newDocument(newName.c_str(), (const char*)path.c_str(), true); + GetApplication().setActiveDocument(newDoc); + this->cloudRestore((const char*)path.c_str()); + GetApplication().setActiveDocument(currentDoc); +} bool Cloud::Module::cloudRestore (const char *BucketName) { @@ -1272,6 +1306,7 @@ bool Cloud::Module::cloudRestore (const char *BucketName) Document* doc = GetApplication().getActiveDocument(); // clean up if the document is not empty // !TODO: mind exceptions while restoring! + doc->signalLinkXsetValue.connect(boost::bind(&Cloud::Module::LinkXSetValue,this,_1)); doc->clearUndos(); @@ -1296,7 +1331,7 @@ bool Cloud::Module::cloudRestore (const char *BucketName) GetApplication().signalStartRestoreDocument(*doc); doc->setStatus(Document::Restoring, true); - + try { // Document::Restore(reader); doc->Restore(reader); @@ -1320,6 +1355,12 @@ bool Cloud::Module::cloudRestore (const char *BucketName) GetApplication().signalFinishRestoreDocument(*doc); doc->setStatus(Document::Restoring, false); + doc->Label.setValue(BucketName); + // The FileName shall be an URI format + string uri; + uri = this->URL.getStrValue()+":"+this->TCPPort.getStrValue()+"/"+string(BucketName); + doc->FileName.setValue(uri); + doc->signalLinkXsetValue.disconnect(boost::bind(&Cloud::Module::LinkXSetValue,this,_1)); return(true); } diff --git a/src/Mod/Cloud/App/AppCloud.h b/src/Mod/Cloud/App/AppCloud.h index 2be1237b83..6b7ee7d838 100644 --- a/src/Mod/Cloud/App/AppCloud.h +++ b/src/Mod/Cloud/App/AppCloud.h @@ -72,7 +72,7 @@ size_t CurlWrite_CallbackFunc_StdString(void *contents, size_t size, size_t nmem 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, 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); +struct curl_slist *BuildHeaderAmzS3v4(const char *URL, const char *PublicKey, struct AmzDatav4 *Data); char *MD5Sum(const char *ptr, long size); char *SHA256Sum(const char *ptr, long size); @@ -159,6 +159,7 @@ public: App::PropertyString Region; bool cloudSave(const char* BucketName); bool cloudRestore(const char* BucketName); + void LinkXSetValue(std::string filename); private: Py::Object sCloudURL (const Py::Tuple& args); diff --git a/src/Mod/Cloud/CMakeLists.txt b/src/Mod/Cloud/CMakeLists.txt index 5038e7308b..790ac3ee71 100644 --- a/src/Mod/Cloud/CMakeLists.txt +++ b/src/Mod/Cloud/CMakeLists.txt @@ -1,3 +1,4 @@ +add_compile_options("-DBUILD_CLOUD") #----------------------------- Control certificate validation ------------ option(ALLOW_SELF_SIGNED_CERTIFICATE "Allow self signed certificate" OFF) if (ALLOW_SELF_SIGNED_CERTIFICATE)