Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2013. 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. ;;                                                                 ;;
  10. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  11. ;;             Version 2, June 1991                                ;;
  12. ;;                                                                 ;;
  13. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  14.  
  15. format binary as ""
  16.  
  17. BUFFERSIZE              = 4096
  18.  
  19. STATUS_CONNECTING       = 0
  20. STATUS_CONNECTED        = 1
  21. STATUS_NEEDPASSWORD     = 2
  22. STATUS_LOGGED_IN        = 3
  23.  
  24. OPERATION_LIST          = 0
  25. OPERATION_RETR          = 1
  26. OPERATION_STOR          = 2
  27.  
  28. use32
  29. ; standard header
  30.         db      'MENUET01'      ; signature
  31.         dd      1               ; header version
  32.         dd      start           ; entry point
  33.         dd      i_end           ; initialized size
  34.         dd      mem+0x1000      ; required memory
  35.         dd      mem+0x1000      ; stack pointer
  36.         dd      s               ; parameters
  37.         dd      0               ; path
  38.  
  39. include '../../macros.inc'
  40. purge mov,add,sub
  41. include '../../proc32.inc'
  42. include '../../dll.inc'
  43. include '../../network.inc'
  44.  
  45. include 'usercommands.inc'
  46. include 'servercommands.inc'
  47.  
  48. start:
  49. ; disable all events
  50.         mcall   40, 0
  51. ; load libraries
  52.         stdcall dll.Load, @IMPORT
  53.         test    eax, eax
  54.         jnz     exit
  55. ; initialize console
  56.         invoke  con_start, 1
  57.         invoke  con_init, 80, 25, 80, 250, str_title
  58. ; Check for parameters, if there are some, resolve the address right away
  59.         cmp     byte [s], 0
  60.         jne     resolve
  61.  
  62. main:
  63. ; Clear screen
  64.         invoke  con_cls
  65. ; Welcome user
  66.         invoke  con_write_asciiz, str_welcome
  67. ; write prompt (in green color)
  68.         invoke  con_set_flags, 0x0a
  69.         invoke  con_write_asciiz, str_prompt
  70. ; read string
  71.         invoke  con_gets, s, 256
  72. ; check for exit
  73.         test    eax, eax
  74.         jz      done
  75.         cmp     byte [s], 10
  76.         jz      done
  77. ; reset color back to grey and print newline
  78.         invoke  con_set_flags, 0x07
  79.         invoke  con_write_asciiz, str_newline
  80.  
  81. resolve:
  82. ; delete terminating '\n'
  83.         mov     esi, s
  84.   @@:
  85.         lodsb
  86.         cmp     al, 0x20
  87.         ja      @r
  88.         mov     byte [esi-1], 0
  89. ; Say to the user that we're resolving
  90.         invoke  con_write_asciiz, str_resolve
  91.         invoke  con_write_asciiz, s
  92. ; resolve name
  93.         push    esp     ; reserve stack place
  94.         invoke  getaddrinfo, s, 0, 0, esp
  95.         pop     esi
  96. ; test for error
  97.         test    eax, eax
  98.         jnz     error_resolve
  99. ; write results
  100.         invoke  con_write_asciiz, str8          ; ' (',0
  101.         mov     eax, [esi+addrinfo.ai_addr]     ; convert IP address to decimal notation
  102.         mov     eax, [eax+sockaddr_in.sin_addr] ;
  103.         mov     [sockaddr1.ip], eax             ;
  104.         invoke  inet_ntoa, eax                  ;
  105.         invoke  con_write_asciiz, eax           ; print ip
  106.         invoke  freeaddrinfo, esi               ; free allocated memory
  107.         invoke  con_write_asciiz, str9          ; ')',10,0
  108. ; open the socket
  109.         mcall   socket, AF_INET4, SOCK_STREAM, 0
  110.         cmp     eax, -1
  111.         je      error_socket
  112.         mov     [socketnum], eax
  113. ; connect to the server
  114.         invoke  con_write_asciiz, str_connect
  115.         mcall   connect, [socketnum], sockaddr1, 18
  116.         mov     [status], STATUS_CONNECTING
  117. ; Tell the user we're waiting for the server now.
  118.         invoke  con_write_asciiz, str_waiting
  119.  
  120. ; Reset 'offset' variable, it's used by the data receiver
  121.         mov     [offset], 0
  122.  
  123. wait_for_servercommand:
  124. ; Any commands still in our buffer?
  125.         cmp     [offset], 0
  126.         je      .receive                        ; nope, receive some more
  127.         mov     esi, [offset]
  128.         mov     edi, s
  129.         mov     ecx, [size]
  130.         add     ecx, esi
  131.         jmp     .byteloop
  132.  
  133. ; receive socket data
  134.   .receive:
  135.         mcall   recv, [socketnum], buffer_ptr, BUFFERSIZE, 0
  136.         inc     eax
  137.         jz      error_socket
  138.         dec     eax
  139.         jz      wait_for_servercommand
  140.  
  141.         mov     [offset], 0
  142.  
  143. ; extract commands, copy them to "s" buffer
  144.         lea     ecx, [eax + buffer_ptr]         ; ecx = end pointer
  145.         mov     esi, buffer_ptr                 ; esi = current pointer
  146.         mov     edi, s
  147.   .byteloop:
  148.         cmp     esi, ecx
  149.         jae     wait_for_servercommand
  150.         lodsb
  151.         cmp     al, 10                          ; excellent, we might have a command
  152.         je      .got_command
  153.         cmp     al, 13                          ; just ignore this byte
  154.         je      .byteloop
  155.         stosb
  156.         jmp     .byteloop
  157.   .got_command:                                 ; we have a newline check if its a command
  158.         cmp     esi, ecx
  159.         je      .no_more_data
  160.         mov     [offset], esi
  161.         sub     ecx, esi
  162.         mov     [size], ecx
  163.         jmp     .go_cmd
  164.   .no_more_data:
  165.         mov     [offset], 0
  166.   .go_cmd:
  167.         lea     ecx, [edi - s]                  ; length of command
  168.         xor     al, al
  169.         stosb
  170.  
  171.         invoke  con_set_flags, 0x03             ; change color
  172.         invoke  con_write_asciiz, s             ; print servercommand
  173.         invoke  con_write_asciiz, str_newline
  174.         invoke  con_set_flags, 0x07             ; reset color
  175.  
  176.         jmp     server_parser                   ; parse command
  177.  
  178.  
  179.  
  180. wait_for_usercommand:
  181.  
  182. ; change color to green for user input
  183.         invoke  con_set_flags, 0x0a
  184.  
  185. ; If we are not yet connected, request username/password
  186.         cmp     [status], STATUS_CONNECTED
  187.         je      .connected
  188.  
  189.         cmp     [status], STATUS_NEEDPASSWORD
  190.         je      .needpass
  191.  
  192. ; write prompt
  193.         invoke  con_write_asciiz, str_prompt
  194. ; read string
  195.         invoke  con_gets, s, 256
  196.  
  197. ; print a newline and reset the color back to grey
  198.         invoke  con_write_asciiz, str_newline
  199.         invoke  con_set_flags, 0x07
  200.  
  201.         cmp     dword[s], "cwd "
  202.         je      cmd_cwd
  203.  
  204.         cmp     dword[s], "mkd "
  205.         je      cmd_mkd
  206.  
  207.         cmp     dword[s], "rmd "
  208.         je      cmd_rmd
  209.  
  210.         cmp     dword[s], "pwd" + 10 shl 24
  211.         je      cmd_pwd
  212.  
  213.         cmp     dword[s], "bye" + 10 shl 24
  214.         je      cmd_bye
  215.  
  216.         cmp     byte[s+4], " "
  217.         jne     @f
  218.  
  219.         cmp     dword[s], "lcwd"
  220.         je      cmd_lcwd
  221.  
  222.         cmp     dword[s], "retr"
  223.         je      cmd_retr
  224.  
  225.         cmp     dword[s], "stor"
  226.         je      cmd_stor
  227.  
  228.         cmp     dword[s], "dele"
  229.         je      cmd_dele
  230.  
  231.   @@:
  232.         cmp     byte[s+4], 10
  233.         jne     @f
  234.  
  235.         cmp     dword[s], "list"
  236.         je      cmd_list
  237.  
  238.         cmp     dword[s], "help"
  239.         je      cmd_help
  240.  
  241.         cmp     dword[s], "cdup"
  242.         je      cmd_cdup
  243.  
  244.   @@:
  245. ; Uh oh.. unknown command, tell the user and wait for new input
  246.         invoke  con_write_asciiz, str_unknown
  247.         jmp     wait_for_usercommand
  248.  
  249.  
  250.   .connected:
  251. ; request username
  252.         invoke  con_write_asciiz, str_user
  253.         mov     dword[s], "USER"
  254.         mov     byte[s+4], " "
  255.         jmp     .send
  256.  
  257.  
  258.   .needpass:
  259. ; request password
  260.         invoke  con_write_asciiz, str_pass
  261.         mov     dword[s], "PASS"
  262.         mov     byte[s+4], " "
  263.         invoke  con_set_flags, 0x00     ; black text on black background for password
  264.  
  265.   .send:
  266. ; read string
  267.         mov     esi, s+5
  268.         invoke  con_gets, esi, 256
  269.  
  270. ; find end of string
  271.         mov     edi, s+5
  272.         mov     ecx, 256
  273.         xor     al, al
  274.         repne   scasb
  275.         lea     esi, [edi-s]
  276.         mov     word[edi-2], 0x0a0d
  277. ; and send it to the server
  278.         mcall   send, [socketnum], s, , 0
  279.  
  280.         invoke  con_write_asciiz, str_newline
  281.         invoke  con_set_flags, 0x07     ; reset color
  282.         jmp     wait_for_servercommand
  283.  
  284.  
  285.  
  286. open_dataconnection:                    ; only passive for now..
  287.         cmp     [status], STATUS_LOGGED_IN
  288.         jne     .fail
  289.  
  290.         mov     dword[s], "PASV"
  291.         mov     word[s+4], 0x0a0d
  292.         mcall   send, [socketnum], s, 6, 0
  293.         ret
  294.  
  295.   .fail:
  296.         invoke  con_get_flags
  297.         push    eax
  298.         invoke  con_set_flags, 0x0c                     ; print errors in red
  299.         invoke  con_write_asciiz, str_err_socket
  300.         invoke  con_set_flags                           ; reset color
  301.         ret
  302.  
  303.  
  304.  
  305. error_socket:
  306.         invoke  con_set_flags, 0x0c                     ; print errors in red
  307.         invoke  con_write_asciiz, str_err_socket
  308.         jmp     wait_for_keypress
  309.  
  310. error_resolve:
  311.         invoke  con_set_flags, 0x0c                     ; print errors in red
  312.         invoke  con_write_asciiz, str_err_resolve
  313.  
  314. wait_for_keypress:
  315.         invoke  con_set_flags, 0x07                     ; reset color to grey
  316.         invoke  con_write_asciiz, str_push
  317.         invoke  con_getch2
  318.         mcall   close, [socketnum]
  319.         jmp     main
  320.  
  321. done:
  322.         invoke  con_exit, 1
  323.  
  324. exit:
  325.         mcall   close, [socketnum]
  326.         mcall   -1
  327.  
  328.  
  329.  
  330. ; data
  331. str_title       db 'FTP client',0
  332. str_welcome     db 'FTP client for KolibriOS v0.09',10
  333.                 db 10
  334.                 db 'Please enter ftp server address.',10,0
  335.  
  336. str_prompt      db '> ',0
  337. str_resolve     db 'Resolving ',0
  338. str_newline     db 10,0
  339. str_err_resolve db 10,'Name resolution failed.',10,0
  340. str_err_socket  db 10,'Socket error.',10,0
  341. str8            db ' (',0
  342. str9            db ')',10,0
  343. str_push        db 'Push any key to continue.',0
  344. str_connect     db 'Connecting...',10,0
  345. str_waiting     db 'Waiting for welcome message.',10,0
  346. str_user        db "username: ",0
  347. str_pass        db "password: ",0
  348. str_unknown     db "Unknown command or insufficient parameters - type help for more information.",10,0
  349. str_lcwd        db "Local working directory is now: ",0
  350.  
  351. str_open        db "opening data socket",10,0
  352.  
  353. str_help        db "available commands:",10
  354.                 db 10
  355.                 db "bye             - close the connection",10
  356.                 db "cdup            - change to parent of current directory on the server",10
  357.                 db "cwd <directory> - change working directoy on the server",10
  358.                 db "dele <file>     - delete file from the server",10
  359.                 db "list            - list files and folders in current server directory",10
  360.                 db "lcwd <path>     - change local working directory",10
  361.                 db "mkd <directory> - make directory on the server",10
  362.                 db "pwd             - print server working directory",10
  363.                 db "retr <file>     - retreive file from the server",10
  364.                 db "rmd <directory> - remove directory from the server",10
  365.                 db "stor <file>     - store file on the server",10
  366.                 db 10,0
  367.  
  368. sockaddr1:
  369.         dw AF_INET4
  370. .port   dw 0x1500       ; 21
  371. .ip     dd 0
  372.         rb 10
  373.  
  374. sockaddr2:
  375.         dw AF_INET4
  376. .port   dw 0
  377. .ip     dd 0
  378.         rb 10
  379.  
  380. ; import
  381. align 4
  382. @IMPORT:
  383.  
  384. library network, 'network.obj', console, 'console.obj'
  385.  
  386. import  network,        \
  387.         getaddrinfo,    'getaddrinfo',  \
  388.         freeaddrinfo,   'freeaddrinfo', \
  389.         inet_ntoa,      'inet_ntoa'
  390.  
  391. import  console,        \
  392.         con_start,      'START',        \
  393.         con_init,       'con_init',     \
  394.         con_write_asciiz,'con_write_asciiz',     \
  395.         con_exit,       'con_exit',     \
  396.         con_gets,       'con_gets',\
  397.         con_cls,        'con_cls',\
  398.         con_getch2,     'con_getch2',\
  399.         con_set_cursor_pos, 'con_set_cursor_pos',\
  400.         con_write_string, 'con_write_string',\
  401.         con_get_flags,  'con_get_flags', \
  402.         con_set_flags,  'con_set_flags'
  403.  
  404.  
  405. i_end:
  406.  
  407. ; uninitialised data
  408.  
  409. status          db ?
  410. active_passive  db ?
  411.  
  412. socketnum       dd ?
  413. datasocket      dd ?
  414. offset          dd ?
  415. size            dd ?
  416. operation       dd ?
  417.  
  418. filestruct:
  419. .subfn  dd ?
  420. .offset dd ?
  421.         dd ?
  422. .size   dd ?
  423. .ptr    dd ?
  424. .name   rb 1024
  425.  
  426. buffer_ptr      rb BUFFERSIZE+1
  427. buffer_ptr2     rb BUFFERSIZE+1
  428.  
  429. s               rb 1024
  430.  
  431. mem:
  432.