Subversion Repositories Kolibri OS

Rev

Rev 2562 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1.  
  2.  
  3.  
  4. align 4
  5. parse_cmd:                              ; esi must point to command
  6.  
  7.         cmp     byte [esi+3], 0x20
  8.         jae     @f
  9.         mov     byte [esi+3], 0
  10.        @@:
  11.  
  12.         mov     eax, [esi]
  13.         and     eax, not 0x20202020     ; convert to upper case
  14.                                         ; (also convert spaces to null)
  15.         mov     edi, commands           ; list of commands to scan
  16.   .scanloop:
  17.         cmp     eax, [edi]
  18.         jne     .try_next
  19.  
  20.         jmp     dword [edi+4]
  21.  
  22.   .try_next:
  23.         add     edi, 8
  24.         cmp     byte [edi], 0
  25.         jne     .scanloop
  26.  
  27.   .error:
  28.         mcall   send, [socketnum2], str500, str500.length, 0
  29.  
  30.         ret
  31.  
  32.  
  33. align 4
  34. commands:               ; all commands must be in uppercase
  35.  
  36.         db 'ABOR'
  37.         dd cmdABOR
  38.         db 'CWD', 0
  39.         dd cmdCWD
  40.         db 'DELE'
  41.         dd cmdDELE
  42.         db 'LIST'
  43.         dd cmdLIST
  44.         db 'NLST'
  45.         dd cmdNLST
  46.         db 'NOOP'
  47.         dd cmdNOOP
  48.         db 'PASS'
  49.         dd cmdPASS
  50.         db 'PASV'
  51.         dd cmdPASV
  52.         db 'PWD', 0
  53.         dd cmdPWD
  54.         db 'PORT'
  55.         dd cmdPORT
  56.         db 'QUIT'
  57.         dd cmdQUIT
  58.         db 'RETR'
  59.         dd cmdRETR
  60.         db 'STOR'
  61.         dd cmdSTOR
  62.         db 'SYST'
  63.         dd cmdSYST
  64.         db 'TYPE'
  65.         dd cmdTYPE
  66.         db 'USER'
  67.         dd cmdUSER
  68.         db 'XPWD'
  69.         dd cmdPWD
  70.         db 0            ; end marker
  71.  
  72.  
  73. align 4
  74. cmdABOR:
  75.  
  76.         ret
  77.  
  78. align 4
  79. cmdCWD:                 ; Change Working Directory
  80.  
  81.         sub     ecx, 4
  82.         jb      .err
  83.         add     esi, 4
  84.         mov     edi, work_dir + 1
  85.  
  86.         cmp     byte [esi], '/'
  87.         jne     @f
  88.         inc     esi
  89.         dec     ecx
  90.         jz      .done
  91.        @@:
  92.  
  93.   .loop:
  94.         lodsb
  95.         cmp     al, 0x20
  96.         jb      .done
  97.         stosb
  98.         loop    .loop
  99.   .done:
  100.         cmp     byte [edi-1], '/'
  101.         je      @f
  102.         mov     byte [edi], '/'
  103.         inc     edi
  104.        @@:
  105.         mov     byte [edi], 0
  106.  
  107.         mcall   send, [socketnum2], str250, str250.length, 0
  108.  
  109.         ret
  110.  
  111.   .err:
  112.  
  113.         ret
  114.  
  115. align 4
  116. cmdDELE:
  117.  
  118.         ret
  119.  
  120. align 4
  121. cmdLIST:
  122.  
  123. ; If we are in active mode, it's time to open a data socket..
  124.         cmp     [mode], MODE_ACTIVE
  125.         jne     @f
  126.         mcall   connect, [datasocketnum], datasock, datasock.length
  127.         cmp     eax, -1
  128.         je      .err
  129.   @@:
  130.  
  131. ; Warn the client we're about to send the data
  132.         mcall   send, [socketnum2], str150, str150.length, 0    ; here it comes..
  133.  
  134. ; Create fpath from home_dir and work_dir
  135.         call    create_path
  136.  
  137. ; Start the search
  138.         push    FA_READONLY + FA_FOLDER
  139.         push    str_mask
  140.         push    fpath
  141.         call    [file.find.first]
  142.  
  143.         mov     edi, buffer
  144.   .parse_file:
  145.         test    eax, eax        ; did we find a file?
  146.         jz      .done
  147.  
  148.         mov     edx, eax        ; yes, save the descripter
  149.  
  150. ; first, convert the attributes
  151.         test    [edx + FileInfoA.Attributes], FA_FOLDER
  152.         jnz     .folder
  153.  
  154.         test    [edx + FileInfoA.Attributes], FA_READONLY
  155.         jnz     .readonly
  156.  
  157.         mov     eax, '-rw-'
  158.         stosd
  159.         jmp     .attr
  160.  
  161.   .folder:
  162.         mov     eax, 'drwx'
  163.         stosd
  164.         jmp     .attr
  165.  
  166.   .readonly:
  167.         mov     eax, '-r--'
  168.         stosd
  169.  
  170.   .attr:
  171.         mov     eax, 'rw-r'
  172.         stosd
  173.         mov     ax, 'w-'
  174.         stosw
  175.         mov     al, ' '
  176.         stosb
  177.  
  178. ; now..
  179.         mov     ax, '1 '
  180.         stosw
  181.  
  182. ; now write owner, everything is owned by FTP, woohoo!
  183.         mov     eax, 'FTP '
  184.         stosd
  185.         stosd
  186.  
  187. ; now the filesize in ascii
  188.         mov     ebx, [edx + FileInfoA.FileSizeLow]
  189.         call    dword_to_ascii
  190.  
  191.         mov     al, ' '
  192.         stosb
  193.  
  194. ; then date (month/day/year)
  195.         movzx   ebx, [edx + FileInfoA.DateModify + FileDateTime.month]
  196.         mov     eax, [months + 4*ebx]
  197.         stosd
  198.  
  199.         movzx   ebx, [edx + FileInfoA.DateModify + FileDateTime.day]
  200.         call    dword_to_ascii
  201.  
  202.         mov     al, ' '
  203.         stosb
  204.  
  205.         movzx   ebx, [edx + FileInfoA.DateModify + FileDateTime.year]
  206.         call    dword_to_ascii
  207.  
  208.         mov     al, ' '
  209.         stosb
  210.  
  211. ; and last but not least, filename
  212.         lea     esi, [edx + FileInfoA.FileName]
  213.         mov     ecx, 250
  214.   .nameloop:
  215.         lodsb
  216.         test    al, al
  217.         jz      .namedone
  218.         stosb
  219.         loop    .nameloop
  220.  
  221. ; insert a cr lf
  222.   .namedone:
  223.         mov     ax, 0x0d0a
  224.         stosw
  225.  
  226. ; check next file
  227.         push    edx
  228.         call    [file.find.next]
  229.         jmp     .parse_file
  230.  
  231. ; close file desc
  232.   .done:
  233.         push    edx
  234.         call    [file.find.close]
  235.  
  236. ; append the string with a 0
  237.         xor     al, al
  238.         stosb
  239.  
  240. ; print everything on the console
  241.         push    buffer
  242.         call    [con_write_asciiz]
  243.  
  244. ; and send it to the client
  245.         lea     esi, [edi - buffer]
  246.         mcall   send, [datasocketnum], buffer, , 0
  247.  
  248. ; close the data socket..
  249.         mcall   close, [datasocketnum]
  250.  
  251.         cmp     [mode], MODE_PASSIVE_OK
  252.         jne     @f
  253.         mov     [mode], MODE_PASSIVE_WAIT
  254.       @@:
  255.  
  256. ; And send "transfer ok" on the base connection
  257.         mcall   send, [socketnum2], str226, str226.length, 0
  258.  
  259.         ret
  260.  
  261.   .err:
  262.         pushd   0x0c
  263.         call    [con_set_flags]
  264.  
  265.         push    str_err1
  266.         call    [con_write_asciiz]
  267.  
  268.         pushd   0x07
  269.         call    [con_set_flags]
  270.  
  271.         ret
  272.  
  273. align 4
  274. cmdNLST:
  275.  
  276.         ret
  277.  
  278. align 4
  279. cmdNOOP:
  280.  
  281.         ret
  282.  
  283. align 4
  284. cmdPASS:
  285.  
  286.         mcall   send, [socketnum2], str230, str230.length, 0
  287.  
  288.         push    str_pass_ok
  289.         call    [con_write_asciiz]
  290.  
  291.         mov     [state], STATE_ACTIVE
  292.  
  293.         ret
  294.  
  295. align 4
  296. cmdPASV:
  297.  
  298. ; 227 Entering Passive Mode (a1,a2,a3,a4,p1,p2)
  299. ; where a1.a2.a3.a4 is the IP address and p1*256+p2 is the port number.
  300.  
  301.         mcall   socket, AF_INET4, SOCK_STREAM, 0
  302.         cmp     eax, -1
  303. ;        je      .err
  304.         mov     [passivesocknum], eax
  305.  
  306.         mov     [datasock.port], 2000
  307.         mov     [datasock.ip], 0
  308.  
  309.         mcall   bind, [passivesocknum], datasock, datasock.length
  310.         cmp     eax, -1
  311.         je      bind_err
  312.  
  313.         mcall   listen, [passivesocknum], 1
  314.  
  315.         mov     [mode], MODE_PASSIVE_WAIT
  316.  
  317.         mov     edi, buffer
  318.         mov     eax, '227 '     ; FIXME (now hardcoded to 127.0.0.1:2000)
  319.         stosd
  320.         mov     eax, '(127'
  321.         stosd
  322.         mov     eax, ',0,0'
  323.         stosd
  324.         mov     eax, ',1,7'
  325.         stosd
  326.         mov     eax, ',208'
  327.         stosd
  328.         mov     al, ')'
  329.         stosb
  330.         mov     ax, 0x0d0a
  331.         stosw
  332.         xor     al, al
  333.         stosb
  334.  
  335.         lea     esi, [edi - buffer]
  336.  
  337.         mcall   send, [socketnum2], buffer, ,0
  338.  
  339.         ret
  340.  
  341. align 4
  342. cmdPWD:         ; Print Working Directory
  343.  
  344.         mov     dword[buffer], '257 '
  345.         mov     byte[buffer+4], '"'
  346.  
  347.         lea     edi, [buffer+5]
  348.         mov     esi, work_dir
  349.         mov     ecx, 1024
  350.   .loop:
  351.         lodsb
  352.         or      al, al
  353.         jz      .ok
  354.         stosb
  355.         dec     ecx
  356.         jnz     .loop
  357.  
  358.   .ok:
  359.         mov     dword[edi], '"' + 0x000a0d00    ; '"',13,10,0
  360.         lea     esi, [edi - buffer + 4]
  361.  
  362.         mcall   send, [socketnum2], buffer, , 0
  363.  
  364. ;        push    work_dir
  365. ;        push    str_pwd
  366. ;        call    [con_printf]
  367.  
  368.         ret
  369.  
  370. align 4
  371. cmdPORT:
  372.  
  373. ; PORT a1,a2,a3,a4,p1,p2
  374. ; IP address a1.a2.a3.a4, port p1*256+p2
  375.  
  376.         mov     [mode], MODE_ACTIVE
  377.  
  378.         lea     esi, [esi+5]
  379.         xor     edx, edx
  380.  
  381.         call    ascii_to_byte
  382.         mov     dh, bl
  383.         inc     esi
  384.         call    ascii_to_byte
  385.         mov     dl, bl
  386.         shl     edx, 16
  387.         inc     esi
  388.         call    ascii_to_byte
  389.         mov     dh, bl
  390.         inc     esi
  391.         call    ascii_to_byte
  392.         mov     dl, bl
  393.         inc     esi
  394.  
  395.         mov     [datasock.ip], edx
  396.  
  397.         call    ascii_to_byte
  398.         mov     dh, bl
  399.         inc     esi
  400.         call    ascii_to_byte
  401.         mov     dl, bl
  402.  
  403.         mov     [datasock.port], dx
  404.  
  405.         mcall   socket, AF_INET4, SOCK_STREAM, 0
  406.         cmp     eax, -1
  407.         je      .err
  408.         mov     [datasocketnum], eax
  409.  
  410.         mcall   send, [socketnum2], str225, str225.length, 0
  411.         ret
  412.  
  413.   .err:
  414.  
  415.         mcall   send, [socketnum2], str425, str425.length, 0
  416.         ret
  417.  
  418. align 4
  419. cmdQUIT:
  420.  
  421.         mcall   send, [socketnum2], str221, str221.length, 0
  422.         mcall   close, [socketnum2]
  423.  
  424.         ret
  425.  
  426. align 4
  427. cmdRETR:
  428.  
  429.         cmp     [mode], MODE_ACTIVE
  430.         jne     @f
  431.         mcall   connect, [datasocketnum], datasock, datasock.length
  432. ;        cmp     eax, -1
  433. ;        je      .err
  434.   @@:
  435.  
  436.         mcall   send, [socketnum2], str150, str150.length, 0    ; here it comes..
  437.  
  438.         push    O_READ
  439.         push    home_dir
  440.         call    [file.open]
  441. ;        test    eax, eax
  442. ;        jz      .cannot_open
  443.  
  444.         mov     ebx, eax
  445.  
  446.   .read_more:
  447.         push    BUFFERSIZE
  448.         push    buffer
  449.         push    ebx
  450.         call    [file.read]
  451. ;        cmp     eax, -1
  452. ;        je      .cannot_open
  453.  
  454.         push    eax
  455.         push    ebx
  456.         mov     esi, eax
  457.         mcall   send, [datasocketnum], buffer, , 0
  458.         pop     ebx
  459.         pop     ecx
  460. ;        cmp     eax, -1
  461. ;        je      .socketerr
  462.  
  463.         cmp     ecx, BUFFERSIZE
  464.         je      .read_more
  465.  
  466.         mcall   close, [datasocketnum]
  467.  
  468.         cmp     [mode], MODE_PASSIVE_OK
  469.         jne     @f
  470.         mov     [mode], MODE_PASSIVE_WAIT
  471.       @@:
  472.  
  473.         mcall   send, [socketnum2], str226, str226.length, 0    ; transfer ok
  474.  
  475.         ret
  476.  
  477. align 4
  478. cmdSTOR:
  479.  
  480.         ret
  481.  
  482. align 4
  483. cmdSYST:
  484.  
  485.         mcall   send, [socketnum2], str215, str215.length, 0
  486.  
  487.         ret
  488.  
  489. align 4
  490. cmdTYPE:
  491.  
  492.  
  493.         cmp     ecx, 6
  494.         jb      parse_cmd.error
  495.  
  496.         mov     al, byte[esi+5]
  497.         and     al, not 0x20
  498.  
  499.         cmp     al, 'A'
  500.         je      .ascii
  501.         cmp     al, 'E'
  502.         je      .ebdic
  503.         cmp     al, 'I'
  504.         je      .image
  505.         cmp     al, 'L'
  506.         je      .local
  507.  
  508.         jmp     parse_cmd.error
  509.  
  510.   .ascii:
  511.         mov     [type], TYPE_ASCII
  512.         jmp     .subtype
  513.  
  514.   .ebdic:
  515.         mov     [type], TYPE_EBDIC
  516.  
  517.   .subtype:
  518.  
  519.         cmp     ecx, 8
  520.         jb      .non_print
  521.  
  522.         mov     al, byte[esi+7]
  523.         and     al, not 0x20
  524.  
  525.         cmp     al, 'N'
  526.         je      .non_print
  527.         cmp     al, 'T'
  528.         je      .telnet
  529.         cmp     al, 'C'
  530.         je      .asacc
  531.  
  532.         jmp     parse_cmd.error
  533.  
  534.   .non_print:
  535.         or      [type], TYPE_NP
  536.         jmp     .ok
  537.  
  538.   .telnet:
  539.         or      [type], TYPE_TELNET
  540.         jmp     .ok
  541.  
  542.   .asacc:
  543.         or      [type], TYPE_ASA
  544.         jmp     .ok
  545.  
  546.   .image:
  547.         mov     [type], TYPE_IMAGE
  548.         jmp     .ok
  549.  
  550.   .local:
  551.         cmp     ecx, 8
  552.         jb      parse_cmd.error
  553.  
  554.         mov     al, byte[esi+7]
  555.         sub     al, '0'
  556.         jb      parse_cmd.error
  557.         cmp     al, 9
  558.         ja      parse_cmd.error
  559.         or      al, TYPE_LOCAL
  560.         mov     [type], al
  561.  
  562.   .ok:
  563.         mcall   send, [socketnum2], str200, str200.length, 0
  564.  
  565.         ret
  566.  
  567. align 4
  568. cmdUSER:
  569.  
  570.         mcall   send, [socketnum2], str331, str331.length, 0
  571.         mov     [state], STATE_LOGIN
  572.  
  573.         mov     byte [work_dir], "/"
  574.         mov     byte [work_dir+1], 0
  575.  
  576.         push    str_logged_in
  577.         call    [con_write_asciiz]
  578.  
  579.         ret
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587. align 4         ; esi = ptr to str
  588. ascii_to_byte:
  589.  
  590.         xor     ebx, ebx
  591.  
  592.   .loop:
  593.  
  594.         movzx   eax, byte[esi]
  595.         sub     al, '0'
  596.         jb      .done
  597.         cmp     al, 9
  598.         ja      .done
  599.         lea     ebx, [ebx*4 + ebx]
  600.         shl     ebx, 1
  601.         add     ebx, eax
  602.         inc     esi
  603.  
  604.         jmp     .loop
  605.  
  606.   .done:
  607.         ret
  608.  
  609. align 4
  610. dword_to_ascii: ; edi = ptr where to write, ebx is number
  611.  
  612.         mov     eax, '1'
  613.         stosb
  614.  
  615.         ret
  616.  
  617. align 4
  618. create_path:            ; combine home_dir and work_dir strings into fpath
  619.         mov     edi, fpath
  620.         mov     esi, home_dir
  621.         mov     ecx, 1024
  622.  
  623.   .loop1:
  624.         lodsb
  625.         or      al, al
  626.         jz      .next
  627.         stosb
  628.         loop    .loop1
  629.   .next:
  630.  
  631.         cmp     byte[edi-1], '/'
  632.         jne     @f
  633.         dec     edi
  634.        @@:
  635.  
  636.         mov     esi, work_dir
  637.         mov     ecx, 1024
  638.  
  639.   .loop2:
  640.         lodsb
  641.         or      al, al
  642.         jz      .done
  643.         stosb
  644.         loop    .loop2
  645.  
  646.   .done:
  647.         stosb
  648.  
  649.         ret
  650.  
  651.  
  652.  
  653.  
  654.  
  655.  
  656. str150  db '150 Here it comes...', 13, 10
  657. .length = $ - str150
  658. str200  db '200 Command OK.', 13, 10
  659. .length = $ - str200
  660. str215  db '215 UNIX type: L8', 13, 10
  661. .length = $ - str215
  662. str220  db '220 KolibriOS FTP Daemon 1.0', 13, 10
  663. .length = $ - str220
  664. str221  db '221 Bye!', 13, 10
  665. .length = $ - str221
  666. str225  db '225 Data connection open', 13, 10
  667. .length = $ - str225
  668. str226  db '226 Transfer OK, Closing connection', 13, 10
  669. .length = $ - str226
  670. str230  db '230 You are now logged in.', 13, 10
  671. .length = $ - str230
  672. str250  db '250 command successful', 13, 10
  673. .length = $ - str250
  674. str331  db '331 Please specify the password.', 13, 10
  675. .length = $ - str331
  676. str421  db '421 Timeout!', 13, 10
  677. .length = $ - str421
  678. str425  db '425 Cant open data connection.', 13, 10
  679. .length = $ - str425
  680. str500  db '500 Unsupported command', 13, 10
  681. .length = $ - str500
  682. str550  db '550 No such file', 13, 10
  683. .length = $ - str550