]> gitweb.factorcode.org Git - factor.git/commitdiff
move ftp to basis
authorDoug Coleman <doug.coleman@gmail.com>
Thu, 4 Dec 2008 00:19:06 +0000 (18:19 -0600)
committerDoug Coleman <doug.coleman@gmail.com>
Thu, 4 Dec 2008 00:19:06 +0000 (18:19 -0600)
18 files changed:
basis/ftp/client/authors.txt [new file with mode: 0644]
basis/ftp/client/client.factor [new file with mode: 0644]
basis/ftp/client/listing-parser/authors.txt [new file with mode: 0644]
basis/ftp/client/listing-parser/listing-parser.factor [new file with mode: 0644]
basis/ftp/client/tags.txt [new file with mode: 0644]
basis/ftp/ftp.factor [new file with mode: 0644]
basis/ftp/server/server.factor [new file with mode: 0644]
basis/ftp/server/tags.txt [new file with mode: 0644]
basis/ftp/tags.txt [new file with mode: 0644]
extra/ftp/client/authors.txt [deleted file]
extra/ftp/client/client.factor [deleted file]
extra/ftp/client/listing-parser/authors.txt [deleted file]
extra/ftp/client/listing-parser/listing-parser.factor [deleted file]
extra/ftp/client/tags.txt [deleted file]
extra/ftp/ftp.factor [deleted file]
extra/ftp/server/server.factor [deleted file]
extra/ftp/server/tags.txt [deleted file]
extra/ftp/tags.txt [deleted file]

