8 #include <QWriteLocker>
35 QMap<int, FileTransfer*>::iterator i;
38 if ((*i)->GetSocket() == socket)
51 QMap<QString, SocketHandler*>::iterator i;
54 if ((*i)->GetSocket() == socket)
65 const QString &wantgroup)
67 QString lpath = QString(path);
69 if (lpath.section(
'/', -2, -2) ==
"channels")
72 QString
file = lpath.section(
'/', -1);
76 query.
prepare(
"SELECT icon FROM channel "
77 "WHERE icon LIKE :FILENAME ;");
82 lpath = query.
value(0).toString();
91 lpath = lpath.section(
'/', -1);
93 QString fpath = lpath;
94 if (fpath.endsWith(
".png"))
95 fpath = fpath.left(fpath.length() - 4);
101 if (pburl.startsWith(
"/"))
103 lpath = pburl.section(
'/', 0, -2) +
"/" + lpath;
104 LOG(VB_FILE, LOG_INFO,
105 QString(
"Local file path: %1").arg(lpath));
109 LOG(VB_GENERAL, LOG_ERR,
110 QString(
"LocalFilePath unable to find local "
111 "path for '%1', found '%2' instead.")
116 else if (!lpath.isEmpty())
119 QString opath = lpath;
122 if (!wantgroup.isEmpty())
124 sgroup.
Init(wantgroup);
125 lpath = QString(path);
129 lpath = QFileInfo(lpath).fileName();
132 QString tmpFile = sgroup.
FindFile(lpath);
133 if (!tmpFile.isEmpty())
136 LOG(VB_FILE, LOG_INFO,
137 QString(
"LocalFilePath(%1 '%2'), found through "
138 "exhaustive search at '%3'")
139 .arg(path, opath, lpath));
143 LOG(VB_GENERAL, LOG_ERR, QString(
"LocalFilePath unable to "
144 "find local path for '%1'.")
175 QStringList &commands, QStringList &slist)
177 if (commands[1] ==
"FileServer")
179 if (slist.size() >= 3)
183 handler->BlockShutdown(
true);
184 handler->AllowStandardEvents(
true);
185 handler->AllowSystemEvents(
true);
187 handler->WriteStringList(QStringList(
"OK"));
190 m_fsMap.insert(commands[2], handler);
200 if (commands[1] !=
"FileTransfer")
203 if (slist.size() < 3)
206 if ((commands.size() < 3) || (commands.size() > 6))
212 bool writemode =
false;
213 bool usereadahead =
true;
214 std::chrono::milliseconds
timeout = 2s;
215 switch (commands.size())
218 timeout = std::chrono::milliseconds(commands[5].toInt());
221 usereadahead = (commands[4].toInt() != 0);
224 writemode = (commands[3].toInt() != 0);
230 QStringList::const_iterator it = slist.cbegin();
231 QString path = *(++it);
232 QString wantgroup = *(++it);
234 QStringList checkfiles;
235 while (++it != slist.cend())
240 LOG(VB_GENERAL, LOG_DEBUG,
"FileServerHandler::HandleAnnounce");
241 LOG(VB_GENERAL, LOG_INFO, QString(
"adding: %1 as remote file transfer")
246 if (wantgroup.isEmpty())
247 wantgroup =
"Default";
253 LOG(VB_GENERAL, LOG_ERR,
"Unable to determine directory "
254 "to write to in FileTransfer write command");
256 slist <<
"ERROR" <<
"filetransfer_directory_not_found";
263 LOG(VB_GENERAL, LOG_ERR, QString(
"FileTransfer write "
264 "filename is empty in path '%1'.")
267 slist <<
"ERROR" <<
"filetransfer_filename_empty";
272 if ((path.contains(
"/../")) ||
273 (path.startsWith(
"../")))
275 LOG(VB_GENERAL, LOG_ERR, QString(
"FileTransfer write "
276 "filename '%1' does not pass sanity checks.")
279 slist <<
"ERROR" <<
"filetransfer_filename_dangerous";
292 LOG(VB_GENERAL, LOG_ERR, QString(
"FileTransfer filename "
293 "'%1' is actually a directory, cannot transfer.")
296 slist <<
"ERROR" <<
"filetransfer_filename_is_a_directory";
303 QString dirPath = finfo.absolutePath();
307 if (!qdir.mkpath(dirPath))
309 LOG(VB_GENERAL, LOG_ERR, QString(
"FileTransfer "
310 "filename '%1' is in a subdirectory which does "
311 "not exist, but can not be created.")
314 slist <<
"ERROR" <<
"filetransfer_unable_to_create_subdirectory";
336 if (!checkfiles.empty())
339 QDir dir = fi.absoluteDir();
340 for (
const auto &
file : qAsConst(checkfiles))
342 if (dir.exists(
file) &&
356 QStringList &commands, QStringList &slist)
358 if (commands[1] ==
"SlaveBackend")
362 if (slist.size() >= 3)
365 if (handler ==
nullptr)
369 m_fsMap.insert(commands[2], handler);
378 bool handled =
false;
379 QString command = commands[0];
381 if (command ==
"QUERY_FILETRANSFER")
383 else if (command ==
"QUERY_FREE_SPACE")
385 else if (command ==
"QUERY_FREE_SPACE_LIST")
387 else if (command ==
"QUERY_FREE_SPACE_SUMMARY")
389 else if (command ==
"QUERY_CHECKFILE")
391 else if (command ==
"QUERY_FILE_EXISTS")
393 else if (command ==
"QUERY_FILE_HASH")
395 else if (command ==
"DELETE_FILE")
397 else if (command ==
"QUERY_SG_GETFILELIST")
399 else if (command ==
"QUERY_SG_FILEQUERY")
401 else if (command ==
"DOWNLOAD_FILE" || command ==
"DOWNLOAD_FILE_NOW")
411 for (
const auto & disk : qAsConst(disks))
412 disk.ToStringList(res);
424 for (
const auto & disk : qAsConst(disks))
425 if (!hosts.contains(disk.getHostname()))
426 hosts << disk.getHostname();
433 for (
const auto & disk : qAsConst(disks))
435 disk.ToStringList(res);
436 total += disk.getTotalSpace();
437 used += disk.getUsedSpace();
440 res << hosts.join(
",")
446 << QString::number(total)
447 << QString::number(used);
462 for (
const auto & disk : qAsConst(disks))
464 total += disk.getTotalSpace();
465 used += disk.getUsedSpace();
468 res << QString::number(total) << QString::number(used);
476 groups.removeAll(
"LiveTV");
477 QString specialGroups = groups.join(
"', '");
480 query.
prepare(QString(
"SELECT MIN(id),dirname "
482 "WHERE hostname = :HOSTNAME "
483 "AND groupname NOT IN ( '%1' ) "
484 "GROUP BY dirname;").arg(specialGroups));
487 QList<FileSystemInfo> disks;
492 query.
prepare(
"SELECT MIN(id),dirname "
494 "WHERE groupname = :GROUP "
495 "GROUP BY dirname;");
504 QMap <QString, bool>foundDirs;
517 currentDir = QString::fromUtf8(query.
value(1)
518 .toByteArray().constData());
521 if (currentDir.endsWith(
"/"))
522 currentDir.remove(currentDir.length() - 1, 1);
524 checkDir.setPath(currentDir);
525 if (!foundDirs.contains(currentDir))
527 if (checkDir.exists())
533 foundDirs[currentDir] =
true;
536 foundDirs[currentDir] =
false;
551 QMap<QString, SocketHandler*>::iterator i;
567 QStringList::const_iterator it = slist.cbegin() + 2;
576 exists = QFileInfo::exists(pburl);
581 QStringList res(QString::number(
static_cast<int>(exists)));
595 QString storageGroup =
"Default";
598 if (slist.size() == 3)
600 if (!slist[2].isEmpty())
601 storageGroup = slist[2];
603 else if (slist.size() != 2)
611 LOG(VB_GENERAL, LOG_ERR,
612 QString(
"ERROR checking for file, filename '%1' "
613 "fails sanity checks").arg(
filename));
622 if (!fullname.isEmpty())
628 struct stat fileinfo {};
629 if (stat(fullname.toLocal8Bit().constData(), &fileinfo) >= 0)
631 res << QString::number(fileinfo.st_dev)
632 << QString::number(fileinfo.st_ino)
633 << QString::number(fileinfo.st_mode)
634 << QString::number(fileinfo.st_nlink)
635 << QString::number(fileinfo.st_uid)
636 << QString::number(fileinfo.st_gid)
637 << QString::number(fileinfo.st_rdev)
638 << QString::number(fileinfo.st_size)
643 << QString::number(fileinfo.st_blksize)
644 << QString::number(fileinfo.st_blocks)
646 << QString::number(fileinfo.st_atime)
647 << QString::number(fileinfo.st_mtime)
648 << QString::number(fileinfo.st_ctime);
665 QString storageGroup =
"Default";
670 switch (slist.size()) {
672 if (!slist[3].isEmpty())
676 if (!slist[2].isEmpty())
677 storageGroup = slist[2];
685 LOG(VB_GENERAL, LOG_ERR,
686 QString(
"ERROR checking for file, filename '%1' "
687 "fails sanity checks").arg(
filename));
730 if (slist.size() != 3)
742 const QString&
filename,
const QString& storagegroup)
751 LOG(VB_GENERAL, LOG_ERR,
752 QString(
"ERROR deleting file, filename '%1' fails sanity checks")
765 if (fullfile.isEmpty())
767 LOG(VB_GENERAL, LOG_ERR,
768 QString(
"Unable to find %1 in HandleDeleteFile()") .arg(
filename));
778 QFile checkFile(fullfile);
779 if (checkFile.exists())
791 LOG(VB_GENERAL, LOG_ERR, QString(
"Error deleting file: '%1'")
814 bool fileNamesOnly =
false;
815 if (slist.size() == 5)
816 fileNamesOnly = (slist[4].toInt() != 0);
817 else if (slist.size() != 4)
819 LOG(VB_GENERAL, LOG_ERR, QString(
"Invalid Request. %1")
820 .arg(slist.join(
"[]:[]")));
827 QString wantHost = slist[1];
828 QString groupname = slist[2];
829 QString path = slist[3];
831 LOG(VB_FILE, LOG_INFO,
832 QString(
"HandleSGGetFileList: group = %1 host = %2 "
833 "path = %3 wanthost = %4")
834 .arg(groupname, host, path, wantHost));
839 LOG(VB_FILE, LOG_INFO,
"Getting local info");
845 if (res.count() == 0)
854 if (
m_fsMap.contains(wantHost))
863 LOG(VB_FILE, LOG_INFO,
"Getting remote info");
864 res <<
"QUERY_SG_GETFILELIST" << wantHost << groupname << path
865 << QString::number(
static_cast<int>(fileNamesOnly));
871 LOG(VB_FILE, LOG_ERR, QString(
"Failed to grab slave socket : %1 :")
873 res <<
"SLAVE UNREACHABLE: " << wantHost;
886 if (slist.size() != 4)
888 LOG(VB_GENERAL, LOG_ERR, QString(
"Invalid Request. %1")
889 .arg(slist.join(
"[]:[]")));
895 QString wantHost = slist[1];
896 QString groupname = slist[2];
899 LOG(VB_FILE, LOG_DEBUG, QString(
"HandleSGFileQuery: myth://%1@%2/%3")
900 .arg(groupname, wantHost,
filename));
905 LOG(VB_FILE, LOG_DEBUG, QString(
"Getting local info"));
909 if (res.count() == 0)
918 if (
m_fsMap.contains(wantHost))
927 res <<
"QUERY_SG_FILEQUERY" << wantHost << groupname <<
filename;
933 res <<
"SLAVE UNREACHABLE: " << wantHost;
942 QStringList &commands, QStringList &slist)
944 if (commands.size() != 2)
947 if (slist.size() < 2)
951 int recnum = commands[1].toInt();
958 if (slist[1] ==
"DONE")
962 LOG(VB_GENERAL, LOG_ERR,
963 QString(
"Unknown file transfer socket: %1").arg(recnum));
965 <<
"unknown_file_transfer_socket";
976 if (slist[1] ==
"REQUEST_BLOCK")
978 if (slist.size() != 3)
980 LOG(VB_GENERAL, LOG_ERR,
"Invalid QUERY_FILETRANSFER "
981 "REQUEST_BLOCK call");
982 res <<
"ERROR" <<
"invalid_call";
986 int size = slist[2].toInt();
990 else if (slist[1] ==
"WRITE_BLOCK")
992 if (slist.size() != 3)
994 LOG(VB_GENERAL, LOG_ERR,
"Invalid QUERY_FILETRANSFER "
996 res <<
"ERROR" <<
"invalid_call";
1000 int size = slist[2].toInt();
1001 res << QString::number(ft->
WriteBlock(size));
1004 else if (slist[1] ==
"SEEK")
1006 if (slist.size() != 5)
1008 LOG(VB_GENERAL, LOG_ERR,
"Invalid QUERY_FILETRANSFER SEEK call");
1009 res <<
"ERROR" <<
"invalid_call";
1013 long long pos = slist[2].toLongLong();
1014 int whence = slist[3].toInt();
1015 long long curpos = slist[4].toLongLong();
1017 res << QString::number(ft->
Seek(curpos, pos, whence));
1020 else if (slist[1] ==
"IS_OPEN")
1022 res << QString::number(static_cast<int>(ft->
isOpen()));
1024 else if (slist[1] ==
"DONE")
1029 else if (slist[1] ==
"SET_TIMEOUT")
1031 if (slist.size() != 3)
1033 LOG(VB_GENERAL, LOG_ERR,
"Invalid QUERY_FILETRANSFER "
1034 "SET_TIMEOUT call");
1035 res <<
"ERROR" <<
"invalid_call";
1039 bool fast = slist[2].toInt() != 0;
1044 else if (slist[1] ==
"REQUEST_SIZE")
1052 LOG(VB_GENERAL, LOG_ERR,
"Invalid QUERY_FILETRANSFER call");
1053 res <<
"ERROR" <<
"invalid_call";
1066 if (slist.size() != 4)
1068 res <<
"ERROR" << QString(
"Bad %1 command").arg(slist[0]);
1073 bool synchronous = (slist[0] ==
"DOWNLOAD_FILE_NOW");
1074 QString srcURL = slist[1];
1075 QString storageGroup = slist[2];
1083 QFileInfo finfo(srcURL);
1087 if (outDir.isEmpty())
1089 LOG(VB_GENERAL, LOG_ERR, QString(
"Unable to determine directory "
1090 "to write to in %1 write command").arg(slist[0]));
1091 res <<
"ERROR" <<
"downloadfile_directory_not_found";
1099 LOG(VB_GENERAL, LOG_ERR, QString(
"ERROR: %1 write "
1100 "filename '%2' does not pass sanity checks.")
1102 res <<
"ERROR" <<
"downloadfile_filename_dangerous";