Subversion Repositories Kolibri OS

Rev

Rev 8442 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3701 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
9164 hidnplayr 3
;; Copyright (C) KolibriOS team 2013-2021. All rights reserved.    ;;
3701 hidnplayr 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                             ;;
6582 nisargshah 9
;;  Modified by nisargshah323@gmail.com (2016)                     ;;
3701 hidnplayr 10
;;                                                                 ;;
11
;;          GNU GENERAL PUBLIC LICENSE                             ;;
12
;;             Version 2, June 1991                                ;;
13
;;                                                                 ;;
14
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15
 
16
format binary as ""
17
 
4918 hidnplayr 18
TIMEOUT                 = 3     ; seconds
19
 
3800 hidnplayr 20
BUFFERSIZE              = 4096
3701 hidnplayr 21
 
22
STATUS_CONNECTING       = 0
23
STATUS_CONNECTED        = 1
24
STATUS_NEEDPASSWORD     = 2
25
STATUS_LOGGED_IN        = 3
26
 
3821 hidnplayr 27
OPERATION_NONE          = 0
28
OPERATION_LIST          = 1
29
OPERATION_RETR          = 2
30
OPERATION_STOR          = 3
5011 hidnplayr 31
OPERATION_RDIR          = 4
32
 
3701 hidnplayr 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
4922 ashmew2 41
        dd      buf_cmd         ; parameters
5011 hidnplayr 42
        dd      path            ; path
3701 hidnplayr 43
 
44
include '../../macros.inc'
6582 nisargshah 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
 
3701 hidnplayr 61
purge mov,add,sub
6582 nisargshah 62
 
3701 hidnplayr 63
include '../../proc32.inc'
64
include '../../network.inc'
7167 nisargshah 65
include '../../KOSfuncs.inc'
6582 nisargshah 66
 
67
include 'console.inc'
68
include 'gui.inc'
69
include 'login_gui.inc'
3701 hidnplayr 70
include 'usercommands.inc'
71
include 'servercommands.inc'
6394 nisargshah 72
include 'parser.inc'
3701 hidnplayr 73
 
6582 nisargshah 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
;;================================================================================================;;
4922 ashmew2 85
; initialize heap for using dynamic blocks
6835 hidnplayr 86
        mcall   68, 11
87
        test    eax, eax
5011 hidnplayr 88
        je      exit2
89
 
4918 hidnplayr 90
; disable all events except network event
91
        mcall   40, EV_STACK
3701 hidnplayr 92
; load libraries
93
        stdcall dll.Load, @IMPORT
94
        test    eax, eax
95
        jnz     exit
5011 hidnplayr 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
 
6582 nisargshah 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
3701 hidnplayr 138
 
6582 nisargshah 139
; Usage: ftpc [-cli] [ftp://username:password@server:port/path]
3701 hidnplayr 140
 
6582 nisargshah 141
        ; mov     dword[buf_cmd], '-cli' ;;;; to test CLI ;;;;;
5011 hidnplayr 142
 
6582 nisargshah 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
3701 hidnplayr 189
  @@:
6582 nisargshah 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
  @@:
3701 hidnplayr 219
        lodsb
6582 nisargshah 220
        stosb
3701 hidnplayr 221
        cmp     al, 0x20
6582 nisargshah 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
3701 hidnplayr 236
        ja      @r
6582 nisargshah 237
        mov     byte[edi-1], 0 ; delete terminating '\n'
5011 hidnplayr 238
 
6582 nisargshah 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
5011 hidnplayr 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'
6436 nisargshah 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]
5011 hidnplayr 281
        shl     ebx, 1
282
        add     ebx, eax
283
        jmp     .portloop
284
 
285
  .port_done:
286
        xchg    bl, bh
287
        mov     [sockaddr1.port], bx
6582 nisargshah 288
        jmp     .done
5011 hidnplayr 289
 
6582 nisargshah 290
  .default_port:
291
        mov     [sockaddr1.port], 21 shl 8
292
 
5011 hidnplayr 293
  .done:
3813 hidnplayr 294
; Say to the user that we're resolving
6582 nisargshah 295
        icall   eax, interface_addr, interface.set_flags, 0x07 ; reset color
