📄 ftp.cc
字号:
{ m_error = ERR_CANNOT_RESUME; m_errorText = _path; return false; } } } tmp = _command; // only add path if it's not a list command // we are changing into this directory anyway, so it's enough just to send "list" // and this also works for symlinks if ( _path != 0L && strcmp( _command, "list" )) { tmp += " "; tmp += _path; } if ( !ftpSendCmd( tmp.c_str(), '1' ) ) // We can not give any error code here since the error depends on the command return false; if ( ( sData = ftpAcceptConnect() ) < 0 ) { if ( !m_error ) { m_error = ERR_COULD_NOT_ACCEPT; m_errorText = ""; return false; } } return true;}bool Ftp::ftpCloseCommand(){ if( sData != 0 ) { shutdown( sData, 2 ); ::close( sData ); sData = 0; } if( sDatal != 0 ) { ::close( sDatal ); sDatal = 0; } return true;}/* * ftpMkdir - create a directory at server * * return 1 if successful, 0 otherwise */bool Ftp::ftpMkdir( const char *path ){ assert( m_bLoggedOn ); string buf = "mkd "; buf += path; return ftpSendCmd( buf.c_str() , '2' );}/* * ftpChdir - change path at remote * * return 1 if successful, 0 otherwise */bool Ftp::ftpChdir( const char *path){ assert( m_bLoggedOn ); string buf = "cwd "; buf += path; return ftpSendCmd( buf.c_str(), '2' );}bool Ftp::ftpRmdir( const char *path){ assert( m_bLoggedOn ); string buf = "rmd "; buf += path; return ftpSendCmd( buf.c_str() ,'2' );}/* * ftpRename - rename a file at remote * * return 1 if successful, 0 otherwise */bool Ftp::ftpRename( const char *src, const char *dst){ assert( m_bLoggedOn ); string cmd; cmd = "RNFR "; cmd += src; if ( !ftpSendCmd( cmd.c_str(), '3') ) return false; cmd = "RNTO "; cmd += dst; if ( !ftpSendCmd( cmd.c_str() ,'2' ) ) return false; return true;}/* * ftpDelete - delete a file at remote * * return 1 if successful, 0 otherwise */bool Ftp::ftpDelete( const char *fnm ){ assert( m_bLoggedOn ); string cmd = "DELE "; cmd += fnm; return ftpSendCmd( cmd.c_str(), '2' );}/* * ftpChmod - do chmod on a remote file * * return 1 if successful, 0 otherwise */bool Ftp::ftpChmod( const char *src, int mode ){ assert( m_bLoggedOn ); string cmd; cmd = "SITE CHMOD "; char buf[10]; // we need to do bit AND 777 to get permissions sprintf(buf, "%o ", mode & 511 ); cmd += buf; cmd += src; if ( !ftpSendCmd( cmd.c_str() ,'2' ) ) return false; return true;}FtpEntry* Ftp::stat( K2URL& _url ){ string redirect; if( !ftpConnect( _url.host(), _url.port(), _url.user(), _url.pass(), redirect ) ) // The error is already set => we just return return 0L; K2URL url( _url ); if ( !redirect.empty() && !_url.hasPath() ) { url.setPath( redirect.c_str() ); } FtpEntry* e = ftpStat( _url ); ftpDisconnect(); return e;}FtpEntry* Ftp::ftpStat( K2URL& _url ){ static FtpEntry fe; cerr << "ftpStat : " << _url.url() << endl; string path = _url.directory(); if ( path == "" || path == "/" ) { fe.access = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; fe.type = S_IFDIR; fe.link = ""; fe.name = ""; fe.owner = "root"; fe.group = "root"; fe.date = 0; fe.size = 0; return &fe; } if( !ftpOpenCommand( "list", path.c_str(), 'A' ) ) { cerr << "COULD NOT LIST" << endl; return 0L; } dirfile = fdopen( sData, "r" ); if( !dirfile ) return 0L; cerr << "Starting of list was ok" << endl; string search = _url.filename(); assert( search != "" && search != "/" ); bool found = false; FtpEntry *e; while( ( e = readdir() ) && !found ) { if ( error() ) { cerr << "FAILED: Read " << error() << " " << errorText() << endl; return 0L; } if ( search == e->name ) { found = true; fe = *e; } cerr << "$#" << e->name << endl; } if ( !ftpCloseDir() ) return 0L; if ( !found ) return 0L; return &fe;}bool Ftp::opendir( K2URL &_url ){ string path( _url.path(-1) ); bool haspath = _url.hasPath(); string redirect; if( !ftpConnect( _url.host(), _url.port(), _url.user(), _url.pass(), redirect ) ) // The error is already set => we just return return false; // Did we get a redirect and did not we specify a path ourselfs ? if ( path != redirect && !haspath ) redirection( _url.url().c_str() ); else redirect = path; cerr << "hunting for path '" << redirect << "' now" << endl; K2URL url( _url ); url.setPath( redirect.c_str() ); return ftpOpenDir( url );}bool Ftp::ftpOpenDir( K2URL& _url ){ string path( _url.path(-1) ); if( !ftpOpenCommand( "list", path.c_str(), 'A' ) ) { cerr << "COULD NOT LIST " << error() << " " << errorText() << endl; return false; } dirfile = fdopen( sData, "r" ); if( !dirfile ) return false; cerr << "Starting of list was ok" << endl; return true;}FtpEntry *Ftp::readdir(){ char buffer[1024]; while( fgets( buffer, 1024, dirfile ) != 0 ) { FtpEntry* e = ftpParseDir( buffer ); if ( e ) return e; } return 0L;}FtpEntry* Ftp::ftpParseDir( char* buffer ){ string tmp; static FtpEntry de; const char *p_access, *p_junk, *p_owner, *p_group; const char *p_size, *p_date_1, *p_date_2, *p_date_3, *p_name; if ((p_access = strtok(buffer," ")) != 0) if ((p_junk = strtok(NULL," ")) != 0) if ((p_owner = strtok(NULL," ")) != 0) if ((p_group = strtok(NULL," ")) != 0) if ((p_size = strtok(NULL," ")) != 0) { // A special hack for "/dev". A listing may look like this: // crw-rw-rw- 1 root root 1, 5 Jun 29 1997 zero // So we just ignore the number in front of the ",". Ok, its a hack :-) if ( strchr( p_size, ',' ) != 0L ) if ((p_size = strtok(NULL," ")) == 0) return 0L; if ((p_date_1 = strtok(NULL," ")) != 0) if ((p_date_2 = strtok(NULL," ")) != 0) if ((p_date_3 = strtok(NULL," ")) != 0) if ((p_name = strtok(NULL,"\r\n")) != 0) { if ( p_access[0] == 'l' ) { tmp = p_name; int i = tmp.rfind( " -> " ); if ( i != -1 ) { de.link = p_name + i + 4; tmp.erase( i ); p_name = tmp.c_str(); } else de.link = ""; } else de.link = ""; de.access = 0; de.type = 0; if ( p_access[0] == 'd' ) de.type = S_IFDIR; else if ( p_access[0] == 's' ) de.type = S_IFSOCK; else if ( p_access[0] == 'b' ) de.type = S_IFBLK; else if ( p_access[0] == 'c' ) de.type = S_IFCHR; else if ( p_access[0] == 'l' ) de.type = S_IFLNK; if ( p_access[1] == 'r' ) de.access |= S_IRUSR; if ( p_access[2] == 'w' ) de.access |= S_IWUSR; if ( p_access[3] == 'x' ) de.access |= S_IXUSR; if ( p_access[4] == 'r' ) de.access |= S_IRGRP; if ( p_access[5] == 'w' ) de.access |= S_IWGRP; if ( p_access[6] == 'x' ) de.access |= S_IXGRP; if ( p_access[7] == 'r' ) de.access |= S_IROTH; if ( p_access[8] == 'w' ) de.access |= S_IWOTH; if ( p_access[9] == 'x' ) de.access |= S_IXOTH; de.owner = p_owner; de.group = p_group; de.size = atoi(p_size); // string tmp( p_name ); de.name = p_name; /* tmp.stripWhiteSpace(); */ // TODO: de.date.sprintf( "%s %s %s", p_date_1, p_date_2, p_date_3 ); return( &de ); } } return 0L;}bool Ftp::closedir(){ if( dirfile ) { ftpCloseDir(); fclose( dirfile ); dirfile = NULL; ftpDisconnect(); } return true;}bool Ftp::ftpCloseDir(){ cerr << "... closing" << endl; if ( !readresp( '2' ) ) { cerr << "Did not get transfer complete message" << endl; return false; } return ftpCloseCommand();}bool Ftp::open( K2URL& _url, Ftp::Mode mode ){ string redirect; if( !ftpConnect( _url.host(), _url.port(), _url.user(), _url.pass(), redirect ) ) // The error is already set => just quit return false; return ftpOpen( _url, mode );}bool Ftp::ftpOpen( K2URL& _url, Ftp::Mode mode, unsigned long offset ){ if( mode & READ ) { ftpSize( _url.path(),'I'); // try to find the size of the file if ( !ftpOpenCommand( "retr", _url.path(), 'I', offset ) ) { if ( ! m_error ) { cerr << "Can't open for reading\n"; m_error = ERR_CANNOT_OPEN_FOR_READING; m_errorText = _url.url(); } return false; } // Read the size from the response string if ( strlen( rspbuf ) > 4 && m_size == 0 ) { // char *p = strchr( rspbuf, '(' ); // Patch from Alessandro Mirone <alex@greco2.polytechnique.fr> const char *p = rspbuf; const char *oldp = 0L; while ( *( p = strnextchr( p , '(' ) ) == '(' ) { oldp = p; p++; } p = oldp; // end patch } m_bytesLeft = m_size - offset; return true; } else if( mode & WRITE ) { if( !ftpOpenCommand( "stor", _url.path(), 'I', offset ) ) { if ( !m_error ) { m_error = ERR_COULD_NOT_WRITE; m_errorText = _url.url(); } return false; } return true; } // Never reached assert( 0 );}bool Ftp::ftpClose(){ cerr << "... closing" << endl; // first close, then read response ( should be 226 ) bool tmp = ftpCloseCommand(); if ( !readresp( '2' ) ) { cerr << "Did not get transfer complete message" << endl; return false; } return tmp;}bool Ftp::ftpResume( unsigned long offset ){ char buf[100]; sprintf(buf, "rest %ld", offset); if ( !ftpSendCmd( buf, '3' ) ) { m_error = ERR_CANNOT_RESUME; return false; } return true;}/** Use the SIZE command to get the file size. David. Warning : the size depends on the transfer mode, hence the second arg. */bool Ftp::ftpSize( const char *path, char mode){ char buf[100]; sprintf( buf, "type %c", mode ); if ( !ftpSendCmd( buf, '2' ) ) { m_error = ERR_COULD_NOT_CONNECT; m_errorText = ""; return false; } sprintf( buf, "SIZE %s", path ); if (!ftpSendCmd(buf,'2')) { m_size = 0; return false; } m_size = atol(rspbuf+4); // skip leading "213 " (response code) return true;}bool Ftp::close(){ ftpCloseCommand(); ftpDisconnect(); return true;}size_t Ftp::size(){ return m_size;}bool Ftp::atEOF(){ return( m_bytesLeft <= 0 );}size_t Ftp::read(void *buffer, long len){ size_t n = ::read( sData, buffer, len ); m_bytesLeft -= n; return n;}size_t Ftp::write(void *buffer, long len){ return( ::write( sData,buffer,len ) );}bool Ftp::mkdir( K2URL& _url ){ string redirect; if( !ftpConnect( _url.host(), _url.port(), _url.user(), _url.pass(), redirect ) ) return false; bool res = ftpMkdir( _url.path() ); ftpDisconnect(); if ( !res ) { if ( !m_error ) { m_error = ERR_COULD_NOT_MKDIR; m_errorText = _url.url(); } return false; } return true;}// Patch from Alessandro Mirone <alex@greco2.polytechnique.fr>// Little helper functionconst char* strnextchr( const char * p , char c ){ while( *p != c && *p != 0L ) { p++; } return p;} // end patch
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -