1 
2 
3 #include "tsystem.h"
4 
5 using namespace std;
6 
7 #include <set>
8 #include "tfilepath_io.h"
9 #include "tconvert.h"
10 
11 #ifndef TNZCORE_LIGHT
12 
13 #include <QDateTime>
14 #include <QStringList>
15 #include <QProcess>
16 #include <QDir>
17 #include <QFile>
18 #include <QFileInfo>
19 #include <QSettings>
20 #include <QVariant>
21 #include <QThread>
22 #include <QUrl>
23 #include <QCoreApplication>
24 #include <QUuid>
25 
26 #include <QDesktopServices>
27 #include <QHostInfo>
28 
29 #ifdef _WIN32
30 #include <shlobj.h>
31 #include <shellapi.h>
32 #include <winnt.h>
33 #endif
34 
35 namespace {
36 
toQString(const TFilePath & path)37 inline QString toQString(const TFilePath &path) {
38   return QString::fromStdWString(path.getWideString());
39 }
40 
41 int HasMainLoop = -1;
42 
43 }  // namespace
44 //-----------------------------------------------------------------------------------
45 
TFileStatus(const TFilePath & path)46 TFileStatus::TFileStatus(const TFilePath &path) {
47   m_fileInfo = QFileInfo(QString::fromStdWString(path.getWideString()));
48   m_exist    = m_fileInfo.exists();
49 }
50 
51 //-----------------------------------------------------------------------------------
52 
getGroup() const53 QString TFileStatus::getGroup() const {
54   if (!m_exist) return QString();
55   return m_fileInfo.group();
56 }
57 
58 //-----------------------------------------------------------------------------------
59 
getUser() const60 QString TFileStatus::getUser() const {
61   if (!m_exist) return QString();
62   return m_fileInfo.owner();
63 }
64 
65 //-----------------------------------------------------------------------------------
66 
getSize() const67 TINT64 TFileStatus::getSize() const {
68   if (!m_exist) return 0;
69   return m_fileInfo.size();
70 }
71 
72 //-----------------------------------------------------------------------------------
73 
getLastAccessTime() const74 QDateTime TFileStatus::getLastAccessTime() const {
75   if (!m_exist) return QDateTime();
76   return m_fileInfo.lastRead();
77 }
78 
79 //-----------------------------------------------------------------------------------
80 
getLastModificationTime() const81 QDateTime TFileStatus::getLastModificationTime() const {
82   if (!m_exist) return QDateTime();
83   return m_fileInfo.lastModified();
84 }
85 
86 //-----------------------------------------------------------------------------------
87 
getCreationTime() const88 QDateTime TFileStatus::getCreationTime() const {
89   if (!m_exist) return QDateTime();
90   return m_fileInfo.created();
91 }
92 
93 //-----------------------------------------------------------------------------------
94 
getPermissions() const95 QFile::Permissions TFileStatus::getPermissions() const {
96   if (!m_exist) return 0;
97   return m_fileInfo.permissions();
98 }
99 
100 //-----------------------------------------------------------------------------------
101 
isDirectory() const102 bool TFileStatus::isDirectory() const {
103   if (!m_exist) return 0;
104   return m_fileInfo.isDir();
105 }
106 
107 //-----------------------------------------------------------------------------------
108 
isLink() const109 bool TFileStatus::isLink() const { return m_fileInfo.isSymLink(); }
110 
111 //-----------------------------------------------------------------------------------
112 
doHaveMainLoop()113 bool TSystem::doHaveMainLoop() {
114   if (HasMainLoop == -1)
115     assert(!"you MUST call the TSystem::hasMainLoop function in the main of the program!");
116   return HasMainLoop == 1;
117 }
118 
119 //-----------------------------------------------------------------------------------
120 
hasMainLoop(bool state)121 void TSystem::hasMainLoop(bool state) {
122   assert(HasMainLoop == -1);
123   HasMainLoop = state ? 1 : 0;
124 }
125 
126 //-----------------------------------------------------------------------------------
127 
getHostName()128 QString TSystem::getHostName() { return QHostInfo::localHostName(); }
129 
130 //------------------------------------------------------------
131 
getUserName()132 QString TSystem::getUserName() {
133   QStringList list = QProcess::systemEnvironment();
134   int j;
135   for (j = 0; j < list.size(); j++) {
136     QString value = list.at(j);
137     QString user;
138 #ifdef _WIN32
139     if (value.startsWith("USERNAME=")) user = value.right(value.size() - 9);
140 #else
141     if (value.startsWith("USER=")) user = value.right(value.size() - 5);
142 #endif
143     if (!user.isEmpty()) return user;
144   }
145   return QString("none");
146 }
147 
148 //------------------------------------------------------------
149 
getTempDir()150 TFilePath TSystem::getTempDir() {
151   return TFilePath(QDir::tempPath().toStdString());
152 }
153 
154 //------------------------------------------------------------
155 
getTestDir(string name)156 TFilePath TSystem::getTestDir(string name) {
157   return TFilePath("C:") + TFilePath(name);
158 }
159 
160 //------------------------------------------------------------
161 
getSystemValue(const TFilePath & name)162 QString TSystem::getSystemValue(const TFilePath &name) {
163   QStringList strlist = toQString(name).split("\\", QString::SkipEmptyParts);
164 
165   assert(strlist.size() > 3);
166   assert(strlist.at(0) == "SOFTWARE");
167 
168   QSettings qs(QSettings::SystemScope, strlist.at(1), strlist.at(2));
169 
170   int i;
171   QString varName;
172 
173   for (i = 3; i < strlist.size(); i++) {
174     varName += strlist.at(i);
175     if (i < strlist.size() - 1) varName += "//";
176   }
177 
178   return qs.value(varName).toString();
179 }
180 
181 //------------------------------------------------------------
182 
getBinDir()183 TFilePath TSystem::getBinDir() {
184   TFilePath fp =
185       TFilePath(QCoreApplication::applicationFilePath().toStdString());
186   return fp.getParentDir();
187 }
188 
189 //------------------------------------------------------------
190 
getDllDir()191 TFilePath TSystem::getDllDir() { return getBinDir(); }
192 //------------------------------------------------------------
193 
getUniqueFile(QString field)194 TFilePath TSystem::getUniqueFile(QString field) {
195   QString uuid = QUuid::createUuid()
196                      .toString()
197                      .replace("-", "")
198                      .replace("{", "")
199                      .replace("}", "")
200                      .toLatin1()
201                      .data();
202 
203   QString path = QDir::tempPath() + QString("\\") + field + uuid;
204 
205   return TFilePath(path.toStdString());
206 }
207 
208 //------------------------------------------------------------
209 
210 namespace {
getPathsToCreate(const TFilePath & path)211 TFilePathSet getPathsToCreate(const TFilePath &path) {
212   TFilePathSet pathList;
213   if (path.isEmpty()) return pathList;
214   TFilePath parentDir = path;
215   while (!TFileStatus(parentDir).doesExist()) {
216     if (parentDir == parentDir.getParentDir()) return TFilePathSet();
217     pathList.push_back(parentDir);
218     parentDir = parentDir.getParentDir();
219   }
220   return pathList;
221 }
222 
setPathsPermissions(const TFilePathSet & pathSet,QFile::Permissions permissions)223 void setPathsPermissions(const TFilePathSet &pathSet,
224                          QFile::Permissions permissions) {
225   TFilePathSet::const_iterator it;
226   for (it = pathSet.begin(); it != pathSet.end(); it++) {
227     QFile f(toQString(*it));
228     f.setPermissions(permissions);
229   }
230 }
231 }
232 
233 // gestire exception
mkDir(const TFilePath & path)234 void TSystem::mkDir(const TFilePath &path) {
235   TFilePathSet pathSet = getPathsToCreate(path);
236   QString qPath        = toQString(path);
237   assert(!qPath.contains("+"));
238   if (!QDir::current().mkpath(qPath))
239     throw TSystemException(path, "can't create folder!");
240 
241   setPathsPermissions(
242       pathSet, QFile::ReadUser | QFile::WriteUser | QFile::ExeUser |
243                    QFile::ReadGroup | QFile::WriteGroup | QFile::ExeGroup |
244                    QFile::ReadOther | QFile::WriteOther | QFile::ExeOther);
245 }
246 
247 //------------------------------------------------------------
248 // gestire exception
rmDir(const TFilePath & path)249 void TSystem::rmDir(const TFilePath &path) {
250   if (!QDir(toQString(path.getParentDir()))
251            .rmdir(QString::fromStdString(path.getName())))
252     throw TSystemException(path, "can't remove folder!");
253 }
254 
255 // vinz
256 
257 //------------------------------------------------------------
258 
259 namespace {
rmDirTree(const QString & path)260 void rmDirTree(const QString &path) {
261   int i;
262   QFileInfoList fil = QDir(path).entryInfoList();
263   for (i = 0; i < fil.size(); i++) {
264     QFileInfo fi = fil.at(i);
265     if (fi.fileName() == QString(".") || fi.fileName() == QString(".."))
266       continue;
267     QString son = fi.absoluteFilePath();
268     if (QFileInfo(son).isDir())
269       rmDirTree(son);
270     else if (QFileInfo(son).isFile())
271       if (!QFile::remove(son))
272         throw TSystemException("can't remove file" + son.toStdString());
273   }
274   if (!QDir::current().rmdir(path))
275     throw TSystemException("can't remove path!");
276 }
277 
278 }  // namespace
279 
280 //------------------------------------------------------------
281 
rmDirTree(const TFilePath & path)282 void TSystem::rmDirTree(const TFilePath &path) { ::rmDirTree(toQString(path)); }
283 
284 //------------------------------------------------------------
285 
copyDir(const TFilePath & dst,const TFilePath & src)286 void TSystem::copyDir(const TFilePath &dst, const TFilePath &src) {
287   QFileInfoList fil = QDir(toQString(src)).entryInfoList();
288 
289   QDir::current().mkdir(toQString(dst));
290 
291   int i;
292   for (i = 0; i < fil.size(); i++) {
293     QFileInfo fi = fil.at(i);
294     if (fi.fileName() == QString(".") || fi.fileName() == QString(".."))
295       continue;
296     if (fi.isDir()) {
297       TFilePath srcDir = TFilePath(fi.filePath().toStdString());
298       TFilePath dstDir = dst + srcDir.getName();
299       copyDir(dstDir, srcDir);
300     } else {
301       TFilePath srcFi = dst + TFilePath(fi.fileName());
302       QFile::copy(fi.filePath(), toQString(srcFi));
303     }
304   }
305 }
306 
307 //------------------------------------------------------------
308 /*
309 void TSystem::touchFile(const TFilePath &path)
310 {
311 QFile f(toQString(path));
312 
313 if (!f.open(QIODevice::ReadWrite))
314   throw TSystemException(path, "can't touch file!");
315 else
316   f.close();
317 }
318 */
319 //------------------------------------------------------------
320 /*
321 #ifdef _WIN32
322 
323 wstring getFormattedMessage(DWORD lastError)
324 {
325 LPVOID lpMsgBuf;
326 FormatMessage(
327     FORMAT_MESSAGE_ALLOCATE_BUFFER |
328     FORMAT_MESSAGE_FROM_SYSTEM |
329     FORMAT_MESSAGE_IGNORE_INSERTS,
330     NULL,
331     lastError,
332     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
333     (LPTSTR) &lpMsgBuf,
334     0,
335     NULL
336 );
337 
338 int wSize = MultiByteToWideChar(0,0,(char*)lpMsgBuf,-1,0,0);
339 if(!wSize)
340   return wstring();
341 
342 wchar_t* wBuffer = new wchar_t [wSize+1];
343 MultiByteToWideChar(0,0,(char*)lpMsgBuf,-1,wBuffer,wSize);
344 wBuffer[wSize]='\0';
345 wstring wmsg(wBuffer);
346 
347 delete []wBuffer;
348 LocalFree(lpMsgBuf);
349 return wmsg;
350 }
351 
352 //------------------------------------------------------------
353 
354 #endif
355 */
356 //------------------------------------------------------------
357 
copyFile(const TFilePath & dst,const TFilePath & src,bool overwrite)358 void TSystem::copyFile(const TFilePath &dst, const TFilePath &src,
359                        bool overwrite) {
360   assert(dst != TFilePath());
361 
362   if (dst == src) return;
363 
364   // Create the containing folder before trying to copy or it will crash!
365   touchParentDir(dst);
366 
367   const QString &qDst = toQString(dst);
368   if (overwrite && QFile::exists(qDst)) QFile::remove(qDst);
369 
370   if (!QFile::copy(toQString(src), qDst))
371     throw TSystemException(dst, "can't copy file!");
372 }
373 
374 //------------------------------------------------------------
375 
renameFile(const TFilePath & dst,const TFilePath & src,bool overwrite)376 void TSystem::renameFile(const TFilePath &dst, const TFilePath &src,
377                          bool overwrite) {
378   assert(dst != TFilePath());
379 
380   if (dst == src) return;
381 
382   const QString &qDst = toQString(dst);
383   if (overwrite && QFile::exists(qDst)) QFile::remove(qDst);
384 
385   if (!QFile::rename(toQString(src), qDst))
386     throw TSystemException(dst, "can't rename file!");
387 }
388 
389 //------------------------------------------------------------
390 
391 // gestire gli errori con GetLastError?
deleteFile(const TFilePath & fp)392 void TSystem::deleteFile(const TFilePath &fp) {
393   if (!QFile::remove(toQString(fp)))
394     throw TSystemException(fp, "can't delete file!");
395 }
396 
397 //------------------------------------------------------------
398 
hideFile(const TFilePath & fp)399 void TSystem::hideFile(const TFilePath &fp) {
400 #ifdef _WIN32
401   if (!SetFileAttributesW(fp.getWideString().c_str(), FILE_ATTRIBUTE_HIDDEN))
402     throw TSystemException(fp, "can't hide file!");
403 #else  // MACOSX, and others
404   TSystem::renameFile(TFilePath(fp.getParentDir() + L"." + fp.getLevelNameW()),
405                       fp);
406 #endif
407 }
408 
409 //------------------------------------------------------------
410 
411 class CaselessFilepathLess final
412     : public std::binary_function<TFilePath, TFilePath, bool> {
413 public:
operator ()(const TFilePath & a,const TFilePath & b) const414   bool operator()(const TFilePath &a, const TFilePath &b) const {
415     // Perform case sensitive compare, fallback to case insensitive.
416     const wstring a_str = a.getWideString();
417     const wstring b_str = b.getWideString();
418 
419     unsigned int i   = 0;
420     int case_compare = -1;
421     while (a_str[i] || b_str[i]) {
422       if (a_str[i] != b_str[i]) {
423         const wchar_t a_wchar = towlower(a_str[i]);
424         const wchar_t b_wchar = towlower(b_str[i]);
425         if (a_wchar < b_wchar) {
426           return true;
427         } else if (a_wchar > b_wchar) {
428           return false;
429         } else if (case_compare == -1) {
430           case_compare = a_str[i] < b_str[i];
431         }
432       }
433       i++;
434     }
435     return (case_compare == 1);
436   }
437 };
438 
439 //------------------------------------------------------------
440 /*! return the folder path list which is readable and executable
441 */
readDirectory_Dir_ReadExe(TFilePathSet & dst,const TFilePath & path)442 void TSystem::readDirectory_Dir_ReadExe(TFilePathSet &dst,
443                                         const TFilePath &path) {
444   QStringList dirItems;
445   readDirectory_DirItems(dirItems, path);
446 
447   for (const QString &item : dirItems) {
448     TFilePath son = path + TFilePath(item.toStdWString());
449     dst.push_back(son);
450   }
451 }
452 
453 //------------------------------------------------------------
454 // return the folder item list which is readable and executable
455 // (returns only names, not full path)
readDirectory_DirItems(QStringList & dst,const TFilePath & path)456 void TSystem::readDirectory_DirItems(QStringList &dst, const TFilePath &path) {
457   if (!TFileStatus(path).isDirectory())
458     throw TSystemException(path, " is not a directory");
459 
460   QDir dir(toQString(path));
461 
462 #ifdef _WIN32
463   // equivalent to sorting with QDir::LocaleAware
464   auto const strCompare = [](const QString &s1, const QString &s2) {
465     return QString::localeAwareCompare(s1, s2) < 0;
466   };
467 
468   std::set<QString, decltype(strCompare)> entries(strCompare);
469 
470   WIN32_FIND_DATA find_dir_data;
471   QString dir_search_path = dir.absolutePath() + "\\*";
472   auto addEntry           = [&]() {
473     // QDir::NoDotAndDotDot condition
474     if (wcscmp(find_dir_data.cFileName, L".") != 0 &&
475         wcscmp(find_dir_data.cFileName, L"..") != 0) {
476       // QDir::AllDirs condition
477       if (find_dir_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY &&
478           (find_dir_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0) {
479         entries.insert(QString::fromWCharArray(find_dir_data.cFileName));
480       }
481     }
482   };
483   HANDLE hFind =
484       FindFirstFile((const wchar_t *)dir_search_path.utf16(), &find_dir_data);
485   if (hFind != INVALID_HANDLE_VALUE) {
486     addEntry();
487     while (FindNextFile(hFind, &find_dir_data)) addEntry();
488   }
489   for (const QString &name : entries) dst.push_back(QString(name));
490 
491 #else
492   dst = dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Readable,
493                       QDir::Name | QDir::LocaleAware);
494 #endif
495 }
496 
497 //------------------------------------------------------------
498 /*! to retrieve the both lists with groupFrames option = on and off.
499 */
readDirectory(TFilePathSet & groupFpSet,TFilePathSet & allFpSet,const TFilePath & path)500 void TSystem::readDirectory(TFilePathSet &groupFpSet, TFilePathSet &allFpSet,
501                             const TFilePath &path) {
502   if (!TFileStatus(path).isDirectory())
503     throw TSystemException(path, " is not a directory");
504 
505   std::set<TFilePath, CaselessFilepathLess> fileSet_group;
506   std::set<TFilePath, CaselessFilepathLess> fileSet_all;
507 
508   QStringList fil;
509 #ifdef _WIN32
510   WIN32_FIND_DATA find_dir_data;
511   QString dir_search_path = QDir(toQString(path)).absolutePath() + "\\*";
512   auto addEntry           = [&]() {
513     // QDir::NoDotAndDotDot condition
514     if (wcscmp(find_dir_data.cFileName, L".") != 0 &&
515         wcscmp(find_dir_data.cFileName, L"..") != 0) {
516       // QDir::Files condition
517       if ((find_dir_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 &&
518           (find_dir_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0) {
519         fil.append(QString::fromWCharArray(find_dir_data.cFileName));
520       }
521     }
522   };
523   HANDLE hFind =
524       FindFirstFile((const wchar_t *)dir_search_path.utf16(), &find_dir_data);
525   if (hFind != INVALID_HANDLE_VALUE) {
526     addEntry();
527     while (FindNextFile(hFind, &find_dir_data)) addEntry();
528   }
529 #else
530   fil = QDir(toQString(path))
531             .entryList(QDir::Files | QDir::NoDotAndDotDot | QDir::Readable);
532 #endif
533   if (fil.size() == 0) return;
534 
535   for (int i = 0; i < fil.size(); i++) {
536     QString fi = fil.at(i);
537 
538     TFilePath son = path + TFilePath(fi.toStdWString());
539 
540     // store all file paths
541     fileSet_all.insert(son);
542 
543     // in case of the sequencial files
544     if (son.getDots() == "..") son = son.withFrame();
545 
546     // store the group. insersion avoids duplication of the item
547     fileSet_group.insert(son);
548   }
549 
550   groupFpSet.insert(groupFpSet.end(), fileSet_group.begin(),
551                     fileSet_group.end());
552   allFpSet.insert(allFpSet.end(), fileSet_all.begin(), fileSet_all.end());
553 }
554 
555 //------------------------------------------------------------
556 
readDirectory(TFilePathSet & dst,const QDir & dir,bool groupFrames)557 void TSystem::readDirectory(TFilePathSet &dst, const QDir &dir,
558                             bool groupFrames) {
559   if (!(dir.exists() && QFileInfo(dir.path()).isDir()))
560     throw TSystemException(TFilePath(dir.path().toStdWString()),
561                            " is not a directory");
562   QStringList entries;
563 #ifdef _WIN32
564   WIN32_FIND_DATA find_dir_data;
565   QString dir_search_path = dir.absolutePath() + "\\*";
566   QDir::Filters filter    = dir.filter();
567 
568   // store name filters
569   bool hasNameFilter = false;
570   QList<QRegExp> nameFilters;
571   for (const QString &nameFilter : dir.nameFilters()) {
572     if (nameFilter == "*") {
573       hasNameFilter = false;
574       break;
575     }
576     QRegExp regExp(nameFilter);
577     regExp.setPatternSyntax(QRegExp::Wildcard);
578     nameFilters.append(regExp);
579     hasNameFilter = true;
580   }
581 
582   auto addEntry = [&]() {
583     // QDir::NoDotAndDotDot condition
584     if (wcscmp(find_dir_data.cFileName, L".") != 0 &&
585         wcscmp(find_dir_data.cFileName, L"..") != 0) {
586       // QDir::Files condition
587       if ((filter & QDir::Files) == 0 &&
588           (find_dir_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
589         return;
590       // QDir::Dirs condition
591       if ((filter & QDir::Dirs) == 0 &&
592           (find_dir_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
593         return;
594       // QDir::Hidden condition
595       if ((filter & QDir::Hidden) == 0 &&
596           (find_dir_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
597         return;
598 
599       QString fileName = QString::fromWCharArray(find_dir_data.cFileName);
600 
601       // name filter
602       if (hasNameFilter) {
603         bool matched = false;
604         for (const QRegExp &regExp : nameFilters) {
605           if (regExp.exactMatch(fileName)) {
606             matched = true;
607             break;
608           }
609         }
610         if (!matched) return;
611       }
612 
613       entries.append(fileName);
614     }
615   };
616   HANDLE hFind =
617       FindFirstFile((const wchar_t *)dir_search_path.utf16(), &find_dir_data);
618   if (hFind != INVALID_HANDLE_VALUE) {
619     addEntry();
620     while (FindNextFile(hFind, &find_dir_data)) addEntry();
621   }
622 #else
623   entries    = (dir.entryList(dir.filter() | QDir::NoDotAndDotDot));
624 #endif
625 
626   TFilePath dirPath(dir.path().toStdWString());
627 
628   std::set<TFilePath, CaselessFilepathLess> fpSet;
629 
630   int e, eCount = entries.size();
631   for (e = 0; e != eCount; ++e) {
632     TFilePath path(dirPath + TFilePath(entries.at(e).toStdWString()));
633 
634     if (groupFrames && path.getDots() == "..") path = path.withFrame();
635 
636     fpSet.insert(path);
637   }
638 
639   dst.insert(dst.end(), fpSet.begin(), fpSet.end());
640 }
641 
642 //------------------------------------------------------------
643 
readDirectory(TFilePathSet & dst,const TFilePath & path,bool groupFrames,bool onlyFiles,bool getHiddenFiles)644 void TSystem::readDirectory(TFilePathSet &dst, const TFilePath &path,
645                             bool groupFrames, bool onlyFiles,
646                             bool getHiddenFiles) {
647   QDir dir(toQString(path));
648 
649   QDir::Filters filters(QDir::Files);
650   if (!onlyFiles) filters |= QDir::Dirs;
651   if (getHiddenFiles) filters |= QDir::Hidden;
652   dir.setFilter(filters);
653 
654   readDirectory(dst, dir, groupFrames);
655 }
656 
657 //------------------------------------------------------------
658 
readDirectory(TFilePathSet & dst,const TFilePathSet & pathSet,bool groupFrames,bool onlyFiles,bool getHiddenFiles)659 void TSystem::readDirectory(TFilePathSet &dst, const TFilePathSet &pathSet,
660                             bool groupFrames, bool onlyFiles,
661                             bool getHiddenFiles) {
662   for (TFilePathSet::const_iterator it = pathSet.begin(); it != pathSet.end();
663        it++)
664     readDirectory(dst, *it, groupFrames, onlyFiles);
665 }
666 
667 //------------------------------------------------------------
668 
readDirectory(const TFilePath & path,bool groupFrames,bool onlyFiles,bool getHiddenFiles)669 TFilePathSet TSystem::readDirectory(const TFilePath &path, bool groupFrames,
670                                     bool onlyFiles, bool getHiddenFiles) {
671   TFilePathSet filePathSet;
672   readDirectory(filePathSet, path, groupFrames, onlyFiles, getHiddenFiles);
673   return filePathSet;
674 }
675 
676 //------------------------------------------------------------
677 
readDirectory(const TFilePathSet & pathSet,bool groupFrames,bool onlyFiles,bool getHiddenFiles)678 TFilePathSet TSystem::readDirectory(const TFilePathSet &pathSet,
679                                     bool groupFrames, bool onlyFiles,
680                                     bool getHiddenFiles) {
681   TFilePathSet dst;
682   readDirectory(dst, pathSet, groupFrames, onlyFiles, getHiddenFiles);
683   return dst;
684 }
685 
686 //------------------------------------------------------------
687 
readDirectoryTree(TFilePathSet & dst,const TFilePath & path,bool groupFrames,bool onlyFiles)688 void TSystem::readDirectoryTree(TFilePathSet &dst, const TFilePath &path,
689                                 bool groupFrames, bool onlyFiles) {
690   if (!TFileStatus(path).isDirectory())
691     throw TSystemException(path, " is not a directory");
692 
693   QFileInfoList fil = QDir(toQString(path)).entryInfoList();
694   int i;
695   for (i = 0; i < fil.size(); i++) {
696     QFileInfo fi = fil.at(i);
697     if (fi.fileName() == QString(".") || fi.fileName() == QString(".."))
698       continue;
699     TFilePath son = TFilePath(fi.filePath().toStdWString());
700     if (TFileStatus(son).isDirectory()) {
701       if (!onlyFiles) dst.push_back(son);
702       readDirectoryTree(dst, son, groupFrames, onlyFiles);
703     } else
704       dst.push_back(son);
705   }
706 }
707 
708 //------------------------------------------------------------
709 
readDirectoryTree(TFilePathSet & dst,const TFilePathSet & pathSet,bool groupFrames,bool onlyFiles)710 void TSystem::readDirectoryTree(TFilePathSet &dst, const TFilePathSet &pathSet,
711                                 bool groupFrames, bool onlyFiles) {
712   for (TFilePathSet::const_iterator it = pathSet.begin(); it != pathSet.end();
713        it++)
714     readDirectoryTree(dst, *it, groupFrames, onlyFiles);
715 }
716 
717 //------------------------------------------------------------
718 
readDirectoryTree(const TFilePath & path,bool groupFrames,bool onlyFiles)719 TFilePathSet TSystem::readDirectoryTree(const TFilePath &path, bool groupFrames,
720                                         bool onlyFiles) {
721   TFilePathSet dst;
722   readDirectoryTree(dst, path, groupFrames, onlyFiles);
723   return dst;
724 }
725 
726 //------------------------------------------------------------
727 
readDirectoryTree(const TFilePathSet & pathSet,bool groupFrames,bool onlyFiles)728 TFilePathSet TSystem::readDirectoryTree(const TFilePathSet &pathSet,
729                                         bool groupFrames, bool onlyFiles) {
730   TFilePathSet dst;
731   readDirectoryTree(dst, pathSet, groupFrames, onlyFiles);
732   return dst;
733 }
734 
735 //------------------------------------------------------------
736 
packLevelNames(const TFilePathSet & fps)737 TFilePathSet TSystem::packLevelNames(const TFilePathSet &fps) {
738   std::set<TFilePath> tmpSet;
739   TFilePathSet::const_iterator cit;
740   for (cit = fps.begin(); cit != fps.end(); ++cit)
741     tmpSet.insert(cit->getParentDir() + cit->getLevelName());
742 
743   TFilePathSet fps2;
744   for (std::set<TFilePath>::const_iterator c_sit = tmpSet.begin();
745        c_sit != tmpSet.end(); ++c_sit) {
746     fps2.push_back(*c_sit);
747   }
748   return fps2;
749 }
750 
751 //------------------------------------------------------------
752 
getDisks()753 TFilePathSet TSystem::getDisks() {
754   TFilePathSet filePathSet;
755   QFileInfoList fil = QDir::drives();
756   int i;
757   for (i = 0; i < fil.size(); i++)
758     filePathSet.push_back(TFilePath(fil.at(i).filePath().toStdWString()));
759 
760   return filePathSet;
761 }
762 
763 //------------------------------------------------------------
764 
765 class LocalThread final : public QThread {
766 public:
currentThread()767   static LocalThread *currentThread() {
768     return (LocalThread *)QThread::currentThread();
769   }
sleep(TINT64 delay)770   void sleep(TINT64 delay) { msleep(delay); }
771 };
772 
sleep(TINT64 delay)773 void TSystem::sleep(TINT64 delay) {
774   LocalThread::currentThread()->sleep(delay);
775 }
776 
777 //--------------------------------------------------------------
778 
getProcessorCount()779 int TSystem::getProcessorCount() { return QThread::idealThreadCount(); }
780 
781 //--------------------------------------------------------------
782 
doesExistFileOrLevel(const TFilePath & fp)783 bool TSystem::doesExistFileOrLevel(const TFilePath &fp) {
784   if (TFileStatus(fp).doesExist()) return true;
785 
786   if (fp.isLevelName()) {
787     const TFilePath &parentDir = fp.getParentDir();
788     if (!TFileStatus(parentDir).doesExist()) return false;
789 
790     TFilePathSet files;
791     try {
792       files = TSystem::readDirectory(parentDir, false, true, true);
793     } catch (...) {
794     }
795 
796     TFilePathSet::iterator it, end = files.end();
797     for (it = files.begin(); it != end; ++it) {
798       if (it->getLevelNameW() == fp.getLevelNameW()) return true;
799     }
800   } else if (fp.getType() == "psd") {
801     QString name(QString::fromStdWString(fp.getWideName()));
802     name.append(QString::fromStdString(fp.getDottedType()));
803 
804     int sepPos                               = name.indexOf("#");
805     int dotPos                               = name.indexOf(".", sepPos);
806     int removeChars                          = dotPos - sepPos;
807     int doubleUnderscorePos                  = name.indexOf("__", sepPos);
808     if (doubleUnderscorePos > 0) removeChars = doubleUnderscorePos - sepPos;
809 
810     name.remove(sepPos, removeChars);
811 
812     TFilePath psdpath(fp.getParentDir() + TFilePath(name.toStdWString()));
813     if (TFileStatus(psdpath).doesExist()) return true;
814   }
815 
816   return false;
817 }
818 
819 //--------------------------------------------------------------
820 
copyFileOrLevel_throw(const TFilePath & dst,const TFilePath & src)821 void TSystem::copyFileOrLevel_throw(const TFilePath &dst,
822                                     const TFilePath &src) {
823   if (src.isLevelName()) {
824     TFilePathSet files;
825     files = TSystem::readDirectory(src.getParentDir(), false);
826 
827     TFilePathSet::iterator it, end = files.end();
828     for (it = files.begin(); it != end; ++it) {
829       if (it->getLevelNameW() == src.getLevelNameW()) {
830         TFilePath src1 = *it;
831         TFilePath dst1 = dst.withFrame(it->getFrame());
832 
833         TSystem::copyFile(dst1, src1);
834       }
835     }
836   } else
837     TSystem::copyFile(dst, src);
838 }
839 
840 //--------------------------------------------------------------
841 
renameFileOrLevel_throw(const TFilePath & dst,const TFilePath & src,bool renamePalette)842 void TSystem::renameFileOrLevel_throw(const TFilePath &dst,
843                                       const TFilePath &src,
844                                       bool renamePalette) {
845   if (renamePalette && ((src.getType() == "tlv") || (src.getType() == "tzp") ||
846                         (src.getType() == "tzu"))) {
847     // Special case: since renames cannot be 'grouped' in the UI, palettes are
848     // automatically
849     // renamed here if required
850     const char *type = (src.getType() == "tlv") ? "tpl" : "plt";
851 
852     TFilePath srcpltname(src.withNoFrame().withType(type));
853     TFilePath dstpltname(dst.withNoFrame().withType(type));
854 
855     if (TSystem::doesExistFileOrLevel(src) &&
856         TSystem::doesExistFileOrLevel(srcpltname))
857       TSystem::renameFile(dstpltname, srcpltname, false);
858   }
859 
860   if (src.isLevelName()) {
861     TFilePathSet files;
862     files = TSystem::readDirectory(src.getParentDir(), false);
863 
864     for (TFilePathSet::iterator it = files.begin(); it != files.end(); it++) {
865       if (it->getLevelName() == src.getLevelName()) {
866         TFilePath src1 = *it;
867         TFilePath dst1 = dst.withFrame(it->getFrame());
868 
869         TSystem::renameFile(dst1, src1);
870       }
871     }
872   } else
873     TSystem::renameFile(dst, src);
874 }
875 
876 //--------------------------------------------------------------
877 
removeFileOrLevel_throw(const TFilePath & fp)878 void TSystem::removeFileOrLevel_throw(const TFilePath &fp) {
879   if (fp.isLevelName()) {
880     TFilePathSet files;
881     files = TSystem::readDirectory(fp.getParentDir(), false, true, true);
882 
883     TFilePathSet::iterator it, end = files.end();
884     for (it = files.begin(); it != end; ++it) {
885       if (it->getLevelName() == fp.getLevelName()) TSystem::deleteFile(*it);
886     }
887   } else
888     TSystem::deleteFile(fp);
889 }
890 
891 //--------------------------------------------------------------
892 
hideFileOrLevel_throw(const TFilePath & fp)893 void TSystem::hideFileOrLevel_throw(const TFilePath &fp) {
894   if (fp.isLevelName()) {
895     TFilePathSet files;
896     files = TSystem::readDirectory(fp.getParentDir(), false);
897 
898     TFilePathSet::iterator it, end = files.end();
899     for (it = files.begin(); it != end; ++it) {
900       if (it->getLevelNameW() == fp.getLevelNameW()) TSystem::hideFile(*it);
901     }
902   } else
903     TSystem::hideFile(fp);
904 }
905 
906 //--------------------------------------------------------------
907 
moveFileOrLevelToRecycleBin_throw(const TFilePath & fp)908 void TSystem::moveFileOrLevelToRecycleBin_throw(const TFilePath &fp) {
909   if (fp.isLevelName()) {
910     TFilePathSet files;
911     files = TSystem::readDirectory(fp.getParentDir(), false, true, true);
912 
913     TFilePathSet::iterator it, end = files.end();
914     for (it = files.begin(); it != end; ++it) {
915       if (it->getLevelNameW() == fp.getLevelNameW())
916         TSystem::moveFileToRecycleBin(*it);
917     }
918   } else
919     TSystem::moveFileToRecycleBin(fp);
920 }
921 
922 //--------------------------------------------------------------
923 
copyFileOrLevel(const TFilePath & dst,const TFilePath & src)924 bool TSystem::copyFileOrLevel(const TFilePath &dst, const TFilePath &src) {
925   try {
926     copyFileOrLevel_throw(dst, src);
927   } catch (...) {
928     return false;
929   }
930   return true;
931 }
932 
933 //--------------------------------------------------------------
934 
renameFileOrLevel(const TFilePath & dst,const TFilePath & src,bool renamePalette)935 bool TSystem::renameFileOrLevel(const TFilePath &dst, const TFilePath &src,
936                                 bool renamePalette) {
937   try {
938     renameFileOrLevel_throw(dst, src, renamePalette);
939   } catch (...) {
940     return false;
941   }
942   return true;
943 }
944 
945 //--------------------------------------------------------------
946 
removeFileOrLevel(const TFilePath & fp)947 bool TSystem::removeFileOrLevel(const TFilePath &fp) {
948   try {
949     removeFileOrLevel_throw(fp);
950   } catch (...) {
951     return false;
952   }
953   return true;
954 }
955 
956 //--------------------------------------------------------------
957 
hideFileOrLevel(const TFilePath & fp)958 bool TSystem::hideFileOrLevel(const TFilePath &fp) {
959   try {
960     hideFileOrLevel_throw(fp);
961   } catch (...) {
962     return false;
963   }
964   return true;
965 }
966 
967 //--------------------------------------------------------------
968 
moveFileOrLevelToRecycleBin(const TFilePath & fp)969 bool TSystem::moveFileOrLevelToRecycleBin(const TFilePath &fp) {
970   try {
971     moveFileOrLevelToRecycleBin_throw(fp);
972   } catch (...) {
973     return false;
974   }
975   return true;
976 }
977 
978 //--------------------------------------------------------------
979 
touchParentDir(const TFilePath & fp)980 bool TSystem::touchParentDir(const TFilePath &fp) {
981   TFilePath parentDir = fp.getParentDir();
982   TFileStatus fs(parentDir);
983   if (fs.isDirectory())
984     return true;
985   else if (fs.doesExist())
986     return false;
987   try {
988     mkDir(parentDir);
989   } catch (...) {
990     return false;
991   }
992   return true;
993 }
994 
995 //--------------------------------------------------------------
996 
showDocument(const TFilePath & path)997 bool TSystem::showDocument(const TFilePath &path) {
998 #ifdef _WIN32
999   int ret = (int)ShellExecuteW(0, L"open", path.getWideString().c_str(), 0, 0,
1000                                SW_SHOWNORMAL);
1001   if (ret <= 32) {
1002     return false;
1003     throw TSystemException(path, "Can't open");
1004   }
1005   return true;
1006 #else
1007   string cmd = "open ";
1008   string thePath(::to_string(path));
1009   UINT pos = 0, count = 0;
1010   // string newPath;
1011   char newPath[2048];
1012 
1013   while (pos < thePath.size()) {
1014     char c                         = thePath[pos];
1015     if (c == ' ') newPath[count++] = '\\';
1016 
1017     newPath[count++] = c;
1018     ++pos;
1019   }
1020   newPath[count] = 0;
1021 
1022   cmd = cmd + string(newPath);
1023   system(cmd.c_str());
1024   return true;
1025 #endif
1026 }
1027 
1028 #else
1029 
1030 #include <windows.h>
1031 
sleep(TINT64 delay)1032 void TSystem::sleep(TINT64 delay) { Sleep((DWORD)delay); }
1033 
1034 // gestire gli errori con GetLastError?
deleteFile(const TFilePath & fp)1035 void TSystem::deleteFile(const TFilePath &fp) { assert(false); }
1036 
rmDirTree(const TFilePath & path)1037 void TSystem::rmDirTree(const TFilePath &path) { assert(false); }
1038 
1039 //------------------------------------------------------------
1040 
1041 //------------------------------------------------------------
1042 
1043 #endif  // TNZCORE_LIGHT
1044 
1045 //--------------------------------------------------------------
1046 
TSystemException(const TFilePath & fname,int err)1047 TSystemException::TSystemException(const TFilePath &fname, int err)
1048     : m_fname(fname)
1049     , m_err(err)
1050     , m_msg(L"")
1051 
1052 {}
1053 
1054 //--------------------------------------------------------------
1055 
TSystemException(const TFilePath & fname,const std::string & msg)1056 TSystemException::TSystemException(const TFilePath &fname,
1057                                    const std::string &msg)
1058     : m_fname(fname), m_err(-1), m_msg(::to_wstring(msg)) {}
1059 //--------------------------------------------------------------
1060 
TSystemException(const TFilePath & fname,const wstring & msg)1061 TSystemException::TSystemException(const TFilePath &fname, const wstring &msg)
1062     : m_fname(fname), m_err(-1), m_msg(msg) {}
1063 
1064 //--------------------------------------------------------------
1065 
TSystemException(const std::string & msg)1066 TSystemException::TSystemException(const std::string &msg)
1067     : m_fname(""), m_err(-1), m_msg(::to_wstring(msg)) {}
1068 //--------------------------------------------------------------
1069 
TSystemException(const wstring & msg)1070 TSystemException::TSystemException(const wstring &msg)
1071     : m_fname(""), m_err(-1), m_msg(msg) {}
1072