Subversion Repositories Kolibri OS

Rev

Rev 6835 | Rev 7201 | 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'
66
include '../../load_img.inc'
67
include '../../develop/libraries/libs-dev/libimg/libimg.inc'
6582 nisargshah 68
include '../../develop/libraries/box_lib/trunk/box_lib.mac'
69
include '../../develop/libraries/box_lib/load_lib.mac'
70
 
71
include 'console.inc'
72
include 'gui.inc'
73
include 'login_gui.inc'
3701 hidnplayr 74
include 'usercommands.inc'
75
include 'servercommands.inc'
6394 nisargshah 76
include 'parser.inc'
3701 hidnplayr 77
 
6582 nisargshah 78
; TODO: Add Pasta support to FTPC
79
 
80
;;================================================================================================;;
81
start: ;//////////////////////////////////////////////////////////////////////////////////////////;;
82
;;------------------------------------------------------------------------------------------------;;
83
;? Program entry point - initialize heap, load libraries and settings                             ;;
84
;;------------------------------------------------------------------------------------------------;;
85
;>                                                                                                ;;
86
;;------------------------------------------------------------------------------------------------;;
87
;< none                                                                                           ;;
88
;;================================================================================================;;
4922 ashmew2 89
; initialize heap for using dynamic blocks
6835 hidnplayr 90
        mcall   68, 11
91
        test    eax, eax
5011 hidnplayr 92
        je      exit2
93
 
4918 hidnplayr 94
; disable all events except network event
95
        mcall   40, EV_STACK
3701 hidnplayr 96
; load libraries
97
        stdcall dll.Load, @IMPORT
98
        test    eax, eax
99
        jnz     exit
5011 hidnplayr 100
; find path to main settings file (ftpc.ini)
101
        mov     edi, path               ; Calculate the length of zero-terminated string
102
        xor     al, al
103
        mov     ecx, 1024
104
        repne   scasb
105
        dec     edi
106
        mov     esi, str_ini            ; append it with '.ini', 0
107
        movsd
108
        movsb
109
; get settings from ini
110
        invoke  ini.get_str, path, str_active, str_ip, str_active_ip, 16, 0
111
        mov     esi, str_active_ip
112
  .ip_loop:
113
        lodsb
114
        test    al, al
115
        jz      .ip_ok
116
        cmp     al, ' '
117
        je      .ip_ok
118
        cmp     al, '.'
119
        jne     .ip_loop
120
        mov     byte[esi-1], ','
121
        jmp     .ip_loop
122
  .ip_ok:
123
        mov     byte[esi-1], 0
124
 
125
        invoke  ini.get_int, path, str_active, str_port_start, 64000
126
        mov     [acti_port_start], ax
127
 
128
        invoke  ini.get_int, path, str_active, str_port_stop, 65000
129
        mov     [acti_port_stop], ax
130
 
131
        invoke  ini.get_str, path, str_general, str_dir, buf_buffer1, BUFFERSIZE, 0
132
        mcall   30, 1, buf_buffer1                      ; set working directory
133
 
6582 nisargshah 134
        ; initialize log file
135
        invoke  ini.get_str, path, str_general, str_logfile, log_file, 512, 0
136
        mov     [filestruct2.subfn], 2
137
        mov     [filestruct2.offset], 0
138
        mov     [filestruct2.size], 0
139
        mov     [filestruct2.ptr], 0
140
        mov     [filestruct2.name], log_file
141
        mcall   70, filestruct2
3701 hidnplayr 142
 