296
        icall   eax, interface_addr, interface.print, str_resolve, buf_cmd
3701 hidnplayr 297
; resolve name
298
        push    esp     ; reserve stack place
4922 ashmew2 299
        invoke  getaddrinfo, buf_cmd, 0, 0, esp
3701 hidnplayr 300
        pop     esi
301
; test for error
302
        test    eax, eax
6436 nisargshah 303
        jz      @f
304
        mov     eax, str_err_resolve
305
        jmp     error
306
    @@:
3701 hidnplayr 307
; write results
6582 nisargshah 308
        icall   eax, interface_addr, interface.print, str8 ; ' (',0
3800 hidnplayr 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                  ;
6582 nisargshah 313
        icall   ebx, interface_addr, interface.print, eax, str9 ; ,')',10,0
3800 hidnplayr 314
        invoke  freeaddrinfo, esi               ; free allocated memory
315
; open the socket
3701 hidnplayr 316
        mcall   socket, AF_INET4, SOCK_STREAM, 0
317
        cmp     eax, -1
6436 nisargshah 318
        jne     @f
319
        mov     eax, str_err_socket
320
        jmp     error
321
    @@: mov     [controlsocket], eax
3800 hidnplayr 322
; connect to the server
6582 nisargshah 323
        icall   eax, interface_addr, interface.print, str_connect
5011 hidnplayr 324
        mcall   connect, [controlsocket], sockaddr1, 18
4918 hidnplayr 325
        cmp     eax, -1
6436 nisargshah 326
        jne     @f
327
        mov     eax, str_err_connect
328
        jmp     error
329
    @@: mov     [status], STATUS_CONNECTING
3813 hidnplayr 330
; Tell the user we're waiting for the server now.
6582 nisargshah 331
        icall   eax, interface_addr, interface.print, str_waiting
3701 hidnplayr 332
 
3813 hidnplayr 333
; Reset 'offset' variable, it's used by the data receiver
3790 hidnplayr 334
        mov     [offset], 0
335
 
6582 nisargshah 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
;;================================================================================================;;
3813 hidnplayr 347
; Any commands still in our buffer?
3790 hidnplayr 348
        cmp     [offset], 0
3813 hidnplayr 349
        je      .receive                        ; nope, receive some more
3790 hidnplayr 350
        mov     esi, [offset]
4922 ashmew2 351
        mov     edi, buf_cmd
3790 hidnplayr 352
        mov     ecx, [size]
353
        add     ecx, esi
354
        jmp     .byteloop
3701 hidnplayr 355
 
9164 hidnplayr 356
; receive socket data with timeout
3790 hidnplayr 357
  .receive:
4918 hidnplayr 358
        mcall   26, 9
359
        add     eax, TIMEOUT*100
360
        mov     [timeout], eax
9164 hidnplayr 361
  .again:
362
        mcall   recv, [controlsocket], buf_buffer1, BUFFERSIZE, MSG_DONTWAIT
363
        cmp     eax, 0
364
        jg      .got_data
365
        je      .closed
366
        cmp     ebx, EWOULDBLOCK
367
        jne     .sock_err
4918 hidnplayr 368
        mcall   26, 9
9164 hidnplayr 369
        mov     ebx, [timeout]
370
        sub     ebx, eax
371
        jle     .timeout
372
        mcall   23      ; Wait for event with timeout
373
        jmp     .again
374
 
375
  .sock_err:
6436 nisargshah 376
        mov     eax, str_err_recv
377
        jmp     error
3701 hidnplayr 378
 
9164 hidnplayr 379
  .closed:
380
        mov     eax, str_err_closed
381
        jmp     error
382
 
383
  .timeout:
384
        mov     eax, str_err_timeout
385
        jmp     error
386
 
4918 hidnplayr 387
  .got_data:
3790 hidnplayr 388
        mov     [offset], 0
3789 hidnplayr 389
 
4922 ashmew2 390
; extract commands, copy them to "buf_cmd" buffer
391
        lea     ecx, [eax + buf_buffer1]         ; ecx = end pointer
392
        mov     esi, buf_buffer1                 ; esi = current pointer
393
        mov     edi, buf_cmd
3701 hidnplayr 394
  .byteloop:
3789 hidnplayr 395
        cmp     esi, ecx
396
        jae     wait_for_servercommand
3701 hidnplayr 397
        lodsb
398
        cmp     al, 10                          ; excellent, we might have a command
399
        je      .got_command
3789 hidnplayr 400
        cmp     al, 13                          ; just ignore this byte
3701 hidnplayr 401
        je      .byteloop
402
        stosb
403
        jmp     .byteloop
3789 hidnplayr 404
  .got_command:                                 ; we have a newline check if its a command
3790 hidnplayr 405
        cmp     esi, ecx
406
        je      .no_more_data
407
        mov     [offset], esi
408
        sub     ecx, esi
409
        mov     [size], ecx
410
        jmp     .go_cmd
411
  .no_more_data:
412
        mov     [offset], 0
413
  .go_cmd:
4922 ashmew2 414
        lea     ecx, [edi - buf_cmd]                  ; length of command
3701 hidnplayr 415
        xor     al, al
416
        stosb
417
 
6582 nisargshah 418
        icall   eax, interface_addr, interface.set_flags, 0x03 ; change color
419
        icall   eax, interface_addr, interface.print, buf_cmd, str_newline
420
        icall   eax, interface_addr, interface.set_flags, 0x07 ; reset color
3701 hidnplayr 421
 
3789 hidnplayr 422
        jmp     server_parser                   ; parse command
3701 hidnplayr 423
 
3813 hidnplayr 424
 
425
 
6582 nisargshah 426
;;================================================================================================;;
427
wait_for_usercommand: ;///////////////////////////////////////////////////////////////////////////;;
428
;;------------------------------------------------------------------------------------------------;;
429
;? Reads the FTP command entered by the user and compares it with valid FTP commands.             ;;
430
;? Jumps to appropriate handling routine in usercommands.inc                                      ;;
431
;;------------------------------------------------------------------------------------------------;;
432
;> status = socket connection status                                                              ;;
433
;> buf_cmd = command entered by the user                                                          ;;
434
;;------------------------------------------------------------------------------------------------;;
435
;< none                                                                                           ;;
436
;;================================================================================================;;
3701 hidnplayr 437
 
4922 ashmew2 438
; Are there any files in the transfer queue?
439
 
5011 hidnplayr 440
        cmp     [queued], 0
4922 ashmew2 441
        ja      transfer_queued                 ; Yes, transfer those first.
6582 nisargshah 442
 
3813 hidnplayr 443
; change color to green for user input
6582 nisargshah 444
        icall   eax, interface_addr, interface.set_flags, 0x0a
3701 hidnplayr 445
 
3813 hidnplayr 446
; If we are not yet connected, request username/password
6582 nisargshah 447
 
3701 hidnplayr 448
        cmp     [status], STATUS_CONNECTED
6582 nisargshah 449
        je      arg_handler.get_username
3701 hidnplayr 450
 
451
        cmp     [status], STATUS_NEEDPASSWORD
6582 nisargshah 452
        je      arg_handler.get_pass
3701 hidnplayr 453
 
6582 nisargshah 454
        ijmp    eax, interface_addr, interface.get_cmd
3794 hidnplayr 455
 
6582 nisargshah 456
  .parse_cmd:
4922 ashmew2 457
        cmp     dword[buf_cmd], "cwd "
3790 hidnplayr 458
        je      cmd_cwd
459
 
4922 ashmew2 460
        cmp     dword[buf_cmd], "mkd "
3813 hidnplayr 461
        je      cmd_mkd
3793 hidnplayr 462
 
4922 ashmew2 463
        cmp     dword[buf_cmd], "rmd "
3813 hidnplayr 464
        je      cmd_rmd
465
 
4922 ashmew2 466
        cmp     dword[buf_cmd], "pwd" + 10 shl 24
3794 hidnplayr 467
        je      cmd_pwd
468
 
4922 ashmew2 469
        cmp     dword[buf_cmd], "bye" + 10 shl 24
3813 hidnplayr 470
        je      cmd_bye
471
 
4922 ashmew2 472
        cmp     dword[buf_cmd], "rdir"
5011 hidnplayr 473
        je      cmd_rdir
474
 
4922 ashmew2 475
        cmp     byte[buf_cmd+4], " "
3813 hidnplayr 476
        jne     @f
477
 
4922 ashmew2 478
        cmp     dword[buf_cmd], "lcwd"
3813 hidnplayr 479
        je      cmd_lcwd
480
 
4922 ashmew2 481
        cmp     dword[buf_cmd], "retr"
3813 hidnplayr 482
        je      cmd_retr
483
 
4922 ashmew2 484
        cmp     dword[buf_cmd], "stor"
3800 hidnplayr 485
        je      cmd_stor
3793 hidnplayr 486
 
4922 ashmew2 487
        cmp     dword[buf_cmd], "dele"
3800 hidnplayr 488
        je      cmd_dele
489
 
3813 hidnplayr 490
  @@:
4922 ashmew2 491
        cmp     byte[buf_cmd+4], 10
3813 hidnplayr 492
        jne     @f
3800 hidnplayr 493
 
4922 ashmew2 494
        cmp     dword[buf_cmd], "list"
3813 hidnplayr 495
        je      cmd_list
3802 hidnplayr 496
 
4922 ashmew2 497
        cmp     dword[buf_cmd], "help"
3813 hidnplayr 498
        je      cmd_help
3804 hidnplayr 499
 
4922 ashmew2 500
        cmp     dword[buf_cmd], "cdup"
3804 hidnplayr 501
        je      cmd_cdup
502
 
6582 nisargshah 503
        cmp     dword[buf_cmd], "abor"
504
        je      cmd_abor
505
 
3813 hidnplayr 506
  @@:
507
; Uh oh.. unknown command, tell the user and wait for new input
6582 nisargshah 508
        icall   eax, interface_addr, interface.print, str_unknown
3701 hidnplayr 509
        jmp     wait_for_usercommand
510
 
511
 
5011 hidnplayr 512
; files for rdir operation are queued
513
transfer_queued:
3701 hidnplayr 514
 
5011 hidnplayr 515
        mov     esi, [ptr_queue]                ; always pointing to current part of ptr_fname_start
516
        mov     edi, buf_cmd+5                  ; always point to filename for retr command
517
  .build_filename:
518
        lodsb
519
        stosb
520
        cmp     al, 10
521
        je      .get_file                       ; filename ends with character 10
522
        test    al, al
523
        jnz     .build_filename
524
 
525
        ; Error occured, we reached the end of the buffer before [queued] reached 0
526
        mov     [queued], 0
527
        mcall   68, 13, [ptr_fname]             ; free buffer
528
        test    eax, eax
529
        jz      error_heap
530
        jmp     wait_for_usercommand
531
 
532
  .get_file:
533
        mov     byte[edi], 0                    ; end filename with 0 byte
534
        mov     [ptr_queue], esi
535
        dec     [queued]
536
        jnz     cmd_retr
537
 
538
        mcall   68, 13, [ptr_fname]             ; free buffer
539
        test    eax, eax
540
        jz      error_heap
541
        jmp     cmd_retr
542
 
543
 
544
 
545
open_dataconnection:
546
 
547
        test    [mode], 1
548
        jnz     .active
549
 
550
        mcall   send, [controlsocket], str_PASV, str_PASV.length, 0
3701 hidnplayr 551
        ret
552
 
5011 hidnplayr 553
  .active:
554
        mcall   socket, AF_INET4, SOCK_STREAM, 0
555
        cmp     eax, -1
6436 nisargshah 556
        jne     @f
557
        mov     eax, str_err_socket
558
        jmp     error
559
    @@: mov     [datasocket], eax
5011 hidnplayr 560
 
561
        mov     ax, [acti_port_start]
562
        xchg    al, ah
563
        mov     [sockaddr2.port], ax
564
 
565
        mcall   bind, [datasocket], sockaddr2, 18
566
        cmp     eax, -1
6436 nisargshah 567
        jne     @f
568
        mov     eax, str_err_bind
569
        jmp     error
570
    @@:
5011 hidnplayr 571
 
572
        mcall   listen, [datasocket], 1
573
        cmp     eax, -1
6436 nisargshah 574
        jne     @f
575
        mov     eax, str_err_listen
576
        jmp     error
577
    @@:
5011 hidnplayr 578
 
579
        mov     dword[buf_buffer1], 'PORT'
580
        mov     byte[buf_buffer1+4], ' '
581
        mov     edi, buf_buffer1+5
582
        mov     esi, str_active_ip
583
  .loop:
584
        lodsb
585
        test    al, al
586
        jz      .ip_ok
587
        stosb
588
        jmp     .loop
589
  .ip_ok:
590
        mov     al, ','
591
        stosb
592
        movzx   eax, byte[sockaddr2.port+0]
593
        call    dword_ascii
594
        mov     al, ','
595
        stosb
596
        movzx   eax, byte[sockaddr2.port+1]
597
        call    dword_ascii
598
        mov     ax, 0x0a0d
599
        stosw
600
        lea     esi, [edi - buf_buffer1]
601
        mcall   send, [controlsocket], buf_buffer1, , 0
602
 
603
        mcall   accept, [datasocket], sockaddr2, 18        ; time to accept the awaiting connection..
604
        cmp     eax, -1
6436 nisargshah 605
        jne     @f
606
        mov     eax, str_err_accept
607
        jmp     error
608
    @@: push    eax
5011 hidnplayr 609
        mcall   close, [datasocket]
610
        pop     [datasocket]
611
 
612
        mcall   recv, [controlsocket], buf_buffer1, BUFFERSIZE, 0
613
 
3701 hidnplayr 614
        ret
615
 
5011 hidnplayr 616
; eax = input
617
; edi = ptr where to write
618
dword_ascii:
619
 
620
        push    edx ebx ecx
621
        mov     ebx, 10
622
        xor     ecx, ecx
623
 
624
       @@:
625
        xor     edx, edx
626
        div     ebx
627
        add     edx, '0'
628
        push    dx
629
        inc     ecx
630
        test    eax, eax
631
        jnz     @r
632
 
633
       @@:
634
        pop     ax
635
        stosb
636
        dec     ecx
637
        jnz     @r
638
 
639
        pop     ecx ebx edx
640
        ret
641
 
6582 nisargshah 642
 
643
;;================================================================================================;;
644
write_to_file: ;//////////////////////////////////////////////////////////////////////////////////;;
645
;;------------------------------------------------------------------------------------------------;;
646
;? Writes input buffer to log file                                                                ;;
647
;;------------------------------------------------------------------------------------------------;;
648
;> eax = pointer to buffer                                                                        ;;
649
;> ecx = size of buffer                                                                           ;;
650
;;------------------------------------------------------------------------------------------------;;
651
;< eax = status of SF 70.3                                                                        ;;
652
;;================================================================================================;;
7201 nisargshah 653
        cmp     [logfile_offset], -1 ; if offset == -1 => logging disabled
654
        jne     @f
655
        mov     eax, 0
656
        ret
657
      @@:
6582 nisargshah 658
        mov     [filestruct2.subfn], 3
659
        m2m     [filestruct2.offset], [logfile_offset]
660
        mov     [filestruct2.size], ecx
661
        mov     [filestruct2.ptr], eax
662
        mov     [filestruct2.name], log_file
663
        mcall   70, filestruct2
664
        test    eax, eax
665
        jz      @f
666
        mov     [logfile_offset], -1 ; disable logging
667
        call    error_fs
668
        icall   ebx, interface_addr, interface.print, str_no_logging
669
        ret
670
      @@:
671
        mov     eax, [logfile_offset]
672
        add     eax, ecx
673
        mov     [logfile_offset], eax
674
        ret
675
 
676
;;================================================================================================;;
677
error: ;//////////////////////////////////////////////////////////////////////////////////////////;;
678
;;------------------------------------------------------------------------------------------------;;
679
;? Generic error routine. Prints the error string passed to it.                                   ;;
680
;;------------------------------------------------------------------------------------------------;;
681
;> eax = pointer to the error string                                                              ;;
682
;;------------------------------------------------------------------------------------------------;;
683
;< none                                                                                           ;;
684
;;================================================================================================;;
6436 nisargshah 685
        push    eax
6582 nisargshah 686
        icall   ebx, interface_addr, interface.set_flags, 0x0c ; print errors in red
6436 nisargshah 687
        pop     eax
6582 nisargshah 688
        icall   ebx, interface_addr, interface.print, eax
5011 hidnplayr 689
        jmp     wait_for_keypress
690
 
6582 nisargshah 691
 
692
; Error handling block for filesystem errors
693
error_fs:
694
 
695
        cmp     eax, 12
696
        jne     @f
697
        mov     ebx, str_fs_err_12
698
  @@:
699
        cmp     eax, 11
700
        jne     @f
701
        mov     ebx, str_fs_err_11
702
  @@:
703
        cmp     eax, 10
704
        jne     @f
705
        mov     ebx, str_fs_err_10
706
  @@:
707
        cmp     eax, 9
708
        jne     @f
709
        mov     ebx, str_fs_err_9
710
  @@:
711
        cmp     eax, 8
712
        jne     @f
713
        mov     ebx, str_fs_err_8
714
  @@:
715
        cmp     eax, 7
716
        jne     @f
717
        mov     ebx, str_fs_err_7
718
  @@:
719
        cmp     eax, 6
720
        jne     @f
721
        mov     ebx, str_fs_err_6
722
  @@:
723
        cmp     eax, 5
724
        jne     @f
725
        mov     ebx, str_fs_err_5
726
  @@:
727
        cmp     eax, 3
728
        jne     @f
729
        mov     ebx, str_fs_err_3
730
  @@:
731
        cmp     eax, 2
732
        jne     @f
733
        mov     ebx, str_fs_err_2
734
  @@:
735
        mov     edi, fs_error_code
736
        call    dword_ascii    ; convert error code in eax to ascii
737
        icall   eax, interface_addr, interface.set_flags, 0x0c ; print errors in red
738
        icall   eax, interface_addr, interface.print, str_err_fs, fs_error_code, ebx
739
        mov     word[fs_error_code], '  '   ; clear error code for next time
740
        icall   eax, interface_addr, interface.set_flags, 0x0a
741
 
742
        ret
743
 
4922 ashmew2 744
error_heap:
6582 nisargshah 745
        icall   eax, interface_addr, interface.set_flags, 0x0c ; print errors in red
746
        icall   eax, interface_addr, interface.print, str_err_heap
5011 hidnplayr 747
 
3813 hidnplayr 748
wait_for_keypress:
5011 hidnplayr 749
        mcall   close, [controlsocket]
6582 nisargshah 750
        icall   eax, interface_addr, interface.set_flags, 0x07 ; reset color to grey
751
        icall   eax, interface_addr, interface.print, str_push
752
        ijmp    eax, interface_addr, interface.error
3701 hidnplayr 753
 
754
exit:
5011 hidnplayr 755
        mcall   close, [controlsocket]
756
exit2:
3701 hidnplayr 757
        mcall   -1
758
 
759
 
760
 
761
; data
7464 leency 762
str_title       db 'FTP client for KolibriOS',0
9164 hidnplayr 763
str_welcome     db 'FTP client for KolibriOS v0.16',10
6582 nisargshah 764
                db 10,0
765
str_srv_addr    db 'Please enter ftp server address.',10,0
3800 hidnplayr 766
 
3813 hidnplayr 767
str_prompt      db '> ',0
768
str_resolve     db 'Resolving ',0
769
str_newline     db 10,0
770
str_err_resolve db 10,'Name resolution failed.',10,0
9164 hidnplayr 771
str_err_closed  db 10,'The connection was closed by the remote end',10,0
6436 nisargshah 772
str_err_socket  db 10,'[75,0 socket]: Error creating a socket',10,0
773
str_err_bind    db 10,'[75,2 bind]: Error binding to socket',10,0
774
str_err_listen  db 10,'[75,3 listen]: Cannot accept incoming connections',10,0
775
str_err_accept  db 10,'[75,5 accept]: Error accepting a connection',10,0
776
str_err_recv    db 10,'[75,7 recv]: Error receiving data from server',10,0
5011 hidnplayr 777
str_err_heap    db 10,'Cannot allocate memory from heap.',10,0
4918 hidnplayr 778
str_err_timeout db 10,'Timeout - no response from server.',10,0
6436 nisargshah 779
str_err_connect db 10,'[75,4 connect]: Cannot connect to the server.',10,0
5011 hidnplayr 780
str_err_host    db 10,'Invalid hostname.',10,0
6436 nisargshah 781
str_err_params  db 10,'Invalid parameters',10,0
6582 nisargshah 782
str_err_fs      db 10,'File system error: code ',0
783
fs_error_code   db '  ',0    ; file system error code
784
str_fs_err_2    db ' [Function is not supported for the given file system]',10,0
785
str_fs_err_3    db ' [Unknown file system]',10,0
786
str_fs_err_5    db ' [File/Folder not found]',10,0
787
str_fs_err_6    db ' [End of file, EOF]',10,0
788
str_fs_err_7    db ' [Pointer lies outside of application memory]',10,0
789
str_fs_err_8    db ' [Disk is full]',10,0
790
str_fs_err_9    db ' [File system error]',10,0
791
str_fs_err_10   db ' [Access denied]',10,0
792
str_fs_err_11   db ' [Device error]',10,0
793
str_fs_err_12   db ' [File system requires more memory]',10,0
3813 hidnplayr 794
str8            db ' (',0
795
str9            db ')',10,0
796
str_push        db 'Push any key to continue.',0
797
str_connect     db 'Connecting...',10,0
798
str_waiting     db 'Waiting for welcome message.',10,0
799
str_user        db "username: ",0
800
str_pass        db "password: ",0
6582 nisargshah 801
str_port        db "port (default 21): ",0
802
str_path        db "path (optional): ",0
3813 hidnplayr 803
str_unknown     db "Unknown command or insufficient parameters - type help for more information.",10,0
804
str_lcwd        db "Local working directory is now: ",0
6582 nisargshah 805
str_bytes_done  db '          ',0
806
str_downloaded  db 'Downloaded ',0
807
str_bytes       db ' bytes',13,0
808
str_args_err    db 'Invalid arguments. USAGE: ftpc [-cli] [ftp://username:password@server:port/path]',10,0
3701 hidnplayr 809
 
3813 hidnplayr 810
str_open        db "opening data socket",10,0
4922 ashmew2 811
str_close       db 10,"closing data socket",10,0
812
str_dot         db '.',0
3701 hidnplayr 813
 
3813 hidnplayr 814
str_help        db "available commands:",10
815
                db 10
816
                db "bye             - close the connection",10
817
                db "cdup            - change to parent of current directory on the server",10
818
                db "cwd  - change working directoy on the server",10
819
                db "dele      - delete file from the server",10
820
                db "list            - list files and folders in current server directory",10
821
                db "lcwd      - change local working directory",10
822
                db "mkd  - make directory on the server",10
823
                db "pwd             - print server working directory",10
824
                db "retr      - retreive file from the server",10
825
                db "rmd  - remove directory from the server",10
826
                db "stor      - store file on the server",10
6582 nisargshah 827
                db "rdir            - retreive all files from current server dir",10
3813 hidnplayr 828
                db 10,0
829
 
5011 hidnplayr 830
str_ini         db '.ini', 0
831
str_active      db 'active', 0
832
str_port_start  db 'port_start', 0
833
str_port_stop   db 'port_stop', 0
834
str_ip          db 'ip', 0
835
str_dir         db 'dir', 0
836
str_general     db 'general', 0
6582 nisargshah 837
str_logfile     db 'logfile',0
838
str_no_logging  db 'Error writing to log file. Logging disabled',0
3821 hidnplayr 839
 
5011 hidnplayr 840
queued          dd 0
841
mode            db 0    ; passive = 0, active = 1
842
 
6582 nisargshah 843
 
3821 hidnplayr 844
; FTP strings
845
 
846
str_PASV        db 'PASV',13,10
847
.length = $ - str_PASV
848
 
3701 hidnplayr 849
sockaddr1:
850
        dw AF_INET4
5011 hidnplayr 851
.port   dw ?
852
.ip     dd ?
3701 hidnplayr 853
        rb 10
854
 
855
sockaddr2:
856
        dw AF_INET4
5011 hidnplayr 857
.port   dw ?
858
.ip     dd ?
3701 hidnplayr 859
        rb 10
