32#define KIO_FTP_PRIVATE_INCLUDE
48#include <QtCore/QCoreApplication>
50#include <QtNetwork/QHostAddress>
51#include <QtNetwork/QTcpSocket>
52#include <QtNetwork/QTcpServer>
53#include <QtNetwork/QAuthenticator>
68 #define charToLongLong(a) strtoll(a, 0, 10)
70 #define charToLongLong(a) strtol(a, 0, 10)
73#define FTP_LOGIN "anonymous"
74#define FTP_PASSWD "anonymous@"
77#define ENABLE_CAN_RESUME
81 if (path.endsWith(QLatin1String(
";type=A"), Qt::CaseInsensitive) ||
82 path.endsWith(QLatin1String(
";type=I"), Qt::CaseInsensitive) ||
83 path.endsWith(QLatin1String(
";type=D"), Qt::CaseInsensitive)) {
84 return path.left((path.length() - qstrlen(
";type=X")));
92 const int index = path.lastIndexOf(QLatin1String(
";type="));
94 if (index > -1 && (index+6) < path.size()) {
95 const QChar mode = path.at(index+6);
97 if (mode == QLatin1Char(
'A') || mode == QLatin1Char(
'a') ||
98 mode == QLatin1Char(
'I') || mode == QLatin1Char(
'i')) {
99 return mode.toUpper().toLatin1();
108 return (scheme == QLatin1String(
"ftp") || scheme == QLatin1String(
"socks"));
113 return (QNetworkProxy::applicationProxy().type() == QNetworkProxy::Socks5Proxy);
150 ssize_t written = write(fd, buf, len);
157 {
case EINTR:
continue;
171extern "C" int KDE_EXPORT
kdemain(
int argc,
char **argv )
173 QCoreApplication app(argc, argv);
177 kDebug(7102) <<
"Starting " << getpid();
181 fprintf(stderr,
"Usage: kio_ftp protocol domain-socket1 domain-socket2\n");
185 Ftp slave(argv[2], argv[3]);
196Ftp::Ftp(
const QByteArray &pool,
const QByteArray &app )
200 m_data = m_control = NULL;
202 ftpCloseControlConnection();
206 m_socketProxyAuth = 0;
219void Ftp::ftpCloseDataConnection()
231void Ftp::ftpCloseControlConnection()
246const char* Ftp::ftpResponse(
int iOffset)
248 Q_ASSERT(m_control != NULL);
249 const char *pTxt = m_lastControlLine.data();
263 while (!m_control->canReadLine() && m_control->waitForReadyRead((
readTimeout() * 1000))) {}
264 m_lastControlLine = m_control->readLine();
265 pTxt = m_lastControlLine.data();
266 int iCode = atoi(pTxt);
269 kDebug(7102) <<
" > " << pTxt;
272 if (pTxt[3] ==
'-') {
277 kWarning(7102) <<
"Cannot parse valid code from line" << pTxt;
281 kDebug(7102) <<
" > " << pTxt;
282 if (iCode >= 100 && iCode == iMore && pTxt[3] ==
' ') {
287 kDebug(7102) <<
"resp> " << pTxt;
289 m_iRespType = (m_iRespCode > 0) ? m_iRespCode / 100 : 0;
293 while(iOffset-- > 0 && pTxt[0])
301 if(m_control != NULL || m_data != NULL)
302 kDebug(7102) <<
"m_bLoggedOn=" << m_bLoggedOn <<
" m_bBusy=" << m_bBusy;
306 kWarning(7102) <<
"Abandoned data stream";
307 ftpCloseDataConnection();
312 if( !ftpSendCmd(
"quit", 0 ) || (m_iRespType != 2) )
313 kWarning(7102) <<
"QUIT returned error: " << m_iRespCode;
317 ftpCloseDataConnection();
318 ftpCloseControlConnection();
321void Ftp::setHost(
const QString& _host, quint16 _port,
const QString& _user,
322 const QString& _pass )
324 kDebug(7102) << _host <<
"port=" << _port <<
"user=" << _user;
328 kDebug(7102) <<
"proxy urls:" << m_proxyUrls;
330 if ( m_host != _host || m_port != _port ||
331 m_user != _user || m_pass != _pass )
342 ftpOpenConnection(loginExplicit);
345bool Ftp::ftpOpenConnection (LoginMode loginMode)
348 if(loginMode == loginImplicit && m_bLoggedOn)
350 Q_ASSERT(m_control != NULL);
354 kDebug(7102) <<
"host=" << m_host <<
", port=" << m_port <<
", user=" << m_user <<
"password= [password hidden]";
358 if ( m_host.isEmpty() )
360 error( ERR_UNKNOWN_HOST, QString() );
364 Q_ASSERT( !m_bLoggedOn );
366 m_initialPath.clear();
367 m_currentPath.clear();
369 if (!ftpOpenControlConnection() )
373 bool userNameChanged =
false;
374 if(loginMode != loginDefered)
376 m_bLoggedOn = ftpLogin(&userNameChanged);
385 if (userNameChanged && m_bLoggedOn)
393 realURL.setHost( m_host );
394 if ( m_port > 0 && m_port != DEFAULT_FTP_PORT )
395 realURL.setPort( m_port );
396 if ( m_initialPath.isEmpty() )
398 realURL.
setPath( m_initialPath );
399 kDebug(7102) <<
"User name changed! Redirecting to" << realURL.
prettyUrl();
414bool Ftp::ftpOpenControlConnection()
416 if (m_proxyUrls.isEmpty())
417 return ftpOpenControlConnection(m_host, m_port);
420 QString errorMessage;
422 Q_FOREACH (
const QString& proxyUrl, m_proxyUrls) {
423 const KUrl url (proxyUrl);
424 const QString scheme (url.protocol());
429 errorMessage = url.url();
433 if (scheme == QLatin1String(
"socks")) {
434 kDebug(7102) <<
"Connecting to SOCKS proxy @" << url;
435 const int proxyPort = url.port();
436 QNetworkProxy proxy (QNetworkProxy::Socks5Proxy, url.host(), (proxyPort == -1 ? 0 : proxyPort));
437 QNetworkProxy::setApplicationProxy(proxy);
438 if (ftpOpenControlConnection(m_host, m_port)) {
441 QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy);
443 if (ftpOpenControlConnection(url.host(), url.port())) {
451 error(errorCode, errorMessage);
457bool Ftp::ftpOpenControlConnection(
const QString &host,
int port )
467 connect(m_control, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
468 this, SLOT(proxyAuthentication(QNetworkProxy,QAuthenticator*)));
474 const char* psz = ftpResponse(-1);
478 sErrorMsg =
i18n(
"%1.\n\nReason: %2", host, psz);
484 if (m_control->error() == QAbstractSocket::HostNotFoundError)
487 sErrorMsg = QString(
"%1: %2").arg(host).arg(m_control->errorString());
494 error(iErrorCode, sErrorMsg);
505bool Ftp::ftpLogin(
bool* userChanged)
509 Q_ASSERT( !m_bLoggedOn );
511 QString user (m_user);
512 QString pass (m_pass);
526 info.
url.setHost( m_host );
527 if ( m_port > 0 && m_port != DEFAULT_FTP_PORT )
528 info.
url.setPort( m_port );
543 if (user.isEmpty() && pass.isEmpty())
550 QString lastServerResponse;
552 bool promptForRetry =
false;
562 if ( failedAuth > 0 || (!user.isEmpty() && pass.isEmpty()) )
565 kDebug(7102) <<
"Prompting user for login info...";
568 if( failedAuth > 0 && promptForRetry)
570 errorMsg =
i18n(
"Message sent:\nLogin using username=%1 and "
571 "password=[hidden]\n\nServer replied:\n%2\n\n"
572 , user, lastServerResponse);
578 info.
prompt =
i18n(
"You need to supply a username and a password "
579 "to access this site.");
588 error( ERR_USER_CANCELED, m_host );
604 promptForRetry =
true;
609 tempbuf += user.toLatin1();
610 if ( m_proxyURL.isValid() )
613 tempbuf += m_host.toLatin1();
614 if ( m_port > 0 && m_port != DEFAULT_FTP_PORT )
617 tempbuf += QString::number(m_port).toLatin1();
621 kDebug(7102) <<
"Sending Login name: " << tempbuf;
623 bool loggedIn = ( ftpSendCmd(tempbuf) && (m_iRespCode == 230) );
624 bool needPass = (m_iRespCode == 331);
627 if ( !loggedIn && !needPass )
629 lastServerResponse = ftpResponse(0);
630 kDebug(7102) <<
"Login failed: " << lastServerResponse;
638 tempbuf += pass.toLatin1();
639 kDebug(7102) <<
"Sending Login password: " <<
"[protected]";
640 loggedIn = ( ftpSendCmd(tempbuf) && (m_iRespCode == 230) );
647 *userChanged = (!m_user.isEmpty() && (m_user != user));
653 if (!m_user.isEmpty()) {
669 lastServerResponse = ftpResponse(0);
670 if (!ftpOpenControlConnection())
675 }
while( ++failedAuth );
678 kDebug(7102) <<
"Login OK";
683 if( ftpSendCmd(
"SYST") && (m_iRespType == 2) )
685 if( !qstrncmp( ftpResponse(0),
"215 Windows_NT", 14 ) )
687 ftpSendCmd(
"site dirstyle" );
690 if( !qstrncmp( ftpResponse(0),
"200 MSDOS-like directory output is on", 37 ))
692 ftpSendCmd(
"site dirstyle" );
694 m_extControl |= chmodUnknown;
700 if (
config()->readEntry (
"EnableAutoLoginMacro",
false) )
701 ftpAutoLoginMacro ();
704 kDebug(7102) <<
"Searching for pwd";
705 if( !ftpSendCmd(
"PWD") || (m_iRespType != 2) )
707 kDebug(7102) <<
"Couldn't issue pwd command";
708 error( ERR_COULD_NOT_LOGIN,
i18n(
"Could not login to %1.", m_host) );
713 int iBeg = sTmp.indexOf(
'"');
714 int iEnd = sTmp.lastIndexOf(
'"');
715 if(iBeg > 0 && iBeg < iEnd)
717 m_initialPath = sTmp.mid(iBeg+1, iEnd-iBeg-1);
718 if(m_initialPath[0] !=
'/') m_initialPath.prepend(
'/');
719 kDebug(7102) <<
"Initial path set to: " << m_initialPath;
720 m_currentPath = m_initialPath;
725void Ftp::ftpAutoLoginMacro ()
727 QString macro =
metaData(
"autoLoginMacro" );
729 if ( macro.isEmpty() )
732 const QStringList
list = macro.split(
'\n',QString::SkipEmptyParts);
734 for(QStringList::const_iterator it =
list.begin() ; it !=
list.end() ; ++it )
736 if ( (*it).startsWith(QLatin1String(
"init")) )
738 const QStringList list2 = macro.split(
'\\',QString::SkipEmptyParts);
742 for( ; it != list2.end() ; ++it )
746 if ( (*it).startsWith( QLatin1String(
"cwd") ) )
747 (void)ftpFolder( (*it).mid(4), false );
765bool Ftp::ftpSendCmd(
const QByteArray& cmd,
int maxretries )
767 Q_ASSERT(m_control != NULL);
769 if ( cmd.indexOf(
'\r' ) != -1 || cmd.indexOf(
'\n' ) != -1)
771 kWarning(7102) <<
"Invalid command received (contains CR or LF):"
773 error( ERR_UNSUPPORTED_ACTION, m_host );
778 bool isPassCmd = (cmd.left(4).toLower() ==
"pass");
780 kDebug(7102) <<
"send> " << cmd.data();
782 kDebug(7102) <<
"send> pass [protected]";
785 QByteArray buf = cmd;
787 int num = m_control->write(buf);
788 while (m_control->bytesToWrite() && m_control->waitForBytesWritten()) {}
797 m_iRespType = m_iRespCode = 0;
802 if( (m_iRespType <= 0) || (m_iRespCode == 421) )
811 if (maxretries > 0 && !isPassCmd)
814 if( ftpOpenConnection(loginDefered) )
815 ftpSendCmd ( cmd, maxretries - 1 );
822 if ( maxretries < 1 )
826 kDebug(7102) <<
"Was not able to communicate with " << m_host
827 <<
"Attempting to re-establish connection.";
834 if (m_control != NULL)
836 kDebug(7102) <<
"Login failure, aborting";
837 error (ERR_COULD_NOT_LOGIN, m_host);
843 kDebug(7102) <<
"Logged back in, re-issuing command";
849 return ftpSendCmd( cmd, maxretries );
864int Ftp::ftpOpenPASVDataConnection()
866 Q_ASSERT(m_control != NULL);
867 Q_ASSERT(m_data == NULL);
870 QHostAddress address = m_control->peerAddress();
871 if (address.protocol() != QAbstractSocket::IPv4Protocol && !
isSocksProxy())
874 if (m_extControl & pasvUnknown)
880 if( !ftpSendCmd(
"PASV") || (m_iRespType != 2) )
882 kDebug(7102) <<
"PASV attempt failed";
884 if( m_iRespType == 5 )
886 kDebug(7102) <<
"disabling use of PASV";
887 m_extControl |= pasvUnknown;
895 const char *start = strchr(ftpResponse(3),
'(');
897 start = strchr(ftpResponse(3),
'=');
899 ( sscanf(start,
"(%d,%d,%d,%d,%d,%d)",&i[0], &i[1], &i[2], &i[3], &i[4], &i[5]) != 6 &&
900 sscanf(start,
"=%d,%d,%d,%d,%d,%d", &i[0], &i[1], &i[2], &i[3], &i[4], &i[5]) != 6 ) )
902 kError(7102) <<
"parsing IP and port numbers failed. String parsed: " << start;
911 quint16 port = i[4] << 8 | i[5];
912 const QString host = (
isSocksProxy() ? m_host : address.toString());
915 return m_data->state() == QAbstractSocket::ConnectedState ? 0 :
ERR_INTERNAL;
921int Ftp::ftpOpenEPSVDataConnection()
923 Q_ASSERT(m_control != NULL);
924 Q_ASSERT(m_data == NULL);
926 QHostAddress address = m_control->peerAddress();
929 if (m_extControl & epsvUnknown)
933 if( !ftpSendCmd(
"EPSV") || (m_iRespType != 2) )
936 if( m_iRespType == 5 )
938 kDebug(7102) <<
"disabling use of EPSV";
939 m_extControl |= epsvUnknown;
944 const char *start = strchr(ftpResponse(3),
'|');
945 if ( !start || sscanf(start,
"|||%d|", &portnum) != 1)
948 const QString host = (
isSocksProxy() ? m_host : address.toString());
965int Ftp::ftpOpenDataConnection()
968 Q_ASSERT( m_bLoggedOn );
969 ftpCloseDataConnection();
972 int iErrCodePASV = 0;
977 iErrCode = ftpOpenPASVDataConnection();
980 iErrCodePASV = iErrCode;
981 ftpCloseDataConnection();
985 iErrCode = ftpOpenEPSVDataConnection();
988 ftpCloseDataConnection();
993 if (m_extControl & epsvAllSent)
998 iErrCode = ftpOpenPortDataConnection();
1002 ftpCloseDataConnection();
1004 return iErrCodePASV ? iErrCodePASV : iErrCode;
1013int Ftp::ftpOpenPortDataConnection()
1015 Q_ASSERT(m_control != NULL);
1016 Q_ASSERT(m_data == NULL);
1019 if (m_extControl & eprtUnknown)
1025 if (!m_server->isListening()) {
1031 m_server->setMaxPendingConnections(1);
1034 QHostAddress localAddress = m_control->localAddress();
1035 if (localAddress.protocol() == QAbstractSocket::IPv4Protocol)
1042 data.ip4 = localAddress.toIPv4Address();
1043 data.port = m_server->serverPort();
1045 unsigned char *pData =
reinterpret_cast<unsigned char*
>(&
data);
1046 command.sprintf(
"PORT %d,%d,%d,%d,%d,%d",pData[3],pData[2],pData[1],pData[0],pData[5],pData[4]);
1048 else if (localAddress.protocol() == QAbstractSocket::IPv6Protocol)
1050 command = QString(
"EPRT |2|%2|%3|").arg(localAddress.toString()).arg(m_server->serverPort());
1053 if( ftpSendCmd(command.toLatin1()) && (m_iRespType == 2) )
1063bool Ftp::ftpOpenCommand(
const char *_command,
const QString & _path,
char _mode,
1070 errCode = ftpOpenDataConnection();
1074 error(errCode, m_host);
1078 if ( _offset > 0 ) {
1081 sprintf(buf,
"rest %lld", _offset);
1082 if ( !ftpSendCmd( buf ) )
1084 if( m_iRespType != 3 )
1086 error( ERR_CANNOT_RESUME, _path );
1091 QByteArray tmp = _command;
1092 QString errormessage;
1094 if ( !_path.isEmpty() ) {
1099 if( !ftpSendCmd( tmp ) || (m_iRespType != 1) )
1101 if( _offset > 0 && qstrcmp(_command,
"retr") == 0 && (m_iRespType == 4) )
1104 errormessage = _path;
1110 if ( _offset > 0 && qstrcmp(_command,
"retr") == 0 )
1113 if(m_server && !m_data) {
1114 kDebug(7102) <<
"waiting for connection from remote.";
1116 m_data = m_server->nextPendingConnection();
1120 kDebug(7102) <<
"connected with remote.";
1125 kDebug(7102) <<
"no connection received from remote.";
1127 errormessage=m_host;
1131 error(errorcode, errormessage);
1136bool Ftp::ftpCloseCommand()
1140 ftpCloseDataConnection();
1145 kDebug(7102) <<
"ftpCloseCommand: reading command result";
1148 if(!ftpResponse(-1) || (m_iRespType != 2) )
1150 kDebug(7102) <<
"ftpCloseCommand: no transfer complete message";
1158 if( !ftpOpenConnection(loginImplicit) )
1162 const QString path = QString::fromLatin1(encodedPath.constData(), encodedPath.size());
1164 if( !ftpSendCmd( (QByteArray (
"mkd ") + encodedPath) ) || (m_iRespType != 2) )
1166 QString currentPath( m_currentPath );
1170 if( ftpFolder( path,
false ) )
1174 (void) ftpFolder( currentPath,
false );
1182 if ( permissions != -1 )
1185 (void) ftpChmod( path, permissions );
1193 if( !ftpOpenConnection(loginImplicit) )
1197 if ( ftpRename( src.
path(), dst.
path(), flags ) )
1201bool Ftp::ftpRename(
const QString & src,
const QString & dst, KIO::JobFlags jobFlags)
1203 Q_ASSERT(m_bLoggedOn);
1207 if (ftpFileExists(dst)) {
1208 error(ERR_FILE_ALREADY_EXIST, dst);
1213 if (ftpFolder(dst,
false)) {
1214 error(ERR_DIR_ALREADY_EXIST, dst);
1219 const int pos = src.lastIndexOf(
'/');
1221 if(!ftpFolder(src.left(pos+1),
false))
1225 QByteArray from_cmd =
"RNFR ";
1227 if (!ftpSendCmd(from_cmd) || (m_iRespType != 3)) {
1228 error( ERR_CANNOT_RENAME, src );
1232 QByteArray to_cmd =
"RNTO ";
1234 if (!ftpSendCmd(to_cmd) || (m_iRespType != 2)) {
1235 error( ERR_CANNOT_RENAME, src );
1244 if( !ftpOpenConnection(loginImplicit) )
1252 QByteArray cmd = isfile ?
"DELE " :
"RMD ";
1255 if( !ftpSendCmd( cmd ) || (m_iRespType != 2) )
1261bool Ftp::ftpChmod(
const QString & path,
int permissions )
1263 Q_ASSERT( m_bLoggedOn );
1265 if(m_extControl & chmodUnknown)
1270 QString cmd = QString::fromLatin1(
"SITE CHMOD ") + QString::number( permissions & 511, 8 ) +
' ';
1274 if(m_iRespType == 2)
1277 if(m_iRespCode == 500)
1279 m_extControl |= chmodUnknown;
1280 kDebug(7102) <<
"ftpChmod: CHMOD not supported - disabling";
1287 if( !ftpOpenConnection(loginImplicit) )
1290 if ( !ftpChmod( url.
path(), permissions ) )
1296void Ftp::ftpCreateUDSEntry(
const QString & filename,
const FtpEntry& ftpEnt,
UDSEntry& entry,
bool isDir )
1298 Q_ASSERT(entry.
count() == 0);
1305 if ( !ftpEnt.
group.isEmpty() )
1310 if ( !ftpEnt.
link.isEmpty() )
1321 kDebug(7102) <<
"Setting guessed mime type to inode/directory for " << filename;
1333void Ftp::ftpShortStatAnswer(
const QString& filename,
bool isDir )
1350void Ftp::ftpStatAnswerNotFound(
const QString & path,
const QString & filename )
1355 QString statSide =
metaData(
"statSide");
1356 kDebug(7102) <<
"statSide=" << statSide;
1357 if ( statSide ==
"source" )
1359 kDebug(7102) <<
"Not found, but assuming found, because some servers don't allow listing";
1365 ftpShortStatAnswer( filename,
false );
1370 error( ERR_DOES_NOT_EXIST, path );
1376 if( !ftpOpenConnection(loginImplicit) )
1380 kDebug(7102) <<
"cleaned path=" << path;
1383 if( path.isEmpty() || path ==
"/" )
1400 KUrl tempurl( url );
1404 QString filename = tempurl.
fileName();
1405 Q_ASSERT(!filename.isEmpty());
1406 QString search = filename;
1410 bool isDir = ftpFolder(path,
false);
1413 QString sDetails =
metaData(
"details");
1414 int details = sDetails.isEmpty() ? 2 : sDetails.toInt();
1415 kDebug(7102) <<
"details=" << details;
1418 if ( !isDir && !ftpFileExists(path) )
1420 ftpStatAnswerNotFound( path, filename );
1423 ftpShortStatAnswer( filename, isDir );
1451 if( !ftpFolder(parentDir,
true) )
1456 kError(7102) <<
"COULD NOT LIST";
1459 kDebug(7102) <<
"Starting of list was ok";
1461 Q_ASSERT( !search.isEmpty() && search !=
"/" );
1463 bool bFound =
false;
1467 while (ftpReadDir(ftpEnt)) {
1468 if (!ftpEnt.
name.isEmpty() && ftpEnt.
name.at(0).isSpace()) {
1469 ftpValidateEntList.append(ftpEnt);
1476 bFound = maybeEmitStatEntry(ftpEnt, search, filename, isDir);
1481 for (
int i = 0, count = ftpValidateEntList.count(); i < count; ++i) {
1482 FtpEntry& ftpEnt = ftpValidateEntList[i];
1483 fixupEntryName(&ftpEnt);
1484 if (maybeEmitStatEntry(ftpEnt, search, filename, isDir)) {
1493 ftpStatAnswerNotFound( path, filename );
1497 if ( !linkURL.isEmpty() )
1499 if ( linkURL == url || linkURL == tempurl )
1508 kDebug(7102) <<
"stat : finished successfully";
1512bool Ftp::maybeEmitStatEntry(
FtpEntry& ftpEnt,
const QString& search,
const QString& filename,
bool isDir)
1514 if ((search == ftpEnt.
name || filename == ftpEnt.
name) && !filename.isEmpty()) {
1516 ftpCreateUDSEntry( filename, ftpEnt, entry, isDir );
1527 if( !ftpOpenConnection(loginImplicit) )
1531 QString path = url.
path();
1532 if ( path.isEmpty() )
1538 realURL.setHost( m_host );
1540 realURL.setPort( m_port );
1541 if ( m_initialPath.isEmpty() )
1542 m_initialPath =
'/';
1543 realURL.
setPath( m_initialPath );
1550 kDebug(7102) <<
"hunting for path" << path;
1552 if (!ftpOpenDir(path)) {
1553 if (ftpFileExists(path)) {
1566 while( ftpReadDir(ftpEnt) )
1570 if (!ftpEnt.
name.isEmpty()) {
1571 if (ftpEnt.
name.at(0).isSpace()) {
1572 ftpValidateEntList.append(ftpEnt);
1580 ftpCreateUDSEntry( ftpEnt.
name, ftpEnt, entry,
false );
1586 for (
int i = 0, count = ftpValidateEntList.count(); i < count; ++i) {
1587 FtpEntry& ftpEnt = ftpValidateEntList[i];
1588 fixupEntryName(&ftpEnt);
1589 ftpCreateUDSEntry( ftpEnt.
name, ftpEnt, entry,
false );
1601 kDebug(7102) <<
"Got slave_status host = " << (!m_host.toLatin1().isEmpty() ? m_host.toAscii() :
"[None]") <<
" [" << (m_bLoggedOn ?
"Connected" :
"Not connected") <<
"]";
1605bool Ftp::ftpOpenDir(
const QString & path )
1611 QString tmp = path.isEmpty() ? QString(
"/") : path;
1614 if( !ftpFolder(tmp,
false) )
1623 if( !ftpOpenCommand(
"list -la", QString(),
'I', ERR_CANNOT_ENTER_DIRECTORY ) )
1625 if ( !ftpOpenCommand(
"list", QString(),
'I', ERR_CANNOT_ENTER_DIRECTORY ) )
1627 kWarning(7102) <<
"Can't open for listing";
1631 kDebug(7102) <<
"Starting of list was ok";
1637 Q_ASSERT(m_data != NULL);
1642 while (!m_data->canReadLine() && m_data->waitForReadyRead((
readTimeout() * 1000))) {}
1643 QByteArray
data = m_data->readLine();
1644 if (
data.size() == 0)
1647 const char* buffer =
data.data();
1648 kDebug(7102) <<
"dir > " << buffer;
1656 const char *p_access, *p_junk, *p_owner, *p_group, *p_size;
1657 if( (p_access = strtok((
char*)buffer,
" ")) == 0)
continue;
1658 if( (p_junk = strtok(NULL,
" ")) == 0)
continue;
1659 if( (p_owner = strtok(NULL,
" ")) == 0)
continue;
1660 if( (p_group = strtok(NULL,
" ")) == 0)
continue;
1661 if( (p_size = strtok(NULL,
" ")) == 0)
continue;
1666 if ( qstrlen( p_access ) == 1 && p_junk[0] ==
'[' ) {
1667 de.
access = S_IRWXU | S_IRWXG | S_IRWXO;
1670 const char *p_date_1, *p_date_2, *p_date_3, *p_name;
1675 if ( strchr( p_size,
',' ) != 0L )
1678 if ((p_size = strtok(NULL,
" ")) == 0)
1695 p_date_1 = strtok(NULL,
" ");
1699 if ( p_date_1 != 0 &&
1700 (p_date_2 = strtok(NULL,
" ")) != 0 &&
1701 (p_date_3 = strtok(NULL,
" ")) != 0 &&
1702 (p_name = strtok(NULL,
"\r\n")) != 0 )
1705 QByteArray tmp( p_name );
1706 if ( p_access[0] ==
'l' )
1708 int i = tmp.lastIndexOf(
" -> " );
1719 if ( tmp[0] ==
'/' )
1722 if (tmp.indexOf(
'/') != -1)
1729 switch ( p_access[0] ) {
1750 if ( p_access[1] ==
'r' )
1752 if ( p_access[2] ==
'w' )
1754 if ( p_access[3] ==
'x' || p_access[3] ==
's' )
1756 if ( p_access[4] ==
'r' )
1758 if ( p_access[5] ==
'w' )
1760 if ( p_access[6] ==
'x' || p_access[6] ==
's' )
1762 if ( p_access[7] ==
'r' )
1764 if ( p_access[8] ==
'w' )
1766 if ( p_access[9] ==
'x' || p_access[9] ==
't' )
1768 if ( p_access[3] ==
's' || p_access[3] ==
'S' )
1770 if ( p_access[6] ==
's' || p_access[6] ==
'S' )
1772 if ( p_access[9] ==
't' || p_access[9] ==
'T' )
1783 time_t currentTime = time( 0L );
1784 struct tm * tmptr = gmtime( ¤tTime );
1785 int currentMonth = tmptr->tm_mon;
1788 tmptr->tm_isdst = -1;
1794 tmptr->tm_mday = atoi( p_date_2 );
1799 static const char *
const s_months[12] = {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
1800 "Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec" };
1801 for (
int c = 0 ; c < 12 ; c ++ )
1802 if ( !qstrcmp( p_date_1, s_months[c]) )
1810 if ( qstrlen( p_date_3 ) == 4 )
1811 tmptr->tm_year = atoi( p_date_3 ) - 1900;
1820 if ( tmptr->tm_mon > currentMonth + 1 )
1825 if ( p_date_3 && ( semicolon = (
char*)strchr( p_date_3,
':' ) ) )
1828 tmptr->tm_min = atoi( semicolon + 1 );
1829 tmptr->tm_hour = atoi( p_date_3 );
1832 kWarning(7102) <<
"Can't parse third field " << p_date_3;
1836 de.
date = mktime( tmptr );
1852 const StatusCode cs = ftpGet(iError, -1, url, 0);
1855 if (cs == statusSuccess) {
1868 if( !ftpOpenConnection(loginImplicit) )
1869 return statusServerError;
1876 if ( !ftpSize( url.
path(),
'?' ) && (m_iRespCode == 550) &&
1877 ftpFolder(url.
path(),
false) )
1880 kDebug(7102) <<
"it is a directory in fact";
1882 return statusServerError;
1885 QString resumeOffset =
metaData(
"resume");
1886 if ( !resumeOffset.isEmpty() )
1888 llOffset = resumeOffset.toLongLong();
1889 kDebug(7102) <<
"got offset from metadata : " << llOffset;
1892 if( !ftpOpenCommand(
"retr", url.
path(),
'?', ERR_CANNOT_OPEN_FOR_READING, llOffset) )
1894 kWarning(7102) <<
"Can't open for reading";
1895 return statusServerError;
1899 if(m_size == UnknownSize)
1901 const char* psz = strrchr( ftpResponse(4),
'(' );
1903 if (!m_size) m_size = UnknownSize;
1907 if (iCopyFile == -1) {
1908 StatusCode status = ftpSendMimeType(iError, url);
1909 if (status != statusSuccess) {
1915 if ( m_size != UnknownSize ) {
1916 bytesLeft = m_size - llOffset;
1920 kDebug(7102) <<
"starting with offset=" << llOffset;
1931 while(m_size == UnknownSize || bytesLeft > 0)
1933 if(processed_size-llOffset > 1024 * 64)
1937 if(iBlockSize+iBufferCur > (
int)
sizeof(buffer))
1938 iBlockSize =
sizeof(buffer) - iBufferCur;
1939 if (m_data->bytesAvailable() == 0)
1941 int n = m_data->read( buffer+iBufferCur, iBlockSize );
1944 if( m_size == UnknownSize && n == 0 )
1948 return statusServerError;
1950 processed_size += n;
1953 if(m_size != UnknownSize)
1957 if(iBufferCur < minimumMimeSize && bytesLeft > 0)
1969 array = QByteArray::fromRawData(buffer, n);
1973 else if( (iError =
WriteToFile(iCopyFile, buffer, n)) != 0)
1974 return statusClientError;
1982 processedSize( m_size == UnknownSize ? processed_size : m_size );
1983 return statusSuccess;
1989 if( !ftpOpenConnection(loginImplicit) )
1992 if ( !ftpOpenCommand(
"retr", url.
path(),
'I', ERR_CANNOT_OPEN_FOR_READING, 0 ) ) {
1993 kWarning(7102) <<
"Can't open for reading";
1996 char buffer[ 2048 ];
2000 int n = m_data->read( buffer, 2048 );
2001 array.setRawData(buffer, n);
2003 array.resetRawData(buffer, n);
2005 kDebug(7102) <<
"aborting";
2008 kDebug(7102) <<
"finished";
2010 kDebug(7102) <<
"after finished";
2013 void Ftp::ftpAbortTransfer()
2021 msg[0] = (char) 255;
2022 msg[1] = (char) 254;
2023 (void) send(sControl, msg, 2, 0);
2025 msg[0] = (char) 255;
2026 msg[1] = (char) 242;
2027 if (send(sControl, msg, 2, MSG_OOB) != 2)
2031 kDebug(7102) <<
"send ABOR";
2032 QCString buf =
"ABOR\r\n";
2033 if ( KSocks::self()->
write( sControl, buf.data(), buf.length() ) <= 0 ) {
2034 error( ERR_COULD_NOT_WRITE, QString() );
2039 kDebug(7102) <<
"read resp";
2040 if ( readresp() !=
'2' )
2042 error( ERR_COULD_NOT_READ, QString() );
2046 kDebug(7102) <<
"close sockets";
2060 const StatusCode cs = ftpPut(iError, -1, url, permissions, flags);
2063 if (cs == statusSuccess) {
2073Ftp::StatusCode Ftp::ftpPut(
int& iError,
int iCopyFile,
const KUrl& dest_url,
2074 int permissions, KIO::JobFlags flags)
2076 if( !ftpOpenConnection(loginImplicit) )
2077 return statusServerError;
2082 if (m_user.isEmpty () || m_user ==
FTP_LOGIN)
2083 bMarkPartial =
false;
2087 QString dest_orig = dest_url.
path();
2088 QString dest_part( dest_orig );
2089 dest_part +=
".part";
2091 if ( ftpSize( dest_orig,
'I' ) )
2095 QByteArray cmd =
"DELE ";
2097 if( !ftpSendCmd( cmd ) || (m_iRespType != 2) )
2100 return statusServerError;
2106 return statusServerError;
2108 else if ( bMarkPartial )
2113 return statusServerError;
2119 else if ( bMarkPartial && ftpSize( dest_part,
'I' ) )
2123 QByteArray cmd =
"DELE ";
2125 if ( !ftpSendCmd( cmd ) || (m_iRespType != 2) )
2128 return statusServerError;
2137 return statusServerError;
2147 if ( bMarkPartial ) {
2148 kDebug(7102) <<
"Adding .part extension to " << dest_orig;
2161 if( KDE_lseek(iCopyFile, offset, SEEK_SET) < 0 )
2164 return statusClientError;
2169 if (! ftpOpenCommand(
"stor", dest,
'?', ERR_COULD_NOT_WRITE, offset ) )
2170 return statusServerError;
2172 kDebug(7102) <<
"ftpPut: starting with offset=" << offset;
2188 if(processed_size-offset > 1024 * 64)
2190 buffer.resize(iBlockSize);
2191 result =
::read(iCopyFile, buffer.data(), buffer.size());
2195 buffer.resize(result);
2200 m_data->write( buffer );
2201 while (m_data->bytesToWrite() && m_data->waitForBytesWritten()) {}
2202 processed_size += result;
2206 while ( result > 0 );
2211 kDebug(7102) <<
"Error during 'put'. Aborting.";
2215 if ( ftpSize( dest,
'I' ) &&
2216 ( processed_size <
config()->
readEntry(
"MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE) ) )
2218 QByteArray cmd =
"DELE ";
2220 (void) ftpSendCmd( cmd );
2223 return statusServerError;
2226 if ( !ftpCloseCommand() )
2229 return statusServerError;
2235 kDebug(7102) <<
"renaming dest (" << dest <<
") back to dest_orig (" << dest_orig <<
")";
2239 return statusServerError;
2244 if ( permissions != -1 )
2247 kDebug(7102) <<
"Trying to chmod over anonymous FTP ???";
2249 if ( ! ftpChmod( dest_orig, permissions ) )
2257 return statusSuccess;
2260const char* Ftp::ftpSendSizeCmd(
const QString& path)
2264 QString currentPath(m_currentPath);
2265 if (!currentPath.endsWith(QLatin1Char(
'/'))) {
2266 currentPath += QLatin1Char(
'/');
2271 if (path.startsWith(currentPath)) {
2277 if (!ftpSendCmd(buf) || m_iRespType != 2) {
2282 return ftpResponse(4);
2288bool Ftp::ftpSize(
const QString & path,
char mode)
2290 m_size = UnknownSize;
2291 if (!ftpDataMode(mode)) {
2295 const QByteArray psz(ftpSendSizeCmd(path));
2296 if (psz.isEmpty()) {
2301 m_size = psz.trimmed().toLongLong(&ok);
2303 m_size = UnknownSize;
2309bool Ftp::ftpFileExists(
const QString& path)
2311 return ftpSendSizeCmd(path) != 0;
2321bool Ftp::ftpDataMode(
char cMode)
2323 if(cMode ==
'?') cMode = m_bTextMode ?
'A' :
'I';
2324 else if(cMode ==
'a') cMode =
'A';
2325 else if(cMode !=
'A') cMode =
'I';
2327 kDebug(7102) <<
"want" << cMode <<
"has" << m_cDataMode;
2328 if(m_cDataMode == cMode)
2331 QByteArray buf =
"TYPE ";
2333 if( !ftpSendCmd(buf) || (m_iRespType != 2) )
2335 m_cDataMode = cMode;
2340bool Ftp::ftpFolder(
const QString& path,
bool bReportError)
2342 QString newPath = path;
2343 int iLen = newPath.length();
2344 if(iLen > 1 && newPath[iLen-1] ==
'/') newPath.truncate(iLen-1);
2347 if(m_currentPath == newPath)
2350 QByteArray tmp =
"cwd ";
2352 if( !ftpSendCmd(tmp) )
2354 if(m_iRespType != 2)
2357 error(ERR_CANNOT_ENTER_DIRECTORY, path);
2360 m_currentPath = newPath;
2374 StatusCode cs = statusSuccess;
2379 if(bSrcLocal && !bDestLocal) {
2381 kDebug(7102) <<
"local file" << sCopyFile <<
"-> ftp" << dest.
path();
2382 cs = ftpCopyPut(iError, iCopyFile, sCopyFile, dest, permissions, flags);
2383 if(cs == statusServerError) {
2384 sCopyFile = dest.
url();
2386 }
else if(!bSrcLocal && bDestLocal) {
2388 kDebug(7102) <<
"ftp" << src.
path() <<
"-> local file" << sCopyFile;
2389 cs = ftpCopyGet(iError, iCopyFile, sCopyFile, src, permissions, flags);
2390 if(cs == statusServerError) {
2391 sCopyFile = src.
url();
2399 if(iCopyFile != -1) {
2405 if (cs == statusSuccess) {
2411 error(iError, sCopyFile);
2416Ftp::StatusCode Ftp::ftpCopyPut(
int& iError,
int& iCopyFile,
const QString &sCopyFile,
2417 const KUrl& url,
int permissions, KIO::JobFlags flags)
2420 KDE_struct_stat buff;
2421 bool bSrcExists = (
KDE::stat( sCopyFile, &buff ) != -1);
2423 {
if(S_ISDIR(buff.st_mode))
2426 return statusClientError;
2432 return statusClientError;
2435 iCopyFile =
KDE::open( sCopyFile, O_RDONLY );
2439 return statusClientError;
2444#ifdef ENABLE_CAN_RESUME
2445 return ftpPut(iError, iCopyFile, url, permissions, flags & ~
KIO::Resume);
2447 return ftpPut(iError, iCopyFile, url, permissions, flags |
KIO::Resume);
2452Ftp::StatusCode Ftp::ftpCopyGet(
int& iError,
int& iCopyFile,
const QString &sCopyFile,
2453 const KUrl& url,
int permissions, KIO::JobFlags flags)
2456 KDE_struct_stat buff;
2457 const bool bDestExists = (
KDE::stat( sCopyFile, &buff ) != -1);
2459 {
if(S_ISDIR(buff.st_mode))
2462 return statusClientError;
2467 return statusClientError;
2472 const QString sPart = sCopyFile + QLatin1String(
".part");
2473 bool bResume =
false;
2474 const bool bPartExists = (
KDE::stat( sPart, &buff ) != -1);
2476 const QString dest = bMarkPartial ? sPart : sCopyFile;
2477 if (bMarkPartial && bPartExists && buff.st_size > 0)
2479 if(S_ISDIR(buff.st_mode))
2482 return statusClientError;
2485#ifdef ENABLE_CAN_RESUME
2492 if (bPartExists && !bResume)
2493 QFile::remove(sPart);
2498 if (permissions != -1)
2499 initialMode = permissions | S_IWUSR;
2507 hCopyOffset = KDE_lseek(iCopyFile, 0, SEEK_END);
2511 return statusClientError;
2513 kDebug(7102) <<
"resuming at " << hCopyOffset;
2516 iCopyFile =
KDE::open(dest, O_CREAT | O_TRUNC | O_WRONLY, initialMode);
2521 kDebug(7102) <<
"### COULD NOT WRITE " << sCopyFile;
2522 iError = (errno == EACCES) ? ERR_WRITE_ACCESS_DENIED
2523 : ERR_CANNOT_OPEN_FOR_WRITING;
2524 return statusClientError;
2528 StatusCode iRes = ftpGet(iError, iCopyFile, url, hCopyOffset);
2529 if(
::close(iCopyFile) && iRes == statusSuccess )
2532 iRes = statusClientError;
2539 if(iRes == statusSuccess)
2544 if (!bDestExists || !(QFile::remove(sCopyFile) &&
KDE::rename(sPart, sCopyFile) == 0)) {
2545 kDebug(7102) <<
"cannot rename " << sPart <<
" to " << sCopyFile;
2547 iRes = statusClientError;
2553 int size =
config()->
readEntry(
"MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE);
2554 if (buff.st_size < size)
2555 QFile::remove(sPart);
2559 if (iRes == statusSuccess) {
2560 const QString mtimeStr =
metaData(
"modified");
2561 if (!mtimeStr.isEmpty()) {
2562 QDateTime dt = QDateTime::fromString(mtimeStr, Qt::ISODate);
2564 kDebug(7102) <<
"Updating modified timestamp to" << mtimeStr;
2565 struct utimbuf utbuf;
2566 utbuf.actime = buff.st_atime;
2567 utbuf.modtime = dt.toTime_t();
2576Ftp::StatusCode Ftp::ftpSendMimeType(
int& iError,
const KUrl& url)
2580 mimeType(QLatin1String(
"application/x-zerosize"));
2581 return statusSuccess;
2584 const int totalSize = ((m_size == UnknownSize || m_size > 1024) ? 1024 : m_size);
2589 if (m_data->bytesAvailable() == 0 && !m_data->waitForReadyRead((
readTimeout() * 1000))) {
2591 return statusServerError;
2594 const int bytesRead = m_data->peek(buffer.data(),
totalSize);
2597 if (bytesRead == -1) {
2599 return statusServerError;
2604 if (bytesRead == 0 || bytesRead ==
totalSize || m_size == UnknownSize) {
2609 if (!buffer.isEmpty()) {
2611 kDebug(7102) <<
"Emitting mimetype" << mime->name();
2615 return statusSuccess;
2618void Ftp::proxyAuthentication(
const QNetworkProxy& proxy, QAuthenticator* authenticator)
2621 kDebug(7102) <<
"Authenticator received -- realm:" << authenticator->realm() <<
"user:"
2622 << authenticator->user();
2625 info.
url = m_proxyURL;
2628 info.
username = authenticator->user();
2634 if (!haveCachedCredentials || m_socketProxyAuth) {
2637 connect(m_control, SIGNAL(
connected()),
this, SLOT(saveProxyAuthentication()));
2639 info.
prompt =
i18n(
"You need to supply a username and a password for "
2640 "the proxy server listed below before you are allowed "
2641 "to access any sites.");
2647 kDebug(7102) <<
"looks like the user canceled proxy authentication.";
2648 error(ERR_USER_CANCELED, m_proxyURL.host());
2652 authenticator->setUser(info.
username);
2653 authenticator->setPassword(info.
password);
2654 authenticator->setOption(QLatin1String(
"keepalive"), info.
keepPassword);
2656 if (m_socketProxyAuth) {
2657 *m_socketProxyAuth = *authenticator;
2659 m_socketProxyAuth =
new QAuthenticator(*authenticator);
2663 m_proxyURL.setPassword(info.
password);
2666void Ftp::saveProxyAuthentication()
2669 disconnect(m_control, SIGNAL(
connected()),
this, SLOT(saveProxyAuthentication()));
2670 Q_ASSERT(m_socketProxyAuth);
2671 if (m_socketProxyAuth) {
2672 kDebug(7102) <<
"-- realm:" << m_socketProxyAuth->realm() <<
"user:" << m_socketProxyAuth->user();
2677 a.
username = m_socketProxyAuth->user();
2678 a.
password = m_socketProxyAuth->password();
2679 a.
keepPassword = m_socketProxyAuth->option(QLatin1String(
"keepalive")).toBool();
2682 delete m_socketProxyAuth;
2683 m_socketProxyAuth = 0;
2686void Ftp::fixupEntryName(
FtpEntry* e)
2689 if (e->
type == S_IFDIR) {
2690 if (!ftpFolder(e->
name,
false)) {
2692 if (ftpFolder(name,
false)) {
2694 kDebug(7102) <<
"fixing up directory name from" << e->
name <<
"to" <<
name;
2697 while (e->
name.at(index).isSpace()) {
2700 if (ftpFolder(name,
false)) {
2701 kDebug(7102) <<
"fixing up directory name from" << e->
name <<
"to" <<
name;
2709 if (!ftpFileExists(e->
name)) {
2711 if (ftpFileExists(name)) {
2713 kDebug(7102) <<
"fixing up filename from" << e->
name <<
"to" <<
name;
2716 while (e->
name.at(index).isSpace()) {
2719 if (ftpFileExists(name)) {
2720 kDebug(7102) <<
"fixing up filename from" << e->
name <<
"to" <<
name;
virtual void rename(const KUrl &src, const KUrl &dst, KIO::JobFlags flags)
virtual void del(const KUrl &url, bool isfile)
virtual void chmod(const KUrl &url, int permissions)
virtual void put(const KUrl &url, int permissions, KIO::JobFlags flags)
virtual void setHost(const QString &host, quint16 port, const QString &user, const QString &pass)
virtual void mkdir(const KUrl &url, int permissions)
virtual void listDir(const KUrl &url)
virtual void closeConnection()
Closes the connection.
virtual void copy(const KUrl &src, const KUrl &dest, int permissions, KIO::JobFlags flags)
Handles the case that one side of the job is a local file.
virtual void openConnection()
Connects to a ftp server and logs us in m_bLoggedOn is set to true if logging on was successful.
Ftp(const QByteArray &pool, const QByteArray &app)
virtual void get(const KUrl &url)
virtual void stat(const KUrl &url)
virtual void slave_status()
QString readEntry(const char *key, const char *aDefault=0) const
void setModified(bool flag)
QVariant getExtraField(const QString &fieldName) const
void setExtraField(const QString &fieldName, const QVariant &value)
void mimeType(const QString &_type)
QString metaData(const QString &key) const
void infoMessage(const QString &msg)
void processedSize(KIO::filesize_t _bytes)
virtual void mimetype(const KUrl &url)
void slaveStatus(const QString &host, bool connected)
bool cacheAuthentication(const AuthInfo &info)
virtual void write(const QByteArray &data)
void redirection(const KUrl &_url)
void error(int _errid, const QString &_text)
void statEntry(const UDSEntry &_entry)
bool openPasswordDialog(KIO::AuthInfo &info, const QString &errorMsg=QString())
KRemoteEncoding * remoteEncoding()
int readData(QByteArray &buffer)
void data(const QByteArray &data)
void listEntry(const UDSEntry &_entry, bool ready)
void totalSize(KIO::filesize_t _bytes)
virtual void read(KIO::filesize_t size)
bool checkCachedAuthentication(AuthInfo &info)
void insert(uint field, const QString &value)
static QString defaultMimeType()
static Ptr findByNameAndContent(const QString &name, const QByteArray &data, mode_t mode=0, int *accuracy=0)
static Ptr findByUrl(const KUrl &url, mode_t mode=0, bool is_local_file=false, bool fast_mode=false, int *accuracy=0)
QString decode(const QByteArray &name) const
QByteArray encode(const KUrl &url) const
QString prettyUrl(AdjustPathOption trailing=LeaveTrailingSlash) const
QString url(AdjustPathOption trailing=LeaveTrailingSlash) const
QString path(AdjustPathOption trailing=LeaveTrailingSlash) const
void setProtocol(const QString &proto)
QString directory(const DirectoryOptions &options=IgnoreTrailingSlash) const
void setPath(const QString &path)
void setPass(const QString &pass)
QString fileName(const DirectoryOptions &options=IgnoreTrailingSlash) const
QString toLocalFile(AdjustPathOption trailing=LeaveTrailingSlash) const
void setUser(const QString &user)
static bool isSocksProxy()
int kdemain(int argc, char **argv)
static QString ftpCleanPath(const QString &path)
static bool supportedProxyScheme(const QString &scheme)
static char ftpModeFromPath(const QString &path, char defaultMode='\0')
#define charToLongLong(a)
KAutostart::StartPhase readEntry(const KConfigGroup &group, const char *key, const KAutostart::StartPhase &aDefault)
QString i18n(const char *text)
int utime(const QString &filename, struct utimbuf *buf)
int open(const QString &pathname, int flags, mode_t mode)
int stat(const QString &path, KDE_struct_stat *buf)
int rename(const QString &in, const QString &out)
static int WriteToFile(int fd, const char *buf, size_t len)
This helper handles some special issues (blocking and interrupted system call) when writing to a file...
@ maximumIpcSize
largest buffer size that should be used to transfer data between KIO slaves using the data() function
@ minimumMimeSize
recommended size of a data block passed to findBufferFileType()
@ initialIpcSize
this is a reasonable value for an initial read() that a KIO slave can do to obtain data via a slow ne...
ERR_CANNOT_DELETE_PARTIAL
ERR_CANNOT_OPEN_FOR_READING
ERR_CANNOT_ENTER_DIRECTORY
ERR_CANNOT_RENAME_PARTIAL
QStringList list(const QString &fileClass)
QTcpSocket * synchronousConnectToHost(const QString &protocol, const QString &host, quint16 port, int msecs=30000, QObject *parent=0)
QTcpServer * listen(const QString &protocol, const QHostAddress &address=QHostAddress::Any, quint16 port=0, QObject *parent=0)
const char * name(StandardAction id)