Qt 4.8
qftp.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtNetwork module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 //#define QFTPPI_DEBUG
43 //#define QFTPDTP_DEBUG
44 
45 #include "qftp.h"
46 #include "qabstractsocket.h"
47 
48 #ifndef QT_NO_FTP
49 
50 #include "qcoreapplication.h"
51 #include "qtcpsocket.h"
52 #include "qurlinfo.h"
53 #include "qstringlist.h"
54 #include "qregexp.h"
55 #include "qtimer.h"
56 #include "qfileinfo.h"
57 #include "qhash.h"
58 #include "qtcpserver.h"
59 #include "qlocale.h"
60 
62 
63 class QFtpPI;
64 
65 /*
66  The QFtpDTP (DTP = Data Transfer Process) controls all client side
67  data transfer between the client and server.
68 */
69 class QFtpDTP : public QObject
70 {
71  Q_OBJECT
72 
73 public:
74  enum ConnectState {
80  };
81 
82  QFtpDTP(QFtpPI *p, QObject *parent = 0);
83 
84  void setData(QByteArray *);
85  void setDevice(QIODevice *);
86  void writeData();
87  void setBytesTotal(qint64 bytes);
88 
89  bool hasError() const;
90  QString errorMessage() const;
91  void clearError();
92 
93  void connectToHost(const QString & host, quint16 port);
94  int setupListener(const QHostAddress &address);
95  void waitForConnection();
96 
98  qint64 bytesAvailable() const;
99  qint64 read(char *data, qint64 maxlen);
101 
102  void abortConnection();
103 
104  static bool parseDir(const QByteArray &buffer, const QString &userName, QUrlInfo *info);
105 
106 signals:
107  void listInfo(const QUrlInfo&);
108  void readyRead();
110 
111  void connectState(int);
112 
113 private slots:
114  void socketConnected();
115  void socketReadyRead();
117  void socketConnectionClosed();
119  void setupSocket();
120 
121  void dataReadyRead();
122 
123 private:
124  void clearData();
125 
128 
134 
135  // If is_ba is true, ba is used; ba is never 0.
136  // Otherwise dev is used; dev can be 0 or not.
137  union {
140  } data;
141  bool is_ba;
142 
144 };
145 
146 /**********************************************************************
147  *
148  * QFtpPI - Protocol Interpreter
149  *
150  *********************************************************************/
151 
152 class QFtpPI : public QObject
153 {
154  Q_OBJECT
155 
156 public:
157  QFtpPI(QObject *parent = 0);
158 
159  void connectToHost(const QString &host, quint16 port);
160 
161  bool sendCommands(const QStringList &cmds);
162  bool sendCommand(const QString &cmd)
163  { return sendCommands(QStringList(cmd)); }
164 
165  void clearPendingCommands();
166  void abort();
167 
169  { return currentCmd; }
170 
173 
174  QFtpDTP dtp; // the PI has a DTP which is not the design of RFC 959, but it
175  // makes the design simpler this way
176 signals:
177  void connectState(int);
178  void finished(const QString&);
179  void error(int, const QString&);
180  void rawFtpReply(int, const QString&);
181 
182 private slots:
183  void hostFound();
184  void connected();
185  void connectionClosed();
186  void delayedCloseFinished();
187  void readyRead();
189 
190  void dtpConnectState(int);
191 
192 private:
193  // the states are modelled after the generalized state diagram of RFC 959,
194  // page 58
195  enum State {
200  Failure
201  };
202 
203  enum AbortState {
206  WaitForAbortToFinish
207  };
208 
209  bool processReply();
210  bool startNextCmd();
211 
214  char replyCode[3];
219 
222 
224 
225  friend class QFtpDTP;
226 };
227 
228 /**********************************************************************
229  *
230  * QFtpCommand implemenatation
231  *
232  *********************************************************************/
234 {
235 public:
238  ~QFtpCommand();
239 
240  int id;
243 
244  // If is_ba is true, ba is used; ba is never 0.
245  // Otherwise dev is used; dev can be 0 or not.
246  union {
249  } data;
250  bool is_ba;
251 
253 };
254 
256 
258  : command(cmd), rawCmds(raw), is_ba(true)
259 {
261  data.ba = new QByteArray(ba);
262 }
263 
265  : command(cmd), rawCmds(raw), is_ba(false)
266 {
268  data.dev = dev;
269 }
270 
272 {
273  if (is_ba)
274  delete data.ba;
275 }
276 
277 /**********************************************************************
278  *
279  * QFtpDTP implemenatation
280  *
281  *********************************************************************/
283  QObject(parent),
284  socket(0),
285  listener(this),
286  pi(p),
287  callWriteData(false)
288 {
289  clearData();
290  listener.setObjectName(QLatin1String("QFtpDTP active state server"));
291  connect(&listener, SIGNAL(newConnection()), SLOT(setupSocket()));
292 }
293 
295 {
296  is_ba = true;
297  data.ba = ba;
298 }
299 
301 {
302  is_ba = false;
303  data.dev = dev;
304 }
305 
307 {
308  bytesTotal = bytes;
309  bytesDone = 0;
311 }
312 
313 void QFtpDTP::connectToHost(const QString & host, quint16 port)
314 {
316 
317  if (socket) {
318  delete socket;
319  socket = 0;
320  }
321  socket = new QTcpSocket(this);
322 #ifndef QT_NO_BEARERMANAGEMENT
323  //copy network session down to the socket
324  socket->setProperty("_q_networksession", property("_q_networksession"));
325 #endif
326  socket->setObjectName(QLatin1String("QFtpDTP Passive state socket"));
330  connect(socket, SIGNAL(disconnected()), SLOT(socketConnectionClosed()));
332 
333  socket->connectToHost(host, port);
334 }
335 
337 {
338 #ifndef QT_NO_BEARERMANAGEMENT
339  //copy network session down to the socket
340  listener.setProperty("_q_networksession", property("_q_networksession"));
341 #endif
342  if (!listener.isListening() && !listener.listen(address, 0))
343  return -1;
344  return listener.serverPort();
345 }
346 
348 {
349  // This function is only interesting in Active transfer mode; it works
350  // around a limitation in QFtp's design by blocking, waiting for an
351  // incoming connection. For the default Passive mode, it does nothing.
352  if (listener.isListening())
354 }
355 
357 {
359 }
360 
362 {
364  return (qint64) bytesFromSocket.size();
365  return socket->bytesAvailable();
366 }
367 
369 {
370  qint64 read;
372  read = socket->read(data, maxlen);
373  } else {
374  read = qMin(maxlen, qint64(bytesFromSocket.size()));
375  memcpy(data, bytesFromSocket.data(), read);
376  bytesFromSocket.remove(0, read);
377  }
378 
379  bytesDone += read;
380  return read;
381 }
382 
384 {
385  QByteArray tmp;
387  tmp = socket->readAll();
388  bytesDone += tmp.size();
389  } else {
390  tmp = bytesFromSocket;
392  }
393  return tmp;
394 }
395 
397 {
398  if (!socket)
399  return;
400 
401  if (is_ba) {
402 #if defined(QFTPDTP_DEBUG)
403  qDebug("QFtpDTP::writeData: write %d bytes", data.ba->size());
404 #endif
405  if (data.ba->size() == 0)
407  else
408  socket->write(data.ba->data(), data.ba->size());
409 
410  socket->close();
411 
412  clearData();
413  } else if (data.dev) {
414  callWriteData = false;
415  const qint64 blockSize = 16*1024;
416  char buf[16*1024];
417  qint64 read = data.dev->read(buf, blockSize);
418 #if defined(QFTPDTP_DEBUG)
419  qDebug("QFtpDTP::writeData: write() of size %lli bytes", read);
420 #endif
421  if (read > 0) {
422  socket->write(buf, read);
423  } else if (read == -1 || (!data.dev->isSequential() && data.dev->atEnd())) {
424  // error or EOF
425  if (bytesDone == 0 && socket->bytesToWrite() == 0)
427  socket->close();
428  clearData();
429  }
430 
431  // do we continue uploading?
432  callWriteData = data.dev != 0;
433  }
434 }
435 
437 {
438  writeData();
439 }
440 
441 inline bool QFtpDTP::hasError() const
442 {
443  return !err.isNull();
444 }
445 
447 {
448  return err;
449 }
450 
451 inline void QFtpDTP::clearError()
452 {
453  err.clear();
454 }
455 
457 {
458 #if defined(QFTPDTP_DEBUG)
459  qDebug("QFtpDTP::abortConnection, bytesAvailable == %lli",
460  socket ? socket->bytesAvailable() : (qint64) 0);
461 #endif
462  callWriteData = false;
463  clearData();
464 
465  if (socket)
466  socket->abort();
467 }
468 
469 static void _q_fixupDateTime(QDateTime *dateTime, bool leapYear = false)
470 {
471  // Adjust for future tolerance.
472  const int futureTolerance = 86400;
473  if (dateTime->secsTo(QDateTime::currentDateTime()) < -futureTolerance) {
474  QDate d = dateTime->date();
475  if (leapYear) {
476  int prevLeapYear = d.year() - 1;
477 
478  while (!QDate::isLeapYear(prevLeapYear))
479  prevLeapYear--;
480 
481  d.setYMD(prevLeapYear, d.month(), d.day());
482  } else {
483  d.setYMD(d.year() - 1, d.month(), d.day());
484  }
485  dateTime->setDate(d);
486  }
487 }
488 
489 static void _q_parseUnixDir(const QStringList &tokens, const QString &userName, QUrlInfo *info)
490 {
491  // Unix style, 7 + 1 entries
492  // -rw-r--r-- 1 ftp ftp 17358091 Aug 10 2004 qt-x11-free-3.3.3.tar.gz
493  // drwxr-xr-x 3 ftp ftp 4096 Apr 14 2000 compiled-examples
494  // lrwxrwxrwx 1 ftp ftp 9 Oct 29 2005 qtscape -> qtmozilla
495  if (tokens.size() != 8)
496  return;
497 
498  char first = tokens.at(1).at(0).toLatin1();
499  if (first == 'd') {
500  info->setDir(true);
501  info->setFile(false);
502  info->setSymLink(false);
503  } else if (first == '-') {
504  info->setDir(false);
505  info->setFile(true);
506  info->setSymLink(false);
507  } else if (first == 'l') {
508  info->setDir(true);
509  info->setFile(false);
510  info->setSymLink(true);
511  }
512 
513  // Resolve filename
514  QString name = tokens.at(7);
515  if (info->isSymLink()) {
516  int linkPos = name.indexOf(QLatin1String(" ->"));
517  if (linkPos != -1)
518  name.resize(linkPos);
519  }
520  info->setName(name);
521 
522  // Resolve owner & group
523  info->setOwner(tokens.at(3));
524  info->setGroup(tokens.at(4));
525 
526  // Resolve size
527  info->setSize(tokens.at(5).toLongLong());
528 
529  QStringList formats;
530  formats << QLatin1String("MMM dd yyyy") << QLatin1String("MMM dd hh:mm") << QLatin1String("MMM d yyyy")
531  << QLatin1String("MMM d hh:mm") << QLatin1String("MMM d yyyy") << QLatin1String("MMM dd yyyy");
532 
533  QString dateString = tokens.at(6);
534  dateString[0] = dateString[0].toUpper();
535 
536  // Resolve the modification date by parsing all possible formats
537  QDateTime dateTime;
538  int n = 0;
539 #ifndef QT_NO_DATESTRING
540  do {
541  dateTime = QLocale::c().toDateTime(dateString, formats.at(n++));
542  } while (n < formats.size() && (!dateTime.isValid()));
543 #endif
544 
545  if (n == 2 || n == 4) {
546  // Guess the year.
547  dateTime.setDate(QDate(QDate::currentDate().year(),
548  dateTime.date().month(),
549  dateTime.date().day()));
550  _q_fixupDateTime(&dateTime);
551  }
552  if (dateTime.isValid())
553  info->setLastModified(dateTime);
554  else if (dateString.startsWith(QLatin1String("Feb 29"))) {
555 
556  // When the current year on the FTP server is a leap year and a
557  // file's last modified date is Feb 29th, and the current day on
558  // the FTP server is also Feb 29th, then the date can be in
559  // formats n==2 or n==4. toDateTime in that case defaults to 1900
560  // for the missing year. Feb 29 1900 is an invalid date and so
561  // wont be parsed. This adds an exception that handles it.
562 
563  int recentLeapYear;
564  QString timeString = dateString.mid(7);
565 
566  dateTime = QLocale::c().toDateTime(timeString, QLatin1String("hh:mm"));
567 
568  recentLeapYear = QDate::currentDate().year();
569 
570  while (!QDate::isLeapYear(recentLeapYear))
571  recentLeapYear--;
572 
573  dateTime.setDate(QDate(recentLeapYear, 2, 29));
574 
575  _q_fixupDateTime(&dateTime, true);
576  info->setLastModified(dateTime);
577  }
578 
579  // Resolve permissions
580  int permissions = 0;
581  QString p = tokens.at(2);
582  permissions |= (p[0] == QLatin1Char('r') ? QUrlInfo::ReadOwner : 0);
583  permissions |= (p[1] == QLatin1Char('w') ? QUrlInfo::WriteOwner : 0);
584  permissions |= (p[2] == QLatin1Char('x') ? QUrlInfo::ExeOwner : 0);
585  permissions |= (p[3] == QLatin1Char('r') ? QUrlInfo::ReadGroup : 0);
586  permissions |= (p[4] == QLatin1Char('w') ? QUrlInfo::WriteGroup : 0);
587  permissions |= (p[5] == QLatin1Char('x') ? QUrlInfo::ExeGroup : 0);
588  permissions |= (p[6] == QLatin1Char('r') ? QUrlInfo::ReadOther : 0);
589  permissions |= (p[7] == QLatin1Char('w') ? QUrlInfo::WriteOther : 0);
590  permissions |= (p[8] == QLatin1Char('x') ? QUrlInfo::ExeOther : 0);
591  info->setPermissions(permissions);
592 
593  bool isOwner = info->owner() == userName;
594  info->setReadable((permissions & QUrlInfo::ReadOther) || ((permissions & QUrlInfo::ReadOwner) && isOwner));
595  info->setWritable((permissions & QUrlInfo::WriteOther) || ((permissions & QUrlInfo::WriteOwner) && isOwner));
596 }
597 
598 static void _q_parseDosDir(const QStringList &tokens, const QString &userName, QUrlInfo *info)
599 {
600  // DOS style, 3 + 1 entries
601  // 01-16-02 11:14AM <DIR> epsgroup
602  // 06-05-03 03:19PM 1973 readme.txt
603  if (tokens.size() != 4)
604  return;
605 
606  Q_UNUSED(userName);
607 
608  QString name = tokens.at(3);
609  info->setName(name);
610  info->setSymLink(name.toLower().endsWith(QLatin1String(".lnk")));
611 
612  if (tokens.at(2) == QLatin1String("<DIR>")) {
613  info->setFile(false);
614  info->setDir(true);
615  } else {
616  info->setFile(true);
617  info->setDir(false);
618  info->setSize(tokens.at(2).toLongLong());
619  }
620 
621  // Note: We cannot use QFileInfo; permissions are for the server-side
622  // machine, and QFileInfo's behavior depends on the local platform.
623  int permissions = QUrlInfo::ReadOwner | QUrlInfo::WriteOwner
626  QString ext;
627  int extIndex = name.lastIndexOf(QLatin1Char('.'));
628  if (extIndex != -1)
629  ext = name.mid(extIndex + 1);
630  if (ext == QLatin1String("exe") || ext == QLatin1String("bat") || ext == QLatin1String("com"))
632  info->setPermissions(permissions);
633 
634  info->setReadable(true);
635  info->setWritable(info->isFile());
636 
637  QDateTime dateTime;
638 #ifndef QT_NO_DATESTRING
639  dateTime = QLocale::c().toDateTime(tokens.at(1), QLatin1String("MM-dd-yy hh:mmAP"));
640  if (dateTime.date().year() < 1971) {
641  dateTime.setDate(QDate(dateTime.date().year() + 100,
642  dateTime.date().month(),
643  dateTime.date().day()));
644  }
645 #endif
646 
647  info->setLastModified(dateTime);
648 
649 }
650 
651 bool QFtpDTP::parseDir(const QByteArray &buffer, const QString &userName, QUrlInfo *info)
652 {
653  if (buffer.isEmpty())
654  return false;
655 
656  QString bufferStr = QString::fromLatin1(buffer).trimmed();
657 
658  // Unix style FTP servers
659  QRegExp unixPattern(QLatin1String("^([\\-dl])([a-zA-Z\\-]{9,9})\\s+\\d+\\s+(\\S*)\\s+"
660  "(\\S*)\\s+(\\d+)\\s+(\\S+\\s+\\S+\\s+\\S+)\\s+(\\S.*)"));
661  if (unixPattern.indexIn(bufferStr) == 0) {
662  _q_parseUnixDir(unixPattern.capturedTexts(), userName, info);
663  return true;
664  }
665 
666  // DOS style FTP servers
667  QRegExp dosPattern(QLatin1String("^(\\d\\d-\\d\\d-\\d\\d\\ \\ \\d\\d:\\d\\d[AP]M)\\s+"
668  "(<DIR>|\\d+)\\s+(\\S.*)$"));
669  if (dosPattern.indexIn(bufferStr) == 0) {
670  _q_parseDosDir(dosPattern.capturedTexts(), userName, info);
671  return true;
672  }
673 
674  // Unsupported
675  return false;
676 }
677 
679 {
680  bytesDone = 0;
681 #if defined(QFTPDTP_DEBUG)
682  qDebug("QFtpDTP::connectState(CsConnected)");
683 #endif
685 }
686 
688 {
689  if (!socket)
690  return;
691 
692  if (pi->currentCommand().isEmpty()) {
693  socket->close();
694 #if defined(QFTPDTP_DEBUG)
695  qDebug("QFtpDTP::connectState(CsClosed)");
696 #endif
698  return;
699  }
700 
701  if (pi->abortState != QFtpPI::None) {
702  // discard data
703  socket->readAll();
704  return;
705  }
706 
707  if (pi->currentCommand().startsWith(QLatin1String("LIST"))) {
708  while (socket->canReadLine()) {
709  QUrlInfo i;
710  QByteArray line = socket->readLine();
711 #if defined(QFTPDTP_DEBUG)
712  qDebug("QFtpDTP read (list): '%s'", line.constData());
713 #endif
714  if (parseDir(line, QLatin1String(""), &i)) {
715  emit listInfo(i);
716  } else {
717  // some FTP servers don't return a 550 if the file or directory
718  // does not exist, but rather write a text to the data socket
719  // -- try to catch these cases
720  if (line.endsWith("No such file or directory\r\n"))
721  err = QString::fromLatin1(line);
722  }
723  }
724  } else {
725  if (!is_ba && data.dev) {
726  do {
727  QByteArray ba;
729  qint64 bytesRead = socket->read(ba.data(), ba.size());
730  if (bytesRead < 0) {
731  // a read following a readyRead() signal will
732  // never fail.
733  return;
734  }
735  ba.resize(bytesRead);
736  bytesDone += bytesRead;
737 #if defined(QFTPDTP_DEBUG)
738  qDebug("QFtpDTP read: %lli bytes (total %lli bytes)", bytesRead, bytesDone);
739 #endif
740  if (data.dev) // make sure it wasn't deleted in the slot
741  data.dev->write(ba);
743 
744  // Need to loop; dataTransferProgress is often connected to
745  // slots that update the GUI (e.g., progress bar values), and
746  // if events are processed, more data may have arrived.
747  } while (socket->bytesAvailable());
748  } else {
749 #if defined(QFTPDTP_DEBUG)
750  qDebug("QFtpDTP readyRead: %lli bytes available (total %lli bytes read)",
752 #endif
754  emit readyRead();
755  }
756  }
757 }
758 
760 {
762 #if defined(QFTPDTP_DEBUG)
763  qDebug("QFtpDTP::connectState(CsHostNotFound)");
764 #endif
766  } else if (e == QTcpSocket::ConnectionRefusedError) {
767 #if defined(QFTPDTP_DEBUG)
768  qDebug("QFtpDTP::connectState(CsConnectionRefused)");
769 #endif
771  }
772 }
773 
775 {
776  if (!is_ba && data.dev) {
777  clearData();
778  }
779 
781 #if defined(QFTPDTP_DEBUG)
782  qDebug("QFtpDTP::connectState(CsClosed)");
783 #endif
785 }
786 
788 {
789  bytesDone += bytes;
790 #if defined(QFTPDTP_DEBUG)
791  qDebug("QFtpDTP::bytesWritten(%lli)", bytesDone);
792 #endif
794  if (callWriteData)
795  writeData();
796 }
797 
799 {
801  socket->setObjectName(QLatin1String("QFtpDTP Active state socket"));
805  connect(socket, SIGNAL(disconnected()), SLOT(socketConnectionClosed()));
807 
808  listener.close();
809 }
810 
812 {
813  is_ba = false;
814  data.dev = 0;
815 }
816 
817 /**********************************************************************
818  *
819  * QFtpPI implemenatation
820  *
821  *********************************************************************/
823  QObject(parent),
824  rawCommand(false),
825  transferConnectionExtended(true),
826  dtp(this),
827  commandSocket(0),
828  state(Begin), abortState(None),
829  currentCmd(QString()),
830  waitForDtpToConnect(false),
831  waitForDtpToClose(false)
832 {
833  commandSocket.setObjectName(QLatin1String("QFtpPI_socket"));
835  SLOT(hostFound()));
837  SLOT(connected()));
838  connect(&commandSocket, SIGNAL(disconnected()),
841  SLOT(readyRead()));
844 
845  connect(&dtp, SIGNAL(connectState(int)),
846  SLOT(dtpConnectState(int)));
847 }
848 
849 void QFtpPI::connectToHost(const QString &host, quint16 port)
850 {
852 #ifndef QT_NO_BEARERMANAGEMENT
853  //copy network session down to the socket & DTP
854  commandSocket.setProperty("_q_networksession", property("_q_networksession"));
855  dtp.setProperty("_q_networksession", property("_q_networksession"));
856 #endif
857  commandSocket.connectToHost(host, port);
858 }
859 
860 /*
861  Sends the sequence of commands \a cmds to the FTP server. When the commands
862  are all done the finished() signal is emitted. When an error occurs, the
863  error() signal is emitted.
864 
865  If there are pending commands in the queue this functions returns false and
866  the \a cmds are not added to the queue; otherwise it returns true.
867 */
869 {
870  if (!pendingCommands.isEmpty())
871  return false;
872 
874  emit error(QFtp::NotConnected, QFtp::tr("Not connected"));
875  return true; // there are no pending commands
876  }
877 
878  pendingCommands = cmds;
879  startNextCmd();
880  return true;
881 }
882 
884 {
887  currentCmd.clear();
888  state = Idle;
889 }
890 
892 {
894 
895  if (abortState != None)
896  // ABOR already sent
897  return;
898 
899  if (currentCmd.isEmpty())
900  return; //no command in progress
901 
902  if (currentCmd.startsWith(QLatin1String("STOR "))) {
904 #if defined(QFTPPI_DEBUG)
905  qDebug("QFtpPI send: ABOR");
906 #endif
907  commandSocket.write("ABOR\r\n", 6);
908 
910  } else {
911  //Deviation from RFC 959:
912  //Most FTP servers do not support ABOR, or require the telnet
913  //IP & synch sequence (TCP urgent data) which is not supported by QTcpSocket.
914  //Following what most FTP clients do, just reset the data connection and wait for 426
917  }
918 }
919 
921 {
923 }
924 
926 {
927  state = Begin;
928 #if defined(QFTPPI_DEBUG)
929 // qDebug("QFtpPI state: %d [connected()]", state);
930 #endif
931  // try to improve performance by setting TCP_NODELAY
933 
935 }
936 
938 {
941 }
942 
944 {
946 }
947 
949 {
953  QFtp::tr("Host %1 not found").arg(commandSocket.peerName()));
954  } else if (e == QTcpSocket::ConnectionRefusedError) {
957  QFtp::tr("Connection refused to host %1").arg(commandSocket.peerName()));
958  } else if (e == QTcpSocket::SocketTimeoutError) {
961  QFtp::tr("Connection timed out to host %1").arg(commandSocket.peerName()));
962  }
963 }
964 
966 {
967  if (waitForDtpToClose)
968  return;
969 
970  while (commandSocket.canReadLine()) {
971  // read line with respect to line continuation
973  if (replyText.isEmpty()) {
974  if (line.length() < 3) {
975  // protocol error
976  return;
977  }
978  const int lowerLimit[3] = {1,0,0};
979  const int upperLimit[3] = {5,5,9};
980  for (int i=0; i<3; i++) {
981  replyCode[i] = line[i].digitValue();
982  if (replyCode[i]<lowerLimit[i] || replyCode[i]>upperLimit[i]) {
983  // protocol error
984  return;
985  }
986  }
987  }
988  QString endOfMultiLine;
989  endOfMultiLine[0] = '0' + replyCode[0];
990  endOfMultiLine[1] = '0' + replyCode[1];
991  endOfMultiLine[2] = '0' + replyCode[2];
992  endOfMultiLine[3] = QLatin1Char(' ');
993  QString lineCont(endOfMultiLine);
994  lineCont[3] = QLatin1Char('-');
995  QString lineLeft4 = line.left(4);
996 
997  while (lineLeft4 != endOfMultiLine) {
998  if (lineLeft4 == lineCont)
999  replyText += line.mid(4); // strip 'xyz-'
1000  else
1001  replyText += line;
1002  if (!commandSocket.canReadLine())
1003  return;
1005  lineLeft4 = line.left(4);
1006  }
1007  replyText += line.mid(4); // strip reply code 'xyz '
1008  if (replyText.endsWith(QLatin1String("\r\n")))
1009  replyText.chop(2);
1010 
1011  if (processReply())
1012  replyText = QLatin1String("");
1013  }
1014 }
1015 
1016 /*
1017  Process a reply from the FTP server.
1018 
1019  Returns true if the reply was processed or false if the reply has to be
1020  processed at a later point.
1021 */
1023 {
1024 #if defined(QFTPPI_DEBUG)
1025 // qDebug("QFtpPI state: %d [processReply() begin]", state);
1026  if (replyText.length() < 400)
1027  qDebug("QFtpPI recv: %d %s", 100*replyCode[0]+10*replyCode[1]+replyCode[2], replyText.toLatin1().constData());
1028  else
1029  qDebug("QFtpPI recv: %d (text skipped)", 100*replyCode[0]+10*replyCode[1]+replyCode[2]);
1030 #endif
1031 
1032  int replyCodeInt = 100*replyCode[0] + 10*replyCode[1] + replyCode[2];
1033 
1034  // process 226 replies ("Closing Data Connection") only when the data
1035  // connection is really closed to avoid short reads of the DTP
1036  if (replyCodeInt == 226 || (replyCodeInt == 250 && currentCmd.startsWith(QLatin1String("RETR")))) {
1038  waitForDtpToClose = true;
1039  return false;
1040  }
1041  }
1042 
1043  switch (abortState) {
1044  case AbortStarted:
1046  break;
1047  case WaitForAbortToFinish:
1048  abortState = None;
1049  return true;
1050  default:
1051  break;
1052  }
1053 
1054  // get new state
1055  static const State table[5] = {
1056  /* 1yz 2yz 3yz 4yz 5yz */
1057  Waiting, Success, Idle, Failure, Failure
1058  };
1059  switch (state) {
1060  case Begin:
1061  if (replyCode[0] == 1) {
1062  return true;
1063  } else if (replyCode[0] == 2) {
1064  state = Idle;
1065  emit finished(QFtp::tr("Connected to host %1").arg(commandSocket.peerName()));
1066  break;
1067  }
1068  // reply codes not starting with 1 or 2 are not handled.
1069  return true;
1070  case Waiting:
1071  if (static_cast<signed char>(replyCode[0]) < 0 || replyCode[0] > 5)
1072  state = Failure;
1073  else
1074 #if defined(Q_OS_IRIX) && defined(Q_CC_GNU)
1075  {
1076  // work around a crash on 64 bit gcc IRIX
1077  State *t = (State *) table;
1078  state = t[replyCode[0] - 1];
1079  }
1080 #else
1081  if (replyCodeInt == 202)
1082  state = Failure;
1083  else
1084  state = table[replyCode[0] - 1];
1085 #endif
1086  break;
1087  default:
1088  // ignore unrequested message
1089  return true;
1090  }
1091 #if defined(QFTPPI_DEBUG)
1092 // qDebug("QFtpPI state: %d [processReply() intermediate]", state);
1093 #endif
1094 
1095  // special actions on certain replies
1096  emit rawFtpReply(replyCodeInt, replyText);
1097  if (rawCommand) {
1098  rawCommand = false;
1099  } else if (replyCodeInt == 227) {
1100  // 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2)
1101  // rfc959 does not define this response precisely, and gives
1102  // both examples where the parenthesis are used, and where
1103  // they are missing. We need to scan for the address and host
1104  // info.
1105  QRegExp addrPortPattern(QLatin1String("(\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+)"));
1106  if (addrPortPattern.indexIn(replyText) == -1) {
1107 #if defined(QFTPPI_DEBUG)
1108  qDebug("QFtp: bad 227 response -- address and port information missing");
1109 #endif
1110  // this error should be reported
1111  } else {
1112  QStringList lst = addrPortPattern.capturedTexts();
1113  QString host = lst[1] + QLatin1Char('.') + lst[2] + QLatin1Char('.') + lst[3] + QLatin1Char('.') + lst[4];
1114  quint16 port = (lst[5].toUInt() << 8) + lst[6].toUInt();
1115  waitForDtpToConnect = true;
1116  dtp.connectToHost(host, port);
1117  }
1118  } else if (replyCodeInt == 229) {
1119  // 229 Extended Passive mode OK (|||10982|)
1120  int portPos = replyText.indexOf(QLatin1Char('('));
1121  if (portPos == -1) {
1122 #if defined(QFTPPI_DEBUG)
1123  qDebug("QFtp: bad 229 response -- port information missing");
1124 #endif
1125  // this error should be reported
1126  } else {
1127  ++portPos;
1128  QChar delimiter = replyText.at(portPos);
1129  QStringList epsvParameters = replyText.mid(portPos).split(delimiter);
1130 
1131  waitForDtpToConnect = true;
1133  epsvParameters.at(3).toInt());
1134  }
1135 
1136  } else if (replyCodeInt == 230) {
1137  if (currentCmd.startsWith(QLatin1String("USER ")) && pendingCommands.count()>0 &&
1139  // no need to send the PASS -- we are already logged in
1141  }
1142  // 230 User logged in, proceed.
1144  } else if (replyCodeInt == 213) {
1145  // 213 File status.
1146  if (currentCmd.startsWith(QLatin1String("SIZE ")))
1148  } else if (replyCode[0]==1 && currentCmd.startsWith(QLatin1String("STOR "))) {
1150  dtp.writeData();
1151  }
1152 
1153  // react on new state
1154  switch (state) {
1155  case Begin:
1156  // should never happen
1157  break;
1158  case Success:
1159  // success handling
1160  state = Idle;
1161  // no break!
1162  case Idle:
1163  if (dtp.hasError()) {
1165  dtp.clearError();
1166  }
1167  startNextCmd();
1168  break;
1169  case Waiting:
1170  // do nothing
1171  break;
1172  case Failure:
1173  // If the EPSV or EPRT commands fail, replace them with
1174  // the old PASV and PORT instead and try again.
1175  if (currentCmd.startsWith(QLatin1String("EPSV"))) {
1177  pendingCommands.prepend(QLatin1String("PASV\r\n"));
1178  } else if (currentCmd.startsWith(QLatin1String("EPRT"))) {
1180  pendingCommands.prepend(QLatin1String("PORT\r\n"));
1181  } else {
1183  }
1184  if (state != Waiting) {
1185  state = Idle;
1186  startNextCmd();
1187  }
1188  break;
1189  }
1190 #if defined(QFTPPI_DEBUG)
1191 // qDebug("QFtpPI state: %d [processReply() end]", state);
1192 #endif
1193  return true;
1194 }
1195 
1196 /*
1197  Starts next pending command. Returns false if there are no pending commands,
1198  otherwise it returns true.
1199 */
1201 {
1202  if (waitForDtpToConnect)
1203  // don't process any new commands until we are connected
1204  return true;
1205 
1206 #if defined(QFTPPI_DEBUG)
1207  if (state != Idle)
1208  qDebug("QFtpPI startNextCmd: Internal error! QFtpPI called in non-Idle state %d", state);
1209 #endif
1210  if (pendingCommands.isEmpty()) {
1211  currentCmd.clear();
1213  return false;
1214  }
1216 
1217  // PORT and PASV are edited in-place, depending on whether we
1218  // should try the extended transfer connection commands EPRT and
1219  // EPSV. The PORT command also triggers setting up a listener, and
1220  // the address/port arguments are edited in.
1222  if (currentCmd.startsWith(QLatin1String("PORT"))) {
1224  int port = dtp.setupListener(address);
1225  currentCmd = QLatin1String("EPRT |");
1226  currentCmd += (address.protocol() == QTcpSocket::IPv4Protocol) ? QLatin1Char('1') : QLatin1Char('2');
1227  currentCmd += QLatin1Char('|') + address.toString() + QLatin1Char('|') + QString::number(port);
1228  currentCmd += QLatin1Char('|');
1229  } else if (address.protocol() == QTcpSocket::IPv4Protocol) {
1230  int port = dtp.setupListener(address);
1231  QString portArg;
1232  quint32 ip = address.toIPv4Address();
1233  portArg += QString::number((ip & 0xff000000) >> 24);
1234  portArg += QLatin1Char(',') + QString::number((ip & 0xff0000) >> 16);
1235  portArg += QLatin1Char(',') + QString::number((ip & 0xff00) >> 8);
1236  portArg += QLatin1Char(',') + QString::number(ip & 0xff);
1237  portArg += QLatin1Char(',') + QString::number((port & 0xff00) >> 8);
1238  portArg += QLatin1Char(',') + QString::number(port & 0xff);
1239 
1240  currentCmd = QLatin1String("PORT ");
1241  currentCmd += portArg;
1242  } else {
1243  // No IPv6 connection can be set up with the PORT
1244  // command.
1245  return false;
1246  }
1247 
1248  currentCmd += QLatin1String("\r\n");
1249  } else if (currentCmd.startsWith(QLatin1String("PASV"))) {
1251  currentCmd = QLatin1String("EPSV\r\n");
1252  }
1253 
1255 #if defined(QFTPPI_DEBUG)
1256  qDebug("QFtpPI send: %s", currentCmd.left(currentCmd.length()-2).toLatin1().constData());
1257 #endif
1258  state = Waiting;
1260  return true;
1261 }
1262 
1264 {
1265  switch (s) {
1266  case QFtpDTP::CsClosed:
1267  if (waitForDtpToClose) {
1268  // there is an unprocessed reply
1269  if (processReply())
1270  replyText = QLatin1String("");
1271  else
1272  return;
1273  }
1274  waitForDtpToClose = false;
1275  readyRead();
1276  return;
1277  case QFtpDTP::CsConnected:
1278  waitForDtpToConnect = false;
1279  startNextCmd();
1280  return;
1284  QFtp::tr("Connection refused for data connection"));
1285  startNextCmd();
1286  return;
1287  default:
1288  return;
1289  }
1290 }
1291 
1292 /**********************************************************************
1293  *
1294  * QFtpPrivate
1295  *
1296  *********************************************************************/
1297 
1299 #include <private/qobject_p.h>
1301 
1303 {
1305 public:
1306 
1307  inline QFtpPrivate() : close_waitForStateChange(false), state(QFtp::Unconnected),
1308  transferMode(QFtp::Passive), error(QFtp::NoError)
1309  { }
1310 
1311  ~QFtpPrivate() { while (!pending.isEmpty()) delete pending.takeFirst(); }
1312 
1313  // private slots
1314  void _q_startNextCommand();
1315  void _q_piFinished(const QString&);
1316  void _q_piError(int, const QString&);
1317  void _q_piConnectState(int);
1318  void _q_piFtpReply(int, const QString&);
1319 
1320  int addCommand(QFtpCommand *cmd);
1321 
1329 
1334 };
1335 
1337 {
1338  pending.append(cmd);
1339 
1340  if (pending.count() == 1) {
1341  // don't emit the commandStarted() signal before the ID is returned
1342  QTimer::singleShot(0, q_func(), SLOT(_q_startNextCommand()));
1343  }
1344  return cmd->id;
1345 }
1346 
1347 /**********************************************************************
1348  *
1349  * QFtp implementation
1350  *
1351  *********************************************************************/
1462  : QObject(*new QFtpPrivate, parent)
1463 {
1464  Q_D(QFtp);
1465  d->errorString = tr("Unknown error");
1466 
1467  connect(&d->pi, SIGNAL(connectState(int)),
1468  SLOT(_q_piConnectState(int)));
1469  connect(&d->pi, SIGNAL(finished(QString)),
1470  SLOT(_q_piFinished(QString)));
1471  connect(&d->pi, SIGNAL(error(int,QString)),
1472  SLOT(_q_piError(int,QString)));
1473  connect(&d->pi, SIGNAL(rawFtpReply(int,QString)),
1474  SLOT(_q_piFtpReply(int,QString)));
1475 
1476  connect(&d->pi.dtp, SIGNAL(readyRead()),
1477  SIGNAL(readyRead()));
1480  connect(&d->pi.dtp, SIGNAL(listInfo(QUrlInfo)),
1482 }
1483 
1484 #ifdef QT3_SUPPORT
1485 
1489 QFtp::QFtp(QObject *parent, const char *name)
1490  : QObject(*new QFtpPrivate, parent)
1491 {
1492  Q_D(QFtp);
1494  d->errorString = tr("Unknown error");
1495 
1496  connect(&d->pi, SIGNAL(connectState(int)),
1497  SLOT(_q_piConnectState(int)));
1498  connect(&d->pi, SIGNAL(finished(QString)),
1499  SLOT(_q_piFinished(QString)));
1500  connect(&d->pi, SIGNAL(error(int,QString)),
1501  SLOT(_q_piError(int,QString)));
1502  connect(&d->pi, SIGNAL(rawFtpReply(int,QString)),
1503  SLOT(_q_piFtpReply(int,QString)));
1504 
1505  connect(&d->pi.dtp, SIGNAL(readyRead()),
1506  SIGNAL(readyRead()));
1509  connect(&d->pi.dtp, SIGNAL(listInfo(QUrlInfo)),
1511 }
1512 #endif
1513 
1763 int QFtp::connectToHost(const QString &host, quint16 port)
1764 {
1765  QStringList cmds;
1766  cmds << host;
1767  cmds << QString::number((uint)port);
1768  int id = d_func()->addCommand(new QFtpCommand(ConnectToHost, cmds));
1769  d_func()->pi.transferConnectionExtended = true;
1770  return id;
1771 }
1772 
1791 int QFtp::login(const QString &user, const QString &password)
1792 {
1793  QStringList cmds;
1794  cmds << (QLatin1String("USER ") + (user.isNull() ? QLatin1String("anonymous") : user) + QLatin1String("\r\n"));
1795  cmds << (QLatin1String("PASS ") + (password.isNull() ? QLatin1String("anonymous@") : password) + QLatin1String("\r\n"));
1796  return d_func()->addCommand(new QFtpCommand(Login, cmds));
1797 }
1798 
1818 {
1819  return d_func()->addCommand(new QFtpCommand(Close, QStringList(QLatin1String("QUIT\r\n"))));
1820 }
1821 
1828 {
1829  int id = d_func()->addCommand(new QFtpCommand(SetTransferMode, QStringList()));
1830  d_func()->pi.transferConnectionExtended = true;
1831  d_func()->transferMode = mode;
1832  return id;
1833 }
1834 
1842 int QFtp::setProxy(const QString &host, quint16 port)
1843 {
1844  QStringList args;
1845  args << host << QString::number(port);
1846  return d_func()->addCommand(new QFtpCommand(SetProxy, args));
1847 }
1848 
1866 int QFtp::list(const QString &dir)
1867 {
1868  QStringList cmds;
1869  cmds << QLatin1String("TYPE A\r\n");
1870  cmds << QLatin1String(d_func()->transferMode == Passive ? "PASV\r\n" : "PORT\r\n");
1871  if (dir.isEmpty())
1872  cmds << QLatin1String("LIST\r\n");
1873  else
1874  cmds << (QLatin1String("LIST ") + dir + QLatin1String("\r\n"));
1875  return d_func()->addCommand(new QFtpCommand(List, cmds));
1876 }
1877 
1892 int QFtp::cd(const QString &dir)
1893 {
1894  return d_func()->addCommand(new QFtpCommand(Cd, QStringList(QLatin1String("CWD ") + dir + QLatin1String("\r\n"))));
1895 }
1896 
1938 {
1939  QStringList cmds;
1940  if (type == Binary)
1941  cmds << QLatin1String("TYPE I\r\n");
1942  else
1943  cmds << QLatin1String("TYPE A\r\n");
1944  cmds << QLatin1String("SIZE ") + file + QLatin1String("\r\n");
1945  cmds << QLatin1String(d_func()->transferMode == Passive ? "PASV\r\n" : "PORT\r\n");
1946  cmds << QLatin1String("RETR ") + file + QLatin1String("\r\n");
1947  return d_func()->addCommand(new QFtpCommand(Get, cmds, dev));
1948 }
1949 
1978 {
1979  QStringList cmds;
1980  if (type == Binary)
1981  cmds << QLatin1String("TYPE I\r\n");
1982  else
1983  cmds << QLatin1String("TYPE A\r\n");
1984  cmds << QLatin1String(d_func()->transferMode == Passive ? "PASV\r\n" : "PORT\r\n");
1985  cmds << QLatin1String("ALLO ") + QString::number(data.size()) + QLatin1String("\r\n");
1986  cmds << QLatin1String("STOR ") + file + QLatin1String("\r\n");
1987  return d_func()->addCommand(new QFtpCommand(Put, cmds, data));
1988 }
1989 
2005 {
2006  QStringList cmds;
2007  if (type == Binary)
2008  cmds << QLatin1String("TYPE I\r\n");
2009  else
2010  cmds << QLatin1String("TYPE A\r\n");
2011  cmds << QLatin1String(d_func()->transferMode == Passive ? "PASV\r\n" : "PORT\r\n");
2012  if (!dev->isSequential())
2013  cmds << QLatin1String("ALLO ") + QString::number(dev->size()) + QLatin1String("\r\n");
2014  cmds << QLatin1String("STOR ") + file + QLatin1String("\r\n");
2015  return d_func()->addCommand(new QFtpCommand(Put, cmds, dev));
2016 }
2017 
2032 int QFtp::remove(const QString &file)
2033 {
2034  return d_func()->addCommand(new QFtpCommand(Remove, QStringList(QLatin1String("DELE ") + file + QLatin1String("\r\n"))));
2035 }
2036 
2051 int QFtp::mkdir(const QString &dir)
2052 {
2053  return d_func()->addCommand(new QFtpCommand(Mkdir, QStringList(QLatin1String("MKD ") + dir + QLatin1String("\r\n"))));
2054 }
2055 
2070 int QFtp::rmdir(const QString &dir)
2071 {
2072  return d_func()->addCommand(new QFtpCommand(Rmdir, QStringList(QLatin1String("RMD ") + dir + QLatin1String("\r\n"))));
2073 }
2074 
2089 int QFtp::rename(const QString &oldname, const QString &newname)
2090 {
2091  QStringList cmds;
2092  cmds << QLatin1String("RNFR ") + oldname + QLatin1String("\r\n");
2093  cmds << QLatin1String("RNTO ") + newname + QLatin1String("\r\n");
2094  return d_func()->addCommand(new QFtpCommand(Rename, cmds));
2095 }
2096 
2115 int QFtp::rawCommand(const QString &command)
2116 {
2117  QString cmd = command.trimmed() + QLatin1String("\r\n");
2118  return d_func()->addCommand(new QFtpCommand(RawCommand, QStringList(cmd)));
2119 }
2120 
2128 {
2129  return d_func()->pi.dtp.bytesAvailable();
2130 }
2131 
2144 {
2145  return d_func()->pi.dtp.read(data, maxlen);
2146 }
2147 
2155 {
2156  return d_func()->pi.dtp.readAll();
2157 }
2158 
2189 {
2190  if (d_func()->pending.isEmpty())
2191  return;
2192 
2194  d_func()->pi.abort();
2195 }
2196 
2203 int QFtp::currentId() const
2204 {
2205  if (d_func()->pending.isEmpty())
2206  return 0;
2207  return d_func()->pending.first()->id;
2208 }
2209 
2217 {
2218  if (d_func()->pending.isEmpty())
2219  return None;
2220  return d_func()->pending.first()->command;
2221 }
2222 
2234 {
2235  if (d_func()->pending.isEmpty())
2236  return 0;
2237  QFtpCommand *c = d_func()->pending.first();
2238  if (c->is_ba)
2239  return 0;
2240  return c->data.dev;
2241 }
2242 
2253 {
2254  return d_func()->pending.count() > 1;
2255 }
2256 
2265 {
2266  // delete all entires except the first one
2267  while (d_func()->pending.count() > 1)
2268  delete d_func()->pending.takeLast();
2269 }
2270 
2278 {
2279  return d_func()->state;
2280 }
2281 
2290 {
2291  return d_func()->error;
2292 }
2293 
2306 {
2307  return d_func()->errorString;
2308 }
2309 
2313 {
2314  Q_Q(QFtp);
2315  if (pending.isEmpty())
2316  return;
2317  QFtpCommand *c = pending.first();
2318 
2319  error = QFtp::NoError;
2320  errorString = QT_TRANSLATE_NOOP(QFtp, QLatin1String("Unknown error"));
2321 
2322  if (q->bytesAvailable())
2323  q->readAll(); // clear the data
2324  emit q->commandStarted(c->id);
2325 
2326  // Proxy support, replace the Login argument in place, then fall
2327  // through.
2328  if (c->command == QFtp::Login && !proxyHost.isEmpty()) {
2329  QString loginString = c->rawCmds.first().trimmed();
2330  loginString += QLatin1Char('@') + host;
2331  if (port && port != 21)
2332  loginString += QLatin1Char(':') + QString::number(port);
2333  loginString += QLatin1String("\r\n");
2334  c->rawCmds[0] = loginString;
2335  }
2336 
2337  if (c->command == QFtp::SetTransferMode) {
2338  _q_piFinished(QLatin1String("Transfer mode set"));
2339  } else if (c->command == QFtp::SetProxy) {
2340  proxyHost = c->rawCmds[0];
2341  proxyPort = c->rawCmds[1].toUInt();
2342  c->rawCmds.clear();
2343  _q_piFinished(QLatin1String("Proxy set to ") + proxyHost + QLatin1Char(':') + QString::number(proxyPort));
2344  } else if (c->command == QFtp::ConnectToHost) {
2345 #ifndef QT_NO_BEARERMANAGEMENT
2346  //copy network session down to the PI
2347  pi.setProperty("_q_networksession", q->property("_q_networksession"));
2348 #endif
2349  if (!proxyHost.isEmpty()) {
2350  host = c->rawCmds[0];
2351  port = c->rawCmds[1].toUInt();
2352  pi.connectToHost(proxyHost, proxyPort);
2353  } else {
2354  pi.connectToHost(c->rawCmds[0], c->rawCmds[1].toUInt());
2355  }
2356  } else {
2357  if (c->command == QFtp::Put) {
2358  if (c->is_ba) {
2359  pi.dtp.setData(c->data.ba);
2360  pi.dtp.setBytesTotal(c->data.ba->size());
2361  } else if (c->data.dev && (c->data.dev->isOpen() || c->data.dev->open(QIODevice::ReadOnly))) {
2362  pi.dtp.setDevice(c->data.dev);
2363  if (c->data.dev->isSequential()) {
2364  pi.dtp.setBytesTotal(0);
2365  pi.dtp.connect(c->data.dev, SIGNAL(readyRead()), SLOT(dataReadyRead()));
2366  pi.dtp.connect(c->data.dev, SIGNAL(readChannelFinished()), SLOT(dataReadyRead()));
2367  } else {
2368  pi.dtp.setBytesTotal(c->data.dev->size());
2369  }
2370  }
2371  } else if (c->command == QFtp::Get) {
2372  if (!c->is_ba && c->data.dev) {
2373  pi.dtp.setDevice(c->data.dev);
2374  }
2375  } else if (c->command == QFtp::Close) {
2376  state = QFtp::Closing;
2377  emit q->stateChanged(state);
2378  }
2379  pi.sendCommands(c->rawCmds);
2380  }
2381 }
2382 
2386 {
2387  if (pending.isEmpty())
2388  return;
2389  QFtpCommand *c = pending.first();
2390 
2391  if (c->command == QFtp::Close) {
2392  // The order of in which the slots are called is arbitrary, so
2393  // disconnect the SIGNAL-SIGNAL temporary to make sure that we
2394  // don't get the commandFinished() signal before the stateChanged()
2395  // signal.
2396  if (state != QFtp::Unconnected) {
2397  close_waitForStateChange = true;
2398  return;
2399  }
2400  }
2401  emit q_func()->commandFinished(c->id, false);
2402  pending.removeFirst();
2403 
2404  delete c;
2405 
2406  if (pending.isEmpty()) {
2407  emit q_func()->done(false);
2408  } else {
2409  _q_startNextCommand();
2410  }
2411 }
2412 
2415 void QFtpPrivate::_q_piError(int errorCode, const QString &text)
2416 {
2417  Q_Q(QFtp);
2418 
2419  if (pending.isEmpty()) {
2420  qWarning("QFtpPrivate::_q_piError was called without pending command!");
2421  return;
2422  }
2423 
2424  QFtpCommand *c = pending.first();
2425 
2426  // non-fatal errors
2427  if (c->command == QFtp::Get && pi.currentCommand().startsWith(QLatin1String("SIZE "))) {
2428  pi.dtp.setBytesTotal(0);
2429  return;
2430  } else if (c->command==QFtp::Put && pi.currentCommand().startsWith(QLatin1String("ALLO "))) {
2431  return;
2432  }
2433 
2434  error = QFtp::Error(errorCode);
2435  switch (q->currentCommand()) {
2436  case QFtp::ConnectToHost:
2437  errorString = QString::fromLatin1(QT_TRANSLATE_NOOP("QFtp", "Connecting to host failed:\n%1"))
2438  .arg(text);
2439  break;
2440  case QFtp::Login:
2441  errorString = QString::fromLatin1(QT_TRANSLATE_NOOP("QFtp", "Login failed:\n%1"))
2442  .arg(text);
2443  break;
2444  case QFtp::List:
2445  errorString = QString::fromLatin1(QT_TRANSLATE_NOOP("QFtp", "Listing directory failed:\n%1"))
2446  .arg(text);
2447  break;
2448  case QFtp::Cd:
2449  errorString = QString::fromLatin1(QT_TRANSLATE_NOOP("QFtp", "Changing directory failed:\n%1"))
2450  .arg(text);
2451  break;
2452  case QFtp::Get:
2453  errorString = QString::fromLatin1(QT_TRANSLATE_NOOP("QFtp", "Downloading file failed:\n%1"))
2454  .arg(text);
2455  break;
2456  case QFtp::Put:
2457  errorString = QString::fromLatin1(QT_TRANSLATE_NOOP("QFtp", "Uploading file failed:\n%1"))
2458  .arg(text);
2459  break;
2460  case QFtp::Remove:
2461  errorString = QString::fromLatin1(QT_TRANSLATE_NOOP("QFtp", "Removing file failed:\n%1"))
2462  .arg(text);
2463  break;
2464  case QFtp::Mkdir:
2465  errorString = QString::fromLatin1(QT_TRANSLATE_NOOP("QFtp", "Creating directory failed:\n%1"))
2466  .arg(text);
2467  break;
2468  case QFtp::Rmdir:
2469  errorString = QString::fromLatin1(QT_TRANSLATE_NOOP("QFtp", "Removing directory failed:\n%1"))
2470  .arg(text);
2471  break;
2472  default:
2473  errorString = text;
2474  break;
2475  }
2476 
2477  pi.clearPendingCommands();
2478  q->clearPendingCommands();
2479  emit q->commandFinished(c->id, true);
2480 
2481  pending.removeFirst();
2482  delete c;
2483  if (pending.isEmpty())
2484  emit q->done(true);
2485  else
2486  _q_startNextCommand();
2487 }
2488 
2491 void QFtpPrivate::_q_piConnectState(int connectState)
2492 {
2493  state = QFtp::State(connectState);
2494  emit q_func()->stateChanged(state);
2495  if (close_waitForStateChange) {
2496  close_waitForStateChange = false;
2497  _q_piFinished(QLatin1String(QT_TRANSLATE_NOOP("QFtp", "Connection closed")));
2498  }
2499 }
2500 
2504 {
2505  if (q_func()->currentCommand() == QFtp::RawCommand) {
2506  pi.rawCommand = true;
2507  emit q_func()->rawCommandReply(code, text);
2508  }
2509 }
2510 
2515 {
2516  abort();
2517  close();
2518 }
2519 
2521 
2522 #include "qftp.moc"
2523 
2524 #include "moc_qftp.cpp"
2525 
2526 #endif // QT_NO_FTP
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qstring.cpp:6448
void socketConnectionClosed()
Definition: qftp.cpp:774
virtual void setSize(qint64 size)
Specifies the size of the URL.
Definition: qurlinfo.cpp:374
double d
Definition: qnumeric_p.h:62
const int blockSize
virtual void setFile(bool b)
If b is true then the URL is set to be a file; if is false then the URL is set not to be a file (whic...
Definition: qurlinfo.cpp:272
QString owner() const
Returns the owner of the URL.
Definition: qurlinfo.cpp:495
bool transferConnectionExtended
Definition: qftp.cpp:172
qlonglong toLongLong(bool *ok=0, int base=10) const
Returns the string converted to a long long using base base, which is 10 by default and must be betwe...
Definition: qstring.cpp:5943
virtual qint64 size() const
For open random-access devices, this function returns the size of the device.
Definition: qiodevice.cpp:642
QString peerName() const
Returns the name of the peer as specified by connectToHost(), or an empty QString if connectToHost() ...
bool isFile() const
Returns true if the URL is a file; otherwise returns false.
Definition: qurlinfo.cpp:573
int type
Definition: qmetatype.cpp:239
QFtp::Command command
Definition: qftp.cpp:241
qint64 bytesAvailable() const
Definition: qftp.cpp:361
int connectToHost(const QString &host, quint16 port=21)
Connects to the FTP server host using port port.
Definition: qftp.cpp:1763
static mach_timebase_info_data_t info
bool callWriteData
Definition: qftp.cpp:133
unsigned char c[8]
Definition: qnumeric_p.h:62
int id
Definition: qftp.cpp:240
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
QByteArray readAll()
Reads all the bytes available from the data socket and returns them.
Definition: qftp.cpp:2154
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
static QString fromAscii(const char *, int size=-1)
Returns a QString initialized with the first size characters from the string str. ...
Definition: qstring.cpp:4276
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
const QChar at(int i) const
Returns the character at the given index position in the string.
Definition: qstring.h:698
bool hasError() const
Definition: qftp.cpp:441
QHostAddress localAddress() const
Returns the host address of the local socket if available; otherwise returns QHostAddress::Null.
void connectToHost(const QString &host, quint16 port)
Definition: qftp.cpp:313
The QRegExp class provides pattern matching using regular expressions.
Definition: qregexp.h:61
qint64 bytesAvailable() const
Returns the number of incoming bytes that are waiting to be read.
QString errorString
Definition: qftp.cpp:1328
int toInt(bool *ok=0, int base=10) const
Returns the string converted to an int using base base, which is 10 by default and must be between 2 ...
Definition: qstring.cpp:6090
State state
Definition: qftp.cpp:215
QFtpPrivate()
Definition: qftp.cpp:1307
void rawFtpReply(int, const QString &)
void writeData()
Definition: qftp.cpp:396
QFtpPI pi
Definition: qftp.cpp:1322
void setupSocket()
Definition: qftp.cpp:798
QDateTime toDateTime(const QString &string, FormatType format=LongFormat) const
Parses the date/time string given in string and returns the time.
Definition: qlocale.cpp:1649
int cd(const QString &dir)
Changes the working directory of the server to dir.
Definition: qftp.cpp:1892
#define error(msg)
void _q_piFinished(const QString &)
Definition: qftp.cpp:2385
void connectToHost(const QString &hostName, quint16 port, OpenMode mode=ReadWrite)
Attempts to make a connection to hostName on the given port.
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
void chop(int n)
Removes n characters from the end of the string.
Definition: qstring.cpp:4623
void error(int, const QString &)
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
QString toUpper() const Q_REQUIRED_RESULT
Returns an uppercase copy of the string.
Definition: qstring.cpp:5483
#define SLOT(a)
Definition: qobjectdefs.h:226
qint64 bytesTotal
Definition: qftp.cpp:132
virtual void setGroup(const QString &s)
Specifies that the owning group of the URL is called s.
Definition: qurlinfo.cpp:358
int month() const
Returns the number corresponding to the month of this date, using the following convention: ...
Definition: qdatetime.cpp:382
int rawCommand(const QString &command)
Sends the raw FTP command command to the FTP server.
Definition: qftp.cpp:2115
QString currentCmd
Definition: qftp.cpp:218
QFtpDTP(QFtpPI *p, QObject *parent=0)
Definition: qftp.cpp:282
bool setProperty(const char *name, const QVariant &value)
Sets the value of the object&#39;s name property to value.
Definition: qobject.cpp:3755
Command
This enum is used as the return value for the currentCommand() function.
Definition: qftp.h:82
Definition: qftp.h:90
bool listen(const QHostAddress &address=QHostAddress::Any, quint16 port=0)
Tells the server to listen for incoming connections on address address and port port.
Definition: qtcpserver.cpp:281
State
This enum defines the connection state:
Definition: qftp.h:67
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition: qstring.cpp:3734
int day() const
Returns the day of the month (1 to 31) of this date.
Definition: qdatetime.cpp:395
Command currentCommand() const
Returns the command type of the FTP command being executed or None if there is no command being execu...
Definition: qftp.cpp:2216
int rmdir(const QString &dir)
Removes the directory called dir from the server.
Definition: qftp.cpp:2070
bool isValid() const
Returns true if both the date and the time are valid; otherwise returns false.
Definition: qdatetime.cpp:2346
bool isSymLink() const
Returns true if the URL is a symbolic link; otherwise returns false.
Definition: qurlinfo.cpp:586
#define QT_TRANSLATE_NOOP(scope, x)
Marks the string literal sourceText for dynamic translation in the given context; i...
Definition: qglobal.h:2487
#define QT_END_INCLUDE_NAMESPACE
This macro is equivalent to QT_BEGIN_NAMESPACE.
Definition: qglobal.h:92
static QString tr(const char *sourceText, const char *comment=0, int n=-1)
The QDate class provides date functions.
Definition: qdatetime.h:55
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
static QBasicAtomicInt idCounter
Definition: qftp.cpp:252
void pop_front()
This function is provided for STL compatibility.
Definition: qlist.h:302
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
char replyCode[3]
Definition: qftp.cpp:214
void connectionClosed()
Definition: qftp.cpp:937
quint32 toIPv4Address() const
Returns the IPv4 address as a number.
void abort()
Aborts the current connection and resets the socket.
The QString class provides a Unicode character string.
Definition: qstring.h:83
int put(const QByteArray &data, const QString &file, TransferType type=Binary)
Writes a copy of the given data to the file called file on the server.
Definition: qftp.cpp:1977
void setData(QByteArray *)
Definition: qftp.cpp:294
The QFtp class provides an implementation of the client side of FTP protocol.
Definition: qftp.h:59
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
#define Q_BASIC_ATOMIC_INITIALIZER(a)
Definition: qbasicatomic.h:218
int setTransferMode(TransferMode mode)
Sets the current FTP transfer mode to mode.
Definition: qftp.cpp:1827
void abort()
Aborts the current command and deletes all scheduled commands.
Definition: qftp.cpp:2188
#define Q_D(Class)
Definition: qglobal.h:2482
virtual void setDir(bool b)
If b is true then the URL is set to be a directory; if b is false then the URL is set not to be a dir...
Definition: qurlinfo.cpp:252
virtual void setOwner(const QString &s)
Specifies that the owner of the URL is called s.
Definition: qurlinfo.cpp:342
bool isListening() const
Returns true if the server is currently listening for incoming connections; otherwise returns false...
Definition: qtcpserver.cpp:358
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
void connectState(int)
int setupListener(const QHostAddress &address)
Definition: qftp.cpp:336
union QFtpDTP::@310 data
void setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value)
Sets the given option to the value described by value.
static bool isLeapYear(int year)
Returns true if the specified year is a leap year; otherwise returns false.
Definition: qdatetime.cpp:1404
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
int currentId() const
Returns the identifier of the FTP command that is being executed or 0 if there is no command being ex...
Definition: qftp.cpp:2203
void setObjectName(const QString &name)
Definition: qobject.cpp:1112
#define Q_Q(Class)
Definition: qglobal.h:2483
QString errorMessage() const
Definition: qftp.cpp:446
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read...
Definition: qiodevice.cpp:791
ConnectState
Definition: qftp.cpp:74
SocketState
This enum describes the different states in which a socket can be.
static bool parseDir(const QByteArray &buffer, const QString &userName, QUrlInfo *info)
Definition: qftp.cpp:651
Q_CORE_EXPORT void qDebug(const char *,...)
bool is_ba
Definition: qftp.cpp:250
void socketError(QAbstractSocket::SocketError)
Definition: qftp.cpp:759
#define SIGNAL(a)
Definition: qobjectdefs.h:227
void socketConnected()
Definition: qftp.cpp:678
The QUrlInfo class stores information about URLs.
Definition: qurlinfo.h:60
void socketBytesWritten(qint64)
Definition: qftp.cpp:787
TransferMode
FTP works with two socket connections; one for commands and another for transmitting data...
Definition: qftp.h:99
virtual void setName(const QString &name)
Sets the name of the URL to name.
Definition: qurlinfo.cpp:232
virtual void setPermissions(int p)
Specifies that the URL has access permissions p.
Definition: qurlinfo.cpp:390
int addCommand(QFtpCommand *cmd)
Definition: qftp.cpp:1336
bool waitForDtpToConnect
Definition: qftp.cpp:220
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static QIntfbScreen * connected
qint64 read(char *data, qint64 maxlen)
Reads maxlen bytes from the data socket into data and returns the number of bytes read...
Definition: qftp.cpp:2143
bool isOpen() const
Returns true if the device is open; otherwise returns false.
Definition: qiodevice.cpp:530
void clearPendingCommands()
Deletes all pending commands from the list of scheduled commands.
Definition: qftp.cpp:2264
Error
This enum identifies the error that occurred.
Definition: qftp.h:75
QString replyText
Definition: qftp.cpp:213
void setDate(const QDate &date)
Sets the date part of this datetime to date.
Definition: qdatetime.cpp:2399
int indexIn(const QString &str, int offset=0, CaretMode caretMode=CaretAtZero) const
Attempts to find a match in str from position offset (0 by default).
Definition: qregexp.cpp:4136
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
Definition: qstring.cpp:3664
int get(const QString &file, QIODevice *dev=0, TransferType type=Binary)
Downloads the file file from the server.
Definition: qftp.cpp:1937
QString trimmed() const Q_REQUIRED_RESULT
Returns a string that has whitespace removed from the start and the end.
Definition: qstring.cpp:4506
virtual QTcpSocket * nextPendingConnection()
Returns the next pending connection as a connected QTcpSocket object.
Definition: qtcpserver.cpp:554
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
Definition: qobject.cpp:2580
QStringList capturedTexts() const
Returns a list of the captured text strings.
Definition: qregexp.cpp:4267
static QDate currentDate()
Returns the current date, as reported by the system clock.
Definition: qdatetime.cpp:3115
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
QString err
Definition: qftp.cpp:130
QTcpSocket * socket
Definition: qftp.cpp:126
QFtpPI(QObject *parent=0)
Definition: qftp.cpp:822
QByteArray readAll()
Definition: qftp.cpp:383
QFtp::TransferMode transferMode
Definition: qftp.cpp:1326
QByteArray * ba
Definition: qftp.cpp:138
const char * name
void prepend(const T &t)
Inserts value at the beginning of the list.
Definition: qlist.h:541
QString currentCommand() const
Definition: qftp.cpp:168
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
#define emit
Definition: qobjectdefs.h:76
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
SocketError
This enum describes the socket errors that can occur.
int secsTo(const QDateTime &) const
Returns the number of seconds from this datetime to the other datetime.
Definition: qdatetime.cpp:2914
QString proxyHost
Definition: qftp.cpp:1332
unsigned short quint16
Definition: qglobal.h:936
Q_CORE_EXPORT void qWarning(const char *,...)
QIODevice * currentDevice() const
Returns the QIODevice pointer that is used by the FTP command to read data from or store data to...
Definition: qftp.cpp:2233
void abortConnection()
Definition: qftp.cpp:456
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
int indexOf(QChar c, int from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:2838
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
QIODevice * dev
Definition: qftp.cpp:248
The QTcpSocket class provides a TCP socket.
Definition: qtcpsocket.h:56
void dataTransferProgress(qint64, qint64)
This signal is emitted in response to a get() or put() request to indicate the current progress of th...
QString toString() const
Returns the address as a string.
void listInfo(const QUrlInfo &)
This signal is emitted for each directory entry the list() command finds.
void connectToHost(const QString &host, quint16 port)
Definition: qftp.cpp:849
bool waitForNewConnection(int msec=0, bool *timedOut=0)
Waits for at most msec milliseconds or until an incoming connection is available. ...
Definition: qtcpserver.cpp:505
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
void clear()
Removes all items from the list.
Definition: qlist.h:764
__int64 qint64
Definition: qglobal.h:942
The State element defines configurations of objects and properties.
QIODevice * dev
Definition: qftp.cpp:139
void finished(const QString &)
int mkdir(const QString &dir)
Creates a directory called dir on the server.
Definition: qftp.cpp:2051
void close()
Closes the I/O device for the socket, disconnects the socket&#39;s connection with the host...
void socketReadyRead()
Definition: qftp.cpp:687
QFtpCommand(QFtp::Command cmd, QStringList raw, const QByteArray &ba)
Definition: qftp.cpp:257
bool waitForDtpToClose
Definition: qftp.cpp:221
#define Q_OBJECT
Definition: qobjectdefs.h:157
bool processReply()
Definition: qftp.cpp:1022
AbortState abortState
Definition: qftp.cpp:216
void setBytesTotal(qint64 bytes)
Definition: qftp.cpp:306
#define None
virtual bool isSequential() const
Returns true if this device is sequential; otherwise returns false.
Definition: qiodevice.cpp:454
void resize(int size)
Sets the size of the string to size characters.
Definition: qstring.cpp:1353
T & first()
Returns a reference to the first item in the list.
Definition: qlist.h:282
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
QDate date() const
Returns the date part of the datetime.
Definition: qdatetime.cpp:2357
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition: qstring.h:505
bool is_ba
Definition: qftp.cpp:141
void waitForConnection()
Definition: qftp.cpp:347
QString mid(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a string that contains n characters of this string, starting at the specified position index...
Definition: qstring.cpp:3706
void abort()
Definition: qftp.cpp:891
qint64 bytesDone
Definition: qftp.cpp:131
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
static void _q_fixupDateTime(QDateTime *dateTime, bool leapYear=false)
Definition: qftp.cpp:469
static QLocale c()
Returns a QLocale object initialized to the "C" locale.
Definition: qlocale.h:773
#define Q_DECLARE_PUBLIC(Class)
Definition: qglobal.h:2477
QFtp(QObject *parent=0)
Constructs a QFtp object with the given parent.
Definition: qftp.cpp:1461
void clearError()
Definition: qftp.cpp:451
QAbstractSocket::NetworkLayerProtocol protocol() const
Returns the network layer protocol of the host address.
bool sendCommands(const QStringList &cmds)
Definition: qftp.cpp:868
The QDateTime class provides date and time functions.
Definition: qdatetime.h:216
int list(const QString &dir=QString())
Lists the contents of directory dir on the FTP server.
Definition: qftp.cpp:1866
~QFtpCommand()
Definition: qftp.cpp:271
~QFtpPrivate()
Definition: qftp.cpp:1311
QList< QFtpCommand * > pending
Definition: qftp.cpp:1323
qint64 readLine(char *data, qint64 maxlen)
This function reads a line of ASCII characters from the device, up to a maximum of maxSize - 1 bytes...
Definition: qiodevice.cpp:1110
QString simplified() const Q_REQUIRED_RESULT
Returns a string that has whitespace removed from the start and the end, and that has each sequence o...
Definition: qstring.cpp:4415
void clear()
Clears the contents of the string and makes it empty.
Definition: qstring.h:723
void readyRead()
This signal is emitted in response to a get() command when there is new data to read.
virtual void setSymLink(bool b)
Specifies that the URL refers to a symbolic link if b is true and that it does not if b is false...
Definition: qurlinfo.cpp:290
int lastIndexOf(QChar c, int from=-1, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:3000
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
void _q_startNextCommand()
Definition: qftp.cpp:2312
Q_INVOKABLE QObject(QObject *parent=0)
Constructs an object with parent object parent.
Definition: qobject.cpp:753
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
QStringList rawCmds
Definition: qftp.cpp:242
int rename(const QString &oldname, const QString &newname)
Renames the file called oldname to newname on the server.
Definition: qftp.cpp:2089
Definition: qftp.h:91
bool singleShot
This static function calls a slot after a given time interval.
Definition: qtimer.h:59
QString toLower() const Q_REQUIRED_RESULT
Returns a lowercase copy of the string.
Definition: qstring.cpp:5389
int remove(const QString &file)
Deletes the file called file from the server.
Definition: qftp.cpp:2032
void resize(int size)
Sets the size of the byte array to size bytes.
int close()
Closes the connection to the FTP server.
Definition: qftp.cpp:1817
unsigned int quint32
Definition: qglobal.h:938
QByteArray * ba
Definition: qftp.cpp:247
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
QTcpSocket commandSocket
Definition: qftp.cpp:212
The QTcpServer class provides a TCP-based server.
Definition: qtcpserver.h:61
QString errorString() const
Returns a human-readable description of the last error that occurred.
Definition: qftp.cpp:2305
void hostFound()
Definition: qftp.cpp:920
int fetchAndAddRelaxed(int valueToAdd)
static QDateTime currentDateTime()
Returns the current datetime, as reported by the system clock, in the local time zone.
Definition: qdatetime.cpp:3138
bool setYMD(int y, int m, int d)
Sets the date&#39;s year y, month m, and day d.
Definition: qdatetime.cpp:937
quint16 proxyPort
Definition: qftp.cpp:1333
qint64 bytesAvailable() const
Returns the number of bytes that can be read from the data socket at the moment.
Definition: qftp.cpp:2127
qint64 bytesToWrite() const
Returns the number of bytes that are waiting to be written.
QTcpSocket::SocketState state() const
Definition: qftp.cpp:356
QByteArray readAll()
Reads all available data from the device, and returns it as a QByteArray.
Definition: qiodevice.cpp:1025
Definition: qftp.cpp:69
quint16 serverPort() const
Returns the server&#39;s port if the server is listening for connections; otherwise returns 0...
Definition: qtcpserver.cpp:466
TransferType
This enum identifies the data transfer type used with get and put commands.
Definition: qftp.h:103
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
QHostAddress peerAddress() const
Returns the address of the connected peer if the socket is in ConnectedState; otherwise returns QHost...
char toLatin1() const
Returns the Latin-1 character equivalent to the QChar, or 0.
Definition: qchar.h:376
void listInfo(const QUrlInfo &)
virtual bool open(OpenMode mode)
Opens the device and sets its OpenMode to mode.
Definition: qiodevice.cpp:570
void connected()
Definition: qftp.cpp:925
void dataTransferProgress(qint64, qint64)
bool close_waitForStateChange
Definition: qftp.cpp:1324
void _q_piConnectState(int)
Definition: qftp.cpp:2491
QVariant property(const char *name) const
Returns the value of the object&#39;s name property.
Definition: qobject.cpp:3807
QByteArray bytesFromSocket
Definition: qftp.cpp:223
virtual void setWritable(bool b)
Specifies that the URL is writable if b is true and not writable if b is false.
Definition: qurlinfo.cpp:308
#define QT_BEGIN_INCLUDE_NAMESPACE
This macro is equivalent to QT_END_NAMESPACE.
Definition: qglobal.h:91
virtual void setLastModified(const QDateTime &dt)
Specifies that the object the URL refers to was last modified at dt.
Definition: qurlinfo.cpp:407
void delayedCloseFinished()
Definition: qftp.cpp:943
union QFtpCommand::@311 data
QStringList pendingCommands
Definition: qftp.cpp:217
void _q_piFtpReply(int, const QString &)
Definition: qftp.cpp:2503
QTcpServer listener
Definition: qftp.cpp:127
static void _q_parseDosDir(const QStringList &tokens, const QString &userName, QUrlInfo *info)
Definition: qftp.cpp:598
int year() const
Returns the year of this date.
Definition: qdatetime.cpp:353
void clearData()
Definition: qftp.cpp:811
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
void dtpConnectState(int)
Definition: qftp.cpp:1263
static void _q_parseUnixDir(const QStringList &tokens, const QString &userName, QUrlInfo *info)
Definition: qftp.cpp:489
QStringList split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const Q_REQUIRED_RESULT
Splits the string into substrings wherever sep occurs, and returns the list of those strings...
Definition: qstring.cpp:6526
virtual ~QFtp()
Destructor.
Definition: qftp.cpp:2514
int login(const QString &user=QString(), const QString &password=QString())
Logs in to the FTP server with the username user and the password password.
Definition: qftp.cpp:1791
void close()
Closes the server.
Definition: qtcpserver.cpp:371
Definition: qftp.cpp:152
The QHostAddress class provides an IP address.
Definition: qhostaddress.h:70
static QNSListener * listener
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
Definition: qiodevice.cpp:1342
QFtp::Error error
Definition: qftp.cpp:1327
#define slots
Definition: qobjectdefs.h:68
quint16 port
Definition: qftp.cpp:1331
void dataReadyRead()
Definition: qftp.cpp:436
void clearPendingCommands()
Definition: qftp.cpp:883
virtual void setReadable(bool b)
Specifies that the URL is readable if b is true and not readable if b is false.
Definition: qurlinfo.cpp:326
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition: qstring.cpp:3796
Error error() const
Returns the last error that occurred.
Definition: qftp.cpp:2289
#define signals
Definition: qobjectdefs.h:69
bool startNextCmd()
Definition: qftp.cpp:1200
The QIODevice class is the base interface class of all I/O devices in Qt.
Definition: qiodevice.h:66
void readyRead()
int setProxy(const QString &host, quint16 port)
Enables use of the FTP proxy on host host and port port.
Definition: qftp.cpp:1842
QByteArray bytesFromSocket
Definition: qftp.cpp:143
bool sendCommand(const QString &cmd)
Definition: qftp.cpp:162
bool canReadLine() const
Returns true if a line of data can be read from the socket; otherwise returns false.
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
void setDevice(QIODevice *)
Definition: qftp.cpp:300
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
QFtpDTP dtp
Definition: qftp.cpp:174
const QChar * constData() const
Returns a pointer to the data stored in the QString.
Definition: qstring.h:712
void connectState(int)
QString host
Definition: qftp.cpp:1330
QByteArray & remove(int index, int len)
Removes len bytes from the array, starting at index position pos, and returns a reference to the arra...
State state() const
Returns the current state of the object.
Definition: qftp.cpp:2277
void clear()
Clears the contents of the byte array and makes it empty.
void readyRead()
Definition: qftp.cpp:965
SocketState state() const
Returns the state of the socket.
AbortState
Definition: qftp.cpp:203
#define text
Definition: qobjectdefs.h:80
bool endsWith(const QByteArray &a) const
Returns true if this byte array ends with byte array ba; otherwise returns false. ...
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
qint64 read(char *data, qint64 maxlen)
Definition: qftp.cpp:368
bool rawCommand
Definition: qftp.cpp:171
QFtpPI * pi
Definition: qftp.cpp:129
Definition: qftp.h:92
void _q_piError(int, const QString &)
Definition: qftp.cpp:2415
bool hasPendingCommands() const
Returns true if there are any commands scheduled that have not yet been executed; otherwise returns f...
Definition: qftp.cpp:2252
QFtp::State state
Definition: qftp.cpp:1325