// То же самое что и pushFatDataToDisk, только в нужную директорию void Attach::pushFatDataToDirectory(QString dirName) { if(getField("type")!="file") criticalError("Can't save to directory "+dirName+" non-file attach."); if(liteFlag==true) criticalError("Can't save to directory lite attach. Attach id: "+getField("id")+" File name: "+getField("fileName")); QMap<QString, QByteArray> fileList; fileList[ getInnerFileName() ]=fileContent; DiskHelper::saveFilesToDirectory(dirName, fileList); }
void Attach::pushFatDataToDisk() { if(getField("type")!="file") criticalError("Can't push fat data for non-file attach."); if(liteFlag==true) criticalError("Can't push fat data for lite attach. Attach id: "+getField("id")+" File name: "+getField("fileName")); QString innerFileName=getInnerFileName(); QString innerDirName=parentTable->record->getFullDirName(); QMap<QString, QByteArray> fileList; fileList[innerFileName]=fileContent; DiskHelper::saveFilesToDirectory(innerDirName, fileList); }
void AppConfig::set_addnewrecord_expand_info(QString state) { if(state=="0" || state=="1") conf->setValue("addnewrecord_expand_info",state); else criticalError("Set unavailable value for addnewrecord_expand_info "+state); }
// Расшифровка аттача на диске и в памяти void Attach::decrypt(unsigned int area) { // Если аттач не зашифрован, и происходит расшифровка, значит есть какая-то ошибка в логике выше if(getField("crypt")!="1") criticalError("Attach::decrypt() : Cant decrypt unencrypted attach."); // Расшифровывается файл if(area & areaFile) if(getField("type")=="file") CryptService::decryptFile(globalParameters.getCryptKey(), getFullInnerFileName()); // Расшифровывается содержимое файла в памяти, если таковое есть if(area & areaMemory) if(liteFlag==false && fileContent.length()>0) fileContent=CryptService::decryptByteArray(globalParameters.getCryptKey(), fileContent); // Расшифровываются поля, которые подлежат шифрованию foreach( QString fieldName, fieldCryptedList() ) { // У аттача с типом file не должно быть обращений к полю link (оно не должно использоваться) if(getField("type")=="file" && fieldName=="link") continue; // Если поле с указанным именем существует и содержит данные, оно расшифровывается из исходных зашифрованных данных if(getField(fieldName).length()>0) setFieldSource(fieldName, CryptService::decryptString( globalParameters.getCryptKey(), fields[fieldName])); } // Устанавливается флаг, что запись не зашифрована setField("crypt", ""); // Отсутсвие значения предпочтительней, так как тогда в XML-данные не будет попадать атрибут crypt="0" }
void AppConfig::set_howpassrequest(QString mode) { if(mode=="atClickOnCryptBranch" || mode=="atStartProgram") conf->setValue("howpassrequest", mode); else criticalError("Set unavailable value for howpassrequest "+mode); }
// Получение значения поля // Метод возвращает расшифрованные данные, если запись была зашифрована QString Attach::getField(QString name) const { // Если имя поля недопустимо if(fieldAvailableList().contains(name)==false) criticalError("Attach::getField() : get unavailable field "+name); // ------------------------------------------ // Проверки и действия для разных типов полей // ------------------------------------------ // Если запрашивается линк на файл if(name=="link") if(fields["type"]!="link") // И тип аттача не является линком criticalError("Attach::getField() : Can't get link from non-link attach."); // ----------------------- // Получение значения поля // ----------------------- // Если запись зашифрована, но ключ не установлен (т.е. человек не вводил пароль) // то расшифровка невозможна if(fieldCryptedList().contains(name)) if(fields.contains("crypt")) if(fields["crypt"]=="1") if(globalParameters.getCryptKey().length()==0) return QString(); bool isCrypt=false; // Если имя поля принадлежит списку полей, которые могут шифроваться // и в наборе полей есть поле crypt // и поле crypt установлено в 1 // и запрашиваемое поле не пустое (пустые данные невозможно расшифровать) if(fieldCryptedList().contains(name)) if(fields.contains("crypt")) if(fields["crypt"]=="1") if(fields[name].length()>0) isCrypt=true; // Если поле не подлежит шифрованию if(isCrypt==false) return fields[name]; // Возвращается значение поля else return CryptService::decryptString(globalParameters.getCryptKey(), fields[name]); // Поле расшифровывается }
void Attach::switchToFat() { // Переключение возможно только из легкого состояния if(liteFlag!=true) criticalError("Unavailable switching attach object to fat state. Attach Id: "+getField("id")+" File name: "+getField("fileName")); liteFlag=false; }
// Получение параметра по имени в виде строки с проверкой его существования QString AppConfig::get_parameter(QString name) { if(conf->contains(name)) return conf->value(name).toString(); else criticalError("In config not found parameter " + name); return QString(); }
// Защищенный метод - Установка значения поля напрямую // Используеся при шифрации-дешифрации данных аттача // todo: подумать, может быть отказаться от этого метода void Attach::setFieldSource(QString name, QString value) { // Если имя поля недопустимо if(fieldAvailableList().contains(name)==false) criticalError("Attach::setField() : set unavailable field "+name); // Устанавливается значение поля fields.insert(name, value); }
// Конструктор прикрепляемого файла с указанием типа прикрепления // в настоящий момент есть два типа прикрепления - просто файл "file" или линк на файл "link" Attach::Attach(QString iType, AttachTableData *iParentTable) { if( !typeAvailableList().contains(iType) ) criticalError("Incorrect attach type in Attach constructor: "+iType); setField("type", iType); init(iParentTable); }
//IDENT_MPTR_RAW * BetterString_$_toLower_$_(IDENT_MPTR_RAW * b) //{ // int result = btolower(b); // if (result==BSTR_OK) { // return (BetterString * ) b; // } else { // criticalError(ERROR_RuntimeError,"Error in BetterString_$_toLower_$_"); // } //} // //IDENT_MPTR_RAW * BetterString_$_toUpper_$_(IDENT_MPTR_RAW * b) //{ // int result = btoupper(b); // if (result==BSTR_OK) { // return (BetterString * ) b; // } else { // criticalError(ERROR_RuntimeError,"Error in BetterString_$_toUpper_$_"); // } //} // void BetterString_$_destructor_$_(IDENT_MPTR_RAW * b_) { BetterString * b = (BetterString *) b_->obj; int result = bdestroy((BetterString * )b); if (result==BSTR_OK) { //Do nothing? } else { criticalError(ERROR_RuntimeError,"Error in BetterString_$_destructor_$_"); } }
void Attach::switchToLite() { // Переключение возможно только из полновесного состояния if(liteFlag==true) criticalError("Can't switch attach to lite state. Attach id: "+getField("id")+" File name: "+getField("fileName")); fileContent.clear(); liteFlag=true; }
// Метод предполагает, что разбиваются // либо набор вертикально объединенных суперячеек // когда разбивка по горизонтали уже была осуществлена (при этом x1<x2) // либо одна суперячейка с объединением по вертикали // когда разбивки по горизонтали небыло (при этом x1=x2) void EditorAbsTable::split_merged_cell_by_vertical(int x1, int x2, int y) { qDebug() << "Split merged cell ("<<x1<<","<<y<<")-("<<x2<<","<<y<<") by vertical"; print_internal_table(); // Проверка, можно ли разбивать ячейки for(int x=x1; x<=x2; x++) { if(!(cells[x][y].get_cell_type()==EditorAbsTableCell::IS_SUPER_CELL && cells[x][y].get_html_property("rowspan").toInt()>=2)) criticalError("Cell ("+QString::number(x)+","+QString::number(y)+") can not split by vertical, this is not supercell with rowspan>2"); } for(int x=x1; x<=x2; x++) if(cells[x][y].get_cell_type()==EditorAbsTableCell::IS_SUPER_CELL) { // На сколько частей по вертикали можно разбить эту ячейку int div=cells[x][y].get_html_property("rowspan").toInt(); qDebug() << "Split cell to"<<div<<"by vertical"; // Сколько ячек эта суперячейка объединяет по горизонтали int colSpan=cells[x][y].get_html_property("colspan").toInt(); qDebug() << "This cell merge by horisontal"<<colSpan<<"cells"; // Если суперячейка объединяла только вертикальные ячейки if(colSpan<2) { // Все ячейки превращаются в обычную ячейку for(int i=y; i<=(y+div-1); i++) { cells[x][i].set_cell_type(EditorAbsTableCell::IS_NORMAL_CELL); cells[x][i].set_html_property("colspan","0"); cells[x][i].set_html_property("rowspan","0"); cells[x][i].set_ref_super_cell_xy(0,0); } } else { // Иначе суперячейка объединяла ячейки и по вертикали // Все "левые" ячейки превращаются в суперячейки с нужным colspan for(int i=y; i<=(y+div-1); i++) { cells[x][i].set_cell_type(EditorAbsTableCell::IS_SUPER_CELL); cells[x][i].set_html_property("rowspan","0"); cells[x][i].set_html_property("colspan",QString::number(colSpan)); cells[x][i].set_ref_super_cell_xy(0,0); // А все "правые" уже являются подчиненными ячейками, // и им только корректируются ссылки на суперячейку for(int j=(x+1); j<=(x+colSpan-1); j++) cells[j][i].set_ref_super_cell_xy(x,i); } } // Закрылось условие объединяла ли суперячейка только горизонтальные ячейки } // Закрылся цикл перебора суперячеек слева направо qDebug() << "Internal table after split by horisontal"; print_internal_table(); }
void insertNode(valType id, char nome[], list *lList) { pos p; p = (struct Node *) malloc(sizeof(struct Node)); if (p == NULL) criticalError("There is no space!"); p->id = id; strcpy(p->nome, nome); p->next = *lList; *lList = p; }
// Втаскивание в объект содержимого файла с диска void Attach::popFatDataFromDisk() { // Втаскивание возможно только в полновесном состоянии if(liteFlag==true) criticalError("Can't' pop data for lite attach. Attach id: "+getField("id")+" File name: "+getField("fileName")); fileContent.clear(); QString innerFileName=getInnerFileName(); QString innerDirName=parentTable->record->getFullDirName(); fileContent.append( (DiskHelper::getFilesFromDirectory(innerDirName, innerFileName)).value(innerFileName) ); }
ShellChannel::ReadReply ShellChannel::readUntil(const QByteArray& marker) { ReadReply result; result.readAgain = false; // Check if the buffer is already loaded and ready to go. int markerIndex = mReadBuffer.indexOf(marker); if (markerIndex == -1) { // Actually do the read int rc = libssh2_channel_read(mHandle, mScratchBuffer, SSH_SHELL_BUFFER_SIZE); if (rc > 0) mReadBuffer.append(mScratchBuffer, rc); else if (rc == LIBSSH2_ERROR_EAGAIN) { result.readAgain = true; return result; } else if (rc == 0) { if (libssh2_channel_eof(mHandle)) criticalError("Connection closed unexpectedly"); } else criticalError("Failed to read from host"); // Check again to see if the buffer is ready to go. markerIndex = mReadBuffer.indexOf(marker); } // If there's data ready to go, pack it into the reply. if (markerIndex > -1) { result.data = mReadBuffer.left(markerIndex); mReadBuffer = mReadBuffer.right(mReadBuffer.size() - (markerIndex + marker.length())); } return result; }
void CryptService::encDecFileSmart(QByteArray key, QString fileName, int mode) { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); QFile file(fileName); if(!file.open(QIODevice::ReadOnly)) criticalError("encDecFileSmart() : Cant open binary file "+fileName+" for reading."); vector<unsigned char> vectorKey; convertByteArrayToVector(key, vectorKey); vector<unsigned char> vectorDataIn; convertByteArrayToVector(file.readAll(), vectorDataIn); vector<unsigned char> vectorDataOut; file.close(); // Шифрация / дешифрация RC5Simple rc5; rc5.RC5_SetKey(vectorKey); if(mode==0) rc5.RC5_Encrypt(vectorDataIn, vectorDataOut); else rc5.RC5_Decrypt(vectorDataIn, vectorDataOut); QByteArray result; convertVectorToByteArray(vectorDataOut, result); if(!file.open(QIODevice::WriteOnly)) criticalError("encryptFile() : Cant open binary file "+fileName+" for write."); file.write(result); QApplication::restoreOverrideCursor(); }
// Внутрисистемное имя файла с путем QString Attach::getFullInnerFileName() const { if(getField("type")=="file") { // Для файла QString resultFileName=getFullInnerDirName()+"/"+getInnerFileName(); return resultFileName; } if(getField("type")=="link") // Для линка return getField("link"); criticalError("Bad attach type in getFullInnerFileName():"+getField("type")); return ""; }
ShellChannel::SendResponse ShellChannel::sendData(const QByteArray &data) { int rc = libssh2_channel_write(mHandle, data, data.length()); if (rc < 0) { if (rc == -1) rc = libssh2_session_last_errno(mSession->sessionHandle()); if (rc == LIBSSH2_ERROR_EAGAIN) return SendAgain; criticalError(tr("Failed to initialize send a slave request: %1").arg(rc)); return SendFail; } return SendSucceed; }
ShellChannel::ReadReply XferChannel::readBinaryData( int size ) { ReadReply reply; reply.readAgain = false; if ( size <= 0 ) { return reply; } while ( mBinaryReadBuffer.length() < size ) { // Flush anything from the read buffer into the binary buffer int transferred = Tools::unbin( mBinaryReadBuffer, mReadBuffer, size, mReadBuffer.length(), &mLeftoverEscape ); mReadBuffer = mReadBuffer.right( mReadBuffer.size() - transferred ); if ( mBinaryReadBuffer.length() == size ) { break; } // See if there's data waiting to be read, push it into the read buffer (raw) int rc = libssh2_channel_read( mHandle, mScratchBuffer, SSH_SHELL_BUFFER_SIZE ); if ( rc > 0 ) { mReadBuffer.append( mScratchBuffer, rc ); } else if ( rc == LIBSSH2_ERROR_EAGAIN || ( rc == -1 && libssh2_session_last_errno( mSession->sessionHandle() ) == LIBSSH2_ERROR_EAGAIN ) ) { reply.readAgain = true; return reply; } else { criticalError( "Connection closed unexpectedly!" ); } int currentLength = mBinaryReadBuffer.length(); int percent = ( int ) ( ( ( float ) currentLength / size ) * 100 ); mCurrentRequest->handleProgress( percent ); } // If it reaches here, enough data has been read. reply.data = mBinaryReadBuffer; mBinaryReadBuffer.clear(); return reply; }
// Внутрисистемное имя файла (без пути) // Внутрисистемное имя складывается из идентификатора аттача и расширения, взятого от имени файла QString Attach::getInnerFileName() const { if(getField("type")=="file") { // Для файла // Выясняется расширение по видимому имени файла QFileInfo fileInfo( getField("fileName") ); QString suffix=fileInfo.suffix(); QString innerFileName=getField("id")+"."+suffix; return innerFileName; } if(getField("type")=="link") // Для линка просто возвращается имя файла, куда указывает линк return getField("fileName"); criticalError("Bad attach type in getInnerFileName():"+getField("type")); return ""; }
void AppConfig::init(void) { // Создается имя файла конфигурации QString configFileName=globalParameters.getWorkDirectory()+"/conf.ini"; // Проверяется, есть ли файл конфигурации QFile confFile(configFileName); if(!confFile.exists()) criticalError("File "+configFileName+" not found."); // Создается указатель на объект хранилища конфигурации conf=new QSettings(configFileName, QSettings::IniFormat); update_version_process(); sync(); is_init_flag=true; }
int EditorAbsTable::get_cell_col_or_row_span(int x, int y, QString propName) { if(cells[x][y].get_cell_type()==EditorAbsTableCell::IS_NULL_CELL) criticalError("Detect bad table structure"); if(cells[x][y].get_cell_type()==EditorAbsTableCell::IS_NORMAL_CELL) return 1; if(cells[x][y].get_cell_type()==EditorAbsTableCell::IS_SUPER_CELL) return cells[x][y].get_html_property(propName).toInt(); if(cells[x][y].get_cell_type()==EditorAbsTableCell::IS_SUB_CELL) { int x_super=cells[x][y].get_ref_super_cell_x(); int y_super=cells[x][y].get_ref_super_cell_y(); return cells[x_super][y_super].get_html_property(propName).toInt(); } return 0; }
int TrDo::qt_metacall(QMetaObject::Call _c, int _id, void **_a) { _id = QObject::qt_metacall(_c, _id, _a); if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod) { switch (_id) { case 0: criticalError(); break; case 1: tracerouteFinished(); break; case 2: childStarted(); break; case 3: childFinished((*reinterpret_cast< int(*)>(_a[1])),(*reinterpret_cast< QProcess::ExitStatus(*)>(_a[2]))); break; case 4: childError((*reinterpret_cast< QProcess::ProcessError(*)>(_a[1]))); break; case 5: cancel(); break; case 6: cancel((*reinterpret_cast< int(*)>(_a[1]))); break; default: ; } _id -= 7; } return _id; }
bool SFTPChannel::handleOpening() { mHandle = libssh2_sftp_init(mSession->sessionHandle()); if (mHandle == NULL) { int rc = libssh2_session_last_errno(mSession->sessionHandle()); if (rc == LIBSSH2_ERROR_EAGAIN) return true; else { if (rc == LIBSSH2_ERROR_CHANNEL_FAILURE) // Reassign this channel elsewhere setSession(NULL); else criticalError(tr("Failed to open a channel %1: %2").arg((unsigned long)mHandle, 0, 16).arg(rc)); return false; } } setStatus(Open); return true; }
// Шифрация аттача на диске и в памяти void Attach::encrypt(unsigned int area) { // В этом методе важна последовательность действий, // чтобы не получилась ситуации, когда часть данных зашифрована, // а другая пытается их использовать, а флаг шифрации еще не установлен // Если аттач уже зашифрован, значит есть какая-то ошибка в логике выше if(getField("crypt")=="1") criticalError("Attach::encrypt() : Cant encrypt already encrypted attach."); // Шифруется файл if(area & areaFile) if(getField("type")=="file") CryptService::encryptFile(globalParameters.getCryptKey(), getFullInnerFileName()); // Шифруется содержимое файла в памяти, если таковое есть if(area & areaMemory) if(liteFlag==false && fileContent.length()>0) fileContent=CryptService::encryptByteArray(globalParameters.getCryptKey(), fileContent); // Шифруются поля, которые подлежат шифрованию foreach( QString fieldName, fieldCryptedList() ) { // У аттача с типом file не должно быть обращений к полю link (оно не должно использоваться) if(getField("type")=="file" && fieldName=="link") continue; // Если поле с указанным именем существует if(getField(fieldName).length()>0) setFieldSource(fieldName, CryptService::encryptString( globalParameters.getCryptKey(), getField(fieldName))); } // Устанавливается флаг, что запись зашифрована setField("crypt", "1"); }
bool XferChannel::mainUpdate() { if (mInternalStatus == _WaitingForRequests) { mCurrentRequest = mHost->getNextXferRequest(mSudo); if (mCurrentRequest == NULL) return false; else { mInternalStatus = _SendingRequestHeader; return true; } } if (mInternalStatus == _SendingRequestHeader) { // If uploading, make sure the data to be uploaded is encoded. if (mCurrentRequest->isUploadRequest() && mCurrentRequest->getEncodedData().isEmpty()) mCurrentRequest->setEncodedData(Tools::bin(mCurrentRequest->getData())); SendResponse r = sendData(mCurrentRequest->getRequestHeader()); if (r != SendSucceed) return (r == SendAgain); mInternalStatus = (mCurrentRequest->isUploadRequest() ? _WaitingForReady : _ReadingDownloadHeader); } if (mInternalStatus == _ReadingDownloadHeader) { ReadReply r = readUntil("\n"); if (r.readAgain) return false; if (r.data.isEmpty()) throw(tr("Invalid response to download header")); if (r.data.startsWith("Error: ")) { if(r.data.contains("File not found")) { mCurrentRequest->handleFailure(QString(mCurrentRequest->getFilename()) + " - " + tr("File not found"), 0); mInternalStatus = _WaitingForRequests; return true; } else { throw(QString(r.data)); } } if (r.data.endsWith('\r')) { SSHLOG_WARN(mHost) << "Warning: Stray carriage-return after xfer header"; r.data.chop(1); } QList<QByteArray> parts = r.data.split(','); mCurrentRequest->setDataSize(parts[0].toInt()); mCurrentRequest->setChecksum(parts[1]); mLeftoverEscape = false; mInternalStatus = _DownloadingBody; } if (mInternalStatus == _DownloadingBody) { ReadReply r = readBinaryData(mCurrentRequest->getDataSize()); if (r.readAgain) return false; // Check the checksum. QCryptographicHash hash(QCryptographicHash::Md5); hash.addData(r.data); QByteArray checksum = hash.result().toHex().toLower(); if (checksum != mCurrentRequest->getChecksum()) mCurrentRequest->handleFailure(tr("Checksum failure: %1 vs %2").arg(QString(checksum)).arg(QString(mCurrentRequest->getChecksum())), 0); else { mCurrentRequest->setData(r.data); mCurrentRequest->handleSuccess(); } mInternalStatus = _WaitingForOk; } if (mInternalStatus == _WaitingForReady) { ReadReply r = readUntil("\n"); if (r.readAgain) return true; if (r.data != "Ready") criticalError("Failed to upload file"); mInternalStatus = _UploadingBody; } if (mInternalStatus == _UploadingBody) { QByteArray encoded = mCurrentRequest->getEncodedData(); SendResponse r = sendData(encoded); if (r != SendSucceed) return (r == SendAgain); mCurrentRequest->handleSuccess(); mInternalStatus = _WaitingForOk; } if (mInternalStatus == _WaitingForOk) { ReadReply r = readUntil("\n"); if (r.readAgain) return true; if (r.data.endsWith('\r')) { SSHLOG_WARN(mHost) << "Warning: Stray carriage-return after xfer OK"; r.data.chop(1); } if (r.data != "OK") criticalError("Did not receive OK at the end of transmission. Got: " + r.data); mInternalStatus = _WaitingForRequests; return true; } return false; }
/* * Main. NO COMPLETO. */ int main(int argc, char *argv[]) { int sockfd; // Socket de escucha int newsockfd; // Socket de nueva conexion struct sockaddr_in clientAddr, serverAddr; // Direcciones de Internet socklen_t socklen = sizeof(clientAddr); // Tamano de dir de cliente int portNum = DEFAULT_PORT; // Puerto del servidor char *inRoomName; Room initialRoom; pthread_t pthreadStruct; // Contenedor Dummy threadStruct *threadArg; // Apuntador del arg del hilp int status; // Estatus de crear hilo // Setear argumentos svOptionHandler(argc,argv,&portNum,&inRoomName); // Creacion de socket if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { criticalError(SV_SOCKET); } // Anclaje de socket bzero((void *) &serverAddr, sizeof(serverAddr)); serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = INADDR_ANY; serverAddr.sin_port = htons(portNum); if (bind(sockfd,(void *)&serverAddr,sizeof(serverAddr)) < 0) { criticalError(SV_BIND); } // Colocar el socket en modo escucha if (listen(sockfd, NUM_CONNECTIONS) < 0) { criticalError(SV_LISTEN); } // Inicializar las listas de salas y usuarios (con la sala inicial) list_new(&Rooms,sizeof(Room)); list_new(&Users,sizeof(User)); strncpy(initialRoom.name,inRoomName,NAMES_SIZE); *(initialRoom.name + NAMES_SIZE - 1) = '\0'; list_new(&(initialRoom.users),sizeof(User *)); list_append(&Rooms,&initialRoom); while (1) { // Aceptar una conexion if ((newsockfd = accept(sockfd,(struct sockaddr *) &clientAddr, &socklen)) < 0) { criticalError(SV_ACCEPT); } // Crear el thread que maneje la conexion con el cliente en especifico threadArg = malloc(sizeof(threadStruct)); // El thread libera threadArg->sockfd = newsockfd; status = pthread_create(&pthreadStruct, NULL, &clientHandler, (void *) threadArg); if (status != 0) { criticalError(69); } } return 0; }
bool SFTPChannel::updateWriteFile() { int rc; if (mRequestState == Beginning) { QByteArray path = mCurrentRequest->getPath().toUtf8(); mOperationHandle = libssh2_sftp_open_ex(mHandle, path, path.length(), LIBSSH2_FXF_WRITE | LIBSSH2_FXF_TRUNC | LIBSSH2_FXF_CREAT, 0644, LIBSSH2_SFTP_OPENFILE); if (mOperationHandle) mRequestState = Writing; else if ((rc = libssh2_session_last_errno(mSession->sessionHandle())) == LIBSSH2_ERROR_EAGAIN) return true; // try again else { criticalError(tr("Failed to open remote file for writing: %1").arg(rc)); return false; } mOperationCursor = 0; } if (mRequestState == Writing) { const QByteArray& content = mCurrentRequest->getContent(); rc = libssh2_sftp_write(mOperationHandle, content.constData() + mOperationCursor, content.length() - mOperationCursor); if (rc == LIBSSH2_ERROR_EAGAIN) return true; // Try again else if (rc < 0) { criticalError(tr("Error while writing file contents: %1").arg(rc)); return false; } else // Wrote some data { mOperationCursor += rc; mCurrentRequest->triggerProgress((mOperationCursor * 100) / content.length()); } if (mOperationCursor >= content.length()) mRequestState = Finishing; } if (mRequestState == Finishing) { rc = libssh2_sftp_close_handle(mOperationHandle); if (rc == LIBSSH2_ERROR_EAGAIN) return true; else if (rc < 0) { criticalError(tr("Failed to cleanly close SFTP file: %1").arg(rc)); return false; } // Success! Send a response and finish up. QVariantMap finalResult; finalResult.insert("revision", mCurrentRequest->getRevision()); finalResult.insert("undoLength", mCurrentRequest->getUndoLength()); finalResult.insert("checksum", BaseFile::getChecksum(mCurrentRequest->getContent())); mCurrentRequest->triggerSuccess(finalResult); return false; } return true; }
bool SFTPChannel::updateReadFile() { int rc; if (mRequestState == Beginning) { QByteArray path = mCurrentRequest->getPath().toUtf8(); mOperationHandle = libssh2_sftp_open_ex(mHandle, path, path.length(), LIBSSH2_FXF_READ, 0, LIBSSH2_SFTP_OPENFILE); if (mOperationHandle) mRequestState = Sizing; else if ((rc = libssh2_session_last_errno(mSession->sessionHandle())) == LIBSSH2_ERROR_EAGAIN) return true; // try again else { criticalError(tr("Failed to open remote file for reading: %1").arg(rc)); return false; } } if (mRequestState == Sizing) { LIBSSH2_SFTP_ATTRIBUTES attr; int rc = libssh2_sftp_fstat_ex(mOperationHandle, &attr, 0); if (rc == LIBSSH2_ERROR_EAGAIN) return true; else if (rc < 0) { criticalError(tr("Failed to stat remote file: %1").arg(rc)); return false; } mOperationSize = attr.filesize; if (mOperationSize == 0) mOperationSize = 1; mRequestState = Reading; } if (mRequestState == Reading) { char buffer[4096]; rc = libssh2_sftp_read(mOperationHandle, buffer, sizeof(buffer)); if (rc == LIBSSH2_ERROR_EAGAIN) return true; // Try again else if (rc == 0) mRequestState = Finishing; else if (rc < 0) { criticalError(tr("Error while reading file contents: %1").arg(rc)); return false; } else // Got some data { mCurrentRequest->addContent(buffer, rc); mCurrentRequest->triggerProgress((mCurrentRequest->getContent().length() * 100) / mOperationSize); } } if (mRequestState == Finishing) { rc = libssh2_sftp_close_handle(mOperationHandle); if (rc == LIBSSH2_ERROR_EAGAIN) return true; else if (rc < 0) { criticalError(tr("Failed to cleanly close SFTP file: %1").arg(rc)); return false; } // Success! Send a response and finish up. QVariantMap finalResult; finalResult.insert("content", mCurrentRequest->getContent()); mCurrentRequest->triggerSuccess(finalResult); return false; } return true; }