Subversion Repositories Kolibri OS

Rev

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

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