#include "ScanFileOrFolder.h" #include "TransferThread.h" #include #include #include "../../../cpp11addition.h" #ifdef Q_OS_WIN32 #ifndef NOMINMAX #define NOMINMAX #endif #include #endif #ifdef WIDESTRING std::wstring ScanFileOrFolder::text_slash=L"/"; std::wstring ScanFileOrFolder::text_antislash=L"\\"; std::wstring ScanFileOrFolder::text_dot=L"."; #else std::string ScanFileOrFolder::text_slash="/"; std::string ScanFileOrFolder::text_antislash="\\"; std::string ScanFileOrFolder::text_dot="."; #endif ScanFileOrFolder::ScanFileOrFolder(const Ultracopier::CopyMode &mode) : moveTheWholeFolder(false), stopIt(false), stopped(false), folderExistsAction(FolderExistsAction::FolderExists_NotSet), fileErrorAction(FileErrorAction::FileError_NotSet), checkDestinationExists(false), copyListOrder(false), #ifdef ULTRACOPIER_PLUGIN_RSYNC rsync(false), #endif mode(Ultracopier::CopyMode::Copy), reloadTheNewFilters(false), haveFilters(false) { #ifdef ULTRACOPIER_PLUGIN_RSYNC rsync = false; #endif moveTheWholeFolder = true; stopped = true; stopIt = false; this->mode = mode; folder_isolation = std::regex("^(.*/)?([^/]+)/$"); setObjectName(QStringLiteral("ScanFileOrFolder")); /*#ifdef Q_OS_WIN32 QString userName; DWORD size=255; WCHAR * userNameW=new WCHAR[size]; if(GetUserNameW(userNameW,&size)) { userName=QString::fromWCharArray(userNameW,size-1); blackList.push_back(QFileInfo(QStringLiteral("C:/Users/%1/AppData/Roaming/").arg(userName))); } delete userNameW; #endif*/ } ScanFileOrFolder::~ScanFileOrFolder() { stop(); quit(); wait(); } bool ScanFileOrFolder::isFinished() const { return stopped; } void ScanFileOrFolder::addToList(const std::vector& sources,const INTERNALTYPEPATH& destination) { stopIt=false; this->sources=parseWildcardSources(sources); this->destination=destination; #ifdef WIDESTRING QFileInfo destinationInfo(QString::fromStdWString(this->destination)); ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"check symblink: "+destinationInfo.absoluteFilePath().toStdString()+", destination: "+TransferThread::internalStringTostring(destination)); #ifdef WIDESTRING while(TransferThread::is_symlink(destinationInfo.absoluteFilePath().toStdWString())) #else while(TransferThread::is_symlink(destinationInfo.absoluteFilePath().toStdString())) #endif { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"resolv destination to: "+destinationInfo.symLinkTarget().toStdString()); if(QFileInfo(destinationInfo.symLinkTarget()).isAbsolute()) this->destination=destinationInfo.symLinkTarget().toStdWString(); else this->destination=destinationInfo.absolutePath().toStdWString()+text_slash+destinationInfo.symLinkTarget().toStdWString(); destinationInfo.setFile(QString::fromStdWString(this->destination)); } if(sources.size()>1 || QFileInfo(QString::fromStdWString(destination)).isDir()) /* Disabled because the separator transformation product bug * if(!destination.endsWith(QDir::separator())) this->destination+=QDir::separator();*/ if(!stringEndsWith(destination,'/') && !stringEndsWith(destination,'\\')) this->destination+=text_slash;//put unix separator because it's transformed into that's under windows too #else QFileInfo destinationInfo(QString::fromStdString(this->destination)); ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"check symblink: "+destinationInfo.absoluteFilePath().toStdString()); while(destinationInfo.isSymLink()) { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"resolv destination to: "+destinationInfo.symLinkTarget().toStdString()); if(QFileInfo(destinationInfo.symLinkTarget()).isAbsolute()) this->destination=destinationInfo.symLinkTarget().toStdString(); else this->destination=destinationInfo.absolutePath().toStdString()+text_slash+destinationInfo.symLinkTarget().toStdString(); destinationInfo.setFile(QString::fromStdString(this->destination)); } if(sources.size()>1 || QFileInfo(QString::fromStdString(destination)).isDir()) /* Disabled because the separator transformation product bug * if(!destination.endsWith(QDir::separator())) this->destination+=QDir::separator();*/ if(!stringEndsWith(destination,'/') && !stringEndsWith(destination,'\\')) this->destination+=text_slash;//put unix separator because it's transformed into that's under windows too #endif //ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"addToList("+stringimplode(sources,";")+","+this->destination+")"); } std::vector ScanFileOrFolder::parseWildcardSources(const std::vector &sources) const { std::regex splitFolder("[/\\\\]"); std::vector returnList; unsigned int index=0; while(index<(unsigned int)sources.size()) { std::string sourceAt=TransferThread::internalStringTostring(sources.at(index)); if(sourceAt.find("*") != std::string::npos) { std::vector toParse=stringregexsplit(sourceAt,splitFolder); ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"before wildcard parse: "+sourceAt+", toParse: "+stringimplode(toParse,", ")); std::vector > recomposedSource; { std::vector t; t.push_back(""); recomposedSource.push_back(t); } while(toParse.size()>0) { if(toParse.front().find("*") != std::string::npos) { std::string toParseFirst=toParse.front(); if(toParseFirst.empty()) toParseFirst=TransferThread::internalStringTostring(text_slash); std::vector > newRecomposedSource; stringreplaceAll(toParseFirst,"*","[^/\\\\]*"); std::regex toResolv=std::regex(toParseFirst); unsigned int index_recomposedSource=0; while(index_recomposedSource list; if(TransferThread::is_dir(fileInfo.c_str())) { if(TransferThread::entryInfoList(TransferThread::stringToInternalString(fileInfo),list)) { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"list the folder: "+fileInfo+", with the wildcard: "+toParseFirst); unsigned int index_fileList=0; while(index_fileList tempList=recomposedSource.at(index_recomposedSource); tempList.push_back(fileName); newRecomposedSource.push_back(tempList); } index_fileList++; } } } index_recomposedSource++; } recomposedSource=newRecomposedSource; } else { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"add toParse: "+stringimplode(toParse,TransferThread::internalStringTostring(text_slash))); unsigned int index_recomposedSource=0; while(index_recomposedSource &include, const std::vector &exclude) { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start"); QMutexLocker lock(&filtersMutex); this->include_send=include; this->exclude_send=exclude; reloadTheNewFilters=true; haveFilters=include_send.size()>0 || exclude_send.size()>0; ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"haveFilters: "+std::to_string(haveFilters)+", include_send.size(): "+std::to_string(include_send.size())+", exclude_send.size(): "+std::to_string(exclude_send.size())); } //set action if Folder are same or exists void ScanFileOrFolder::setFolderExistsAction(const FolderExistsAction &action, const std::string &newName) { this->newName=TransferThread::stringToInternalString(newName); folderExistsAction=action; waitOneAction.release(); } //set action if error void ScanFileOrFolder::setFolderErrorAction(const FileErrorAction &action) { fileErrorAction=action; waitOneAction.release(); } void ScanFileOrFolder::stop() { stopIt=true; waitOneAction.release(); } void ScanFileOrFolder::run() { stopped=false; ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice, "start the listing with destination: "+TransferThread::internalStringTostring(destination)+", mode: "+std::to_string(mode)); #ifdef Q_OS_UNIX destination=resolvDestination(destination); #endif #ifdef WIDESTRING stringreplaceAll(destination,L"\\",L"/"); #else stringreplaceAll(destination,"\\","/"); #endif if(stopIt) { stopped=true; return; } if(fileErrorAction==FileError_Skip) { stopped=true; return; } unsigned int sourceIndex=0; while(sourceIndex buf(512); ssize_t nbytes=0; do { buf.resize(buf.size()*2); nbytes=readlink(TransferThread::internalStringTostring(destination).c_str(), buf.data(), buf.size()); } while (nbytes == buf.size()); if (nbytes!=-1) buf.resize(nbytes); while(nbytes!=-1) { temp=FSabsolutePath(temp); if(!stringEndsWith(destination,'/') #ifdef Q_OS_WIN32 && !stringEndsWith(destination,'\\') #endif ) temp+=TransferThread::stringToInternalString("/"); temp+=TransferThread::stringToInternalString(std::string(buf.data(), buf.size())); /// \todo change for pure c++ code #ifdef WIDESTRING temp=QFileInfo(QString::fromStdWString(temp)).absoluteFilePath().toStdWString(); #else temp=QFileInfo(QString::fromStdString(temp)).absoluteFilePath().toStdString(); #endif do { buf.resize(buf.size() * 2); nbytes=readlink(TransferThread::internalStringTostring(temp).c_str(), buf.data(), buf.size()); } while (nbytes == buf.size()); if (nbytes!=-1) buf.resize(nbytes); } return temp; /*do { fileErrorAction=FileError_NotSet; if(isBlackListed(destination)) { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"isBlackListed: "+destination); emit errorOnFolder(destination,tr("Blacklisted folder").toStdString(),ErrorType_Folder); waitOneAction.acquire(); ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"actionNum: "+std::to_string(fileErrorAction)); } } while(fileErrorAction==FileError_Retry || fileErrorAction==FileError_PutToEndOfTheList); return newDestination;*/ } #endif /*bool ScanFileOrFolder::isBlackListed(const QFileInfo &destination) { int index=0; int size=blackList.size(); while(index entryList; do { fileErrorAction=FileError_NotSet; if(!TransferThread::entryInfoList(source,entryList)) { #ifdef Q_OS_UNIX int saveerrno=errno; const std::string &errorStr=strerror(saveerrno); ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"Problem with the folder "+TransferThread::internalStringTostring(source)+" to read: "+std::to_string(saveerrno)); emit errorOnFolder(source,tr("Problem with folder read").toStdString()+": "+errorStr); #else const std::string &errorStr=TransferThread::GetLastErrorStdStr(); ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"Problem with the folder "+TransferThread::internalStringTostring(source)+" to read: "+errorStr); emit errorOnFolder(source,tr("Problem with folder read").toStdString()+": "+errorStr); #endif waitOneAction.acquire(); ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"actionNum: "+std::to_string(fileErrorAction)); } } while(fileErrorAction==FileError_Retry); if(copyListOrder) std::sort(entryList.begin(), entryList.end(), [](TransferThread::dirent_uc a, TransferThread::dirent_uc b) { return a.d_nameinclude=this->include_send; this->exclude=this->exclude_send; } const INTERNALTYPEPATH &fileName=fileInfo.d_name; if(fileInfo.isFolder) { bool excluded=false,included=(include.size()==0); unsigned int filters_index=0; while(filters_indexcheckDestinationExists=checkDestinationFolderExists; } void ScanFileOrFolder::setRenamingRules(const std::string &firstRenamingRule, const std::string &otherRenamingRule) { this->firstRenamingRule=firstRenamingRule; this->otherRenamingRule=otherRenamingRule; } void ScanFileOrFolder::setMoveTheWholeFolder(const bool &moveTheWholeFolder) { this->moveTheWholeFolder=moveTheWholeFolder; } void ScanFileOrFolder::setFollowTheStrictOrder(const bool &order) { this->copyListOrder=order; } #ifdef ULTRACOPIER_PLUGIN_RSYNC /// \brief set rsync void ScanFileOrFolder::setRsync(const bool rsync) { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"set rsync: "+std::to_string(rsync)); this->rsync=rsync; } #endif void ScanFileOrFolder::set_updateMount() { driveManagement.tryUpdate(); }