diff --git a/extra/checksums/null/null.factor b/extra/checksums/null/null.factor new file mode 100644 index 0000000000..d2dc305ac2 --- /dev/null +++ b/extra/checksums/null/null.factor @@ -0,0 +1,8 @@ +USING: checksums ; +IN: checksums.null + +SINGLETON: null + +INSTANCE: null checksum + +M: null checksum-bytes ; diff --git a/extra/http/http-tests.factor b/extra/http/http-tests.factor index 39e708c879..1f1ce361b2 100755 --- a/extra/http/http-tests.factor +++ b/extra/http/http-tests.factor @@ -1,6 +1,6 @@ USING: http tools.test multiline tuple-syntax io.streams.string kernel arrays splitting sequences -assocs io.sockets db db.sqlite ; +assocs io.sockets db db.sqlite continuations ; IN: http.tests [ "hello%20world" ] [ "hello world" url-encode ] unit-test @@ -93,7 +93,7 @@ Host: www.sex.com STRING: read-response-test-1 HTTP/1.1 404 not found -Content-Type: text/html +Content-Type: text/html; charset=UTF8 blah ; @@ -103,8 +103,10 @@ blah version: "1.1" code: 404 message: "not found" - header: H{ { "content-type" "text/html" } } + header: H{ { "content-type" "text/html; charset=UTF8" } } cookies: V{ } + content-type: "text/html" + content-charset: "UTF8" } ] [ read-response-test-1 lf>crlf @@ -114,7 +116,7 @@ blah STRING: read-response-test-1' HTTP/1.1 404 not found -content-type: text/html +content-type: text/html; charset=UTF8 ; @@ -140,11 +142,13 @@ accessors namespaces threads ; : add-quit-action - [ stop-server "text/html" [ "Goodbye" write ] >>body ] >>display + [ stop-server [ "Goodbye" write ] ] >>display "quit" add-responder ; : test-db "test.db" temp-file sqlite-db ; +[ test-db drop delete-file ] ignore-errors + test-db [ init-sessions-table ] with-db @@ -191,7 +195,7 @@ test-db [ [ ] [ [ - + f "" add-responder diff --git a/extra/http/http.factor b/extra/http/http.factor index 9729542ea4..c5f57d4c04 100755 --- a/extra/http/http.factor +++ b/extra/http/http.factor @@ -291,6 +291,12 @@ SYMBOL: max-post-request : extract-cookies ( request -- request ) dup "cookie" header [ parse-cookies >>cookies ] when* ; +: parse-content-type-attributes ( string -- attributes ) + " " split [ empty? not ] filter [ "=" split1 >r >lower r> ] { } map>assoc ; + +: parse-content-type ( content-type -- type encoding ) + ";" split1 parse-content-type-attributes "charset" swap at ; + : read-request ( -- request ) read-method @@ -377,6 +383,8 @@ code message header cookies +content-type +content-charset body ; : @@ -403,7 +411,10 @@ body ; : read-response-header read-header >>header - dup "set-cookie" header [ parse-cookies >>cookies ] when* ; + extract-cookies + dup "content-type" header [ + parse-content-type [ >>content-type ] [ >>content-charset ] bi* + ] when* ; : read-response ( -- response ) @@ -422,10 +433,15 @@ body ; : write-response-message ( response -- response ) dup message>> write crlf ; +: unparse-content-type ( request -- content-type ) + [ content-type>> "application/octet-stream" or ] + [ content-charset>> ] bi + [ "; charset=" swap 3append ] when* ; + : write-response-header ( response -- response ) dup header>> clone - over cookies>> f like - [ unparse-cookies "set-cookie" pick set-at ] when* + over cookies>> f like [ unparse-cookies "set-cookie" pick set-at ] when* + over unparse-content-type "content-type" pick set-at write-header ; GENERIC: write-response-body* ( body -- ) @@ -453,9 +469,6 @@ M: response write-full-response ( request response -- ) dup write-response swap method>> "HEAD" = [ write-response-body ] unless ; -: set-content-type ( request/response content-type -- request/response ) - "content-type" set-header ; - : get-cookie ( request/response name -- cookie/f ) >r cookies>> r> '[ , _ name>> = ] find nip ; @@ -466,7 +479,7 @@ M: response write-full-response ( request response -- ) [ name>> dupd get-cookie [ dupd delete-cookie ] when* ] keep over cookies>> push ; -TUPLE: raw-response +TUPLE: raw-response version code message diff --git a/extra/http/server/auth/admin/admin.factor b/extra/http/server/auth/admin/admin.factor index c9d2769292..0dc5d3560e 100644 --- a/extra/http/server/auth/admin/admin.factor +++ b/extra/http/server/auth/admin/admin.factor @@ -7,6 +7,7 @@ http.server.boilerplate http.server.auth.providers http.server.auth.providers.db http.server.auth.login +http.server.auth http.server.forms http.server.components.inspector http.server.components @@ -28,6 +29,7 @@ IN: http.server.auth.admin "new-password" t >>required add-field "verify-password" t >>required add-field "email" add-field ; + ! "capabilities" add-field ; : ( -- form ) "user"
@@ -39,6 +41,7 @@ IN: http.server.auth.admin "verify-password" add-field "email" add-field "profile" add-field ; + ! "capabilities" add-field ; : ( -- form ) "user-list" @@ -77,7 +80,7 @@ IN: http.server.auth.admin "username" value "realname" value >>realname "email" value >>email - "new-password" value >>password + "new-password" value >>encoded-password H{ } clone >>profile insert-tuple @@ -116,7 +119,7 @@ IN: http.server.auth.admin { "new-password" "verify-password" } [ value empty? ] all? [ same-password-twice - "new-password" value >>password + "new-password" value >>encoded-password ] unless update-tuple @@ -139,6 +142,10 @@ IN: http.server.auth.admin TUPLE: user-admin < dispatcher ; +SYMBOL: can-administer-users? + +can-administer-users? define-capability + :: ( -- responder ) [let | ctor [ [ ] ] | user-admin new-dispatcher @@ -148,5 +155,5 @@ TUPLE: user-admin < dispatcher ; ctor "$user-admin" "delete" add-responder "admin" admin-template >>template - + { can-administer-users? } ] ; diff --git a/extra/http/server/auth/auth.factor b/extra/http/server/auth/auth.factor index a25baf3ed2..36fcff4b2e 100755 --- a/extra/http/server/auth/auth.factor +++ b/extra/http/server/auth/auth.factor @@ -1,6 +1,6 @@ ! Copyright (c) 2008 Slava Pestov ! See http://factorcode.org/license.txt for BSD license. -USING: accessors assocs namespaces kernel +USING: accessors assocs namespaces kernel sequences http.server http.server.sessions http.server.auth.providers ; @@ -33,3 +33,9 @@ M: filter-responder init-user-profile : uchange ( quot key -- ) profile swap change-at user-changed ; inline + +SYMBOL: capabilities + +V{ } clone capabilities set-global + +: define-capability ( word -- ) capabilities get push-new ; diff --git a/extra/http/server/auth/login/login.factor b/extra/http/server/auth/login/login.factor index 453f4cc4d6..9eb79649b9 100755 --- a/extra/http/server/auth/login/login.factor +++ b/extra/http/server/auth/login/login.factor @@ -1,16 +1,23 @@ ! Copyright (c) 2008 Slava Pestov ! See http://factorcode.org/license.txt for BSD license. USING: accessors quotations assocs kernel splitting -base64 io combinators sequences io.files namespaces hashtables -fry io.sockets arrays threads locals qualified continuations +combinators sequences namespaces hashtables +fry arrays threads locals qualified random +io +io.sockets +io.encodings.utf8 +io.encodings.string +io.binary +continuations destructors - +checksums +checksums.sha2 html.elements http http.server http.server.auth http.server.auth.providers -http.server.auth.providers.null +http.server.auth.providers.db http.server.actions http.server.components http.server.flows @@ -25,9 +32,24 @@ QUALIFIED: smtp SYMBOL: login-failed? -TUPLE: login < dispatcher users ; +TUPLE: login < dispatcher users checksum ; -: users login get users>> ; +: users ( -- provider ) + login get users>> ; + +: encode-password ( string salt -- bytes ) + [ utf8 encode ] [ 4 >be ] bi* append + login get checksum>> checksum-bytes ; + +: >>encoded-password ( user string -- user ) + 32 random-bits [ encode-password ] keep + [ >>password ] [ >>salt ] bi* ; inline + +: valid-login? ( password user -- ? ) + [ salt>> encode-password ] [ password>> ] bi = ; + +: check-login ( password username -- user/f ) + users get-user dup [ [ valid-login? ] keep and ] [ 2drop f ] if ; ! Destructor TUPLE: user-saver user ; @@ -72,8 +94,7 @@ M: user-saver dispose form validate-form - "password" value "username" value - users check-login [ + "password" value "username" value check-login [ successful-login ] [ login-failed? on @@ -125,7 +146,7 @@ SYMBOL: user-exists? "username" value "realname" value >>realname - "new-password" value >>password + "new-password" value >>encoded-password "email" value >>email H{ } clone >>profile @@ -179,10 +200,10 @@ SYMBOL: user-exists? [ value empty? ] all? [ same-password-twice - "password" value uid users check-login + "password" value uid check-login [ login-failed? on validation-failed ] unless - "new-password" value >>password + "new-password" value >>encoded-password ] unless "realname" value >>realname @@ -314,7 +335,7 @@ SYMBOL: lost-password-from "ticket" value "username" value users claim-ticket [ - "new-password" value >>password + "new-password" value >>encoded-password users update-user "recover-4" login-template serve-template @@ -334,7 +355,7 @@ SYMBOL: lost-password-from ! ! ! Authentication logic -TUPLE: protected < filter-responder ; +TUPLE: protected < filter-responder capabilities ; C: protected @@ -342,11 +363,17 @@ C: protected begin-flow "$login/login" f ; +: check-capabilities ( responder user -- ? ) + [ capabilities>> ] [ profile>> ] bi* '[ , at ] all? ; + M: protected call-responder* ( path responder -- response ) uid dup [ - users get-user - [ logged-in-user set ] [ save-user-after ] bi - call-next-method + users get-user 2dup check-capabilities [ + [ logged-in-user set ] [ save-user-after ] bi + call-next-method + ] [ + 3drop show-login-page + ] if ] [ 3drop show-login-page ] if ; @@ -364,12 +391,13 @@ M: login call-responder* ( path responder -- response ) swap >>default "login" add-responder "logout" add-responder - no-users >>users ; + users-in-db >>users + sha-256 >>checksum ; ! ! ! Configuration : allow-edit-profile ( login -- login ) - + f "edit-profile" add-responder ; : allow-registration ( login -- login ) diff --git a/extra/http/server/auth/providers/assoc/assoc-tests.factor b/extra/http/server/auth/providers/assoc/assoc-tests.factor index 82a2b54b0e..09022b0921 100755 --- a/extra/http/server/auth/providers/assoc/assoc-tests.factor +++ b/extra/http/server/auth/providers/assoc/assoc-tests.factor @@ -1,33 +1,35 @@ IN: http.server.auth.providers.assoc.tests -USING: http.server.auth.providers +USING: http.server.actions http.server.auth.providers http.server.auth.providers.assoc tools.test namespaces accessors kernel ; - "provider" set + + >>users +login set [ t ] [ "slava" - "foobar" >>password + "foobar" >>encoded-password "slava@factorcode.org" >>email H{ } clone >>profile - "provider" get new-user + users new-user username>> "slava" = ] unit-test [ f ] [ "slava" H{ } clone >>profile - "provider" get new-user + users new-user ] unit-test -[ f ] [ "fdasf" "slava" "provider" get check-login >boolean ] unit-test +[ f ] [ "fdasf" "slava" check-login >boolean ] unit-test -[ ] [ "foobar" "slava" "provider" get check-login "user" set ] unit-test +[ ] [ "foobar" "slava" check-login "user" set ] unit-test [ t ] [ "user" get >boolean ] unit-test -[ ] [ "user" get "fdasf" >>password drop ] unit-test +[ ] [ "user" get "fdasf" >>encoded-password drop ] unit-test -[ t ] [ "fdasf" "slava" "provider" get check-login >boolean ] unit-test +[ t ] [ "fdasf" "slava" check-login >boolean ] unit-test -[ f ] [ "foobar" "slava" "provider" get check-login >boolean ] unit-test +[ f ] [ "foobar" "slava" check-login >boolean ] unit-test diff --git a/extra/http/server/auth/providers/db/db-tests.factor b/extra/http/server/auth/providers/db/db-tests.factor index 1a5298f050..a6a92356b6 100755 --- a/extra/http/server/auth/providers/db/db-tests.factor +++ b/extra/http/server/auth/providers/db/db-tests.factor @@ -1,10 +1,14 @@ IN: http.server.auth.providers.db.tests -USING: http.server.auth.providers +USING: http.server.actions +http.server.auth.login +http.server.auth.providers http.server.auth.providers.db tools.test namespaces db db.sqlite db.tuples continuations io.files accessors kernel ; -users-in-db "provider" set + + users-in-db >>users +login set [ "auth-test.db" temp-file delete-file ] ignore-errors @@ -14,30 +18,30 @@ users-in-db "provider" set [ t ] [ "slava" - "foobar" >>password + "foobar" >>encoded-password "slava@factorcode.org" >>email H{ } clone >>profile - "provider" get new-user + users new-user username>> "slava" = ] unit-test [ f ] [ "slava" H{ } clone >>profile - "provider" get new-user + users new-user ] unit-test - [ f ] [ "fdasf" "slava" "provider" get check-login >boolean ] unit-test + [ f ] [ "fdasf" "slava" check-login >boolean ] unit-test - [ ] [ "foobar" "slava" "provider" get check-login "user" set ] unit-test + [ ] [ "foobar" "slava" check-login "user" set ] unit-test [ t ] [ "user" get >boolean ] unit-test - [ ] [ "user" get "fdasf" >>password drop ] unit-test + [ ] [ "user" get "fdasf" >>encoded-password drop ] unit-test - [ ] [ "user" get "provider" get update-user ] unit-test + [ ] [ "user" get users update-user ] unit-test - [ t ] [ "fdasf" "slava" "provider" get check-login >boolean ] unit-test + [ t ] [ "fdasf" "slava" check-login >boolean ] unit-test - [ f ] [ "foobar" "slava" "provider" get check-login >boolean ] unit-test + [ f ] [ "foobar" "slava" check-login >boolean ] unit-test ] with-db diff --git a/extra/http/server/auth/providers/db/db.factor b/extra/http/server/auth/providers/db/db.factor index 66d3a00a42..b72f94f3bd 100755 --- a/extra/http/server/auth/providers/db/db.factor +++ b/extra/http/server/auth/providers/db/db.factor @@ -9,7 +9,8 @@ user "USERS" { { "username" "USERNAME" { VARCHAR 256 } +user-assigned-id+ } { "realname" "REALNAME" { VARCHAR 256 } } - { "password" "PASSWORD" { VARCHAR 256 } +not-null+ } + { "password" "PASSWORD" BLOB +not-null+ } + { "salt" "SALT" INTEGER +not-null+ } { "email" "EMAIL" { VARCHAR 256 } } { "ticket" "TICKET" { VARCHAR 256 } } { "profile" "PROFILE" FACTOR-BLOB } diff --git a/extra/http/server/auth/providers/providers.factor b/extra/http/server/auth/providers/providers.factor index 121f065292..f4c7dbbf1d 100755 --- a/extra/http/server/auth/providers/providers.factor +++ b/extra/http/server/auth/providers/providers.factor @@ -4,7 +4,7 @@ USING: kernel accessors random math.parser locals sequences math ; IN: http.server.auth.providers -TUPLE: user username realname password email ticket profile deleted changed? ; +TUPLE: user username realname password salt email ticket profile deleted changed? ; : ( username -- user ) user new @@ -17,9 +17,6 @@ GENERIC: update-user ( user provider -- ) GENERIC: new-user ( user provider -- user/f ) -: check-login ( password username provider -- user/f ) - get-user dup [ [ password>> = ] keep and ] [ 2drop f ] if ; - ! Password recovery support :: issue-ticket ( email username provider -- user/f ) diff --git a/extra/http/server/boilerplate/boilerplate.factor b/extra/http/server/boilerplate/boilerplate.factor index 1dc5effbe2..e0a4037e31 100644 --- a/extra/http/server/boilerplate/boilerplate.factor +++ b/extra/http/server/boilerplate/boilerplate.factor @@ -1,7 +1,7 @@ ! Copyright (c) 2008 Slava Pestov ! See http://factorcode.org/license.txt for BSD license. USING: accessors kernel namespaces boxes sequences strings -io io.streams.string arrays +io io.streams.string arrays locals html.elements http http.server @@ -47,7 +47,7 @@ SYMBOL: nested-template? SYMBOL: next-template : call-next-template ( -- ) - next-template get write ; + next-template get write-html ; M: f call-template* drop call-next-template ; @@ -68,9 +68,10 @@ M: f call-template* drop call-next-template ; bi* ] with-scope ; inline -M: boilerplate call-responder* - tuck call-next-method - dup "content-type" header "text/html" = [ - clone swap template>> - [ [ with-boilerplate ] 2curry ] curry change-body - ] [ nip ] if ; +M:: boilerplate call-responder* ( path responder -- ) + path responder call-next-method + dup content-type>> "text/html" = [ + clone [| body | + [ body responder template>> with-boilerplate ] + ] change-body + ] when ; diff --git a/extra/http/server/callbacks/callbacks-tests.factor b/extra/http/server/callbacks/callbacks-tests.factor index cca5942328..31ea164a58 100755 --- a/extra/http/server/callbacks/callbacks-tests.factor +++ b/extra/http/server/callbacks/callbacks-tests.factor @@ -24,7 +24,7 @@ splitting kernel hashtables continuations ; [ [ "hello" print - "text/html" swap '[ , write ] >>body + '[ , write ] ] show-page "byebye" print [ 123 ] show-final diff --git a/extra/http/server/components/code/code.factor b/extra/http/server/components/code/code.factor index 90b70c7bcc..8bf07700e8 100644 --- a/extra/http/server/components/code/code.factor +++ b/extra/http/server/components/code/code.factor @@ -1,7 +1,7 @@ ! Copyright (C) 2008 Slava Pestov ! See http://factorcode.org/license.txt for BSD license. USING: splitting kernel io sequences xmode.code2html accessors -http.server.components ; +http.server.components xml.entities ; IN: http.server.components.code TUPLE: code-renderer < text-renderer mode ; diff --git a/extra/http/server/components/components.factor b/extra/http/server/components/components.factor index cb109fc847..eb97092fb7 100755 --- a/extra/http/server/components/components.factor +++ b/extra/http/server/components/components.factor @@ -3,7 +3,7 @@ USING: accessors namespaces kernel io math.parser assocs classes words classes.tuple arrays sequences splitting mirrors hashtables fry combinators continuations math -calendar.format html.elements +calendar.format html.elements xml.entities http.server.validators ; IN: http.server.components @@ -18,13 +18,13 @@ TUPLE: field type ; C: field -M: field render-view* drop write ; +M: field render-view* drop escape-string write ; M: field render-edit* > =type [ =id ] [ =name ] bi =value input/> ; : render-error ( message -- ) - write ; + escape-string write ; TUPLE: hidden < field ; @@ -232,7 +232,7 @@ TUPLE: text-renderer rows cols ; text-renderer new-text-renderer ; M: text-renderer render-view* - drop write ; + drop escape-string write ; M: text-renderer render-edit* ; TUPLE: text < string ; @@ -261,7 +261,7 @@ TUPLE: html-text-renderer < text-renderer ; html-text-renderer new-text-renderer ; M: html-text-renderer render-view* - drop write ; + drop escape-string write ; TUPLE: html-text < text ; @@ -286,7 +286,7 @@ GENERIC: link-href ( obj -- url ) SINGLETON: link-renderer M: link-renderer render-view* - drop link-title write ; + drop link-title escape-string write ; TUPLE: link < string ; @@ -341,15 +341,19 @@ TUPLE: choice-renderer choices ; C: choice-renderer M: choice-renderer render-view* - drop write ; + drop escape-string write ; + +: render-option ( text selected? -- ) + ; + +: render-options ( text selected -- ) + [ [ drop ] [ member? ] 2bi render-option ] curry each ; M: choice-renderer render-edit* ; TUPLE: choice < string ; @@ -357,3 +361,19 @@ TUPLE: choice < string ; : ( id choices -- component ) swap choice new-string swap >>renderer ; + +! Menu +TUPLE: menu-renderer choices size ; + +C: menu-renderer + +M: menu-renderer render-edit* + ; + +TUPLE: menu < string ; + +: ( id choices -- component ) + swap menu new-string + swap >>renderer ; diff --git a/extra/http/server/components/farkup/farkup.factor b/extra/http/server/components/farkup/farkup.factor index a8d320f82f..87b7170bbf 100755 --- a/extra/http/server/components/farkup/farkup.factor +++ b/extra/http/server/components/farkup/farkup.factor @@ -1,7 +1,7 @@ ! Copyright (C) 2008 Slava Pestov ! See http://factorcode.org/license.txt for BSD license. USING: splitting kernel io sequences farkup accessors -http.server.components ; +http.server.components xml.entities ; IN: http.server.components.farkup TUPLE: farkup-renderer < text-renderer ; diff --git a/extra/http/server/components/inspector/inspector.factor b/extra/http/server/components/inspector/inspector.factor index 25ee631a06..42366b57e4 100644 --- a/extra/http/server/components/inspector/inspector.factor +++ b/extra/http/server/components/inspector/inspector.factor @@ -1,13 +1,13 @@ ! Copyright (C) 2008 Slava Pestov ! See http://factorcode.org/license.txt for BSD license. USING: splitting kernel io sequences inspector accessors -http.server.components ; +http.server.components xml.entities html ; IN: http.server.components.inspector SINGLETON: inspector-renderer M: inspector-renderer render-view* - drop describe ; + drop [ describe ] with-html-stream ; TUPLE: inspector < component ; diff --git a/extra/http/server/forms/forms.factor b/extra/http/server/forms/forms.factor index 60f3da25b6..92fb25bb16 100644 --- a/extra/http/server/forms/forms.factor +++ b/extra/http/server/forms/forms.factor @@ -37,9 +37,7 @@ M: form init V{ } clone >>components ; ] with-form ; : ( form template -- response ) - [ components>> components set ] - [ "text/html" swap >>body ] - bi* ; + [ components>> components set ] [ ] bi* ; : view-form ( form -- response ) dup view-template>> ; diff --git a/extra/http/server/server.factor b/extra/http/server/server.factor index ad04812c63..f6dd6c57bb 100755 --- a/extra/http/server/server.factor +++ b/extra/http/server/server.factor @@ -1,9 +1,9 @@ ! Copyright (C) 2003, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: assocs kernel namespaces io io.timeouts strings splitting -threads http sequences prettyprint io.server logging calendar -html.elements accessors math.parser combinators.lib -tools.vocabs debugger html continuations random combinators +threads sequences prettyprint io.server logging calendar +http html html.elements accessors math.parser combinators.lib +tools.vocabs debugger continuations random combinators destructors io.encodings.8-bit fry classes words ; IN: http.server @@ -22,7 +22,10 @@ GENERIC: call-responder* ( path responder -- response ) 200 >>code "Document follows" >>message - swap set-content-type ; + swap >>content-type ; + +: ( quot -- response ) + "text/html" swap >>body ; TUPLE: trivial-responder response ; @@ -38,9 +41,7 @@ M: trivial-responder call-responder* nip response>> call ; ; : ( code message -- response ) - 2dup '[ , , trivial-response-body ] - "text/html" - swap >>body + 2dup '[ , , trivial-response-body ] swap >>message swap >>code ; diff --git a/extra/http/server/sessions/sessions-tests.factor b/extra/http/server/sessions/sessions-tests.factor index b4cf0bd679..0d98bf2150 100755 --- a/extra/http/server/sessions/sessions-tests.factor +++ b/extra/http/server/sessions/sessions-tests.factor @@ -143,7 +143,7 @@ M: foo call-responder* ] with-destructors response set ] unit-test - [ "text/plain" ] [ response get "content-type" header ] unit-test + [ "text/plain" ] [ response get content-type>> ] unit-test [ f ] [ response get cookies>> empty? ] unit-test ] with-scope diff --git a/extra/http/server/static/static.factor b/extra/http/server/static/static.factor index af6018fbdc..f0a367f0fb 100755 --- a/extra/http/server/static/static.factor +++ b/extra/http/server/static/static.factor @@ -1,21 +1,20 @@ ! Copyright (C) 2004, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: calendar html io io.files kernel math math.parser http -http.server namespaces parser sequences strings assocs -hashtables debugger http.mime sorting html.elements logging -calendar.format accessors io.encodings.binary fry ; +USING: calendar html io io.files kernel math math.order +math.parser http http.server namespaces parser sequences strings +assocs hashtables debugger http.mime sorting html.elements +logging calendar.format accessors io.encodings.binary fry ; IN: http.server.static ! special maps mime types to quots with effect ( path -- ) TUPLE: file-responder root hook special ; -: file-http-date ( filename -- string ) - file-info modified>> timestamp>http-string ; - -: last-modified-matches? ( filename -- ? ) - file-http-date dup [ - request get "if-modified-since" header = - ] when ; +: modified-since? ( filename -- ? ) + request get "if-modified-since" header dup [ + [ file-info modified>> ] [ rfc822>timestamp ] bi* after? + ] [ + 2drop t + ] if ; : <304> ( -- response ) 304 "Not modified" ; @@ -26,16 +25,17 @@ TUPLE: file-responder root hook special ; : ( root -- responder ) [ - swap - [ file-info size>> "content-length" set-header ] - [ file-http-date "last-modified" set-header ] - [ '[ , binary stdio get stream-copy ] >>body ] - tri + swap [ + file-info + [ size>> "content-length" set-header ] + [ modified>> "last-modified" set-header ] bi + ] + [ '[ , binary stdio get stream-copy ] >>body ] bi ] ; : serve-static ( filename mime-type -- response ) - over last-modified-matches? - [ 2drop <304> ] [ file-responder get hook>> call ] if ; + over modified-since? + [ file-responder get hook>> call ] [ 2drop <304> ] if ; : serving-path ( filename -- filename ) file-responder get root>> right-trim-separators @@ -65,8 +65,7 @@ TUPLE: file-responder root hook special ; ] simple-html-document ; : list-directory ( directory -- response ) - "text/html" - swap '[ , directory. ] >>body ; + '[ , directory. ] ; : find-index ( filename -- path ) "index.html" append-path dup exists? [ drop f ] unless ; diff --git a/extra/http/server/templating/templating.factor b/extra/http/server/templating/templating.factor index 610ec78fed..73f6095eae 100644 --- a/extra/http/server/templating/templating.factor +++ b/extra/http/server/templating/templating.factor @@ -24,5 +24,4 @@ M: template write-response-body* call-template ; ! responder integration : serve-template ( template -- response ) - "text/html" - swap '[ , call-template ] >>body ; + '[ , call-template ] ; diff --git a/extra/webapps/pastebin/pastebin.factor b/extra/webapps/pastebin/pastebin.factor index 76e7a1464a..144900d6ec 100644 --- a/extra/webapps/pastebin/pastebin.factor +++ b/extra/webapps/pastebin/pastebin.factor @@ -8,6 +8,7 @@ http.server.actions http.server.components http.server.components.code http.server.templating.chloe +http.server.auth http.server.auth.login http.server.boilerplate http.server.validators @@ -236,13 +237,17 @@ annotation "ANNOTATION" TUPLE: pastebin < dispatcher ; +SYMBOL: can-delete-pastes? + +can-delete-pastes? define-capability + : ( -- responder ) pastebin new-dispatcher "list" add-main-responder "feed.xml" add-responder [ ] "view-paste" add-responder - [ ] "$pastebin/list" "delete-paste" add-responder - [ ] "$pastebin/view-paste" "delete-annotation" add-responder + [ ] "$pastebin/list" { can-delete-pastes? } "delete-paste" add-responder + [ ] "$pastebin/view-paste" { can-delete-pastes? } "delete-annotation" add-responder [ ] "$pastebin/view-paste" add-responder [ now >>date ] "$pastebin/view-paste" "new-paste" add-responder [ now >>date ] "$pastebin/view-paste" "annotate" add-responder diff --git a/extra/webapps/planet/planet.factor b/extra/webapps/planet/planet.factor index d3260e1c70..c8aeab35a8 100755 --- a/extra/webapps/planet/planet.factor +++ b/extra/webapps/planet/planet.factor @@ -11,7 +11,8 @@ http.server.actions http.server.boilerplate http.server.templating.chloe http.server.components -http.server.auth.login ; +http.server.auth.login +http.server.auth ; IN: webapps.planet TUPLE: planet-factor < dispatcher postings ; @@ -159,11 +160,15 @@ blog "BLOGS" blog-form blog-ctor "$planet-factor/admin" "edit-blog" add-responder ] ; +SYMBOL: can-administer-planet-factor? + +can-administer-planet-factor? define-capability + : ( -- responder ) planet-factor new-dispatcher dup "list" add-main-responder dup "feed.xml" add-responder - dup "admin" add-responder + dup { can-administer-planet-factor? } "admin" add-responder "planet" planet-template >>template ; diff --git a/extra/webapps/todo/edit-todo.xml b/extra/webapps/todo/edit-todo.xml index ef1e1fd26a..9b7e9e667a 100644 --- a/extra/webapps/todo/edit-todo.xml +++ b/extra/webapps/todo/edit-todo.xml @@ -4,22 +4,22 @@ Edit Item - - + + - - - + + +
Summary:
Priority:
Description:
Summary:
Priority:
Description:
- View + View | - - + + diff --git a/extra/webapps/todo/todo.factor b/extra/webapps/todo/todo.factor index e1ebc65bb5..8bfda1aad5 100755 --- a/extra/webapps/todo/todo.factor +++ b/extra/webapps/todo/todo.factor @@ -76,5 +76,5 @@ TUPLE: todo-list < dispatcher ; ctor "$todo-list/list" "delete" add-responder "todo" todo-template >>template - + f ] ; diff --git a/extra/webapps/todo/view-todo.xml b/extra/webapps/todo/view-todo.xml index f77396c73c..1bd73f48e1 100644 --- a/extra/webapps/todo/view-todo.xml +++ b/extra/webapps/todo/view-todo.xml @@ -5,8 +5,8 @@ View Item - - + +
Summary:
Priority:
Summary:
Priority: