Subversion Repositories Kolibri OS

Rev

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