├── .gitignore ├── COPYING ├── CREDITS ├── ChangeLog ├── Dockerfile ├── Makefile ├── README.md ├── ToDo ├── ftplib.cpp ├── ftplib.h └── sample ├── Readme.md └── sample.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.o 3 | 4 | *.a 5 | 6 | *.so 7 | 8 | *.2 9 | 10 | *.0 11 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 489 | 490 | Also add information on how to contact you by electronic and paper mail. 491 | 492 | You should also get your employer (if you work as a programmer) or your 493 | school, if any, to sign a "copyright disclaimer" for the library, if 494 | necessary. Here is a sample; alter the names: 495 | 496 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 497 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 498 | 499 | , 1 April 1990 500 | Ty Coon, President of Vice 501 | 502 | That's all there is to it! 503 | -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | Thomas Pfau (ftplib author) 2 | Eli Moulton (bugfix) 3 | wangxi19 (bugfix) 4 | Fojtik (bugfix) 5 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | v2.0.5 2 | - Fixed Bug when seeking on potentially unopened file. 3 | - Removed some compiler warnings. 4 | - Fixed sprintf undefined behaviour. 5 | 6 | v2.0.4 7 | 8 | - Added support for MSVC 2012. 9 | - Documentation migrated from HTML to Markdown. 10 | 11 | v2.0.3 12 | 13 | - License changed to LGPL. 14 | - Added support for OSX. 15 | 16 | v2.0.2 17 | 18 | - Fixed a bug in the upload routine. 19 | 20 | v2.0.1 21 | 22 | - Fixed a problem with the -DNOSSL compile flag. 23 | - Removed an unnecessary sys/time.h dependance. 24 | 25 | v2.0.0 26 | 27 | - Implemented SSL/TLS certification callback. 28 | - SSLv2 connections aren't allowed any more. 29 | - Made library work on win32 systems. 30 | - Correct pasv reply functionality for misbehaving NAT servers. 31 | - Cleaned up code and slightly modified interface. 32 | - SSL support can be turned off now. 33 | - Large file support. 34 | - Fixed error when fxp'ing a rejected file. 35 | - Logging functionality extended. 36 | - Callback mechanisms improved. 37 | 38 | v1.0.1 39 | 40 | - ftplib::Fxp was always returning 0, fixed this. 41 | - Quit returns if there's no connection anymore to do QUIT. 42 | - Fixed a bug in secure upload. 43 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:jessie 2 | 3 | RUN apt-get -y update 4 | RUN apt-get -y install build-essential libssl-dev 5 | # COPY / /src 6 | # WORKDIR /src 7 | # CMD make 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # ftplibpp makefile 2 | 3 | SONAME = 2 4 | SOVERSION = $(SONAME).0 5 | 6 | TARGETS = libftp++.a libftp++.so 7 | OBJECTS = ftplib.o 8 | SOURCES = ftplib.cpp 9 | 10 | CFLAGS = -Wall $(DEBUG) -I. $(INCLUDES) $(DEFINES) 11 | LDFLAGS = -L. 12 | DEPFLAGS = 13 | 14 | UNAME := $(shell uname) 15 | ifeq ($(UNAME), Darwin) 16 | SOFLAG=install_name 17 | ifndef NOSSL 18 | LIBS = -lssl -lcrypto 19 | else 20 | LIBS = 21 | endif 22 | endif 23 | ifeq ($(UNAME), Linux) 24 | SOFLAG=soname 25 | ifndef NOSSL 26 | LIBS = -lssl 27 | else 28 | LIBS = 29 | endif 30 | endif 31 | 32 | all : $(TARGETS) 33 | 34 | clean : 35 | rm -f $(OBJECTS) core *.bak 36 | rm -rf unshared 37 | rm -f $(TARGETS) .depend 38 | rm -f libftp.so.* 39 | 40 | uninstall : 41 | rm -f /usr/local/lib/libftp.so.* 42 | rm -f /usr/local/include/libftp.h 43 | 44 | install : all 45 | install -m 644 libftp.so.$(SOVERSION) /usr/local/lib 46 | install -m 644 ftplib.h /usr/local/include 47 | (cd /usr/local/lib && \ 48 | ln -sf libftp.so.$(SOVERSION) libftp.so.$(SONAME) && \ 49 | ln -sf libftp.so.$(SONAME) libftp.so) 50 | 51 | depend : 52 | $(CC) $(CFLAGS) -M $(SOURCES) > .depend 53 | 54 | ftplib.o: ftplib.cpp ftplib.h 55 | $(CC) -c $(CFLAGS) -fPIC -D_REENTRANT -DNOSSL $< -o $@ 56 | 57 | libftp++.a: ftplib.o 58 | ar -rcs $@ $< 59 | 60 | libftp.so.$(SOVERSION): ftplib.o 61 | $(CC) -shared -Wl,-$(SOFLAG),libftp.so.$(SONAME) $(LIBS) -lc -o $@ $< 62 | 63 | libftp++.so: libftp.so.$(SOVERSION) 64 | ln -sf $< libftp.so.$(SONAME) 65 | ln -sf $< $@ 66 | 67 | ifeq (.depend,$(wildcard .depend)) 68 | include .depend 69 | endif 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ftplibpp 2 | 3 | Platform independent c++ library providing ftp client functionality. 4 | 5 | ftplibpp contains a c++ class providing ftp client functionality. It supports all basic ftp functionality plus some advanced features like resuming, fxp, ssl/tls encryption, large file support, or logging to fit todays standards. 6 | 7 | ## Build 8 | 9 | ### Docker (Linux) 10 | 11 | ``` 12 | docker build -t build-env . 13 | docker run -e -v $PWD:/src -w /src build-env make 14 | ``` 15 | 16 | ### MacOS without SSL 17 | 18 | ``` 19 | NOSSL=1 make 20 | ``` 21 | 22 | ## Documentation 23 | 24 | ftplibpp provides a c++ class providing ftp client functionality. It supports all basic ftp functionality plus some 25 | advanced features like resuming, fxp, ssl/tls encryption, large file support, or logging to fit todays standards. The 26 | very base of ftplibpp is Thomas Pfau's [ftplib c library](http://nbpfaus.net/%7Epfau/ftplib/). 27 | 28 | Every ftp session is represented by an ftplib object, whose methods are called to communicate with the ftp server. The 29 | ftp sessions should begin with a call to `myftp.Connect("myftp.org:21")` (and maybe `myftp.NegotiateEncryption()` ), be 30 | followed with `myftp.Login("myuser","mypass")` and ended by `myftp.Quit()`. For the magic in between, read the class 31 | methods documentation. Most methods have their tasks pretty much explained in their name. ftplibpp uses OpenSSL for 32 | encryption functionality, if you don't need it you can set the `NOSSL` flag (e.g. `g++ -c ftplib.cpp -DNOSSL`). If your 33 | system does not feature large file support (or does not need specific LFS functions, because it's built in yet) you can 34 | use the `NOLFS` flag (e.g. `g++ -c ftplib.cpp -DNOLFS`). The flag `_FTPLIB_SSL_CLIENT_METHOD_` exists to override the 35 | openssl client method in use, the default is `TLSv1_2_client_method`, override by compiling with `-D_FTPLIB_SSL_CLIENT_METHOD_=${SOME_METHOD}`. 36 | 37 | ### Public types 38 | 39 | * [`int (* FtpCallbackIdle )(void *arg)`](#ftpcallbackidle) 40 | * [`void (* FtpCallbackLog )(char *str, void* arg, bool out)`](#ftpcallbacklog) 41 | * [`int (* FtpCallbackXfer )(off64_t xfered, void *arg)`](#ftpcallbackxfer) 42 | * [`bool (* FtpCallbackCert )(void *arg, X509 *cert)`](#ftpcallbackCert) 43 | * [`enum accesstype`](#accesstype) 44 | * [`enum transfermode`](#transfermode) 45 | * [`enum connmode`](#connmode) 46 | * [`enum fxpmethod`](#fxpmethod) 47 | * [`enum dataencryption`](#dataencryption) 48 | 49 | ### Methods 50 | 51 | * [`ftplib ()`](#ftplib) 52 | * [`char* LastResponse ()`](#lastresponse) 53 | * [`int Connect (const char *host)`](#connect) 54 | * [`int Login (const char *user, const char *pass)`](#login) 55 | * [`int Site (const char *cmd)`](#site) 56 | * [`int Raw (const char *cmd)`](#raw) 57 | * [`int SysType (char* buf, int max)`](#systype) 58 | * [`int Mkdir (const char *path)`](#mkdir) 59 | * [`int Chdir (const char *path)`](#chdir) 60 | * [`int Cdup ()`](#cdup) 61 | * [`int Rmdir (const char *path)`](#rmdir) 62 | * [`int Pwd (char *path, int max)`](#pwd) 63 | * [`int Nlst (const char *outputfile, const char *path)`](#nlst) 64 | * [`int Dir (const char *outputfile, const char *path)`](#dir) 65 | * [`int Size (const char *path, int *size, transfermode mode)`](#size) 66 | * [`int ModDate (const char *path, char *dt, int max)`](#moddate) 67 | * [`int Get (const char *outputfile, const char *path, transfermode mode)`](#get) 68 | * [`int Get (const char *outputfile, const char *path, transfermode mode, off64_t offset)`](#get2) 69 | * [`int Put (const char *inputfile, const char *path, transfermode mode)`](#put) 70 | * [`int Put (const char *inputfile, const char *path, transfermode mode, off64_t offset)`](#put2) 71 | * [`int Rename (const char *src, const char *dst)`](#rename) 72 | * [`int Delete (const char *path)`](#delete) 73 | * [`int SetDataEncryption (dataencryption enc)`](#setdataencryption) 74 | * [`int NegotiateEncryption ()`](#negotiateencryption) 75 | * [`ftphandle* RawOpen (const char *path, accesstype type, transfermode mode)`](#rawopen) 76 | * [`int RawRead (void *buf, int max, ftphandle *handle)`](#rawread) 77 | * [`int RawWrite (void *buf, int len, ftphandle *handle)`](#rawwrite) 78 | * [`int RawClose (ftphandle *handle)`](#rawclose) 79 | * [`void Quit ()`](#quit) 80 | * [`void SetCallbackIdleFunction (FtpCallbackIdle pointer)`](#setcallbackidlefunction) 81 | * [`void SetCallbackLogFunction (FtpCallbackLog pointer)`](#setcallbacklogfunction) 82 | * [`void SetCallbackXferFunction (FtpCallbackXfer pointer)`](#setcallbackxferfunction) 83 | * [`void SetCallbackCertFunction (FtpCallbackCert pointer)`](#setcallbackcertfunction) 84 | * [`void SetCallbackArg (void *arg)`](#setcallbackarg) 85 | * [`void SetCallbackBytes (off64_t bytes)`](#setcallbackbytes) 86 | * [`void SetCallbackIdletime (int time)`](#setcallbackidletime) 87 | * [`void SetCorrectPasv (bool b)`](#setcorrectpasv) 88 | * [`void SetConnmode (ftplib::ftp mode)`](#setconnmode) 89 | 90 | ### Public static methods 91 | 92 | * [`static int Fxp (ftplib* src, ftplib* dst, const char *pathSrc, const char *pathDst, ftplib::ftp mode, ftplib::ftp method)`](#fxp) 93 | 94 | ## Details 95 | 96 | 97 | 98 | ### int (* FtpCallbackIdle )(void *arg) 99 | 100 | [typedef] 101 | 102 | `typedef int (*FtpCallbackIdle)(void *arg);` 103 | 104 | 105 | 106 | ### void (* FtpCallbackLog )(char *str, void* arg, bool out) 107 | 108 | [typedef] 109 | 110 | `typedef void (* FtpCallbackLog)(char *str, void* arg, bool out);` 111 | 112 | #### Notes: 113 | 114 | *out* indicates wether the log information in *str* is incoming or outgoing. 115 | 116 | 117 | 118 | ### int (* FtpCallbackXfer )(off64_t xfered, void *arg) 119 | 120 | [typedef] 121 | 122 | `typedef int (*FtpCallbackXfer)(off64_t xfered, void *arg);` 123 | 124 | 125 | 126 | ### bool (* FtpCallbackCert )(void* arg, X509 *cert) 127 | 128 | [typedef] 129 | 130 | `typedef int (*FtpCallbackCert)(void *arg, X509 *cert);` 131 | 132 | 133 | 134 | ### enum accesstype { dir = 1, dirverbose, fileread, filewrite, filereadappend, filewriteappend }; 135 | 136 | This type is used in [RawOpen](#rawopen). 137 | 138 | 139 | 140 | ### enum transfermode { ascii = 'A', image = 'I' }; 141 | 142 | This type determines how data is transferred. 143 | 144 | 145 | 146 | ### enum connmode { pasv = 1, port }; 147 | 148 | This type determines wether data is to be transferred using the pasv or active mode. 149 | 150 | 151 | 152 | ### enum fxpmethod { defaultfxp = 0, alternativefxp }; 153 | 154 | This type is used in the Fxp method. 155 | 156 | 157 | 158 | ### enum dataencryption { unencrypted = 0, secure }; 159 | 160 | This type determines wether data is encrypted or not. 161 | 162 | 163 | 164 | ### ftplib() 165 | 166 | [constructor] 167 | 168 | Class constructor, an ftplib object is responsible for the ftp session. 169 | 170 | 171 | 172 | ### char* LastResponse() 173 | 174 | LastResponse returns a pointer to the last response c-styled string sent by the server. This can be parsed by the 175 | user program todetermine more information about the last request or can be displayed along with an error message. 176 | 177 | #### Returns: 178 | 179 | A pointer to the last server response string. Otherwise, `NULL` is returned. 180 | 181 | 182 | 183 | ### int Connect ( const char* host ) 184 | 185 | Connect establishes a connection to the FTP server on the specified machine and returns a handle which can be used to 186 | initiate data transfers. The host name should be specified in the form of `:` `` may be either a host name or ip 187 | address. `` may be either a service name or a port number. 188 | 189 | #### Parameters: 190 | 191 | - `host`: The name of the host machine to connect to and optionally an alternate port number to use (`ftp.myftp.com:321`). 192 | 193 | #### Returns: 194 | 195 | If the connection to the remote server if successful, `Connect()` returns `1`. Otherwise, `0` is returned. 196 | 197 | 198 | 199 | ### int Login( const char* user, const char* pass ) 200 | 201 | Login attempts to login to the remote system with the supplied username and password. 202 | 203 | #### Parameters: 204 | 205 | - `user`: Specifies the username. 206 | - `pass`: Specifies the user's password. 207 | 208 | #### Returns: 209 | 210 | Returns `1` if successful or `0` on error. 211 | 212 | 213 | 214 | ### int Site( const char *cmd ) 215 | 216 | Site sends the specified command as an argument to a `SITE` command. 217 | 218 | #### Parameters: 219 | 220 | - `cmd`: A string containing a `SITE` subcommand. 221 | 222 | #### Returns: 223 | 224 | Returns `1` if successful or `0` on error. 225 | 226 | 227 | 228 | ### int Raw ( const char *cmd ) 229 | 230 | Raw sends the specified command unmodified. 231 | 232 | #### Parameters: 233 | 234 | - `cmd`: A string containing a custom ftp command. 235 | 236 | #### Returns: 237 | 238 | Returns `1` if successful or `0` on error. 239 | 240 | 241 | 242 | ### int SysType ( char *buf, int max ) 243 | 244 | SysType issues a `SYST` command to the remote system and attempts to parse the system type out of the response and return 245 | it to the user's buffer. 246 | 247 | #### Parameters: 248 | 249 | - `buf`: A pointer to a buffer where the result will be returned to. 250 | - `max`: Specifies the size of the user buffer. 251 | 252 | #### Returns: 253 | 254 | Returns `1` if successful or `0` on error. 255 | 256 | 257 | 258 | ### int Mkdir ( const char* path) 259 | 260 | Mkdir sends a make directory request to the remote system. 261 | 262 | #### Parameters: 263 | 264 | - `path`: Specifies the argument to mkdir on the remote system. 265 | 266 | #### Returns: 267 | 268 | Returns `1` if successful or `0` on error. 269 | 270 | 271 | 272 | ### int Chdir ( const char* path) 273 | 274 | Sends a change working directory request to the server using the specified path. 275 | 276 | #### Parameters: 277 | 278 | - `path`: Specifies the desired working directory on the server. 279 | 280 | #### Returns: 281 | 282 | Returns `1` if successful or `0` on error. 283 | 284 | 285 | 286 | ### int Cdup () 287 | 288 | Cdup sends a CDUP command to the remote server. 289 | 290 | #### Returns: 291 | 292 | Returns `1` if successful or `0` on error. 293 | 294 | 295 | 296 | ### int Rmdir ( const char* path ) 297 | 298 | Rmdir sends a remove directory request to the remote server. 299 | 300 | #### Parameters: 301 | 302 | - `path`: A string containing the name of a remote directory. 303 | 304 | #### Returns: 305 | 306 | Returns `1` if successful or `0` on error. 307 | 308 | 309 | 310 | ### int Pwd (char* path, int max ) 311 | 312 | Pwd attempts to determine the current default directory at the server and return it to the user's buffer. 313 | 314 | #### Parameters: 315 | 316 | - `path`: A pointer to a buffer where the result should be returned. 317 | - `max`: Specifies the size of the user's buffer. 318 | 319 | #### Returns: 320 | 321 | Returns `1` if successful or `0` on error. 322 | 323 | 324 | 325 | ### int Nlst ( const char* outputfile, const char* path ) 326 | 327 | Performs a short form directory listing of the specified path on the remote system. The results are written to the 328 | specified file. 329 | 330 | #### Parameters: 331 | 332 | - `output`: Specifies the name of a file to receive the directory listing. path Specifies an argument to `ls` on the remote system. 333 | 334 | #### Returns: 335 | 336 | Returns `1` if successful or `0` on error. 337 | 338 | 339 | 340 | ### int Dir ( const char* outputfile, const char* path ) 341 | 342 | Sends a `LIST -aL` command to the server with the specified path. The response to this is usually a long format directory 343 | listing which will be written to the file named in outputfile. If outputfile is specified as `NULL`, the list will be 344 | written to stdout. 345 | 346 | #### Parameters: 347 | 348 | - `output`: Specifies the name of a file to receive the directory listing. 349 | - `path`: Specifies an argument to 'ls' on the remote system. 350 | 351 | #### Returns: 352 | 353 | Returns `1` if successful or `0` on error. 354 | 355 | 356 | 357 | ### int Size ( const char* path, int* size, transfermode mode ) 358 | 359 | Size attempts to determine the size of a remote file. 360 | 361 | #### Parameters: 362 | 363 | - `path`: A pointer to a buffer where the result should be returned. 364 | - `size`: A pointer to an int where the size will be returned. 365 | - `mode`: Specifies the transfer mode as `ftplib::image` or `ftplib::ascii`. 366 | 367 | #### Returns: 368 | 369 | If a good response is received and the size is successfully parsed out of the result, `1` is returned. Otherwise, `0` is returned. 370 | 371 | 372 | 373 | ### int ModDate ( const char* path, char* dt, int max ) 374 | 375 | ModDate attempts to determine the last access time of a remote file and return it to the user's buffer. The date and 376 | time are returned as a string in the format 'YYYYMMDDHHMMSS'. 377 | 378 | #### Parameters: 379 | 380 | - `path`: Name of remote file to be checked. 381 | - `buf`: A pointer to a buffer where the result should be returned. 382 | - `max`: Specifies the size of the user's buffer. 383 | 384 | #### Returns: 385 | 386 | If a good response is received and the size is successfully parsed out of the result, `1` is returned. Otherwise, `0` is returned. 387 | 388 | 389 | 390 | ### int Get (const char* outputfile, const char *path, transfermode mode ) 391 | 392 | Copies the contents of a remote file to a local file. 393 | 394 | #### Parameters: 395 | 396 | - `output`: Name of a local file to receive the contents of the remote file. 397 | - `path`: Name of remote file to be retrieved. 398 | - `mode`: Specifies the transfer mode as `ftplib::image` or `ftplib::ascii`. 399 | 400 | #### Returns: 401 | 402 | Returns `1` if successful or `0` on error. 403 | 404 | 405 | 406 | ### int Get (const char* outputfile, const char *path, transfermode mode, off64_t offset ) 407 | 408 | Copies the contents of a remote file from a given offset and appends it to a local file. Not all ftp servers might 409 | implement this feature. 410 | 411 | #### Parameters: 412 | 413 | - `output`: Name of a local file to receive the contents of the remote file. 414 | - `path`: Name of remote file to be retrieved. mode Specifies the transfer mode as `ftplib::image` or `ftplib::ascii`. 415 | - `offset`: Point from where the copy is suppossed to begin. 416 | 417 | #### Returns: 418 | 419 | Returns `1` if successful or `0` on error. 420 | 421 | 422 | 423 | ### int Put ( const char* inputfile, const char *path, transfermode mode ) 424 | 425 | Transfers a local file to the remote system. 426 | 427 | #### Parameters: 428 | 429 | - `input`: Specifies the name of a local file to be transfered to the server. 430 | - `path`: Specifies the name to be given to the file on the remote system. 431 | - `mode`: Specifies the transfer mode as `ftplib::image` or `ftplib::ascii`. 432 | 433 | #### Returns: 434 | 435 | Returns `1` if successful or `0` on error. 436 | 437 | 438 | 439 | ### int Put ( const char* inputfile, const char *path, transfermode mode, off64_t offset ) 440 | 441 | Copies the contents of a local file from a given offset and appends it to a remote file. Not all ftp servers might 442 | implement this feature. 443 | 444 | #### Parameters: 445 | 446 | - `input`: Specifies the name of a local file to be transfered to the server. 447 | - `path`: Specifies the name to be given to the file on the remote system. 448 | - `mode`: Specifies the transfer mode as `ftplib::image` or `ftplib::ascii`. 449 | - `offset`: Point from where the copy begins. 450 | 451 | #### Returns: Returns 1 if successful or 0 on error. 452 | 453 | 454 | 455 | ### int Rename ( const char *src, const char *dst ) 456 | 457 | FtpRename sends a rename request to the remote server. 458 | 459 | #### Parameters: 460 | 461 | - `src`: A string containing the current name of the remote file. 462 | - `dst`: A string containing the desired new name for the remote file. 463 | 464 | #### Returns: Returns 1 if successful or 0 on error. 465 | 466 | 467 | 468 | ### int Delete ( const char *path ) 469 | 470 | Requests that the server remove the specified file from the remote file system. 471 | 472 | #### Parameters: 473 | 474 | - `path`: The path to the file which is to be removed. 475 | 476 | #### Returns: 477 | 478 | Returns `1` if successful or `0` on error. 479 | 480 | 481 | 482 | ### int SetDataEncryption ( dataencryption enc ) 483 | 484 | On an already secured ftp session, SetDataEncryption() specifies if the data connection channel will be secured for the next data transfer. 485 | 486 | #### Parameters: 487 | 488 | - `enc`: either `ftplib::unencrypted` or `ftplib::secure`. 489 | 490 | #### Returns: 491 | 492 | Returns `1` if successful and `0` if the control connection isn't secure or on error. 493 | 494 | #### Notes: 495 | 496 | See [NegotiateEncryption](#negotiateencryption) 497 | 498 | 499 | 500 | ### int NegotiateEncryption () 501 | 502 | This Method is to be called after Connect and before Login to secure the ftp communication channel. 503 | 504 | #### Returns: 505 | 506 | Returns `1` if successful and `0` if the ssl negotiation failed. 507 | 508 | #### Notes: 509 | 510 | The ftplibpp library uses an ssl/tls encryption approach defined in the RFC4217 standard. 511 | 512 | 513 | 514 | ### void Quit () 515 | 516 | Quit() issues a 'QUIT' command and closes the connection to the remote server. 517 | 518 | 519 | 520 | ### void SetCallbackXferFunction ( FtpCallbackXfer pointer ) 521 | 522 | When SetCallbackBytes is set to a bigger value than `0`, a callback function can be called during an ftp data transfer. If 523 | the callback function returns 0, the data transfer is aborted. The callback function has two parameters: `xfered` & `arg`. 524 | `xfered` is the amount of bytes yet transfered during the data connection and `arg` contains either `NULL` or a custom 525 | pointer set by [SetCallbackArg](#setcallbackarg). If `pointer` is specified as `NULL` the xfer callback is disabled. 526 | 527 | #### Parameters: 528 | 529 | - `pointer`: A pointer to a static function of the type FtpCallbackXfer. 530 | 531 | #### Notes: 532 | 533 | Since `FtpCallbackXferFunction` only accepts pointers to static functions, it might appear problematic in an oo c++ context. 534 | However there's an easy way to use it anyway. Using `SetCallbackArg` you supply the class a pointer to the object the method 535 | of which you'd like to call from the ftplib object. That pointer is then passed back with call to the callback function. 536 | From the static callback function you can perform a cast of `arg` to a pointer of the your desired object, and call its 537 | method. valid code could look like this: 538 | 539 | ```cpp 540 | ... 541 | static int callback(off64_t xfered, void* arg); // static callback function defined in myclass.h 542 | void mymethod(); // common myclass method 543 | ... 544 | int myclass::callback(off64_t xfered, void* arg) { 545 | ((*myclass)(arg)->mymethod(); // casting the pointers to the correct type and calling class method 546 | return 1; 547 | } 548 | ... 549 | void myclass::mymethod() { 550 | DoSomething(); 551 | } 552 | ... 553 | myftp.SetCallbackArg(this); // supply the myftp object the pointer to the current (myclass) object 554 | myftp.SetCallbackBytes(1024); // issue a xfer callback every kb 555 | myftp.SetCallbackXferFunction(class::callback); 556 | ... 557 | ``` 558 | 559 | 560 | ### void SetCallbackLogFunction ( FtpCallbackLog pointer ) 561 | 562 | `SetCallbackLogFunction` enables the logging callback. Every time there's been data read from the control connection, 563 | `pointer` is called with a c-styled string and a custom pointer specified in [SetCallbackArg](#setcallbackarg). If 564 | `pointer` is specified as `NULL` logging callback is disabled. 565 | 566 | #### Parameters: 567 | 568 | - `pointer`: A pointer to a static function of the type [FtpCallbackLog](#ftpcallbacklog). 569 | 570 | #### Notes: 571 | 572 | See SetCallbackIdleFunction. 573 | 574 | 575 | 576 | ### bool SetCallbackCertFunction ( FtpCallbackCert pointer ) 577 | 578 | SetCallbackCertFunction enables the ssl/tls certification callback. When you use encryption and you call this method 579 | with a certification callback function, it is called when connecting to the server. In the callback function you decide 580 | via the boolean return value whether the certificate is valid or not. Certification checking is an advanced issue, and 581 | you should read into the openssl documentation if you plan to implement it. `pointer` is called with a custom pointer 582 | specified in [SetCallbackArg](#setcallbackarg) and the certificate from the Server. If pointer is specified as `NULL` 583 | certification callback is disabled. 584 | 585 | #### Parameters: 586 | 587 | - `pointer`: a pointer to a static function of the type [FtpCallbackCert](#ftpcallbackcert). 588 | 589 | #### Notes: 590 | 591 | Sample implementation: 592 | ```cpp 593 | bool MyCallbackCert(void *arg, X509 *cert) { 594 | if (cert == NULL) { 595 | printf("Peer sent no certificate.\n"); 596 | return false; 597 | } else { 598 | char peer_CN[265]; 599 | int len; 600 | X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, peer_CN, 256); 601 | printf("subject: %s\n", peer_CN); 602 | X509_NAME_get_text_by_NID(X509_get_issuer_name(cert), NID_commonName, peer_CN, 256); 603 | printf("issuer: %s\n", peer_CN); return true; 604 | } 605 | } 606 | ``` 607 | ### void SetCallbackIdleFunction ( FtpCallbackIdle pointer ) 608 | 609 | SetCallbackLogFunction enables the idle callback. When a connection idles, for a period bigger than 0 set in 610 | [SetCallbackIdletime](#setcallbackidletime) a callback to the argument function is issued. 611 | 612 | #### Parameters: 613 | 614 | - `pointer`: A pointer to a static function of the type [FtpCallbackIdle](#ftpcallbackidle). 615 | 616 | #### Notes: 617 | 618 | See SetCallbackXferFunction. 619 | 620 | 621 | 622 | ### void SetCallbackArg ( void* arg ) 623 | 624 | SetCallbackArg submits a pointer of custom type to the object, this pointer is returned with a callback function. A good 625 | idea is to store the ftplib owners (or whatever object should handle the callback) pointer in it to use it the way 626 | described in the [SetCallbackXferFunction](#setcallbackxferfunction) entry. 627 | 628 | #### Parameters: 629 | 630 | - `arg`: A pointer of a custom type. 631 | 632 | 633 | 634 | ### void SetCallbackBytes ( off64_t bytes ) 635 | 636 | SetCallbackBytes specifies the frequency of xfer callbacks. The xfer callback returns the amount of bytes yet transfered 637 | on this transfer. 638 | 639 | #### Parameters: 640 | 641 | - `bytes`: Specifies the frequency in transfered bytes. A value of 100000 would mean every 100000 bytes an xfer callback is 642 | issued. 643 | 644 | 645 | 646 | ### void SetCallbackIdletime ( int time ) 647 | 648 | SetCallbackIdletime specifies how long a data socket can idle, without an idle callback beeing issued. 649 | 650 | #### Parameters: 651 | 652 | - `time`: Time in msec. 653 | 654 | #### Notes: 655 | 656 | The default value of `0`, means that on every idle a callback happens. if you don't want this behaviour you have to set a 657 | (higher) value. 658 | 659 | 660 | 661 | ### void SetConnmode ( ftplib::ftp mode ) 662 | 663 | SetConnmode specifies which data connection method is to be used for the next data transfer. 664 | 665 | #### Parameters: 666 | 667 | - `mode`: Either `ftplib::pasv` (passive mode, default) or `ftplib::port` (active mode). 668 | 669 | 670 | 671 | ### void SetCorrectPasv ( bool b ) 672 | 673 | Some Ftp-Servers, which run behind a NAT, return their local ip-adresses as PASV replies. When this option is turned on 674 | PASV replies are corrected using the ip address the ftp session is currently connected to. 675 | 676 | #### Parameters: 677 | 678 | - `b`: `true` turns the correction on, `false` turns it off. 679 | 680 | 681 | 682 | ### int Fxp ( ftplib* src, ftplib* dst, const char *pathSrc, const char *pathDst, ftplib::ftp mode, ftplib::ftp method ) 683 | 684 | [static] 685 | 686 | Fxp is a static function. It uses two ftp session objects and transfer a certain file between them. 687 | 688 | #### Parameters: 689 | 690 | - `src`: Source ftplib object. 691 | - `dst`: Destination ftplib object. 692 | - `pathSrc`: Path to file to be copied copy (`/incoming/myfile.tar.gz`). 693 | - `pathDst`: Path to file destination (`/pub/myfile_from_some_ftp.tar.gz`). 694 | - `mode`: Either `ftplib::ascii` (ascii) or `ftplib::image` (binary). Method either `ftplib::defaultfxp` (`PASV` on `dst`, `PORT` on `src`) or `ftplib::alternativefxp` (`PASV` on `src`, `PORT` on `dst`). 695 | 696 | #### Returns: 697 | 698 | Returns `1` if successful, `-`1 if initilization failed ("PORT" and "PASV"), or `0` if the data transfer somehow failed. 699 | 700 | #### Notes: 701 | 702 | Fxp - direct Ftp to Ftp transfer - is rather an exploit than a feature and might thus be prevented by many servers. 703 | Currently Fxp does not work with encrypted data connections, so be sure to switch to unencrypted data channels before 704 | performing fxp. 705 | 706 | 707 | ### int RawRead ( void* buf, int max, ftphandle *handle ) 708 | 709 | RawRead copies up to max bytes of data from the specified data connection and returns it to the user's buffer. If the data 710 | connection was opened in ascii mode, no more than one line of data will be returned. 711 | 712 | #### Parameters: 713 | 714 | - `buf`: Specifies the address of a buffer where received data will be written. max Specifies the size of the user's buffer. 715 | - `handle`: A handle returned by FtpAccess(). 716 | 717 | #### Returns: 718 | 719 | Returns the number of bytes written to the user's buffer or `-1` on error or end of file. 720 | 721 | 722 | 723 | #### int RawWrite ( void* buf, int len, ftphandle *handle ) 724 | 725 | RawWrite sends data to a remote file. If the file were accessed in record mode, the necessary conversions are performed. 726 | 727 | #### Parameters: 728 | 729 | - `buf`: A buffer containing the data to be sent to the remote file. 730 | - `len`: The number of bytes to be sent from 'buf'. 731 | - `handle`: A handle returned by [RawOpen()](#rawopen). 732 | 733 | #### Returns: 734 | 735 | Returns the number of bytes sent from the user's buffer or `-1` on error. 736 | 737 | 738 | 739 | ### ftphandle* RawOpen ( const char *path, accesstype type, transfermode mode ) 740 | 741 | RawOpen() opens a remote file or directory and returns a handle for the calling program to use to transfer data. 742 | 743 | #### Parameters: 744 | 745 | - `path`: Specifies the name of the remote file or directory to open. 746 | - `type`: Specifies the type of transfer to be performed. `ftplib::dir` performs a terse directory. `ftplib::dirverbose` 747 | performs a verbose directory. `ftplib::fileread` opens a remote file for reading. `ftplib::filewrite` creates a remote 748 | file and readies it for writing. `ftplib::filewriteappend` and `ftplib::filereadappend` are for appending file operations. 749 | - `mode`: Specifies the transfer mode as `ftplib::ascii` or `ftplib::image`. 750 | 751 | #### Returns: 752 | 753 | Returns `1` if successful or `0` on error. 754 | 755 | 756 | 757 | ### int RawClose ( ftphandle* handle ) 758 | 759 | Closes the data connection specified by handle and frees associated resources. 760 | 761 | #### Parameters: 762 | 763 | - `handle`: A handle returned by [RawOpen()](#rawopen). 764 | 765 | #### Returns: 766 | 767 | Returns `1` if successful or `0` on error. 768 | -------------------------------------------------------------------------------- /ToDo: -------------------------------------------------------------------------------- 1 | - implement up and download speed limitation. 2 | -------------------------------------------------------------------------------- /ftplib.cpp: -------------------------------------------------------------------------------- 1 | // enable > 2gb support (LFS) 2 | 3 | #ifndef NOLFS 4 | #define _LARGEFILE_SOURCE 5 | #define _LARGEFILE64_SOURCE 6 | #endif 7 | 8 | #ifndef NOSSL 9 | #include 10 | #endif 11 | 12 | #include "ftplib.h" 13 | 14 | #ifndef NOSSL 15 | #include 16 | #endif 17 | 18 | #if defined(_WIN32) 19 | #include 20 | #include 21 | #else 22 | #include 23 | #include 24 | #include 25 | #include 26 | #endif 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #if defined(_WIN32) 36 | #define SETSOCKOPT_OPTVAL_TYPE (const char *) 37 | #else 38 | #define SETSOCKOPT_OPTVAL_TYPE (void *) 39 | #endif 40 | 41 | #if defined(_WIN32) 42 | #define net_read(x,y,z) recv(x,(char*)y,z,0) 43 | #define net_write(x,y,z) send(x,(char*)y,z,0) 44 | #define net_close closesocket 45 | #else 46 | #define net_read read 47 | #define net_write write 48 | #define net_close close 49 | #endif 50 | 51 | #if defined(_WIN32) 52 | typedef int socklen_t; 53 | #endif 54 | 55 | #if defined(_WIN32) 56 | #define memccpy _memccpy 57 | #define strdup _strdup 58 | #endif 59 | 60 | using namespace std; 61 | 62 | /* socket values */ 63 | //#define SETSOCKOPT_OPTVAL_TYPE (void *) 64 | #define FTPLIB_BUFSIZ 1024 65 | #define ACCEPT_TIMEOUT 30 66 | 67 | /* io types */ 68 | #define FTPLIB_CONTROL 0 69 | #define FTPLIB_READ 1 70 | #define FTPLIB_WRITE 2 71 | 72 | /* win32 dll initializer */ 73 | 74 | #if defined(_WIN32) 75 | BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) 76 | { 77 | switch (reason) 78 | { 79 | case DLL_PROCESS_ATTACH: 80 | break; 81 | case DLL_PROCESS_DETACH: 82 | break; 83 | case DLL_THREAD_ATTACH: 84 | break; 85 | case DLL_THREAD_DETACH: 86 | break; 87 | } 88 | 89 | /* Returns TRUE on success, FALSE on failure */ 90 | return TRUE; 91 | } 92 | #endif 93 | 94 | /* 95 | * Constructor 96 | */ 97 | 98 | ftplib::ftplib() 99 | { 100 | #if defined(_WIN32) 101 | WSADATA wsa; 102 | if (WSAStartup(MAKEWORD(1, 1), &wsa)) 103 | { 104 | printf("WSAStartup() failed, %lu\n", (unsigned long)GetLastError()); 105 | } 106 | #endif 107 | 108 | #ifndef NOSSL 109 | SSL_library_init(); 110 | #endif 111 | 112 | mp_ftphandle = static_cast(calloc(1,sizeof(ftphandle))); 113 | if (mp_ftphandle == NULL) perror("calloc"); 114 | mp_ftphandle->buf = static_cast(malloc(FTPLIB_BUFSIZ)); 115 | if (mp_ftphandle->buf == NULL) 116 | { 117 | perror("calloc"); 118 | free(mp_ftphandle); 119 | } 120 | #ifndef NOSSL 121 | mp_ftphandle->ctx = SSL_CTX_new(_FTPLIB_SSL_CLIENT_METHOD_()); 122 | SSL_CTX_set_verify(mp_ftphandle->ctx, SSL_VERIFY_NONE, NULL); 123 | mp_ftphandle->ssl = SSL_new(mp_ftphandle->ctx); 124 | #endif 125 | ClearHandle(); 126 | } 127 | 128 | /* 129 | * Destructor 130 | */ 131 | 132 | ftplib::~ftplib() 133 | { 134 | #ifndef NOSSL 135 | SSL_free(mp_ftphandle->ssl); 136 | SSL_CTX_free(mp_ftphandle->ctx); 137 | #endif 138 | free(mp_ftphandle->buf); 139 | free(mp_ftphandle); 140 | } 141 | 142 | void ftplib::sprint_rest(char *buf, off64_t offset) { 143 | #if defined(__APPLE__) 144 | sprintf(buf,"REST %lld",offset); 145 | #else 146 | sprintf(buf,"REST %ld",offset); 147 | #endif 148 | } 149 | 150 | /* 151 | * socket_wait - wait for socket to receive or flush data 152 | * 153 | * return 1 if no user callback, otherwise, return value returned by 154 | * user callback 155 | */ 156 | int ftplib::socket_wait(ftphandle *ctl) 157 | { 158 | fd_set fd,*rfd = NULL,*wfd = NULL; 159 | struct timeval tv; 160 | int rv = 0; 161 | 162 | if (ctl->idlecb == NULL) return 1; 163 | 164 | /*if ((ctl->dir == FTPLIB_CONTROL) 165 | || (ctl->idlecb == NULL) 166 | || ((ctl->idletime.tv_sec == 0) 167 | && //(ctl->idletime.tv_usec 0)) 168 | return 1;*/ 169 | 170 | if (ctl->dir == FTPLIB_WRITE) wfd = &fd; 171 | else rfd = &fd; 172 | 173 | FD_ZERO(&fd); 174 | do 175 | { 176 | FD_SET(ctl->handle,&fd); 177 | tv = ctl->idletime; 178 | rv = select(ctl->handle+1, rfd, wfd, NULL, &tv); 179 | if (rv == -1) 180 | { 181 | rv = 0; 182 | strncpy(ctl->ctrl->response, strerror(errno), sizeof(ctl->ctrl->response)); 183 | break; 184 | } 185 | else if (rv > 0) 186 | { 187 | rv = 1; 188 | break; 189 | } 190 | } while ((rv = ctl->idlecb(ctl->cbarg))); 191 | 192 | return rv; 193 | } 194 | 195 | /* 196 | * read a line of text 197 | * 198 | * return -1 on error or bytecount 199 | */ 200 | int ftplib::readline(char *buf,int max,ftphandle *ctl) 201 | { 202 | int x,retval = 0; 203 | char *end,*bp=buf; 204 | int eof = 0; 205 | 206 | if ((ctl->dir != FTPLIB_CONTROL) && (ctl->dir != FTPLIB_READ)) 207 | return -1; 208 | if (max == 0) 209 | return 0; 210 | do 211 | { 212 | if (ctl->cavail > 0) 213 | { 214 | x = (max >= ctl->cavail) ? ctl->cavail : max-1; 215 | end = static_cast(memccpy(bp,ctl->cget,'\n',x)); 216 | if (end != NULL) 217 | x = end - bp; 218 | retval += x; 219 | bp += x; 220 | *bp = '\0'; 221 | max -= x; 222 | ctl->cget += x; 223 | ctl->cavail -= x; 224 | if (end != NULL) 225 | { 226 | bp -= 2; 227 | if (strcmp(bp,"\r\n") == 0) 228 | { 229 | *bp++ = '\n'; 230 | *bp++ = '\0'; 231 | --retval; 232 | } 233 | break; 234 | } 235 | } 236 | if (max == 1) 237 | { 238 | *buf = '\0'; 239 | break; 240 | } 241 | if (ctl->cput == ctl->cget) 242 | { 243 | ctl->cput = ctl->cget = ctl->buf; 244 | ctl->cavail = 0; 245 | ctl->cleft = FTPLIB_BUFSIZ; 246 | } 247 | if (eof) 248 | { 249 | if (retval == 0) 250 | retval = -1; 251 | break; 252 | } 253 | 254 | if (!socket_wait(ctl)) return retval; 255 | 256 | #ifndef NOSSL 257 | if (ctl->tlsdata) x = SSL_read(ctl->ssl, ctl->cput, ctl->cleft); 258 | else 259 | { 260 | if (ctl->tlsctrl) x = SSL_read(ctl->ssl, ctl->cput, ctl->cleft); 261 | else x = net_read(ctl->handle,ctl->cput,ctl->cleft); 262 | } 263 | #else 264 | x = net_read(ctl->handle,ctl->cput,ctl->cleft); 265 | #endif 266 | if ( x == -1) 267 | { 268 | perror("read"); 269 | retval = -1; 270 | break; 271 | } 272 | 273 | // LOGGING FUNCTIONALITY!!! 274 | 275 | if ((ctl->dir == FTPLIB_CONTROL) && (mp_ftphandle->logcb != NULL)) 276 | { 277 | *((ctl->cput)+x) = '\0'; 278 | mp_ftphandle->logcb(ctl->cput, mp_ftphandle->cbarg, true); 279 | } 280 | 281 | if (x == 0) eof = 1; 282 | ctl->cleft -= x; 283 | ctl->cavail += x; 284 | ctl->cput += x; 285 | } while (1); 286 | return retval; 287 | } 288 | 289 | /* 290 | * write lines of text 291 | * 292 | * return -1 on error or bytecount 293 | */ 294 | int ftplib::writeline(char *buf, int len, ftphandle *nData) 295 | { 296 | int x, nb=0, w; 297 | char *ubp = buf, *nbp; 298 | char lc=0; 299 | 300 | if (nData->dir != FTPLIB_WRITE) 301 | return -1; 302 | nbp = nData->buf; 303 | for (x=0; x < len; x++) 304 | { 305 | if ((*ubp == '\n') && (lc != '\r')) 306 | { 307 | if (nb == FTPLIB_BUFSIZ) 308 | { 309 | if (!socket_wait(nData)) return x; 310 | #ifndef NOSSL 311 | if (nData->tlsctrl) w = SSL_write(nData->ssl, nbp, FTPLIB_BUFSIZ); 312 | else w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ); 313 | #else 314 | w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ); 315 | #endif 316 | if (w != FTPLIB_BUFSIZ) 317 | { 318 | printf("write(1) returned %d, errno = %d\n", w, errno); 319 | return(-1); 320 | } 321 | nb = 0; 322 | } 323 | nbp[nb++] = '\r'; 324 | } 325 | if (nb == FTPLIB_BUFSIZ) 326 | { 327 | if (!socket_wait(nData)) 328 | return x; 329 | #ifndef NOSSL 330 | if (nData->tlsctrl) w = SSL_write(nData->ssl, nbp, FTPLIB_BUFSIZ); 331 | else w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ); 332 | #else 333 | w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ); 334 | #endif 335 | if (w != FTPLIB_BUFSIZ) 336 | { 337 | printf("write(2) returned %d, errno = %d\n", w, errno); 338 | return(-1); 339 | } 340 | nb = 0; 341 | } 342 | nbp[nb++] = lc = *ubp++; 343 | } 344 | if (nb) 345 | { 346 | if (!socket_wait(nData)) return x; 347 | #ifndef NOSSL 348 | if (nData->tlsctrl) w = SSL_write(nData->ssl, nbp, nb); 349 | else w = net_write(nData->handle, nbp, nb); 350 | #else 351 | w = net_write(nData->handle, nbp, nb); 352 | #endif 353 | if (w != nb) 354 | { 355 | printf("write(3) returned %d, errno = %d\n", w, errno); 356 | return(-1); 357 | } 358 | } 359 | return len; 360 | } 361 | 362 | /* 363 | * read a response from the server 364 | * 365 | * return 0 if first char doesn't match 366 | * return 1 if first char matches 367 | */ 368 | int ftplib::readresp(char c, ftphandle *nControl) 369 | { 370 | char match[5]; 371 | 372 | if (readline(nControl->response,256,nControl) == -1) 373 | { 374 | perror("Control socket read failed"); 375 | return 0; 376 | } 377 | 378 | if (nControl->response[3] == '-') 379 | { 380 | strncpy(match,nControl->response,3); 381 | match[3] = ' '; 382 | match[4] = '\0'; 383 | do 384 | { 385 | if (readline(nControl->response,256,nControl) == -1) 386 | { 387 | perror("Control socket read failed"); 388 | return 0; 389 | } 390 | } while (strncmp(nControl->response,match,4)); 391 | } 392 | if (nControl->response[0] == c) return 1; 393 | return 0; 394 | } 395 | 396 | /* 397 | * FtpLastResponse - return a pointer to the last response received 398 | */ 399 | char* ftplib::LastResponse() 400 | { 401 | if ((mp_ftphandle) && (mp_ftphandle->dir == FTPLIB_CONTROL)) return mp_ftphandle->response; 402 | return NULL; 403 | } 404 | 405 | /* 406 | * ftplib::Connect - connect to remote server 407 | * 408 | * return 1 if connected, 0 if not 409 | */ 410 | int ftplib::Connect(const char *host) 411 | { 412 | int sControl; 413 | struct sockaddr_in sin; 414 | struct hostent *phe; 415 | struct servent *pse; 416 | int on=1; 417 | int ret; 418 | char *lhost; 419 | char *pnum; 420 | 421 | mp_ftphandle->dir = FTPLIB_CONTROL; 422 | mp_ftphandle->ctrl = NULL; 423 | mp_ftphandle->xfered = 0; 424 | mp_ftphandle->xfered1 = 0; 425 | #ifndef NOSSL 426 | mp_ftphandle->tlsctrl = 0; 427 | mp_ftphandle->tlsdata = 0; 428 | #endif 429 | mp_ftphandle->offset = 0; 430 | mp_ftphandle->handle = 0; 431 | 432 | memset(&sin,0,sizeof(sin)); 433 | sin.sin_family = AF_INET; 434 | lhost = strdup(host); 435 | pnum = strchr(lhost,':'); 436 | if (pnum == NULL) 437 | { 438 | if ((pse = getservbyname("ftp","tcp")) == NULL) 439 | { 440 | perror("getservbyname"); 441 | free(lhost); 442 | return 0; 443 | } 444 | sin.sin_port = pse->s_port; 445 | } 446 | else 447 | { 448 | *pnum++ = '\0'; 449 | if (isdigit(*pnum)) sin.sin_port = htons(atoi(pnum)); 450 | else 451 | { 452 | pse = getservbyname(pnum,"tcp"); 453 | sin.sin_port = pse->s_port; 454 | } 455 | } 456 | 457 | #if defined(_WIN32) 458 | if ((sin.sin_addr.s_addr = inet_addr(lhost)) == -1) 459 | #else 460 | ret = inet_aton(lhost, &sin.sin_addr); 461 | if (ret == 0) 462 | #endif 463 | { 464 | if ((phe = gethostbyname(lhost)) == NULL) 465 | { 466 | perror("gethostbyname"); 467 | free(lhost); 468 | return 0; 469 | } 470 | memcpy((char *)&sin.sin_addr, phe->h_addr, phe->h_length); 471 | } 472 | 473 | free(lhost); 474 | 475 | sControl = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 476 | if (sControl == -1) 477 | { 478 | perror("socket"); 479 | return 0; 480 | } 481 | 482 | if (setsockopt(sControl,SOL_SOCKET,SO_REUSEADDR, SETSOCKOPT_OPTVAL_TYPE &on, sizeof(on)) == -1) 483 | { 484 | perror("setsockopt"); 485 | net_close(sControl); 486 | return 0; 487 | } 488 | if (connect(sControl, (struct sockaddr *)&sin, sizeof(sin)) == -1) 489 | { 490 | perror("connect"); 491 | net_close(sControl); 492 | return 0; 493 | } 494 | 495 | mp_ftphandle->handle = sControl; 496 | 497 | if (readresp('2', mp_ftphandle) == 0) 498 | { 499 | net_close(sControl); 500 | mp_ftphandle->handle = 0; 501 | return 0; 502 | } 503 | 504 | return 1; 505 | } 506 | 507 | /* 508 | * FtpSendCmd - send a command and wait for expected response 509 | * 510 | * return 1 if proper response received, 0 otherwise 511 | */ 512 | int ftplib::FtpSendCmd(const char *cmd, char expresp, ftphandle *nControl) 513 | { 514 | char buf[256]; 515 | int x; 516 | 517 | if (!nControl->handle) return 0; 518 | 519 | if (nControl->dir != FTPLIB_CONTROL) return 0; 520 | sprintf(buf,"%s\r\n",cmd); 521 | 522 | #ifndef NOSSL 523 | if (nControl->tlsctrl) x = SSL_write(nControl->ssl,buf,strlen(buf)); 524 | else x = net_write(nControl->handle,buf,strlen(buf)); 525 | #else 526 | x = net_write(nControl->handle,buf,strlen(buf)); 527 | #endif 528 | if (x <= 0) 529 | { 530 | perror("write"); 531 | return 0; 532 | } 533 | 534 | if (mp_ftphandle->logcb != NULL) mp_ftphandle->logcb(buf, mp_ftphandle->cbarg, false); 535 | 536 | return readresp(expresp, nControl); 537 | } 538 | 539 | /* 540 | * FtpLogin - log in to remote server 541 | * 542 | * return 1 if logged in, 0 otherwise 543 | */ 544 | int ftplib::Login(const char *user, const char *pass) 545 | { 546 | char tempbuf[64]; 547 | 548 | if (((strlen(user) + 7) > sizeof(tempbuf)) || ((strlen(pass) + 7) > sizeof(tempbuf))) return 0; 549 | sprintf(tempbuf, "USER %s", user); 550 | if (!FtpSendCmd(tempbuf,'3',mp_ftphandle)) 551 | { 552 | if (mp_ftphandle->ctrl != NULL) return 1; 553 | if (*LastResponse() == '2') return 1; 554 | return 0; 555 | } 556 | sprintf(tempbuf,"PASS %s",pass); 557 | return FtpSendCmd(tempbuf,'2',mp_ftphandle); 558 | } 559 | 560 | /* 561 | * FtpAcceptConnection - accept connection from server 562 | * 563 | * return 1 if successful, 0 otherwise 564 | */ 565 | int ftplib::FtpAcceptConnection(ftphandle *nData, ftphandle *nControl) 566 | { 567 | int sData; 568 | struct sockaddr addr; 569 | socklen_t l; 570 | int i; 571 | struct timeval tv; 572 | fd_set mask; 573 | int rv = 0; 574 | 575 | FD_ZERO(&mask); 576 | FD_SET(nControl->handle, &mask); 577 | FD_SET(nData->handle, &mask); 578 | tv.tv_usec = 0; 579 | tv.tv_sec = ACCEPT_TIMEOUT; 580 | i = nControl->handle; 581 | if (i < nData->handle) i = nData->handle; 582 | i = select(i+1, &mask, NULL, NULL, &tv); 583 | 584 | if (i == -1) 585 | { 586 | strncpy(nControl->response, strerror(errno), sizeof(nControl->response)); 587 | net_close(nData->handle); 588 | nData->handle = 0; 589 | rv = 0; 590 | } 591 | else if (i == 0) 592 | { 593 | strcpy(nControl->response, "timed out waiting for connection"); 594 | net_close(nData->handle); 595 | nData->handle = 0; 596 | rv = 0; 597 | } 598 | else 599 | { 600 | if (FD_ISSET(nData->handle, &mask)) 601 | { 602 | l = sizeof(addr); 603 | sData = accept(nData->handle, &addr, &l); 604 | i = errno; 605 | net_close(nData->handle); 606 | if (sData > 0) 607 | { 608 | rv = 1; 609 | nData->handle = sData; 610 | nData->ctrl = nControl; 611 | } 612 | else 613 | { 614 | strncpy(nControl->response, strerror(i), sizeof(nControl->response)); 615 | nData->handle = 0; 616 | rv = 0; 617 | } 618 | } 619 | else if (FD_ISSET(nControl->handle, &mask)) 620 | { 621 | net_close(nData->handle); 622 | nData->handle = 0; 623 | readresp('2', nControl); 624 | rv = 0; 625 | } 626 | } 627 | return rv; 628 | } 629 | 630 | /* 631 | * FtpAccess - return a handle for a data stream 632 | * 633 | * return 1 if successful, 0 otherwise 634 | */ 635 | int ftplib::FtpAccess(const char *path, accesstype type, transfermode mode, ftphandle *nControl, ftphandle **nData) 636 | { 637 | char buf[256]; 638 | int dir; 639 | 640 | if ((path == NULL) && ((type == ftplib::filewrite) 641 | || (type == ftplib::fileread) 642 | || (type == ftplib::filereadappend) 643 | || (type == ftplib::filewriteappend))) 644 | { 645 | sprintf(nControl->response,"Missing path argument for file transfer\n"); 646 | return 0; 647 | } 648 | sprintf(buf, "TYPE %c", mode); 649 | if (!FtpSendCmd(buf, '2', nControl)) return 0; 650 | 651 | switch (type) 652 | { 653 | case ftplib::dir: 654 | strcpy(buf,"NLST"); 655 | dir = FTPLIB_READ; 656 | break; 657 | case ftplib::dirverbose: 658 | strcpy(buf,"LIST -aL"); 659 | dir = FTPLIB_READ; 660 | break; 661 | case ftplib::filereadappend: 662 | case ftplib::fileread: 663 | strcpy(buf,"RETR"); 664 | dir = FTPLIB_READ; 665 | break; 666 | case ftplib::filewriteappend: 667 | case ftplib::filewrite: 668 | strcpy(buf,"STOR"); 669 | dir = FTPLIB_WRITE; 670 | break; 671 | default: 672 | sprintf(nControl->response, "Invalid open type %d\n", type); 673 | return 0; 674 | } 675 | if (path != NULL) 676 | { 677 | int i = strlen(buf); 678 | buf[i++] = ' '; 679 | if ((strlen(path) + i) >= sizeof(buf)) return 0; 680 | strcpy(&buf[i],path); 681 | } 682 | 683 | if (nControl->cmode == ftplib::pasv) 684 | { 685 | if (FtpOpenPasv(nControl, nData, mode, dir, buf) == -1) return 0; 686 | } 687 | 688 | if (nControl->cmode == ftplib::port) 689 | { 690 | if (FtpOpenPort(nControl, nData, mode, dir, buf) == -1) return 0; 691 | if (!FtpAcceptConnection(*nData,nControl)) 692 | { 693 | FtpClose(*nData); 694 | *nData = NULL; 695 | return 0; 696 | } 697 | } 698 | 699 | #ifndef NOSSL 700 | if (nControl->tlsdata) 701 | { 702 | (*nData)->ssl = SSL_new(nControl->ctx); 703 | (*nData)->sbio = BIO_new_socket((*nData)->handle, BIO_NOCLOSE); 704 | SSL_set_bio((*nData)->ssl,(*nData)->sbio,(*nData)->sbio); 705 | ret = SSL_connect((*nData)->ssl); 706 | if (ret != 1) return 0; 707 | (*nData)->tlsdata = 1; 708 | } 709 | #endif 710 | return 1; 711 | } 712 | 713 | /* 714 | * FtpOpenPort - Establishes a PORT connection for data transfer 715 | * 716 | * return 1 if successful, -1 otherwise 717 | */ 718 | int ftplib::FtpOpenPort(ftphandle *nControl, ftphandle **nData, transfermode mode, int dir, char *cmd) 719 | { 720 | int sData; 721 | union { 722 | struct sockaddr sa; 723 | struct sockaddr_in in; 724 | } sin; 725 | struct linger lng = { 0, 0 }; 726 | socklen_t l; 727 | int on=1; 728 | ftphandle *ctrl; 729 | char buf[256]; 730 | 731 | if (nControl->dir != FTPLIB_CONTROL) return -1; 732 | if ((dir != FTPLIB_READ) && (dir != FTPLIB_WRITE)) 733 | { 734 | sprintf(nControl->response, "Invalid direction %d\n", dir); 735 | return -1; 736 | } 737 | if ((mode != ftplib::ascii) && (mode != ftplib::image)) 738 | { 739 | sprintf(nControl->response, "Invalid mode %c\n", mode); 740 | return -1; 741 | } 742 | l = sizeof(sin); 743 | 744 | if (getsockname(nControl->handle, &sin.sa, &l) < 0) 745 | { 746 | perror("getsockname"); 747 | return -1; 748 | } 749 | 750 | sData = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); 751 | if (sData == -1) 752 | { 753 | perror("socket"); 754 | return -1; 755 | } 756 | if (setsockopt(sData,SOL_SOCKET,SO_REUSEADDR, SETSOCKOPT_OPTVAL_TYPE &on,sizeof(on)) == -1) 757 | { 758 | perror("setsockopt"); 759 | net_close(sData); 760 | return -1; 761 | } 762 | if (setsockopt(sData,SOL_SOCKET,SO_LINGER, SETSOCKOPT_OPTVAL_TYPE &lng,sizeof(lng)) == -1) 763 | { 764 | perror("setsockopt"); 765 | net_close(sData); 766 | return -1; 767 | } 768 | 769 | sin.in.sin_port = 0; 770 | if (bind(sData, &sin.sa, sizeof(sin)) == -1) 771 | { 772 | perror("bind"); 773 | net_close(sData); 774 | return -1; 775 | } 776 | if (listen(sData, 1) < 0) 777 | { 778 | perror("listen"); 779 | net_close(sData); 780 | return -1; 781 | } 782 | if (getsockname(sData, &sin.sa, &l) < 0) return 0; 783 | sprintf(buf, "PORT %hhu,%hhu,%hhu,%hhu,%hhu,%hhu", 784 | (unsigned char) sin.sa.sa_data[2], 785 | (unsigned char) sin.sa.sa_data[3], 786 | (unsigned char) sin.sa.sa_data[4], 787 | (unsigned char) sin.sa.sa_data[5], 788 | (unsigned char) sin.sa.sa_data[0], 789 | (unsigned char) sin.sa.sa_data[1]); 790 | if (!FtpSendCmd(buf,'2',nControl)) 791 | { 792 | net_close(sData); 793 | return -1; 794 | } 795 | 796 | if (mp_ftphandle->offset != 0) 797 | { 798 | char buf[256]; 799 | sprint_rest(buf, mp_ftphandle->offset); 800 | if (!FtpSendCmd(buf,'3',nControl)) 801 | { 802 | net_close(sData); 803 | return 0; 804 | } 805 | } 806 | 807 | ctrl = static_cast(calloc(1,sizeof(ftphandle))); 808 | if (ctrl == NULL) 809 | { 810 | perror("calloc"); 811 | net_close(sData); 812 | return -1; 813 | } 814 | if ((mode == 'A') && ((ctrl->buf = static_cast(malloc(FTPLIB_BUFSIZ))) == NULL)) 815 | { 816 | perror("calloc"); 817 | net_close(sData); 818 | free(ctrl); 819 | return -1; 820 | } 821 | 822 | if (!FtpSendCmd(cmd, '1', nControl)) 823 | { 824 | FtpClose(*nData); 825 | *nData = NULL; 826 | return -1; 827 | } 828 | 829 | ctrl->handle = sData; 830 | ctrl->dir = dir; 831 | ctrl->ctrl = (nControl->cmode == ftplib::pasv) ? nControl : NULL; 832 | ctrl->idletime = nControl->idletime; 833 | ctrl->cbarg = nControl->cbarg; 834 | ctrl->xfered = 0; 835 | ctrl->xfered1 = 0; 836 | ctrl->cbbytes = nControl->cbbytes; 837 | if (ctrl->idletime.tv_sec || ctrl->idletime.tv_usec) ctrl->idlecb = nControl->idlecb; 838 | else ctrl->idlecb = NULL; 839 | if (ctrl->cbbytes ) ctrl->xfercb = nControl->xfercb; 840 | else ctrl->xfercb = NULL; 841 | *nData = ctrl; 842 | 843 | return 1; 844 | } 845 | 846 | /* 847 | * FtpOpenPasv - Establishes a PASV connection for data transfer 848 | * 849 | * return 1 if successful, -1 otherwise 850 | */ 851 | int ftplib::FtpOpenPasv(ftphandle *nControl, ftphandle **nData, transfermode mode, int dir, char *cmd) 852 | { 853 | int sData; 854 | union { 855 | struct sockaddr sa; 856 | struct sockaddr_in in; 857 | } sin; 858 | struct linger lng = { 0, 0 }; 859 | unsigned int l; 860 | int on=1; 861 | ftphandle *ctrl; 862 | char *cp; 863 | unsigned char v[6]; 864 | int ret; 865 | 866 | if (nControl->dir != FTPLIB_CONTROL) return -1; 867 | if ((dir != FTPLIB_READ) && (dir != FTPLIB_WRITE)) 868 | { 869 | sprintf(nControl->response, "Invalid direction %d\n", dir); 870 | return -1; 871 | } 872 | if ((mode != ftplib::ascii) && (mode != ftplib::image)) 873 | { 874 | sprintf(nControl->response, "Invalid mode %c\n", mode); 875 | return -1; 876 | } 877 | l = sizeof(sin); 878 | 879 | memset(&sin, 0, l); 880 | sin.in.sin_family = AF_INET; 881 | if (!FtpSendCmd("PASV",'2',nControl)) return -1; 882 | cp = strchr(nControl->response,'('); 883 | if (cp == NULL) return -1; 884 | cp++; 885 | #if defined(_WIN32) 886 | unsigned int v_i[6]; 887 | sscanf(cp,"%u,%u,%u,%u,%u,%u",&v_i[2],&v_i[3],&v_i[4],&v_i[5],&v_i[0],&v_i[1]); 888 | for (int i = 0; i < 6; i++) v[i] = (unsigned char) v_i[i]; 889 | #else 890 | sscanf(cp,"%hhu,%hhu,%hhu,%hhu,%hhu,%hhu",&v[2],&v[3],&v[4],&v[5],&v[0],&v[1]); 891 | #endif 892 | if (nControl->correctpasv) if (!CorrectPasvResponse(v)) return -1; 893 | sin.sa.sa_data[2] = v[2]; 894 | sin.sa.sa_data[3] = v[3]; 895 | sin.sa.sa_data[4] = v[4]; 896 | sin.sa.sa_data[5] = v[5]; 897 | sin.sa.sa_data[0] = v[0]; 898 | sin.sa.sa_data[1] = v[1]; 899 | 900 | if (mp_ftphandle->offset != 0) 901 | { 902 | char buf[256]; 903 | sprint_rest(buf, mp_ftphandle->offset); 904 | if (!FtpSendCmd(buf,'3',nControl)) return 0; 905 | } 906 | 907 | sData = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); 908 | if (sData == -1) 909 | { 910 | perror("socket"); 911 | return -1; 912 | } 913 | if (setsockopt(sData,SOL_SOCKET,SO_REUSEADDR, SETSOCKOPT_OPTVAL_TYPE &on,sizeof(on)) == -1) 914 | { 915 | perror("setsockopt"); 916 | net_close(sData); 917 | return -1; 918 | } 919 | if (setsockopt(sData,SOL_SOCKET,SO_LINGER, SETSOCKOPT_OPTVAL_TYPE &lng,sizeof(lng)) == -1) 920 | { 921 | perror("setsockopt"); 922 | net_close(sData); 923 | return -1; 924 | } 925 | 926 | if (nControl->dir != FTPLIB_CONTROL) return -1; 927 | memcpy(cmd + strlen(cmd), "\r\n\0", 3); 928 | #ifndef NOSSL 929 | if (nControl->tlsctrl) ret = SSL_write(nControl->ssl,cmd,strlen(cmd)); 930 | else ret = net_write(nControl->handle,cmd,strlen(cmd)); 931 | #else 932 | ret = net_write(nControl->handle,cmd,strlen(cmd)); 933 | #endif 934 | if (ret <= 0) 935 | { 936 | perror("write"); 937 | return -1; 938 | } 939 | 940 | if (connect(sData, &sin.sa, sizeof(sin.sa)) == -1) 941 | { 942 | perror("connect"); 943 | net_close(sData); 944 | return -1; 945 | } 946 | if (!readresp('1', nControl)) 947 | { 948 | net_close(sData); 949 | return -1; 950 | } 951 | ctrl = static_cast(calloc(1,sizeof(ftphandle))); 952 | if (ctrl == NULL) 953 | { 954 | perror("calloc"); 955 | net_close(sData); 956 | return -1; 957 | } 958 | if ((mode == 'A') && ((ctrl->buf = static_cast(malloc(FTPLIB_BUFSIZ))) == NULL)) 959 | { 960 | perror("calloc"); 961 | net_close(sData); 962 | free(ctrl); 963 | return -1; 964 | } 965 | ctrl->handle = sData; 966 | ctrl->dir = dir; 967 | ctrl->ctrl = (nControl->cmode == ftplib::pasv) ? nControl : NULL; 968 | ctrl->idletime = nControl->idletime; 969 | ctrl->cbarg = nControl->cbarg; 970 | ctrl->xfered = 0; 971 | ctrl->xfered1 = 0; 972 | ctrl->cbbytes = nControl->cbbytes; 973 | if (ctrl->idletime.tv_sec || ctrl->idletime.tv_usec) ctrl->idlecb = nControl->idlecb; 974 | else ctrl->idlecb = NULL; 975 | if (ctrl->cbbytes ) ctrl->xfercb = nControl->xfercb; 976 | else ctrl->xfercb = NULL; 977 | *nData = ctrl; 978 | 979 | return 1; 980 | } 981 | 982 | /* 983 | * FtpClose - close a data connection 984 | */ 985 | int ftplib::FtpClose(ftphandle *nData) 986 | { 987 | ftphandle *ctrl; 988 | 989 | if (nData->dir == FTPLIB_WRITE) 990 | { 991 | if (nData->buf != NULL) writeline(NULL, 0, nData); 992 | } 993 | else if (nData->dir != FTPLIB_READ) return 0; 994 | if (nData->buf) free(nData->buf); 995 | shutdown(nData->handle,2); 996 | net_close(nData->handle); 997 | 998 | ctrl = nData->ctrl; 999 | #ifndef NOSSL 1000 | SSL_free(nData->ssl); 1001 | #endif 1002 | free(nData); 1003 | if (ctrl) return readresp('2', ctrl); 1004 | return 1; 1005 | } 1006 | 1007 | /* 1008 | * FtpRead - read from a data connection 1009 | */ 1010 | int ftplib::FtpRead(void *buf, int max, ftphandle *nData) 1011 | { 1012 | int i; 1013 | 1014 | if (nData->dir != FTPLIB_READ) 1015 | return 0; 1016 | if (nData->buf) i = readline(static_cast(buf), max, nData); 1017 | else 1018 | { 1019 | i = socket_wait(nData); 1020 | if (i != 1) return 0; 1021 | #ifndef NOSSL 1022 | if (nData->tlsdata) i = SSL_read(nData->ssl, buf, max); 1023 | else i = net_read(nData->handle,buf,max); 1024 | #else 1025 | i = net_read(nData->handle,buf,max); 1026 | #endif 1027 | } 1028 | if (i == -1) return 0; 1029 | nData->xfered += i; 1030 | if (nData->xfercb && nData->cbbytes) 1031 | { 1032 | nData->xfered1 += i; 1033 | if (nData->xfered1 > nData->cbbytes) 1034 | { 1035 | if (nData->xfercb(nData->xfered, nData->cbarg) == 0) return 0; 1036 | nData->xfered1 = 0; 1037 | } 1038 | } 1039 | return i; 1040 | } 1041 | 1042 | /* 1043 | * FtpWrite - write to a data connection 1044 | */ 1045 | int ftplib::FtpWrite(void *buf, int len, ftphandle *nData) 1046 | { 1047 | int i; 1048 | 1049 | if (nData->dir != FTPLIB_WRITE) return 0; 1050 | if (nData->buf) i = writeline(static_cast(buf), len, nData); 1051 | else 1052 | { 1053 | socket_wait(nData); 1054 | #ifndef NOSSL 1055 | if (nData->tlsdata) i = SSL_write(nData->ssl, buf, len); 1056 | else i = net_write(nData->handle, buf, len); 1057 | #else 1058 | i = net_write(nData->handle, buf, len); 1059 | #endif 1060 | } 1061 | if (i == -1) return 0; 1062 | nData->xfered += i; 1063 | 1064 | if (nData->xfercb && nData->cbbytes) 1065 | { 1066 | nData->xfered1 += i; 1067 | if (nData->xfered1 > nData->cbbytes) 1068 | { 1069 | if (nData->xfercb(nData->xfered, nData->cbarg) == 0) return 0; 1070 | nData->xfered1 = 0; 1071 | } 1072 | } 1073 | return i; 1074 | } 1075 | 1076 | /* 1077 | * FtpSite - send a SITE command 1078 | * 1079 | * return 1 if command successful, 0 otherwise 1080 | */ 1081 | int ftplib::Site(const char *cmd) 1082 | { 1083 | char buf[256]; 1084 | 1085 | if ((strlen(cmd) + 7) > sizeof(buf)) return 0; 1086 | sprintf(buf,"SITE %s",cmd); 1087 | if (!FtpSendCmd(buf,'2',mp_ftphandle)) return 0; 1088 | return 1; 1089 | } 1090 | 1091 | /* 1092 | * FtpRaw - send a raw string string 1093 | * 1094 | * return 1 if command successful, 0 otherwise 1095 | */ 1096 | 1097 | int ftplib::Raw(const char *cmd) 1098 | { 1099 | char buf[256]; 1100 | strncpy(buf, cmd, 256); 1101 | if (!FtpSendCmd(buf,'2',mp_ftphandle)) return 0; 1102 | return 1; 1103 | } 1104 | 1105 | /* 1106 | * FtpSysType - send a SYST command 1107 | * 1108 | * Fills in the user buffer with the remote system type. If more 1109 | * information from the response is required, the user can parse 1110 | * it out of the response buffer returned by FtpLastResponse(). 1111 | * 1112 | * return 1 if command successful, 0 otherwise 1113 | */ 1114 | int ftplib::SysType(char *buf, int max) 1115 | { 1116 | int l = max; 1117 | char *b = buf; 1118 | char *s; 1119 | if (!FtpSendCmd("SYST",'2',mp_ftphandle)) return 0; 1120 | s = &mp_ftphandle->response[4]; 1121 | while ((--l) && (*s != ' ')) *b++ = *s++; 1122 | *b++ = '\0'; 1123 | return 1; 1124 | } 1125 | 1126 | /* 1127 | * FtpMkdir - create a directory at server 1128 | * 1129 | * return 1 if successful, 0 otherwise 1130 | */ 1131 | int ftplib::Mkdir(const char *path) 1132 | { 1133 | char buf[256]; 1134 | 1135 | if ((strlen(path) + 6) > sizeof(buf)) return 0; 1136 | sprintf(buf,"MKD %s",path); 1137 | if (!FtpSendCmd(buf,'2', mp_ftphandle)) return 0; 1138 | return 1; 1139 | } 1140 | 1141 | /* 1142 | * FtpChdir - change path at remote 1143 | * 1144 | * return 1 if successful, 0 otherwise 1145 | */ 1146 | int ftplib::Chdir(const char *path) 1147 | { 1148 | char buf[256]; 1149 | 1150 | if ((strlen(path) + 6) > sizeof(buf)) return 0; 1151 | sprintf(buf,"CWD %s",path); 1152 | if (!FtpSendCmd(buf,'2',mp_ftphandle)) return 0; 1153 | return 1; 1154 | } 1155 | 1156 | /* 1157 | * FtpCDUp - move to parent directory at remote 1158 | * 1159 | * return 1 if successful, 0 otherwise 1160 | */ 1161 | int ftplib::Cdup() 1162 | { 1163 | if (!FtpSendCmd("CDUP",'2',mp_ftphandle)) return 0; 1164 | return 1; 1165 | } 1166 | 1167 | /* 1168 | * FtpRmdir - remove directory at remote 1169 | * 1170 | * return 1 if successful, 0 otherwise 1171 | */ 1172 | int ftplib::Rmdir(const char *path) 1173 | { 1174 | char buf[256]; 1175 | 1176 | if ((strlen(path) + 6) > sizeof(buf)) return 0; 1177 | sprintf(buf,"RMD %s",path); 1178 | if (!FtpSendCmd(buf,'2',mp_ftphandle)) return 0; 1179 | return 1; 1180 | } 1181 | 1182 | /* 1183 | * FtpPwd - get working directory at remote 1184 | * 1185 | * return 1 if successful, 0 otherwise 1186 | */ 1187 | int ftplib::Pwd(char *path, int max) 1188 | { 1189 | int l = max; 1190 | char *b = path; 1191 | char *s; 1192 | 1193 | if (!FtpSendCmd("PWD",'2',mp_ftphandle)) return 0; 1194 | s = strchr(mp_ftphandle->response, '"'); 1195 | if (s == NULL) return 0; 1196 | s++; 1197 | while ((--l) && (*s) && (*s != '"')) *b++ = *s++; 1198 | *b = '\0'; 1199 | return 1; 1200 | } 1201 | 1202 | /* 1203 | * FtpXfer - issue a command and transfer data 1204 | * 1205 | * return 1 if successful, 0 otherwise 1206 | */ 1207 | int ftplib::FtpXfer(const char *localfile, const char *path, ftphandle *nControl, accesstype type, transfermode mode) 1208 | { 1209 | int l,c; 1210 | char *dbuf; 1211 | FILE *local = NULL; 1212 | ftphandle *nData; 1213 | 1214 | if (localfile != NULL) 1215 | { 1216 | char ac[3] = " "; 1217 | if ((type == ftplib::dir) || (type == ftplib::dirverbose)) { ac[0] = 'w'; ac[1] = '\0'; } 1218 | if (type == ftplib::fileread) { ac[0] = 'w'; ac[1] = '\0'; } 1219 | if (type == ftplib::filewriteappend) { ac[0] = 'r'; ac[1] = '\0'; } 1220 | if (type == ftplib::filereadappend) { ac[0] = 'a'; ac[1] = '\0'; } 1221 | if (type == ftplib::filewrite) { ac[0] = 'r'; ac[1] = '\0'; } 1222 | if (mode == ftplib::image) ac[1] = 'b'; 1223 | 1224 | local = fopen64(localfile, ac); 1225 | if (local == NULL) 1226 | { 1227 | strncpy(nControl->response, strerror(errno), sizeof(nControl->response)); 1228 | return 0; 1229 | } 1230 | if (type == ftplib::filewriteappend) fseeko64(local,mp_ftphandle->offset,SEEK_SET); 1231 | } 1232 | if (local == NULL) local = ((type == ftplib::filewrite) 1233 | || (type == ftplib::filewriteappend)) ? stdin : stdout; 1234 | if (!FtpAccess(path, type, mode, nControl, &nData)) { 1235 | if (localfile != NULL) fclose(local); 1236 | return 0; 1237 | } 1238 | 1239 | dbuf = static_cast(malloc(FTPLIB_BUFSIZ)); 1240 | if ((type == ftplib::filewrite) || (type == ftplib::filewriteappend)) 1241 | { 1242 | while ((l = fread(dbuf, 1, FTPLIB_BUFSIZ, local)) > 0) 1243 | { 1244 | if ((c = FtpWrite(dbuf, l, nData)) < l) 1245 | { 1246 | printf("short write: passed %d, wrote %d\n", l, c); 1247 | break; 1248 | } 1249 | } 1250 | } 1251 | else 1252 | { 1253 | while ((l = FtpRead(dbuf, FTPLIB_BUFSIZ, nData)) > 0) 1254 | { 1255 | if (fwrite(dbuf, 1, l, local) <= 0) 1256 | { 1257 | perror("localfile write"); 1258 | break; 1259 | } 1260 | } 1261 | } 1262 | free(dbuf); 1263 | fflush(local); 1264 | if (localfile != NULL) fclose(local); 1265 | return FtpClose(nData); 1266 | } 1267 | 1268 | /* 1269 | * FtpNlst - issue an NLST command and write response to output 1270 | * 1271 | * return 1 if successful, 0 otherwise 1272 | */ 1273 | int ftplib::Nlst(const char *outputfile, const char *path) 1274 | { 1275 | mp_ftphandle->offset = 0; 1276 | return FtpXfer(outputfile, path, mp_ftphandle, ftplib::dir, ftplib::ascii); 1277 | } 1278 | 1279 | /* 1280 | * FtpDir - issue a LIST command and write response to output 1281 | * 1282 | * return 1 if successful, 0 otherwise 1283 | */ 1284 | int ftplib::Dir(const char *outputfile, const char *path) 1285 | { 1286 | mp_ftphandle->offset = 0; 1287 | return FtpXfer(outputfile, path, mp_ftphandle, ftplib::dirverbose, ftplib::ascii); 1288 | } 1289 | 1290 | /* 1291 | * FtpSize - determine the size of a remote file 1292 | * 1293 | * return 1 if successful, 0 otherwise 1294 | */ 1295 | int ftplib::Size(const char *path, int *size, transfermode mode) 1296 | { 1297 | char cmd[256]; 1298 | int resp,sz,rv=1; 1299 | 1300 | if ((strlen(path) + 7) > sizeof(cmd)) return 0; 1301 | 1302 | sprintf(cmd, "TYPE %c", mode); 1303 | if (!FtpSendCmd(cmd, '2', mp_ftphandle)) return 0; 1304 | 1305 | sprintf(cmd,"SIZE %s",path); 1306 | if (!FtpSendCmd(cmd,'2',mp_ftphandle)) rv = 0; 1307 | else 1308 | { 1309 | if (sscanf(mp_ftphandle->response, "%d %d", &resp, &sz) == 2) *size = sz; 1310 | else rv = 0; 1311 | } 1312 | return rv; 1313 | } 1314 | 1315 | /* 1316 | * FtpModDate - determine the modification date of a remote file 1317 | * 1318 | * return 1 if successful, 0 otherwise 1319 | */ 1320 | int ftplib::ModDate(const char *path, char *dt, int max) 1321 | { 1322 | char buf[256]; 1323 | int rv = 1; 1324 | 1325 | if ((strlen(path) + 7) > sizeof(buf)) return 0; 1326 | sprintf(buf,"MDTM %s",path); 1327 | if (!FtpSendCmd(buf,'2',mp_ftphandle)) rv = 0; 1328 | else strncpy(dt, &mp_ftphandle->response[4], max); 1329 | return rv; 1330 | } 1331 | 1332 | /* 1333 | * FtpGet - issue a GET command and write received data to output 1334 | * 1335 | * return 1 if successful, 0 otherwise 1336 | */ 1337 | 1338 | int ftplib::Get(const char *outputfile, const char *path, transfermode mode, off64_t offset) 1339 | { 1340 | mp_ftphandle->offset = offset; 1341 | if (offset == 0) return FtpXfer(outputfile, path, mp_ftphandle, ftplib::fileread, mode); 1342 | else return FtpXfer(outputfile, path, mp_ftphandle, ftplib::filereadappend, mode); 1343 | } 1344 | 1345 | /* 1346 | * FtpPut - issue a PUT command and send data from input 1347 | * 1348 | * return 1 if successful, 0 otherwise 1349 | */ 1350 | 1351 | int ftplib::Put(const char *inputfile, const char *path, transfermode mode, off64_t offset) 1352 | { 1353 | mp_ftphandle->offset = offset; 1354 | if (offset == 0) return FtpXfer(inputfile, path, mp_ftphandle, ftplib::filewrite, mode); 1355 | else return FtpXfer(inputfile, path, mp_ftphandle, ftplib::filewriteappend, mode); 1356 | } 1357 | 1358 | 1359 | int ftplib::Rename(const char *src, const char *dst) 1360 | { 1361 | char cmd[256]; 1362 | 1363 | if (((strlen(src) + 7) > sizeof(cmd)) || ((strlen(dst) + 7) > sizeof(cmd))) return 0; 1364 | sprintf(cmd,"RNFR %s",src); 1365 | if (!FtpSendCmd(cmd,'3',mp_ftphandle)) return 0; 1366 | sprintf(cmd,"RNTO %s",dst); 1367 | if (!FtpSendCmd(cmd,'2',mp_ftphandle)) return 0; 1368 | 1369 | return 1; 1370 | } 1371 | 1372 | int ftplib::Delete(const char *path) 1373 | { 1374 | char cmd[256]; 1375 | 1376 | if ((strlen(path) + 7) > sizeof(cmd)) return 0; 1377 | sprintf(cmd,"DELE %s",path); 1378 | if (!FtpSendCmd(cmd,'2', mp_ftphandle)) return 0; 1379 | return 1; 1380 | } 1381 | 1382 | /* 1383 | * FtpQuit - disconnect from remote 1384 | * 1385 | * return 1 if successful, 0 otherwise 1386 | */ 1387 | int ftplib::Quit() 1388 | { 1389 | if (mp_ftphandle->dir != FTPLIB_CONTROL) return 0; 1390 | if (mp_ftphandle->handle == 0) 1391 | { 1392 | strcpy(mp_ftphandle->response, "error: no anwser from server\n"); 1393 | return 0; 1394 | } 1395 | if (!FtpSendCmd("QUIT",'2',mp_ftphandle)) 1396 | { 1397 | net_close(mp_ftphandle->handle); 1398 | return 0; 1399 | } 1400 | else 1401 | { 1402 | net_close(mp_ftphandle->handle); 1403 | return 1; 1404 | } 1405 | } 1406 | 1407 | int ftplib::Fxp(ftplib* src, ftplib* dst, const char *pathSrc, const char *pathDst, transfermode mode, fxpmethod method) 1408 | { 1409 | char *cp; 1410 | unsigned char v[6]; 1411 | char buf[256]; 1412 | int retval = 0; 1413 | 1414 | sprintf(buf, "TYPE %c", mode); 1415 | if (!dst->FtpSendCmd(buf,'2',dst->mp_ftphandle)) return -1; 1416 | if (!src->FtpSendCmd(buf,'2',src->mp_ftphandle)) return -1; 1417 | 1418 | if (method == ftplib::defaultfxp) 1419 | { 1420 | // PASV dst 1421 | 1422 | if (!dst->FtpSendCmd("PASV",'2',dst->mp_ftphandle)) return -1; 1423 | cp = strchr(dst->mp_ftphandle->response,'('); 1424 | if (cp == NULL) return -1; 1425 | cp++; 1426 | #if defined(_WIN32) 1427 | unsigned int v_i[6]; 1428 | sscanf(cp,"%u,%u,%u,%u,%u,%u",&v_i[2],&v_i[3],&v_i[4],&v_i[5],&v_i[0],&v_i[1]); 1429 | for (int i = 0; i < 6; i++) v[i] = (unsigned char) v_i[i]; 1430 | #else 1431 | sscanf(cp,"%hhu,%hhu,%hhu,%hhu,%hhu,%hhu",&v[2],&v[3],&v[4],&v[5],&v[0],&v[1]); 1432 | #endif 1433 | if (dst->mp_ftphandle->correctpasv) if (!dst->CorrectPasvResponse(v)) return -1; 1434 | 1435 | // PORT src 1436 | 1437 | sprintf(buf, "PORT %d,%d,%d,%d,%d,%d", v[2],v[3],v[4],v[5],v[0],v[1]); 1438 | if (!src->FtpSendCmd(buf,'2',src->mp_ftphandle)) return -1; 1439 | 1440 | // RETR src 1441 | 1442 | strcpy(buf,"RETR"); 1443 | if (pathSrc != NULL) 1444 | { 1445 | int i = strlen(buf); 1446 | buf[i++] = ' '; 1447 | if ((strlen(pathSrc) + i) >= sizeof(buf)) return 0; 1448 | strcpy(&buf[i],pathSrc); 1449 | } 1450 | if (!src->FtpSendCmd(buf, '1', src->mp_ftphandle)) return 0; 1451 | 1452 | // STOR dst 1453 | 1454 | strcpy(buf,"STOR"); 1455 | if (pathDst != NULL) 1456 | { 1457 | int i = strlen(buf); 1458 | buf[i++] = ' '; 1459 | if ((strlen(pathDst) + i) >= sizeof(buf)) return 0; 1460 | strcpy(&buf[i],pathDst); 1461 | } 1462 | if (!dst->FtpSendCmd(buf, '1', dst->mp_ftphandle)) 1463 | { 1464 | /* this closes the data connection, to abort the RETR on 1465 | the source ftp. all hail pftp, it took me several 1466 | hours and i was absolutely clueless, playing around with 1467 | ABOR and whatever, when i desperately checked the pftp 1468 | source which gave me this final hint. thanks dude(s). */ 1469 | 1470 | dst->FtpSendCmd("PASV", '2', dst->mp_ftphandle); 1471 | src->readresp('4', src->mp_ftphandle); 1472 | return 0; 1473 | } 1474 | 1475 | retval = (src->readresp('2', src->mp_ftphandle)) & (dst->readresp('2', dst->mp_ftphandle)); 1476 | 1477 | } 1478 | else 1479 | { 1480 | // PASV src 1481 | 1482 | if (!src->FtpSendCmd("PASV",'2',src->mp_ftphandle)) return -1; 1483 | cp = strchr(src->mp_ftphandle->response,'('); 1484 | if (cp == NULL) return -1; 1485 | cp++; 1486 | #if defined(_WIN32) 1487 | unsigned int v_i[6]; 1488 | sscanf(cp,"%u,%u,%u,%u,%u,%u",&v_i[2],&v_i[3],&v_i[4],&v_i[5],&v_i[0],&v_i[1]); 1489 | for (int i = 0; i < 6; i++) v[i] = (unsigned char) v_i[i]; 1490 | #else 1491 | sscanf(cp,"%hhu,%hhu,%hhu,%hhu,%hhu,%hhu",&v[2],&v[3],&v[4],&v[5],&v[0],&v[1]); 1492 | #endif 1493 | if (src->mp_ftphandle->correctpasv) if (!src->CorrectPasvResponse(v)) return -1; 1494 | 1495 | // PORT dst 1496 | 1497 | sprintf(buf, "PORT %d,%d,%d,%d,%d,%d", v[2],v[3],v[4],v[5],v[0],v[1]); 1498 | if (!dst->FtpSendCmd(buf,'2',dst->mp_ftphandle)) return -1; 1499 | 1500 | // STOR dest 1501 | 1502 | strcpy(buf,"STOR"); 1503 | if (pathDst != NULL) 1504 | { 1505 | int i = strlen(buf); 1506 | buf[i++] = ' '; 1507 | if ((strlen(pathDst) + i) >= sizeof(buf)) return 0; 1508 | strcpy(&buf[i],pathDst); 1509 | } 1510 | if (!dst->FtpSendCmd(buf, '1', dst->mp_ftphandle)) return 0; 1511 | 1512 | // RETR src 1513 | 1514 | strcpy(buf,"RETR"); 1515 | if (pathSrc != NULL) 1516 | { 1517 | int i = strlen(buf); 1518 | buf[i++] = ' '; 1519 | if ((strlen(pathSrc) + i) >= sizeof(buf)) return 0; 1520 | strcpy(&buf[i],pathSrc); 1521 | } 1522 | if (!src->FtpSendCmd(buf, '1', src->mp_ftphandle)) 1523 | { 1524 | src->FtpSendCmd("PASV", '2', src->mp_ftphandle); 1525 | dst->readresp('4', dst->mp_ftphandle); 1526 | return 0; 1527 | } 1528 | 1529 | // wait til its finished! 1530 | 1531 | retval = (src->readresp('2', src->mp_ftphandle)) & (dst->readresp('2', dst->mp_ftphandle)); 1532 | 1533 | } 1534 | 1535 | return retval; 1536 | } 1537 | 1538 | 1539 | int ftplib::SetDataEncryption(dataencryption enc) 1540 | { 1541 | #ifdef NOSSL 1542 | (void)enc; 1543 | return 0; 1544 | #else 1545 | if (!mp_ftphandle->tlsctrl) return 0; 1546 | if (!FtpSendCmd("PBSZ 0",'2',mp_ftphandle)) return 0; 1547 | switch(enc) 1548 | { 1549 | case ftplib::unencrypted: 1550 | mp_ftphandle->tlsdata = 0; 1551 | if (!FtpSendCmd("PROT C",'2',mp_ftphandle)) return 0; 1552 | break; 1553 | case ftplib::secure: 1554 | mp_ftphandle->tlsdata = 1; 1555 | if (!FtpSendCmd("PROT P",'2',mp_ftphandle)) return 0; 1556 | break; 1557 | default: 1558 | return 0; 1559 | } 1560 | return 1; 1561 | #endif 1562 | } 1563 | 1564 | int ftplib::NegotiateEncryption() 1565 | { 1566 | #ifdef NOSSL 1567 | return 0; 1568 | #else 1569 | int ret; 1570 | 1571 | if (!FtpSendCmd("AUTH TLS",'2',mp_ftphandle)) return 0; 1572 | 1573 | mp_ftphandle->sbio = BIO_new_socket(mp_ftphandle->handle, BIO_NOCLOSE); 1574 | SSL_set_bio(mp_ftphandle->ssl,mp_ftphandle->sbio,mp_ftphandle->sbio); 1575 | 1576 | ret = SSL_connect(mp_ftphandle->ssl); 1577 | if (ret == 1) mp_ftphandle->tlsctrl = 1; 1578 | 1579 | if (mp_ftphandle->certcb != NULL) 1580 | { 1581 | X509 *cert = SSL_get_peer_certificate(mp_ftphandle->ssl); 1582 | if (!mp_ftphandle->certcb(mp_ftphandle->cbarg, cert)) return 0; 1583 | } 1584 | 1585 | if (ret < 1) return 0; 1586 | 1587 | return 1; 1588 | #endif 1589 | } 1590 | 1591 | void ftplib::SetCallbackCertFunction(FtpCallbackCert pointer) 1592 | { 1593 | #ifdef NOSSL 1594 | (void)pointer; 1595 | #else 1596 | mp_ftphandle->certcb = pointer; 1597 | #endif 1598 | } 1599 | 1600 | void ftplib::SetCallbackIdleFunction(FtpCallbackIdle pointer) 1601 | { 1602 | mp_ftphandle->idlecb = pointer; 1603 | } 1604 | 1605 | void ftplib::SetCallbackXferFunction(FtpCallbackXfer pointer) 1606 | { 1607 | mp_ftphandle->xfercb = pointer; 1608 | } 1609 | 1610 | void ftplib::SetCallbackLogFunction(FtpCallbackLog pointer) 1611 | { 1612 | mp_ftphandle->logcb = pointer; 1613 | } 1614 | 1615 | void ftplib::SetCallbackArg(void *arg) 1616 | { 1617 | mp_ftphandle->cbarg = arg; 1618 | } 1619 | 1620 | void ftplib::SetCallbackBytes(off64_t bytes) 1621 | { 1622 | mp_ftphandle->cbbytes = bytes; 1623 | } 1624 | 1625 | void ftplib::SetCallbackIdletime(int time) 1626 | { 1627 | mp_ftphandle->idletime.tv_sec = time / 1000; 1628 | mp_ftphandle->idletime.tv_usec = (time % 1000) * 1000; 1629 | } 1630 | 1631 | void ftplib::SetConnmode(connmode mode) 1632 | { 1633 | mp_ftphandle->cmode = mode; 1634 | } 1635 | 1636 | void ftplib::ClearHandle() 1637 | { 1638 | mp_ftphandle->dir = FTPLIB_CONTROL; 1639 | mp_ftphandle->ctrl = NULL; 1640 | mp_ftphandle->cmode = ftplib::pasv; 1641 | mp_ftphandle->idlecb = NULL; 1642 | mp_ftphandle->idletime.tv_sec = mp_ftphandle->idletime.tv_usec = 0; 1643 | mp_ftphandle->cbarg = NULL; 1644 | mp_ftphandle->xfered = 0; 1645 | mp_ftphandle->xfered1 = 0; 1646 | mp_ftphandle->cbbytes = 0; 1647 | #ifndef NOSSL 1648 | mp_ftphandle->tlsctrl = 0; 1649 | mp_ftphandle->tlsdata = 0; 1650 | mp_ftphandle->certcb = NULL; 1651 | #endif 1652 | mp_ftphandle->offset = 0; 1653 | mp_ftphandle->handle = 0; 1654 | mp_ftphandle->logcb = NULL; 1655 | mp_ftphandle->xfercb = NULL; 1656 | mp_ftphandle->correctpasv = false; 1657 | } 1658 | 1659 | int ftplib::CorrectPasvResponse(unsigned char *v) 1660 | { 1661 | struct sockaddr ipholder; 1662 | socklen_t ipholder_size = sizeof(ipholder); 1663 | 1664 | if (getpeername(mp_ftphandle->handle, &ipholder, &ipholder_size) == -1) 1665 | { 1666 | perror("getpeername"); 1667 | net_close(mp_ftphandle->handle); 1668 | return 0; 1669 | } 1670 | 1671 | for (int i = 2; i < 6; i++) v[i] = ipholder.sa_data[i]; 1672 | 1673 | return 1; 1674 | } 1675 | 1676 | ftphandle* ftplib::RawOpen(const char *path, accesstype type, transfermode mode) 1677 | { 1678 | int ret; 1679 | ftphandle* datahandle; 1680 | ret = FtpAccess(path, type, mode, mp_ftphandle, &datahandle); 1681 | if (ret) return datahandle; 1682 | else return NULL; 1683 | } 1684 | 1685 | int ftplib::RawClose(ftphandle* handle) 1686 | { 1687 | return FtpClose(handle); 1688 | } 1689 | 1690 | int ftplib::RawWrite(void* buf, int len, ftphandle* handle) 1691 | { 1692 | return FtpWrite(buf, len, handle); 1693 | } 1694 | 1695 | int ftplib::RawRead(void* buf, int max, ftphandle* handle) 1696 | { 1697 | return FtpRead(buf, max, handle); 1698 | } 1699 | -------------------------------------------------------------------------------- /ftplib.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | ftplib.h - description 3 | ------------------- 4 | begin : Son Jul 27 2003 5 | copyright : (C) 2013 by magnus kulke 6 | email : mkulke@gmail.com 7 | ***************************************************************************/ 8 | 9 | /*************************************************************************** 10 | * * 11 | * This program is free software; you can redistribute it and/or modify * 12 | * it under the terms of the GNU Lesser General Public License as * 13 | * published by the Free Software Foundation; either version 2.1 of the * 14 | * License, or (at your option) any later version. * 15 | * * 16 | ***************************************************************************/ 17 | 18 | /*************************************************************************** 19 | * Note: ftplib, on which ftplibpp was originally based upon used to be * 20 | * licensed as GPL 2.0 software, as of Jan. 26th 2013 its author Thomas * 21 | * Pfau allowed the distribution of ftplib via LGPL. Thus the license of * 22 | * ftplibpp changed aswell. * 23 | ***************************************************************************/ 24 | 25 | #ifndef FTPLIB_H 26 | #define FTPLIB_H 27 | 28 | #if defined(_WIN32) 29 | 30 | #if BUILDING_DLL 31 | # define DLLIMPORT __declspec (dllexport) 32 | #else /* Not BUILDING_DLL */ 33 | # define DLLIMPORT __declspec (dllimport) 34 | #endif /* Not BUILDING_DLL */ 35 | 36 | #include 37 | #endif 38 | 39 | #ifndef _WIN32 40 | #include 41 | #include 42 | #endif 43 | 44 | #ifdef NOLFS 45 | #define off64_t long 46 | #define fseeko64 fseek 47 | #define fopen64 fopen 48 | #endif 49 | 50 | #if defined(__APPLE__) 51 | #define off64_t __darwin_off_t 52 | #define fseeko64 fseeko 53 | #define fopen64 fopen 54 | #endif 55 | 56 | //SSL 57 | typedef struct ssl_st SSL; 58 | typedef struct ssl_ctx_st SSL_CTX; 59 | typedef struct bio_st BIO; 60 | typedef struct x509_st X509; 61 | 62 | #include 63 | 64 | #ifndef _FTPLIB_SSL_CLIENT_METHOD_ 65 | #define _FTPLIB_SSL_CLIENT_METHOD_ TLSv1_2_client_method 66 | #endif 67 | 68 | using namespace std; 69 | 70 | //SSL 71 | typedef struct ssl_st SSL; 72 | typedef struct ssl_ctx_st SSL_CTX; 73 | typedef struct bio_st BIO; 74 | typedef struct x509_st X509; 75 | 76 | /** 77 | *@author mkulke 78 | */ 79 | 80 | typedef int (*FtpCallbackXfer)(off64_t xfered, void *arg); 81 | typedef int (*FtpCallbackIdle)(void *arg); 82 | typedef void (*FtpCallbackLog)(char *str, void* arg, bool out); 83 | //SSL 84 | typedef bool (*FtpCallbackCert)(void *arg, X509 *cert); 85 | 86 | 87 | struct ftphandle { 88 | char *cput,*cget; 89 | int handle; 90 | int cavail,cleft; 91 | char *buf; 92 | int dir; 93 | ftphandle *ctrl; 94 | int cmode; 95 | struct timeval idletime; 96 | FtpCallbackXfer xfercb; 97 | FtpCallbackIdle idlecb; 98 | FtpCallbackLog logcb; 99 | void *cbarg; 100 | off64_t xfered; 101 | off64_t cbbytes; 102 | off64_t xfered1; 103 | char response[256]; 104 | //SSL 105 | SSL* ssl; 106 | SSL_CTX* ctx; 107 | BIO* sbio; 108 | int tlsctrl; 109 | int tlsdata; 110 | FtpCallbackCert certcb; 111 | 112 | off64_t offset; 113 | bool correctpasv; 114 | }; 115 | 116 | #if defined(_WIN32) 117 | class DLLIMPORT ftplib { 118 | #else 119 | class ftplib { 120 | #endif 121 | public: 122 | 123 | enum accesstype 124 | { 125 | dir = 1, 126 | dirverbose, 127 | fileread, 128 | filewrite, 129 | filereadappend, 130 | filewriteappend 131 | }; 132 | 133 | enum transfermode 134 | { 135 | ascii = 'A', 136 | image = 'I' 137 | }; 138 | 139 | enum connmode 140 | { 141 | pasv = 1, 142 | port 143 | }; 144 | 145 | enum fxpmethod 146 | { 147 | defaultfxp = 0, 148 | alternativefxp 149 | }; 150 | 151 | enum dataencryption 152 | { 153 | unencrypted = 0, 154 | secure 155 | }; 156 | 157 | ftplib(); 158 | ~ftplib(); 159 | char* LastResponse(); 160 | int Connect(const char *host); 161 | int Login(const char *user, const char *pass); 162 | int Site(const char *cmd); 163 | int Raw(const char *cmd); 164 | int SysType(char *buf, int max); 165 | int Mkdir(const char *path); 166 | int Chdir(const char *path); 167 | int Cdup(); 168 | int Rmdir(const char *path); 169 | int Pwd(char *path, int max); 170 | int Nlst(const char *outputfile, const char *path); 171 | int Dir(const char *outputfile, const char *path); 172 | int Size(const char *path, int *size, transfermode mode); 173 | int ModDate(const char *path, char *dt, int max); 174 | int Get(const char *outputfile, const char *path, transfermode mode, off64_t offset = 0); 175 | int Put(const char *inputfile, const char *path, transfermode mode, off64_t offset = 0); 176 | int Rename(const char *src, const char *dst); 177 | int Delete(const char *path); 178 | int Quit(); 179 | void SetCallbackIdleFunction(FtpCallbackIdle pointer); 180 | void SetCallbackLogFunction(FtpCallbackLog pointer); 181 | void SetCallbackXferFunction(FtpCallbackXfer pointer); 182 | void SetCallbackArg(void *arg); 183 | void SetCallbackBytes(off64_t bytes); 184 | void SetCorrectPasv(bool b) { mp_ftphandle->correctpasv = b; }; 185 | void SetCallbackIdletime(int time); 186 | void SetConnmode(connmode mode); 187 | static int Fxp(ftplib* src, ftplib* dst, const char *pathSrc, const char *pathDst, transfermode mode, fxpmethod method); 188 | ftphandle* RawOpen(const char *path, accesstype type, transfermode mode); 189 | int RawClose(ftphandle* handle); 190 | int RawWrite(void* buf, int len, ftphandle* handle); 191 | int RawRead(void* buf, int max, ftphandle* handle); 192 | // SSL 193 | int SetDataEncryption(dataencryption enc); 194 | int NegotiateEncryption(); 195 | void SetCallbackCertFunction(FtpCallbackCert pointer); 196 | 197 | private: 198 | ftphandle* mp_ftphandle; 199 | 200 | int FtpXfer(const char *localfile, const char *path, ftphandle *nControl, accesstype type, transfermode mode); 201 | int FtpOpenPasv(ftphandle *nControl, ftphandle **nData, transfermode mode, int dir, char *cmd); 202 | int FtpSendCmd(const char *cmd, char expresp, ftphandle *nControl); 203 | int FtpAcceptConnection(ftphandle *nData, ftphandle *nControl); 204 | int FtpOpenPort(ftphandle *nControl, ftphandle **nData, transfermode mode, int dir, char *cmd); 205 | int FtpRead(void *buf, int max, ftphandle *nData); 206 | int FtpWrite(void *buf, int len, ftphandle *nData); 207 | int FtpAccess(const char *path, accesstype type, transfermode mode, ftphandle *nControl, ftphandle **nData); 208 | int FtpClose(ftphandle *nData); 209 | int socket_wait(ftphandle *ctl); 210 | int readline(char *buf,int max,ftphandle *ctl); 211 | int writeline(char *buf, int len, ftphandle *nData); 212 | int readresp(char c, ftphandle *nControl); 213 | void sprint_rest(char *buf, off64_t offset); 214 | void ClearHandle(); 215 | int CorrectPasvResponse(unsigned char *v); 216 | }; 217 | 218 | #endif 219 | -------------------------------------------------------------------------------- /sample/Readme.md: -------------------------------------------------------------------------------- 1 | # Sample Project 2 | 3 | ``` 4 | g++ -I.. -c sample.cpp 5 | g++ -L.. -o sample sample.o -lftp++ 6 | ``` 7 | 8 | ## MacOs 9 | 10 | ``` 11 | DYLD_LIBRARY_PATH=.. ./sample 12 | ``` 13 | 14 | ## Linux 15 | 16 | ``` 17 | LD_LIBRARY_PATH=.. ./sample 18 | ``` 19 | -------------------------------------------------------------------------------- /sample/sample.cpp: -------------------------------------------------------------------------------- 1 | #include "ftplib.h" 2 | 3 | int main(void) 4 | { 5 | ftplib *ftp = new ftplib(); 6 | ftp->Connect("ftp.gwdg.de:21"); 7 | ftp->Login("anonymous", ""); 8 | ftp->Dir(NULL, "/pub/linux/apache"); 9 | ftp->Quit(); 10 | return 0; 11 | } 12 | --------------------------------------------------------------------------------