Advertisement
Guest User

Untitled

a guest
Mar 16th, 2016
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.23 KB | None | 0 0
  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;; ;;
  3. ;; Copyright (C) KolibriOS team 2013-2014. 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. TIMEOUT = 3 ; seconds
  18.  
  19. BUFFERSIZE = 4096
  20.  
  21. STATUS_CONNECTING = 0
  22. STATUS_CONNECTED = 1
  23. STATUS_NEEDPASSWORD = 2
  24. STATUS_LOGGED_IN = 3
  25.  
  26. OPERATION_NONE = 0
  27. OPERATION_LIST = 1
  28. OPERATION_RETR = 2
  29. OPERATION_STOR = 3
  30. OPERATION_RDIR = 4
  31.  
  32. use32
  33. ; standard header
  34. db 'MENUET01' ; signature
  35. dd 1 ; header version
  36. dd start ; entry point
  37. dd i_end ; initialized size
  38. dd mem+0x1000 ; required memory
  39. dd mem+0x1000 ; stack pointer
  40. dd buf_cmd ; parameters
  41. dd path ; path
  42.  
  43. include '../../macros.inc'
  44. purge mov,add,sub
  45. include '../../proc32.inc'
  46. include '../../dll.inc'
  47. include '../../network.inc'
  48.  
  49. include 'usercommands.inc'
  50. include 'servercommands.inc'
  51.  
  52. start:
  53. ; initialize heap for using dynamic blocks
  54. mcall 68,11
  55. test eax,eax
  56. je exit2
  57.  
  58. ; disable all events except network event
  59. mcall 40, EV_STACK
  60. ; load libraries
  61. stdcall dll.Load, @IMPORT
  62. test eax, eax
  63. jnz exit
  64. ; initialize console
  65. invoke con_start, 1
  66. invoke con_init, 80, 25, 80, 250, str_title
  67. ; find path to main settings file (ftpc.ini)
  68. mov edi, path ; Calculate the length of zero-terminated string
  69. xor al, al
  70. mov ecx, 1024
  71. repne scasb
  72. dec edi
  73. mov esi, str_ini ; append it with '.ini', 0
  74. movsd
  75. movsb
  76. ; get settings from ini
  77. invoke ini.get_str, path, str_active, str_ip, str_active_ip, 16, 0
  78. mov esi, str_active_ip
  79. .ip_loop:
  80. lodsb
  81. test al, al
  82. jz .ip_ok
  83. cmp al, ' '
  84. je .ip_ok
  85. cmp al, '.'
  86. jne .ip_loop
  87. mov byte[esi-1], ','
  88. jmp .ip_loop
  89. .ip_ok:
  90. mov byte[esi-1], 0
  91.  
  92. invoke ini.get_int, path, str_active, str_port_start, 64000
  93. mov [acti_port_start], ax
  94.  
  95. invoke ini.get_int, path, str_active, str_port_stop, 65000
  96. mov [acti_port_stop], ax
  97.  
  98. invoke ini.get_str, path, str_general, str_dir, buf_buffer1, BUFFERSIZE, 0
  99. mcall 30, 1, buf_buffer1 ; set working directory
  100.  
  101. ; Check for parameters, if there are some, resolve the address right away
  102. ; TODO: parse ftp://user:password@server.com:port/folder/subfolder type urls.
  103. cmp byte [buf_cmd], 0
  104. jne resolve
  105.  
  106. main:
  107. ; Clear screen
  108. invoke con_cls
  109. ; Welcome user
  110. invoke con_write_asciiz, str_welcome
  111. ; write prompt (in green color)
  112. invoke con_set_flags, 0x0a
  113. invoke con_write_asciiz, str_prompt
  114. ; read string
  115. invoke con_gets, buf_cmd, 256
  116. ; check for exit
  117. test eax, eax
  118. jz done
  119. cmp byte [buf_cmd], 10
  120. jz done
  121. ; reset color back to grey and print newline
  122. invoke con_set_flags, 0x07
  123. invoke con_write_asciiz, str_newline
  124.  
  125. resolve:
  126. mov [sockaddr1.port], 21 shl 8
  127.  
  128. ; delete terminating '\n'
  129. mov esi, buf_cmd
  130. @@:
  131. lodsb
  132. cmp al, ':'
  133. je .do_port
  134. cmp al, 0x20
  135. ja @r
  136. mov byte [esi-1], 0
  137. jmp .done
  138.  
  139. .do_port:
  140. xor eax, eax
  141. xor ebx, ebx
  142. mov byte [esi-1], 0
  143. .portloop:
  144. lodsb
  145. cmp al, 0x20
  146. jbe .port_done
  147. sub al, '0'
  148. jb error_hostname
  149. cmp al, 9
  150. ja error_hostname
  151. lea ebx, [ebx*4 + ebx]
  152. shl ebx, 1
  153. add ebx, eax
  154. jmp .portloop
  155.  
  156. .port_done:
  157. xchg bl, bh
  158. mov [sockaddr1.port], bx
  159.  
  160. .done:
  161. ; Say to the user that we're resolving
  162. invoke con_write_asciiz, str_resolve
  163. invoke con_write_asciiz, buf_cmd
  164. ; resolve name
  165. push esp ; reserve stack place
  166. invoke getaddrinfo, buf_cmd, 0, 0, esp
  167. pop esi
  168. ; test for error
  169. test eax, eax
  170. jnz error_resolve
  171. ; write results
  172. invoke con_write_asciiz, str8 ; ' (',0
  173. mov eax, [esi+addrinfo.ai_addr] ; convert IP address to decimal notation
  174. mov eax, [eax+sockaddr_in.sin_addr] ;
  175. mov [sockaddr1.ip], eax ;
  176. invoke inet_ntoa, eax ;
  177. invoke con_write_asciiz, eax ; print ip
  178. invoke freeaddrinfo, esi ; free allocated memory
  179. invoke con_write_asciiz, str9 ; ')',10,0
  180. ; open the socket
  181. mcall socket, AF_INET4, SOCK_STREAM, 0
  182. cmp eax, -1
  183. je error_socket
  184. mov [controlsocket], eax
  185. ; connect to the server
  186. invoke con_write_asciiz, str_connect
  187. mcall connect, [controlsocket], sockaddr1, 18
  188. cmp eax, -1
  189. je error_connect
  190. mov [status], STATUS_CONNECTING
  191. ; Tell the user we're waiting for the server now.
  192. invoke con_write_asciiz, str_waiting
  193.  
  194. ; Reset 'offset' variable, it's used by the data receiver
  195. mov [offset], 0
  196.  
  197. wait_for_servercommand:
  198. ; Any commands still in our buffer?
  199. cmp [offset], 0
  200. je .receive ; nope, receive some more
  201. mov esi, [offset]
  202. mov edi, buf_cmd
  203. mov ecx, [size]
  204. add ecx, esi
  205. jmp .byteloop
  206.  
  207. ; receive socket data
  208. .receive:
  209. mcall 26, 9
  210. add eax, TIMEOUT*100
  211. mov [timeout], eax
  212. .receive_loop:
  213. mcall 23, 50 ; Wait for event with timeout
  214. mcall 26, 9
  215. cmp eax, [timeout]
  216. jge error_timeout
  217. mcall recv, [controlsocket], buf_buffer1, BUFFERSIZE, MSG_DONTWAIT
  218. test eax, eax
  219. jnz .got_data
  220. cmp ebx, EWOULDBLOCK
  221. jne error_socket
  222. jmp .receive_loop
  223.  
  224. .got_data:
  225. mov [offset], 0
  226.  
  227. ; extract commands, copy them to "buf_cmd" buffer
  228. lea ecx, [eax + buf_buffer1] ; ecx = end pointer
  229. mov esi, buf_buffer1 ; esi = current pointer
  230. mov edi, buf_cmd
  231. .byteloop:
  232. cmp esi, ecx
  233. jae wait_for_servercommand
  234. lodsb
  235. cmp al, 10 ; excellent, we might have a command
  236. je .got_command
  237. cmp al, 13 ; just ignore this byte
  238. je .byteloop
  239. stosb
  240. jmp .byteloop
  241. .got_command: ; we have a newline check if its a command
  242. cmp esi, ecx
  243. je .no_more_data
  244. mov [offset], esi
  245. sub ecx, esi
  246. mov [size], ecx
  247. jmp .go_cmd
  248. .no_more_data:
  249. mov [offset], 0
  250. .go_cmd:
  251. lea ecx, [edi - buf_cmd] ; length of command
  252. xor al, al
  253. stosb
  254.  
  255. invoke con_set_flags, 0x03 ; change color
  256. invoke con_write_asciiz, buf_cmd ; print servercommand
  257. invoke con_write_asciiz, str_newline
  258. invoke con_set_flags, 0x07 ; reset color
  259.  
  260. jmp server_parser ; parse command
  261.  
  262.  
  263.  
  264. wait_for_usercommand:
  265.  
  266. ; Are there any files in the transfer queue?
  267.  
  268. cmp [queued], 0
  269. ja transfer_queued ; Yes, transfer those first.
  270.  
  271. ; change color to green for user input
  272. invoke con_set_flags, 0x0a
  273.  
  274. ; If we are not yet connected, request username/password
  275. cmp [status], STATUS_CONNECTED
  276. je .connected
  277.  
  278. cmp [status], STATUS_NEEDPASSWORD
  279. je .needpass
  280.  
  281. ; write prompt
  282. invoke con_write_asciiz, str_prompt
  283. ; read string
  284. invoke con_gets, buf_cmd, 256
  285.  
  286. ; print a newline and reset the color back to grey
  287. invoke con_write_asciiz, str_newline
  288. invoke con_set_flags, 0x07
  289.  
  290. cmp dword[buf_cmd], "cwd "
  291. je cmd_cwd
  292.  
  293. cmp dword[buf_cmd], "mkd "
  294. je cmd_mkd
  295.  
  296. cmp dword[buf_cmd], "rmd "
  297. je cmd_rmd
  298.  
  299. cmp dword[buf_cmd], "pwd" + 10 shl 24
  300. je cmd_pwd
  301.  
  302. cmp dword[buf_cmd], "bye" + 10 shl 24
  303. je cmd_bye
  304.  
  305. cmp dword[buf_cmd], "rdir"
  306. je cmd_rdir
  307.  
  308. cmp byte[buf_cmd+4], " "
  309. jne @f
  310.  
  311. cmp dword[buf_cmd], "lcwd"
  312. je cmd_lcwd
  313.  
  314. cmp dword[buf_cmd], "retr"
  315. je cmd_retr
  316.  
  317. cmp dword[buf_cmd], "stor"
  318. je cmd_stor
  319.  
  320. cmp dword[buf_cmd], "dele"
  321. je cmd_dele
  322.  
  323. @@:
  324. cmp byte[buf_cmd+4], 10
  325. jne @f
  326.  
  327. cmp dword[buf_cmd], "list"
  328. je cmd_list
  329.  
  330. cmp dword[buf_cmd], "help"
  331. je cmd_help
  332.  
  333. cmp dword[buf_cmd], "cdup"
  334. je cmd_cdup
  335.  
  336. @@:
  337. ; Uh oh.. unknown command, tell the user and wait for new input
  338. invoke con_write_asciiz, str_unknown
  339. jmp wait_for_usercommand
  340.  
  341.  
  342. .connected:
  343. ; request username
  344. invoke con_write_asciiz, str_user
  345. mov dword[buf_cmd], "USER"
  346. mov byte[buf_cmd+4], " "
  347. jmp .send
  348.  
  349.  
  350. .needpass:
  351. ; request password
  352. invoke con_write_asciiz, str_pass
  353. mov dword[buf_cmd], "PASS"
  354. mov byte[buf_cmd+4], " "
  355. invoke con_set_flags, 0x00 ; black text on black background for password
  356.  
  357. .send:
  358. ; read string
  359. mov esi, buf_cmd+5
  360. invoke con_gets, esi, 256
  361.  
  362. ; find end of string
  363. mov edi, buf_cmd+5
  364. mov ecx, 256
  365. xor al, al
  366. repne scasb
  367. lea esi, [edi-buf_cmd]
  368. mov word[edi-2], 0x0a0d
  369. ; and send it to the server
  370. mcall send, [controlsocket], buf_cmd, , 0
  371.  
  372. invoke con_write_asciiz, str_newline
  373. invoke con_set_flags, 0x07 ; reset color
  374. jmp wait_for_servercommand
  375.  
  376.  
  377.  
  378. ; files for rdir operation are queued
  379. transfer_queued:
  380.  
  381. mov esi, [ptr_queue] ; always pointing to current part of ptr_fname_start
  382. mov edi, buf_cmd+5 ; always point to filename for retr command
  383. .build_filename:
  384. lodsb
  385. stosb
  386. cmp al, 10
  387. je .get_file ; filename ends with character 10
  388. test al, al
  389. jnz .build_filename
  390.  
  391. ; Error occured, we reached the end of the buffer before [queued] reached 0
  392. mov [queued], 0
  393. mcall 68, 13, [ptr_fname] ; free buffer
  394. test eax, eax
  395. jz error_heap
  396. jmp wait_for_usercommand
  397.  
  398. .get_file:
  399. mov byte[edi], 0 ; end filename with 0 byte
  400. mov [ptr_queue], esi
  401. dec [queued]
  402. jnz cmd_retr
  403.  
  404. mcall 68, 13, [ptr_fname] ; free buffer
  405. test eax, eax
  406. jz error_heap
  407. jmp cmd_retr
  408.  
  409.  
  410.  
  411. open_dataconnection:
  412.  
  413. test [mode], 1
  414. jnz .active
  415.  
  416. mcall send, [controlsocket], str_PASV, str_PASV.length, 0
  417. ret
  418.  
  419. .active:
  420. mcall socket, AF_INET4, SOCK_STREAM, 0
  421. cmp eax, -1
  422. je error_socket
  423. mov [datasocket], eax
  424.  
  425. mov ax, [acti_port_start]
  426. xchg al, ah
  427. mov [sockaddr2.port], ax
  428.  
  429. mcall bind, [datasocket], sockaddr2, 18
  430. cmp eax, -1
  431. je error_socket
  432.  
  433. mcall listen, [datasocket], 1
  434. cmp eax, -1
  435. je error_socket
  436.  
  437. mov dword[buf_buffer1], 'PORT'
  438. mov byte[buf_buffer1+4], ' '
  439. mov edi, buf_buffer1+5
  440. mov esi, str_active_ip
  441. .loop:
  442. lodsb
  443. test al, al
  444. jz .ip_ok
  445. stosb
  446. jmp .loop
  447. .ip_ok:
  448. mov al, ','
  449. stosb
  450. movzx eax, byte[sockaddr2.port+0]
  451. call dword_ascii
  452. mov al, ','
  453. stosb
  454. movzx eax, byte[sockaddr2.port+1]
  455. call dword_ascii
  456. mov ax, 0x0a0d
  457. stosw
  458. lea esi, [edi - buf_buffer1]
  459. mcall send, [controlsocket], buf_buffer1, , 0
  460.  
  461. mcall accept, [datasocket], sockaddr2, 18 ; time to accept the awaiting connection..
  462. cmp eax, -1
  463. je error_socket
  464. push eax
  465. mcall close, [datasocket]
  466. pop [datasocket]
  467.  
  468. mcall recv, [controlsocket], buf_buffer1, BUFFERSIZE, 0
  469.  
  470. ret
  471.  
  472. ; eax = input
  473. ; edi = ptr where to write
  474. dword_ascii:
  475.  
  476. push edx ebx ecx
  477. mov ebx, 10
  478. xor ecx, ecx
  479.  
  480. @@:
  481. xor edx, edx
  482. div ebx
  483. add edx, '0'
  484. push dx
  485. inc ecx
  486. test eax, eax
  487. jnz @r
  488.  
  489. @@:
  490. pop ax
  491. stosb
  492. dec ecx
  493. jnz @r
  494.  
  495. pop ecx ebx edx
  496. ret
  497.  
  498. error_hostname:
  499. invoke con_set_flags, 0x0c ; print errors in red
  500. invoke con_write_asciiz, str_err_host
  501. jmp wait_for_keypress
  502.  
  503. error_connect:
  504. invoke con_set_flags, 0x0c ; print errors in red
  505. invoke con_write_asciiz, str_err_connect
  506. jmp wait_for_keypress
  507.  
  508. error_timeout:
  509. invoke con_set_flags, 0x0c ; print errors in red
  510. invoke con_write_asciiz, str_err_timeout
  511. jmp wait_for_keypress
  512.  
  513. error_socket:
  514. invoke con_set_flags, 0x0c ; print errors in red
  515. invoke con_write_asciiz, str_err_socket
  516. jmp wait_for_keypress
  517.  
  518. error_resolve:
  519. invoke con_set_flags, 0x0c ; print errors in red
  520. invoke con_write_asciiz, str_err_resolve
  521. jmp wait_for_keypress
  522.  
  523. error_heap:
  524. invoke con_set_flags, 0x0c ; print errors in red
  525. invoke con_write_asciiz, str_err_heap
  526.  
  527. wait_for_keypress:
  528. invoke con_set_flags, 0x07 ; reset color to grey
  529. invoke con_write_asciiz, str_push
  530. invoke con_getch2
  531. mcall close, [controlsocket]
  532. jmp main
  533.  
  534. done:
  535. invoke con_exit, 1
  536.  
  537. exit:
  538. mcall close, [controlsocket]
  539. exit2:
  540. mcall -1
  541.  
  542.  
  543.  
  544. ; data
  545. str_title db 'FTP client',0
  546. str_welcome db 'FTP client for KolibriOS v0.12',10
  547. db 10
  548. db 'Please enter ftp server address.',10,0
  549.  
  550. str_prompt db '> ',0
  551. str_resolve db 'Resolving ',0
  552. str_newline db 10,0
  553. str_err_resolve db 10,'Name resolution failed.',10,0
  554. str_err_socket db 10,'Socket error.',10,0
  555. str_err_heap db 10,'Cannot allocate memory from heap.',10,0
  556. str_err_timeout db 10,'Timeout - no response from server.',10,0
  557. str_err_connect db 10,'Cannot connect to the server.',10,0
  558. str_err_host db 10,'Invalid hostname.',10,0
  559. str8 db ' (',0
  560. str9 db ')',10,0
  561. str_push db 'Push any key to continue.',0
  562. str_connect db 'Connecting...',10,0
  563. str_waiting db 'Waiting for welcome message.',10,0
  564. str_user db "username: ",0
  565. str_pass db "password: ",0
  566. str_unknown db "Unknown command or insufficient parameters - type help for more information.",10,0
  567. str_lcwd db "Local working directory is now: ",0
  568.  
  569. str_open db "opening data socket",10,0
  570. str_close db 10,"closing data socket",10,0
  571. str_dot db '.',0
  572.  
  573. str_help db "available commands:",10
  574. db 10
  575. db "bye - close the connection",10
  576. db "cdup - change to parent of current directory on the server",10
  577. db "cwd <directory> - change working directoy on the server",10
  578. db "dele <file> - delete file from the server",10
  579. db "list - list files and folders in current server directory",10
  580. db "lcwd <path> - change local working directory",10
  581. db "mkd <directory> - make directory on the server",10
  582. db "pwd - print server working directory",10
  583. db "retr <file> - retreive file from the server",10
  584. db "rmd <directory> - remove directory from the server",10
  585. db "stor <file> - store file on the server",10
  586. db "rdir - retreive all files from current server dir",10
  587. db 10,0
  588.  
  589. str_ini db '.ini', 0
  590. str_active db 'active', 0
  591. str_port_start db 'port_start', 0
  592. str_port_stop db 'port_stop', 0
  593. str_ip db 'ip', 0
  594. str_dir db 'dir', 0
  595. str_general db 'general', 0
  596.  
  597. queued dd 0
  598. mode db 0 ; passive = 0, active = 1
  599.  
  600. ; FTP strings
  601.  
  602. str_PASV db 'PASV',13,10
  603. .length = $ - str_PASV
  604.  
  605. sockaddr1:
  606. dw AF_INET4
  607. .port dw ?
  608. .ip dd ?
  609. rb 10
  610.  
  611. sockaddr2:
  612. dw AF_INET4
  613. .port dw ?
  614. .ip dd ?
  615. rb 10
  616.  
  617. ; import
  618. align 4
  619. @IMPORT:
  620.  
  621. library network, 'network.obj', console, 'console.obj', libini, 'libini.obj'
  622.  
  623. import network, \
  624. getaddrinfo, 'getaddrinfo', \
  625. freeaddrinfo, 'freeaddrinfo', \
  626. inet_ntoa, 'inet_ntoa'
  627.  
  628. import console, \
  629. con_start, 'START', \
  630. con_init, 'con_init', \
  631. con_write_asciiz,'con_write_asciiz', \
  632. con_exit, 'con_exit', \
  633. con_gets, 'con_gets',\
  634. con_cls, 'con_cls',\
  635. con_getch2, 'con_getch2',\
  636. con_set_cursor_pos, 'con_set_cursor_pos',\
  637. con_write_string, 'con_write_string',\
  638. con_get_flags, 'con_get_flags', \
  639. con_set_flags, 'con_set_flags'
  640.  
  641. import libini, \
  642. ini.get_str, 'ini_get_str',\
  643. ini.get_int, 'ini_get_int'
  644.  
  645.  
  646. i_end:
  647.  
  648. ; uninitialised data
  649.  
  650. status db ?
  651.  
  652. controlsocket dd ?
  653. datasocket dd ?
  654. offset dd ?
  655. size dd ?
  656. operation dd ?
  657. timeout dd ?
  658.  
  659. ptr_fname dd ?
  660. size_fname dd ?
  661. ptr_queue dd ?
  662.  
  663. acti_port_start dw ?
  664. acti_port_stop dw ?
  665. acti_port dw ?
  666.  
  667. str_active_ip rb 16
  668.  
  669. filestruct:
  670. .subfn dd ?
  671. .offset dd ?
  672. dd ?
  673. .size dd ?
  674. .ptr dd ?
  675. .name rb 1024
  676.  
  677. buf_buffer1 rb BUFFERSIZE+1
  678. buf_buffer2 rb BUFFERSIZE+1
  679. buf_cmd rb 1024 ; buffer for holding command string
  680.  
  681. path rb 1024
  682.  
  683. mem:
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement