Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3701 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2013. All rights reserved.         ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  ftpc.asm - FTP client for KolibriOS                            ;;
7
;;                                                                 ;;
8
;;  Written by hidnplayr@kolibrios.org                             ;;
9
;;                                                                 ;;
10
;;          GNU GENERAL PUBLIC LICENSE                             ;;
11
;;             Version 2, June 1991                                ;;
12
;;                                                                 ;;
13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14
 
15
format binary as ""
16
 
3800 hidnplayr 17
BUFFERSIZE              = 4096
3701 hidnplayr 18
 
19
STATUS_CONNECTING       = 0
20
STATUS_CONNECTED        = 1
21
STATUS_NEEDPASSWORD     = 2
22
STATUS_LOGGED_IN        = 3
23
 
3800 hidnplayr 24
OPERATION_LIST          = 0
25
OPERATION_RETR          = 1
26
OPERATION_STOR          = 2
27
 
3701 hidnplayr 28
use32
29
; standard header
30
        db      'MENUET01'      ; signature
31
        dd      1               ; header version
32
        dd      start           ; entry point
33
        dd      i_end           ; initialized size
34
        dd      mem+0x1000      ; required memory
35
        dd      mem+0x1000      ; stack pointer
36
        dd      s               ; parameters
37
        dd      0               ; path
38
 
39
include '../../macros.inc'
40
purge mov,add,sub
41
include '../../proc32.inc'
42
include '../../dll.inc'
43
include '../../network.inc'
44
 
45
include 'usercommands.inc'
46
include 'servercommands.inc'
47
 
48
; entry point
49
start:
50
 
3789 hidnplayr 51
        mcall   40, 0
3701 hidnplayr 52
; load libraries
53
        stdcall dll.Load, @IMPORT
54
        test    eax, eax
55
        jnz     exit
56
; initialize console
3789 hidnplayr 57
        invoke  con_start, 1
3792 hidnplayr 58
        invoke  con_init, 80, 25, 80, 250, title
3701 hidnplayr 59
 
60
; Check for parameters
61
        cmp     byte [s], 0
62
        jne     resolve
63
 
64
main:
3789 hidnplayr 65
        invoke  con_cls
3701 hidnplayr 66
; Welcome user
3789 hidnplayr 67
        invoke  con_write_asciiz, str1
3701 hidnplayr 68
 
69
; write prompt
3789 hidnplayr 70
        invoke  con_set_flags, 0x0a
71
        invoke  con_write_asciiz, str2
3701 hidnplayr 72
; read string
73
        mov     esi, s
3789 hidnplayr 74
        invoke  con_gets, esi, 256
75
        invoke  con_write_asciiz, str4  ; newline
76
        invoke  con_set_flags, 0x07
3701 hidnplayr 77
; check for exit
78
        test    eax, eax
79
        jz      done
80
        cmp     byte [esi], 10
81
        jz      done
82
 
83
resolve:
84
; delete terminating '\n'
85
        mov     esi, s
86
  @@:
87
        lodsb
88
        cmp     al, 0x20
89
        ja      @r
90
        mov     byte [esi-1], 0
91
 
3789 hidnplayr 92
        invoke  con_write_asciiz, str3
93
        invoke  con_write_asciiz, s
3701 hidnplayr 94
 
95
; resolve name
96
        push    esp     ; reserve stack place
3789 hidnplayr 97
        invoke  getaddrinfo, s, 0, 0, esp
3701 hidnplayr 98
        pop     esi
99
; test for error
100
        test    eax, eax
101
        jnz     fail
102
 
103
; write results
3800 hidnplayr 104
        invoke  con_write_asciiz, str8          ; ' (',0
105
        mov     eax, [esi+addrinfo.ai_addr]     ; convert IP address to decimal notation
106
        mov     eax, [eax+sockaddr_in.sin_addr] ;
107
        mov     [sockaddr1.ip], eax             ;
108
        invoke  inet_ntoa, eax                  ;
109
        invoke  con_write_asciiz, eax           ; print ip
110
        invoke  freeaddrinfo, esi               ; free allocated memory
111
        invoke  con_write_asciiz, str9          ; ')',10,0