860
 
6582 nisargshah 861
struc interface
862
{
863
    .init           dd 0
864
    .server_addr    dd 4
865
    .get_username   dd 8
866
    .get_cmd        dd 12
867
    .print          dd 16
868
    .set_flags      dd 20
869
    .list           dd 24
870
    .progress       dd 28
871
    .error          dd 32
872
}
873
interface interface
874
 
3701 hidnplayr 875
; import
876
align 4
877
@IMPORT:
878
 
6582 nisargshah 879
library network, 'network.obj', libini, 'libini.obj'
3701 hidnplayr 880
 
6582 nisargshah 881
import  network, \
882
        getaddrinfo,    'getaddrinfo', \
3701 hidnplayr 883
        freeaddrinfo,   'freeaddrinfo', \
884
        inet_ntoa,      'inet_ntoa'
885
 
6582 nisargshah 886
import  libini, \
887
        ini.get_str,    'ini_get_str', \
5011 hidnplayr 888
        ini.get_int,    'ini_get_int'
3701 hidnplayr 889
 
8442 IgorA 890
param_user:     db 'anonymous',0
891
rb 60
5011 hidnplayr 892
 
8442 IgorA 893
param_server_addr db 'kolibrios.org'
894
rb 1024
895
 
896
align 4
3701 hidnplayr 897
i_end:
3813 hidnplayr 898
; uninitialised data
899
 
8442 IgorA 900
run_file_70 FileInfoBlock ; required for libimg
901
 
902
new_dir_buf rb 64
903
folder_data rb 32+32*304
904
 
905
remote_list_buf rb 1024
906
file_name   rb 4096 ; required for libimg
907
conv_tabl   rb 128
908
ed_buffer   rb 100
909
tedit_buffer rb 1024
910
el_focus    dd ?
911
;-----------------------
912
 
913
procinfo        process_information
914
 
6582 nisargshah 915
interface_addr  rd 1
916
 
3794 hidnplayr 917
status          db ?
918
 
6582 nisargshah 919
file_size       dd ?
920
 
5011 hidnplayr 921
controlsocket   dd ?
3701 hidnplayr 922
datasocket      dd ?
3790 hidnplayr 923
offset          dd ?
924
size            dd ?
3800 hidnplayr 925
operation       dd ?
4918 hidnplayr 926
timeout         dd ?
927
 
5011 hidnplayr 928
ptr_fname       dd ?
929
size_fname      dd ?
930
ptr_queue       dd ?
931
 
932
acti_port_start dw ?
933
acti_port_stop  dw ?
934
acti_port       dw ?
935
 
936
str_active_ip   rb 16
937
 
3800 hidnplayr 938
filestruct:
5011 hidnplayr 939
  .subfn        dd ?
940
  .offset       dd ?
941
                dd ?
942
  .size         dd ?
943
  .ptr          dd ?
944
  .name         rb 1024
3800 hidnplayr 945
 
6582 nisargshah 946
filestruct2:
947
  .subfn        dd ?
948
  .offset       dd ?
8442 IgorA 949
                dd ?
6582 nisargshah 950
  .size         dd ?
951
  .ptr          dd ?
8442 IgorA 952
                db ?
6582 nisargshah 953
  .name         dd ?
954
 
955
folder_buf      rb 40
956
 
957
 
4922 ashmew2 958
buf_buffer1     rb BUFFERSIZE+1
959
buf_buffer2     rb BUFFERSIZE+1
5011 hidnplayr 960
buf_cmd         rb 1024                 ; buffer for holding command string
6582 nisargshah 961
log_file        rb 512 ; holds log file path
962
logfile_offset  rd 1
3794 hidnplayr 963
 
5011 hidnplayr 964
path            rb 1024
965
 
6582 nisargshah 966
initial_login   rb 1
7959 leency 967
 
6394 nisargshah 968
param_password  rb 1024
7959 leency 969
 
6394 nisargshah 970
param_path      rb 1024
6582 nisargshah 971
param_port      rb 6
6394 nisargshah 972
 
6582 nisargshah 973
sc system_colors
974
rb 1024
975
 
3701 hidnplayr 976
mem: