+
+bool wxFTP::FileExists(const wxString& fileName)
+{
+ // This function checks if the file specified in fileName exists in the
+ // current dir. It does so by simply doing an NLST (via GetList).
+ // If this succeeds (and the list is not empty) the file exists.
+
+ bool retval = FALSE;
+ wxArrayString fileList;
+
+ if ( GetList(fileList, fileName, FALSE) )
+ {
+ // Some ftp-servers (Ipswitch WS_FTP Server 1.0.5 does this)
+ // displays this behaviour when queried on a non-existing file:
+ // NLST this_file_does_not_exist
+ // 150 Opening ASCII data connection for directory listing
+ // (no data transferred)
+ // 226 Transfer complete
+ // Here wxFTP::GetList(...) will succeed but it will return an empty
+ // list.
+ retval = !fileList.IsEmpty();
+ }
+
+ return retval;
+}
+
+// ----------------------------------------------------------------------------
+// FTP GetSize
+// ----------------------------------------------------------------------------
+
+int wxFTP::GetFileSize(const wxString& fileName)
+{
+ // return the filesize of the given file if possible
+ // return -1 otherwise (predominantly if file doesn't exist
+ // in current dir)
+
+ int filesize = -1;
+
+ // Check for existance of file via wxFTP::FileExists(...)
+ if ( FileExists(fileName) )
+ {
+ wxString command;
+
+ // First try "SIZE" command using BINARY(IMAGE) transfermode
+ // Especially UNIX ftp-servers distinguish between the different
+ // transfermodes and reports different filesizes accordingly.
+ // The BINARY size is the interesting one: How much memory
+ // will we need to hold this file?
+ TransferMode oldTransfermode = m_currentTransfermode;
+ SetTransferMode(BINARY);
+ command << _T("SIZE ") << fileName;
+
+ bool ok = CheckCommand(command, '2');
+
+ if ( ok )
+ {
+ // The answer should be one line: "213 <filesize>\n"
+ // 213 is File Status (STD9)
+ // "SIZE" is not described anywhere..? It works on most servers
+ int statuscode;
+ if ( wxSscanf(GetLastResult().c_str(), _T("%i %i"),
+ &statuscode, &filesize) == 2 )
+ {
+ // We've gotten a good reply.
+ ok = TRUE;
+ }
+ else
+ {
+ // Something bad happened.. A "2yz" reply with no size
+ // Fallback
+ ok = FALSE;
+ }
+ }
+
+ // Set transfermode back to the original. Only the "SIZE"-command
+ // is dependant on transfermode
+ if ( oldTransfermode != NONE )
+ {
+ SetTransferMode(oldTransfermode);
+ }
+
+ if ( !ok ) // this is not a direct else clause.. The size command might return an invalid "2yz" reply
+ {
+ // The server didn't understand the "SIZE"-command or it
+ // returned an invalid reply.
+ // We now try to get details for the file with a "LIST"-command
+ // and then parse the output from there..
+ wxArrayString fileList;
+ if ( GetList(fileList, fileName, TRUE) )
+ {
+ if ( !fileList.IsEmpty() )
+ {
+ // We _should_ only get one line in return, but just to be
+ // safe we run through the line(s) returned and look for a
+ // substring containing the name we are looking for. We
+ // stop the iteration at the first occurrence of the
+ // filename. The search is not case-sensitive.
+ bool foundIt = FALSE;
+
+ size_t i;
+ for ( i = 0; !foundIt && i < fileList.Count(); i++ )
+ {
+ foundIt = fileList[i].Upper().Contains(fileName.Upper());
+ }
+
+ if ( foundIt )
+ {
+ // The index i points to the first occurrence of
+ // fileName in the array Now we have to find out what
+ // format the LIST has returned. There are two
+ // "schools": Unix-like
+ //
+ // '-rw-rw-rw- owner group size month day time filename'
+ //
+ // or Windows-like
+ //
+ // 'date size filename'
+
+ // check if the first character is '-'. This would
+ // indicate Unix-style (this also limits this function
+ // to searching for files, not directories)
+ if ( fileList[i].Mid(0, 1) == _T("-") )
+ {
+
+ if ( wxSscanf(fileList[i].c_str(),
+ _T("%*s %*s %*s %*s %i %*s %*s %*s %*s"),
+ &filesize) == 9 )
+ {
+ // We've gotten a good response
+ ok = TRUE;
+ }
+ else
+ {
+ // Hmm... Invalid response
+ wxLogTrace(FTP_TRACE_MASK,
+ _T("Invalid LIST response"));
+ }
+ }
+ else // Windows-style response (?)
+ {
+ if ( wxSscanf(fileList[i].c_str(),
+ _T("%*s %*s %i %*s"),
+ &filesize) == 4 )
+ {
+ // valid response
+ ok = TRUE;
+ }
+ else
+ {
+ // something bad happened..?
+ wxLogTrace(FTP_TRACE_MASK,
+ _T("Invalid or unknown LIST response"));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // filesize might still be -1 when exiting
+ return filesize;
+}
+
+
+#if WXWIN_COMPATIBILITY_2
+// deprecated
+wxList *wxFTP::GetList(const wxString& wildcard, bool details)
+{
+ wxSocketBase *sock = GetPort();
+ if (!sock)
+ return FALSE;
+ wxList *file_list = new wxList;
+ wxString line;
+ // NLST : List of Filenames (including Directory's !)
+ // LIST : depending on BS of FTP-Server
+ // - Unix : result like "ls" command
+ // - Windows : like "dir" command
+ // - others : ?
+ if (!details)
+ line = _T("NLST"); // Default
+ else
+ line = _T("LIST");
+ if (!wildcard.IsNull())
+ line += wildcard;
+ if (!CheckCommand(line, '1'))
+ {
+ delete sock;
+ delete file_list;
+ return NULL;
+ }
+ while (GetLine(sock, line) == wxPROTO_NOERR)
+ {
+ file_list->Append((wxObject *)(new wxString(line)));
+ }
+ if (!CheckResult('2'))
+ {
+ delete sock;
+ file_list->DeleteContents(TRUE);
+ delete file_list;
+ return NULL;
+ }
+ return file_list;
+}
+#endif // WXWIN_COMPATIBILITY_2
+
+#endif // wxUSE_PROTOCOL_FTP
+