Subversion Repositories Kolibri OS

Rev

Rev 7167 | Rev 7463 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2013-2018. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  ftpc.asm - FTP client for KolibriOS                            ;;
  7. ;;                                                                 ;;
  8. ;;  Written by hidnplayr@kolibrios.org                             ;;
  9. ;;  Modified by nisargshah323@gmail.com (2016)                     ;;
  10. ;;                                                                 ;;
  11. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  12. ;;             Version 2, June 1991                                ;;
  13. ;;                                                                 ;;
  14. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  15.  
  16. format binary as ""
  17.  
  18. TIMEOUT                 = 3     ; seconds
  19.  
  20. BUFFERSIZE              = 4096
  21.  
  22. STATUS_CONNECTING       = 0
  23. STATUS_CONNECTED        = 1
  24. STATUS_NEEDPASSWORD     = 2
  25. STATUS_LOGGED_IN        = 3
  26.  
  27. OPERATION_NONE          = 0
  28. OPERATION_LIST          = 1
  29. OPERATION_RETR          = 2
  30. OPERATION_STOR          = 3
  31. OPERATION_RDIR          = 4
  32.        
  33. use32
  34. ; standard header
  35.         db      'MENUET01'      ; signature
  36.         dd      1               ; header version
  37.         dd      start           ; entry point
  38.         dd      i_end           ; initialized size
  39.         dd      mem+0x1000      ; required memory
  40.         dd      mem+0x1000      ; stack pointer
  41.         dd      buf_cmd         ; parameters
  42.         dd      path            ; path
  43.  
  44. include '../../macros.inc'
  45. macro ijmp reg, addr, method
  46. {  
  47.     mov  reg, [addr]
  48.     add  reg, [method]
  49.     jmp  dword[reg]
  50. }
  51. macro icall reg, addr, method, [arg]
  52. {  
  53.     mov  reg, [addr]
  54.     add  reg, [method]
  55.     if ~ arg eq
  56.       pushd arg
  57.     end if
  58.     call dword[reg]
  59. }
  60.  
  61. purge mov,add,sub
  62.  
  63. include '../../proc32.inc'
  64. include '../../network.inc'
  65. include '../../KOSfuncs.inc'
  66. include '../../load_img.inc'
  67. include '../../develop/libraries/libs-dev/libimg/libimg.inc'
  68. include '../../develop/libraries/box_lib/trunk/box_lib.mac'
  69. include '../../develop/libraries/box_lib/load_lib.mac'
  70.  
  71. include 'console.inc'
  72. include 'gui.inc'
  73. include 'login_gui.inc'
  74. include 'usercommands.inc'
  75. include 'servercommands.inc'
  76. include 'parser.inc'
  77.  
  78. ; TODO: Add Pasta support to FTPC
  79.  
  80. ;;================================================================================================;;
  81. start: ;//////////////////////////////////////////////////////////////////////////////////////////;;
  82. ;;------------------------------------------------------------------------------------------------;;
  83. ;? Program entry point - initialize heap, load libraries and settings                             ;;
  84. ;;------------------------------------------------------------------------------------------------;;
  85. ;>                                                                                                ;;
  86. ;;------------------------------------------------------------------------------------------------;;
  87. ;< none                                                                                           ;;
  88. ;;================================================================================================;;
  89. ; initialize heap for using dynamic blocks
  90.         mcall   68, 11
  91.         test    eax, eax
  92.         je      exit2
  93.        
  94. ; disable all events except network event
  95.         mcall   40, EV_STACK
  96. ; load libraries
  97.         stdcall dll.Load, @IMPORT
  98.         test    eax, eax
  99.         jnz     exit
  100. ; find path to main settings file (ftpc.ini)
  101.         mov     edi, path               ; Calculate the length of zero-terminated string
  102.         xor     al, al
  103.         mov     ecx, 1024
  104.         repne   scasb
  105.         dec     edi
  106.         mov     esi, str_ini            ; append it with '.ini', 0
  107.         movsd
  108.         movsb
  109. ; get settings from ini
  110.         invoke  ini.get_str, path, str_active, str_ip, str_active_ip, 16, 0
  111.         mov     esi, str_active_ip
  112.   .ip_loop:
  113.         lodsb
  114.         test    al, al
  115.         jz      .ip_ok
  116.         cmp     al, ' '
  117.         je      .ip_ok
  118.         cmp     al, '.'
  119.         jne     .ip_loop
  120.         mov     byte[esi-1], ','
  121.         jmp     .ip_loop
  122.   .ip_ok:
  123.         mov     byte[esi-1], 0
  124.  
  125.         invoke  ini.get_int, path, str_active, str_port_start, 64000
  126.         mov     [acti_port_start], ax
  127.  
  128.         invoke  ini.get_int, path, str_active, str_port_stop, 65000
  129.         mov     [acti_port_stop], ax
  130.  
  131.         invoke  ini.get_str, path, str_general, str_dir, buf_buffer1, BUFFERSIZE, 0
  132.         mcall   30, 1, buf_buffer1                      ; set working directory
  133.  
  134.         ; initialize log file
  135.         invoke  ini.get_str, path, str_general, str_logfile, log_file, 512, 0
  136.         mov     [filestruct2.subfn], 2
  137.         mov     [filestruct2.offset], 0
  138.         mov     [filestruct2.size], 0
  139.         mov     [filestruct2.ptr], 0
  140.         mov     [filestruct2.name], log_file
  141.         mcall   70, filestruct2
  142.  
  143. ; Usage: ftpc [-cli] [ftp://username:password@server:port/path]
  144.  
  145.         ; mov     dword[buf_cmd], '-cli' ;;;; to test CLI ;;;;;
  146.  
  147.         cmp     byte[buf_cmd], 0
  148.         jne     @f
  149.         mov     [interface_addr], gui
  150.         jmp     .args_ok
  151.   @@:   cmp     dword[buf_cmd], '-cli'
  152.         jne     .error
  153.         mov     [interface_addr], console
  154.         jmp     .args_ok
  155.  
  156.   .args_ok:
  157.  
  158.         icall   eax, interface_addr, interface.init
  159.         ; check for ftp://username:pass@server:port/path urls
  160.         cmp     dword[buf_cmd], 'ftp:'
  161.         je      parse_args
  162.         cmp     dword[buf_cmd+5], 'ftp:'
  163.         je      parse_args
  164.         ijmp    eax, interface_addr, interface.server_addr
  165.  
  166.   .error:
  167.         call    console.init
  168.         invoke  con_write_asciiz, str_args_err
  169.         invoke  con_getch2
  170.         call    console.exit
  171.         jmp     exit
  172.  
  173. ;;================================================================================================;;
  174. arg_handler: ;////////////////////////////////////////////////////////////////////////////////////;;
  175. ;;------------------------------------------------------------------------------------------------;;
  176. ;? Passes initial connection info from console/GUI to FTP core and the other way around           ;;
  177. ;;------------------------------------------------------------------------------------------------;;
  178. ;> esp+4 = pointer to the argument passed to the function                                         ;;
  179. ;;------------------------------------------------------------------------------------------------;;
  180. ;< none                                                                                           ;;
  181. ;;================================================================================================;;
  182.  
  183.   .get_username:
  184. ; request username
  185.         ijmp    eax, interface_addr, interface.get_username
  186.  
  187.   .copy_user:
  188.         mov     dword[buf_cmd], "USER"
  189.         mov     byte[buf_cmd+4], " "
  190. ; copy user name to buf_cmd (for command line args)
  191.         mov     edi, buf_cmd+5
  192.         mov     esi, param_user
  193.   @@:
  194.         movsb
  195.         cmp     byte [esi-1], 0
  196.         jne     @b
  197.         mov     word[edi-1], 0x0a0d
  198.  
  199.         lea     esi, [edi+1-buf_cmd]
  200.         jmp     server_connect.send
  201.  
  202.   .get_pass:
  203.         mov     dword[buf_cmd], "PASS"
  204.         mov     byte[buf_cmd+4], " "
  205. ; copy password to buf_cmd (for command line args)
  206.         mov     edi, buf_cmd+5
  207.         mov     esi, param_password
  208.   @@:
  209.         movsb
  210.         cmp     byte[esi-1], 0
  211.         jne     @b
  212.         mov     word[edi-1], 0x0a0d
  213.  
  214.         lea     esi, [edi+1-buf_cmd]
  215.         jmp     server_connect.send
  216.  
  217.   .get_path:
  218. ; copy path from param_path to buf_cmd
  219.         mov     dword[buf_cmd], "CWD "
  220.         mov     edi, buf_cmd+4
  221.         mov     esi, param_path
  222.   @@:
  223.         lodsb
  224.         stosb
  225.         cmp     al, 0x20
  226.         ja      @b
  227.         mov     word[edi-1], 0x0a0d
  228.  
  229.         lea     esi, [edi+1-buf_cmd]
  230.         jmp     server_connect.send
  231.  
  232.   .connect:
  233.         ; copy server address to buf_cmd
  234.         mov     esi, param_server_addr
  235.         mov     edi, buf_cmd
  236.   @@:
  237.         lodsb
  238.         stosb
  239.         cmp     al, 0x20
  240.         ja      @r
  241.         mov     byte[edi-1], 0 ; delete terminating '\n'
  242.  
  243.         cmp     [param_port], 0x20
  244.         jbe     server_connect.default_port
  245.         mov     esi, param_port
  246.         jmp     server_connect.do_port
  247.  
  248.  
  249. ;;================================================================================================;;
  250. server_connect: ;/////////////////////////////////////////////////////////////////////////////////;;
  251. ;;------------------------------------------------------------------------------------------------;;
  252. ;? Establishes a connection to the FTP server (common block for all interfaces)                   ;;
  253. ;? .do_port - Port is specified by the user and needs to be converted from ASCII                  ;;
  254. ;;------------------------------------------------------------------------------------------------;;
  255. ;> esi = pointer to port no.                                                                      ;;
  256. ;;------------------------------------------------------------------------------------------------;;
  257. ;< none                                                                                           ;;
  258. ;;================================================================================================;;
  259.  
  260.   .send:
  261. ; send username/password/path to the server
  262.         mcall   send, [controlsocket], buf_cmd, , 0
  263.         icall   eax, interface_addr, interface.print, str_newline
  264.         icall   eax, interface_addr, interface.set_flags, 0x07 ; reset color
  265.        
  266.         jmp     wait_for_servercommand
  267.  
  268. ; resolve port if specified
  269.   .do_port:
  270.         xor     eax, eax
  271.         xor     ebx, ebx
  272.   .portloop:
  273.         lodsb
  274.         cmp     al, 0x20
  275.         jbe     .port_done
  276.         sub     al, '0'
  277.         jnb     @f
  278.         mov     eax, str_err_host
  279.         jmp     error
  280.     @@: cmp     al, 9
  281.         jna     @f
  282.         mov     eax, str_err_host
  283.         jmp     error
  284.     @@: lea     ebx, [ebx*4 + ebx]
  285.         shl     ebx, 1
  286.         add     ebx, eax
  287.         jmp     .portloop
  288.  
  289.   .port_done:
  290.         xchg    bl, bh
  291.         mov     [sockaddr1.port], bx
  292.         jmp     .done
  293.  
  294.   .default_port:
  295.         mov     [sockaddr1.port], 21 shl 8
  296.  
  297.   .done:
  298. ; Say to the user that we're resolving
  299.         icall   eax, interface_addr, interface.set_flags, 0x07 ; reset color
  300.         icall   eax, interface_addr, interface.print, str_resolve, buf_cmd
  301. ; resolve name
  302.         push    esp     ; reserve stack place
  303.         invoke  getaddrinfo, buf_cmd, 0, 0, esp
  304.         pop     esi
  305. ; test for error
  306.         test    eax, eax
  307.         jz      @f
  308.         mov     eax, str_err_resolve
  309.         jmp     error
  310.     @@:
  311. ; write results
  312.         icall   eax, interface_addr, interface.print, str8 ; ' (',0
  313.         mov     eax, [esi+addrinfo.ai_addr]     ; convert IP address to decimal notation
  314.         mov     eax, [eax+sockaddr_in.sin_addr] ;
  315.         mov     [sockaddr1.ip], eax             ;
  316.         invoke  inet_ntoa, eax                  ;
  317.         icall   ebx, interface_addr, interface.print, eax, str9 ; <ip>,')',10,0
  318.         invoke  freeaddrinfo, esi               ; free allocated memory
  319. ; open the socket
  320.         mcall   socket, AF_INET4, SOCK_STREAM, 0
  321.         cmp     eax, -1
  322.         jne     @f
  323.         mov     eax, str_err_socket
  324.         jmp     error
  325.     @@: mov     [controlsocket], eax
  326. ; connect to the server
  327.         icall   eax, interface_addr, interface.print, str_connect
  328.         mcall   connect, [controlsocket], sockaddr1, 18
  329.         cmp     eax, -1
  330.         jne     @f
  331.         mov     eax, str_err_connect
  332.         jmp     error
  333.     @@: mov     [status], STATUS_CONNECTING
  334. ; Tell the user we're waiting for the server now.
  335.         icall   eax, interface_addr, interface.print, str_waiting
  336.  
  337. ; Reset 'offset' variable, it's used by the data receiver
  338.         mov     [offset], 0
  339.  
  340.  
  341. ;;================================================================================================;;
  342. wait_for_servercommand: ;/////////////////////////////////////////////////////////////////////////;;
  343. ;;------------------------------------------------------------------------------------------------;;
  344. ;? Checks if any data received from the server is present in buffer.                              ;;
  345. ;? If not, receives and processes it                                                              ;;
  346. ;;------------------------------------------------------------------------------------------------;;
  347. ;>                                                                                                ;;
  348. ;;------------------------------------------------------------------------------------------------;;
  349. ;< none                                                                                           ;;
  350. ;;================================================================================================;;
  351. ; Any commands still in our buffer?
  352.         cmp     [offset], 0
  353.         je      .receive                        ; nope, receive some more
  354.         mov     esi, [offset]
  355.         mov     edi, buf_cmd
  356.         mov     ecx, [size]
  357.         add     ecx, esi
  358.         jmp     .byteloop
  359.  
  360. ; receive socket data
  361.   .receive:
  362.         mcall   26, 9
  363.         add     eax, TIMEOUT*100
  364.         mov     [timeout], eax
  365.   .receive_loop:
  366.         mcall   23, 50          ; Wait for event with timeout
  367.         mcall   26, 9
  368.         cmp     eax, [timeout]
  369.         jl      @f
  370.         mov     eax, str_err_timeout
  371.         jmp     error
  372.     @@: mcall   recv, [controlsocket], buf_buffer1, BUFFERSIZE, MSG_DONTWAIT
  373.         test    eax, eax
  374.         jnz     .got_data
  375.         cmp     ebx, EWOULDBLOCK
  376.         je      @f
  377.         mov     eax, str_err_recv
  378.         jmp     error
  379.     @@: jmp     .receive_loop
  380.  
  381.   .got_data:
  382.         mov     [offset], 0
  383.  
  384. ; extract commands, copy them to "buf_cmd" buffer
  385.         lea     ecx, [eax + buf_buffer1]         ; ecx = end pointer
  386.         mov     esi, buf_buffer1                 ; esi = current pointer
  387.         mov     edi, buf_cmd
  388.   .byteloop:
  389.         cmp     esi, ecx
  390.         jae     wait_for_servercommand
  391.         lodsb
  392.         cmp     al, 10                          ; excellent, we might have a command
  393.         je      .got_command
  394.         cmp     al, 13                          ; just ignore this byte
  395.         je      .byteloop
  396.         stosb
  397.         jmp     .byteloop
  398.   .got_command:                                 ; we have a newline check if its a command
  399.         cmp     esi, ecx
  400.         je      .no_more_data
  401.         mov     [offset], esi
  402.         sub     ecx, esi
  403.         mov     [size], ecx
  404.         jmp     .go_cmd
  405.   .no_more_data:
  406.         mov     [offset], 0
  407.   .go_cmd:
  408.         lea     ecx, [edi - buf_cmd]                  ; length of command
  409.         xor     al, al
  410.         stosb
  411.  
  412.         icall   eax, interface_addr, interface.set_flags, 0x03 ; change color
  413.         icall   eax, interface_addr, interface.print, buf_cmd, str_newline
  414.         icall   eax, interface_addr, interface.set_flags, 0x07 ; reset color
  415.  
  416.         jmp     server_parser                   ; parse command
  417.  
  418.  
  419.  
  420. ;;================================================================================================;;
  421. wait_for_usercommand: ;///////////////////////////////////////////////////////////////////////////;;
  422. ;;------------------------------------------------------------------------------------------------;;
  423. ;? Reads the FTP command entered by the user and compares it with valid FTP commands.             ;;
  424. ;? Jumps to appropriate handling routine in usercommands.inc                                      ;;
  425. ;;------------------------------------------------------------------------------------------------;;
  426. ;> status = socket connection status                                                              ;;
  427. ;> buf_cmd = command entered by the user                                                          ;;
  428. ;;------------------------------------------------------------------------------------------------;;
  429. ;< none                                                                                           ;;
  430. ;;================================================================================================;;
  431.  
  432. ; Are there any files in the transfer queue?
  433.  
  434.         cmp     [queued], 0
  435.         ja      transfer_queued                 ; Yes, transfer those first.
  436.  
  437. ; change color to green for user input
  438.         icall   eax, interface_addr, interface.set_flags, 0x0a
  439.  
  440. ; If we are not yet connected, request username/password
  441.  
  442.         cmp     [status], STATUS_CONNECTED
  443.         je      arg_handler.get_username
  444.  
  445.         cmp     [status], STATUS_NEEDPASSWORD
  446.         je      arg_handler.get_pass
  447.  
  448.         ijmp    eax, interface_addr, interface.get_cmd
  449.  
  450.   .parse_cmd:
  451.         cmp     dword[buf_cmd], "cwd "
  452.         je      cmd_cwd
  453.  
  454.         cmp     dword[buf_cmd], "mkd "
  455.         je      cmd_mkd
  456.  
  457.         cmp     dword[buf_cmd], "rmd "
  458.         je      cmd_rmd
  459.  
  460.         cmp     dword[buf_cmd], "pwd" + 10 shl 24
  461.         je      cmd_pwd
  462.  
  463.         cmp     dword[buf_cmd], "bye" + 10 shl 24
  464.         je      cmd_bye
  465.  
  466.         cmp     dword[buf_cmd], "rdir"
  467.         je      cmd_rdir
  468.        
  469.         cmp     byte[buf_cmd+4], " "
  470.         jne     @f
  471.  
  472.         cmp     dword[buf_cmd], "lcwd"
  473.         je      cmd_lcwd
  474.  
  475.         cmp     dword[buf_cmd], "retr"
  476.         je      cmd_retr
  477.  
  478.         cmp     dword[buf_cmd], "stor"
  479.         je      cmd_stor
  480.  
  481.         cmp     dword[buf_cmd], "dele"
  482.         je      cmd_dele
  483.  
  484.   @@:
  485.         cmp     byte[buf_cmd+4], 10
  486.         jne     @f
  487.  
  488.         cmp     dword[buf_cmd], "list"
  489.         je      cmd_list
  490.  
  491.         cmp     dword[buf_cmd], "help"
  492.         je      cmd_help
  493.  
  494.         cmp     dword[buf_cmd], "cdup"
  495.         je      cmd_cdup
  496.  
  497.         cmp     dword[buf_cmd], "abor"
  498.         je      cmd_abor
  499.  
  500.   @@:
  501. ; Uh oh.. unknown command, tell the user and wait for new input
  502.         icall   eax, interface_addr, interface.print, str_unknown
  503.         jmp     wait_for_usercommand
  504.  
  505.  
  506. ; files for rdir operation are queued
  507. transfer_queued:
  508.  
  509.         mov     esi, [ptr_queue]                ; always pointing to current part of ptr_fname_start
  510.         mov     edi, buf_cmd+5                  ; always point to filename for retr command
  511.   .build_filename:
  512.         lodsb  
  513.         stosb
  514.         cmp     al, 10
  515.         je      .get_file                       ; filename ends with character 10
  516.         test    al, al
  517.         jnz     .build_filename
  518.  
  519.         ; Error occured, we reached the end of the buffer before [queued] reached 0
  520.         mov     [queued], 0
  521.         mcall   68, 13, [ptr_fname]             ; free buffer
  522.         test    eax, eax
  523.         jz      error_heap
  524.         jmp     wait_for_usercommand
  525.  
  526.   .get_file:
  527.         mov     byte[edi], 0                    ; end filename with 0 byte
  528.         mov     [ptr_queue], esi
  529.         dec     [queued]
  530.         jnz     cmd_retr
  531.  
  532.         mcall   68, 13, [ptr_fname]             ; free buffer
  533.         test    eax, eax
  534.         jz      error_heap
  535.         jmp     cmd_retr
  536.  
  537.  
  538.  
  539. open_dataconnection:
  540.  
  541.         test    [mode], 1
  542.         jnz     .active
  543.  
  544.         mcall   send, [controlsocket], str_PASV, str_PASV.length, 0
  545.         ret
  546.  
  547.   .active:
  548.         mcall   socket, AF_INET4, SOCK_STREAM, 0
  549.         cmp     eax, -1
  550.         jne     @f
  551.         mov     eax, str_err_socket
  552.         jmp     error
  553.     @@: mov     [datasocket], eax
  554.  
  555.         mov     ax, [acti_port_start]
  556.         xchg    al, ah
  557.         mov     [sockaddr2.port], ax
  558.  
  559.         mcall   bind, [datasocket], sockaddr2, 18
  560.         cmp     eax, -1
  561.         jne     @f
  562.         mov     eax, str_err_bind
  563.         jmp     error
  564.     @@:
  565.  
  566.         mcall   listen, [datasocket], 1
  567.         cmp     eax, -1
  568.         jne     @f
  569.         mov     eax, str_err_listen
  570.         jmp     error
  571.     @@:
  572.  
  573.         mov     dword[buf_buffer1], 'PORT'
  574.         mov     byte[buf_buffer1+4], ' '
  575.         mov     edi, buf_buffer1+5
  576.         mov     esi, str_active_ip
  577.   .loop:
  578.         lodsb
  579.         test    al, al
  580.         jz      .ip_ok
  581.         stosb
  582.         jmp     .loop
  583.   .ip_ok:
  584.         mov     al, ','
  585.         stosb
  586.         movzx   eax, byte[sockaddr2.port+0]
  587.         call    dword_ascii
  588.         mov     al, ','
  589.         stosb
  590.         movzx   eax, byte[sockaddr2.port+1]
  591.         call    dword_ascii
  592.         mov     ax, 0x0a0d
  593.         stosw
  594.         lea     esi, [edi - buf_buffer1]
  595.         mcall   send, [controlsocket], buf_buffer1, , 0
  596.  
  597.         mcall   accept, [datasocket], sockaddr2, 18        ; time to accept the awaiting connection..
  598.         cmp     eax, -1
  599.         jne     @f
  600.         mov     eax, str_err_accept
  601.         jmp     error
  602.     @@: push    eax
  603.         mcall   close, [datasocket]
  604.         pop     [datasocket]
  605.  
  606.         mcall   recv, [controlsocket], buf_buffer1, BUFFERSIZE, 0
  607.  
  608.         ret
  609.  
  610. ; eax = input
  611. ; edi = ptr where to write
  612. dword_ascii:
  613.  
  614.         push    edx ebx ecx
  615.         mov     ebx, 10
  616.         xor     ecx, ecx
  617.  
  618.        @@:
  619.         xor     edx, edx
  620.         div     ebx
  621.         add     edx, '0'
  622.         push    dx
  623.         inc     ecx
  624.         test    eax, eax
  625.         jnz     @r
  626.  
  627.        @@:
  628.         pop     ax
  629.         stosb
  630.         dec     ecx
  631.         jnz     @r
  632.  
  633.         pop     ecx ebx edx
  634.         ret
  635.  
  636.  
  637. ;;================================================================================================;;
  638. write_to_file: ;//////////////////////////////////////////////////////////////////////////////////;;
  639. ;;------------------------------------------------------------------------------------------------;;
  640. ;? Writes input buffer to log file                                                                ;;
  641. ;;------------------------------------------------------------------------------------------------;;
  642. ;> eax = pointer to buffer                                                                        ;;
  643. ;> ecx = size of buffer                                                                           ;;
  644. ;;------------------------------------------------------------------------------------------------;;
  645. ;< eax = status of SF 70.3                                                                        ;;
  646. ;;================================================================================================;;
  647.         cmp     [logfile_offset], -1 ; if offset == -1 => logging disabled
  648.         jne     @f
  649.         mov     eax, 0
  650.         ret
  651.       @@:
  652.         mov     [filestruct2.subfn], 3
  653.         m2m     [filestruct2.offset], [logfile_offset]
  654.         mov     [filestruct2.size], ecx
  655.         mov     [filestruct2.ptr], eax
  656.         mov     [filestruct2.name], log_file
  657.         mcall   70, filestruct2
  658.         test    eax, eax
  659.         jz      @f
  660.         mov     [logfile_offset], -1 ; disable logging
  661.         call    error_fs
  662.         icall   ebx, interface_addr, interface.print, str_no_logging
  663.         ret
  664.       @@:
  665.         mov     eax, [logfile_offset]
  666.         add     eax, ecx
  667.         mov     [logfile_offset], eax
  668.         ret
  669.  
  670. ;;================================================================================================;;
  671. error: ;//////////////////////////////////////////////////////////////////////////////////////////;;
  672. ;;------------------------------------------------------------------------------------------------;;
  673. ;? Generic error routine. Prints the error string passed to it.                                   ;;
  674. ;;------------------------------------------------------------------------------------------------;;
  675. ;> eax = pointer to the error string                                                              ;;
  676. ;;------------------------------------------------------------------------------------------------;;
  677. ;< none                                                                                           ;;
  678. ;;================================================================================================;;
  679.         push    eax
  680.         icall   ebx, interface_addr, interface.set_flags, 0x0c ; print errors in red
  681.         pop     eax
  682.         icall   ebx, interface_addr, interface.print, eax
  683.         jmp     wait_for_keypress
  684.  
  685.  
  686. ; Error handling block for filesystem errors
  687. error_fs:
  688.        
  689.         cmp     eax, 12
  690.         jne     @f
  691.         mov     ebx, str_fs_err_12
  692.   @@:
  693.         cmp     eax, 11
  694.         jne     @f
  695.         mov     ebx, str_fs_err_11
  696.   @@:
  697.         cmp     eax, 10
  698.         jne     @f
  699.         mov     ebx, str_fs_err_10
  700.   @@:
  701.         cmp     eax, 9
  702.         jne     @f
  703.         mov     ebx, str_fs_err_9
  704.   @@:
  705.         cmp     eax, 8
  706.         jne     @f
  707.         mov     ebx, str_fs_err_8
  708.   @@:
  709.         cmp     eax, 7
  710.         jne     @f
  711.         mov     ebx, str_fs_err_7
  712.   @@:
  713.         cmp     eax, 6
  714.         jne     @f
  715.         mov     ebx, str_fs_err_6
  716.   @@:
  717.         cmp     eax, 5
  718.         jne     @f
  719.         mov     ebx, str_fs_err_5
  720.   @@:
  721.         cmp     eax, 3
  722.         jne     @f
  723.         mov     ebx, str_fs_err_3
  724.   @@:
  725.         cmp     eax, 2
  726.         jne     @f
  727.         mov     ebx, str_fs_err_2
  728.   @@:
  729.         mov     edi, fs_error_code
  730.         call    dword_ascii    ; convert error code in eax to ascii
  731.         icall   eax, interface_addr, interface.set_flags, 0x0c ; print errors in red
  732.         icall   eax, interface_addr, interface.print, str_err_fs, fs_error_code, ebx
  733.         mov     word[fs_error_code], '  '   ; clear error code for next time
  734.         icall   eax, interface_addr, interface.set_flags, 0x0a
  735.  
  736.         ret
  737.  
  738. error_heap:
  739.         icall   eax, interface_addr, interface.set_flags, 0x0c ; print errors in red
  740.         icall   eax, interface_addr, interface.print, str_err_heap
  741.        
  742. wait_for_keypress:
  743.         mcall   close, [controlsocket]
  744.         icall   eax, interface_addr, interface.set_flags, 0x07 ; reset color to grey
  745.         icall   eax, interface_addr, interface.print, str_push
  746.         ijmp    eax, interface_addr, interface.error
  747.  
  748. exit:
  749.         mcall   close, [controlsocket]
  750. exit2:  
  751.         mcall   -1
  752.  
  753.  
  754.  
  755. ; data
  756. str_title       db 'FTP client',0
  757. str_welcome     db 'FTP client for KolibriOS v0.12',10
  758.                 db 10,0
  759. str_srv_addr    db 'Please enter ftp server address.',10,0
  760.  
  761. str_prompt      db '> ',0
  762. str_resolve     db 'Resolving ',0
  763. str_newline     db 10,0
  764. str_err_resolve db 10,'Name resolution failed.',10,0
  765. str_err_socket  db 10,'[75,0 socket]: Error creating a socket',10,0
  766. str_err_bind    db 10,'[75,2 bind]: Error binding to socket',10,0
  767. str_err_listen  db 10,'[75,3 listen]: Cannot accept incoming connections',10,0
  768. str_err_accept  db 10,'[75,5 accept]: Error accepting a connection',10,0
  769. str_err_recv    db 10,'[75,7 recv]: Error receiving data from server',10,0
  770. str_err_heap    db 10,'Cannot allocate memory from heap.',10,0
  771. str_err_timeout db 10,'Timeout - no response from server.',10,0
  772. str_err_connect db 10,'[75,4 connect]: Cannot connect to the server.',10,0
  773. str_err_host    db 10,'Invalid hostname.',10,0
  774. str_err_params  db 10,'Invalid parameters',10,0
  775. str_err_fs      db 10,'File system error: code ',0
  776. fs_error_code   db '  ',0    ; file system error code
  777. str_fs_err_2    db ' [Function is not supported for the given file system]',10,0
  778. str_fs_err_3    db ' [Unknown file system]',10,0
  779. str_fs_err_5    db ' [File/Folder not found]',10,0
  780. str_fs_err_6    db ' [End of file, EOF]',10,0
  781. str_fs_err_7    db ' [Pointer lies outside of application memory]',10,0
  782. str_fs_err_8    db ' [Disk is full]',10,0
  783. str_fs_err_9    db ' [File system error]',10,0
  784. str_fs_err_10   db ' [Access denied]',10,0
  785. str_fs_err_11   db ' [Device error]',10,0
  786. str_fs_err_12   db ' [File system requires more memory]',10,0
  787. str8            db ' (',0
  788. str9            db ')',10,0
  789. str_push        db 'Push any key to continue.',0
  790. str_connect     db 'Connecting...',10,0
  791. str_waiting     db 'Waiting for welcome message.',10,0
  792. str_user        db "username: ",0
  793. str_pass        db "password: ",0
  794. str_port        db "port (default 21): ",0
  795. str_path        db "path (optional): ",0
  796. str_unknown     db "Unknown command or insufficient parameters - type help for more information.",10,0
  797. str_lcwd        db "Local working directory is now: ",0
  798. str_bytes_done  db '          ',0
  799. str_downloaded  db 'Downloaded ',0
  800. str_bytes       db ' bytes',13,0
  801. str_args_err    db 'Invalid arguments. USAGE: ftpc [-cli] [ftp://username:password@server:port/path]',10,0
  802.  
  803. str_open        db "opening data socket",10,0
  804. str_close       db 10,"closing data socket",10,0
  805. str_dot         db '.',0
  806.  
  807. str_help        db "available commands:",10
  808.                 db 10
  809.                 db "bye             - close the connection",10
  810.                 db "cdup            - change to parent of current directory on the server",10
  811.                 db "cwd <directory> - change working directoy on the server",10
  812.                 db "dele <file>     - delete file from the server",10
  813.                 db "list            - list files and folders in current server directory",10
  814.                 db "lcwd <path>     - change local working directory",10
  815.                 db "mkd <directory> - make directory on the server",10
  816.                 db "pwd             - print server working directory",10
  817.                 db "retr <file>     - retreive file from the server",10
  818.                 db "rmd <directory> - remove directory from the server",10
  819.                 db "stor <file>     - store file on the server",10
  820.                 db "rdir            - retreive all files from current server dir",10
  821.                 db 10,0
  822.  
  823. str_ini         db '.ini', 0
  824. str_active      db 'active', 0
  825. str_port_start  db 'port_start', 0
  826. str_port_stop   db 'port_stop', 0
  827. str_ip          db 'ip', 0
  828. str_dir         db 'dir', 0
  829. str_general     db 'general', 0
  830. str_logfile     db 'logfile',0
  831. str_no_logging  db 'Error writing to log file. Logging disabled',0
  832.  
  833. queued          dd 0
  834. mode            db 0    ; passive = 0, active = 1
  835.  
  836.  
  837. ; FTP strings
  838.  
  839. str_PASV        db 'PASV',13,10
  840. .length = $ - str_PASV
  841.  
  842. sockaddr1:
  843.         dw AF_INET4
  844. .port   dw ?
  845. .ip     dd ?
  846.         rb 10
  847.  
  848. sockaddr2:
  849.         dw AF_INET4
  850. .port   dw ?
  851. .ip     dd ?
  852.         rb 10
  853.  
  854. struc interface
  855. {
  856.     .init           dd 0
  857.     .server_addr    dd 4
  858.     .get_username   dd 8
  859.     .get_cmd        dd 12
  860.     .print          dd 16
  861.     .set_flags      dd 20
  862.     .list           dd 24
  863.     .progress       dd 28
  864.     .error          dd 32
  865. }
  866. interface interface
  867.  
  868. ; import
  869. align 4
  870. @IMPORT:
  871.  
  872. library network, 'network.obj', libini, 'libini.obj'
  873.  
  874. import  network, \
  875.         getaddrinfo,    'getaddrinfo', \
  876.         freeaddrinfo,   'freeaddrinfo', \
  877.         inet_ntoa,      'inet_ntoa'
  878.  
  879. import  libini, \
  880.         ini.get_str,    'ini_get_str', \
  881.         ini.get_int,    'ini_get_int'
  882.  
  883.  
  884. i_end:
  885.  
  886. ; uninitialised data
  887.  
  888. interface_addr  rd 1
  889.  
  890. status          db ?
  891.  
  892. file_size       dd ?
  893.  
  894. controlsocket   dd ?
  895. datasocket      dd ?
  896. offset          dd ?
  897. size            dd ?
  898. operation       dd ?
  899. timeout         dd ?
  900.  
  901. ptr_fname       dd ?
  902. size_fname      dd ?
  903. ptr_queue       dd ?
  904.  
  905. acti_port_start dw ?
  906. acti_port_stop  dw ?
  907. acti_port       dw ?
  908.  
  909. str_active_ip   rb 16
  910.  
  911. filestruct:
  912.   .subfn        dd ?
  913.   .offset       dd ?
  914.                 dd ?
  915.   .size         dd ?
  916.   .ptr          dd ?
  917.   .name         rb 1024
  918.  
  919. filestruct2:
  920.   .subfn        dd ?
  921.   .offset       dd ?
  922.                 dd 0
  923.   .size         dd ?
  924.   .ptr          dd ?
  925.                 db 0
  926.   .name         dd ?
  927.  
  928. folder_buf      rb 40
  929.  
  930.  
  931. buf_buffer1     rb BUFFERSIZE+1
  932. buf_buffer2     rb BUFFERSIZE+1
  933. buf_cmd         rb 1024                 ; buffer for holding command string
  934. log_file        rb 512 ; holds log file path
  935. logfile_offset  rd 1
  936.  
  937. path            rb 1024
  938.  
  939. initial_login   rb 1
  940. param_user      rb 1024
  941. param_password  rb 1024
  942. param_server_addr rb 1024
  943. param_path      rb 1024
  944. param_port      rb 6
  945.  
  946. sc system_colors
  947. rb 1024
  948.  
  949. mem:
  950.