diff --git a/basis/ftp/client/authors.txt b/basis/ftp/client/authors.txt
new file mode 100644 (file)
index 0000000..7c1b2f2
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
diff --git a/basis/ftp/client/client.factor b/basis/ftp/client/client.factor
new file mode 100644 (file)
index 0000000..9c82cdb
--- /dev/null
@@ -0,0 +1,110 @@
+! Copyright (C) 2008 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors arrays classes.singleton combinators
+continuations io io.encodings.binary io.encodings.utf8
+io.files io.sockets kernel io.streams.duplex math
+math.parser sequences splitting namespaces strings fry ftp
+ftp.client.listing-parser urls ;
+IN: ftp.client
+
+: (ftp-response-code) ( str -- n )
+    3 head string>number ;
+
+: ftp-response-code ( string -- n/f )
+    dup fourth CHAR: - = [ drop f ] [ (ftp-response-code) ] if ;
+
+: read-response-loop ( ftp-response -- ftp-response )
+    readln
+    [ add-response-line ] [ ftp-response-code ] bi
+    over n>> = [ read-response-loop ] unless ;
+
+: read-response ( -- ftp-response )
+    <ftp-response> readln
+    [ (ftp-response-code) >>n ]
+    [ add-response-line ]
+    [ fourth CHAR: - = ] tri
+    [ read-response-loop ] when ;
+
+ERROR: ftp-error got expected ;
+
+: ftp-assert ( ftp-response n -- )
+    2dup [ n>> ] dip = [ 2drop ] [ ftp-error ] if ;
+
+: ftp-command ( string -- ftp-response )
+    ftp-send read-response ;
+
+: ftp-user ( url -- ftp-response )
+    username>> "USER " prepend ftp-command ;
+
+: ftp-password ( url -- ftp-response )
+    password>> "PASS " prepend ftp-command ;
+
+: ftp-cwd ( directory -- ftp-response )
+    "CWD " prepend ftp-command ;
+
+: ftp-retr ( filename -- ftp-response )
+    "RETR " prepend ftp-command ;
+
+: ftp-set-binary ( -- ftp-response ) "TYPE I" ftp-command ;
+
+: ftp-pwd ( -- ftp-response ) "PWD" ftp-command ;
+
+: ftp-list ( -- )
+    "LIST" ftp-command 150 ftp-assert ;
+
+: ftp-quit ( -- ftp-response ) "QUIT" ftp-command ;
+
+: ftp-epsv ( -- ftp-response )
+    "EPSV" ftp-command dup 229 ftp-assert ;
+
+: parse-epsv ( ftp-response -- port )
+    strings>> first "|" split 2 tail* first string>number ;
+
+: open-passive-client ( url protocol -- stream )
+    [ host>> ftp-epsv parse-epsv <inet> ] dip <client> drop ;
+
+: list ( url -- ftp-response )
+    utf8 open-passive-client
+    ftp-list
+    lines
+    <ftp-response> swap >>strings
+    read-response 226 ftp-assert
+    parse-list ;
+
+: (ftp-get) ( url path -- )
+    [ binary open-passive-client ] dip
+    [ ftp-retr 150 ftp-assert drop ]
+    [ binary <file-writer> stream-copy ] 2bi
+    read-response 226 ftp-assert ;
+
+: ftp-login ( url -- )
+    read-response 220 ftp-assert
+    [ ftp-user 331 ftp-assert ]
+    [ ftp-password 230 ftp-assert ] bi
+    ftp-set-binary 200 ftp-assert ;
+
+: ftp-connect ( url -- stream )
+    [ host>> ] [ port>> ] bi <inet> utf8 <client> drop ;
+
+: with-ftp-client ( url quot -- )
+    [ [ ftp-connect ] keep ] dip
+    '[ _ [ ftp-login ] _ bi ftp-quit drop ] with-stream ; inline
+
+: ensure-login ( url -- url )
+    dup username>> [
+        "anonymous" >>username
+        "ftp-client" >>password
+    ] unless ;
+
+: >ftp-url ( url -- url' ) >url ensure-port ensure-login ;
+
+: ftp-get ( url -- )
+    >ftp-url [
+        dup path>>
+        [ nip parent-directory ftp-cwd drop ]
+        [ file-name (ftp-get) ] 2bi
+    ] with-ftp-client ;
+
+
+
+
diff --git a/basis/ftp/client/listing-parser/authors.txt b/basis/ftp/client/listing-parser/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/basis/ftp/client/listing-parser/listing-parser.factor b/basis/ftp/client/listing-parser/listing-parser.factor
new file mode 100644 (file)
index 0000000..04e96ed
--- /dev/null
@@ -0,0 +1,89 @@
+! Copyright (C) 2008 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors combinators io.files kernel math.parser
+sequences splitting ;
+IN: ftp.client.listing-parser
+
+: ch>file-type ( ch -- type )
+    {
+        { CHAR: b [ +block-device+ ] }
+        { CHAR: c [ +character-device+ ] }
+        { CHAR: d [ +directory+ ] }
+        { CHAR: l [ +symbolic-link+ ] }
+        { CHAR: s [ +socket+ ] }
+        { CHAR: p [ +fifo+ ] }
+        { CHAR: - [ +regular-file+ ] }
+        [ drop +unknown+ ]
+    } case ;
+
+: file-type>ch ( type -- string )
+    {
+        { +block-device+ [ CHAR: b ] }
+        { +character-device+ [ CHAR: c ] }
+        { +directory+ [ CHAR: d ] }
+        { +symbolic-link+ [ CHAR: l ] }
+        { +socket+ [ CHAR: s ] }
+        { +fifo+ [ CHAR: p ] }
+        { +regular-file+ [ CHAR: - ] }
+        [ drop CHAR: - ]
+    } case ;
+
+: parse-permissions ( remote-file str -- remote-file )
+    [ first ch>file-type >>type ] [ rest >>permissions ] bi ;
+
+TUPLE: remote-file
+type permissions links owner group size month day time year
+name target ;
+
+: <remote-file> ( -- remote-file ) remote-file new ;
+
+: parse-list-11 ( lines -- seq )
+    [
+        11 f pad-right
+        <remote-file> swap {
+            [ 0 swap nth parse-permissions ]
+            [ 1 swap nth string>number >>links ]
+            [ 2 swap nth >>owner ]
+            [ 3 swap nth >>group ]
+            [ 4 swap nth string>number >>size ]
+            [ 5 swap nth >>month ]
+            [ 6 swap nth >>day ]
+            [ 7 swap nth >>time ]
+            [ 8 swap nth >>name ]
+            [ 10 swap nth >>target ]
+        } cleave
+    ] map ;
+
+: parse-list-8 ( lines -- seq )
+    [
+        <remote-file> swap {
+            [ 0 swap nth parse-permissions ]
+            [ 1 swap nth string>number >>links ]
+            [ 2 swap nth >>owner ]
+            [ 3 swap nth >>size ]
+            [ 4 swap nth >>month ]
+            [ 5 swap nth >>day ]
+            [ 6 swap nth >>time ]
+            [ 7 swap nth >>name ]
+        } cleave
+    ] map ;
+
+: parse-list-3 ( lines -- seq )
+    [
+        <remote-file> swap {
+            [ 0 swap nth parse-permissions ]
+            [ 1 swap nth string>number >>links ]
+            [ 2 swap nth >>name ]
+        } cleave
+    ] map ;
+
+: parse-list ( ftp-response -- ftp-response )
+    dup strings>>
+    [ " " split harvest ] map
+    dup length {
+        { 11 [ parse-list-11 ] }
+        { 9 [ parse-list-11 ] }
+        { 8 [ parse-list-8 ] }
+        { 3 [ parse-list-3 ] }
+        [ drop ]
+    } case >>parsed ;
diff --git a/basis/ftp/client/tags.txt b/basis/ftp/client/tags.txt
new file mode 100644 (file)
index 0000000..992ae12
--- /dev/null
@@ -0,0 +1 @@
+network
diff --git a/basis/ftp/ftp.factor b/basis/ftp/ftp.factor
new file mode 100644 (file)
index 0000000..adf7d5b
--- /dev/null
@@ -0,0 +1,21 @@
+! Copyright (C) 2008 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors arrays assocs combinators io io.files kernel
+math.parser sequences strings ;
+IN: ftp
+
+SINGLETON: active
+SINGLETON: passive
+
+TUPLE: ftp-response n strings parsed ;
+
+: <ftp-response> ( -- ftp-response )
+    ftp-response new
+        V{ } clone >>strings ;
+
+: add-response-line ( ftp-response string -- ftp-response )
+    over strings>> push ;
+
+: ftp-send ( string -- ) write "\r\n" write flush ;
+: ftp-ipv4 1 ; inline
+: ftp-ipv6 2 ; inline
diff --git a/basis/ftp/server/server.factor b/basis/ftp/server/server.factor
new file mode 100644 (file)
index 0000000..b0ec340
--- /dev/null
@@ -0,0 +1,353 @@
+! Copyright (C) 2008 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: combinators.short-circuit accessors combinators io
+io.encodings.8-bit io.encodings io.encodings.binary
+io.encodings.utf8 io.files io.sockets kernel math.parser
+namespaces make sequences ftp io.unix.launcher.parser
+unicode.case splitting assocs classes io.servers.connection
+destructors calendar io.timeouts io.streams.duplex threads
+continuations math concurrency.promises byte-arrays
+io.backend tools.hexdump tools.files io.streams.string ;
+IN: ftp.server
+
+TUPLE: ftp-client url mode state command-promise user password ;
+
+: <ftp-client> ( url -- ftp-client )
+    ftp-client new
+        swap >>url ;
+    
+SYMBOL: client
+
+: ftp-server-directory ( -- str )
+    \ ftp-server-directory get-global "resource:temp" or
+    normalize-path ;
+
+TUPLE: ftp-command raw tokenized ;
+
+: <ftp-command> ( -- obj )
+    ftp-command new ;
+
+TUPLE: ftp-get path ;
+
+: <ftp-get> ( path -- obj )
+    ftp-get new
+        swap >>path ;
+
+TUPLE: ftp-put path ;
+
+: <ftp-put> ( path -- obj )
+    ftp-put new
+        swap >>path ;
+
+TUPLE: ftp-list ;
+
+C: <ftp-list> ftp-list
+
+: read-command ( -- ftp-command )
+    <ftp-command> readln
+    [ >>raw ] [ tokenize-command >>tokenized ] bi ;
+
+: (send-response) ( n string separator -- )
+    rot number>string write write ftp-send ;
+
+: send-response ( ftp-response -- )
+    [ n>> ] [ strings>> ] bi
+    [ but-last-slice [ "-" (send-response) ] with each ]
+    [ first " " (send-response) ] 2bi ;
+
+: server-response ( n string -- )
+    <ftp-response>
+        swap add-response-line
+        swap >>n
+    send-response ;
+
+: ftp-error ( string -- )
+    500 "Unrecognized command: " rot append server-response ;
+
+: send-banner ( -- )
+    220 "Welcome to " host-name append server-response ;
+
+: anonymous-only ( -- )
+    530 "This FTP server is anonymous only." server-response ;
+
+: handle-QUIT ( obj -- )
+    drop 221 "Goodbye." server-response ;
+
+: handle-USER ( ftp-command -- )
+    [
+        tokenized>> second client get (>>user)
+        331 "Please specify the password." server-response
+    ] [
+        2drop "bad USER" ftp-error
+    ] recover ;
+
+: handle-PASS ( ftp-command -- )
+    [
+        tokenized>> second client get (>>password)
+        230 "Login successful" server-response
+    ] [
+        2drop "PASS error" ftp-error
+    ] recover ;
+
+ERROR: type-error type ;
+
+: parse-type ( string -- string' )
+    >upper {
+        { "IMAGE" [ "Binary" ] }
+        { "I" [ "Binary" ] }
+        [ type-error ]
+    } case ;
+
+: handle-TYPE ( obj -- )
+    [
+        tokenized>> second parse-type
+        200 "Switching to " rot " mode" 3append server-response
+    ] [
+        2drop "TYPE is binary only" ftp-error
+    ] recover ;
+
+: random-local-server ( -- server )
+    remote-address get class new 0 >>port binary <server> ;
+
+: port>bytes ( port -- hi lo )
+    [ -8 shift ] keep [ HEX: ff bitand ] bi@ ;
+
+: handle-PWD ( obj -- )
+    drop
+    257 current-directory get "\"" "\"" surround server-response ;
+
+: handle-SYST ( obj -- )
+    drop
+    215 "UNIX Type: L8" server-response ;
+
+: if-command-promise ( quot -- )
+    [ client get command-promise>> ] dip
+    [ "Establish an active or passive connection first" ftp-error ] if* ;
+
+: handle-STOR ( obj -- )
+    [
+        tokenized>> second
+        [ [ <ftp-put> ] dip fulfill ] if-command-promise
+    ] [
+        2drop
+    ] recover ;
+
+! EPRT |2|::1|62138|
+! : handle-EPRT ( obj -- )
+    ! tokenized>> second "|" split harvest ;
+
+: start-directory ( -- )
+    150 "Here comes the directory listing." server-response ;
+
+: finish-directory ( -- )
+    226 "Directory send OK." server-response ;
+
+GENERIC: service-command ( stream obj -- )
+
+M: ftp-list service-command ( stream obj -- )
+    drop
+    start-directory [
+        utf8 encode-output
+        [ current-directory get directory. ] with-string-writer string-lines
+        harvest [ ftp-send ] each
+    ] with-output-stream
+    finish-directory ;
+
+: transfer-outgoing-file ( path -- )
+    150 "Opening BINARY mode data connection for "
+    rot   
+    [ file-name ] [
+        " " swap  file-info size>> number>string
+        "(" " bytes)." surround append
+    ] bi 3append server-response ;
+
+: transfer-incoming-file ( path -- )
+    150 "Opening BINARY mode data connection for " rot append
+    server-response ;
+
+: finish-file-transfer ( -- )
+    226 "File send OK." server-response ;
+
+M: ftp-get service-command ( stream obj -- )
+    [
+        path>>
+        [ transfer-outgoing-file ]
+        [ binary <file-reader> swap stream-copy ] bi
+        finish-file-transfer
+    ] [
+        3drop "File transfer failed" ftp-error
+    ] recover ;
+
+M: ftp-put service-command ( stream obj -- )
+    [
+        path>>
+        [ transfer-incoming-file ]
+        [ binary <file-writer> stream-copy ] bi
+        finish-file-transfer
+    ] [
+        3drop "File transfer failed" ftp-error
+    ] recover ;
+
+: passive-loop ( server -- )
+    [
+        [
+            |dispose
+            30 seconds over set-timeout
+            accept drop &dispose
+            client get command-promise>>
+            30 seconds ?promise-timeout
+            service-command
+        ]
+        [ client get f >>command-promise drop ]
+        [ drop ] cleanup
+    ] with-destructors ;
+
+: handle-LIST ( obj -- )
+    drop
+    [ [ <ftp-list> ] dip fulfill ] if-command-promise ;
+
+: handle-SIZE ( obj -- )
+    [
+        tokenized>> second file-info size>>
+        213 swap number>string server-response
+    ] [
+        2drop
+        550 "Could not get file size" server-response
+    ] recover ;
+
+: handle-RETR ( obj -- )
+    [ tokenized>> second <ftp-get> swap fulfill ]
+    curry if-command-promise ;
+
+: expect-connection ( -- port )
+    random-local-server
+    client get <promise> >>command-promise drop
+    [ [ passive-loop ] curry in-thread ]
+    [ addr>> port>> ] bi ;
+
+: handle-PASV ( obj -- )
+    drop client get passive >>mode drop
+    expect-connection
+    [
+        "Entering Passive Mode (127,0,0,1," %
+        port>bytes [ number>string ] bi@ "," glue %
+        ")" %
+    ] "" make 227 swap server-response ;
+
+: handle-EPSV ( obj -- )
+    drop
+    client get command-promise>> [
+        "You already have a passive stream" ftp-error
+    ] [
+        229 "Entering Extended Passive Mode (|||"
+        expect-connection number>string
+        "|)" 3append server-response
+    ] if ;
+
+! LPRT 6,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,242,186
+! : handle-LPRT ( obj -- ) tokenized>> "," split ;
+
+ERROR: not-a-directory ;
+ERROR: no-permissions ;
+
+: handle-CWD ( obj -- )
+    [
+        tokenized>> second dup normalize-path
+        dup ftp-server-directory head? [
+            no-permissions
+        ] unless
+
+        file-info directory? [
+            set-current-directory
+            250 "Directory successully changed." server-response
+        ] [
+            not-a-directory
+        ] if
+    ] [
+        2drop
+        550 "Failed to change directory." server-response
+    ] recover ;
+
+: unrecognized-command ( obj -- ) raw>> ftp-error ;
+
+: handle-client-loop ( -- )
+    <ftp-command> readln
+    USE: prettyprint    global [ dup . flush ] bind
+    [ >>raw ]
+    [ tokenize-command >>tokenized ] bi
+    dup tokenized>> first >upper {
+        { "USER" [ handle-USER t ] }
+        { "PASS" [ handle-PASS t ] }
+        { "ACCT" [ drop "ACCT unimplemented" ftp-error t ] }
+        { "CWD" [ handle-CWD t ] }
+        ! { "XCWD" [ ] }
+        ! { "CDUP" [ ] }
+        ! { "SMNT" [ ] }
+
+        ! { "REIN" [ drop client get reset-ftp-client t ] }
+        { "QUIT" [ handle-QUIT f ] }
+
+        ! { "PORT" [  ] } ! TODO
+        { "PASV" [ handle-PASV t ] }
+        ! { "MODE" [ ] }
+        { "TYPE" [ handle-TYPE t ] }
+        ! { "STRU" [ ] }
+
+        ! { "ALLO" [ ] }
+        ! { "REST" [ ] }
+        { "STOR" [ handle-STOR t ] }
+        ! { "STOU" [ ] }
+        { "RETR" [ handle-RETR t ] }
+        { "LIST" [ handle-LIST t ] }
+        { "SIZE" [ handle-SIZE t ] }
+        ! { "NLST" [ ] }
+        ! { "APPE" [ ] }
+        ! { "RNFR" [ ] }
+        ! { "RNTO" [ ] }
+        ! { "DELE" [ handle-DELE t ] }
+        ! { "RMD" [ handle-RMD t ] }
+        ! ! { "XRMD" [ handle-XRMD t ] }
+        ! { "MKD" [ handle-MKD t ] }
+        { "PWD" [ handle-PWD t ] }
+        ! { "ABOR" [ ] }
+
+        { "SYST" [ handle-SYST t ] }
+        ! { "STAT" [ ] }
+        ! { "HELP" [ ] }
+
+        ! { "SITE" [ ] }
+        ! { "NOOP" [ ] }
+
+        ! { "EPRT" [ handle-EPRT ] }
+        ! { "LPRT" [ handle-LPRT ] }
+        { "EPSV" [ handle-EPSV t ] }
+        ! { "LPSV" [ drop handle-LPSV t ] }
+        [ drop unrecognized-command t ]
+    } case [ handle-client-loop ] when ;
+
+TUPLE: ftp-server < threaded-server ;
+
+M: ftp-server handle-client* ( server -- )
+    drop
+    [
+        ftp-server-directory [
+            host-name <ftp-client> client set
+            send-banner handle-client-loop
+        ] with-directory
+    ] with-destructors ;
+
+: <ftp-server> ( port -- server )
+    ftp-server new-threaded-server
+        swap >>insecure
+        "ftp.server" >>name
+        5 minutes >>timeout
+        latin1 >>encoding ;
+
+: ftpd ( port -- )
+    <ftp-server> start-server ;
+
+: ftpd-main ( -- ) 2100 ftpd ;
+
+MAIN: ftpd-main
+
+! sudo tcpdump -i en1 -A -s 10000  tcp port 21
diff --git a/basis/ftp/server/tags.txt b/basis/ftp/server/tags.txt
new file mode 100644 (file)
index 0000000..992ae12
--- /dev/null
@@ -0,0 +1 @@
+network
diff --git a/basis/ftp/tags.txt b/basis/ftp/tags.txt
new file mode 100644 (file)
index 0000000..992ae12
--- /dev/null
@@ -0,0 +1 @@
+network
diff --git a/extra/ftp/client/authors.txt b/extra/ftp/client/authors.txt
deleted file mode 100644 (file)
index 7c1b2f2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Doug Coleman
diff --git a/extra/ftp/client/client.factor b/extra/ftp/client/client.factor
deleted file mode 100644 (file)
index 9c82cdb..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-! Copyright (C) 2008 Doug Coleman.
-! See http://factorcode.org/license.txt for BSD license.
-USING: accessors arrays classes.singleton combinators
-continuations io io.encodings.binary io.encodings.utf8
-io.files io.sockets kernel io.streams.duplex math
-math.parser sequences splitting namespaces strings fry ftp
-ftp.client.listing-parser urls ;
-IN: ftp.client
-
-: (ftp-response-code) ( str -- n )
-    3 head string>number ;
-
-: ftp-response-code ( string -- n/f )
-    dup fourth CHAR: - = [ drop f ] [ (ftp-response-code) ] if ;
-
-: read-response-loop ( ftp-response -- ftp-response )
-    readln
-    [ add-response-line ] [ ftp-response-code ] bi
-    over n>> = [ read-response-loop ] unless ;
-
-: read-response ( -- ftp-response )
-    <ftp-response> readln
-    [ (ftp-response-code) >>n ]
-    [ add-response-line ]
-    [ fourth CHAR: - = ] tri
-    [ read-response-loop ] when ;
-
-ERROR: ftp-error got expected ;
-
-: ftp-assert ( ftp-response n -- )
-    2dup [ n>> ] dip = [ 2drop ] [ ftp-error ] if ;
-
-: ftp-command ( string -- ftp-response )
-    ftp-send read-response ;
-
-: ftp-user ( url -- ftp-response )
-    username>> "USER " prepend ftp-command ;
-
-: ftp-password ( url -- ftp-response )
-    password>> "PASS " prepend ftp-command ;
-
-: ftp-cwd ( directory -- ftp-response )
-    "CWD " prepend ftp-command ;
-
-: ftp-retr ( filename -- ftp-response )
-    "RETR " prepend ftp-command ;
-
-: ftp-set-binary ( -- ftp-response ) "TYPE I" ftp-command ;
-
-: ftp-pwd ( -- ftp-response ) "PWD" ftp-command ;
-
-: ftp-list ( -- )
-    "LIST" ftp-command 150 ftp-assert ;
-
-: ftp-quit ( -- ftp-response ) "QUIT" ftp-command ;
-
-: ftp-epsv ( -- ftp-response )
-    "EPSV" ftp-command dup 229 ftp-assert ;
-
-: parse-epsv ( ftp-response -- port )
-    strings>> first "|" split 2 tail* first string>number ;
-
-: open-passive-client ( url protocol -- stream )
-    [ host>> ftp-epsv parse-epsv <inet> ] dip <client> drop ;
-
-: list ( url -- ftp-response )
-    utf8 open-passive-client
-    ftp-list
-    lines
-    <ftp-response> swap >>strings
-    read-response 226 ftp-assert
-    parse-list ;
-
-: (ftp-get) ( url path -- )
-    [ binary open-passive-client ] dip
-    [ ftp-retr 150 ftp-assert drop ]
-    [ binary <file-writer> stream-copy ] 2bi
-    read-response 226 ftp-assert ;
-
-: ftp-login ( url -- )
-    read-response 220 ftp-assert
-    [ ftp-user 331 ftp-assert ]
-    [ ftp-password 230 ftp-assert ] bi
-    ftp-set-binary 200 ftp-assert ;
-
-: ftp-connect ( url -- stream )
-    [ host>> ] [ port>> ] bi <inet> utf8 <client> drop ;
-
-: with-ftp-client ( url quot -- )
-    [ [ ftp-connect ] keep ] dip
-    '[ _ [ ftp-login ] _ bi ftp-quit drop ] with-stream ; inline
-
-: ensure-login ( url -- url )
-    dup username>> [
-        "anonymous" >>username
-        "ftp-client" >>password
-    ] unless ;
-
-: >ftp-url ( url -- url' ) >url ensure-port ensure-login ;
-
-: ftp-get ( url -- )
-    >ftp-url [
-        dup path>>
-        [ nip parent-directory ftp-cwd drop ]
-        [ file-name (ftp-get) ] 2bi
-    ] with-ftp-client ;
-
-
-
-
diff --git a/extra/ftp/client/listing-parser/authors.txt b/extra/ftp/client/listing-parser/authors.txt
deleted file mode 100644 (file)
index b4bd0e7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Doug Coleman
\ No newline at end of file
diff --git a/extra/ftp/client/listing-parser/listing-parser.factor b/extra/ftp/client/listing-parser/listing-parser.factor
deleted file mode 100644 (file)
index 04e96ed..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-! Copyright (C) 2008 Doug Coleman.
-! See http://factorcode.org/license.txt for BSD license.
-USING: accessors combinators io.files kernel math.parser
-sequences splitting ;
-IN: ftp.client.listing-parser
-
-: ch>file-type ( ch -- type )
-    {
-        { CHAR: b [ +block-device+ ] }
-        { CHAR: c [ +character-device+ ] }
-        { CHAR: d [ +directory+ ] }
-        { CHAR: l [ +symbolic-link+ ] }
-        { CHAR: s [ +socket+ ] }
-        { CHAR: p [ +fifo+ ] }
-        { CHAR: - [ +regular-file+ ] }
-        [ drop +unknown+ ]
-    } case ;
-
-: file-type>ch ( type -- string )
-    {
-        { +block-device+ [ CHAR: b ] }
-        { +character-device+ [ CHAR: c ] }
-        { +directory+ [ CHAR: d ] }
-        { +symbolic-link+ [ CHAR: l ] }
-        { +socket+ [ CHAR: s ] }
-        { +fifo+ [ CHAR: p ] }
-        { +regular-file+ [ CHAR: - ] }
-        [ drop CHAR: - ]
-    } case ;
-
-: parse-permissions ( remote-file str -- remote-file )
-    [ first ch>file-type >>type ] [ rest >>permissions ] bi ;
-
-TUPLE: remote-file
-type permissions links owner group size month day time year
-name target ;
-
-: <remote-file> ( -- remote-file ) remote-file new ;
-
-: parse-list-11 ( lines -- seq )
-    [
-        11 f pad-right
-        <remote-file> swap {
-            [ 0 swap nth parse-permissions ]
-            [ 1 swap nth string>number >>links ]
-            [ 2 swap nth >>owner ]
-            [ 3 swap nth >>group ]
-            [ 4 swap nth string>number >>size ]
-            [ 5 swap nth >>month ]
-            [ 6 swap nth >>day ]
-            [ 7 swap nth >>time ]
-            [ 8 swap nth >>name ]
-            [ 10 swap nth >>target ]
-        } cleave
-    ] map ;
-
-: parse-list-8 ( lines -- seq )
-    [
-        <remote-file> swap {
-            [ 0 swap nth parse-permissions ]
-            [ 1 swap nth string>number >>links ]
-            [ 2 swap nth >>owner ]
-            [ 3 swap nth >>size ]
-            [ 4 swap nth >>month ]
-            [ 5 swap nth >>day ]
-            [ 6 swap nth >>time ]
-            [ 7 swap nth >>name ]
-        } cleave
-    ] map ;
-
-: parse-list-3 ( lines -- seq )
-    [
-        <remote-file> swap {
-            [ 0 swap nth parse-permissions ]
-            [ 1 swap nth string>number >>links ]
-            [ 2 swap nth >>name ]
-        } cleave
-    ] map ;
-
-: parse-list ( ftp-response -- ftp-response )
-    dup strings>>
-    [ " " split harvest ] map
-    dup length {
-        { 11 [ parse-list-11 ] }
-        { 9 [ parse-list-11 ] }
-        { 8 [ parse-list-8 ] }
-        { 3 [ parse-list-3 ] }
-        [ drop ]
-    } case >>parsed ;
diff --git a/extra/ftp/client/tags.txt b/extra/ftp/client/tags.txt
deleted file mode 100644 (file)
index 992ae12..0000000
+++ /dev/null
@@ -1 +0,0 @@
-network
diff --git a/extra/ftp/ftp.factor b/extra/ftp/ftp.factor
deleted file mode 100644 (file)
index adf7d5b..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-! Copyright (C) 2008 Doug Coleman.
-! See http://factorcode.org/license.txt for BSD license.
-USING: accessors arrays assocs combinators io io.files kernel
-math.parser sequences strings ;
-IN: ftp
-
-SINGLETON: active
-SINGLETON: passive
-
-TUPLE: ftp-response n strings parsed ;
-
-: <ftp-response> ( -- ftp-response )
-    ftp-response new
-        V{ } clone >>strings ;
-
-: add-response-line ( ftp-response string -- ftp-response )
-    over strings>> push ;
-
-: ftp-send ( string -- ) write "\r\n" write flush ;
-: ftp-ipv4 1 ; inline
-: ftp-ipv6 2 ; inline
diff --git a/extra/ftp/server/server.factor b/extra/ftp/server/server.factor
deleted file mode 100644 (file)
index b0ec340..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-! Copyright (C) 2008 Doug Coleman.
-! See http://factorcode.org/license.txt for BSD license.
-USING: combinators.short-circuit accessors combinators io
-io.encodings.8-bit io.encodings io.encodings.binary
-io.encodings.utf8 io.files io.sockets kernel math.parser
-namespaces make sequences ftp io.unix.launcher.parser
-unicode.case splitting assocs classes io.servers.connection
-destructors calendar io.timeouts io.streams.duplex threads
-continuations math concurrency.promises byte-arrays
-io.backend tools.hexdump tools.files io.streams.string ;
-IN: ftp.server
-
-TUPLE: ftp-client url mode state command-promise user password ;
-
-: <ftp-client> ( url -- ftp-client )
-    ftp-client new
-        swap >>url ;
-    
-SYMBOL: client
-
-: ftp-server-directory ( -- str )
-    \ ftp-server-directory get-global "resource:temp" or
-    normalize-path ;
-
-TUPLE: ftp-command raw tokenized ;
-
-: <ftp-command> ( -- obj )
-    ftp-command new ;
-
-TUPLE: ftp-get path ;
-
-: <ftp-get> ( path -- obj )
-    ftp-get new
-        swap >>path ;
-
-TUPLE: ftp-put path ;
-
-: <ftp-put> ( path -- obj )
-    ftp-put new
-        swap >>path ;
-
-TUPLE: ftp-list ;
-
-C: <ftp-list> ftp-list
-
-: read-command ( -- ftp-command )
-    <ftp-command> readln
-    [ >>raw ] [ tokenize-command >>tokenized ] bi ;
-
-: (send-response) ( n string separator -- )
-    rot number>string write write ftp-send ;
-
-: send-response ( ftp-response -- )
-    [ n>> ] [ strings>> ] bi
-    [ but-last-slice [ "-" (send-response) ] with each ]
-    [ first " " (send-response) ] 2bi ;
-
-: server-response ( n string -- )
-    <ftp-response>
-        swap add-response-line
-        swap >>n
-    send-response ;
-
-: ftp-error ( string -- )
-    500 "Unrecognized command: " rot append server-response ;
-
-: send-banner ( -- )
-    220 "Welcome to " host-name append server-response ;
-
-: anonymous-only ( -- )
-    530 "This FTP server is anonymous only." server-response ;
-
-: handle-QUIT ( obj -- )
-    drop 221 "Goodbye." server-response ;
-
-: handle-USER ( ftp-command -- )
-    [
-        tokenized>> second client get (>>user)
-        331 "Please specify the password." server-response
-    ] [
-        2drop "bad USER" ftp-error
-    ] recover ;
-
-: handle-PASS ( ftp-command -- )
-    [
-        tokenized>> second client get (>>password)
-        230 "Login successful" server-response
-    ] [
-        2drop "PASS error" ftp-error
-    ] recover ;
-
-ERROR: type-error type ;
-
-: parse-type ( string -- string' )
-    >upper {
-        { "IMAGE" [ "Binary" ] }
-        { "I" [ "Binary" ] }
-        [ type-error ]
-    } case ;
-
-: handle-TYPE ( obj -- )
-    [
-        tokenized>> second parse-type
-        200 "Switching to " rot " mode" 3append server-response
-    ] [
-        2drop "TYPE is binary only" ftp-error
-    ] recover ;
-
-: random-local-server ( -- server )
-    remote-address get class new 0 >>port binary <server> ;
-
-: port>bytes ( port -- hi lo )
-    [ -8 shift ] keep [ HEX: ff bitand ] bi@ ;
-
-: handle-PWD ( obj -- )
-    drop
-    257 current-directory get "\"" "\"" surround server-response ;
-
-: handle-SYST ( obj -- )
-    drop
-    215 "UNIX Type: L8" server-response ;
-
-: if-command-promise ( quot -- )
-    [ client get command-promise>> ] dip
-    [ "Establish an active or passive connection first" ftp-error ] if* ;
-
-: handle-STOR ( obj -- )
-    [
-        tokenized>> second
-        [ [ <ftp-put> ] dip fulfill ] if-command-promise
-    ] [
-        2drop
-    ] recover ;
-
-! EPRT |2|::1|62138|
-! : handle-EPRT ( obj -- )
-    ! tokenized>> second "|" split harvest ;
-
-: start-directory ( -- )
-    150 "Here comes the directory listing." server-response ;
-
-: finish-directory ( -- )
-    226 "Directory send OK." server-response ;
-
-GENERIC: service-command ( stream obj -- )
-
-M: ftp-list service-command ( stream obj -- )
-    drop
-    start-directory [
-        utf8 encode-output
-        [ current-directory get directory. ] with-string-writer string-lines
-        harvest [ ftp-send ] each
-    ] with-output-stream
-    finish-directory ;
-
-: transfer-outgoing-file ( path -- )
-    150 "Opening BINARY mode data connection for "
-    rot   
-    [ file-name ] [
-        " " swap  file-info size>> number>string
-        "(" " bytes)." surround append
-    ] bi 3append server-response ;
-
-: transfer-incoming-file ( path -- )
-    150 "Opening BINARY mode data connection for " rot append
-    server-response ;
-
-: finish-file-transfer ( -- )
-    226 "File send OK." server-response ;
-
-M: ftp-get service-command ( stream obj -- )
-    [
-        path>>
-        [ transfer-outgoing-file ]
-        [ binary <file-reader> swap stream-copy ] bi
-        finish-file-transfer
-    ] [
-        3drop "File transfer failed" ftp-error
-    ] recover ;
-
-M: ftp-put service-command ( stream obj -- )
-    [
-        path>>
-        [ transfer-incoming-file ]
-        [ binary <file-writer> stream-copy ] bi
-        finish-file-transfer
-    ] [
-        3drop "File transfer failed" ftp-error
-    ] recover ;
-
-: passive-loop ( server -- )
-    [
-        [
-            |dispose
-            30 seconds over set-timeout
-            accept drop &dispose
-            client get command-promise>>
-            30 seconds ?promise-timeout
-            service-command
-        ]
-        [ client get f >>command-promise drop ]
-        [ drop ] cleanup
-    ] with-destructors ;
-
-: handle-LIST ( obj -- )
-    drop
-    [ [ <ftp-list> ] dip fulfill ] if-command-promise ;
-
-: handle-SIZE ( obj -- )
-    [
-        tokenized>> second file-info size>>
-        213 swap number>string server-response
-    ] [
-        2drop
-        550 "Could not get file size" server-response
-    ] recover ;
-
-: handle-RETR ( obj -- )
-    [ tokenized>> second <ftp-get> swap fulfill ]
-    curry if-command-promise ;
-
-: expect-connection ( -- port )
-    random-local-server
-    client get <promise> >>command-promise drop
-    [ [ passive-loop ] curry in-thread ]
-    [ addr>> port>> ] bi ;
-
-: handle-PASV ( obj -- )
-    drop client get passive >>mode drop
-    expect-connection
-    [
-        "Entering Passive Mode (127,0,0,1," %
-        port>bytes [ number>string ] bi@ "," glue %
-        ")" %
-    ] "" make 227 swap server-response ;
-
-: handle-EPSV ( obj -- )
-    drop
-    client get command-promise>> [
-        "You already have a passive stream" ftp-error
-    ] [
-        229 "Entering Extended Passive Mode (|||"
-        expect-connection number>string
-        "|)" 3append server-response
-    ] if ;
-
-! LPRT 6,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,242,186
-! : handle-LPRT ( obj -- ) tokenized>> "," split ;
-
-ERROR: not-a-directory ;
-ERROR: no-permissions ;
-
-: handle-CWD ( obj -- )
-    [
-        tokenized>> second dup normalize-path
-        dup ftp-server-directory head? [
-            no-permissions
-        ] unless
-
-        file-info directory? [
-            set-current-directory
-            250 "Directory successully changed." server-response
-        ] [
-            not-a-directory
-        ] if
-    ] [
-        2drop
-        550 "Failed to change directory." server-response
-    ] recover ;
-
-: unrecognized-command ( obj -- ) raw>> ftp-error ;
-
-: handle-client-loop ( -- )
-    <ftp-command> readln
-    USE: prettyprint    global [ dup . flush ] bind
-    [ >>raw ]
-    [ tokenize-command >>tokenized ] bi
-    dup tokenized>> first >upper {
-        { "USER" [ handle-USER t ] }
-        { "PASS" [ handle-PASS t ] }
-        { "ACCT" [ drop "ACCT unimplemented" ftp-error t ] }
-        { "CWD" [ handle-CWD t ] }
-        ! { "XCWD" [ ] }
-        ! { "CDUP" [ ] }
-        ! { "SMNT" [ ] }
-
-        ! { "REIN" [ drop client get reset-ftp-client t ] }
-        { "QUIT" [ handle-QUIT f ] }
-
-        ! { "PORT" [  ] } ! TODO
-        { "PASV" [ handle-PASV t ] }
-        ! { "MODE" [ ] }
-        { "TYPE" [ handle-TYPE t ] }
-        ! { "STRU" [ ] }
-
-        ! { "ALLO" [ ] }
-        ! { "REST" [ ] }
-        { "STOR" [ handle-STOR t ] }
-        ! { "STOU" [ ] }
-        { "RETR" [ handle-RETR t ] }
-        { "LIST" [ handle-LIST t ] }
-        { "SIZE" [ handle-SIZE t ] }
-        ! { "NLST" [ ] }
-        ! { "APPE" [ ] }
-        ! { "RNFR" [ ] }
-        ! { "RNTO" [ ] }
-        ! { "DELE" [ handle-DELE t ] }
-        ! { "RMD" [ handle-RMD t ] }
-        ! ! { "XRMD" [ handle-XRMD t ] }
-        ! { "MKD" [ handle-MKD t ] }
-        { "PWD" [ handle-PWD t ] }
-        ! { "ABOR" [ ] }
-
-        { "SYST" [ handle-SYST t ] }
-        ! { "STAT" [ ] }
-        ! { "HELP" [ ] }
-
-        ! { "SITE" [ ] }
-        ! { "NOOP" [ ] }
-
-        ! { "EPRT" [ handle-EPRT ] }
-        ! { "LPRT" [ handle-LPRT ] }
-        { "EPSV" [ handle-EPSV t ] }
-        ! { "LPSV" [ drop handle-LPSV t ] }
-        [ drop unrecognized-command t ]
-    } case [ handle-client-loop ] when ;
-
-TUPLE: ftp-server < threaded-server ;
-
-M: ftp-server handle-client* ( server -- )
-    drop
-    [
-        ftp-server-directory [
-            host-name <ftp-client> client set
-            send-banner handle-client-loop
-        ] with-directory
-    ] with-destructors ;
-
-: <ftp-server> ( port -- server )
-    ftp-server new-threaded-server
-        swap >>insecure
-        "ftp.server" >>name
-        5 minutes >>timeout
-        latin1 >>encoding ;
-
-: ftpd ( port -- )
-    <ftp-server> start-server ;
-
-: ftpd-main ( -- ) 2100 ftpd ;
-
-MAIN: ftpd-main
-
-! sudo tcpdump -i en1 -A -s 10000  tcp port 21
diff --git a/extra/ftp/server/tags.txt b/extra/ftp/server/tags.txt
deleted file mode 100644 (file)
index 992ae12..0000000
+++ /dev/null
@@ -1 +0,0 @@
-network
diff --git a/extra/ftp/tags.txt b/extra/ftp/tags.txt
deleted file mode 100644 (file)
index 992ae12..0000000
+++ /dev/null
@@ -1 +0,0 @@
-network