bool ParzeLink( FSPath& path, FSString& link ) { FSPath t( link ); if ( !path.IsAbsolute() && !t.IsAbsolute() ) { return false; } //не абсолютный путь int first = 0; if ( t.IsAbsolute() ) { path.Clear(); path.PushStr( FSString( "" ) ); first = 1; } for ( int i = first; i < t.Count(); i++ ) { FSString p = *( t.GetItem( i ) ); if ( p.IsDot() ) { continue; } if ( p.Is2Dot() ) { if ( path.Count() > 1 ) { path.Pop(); } } else { path.PushStr( p ); } } return true; }
bool FSGetApplPath(FSString &applPath, bool withPS/* = true*/) { #if defined(WIN32) || defined(_WIN32_WCE) char Temp[_MAX_PATH+1]; ::GetModuleFileNameA(NULL, Temp, _MAX_PATH); applPath = Temp; STRIndex_t pos = applPath.FindRAt(PATH_SEPARATOR_CHAR); if ( STRING_FOUND(pos) ) applPath.Truncate( withPS ? pos + 1 : pos ); return true; #else UniString uniString; if ( FSGetApplPath(uniString, withPS) ) { applPath = uniString; } return false; #endif }
FSArchNode* ArchGetParentDir( FSArchNode* CurrDir, FSPath& ItemPath, const FSStat& ItemStat ) { for ( int i = 0; i < ItemPath.Count() - 1; i++ ) { FSString* Name = ItemPath.GetItem( i ); if ( i == 0 && ( Name->IsDot() || Name->IsEmpty() ) ) { // skip root dir continue; } FSArchNode* Dir = CurrDir->findByName( *Name ); if ( Dir == nullptr ) { FSStat Stat = ItemStat; Stat.mode = S_IFDIR; Stat.size = 0; Dir = CurrDir->Add( FSArchNode( Name->GetUtf8(), Stat ) ); } CurrDir = Dir; } return CurrDir; }
FSTmpNode* FSTmpNode::findByFsPath(FSPath* fsPath, int fsPathLevel) { FSString* curName = fsPath->GetItem(fsPathLevel); if (parentDir == 0 && fsPathLevel == fsPath->Count()-1 && (curName == 0 || curName->GetUnicode() == 0 || curName->GetUnicode()[0] == 0)) // request to find root node, and we are root return this; if (name.Cmp(*curName) == 0) { if (fsPath->Count() <= fsPathLevel) { // exact match return this; } else { FSString* childName = fsPath->GetItem(fsPathLevel + 1); FSTmpNode* n = findByName(childName, false); if (n == 0) return 0; if (fsPath->Count() <= fsPathLevel + 2) // no further recursion return n; else if (n->nodeType == NODE_DIR) // recurse into subdir return n->findByFsPath(fsPath, fsPathLevel + 1); else return 0; } } else return 0; }
FSString FSSys::StrError( int err ) { sys_char_t buf[1024]; FSString ret; ret.SetSys( sys_error_str( err, buf, 0x100 ) ); return ret; }
void FSPath::Copy( const FSPath& a ) { cacheCs = -2; data.clear(); for ( int i = 0 ; i < a.Count(); i++ ) { FSString s; s.Copy( a.data.const_item( i ) ); data.append( s ); } }
FSString FSWin32Net::StrError( int err ) { if ( err == ERRNOSUPPORT ) { return FSString( "Operation not supported by net fs" ); } FSString ret; sys_char_t buf[1024]; ret.SetSys( sys_error_str( err, buf, 0x100 ) ); return ret; }
static void stripPathFromLastItem(FSPath& path) { FSString* lastItem = path.GetItem(path.Count() - 1); if (lastItem) { const unicode_t* lastU = lastItem->GetUnicode(); const unicode_t* lastDelim = unicode_strrchr(lastU, DIR_SPLITTER); if (lastDelim != 0) { path.SetItemStr(path.Count() - 1,FSString(lastDelim + 1)); } } }
void FSPath::SetItemStr( int n, const FSString& str ) // n>=0 && n<=Count(); если n == Count то в конец добавляется еще один элемент { if ( n < 0 || n > Count() ) { return; } cacheCs = -2; //чтоб не сработал эффект cptr FSString s; s.Copy( str ); if ( n == Count() ) { data.append( s ); } else { data[n] = s; } }
void Clear() { executed = false; errorString.Clear(); srcList.clear(); pathChanged = false; // uint64_t infoCount = 0; infoSrcUri.Clear(); infoDstUri.Clear(); progressChanged = false; infoSize = 0; infoProgress = 0; }
void FSPath::Copy(const FSPath& a, int elementCount) { cacheCs = -2; data.clear(); if (elementCount<0 || elementCount>a.Count()) elementCount = a.Count(); for (int i = 0; i < elementCount; i++) { FSString s; s.Copy(a.data.const_item(i)); data.append(s); } }
FSArchNode* FSArchNode::findByName( const FSString& name, bool isRecursive ) { dbg_printf( "FSArchNodeDir::findByName name=%s\n", name.GetUtf8() ); // first, try all nodes in current for ( FSArchNode& n : content ) { dbg_printf( "FSArchNodeDir::findByName n.name=%s\n", n.name.GetUtf8() ); if ( n.name.Cmp( ( FSString& ) name ) == 0 ) { return &n; } } // only if not found in current dir, try inside subdirs if ( isRecursive ) { for ( FSArchNode& n : content ) { if ( n.IsDir() ) { FSArchNode* pn = n.findByName( name, isRecursive ); if ( pn ) { return pn; } } } } return nullptr; }
int FSString::Cmp( FSString& a ) { if ( !_primary.str() ) { return ( !a._primary.str() ) ? 0 : -1; } if ( !a._primary.str() ) { return 1; } return CmpStr<const unicode_t>( GetUnicode(), a.GetUnicode() ); }
FSArchNode* FSArchNode::findByFsPath( FSPath& fsPath, int fsPathLevel ) { FSString* curName = fsPath.GetItem( fsPathLevel ); if ( parentDir == nullptr && fsPathLevel == fsPath.Count() - 1 && ( curName == nullptr || curName->GetUnicode() == 0 || curName->GetUnicode()[0] == 0 ) ) { // request to find root node, and we are root return this; } if ( name.Cmp( *curName ) == 0 ) { if ( fsPath.Count() <= fsPathLevel ) { // exact match return this; } FSString* childName = fsPath.GetItem( fsPathLevel + 1 ); FSArchNode* n = findByName( *childName ); if ( n == nullptr ) { return nullptr; } if ( fsPath.Count() <= fsPathLevel + 2 ) { // no further recursion return n; } if ( n->IsDir() ) { // recurse into subdir return n->findByFsPath( fsPath, fsPathLevel + 1 ); } } return nullptr; }
int FSSys::Symlink( FSPath& path, FSString& str, int* err, FSCInfo* info ) { if ( symlink( ( char* )str.Get( sys_charset_id ), ( char* )path.GetString( sys_charset_id ) ) ) { SetError( err, errno ); return -1; } return 0; }
FSString::FSString(const FSString& rhs) : FSValue(rhs), buffer(0), strLength(0), bufferLength(0) { strLength = rhs.length(); bufferLength = strLength + 1; buffer = new char[bufferLength]; if (bufferLength > 0 && buffer == 0) throw FSAllocationException("Cannot allocate memory to copy an FSString."); strcpy(buffer, rhs.buffer); }
void OpenHomeDir( PanelWin* p ) { #ifdef _WIN32 std::vector<unicode_t> homeUri = GetHomeUriWin(); if ( homeUri.data() ) { const std::vector<clPtr<FS>> checkFS = { p->GetFSPtr(), g_MainWin->GetOtherPanel( p )->GetFSPtr() }; FSPath path; clPtr<FS> fs = ParzeURI( homeUri.data(), path, checkFS ); if ( fs.IsNull() ) { char buf[4096]; FSString name = homeUri.data(); Lsnprintf( buf, sizeof( buf ), "bad home path: %s\n", name.GetUtf8() ); NCMessageBox( g_MainWin, "Home", buf, true ); } else { p->LoadPath( fs, path, 0, 0, PanelWin::SET ); } } #else const sys_char_t* home = (sys_char_t*) getenv( "HOME" ); if ( !home ) { return; } FSPath path( sys_charset_id, home ); p->LoadPath( new FSSys(), path, 0, 0, PanelWin::SET ); #endif }
clPtr<FS> clArchPlugin::OpenFS( clPtr<FS> Fs, FSPath& Path ) const { FSString Uri = Fs->Uri( Path ); struct archive* Arch = ArchOpen( Uri.GetUtf8() ); if ( Arch == nullptr ) { return nullptr; } FSArchNode RootDir; RootDir.fsStat.mode = S_IFDIR; FSPath NodePath; struct archive_entry* entry = archive_entry_new2( Arch ); int Res; while ( ( Res = archive_read_next_header2( Arch, entry ) ) == ARCHIVE_OK ) { NodePath.Set( CS_UTF8, archive_entry_pathname( entry ) ); FSString* ItemName = NodePath.GetItem( NodePath.Count() - 1 ); if ( NodePath.Count() == 1 && ( ItemName->IsDot() || ItemName->IsEmpty() ) ) { // skip root dir continue; } const mode_t Mode = archive_entry_mode( entry ); const int64_t Size = archive_entry_size( entry ); RootDir.entryOffset += Size; FSStat ItemStat; ItemStat.mode = S_ISREG( Mode ) ? Mode : S_IFDIR; ItemStat.size = Size; ItemStat.m_CreationTime = archive_entry_ctime( entry ); ItemStat.m_LastAccessTime = archive_entry_atime( entry ); ItemStat.m_LastWriteTime = archive_entry_mtime( entry ); ItemStat.m_ChangeTime = ItemStat.m_LastWriteTime; FSArchNode* Dir = ArchGetParentDir( &RootDir, NodePath, ItemStat ); FSArchNode* Item = Dir->Add( FSArchNode( ItemName->GetUtf8(), ItemStat ) ); if (Item) { Item->entryOffset = archive_read_header_position( Arch ); } } if ( Res != ARCHIVE_EOF ) { dbg_printf( "Couldn't read archive entry: %s\n", archive_error_string( Arch ) ); } archive_entry_free( entry ); ArchClose( Arch ); return new FSArch( RootDir, Uri ); }
int FSArch::OpenRead( FSPath& path, int flags, int* err, FSCInfo* info ) { dbg_printf( "FSArch::Open\n" ); FSArchNode* Node = m_RootDir.findByFsPath( path ); if ( Node == nullptr ) { FS::SetError( err, FSARCH_ERROR_FILE_NOT_FOUND ); return -1; } struct archive* Arch = ArchOpen( m_Uri.GetUtf8() ); if ( Arch == nullptr ) { FS::SetError( err, FSARCH_ERROR_FILE_NOT_FOUND ); return -1; } struct archive_entry* entry = archive_entry_new2( Arch ); int Res; // seek to the entry while ( ( Res = archive_read_next_header2( Arch, entry ) ) == ARCHIVE_OK ) { int64_t EntryOffset = archive_read_header_position( Arch ); if ( EntryOffset == Node->entryOffset ) { break; } } archive_entry_free( entry ); if ( Res != ARCHIVE_OK ) { ArchClose( Arch ); dbg_printf( "Couldn't read archive entry: %s\n", archive_error_string( Arch ) ); FS::SetError( err, FSARCH_ERROR_FILE_NOT_FOUND ); return -1; } const int fd = g_NextArchFD++; m_OpenFiles[ fd ] = Arch; return fd; }
bool FileAttributesDlg( NCDialogParent* Parent, PanelWin* Panel ) { clFileAttributesWin Dialog( Parent, Panel ); if ( Dialog.DoModal( ) == CMD_OK ) { FSNode* Node = Dialog.GetNode(); // apply changes if ( Node ) { FSPath fspath; FSString URI = Dialog.GetURI(); clPtr<FS> fs = ParzeURI( URI.GetUnicode(), fspath, {} ); if ( fs ) { int Err = 0; FSCInfo Info; fs->StatSetAttr( fspath, &Node->st, &Err, &Info ); if ( Err != 0 ) { throw_msg( "Error setting file attributes: %s", fs->StrError( Err ).GetUtf8() ); } fs->SetFileTime( fspath, Node->GetCreationTime(), Node->GetLastAccessTime(), Node->GetLastWriteTime(), &Err, &Info ); if ( Err != 0 ) { throw_msg("Error setting file date & time: %s", fs->StrError(Err).GetUtf8()); } } } return true; } return false; }
int FSSftp::Symlink ( FSPath& path, FSString& str, int* err, FSCInfo* info ) { MutexLock lock( &mutex ); int ret = CheckSession( err, info ); if ( ret ) { return ret; } if ( sftp_symlink( sftpSession, ( char* )str.Get( _operParam.charset ), ( char* )path.GetString( _operParam.charset ) ) ) { if ( err ) { *err = sftp_get_error( sftpSession ); } return -1; } return 0; }
int FSString::CmpNoCase( FSString& par ) { if ( !_primary.str() ) { return ( !par._primary.str() ) ? 0 : -1; } if ( !par._primary.str() ) { return 1; } const unicode_t* a = GetUnicode(); const unicode_t* b = par.GetUnicode(); unicode_t au = 0; unicode_t bu = 0; for ( ; *a; a++, b++ ) { au = UnicodeLC( *a ); bu = UnicodeLC( *b ); if ( au != bu ) { break; } }; return ( *a ? ( *b ? ( au < bu ? -1 : ( au == bu ? 0 : 1 ) ) : 1 ) : ( *b ? -1 : 0 ) ); }
int FSSftp::Symlink ( FSPath& path, FSString& str, int* err, FSCInfo* info ) { MutexLock lock( &mutex ); int ret = CheckSession( err, info ); if ( ret ) { return ret; } try { int ret; WHILE_EAGAIN_( ret, libssh2_sftp_symlink( sftpSession, ( char* )str.Get( _operParam.charset ), ( char* )path.GetString( _operParam.charset, '/' ) ) ); CheckSFTP( ret ); } catch ( int e ) { if ( err ) { *err = e; } return ( e == -2 ) ? -2 : -1; } return 0; }
void _DeleteFolderAndFiles(const char *dirName) { FSString fsString; DIR *dirp = NULL; dirp = opendir(dirName); if ( dirp == NULL ) return; struct dirent *dp; while ((dp = readdir(dirp)) != NULL) { // printf("%s\n", dp->d_name); if ( dp->d_type == DT_REG ) { fsString = dirName; fsString.Append(PATH_SEPARATOR_CHAR); fsString.Append( dp->d_name); remove(fsString.GetString()); } else if (dp->d_type == DT_DIR ) { if (strcmp(dp->d_name, ".") == 0 ) continue; if (strcmp(dp->d_name, "..") == 0 ) continue; fsString = dirName; fsString.Append(PATH_SEPARATOR_CHAR); fsString.Append( dp->d_name); _DeleteFolderAndFiles(fsString.GetString()); } } closedir(dirp); rmdir(dirName); }
void OperRDThread::Run() { if ( !fs.Ptr() ) { return; } int n = 8; int ret_err; int havePostponedStatError = 0; FSString postponedStrError; while ( true ) { if ( !( fs->Flags() & FS::HAVE_SYMLINK ) ) { break; } FSStat st; // if path is inaccessible, try .. path. Throw the exception later // This makes panel at least having some valid folder while ( fs->Stat( path, &st, &ret_err, Info() ) ) { havePostponedStatError = 1; postponedStrError = fs->StrError( ret_err ); if ( !path.IsAbsolute() || path.Count() <= 1 || !path.Pop() ) { throw_msg( "%s", postponedStrError.GetUtf8() ); } } // yell immediately if the path is inaccessible (orig behavior) //if (fs->Stat(path, &st, &ret_err, Info())) // throw_msg("%s", fs->StrError(ret_err).GetUtf8()); if ( !st.IsLnk() ) { break; } n--; if ( n < 0 ) { throw_msg( "too many symbolic links '%s'", path.GetUtf8() ); } path.Pop(); if ( !ParzeLink( path, st.link ) ) { throw_msg( "invalid symbolic link '%s'", path.GetUtf8() ); } } clPtr<FSList> list = new FSList; int havePostponedReadError = 0; // if directory is not readable, try .. path. Throw the exception later // "Stat" call above does not catch this: it checks only folder existence, but not accessibilly while ( fs->ReadDir( list.ptr(), path, &ret_err, Info() ) ) { havePostponedReadError = 1; postponedStrError = fs->StrError( ret_err ); if ( !path.IsAbsolute() || path.Count() <= 1 || !path.Pop() ) { throw_msg( "%s", postponedStrError.GetUtf8() ); } } // yell immediately if the dir is unreadable (orig behavior) //int ret = fs->ReadDir(list.ptr(), path, &ret_err, Info()); //if (ret) // throw_msg("%s", fs->StrError(ret_err).GetUtf8()); FSStatVfs vst; fs->StatVfs( path, &vst, &ret_err, Info() ); MutexLock lock( Node().GetMutex() ); //!!! if ( Node().NBStopped() ) { return; } OperRDData* data = ( ( OperRDData* )Node().Data() ); data->list = list; data->path = path; data->executed = true; data->vst = vst; if ( havePostponedReadError || havePostponedStatError ) { data->nonFatalErrorString = postponedStrError; } }
int FSSftp::CheckSession( int* err, FSCInfo* info ) { if ( sshSession ) { return 0; } try { sshSession = ssh_new(); if ( !sshSession ) { throw int( SSH_INTERROR_X3 ); } if ( ssh_options_set( sshSession, SSH_OPTIONS_HOST, unicode_to_utf8( _operParam.server.Data() ).ptr() ) ) { throw int( SSH_INTERROR_X3 ); } int port = _operParam.port; if ( ssh_options_set( sshSession, SSH_OPTIONS_PORT, &port ) ) { throw int( SSH_INTERROR_X3 ); } FSString userName = ""; if ( _operParam.user.Data()[0] ) { userName = _operParam.user.Data(); } else { char* ret = getenv( "LOGNAME" ); if ( ret ) { userName = FSString( sys_charset_id, ret ); _operParam.user = userName.GetUnicode(); MutexLock infoLock( &infoMutex ); _infoParam.user = userName.GetUnicode(); } }; if ( ssh_options_set( sshSession, SSH_OPTIONS_USER, ( char* )userName.Get( _operParam.charset ) ) ) //есть сомнения, что надо все таки в utf8 { throw int( SSH_INTERROR_X3 ); } if ( ssh_connect( sshSession ) != SSH_OK ) { throw int( SSH_INTERROR_CONNECT ); } int method = ssh_userauth_list( sshSession, 0 ); int ret; static unicode_t userSymbol = '@'; if ( method & SSH_AUTH_METHOD_PASSWORD ) { FSPromptData data; data.visible = false; data.prompt = utf8_to_unicode( "Password:"******"SFTP_" ).ptr(), carray_cat<unicode_t>( userName.GetUnicode(), &userSymbol, _operParam.server.Data() ).ptr(), &data, 1 ) ) { throw int( SSH_INTERROR_STOPPED ); } ret = ssh_userauth_password( sshSession, ( char* )FSString( _operParam.user.Data() ).Get( _operParam.charset ), ( char* )FSString( data.prompt.Data() ).Get( _operParam.charset ) ); } if ( ret != SSH_AUTH_SUCCESS && ( method & SSH_AUTH_METHOD_INTERACTIVE ) != 0 ) { while ( true ) { ret = ssh_userauth_kbdint( sshSession, 0, 0 ); if ( ret != SSH_AUTH_INFO ) { break; } const char* instruction = ssh_userauth_kbdint_getinstruction( sshSession ); if ( !instruction ) { instruction = ""; } int n = ssh_userauth_kbdint_getnprompts( sshSession ); if ( n <= 0 ) { continue; } std::vector<FSPromptData> pData( n ); int i; for ( i = 0; i < n; i++ ) { char echo; const char* prompt = ssh_userauth_kbdint_getprompt( sshSession, i, &echo ); if ( !prompt ) { break; } pData[i].visible = echo != 0; pData[i].prompt = utf8_to_unicode( prompt ).ptr(); } if ( !info ) { throw int( SSH_INTERROR_AUTH ); } if ( !info->Prompt( utf8_to_unicode( "SFTP" ).ptr(), carray_cat<unicode_t>( userName.GetUnicode(), &userSymbol, _operParam.server.Data() ).ptr(), pData.ptr(), n ) ) { throw int( SSH_INTERROR_STOPPED ); } for ( i = 0; i < n; i++ ) { if ( ssh_userauth_kbdint_setanswer( sshSession, i, ( char* )FSString( pData[i].prompt.Data() ).Get( _operParam.charset ) ) < 0 ) { throw int( SSH_INTERROR_AUTH ); } } } } if ( ret != SSH_AUTH_SUCCESS ) { if ( ret == SSH_AUTH_PARTIAL ) { throw int( SSH_INTERROR_UNSUPPORTED_AUTH ); } else { throw int( SSH_INTERROR_AUTH ); } } sftpSession = sftp_new( sshSession ); if ( !sftpSession ) { throw int( SSH_INTERROR_FATAL ); } if ( sftp_init( sftpSession ) != SSH_OK ) { throw int( SSH_INTERROR_FATAL ); } } catch ( int e ) { if ( err ) { *err = e; } if ( sftpSession ) { sftp_free( sftpSession ); } if ( sshSession ) { ssh_free( sshSession ); } sshSession = 0; sftpSession = 0; return ( e == SSH_INTERROR_STOPPED ) ? -2 : -1; } return 0; }
FSString FSSftp::StrError( int err ) { const char* s = ""; if ( err < -500 ) { switch ( err + 1000 ) { case LIBSSH2_ERROR_SOCKET_NONE: s = "LIBSSH2_ERROR_SOCKET_NONE"; break; case LIBSSH2_ERROR_BANNER_RECV: s = "LIBSSH2_ERROR_BANNER_RECV"; break; case LIBSSH2_ERROR_BANNER_SEND: s = "LIBSSH2_ERROR_BANNER_SEND"; break; case LIBSSH2_ERROR_INVALID_MAC: s = "LIBSSH2_ERROR_INVALID_MAC"; break; case LIBSSH2_ERROR_KEX_FAILURE: s = "LIBSSH2_ERROR_KEX_FAILURE"; break; case LIBSSH2_ERROR_ALLOC: s = "LIBSSH2_ERROR_ALLOC"; break; case LIBSSH2_ERROR_SOCKET_SEND: s = "LIBSSH2_ERROR_SOCKET_SEND"; break; case LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE: s = "LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE"; break; case LIBSSH2_ERROR_TIMEOUT: s = "LIBSSH2_ERROR_TIMEOUT"; break; case LIBSSH2_ERROR_HOSTKEY_INIT: s = "LIBSSH2_ERROR_HOSTKEY_INIT"; break; case LIBSSH2_ERROR_HOSTKEY_SIGN: s = "LIBSSH2_ERROR_HOSTKEY_SIGN"; break; case LIBSSH2_ERROR_DECRYPT: s = "LIBSSH2_ERROR_DECRYPT"; break; case LIBSSH2_ERROR_SOCKET_DISCONNECT: s = "LIBSSH2_ERROR_SOCKET_DISCONNECT"; break; case LIBSSH2_ERROR_PROTO: s = "LIBSSH2_ERROR_PROTO"; break; case LIBSSH2_ERROR_PASSWORD_EXPIRED: s = "LIBSSH2_ERROR_PASSWORD_EXPIRED"; break; case LIBSSH2_ERROR_FILE: s = "LIBSSH2_ERROR_FILE"; break; case LIBSSH2_ERROR_METHOD_NONE: s = "LIBSSH2_ERROR_METHOD_NONE"; break; case LIBSSH2_ERROR_AUTHENTICATION_FAILED: s = "Authentication failed"; break; case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED: s = "LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED"; break; case LIBSSH2_ERROR_CHANNEL_OUTOFORDER: s = "LIBSSH2_ERROR_CHANNEL_OUTOFORDER"; break; case LIBSSH2_ERROR_CHANNEL_FAILURE: s = "LIBSSH2_ERROR_CHANNEL_FAILURE"; break; case LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED: s = "LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED"; break; case LIBSSH2_ERROR_CHANNEL_UNKNOWN: s = "LIBSSH2_ERROR_CHANNEL_UNKNOWN"; break; case LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED: s = "LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED"; break; case LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED: s = "LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED"; break; case LIBSSH2_ERROR_CHANNEL_CLOSED: s = "LIBSSH2_ERROR_CHANNEL_CLOSED"; break; case LIBSSH2_ERROR_CHANNEL_EOF_SENT: s = "LIBSSH2_ERROR_CHANNEL_EOF_SENT"; break; case LIBSSH2_ERROR_SCP_PROTOCOL: s = "LIBSSH2_ERROR_SCP_PROTOCOL"; break; case LIBSSH2_ERROR_ZLIB: s = "LIBSSH2_ERROR_ZLIB"; break; case LIBSSH2_ERROR_SOCKET_TIMEOUT: s = "LIBSSH2_ERROR_SOCKET_TIMEOUT"; break; case LIBSSH2_ERROR_SFTP_PROTOCOL: s = "LIBSSH2_ERROR_SFTP_PROTOCOL"; break; case LIBSSH2_ERROR_REQUEST_DENIED: s = "LIBSSH2_ERROR_REQUEST_DENIED"; break; case LIBSSH2_ERROR_METHOD_NOT_SUPPORTED: s = "LIBSSH2_ERROR_METHOD_NOT_SUPPORTED"; break; case LIBSSH2_ERROR_INVAL: s = "LIBSSH2_ERROR_INVAL"; break; case LIBSSH2_ERROR_INVALID_POLL_TYPE: s = "LIBSSH2_ERROR_INVALID_POLL_TYPE"; break; case LIBSSH2_ERROR_PUBLICKEY_PROTOCOL: s = "LIBSSH2_ERROR_PUBLICKEY_PROTOCOL"; break; case LIBSSH2_ERROR_EAGAIN: s = "LIBSSH2_ERROR_EAGAIN"; break; case LIBSSH2_ERROR_BUFFER_TOO_SMALL: s = "LIBSSH2_ERROR_BUFFER_TOO_SMALL"; break; case LIBSSH2_ERROR_BAD_USE: s = "LIBSSH2_ERROR_BAD_USE"; break; case LIBSSH2_ERROR_COMPRESS: s = "LIBSSH2_ERROR_COMPRESS"; break; case LIBSSH2_ERROR_OUT_OF_BOUNDARY: s = "LIBSSH2_ERROR_OUT_OF_BOUNDARY"; break; case LIBSSH2_ERROR_AGENT_PROTOCOL: s = "LIBSSH2_ERROR_AGENT_PROTOCOL"; break; case LIBSSH2_ERROR_SOCKET_RECV: s = "LIBSSH2_ERROR_SOCKET_RECV"; break; case LIBSSH2_ERROR_ENCRYPT: s = "LIBSSH2_ERROR_ENCRYPT"; break; case LIBSSH2_ERROR_BAD_SOCKET: s = "LIBSSH2_ERROR_BAD_SOCKET"; break; default: s = "LIBSSH2_ERROR_???"; break; } } else { switch ( err ) { case SSH_INTERROR_NOTSUPPORT: s = "not supported operation"; break; case SSH_INTERROR_X3: s = "X3"; break; case SSH_INTERROR_CONNECT: s = "connection failed"; break; case SSH_INTERROR_AUTH: s = "authorization failed"; break; case SSH_INTERROR_FATAL: s = "fatal ssh error"; break; case SSH_INTERROR_STOPPED: s = "Process stopped"; break; default: if ( err >= 0 ) { sys_char_t buf[0x100]; FSString str; str.SetSys( sys_error_str( err, buf, 0x100 ) ); return str; } char buf[0x100]; snprintf( buf, sizeof( buf ), "err : %i ???", err ); FSString str( CS_UTF8, buf ); return str; } } return FSString( CS_UTF8, s ); }
int FSSftp::CheckSession( int* err, FSCInfo* info ) { if ( sshSession ) { return 0; } try { unsigned ip; int e; if ( !GetHostIp( unicode_to_utf8( _operParam.server.Data() ).data(), &ip, &e ) ) { throw int( e ); } _sock.Create(); _sock.Connect( ntohl( ip ), _operParam.port ); sshSession = libssh2_session_init(); if ( !sshSession ) { throw int( SSH_INTERROR_X3 ); } libssh2_session_set_blocking( sshSession, 0 ); WHILE_EAGAIN_( e, libssh2_session_handshake( sshSession, _sock.Id() ) ); if ( e ) { throw int( e - 1000 ); } FSString userName = ""; if ( _operParam.user.Data()[0] ) { userName = _operParam.user.Data(); } else { #ifndef _WIN32 char* ret = getenv( "LOGNAME" ); if ( ret ) { userName = FSString( sys_charset_id, ret ); _operParam.user = userName.GetUnicode(); MutexLock infoLock( &infoMutex ); _infoParam.user = userName.GetUnicode(); } #endif }; char* authList = 0; char* charUserName = ( char* )userName.Get( _operParam.charset ); while ( true ) { authList = libssh2_userauth_list( sshSession, charUserName, strlen( charUserName ) ); if ( authList ) { break; } CheckSessionEagain(); WaitSocket( info ); } //publickey,password,keyboard-interactive static const char passId[] = "password"; static const char kInterId[] = "keyboard-interactive"; static unicode_t userSymbol = '@'; while ( true ) { if ( !strncmp( authList, passId, strlen( passId ) ) ) { FSPromptData data; data.visible = false; data.prompt = utf8_to_unicode( "Password:"******"SFTP_" ).data(), carray_cat<unicode_t>( userName.GetUnicode(), &userSymbol, _operParam.server.Data() ).data(), &data, 1 ) ) { throw int( SSH_INTERROR_STOPPED ); } int ret; WHILE_EAGAIN_( ret, libssh2_userauth_password( sshSession, ( char* )FSString( _operParam.user.Data() ).Get( _operParam.charset ), ( char* )FSString( data.prompt.Data() ).Get( _operParam.charset ) ) ); if ( ret ) { throw int( ret - 1000 ); } break; //!!! } else if ( !strncmp( authList, kInterId, strlen( kInterId ) ) ) { MutexLock lock( &kbdIntMutex ); kbdIntInfo = info; kbdIntParam = &_operParam; int ret; WHILE_EAGAIN_( ret, libssh2_userauth_keyboard_interactive( sshSession, ( char* )FSString( _operParam.user.Data() ).Get( _operParam.charset ), KbIntCallback ) ); if ( ret ) { throw int( ret - 1000 ); } break; //!!! } char* s = authList; while ( *s && *s != ',' ) { s++; } if ( !*s ) { break; } authList = s + 1; }; while ( true ) { sftpSession = libssh2_sftp_init( sshSession ); if ( sftpSession ) { break; } if ( !sftpSession ) { int e = libssh2_session_last_errno( sshSession ); if ( e != LIBSSH2_ERROR_EAGAIN ) { throw int( e - 1000 ); } } WaitSocket( info ); } return 0; } catch ( int e ) { if ( err ) { *err = e; } //if (sftpSession) ??? похоже закрытие сессии все решает if ( sshSession ) { libssh2_session_free( sshSession ); } sshSession = 0; sftpSession = 0; _sock.Close( false ); return ( e == -2 ) ? -2 : -1; } }