Subversion Repositories Kolibri OS

Rev

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