PageRenderTime 62ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/ProSnooperFx_src/indy10.0.52_source/Protocols/IdFTP.pas

http://github.com/lookias/ProSnooper
Pascal | 3570 lines | 2455 code | 217 blank | 898 comment | 270 complexity | 8f38ef32b852a662d62336598357674d MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. { $HDR$}
  2. {**********************************************************************}
  3. { Unit archived using Team Coherence }
  4. { Team Coherence is Copyright 2002 by Quality Software Components }
  5. { }
  6. { For further information / comments, visit our WEB site at }
  7. { http://www.TeamCoherence.com }
  8. {**********************************************************************}
  9. {}
  10. { $Log: 13828: IdFTP.pas
  11. {
  12. { Rev 1.102 11/5/2004 1:54:42 AM JPMugaas
  13. { Minor adjustment - should not detect TitanFTPD better (tested at:
  14. { ftp.southrivertech.com).
  15. {
  16. { If MLSD is being used, SITE ZONE will not be issued. It's not needed because
  17. { the MLSD spec indicates the time is based on GMT.
  18. }
  19. {
  20. { Rev 1.101 10/27/2004 12:58:08 AM JPMugaas
  21. { Improvement from Tobias Giesen http://www.superflexible.com
  22. { His notation is below:
  23. {
  24. { "here's a fix for TIdFTP.IndexOfFeatLine. It does not work the
  25. { way it is used in TIdFTP.SetModTime, because it only
  26. { compares the first word of the FeatLine."
  27. }
  28. {
  29. { Rev 1.100 10/26/2004 9:19:10 PM JPMugaas
  30. { Fixed references.
  31. }
  32. {
  33. { Rev 1.99 9/16/2004 3:24:04 AM JPMugaas
  34. { TIdFTP now compresses to the IOHandler and decompresses from the IOHandler.
  35. {
  36. { Noted some that the ZLib code is based was taken from ZLibEx.
  37. }
  38. {
  39. { Rev 1.98 9/13/2004 12:15:42 AM JPMugaas
  40. { Now should be able to handle some values better as suggested by Michael J.
  41. { Leave.
  42. }
  43. {
  44. { Rev 1.97 9/11/2004 10:58:06 AM JPMugaas
  45. { FTP now decompresses output directly to the IOHandler.
  46. }
  47. {
  48. { Rev 1.96 9/10/2004 7:37:42 PM JPMugaas
  49. { Fixed a bug. We needed to set Passthrough instead of calling StartSSL. This
  50. { was causing a SSL problem with upload.
  51. }
  52. {
  53. { Rev 1.95 8/2/04 5:56:16 PM RLebeau
  54. { Tweaks to TIdFTP.InitDataChannel()
  55. }
  56. {
  57. Rev 1.94 7/30/2004 1:55:04 AM DSiders
  58. Corrected DoOnRetrievedDir naming.
  59. }
  60. {
  61. Rev 1.93 7/30/2004 12:36:32 AM DSiders
  62. Corrected spelling in OnRetrievedDir, DoOnRetrievedDir declarations.
  63. }
  64. {
  65. { Rev 1.92 7/29/2004 2:15:28 AM JPMugaas
  66. { New property for controlling what AUTH command is sent. Fixed some minor
  67. { issues with FTP properties. Some were not set to defaults causing
  68. { unpredictable results -- OOPS!!!
  69. }
  70. {
  71. { Rev 1.91 7/29/2004 12:04:40 AM JPMugaas
  72. { New events for Get and Put as suggested by Don Sides and to complement an
  73. { event done by APR.
  74. }
  75. {
  76. { Rev 1.90 7/28/2004 10:16:14 AM JPMugaas
  77. { New events for determining when a listing is finished and when the dir
  78. { parsing begins and ends. Dir parsing is done sometimes when DirectoryListing
  79. { is referenced.
  80. }
  81. {
  82. { Rev 1.89 7/27/2004 2:03:54 AM JPMugaas
  83. { New property:
  84. {
  85. { ExternalIP - used to specify an IP address for the PORT and EPRT commands.
  86. { This should be blank unless you are behind a NAT and you need to use PORT
  87. { transfers with SSL. You would set ExternalIP to the NAT's IP address on the
  88. { Internet.
  89. {
  90. { The idea is this:
  91. {
  92. { 1) You set up your NAT to forward a range ports ports to your computer behind
  93. { the NAT.
  94. { 2) You specify that a port range with the DataPortMin and DataPortMin
  95. { properties.
  96. { 3) You set ExternalIP to the NAT's Internet IP address.
  97. {
  98. { I have verified this with Indy and WS FTP Pro behind a NAT router.
  99. }
  100. {
  101. { Rev 1.88 7/23/04 7:09:50 PM RLebeau
  102. { Bug fix for TFileStream access rights in Get()
  103. }
  104. {
  105. Rev 1.87 7/18/2004 3:00:12 PM DSiders
  106. Added localization comments.
  107. }
  108. {
  109. { Rev 1.86 7/16/2004 4:28:40 AM JPMugaas
  110. { CCC Support in TIdFTP to complement that capability in TIdFTPServer.
  111. }
  112. {
  113. { Rev 1.85 7/13/04 6:48:14 PM RLebeau
  114. { Added support for new DataPort and DataPortMin/Max properties
  115. }
  116. {
  117. Rev 1.84 7/6/2004 4:51:46 PM DSiders
  118. Corrected spelling of Challenge in properties, methods, types.
  119. }
  120. {
  121. { Rev 1.83 7/3/2004 3:15:50 AM JPMugaas
  122. { Checked in so everyone else can work on stuff while I'm away.
  123. }
  124. {
  125. { Rev 1.82 6/27/2004 1:45:38 AM JPMugaas
  126. { Can now optionally support LastAccessTime like Smartftp's FTP Server could.
  127. { I also made the MLST listing object and parser support this as well.
  128. }
  129. {
  130. { Rev 1.81 6/20/2004 8:31:58 PM JPMugaas
  131. { New events for reporting greeting and after login banners during the login
  132. { sequence.
  133. }
  134. {
  135. { Rev 1.80 6/20/2004 6:56:42 PM JPMugaas
  136. { Start oin attempt to support FXP with Deflate compression. More work will
  137. { need to be done.
  138. }
  139. {
  140. { Rev 1.79 6/17/2004 3:42:32 PM JPMugaas
  141. { Adjusted code for removal of dmBlock and dmCompressed. Made TransferMode a
  142. { property. Note that the Set method is odd because I am trying to keep
  143. { compatibility with older Indy versions.
  144. }
  145. {
  146. { Rev 1.78 6/14/2004 6:19:02 PM JPMugaas
  147. { This now refers to TIdStreamVCL when downloading isntead of directly to a
  148. { memory stream when compressing data.
  149. }
  150. {
  151. { Rev 1.77 6/14/2004 8:34:52 AM JPMugaas
  152. { Fix for AV on Put with Passive := True.
  153. }
  154. {
  155. Rev 1.76 6/11/2004 9:34:12 AM DSiders
  156. Added "Do not Localize" comments.
  157. }
  158. {
  159. { Rev 1.75 2004.05.20 11:37:16 AM czhower
  160. { IdStreamVCL
  161. }
  162. {
  163. { Rev 1.74 5/6/2004 6:54:26 PM JPMugaas
  164. { FTP Port transfers with TransparentProxies is enabled. This only works if
  165. { the TransparentProxy supports a "bind" request.
  166. }
  167. {
  168. { Rev 1.73 5/4/2004 11:16:28 AM JPMugaas
  169. { TransferTimeout property added and enabled (Bug 96).
  170. }
  171. {
  172. { Rev 1.72 5/4/2004 11:07:12 AM JPMugaas
  173. { Timeouts should now be reenabled in TIdFTP.
  174. }
  175. {
  176. { Rev 1.71 4/19/2004 5:05:02 PM JPMugaas
  177. { Class rework Kudzu wanted.
  178. }
  179. {
  180. { Rev 1.70 2004.04.16 9:31:42 PM czhower
  181. { Remove unnecessary duplicate string parsing and replaced with .assign.
  182. }
  183. {
  184. { Rev 1.69 2004.04.15 7:09:04 PM czhower
  185. { .NET overloads
  186. }
  187. {
  188. { Rev 1.68 4/15/2004 9:46:48 AM JPMugaas
  189. { List no longer requires a TStrings. It turns out that it was an optional
  190. { parameter.
  191. }
  192. {
  193. { Rev 1.67 2004.04.15 2:03:28 PM czhower
  194. { Removed login param from connect and made it a prop like POP3.
  195. }
  196. {
  197. { Rev 1.66 3/3/2004 5:57:40 AM JPMugaas
  198. { Some IFDEF excluses were removed because the functionality is now in DotNET.
  199. }
  200. {
  201. { Rev 1.65 2004.03.03 11:54:26 AM czhower
  202. { IdStream change
  203. }
  204. {
  205. { Rev 1.64 2/20/2004 1:01:06 PM JPMugaas
  206. { Preliminary FTP PRET command support for using PASV with a distributed FTP
  207. { server (Distributed PASV -
  208. { http://drftpd.org/wiki/wiki.phtml?title=Distributed_PASV).
  209. }
  210. {
  211. { Rev 1.63 2/17/2004 12:25:52 PM JPMugaas
  212. { The client now supports MODE Z (deflate) uploads and downloads as specified
  213. { by http://www.ietf.org/internet-drafts/draft-preston-ftpext-deflate-00.txt
  214. }
  215. {
  216. { Rev 1.62 2004.02.03 5:45:10 PM czhower
  217. { Name changes
  218. }
  219. {
  220. { Rev 1.61 2004.02.03 2:12:06 PM czhower
  221. { $I path change
  222. }
  223. {
  224. { Rev 1.60 1/27/2004 10:17:10 PM JPMugaas
  225. { Fix from Steve Loft for a server that sends something like this:
  226. { "227 Passive mode OK (195,92,195,164,4,99 )"
  227. }
  228. {
  229. { Rev 1.59 1/27/2004 3:59:28 PM SPerry
  230. { StringStream ->IdStringStream
  231. }
  232. {
  233. { Rev 1.58 24/01/2004 19:13:58 CCostelloe
  234. { Cleaned up warnings
  235. }
  236. {
  237. { Rev 1.57 1/21/2004 2:27:50 PM JPMugaas
  238. { Bullete Proof FTPD and Titan FTP support SITE ZONE. Saw this in a command
  239. { database in StaffFTP.
  240. { InitComponent.
  241. }
  242. {
  243. { Rev 1.56 1/19/2004 9:05:38 PM JPMugaas
  244. { Fixes to FTP Set Date functionality.
  245. { Introduced properties for Time Zone information from the server. The way it
  246. { works is this, if TIdFTP detects you are using "Serv-U" or SITE ZONE is
  247. { listed in the FEAT reply, Indy obtains the time zone information with the
  248. { SITE ZONE command and makes the appropriate calculation. Indy then uses this
  249. { information to calculate a timestamp to send to the server with the MDTM
  250. { command. You can also use the Time Zone information yourself to convert the
  251. { FTP directory listing item timestamps into GMT and than convert that to your
  252. { local time.
  253. { FTP Voyager uses SITE ZONE as I've described.
  254. }
  255. {
  256. { Rev 1.55 1/19/2004 4:39:08 AM JPMugaas
  257. { You can now set the time for a file on the server. Note that these methods
  258. { try to treat the time as relative to GMT.
  259. }
  260. {
  261. { Rev 1.54 1/17/2004 9:09:30 PM JPMugaas
  262. { Should now compile.
  263. }
  264. {
  265. { Rev 1.53 1/17/2004 7:48:02 PM JPMugaas
  266. { FXP site to site transfer code was redone for improvements with FXP with TLS.
  267. { It actually works and I verified with RaidenFTPD
  268. { (http://www.raidenftpd.com/) and the Indy FTP server components. I also
  269. { lowered the requirements for TLS FXP transfers. The requirements now are:
  270. { 1) Only server (either the recipient or the sendor) has to support SSCN
  271. {
  272. { or
  273. {
  274. { 2) The server receiving a PASV must support CPSV and the transfer is done
  275. { with IPv4.
  276. }
  277. {
  278. { Rev 1.52 1/9/2004 2:51:26 PM JPMugaas
  279. { Started IPv6 support.
  280. }
  281. {
  282. { Rev 1.51 11/27/2003 4:55:28 AM JPMugaas
  283. { Made STOU functionality separate from PUT functionality. Put now requires a
  284. { destination filename except where a source-file name is given. In that case,
  285. { the default is the filename from the source string.
  286. }
  287. {
  288. { Rev 1.50 10/26/2003 04:28:50 PM JPMugaas
  289. { Reworked Status.
  290. {
  291. { The old one was problematic because it assumed that STAT was a request to
  292. { send a directory listing through the control channel. This assumption is not
  293. { correct. It provides a way to get a freeform status report from a server.
  294. { With a Path parameter, it should work like a LIST command except that the
  295. { control connection is used. We don't support that feature and you should use
  296. { our LIst method to get the directory listing anyway, IMAO.
  297. }
  298. {
  299. { Rev 1.49 10/26/2003 9:17:46 PM BGooijen
  300. { Compiles in DotNet, and partially works there
  301. }
  302. {
  303. { Rev 1.48 10/24/2003 12:43:48 PM JPMugaas
  304. { Should work again.
  305. }
  306. {
  307. { Rev 1.47 2003.10.24 10:43:04 AM czhower
  308. { TIdSTream to dos
  309. }
  310. {
  311. { Rev 1.46 10/20/2003 03:06:10 PM JPMugaas
  312. { SHould now work.
  313. }
  314. {
  315. { Rev 1.45 10/20/2003 01:00:38 PM JPMugaas
  316. { EIdException no longer raised. Some things were being gutted needlessly.
  317. }
  318. {
  319. Rev 1.44 10/19/2003 12:58:20 PM DSiders
  320. Added localization comments.
  321. }
  322. {
  323. { Rev 1.43 2003.10.14 9:56:50 PM czhower
  324. { Compile todos
  325. }
  326. {
  327. { Rev 1.42 2003.10.12 3:50:40 PM czhower
  328. { Compile todos
  329. }
  330. {
  331. { Rev 1.41 10/10/2003 11:32:26 PM SPerry
  332. { -
  333. }
  334. {
  335. { Rev 1.40 10/9/2003 10:17:02 AM JPMugaas
  336. { Added overload for GetLoginPassword for providing a challanage string which
  337. { doesn't have to the last command reply.
  338. { Added CLNT support.
  339. }
  340. {
  341. { Rev 1.39 10/7/2003 05:46:20 AM JPMugaas
  342. { SSCN Support added.
  343. }
  344. {
  345. { Rev 1.38 10/6/2003 08:56:44 PM JPMugaas
  346. { Reworked the FTP list parsing framework so that the user can obtain the list
  347. { of capabilities from a parser class with TIdFTP. This should permit the user
  348. { to present a directory listing differently for each parser (some FTP list
  349. { parsers do have different capabilities).
  350. }
  351. {
  352. { Rev 1.37 10/1/2003 12:51:18 AM JPMugaas
  353. { SSL with active (PORT) transfers now should work again.
  354. }
  355. {
  356. { Rev 1.36 9/30/2003 09:50:38 PM JPMugaas
  357. { FTP with TLS should work better. It turned out that we were negotiating it
  358. { several times causing a hang. I also made sure that we send PBSZ 0 and PROT
  359. { P for both implicit and explicit TLS. Data ports should work in PASV again.
  360. }
  361. {
  362. { Rev 1.35 9/28/2003 11:41:06 PM JPMugaas
  363. { Reworked Eldos's proposed FTP fix as suggested by Henrick Hellström by moving
  364. { all of the IOHandler creation code to InitDataChannel. This should reduce
  365. { the likelihood of error.
  366. }
  367. {
  368. { Rev 1.33 9/18/2003 11:22:40 AM JPMugaas
  369. { Removed a temporary workaround for an OnWork bug that was in the Indy Core.
  370. { That bug was fixed so there's no sense in keeping a workaround here.
  371. }
  372. {
  373. { Rev 1.32 9/12/2003 08:05:30 PM JPMugaas
  374. { A temporary fix for OnWork events not firing. The bug is that OnWork events
  375. { aren't used in IOHandler where ReadStream really is located.
  376. }
  377. {
  378. { Rev 1.31 9/8/2003 02:33:00 AM JPMugaas
  379. { OnCustomFTPProxy added to allow Indy to support custom FTP proxies. When
  380. { using this event, you are responsible for programming the FTP Proxy and FTP
  381. { Server login sequence.
  382. { GetLoginPassword method function for returning the password used when logging
  383. { into a FTP server which handles OTP calculation. This way, custom firewall
  384. { support can handle One-Time-Password system transparently. You do have to
  385. { send the User ID before calling this function because the OTP challenge is
  386. { part of the reply.
  387. }
  388. {
  389. { Rev 1.30 6/10/2003 11:10:00 PM JPMugaas
  390. { Made comments about our loop that tries several AUTH command variations.
  391. { Some servers may only accept AUTH SSL while other servers only accept AUTH
  392. { TLS.
  393. }
  394. {
  395. { Rev 1.29 5/26/2003 12:21:54 PM JPMugaas
  396. }
  397. {
  398. { Rev 1.28 5/25/2003 03:54:20 AM JPMugaas
  399. }
  400. {
  401. { Rev 1.27 5/19/2003 08:11:32 PM JPMugaas
  402. { Now should compile properly with new code in Core.
  403. }
  404. {
  405. { Rev 1.26 5/8/2003 11:27:42 AM JPMugaas
  406. { Moved feature negoation properties down to the ExplicitTLSClient level as
  407. { feature negotiation goes hand in hand with explicit TLS support.
  408. }
  409. {
  410. { Rev 1.25 4/5/2003 02:06:34 PM JPMugaas
  411. { TLS handshake itself can now be handled.
  412. }
  413. {
  414. Rev 1.24 4/4/2003 8:01:32 PM BGooijen
  415. now creates iohandler for dataconnection
  416. }
  417. {
  418. { Rev 1.23 3/31/2003 08:40:18 AM JPMugaas
  419. { Fixed problem with QUIT command.
  420. }
  421. {
  422. Rev 1.22 3/27/2003 3:41:28 PM BGooijen
  423. Changed because some properties are moved to IOHandler
  424. }
  425. {
  426. { Rev 1.21 3/27/2003 05:46:24 AM JPMugaas
  427. { Updated framework with an event if the TLS negotiation command fails.
  428. { Cleaned up some duplicate code in the clients.
  429. }
  430. {
  431. { Rev 1.20 3/26/2003 04:19:20 PM JPMugaas
  432. { Cleaned-up some code and illiminated some duplicate things.
  433. }
  434. {
  435. { Rev 1.19 3/24/2003 04:56:10 AM JPMugaas
  436. { A typecast was incorrect and could cause a potential source of instability if
  437. { a TIdIOHandlerStack was not used.
  438. }
  439. {
  440. { Rev 1.18 3/16/2003 06:09:58 PM JPMugaas
  441. { Fixed port setting bug.
  442. }
  443. {
  444. { Rev 1.17 3/16/2003 02:40:16 PM JPMugaas
  445. { FTP client with new design.
  446. }
  447. {
  448. Rev 1.16 3/16/2003 1:02:44 AM BGooijen
  449. Added 2 events to give the user more control to the dataconnection, moved
  450. SendTransferType, enabled ssl
  451. }
  452. {
  453. { Rev 1.15 3/13/2003 09:48:58 AM JPMugaas
  454. { Now uses an abstract SSL base class instead of OpenSSL so 3rd-party vendors
  455. { can plug-in their products.
  456. }
  457. {
  458. { Rev 1.14 3/7/2003 11:51:52 AM JPMugaas
  459. { Fixed a writeln bug and an IOError issue.
  460. }
  461. {
  462. { Rev 1.13 3/3/2003 07:06:26 PM JPMugaas
  463. { FFreeIOHandlerOnDisconnect to FreeIOHandlerOnDisconnect at Bas's instruction
  464. }
  465. {
  466. { Rev 1.12 2/21/2003 06:54:36 PM JPMugaas
  467. { The FTP list processing has been restructured so that Directory output is not
  468. { done by IdFTPList. This now also uses the IdFTPListParserBase for parsing so
  469. { that the code is more scalable.
  470. }
  471. {
  472. { Rev 1.11 2/17/2003 04:45:36 PM JPMugaas
  473. { Now temporarily change the transfer mode to ASCII when requesting a DIR.
  474. { TOPS20 does not like transfering dirs in binary mode and it might be a good
  475. { idea to do it anyway.
  476. }
  477. {
  478. { Rev 1.10 2/16/2003 03:22:20 PM JPMugaas
  479. { Removed the Data Connection assurance stuff. We figure things out from the
  480. { draft specificaiton, the only servers we found would not send any data after
  481. { the new commands were sent, and there were only 2 server types that supported
  482. { it anyway.
  483. }
  484. {
  485. { Rev 1.9 2/16/2003 10:51:08 AM JPMugaas
  486. { Attempt to implement:
  487. {
  488. { http://www.ietf.org/internet-drafts/draft-ietf-ftpext-data-connection-assuranc
  489. { e-00.txt
  490. {
  491. { Currently commented out because it does not work.
  492. }
  493. {
  494. { Rev 1.8 2/14/2003 11:40:16 AM JPMugaas
  495. { Fixed compile error.
  496. }
  497. {
  498. { Rev 1.7 2/14/2003 10:38:32 AM JPMugaas
  499. { Removed a problematic override for GetInternelResponse. It was messing up
  500. { processing of the FEAT.
  501. }
  502. {
  503. { Rev 1.6 12-16-2002 20:48:10 BGooijen
  504. { now uses TIdIOHandler.ConstructIOHandler to construct iohandlers
  505. { IPv6 works again
  506. { Independant of TIdIOHandlerStack again
  507. }
  508. {
  509. { Rev 1.5 12-15-2002 23:27:26 BGooijen
  510. { now compiles on Indy 10, but some things like IPVersion still need to be
  511. { changed
  512. }
  513. {
  514. { Rev 1.4 12/15/2002 04:07:02 PM JPMugaas
  515. { Started port to Indy 10. Still can not complete it though.
  516. }
  517. {
  518. { Rev 1.3 12/6/2002 05:29:38 PM JPMugaas
  519. { Now decend from TIdTCPClientCustom instead of TIdTCPClient.
  520. }
  521. {
  522. { Rev 1.2 12/1/2002 04:18:02 PM JPMugaas
  523. { Moved all dir parsing code to one place. Reworked to use more than one line
  524. { for determining dir format type along with flfNextLine dir format type.
  525. }
  526. {
  527. { Rev 1.1 11/14/2002 04:02:58 PM JPMugaas
  528. { Removed cludgy code that was a workaround for the RFC Reply limitation. That
  529. { is no longer limited.
  530. }
  531. {
  532. { Rev 1.0 11/14/2002 02:20:00 PM JPMugaas
  533. }
  534. unit IdFTP;
  535. {
  536. Change Log:
  537. 2002-10-25 - J. Peter Mugaas
  538. - added XCRC support - specified by "GlobalSCAPE Secure FTP Server User’s Guide"
  539. which is available at http://www.globalscape.com
  540. and also explained at http://www.southrivertech.com/support/titanftp/webhelp/titanftp.htm
  541. - added COMB support - specified by "GlobalSCAPE Secure FTP Server User’s Guide"
  542. which is available at http://www.globalscape.com
  543. and also explained at http://www.southrivertech.com/support/titanftp/webhelp/titanftp.htm
  544. 2002-10-24 - J. Peter Mugaas
  545. - now supports RFC 2640 - FTP Internalization
  546. 2002-09-18
  547. _ added AFromBeginning parameter to InternalPut to correctly honor the AAppend parameter of Put
  548. 2002-09-05 - J. Peter Mugaas
  549. - now complies with RFC 2389 - Feature negotiation mechanism for the File Transfer Protocol
  550. - now complies with RFC 2428 - FTP Extensions for IPv6 and NATs
  551. 2002-08-27 - Andrew P.Rybin
  552. - proxy support fix (non-standard ftp port's)
  553. 2002-01-xx - Andrew P.Rybin
  554. - Proxy support, OnAfterGet (ex:decrypt, set srv timestamp)
  555. - J.Peter Mugaas: not readonly ProxySettings
  556. A Neillans - 10/17/2001
  557. Merged changes submitted by Andrew P.Rybin
  558. Correct command case problems - some servers expect commands in Uppercase only.
  559. SP - 06/08/2001
  560. Added a few more functions
  561. Doychin - 02/18/2001
  562. OnAfterLogin event handler and Login method
  563. OnAfterLogin is executed after successfull login but before setting up the
  564. connection properties. This event can be used to provide FTP proxy support
  565. from the user application. Look at the FTP demo program for more information
  566. on how to provide such support.
  567. Doychin - 02/17/2001
  568. New onFTPStatus event
  569. New Quote method for executing commands not implemented by the compoent
  570. -CleanDir contributed by Amedeo Lanza
  571. TODO: Chage the FTP demo to demonstrate the use of the new events and add proxy support
  572. }
  573. interface
  574. uses
  575. Classes,
  576. IdAssignedNumbers, IdGlobal, IdCustomTransparentProxy, IdExceptionCore,
  577. IdExplicitTLSClientServerBase, IdFTPCommon, IdFTPList, IdFTPListParseBase, IdException,
  578. IdIOHandler, IdIOHandlerSocket,
  579. IdReplyFTP,
  580. IdReplyRFC,
  581. IdReply,
  582. IdSocketHandle, IdStreamVCL,
  583. IdTCPConnection, IdTCPClient, IdThread, IdTStrings, IdZLibCompressorBase;
  584. type
  585. //Added by SP
  586. TIdCreateFTPList = procedure(ASender: TObject; Var VFTPList: TIdFTPListItems) of object;
  587. // TIdCheckListFormat = procedure(ASender: TObject; const ALine: String; Var VListFormat: TIdFTPListFormat) of object;
  588. TOnAfterClientLogin = TNotifyEvent;
  589. TIdFtpAfterGet = procedure (ASender: TObject; VStream: TStream) of object; //APR
  590. TIdOnDataChannelCreate = procedure (ASender: TObject; ADataChannel: TIdTCPConnection) of object;
  591. TIdOnDataChannelDestroy = procedure (ASender: TObject; ADataChannel: TIdTCPConnection) of object;
  592. const
  593. Id_TIdFTP_TransferType = ftBinary;
  594. Id_TIdFTP_Passive = False;
  595. Id_TIdFTP_UseNATFastTrack = False;
  596. Id_TIdFTP_HostPortDelimiter = ':';
  597. Id_TIdFTP_DataConAssurance = False;
  598. type
  599. //APR 011216:
  600. TIdFtpProxyType = (fpcmNone,//Connect method:
  601. fpcmUserSite, //Send command USER user@hostname
  602. fpcmSite, //Send command SITE (with logon)
  603. fpcmOpen, //Send command OPEN
  604. fpcmUserPass,//USER user@firewalluser@hostname / PASS pass@firewallpass
  605. fpcmTransparent, //First use the USER and PASS command with the firewall username and password, and then with the target host username and password.
  606. fpcmHttpProxyWithFtp, //HTTP Proxy with FTP support. Will be supported in Indy 10
  607. fpcmCustomProxy // use OnCustomFTPProxy to customize the proxy login
  608. ); //TIdFtpProxyType
  609. //This has to be in the same order as TLS_AUTH_NAMES
  610. TAuthCmd = (tAuto, tAuthTLS, tAuthSSL, tAuthTLSC, tAuthTLSP);
  611. const
  612. Id_TIdFTP_DataPortProtection = ftpdpsClear;
  613. DEF_Id_TIdFTP_Implicit = False;
  614. DEF_Id_FTP_UseExtendedDataPort = False;
  615. DEF_Id_TIdFTP_UseExtendedData = False;
  616. DEF_Id_TIdFTP_UseMIS = False;
  617. DEF_Id_FTP_UseCCC = False;
  618. DEF_Id_FTP_AUTH_CMD = tAuto;
  619. type
  620. TIdFTPBannerEvent = procedure (ASender: TObject; const AMsg : String) of object;
  621. TIdFTPClientIdentifier = class (TPersistent)
  622. protected
  623. FClientName : String;
  624. FClientVersion : String;
  625. FPlatformDescription : String;
  626. procedure SetClientName(const AValue: String);
  627. procedure SetClientVersion(const AValue: String);
  628. procedure SetPlatformDescription(const AValue: String);
  629. function GetClntOutput: String;
  630. public
  631. procedure Assign(Source: TPersistent); override;
  632. property ClntOutput : String read GetClntOutput;
  633. published
  634. property ClientName : String read FClientName write SetClientName;
  635. property ClientVersion : String read FClientVersion write SetClientVersion;
  636. property PlatformDescription : String read FPlatformDescription write SetPlatformDescription;
  637. end;
  638. TIdFtpProxySettings = class (TPersistent)
  639. protected
  640. FHost, FUserName, FPassword: String;
  641. FProxyType: TIdFtpProxyType;
  642. FPort: Integer;
  643. public
  644. procedure Assign(Source: TPersistent); override;
  645. published
  646. property ProxyType: TIdFtpProxyType read FProxyType write FProxyType;
  647. property Host: String read FHost write FHost;
  648. property UserName: String read FUserName write FUserName;
  649. property Password: String read FPassword write FPassword;
  650. property Port: Integer read FPort write FPort;
  651. End;//TIdFtpProxySettings
  652. TIdFTPTZInfo = class(TPersistent)
  653. protected
  654. FGMTOffset : TDateTime;
  655. FGMTOffsetAvailable : Boolean;
  656. public
  657. procedure Assign(Source: TPersistent); override;
  658. published
  659. property GMTOffset : TDateTime read FGMTOffset write FGMTOffset;
  660. property GMTOffsetAvailable : Boolean read FGMTOffsetAvailable write FGMTOffsetAvailable;
  661. end;
  662. TIdFTP = class(TIdExplicitTLSClient)
  663. protected
  664. FAutoLogin: Boolean;
  665. FCurrentTransferMode : TIdFTPTransferMode;
  666. FClientInfo : TIdFTPClientIdentifier;
  667. FUsingSFTP : Boolean; //enable SFTP internel flag
  668. FUsingCCC : Boolean; //are we using FTP with SSL on a clear control channel?
  669. FCanUseMLS : Boolean; //can we use MLISx instead of LIST
  670. FUsedMLS : Boolean; //Did the developer use MLSx commands for the last list command
  671. FUsingExtDataPort : Boolean; //are NAT Extensions (RFC 2428 available) flag
  672. FUsingNATFastTrack : Boolean;//are we using NAT fastrack feature
  673. FCanResume: Boolean;
  674. FListResult: TIdStrings;
  675. FLoginMsg: TIdReplyFTP;
  676. FPassive: boolean;
  677. FDataPortProtection : TIdFTPDataPortSecurity;
  678. FAUTHCmd : TAuthCmd;
  679. FDataPort: Integer;
  680. FDataPortMin: Integer;
  681. FDataPortMax: Integer;
  682. FExternalIP : String;
  683. FResumeTested: Boolean;
  684. FSystemDesc: string;
  685. FTransferType: TIdFTPTransferType;
  686. FTransferTimeout : Integer;
  687. FDataChannel: TIdTCPConnection;
  688. FDirectoryListing: TIdFTPListItems;
  689. FDirFormat : String;
  690. FListParserClass : TIdFTPListParseClass;
  691. FOnAfterClientLogin: TNotifyEvent;
  692. FOnCreateFTPList: TIdCreateFTPList;
  693. FOnBeforeGet: TNotifyEvent;
  694. FOnBeforePut: TIdFtpAfterGet;
  695. //in case someone needs to do something special with the data being uploaded
  696. FOnAfterGet: TIdFtpAfterGet; //APR
  697. FOnAfterPut: TNotifyEvent; //JPM at Don Sider's suggestion
  698. FOnCustomFTPProxy : TNotifyEvent;
  699. FOnDataChannelCreate:TIdOnDataChannelCreate;
  700. FOnDataChannelDestroy:TIdOnDataChannelDestroy;
  701. FProxySettings: TIdFtpProxySettings;
  702. FUseExtensionDataPort : Boolean;
  703. FTryNATFastTrack : Boolean;
  704. FUseMLIS : Boolean;
  705. FLangsSupported : TIdStrings;
  706. FUseCCC: Boolean;
  707. //is the SSCN Client method on for this connection?
  708. FSSCNOn : Boolean;
  709. FOnBannerBeforeLogin : TIdFTPBannerEvent;
  710. FOnBannerAfterLogin : TIdFTPBannerEvent;
  711. FTZInfo : TIdFTPTZInfo;
  712. FCompressor : TIdZLibCompressorBase;
  713. //ZLib settings
  714. FZLibCompressionLevel : Integer; //7
  715. FZLibWindowBits : Integer; //-15
  716. FZLibMemLevel : Integer; //8
  717. FZLibStratagy : Integer; //0 - default
  718. //dir events for some GUI programs.
  719. //The directory was Retrieved from the FTP server.
  720. FOnRetrievedDir : TNotifyEvent;
  721. //parsing is done only when DirectoryListing is referenced
  722. FOnDirParseStart : TNotifyEvent;
  723. FOnDirParseEnd : TNotifyEvent;
  724. procedure DoOnRetrievedDir;
  725. procedure DoOnDirParseStart;
  726. procedure DoOnDirParseEnd;
  727. procedure SetTZInfo(const Value: TIdFTPTZInfo);
  728. function IsSiteZONESupported : Boolean;
  729. function IndexOfFeatLine(const AFeatLine : String):Integer;
  730. procedure ClearSSCN;
  731. function SetSSCNToOn : Boolean;
  732. procedure SendInternalPassive(const ACmd : String; var VIP: string; var VPort: integer);
  733. procedure SendCPassive(var VIP: string; var VPort: integer);
  734. function FindAuthCmd : String;
  735. function GetReplyClass:TIdReplyClass; override;
  736. //
  737. function EPRTParams(const AIP : String; const APort : Integer; const AIPVersion : TIdIPVersion): String;
  738. procedure ParseFTPList(AData : TIdStrings);
  739. procedure SetPassive(const AValue : Boolean);
  740. procedure SetTryNATFastTrack(const AValue: Boolean);
  741. procedure DoTryNATFastTrack;
  742. procedure SetUseExtensionDataPort(const AValue: Boolean);
  743. procedure SetIPVersion(const AValue: TIdIPVersion); override;
  744. procedure SetIOHandler(AValue: TIdIOHandler); override;
  745. function GetSupportsTLS: Boolean; override;
  746. procedure ConstructDirListing;
  747. procedure DoAfterLogin;
  748. procedure DoFTPList;
  749. procedure DoCustomFTPProxy;
  750. procedure DoOnBannerAfterLogin(AText : TIdStrings);
  751. procedure DoOnBannerBeforeLogin(AText : TIdStrings);
  752. procedure SendPBSZ; //protection buffer size
  753. procedure SendPROT; //data port protection
  754. procedure SendDataSettings; //this is for the extensions only;
  755. // procedure DoCheckListFormat(const ALine: String);
  756. function GetDirectoryListing: TIdFTPListItems;
  757. // function GetOnParseCustomListFormat: TIdOnParseCustomListFormat;
  758. procedure InitDataChannel;
  759. //PRET is to help distributed FTP systems by letting them know what you will do
  760. //before issuing a PASV. See: http://drftpd.mog.se/wiki/wiki.phtml?title=Distributed_PASV#PRE_Transfer_Command_for_Distributed_PASV_Transfers
  761. //for a discussion.
  762. procedure SendPret(const ACommand : String);
  763. procedure InternalGet(const ACommand: string; ADest: TIdStreamVCL; AResume: Boolean = false);
  764. procedure InternalPut(const ACommand: string; ASource: TIdStreamVCL; AFromBeginning: Boolean = true);
  765. // procedure SetOnParseCustomListFormat(const AValue: TIdOnParseCustomListFormat);
  766. procedure SendPassive(var VIP: string; var VPort: integer);
  767. procedure SendPort(AHandle: TIdSocketHandle); overload;
  768. procedure SendPort(const AIP : String; const APort : Integer); overload;
  769. procedure ParseEPSV(const AReply : String; var VIP : String; VPort : Integer);
  770. //These two are for RFC 2428.txt
  771. procedure SendEPort(AHandle: TIdSocketHandle); overload;
  772. procedure SendEPort(const AIP : String; const APort : Integer; const AIPVersion : TIdIPVersion); overload;
  773. procedure SendEPassive(var VIP: string; var VPort: integer);
  774. procedure SetProxySettings(const Value: TIdFtpProxySettings);
  775. procedure SetClientInfo(const AValue: TIdFTPClientIdentifier);
  776. procedure SendTransferType;
  777. procedure SetTransferType(AValue: TIdFTPTransferType);
  778. procedure DoBeforeGet; virtual;
  779. procedure DoBeforePut (AStream: TStream); virtual;
  780. procedure DoAfterGet (AStream: TStream); virtual; //APR
  781. procedure DoAfterPut; virtual;
  782. function IsValidOTPString(const AResponse:string):boolean;
  783. function GenerateOTP(const AResponse:string; const APassword:string):string;
  784. procedure FXPSetTransferPorts(AFromSite, AToSite: TIdFTP;
  785. const ATargetUsesPasv : Boolean);
  786. procedure FXPSendFile(AFromSite, AToSite: TIdFTP;
  787. const ASourceFile, ADestFile: String);
  788. function InternalEncryptedTLSFXP(AFromSite, AToSite: TIdFTP; const ASourceFile,
  789. ADestFile: String; const ATargetUsesPasv : Boolean) : Boolean;
  790. function InternalUnencryptedFXP(AFromSite, AToSite: TIdFTP; const ASourceFile,
  791. ADestFile: String; const ATargetUsesPasv : Boolean): Boolean;
  792. function ValidateInternalIsTLSFXP(AFromSite, AToSite: TIdFTP; const ATargetUsesPasv : Boolean): Boolean;
  793. procedure InitComponent; override;
  794. procedure SetUseTLS(AValue : TIdUseTLS); override;
  795. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  796. procedure SetDataPortProtection(AValue : TIdFTPDataPortSecurity);
  797. procedure SetAUTHCmd(const AValue : TAuthCmd);
  798. procedure SetUseCCC(const AValue: Boolean);
  799. public
  800. function IsExtSupported(const ACmd : String):Boolean;
  801. procedure ExtractFeatFacts(const ACmd : String; AResults : TIdStrings);
  802. //this function transparantly handles OTP based on the Last command response
  803. //so it needs to be called only after the USER command or equivilent.
  804. function GetLoginPassword : String; overload;
  805. function GetLoginPassword(const APrompt : String) : String; overload;
  806. procedure Abort; virtual;
  807. procedure Account(AInfo: String);
  808. procedure Allocate(AAllocateBytes: Integer);
  809. procedure ChangeDir(const ADirName: string);
  810. procedure ChangeDirUp;
  811. procedure Connect; override;
  812. destructor Destroy; override;
  813. procedure Delete(const AFilename: string);
  814. procedure FileStructure(AStructure: TIdFTPDataStructure);
  815. procedure Get(const ASourceFile: string; ADest: TIdStreamVCL; AResume: Boolean = false); overload;
  816. procedure Get(const ASourceFile: string; ADest: TStream; AResume: Boolean = false); overload;
  817. procedure Get(const ASourceFile, ADestFile: string; const ACanOverwrite: boolean = false; AResume: Boolean = false); overload;
  818. procedure Help(var AHelpContents: TIdStringList; ACommand: String = '');
  819. procedure KillDataChannel; virtual;
  820. procedure List; overload; //.NET Overload
  821. procedure List( //.NET Overload
  822. const ASpecifier: string;
  823. ADetails: Boolean = True); overload;
  824. procedure List(
  825. ADest: TIdStrings;
  826. const ASpecifier: string = '';
  827. ADetails: Boolean = True); overload;
  828. procedure ExtListDir(const ADest: TIdStrings=nil; const ADirectory: string = '');
  829. procedure ExtListItem(ADest: TIdStrings; AFList : TIdFTPListItems; const AItem: string=''); overload;
  830. procedure ExtListItem(ADest: TIdStrings; const AItem: string = ''); overload;
  831. procedure ExtListItem(AFList : TIdFTPListItems; const AItem : String= ''); overload;
  832. function FileDate(const AFileName : String; const AsGMT : Boolean = False): TDateTime;
  833. procedure Login;
  834. procedure MakeDir(const ADirName: string);
  835. procedure Noop;
  836. procedure SetCMDOpt(const ACMD, AOptions : String);
  837. procedure Put(const ASource: TIdStreamVCL; const ADestFile: string;
  838. const AAppend: boolean = false); overload;
  839. procedure Put(const ASource: TStream; const ADestFile: string;
  840. const AAppend: boolean = false); overload;
  841. procedure Put(const ASourceFile: string; const ADestFile: string = '';
  842. const AAppend: boolean = false); overload;
  843. procedure StoreUnique(const ASource: TIdStreamVCL); overload;
  844. procedure StoreUnique(const ASource: TStream); overload;
  845. procedure StoreUnique(const ASourceFile: string); overload;
  846. procedure SiteToSiteUpload(const AToSite : TIdFTP; const ASourceFile : String; const ADestFile : String = '');
  847. procedure SiteToSiteDownload(const AFromSite: TIdFTP; const ASourceFile : String; const ADestFile : String = '');
  848. procedure Quit;
  849. function Quote(const ACommand: String): SmallInt;
  850. procedure RemoveDir(const ADirName: string);
  851. procedure Rename(const ASourceFile, ADestFile: string);
  852. function ResumeSupported: Boolean;
  853. function RetrieveCurrentDir: string;
  854. procedure Site(const ACommand: string);
  855. function Size(const AFileName: String): Integer;
  856. procedure Status(AStatusList: TIdStrings);
  857. procedure StructureMount(APath: String);
  858. procedure TransferMode(ATransferMode: TIdFTPTransferMode);
  859. procedure ReInitialize(ADelay: Cardinal = 10);
  860. procedure SetLang(const ALangTag : String);
  861. function CRC(const AFIleName : String; const AStartPoint : Cardinal = 0; const AEndPoint : Cardinal=0) : Int64;
  862. //file parts must be in order in TIdStrings parameter
  863. //GlobalScape FTP Pro uses this for multipart simultanious file uploading
  864. procedure CombineFiles(const ATargetFile : String; AFileParts : TIdStrings);
  865. //Set modified file time.
  866. procedure SetModTime(const AFileName: String; const ALocalTime: TDateTime);
  867. procedure SetModTimeGMT(const AFileName : String; const AGMTTime: TDateTime);
  868. // servers that support MDTM yyyymmddhhmmss[+-xxx] and also support LIST -T
  869. //This is true for servers that are known to support these even if they aren't
  870. //listed in the FEAT reply.
  871. function IsServerMDTZAndListTForm : Boolean;
  872. //
  873. property CanResume: Boolean read ResumeSupported;
  874. property DirectoryListing: TIdFTPListItems read GetDirectoryListing;
  875. property DirFormat : String read FDirFormat;
  876. property LangsSupported : TIdStrings read FLangsSupported;
  877. property ListParserClass : TIdFTPListParseClass read FListParserClass write FListParserClass;
  878. property LoginMsg: TIdReplyFTP read FLoginMsg;
  879. property ListResult: TIdStrings read FListResult;
  880. property SystemDesc: string read FSystemDesc;
  881. property TZInfo : TIdFTPTZInfo read FTZInfo write SetTZInfo;
  882. property UsingExtDataPort : Boolean read FUsingExtDataPort;
  883. property UsingNATFastTrack : Boolean read FUsingNATFastTrack;
  884. property UsingSFTP : Boolean read FUsingSFTP;
  885. property CurrentTransferMode : TIdFTPTransferMode read FCurrentTransferMode write TransferMode;
  886. published
  887. property AutoLogin: Boolean read FAutoLogin write FAutoLogin;
  888. // This is an object that can compress and decompress HTTP Deflate encoding
  889. property Compressor : TIdZLibCompressorBase read FCompressor write FCompressor;
  890. property Host;
  891. property UseCCC : Boolean read FUseCCC write SetUseCCC default DEF_Id_FTP_UseCCC;
  892. property Passive: boolean read FPassive write SetPassive default Id_TIdFTP_Passive;
  893. property DataPortProtection : TIdFTPDataPortSecurity read FDataPortProtection write SetDataPortProtection default Id_TIdFTP_DataPortProtection;
  894. property AUTHCmd : TAuthCmd read FAUTHCmd write SetAUTHCmd default DEF_Id_FTP_AUTH_CMD;
  895. property DataPort: Integer read FDataPort write FDataPort default 0;
  896. property DataPortMin: Integer read FDataPortMin write FDataPortMin default 0;
  897. property DataPortMax: Integer read FDataPortMax write FDataPortMax default 0;
  898. property ExternalIP : String read FExternalIP write FExternalIP;
  899. property Password;
  900. property TransferType: TIdFTPTransferType read FTransferType write SetTransferType default Id_TIdFTP_TransferType;
  901. property TransferTimeout: Integer read FTransferTimeout write FTransferTimeout default IdDefTimeout;
  902. property Username;
  903. property Port default IDPORT_FTP;
  904. property UseExtensionDataPort : Boolean read FUseExtensionDataPort write SetUseExtensionDataPort default DEF_Id_TIdFTP_UseExtendedData;
  905. property UseMLIS : Boolean read FUseMLIS write FUseMLIS default DEF_Id_TIdFTP_UseMIS;
  906. property TryNATFastTrack : Boolean read FTryNATFastTrack write SetTryNATFastTrack default Id_TIdFTP_UseNATFastTrack;
  907. property ProxySettings: TIdFtpProxySettings read FProxySettings write SetProxySettings;
  908. property ClientInfo : TIdFTPClientIdentifier read FClientInfo write SetClientInfo;
  909. property UseTLS;
  910. property OnTLSNotAvailable;
  911. property OnBannerBeforeLogin : TIdFTPBannerEvent read FOnBannerBeforeLogin write FOnBannerBeforeLogin;
  912. property OnBannerAfterLogin : TIdFTPBannerEvent read FOnBannerAfterLogin write FOnBannerAfterLogin;
  913. property OnAfterClientLogin: TOnAfterClientLogin read FOnAfterClientLogin write FOnAfterClientLogin;
  914. property OnCreateFTPList: TIdCreateFTPList read FOnCreateFTPList write FOnCreateFTPList;
  915. property OnAfterGet: TIdFtpAfterGet read FOnAfterGet write FOnAfterGet; //APR
  916. property OnCustomFTPProxy : TNotifyEvent read FOnCustomFTPProxy write FOnCustomFTPProxy;
  917. property OnDataChannelCreate:TIdOnDataChannelCreate read FOnDataChannelCreate write FOnDataChannelCreate;
  918. property OnDataChannelDestroy:TIdOnDataChannelDestroy read FOnDataChannelDestroy write FOnDataChannelDestroy;
  919. //The directory was Retrieved from the FTP server.
  920. property OnRetrievedDir : TNotifyEvent read FOnRetrievedDir write FOnRetrievedDir;
  921. //parsing is done only when DirectoryLiusting is referenced
  922. property OnDirParseStart : TNotifyEvent read FOnDirParseStart write FOnDirParseStart;
  923. property OnDirParseEnd : TNotifyEvent read FOnDirParseEnd write FOnDirParseEnd;
  924. end;
  925. EIdFTPException = class(EIdException);
  926. EIdFTPFileAlreadyExists = class(EIdFTPException);
  927. EIdFTPMustUseExtWithIPv6 = class(EIdFTPException);
  928. EIdFTPMustUseExtWithNATFastTrack = class(EIdFTPException);
  929. EIdFTPPassiveMustBeTrueWithNATFT = class(EIdFTPException);
  930. EIdFTPServerSentInvalidPort = class(EIdFTPException);
  931. EIdFTPSiteToSiteTransfer = class(EIdFTPException);
  932. EIdFTPSToSNATFastTrack = class(EIdFTPSiteToSiteTransfer);
  933. EIdFTPSToSNoDataProtection = class(EIdFTPSiteToSiteTransfer);
  934. EIdFTPSToSIPProtoMustBeSame = class(EIdFTPSiteToSiteTransfer);
  935. EIdFTPSToSBothMostSupportSSCN = class(EIdFTPSiteToSiteTransfer);
  936. EIdFTPSToSTransModesMustBeSame = class(EIdFTPSiteToSiteTransfer);
  937. EIdFTPUnknownOTPMethodException = class(EIdFTPException);
  938. EIdFTPOnCustomFTPProxyRequired = class(EIdFTPException);
  939. EIdFTPConnAssuranceFailure = class(EIdFTPException);
  940. EIdFTPWrongIOHandler = class(EIdFTPException);
  941. EIdFTPUploadFileNameCanNotBeEmpty = class(EIdFTPException);
  942. EIdFTPDataPortProtection = class(EIdFTPException);
  943. EIdFTPNoDataPortProtectionAfterCCC = class(EIdFTPDataPortProtection);
  944. EIdFTPNoDataPortProtectionWOEncryption = class(EIdFTPDataPortProtection);
  945. EIdFTPNoCCCWOEncryption = class(EIdFTPException);
  946. EIdFTPAUTHException = class(EIdFTPException);
  947. EIdFTPNoAUTHWOSSL = class(EIdFTPAUTHException);
  948. EIdFTPCanNotSetAUTHCon = class(EIdFTPAUTHException);
  949. implementation
  950. uses
  951. IdComponent, IdResourceStringsCore, IdIOHandlerStack, IdResourceStringsProtocols,
  952. IdSSL, IdGlobalProtocols,
  953. IdStack, IdSimpleServer,
  954. SysUtils, IdOTPCalculator;
  955. function CleanDirName(const APWDReply: string): string;
  956. begin
  957. Result := APWDReply;
  958. Delete(result, 1, IndyPos('"', result)); // Remove first doublequote {do not localize}
  959. Result := Copy(result, 1, IndyPos('"', result) - 1); // Remove anything from second doublequote {do not localize} // to end of line
  960. end;
  961. function TIdFTP.IsValidOTPString(const AResponse:string):boolean;
  962. var LChallenge:string;
  963. LChallengeStartPos:integer;
  964. LMethod:string;
  965. begin
  966. LChallengeStartPos := pos('otp-',AResponse); {do not localize}
  967. if LChallengeStartPos>0 then begin
  968. inc(LChallengeStartPos,4); // to remove "otp-"
  969. LChallenge:=copy(AResponse,LChallengeStartPos,$FFFF);
  970. LMethod:=Fetch(LChallenge);
  971. result := (LMethod='md4') or (LMethod='md5') or (LMethod='sha1'); // methods are case sensitive {do not localize}
  972. end else result:=false;
  973. end;
  974. function TIdFTP.GenerateOTP(const AResponse:string; const APassword:string):string;
  975. var LChallenge:string;
  976. LChallengeStartPos:integer;
  977. LMethod:string;
  978. LSeed:string;
  979. LCount:integer;
  980. begin
  981. LChallengeStartPos := pos('otp-', AResponse); {do not localize}
  982. if LChallengeStartPos > 0 then begin
  983. inc(LChallengeStartPos, 4); // to remove "otp-"
  984. LChallenge := copy(AResponse,LChallengeStartPos, $FFFF);
  985. LMethod := Fetch(LChallenge);
  986. LCount := StrToInt(Fetch(LChallenge));
  987. LSeed := Fetch(LChallenge);
  988. if LMethod = 'md5' then // methods are case sensitive {do not localize}
  989. begin
  990. Result := TIdOTPCalculator.ToSixWordFormat(TIdOTPCalculator.GenerateKeyMD5(lseed,APassword,LCount))
  991. end
  992. else
  993. begin
  994. if LMethod = 'md4' then {do not localize}
  995. begin
  996. Result := TIdOTPCalculator.ToSixWordFormat(TIdOTPCalculator.GenerateKeyMD4(lseed,APassword,LCount))
  997. end
  998. else
  999. begin
  1000. if LMethod = 'sha1' then {do not localize}
  1001. begin
  1002. Result := TIdOTPCalculator.ToSixWordFormat(TIdOTPCalculator.GenerateKeySHA1(lseed,APassword,LCount))
  1003. end
  1004. else
  1005. begin
  1006. Raise EIdFTPUnknownOTPMethodException.Create(RSFTPOTPMethod);
  1007. end;
  1008. end;
  1009. end;
  1010. end;
  1011. end;
  1012. procedure TIdFTP.InitComponent;
  1013. begin
  1014. inherited;
  1015. //
  1016. FAutoLogin := True;
  1017. FRegularProtPort := IdPORT_FTP;
  1018. FImplicitTLSProtPort := IdPORT_ftps;
  1019. //
  1020. Port := IDPORT_FTP;
  1021. Passive := Id_TIdFTP_Passive;
  1022. FDataPortProtection := Id_TIdFTP_DataPortProtection;
  1023. FUseCCC := DEF_Id_FTP_UseCCC;
  1024. FAUTHCmd := DEF_Id_FTP_AUTH_CMD;
  1025. FDataPort := 0;
  1026. FDataPortMin := 0;
  1027. FDataPortMax := 0;
  1028. FUseExtensionDataPort := DEF_Id_TIdFTP_UseExtendedData;
  1029. FTryNATFastTrack := Id_TIdFTP_UseNATFastTrack;
  1030. FTransferType := Id_TIdFTP_TransferType;
  1031. FTransferTimeout := IdDefTimeout;
  1032. FLoginMsg := TIdReplyFTP.Create(NIL);
  1033. FListResult := TIdStringList.Create;
  1034. FLangsSupported := TIdStringList.Create;
  1035. FCanResume := false;
  1036. FResumeTested := false;
  1037. FProxySettings:= TIdFtpProxySettings.Create; //APR
  1038. FClientInfo := TIdFTPClientIdentifier.Create;
  1039. FTZInfo := TIdFTPTZInfo.Create;
  1040. FTZInfo.FGMTOffsetAvailable := False;
  1041. FUseMLIS := DEF_Id_TIdFTP_UseMIS;
  1042. FUsedMLS := False;
  1043. FCanUseMLS := False; //initialize MLIS flags
  1044. //Settings specified by
  1045. // http://www.ietf.org/internet-drafts/draft-preston-ftpext-deflate-00.txt
  1046. FZLibCompressionLevel := DEF_ZLIB_COMP_LEVEL;
  1047. FZLibWindowBits := DEF_ZLIB_WINDOW_BITS; //-15 - no extra headers
  1048. FZLibMemLevel := DEF_ZLIB_MEM_LEVEL;
  1049. FZLibStratagy := DEF_ZLIB_STRATAGY; // - default
  1050. end;
  1051. procedure TIdFTP.Connect;
  1052. var
  1053. LHost: String;
  1054. LPort: Integer;
  1055. LBuf : String;
  1056. begin
  1057. FCurrentTransferMode := dmStream;
  1058. FTZInfo.FGMTOffsetAvailable := False;
  1059. //FSSCNOn should be set to false to prevent problems.
  1060. FSSCNOn := False;
  1061. FUsingSFTP := False;
  1062. FUsingCCC := False;
  1063. if FUseExtensionDataPort then begin
  1064. FUsingExtDataPort := True;
  1065. end;
  1066. FUsingNATFastTrack := False;
  1067. try
  1068. //APR 011216: proxy support
  1069. LHost := FHost;
  1070. LPort := FPort;
  1071. try
  1072. if (ProxySettings.ProxyType > fpcmNone) and (Length(ProxySettings.Host) > 0) then begin
  1073. FHost := ProxySettings.Host;
  1074. FPort := ProxySettings.Port;
  1075. end;
  1076. if (FUseTLS=utUseImplicitTLS) then
  1077. begin
  1078. //at this point, we treat implicit FTP as if it were explicit FTP with TLS
  1079. FUsingSFTP := True;
  1080. end;
  1081. inherited Connect;
  1082. finally
  1083. FHost := LHost;
  1084. FPort := LPort;
  1085. end;//tryf
  1086. GetResponse([220]);
  1087. FGreeting.Assign(LastCmdResult);
  1088. DoOnBannerBeforeLogin (FGreeting.FormattedReply);
  1089. if AutoLogin then begin
  1090. Login;
  1091. DoAfterLogin;
  1092. //Fast track is set only one time per connection and no more, even
  1093. //with REINIT
  1094. if TryNATFastTrack then begin
  1095. DoTryNATFastTrack;
  1096. end;
  1097. if (FUseTLS=utUseImplicitTLS) then begin
  1098. //at this point, we treat implicit FTP as if it were explicit FTP with TLS
  1099. FUsingSFTP := True;
  1100. end;
  1101. // OpenVMS 7.1 replies with 200 instead of 215 - What does the RFC say about this?
  1102. // if SendCmd('SYST', [200, 215, 500]) = 500 then begin {do not localize}
  1103. //Do not fault if SYST was not understood by the server. Novel Netware FTP
  1104. //may not understand SYST.
  1105. if SendCmd('SYST') = 500 then begin {do not localize}
  1106. FSystemDesc := RSFTPUnknownHost;
  1107. end else begin
  1108. FSystemDesc := LastCmdResult.Text[0];
  1109. end;
  1110. if IsSiteZONESupported then
  1111. begin
  1112. if not FCanUseMLS then
  1113. begin
  1114. if SendCmd('SITE ZONE') = 210 then {do not localize}
  1115. begin
  1116. if LastCmdResult.Text.Count > 0 then
  1117. begin
  1118. LBuf := LastCmdResult.Text[0];
  1119. //remove UTC from reply string "UTC-300"
  1120. IdDelete(LBuf,1,3);
  1121. FTZInfo.GMTOffset := MDTMOffset(LBuf);
  1122. FTZInfo.FGMTOffsetAvailable := True;
  1123. end;
  1124. end;
  1125. end;
  1126. end;
  1127. DoStatus(ftpReady, [RSFTPStatusReady]);
  1128. end;
  1129. except
  1130. Disconnect;
  1131. raise;
  1132. end;
  1133. end;
  1134. procedure TIdFTP.SetTransferType(AValue: TIdFTPTransferType);
  1135. begin
  1136. if AValue <> FTransferType then begin
  1137. if not Assigned(FDataChannel) then begin
  1138. FTransferType := AValue;
  1139. if Connected then begin
  1140. SendTransferType;
  1141. end;
  1142. end
  1143. end;
  1144. end;
  1145. procedure TIdFTP.SendTransferType;
  1146. var
  1147. s: string;
  1148. begin
  1149. case TransferType of
  1150. ftAscii: s := 'A'; {do not localize}
  1151. ftBinary: s := 'I'; {do not localize}
  1152. end;
  1153. SendCmd('TYPE ' + s, 200); {do not localize}
  1154. end;
  1155. function TIdFTP.ResumeSupported: Boolean;
  1156. begin
  1157. if FResumeTested then result := FCanResume
  1158. else begin
  1159. FResumeTested := true;
  1160. FCanResume := Quote('REST 1') = 350; {do not localize}
  1161. result := FCanResume;
  1162. Quote('REST 0'); {do not localize}
  1163. end;
  1164. end;
  1165. procedure TIdFTP.Get(const ASourceFile: string; ADest: TIdStreamVCL; AResume: Boolean = false);
  1166. begin
  1167. //for SSL FXP, we have to do it here because InternalGet is used by the LIST command
  1168. //where SSCN is ignored.
  1169. ClearSSCN;
  1170. AResume := AResume and CanResume;
  1171. DoBeforeGet; //APR
  1172. InternalGet('RETR ' + ASourceFile, ADest, AResume); {do not localize}
  1173. DoAfterGet(ADest.VCLStream ); //APR
  1174. end;
  1175. procedure TIdFTP.Get(const ASourceFile: string; ADest: TStream; AResume: Boolean = false);
  1176. var LStream : TIdStreamVCL;
  1177. begin
  1178. //for SSL FXP, we have to do it here because InternalGet is used by the LIST command
  1179. //where SSCN is ignored.
  1180. ClearSSCN;
  1181. AResume := AResume and CanResume;
  1182. LStream := TIdStreamVCL.Create(ADest);
  1183. try
  1184. Get(ASourceFile,LStream,AResume);
  1185. finally
  1186. FreeAndNil(LStream);
  1187. end;
  1188. end;
  1189. procedure TIdFTP.Get(const ASourceFile, ADestFile: string; const ACanOverwrite: boolean = false;
  1190. AResume: Boolean = false);
  1191. var
  1192. LDestStream: TFileStream;
  1193. begin
  1194. if FileExists(ADestFile) then begin
  1195. AResume := AResume and CanResume;
  1196. if ACanOverwrite and (not AResume) then begin
  1197. DeleteFile(ADestFile);
  1198. LDestStream := TFileStream.Create(ADestFile, fmCreate);
  1199. end
  1200. else begin
  1201. if (not ACanOverwrite) and AResume then begin
  1202. LDestStream := TFileStream.Create(ADestFile, fmOpenReadWrite or fmShareDenyWrite);
  1203. LDestStream.Position := LDestStream.Size;
  1204. end
  1205. else begin
  1206. raise EIdFTPFileAlreadyExists.Create(RSDestinationFileAlreadyExists);
  1207. end;
  1208. end;
  1209. end
  1210. else begin
  1211. LDestStream := TFileStream.Create(ADestFile, fmCreate);
  1212. end;
  1213. try
  1214. Get(ASourceFile, LDestStream, AResume);
  1215. finally
  1216. FreeAndNil(LDestStream);
  1217. end;
  1218. end;
  1219. procedure TIdFTP.DoBeforeGet;
  1220. begin
  1221. if Assigned(FOnBeforeGet) then
  1222. begin
  1223. FOnBeforeGet(Self);
  1224. end;
  1225. end;
  1226. procedure TIdFTP.DoBeforePut (AStream: TStream);
  1227. begin
  1228. if Assigned(FOnBeforePut) then
  1229. begin
  1230. FOnBeforePut(SELF,AStream);
  1231. end;
  1232. end;
  1233. procedure TIdFTP.DoAfterGet (AStream: TStream);//APR
  1234. Begin
  1235. if Assigned(FOnAfterGet) then
  1236. begin
  1237. FOnAfterGet(SELF,AStream);
  1238. end;
  1239. End;//TIdFTP.AtAfterFileGet
  1240. procedure TIdFTP.DoAfterPut;
  1241. begin
  1242. if Assigned(FOnAfterPut) then
  1243. begin
  1244. FOnAfterPut(Self);
  1245. end;
  1246. end;
  1247. procedure TIdFTP.ConstructDirListing;
  1248. begin
  1249. if not Assigned(FDirectoryListing) then begin
  1250. if not (csDesigning in ComponentState) then begin
  1251. DoFTPList;
  1252. end;
  1253. if not Assigned(FDirectoryListing) then begin
  1254. FDirectoryListing := TIdFTPListItems.Create;
  1255. end;
  1256. end else begin
  1257. FDirectoryListing.Clear;
  1258. end;
  1259. end;
  1260. procedure TIdFTP.List(
  1261. ADest: TIdStrings;
  1262. const ASpecifier: string = ''; {do not localize}
  1263. ADetails: Boolean = True);
  1264. var
  1265. LDest: TIdStringStream;
  1266. LTrans : TIdFTPTransferType;
  1267. LStream : TIdStreamVCL;
  1268. begin
  1269. if FCanUseMLS then begin
  1270. ExtListDir(ADest);
  1271. Exit;
  1272. end;
  1273. //Note that for LIST, it might be best to put the connection in ASCII
  1274. //mode because some old servers such as TOPS20 might require this. We restore it
  1275. //if the original mode was not ASCII. It's a good idea to do this anyway
  1276. //because some clients still do this such as WS_FTP Pro and Microsoft's FTP Client.
  1277. LTrans := Self.TransferType;
  1278. if LTrans <> ftASCII then begin
  1279. Self.TransferType := ftASCII;
  1280. end;
  1281. try
  1282. LDest := TIdStringStream.Create(''); try
  1283. LStream := TIdStreamVCL.Create(LDest); try
  1284. InternalGet(Trim(iif(ADetails, 'LIST', 'NLST') + ' ' + ASpecifier), LStream); {do not localize}
  1285. finally FreeAndNil(LStream); end;
  1286. FreeAndNil(FDirectoryListing);
  1287. FListResult.Text := LDest.DataString;
  1288. if ADest <> nil then begin
  1289. ADest.Assign(FListResult);
  1290. end;
  1291. FUsedMLS := False;
  1292. finally FreeAndNil(LDest); end;
  1293. DoOnRetrievedDir;
  1294. finally
  1295. if LTrans…

Large files files are truncated, but you can click here to view the full file