6582 nisargshah 143
; Usage: ftpc [-cli] [ftp://username:password@server:port/path]
3701 hidnplayr 144
 
6582 nisargshah 145
        ; mov     dword[buf_cmd], '-cli' ;;;; to test CLI ;;;;;
5011 hidnplayr 146
 
6582 nisargshah 147
        cmp     byte[buf_cmd], 0
148
        jne     @f
149
        mov     [interface_addr], gui
150
        jmp     .args_ok
151
  @@:   cmp     dword[buf_cmd], '-cli'
152
        jne     .error
153
        mov     [interface_addr], console
154
        jmp     .args_ok
155
 
156
  .args_ok:
157
 
158
        icall   eax, interface_addr, interface.init
159
        ; check for ftp://username:pass@server:port/path urls
160
        cmp     dword[buf_cmd], 'ftp:'
161
        je      parse_args
162
        cmp     dword[buf_cmd+5], 'ftp:'
163
        je      parse_args
164
        ijmp    eax, interface_addr, interface.server_addr
165
 
166
  .error:
167
        call    console.init
168
        invoke  con_write_asciiz, str_args_err
169
        invoke  con_getch2
170
        call    console.exit
171
        jmp     exit
172
 
173
;;================================================================================================;;
174
arg_handler: ;////////////////////////////////////////////////////////////////////////////////////;;
175
;;------------------------------------------------------------------------------------------------;;
176
;? Passes initial connection info from console/GUI to FTP core and the other way around           ;;
177
;;------------------------------------------------------------------------------------------------;;
178
;> esp+4 = pointer to the argument passed to the function                                         ;;
179
;;------------------------------------------------------------------------------------------------;;
180
;< none                                                                                           ;;
181
;;================================================================================================;;
182
 
183
  .get_username:
184
; request username
185
        ijmp    eax, interface_addr, interface.get_username
186
 
187
  .copy_user:
188
        mov     dword[buf_cmd], "USER"
189
        mov     byte[buf_cmd+4], " "
190
; copy user name to buf_cmd (for command line args)
191
        mov     edi, buf_cmd+5
192
        mov     esi, param_user
3701 hidnplayr 193
  @@:
6582 nisargshah 194
        movsb
195
        cmp     byte [esi-1], 0
196
        jne     @b
197
        mov     word[edi-1], 0x0a0d
198
 
199
        lea     esi, [edi+1-buf_cmd]
200
        jmp     server_connect.send
201
 
202
  .get_pass:
203
        mov     dword[buf_cmd], "PASS"
204
        mov     byte[buf_cmd+4], " "
205
; copy password to buf_cmd (for command line args)
206
        mov     edi, buf_cmd+5
207
        mov     esi, param_password
208
  @@:
209
        movsb
210
        cmp     byte[esi-1], 0
211
        jne     @b
212
        mov     word[edi-1], 0x0a0d
213
 
214
        lea     esi, [edi+1-buf_cmd]
215
        jmp     server_connect.send
216
 
217
  .get_path:
218
; copy path from param_path to buf_cmd
219
        mov     dword[buf_cmd], "CWD "
220
        mov     edi, buf_cmd+4
221
        mov     esi, param_path
222
  @@:
3701 hidnplayr 223
        lodsb
6582 nisargshah 224
        stosb
3701 hidnplayr 225
        cmp     al, 0x20
6582 nisargshah 226
        ja      @b
227
        mov     word[edi-1], 0x0a0d
228
 
229
        lea     esi, [edi+1-buf_cmd]
230
        jmp     server_connect.send
231
 
232
  .connect:
233
        ; copy server address to buf_cmd
234
        mov     esi, param_server_addr
235
        mov     edi, buf_cmd
236
  @@:
237
        lodsb
238
        stosb
239
        cmp     al, 0x20
3701 hidnplayr 240
        ja      @r
6582 nisargshah 241
        mov     byte[edi-1], 0 ; delete terminating '\n'
5011 hidnplayr 242
 
6582 nisargshah 243
        cmp     [param_port], 0x20
244
        jbe     server_connect.default_port
245
        mov     esi, param_port
246
        jmp     server_connect.do_port
247
 
248
 
249
;;================================================================================================;;
250
server_connect: ;/////////////////////////////////////////////////////////////////////////////////;;
251
;;------------------------------------------------------------------------------------------------;;
252
;? Establishes a connection to the FTP server (common block for all interfaces)                   ;;
253
;? .do_port - Port is specified by the user and needs to be converted from ASCII                  ;;
254
;;------------------------------------------------------------------------------------------------;;
255
;> esi = pointer to port no.                                                                      ;;
256
;;------------------------------------------------------------------------------------------------;;
257
;< none                                                                                           ;;
258
;;================================================================================================;;
259
 
260
  .send:
261
; send username/password/path to the server
262
        mcall   send, [controlsocket], buf_cmd, , 0
263
        icall   eax, interface_addr, interface.print, str_newline
264
        icall   eax, interface_addr, interface.set_flags, 0x07 ; reset color
265
 
266
        jmp     wait_for_servercommand
267
 
268
; resolve port if specified
5011 hidnplayr 269
  .do_port:
270
        xor     eax, eax
271
        xor     ebx, ebx
272
  .portloop:
273
        lodsb
274
        cmp     al, 0x20
275
        jbe     .port_done
276
        sub     al, '0'
6436 nisargshah 277
        jnb     @f
278
        mov     eax, str_err_host
279
        jmp     error
280
    @@: cmp     al, 9
281
        jna     @f
282
        mov     eax, str_err_host
283
        jmp     error
284
    @@: lea     ebx, [ebx*4 + ebx]
5011 hidnplayr 285
        shl     ebx, 1
286
        add     ebx, eax
287
        jmp     .portloop
288
 
289
  .port_done:
290
        xchg    bl, bh
291
        mov     [sockaddr1.port], bx
6582 nisargshah 292
        jmp     .done
5011 hidnplayr 293
 
6582 nisargshah 294
  .default_port:
295
        mov     [sockaddr1.port], 21 shl 8
296
 
5011 hidnplayr 297
  .done:
3813 hidnplayr 298
; Say to the user that we're resolving
6582 nisargshah 299
        icall   eax, interface_addr, interface.set_flags, 0x07 ; reset color
300
        icall   eax, interface_addr, interface.print, str_resolve, buf_cmd
3701 hidnplayr 301
; resolve name
302
        push    esp     ; reserve stack place
4922 ashmew2 303
        invoke  getaddrinfo, buf_cmd, 0, 0, esp
3701 hidnplayr 304
        pop     esi
305
; test for error
306
        test    eax, eax
6436 nisargshah 307
        jz      @f
308
        mov     eax, str_err_resolve
309
        jmp     error
310
    @@:
3701 hidnplayr 311
; write results
6582 nisargshah 312
        icall   eax, interface_addr, interface.print, str8 ; ' (',0
3800 hidnplayr 313
        mov     eax, [esi+addrinfo.ai_addr]     ; convert IP address to decimal notation
314
        mov     eax, [eax+sockaddr_in.sin_addr] ;
315
        mov     [sockaddr1.ip], eax             ;
316
        invoke  inet_ntoa, eax                  ;
6582 nisargshah 317
        icall   ebx, interface_addr, interface.print, eax, str9 ; ,')',10,0
3800 hidnplayr 318
        invoke  freeaddrinfo, esi               ; free allocated memory
319
; open the socket
3701 hidnplayr 320
        mcall   socket, AF_INET4, SOCK_STREAM, 0
321
        cmp     eax, -1
6436 nisargshah 322
        jne     @f
323
        mov     eax, str_err_socket
324
        jmp     error
325
    @@: mov     [controlsocket], eax
3800 hidnplayr 326
; connect to the server
6582 nisargshah 327
        icall   eax, interface_addr, interface.print, str_connect
5011 hidnplayr 328
        mcall   connect, [controlsocket], sockaddr1, 18
4918 hidnplayr 329
        cmp     eax, -1
6436 nisargshah 330
        jne     @f
331
        mov     eax, str_err_connect
332
        jmp     error
333
    @@: mov     [status], STATUS_CONNECTING
3813 hidnplayr 334
; Tell the user we're waiting for the server now.
6582 nisargshah 335
        icall   eax, interface_addr, interface.print, str_waiting
3701 hidnplayr 336
 
3813 hidnplayr 337
; Reset 'offset' variable, it's used by the data receiver
3790 hidnplayr 338
        mov     [offset], 0
339
 
6582 nisargshah 340
 
341
;;================================================================================================;;
342
wait_for_servercommand: ;/////////////////////////////////////////////////////////////////////////;;
343
;;------------------------------------------------------------------------------------------------;;
344
;? Checks if any data received from the server is present in buffer.                              ;;
345
;? If not, receives and processes it                                                              ;;
346
;;------------------------------------------------------------------------------------------------;;
347
;>                                                                                                ;;
348
;;------------------------------------------------------------------------------------------------;;
349
;< none                                                                                           ;;
350
;;================================================================================================;;
3813 hidnplayr 351
; Any commands still in our buffer?
3790 hidnplayr 352
        cmp     [offset], 0
3813 hidnplayr 353
        je      .receive                        ; nope, receive some more
3790 hidnplayr 354
        mov     esi, [offset]
4922 ashmew2 355
        mov     edi, buf_cmd
3790 hidnplayr 356
        mov     ecx, [size]
357
        add     ecx, esi
358
        jmp     .byteloop
3701 hidnplayr 359
 
360
; receive socket data
3790 hidnplayr 361
  .receive:
4918 hidnplayr 362
        mcall   26, 9
363
        add     eax, TIMEOUT*100
364
        mov     [timeout], eax
365
  .receive_loop:
366
        mcall   23, 50          ; Wait for event with timeout
367
        mcall   26, 9
368
        cmp     eax, [timeout]
6436 nisargshah 369
        jl      @f
370
        mov     eax, str_err_timeout
371
        jmp     error
372
    @@: mcall   recv, [controlsocket], buf_buffer1, BUFFERSIZE, MSG_DONTWAIT
4918 hidnplayr 373
        test    eax, eax
374
        jnz     .got_data
375
        cmp     ebx, EWOULDBLOCK
6436 nisargshah 376
        je      @f
377
        mov     eax, str_err_recv
378
        jmp     error
379
    @@: jmp     .receive_loop
3701 hidnplayr 380
 
4918 hidnplayr 381
  .got_data:
3790 hidnplayr 382
        mov     [offset], 0
3789 hidnplayr 383
 
4922 ashmew2 384
; extract commands, copy them to "buf_cmd" buffer
385
        lea     ecx, [eax + buf_buffer1]         ; ecx = end pointer
386
        mov     esi, buf_buffer1                 ; esi = current pointer
387
        mov     edi, buf_cmd
3701 hidnplayr 388
  .byteloop:
3789 hidnplayr 389
        cmp     esi, ecx
390
        jae     wait_for_servercommand
3701 hidnplayr 391
        lodsb
392
        cmp     al, 10                          ; excellent, we might have a command
393
        je      .got_command
3789 hidnplayr 394
        cmp     al, 13                          ; just ignore this byte
3701 hidnplayr 395
        je      .byteloop
396
        stosb
397
        jmp     .byteloop
3789 hidnplayr 398
  .got_command:                                 ; we have a newline check if its a command
3790 hidnplayr 399
        cmp     esi, ecx
400
        je      .no_more_data
401
        mov     [offset], esi
402
        sub     ecx, esi
403
        mov     [size], ecx
404
        jmp     .go_cmd
405
  .no_more_data:
406
        mov     [offset], 0
407
  .go_cmd:
4922 ashmew2 408
        lea     ecx, [edi - buf_cmd]                  ; length of command
3701 hidnplayr 409
        xor     al, al
410
        stosb
411
 
6582 nisargshah 412
        icall   eax, interface_addr, interface.set_flags, 0x03 ; change color
413
        icall   eax, interface_addr, interface.print, buf_cmd, str_newline
414
        icall   eax, interface_addr, interface.set_flags, 0x07 ; reset color
3701 hidnplayr 415
 
3789 hidnplayr 416
        jmp     server_parser                   ; parse command
3701 hidnplayr 417
 
3813 hidnplayr 418
 
419
 
6582 nisargshah 420
;;================================================================================================;;
421
wait_for_usercommand: ;///////////////////////////////////////////////////////////////////////////;;
422
;;------------------------------------------------------------------------------------------------;;
423
;? Reads the FTP command entered by the user and compares it with valid FTP commands.             ;;
424
;? Jumps to appropriate handling routine in usercommands.inc                                      ;;
425
;;------------------------------------------------------------------------------------------------;;
426
;> status = socket connection status                                                              ;;
427
;> buf_cmd = command entered by the user                                                          ;;
428
;;------------------------------------------------------------------------------------------------;;
429
;< none                                                                                           ;;
430
;;================================================================================================;;
3701 hidnplayr 431
 
4922 ashmew2 432
; Are there any files in the transfer queue?
433
 
5011 hidnplayr 434
        cmp     [queued], 0
4922 ashmew2 435
        ja      transfer_queued                 ; Yes, transfer those first.
6582 nisargshah 436
 
3813 hidnplayr 437
; change color to green for user input
6582 nisargshah 438
        icall   eax, interface_addr, interface.set_flags, 0x0a
3701 hidnplayr 439
 
3813 hidnplayr 440
; If we are not yet connected, request username/password
6582 nisargshah 441
 
3701 hidnplayr 442
        cmp     [status], STATUS_CONNECTED
6582 nisargshah 443
        je      arg_handler.get_username
3701 hidnplayr 444
 
445
        cmp     [status], STATUS_NEEDPASSWORD
6582 nisargshah 446
        je      arg_handler.get_pass
3701 hidnplayr 447
 
6582 nisargshah 448
        ijmp    eax, interface_addr, interface.get_cmd
3794 hidnplayr 449
 
6582 nisargshah 450
  .parse_cmd:
4922 ashmew2 451
        cmp     dword[buf_cmd], "cwd "
3790 hidnplayr 452
        je      cmd_cwd
453
 
4922 ashmew2 454
        cmp     dword[buf_cmd], "mkd "
3813 hidnplayr 455
        je      cmd_mkd
3793 hidnplayr 456
 
4922 ashmew2 457
        cmp     dword[buf_cmd], "rmd "
3813 hidnplayr 458
        je      cmd_rmd
459
 
4922 ashmew2 460
        cmp     dword[buf_cmd], "pwd" + 10 shl 24
3794 hidnplayr 461
        je      cmd_pwd
462
 
4922 ashmew2 463
        cmp     dword[buf_cmd], "bye" + 10 shl 24
3813 hidnplayr 464
        je      cmd_bye
465
 
4922 ashmew2 466
        cmp     dword[buf_cmd], "rdir"
5011 hidnplayr 467
        je      cmd_rdir
468
 
4922 ashmew2 469
        cmp     byte[buf_cmd+4], " "
3813 hidnplayr 470
        jne     @f
471
 
4922 ashmew2 472
        cmp     dword[buf_cmd], "lcwd"
3813 hidnplayr 473
        je      cmd_lcwd
474
 
4922 ashmew2 475
        cmp     dword[buf_cmd], "retr"
3813 hidnplayr 476
        je      cmd_retr
477
 
4922 ashmew2 478
        cmp     dword[buf_cmd], "stor"
3800 hidnplayr 479
        je      cmd_stor
3793 hidnplayr 480
 
4922 ashmew2 481
        cmp     dword[buf_cmd], "dele"
3800 hidnplayr 482
        je      cmd_dele
483
 
3813 hidnplayr 484
  @@:
4922 ashmew2 485
        cmp     byte[buf_cmd+4], 10
3813 hidnplayr 486
        jne     @f
3800 hidnplayr 487
 
4922 ashmew2 488
        cmp     dword[buf_cmd], "list"
3813 hidnplayr 489
        je      cmd_list
3802 hidnplayr 490
 
4922 ashmew2 491
        cmp     dword[buf_cmd], "help"
3813 hidnplayr 492
        je      cmd_help
3804 hidnplayr 493
 
4922 ashmew2 494
        cmp     dword[buf_cmd], "cdup"
3804 hidnplayr 495
        je      cmd_cdup
496
 
6582 nisargshah 497
        cmp     dword[buf_cmd], "abor"
498
        je      cmd_abor
499
 
3813 hidnplayr 500
  @@:
501
; Uh oh.. unknown command, tell the user and wait for new input
6582 nisargshah 502
        icall   eax, interface_addr, interface.print, str_unknown
3701 hidnplayr 503
        jmp     wait_for_usercommand
504
 
505
 
5011 hidnplayr 506
; files for rdir operation are queued
507
transfer_queued:
3701 hidnplayr 508
 
5011 hidnplayr 509
        mov     esi, [ptr_queue]                ; always pointing to current part of ptr_fname_start
510
        mov     edi, buf_cmd+5                  ; always point to filename for retr command
511
  .build_filename:
512
        lodsb
513
        stosb
514
        cmp     al, 10
515
        je      .get_file                       ; filename ends with character 10
516
        test    al, al
517
        jnz     .build_filename
518
 
519
        ; Error occured, we reached the end of the buffer before [queued] reached 0
520
        mov     [queued], 0
521
        mcall   68, 13, [ptr_fname]             ; free buffer
522
        test    eax, eax
523
        jz      error_heap
524
        jmp     wait_for_usercommand
525
 
526
  .get_file:
527
        mov     byte[edi], 0                    ; end filename with 0 byte
528
        mov     [ptr_queue], esi
529
        dec     [queued]
530
        jnz     cmd_retr
531
 
532
        mcall   68, 13, [ptr_fname]             ; free buffer
533
        test    eax, eax
534
        jz      error_heap
535
        jmp     cmd_retr
536
 
537
 
538
 
539
open_dataconnection:
540
 
541
        test    [mode], 1
542
        jnz     .active
543
 
544
        mcall   send, [controlsocket], str_PASV, str_PASV.length, 0
3701 hidnplayr 545
        ret
546
 
5011 hidnplayr 547
  .active:
548
        mcall   socket, AF_INET4, SOCK_STREAM, 0
549
        cmp     eax, -1
6436 nisargshah 550
        jne     @f
551
        mov     eax, str_err_socket
552
        jmp     error
553
    @@: mov     [datasocket], eax
5011 hidnplayr 554
 
555
        mov     ax, [acti_port_start]
556
        xchg    al, ah
557
        mov     [sockaddr2.port], ax
558
 
559
        mcall   bind, [datasocket], sockaddr2, 18
560
        cmp     eax, -1
6436 nisargshah 561
        jne     @f
562
        mov     eax, str_err_bind
563
        jmp     error
564
    @@:
5011 hidnplayr 565
 
566
        mcall   listen, [datasocket], 1
567
        cmp     eax, -1
6436 nisargshah 568
        jne     @f
569
        mov     eax, str_err_listen
570
        jmp     error
571
    @@:
5011 hidnplayr 572
 
573
        mov     dword[buf_buffer1], 'PORT'
574
        mov     byte[buf_buffer1+4], ' '
575
        mov     edi, buf_buffer1+5
576
        mov     esi, str_active_ip
577
  .loop:
578
        lodsb
579
        test    al, al
580
        jz      .ip_ok
581
        stosb
582
        jmp     .loop
583
  .ip_ok:
584
        mov     al, ','
585
        stosb
586
        movzx   eax, byte[sockaddr2.port+0]
587
        call    dword_ascii
588
        mov     al, ','
589
        stosb
590
        movzx   eax, byte[sockaddr2.port+1]
591
        call    dword_ascii
592
        mov     ax, 0x0a0d
593
        stosw
594
        lea     esi, [edi - buf_buffer1]
595
        mcall   send, [controlsocket], buf_buffer1, , 0
596
 
597
        mcall   accept, [datasocket], sockaddr2, 18        ; time to accept the awaiting connection..
598
        cmp     eax, -1
6436 nisargshah 599
        jne     @f
600
        mov     eax, str_err_accept
601
        jmp     error
602
    @@: push    eax
5011 hidnplayr 603
        mcall   close, [datasocket]
604
        pop     [datasocket]
605
 
606
        mcall   recv, [controlsocket], buf_buffer1, BUFFERSIZE, 0
607
 
3701 hidnplayr 608
        ret
609
 
5011 hidnplayr 610
; eax = input
611
; edi = ptr where to write
612
dword_ascii:
613
 
614
        push    edx ebx ecx
615
        mov     ebx, 10
616
        xor     ecx, ecx
617
 
618
       @@:
619
        xor     edx, edx
620
        div     ebx
621
        add     edx, '0'
622
        push    dx
623
        inc     ecx
624
        test    eax, eax
625
        jnz     @r
626
 
627
       @@:
628
        pop     ax
629
        stosb
630
        dec     ecx
631
        jnz     @r
632
 
633
        pop     ecx ebx edx
634
        ret
635
 
6582 nisargshah 636
 
637
;;================================================================================================;;
638
write_to_file: ;//////////////////////////////////////////////////////////////////////////////////;;
639
;;------------------------------------------------------------------------------------------------;;
640
;? Writes input buffer to log file                                                                ;;
641
;;------------------------------------------------------------------------------------------------;;
642
;> eax = pointer to buffer                                                                        ;;
643
;> ecx = size of buffer                                                                           ;;
644
;;------------------------------------------------------------------------------------------------;;
645
;< eax = status of SF 70.3                                                                        ;;
646
;;================================================================================================;;
647
        mov     [filestruct2.subfn], 3
648
        m2m     [filestruct2.offset], [logfile_offset]
649
        mov     [filestruct2.size], ecx
650
        mov     [filestruct2.ptr], eax
651
        mov     [filestruct2.name], log_file
652
        mcall   70, filestruct2
653
        test    eax, eax
654
        jz      @f
655
        mov     [logfile_offset], -1 ; disable logging
656
        call    error_fs
657
        icall   ebx, interface_addr, interface.print, str_no_logging
658
        ret
659
      @@:
660
        mov     eax, [logfile_offset]
661
        add     eax, ecx
662
        mov     [logfile_offset], eax
663
        ret
664
 
665
;;================================================================================================;;
666
error: ;//////////////////////////////////////////////////////////////////////////////////////////;;
667
;;------------------------------------------------------------------------------------------------;;
668
;? Generic error routine. Prints the error string passed to it.                                   ;;
669
;;------------------------------------------------------------------------------------------------;;
670
;> eax = pointer to the error string                                                              ;;
671
;;------------------------------------------------------------------------------------------------;;
672
;< none                                                                                           ;;
673
;;================================================================================================;;
6436 nisargshah 674
        push    eax
6582 nisargshah 675
        icall   ebx, interface_addr, interface.set_flags, 0x0c ; print errors in red
6436 nisargshah 676
        pop     eax
6582 nisargshah 677
        icall   ebx, interface_addr, interface.print, eax
5011 hidnplayr 678
        jmp     wait_for_keypress
679
 
6582 nisargshah 680
 
681
; Error handling block for filesystem errors
682
error_fs:
683
 
684
        cmp     eax, 12
685
        jne     @f
686
        mov     ebx, str_fs_err_12
687
  @@:
688
        cmp     eax, 11
689
        jne     @f
690
        mov     ebx, str_fs_err_11
691
  @@:
692
        cmp     eax, 10
693
        jne     @f
694
        mov     ebx, str_fs_err_10
695
  @@:
696
        cmp     eax, 9
697
        jne     @f
698
        mov     ebx, str_fs_err_9
699
  @@:
700
        cmp     eax, 8
701
        jne     @f
702
        mov     ebx, str_fs_err_8
703
  @@:
704
        cmp     eax, 7
705
        jne     @f
706
        mov     ebx, str_fs_err_7
707
  @@:
708
        cmp     eax, 6
709
        jne     @f
710
        mov     ebx, str_fs_err_6
711
  @@:
712
        cmp     eax, 5
713
        jne     @f
714
        mov     ebx, str_fs_err_5
715
  @@:
716
        cmp     eax, 3
717
        jne     @f
718
        mov     ebx, str_fs_err_3
719
  @@:
720
        cmp     eax, 2
721
        jne     @f
722
        mov     ebx, str_fs_err_2
723
  @@:
724
        mov     edi, fs_error_code
725
        call    dword_ascii    ; convert error code in eax to ascii
726
        icall   eax, interface_addr, interface.set_flags, 0x0c ; print errors in red
727
        icall   eax, interface_addr, interface.print, str_err_fs, fs_error_code, ebx
728
        mov     word[fs_error_code], '  '   ; clear error code for next time
729
        icall   eax, interface_addr, interface.set_flags, 0x0a
730
 
731
        ret
732
 
4922 ashmew2 733
error_heap:
6582 nisargshah 734
        icall   eax, interface_addr, interface.set_flags, 0x0c ; print errors in red
735
        icall   eax, interface_addr, interface.print, str_err_heap
5011 hidnplayr 736
 
3813 hidnplayr 737
wait_for_keypress:
5011 hidnplayr 738
        mcall   close, [controlsocket]
6582 nisargshah 739
        icall   eax, interface_addr, interface.set_flags, 0x07 ; reset color to grey
740
        icall   eax, interface_addr, interface.print, str_push
741
        ijmp    eax, interface_addr, interface.error
3701 hidnplayr 742
 
743
exit:
5011 hidnplayr 744
        mcall   close, [controlsocket]
745
exit2:
3701 hidnplayr 746
        mcall   -1
747
 
748
 
749
 
750
; data
3813 hidnplayr 751
str_title       db 'FTP client',0
4918 hidnplayr 752
str_welcome     db 'FTP client for KolibriOS v0.12',10
6582 nisargshah 753
                db 10,0
754
str_srv_addr    db 'Please enter ftp server address.',10,0
3800 hidnplayr 755
 
3813 hidnplayr 756
str_prompt      db '> ',0
757
str_resolve     db 'Resolving ',0
758
str_newline     db 10,0
759
str_err_resolve db 10,'Name resolution failed.',10,0
6436 nisargshah 760
str_err_socket  db 10,'[75,0 socket]: Error creating a socket',10,0
761
str_err_bind    db 10,'[75,2 bind]: Error binding to socket',10,0
762
str_err_listen  db 10,'[75,3 listen]: Cannot accept incoming connections',10,0
763
str_err_accept  db 10,'[75,5 accept]: Error accepting a connection',10,0
764
str_err_recv    db 10,'[75,7 recv]: Error receiving data from server',10,0
5011 hidnplayr 765
str_err_heap    db 10,'Cannot allocate memory from heap.',10,0
4918 hidnplayr 766
str_err_timeout db 10,'Timeout - no response from server.',10,0
6436 nisargshah 767
str_err_connect db 10,'[75,4 connect]: Cannot connect to the server.',10,0
5011 hidnplayr 768
str_err_host    db 10,'Invalid hostname.',10,0
6436 nisargshah 769
str_err_params  db 10,'Invalid parameters',10,0
6582 nisargshah 770
str_err_fs      db 10,'File system error: code ',0
771
fs_error_code   db '  ',0    ; file system error code
772
str_fs_err_2    db ' [Function is not supported for the given file system]',10,0
773
str_fs_err_3    db ' [Unknown file system]',10,0
774
str_fs_err_5    db ' [File/Folder not found]',10,0
775
str_fs_err_6    db ' [End of file, EOF]',10,0
776
str_fs_err_7    db ' [Pointer lies outside of application memory]',10,0
777
str_fs_err_8    db ' [Disk is full]',10,0
778
str_fs_err_9    db ' [File system error]',10,0
779
str_fs_err_10   db ' [Access denied]',10,0
780
str_fs_err_11   db ' [Device error]',10,0
781
str_fs_err_12   db ' [File system requires more memory]',10,0
3813 hidnplayr 782
str8            db ' (',0
783
str9            db ')',10,0
784
str_push        db 'Push any key to continue.',0
785
str_connect     db 'Connecting...',10,0
786
str_waiting     db 'Waiting for welcome message.',10,0
787
str_user        db "username: ",0
788
str_pass        db "password: ",0
6582 nisargshah 789
str_port        db "port (default 21): ",0
790
str_path        db "path (optional): ",0
3813 hidnplayr 791
str_unknown     db "Unknown command or insufficient parameters - type help for more information.",10,0
792
str_lcwd        db "Local working directory is now: ",0
6582 nisargshah 793
str_bytes_done  db '          ',0
794
str_downloaded  db 'Downloaded ',0
795
str_bytes       db ' bytes',13,0
796
str_args_err    db 'Invalid arguments. USAGE: ftpc [-cli] [ftp://username:password@server:port/path]',10,0
3701 hidnplayr 797
 
3813 hidnplayr 798
str_open        db "opening data socket",10,0
4922 ashmew2 799
str_close       db 10,"closing data socket",10,0
800
str_dot         db '.',0
3701 hidnplayr 801
 
3813 hidnplayr 802
str_help        db "available commands:",10
803
                db 10
804
                db "bye             - close the connection",10
805
                db "cdup            - change to parent of current directory on the server",10
806
                db "cwd  - change working directoy on the server",10
807
                db "dele      - delete file from the server",10
808
                db "list            - list files and folders in current server directory",10
809
                db "lcwd      - change local working directory",10
810
                db "mkd  - make directory on the server",10
811
                db "pwd             - print server working directory",10
812
                db "retr      - retreive file from the server",10
813
                db "rmd  - remove directory from the server",10
814
                db "stor      - store file on the server",10
6582 nisargshah 815
                db "rdir            - retreive all files from current server dir",10
3813 hidnplayr 816
                db 10,0
817
 
5011 hidnplayr 818
str_ini         db '.ini', 0
819
str_active      db 'active', 0
820
str_port_start  db 'port_start', 0
821
str_port_stop   db 'port_stop', 0
822
str_ip          db 'ip', 0
823
str_dir         db 'dir', 0
824
str_general     db 'general', 0
6582 nisargshah 825
str_logfile     db 'logfile',0
826
str_no_logging  db 'Error writing to log file. Logging disabled',0
3821 hidnplayr 827
 
5011 hidnplayr 828
queued          dd 0
829
mode            db 0    ; passive = 0, active = 1
830
 
6582 nisargshah 831
 
3821 hidnplayr 832
; FTP strings
833
 
834
str_PASV        db 'PASV',13,10
835
.length = $ - str_PASV
836
 
3701 hidnplayr 837
sockaddr1:
838
        dw AF_INET4
5011 hidnplayr 839
.port   dw ?
840
.ip     dd ?
3701 hidnplayr 841
        rb 10
842
 
843
sockaddr2:
844
        dw AF_INET4
5011 hidnplayr 845
.port   dw ?
846
.ip     dd ?
3701 hidnplayr 847
        rb 10
848
 
6582 nisargshah 849
struc interface
850
{
851
    .init           dd 0
852
    .server_addr    dd 4
853
    .get_username   dd 8
854
    .get_cmd        dd 12
855
    .print          dd 16
856
    .set_flags      dd 20
857
    .list           dd 24
858
    .progress       dd 28
859
    .error          dd 32
860
}
861
interface interface
862
 
3701 hidnplayr 863
; import
864
align 4
865
@IMPORT:
866
 
6582 nisargshah 867
library network, 'network.obj', libini, 'libini.obj'
3701 hidnplayr 868
 
6582 nisargshah 869
import  network, \
870
        getaddrinfo,    'getaddrinfo', \
3701 hidnplayr 871
        freeaddrinfo,   'freeaddrinfo', \
872
        inet_ntoa,      'inet_ntoa'
873
 
6582 nisargshah 874
import  libini, \
875
        ini.get_str,    'ini_get_str', \
5011 hidnplayr 876
        ini.get_int,    'ini_get_int'
3701 hidnplayr 877
 
5011 hidnplayr 878
 
3701 hidnplayr 879
i_end:
880
 
3813 hidnplayr 881
; uninitialised data
882
 
6582 nisargshah 883
interface_addr  rd 1
884
 
3794 hidnplayr 885
status          db ?
886
 
6582 nisargshah 887
file_size       dd ?
888
 
5011 hidnplayr 889
controlsocket   dd ?
3701 hidnplayr 890
datasocket      dd ?
3790 hidnplayr 891
offset          dd ?
892
size            dd ?
3800 hidnplayr 893
operation       dd ?
4918 hidnplayr 894
timeout         dd ?
895
 
5011 hidnplayr 896
ptr_fname       dd ?
897
size_fname      dd ?
898
ptr_queue       dd ?
899
 
900
acti_port_start dw ?
901
acti_port_stop  dw ?
902
acti_port       dw ?
903
 
904
str_active_ip   rb 16
905
 
3800 hidnplayr 906
filestruct:
5011 hidnplayr 907
  .subfn        dd ?
908
  .offset       dd ?
909
                dd ?
910
  .size         dd ?
911
  .ptr          dd ?
912
  .name         rb 1024
3800 hidnplayr 913
 
6582 nisargshah 914
filestruct2:
915
  .subfn        dd ?
916
  .offset       dd ?
917
                dd 0
918
  .size         dd ?
919
  .ptr          dd ?
920
                db 0
921
  .name         dd ?
922
 
923
folder_buf      rb 40
924
 
925
 
4922 ashmew2 926
buf_buffer1     rb BUFFERSIZE+1
927
buf_buffer2     rb BUFFERSIZE+1
5011 hidnplayr 928
buf_cmd         rb 1024                 ; buffer for holding command string
6582 nisargshah 929
log_file        rb 512 ; holds log file path
930
logfile_offset  rd 1
3794 hidnplayr 931
 
5011 hidnplayr 932
path            rb 1024
933
 
6582 nisargshah 934
initial_login   rb 1
6394 nisargshah 935
param_user      rb 1024
936
param_password  rb 1024
937
param_server_addr rb 1024
938
param_path      rb 1024
6582 nisargshah 939
param_port      rb 6
6394 nisargshah 940
 
6582 nisargshah 941
sc system_colors
942
rb 1024
943
 
3701 hidnplayr 944
mem: