Subversion Repositories Kolibri OS

Rev

Rev 1297 | 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 10ms
  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,1                 ; Delay for up 10ms
  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.     mov     dword [ebx+12], 0x400 ; block size
  1070.  
  1071. sf002a:
  1072.     ; now read the file..
  1073.     mov     eax,70
  1074.     mcall
  1075.     test    eax, eax
  1076.     jz      @f
  1077.     cmp     eax, 6
  1078.     jnz     sf_exit
  1079. @@:
  1080.     push    eax
  1081.     mov     esi, text + 0x1300
  1082.     mov     edx, ebx
  1083.     call    outputDataStr
  1084.     pop     eax
  1085.     test    eax, eax
  1086.     jnz     sf_exit
  1087. ; wait a bit
  1088.     mov     eax, 5
  1089.     mov     ebx, 1
  1090.     mcall
  1091.     mov     ebx, fileinfoblock
  1092.     add     dword [ebx+4], edx
  1093.     jmp     sf002a
  1094.  
  1095. sf_exit:
  1096.     ret
  1097.  
  1098.  
  1099. ;***************************************************************************
  1100. ;   Function
  1101. ;      getFile
  1102. ;
  1103. ;   Description
  1104. ;       Receives the specified file over the open data socket
  1105. ;       The file to receive is named in the buff string
  1106. ;
  1107. ;   Inputs
  1108. ;       None
  1109. ;
  1110. ;   Outputs
  1111. ;       None
  1112. ;
  1113. ;***************************************************************************
  1114. getFile:
  1115.     call    setupFilePath
  1116.  
  1117.     ; init fileblock descriptor, for file write
  1118.     xor     eax, eax
  1119.     mov     [fsize], eax            ; Start filelength at 0
  1120.     mov     [fileinfoblock+4], eax    ; set to 0
  1121.     inc     eax
  1122.     inc     eax
  1123.     mov     [fileinfoblock], eax    ; write cmd
  1124.  
  1125.     ; Read data from the socket until the socket closes
  1126.     ; loop
  1127.     ;   loop
  1128.     ;     read byte from socket
  1129.     ;     write byte to file buffer
  1130.     ;   until no more bytes in socket
  1131.     ;   sleep 100ms
  1132.     ; until socket no longer connected
  1133.     ; write file to ram
  1134.  
  1135. gf000:
  1136.     mov     eax, 53
  1137.     mov     ebx, 2                  ; Get # of bytes in input queue
  1138.     mov     ecx, [DataSocket]
  1139.     mcall
  1140.     test    eax, eax
  1141.     je      gf_sleep
  1142.  
  1143.     mov     eax, 53
  1144.     mov     ebx, 11                 ; Get a bytes from socket
  1145.     mov     ecx, [DataSocket]
  1146.     mov     edx, text + 0x1300
  1147.     add     edx, dword [fsize]
  1148.     mcall                           ; returned data len in eax
  1149.     add     dword [fsize], eax
  1150.  
  1151.     jmp     gf000
  1152.  
  1153. gf_sleep:
  1154.     ; Check to see if socket closed...
  1155.     mov     eax,53
  1156.     mov     ebx,6               ; Get socket status
  1157.     mov     ecx,[DataSocket]
  1158.     mcall
  1159.  
  1160.     cmp     eax, 7
  1161.     jne     gf001               ; still open, so just sleep a bit
  1162.  
  1163.     ; Finished, so write the file
  1164.     mov     eax, [fsize]
  1165.     mov     [fileinfoblock+12], eax
  1166.     mov     eax,70
  1167.     mov     ebx,fileinfoblock
  1168.     mcall
  1169.  
  1170.     ret                         ; Finished
  1171.  
  1172. gf001:
  1173.     ; wait a bit
  1174.     mov     eax,5
  1175.     mov     ebx,1               ; Delay for up 10ms
  1176.     mcall
  1177.     jmp     gf000               ; try for more data
  1178.  
  1179.  
  1180.  
  1181.  
  1182.  
  1183. ;***************************************************************************
  1184. ;   COMMAND HANDLERS FOLLOW
  1185. ;
  1186. ;   These handlers implement the functionality of each supported FTP Command
  1187. ;
  1188. ;***************************************************************************
  1189.  
  1190. cmdPWD:
  1191.     ; OK, show the directory name text
  1192.     mov     esi, ramdir
  1193.     mov     edx, ramdir_end - ramdir
  1194.     call    outputStr
  1195.  
  1196.     ; TODO give real directory
  1197.  
  1198.     ret
  1199.  
  1200.  
  1201. cmdCWD:
  1202.     ; Only / is valid for the ramdisk
  1203.     cmp     [buff+5], byte 0x0d
  1204.     jne     ccwd_000
  1205.  
  1206.     ; OK, show the directory name text
  1207.     mov     esi, chdir
  1208.     mov     edx, chdir_end - chdir
  1209.     jmp     ccwd_001
  1210.  
  1211. ccwd_000:
  1212.     ; Tell user there is no such directory
  1213.     mov     esi, noFileStr
  1214.     mov     edx, noFileStr_end - noFileStr
  1215.  
  1216. ccwd_001:
  1217.     call    outputStr
  1218.  
  1219.     ret
  1220.  
  1221.  
  1222. cmdQUIT:
  1223.     ; The remote end will do the close; We just
  1224.     ; say goodbye.
  1225.     mov     esi, byeStr
  1226.     mov     edx, byeStr_end - byeStr
  1227.     call    outputStr
  1228.     ret
  1229.  
  1230.  
  1231. cmdABOR:
  1232.  
  1233.     ; Close port
  1234.     call    disconnectData
  1235.  
  1236.     mov     esi, abortStr
  1237.     mov     edx, abortStr_end - abortStr
  1238.     call    outputStr
  1239.  
  1240.     ret
  1241.  
  1242. cmdPORT:
  1243.     ; TODO
  1244.     ; Copy the IP and port values to DataIP and DataPort
  1245.  
  1246.     call    parsePortStr
  1247.  
  1248.     ; Indicate the command was accepted
  1249.     mov     esi, cmdOKStr
  1250.     mov     edx, cmdOKStr_end - cmdOKStr
  1251.     call    outputStr
  1252.     ret
  1253.  
  1254. cmdnoop:
  1255.     ; Indicate the command was accepted
  1256.     mov     esi, cmdOKStr
  1257.     mov     edx, cmdOKStr_end - cmdOKStr
  1258.     call    outputStr
  1259.     ret
  1260.  
  1261.  
  1262. cmdTYPE:
  1263.     ; TODO
  1264.     ; Note the type field selected - reject if needed.
  1265.  
  1266.     ; Indicate the command was accepted
  1267.     mov     esi, cmdOKStr
  1268.     mov     edx, cmdOKStr_end - cmdOKStr
  1269.     call    outputStr
  1270.     ret
  1271.  
  1272. cmdsyst:
  1273.     ; Indicate the system type
  1274.     mov     esi, systStr
  1275.     mov     edx, systStr_end - systStr
  1276.     call    outputStr
  1277.     ret
  1278.  
  1279.  
  1280. cmdDELE:
  1281.     call    setupFilePath
  1282.  
  1283.     mov     ebx, fileinfoblock
  1284.     mov     dword [ebx], 8
  1285.     and     dword [ebx+4], 0
  1286.     push    dword [ebx+12]
  1287.     push    dword [ebx+16]
  1288.     and     dword [ebx+12], 0
  1289.     and     dword [ebx+16], 0
  1290.     mov     eax, 70
  1291.     mcall
  1292.     pop     dword [ebx+16]
  1293.     pop     dword [ebx+12]
  1294.  
  1295.     test    eax, eax
  1296.     jne     cmdDele_err
  1297.  
  1298.     mov     esi, delokStr
  1299.     mov     edx, delokStr_end - delokStr
  1300.     call    outputStr
  1301.  
  1302.     jmp     cmdDele_exit
  1303.  
  1304. cmdDele_err:
  1305.     mov     esi, noFileStr
  1306.     mov     edx, noFileStr_end - noFileStr
  1307.     call    outputStr
  1308.  
  1309.  
  1310. cmdDele_exit:
  1311.     ret
  1312.  
  1313.  
  1314. cmdNLST:
  1315. cmdLIST:
  1316.     ; Indicate the command was accepted
  1317.     mov     esi, startStr
  1318.     mov     edx, startStr_end - startStr
  1319.     call    outputStr
  1320.  
  1321.     call    connectData
  1322.  
  1323.     ; Wait for socket to establish
  1324.  
  1325. cl001:
  1326.     ; wait a bit
  1327.     mov     eax,5
  1328.     mov     ebx,10                ; Delay for up 100ms
  1329.     mcall
  1330.  
  1331.     ; check connection status
  1332.     mov     eax,53
  1333.     mov     ebx,6               ; Get socket status
  1334.     mov     ecx,[DataSocket]
  1335.     mcall
  1336.  
  1337.     cmp     eax, 4
  1338.     jne     cl001
  1339.  
  1340.     ; send directory listing
  1341.     call    sendDir
  1342.  
  1343.     ; Close port
  1344.     call    disconnectData
  1345.  
  1346.     mov     esi, endStr
  1347.     mov     edx, endStr_end - endStr
  1348.     call    outputStr
  1349.     ret
  1350.  
  1351. cmdRETR:
  1352.     ; Indicate the command was accepted
  1353.     mov     esi, startStr
  1354.     mov     edx, startStr_end - startStr
  1355.     call    outputStr
  1356.  
  1357.     call    connectData
  1358.  
  1359.     ; Wait for socket to establish
  1360.  
  1361. cr001:
  1362.     ; wait a bit
  1363.     mov     eax,5
  1364.     mov     ebx,10                ; Delay for up 100ms
  1365.     mcall
  1366.  
  1367.     ; check connection status
  1368.     mov     eax,53
  1369.     mov     ebx,6               ; Get socket status
  1370.     mov     ecx,[DataSocket]
  1371.     mcall
  1372.  
  1373.     cmp     eax, 4
  1374.     jne     cr001
  1375.  
  1376.     ; send data to remote user
  1377.     call    sendFile
  1378.  
  1379.     ; Close port
  1380.     call    disconnectData
  1381.  
  1382.     mov     esi, endStr
  1383.     mov     edx, endStr_end - endStr
  1384.     call    outputStr
  1385.  
  1386.  
  1387.     ret
  1388.  
  1389.  
  1390. cmdSTOR:
  1391.     ; Indicate the command was accepted
  1392.     mov     esi, storStr
  1393.     mov     edx, storStr_end - storStr
  1394.     call    outputStr
  1395.  
  1396.     call    connectData
  1397.  
  1398.     ; Wait for socket to establish
  1399.  
  1400. cs001:
  1401.     ; wait a bit
  1402.     mov     eax,5
  1403.     mov     ebx,10                ; Delay for up 100ms
  1404.     mcall
  1405.  
  1406.     ; check connection status
  1407.     mov     eax,53
  1408.     mov     ebx,6               ; Get socket status
  1409.     mov     ecx,[DataSocket]
  1410.     mcall
  1411.  
  1412.     cmp     eax, 4
  1413.     je      @f
  1414.     cmp     eax, 7
  1415.     jne     cs001
  1416. @@:
  1417.  
  1418.     ; get data file from remote user
  1419.     call    getFile
  1420.  
  1421.     mov     esi, endStr
  1422.     mov     edx, endStr_end - endStr
  1423.     call    outputStr
  1424.  
  1425.     ; Close port
  1426.     call    disconnectData
  1427.  
  1428.     ret
  1429.  
  1430.  
  1431.  
  1432. ; DATA AREA
  1433.  
  1434. ; This is the list of supported commands, and the function to call
  1435. ; The list end with a NULL.
  1436. CMDList:
  1437.                     db  'pwd',0
  1438.                     dd  cmdPWD
  1439.  
  1440.                     db  'PWD',0
  1441.                     dd  cmdPWD
  1442.  
  1443.                     db  'XPWD',0
  1444.                     dd  cmdPWD
  1445.  
  1446.                     db  'xpwd',0
  1447.                     dd  cmdPWD
  1448.  
  1449.                     db  'QUIT',0
  1450.                     dd  cmdQUIT
  1451.  
  1452.                     db  'quit',0
  1453.                     dd  cmdQUIT
  1454.  
  1455.                     db  'PORT',0
  1456.                     dd  cmdPORT
  1457.  
  1458.                     db  'port',0
  1459.                     dd  cmdPORT
  1460.  
  1461.                     db  'LIST',0
  1462.                     dd  cmdLIST
  1463.  
  1464.                     db  'list',0
  1465.                     dd  cmdLIST
  1466.  
  1467.                     db  'NLST',0
  1468.                     dd  cmdNLST
  1469.  
  1470.                     db  'nlst',0
  1471.                     dd  cmdNLST
  1472.  
  1473.                     db  'TYPE',0
  1474.                     dd  cmdTYPE
  1475.  
  1476.                     db  'type',0
  1477.                     dd  cmdTYPE
  1478.  
  1479.                     db  'syst',0
  1480.                     dd  cmdsyst
  1481.  
  1482.                     db  'noop',0
  1483.                     dd  cmdnoop
  1484.  
  1485.                     db  'CWD',0
  1486.                     dd  cmdCWD
  1487.  
  1488.                     db  'cwd',0
  1489.                     dd  cmdCWD
  1490.  
  1491.                     db  'RETR',0
  1492.                     dd  cmdRETR
  1493.  
  1494.                     db  'retr',0
  1495.                     dd  cmdRETR
  1496.  
  1497.                     db  'DELE',0
  1498.                     dd  cmdDELE
  1499.  
  1500.                     db  'dele',0
  1501.                     dd  cmdDELE
  1502.  
  1503.                     db  'stor',0
  1504.                     dd  cmdSTOR
  1505.  
  1506.                     db  'STOR',0
  1507.                     dd  cmdSTOR
  1508.  
  1509.                     db  'ABOR',0
  1510.                     dd  cmdABOR
  1511.  
  1512.                     db  'abor',0
  1513.                     dd  cmdABOR
  1514.  
  1515.                     db  0xff,0xf4,0xff,0xf2,'ABOR',0
  1516.                     dd  cmdABOR
  1517.  
  1518.                     db  0
  1519.  
  1520.  
  1521. cmdPtr              dd  0
  1522. CmdSocket           dd  0x0
  1523. CmdSocketStatus     dd  0x0
  1524. DataSocket          dd  0x0
  1525. DataSocketStatus    dd  0x0
  1526. DataPort            dd  0x00
  1527. DataIP              dd  0x00
  1528. pos                 dd  80 * 1
  1529. scroll              dd  1
  1530.                     dd  24
  1531.  
  1532. labelt              db  'FTP Server v0.1',0
  1533. contt               db  'Connected'
  1534. contlen:
  1535. discontt            db  'Disconnected'
  1536. discontlen:
  1537.  
  1538. cmdOKStr:           db  '200 Command OK',0x0d,0x0a
  1539. cmdOKStr_end:
  1540.  
  1541. loginStr0:          db  '220-  Menuet FTP Server v0.1',0x0d,0x0a
  1542.                     db  '220 Username and Password required',0x0d,0x0a
  1543. loginStr0_end:
  1544.  
  1545. loginStr1:          db  '331 Password now required',0x0d,0x0a
  1546. loginStr1_end:
  1547.  
  1548. loginStr2:          db  '230 You are now logged in.',0x0d,0x0a
  1549. loginStr2_end:
  1550.  
  1551. byeStr:             db  '221 Bye bye!',0x0d,0x0a
  1552. byeStr_end:
  1553.  
  1554. systStr:            db  '215 UNIX system type',0x0d,0x0a
  1555. systStr_end:
  1556.  
  1557. ramdir:             db  '257 "/"',0x0d,0x0a
  1558. ramdir_end:
  1559.  
  1560. chdir:              db  '200 directory changed to /',0x0d,0x0a
  1561. chdir_end:
  1562.  
  1563. unsupStr:           db  '500 Unsupported command',0x0d,0x0a
  1564. unsupStr_end:
  1565.  
  1566. noFileStr:          db  '550 No such file',0x0d,0x0a
  1567. noFileStr_end:
  1568.  
  1569. delokStr:           db  '250 DELE command successful',0x0d,0x0a
  1570. delokStr_end:
  1571.  
  1572. startStr:           db  '150 Here it comes...',0x0d,0x0a
  1573. startStr_end:
  1574.  
  1575. storStr:            db  '150 Connecting for STOR',0x0d,0x0a
  1576. storStr_end:
  1577.  
  1578. endStr:             db  '226 Transfer OK, Closing connection',0x0d,0x0a
  1579. endStr_end:
  1580.  
  1581. abortStr:           db  '225 Abort successful',0x0d,0x0a
  1582. abortStr_end:
  1583.  
  1584.  ; This is the buffer used for building up a directory listing line
  1585. dirStr:             times 128 db 0
  1586.  
  1587. ; This is template string used in building up a directory listing line
  1588. tmplStr:            db 'rw-rw-rw-    1 0        0                ',0
  1589.  
  1590. months:
  1591.         dd     'Jan ','Feb ','Mar ','Apr ','May ','Jun '
  1592.         dd     'Jul ','Aug ','Sep ','Oct ','Nov ','Dec '
  1593.  
  1594. fileinfoblock:
  1595.                     dd      0x00
  1596.                     dd      0x00
  1597.                     dd      0x00
  1598.                     dd      0x200         ; bytes to read
  1599.                     dd      text + 0x1300 ; data area
  1600. filename:           times 256 db 0
  1601.  
  1602. ; The following lines define data for reading a directory block
  1603. DirBlocksPerCall = 16
  1604. dirinfoblock:
  1605.                     dd      1
  1606.                     dd      0x00
  1607.                     dd      0x00
  1608.                     dd      DirBlocksPerCall
  1609.                     dd      text + 0x1300   ; data area
  1610. ; The 'filename' for a directory listing
  1611. dirpath             db      '/sys',0
  1612.  
  1613. fsize:              dd      0
  1614.  
  1615. state               db  0
  1616. buffptr             dd  0
  1617. buff:               times 256 db 0  ; Could put this after iend
  1618.  
  1619. ; Ram use at the end of the application:
  1620. ; text                  : 2400 bytes for screen memory
  1621. ; text + 0x1300          : file data area
  1622. text:
  1623. I_END:
  1624.