/*! \file pifiletransfer.h * \ingroup IO * \~\brief * \~english Class for send and receive files and directories via \a PIBaseTransfer * \~russian Класс для отправки и приема файлов и папок с помощью \a PIBaseTransfer */ /* PIP - Platform Independent Primitives Class for send and receive files and directories via PIBaseTransfer Andrey Bychkov work.a.b@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef PIFILETRANSFER_H #define PIFILETRANSFER_H #include "pibasetransfer.h" #include "pidir.h" #define __PIFILETRANSFER_VERSION 2 //! \~english Class for send and receive files and directories via \a PIBaseTransfer //! \~russian Класс для отправки и приема файлов и папок с помощью \a PIBaseTransfer class PIP_EXPORT PIFileTransfer: public PIBaseTransfer { PIOBJECT_SUBCLASS(PIFileTransfer, PIBaseTransfer); public: //! \~english Constructs empty file transfer //! \~russian Создает пустой transfer файлов PIFileTransfer(); //! \~english Destructor //! \~russian Деструктор ~PIFileTransfer(); //! \~english Step type for file transfer //! \~russian Тип шага для передачи файлов enum StepType { pft_None, pft_Description, pft_Data }; //! \~english File information structure //! \~russian Структура информации о файле struct PIP_EXPORT PFTFileInfo: public PIFile::FileInfo { //! \~english Constructor //! \~russian Конструктор PFTFileInfo(const PIFile::FileInfo & fi = PIFile::FileInfo()): PIFile::FileInfo(fi) {} PIString dest_path; }; #pragma pack(push, 1) //! \~english File transfer header structure //! \~russian Структура заголовка передачи файлов struct PIP_EXPORT PFTHeader { union { struct { char sig[3]; // PFT uchar version; }; uint raw_sig; }; int step; // PacketType int session_id; //! \~english Check if signature is valid //! \~russian Проверка валидности подписи bool check_sig() { if (sig[0] != sign[0] || sig[1] != sign[1] || sig[2] != sign[2] || version != __PIFILETRANSFER_VERSION) return false; return true; } }; #pragma pack(pop) //! \~english Send file //! \~russian Отправить файл bool send(const PIFile & file); //! \~english Send file by path //! \~russian Отправить файл по пути bool send(const PIString & file); //! \~english Send files list //! \~russian Отправить список файлов bool send(const PIStringList & files); //! \~english Send file info //! \~russian Отправить информацию о файле bool send(PIFile::FileInfo entry) { return send(PIVector() << entry); } //! \~english Send file info vector //! \~russian Отправить вектор информации о файлах bool send(PIVector entries); //! \~english Set directory //! \~russian Установить директорию void setDirectory(const PIDir & d) { dir = d; } //! \~english Set directory by path //! \~russian Установить директорию по пути void setDirectory(const PIString & path) { dir.setDir(path); } //! \~english Get directory //! \~russian Получить директорию PIDir directory() const { return dir; } //! \~english Check if transfer is started //! \~russian Проверить, начата ли передача bool isStarted() const { return started_; } //! \~english Get current file name //! \~russian Получить имя текущего файла PIString curFile() const; //! \~english Get total bytes of current file //! \~russian Получить общее количество байт текущего файла llong bytesFileAll() const { return bytes_file_all; } //! \~english Get current bytes of current file //! \~russian Получить текущие байты текущего файла llong bytesFileCur() const { return bytes_file_cur; } //! \~english Get pointer to current file name //! \~russian Получить указатель на имя текущего файла const PIString * curFile_ptr() const { return &cur_file_string; } //! \~english Get pointer to total bytes of current file //! \~russian Получить указатель на общее количество байт текущего файла const llong * bytesFileAll_ptr() const { return &bytes_file_all; } //! \~english Get pointer to current bytes of current file //! \~russian Получить указатель на текущие байты текущего файла const llong * bytesFileCur_ptr() const { return &bytes_file_cur; } EVENT(receiveFilesStarted); EVENT1(receiveFilesFinished, bool, ok); EVENT(sendFilesStarted); EVENT1(sendFilesFinished, bool, ok); EVENT3(receiveFilesRequest, PIStringList, files, llong, total_bytes, bool *, ok); private: static const char sign[]; PIVector files_; PIString cur_file_string; llong bytes_file_all, bytes_file_cur; PFTHeader pftheader; PIDir dir; PIFile work_file; PIByteArray desc; PIDir scan_dir; bool started_, scanning; PIMutex step_mutex; bool sendFiles(const PIVector & files); void processFile(int id, ullong start, PIByteArray & data); void receivePart(Part fi, PIByteArray ba, PIByteArray pheader) override; PIByteArray buildPacket(Part fi) override; PIByteArray customHeader() override; void beginReceive() override; EVENT_HANDLER1(void, send_finished, bool, ok); EVENT_HANDLER1(void, receive_finished, bool, ok); }; BINARY_STREAM_WRITE(PIFileTransfer::PFTHeader) { s << v.raw_sig << v.step << v.session_id; return s; } BINARY_STREAM_READ(PIFileTransfer::PFTHeader) { s >> v.raw_sig >> v.step >> v.session_id; return s; } BINARY_STREAM_WRITE(PIFileTransfer::PFTFileInfo) { s << v.dest_path << v.size << v.time_access << v.time_modification << v.flags << v.id_user << v.id_group << v.perm_user.raw << v.perm_group.raw << v.perm_other.raw; return s; } BINARY_STREAM_READ(PIFileTransfer::PFTFileInfo) { s >> v.dest_path >> v.size >> v.time_access >> v.time_modification >> v.flags >> v.id_user >> v.id_group >> v.perm_user.raw >> v.perm_group.raw >> v.perm_other.raw; return s; } inline PICout operator<<(PICout s, const PIFileTransfer::PFTFileInfo & v) { s.saveAndSetControls(0); s << "FileInfo(\"" << v.dest_path << "\", " << PIString::readableSize(v.size) << ", " << v.perm_user.toString() << " " << v.perm_group.toString() << " " << v.perm_other.toString() << ", " << v.time_access.toString() << ", " << v.time_modification.toString() << ", 0x" << PICoutManipulators::Hex << v.flags << ")"; s.restoreControls(); return s; } #endif // PIFILETRANSFER_H