Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;
  3. ;    FTPS
  4. ;    FTP Server
  5. ;
  6. ;    Compile with FASM for Menuet
  7. ;
  8.  
  9. ; note: telnet == 23, ftp cmd == 21, data on 20
  10.  
  11. use32
  12.  
  13.     org     0x0
  14.  
  15.     db      'MENUET01'              ; 8 byte id
  16.     dd      1                       ; header version
  17.     dd      START                   ; program start
  18.     dd      I_END                   ; program image size
  19.     dd      0x170000                ; required amount of memory
  20.     dd      0x7FFF0                 ; esp = 0x7FFF0
  21.     dd      0, 0                    ; no params, no path
  22.  
  23. include 'macros.inc'
  24. ; Various states of client connection
  25. USER_NONE       equ 0   ; Awaiting a connection
  26. USER_CONNECTED  equ 1   ; User just connected, prompt given
  27. USER_USERNAME   equ 2   ; User given username
  28. USER_LOGGED_IN  equ 3   ; User given password
  29.  
  30.  
  31.  
  32.  
  33.  
  34. START:                          ; start of execution
  35.     ; Clear the screen memory
  36.     mov     eax, '    '
  37.     mov     edi,text
  38.     mov     ecx,80*30 /4
  39.     cld
  40.     rep     stosd
  41.  
  42.     call    draw_window
  43.  
  44.     ; init the receive buffer pointer
  45.     mov     [buffptr], buff
  46.  
  47.     ; Init FTP server state machine
  48.     mov     [state], USER_NONE
  49.  
  50.     ; Open the listening socket
  51.     call    connect
  52.  
  53. still:
  54.     ; check connection status
  55.     mov     eax,53
  56.     mov     ebx,6               ; Get socket status
  57.     mov     ecx,[CmdSocket]
  58.     mcall
  59.  
  60.     mov     ebx, [CmdSocketStatus]
  61.     mov     [CmdSocketStatus], eax
  62.  
  63.     cmp     eax, ebx
  64.     je      waitev
  65.  
  66.     ; If the socket closed by remote host, open it again.
  67.     cmp     eax, 7
  68.     je      con
  69.  
  70.     ; If socket closed by Reset, open it again
  71.     cmp     eax, 11
  72.     je      con
  73.  
  74.     ; If a user has just connected, start by outputting welcome msg
  75.     cmp     eax, 4
  76.     jne     noc
  77.  
  78.     mov     esi, loginStr0
  79.     mov     edx, loginStr0_end - loginStr0
  80.     call    outputStr
  81.  
  82.     mov     [state], USER_CONNECTED
  83.     jmp     noc
  84.  
  85.  
  86. con:
  87.     ; Need to call disconnect, since a remote close does not fully
  88.     ; close the socket
  89.     call    disconnect
  90.     mov     eax,5
  91.     mov     ebx,10          ; Delay for 100ms
  92.     mcall
  93.     call    connect
  94.     jmp     noc
  95.  
  96. noc:
  97.     ; Display the changed connected status
  98.     call    draw_window
  99.  
  100. waitev:
  101.     mov     eax,23                 ; wait here for event
  102.     mov     ebx,1                 ; Delay for up to 1s
  103.     mcall
  104.  
  105.     cmp     eax,1                  ; redraw request ?
  106.     je      red
  107.     cmp     eax,2                  ; key in buffer ?
  108.     je      key
  109.     cmp     eax,3                  ; button in buffer ?
  110.     je      button
  111.  
  112.     ; any data from the socket?
  113.  
  114.     mov     eax, 53
  115.     mov     ebx, 2                  ; Get # of bytes in input queue
  116.     mov     ecx, [CmdSocket]
  117.     mcall
  118.     test    eax, eax
  119.     jz      still
  120.  
  121. read_input:
  122.     mov     eax, 53
  123.     mov     ebx, 3                  ; Get a byte from socket in bl
  124.     mov     ecx, [CmdSocket]
  125.     mcall
  126.  
  127.     call    ftpRxCmdData            ; process incoming ftp command
  128.  
  129.     ; Keep processing data until there is no more to process
  130.     mov     eax, 53
  131.     mov     ebx, 2                  ; Get # of bytes in input queue
  132.     mov     ecx, [CmdSocket]
  133.     mcall
  134.     cmp     eax, 0
  135.     jne     read_input
  136.  
  137.     ; Now redraw the text text field.
  138.     ; Probably not required, since ftp requires no
  139.     ; console i/o.
  140.     ; Leave in for now, for debugging.
  141. ; (fall through to "red:")
  142. ;    call    draw_text
  143. ;    jmp     still
  144.  
  145. red:                          ; REDRAW WINDOW
  146.     call    draw_window
  147.     jmp     still
  148.  
  149. key:                          ; KEY
  150.     mov     eax,2                  ; get but ignore
  151.     mcall
  152.     jmp     still
  153.  
  154. button:
  155.     mov     eax,17
  156.     mcall
  157.     cmp     ah,1
  158.     jne     still
  159.  
  160.     ; Exit button pressed, so close socket and quit
  161.     mov     eax,53
  162.     mov     ebx,8
  163.     mov     ecx,[CmdSocket]
  164.     mcall
  165.  
  166.     ; ... terminate program
  167.     or     eax,-1
  168.     mcall
  169.     jmp     still
  170.  
  171.  
  172.  
  173. ;   *********************************************
  174. ;   *******  WINDOW DEFINITIONS AND DRAW ********
  175. ;   *********************************************
  176. draw_window:
  177.     pusha
  178.  
  179.     mov  eax,12
  180.     mov  ebx,1
  181.     mcall
  182.  
  183.     xor  eax,eax                   ; DRAW WINDOW
  184.     mov  ebx,100*65536+491 + 8 +15
  185.     mov  ecx,100*65536+270 + 20     ; 20 for status bar
  186.     mov  edx,0x14000000
  187.     mov  edi,labelt
  188.     mcall
  189.  
  190.     ; draw status bar
  191.     mov     eax, 13
  192.     mov     ebx, 4*65536+484 + 8 +15
  193.     mov     ecx, 270*65536 + 3
  194.     mov     edx, 0x00557799
  195.     mcall
  196.  
  197.  
  198.     mov  esi,contlen-contt          ; display connected status
  199.     mov     edx, contt
  200.     cmp     [CmdSocketStatus], 4    ; 4 is connected
  201.     je      pcon
  202.     mov     esi,discontlen-discontt
  203.     mov     edx, discontt
  204. pcon:
  205.  
  206.     mov  eax,4                      ; status text
  207.     mov  ebx,380*65536+276
  208.     mov  ecx,0x00ffffff
  209.     mcall
  210.  
  211.     ; Draw the text on the screen, clearing it first
  212.     ; This can go when we loose debuggin info.
  213.     xor  eax,eax
  214.     mov  edi,text+80*30
  215.     mov  ecx,80*30 /4
  216.     cld
  217.     rep  stosd
  218.  
  219.     call draw_text
  220.  
  221.     mov  eax,12
  222.     mov  ebx,2
  223.     mcall
  224.  
  225.     popa
  226.  
  227.     ret
  228.  
  229.  
  230. ;***************************************************************************
  231. ;   Function
  232. ;      draw_text
  233. ;
  234. ;   Description
  235. ;       Updates the text on the screen. This is part of the debugging code
  236. ;
  237. ;   Inputs
  238. ;       Character to add in bl
  239. ;
  240. ;***************************************************************************
  241. draw_text:
  242.  
  243.     pusha
  244.  
  245.     mov  esi,text
  246.     mov  eax,0
  247.     mov  ebx,0
  248.   newletter:
  249.     mov  cl,[esi]
  250.     cmp  cl,[esi+30*80]
  251.     jz   noletter
  252.   yesletter:
  253.     mov  [esi+30*80],cl
  254.  
  255.     ; erase character
  256.  
  257.     pusha
  258.     mov     edx, 0                  ; bg colour
  259.     mov     ecx, ebx
  260.     add     ecx, 26
  261.     shl     ecx, 16
  262.     mov     cx, 9
  263.     mov     ebx, eax
  264.     add     ebx, 6
  265.     shl     ebx, 16
  266.     mov     bx, 6
  267.     mov     eax, 13
  268.     mcall
  269.     popa
  270.  
  271.     ; draw character
  272.  
  273.     pusha
  274.     mov     ecx, 0x00ffffff
  275.     push bx
  276.     mov  ebx,eax
  277.     add  ebx,6
  278.     shl  ebx,16
  279.     pop  bx
  280.     add  bx,26
  281.     mov  eax,4
  282.     mov  edx,esi
  283.     mov  esi,1
  284.     mcall
  285.     popa
  286.  
  287.   noletter:
  288.  
  289.     add  esi,1
  290.     add  eax,6
  291.     cmp  eax,80*6
  292.     jb   newletter
  293.     mov  eax,0
  294.     add  ebx,10
  295.     cmp  ebx,24*10
  296.     jb   newletter
  297.  
  298.     popa
  299.     ret
  300.  
  301.  
  302.  
  303. ;***************************************************************************
  304. ;   Function
  305. ;      ftpRxCmdData
  306. ;
  307. ;   Description
  308. ;       Prcoesses incoming command data, calling a handler for each command.
  309. ;       Commands are built up in buff before being processed.
  310. ;
  311. ;   Inputs
  312. ;       Character to add in bl
  313. ;
  314. ;***************************************************************************
  315. ftpRxCmdData:
  316.     ; Quit if we are not connected
  317.     ;( This case shouldn't be necessary, but be safe )
  318.     mov     al, [state]
  319.     cmp     al, USER_NONE
  320.     je      frcd_exit
  321.  
  322.     ; Store the incoming character
  323.     mov     esi, [buffptr]
  324.     mov     [esi], bl
  325.     inc     esi
  326.     mov     [buffptr], esi
  327.  
  328.     ; For debugging, show the data coming in
  329.     pusha
  330.     call    printChar
  331.     popa
  332.  
  333.     ; Do we have an end of line? (LF)
  334.     ; if not, just exit
  335.     cmp     bl, 0x0a
  336.     jne     frcd_exit
  337.  
  338.     ; OK we have a complete command.
  339.     ; Process, and send response
  340.  
  341.     ; There are a number of states involved in ftp,
  342.     ; to do with logging in.
  343.  
  344.     mov     al, [state]
  345.     cmp     al, USER_CONNECTED
  346.     jne     fs001
  347.  
  348.     ; This should be the username
  349.  
  350.     ; TODO validate username
  351.  
  352.     ; OK, username accepted - ask for password
  353.     mov     esi, loginStr1
  354.     mov     edx, loginStr1_end - loginStr1
  355.     call    outputStr
  356.  
  357.     mov     [state], USER_USERNAME
  358.  
  359.     ; init the receive buffer pointer
  360.     mov     [buffptr], buff
  361.  
  362.     jmp     frcd_exit
  363.  
  364. fs001:
  365.     cmp     al, USER_USERNAME
  366.     jne     fs002
  367.  
  368.     ; This should be the password
  369.  
  370.     ; TODO validate password
  371.  
  372.     ; OK, password accepted - show they are logged in
  373.     mov     esi, loginStr2
  374.     mov     edx, loginStr2_end - loginStr2
  375.     call    outputStr
  376.  
  377.     mov     [state], USER_LOGGED_IN
  378.  
  379.     ; init the receive buffer pointer
  380.     mov     [buffptr], buff
  381.  
  382.     jmp     frcd_exit
  383.  
  384. fs002:
  385.     cmp     al, USER_LOGGED_IN
  386.     jne     fs003
  387.  
  388.     ; This should be a cmd
  389.     call    findCmd
  390.     mov     eax, [cmdPtr]
  391.     cmp     eax, 0
  392.  
  393.     je      fs002b
  394.  
  395.     call    [cmdPtr]
  396.  
  397. fs002a:
  398.     ; init the receive buffer pointer
  399.     mov     [buffptr], buff
  400.  
  401.     jmp     frcd_exit
  402.  
  403. fs002b:
  404.     ; an unsupported command was entered.
  405.     ; Tell user that the command is not supported
  406.  
  407.     mov     esi, unsupStr
  408.     mov     edx, unsupStr_end - unsupStr
  409.     call    outputStr
  410.  
  411.     jmp     fs002a
  412.  
  413. fs003:
  414. frcd_exit:
  415.     ret
  416.  
  417.  
  418.  
  419. ;***************************************************************************
  420. ;   Function
  421. ;      outputStr
  422. ;
  423. ;   Description
  424. ;       Sends a string over the 'Command' socket
  425. ;
  426. ;   Inputs
  427. ;       String in esi
  428. ;       Length in edx
  429. ;
  430. ;***************************************************************************
  431. outputStr:
  432.     push    esi
  433.     push    edx
  434.     mov     eax,53
  435.     mov     ebx,7
  436.     mov     ecx,[CmdSocket]
  437.     mcall
  438.     pop     edx
  439.     pop     esi
  440.  
  441.     cmp     eax, 0
  442.     je      os_exit
  443.  
  444.     ; The TCP/IP transmit queue is full; Wait a bit, then retry
  445.     pusha
  446.     mov     eax,5
  447.     mov     ebx,1                 ; Delay for up 100ms
  448.     mcall
  449.     popa
  450.     jmp     outputStr
  451. os_exit:
  452.     ret
  453.  
  454.  
  455.  
  456. ;***************************************************************************
  457. ;   Function
  458. ;      outputDataStr
  459. ;
  460. ;   Description
  461. ;       Sends a string over the 'Data' socket
  462. ;
  463. ;   Inputs
  464. ;       String in esi
  465. ;       Length in edx
  466. ;
  467. ;***************************************************************************
  468. outputDataStr:
  469.     push    esi
  470.     push    edx
  471.     mov     eax,53
  472.     mov     ebx,7
  473.     mov     ecx,[DataSocket]
  474.     mcall
  475.     pop     edx
  476.     pop     esi
  477.  
  478.     cmp     eax, 0
  479.     je      ods_exit
  480.  
  481.     ; The TCP/IP transmit queue is full; Wait a bit, then retry
  482.     pusha
  483.     mov     eax,5
  484.     mov     ebx,20           ; Delay for upto 200ms
  485.     mcall
  486.     popa
  487.     jmp     outputDataStr
  488. ods_exit:
  489.     ret
  490.  
  491.  
  492.  
  493. ;***************************************************************************
  494. ;   Function
  495. ;      printChar
  496. ;
  497. ;   Description
  498. ;       Writes a character to the screen; Used to display the data coming
  499. ;       in from the user. Really only useful for debugging.
  500. ;
  501. ;   Inputs
  502. ;       Character in bl
  503. ;
  504. ;***************************************************************************
  505. printChar:
  506.     cmp     bl,13                          ; BEGINNING OF LINE
  507.     jne     nobol
  508.     mov     ecx,[pos]
  509.     add     ecx,1
  510. boll1:
  511.     sub     ecx,1
  512.     mov     eax,ecx
  513.     xor     edx,edx
  514.     mov     ebx,80
  515.     div     ebx
  516.     cmp     edx,0
  517.     jne     boll1
  518.     mov     [pos],ecx
  519.     jmp     newdata
  520. nobol:
  521.  
  522.     cmp     bl,10                            ; LINE DOWN
  523.     jne     nolf
  524. addx1:
  525.     add     [pos],dword 1
  526.     mov     eax,[pos]
  527.     xor     edx,edx
  528.     mov     ecx,80
  529.     div     ecx
  530.     cmp     edx,0
  531.     jnz     addx1
  532.     mov     eax,[pos]
  533.     jmp     cm1
  534. nolf:
  535.  
  536.     cmp     bl,8                            ; BACKSPACE
  537.     jne     nobasp
  538.     mov     eax,[pos]
  539.     dec     eax
  540.     mov     [pos],eax
  541.     mov     [eax+text],byte 32
  542.     mov     [eax+text+60*80],byte 0
  543.     jmp     newdata
  544. nobasp:
  545.  
  546.     cmp     bl,15                           ; CHARACTER
  547.     jbe     newdata
  548. putcha:
  549.     mov     eax,[pos]
  550.     mov     [eax+text],bl
  551.     mov     eax,[pos]
  552.     add     eax,1
  553. cm1:
  554.     mov     ebx,[scroll+4]
  555.     imul    ebx,80
  556.     cmp     eax,ebx
  557.     jb      noeaxz
  558.     mov     esi,text+80
  559.     mov     edi,text
  560.     mov     ecx,ebx
  561.     cld
  562.     rep     movsb
  563.     mov     eax,ebx
  564.     sub     eax,80
  565. noeaxz:
  566.     mov     [pos],eax
  567. newdata:
  568.     ret
  569.  
  570.  
  571. ;***************************************************************************
  572. ;   Function
  573. ;      disconnect
  574. ;
  575. ;   Description
  576. ;       Closes the command socket
  577. ;
  578. ;   Inputs
  579. ;       None
  580. ;
  581. ;***************************************************************************
  582. disconnect:
  583.     mov     eax, 53         ; Stack Interface
  584.     mov     ebx,8           ; Close TCP socket
  585.     mov     ecx,[CmdSocket]
  586.     mcall
  587.     ret
  588.  
  589.  
  590.  
  591. ;***************************************************************************
  592. ;   Function
  593. ;      disconnectData
  594. ;
  595. ;   Description
  596. ;       Closes the data socket
  597. ;
  598. ;   Inputs
  599. ;       None
  600. ;
  601. ;***************************************************************************
  602. disconnectData:
  603.     ; This delay would be better done by allowing the socket code
  604.     ; to wait for all data to pass through the stack before closing
  605.     pusha
  606.     mov     eax,5
  607.     mov     ebx,10          ; Delay for 100ms
  608.     mcall
  609.     popa
  610.  
  611.     mov     eax, 53         ; Stack Interface
  612.     mov     ebx,8           ; Close TCP socket
  613.     mov     ecx,[DataSocket]
  614.     mcall
  615.     ret
  616.  
  617.  
  618.  
  619.  
  620. ;***************************************************************************
  621. ;   Function
  622. ;      connect
  623. ;
  624. ;   Description
  625. ;       Opens the command socket
  626. ;
  627. ;   Inputs
  628. ;       None
  629. ;
  630. ;***************************************************************************
  631. connect:
  632.     pusha
  633.  
  634.     mov     eax, 53     ; Stack Interface
  635.     mov     ebx, 5      ; Open TCP socket
  636.     mov     esi, 0      ; No remote IP address
  637.     mov     edx, 0      ; No remote port
  638.     mov     ecx, 21     ; ftp command port id
  639.     mov     edi, 0      ; passive open
  640.     mcall
  641.     mov     [CmdSocket], eax
  642.  
  643.     popa
  644.  
  645.     ret
  646.  
  647.  
  648.  
  649. ;***************************************************************************
  650. ;   Function
  651. ;      connectData
  652. ;
  653. ;   Description
  654. ;       Opens the data socket
  655. ;
  656. ;   Inputs
  657. ;       None
  658. ;
  659. ;***************************************************************************
  660. connectData:
  661.     pusha
  662.  
  663.     mov     eax, 53     ; Stack Interface
  664.     mov     ebx, 5      ; Open TCP socket
  665.     mov     esi, [DataIP]      ; remote IP address
  666.     mov     edx, [DataPort]    ; remote port
  667.     mov     ecx, 0      ; ftp data port id
  668.     mov     edi, 1      ; active open
  669.     mcall
  670.     mov     [DataSocket], eax
  671.  
  672.     popa
  673.  
  674.     ret
  675.  
  676.  
  677.  
  678.  
  679. ;***************************************************************************
  680. ;   Function
  681. ;      findCmd
  682. ;
  683. ;   Description
  684. ;       Scans the command string for a valid command. The command string
  685. ;       is in the global variable buff.
  686. ;
  687. ;       Returns result in cmdPtr. This will be zero if none found
  688. ;
  689. ;   Inputs
  690. ;       None
  691. ;
  692. ;***************************************************************************
  693. findCmd:
  694.     ; Setup to return 'none' in cmdPtr, if we find no cmd
  695.     mov     eax, 0
  696.     mov     [cmdPtr], eax
  697.     cld
  698.     mov     esi, buff
  699.     mov     edi, CMDList
  700.  
  701. fc000:
  702.     cmp     [edi], byte 0   ; Are we at the end of the CMDList?
  703.     je      fc_exit
  704.  
  705. fc000a:
  706.     cmpsb
  707.  
  708.     je      fc_nextbyte
  709.  
  710.     ; Command is different - move to the next entry in cmd table
  711.     mov     esi, buff
  712.  
  713. fc001:
  714.     ; skip to the next command in the list
  715.     cmp     [edi], byte 0
  716.     je      fc002
  717.     inc     edi
  718.     jmp     fc001
  719. fc002:
  720.     add     edi, 5
  721.     jmp     fc000
  722.  
  723. fc_nextbyte:
  724.     ; Have we reached the end of the CMD text?
  725.     cmp     [edi], byte 0
  726.     je      fc_got      ; Yes - so we have a match
  727.     jmp     fc000a      ; No - loop back
  728.  
  729. fc_got:
  730.     ; Copy the function pointer for the selected command
  731.     inc     edi
  732.     mov     eax, [edi]
  733.     mov     [cmdPtr], eax
  734.  
  735. fc_exit:
  736.     ret
  737.  
  738.  
  739.  
  740. ;***************************************************************************
  741. ;   Function
  742. ;      decStr2Byte
  743. ;
  744. ;   Description
  745. ;       Converts the decimal string pointed to by esi to a byte
  746. ;
  747. ;   Inputs
  748. ;       string ptr in esi
  749. ;
  750. ;   Outputs
  751. ;       esi points to next character not in string
  752. ;       eax holds result ( 0..255)
  753. ;
  754. ;***************************************************************************
  755. decStr2Byte:
  756.     xor     eax, eax
  757.     xor     ebx, ebx
  758.     mov     ecx, 3
  759.  
  760. dsb001:
  761.     mov     bl, [esi]
  762.  
  763.     cmp     bl, '0'
  764.     jb      dsb_exit
  765.     cmp     bl, '9'
  766.     ja      dsb_exit
  767.  
  768.     imul    eax, 10
  769.     add     eax, ebx
  770.     sub     eax, '0'
  771.     inc     esi
  772.     loop    dsb001
  773.  
  774. dsb_exit:
  775.     ret
  776.  
  777.  
  778.  
  779. ;***************************************************************************
  780. ;   Function
  781. ;      parsePortStr
  782. ;
  783. ;   Description
  784. ;       Converts the parameters of the PORT command, and stores them in the
  785. ;       appropriate variables.
  786. ;
  787. ;   Inputs
  788. ;       None ( string in global variable buff )
  789. ;
  790. ;   Outputs
  791. ;       None
  792. ;
  793. ;***************************************************************************
  794. parsePortStr:
  795.     ; skip past the PORT text to get the the parameters. The command format
  796.     ; is
  797.     ; PORT i,i,i,i,p,p,0x0d,0x0a
  798.     ; where i and p are decimal byte values, high byte first.
  799.     xor     eax, eax
  800.     mov     [DataIP], eax
  801.     mov     [DataPort], eax
  802.     mov     esi, buff + 4       ; Start at first space character
  803.  
  804. pps001:
  805.     cmp     [esi], byte ' '     ; Look for first non space character
  806.     jne     pps002
  807.     inc     esi
  808.     jmp     pps001
  809.  
  810. pps002:
  811.     call    decStr2Byte
  812.     add     [DataIP], eax
  813.     ror     dword [DataIP], 8
  814.     inc     esi
  815.     call    decStr2Byte
  816.     add     [DataIP], eax
  817.     ror     dword [DataIP], 8
  818.     inc     esi
  819.     call    decStr2Byte
  820.     add     [DataIP], eax
  821.     ror     dword [DataIP], 8
  822.     inc     esi
  823.     call    decStr2Byte
  824.     add     [DataIP], eax
  825.     ror     dword [DataIP], 8
  826.     inc     esi
  827.     call    decStr2Byte
  828.     add     [DataPort], eax
  829.     shl     [DataPort], 8
  830.     inc     esi
  831.     call    decStr2Byte
  832.     add     [DataPort], eax
  833.  
  834.     ret
  835.  
  836.  
  837.  
  838. ;***************************************************************************
  839. ;   Function
  840. ;      sendDir
  841. ;
  842. ;   Description
  843. ;       Transmits the directory listing over the data connection.
  844. ;       The data connection is already open.
  845. ;
  846. ;   Inputs
  847. ;       None
  848. ;
  849. ;   Outputs
  850. ;       None
  851. ;
  852. ;***************************************************************************
  853. sendDir:
  854.         mov     ebx, dirinfoblock
  855.         and     dword [ebx+4], 0        ; start from zero block
  856. sd001:
  857. ; Read the next DirBlocksPerCall (=16) blocks
  858.         mov     eax, 70
  859.         mcall
  860. ; Did we read anything?
  861.         test    eax, eax
  862.         jz      @f
  863.         cmp     eax, 6
  864.         jnz     sd_exit
  865. @@:
  866.         test    ebx, ebx
  867.         jz      sd_exit
  868. ; Parse these blocks. There could be up to 16 files specified
  869.         mov     esi, text + 0x1300 + 0x20
  870. sd002:
  871.         dec     ebx
  872.         js      sd004
  873.         push    ebx
  874. ; OK, lets parse the entry. Ignore volume entries
  875.         test    byte [esi], 8
  876.         jnz     sd003
  877. ; Valid file or directory. Start to compose the string we will send
  878.         mov     edi, dirStr
  879. ; If we have been called as a result of an NLST command, we only display
  880. ; the filename
  881.         cmp     [buff], byte 'N'
  882.         jz      sd006
  883.  
  884.         mov     [edi], byte '-'
  885.         test    byte [esi], 10h
  886.         jz      @f
  887.         mov     [edi], byte 'd'
  888. @@:
  889. ; Ok, now copy across the directory listing text that will be constant
  890. ; ( I dont bother looking at the read only or archive bits )
  891.  
  892.         mov     ebx, tmplStr
  893. @@:
  894.         inc     edi
  895.         mov     al, [ebx]
  896.         test    al, al
  897.         jz      @f
  898.         mov     [edi], al
  899.         inc     ebx
  900.         jmp     @b
  901. @@:
  902. ; point to the last character of the string;
  903. ; We will write the file size here, backwards
  904.         push    edi             ; Remember where the string ends
  905.  
  906.         dec     edi
  907. ; eax holds the number
  908.         mov     eax, [esi+32]
  909.         mov     ebx, 10
  910. @@:
  911.         xor     edx, edx
  912.         div     ebx
  913.         add     dl, '0'
  914.         mov     [edi], dl
  915.         dec     edi
  916.         test    eax, eax
  917.         jnz     @b
  918.  
  919.         pop     edi
  920. ; now create the time & date fields
  921. ;timeStr:            db ' Jan 1    2000 ',0
  922.         mov     al, ' '
  923.         stosb
  924.         movzx   eax, byte [esi+28+1]
  925.         mov     eax, dword [months + (eax-1)*4]
  926.         stosd
  927.         mov     al, byte [esi+28]
  928.         aam
  929.         test    ah, ah
  930.         jz      sd005a
  931.         xchg    al, ah
  932.         add     ax, '00'
  933.         jmp     sd005b
  934. sd005a:
  935.         add     al, '0'
  936.         mov     ah, ' '
  937. sd005b:
  938.         stosw
  939.         mov     al, ' '
  940.         mov     ecx, 6
  941.         rep     stosb
  942.         push    edi
  943.         movzx   eax, word [esi+28+2]
  944. @@:
  945.         xor     edx, edx
  946.         div     ebx
  947.         add     dl, '0'
  948.         mov     [edi], dl
  949.         dec     edi
  950.         test    eax, eax
  951.         jnz     @b
  952.         pop     edi
  953.         inc     edi
  954.         mov     al, ' '
  955.         stosb
  956. sd006:
  957. ; ** End of copying
  958.  
  959. ; now copy the filename across
  960.         lea     ebx, [esi+40]
  961. @@:
  962.         mov     al, [ebx]
  963.         inc     ebx
  964.         test    al, al
  965.         jz      @f
  966.         stosb
  967.         jmp     @b
  968. @@:
  969. terminate:
  970. ; Now terminate the line by putting CRLF sequence in
  971.         mov     al, 0x0D
  972.         stosb
  973.         mov     al, 0x0A
  974.         stosb
  975. ; Send the completed line to the user over data socket
  976.         push    esi
  977.         mov     esi, dirStr
  978.         mov     edx, edi
  979.         sub     edx, esi
  980.         call    outputDataStr
  981.         pop     esi
  982.  
  983. sd003:                  ; Move to next entry in the block
  984.         pop     ebx
  985.         add     esi, 304
  986.         jmp     sd002
  987. sd004:
  988.         mov     ebx, dirinfoblock
  989.         add     dword [ebx+4], DirBlocksPerCall
  990.         jmp     sd001
  991.  
  992. sd_exit:
  993.         ret
  994.  
  995.  
  996.  
  997.  
  998.  
  999. ;***************************************************************************
  1000. ;   Function
  1001. ;      setupFilePath
  1002. ;
  1003. ;   Description
  1004. ;       Copies the file name from the input request string into the
  1005. ;       file descriptor
  1006. ;
  1007. ;   Inputs
  1008. ;       None
  1009. ;
  1010. ;   Outputs
  1011. ;       None
  1012. ;
  1013. ;***************************************************************************
  1014. setupFilePath:
  1015.     mov     esi, buff + 4       ; Point to (1 before) first character of file
  1016.  
  1017.     ; Skip any trailing spaces or / character
  1018. sfp001:
  1019.     inc     esi
  1020.     cmp     [esi], byte ' '
  1021.     je      sfp001
  1022.     cmp     [esi], byte '/'
  1023.     je      sfp001
  1024.  
  1025.     ; esi points to start of filename.
  1026.  
  1027.  
  1028.     ; Copy across the directory path '/'
  1029.     ; into the fileinfoblock
  1030.     mov     edi, filename
  1031.     mov     dword [edi], '/RD/'
  1032.     mov     word [edi+4], '1/'
  1033.     add     edi, 6
  1034.  
  1035.     ; Copy across the filename
  1036. sfp002:
  1037.     cld
  1038.     movsb
  1039.     cmp     [esi], byte 0x0d
  1040.     jne     sfp002
  1041.     mov     [edi], byte 0
  1042.     ret
  1043.  
  1044.  
  1045.  
  1046.  
  1047. ;***************************************************************************
  1048. ;   Function
  1049. ;      sendFile
  1050. ;
  1051. ;   Description
  1052. ;       Transmits the requested file over the open data socket
  1053. ;       The file to send is named in the buff string
  1054. ;
  1055. ;   Inputs
  1056. ;       None
  1057. ;
  1058. ;   Outputs
  1059. ;       None
  1060. ;
  1061. ;***************************************************************************
  1062. sendFile:
  1063.     call    setupFilePath
  1064.  
  1065.     ; init fileblock descriptor, for file read
  1066.     mov     ebx, fileinfoblock
  1067.     and     dword [ebx], 0 ; read cmd
  1068.     and     dword [ebx+4], 0 ; first block
  1069.  
  1070. sf002a:
  1071.     ; now read the file..
  1072.     mov     eax,70
  1073.     mcall
  1074.     test    eax, eax
  1075.     jz      @f
  1076.     cmp     eax, 6
  1077.     jnz     sf_exit
  1078. @@:
  1079.     push    eax
  1080.     mov     esi, text + 0x1300
  1081.     mov     edx, ebx
  1082.     call    outputDataStr
  1083.     pop     eax
  1084.     test    eax, eax
  1085.     jnz     sf_exit
  1086. ; wait a bit
  1087.     mov     eax, 5
  1088.     mov     ebx, 10
  1089.     mcall
  1090.     mov     ebx, fileinfoblock
  1091.     add     dword [ebx+4], edx
  1092.     jmp     sf002a
  1093.  
  1094. sf_exit:
  1095.     ret
  1096.  
  1097.  
  1098. ;***************************************************************************
  1099. ;   Function
  1100. ;      getFile
  1101. ;
  1102. ;   Description
  1103. ;       Receives the specified file over the open data socket
  1104. ;       The file to receive is named in the buff string
  1105. ;
  1106. ;   Inputs
  1107. ;       None
  1108. ;
  1109. ;   Outputs
  1110. ;       None
  1111. ;
  1112. ;***************************************************************************
  1113. getFile:
  1114.     call    setupFilePath
  1115.  
  1116.     ; init fileblock descriptor, for file write
  1117.     xor     eax, eax
  1118.     mov     [fsize], eax            ; Start filelength at 0
  1119.     mov     [fileinfoblock+4], eax    ; set to 0
  1120.     inc     eax
  1121.     inc     eax
  1122.     mov     [fileinfoblock], eax    ; write cmd
  1123.  
  1124.     ; Read data from the socket until the socket closes
  1125.     ; loop
  1126.     ;   loop
  1127.     ;     read byte from socket
  1128.     ;     write byte to file buffer
  1129.     ;   until no more bytes in socket
  1130.     ;   sleep 100ms
  1131.     ; until socket no longer connected
  1132.     ; write file to ram
  1133.  
  1134. gf000:
  1135.     mov     eax, 53
  1136.     mov     ebx, 2                  ; Get # of bytes in input queue
  1137.     mov     ecx, [DataSocket]
  1138.     mcall
  1139.     test    eax, eax
  1140.     je      gf_sleep
  1141.  
  1142.     mov     eax, 53
  1143.     mov     ebx, 3                  ; Get a byte from socket in bl
  1144.     mov     ecx, [DataSocket]
  1145.     mcall                    ; returned data in bl
  1146.  
  1147.     mov     esi, text + 0x1300
  1148.     add     esi, dword [fsize]
  1149.     mov     [esi], bl
  1150.     inc     dword [fsize]
  1151.  
  1152.     ; dummy, write to screen
  1153.     ;call    printChar
  1154.  
  1155.     jmp     gf000
  1156.  
  1157. gf_sleep:
  1158.     ; Check to see if socket closed...
  1159.     mov     eax,53
  1160.     mov     ebx,6               ; Get socket status
  1161.     mov     ecx,[DataSocket]
  1162.     mcall
  1163.  
  1164.     cmp     eax, 7
  1165.     jne     gf001               ; still open, so just sleep a bit
  1166.  
  1167.     ; Finished, so write the file
  1168.     mov     eax, [fsize]
  1169.     mov     [fileinfoblock+12], eax
  1170.     mov     eax,70
  1171.     mov     ebx,fileinfoblock
  1172.     mcall
  1173.  
  1174.     ret                         ; Finished
  1175.  
  1176. gf001:
  1177.     ; wait a bit
  1178.     mov     eax,5
  1179.     mov     ebx,10              ; Delay for up 100ms
  1180.     mcall
  1181.     jmp     gf000               ; try for more data
  1182.  
  1183.  
  1184.  
  1185.  
  1186.  
  1187. ;***************************************************************************
  1188. ;   COMMAND HANDLERS FOLLOW
  1189. ;
  1190. ;   These handlers implement the functionality of each supported FTP Command
  1191. ;
  1192. ;***************************************************************************
  1193.  
  1194. cmdPWD:
  1195.     ; OK, show the directory name text
  1196.     mov     esi, ramdir
  1197.     mov     edx, ramdir_end - ramdir
  1198.     call    outputStr
  1199.  
  1200.     ; TODO give real directory
  1201.  
  1202.     ret
  1203.  
  1204.  
  1205. cmdCWD:
  1206.     ; Only / is valid for the ramdisk
  1207.     cmp     [buff+5], byte 0x0d
  1208.     jne     ccwd_000
  1209.  
  1210.     ; OK, show the directory name text
  1211.     mov     esi, chdir
  1212.     mov     edx, chdir_end - chdir
  1213.     jmp     ccwd_001
  1214.  
  1215. ccwd_000:
  1216.     ; Tell user there is no such directory
  1217.     mov     esi, noFileStr
  1218.     mov     edx, noFileStr_end - noFileStr
  1219.  
  1220. ccwd_001:
  1221.     call    outputStr
  1222.  
  1223.     ret
  1224.  
  1225.  
  1226. cmdQUIT:
  1227.     ; The remote end will do the close; We just
  1228.     ; say goodbye.
  1229.     mov     esi, byeStr
  1230.     mov     edx, byeStr_end - byeStr
  1231.     call    outputStr
  1232.     ret
  1233.  
  1234.  
  1235. cmdABOR:
  1236.  
  1237.     ; Close port
  1238.     call    disconnectData
  1239.  
  1240.     mov     esi, abortStr
  1241.     mov     edx, abortStr_end - abortStr
  1242.     call    outputStr
  1243.  
  1244.     ret
  1245.  
  1246. cmdPORT:
  1247.     ; TODO
  1248.     ; Copy the IP and port values to DataIP and DataPort
  1249.  
  1250.     call    parsePortStr
  1251.  
  1252.     ; Indicate the command was accepted
  1253.     mov     esi, cmdOKStr
  1254.     mov     edx, cmdOKStr_end - cmdOKStr
  1255.     call    outputStr
  1256.     ret
  1257.  
  1258. cmdnoop:
  1259.     ; Indicate the command was accepted
  1260.     mov     esi, cmdOKStr
  1261.     mov     edx, cmdOKStr_end - cmdOKStr
  1262.     call    outputStr
  1263.     ret
  1264.  
  1265.  
  1266. cmdTYPE:
  1267.     ; TODO
  1268.     ; Note the type field selected - reject if needed.
  1269.  
  1270.     ; Indicate the command was accepted
  1271.     mov     esi, cmdOKStr
  1272.     mov     edx, cmdOKStr_end - cmdOKStr
  1273.     call    outputStr
  1274.     ret
  1275.  
  1276. cmdsyst:
  1277.     ; Indicate the system type
  1278.     mov     esi, systStr
  1279.     mov     edx, systStr_end - systStr
  1280.     call    outputStr
  1281.     ret
  1282.  
  1283.  
  1284. cmdDELE:
  1285.     call    setupFilePath
  1286.  
  1287.     mov     ebx, fileinfoblock
  1288.     mov     dword [ebx], 8
  1289.     and     dword [ebx+4], 0
  1290.     push    dword [ebx+12]
  1291.     push    dword [ebx+16]
  1292.     and     dword [ebx+12], 0
  1293.     and     dword [ebx+16], 0
  1294.     mov     eax, 70
  1295.     mcall
  1296.     pop     dword [ebx+16]
  1297.     pop     dword [ebx+12]
  1298.  
  1299.     test    eax, eax
  1300.     jne     cmdDele_err
  1301.  
  1302.     mov     esi, delokStr
  1303.     mov     edx, delokStr_end - delokStr
  1304.     call    outputStr
  1305.  
  1306.     jmp     cmdDele_exit
  1307.  
  1308. cmdDele_err:
  1309.     mov     esi, noFileStr
  1310.     mov     edx, noFileStr_end - noFileStr
  1311.     call    outputStr
  1312.  
  1313.  
  1314. cmdDele_exit:
  1315.     ret
  1316.  
  1317.  
  1318. cmdNLST:
  1319. cmdLIST:
  1320.     ; Indicate the command was accepted
  1321.     mov     esi, startStr
  1322.     mov     edx, startStr_end - startStr
  1323.     call    outputStr
  1324.  
  1325.     call    connectData
  1326.  
  1327.     ; Wait for socket to establish
  1328.  
  1329. cl001:
  1330.     ; wait a bit
  1331.     mov     eax,5
  1332.     mov     ebx,10                ; Delay for up 100ms
  1333.     mcall
  1334.  
  1335.     ; check connection status
  1336.     mov     eax,53
  1337.     mov     ebx,6               ; Get socket status
  1338.     mov     ecx,[DataSocket]
  1339.     mcall
  1340.  
  1341.     cmp     eax, 4
  1342.     jne     cl001
  1343.  
  1344.     ; send directory listing
  1345.     call    sendDir
  1346.  
  1347.     ; Close port
  1348.     call    disconnectData
  1349.  
  1350.     mov     esi, endStr
  1351.     mov     edx, endStr_end - endStr
  1352.     call    outputStr
  1353.     ret
  1354.  
  1355. cmdRETR:
  1356.     ; Indicate the command was accepted
  1357.     mov     esi, startStr
  1358.     mov     edx, startStr_end - startStr
  1359.     call    outputStr
  1360.  
  1361.     call    connectData
  1362.  
  1363.     ; Wait for socket to establish
  1364.  
  1365. cr001:
  1366.     ; wait a bit
  1367.     mov     eax,5
  1368.     mov     ebx,10                ; Delay for up 100ms
  1369.     mcall
  1370.  
  1371.     ; check connection status
  1372.     mov     eax,53
  1373.     mov     ebx,6               ; Get socket status
  1374.     mov     ecx,[DataSocket]
  1375.     mcall
  1376.  
  1377.     cmp     eax, 4
  1378.     jne     cr001
  1379.  
  1380.     ; send data to remote user
  1381.     call    sendFile
  1382.  
  1383.     ; Close port
  1384.     call    disconnectData
  1385.  
  1386.     mov     esi, endStr
  1387.     mov     edx, endStr_end - endStr
  1388.     call    outputStr
  1389.  
  1390.  
  1391.     ret
  1392.  
  1393.  
  1394. cmdSTOR:
  1395.     ; Indicate the command was accepted
  1396.     mov     esi, storStr
  1397.     mov     edx, storStr_end - storStr
  1398.     call    outputStr
  1399.  
  1400.     call    connectData
  1401.  
  1402.     ; Wait for socket to establish
  1403.  
  1404. cs001:
  1405.     ; wait a bit
  1406.     mov     eax,5
  1407.     mov     ebx,10                ; Delay for up 100ms
  1408.     mcall
  1409.  
  1410.     ; check connection status
  1411.     mov     eax,53
  1412.     mov     ebx,6               ; Get socket status
  1413.     mov     ecx,[DataSocket]
  1414.     mcall
  1415.  
  1416.     cmp     eax, 4
  1417.     je      @f
  1418.     cmp     eax, 7
  1419.     jne     cs001
  1420. @@:
  1421.  
  1422.     ; get data file from remote user
  1423.     call    getFile
  1424.  
  1425.     mov     esi, endStr
  1426.     mov     edx, endStr_end - endStr
  1427.     call    outputStr
  1428.  
  1429.     ; Close port
  1430.     call    disconnectData
  1431.  
  1432.     ret
  1433.  
  1434.  
  1435.  
  1436. ; DATA AREA
  1437.  
  1438. ; This is the list of supported commands, and the function to call
  1439. ; The list end with a NULL.
  1440. CMDList:
  1441.                     db  'pwd',0
  1442.                     dd  cmdPWD
  1443.  
  1444.                     db  'PWD',0
  1445.                     dd  cmdPWD
  1446.  
  1447.                     db  'XPWD',0
  1448.                     dd  cmdPWD
  1449.  
  1450.                     db  'xpwd',0
  1451.                     dd  cmdPWD
  1452.  
  1453.                     db  'QUIT',0
  1454.                     dd  cmdQUIT
  1455.  
  1456.                     db  'quit',0
  1457.                     dd  cmdQUIT
  1458.  
  1459.                     db  'PORT',0
  1460.                     dd  cmdPORT
  1461.  
  1462.                     db  'port',0
  1463.                     dd  cmdPORT
  1464.  
  1465.                     db  'LIST',0
  1466.                     dd  cmdLIST
  1467.  
  1468.                     db  'list',0
  1469.                     dd  cmdLIST
  1470.  
  1471.                     db  'NLST',0
  1472.                     dd  cmdNLST
  1473.  
  1474.                     db  'nlst',0
  1475.                     dd  cmdNLST
  1476.  
  1477.                     db  'TYPE',0
  1478.                     dd  cmdTYPE
  1479.  
  1480.                     db  'type',0
  1481.                     dd  cmdTYPE
  1482.  
  1483.                     db  'syst',0
  1484.                     dd  cmdsyst
  1485.  
  1486.                     db  'noop',0
  1487.                     dd  cmdnoop
  1488.  
  1489.                     db  'CWD',0
  1490.                     dd  cmdCWD
  1491.  
  1492.                     db  'cwd',0
  1493.                     dd  cmdCWD
  1494.  
  1495.                     db  'RETR',0
  1496.                     dd  cmdRETR
  1497.  
  1498.                     db  'retr',0
  1499.                     dd  cmdRETR
  1500.  
  1501.                     db  'DELE',0
  1502.                     dd  cmdDELE
  1503.  
  1504.                     db  'dele',0
  1505.                     dd  cmdDELE
  1506.  
  1507.                     db  'stor',0
  1508.                     dd  cmdSTOR
  1509.  
  1510.                     db  'STOR',0
  1511.                     dd  cmdSTOR
  1512.  
  1513.                     db  'ABOR',0
  1514.                     dd  cmdABOR
  1515.  
  1516.                     db  'abor',0
  1517.                     dd  cmdABOR
  1518.  
  1519.                     db  0xff,0xf4,0xff,0xf2,'ABOR',0
  1520.                     dd  cmdABOR
  1521.  
  1522.                     db  0
  1523.  
  1524.  
  1525. cmdPtr              dd  0
  1526. CmdSocket           dd  0x0
  1527. CmdSocketStatus     dd  0x0
  1528. DataSocket          dd  0x0
  1529. DataSocketStatus    dd  0x0
  1530. DataPort            dd  0x00
  1531. DataIP              dd  0x00
  1532. pos                 dd  80 * 1
  1533. scroll              dd  1
  1534.                     dd  24
  1535.  
  1536. labelt              db  'FTP Server v0.1',0
  1537. contt               db  'Connected'
  1538. contlen:
  1539. discontt            db  'Disconnected'
  1540. discontlen:
  1541.  
  1542. cmdOKStr:           db  '200 Command OK',0x0d,0x0a
  1543. cmdOKStr_end:
  1544.  
  1545. loginStr0:          db  '220-  Menuet FTP Server v0.1',0x0d,0x0a
  1546.                     db  '220 Username and Password required',0x0d,0x0a
  1547. loginStr0_end:
  1548.  
  1549. loginStr1:          db  '331 Password now required',0x0d,0x0a
  1550. loginStr1_end:
  1551.  
  1552. loginStr2:          db  '230 You are now logged in.',0x0d,0x0a
  1553. loginStr2_end:
  1554.  
  1555. byeStr:             db  '221 Bye bye!',0x0d,0x0a
  1556. byeStr_end:
  1557.  
  1558. systStr:            db  '215 UNIX system type',0x0d,0x0a
  1559. systStr_end:
  1560.  
  1561. ramdir:             db  '257 "/"',0x0d,0x0a
  1562. ramdir_end:
  1563.  
  1564. chdir:              db  '200 directory changed to /',0x0d,0x0a
  1565. chdir_end:
  1566.  
  1567. unsupStr:           db  '500 Unsupported command',0x0d,0x0a
  1568. unsupStr_end:
  1569.  
  1570. noFileStr:          db  '550 No such file',0x0d,0x0a
  1571. noFileStr_end:
  1572.  
  1573. delokStr:           db  '250 DELE command successful',0x0d,0x0a
  1574. delokStr_end:
  1575.  
  1576. startStr:           db  '150 Here it comes...',0x0d,0x0a
  1577. startStr_end:
  1578.  
  1579. storStr:            db  '150 Connecting for STOR',0x0d,0x0a
  1580. storStr_end:
  1581.  
  1582. endStr:             db  '226 Transfer OK, Closing connection',0x0d,0x0a
  1583. endStr_end:
  1584.  
  1585. abortStr:           db  '225 Abort successful',0x0d,0x0a
  1586. abortStr_end:
  1587.  
  1588.  ; This is the buffer used for building up a directory listing line
  1589. dirStr:             times 128 db 0
  1590.  
  1591. ; This is template string used in building up a directory listing line
  1592. tmplStr:            db 'rw-rw-rw-    1 0        0                ',0
  1593.  
  1594. months:
  1595.         dd     'Jan ','Feb ','Mar ','Apr ','May ','Jun '
  1596.         dd     'Jul ','Aug ','Sep ','Oct ','Nov ','Dec '
  1597.  
  1598. fileinfoblock:
  1599.                     dd      0x00
  1600.                     dd      0x00
  1601.                     dd      0x00
  1602.                     dd      0x200         ; bytes to read
  1603.                     dd      text + 0x1300 ; data area
  1604. filename:           times 256 db 0
  1605.  
  1606. ; The following lines define data for reading a directory block
  1607. DirBlocksPerCall = 16
  1608. dirinfoblock:
  1609.                     dd      1
  1610.                     dd      0x00
  1611.                     dd      0x00
  1612.                     dd      DirBlocksPerCall
  1613.                     dd      text + 0x1300   ; data area
  1614. ; The 'filename' for a directory listing
  1615. dirpath             db      '/sys',0
  1616.  
  1617. fsize:              dd      0
  1618.  
  1619. state               db  0
  1620. buffptr             dd  0
  1621. buff:               times 256 db 0  ; Could put this after iend
  1622.  
  1623. ; Ram use at the end of the application:
  1624. ; text                  : 2400 bytes for screen memory
  1625. ; text + 0x1300          : file data area
  1626. text:
  1627. I_END:
  1628.