#include "pifiletransfer.h" const char PIFileTransfer::sign[] = {'P', 'F', 'T'}; PIFileTransfer::PIFileTransfer() { for (uint i = 0; i < sizeof(sign); i++) pftheader.sig[i] = sign[i]; pftheader.version = __PIFILETRANSFER_VERSION; pftheader.session_id = 0; pftheader.step = pft_None; dir = PIDir::current(); started_ = scanning = false; bytes_file_all = bytes_file_cur = 0; // CONNECT(void, this, sendStarted, this, send_started); CONNECT(void, this, receiveStarted, this, receive_started); CONNECT1(void, bool, this, sendFinished, this, send_finished); CONNECT1(void, bool, this, receiveFinished, this, receive_finished); } PIFileTransfer::~PIFileTransfer() { stop(); work_file.close(); } bool PIFileTransfer::send(const PIFile& file) { return send(file.path()); } bool PIFileTransfer::send(const PIString & file) { return send(PIVector() << PIFile::fileInfo(file)); } bool PIFileTransfer::send(const PIStringList& files) { PIVector fil; piForeachC(PIString &file, files) fil << PIFile::fileInfo(file); return send(fil); } bool PIFileTransfer::send(PIVector entries) { started_ = true; PIVector allEntries; for (int i = 0; i < entries.size_s(); i++) { allEntries << PFTFileInfo(entries[i]); allEntries.back().dest_path = entries[i].name(); if (entries[i].isDir()) { cur_file_string = "scanning ... "; scan_dir.setDir(entries[i].path); scanning = true; PIVector fls = scan_dir.allEntries(); scanning = false; scan_dir.up(); //piCout << "files rel to" << d.absolutePath(); for (uint j = 0; j < fls.size(); j++) { allEntries << PFTFileInfo(fls[j]); allEntries.back().dest_path = scan_dir.relative(fls[j].path); //piCout << " abs path" << fls[j].path; //piCout << " rel path" << allEntries.back().dest_path; } } } return sendFiles(allEntries); } bool PIFileTransfer::sendFiles(const PIVector &files) { files_ = files; PIStringList names; // piCoutObj << "prepare to send" << files_.size() << "files"; for(int i=0; i() << Part(0, desc.size())); cur_file_string = ""; if (!send_process()) { sendFilesFinished(false); started_ = false; return false; } pftheader.step = pft_Data; PIVector pts; for (int i=0; i fi.size) { //piCoutObj << "error size" << work_file.size() << fi.size; work_file.clear(); work_file.resize(fi.size); //piCoutObj << "correct size" << work_file.size() << fi.size; } } //piCoutObj << "write file" << path << work_file.path() << work_file.size() << fi.entry.size << work_file.pos() << fi.fstart << fi.fsize; if (work_file.size() < (llong)start) { //piCoutObj << "error pos size" << work_file.pos() << fi.fstart; work_file.resize(start); //piCoutObj << "correct pos size" << work_file.pos() << fi.fstart; } if (work_file.size() > fi.size) { piCoutObj << "****** error size" << work_file.size() << fi.size; work_file.clear(); work_file.resize(fi.size); piCoutObj << "****** correct size" << work_file.size() << fi.size; } //if (fi.fstart != work_file.pos()) piCoutObj << "error pos" << work_file.pos() << fi.fstart; work_file.seek(start); int rs = work_file.write(data.data(), data.size()); if (rs != data.size_s()) { cur_file_string = "ERROR! while write file " + fi.path + " (must " + PIString::fromNumber(data.size()) + ", but write " + PIString::fromNumber(rs) + ")"; piCoutObj << cur_file_string; stopReceive(); return; } } } PIByteArray PIFileTransfer::buildPacket(Part p) { //piCoutObj << "Step" << pftheader.step; //piCoutObj << "session id" << pftheader.session_id; PIByteArray ba; switch(pftheader.step) { case pft_None: stopSend(); return PIByteArray(); case pft_Description: ba.resize(p.size); memcpy(ba.data(), desc.data(p.start), p.size); return ba; case pft_Data: // piCout << "send data" << p.id << files_.size(); PIFile::FileInfo fi = files_[p.id-1]; if (fi.isFile()) { // piCout << "send file" << fi.name() << fi.size; PIString path = fi.path; if (work_file.path() != path || !work_file.isOpened()) { if (!work_file.open(path, PIIODevice::ReadOnly)) { break_ = true; cur_file_string = "ERROR! while open file " + fi.path; piCoutObj << cur_file_string; stopSend(); return PIByteArray(); } } work_file.seek(p.start); ba.resize(p.size); int rs = work_file.read(ba.data(), ba.size()); if ((llong)rs != (llong)p.size) { break_ = true; cur_file_string = "ERROR! while read file " + fi.path + " (must " + PIString::fromNumber(p.size) + ", but read " + PIString::fromNumber(rs) + ")"; piCoutObj << cur_file_string; stopSend(); return PIByteArray(); } } // if (fi.isDir()) { // piCout << "create dir" << fi.path; // dir.make(fi.path); // } cur_file_string = fi.path; bytes_file_all = fi.size; bytes_file_cur = p.start; return ba; } return ba; } void PIFileTransfer::receivePart(PIBaseTransfer::Part fi, PIByteArray ba, PIByteArray pheader) { PFTHeader h; // piCout << pheader.size() << sizeof(PFTHeader); pheader >> h; // piCout << h.session_id; StepType st = (StepType)h.step; pftheader.step = st; if (!h.check_sig()) { cur_file_string = "ERROR check signature: File Transfer incompatable or invalid version!"; piCoutObj << cur_file_string; stopReceive(); return; } switch(st) { case pft_None: break; case pft_Description: pftheader.session_id = h.session_id; if (desc.size() < fi.start + fi.size) desc.resize(fi.start + fi.size); memcpy(desc.data(fi.start), ba.data(), ba.size_s()); break; case pft_Data: if (h.session_id == pftheader.session_id) processFile(fi.id, fi.start, ba); else stopReceive(); break; default: break; } } PIString PIFileTransfer::curFile() const { PIString s = cur_file_string; if (scanning) return s + scan_dir.scanDir(); return s; } PIByteArray PIFileTransfer::customHeader() { PIByteArray ba; ba << pftheader; return ba; } void PIFileTransfer::receive_started() { if (pftheader.step == pft_None) { files_.clear(); // piCoutObj << "start receive" started_ = true; receiveFilesStarted(); } } void PIFileTransfer::receive_finished(bool ok) { if (pftheader.step == pft_Description) { bool user_ok = true; if (ok) { // piCoutObj << desc.size() << PICoutManipulators::Hex << desc; desc >> files_; // piCoutObj << files_; PIStringList files; piForeachC(PFTFileInfo &fi, files_) files << fi.dest_path; pause(); receiveFilesRequest(files, bytesAll(), &user_ok); } if (!ok || !user_ok) { pftheader.session_id--; piCoutObj << "file cancel"; receiveFilesFinished(false); started_ = false; } else resume(); } if (pftheader.step == pft_Data) { //piCoutObj << "file close"; work_file.close(); receiveFilesFinished(ok); started_ = false; } } void PIFileTransfer::send_finished(bool ok) { // piCoutObj << "file close"; if (pftheader.step == pft_Data) { work_file.close(); } }