Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3701 hidnplayr 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
 
3800 hidnplayr 17
BUFFERSIZE              = 4096
3701 hidnplayr 18
 
19
STATUS_CONNECTING       = 0
20
STATUS_CONNECTED        = 1
21
STATUS_NEEDPASSWORD     = 2
22
STATUS_LOGGED_IN        = 3
23
 
3800 hidnplayr 24
OPERATION_LIST          = 0
25
OPERATION_RETR          = 1
26
OPERATION_STOR          = 2
27
 
3701 hidnplayr 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:
3813 hidnplayr 49
; disable all events
3789 hidnplayr 50
        mcall   40, 0
3701 hidnplayr 51
; load libraries
52
        stdcall dll.Load, @IMPORT
53
        test    eax, eax
54
        jnz     exit
55
; initialize console
3789 hidnplayr 56
        invoke  con_start, 1
3813 hidnplayr 57
        invoke  con_init, 80, 25, 80, 250, str_title
58
; Check for parameters, if there are some, resolve the address right away
3701 hidnplayr 59
        cmp     byte [s], 0
60
        jne     resolve
61
 
62
main:
3813 hidnplayr 63
; Clear screen
3789 hidnplayr 64
        invoke  con_cls
3701 hidnplayr 65
; Welcome user
3813 hidnplayr 66
        invoke  con_write_asciiz, str_welcome
67
; write prompt (in green color)
3789 hidnplayr 68
        invoke  con_set_flags, 0x0a
3813 hidnplayr 69
        invoke  con_write_asciiz, str_prompt
3701 hidnplayr 70
; read string
3813 hidnplayr 71
        invoke  con_gets, s, 256
3701 hidnplayr 72
; check for exit
73
        test    eax, eax
74
        jz      done
3813 hidnplayr 75
        cmp     byte [s], 10
3701 hidnplayr 76
        jz      done
3813 hidnplayr 77
; reset color back to grey and print newline
78
        invoke  con_set_flags, 0x07
79
        invoke  con_write_asciiz, str_newline
3701 hidnplayr 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
3813 hidnplayr 89
; Say to the user that we're resolving
90
        invoke  con_write_asciiz, str_resolve
3789 hidnplayr 91
        invoke  con_write_asciiz, s
3701 hidnplayr 92
; resolve name
93
        push    esp     ; reserve stack place
3789 hidnplayr 94
        invoke  getaddrinfo, s, 0, 0, esp
3701 hidnplayr 95
        pop     esi
96
; test for error
97
        test    eax, eax
3813 hidnplayr 98
        jnz     error_resolve
3701 hidnplayr 99
; write results
3800 hidnplayr 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
3701 hidnplayr 109
        mcall   socket, AF_INET4, SOCK_STREAM, 0
110
        cmp     eax, -1
3813 hidnplayr 111
        je      error_socket
3701 hidnplayr 112
        mov     [socketnum], eax
3800 hidnplayr 113
; connect to the server
3813 hidnplayr 114
        invoke  con_write_asciiz, str_connect
3701 hidnplayr 115
        mcall   connect, [socketnum], sockaddr1, 18
116
        mov     [status], STATUS_CONNECTING
3813 hidnplayr 117
; Tell the user we're waiting for the server now.
118
        invoke  con_write_asciiz, str_waiting
3701 hidnplayr 119
 
3813 hidnplayr 120
; Reset 'offset' variable, it's used by the data receiver
3790 hidnplayr 121
        mov     [offset], 0
122
 
3789 hidnplayr 123
wait_for_servercommand:
3813 hidnplayr 124
; Any commands still in our buffer?
3790 hidnplayr 125
        cmp     [offset], 0
3813 hidnplayr 126
        je      .receive                        ; nope, receive some more
3790 hidnplayr 127
        mov     esi, [offset]
128
        mov     edi, s
129
        mov     ecx, [size]
130
        add     ecx, esi
131
        jmp     .byteloop
3701 hidnplayr 132
 
133
; receive socket data
3790 hidnplayr 134
  .receive:
3789 hidnplayr 135
        mcall   recv, [socketnum], buffer_ptr, BUFFERSIZE, 0
3701 hidnplayr 136
        inc     eax
3813 hidnplayr 137
        jz      error_socket
3701 hidnplayr 138
        dec     eax
3789 hidnplayr 139
        jz      wait_for_servercommand
3701 hidnplayr 140
 
3790 hidnplayr 141
        mov     [offset], 0
3789 hidnplayr 142
 
3701 hidnplayr 143
; extract commands, copy them to "s" buffer
3789 hidnplayr 144
        lea     ecx, [eax + buffer_ptr]         ; ecx = end pointer
3701 hidnplayr 145
        mov     esi, buffer_ptr                 ; esi = current pointer
146
        mov     edi, s
147
  .byteloop:
3789 hidnplayr 148
        cmp     esi, ecx
149
        jae     wait_for_servercommand
3701 hidnplayr 150
        lodsb
151
        cmp     al, 10                          ; excellent, we might have a command
152
        je      .got_command
3789 hidnplayr 153
        cmp     al, 13                          ; just ignore this byte
3701 hidnplayr 154
        je      .byteloop
155
        stosb
156
        jmp     .byteloop
3789 hidnplayr 157
  .got_command:                                 ; we have a newline check if its a command
3790 hidnplayr 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:
3818 hidnplayr 167
        lea     ecx, [edi - s]                  ; length of command
3701 hidnplayr 168
        xor     al, al
169
        stosb
170
 
3789 hidnplayr 171
        invoke  con_set_flags, 0x03             ; change color
172
        invoke  con_write_asciiz, s             ; print servercommand
3813 hidnplayr 173
        invoke  con_write_asciiz, str_newline
3800 hidnplayr 174
        invoke  con_set_flags, 0x07             ; reset color
3701 hidnplayr 175
 
3789 hidnplayr 176
        jmp     server_parser                   ; parse command
3701 hidnplayr 177
 
3813 hidnplayr 178
 
179
 
3789 hidnplayr 180
wait_for_usercommand:
3701 hidnplayr 181
 
3813 hidnplayr 182
; change color to green for user input
3789 hidnplayr 183
        invoke  con_set_flags, 0x0a
3701 hidnplayr 184
 
3813 hidnplayr 185
; If we are not yet connected, request username/password
3701 hidnplayr 186
        cmp     [status], STATUS_CONNECTED
187
        je      .connected
188
 
189
        cmp     [status], STATUS_NEEDPASSWORD
190
        je      .needpass
191
 
192
; write prompt
3813 hidnplayr 193
        invoke  con_write_asciiz, str_prompt
3701 hidnplayr 194
; read string
3813 hidnplayr 195
        invoke  con_gets, s, 256
3794 hidnplayr 196
 
3813 hidnplayr 197
; print a newline and reset the color back to grey
198
        invoke  con_write_asciiz, str_newline
3789 hidnplayr 199
        invoke  con_set_flags, 0x07
3701 hidnplayr 200
 
3790 hidnplayr 201
        cmp     dword[s], "cwd "
202
        je      cmd_cwd
203
 
3813 hidnplayr 204
        cmp     dword[s], "mkd "
205
        je      cmd_mkd
3793 hidnplayr 206
 
3813 hidnplayr 207
        cmp     dword[s], "rmd "
208
        je      cmd_rmd
209
 
3794 hidnplayr 210
        cmp     dword[s], "pwd" + 10 shl 24
211
        je      cmd_pwd
212
 
3813 hidnplayr 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
 
3800 hidnplayr 225
        cmp     dword[s], "stor"
226
        je      cmd_stor
3793 hidnplayr 227
 
3800 hidnplayr 228
        cmp     dword[s], "dele"
229
        je      cmd_dele
230
 
3813 hidnplayr 231
  @@:
232
        cmp     byte[s+4], 10
233
        jne     @f
3800 hidnplayr 234
 
3813 hidnplayr 235
        cmp     dword[s], "list"
236
        je      cmd_list
3802 hidnplayr 237
 
3813 hidnplayr 238
        cmp     dword[s], "help"
239
        je      cmd_help
3804 hidnplayr 240
 
241
        cmp     dword[s], "cdup"
242
        je      cmd_cdup
243
 
3813 hidnplayr 244
  @@:
245
; Uh oh.. unknown command, tell the user and wait for new input
3789 hidnplayr 246
        invoke  con_write_asciiz, str_unknown
3701 hidnplayr 247
        jmp     wait_for_usercommand
248
 
249
 
250
  .connected:
3813 hidnplayr 251
; request username
3789 hidnplayr 252
        invoke  con_write_asciiz, str_user
3701 hidnplayr 253
        mov     dword[s], "USER"
254
        mov     byte[s+4], " "
255
        jmp     .send
256
 
257
 
258
  .needpass:
3813 hidnplayr 259
; request password
3789 hidnplayr 260
        invoke  con_write_asciiz, str_pass
3701 hidnplayr 261
        mov     dword[s], "PASS"
262
        mov     byte[s+4], " "
3803 hidnplayr 263
        invoke  con_set_flags, 0x00     ; black text on black background for password
3701 hidnplayr 264
 
265
  .send:
266
; read string
267
        mov     esi, s+5
3789 hidnplayr 268
        invoke  con_gets, esi, 256
3701 hidnplayr 269
 
3800 hidnplayr 270
; find end of string
3701 hidnplayr 271
        mov     edi, s+5
272
        mov     ecx, 256
273
        xor     al, al
274
        repne   scasb
3814 hidnplayr 275
        lea     esi, [edi-s]
276
        mov     word[edi-2], 0x0a0d
3800 hidnplayr 277
; and send it to the server
3789 hidnplayr 278
        mcall   send, [socketnum], s, , 0
3701 hidnplayr 279
 
3813 hidnplayr 280
        invoke  con_write_asciiz, str_newline
3800 hidnplayr 281
        invoke  con_set_flags, 0x07     ; reset color
3789 hidnplayr 282
        jmp     wait_for_servercommand
3701 hidnplayr 283
 
284
 
285
 
3800 hidnplayr 286
open_dataconnection:                    ; only passive for now..
3701 hidnplayr 287
        cmp     [status], STATUS_LOGGED_IN
288
        jne     .fail
289
 
290
        mov     dword[s], "PASV"
3814 hidnplayr 291
        mov     word[s+4], 0x0a0d
292
        mcall   send, [socketnum], s, 6, 0
3701 hidnplayr 293
        ret
294
 
295
  .fail:
3818 hidnplayr 296
        invoke  con_get_flags
297
        push    eax
298
        invoke  con_set_flags, 0x0c                     ; print errors in red
3813 hidnplayr 299
        invoke  con_write_asciiz, str_err_socket
3818 hidnplayr 300
        invoke  con_set_flags                           ; reset color
3701 hidnplayr 301
        ret
302
 
303
 
304
 
3813 hidnplayr 305
error_socket:
3818 hidnplayr 306
        invoke  con_set_flags, 0x0c                     ; print errors in red
3813 hidnplayr 307
        invoke  con_write_asciiz, str_err_socket
308
        jmp     wait_for_keypress
3701 hidnplayr 309
 
3813 hidnplayr 310
error_resolve:
3818 hidnplayr 311
        invoke  con_set_flags, 0x0c                     ; print errors in red
3813 hidnplayr 312
        invoke  con_write_asciiz, str_err_resolve
313
 
314
wait_for_keypress:
3818 hidnplayr 315
        invoke  con_set_flags, 0x07                     ; reset color to grey
3813 hidnplayr 316
        invoke  con_write_asciiz, str_push
3789 hidnplayr 317
        invoke  con_getch2
3818 hidnplayr 318
        mcall   close, [socketnum]
3701 hidnplayr 319
        jmp     main
320
 
321
done:
3789 hidnplayr 322
        invoke  con_exit, 1
323
 
3701 hidnplayr 324
exit:
325
        mcall   close, [socketnum]
326
        mcall   -1
327
 
328
 
329
 
330
; data
3813 hidnplayr 331
str_title       db 'FTP client',0
3818 hidnplayr 332
str_welcome     db 'FTP client for KolibriOS v0.09',10
3813 hidnplayr 333
                db 10
334
                db 'Please enter ftp server address.',10,0
3800 hidnplayr 335
 
3813 hidnplayr 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
3701 hidnplayr 350
 
3813 hidnplayr 351
str_open        db "opening data socket",10,0
3701 hidnplayr 352
 
3813 hidnplayr 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  - change working directoy on the server",10
358
                db "dele      - delete file from the server",10
359
                db "list            - list files and folders in current server directory",10
360
                db "lcwd      - change local working directory",10
361
                db "mkd  - make directory on the server",10
362
                db "pwd             - print server working directory",10
363
                db "retr      - retreive file from the server",10
364
                db "rmd  - remove directory from the server",10
365
                db "stor      - store file on the server",10
366
                db 10,0
367
 
3701 hidnplayr 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',\
3789 hidnplayr 401
        con_get_flags,  'con_get_flags', \
402
        con_set_flags,  'con_set_flags'
3701 hidnplayr 403
 
404
 
405
i_end:
406
 
3813 hidnplayr 407
; uninitialised data
408
 
3794 hidnplayr 409
status          db ?
3701 hidnplayr 410
active_passive  db ?
3794 hidnplayr 411
 
3701 hidnplayr 412
socketnum       dd ?
413
datasocket      dd ?
3790 hidnplayr 414
offset          dd ?
415
size            dd ?
3800 hidnplayr 416
operation       dd ?
3701 hidnplayr 417
 
3800 hidnplayr 418
filestruct:
419
.subfn  dd ?
420
.offset dd ?
421
        dd ?
422
.size   dd ?
423
.ptr    dd ?
424
.name   rb 1024
425
 
3794 hidnplayr 426
buffer_ptr      rb BUFFERSIZE+1
427
buffer_ptr2     rb BUFFERSIZE+1
428
 
3790 hidnplayr 429
s               rb 1024
3701 hidnplayr 430
 
431
mem: