wxTreeListItem SFTPTreeView::DoAddFolder(const wxTreeListItem& parent, const wxString& path) { try { m_sftp->CreateDir(path); SFTPAttribute::Ptr_t attr = m_sftp->Stat(path); // Update the UI MyClientData* newCd = new MyClientData(path); newCd->SetIsFolder(true); newCd->SetInitialized(false); wxTreeListItem child = m_treeListCtrl->AppendItem( parent, newCd->GetFullName(), m_bmpLoader.GetMimeImageId(FileExtManager::TypeFolder), wxNOT_FOUND, newCd); if(IsTypeColumnShown()) { m_treeListCtrl->SetItemText(child, GetTypeColumnIndex(), attr->GetTypeAsString()); } if(IsSizeColumnShown()) { m_treeListCtrl->SetItemText(child, GetSizeColumnIndex(), wxString() << attr->GetSize()); } m_treeListCtrl->AppendItem(child, "<dummy>"); m_treeListCtrl->SetSortColumn(0); return child; } catch(clException& e) { ::wxMessageBox(e.What(), "SFTP", wxICON_ERROR | wxOK | wxCENTER); } return wxTreeListItem(); }
wxTreeListItem SFTPTreeView::DoAddFile(const wxTreeListItem& parent, const wxString& path) { try { m_sftp->Write("", path); SFTPAttribute::Ptr_t attr = m_sftp->Stat(path); // Update the UI MyClientData* newFile = new MyClientData(path); newFile->SetIsFolder(false); newFile->SetInitialized(false); wxTreeListItem child = m_treeListCtrl->AppendItem( parent, newFile->GetFullName(), m_bmpLoader.GetMimeImageId(FileExtManager::GetType(path, FileExtManager::TypeText)), wxNOT_FOUND, newFile); m_treeListCtrl->SetItemText(child, 1, attr->GetTypeAsString()); m_treeListCtrl->SetItemText(child, 2, wxString() << attr->GetSize()); m_treeListCtrl->SetSortColumn(0); return child; } catch(clException& e) { ::wxMessageBox(e.What(), "SFTP", wxICON_ERROR | wxOK | wxCENTER); } return wxTreeListItem(); }
bool SFTPTreeView::DoExpandItem(const wxTreeItemId& item) { MyClientData* cd = GetItemData(item); CHECK_PTR_RET_FALSE(cd); // already initialized this folder before? if(cd->IsInitialized()) { return true; } // get list of files and populate the tree SFTPAttribute::List_t attributes; try { attributes = m_sftp->List(cd->GetFullPath(), clSFTP::SFTP_BROWSE_FILES | clSFTP::SFTP_BROWSE_FOLDERS); } catch(clException& e) { ::wxMessageBox(e.What(), "SFTP", wxOK | wxICON_ERROR | wxCENTER, EventNotifier::Get()->TopFrame()); return false; } // Remove the dummy item and replace it with real items wxTreeItemIdValue cookie; wxTreeItemId dummyItem = m_treeCtrl->GetFirstChild(item, cookie); m_treeCtrl->Delete(dummyItem); cd->SetInitialized(true); int nNumOfRealChildren = 0; SFTPAttribute::List_t::iterator iter = attributes.begin(); for(; iter != attributes.end(); ++iter) { SFTPAttribute::Ptr_t attr = (*iter); if(attr->GetName() == "." || attr->GetName() == "..") continue; ++nNumOfRealChildren; // determine the icon index int imgIdx = wxNOT_FOUND; if(attr->IsFolder()) { imgIdx = m_bmpLoader->GetMimeImageId(FileExtManager::TypeFolder); } else { imgIdx = m_bmpLoader->GetMimeImageId(attr->GetName()); } if(imgIdx == wxNOT_FOUND) { imgIdx = m_bmpLoader->GetMimeImageId(FileExtManager::TypeText); } wxString path; path << cd->GetFullPath() << "/" << attr->GetName(); while(path.Replace("//", "/")) {} MyClientData* childClientData = new MyClientData(path); childClientData->SetIsFolder(attr->IsFolder()); wxTreeItemId child = m_treeCtrl->AppendItem(item, attr->GetName(), imgIdx, imgIdx, childClientData); // if its type folder, add a fake child item if(attr->IsFolder()) { m_treeCtrl->AppendItem(child, "<dummy>"); } } return nNumOfRealChildren > 0; }
void clSFTP::Read(const wxString& remotePath, wxMemoryBuffer& buffer) throw(clException) { if(!m_sftp) { throw clException("SFTP is not initialized"); } sftp_file file = sftp_open(m_sftp, remotePath.mb_str(wxConvUTF8).data(), O_RDONLY, 0); if(file == NULL) { throw clException(wxString() << _("Failed to open remote file: ") << remotePath << ". " << ssh_get_error(m_ssh->GetSession()), sftp_get_error(m_sftp)); } SFTPAttribute::Ptr_t fileAttr = Stat(remotePath); if(!fileAttr) { throw clException(wxString() << _("Could not stat file:") << remotePath << ". " << ssh_get_error(m_ssh->GetSession()), sftp_get_error(m_sftp)); } wxInt64 fileSize = fileAttr->GetSize(); if(fileSize == 0) return; // Allocate buffer for the file content char pBuffer[65536]; // buffer // Read the entire file content wxInt64 bytesLeft = fileSize; wxInt64 bytesRead = 0; while(bytesLeft > 0) { wxInt64 nbytes = sftp_read(file, pBuffer, sizeof(pBuffer)); bytesRead += nbytes; bytesLeft -= nbytes; buffer.AppendData(pBuffer, nbytes); } if(bytesRead != fileSize) { sftp_close(file); buffer.Clear(); throw clException(wxString() << _("Could not read file:") << remotePath << ". " << ssh_get_error(m_ssh->GetSession()), sftp_get_error(m_sftp)); } sftp_close(file); }
bool SFTPAttribute::Compare(SFTPAttribute::Ptr_t one, SFTPAttribute::Ptr_t two) { if ( one->IsFolder() && !two->IsFolder() ) { return true; } else if ( !one->IsFolder() && two->IsFolder() ) { return false; } else { return one->GetName() < two->GetName(); } }
void SFTPWorkerThread::ProcessRequest(ThreadRequest* request) { SFTPThreadRequet* req = dynamic_cast<SFTPThreadRequet*>(request); // Check if we need to open an ssh connection wxString currentAccout = m_sftp ? m_sftp->GetAccount() : ""; wxString requestAccount = req->GetAccount().GetAccountName(); if(currentAccout.IsEmpty() || currentAccout != requestAccount) { m_sftp.reset(NULL); DoConnect(req); } if(req->GetDirection() == SFTPThreadRequet::kConnect) { // Nothing more to be done here // Disconnect m_sftp.reset(NULL); return; } wxString msg; wxString accountName = req->GetAccount().GetAccountName(); if(m_sftp && m_sftp->IsConnected()) { try { msg.Clear(); if(req->GetDirection() == SFTPThreadRequet::kUpload) { DoReportStatusBarMessage(wxString() << _("Uploading file: ") << req->GetRemoteFile()); SFTPAttribute::Ptr_t attr(new SFTPAttribute(NULL)); attr->SetPermissions(req->GetPermissions()); m_sftp->CreateRemoteFile(req->GetRemoteFile(), wxFileName(req->GetLocalFile()), attr); msg << "Successfully uploaded file: " << req->GetLocalFile() << " -> " << req->GetRemoteFile(); DoReportMessage(accountName, msg, SFTPThreadMessage::STATUS_OK); DoReportStatusBarMessage(""); } else if(req->GetDirection() == SFTPThreadRequet::kDownload || req->GetDirection() == SFTPThreadRequet::kDownloadAndOpenContainingFolder || req->GetDirection() == SFTPThreadRequet::kDownloadAndOpenWithDefaultApp) { DoReportStatusBarMessage(wxString() << _("Downloading file: ") << req->GetRemoteFile()); wxMemoryBuffer buffer; SFTPAttribute::Ptr_t fileAttr = m_sftp->Read(req->GetRemoteFile(), buffer); wxFFile fp(req->GetLocalFile(), "w+b"); if(fp.IsOpened()) { fp.Write(buffer.GetData(), buffer.GetDataLen()); fp.Close(); } msg << "Successfully downloaded file: " << req->GetLocalFile() << " <- " << req->GetRemoteFile(); DoReportMessage(accountName, msg, SFTPThreadMessage::STATUS_OK); DoReportStatusBarMessage(""); // We should also notify the parent window about download completed if(req->GetDirection() == SFTPThreadRequet::kDownload) { SFTPClientData cd; cd.SetLocalPath(req->GetLocalFile()); cd.SetRemotePath(req->GetRemoteFile()); cd.SetPermissions(fileAttr ? fileAttr->GetPermissions() : 0); m_plugin->CallAfter(&SFTP::FileDownloadedSuccessfully, cd); } else if(req->GetDirection() == SFTPThreadRequet::kDownloadAndOpenContainingFolder) { m_plugin->CallAfter(&SFTP::OpenContainingFolder, req->GetLocalFile()); } else { m_plugin->CallAfter(&SFTP::OpenWithDefaultApp, req->GetLocalFile()); } } } catch(clException& e) { msg.Clear(); msg << "SFTP error: " << e.What(); DoReportMessage(accountName, msg, SFTPThreadMessage::STATUS_ERROR); DoReportStatusBarMessage(msg); m_sftp.reset(NULL); // Requeue our request if(req->GetRetryCounter() == 0) { msg.Clear(); msg << "Retrying to upload file: " << req->GetRemoteFile(); DoReportMessage(req->GetAccount().GetAccountName(), msg, SFTPThreadMessage::STATUS_NONE); // first time trying this request, requeue it SFTPThreadRequet* retryReq = static_cast<SFTPThreadRequet*>(req->Clone()); retryReq->SetRetryCounter(1); Add(retryReq); } } } }