3701 hidnplayr 112
 
3800 hidnplayr 113
; open the socket
3701 hidnplayr 114
        mcall   socket, AF_INET4, SOCK_STREAM, 0
115
        cmp     eax, -1
3789 hidnplayr 116
        je      socket_error
3701 hidnplayr 117
        mov     [socketnum], eax
118
 
3800 hidnplayr 119
; connect to the server
3789 hidnplayr 120
        invoke  con_write_asciiz, str11
3701 hidnplayr 121
        mcall   connect, [socketnum], sockaddr1, 18
122
        mov     [status], STATUS_CONNECTING
123
 
3800 hidnplayr 124
        invoke  con_write_asciiz, str12         ; 'waiting for welcome'
3701 hidnplayr 125
 
3790 hidnplayr 126
        mov     [offset], 0
127
 
3789 hidnplayr 128
wait_for_servercommand:
3701 hidnplayr 129
 
3790 hidnplayr 130
        cmp     [offset], 0
131
        je      .receive
132
        mov     esi, [offset]
133
        mov     edi, s
134
        mov     ecx, [size]
135
        add     ecx, esi
136
        jmp     .byteloop
3701 hidnplayr 137
 
138
; receive socket data
3790 hidnplayr 139
  .receive:
3789 hidnplayr 140
        mcall   recv, [socketnum], buffer_ptr, BUFFERSIZE, 0
3701 hidnplayr 141
        inc     eax
3789 hidnplayr 142
        jz      socket_error
3701 hidnplayr 143
        dec     eax
3789 hidnplayr 144
        jz      wait_for_servercommand
3701 hidnplayr 145
 
3790 hidnplayr 146
        mov     [offset], 0
3789 hidnplayr 147
 
3701 hidnplayr 148
; extract commands, copy them to "s" buffer
3789 hidnplayr 149
        lea     ecx, [eax + buffer_ptr]         ; ecx = end pointer
3701 hidnplayr 150
        mov     esi, buffer_ptr                 ; esi = current pointer
151
        mov     edi, s
152
  .byteloop:
3789 hidnplayr 153
        cmp     esi, ecx
154
        jae     wait_for_servercommand
3701 hidnplayr 155
        lodsb
156
        cmp     al, 10                          ; excellent, we might have a command
157
        je      .got_command
3789 hidnplayr 158
        cmp     al, 13                          ; just ignore this byte
3701 hidnplayr 159
        je      .byteloop
160
        stosb
161
        jmp     .byteloop
3789 hidnplayr 162
  .got_command:                                 ; we have a newline check if its a command
3790 hidnplayr 163
        cmp     esi, ecx
164
        je      .no_more_data
165
        mov     [offset], esi
166
        sub     ecx, esi
167
        mov     [size], ecx
168
        jmp     .go_cmd
169
  .no_more_data:
170
        mov     [offset], 0
171
  .go_cmd:
3701 hidnplayr 172
        xor     al, al
173
        stosb
174
 
3789 hidnplayr 175
        invoke  con_set_flags, 0x03             ; change color
176
        invoke  con_write_asciiz, s             ; print servercommand
177
        invoke  con_write_asciiz, str4          ; newline
3800 hidnplayr 178
        invoke  con_set_flags, 0x07             ; reset color
3701 hidnplayr 179
 
3789 hidnplayr 180
        jmp     server_parser                   ; parse command
3701 hidnplayr 181
 
3789 hidnplayr 182
wait_for_usercommand:
3701 hidnplayr 183
 
3789 hidnplayr 184
        invoke  con_set_flags, 0x0a
3701 hidnplayr 185
 
186
        cmp     [status], STATUS_CONNECTED
187
        je      .connected
188
 
189
        cmp     [status], STATUS_NEEDPASSWORD
190
        je      .needpass
191
 
192
; write prompt
3789 hidnplayr 193
        invoke  con_write_asciiz, str2
3701 hidnplayr 194
; read string
195
        mov     esi, s
3789 hidnplayr 196
        invoke  con_gets, esi, 256
3794 hidnplayr 197
 
198
        invoke  con_write_asciiz, str4          ; newline
3789 hidnplayr 199
        invoke  con_set_flags, 0x07
3701 hidnplayr 200
 
201
        cmp     dword[s], "list"
202
        je      cmd_list
203
 
204
        cmp     dword[s], "help"
205
        je      cmd_help
206
 
3790 hidnplayr 207
        cmp     dword[s], "cwd "
208
        je      cmd_cwd
209
 
3793 hidnplayr 210
        cmp     dword[s], "retr"
211
        je      cmd_retr
212
 
3794 hidnplayr 213
        cmp     dword[s], "pwd" + 10 shl 24
214
        je      cmd_pwd
215
 
3800 hidnplayr 216
        cmp     dword[s], "stor"
217
        je      cmd_stor
3793 hidnplayr 218
 
3800 hidnplayr 219
        cmp     dword[s], "dele"
220
        je      cmd_dele
221
 
222
        cmp     dword[s], "bye" + 10 shl 24
223
        je      cmd_bye
224
 
3802 hidnplayr 225
        cmp     dword[s], "lcwd"
226
        je      cmd_lcwd
227
 
3804 hidnplayr 228
        cmp     dword[s], "mkd "
229
        je      cmd_mkd
230
 
231
        cmp     dword[s], "rmd "
232
        je      cmd_rmd
233
 
234
        cmp     dword[s], "cdup"
235
        je      cmd_cdup
236
 
3789 hidnplayr 237
        invoke  con_write_asciiz, str_unknown
3701 hidnplayr 238
        jmp     wait_for_usercommand
239
 
240
 
241
  .connected:
242
 
3789 hidnplayr 243
        invoke  con_write_asciiz, str_user
3701 hidnplayr 244
        mov     dword[s], "USER"
245
        mov     byte[s+4], " "
246
        jmp     .send
247
 
248
 
249
  .needpass:
250
 
3789 hidnplayr 251
        invoke  con_write_asciiz, str_pass
3701 hidnplayr 252
        mov     dword[s], "PASS"
253
        mov     byte[s+4], " "
3803 hidnplayr 254
        invoke  con_set_flags, 0x00     ; black text on black background for password
3701 hidnplayr 255
 
256
  .send:
257
; read string
258
        mov     esi, s+5
3789 hidnplayr 259
        invoke  con_gets, esi, 256
3701 hidnplayr 260
 
3800 hidnplayr 261
; find end of string
3701 hidnplayr 262
        mov     edi, s+5
263
        mov     ecx, 256
264
        xor     al, al
265
        repne   scasb
266
        lea     esi, [edi-s-1]
3800 hidnplayr 267
; and send it to the server
3789 hidnplayr 268
        mcall   send, [socketnum], s, , 0
3701 hidnplayr 269
 
3789 hidnplayr 270
        invoke  con_write_asciiz, str4  ; newline
3800 hidnplayr 271
        invoke  con_set_flags, 0x07     ; reset color
3789 hidnplayr 272
        jmp     wait_for_servercommand
3701 hidnplayr 273
 
274
 
275
 
3800 hidnplayr 276
open_dataconnection:                    ; only passive for now..
3701 hidnplayr 277
        cmp     [status], STATUS_LOGGED_IN
278
        jne     .fail
279
 
280
        mov     dword[s], "PASV"
281
        mov     byte[s+4], 10
3789 hidnplayr 282
        mcall   send, [socketnum], s, 5, 0
3701 hidnplayr 283
        ret
284
 
285
  .fail:
3789 hidnplayr 286
        invoke  con_write_asciiz, str6
3701 hidnplayr 287
        ret
288
 
289
 
290
 
3789 hidnplayr 291
socket_error:
292
        invoke  con_write_asciiz, str6
3701 hidnplayr 293
        jmp     fail.wait
294
 
295
fail:
3789 hidnplayr 296
        invoke  con_write_asciiz, str5
3701 hidnplayr 297
  .wait:
3789 hidnplayr 298
        invoke  con_write_asciiz, str10
299
        invoke  con_getch2
3701 hidnplayr 300
        jmp     main
301
 
302
done:
3789 hidnplayr 303
        invoke  con_exit, 1
304
 
3701 hidnplayr 305
exit:
306
        mcall   close, [socketnum]
307
        mcall   -1
308
 
309
 
310
 
311
; data
312
title   db 'FTP client',0
3804 hidnplayr 313
str1    db 'FTP client for KolibriOS v0.07',10,10,'Please enter ftp server address.',10,0
3701 hidnplayr 314
str2    db '> ',0
315
str3    db 'Resolving ',0
316
str4    db 10,0
317
str5    db 10,'Name resolution failed.',10,0
318
str6    db 10,'Socket error.',10,0
319
str8    db ' (',0
320
str9    db ')',10,0
321
str10   db 'Push any key to continue.',0
3789 hidnplayr 322
str11   db 'Connecting...',10,0
323
str12   db 'Waiting for welcome message.',10,0
3701 hidnplayr 324
str_user db "username: ",0
325
str_pass db "password: ",0
3804 hidnplayr 326
str_unknown db "unknown command or insufficient parameters",10,0
3802 hidnplayr 327
str_lcwd db "local working directory is now: ",0
3800 hidnplayr 328
 
3794 hidnplayr 329
str_help db "available commands:",10
3804 hidnplayr 330
         db "help - help",10
331
         db 10
3800 hidnplayr 332
         db "bye  - close connection",10
3804 hidnplayr 333
         db "cdup - change to parent of current directory on server",10
3800 hidnplayr 334
         db "cwd  - change working directoy on server",10
335
         db "dele - delete file from server",10
336
         db "list - list files and folders in current directory",10
3802 hidnplayr 337
         db "lcwd - change local working directory",10
3804 hidnplayr 338
         db "mkd  - make directory on the server",10
3800 hidnplayr 339
         db "pwd  - print working directory",10
340
         db "retr - retreive file from server",10
3804 hidnplayr 341
         db "rmd  - remove directory from the server",10
3800 hidnplayr 342
         db "stor - store file on server",10
343
         db 10,0
3701 hidnplayr 344
 
345
str_open db "opening data socket",10,0
346
 
347
sockaddr1:
348
        dw AF_INET4
349
.port   dw 0x1500       ; 21
350
.ip     dd 0
351
        rb 10
352
 
353
sockaddr2:
354
        dw AF_INET4
355
.port   dw 0
356
.ip     dd 0
357
        rb 10
358
 
359
; import
360
align 4
361
@IMPORT:
362
 
363
library network, 'network.obj', console, 'console.obj'
364
 
365
import  network,        \
366
        getaddrinfo,    'getaddrinfo',  \
367
        freeaddrinfo,   'freeaddrinfo', \
368
        inet_ntoa,      'inet_ntoa'
369
 
370
import  console,        \
371
        con_start,      'START',        \
372
        con_init,       'con_init',     \
373
        con_write_asciiz,'con_write_asciiz',     \
374
        con_exit,       'con_exit',     \
375
        con_gets,       'con_gets',\
376
        con_cls,        'con_cls',\
377
        con_getch2,     'con_getch2',\
378
        con_set_cursor_pos, 'con_set_cursor_pos',\
379
        con_write_string, 'con_write_string',\
3789 hidnplayr 380
        con_get_flags,  'con_get_flags', \
381
        con_set_flags,  'con_set_flags'
3701 hidnplayr 382
 
383
 
384
i_end:
385
 
3794 hidnplayr 386
status          db ?
3701 hidnplayr 387
active_passive  db ?
3794 hidnplayr 388
 
3701 hidnplayr 389
socketnum       dd ?
390
datasocket      dd ?
3790 hidnplayr 391
offset          dd ?
392
size            dd ?
3800 hidnplayr 393
operation       dd ?
3701 hidnplayr 394
 
3800 hidnplayr 395
filestruct:
396
.subfn  dd ?
397
.offset dd ?
398
        dd ?
399
.size   dd ?
400
.ptr    dd ?
401
.name   rb 1024
402
 
3794 hidnplayr 403
buffer_ptr      rb BUFFERSIZE+1
404
buffer_ptr2     rb BUFFERSIZE+1
405
 
3790 hidnplayr 406
s               rb 1024
3701 hidnplayr 407
 
408
mem: