Subversion Repositories Kolibri OS

Rev

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