Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3701 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
7167 nisargshah 3
;; Copyright (C) KolibriOS team 2013-2018. 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
 
356
; receive socket data
3790 hidnplayr 357
  .receive:
4918 hidnplayr 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]
6436 nisargshah 365
        jl      @f
366
        mov     eax, str_err_timeout
367
        jmp     error
368
    @@: mcall   recv, [controlsocket], buf_buffer1, BUFFERSIZE, MSG_DONTWAIT
4918 hidnplayr 369
        test    eax, eax
370
        jnz     .got_data
371
        cmp     ebx, EWOULDBLOCK
6436 nisargshah 372
        je      @f
373
        mov     eax, str_err_recv
374
        jmp     error
375
    @@: jmp     .receive_loop
3701 hidnplayr 376
 
4918 hidnplayr 377
  .got_data:
3790 hidnplayr 378
        mov     [offset], 0
3789 hidnplayr 379
 
4922 ashmew2 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
3701 hidnplayr 384
  .byteloop:
3789 hidnplayr 385
        cmp     esi, ecx
386
        jae     wait_for_servercommand
3701 hidnplayr 387
        lodsb
388
        cmp     al, 10                          ; excellent, we might have a command
389
        je      .got_command
3789 hidnplayr 390
        cmp     al, 13                          ; just ignore this byte
3701 hidnplayr 391
        je      .byteloop
392
        stosb
393
        jmp     .byteloop
3789 hidnplayr 394
  .got_command:                                 ; we have a newline check if its a command
3790 hidnplayr 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:
4922 ashmew2 404
        lea     ecx, [edi - buf_cmd]                  ; length of command
3701 hidnplayr 405
        xor     al, al
406
        stosb
407
 
6582 nisargshah 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
3701 hidnplayr 411
 
3789 hidnplayr 412
        jmp     server_parser                   ; parse command
3701 hidnplayr 413
 
3813 hidnplayr 414
 
415
 
6582 nisargshah 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
;;================================================================================================;;
3701 hidnplayr 427
 
4922 ashmew2 428
; Are there any files in the transfer queue?
429
 
5011 hidnplayr 430
        cmp     [queued], 0
4922 ashmew2 431
        ja      transfer_queued                 ; Yes, transfer those first.
6582 nisargshah 432
 
3813 hidnplayr 433
; change color to green for user input
6582 nisargshah 434
        icall   eax, interface_addr, interface.set_flags, 0x0a
3701 hidnplayr 435
 
3813 hidnplayr 436
; If we are not yet connected, request username/password
6582 nisargshah 437
 
3701 hidnplayr 438
        cmp     [status], STATUS_CONNECTED
6582 nisargshah 439
        je      arg_handler.get_username
3701 hidnplayr 440
 
441
        cmp     [status], STATUS_NEEDPASSWORD
6582 nisargshah 442
        je      arg_handler.get_pass
3701 hidnplayr 443
 
6582 nisargshah 444
        ijmp    eax, interface_addr, interface.get_cmd
3794 hidnplayr 445
 
6582 nisargshah 446
  .parse_cmd:
4922 ashmew2 447
        cmp     dword[buf_cmd], "cwd "
3790 hidnplayr 448
        je      cmd_cwd
449
 
4922 ashmew2 450
        cmp     dword[buf_cmd], "mkd "
3813 hidnplayr 451
        je      cmd_mkd
3793 hidnplayr 452
 
4922 ashmew2 453
        cmp     dword[buf_cmd], "rmd "
3813 hidnplayr 454
        je      cmd_rmd
455
 
4922 ashmew2 456
        cmp     dword[buf_cmd], "pwd" + 10 shl 24
3794 hidnplayr 457
        je      cmd_pwd
458
 
4922 ashmew2 459
        cmp     dword[buf_cmd], "bye" + 10 shl 24
3813 hidnplayr 460
        je      cmd_bye
461
 
4922 ashmew2 462
        cmp     dword[buf_cmd], "rdir"
5011 hidnplayr 463
        je      cmd_rdir
464
 
4922 ashmew2 465
        cmp     byte[buf_cmd+4], " "
3813 hidnplayr 466
        jne     @f
467
 
4922 ashmew2 468
        cmp     dword[buf_cmd], "lcwd"
3813 hidnplayr 469
        je      cmd_lcwd
470
 
4922 ashmew2 471
        cmp     dword[buf_cmd], "retr"
3813 hidnplayr 472
        je      cmd_retr
473
 
4922 ashmew2 474
        cmp     dword[buf_cmd], "stor"
3800 hidnplayr 475
        je      cmd_stor
3793 hidnplayr 476
 
4922 ashmew2 477
        cmp     dword[buf_cmd], "dele"
3800 hidnplayr 478
        je      cmd_dele
479
 
3813 hidnplayr 480
  @@:
4922 ashmew2 481
        cmp     byte[buf_cmd+4], 10
3813 hidnplayr 482
        jne     @f
3800 hidnplayr 483
 
4922 ashmew2 484
        cmp     dword[buf_cmd], "list"
3813 hidnplayr 485
        je      cmd_list
3802 hidnplayr 486
 
4922 ashmew2 487
        cmp     dword[buf_cmd], "help"
3813 hidnplayr 488
        je      cmd_help
3804 hidnplayr 489
 
4922 ashmew2 490
        cmp     dword[buf_cmd], "cdup"
3804 hidnplayr 491
        je      cmd_cdup
492
 
6582 nisargshah 493
        cmp     dword[buf_cmd], "abor"
494
        je      cmd_abor
495
 
3813 hidnplayr 496
  @@:
497
; Uh oh.. unknown command, tell the user and wait for new input
6582 nisargshah 498
        icall   eax, interface_addr, interface.print, str_unknown
3701 hidnplayr 499
        jmp     wait_for_usercommand
500
 
501
 
5011 hidnplayr 502
; files for rdir operation are queued
503
transfer_queued:
3701 hidnplayr 504
 
5011 hidnplayr 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
3701 hidnplayr 541
        ret
542
 
5011 hidnplayr 543
  .active:
544
        mcall   socket, AF_INET4, SOCK_STREAM, 0
545
        cmp     eax, -1
6436 nisargshah 546
        jne     @f
547
        mov     eax, str_err_socket
548
        jmp     error
549
    @@: mov     [datasocket], eax
5011 hidnplayr 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
6436 nisargshah 557
        jne     @f
558
        mov     eax, str_err_bind
559
        jmp     error
560
    @@:
5011 hidnplayr 561
 
562
        mcall   listen, [datasocket], 1
563
        cmp     eax, -1
6436 nisargshah 564
        jne     @f
565
        mov     eax, str_err_listen
566
        jmp     error
567
    @@:
5011 hidnplayr 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
6436 nisargshah 595
        jne     @f
596
        mov     eax, str_err_accept
597
        jmp     error
598
    @@: push    eax
5011 hidnplayr 599
        mcall   close, [datasocket]
600
        pop     [datasocket]
601
 
602
        mcall   recv, [controlsocket], buf_buffer1, BUFFERSIZE, 0
603
 
3701 hidnplayr 604
        ret
605
 
5011 hidnplayr 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
 
6582 nisargshah 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
;;================================================================================================;;
7201 nisargshah 643
        cmp     [logfile_offset], -1 ; if offset == -1 => logging disabled
644
        jne     @f
645
        mov     eax, 0
646
        ret
647
      @@:
6582 nisargshah 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
;;================================================================================================;;
6436 nisargshah 675
        push    eax
6582 nisargshah 676
        icall   ebx, interface_addr, interface.set_flags, 0x0c ; print errors in red
6436 nisargshah 677
        pop     eax
6582 nisargshah 678
        icall   ebx, interface_addr, interface.print, eax
5011 hidnplayr 679
        jmp     wait_for_keypress
680
 
6582 nisargshah 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
 
4922 ashmew2 734
error_heap:
6582 nisargshah 735
        icall   eax, interface_addr, interface.set_flags, 0x0c ; print errors in red
736
        icall   eax, interface_addr, interface.print, str_err_heap
5011 hidnplayr 737
 
3813 hidnplayr 738
wait_for_keypress:
5011 hidnplayr 739
        mcall   close, [controlsocket]
6582 nisargshah 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
3701 hidnplayr 743
 
744
exit:
5011 hidnplayr 745
        mcall   close, [controlsocket]
746
exit2:
3701 hidnplayr 747
        mcall   -1
748
 
749
 
750
 
751
; data
7464 leency 752
str_title       db 'FTP client for KolibriOS',0
753
str_welcome     db 'FTP client for KolibriOS v0.12a',10
6582 nisargshah 754
                db 10,0
755
str_srv_addr    db 'Please enter ftp server address.',10,0
3800 hidnplayr 756
 
3813 hidnplayr 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
6436 nisargshah 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
5011 hidnplayr 766
str_err_heap    db 10,'Cannot allocate memory from heap.',10,0
4918 hidnplayr 767
str_err_timeout db 10,'Timeout - no response from server.',10,0
6436 nisargshah 768
str_err_connect db 10,'[75,4 connect]: Cannot connect to the server.',10,0
5011 hidnplayr 769
str_err_host    db 10,'Invalid hostname.',10,0
6436 nisargshah 770
str_err_params  db 10,'Invalid parameters',10,0
6582 nisargshah 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
3813 hidnplayr 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
6582 nisargshah 790
str_port        db "port (default 21): ",0
791
str_path        db "path (optional): ",0
3813 hidnplayr 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
6582 nisargshah 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
3701 hidnplayr 798
 
3813 hidnplayr 799
str_open        db "opening data socket",10,0
4922 ashmew2 800
str_close       db 10,"closing data socket",10,0
801
str_dot         db '.',0
3701 hidnplayr 802
 
3813 hidnplayr 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  - change working directoy on the server",10
808
                db "dele      - delete file from the server",10
809
                db "list            - list files and folders in current server directory",10
810
                db "lcwd      - change local working directory",10
811
                db "mkd  - make directory on the server",10
812
                db "pwd             - print server working directory",10
813
                db "retr      - retreive file from the server",10
814
                db "rmd  - remove directory from the server",10
815
                db "stor      - store file on the server",10
6582 nisargshah 816
                db "rdir            - retreive all files from current server dir",10
3813 hidnplayr 817
                db 10,0
818
 
5011 hidnplayr 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
6582 nisargshah 826
str_logfile     db 'logfile',0
827
str_no_logging  db 'Error writing to log file. Logging disabled',0
3821 hidnplayr 828
 
5011 hidnplayr 829
queued          dd 0
830
mode            db 0    ; passive = 0, active = 1
831
 
6582 nisargshah 832
 
3821 hidnplayr 833
; FTP strings
834
 
835
str_PASV        db 'PASV',13,10
836
.length = $ - str_PASV
837
 
3701 hidnplayr 838
sockaddr1:
839
        dw AF_INET4
5011 hidnplayr 840
.port   dw ?
841
.ip     dd ?
3701 hidnplayr 842
        rb 10
843
 
844
sockaddr2:
845
        dw AF_INET4
5011 hidnplayr 846
.port   dw ?
847
.ip     dd ?
3701 hidnplayr 848
        rb 10
849
 
6582 nisargshah 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
 
3701 hidnplayr 864
; import
865
align 4
866
@IMPORT:
867
 
6582 nisargshah 868
library network, 'network.obj', libini, 'libini.obj'
3701 hidnplayr 869
 
6582 nisargshah 870
import  network, \
871
        getaddrinfo,    'getaddrinfo', \
3701 hidnplayr 872
        freeaddrinfo,   'freeaddrinfo', \
873
        inet_ntoa,      'inet_ntoa'
874
 
6582 nisargshah 875
import  libini, \
876
        ini.get_str,    'ini_get_str', \
5011 hidnplayr 877
        ini.get_int,    'ini_get_int'
3701 hidnplayr 878
 
5011 hidnplayr 879
 
3701 hidnplayr 880
i_end:
881
 
3813 hidnplayr 882
; uninitialised data
883
 
6582 nisargshah 884
interface_addr  rd 1
885
 
3794 hidnplayr 886
status          db ?
887
 
6582 nisargshah 888
file_size       dd ?
889
 
5011 hidnplayr 890
controlsocket   dd ?
3701 hidnplayr 891
datasocket      dd ?
3790 hidnplayr 892
offset          dd ?
893
size            dd ?
3800 hidnplayr 894
operation       dd ?
4918 hidnplayr 895
timeout         dd ?
896
 
5011 hidnplayr 897
ptr_fname       dd ?
898
size_fname      dd ?
899
ptr_queue       dd ?
900
 
901
acti_port_start dw ?
902
acti_port_stop  dw ?
903
acti_port       dw ?
904
 
905
str_active_ip   rb 16
906
 
3800 hidnplayr 907
filestruct:
5011 hidnplayr 908
  .subfn        dd ?
909
  .offset       dd ?
910
                dd ?
911
  .size         dd ?
912
  .ptr          dd ?
913
  .name         rb 1024
3800 hidnplayr 914
 
6582 nisargshah 915
filestruct2:
916
  .subfn        dd ?
917
  .offset       dd ?
918
                dd 0
919
  .size         dd ?
920
  .ptr          dd ?
921
                db 0
922
  .name         dd ?
923
 
924
folder_buf      rb 40
925
 
926
 
4922 ashmew2 927
buf_buffer1     rb BUFFERSIZE+1
928
buf_buffer2     rb BUFFERSIZE+1
5011 hidnplayr 929
buf_cmd         rb 1024                 ; buffer for holding command string
6582 nisargshah 930
log_file        rb 512 ; holds log file path
931
logfile_offset  rd 1
3794 hidnplayr 932
 
5011 hidnplayr 933
path            rb 1024
934
 
6582 nisargshah 935
initial_login   rb 1
6394 nisargshah 936
param_user      rb 1024
937
param_password  rb 1024
938
param_server_addr rb 1024
939
param_path      rb 1024
6582 nisargshah 940
param_port      rb 6
6394 nisargshah 941
 
6582 nisargshah 942
sc system_colors
943
rb 1024
944
 
3701 hidnplayr 945
mem: