From b88a383151a9143aba747692eb33d0e4ff5ea721 Mon Sep 17 00:00:00 2001 From: Daniel Ehrenberg Date: Sun, 1 Jun 2008 01:23:11 -0500 Subject: [PATCH 01/19] Yahoo updates --- extra/yahoo/authors.txt | 1 + extra/yahoo/summary.txt | 2 +- extra/yahoo/yahoo-tests.factor | 4 +-- extra/yahoo/yahoo.factor | 50 ++++++++++++++++++++++++++-------- 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/extra/yahoo/authors.txt b/extra/yahoo/authors.txt index f990dd0ed2..382fc3fc09 100644 --- a/extra/yahoo/authors.txt +++ b/extra/yahoo/authors.txt @@ -1 +1,2 @@ Daniel Ehrenberg +Walton Chan diff --git a/extra/yahoo/summary.txt b/extra/yahoo/summary.txt index 662369d96e..98287365af 100644 --- a/extra/yahoo/summary.txt +++ b/extra/yahoo/summary.txt @@ -1 +1 @@ -Yahoo! search example using XML-RPC +Yahoo! search example using XML diff --git a/extra/yahoo/yahoo-tests.factor b/extra/yahoo/yahoo-tests.factor index dc684af726..3776715c7b 100644 --- a/extra/yahoo/yahoo-tests.factor +++ b/extra/yahoo/yahoo-tests.factor @@ -1,4 +1,4 @@ -USING: tools.test yahoo kernel io.files xml sequences ; +USING: tools.test yahoo kernel io.files xml sequences accessors ; [ T{ result @@ -8,4 +8,4 @@ USING: tools.test yahoo kernel io.files xml sequences ; "Official site with news, tour dates, discography, store, community, and more." } ] [ "resource:extra/yahoo/test-results.xml" file>xml parse-yahoo first ] unit-test -[ "http://search.yahooapis.com/WebSearchService/V1/webSearch?appid=Factor-search&query=hi&results=1" ] [ "hi" 1 "Factor-search" query ] unit-test +[ "http://search.yahooapis.com/WebSearchService/V1/webSearch?appid=Factor-search&query=hi&results=2&similar_ok=1" ] [ "hi" "Factor-search" >>appid 2 >>results t >>similar-ok query ] unit-test diff --git a/extra/yahoo/yahoo.factor b/extra/yahoo/yahoo.factor index 214ad04979..dd7ce962c2 100755 --- a/extra/yahoo/yahoo.factor +++ b/extra/yahoo/yahoo.factor @@ -1,12 +1,15 @@ -! Copyright (C) 2006 Daniel Ehrenberg +! Copyright (C) 2006 Daniel Ehrenberg, Walton Chan ! See http://factorcode.org/license.txt for BSD license. USING: http.client xml xml.utilities kernel sequences -namespaces http math.parser help math.order locals ; +namespaces http math.parser help math.order locals accessors ; IN: yahoo TUPLE: result title url summary ; C: result + +TUPLE: search query results adult-ok start appid region type +format similar-ok language country site subscription license ; : parse-yahoo ( xml -- seq ) "Result" deep-tags-named [ @@ -18,19 +21,44 @@ C: result : yahoo-url ( -- str ) "http://search.yahooapis.com/WebSearchService/V1/webSearch" ; -:: query ( search num appid -- url ) +: param ( search str quot -- search ) + >r over r> call [ url-encode [ % ] bi@ ] [ drop ] if* ; + inline + +: num-param ( search str quot -- search ) + [ dup [ number>string ] when ] compose param ; inline + +: bool-param ( search str quot -- search ) + [ "1" and ] compose param ; inline + +: query ( search -- url ) [ - yahoo-url % - "?appid=" % appid % - "&query=" % search url-encode % - "&results=" % num # + yahoo-url % + "?appid=" [ appid>> ] param + "&query=" [ query>> ] param + "®ion=" [ region>> ] param + "&type=" [ type>> ] param + "&format=" [ format>> ] param + "&language=" [ language>> ] param + "&country=" [ country>> ] param + "&site=" [ site>> ] param + "&subscription=" [ subscription>> ] param + "&license=" [ license>> ] param + "&results=" [ results>> ] num-param + "&start=" [ start>> ] num-param + "&adult_ok=" [ adult-ok>> ] bool-param + "&similar_ok=" [ similar-ok>> ] bool-param + drop ] "" make ; : factor-id "fRrVAKzV34GDyeRw6bUHDhEWHRedwfOC7e61wwXZLgGF80E67spxdQXuugBe2pgIevMmKwA-" ; -: search-yahoo/id ( search num id -- seq ) - query http-get string>xml parse-yahoo ; +: ( query -- search ) + search new + factor-id >>appid + 10 >>results + swap >>query ; -: search-yahoo ( search num -- seq ) - factor-id search-yahoo/id ; +: search-yahoo ( search -- seq ) + query http-get string>xml parse-yahoo ; From d3d1db199e5c1d13071015f7aa8778dee8d1f9fb Mon Sep 17 00:00:00 2001 From: Daniel Ehrenberg Date: Sun, 1 Jun 2008 11:24:17 -0500 Subject: [PATCH 02/19] Docs for collation --- extra/unicode/collation/collation-docs.factor | 39 ++++++++++++++++++- extra/unicode/collation/collation.factor | 6 +++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/extra/unicode/collation/collation-docs.factor b/extra/unicode/collation/collation-docs.factor index 23538229a4..0e92042ddd 100644 --- a/extra/unicode/collation/collation-docs.factor +++ b/extra/unicode/collation/collation-docs.factor @@ -1,7 +1,42 @@ -USING: help.syntax help.markup ; +USING: help.syntax help.markup strings byte-arrays ; IN: unicode.collation ABOUT: "unicode.collation" ARTICLE: "unicode.collation" "Unicode collation algorithm" -"The Unicode Collation Algorithm (UTS #10) forms a reasonable way to sort strings when accouting for all of the characters in Unicode." ; +"The Unicode Collation Algorithm (UTS #10) forms a reasonable way to sort strings when accouting for all of the characters in Unicode. At the moment, only the default Unicode collation element table (DUCET) is used, but a more accurate collation would take locale into account. The following words are defined:" +{ $subsection sort-strings } +{ $subsection collation-key } +{ $subsection string<=> } +{ $subsection primary= } +{ $subsection secondary= } +{ $subsection tertiary= } +{ $subsection quaternary= } ; + +HELP: sort-strings +{ $values { "strings" "a sequence of strings" } { "sorted" "the strings in DUCET order" } } +{ $description "This word takes a sequence of strings and sorts them according to the UCA, using code point order as a tie-breaker." } ; + +HELP: collation-key +{ $values { "string" string } { "key" byte-array } } +{ $description "This takes a string and gives a representation of the collation key, which can be compared with <=>" } ; + +HELP: string<=> +{ $values { "str1" string } { "str2" string } { "<=>" "one of +lt+, +gt+ or +eq+" } } +{ $description "This word takes two strings and compares them using the UCA with the DUCET, using code point order as a tie-breaker." } ; + +HELP: primary= +{ $values { "str1" string } { "str2" string } { "?" "t or f" } } +{ $description "This checks whether the first level of collation is identical. This is the least specific kind of equality test. In Latin script, it can be understood as ignoring case, punctuation and accent marks." } ; + +HELP: secondary= +{ $values { "str1" string } { "str2" string } { "?" "t or f" } } +{ $description "This checks whether the first two levels of collation are equal. For Latin script, this means accent marks are significant again, and it is otherwise similar to primary=." } ; + +HELP: tertiary= +{ $values { "str1" string } { "str2" string } { "?" "t or f" } } +{ $description "Along the same lines as secondary=, but case is significant." } ; + +HELP: quaternary= +{ $values { "str1" string } { "str2" string } { "?" "t or f" } } +{ $description "This is similar to tertiary= but it makes punctuation significant again, while still leaving out things like null bytes and Hebrew vowel marks, which mean absolutely nothing in collation." } ; diff --git a/extra/unicode/collation/collation.factor b/extra/unicode/collation/collation.factor index b12a10709e..441339d677 100755 --- a/extra/unicode/collation/collation.factor +++ b/extra/unicode/collation/collation.factor @@ -6,6 +6,7 @@ unicode.syntax macros sequences.deep words unicode.breaks quotations ; IN: unicode.collation + : completely-ignorable? ( weight -- ? ) [ primary>> ] [ secondary>> ] [ tertiary>> ] tri @@ -131,11 +133,13 @@ ducet insert-helpers nfd string>graphemes graphemes>weights filter-ignorable weights>bytes ; + : primary= ( str1 str2 -- ? ) 3 insensitive= ; @@ -149,12 +153,14 @@ ducet insert-helpers : quaternary= ( str1 str2 -- ? ) 0 insensitive= ; + ) 2dup [ second ] bi@ <=> dup +eq+ = [ drop <=> ] [ 2nip ] if ; : w/collation-key ( str -- {str,key} ) dup collation-key 2array ; +PRIVATE> : sort-strings ( strings -- sorted ) [ w/collation-key ] map From 53952c320052e097f3b778dd6e93e0e313378dc1 Mon Sep 17 00:00:00 2001 From: Matthew Willis Date: Sun, 1 Jun 2008 10:35:40 -0700 Subject: [PATCH 03/19] enhanced performance of pango and cairo gadgets by making the intermediate byte-arrays short-lived, and by using a global "dummy-cairo" for measuring layout-sizes --- extra/cairo/gadgets/gadgets.factor | 17 +++++++++++++---- extra/pango/cairo/cairo.factor | 7 +++++-- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/extra/cairo/gadgets/gadgets.factor b/extra/cairo/gadgets/gadgets.factor index f5f4d3e965..69252f8303 100644 --- a/extra/cairo/gadgets/gadgets.factor +++ b/extra/cairo/gadgets/gadgets.factor @@ -2,7 +2,8 @@ ! See http://factorcode.org/license.txt for BSD license. USING: sequences math opengl.gadgets kernel byte-arrays cairo.ffi cairo io.backend -opengl.gl arrays ; +ui.gadgets accessors opengl.gl +arrays ; IN: cairo.gadgets @@ -14,9 +15,17 @@ IN: cairo.gadgets [ cairo_image_surface_create_for_data ] 3bi r> with-cairo-from-surface ; -: ( dim quot -- ) - over 2^-bounds swap copy-cairo - GL_BGRA rot ; +TUPLE: cairo-gadget < texture-gadget quot ; + +: ( dim quot -- gadget ) + cairo-gadget construct-gadget + swap >>quot + swap >>dim ; + +M: cairo-gadget graft* ( gadget -- ) + GL_BGRA >>format dup + [ dim>> 2^-bounds ] [ quot>> copy-cairo ] bi + >>bytes call-next-method ; ! maybe also texture>png ! : cairo>png ( gadget path -- ) diff --git a/extra/pango/cairo/cairo.factor b/extra/pango/cairo/cairo.factor index 889052c385..907233a335 100644 --- a/extra/pango/cairo/cairo.factor +++ b/extra/pango/cairo/cairo.factor @@ -4,6 +4,7 @@ ! pangocairo bindings, from pango/pangocairo.h USING: cairo.ffi alien.c-types math alien.syntax system combinators alien +memoize arrays pango pango.fonts ; IN: pango.cairo @@ -111,9 +112,11 @@ M: pango-layout dispose ( alien -- ) alien>> g_object_unref ; 0 0 [ pango_layout_get_pixel_size ] 2keep [ *int ] bi@ ; +MEMO: dummy-cairo ( -- cr ) + CAIRO_FORMAT_ARGB32 0 0 cairo_image_surface_create cairo_create ; + : dummy-pango ( quot -- ) - >r CAIRO_FORMAT_ARGB32 0 0 cairo_image_surface_create - r> [ with-pango ] curry with-cairo-from-surface ; inline + >r dummy-cairo cairo r> [ with-pango ] curry with-variable ; inline : layout-size ( quot -- dim ) [ layout pango-layout-get-pixel-size 2array ] compose dummy-pango ; inline From 94776f6841c6d85131848dab3efbd773dde4c168 Mon Sep 17 00:00:00 2001 From: Daniel Ehrenberg Date: Sun, 1 Jun 2008 13:50:12 -0500 Subject: [PATCH 04/19] Collation cleanup and test added --- extra/unicode/collation/collation-tests.factor | 3 +++ extra/unicode/collation/collation.factor | 11 +++-------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/extra/unicode/collation/collation-tests.factor b/extra/unicode/collation/collation-tests.factor index b4a54bb11d..16ac50d5a9 100755 --- a/extra/unicode/collation/collation-tests.factor +++ b/extra/unicode/collation/collation-tests.factor @@ -24,6 +24,9 @@ IN: unicode.collation.tests [ t t f f ] [ "hello" "HELLO" test-equality ] unit-test [ t t t f ] [ "hello" "h e l l o." test-equality ] unit-test [ t t t t ] [ "hello" "\0hello\0" test-equality ] unit-test +[ { "good bye" "goodbye" "hello" "HELLO" } ] +[ { "HELLO" "goodbye" "good bye" "hello" } sort-strings ] +unit-test parse-test 2 [ [ test-two ] assoc-each ] with-null-writer diff --git a/extra/unicode/collation/collation.factor b/extra/unicode/collation/collation.factor index 441339d677..f71a58be85 100755 --- a/extra/unicode/collation/collation.factor +++ b/extra/unicode/collation/collation.factor @@ -154,18 +154,13 @@ PRIVATE> 0 insensitive= ; ) - 2dup [ second ] bi@ <=> dup +eq+ = - [ drop <=> ] [ 2nip ] if ; - : w/collation-key ( str -- {str,key} ) - dup collation-key 2array ; + [ collation-key ] keep 2array ; PRIVATE> : sort-strings ( strings -- sorted ) [ w/collation-key ] map - [ compare-collation ] sort - keys ; + natural-sort values ; : string<=> ( str1 str2 -- <=> ) - [ w/collation-key ] bi@ compare-collation ; + [ w/collation-key ] compare ; From c5c65a4ce4be28d9deb05db9d6db9e6d83d93cac Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Sun, 1 Jun 2008 17:22:39 -0500 Subject: [PATCH 05/19] Web framework refactoring work in progress --- .../actions/actions-tests.factor | 7 +- .../server => furnace}/actions/actions.factor | 16 +- .../{http/server => furnace}/auth/auth.factor | 6 +- .../auth/basic/basic.factor | 4 +- .../auth/login/boilerplate.xml | 0 .../auth/login/edit-profile.xml | 0 .../auth/login/login-tests.factor | 4 +- .../auth/login/login.factor | 67 +++-- .../server => furnace}/auth/login/login.xml | 0 .../auth/login/recover-1.xml | 0 .../auth/login/recover-2.xml | 0 .../auth/login/recover-3.xml | 0 .../auth/login/recover-4.xml | 0 .../auth/login/register.xml | 0 .../auth/providers/assoc/assoc-tests.factor | 6 +- .../auth/providers/assoc/assoc.factor | 5 +- .../auth/providers/db/db-tests.factor | 10 +- .../auth/providers/db/db.factor | 4 +- .../auth/providers/null/null.factor | 4 +- .../auth/providers/providers.factor | 2 +- .../boilerplate/boilerplate.factor | 10 +- .../callbacks/callbacks-tests.factor | 6 +- .../callbacks/callbacks.factor | 2 +- extra/furnace/db/db-tests.factor | 4 + extra/{http/server => furnace}/db/db.factor | 4 +- .../server => furnace}/flows/flows.factor | 62 ++-- extra/furnace/furnace.factor | 136 +++++++++ .../server => furnace}/sessions/authors.txt | 0 .../sessions/sessions-tests.factor | 34 +-- .../sessions/sessions.factor | 16 +- extra/html/components/components-tests.factor | 4 +- extra/html/components/components.factor | 43 +-- extra/html/elements/elements.factor | 18 +- extra/html/templates/chloe/chloe-tests.factor | 13 +- extra/html/templates/chloe/chloe.factor | 270 +++--------------- .../html/templates/chloe/syntax/syntax.factor | 58 ++++ extra/html/templates/chloe/test/test10.xml | 4 +- extra/html/templates/chloe/test/test11.xml | 13 +- extra/html/templates/chloe/test/test9.xml | 2 +- extra/html/templates/templates.factor | 25 +- extra/http/client/client-tests.factor | 12 +- extra/http/client/client.factor | 5 +- extra/http/http-tests.factor | 66 ++--- extra/http/http.factor | 226 +++------------ extra/http/server/cgi/cgi.factor | 9 +- extra/http/server/db/db-tests.factor | 4 - extra/http/server/server-tests.factor | 57 ++-- extra/http/server/server.factor | 183 +++++------- extra/http/server/static/static.factor | 8 +- extra/io/pools/pools.factor | 20 +- extra/lcs/diff2html/diff2html.factor | 2 +- extra/rss/rss.factor | 19 +- extra/tangle/tangle.factor | 8 +- extra/urls/urls-tests.factor | 13 +- extra/urls/urls.factor | 64 +++-- extra/webapps/counter/counter.factor | 16 +- .../factor-website/factor-website.factor | 22 +- extra/webapps/factor-website/page.xml | 2 + extra/webapps/pastebin/paste.xml | 16 +- extra/webapps/pastebin/pastebin-common.xml | 2 + extra/webapps/pastebin/pastebin.factor | 68 ++--- extra/webapps/pastebin/pastebin.xml | 6 +- extra/webapps/planet/admin.xml | 4 +- extra/webapps/planet/mini-planet.xml | 4 +- extra/webapps/planet/planet.factor | 48 ++-- extra/webapps/planet/planet.xml | 6 +- extra/webapps/todo/edit-todo.xml | 10 +- extra/webapps/todo/new-todo.xml | 17 ++ extra/webapps/todo/todo-list.xml | 4 +- extra/webapps/todo/todo.factor | 52 ++-- extra/webapps/todo/todo.xml | 2 +- extra/webapps/user-admin/edit-user.xml | 6 +- extra/webapps/user-admin/new-user.xml | 6 +- extra/webapps/user-admin/user-admin.factor | 71 ++--- extra/webapps/user-admin/user-list.xml | 4 +- extra/webapps/wiki/articles.xml | 4 +- extra/webapps/wiki/changes.xml | 4 +- extra/webapps/wiki/diff.xml | 16 +- extra/webapps/wiki/revisions.xml | 43 ++- extra/webapps/wiki/user-edits.xml | 4 +- extra/webapps/wiki/wiki.css | 26 +- extra/webapps/wiki/wiki.factor | 80 ++++-- extra/xmode/code2html/code2html.factor | 6 +- .../code2html/responder/responder.factor | 2 +- 84 files changed, 1027 insertions(+), 1079 deletions(-) rename extra/{http/server => furnace}/actions/actions-tests.factor (83%) rename extra/{http/server => furnace}/actions/actions.factor (81%) rename extra/{http/server => furnace}/auth/auth.factor (88%) rename extra/{http/server => furnace}/auth/basic/basic.factor (90%) rename extra/{http/server => furnace}/auth/login/boilerplate.xml (100%) rename extra/{http/server => furnace}/auth/login/edit-profile.xml (100%) rename extra/{http/server => furnace}/auth/login/login-tests.factor (52%) rename extra/{http/server => furnace}/auth/login/login.factor (85%) rename extra/{http/server => furnace}/auth/login/login.xml (100%) rename extra/{http/server => furnace}/auth/login/recover-1.xml (100%) rename extra/{http/server => furnace}/auth/login/recover-2.xml (100%) rename extra/{http/server => furnace}/auth/login/recover-3.xml (100%) rename extra/{http/server => furnace}/auth/login/recover-4.xml (100%) rename extra/{http/server => furnace}/auth/login/register.xml (100%) rename extra/{http/server => furnace}/auth/providers/assoc/assoc-tests.factor (79%) rename extra/{http/server => furnace}/auth/providers/assoc/assoc.factor (80%) rename extra/{http/server => furnace}/auth/providers/db/db-tests.factor (83%) rename extra/{http/server => furnace}/auth/providers/db/db.factor (92%) rename extra/{http/server => furnace}/auth/providers/null/null.factor (71%) rename extra/{http/server => furnace}/auth/providers/providers.factor (94%) rename extra/{http/server => furnace}/boilerplate/boilerplate.factor (67%) rename extra/{http/server => furnace}/callbacks/callbacks-tests.factor (87%) rename extra/{http/server => furnace}/callbacks/callbacks.factor (96%) create mode 100644 extra/furnace/db/db-tests.factor rename extra/{http/server => furnace}/db/db.factor (82%) rename extra/{http/server => furnace}/flows/flows.factor (53%) create mode 100644 extra/furnace/furnace.factor rename extra/{http/server => furnace}/sessions/authors.txt (100%) rename extra/{http/server => furnace}/sessions/sessions-tests.factor (79%) rename extra/{http/server => furnace}/sessions/sessions.factor (92%) create mode 100644 extra/html/templates/chloe/syntax/syntax.factor delete mode 100644 extra/http/server/db/db-tests.factor create mode 100644 extra/webapps/todo/new-todo.xml diff --git a/extra/http/server/actions/actions-tests.factor b/extra/furnace/actions/actions-tests.factor similarity index 83% rename from extra/http/server/actions/actions-tests.factor rename to extra/furnace/actions/actions-tests.factor index 480cbc8e96..8aa0f92b97 100755 --- a/extra/http/server/actions/actions-tests.factor +++ b/extra/furnace/actions/actions-tests.factor @@ -1,7 +1,7 @@ -USING: kernel http.server.actions validators +USING: kernel furnace.actions validators tools.test math math.parser multiline namespaces http io.streams.string http.server sequences splitting accessors ; -IN: http.server.actions.tests +IN: furnace.actions.tests [ "a" param "b" param [ string>number ] bi@ + ] >>display @@ -16,9 +16,8 @@ blah ; [ 25 ] [ - init-request action-request-test-1 lf>crlf [ read-request ] with-string-reader - request set + init-request { } "action-1" get call-responder ] unit-test diff --git a/extra/http/server/actions/actions.factor b/extra/furnace/actions/actions.factor similarity index 81% rename from extra/http/server/actions/actions.factor rename to extra/furnace/actions/actions.factor index eb5b8bfe68..26042d6159 100755 --- a/extra/http/server/actions/actions.factor +++ b/extra/furnace/actions/actions.factor @@ -2,8 +2,9 @@ ! See http://factorcode.org/license.txt for BSD license. USING: accessors sequences kernel assocs combinators http.server validators http hashtables namespaces fry continuations locals -boxes xml.entities html.elements html.components io arrays math ; -IN: http.server.actions +boxes xml.entities html.elements html.components +html.templates.chloe io arrays math ; +IN: furnace.actions SYMBOL: params @@ -17,6 +18,8 @@ SYMBOL: rest-param ] if ; +CHLOE: validation-messages drop render-validation-messages ; + TUPLE: action rest-param init display validate submit ; : new-action ( class -- action ) @@ -75,7 +78,7 @@ M: action call-responder* ( path action -- response ) validation-failed? [ validation-failed ] when ; : validate-params ( validators -- ) - params get swap validate-values from-assoc + params get swap validate-values from-object check-validation ; : validate-integer-id ( -- ) @@ -83,12 +86,15 @@ M: action call-responder* ( path action -- response ) TUPLE: page-action < action template ; +: ( path -- response ) + resolve-template-path "text/html" ; + : ( -- page ) page-action new-action - dup '[ , template>> ] >>display ; + dup '[ , template>> ] >>display ; TUPLE: feed-action < action feed ; : ( -- feed ) - feed-action new + feed-action new-action dup '[ , feed>> call ] >>display ; diff --git a/extra/http/server/auth/auth.factor b/extra/furnace/auth/auth.factor similarity index 88% rename from extra/http/server/auth/auth.factor rename to extra/furnace/auth/auth.factor index 4b34fbe804..c42b73b825 100755 --- a/extra/http/server/auth/auth.factor +++ b/extra/furnace/auth/auth.factor @@ -2,9 +2,9 @@ ! See http://factorcode.org/license.txt for BSD license. USING: accessors assocs namespaces kernel sequences sets http.server -http.server.sessions -http.server.auth.providers ; -IN: http.server.auth +furnace.sessions +furnace.auth.providers ; +IN: furnace.auth SYMBOL: logged-in-user diff --git a/extra/http/server/auth/basic/basic.factor b/extra/furnace/auth/basic/basic.factor similarity index 90% rename from extra/http/server/auth/basic/basic.factor rename to extra/furnace/auth/basic/basic.factor index ff071b34e3..c57f78b315 100755 --- a/extra/http/server/auth/basic/basic.factor +++ b/extra/furnace/auth/basic/basic.factor @@ -2,9 +2,9 @@ ! See http://factorcode.org/license.txt for BSD license. USING: accessors quotations assocs kernel splitting base64 html.elements io combinators http.server -http.server.auth.providers http.server.auth.login +furnace.auth.providers furnace.auth.login http sequences ; -IN: http.server.auth.basic +IN: furnace.auth.basic TUPLE: basic-auth < filter-responder realm provider ; diff --git a/extra/http/server/auth/login/boilerplate.xml b/extra/furnace/auth/login/boilerplate.xml similarity index 100% rename from extra/http/server/auth/login/boilerplate.xml rename to extra/furnace/auth/login/boilerplate.xml diff --git a/extra/http/server/auth/login/edit-profile.xml b/extra/furnace/auth/login/edit-profile.xml similarity index 100% rename from extra/http/server/auth/login/edit-profile.xml rename to extra/furnace/auth/login/edit-profile.xml diff --git a/extra/http/server/auth/login/login-tests.factor b/extra/furnace/auth/login/login-tests.factor similarity index 52% rename from extra/http/server/auth/login/login-tests.factor rename to extra/furnace/auth/login/login-tests.factor index b69630a930..5095ebdb85 100755 --- a/extra/http/server/auth/login/login-tests.factor +++ b/extra/furnace/auth/login/login-tests.factor @@ -1,5 +1,5 @@ -IN: http.server.auth.login.tests -USING: tools.test http.server.auth.login ; +IN: furnace.auth.login.tests +USING: tools.test furnace.auth.login ; \ must-infer \ allow-registration must-infer diff --git a/extra/http/server/auth/login/login.factor b/extra/furnace/auth/login/login.factor similarity index 85% rename from extra/http/server/auth/login/login.factor rename to extra/furnace/auth/login/login.factor index fd4fbab8e8..85d71b574f 100755 --- a/extra/http/server/auth/login/login.factor +++ b/extra/furnace/auth/login/login.factor @@ -15,19 +15,18 @@ checksums.sha2 validators html.components html.elements -html.templates -html.templates.chloe +urls http http.server -http.server.auth -http.server.auth.providers -http.server.auth.providers.db -http.server.actions -http.server.flows -http.server.sessions -http.server.boilerplate ; +furnace.auth +furnace.auth.providers +furnace.auth.providers.db +furnace.actions +furnace.flows +furnace.sessions +furnace.boilerplate ; QUALIFIED: smtp -IN: http.server.auth.login +IN: furnace.auth.login TUPLE: login < dispatcher users checksum ; @@ -59,10 +58,6 @@ M: user-saver dispose : save-user-after ( user -- ) &dispose drop ; -: login-template ( name -- template ) - "resource:extra/http/server/auth/login/" swap ".xml" - 3append ; - ! ! ! Login : successful-login ( user -- response ) username>> set-uid "$login" end-flow ; @@ -72,8 +67,8 @@ M: user-saver dispose validation-failed ; : ( -- action ) - - [ "login" login-template ] >>display + + "$login/login" >>template [ { @@ -102,7 +97,7 @@ M: user-saver dispose : ( -- action ) - "register" login-template >>template + "$login/register" >>template [ { @@ -134,7 +129,7 @@ M: user-saver dispose ! ! ! Editing user profile : ( -- action ) - + [ logged-in-user get [ username>> "username" set-value ] @@ -143,7 +138,7 @@ M: user-saver dispose tri ] >>init - [ "edit-profile" login-template ] >>display + "$login/edit-profile" >>template [ uid "username" set-value @@ -186,10 +181,10 @@ M: user-saver dispose SYMBOL: lost-password-from : current-host ( -- string ) - request get host>> host-name or ; + request get url>> host>> host-name or ; : new-password-url ( user -- url ) - "new-password" + "recover-3" swap [ [ username>> "username" set ] [ ticket>> "ticket" set ] @@ -223,8 +218,8 @@ SYMBOL: lost-password-from "E-mail send thread" spawn drop ; : ( -- action ) - - [ "recover-1" login-template ] >>display + + "$login/recover-1" >>template [ { @@ -240,11 +235,15 @@ SYMBOL: lost-password-from send-password-email ] when* - "recover-2" login-template + URL" $login/recover-2" ] >>submit ; +: ( -- action ) + + "$login/recover-2" >>template ; + : ( -- action ) - + [ { { "username" [ v-username ] } @@ -252,7 +251,7 @@ SYMBOL: lost-password-from } validate-params ] >>init - [ "recover-3" login-template ] >>display + "$login/recover-3" >>template [ { @@ -272,12 +271,16 @@ SYMBOL: lost-password-from "new-password" value >>encoded-password users update-user - "recover-4" login-template + URL" $login/recover-4" ] [ <400> ] if* ] >>submit ; +: ( -- action ) + + "$login/recover-4" >>template ; + ! ! ! Logout : ( -- action ) @@ -294,7 +297,7 @@ C: protected : show-login-page ( -- response ) begin-flow - "$login/login" f ; + URL" $login/login" ; : check-capabilities ( responder user -- ? ) [ capabilities>> ] bi@ subset? ; @@ -317,7 +320,7 @@ M: login call-responder* ( path responder -- response ) : ( responder -- responder' ) - "boilerplate" login-template >>template ; + "$login/boilerplate" >>template ; : ( responder -- auth ) login new-dispatcher @@ -340,8 +343,12 @@ M: login call-responder* ( path responder -- response ) : allow-password-recovery ( login -- login ) "recover-password" add-responder + + "recover-2" add-responder - "new-password" add-responder ; + "recover-3" add-responder + + "recover-4" add-responder ; : allow-edit-profile? ( -- ? ) login get responders>> "edit-profile" swap key? ; diff --git a/extra/http/server/auth/login/login.xml b/extra/furnace/auth/login/login.xml similarity index 100% rename from extra/http/server/auth/login/login.xml rename to extra/furnace/auth/login/login.xml diff --git a/extra/http/server/auth/login/recover-1.xml b/extra/furnace/auth/login/recover-1.xml similarity index 100% rename from extra/http/server/auth/login/recover-1.xml rename to extra/furnace/auth/login/recover-1.xml diff --git a/extra/http/server/auth/login/recover-2.xml b/extra/furnace/auth/login/recover-2.xml similarity index 100% rename from extra/http/server/auth/login/recover-2.xml rename to extra/furnace/auth/login/recover-2.xml diff --git a/extra/http/server/auth/login/recover-3.xml b/extra/furnace/auth/login/recover-3.xml similarity index 100% rename from extra/http/server/auth/login/recover-3.xml rename to extra/furnace/auth/login/recover-3.xml diff --git a/extra/http/server/auth/login/recover-4.xml b/extra/furnace/auth/login/recover-4.xml similarity index 100% rename from extra/http/server/auth/login/recover-4.xml rename to extra/furnace/auth/login/recover-4.xml diff --git a/extra/http/server/auth/login/register.xml b/extra/furnace/auth/login/register.xml similarity index 100% rename from extra/http/server/auth/login/register.xml rename to extra/furnace/auth/login/register.xml diff --git a/extra/http/server/auth/providers/assoc/assoc-tests.factor b/extra/furnace/auth/providers/assoc/assoc-tests.factor similarity index 79% rename from extra/http/server/auth/providers/assoc/assoc-tests.factor rename to extra/furnace/auth/providers/assoc/assoc-tests.factor index 91e802b91c..8f9eeaa7a5 100755 --- a/extra/http/server/auth/providers/assoc/assoc-tests.factor +++ b/extra/furnace/auth/providers/assoc/assoc-tests.factor @@ -1,6 +1,6 @@ -IN: http.server.auth.providers.assoc.tests -USING: http.server.actions http.server.auth.providers -http.server.auth.providers.assoc http.server.auth.login +IN: furnace.auth.providers.assoc.tests +USING: furnace.actions furnace.auth.providers +furnace.auth.providers.assoc furnace.auth.login tools.test namespaces accessors kernel ; diff --git a/extra/http/server/auth/providers/assoc/assoc.factor b/extra/furnace/auth/providers/assoc/assoc.factor similarity index 80% rename from extra/http/server/auth/providers/assoc/assoc.factor rename to extra/furnace/auth/providers/assoc/assoc.factor index d6ba587aa0..f5a79d701b 100755 --- a/extra/http/server/auth/providers/assoc/assoc.factor +++ b/extra/furnace/auth/providers/assoc/assoc.factor @@ -1,8 +1,7 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -IN: http.server.auth.providers.assoc -USING: accessors assocs kernel -http.server.auth.providers ; +IN: furnace.auth.providers.assoc +USING: accessors assocs kernel furnace.auth.providers ; TUPLE: users-in-memory assoc ; diff --git a/extra/http/server/auth/providers/db/db-tests.factor b/extra/furnace/auth/providers/db/db-tests.factor similarity index 83% rename from extra/http/server/auth/providers/db/db-tests.factor rename to extra/furnace/auth/providers/db/db-tests.factor index a6a92356b6..714dcb416f 100755 --- a/extra/http/server/auth/providers/db/db-tests.factor +++ b/extra/furnace/auth/providers/db/db-tests.factor @@ -1,8 +1,8 @@ -IN: http.server.auth.providers.db.tests -USING: http.server.actions -http.server.auth.login -http.server.auth.providers -http.server.auth.providers.db tools.test +IN: furnace.auth.providers.db.tests +USING: furnace.actions +furnace.auth.login +furnace.auth.providers +furnace.auth.providers.db tools.test namespaces db db.sqlite db.tuples continuations io.files accessors kernel ; diff --git a/extra/http/server/auth/providers/db/db.factor b/extra/furnace/auth/providers/db/db.factor similarity index 92% rename from extra/http/server/auth/providers/db/db.factor rename to extra/furnace/auth/providers/db/db.factor index 3ed4845609..90306e5181 100755 --- a/extra/http/server/auth/providers/db/db.factor +++ b/extra/furnace/auth/providers/db/db.factor @@ -1,9 +1,9 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: db db.tuples db.types accessors -http.server.auth.providers kernel continuations +furnace.auth.providers kernel continuations classes.singleton ; -IN: http.server.auth.providers.db +IN: furnace.auth.providers.db user "USERS" { diff --git a/extra/http/server/auth/providers/null/null.factor b/extra/furnace/auth/providers/null/null.factor similarity index 71% rename from extra/http/server/auth/providers/null/null.factor rename to extra/furnace/auth/providers/null/null.factor index 30f6dbd06e..39ea812ae7 100755 --- a/extra/http/server/auth/providers/null/null.factor +++ b/extra/furnace/auth/providers/null/null.factor @@ -1,7 +1,7 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: http.server.auth.providers kernel ; -IN: http.server.auth.providers.null +USING: furnace.auth.providers kernel ; +IN: furnace.auth.providers.null TUPLE: no-users ; diff --git a/extra/http/server/auth/providers/providers.factor b/extra/furnace/auth/providers/providers.factor similarity index 94% rename from extra/http/server/auth/providers/providers.factor rename to extra/furnace/auth/providers/providers.factor index a51c4da1b9..1933fc8c59 100755 --- a/extra/http/server/auth/providers/providers.factor +++ b/extra/furnace/auth/providers/providers.factor @@ -2,7 +2,7 @@ ! See http://factorcode.org/license.txt for BSD license. USING: kernel accessors random math.parser locals sequences math ; -IN: http.server.auth.providers +IN: furnace.auth.providers TUPLE: user username realname diff --git a/extra/http/server/boilerplate/boilerplate.factor b/extra/furnace/boilerplate/boilerplate.factor similarity index 67% rename from extra/http/server/boilerplate/boilerplate.factor rename to extra/furnace/boilerplate/boilerplate.factor index 96c59edd10..ec84ba1391 100644 --- a/extra/http/server/boilerplate/boilerplate.factor +++ b/extra/furnace/boilerplate/boilerplate.factor @@ -1,8 +1,8 @@ ! Copyright (c) 2008 Slava Pestov ! See http://factorcode.org/license.txt for BSD license. USING: accessors kernel namespaces http.server html.templates -locals ; -IN: http.server.boilerplate +html.templates.chloe locals ; +IN: furnace.boilerplate TUPLE: boilerplate < filter-responder template ; @@ -12,6 +12,10 @@ M:: boilerplate call-responder* ( path responder -- ) path responder call-next-method dup content-type>> "text/html" = [ clone [| body | - [ body responder template>> with-boilerplate ] + [ + body + responder template>> resolve-template-path + with-boilerplate + ] ] change-body ] when ; diff --git a/extra/http/server/callbacks/callbacks-tests.factor b/extra/furnace/callbacks/callbacks-tests.factor similarity index 87% rename from extra/http/server/callbacks/callbacks-tests.factor rename to extra/furnace/callbacks/callbacks-tests.factor index 31ea164a58..f72aad3f50 100755 --- a/extra/http/server/callbacks/callbacks-tests.factor +++ b/extra/furnace/callbacks/callbacks-tests.factor @@ -1,5 +1,5 @@ -IN: http.server.callbacks -USING: http.server.actions http.server.callbacks accessors +IN: furnace.callbacks +USING: furnace.actions furnace.callbacks accessors http.server http tools.test namespaces io fry sequences splitting kernel hashtables continuations ; @@ -24,7 +24,7 @@ splitting kernel hashtables continuations ; [ [ "hello" print - '[ , write ] + "text/html" ] show-page "byebye" print [ 123 ] show-final diff --git a/extra/http/server/callbacks/callbacks.factor b/extra/furnace/callbacks/callbacks.factor similarity index 96% rename from extra/http/server/callbacks/callbacks.factor rename to extra/furnace/callbacks/callbacks.factor index 3b819e067b..7b18afe781 100755 --- a/extra/http/server/callbacks/callbacks.factor +++ b/extra/furnace/callbacks/callbacks.factor @@ -4,7 +4,7 @@ USING: http http.server io kernel math namespaces continuations calendar sequences assocs hashtables accessors arrays alarms quotations combinators fry assocs.lib ; -IN: http.server.callbacks +IN: furnace.callbacks SYMBOL: responder diff --git a/extra/furnace/db/db-tests.factor b/extra/furnace/db/db-tests.factor new file mode 100644 index 0000000000..34357ae701 --- /dev/null +++ b/extra/furnace/db/db-tests.factor @@ -0,0 +1,4 @@ +IN: furnace.db.tests +USING: tools.test furnace.db ; + +\ must-infer diff --git a/extra/http/server/db/db.factor b/extra/furnace/db/db.factor similarity index 82% rename from extra/http/server/db/db.factor rename to extra/furnace/db/db.factor index 73d4c35e2c..8d7027073c 100755 --- a/extra/http/server/db/db.factor +++ b/extra/furnace/db/db.factor @@ -1,8 +1,8 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: db db.pools io.pools http.server http.server.sessions +USING: db db.pools io.pools http.server furnace.sessions kernel accessors continuations namespaces destructors ; -IN: http.server.db +IN: furnace.db TUPLE: db-persistence < filter-responder pool ; diff --git a/extra/http/server/flows/flows.factor b/extra/furnace/flows/flows.factor similarity index 53% rename from extra/http/server/flows/flows.factor rename to extra/furnace/flows/flows.factor index 7a9b362111..001335065c 100644 --- a/extra/http/server/flows/flows.factor +++ b/extra/furnace/flows/flows.factor @@ -1,9 +1,10 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: accessors namespaces sequences arrays kernel -assocs assocs.lib hashtables math.parser -html.elements http http.server http.server.sessions ; -IN: http.server.flows +assocs assocs.lib hashtables math.parser urls combinators +html.elements http http.server furnace.sessions +html.templates.chloe.syntax ; +IN: furnace.flows TUPLE: flows < filter-responder ; @@ -11,24 +12,28 @@ C: flows : begin-flow* ( -- id ) request get - [ path>> ] [ request-params ] [ method>> ] tri 3array + [ url>> ] [ post-data>> ] [ method>> ] tri 3array flows sget set-at-unique session-changed ; -: end-flow-post ( path params -- response ) +: end-flow-post ( url post-data -- response ) request [ clone "POST" >>method swap >>post-data - swap >>path + swap >>url ] change - request get path>> split-path + request get url>> path>> split-path flows get responder>> call-responder ; -: end-flow* ( default id -- response ) - flows sget at - [ first3 "POST" = [ end-flow-post ] [ ] if ] - [ f ] ?if ; +: end-flow* ( url id -- response ) + flows sget at [ + first3 { + { "GET" [ drop ] } + { "HEAD" [ drop ] } + { "POST" [ end-flow-post ] } + } case + ] [ ] ?if ; SYMBOL: flow-id @@ -40,10 +45,30 @@ SYMBOL: flow-id : end-flow ( default -- response ) flow-id get end-flow* ; -: add-flow-id ( query -- query' ) +M: flows call-responder* + dup flows set + flow-id-key request get request-params at flow-id set + call-next-method ; + +M: flows init-session* + H{ } clone flows sset + call-next-method ; + +M: flows link-attr ( tag -- ) + drop + "flow" optional-attr { + { "none" [ flow-id off ] } + { "begin" [ begin-flow ] } + { "current" [ ] } + { f [ ] } + } case ; + +M: flows modify-query ( query responder -- query' ) + drop flow-id get [ flow-id-key associate assoc-union ] when* ; -: flow-form-field ( -- ) +M: flows hidden-form-field ( responder -- ) + drop flow-id get [ ] when* ; - -M: flows call-responder* - dup flows set - [ add-flow-id ] add-link-hook - [ flow-form-field ] add-form-hook - flow-id-key request get request-params at flow-id set - call-next-method ; - -M: flows init-session* - H{ } clone flows sset - call-next-method ; diff --git a/extra/furnace/furnace.factor b/extra/furnace/furnace.factor new file mode 100644 index 0000000000..80c9f948ed --- /dev/null +++ b/extra/furnace/furnace.factor @@ -0,0 +1,136 @@ +! Copyright (C) 2003, 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +IN: furnace + +GENERIC: hidden-form-field ( responder -- ) + +M: object hidden-form-field drop ; + +: request-params ( request -- assoc ) + dup method>> { + { "GET" [ url>> query>> ] } + { "HEAD" [ url>> query>> ] } + { "POST" [ post-data>> ] } + } case ; + +: ( body -- response ) + feed>xml "application/atom+xml" ; + +: ( obj -- response ) + >json "application/json" ; + +SYMBOL: exit-continuation + +: exit-with exit-continuation get continue-with ; + +: with-exit-continuation ( quot -- ) + '[ exit-continuation set @ ] callcc1 exit-continuation off ; + +! Chloe tags +: parse-query-attr ( string -- assoc ) + dup empty? + [ drop f ] [ "," split [ dup value ] H{ } map>assoc ] if ; + +CHLOE: atom + [ "title" required-attr ] + [ "href" required-attr ] + [ "query" optional-attr parse-query-attr ] tri + + swap >>query + swap >>path + adjust-url + add-atom-feed ; + +CHLOE: write-atom drop write-atom-feeds ; + +GENERIC: link-attr ( tag responder -- ) + +M: object link-attr 2drop ; + +: link-attrs ( tag -- ) + '[ , _ link-attr ] each-responder ; + +: a-start-tag ( tag -- ) + [ + + swap >>query + swap >>path + adjust-url =href + a> + ] with-scope ; + +CHLOE: a + [ a-start-tag ] + [ process-tag-children ] + [ drop ] + tri ; + +: form-start-tag ( tag -- ) + [ + [ +
+ ] [ + [ hidden-form-field ] each-responder + "for" optional-attr [ hidden render ] when* + ] bi + ] with-scope ; + +CHLOE: form + [ form-start-tag ] + [ process-tag-children ] + [ drop
] + tri ; + +DEFER: process-chloe-tag + +STRING: button-tag-markup + + + +; + +: add-tag-attrs ( attrs tag -- ) + tag-attrs swap update ; + +CHLOE: button + button-tag-markup string>xml delegate + { + [ [ tag-attrs chloe-attrs-only ] dip add-tag-attrs ] + [ [ tag-attrs non-chloe-attrs-only ] dip "button" tag-named add-tag-attrs ] + [ [ children>string 1array ] dip "button" tag-named set-tag-children ] + [ nip ] + } 2cleave process-chloe-tag ; + +: attr>word ( value -- word/f ) + dup ":" split1 swap lookup + [ ] [ "No such word: " swap append throw ] ?if ; + +: attr>var ( value -- word/f ) + attr>word dup symbol? [ + "Must be a symbol: " swap append throw + ] unless ; + +: if-satisfied? ( tag -- ? ) + t swap + { + [ "code" optional-attr [ attr>word execute and ] when* ] + [ "var" optional-attr [ attr>var get and ] when* ] + [ "svar" optional-attr [ attr>var sget and ] when* ] + [ "uvar" optional-attr [ attr>var uget and ] when* ] + [ "value" optional-attr [ value and ] when* ] + } cleave ; + +CHLOE: if dup if-satisfied? [ process-tag-children ] [ drop ] if ; diff --git a/extra/http/server/sessions/authors.txt b/extra/furnace/sessions/authors.txt similarity index 100% rename from extra/http/server/sessions/authors.txt rename to extra/furnace/sessions/authors.txt diff --git a/extra/http/server/sessions/sessions-tests.factor b/extra/furnace/sessions/sessions-tests.factor similarity index 79% rename from extra/http/server/sessions/sessions-tests.factor rename to extra/furnace/sessions/sessions-tests.factor index 8ea312dcb5..949d04d4c3 100755 --- a/extra/http/server/sessions/sessions-tests.factor +++ b/extra/furnace/sessions/sessions-tests.factor @@ -1,8 +1,8 @@ -IN: http.server.sessions.tests -USING: tools.test http http.server.sessions -http.server.actions http.server math namespaces kernel accessors +IN: furnace.sessions.tests +USING: tools.test http furnace.sessions +furnace.actions http.server math namespaces kernel accessors prettyprint io.streams.string io.files splitting destructors -sequences db db.sqlite continuations ; +sequences db db.sqlite continuations urls ; : with-session [ @@ -18,15 +18,16 @@ M: foo init-session* drop 0 "x" sset ; M: foo call-responder* 2drop "x" [ 1+ ] schange - [ "x" sget pprint ] ; + "x" sget number>string "text/html" ; : url-responder-mock-test [ "GET" >>method - "id" get session-id-key set-query-param - "/" >>path - request set + dup url>> + "id" get session-id-key set-query-param + "/" >>path drop + init-request { } sessions get call-responder [ write-response-body drop ] with-string-writer ] with-destructors ; @@ -36,21 +37,21 @@ M: foo call-responder* "GET" >>method "cookies" get >>cookies - "/" >>path - request set + dup url>> "/" >>path drop + init-request { } sessions get call-responder [ write-response-body drop ] with-string-writer ] with-destructors ; : - [ [ ] exit-with ] >>display ; + [ [ ] "text/plain" exit-with ] >>display ; [ "auth-test.db" temp-file sqlite-db delete-file ] ignore-errors "auth-test.db" temp-file sqlite-db [ - init-request + init-request init-sessions-table [ ] [ @@ -112,8 +113,8 @@ M: foo call-responder* [ - "GET" >>method - "/" >>path + "GET" >>method + dup url>> "/" >>path drop request set { "etc" } sessions get call-responder response set [ "1" ] [ [ response get write-response-body drop ] with-string-writer ] unit-test @@ -131,8 +132,9 @@ M: foo call-responder* [ ] [ "GET" >>method - "id" get session-id-key set-query-param - "/" >>path + dup url>> + "id" get session-id-key set-query-param + "/" >>path drop request set [ diff --git a/extra/http/server/sessions/sessions.factor b/extra/furnace/sessions/sessions.factor similarity index 92% rename from extra/http/server/sessions/sessions.factor rename to extra/furnace/sessions/sessions.factor index a7e1a141c4..2b6bf84bdd 100755 --- a/extra/http/server/sessions/sessions.factor +++ b/extra/furnace/sessions/sessions.factor @@ -4,8 +4,8 @@ USING: assocs kernel math.intervals math.parser namespaces random accessors quotations hashtables sequences continuations fry calendar combinators destructors alarms db db.tuples db.types -http http.server html.elements ; -IN: http.server.sessions +http http.server html.elements html.templates.chloe ; +IN: furnace.sessions TUPLE: session id expires uid namespace changed? ; @@ -136,7 +136,8 @@ M: session-saver dispose : put-session-cookie ( response -- response' ) session get id>> number>string put-cookie ; -: session-form-field ( -- ) +M: sessions hidden-form-field ( responder -- ) + drop ; M: sessions call-responder* ( path responder -- response ) - [ session-form-field ] add-form-hook sessions set request-session [ begin-session ] unless* existing-session put-session-cookie ; : logout-all-sessions ( uid -- ) session new swap >>uid delete-tuples ; + +M: sessions link-attr + drop + "session" optional-attr { + { "none" [ session off flow-id off ] } + { "current" [ ] } + { f [ ] } + } case ; diff --git a/extra/html/components/components-tests.factor b/extra/html/components/components-tests.factor index 1a0f849a8f..90dc156ea6 100644 --- a/extra/html/components/components-tests.factor +++ b/extra/html/components/components-tests.factor @@ -11,7 +11,7 @@ html.components namespaces ; TUPLE: color red green blue ; -[ ] [ 1 2 3 color boa from-tuple ] unit-test +[ ] [ 1 2 3 color boa from-object ] unit-test [ 1 ] [ "red" value ] unit-test @@ -107,7 +107,7 @@ TUPLE: color red green blue ; [ ] [ t "delivery" set-value ] unit-test -[ "Delivery" ] [ +[ "Delivery" ] [ [ "delivery" diff --git a/extra/html/components/components.factor b/extra/html/components/components.factor index efac730af6..c013007a14 100644 --- a/extra/html/components/components.factor +++ b/extra/html/components/components.factor @@ -5,7 +5,7 @@ classes.tuple words arrays sequences sequences.lib splitting mirrors hashtables combinators continuations math strings fry locals calendar calendar.format xml.entities validators html.elements html.streams xmode.code2html farkup inspector -lcs.diff2html ; +lcs.diff2html urls ; IN: html.components SYMBOL: values @@ -19,9 +19,9 @@ SYMBOL: values : prepare-value ( name object -- value name object ) [ [ value ] keep ] dip ; inline -: from-assoc ( assoc -- ) values get swap update ; - -: from-tuple ( tuple -- ) from-assoc ; +: from-object ( object -- ) + dup assoc? [ ] unless + values get swap update ; : deposit-values ( destination names -- ) [ dup value ] H{ } map>assoc update ; @@ -32,24 +32,19 @@ SYMBOL: values : with-each-index ( seq quot -- ) '[ [ - blank-values 1+ "index" set-value @ + values [ clone ] change + 1+ "index" set-value @ ] with-scope ] each-index ; inline : with-each-value ( seq quot -- ) '[ "value" set-value @ ] with-each-index ; inline -: with-each-assoc ( seq quot -- ) - '[ from-assoc @ ] with-each-index ; inline +: with-each-object ( seq quot -- ) + '[ from-object @ ] with-each-index ; inline -: with-each-tuple ( seq quot -- ) - '[ from-tuple @ ] with-each-index ; inline - -: with-assoc-values ( assoc quot -- ) - '[ blank-values , from-assoc @ ] with-scope ; inline - -: with-tuple-values ( assoc quot -- ) - '[ blank-values , from-tuple @ ] with-scope ; inline +: with-values ( object quot -- ) + '[ blank-values , from-object @ ] with-scope ; inline : nest-values ( name quot -- ) swap [ @@ -58,22 +53,6 @@ SYMBOL: values ] with-scope ] dip set-value ; inline -: nest-tuple ( name quot -- ) - swap [ - [ - H{ } clone [ values set call ] keep - ] with-scope - ] dip set-value ; inline - -: object>string ( object -- string ) - { - { [ dup real? ] [ number>string ] } - { [ dup timestamp? ] [ timestamp>string ] } - { [ dup string? ] [ ] } - { [ dup word? ] [ word-name ] } - { [ dup not ] [ drop "" ] } - } cond ; - GENERIC: render* ( value name render -- ) : render ( name renderer -- ) @@ -174,7 +153,7 @@ M: checkbox render* label>> escape-string write ; diff --git a/extra/html/elements/elements.factor b/extra/html/elements/elements.factor index e5377cedf8..2b4920d462 100644 --- a/extra/html/elements/elements.factor +++ b/extra/html/elements/elements.factor @@ -4,7 +4,8 @@ ! See http://factorcode.org/license.txt for BSD license. USING: io kernel namespaces prettyprint quotations -sequences strings words xml.entities compiler.units effects ; +sequences strings words xml.entities compiler.units effects +urls math math.parser combinators calendar calendar.format ; IN: html.elements @@ -126,11 +127,22 @@ SYMBOL: html dup def-for-html-word- ; +: object>string ( object -- string ) + #! Should this be generic and in the core? + { + { [ dup real? ] [ number>string ] } + { [ dup timestamp? ] [ timestamp>string ] } + { [ dup url? ] [ url>string ] } + { [ dup string? ] [ ] } + { [ dup word? ] [ word-name ] } + { [ dup not ] [ drop "" ] } + } cond ; + : write-attr ( value name -- ) " " write-html write-html "='" write-html - escape-quoted-string write-html + object>string escape-quoted-string write-html "'" write-html ; : attribute-effect T{ effect f { "string" } 0 } ; @@ -162,7 +174,7 @@ SYMBOL: html "id" "onclick" "style" "valign" "accesskey" "src" "language" "colspan" "onchange" "rel" "width" "selected" "onsubmit" "xmlns" "lang" "xml:lang" - "media" "title" "multiple" + "media" "title" "multiple" "checked" ] [ define-attribute-word ] each >> diff --git a/extra/html/templates/chloe/chloe-tests.factor b/extra/html/templates/chloe/chloe-tests.factor index eaa0f0dc3d..6fb4429ea6 100644 --- a/extra/html/templates/chloe/chloe-tests.factor +++ b/extra/html/templates/chloe/chloe-tests.factor @@ -27,8 +27,7 @@ IN: html.templates.chloe.tests : test-template ( name -- template ) "resource:extra/html/templates/chloe/test/" - swap - ".xml" 3append ; + prepend ; [ "Hello world" ] [ [ @@ -156,6 +155,14 @@ TUPLE: person first-name last-name ; [ "
RBaxterUnknown
DougColeman
" ] [ [ - "test11" test-template call-template + "test10" test-template call-template ] run-template [ blank? not ] filter ] unit-test + +[ ] [ 1 "id" set-value ] unit-test + +[ "Hello" ] [ + [ + "test11" test-template call-template + ] run-template +] unit-test diff --git a/extra/html/templates/chloe/chloe.factor b/extra/html/templates/chloe/chloe.factor index 092f79bb36..93afa44d81 100644 --- a/extra/html/templates/chloe/chloe.factor +++ b/extra/html/templates/chloe/chloe.factor @@ -3,16 +3,12 @@ USING: accessors kernel sequences combinators kernel namespaces classes.tuple assocs splitting words arrays memoize io io.files io.encodings.utf8 io.streams.string -unicode.case tuple-syntax mirrors fry math +unicode.case tuple-syntax mirrors fry math urls multiline xml xml.data xml.writer xml.utilities html.elements html.components html.templates -http.server -http.server.auth -http.server.flows -http.server.actions -http.server.sessions ; +html.templates.chloe.syntax ; IN: html.templates.chloe ! Chloe is Ed's favorite web designer @@ -23,8 +19,6 @@ C: chloe DEFER: process-template -: chloe-ns "http://factorcode.org/chloe/1.0" ; inline - : chloe-attrs-only ( assoc -- assoc' ) [ drop name-url chloe-ns = ] assoc-filter ; @@ -38,35 +32,22 @@ DEFER: process-template [ t ] } cond nip ; -SYMBOL: tags - -MEMO: chloe-name ( string -- name ) - name new - swap >>tag - chloe-ns >>url ; - -: required-attr ( tag name -- value ) - dup chloe-name rot at* - [ nip ] [ drop " attribute is required" append throw ] if ; - -: optional-attr ( tag name -- value ) - chloe-name swap at ; - : process-tag-children ( tag -- ) [ process-template ] each ; +CHLOE: chloe process-tag-children ; + : children>string ( tag -- string ) [ process-tag-children ] with-string-writer ; -: title-tag ( tag -- ) - children>string set-title ; +CHLOE: title children>string set-title ; -: write-title-tag ( tag -- ) +CHLOE: write-title drop "head" tags get member? "title" tags get member? not and [ write-title ] [ write-title ] if ; -: style-tag ( tag -- ) +CHLOE: style dup "include" optional-attr dup [ swap children>string empty? [ "style tag cannot have both an include attribute and a body" throw @@ -76,146 +57,12 @@ MEMO: chloe-name ( string -- name ) drop children>string ] if add-style ; -: write-style-tag ( tag -- ) +CHLOE: write-style drop ; -: atom-tag ( tag -- ) - [ "title" required-attr ] - [ "href" required-attr ] - bi set-atom-feed ; +CHLOE: even "index" value even? [ process-tag-children ] [ drop ] if ; -: write-atom-tag ( tag -- ) - drop - "head" tags get member? [ - write-atom-feed - ] [ - atom-feed get value>> second write - ] if ; - -: parse-query-attr ( string -- assoc ) - dup empty? - [ drop f ] [ "," split [ dup value ] H{ } map>assoc ] if ; - -: flow-attr ( tag -- ) - "flow" optional-attr { - { "none" [ flow-id off ] } - { "begin" [ begin-flow ] } - { "current" [ ] } - { f [ ] } - } case ; - -: session-attr ( tag -- ) - "session" optional-attr { - { "none" [ session off flow-id off ] } - { "current" [ ] } - { f [ ] } - } case ; - -: a-start-tag ( tag -- ) - [ - string =href - a> - ] with-scope ; - -: a-tag ( tag -- ) - [ a-start-tag ] - [ process-tag-children ] - [ drop ] - tri ; - -: form-start-tag ( tag -- ) - [ - [ -
- ] [ - hidden-form-field - "for" optional-attr [ hidden render ] when* - ] bi - ] with-scope ; - -: form-tag ( tag -- ) - [ form-start-tag ] - [ process-tag-children ] - [ drop
] - tri ; - -DEFER: process-chloe-tag - -STRING: button-tag-markup - - - -; - -: add-tag-attrs ( attrs tag -- ) - tag-attrs swap update ; - -: button-tag ( tag -- ) - button-tag-markup string>xml delegate - { - [ [ tag-attrs chloe-attrs-only ] dip add-tag-attrs ] - [ [ tag-attrs non-chloe-attrs-only ] dip "button" tag-named add-tag-attrs ] - [ [ children>string 1array ] dip "button" tag-named set-tag-children ] - [ nip ] - } 2cleave process-chloe-tag ; - -: attr>word ( value -- word/f ) - dup ":" split1 swap lookup - [ ] [ "No such word: " swap append throw ] ?if ; - -: attr>var ( value -- word/f ) - attr>word dup symbol? [ - "Must be a symbol: " swap append throw - ] unless ; - -: if-satisfied? ( tag -- ? ) - t swap - { - [ "code" optional-attr [ attr>word execute and ] when* ] - [ "var" optional-attr [ attr>var get and ] when* ] - [ "svar" optional-attr [ attr>var sget and ] when* ] - [ "uvar" optional-attr [ attr>var uget and ] when* ] - [ "value" optional-attr [ value and ] when* ] - } cleave ; - -: if-tag ( tag -- ) - dup if-satisfied? [ process-tag-children ] [ drop ] if ; - -: even-tag ( tag -- ) - "index" value even? [ process-tag-children ] [ drop ] if ; - -: odd-tag ( tag -- ) - "index" value odd? [ process-tag-children ] [ drop ] if ; - -: (each-tag) ( tag quot -- ) - [ - [ "values" required-attr value ] keep - '[ , process-tag-children ] - ] dip call ; inline - -: each-tag ( tag -- ) - [ with-each-value ] (each-tag) ; - -: each-tuple-tag ( tag -- ) - [ with-each-tuple ] (each-tag) ; - -: each-assoc-tag ( tag -- ) - [ with-each-assoc ] (each-tag) ; +CHLOE: odd "index" value odd? [ process-tag-children ] [ drop ] if ; : (bind-tag) ( tag quot -- ) [ @@ -223,83 +70,36 @@ STRING: button-tag-markup '[ , process-tag-children ] ] dip call ; inline -: bind-tuple-tag ( tag -- ) - [ with-tuple-values ] (bind-tag) ; +CHLOE: each [ with-each-value ] (bind-tag) ; -: bind-assoc-tag ( tag -- ) - [ with-assoc-values ] (bind-tag) ; +CHLOE: bind-each [ with-each-object ] (bind-tag) ; + +CHLOE: bind [ with-values ] (bind-tag) ; : error-message-tag ( tag -- ) children>string render-error ; -: validation-messages-tag ( tag -- ) - drop render-validation-messages ; +CHLOE: comment drop ; -: singleton-component-tag ( tag class -- ) - [ "name" required-attr ] dip render ; +CHLOE: call-next-template drop call-next-template ; -: attrs>slots ( tag tuple -- ) - [ attrs>> ] [ ] bi* - '[ - swap tag>> dup "name" = - [ 2drop ] [ , set-at ] if - ] assoc-each ; +CHLOE-SINGLETON: label +CHLOE-SINGLETON: link +CHLOE-SINGLETON: farkup +CHLOE-SINGLETON: inspector +CHLOE-SINGLETON: comparison +CHLOE-SINGLETON: html +CHLOE-SINGLETON: hidden -: tuple-component-tag ( tag class -- ) - [ drop "name" required-attr ] - [ new [ attrs>slots ] keep ] - 2bi render ; +CHLOE-TUPLE: field +CHLOE-TUPLE: password +CHLOE-TUPLE: choice +CHLOE-TUPLE: checkbox +CHLOE-TUPLE: code : process-chloe-tag ( tag -- ) - dup name-tag { - { "chloe" [ process-tag-children ] } - - ! HTML head - { "title" [ title-tag ] } - { "write-title" [ write-title-tag ] } - { "style" [ style-tag ] } - { "write-style" [ write-style-tag ] } - { "atom" [ atom-tag ] } - { "write-atom" [ write-atom-tag ] } - - ! HTML elements - { "a" [ a-tag ] } - { "button" [ button-tag ] } - - ! Components - { "label" [ label singleton-component-tag ] } - { "link" [ link singleton-component-tag ] } - { "code" [ code tuple-component-tag ] } - { "farkup" [ farkup singleton-component-tag ] } - { "inspector" [ inspector singleton-component-tag ] } - { "comparison" [ comparison singleton-component-tag ] } - { "html" [ html singleton-component-tag ] } - - ! Forms - { "form" [ form-tag ] } - { "error-message" [ error-message-tag ] } - { "validation-messages" [ validation-messages-tag ] } - { "hidden" [ hidden singleton-component-tag ] } - { "field" [ field tuple-component-tag ] } - { "password" [ password tuple-component-tag ] } - { "textarea" [ textarea tuple-component-tag ] } - { "choice" [ choice tuple-component-tag ] } - { "checkbox" [ checkbox tuple-component-tag ] } - - ! Control flow - { "if" [ if-tag ] } - { "even" [ even-tag ] } - { "odd" [ odd-tag ] } - { "each" [ each-tag ] } - { "each-assoc" [ each-assoc-tag ] } - { "each-tuple" [ each-tuple-tag ] } - { "bind-assoc" [ bind-assoc-tag ] } - { "bind-tuple" [ bind-tuple-tag ] } - { "comment" [ drop ] } - { "call-next-template" [ drop call-next-template ] } - - [ "Unknown chloe tag: " prepend throw ] - } case ; + dup name-tag tags get at + [ call ] [ "Unknown chloe tag: " prepend throw ] ?if ; : process-tag ( tag -- ) { @@ -310,7 +110,15 @@ STRING: button-tag-markup [ drop tags get pop* ] } cleave ; +: expand-attrs ( tag -- tag ) + dup [ tag? ] is? [ + clone [ + [ "@" ?head [ value object>string ] when ] assoc-map + ] change-attrs + ] when ; + : process-template ( xml -- ) + expand-attrs { { [ dup [ chloe-tag? ] is? ] [ process-chloe-tag ] } { [ dup [ tag? ] is? ] [ process-tag ] } @@ -334,6 +142,6 @@ STRING: button-tag-markup ] with-scope ; M: chloe call-template* - path>> utf8 read-xml process-chloe ; + path>> ".xml" append utf8 read-xml process-chloe ; INSTANCE: chloe template diff --git a/extra/html/templates/chloe/syntax/syntax.factor b/extra/html/templates/chloe/syntax/syntax.factor new file mode 100644 index 0000000000..d30ddb9168 --- /dev/null +++ b/extra/html/templates/chloe/syntax/syntax.factor @@ -0,0 +1,58 @@ +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +IN: html.templates.chloe.syntax +USING: accessors kernel sequences combinators kernel namespaces +classes.tuple assocs splitting words arrays memoize parser +io io.files io.encodings.utf8 io.streams.string +unicode.case tuple-syntax mirrors fry math urls +multiline xml xml.data xml.writer xml.utilities +html.elements +html.components +html.templates ; + +SYMBOL: tags + +tags global [ H{ } clone or ] change-at + +: define-chloe-tag ( name quot -- ) tags get set-at ; + +: CHLOE: + scan parse-definition swap define-chloe-tag ; + parsing + +: chloe-ns "http://factorcode.org/chloe/1.0" ; inline + +MEMO: chloe-name ( string -- name ) + name new + swap >>tag + chloe-ns >>url ; + +: required-attr ( tag name -- value ) + dup chloe-name rot at* + [ nip ] [ drop " attribute is required" append throw ] if ; + +: optional-attr ( tag name -- value ) + chloe-name swap at ; + +: singleton-component-tag ( tag class -- ) + [ "name" required-attr ] dip render ; + +: CHLOE-SINGLETON: + scan dup '[ , singleton-component-tag ] define-chloe-tag ; + parsing + +: attrs>slots ( tag tuple -- ) + [ attrs>> ] [ ] bi* + '[ + swap tag>> dup "name" = + [ 2drop ] [ , set-at ] if + ] assoc-each ; + +: tuple-component-tag ( tag class -- ) + [ drop "name" required-attr ] + [ new [ attrs>slots ] keep ] + 2bi render ; + +: CHLOE-TUPLE: + scan dup '[ , tuple-component-tag ] define-chloe-tag ; + parsing diff --git a/extra/html/templates/chloe/test/test10.xml b/extra/html/templates/chloe/test/test10.xml index afded9366f..fd4a64ad0a 100644 --- a/extra/html/templates/chloe/test/test10.xml +++ b/extra/html/templates/chloe/test/test10.xml @@ -3,12 +3,12 @@ - + - +
diff --git a/extra/html/templates/chloe/test/test11.xml b/extra/html/templates/chloe/test/test11.xml index 17e31b1a59..a9b2769445 100644 --- a/extra/html/templates/chloe/test/test11.xml +++ b/extra/html/templates/chloe/test/test11.xml @@ -1,14 +1,3 @@ - - - - - - - - - -
- -
+Hello diff --git a/extra/html/templates/chloe/test/test9.xml b/extra/html/templates/chloe/test/test9.xml index bcfc468738..6166c800ed 100644 --- a/extra/html/templates/chloe/test/test9.xml +++ b/extra/html/templates/chloe/test/test9.xml @@ -3,7 +3,7 @@
    - +
diff --git a/extra/html/templates/templates.factor b/extra/html/templates/templates.factor index 580af58ecc..de774f0864 100644 --- a/extra/html/templates/templates.factor +++ b/extra/html/templates/templates.factor @@ -2,7 +2,8 @@ ! See http://factorcode.org/license.txt for BSD license. USING: accessors kernel fry io io.encodings.utf8 io.files debugger prettyprint continuations namespaces boxes sequences -arrays strings html.elements io.streams.string quotations ; +arrays strings html.elements io.streams.string +quotations xml.data xml.writer ; IN: html.templates MIXIN: template @@ -13,6 +14,8 @@ M: string call-template* write ; M: callable call-template* call ; +M: xml call-template* write-xml ; + M: object call-template* output-stream get stream-copy ; ERROR: template-error template error ; @@ -43,17 +46,17 @@ SYMBOL: style : write-style ( -- ) style get >string write ; -SYMBOL: atom-feed +SYMBOL: atom-feeds -: set-atom-feed ( title url -- ) - 2array atom-feed get >box ; +: add-atom-feed ( title url -- ) + 2array atom-feeds get push ; -: write-atom-feed ( -- ) - atom-feed get value>> [ +: write-atom-feeds ( -- ) + atom-feeds get [ - ] when* ; + ] each ; SYMBOL: nested-template? @@ -66,9 +69,9 @@ M: f call-template* drop call-next-template ; : with-boilerplate ( body template -- ) [ - title get [ title set ] unless - atom-feed get [ atom-feed set ] unless - style get [ SBUF" " clone style set ] unless + title [ or ] change + style [ SBUF" " clone or ] change + atom-feeds [ V{ } like ] change [ [ diff --git a/extra/http/client/client-tests.factor b/extra/http/client/client-tests.factor index db90f746ac..7ce066f0d7 100755 --- a/extra/http/client/client-tests.factor +++ b/extra/http/client/client-tests.factor @@ -1,5 +1,5 @@ USING: http.client http.client.private http tools.test -tuple-syntax namespaces ; +tuple-syntax namespaces urls ; [ "localhost" f ] [ "localhost" parse-host ] unit-test [ "localhost" 8888 ] [ "localhost:8888" parse-host ] unit-test @@ -10,11 +10,8 @@ tuple-syntax namespaces ; [ TUPLE{ request - protocol: http + url: TUPLE{ url protocol: "http" host: "www.apple.com" port: 80 path: "/index.html" query: H{ } } method: "GET" - host: "www.apple.com" - port: 80 - path: "/index.html" version: "1.1" cookies: V{ } header: H{ { "connection" "close" } { "user-agent" "Factor http.client vocabulary" } } @@ -28,11 +25,8 @@ tuple-syntax namespaces ; [ TUPLE{ request - protocol: https + url: TUPLE{ url protocol: "https" host: "www.amazon.com" port: 443 path: "/index.html" query: H{ } } method: "GET" - host: "www.amazon.com" - port: 443 - path: "/index.html" version: "1.1" cookies: V{ } header: H{ { "connection" "close" } { "user-agent" "Factor http.client vocabulary" } } diff --git a/extra/http/client/client.factor b/extra/http/client/client.factor index 7b156a4b9b..9fd5f15d6a 100755 --- a/extra/http/client/client.factor +++ b/extra/http/client/client.factor @@ -27,8 +27,7 @@ SYMBOL: redirects redirects inc redirects get max-redirects < [ request get - swap "location" header dup absolute-url? - [ request-with-url ] [ request-with-path ] if + swap "location" header request-with-url "GET" >>method http-request ] [ too-many-redirects @@ -51,7 +50,7 @@ PRIVATE> : http-request ( request -- response data ) dup request [ - dup request-addr latin1 [ + dup url>> url-addr latin1 [ 1 minutes timeouts write-request read-response diff --git a/extra/http/http-tests.factor b/extra/http/http-tests.factor index 151d1ce84f..5a11814f09 100755 --- a/extra/http/http-tests.factor +++ b/extra/http/http-tests.factor @@ -1,37 +1,13 @@ USING: http tools.test multiline tuple-syntax io.streams.string kernel arrays splitting sequences -assocs io.sockets db db.sqlite continuations ; +assocs io.sockets db db.sqlite continuations urls ; IN: http.tests -[ "hello%20world" ] [ "hello world" url-encode ] unit-test -[ "hello world" ] [ "hello%20world" url-decode ] unit-test -[ "~hello world" ] [ "%7ehello+world" url-decode ] unit-test -[ f ] [ "%XX%XX%XX" url-decode ] unit-test -[ f ] [ "%XX%XX%X" url-decode ] unit-test - -[ "hello world" ] [ "hello+world" url-decode ] unit-test -[ "hello world" ] [ "hello%20world" url-decode ] unit-test -[ " ! " ] [ "%20%21%20" url-decode ] unit-test -[ "hello world" ] [ "hello world%" url-decode ] unit-test -[ "hello world" ] [ "hello world%x" url-decode ] unit-test -[ "hello%20world" ] [ "hello world" url-encode ] unit-test -[ "%20%21%20" ] [ " ! " url-encode ] unit-test - -[ "\u001234hi\u002045" ] [ "\u001234hi\u002045" url-encode url-decode ] unit-test - [ "/" ] [ "http://foo.com" url>path ] unit-test [ "/" ] [ "http://foo.com/" url>path ] unit-test [ "/bar" ] [ "http://foo.com/bar" url>path ] unit-test [ "/bar" ] [ "/bar" url>path ] unit-test -[ "a=b&a=c" ] [ { { "a" { "b" "c" } } } assoc>query ] unit-test - -[ H{ { "a" "b" } } ] [ "a=b" query>assoc ] unit-test - -[ H{ { "a" { "b" "c" } } } ] [ "a=b&a=c" query>assoc ] unit-test - -[ "a=3" ] [ { { "a" 3 } } assoc>query ] unit-test - : lf>crlf "\n" split "\r\n" join ; STRING: read-request-test-1 @@ -45,11 +21,8 @@ blah [ TUPLE{ request - protocol: http - port: 80 + url: TUPLE{ url protocol: "http" port: 80 path: "/bar" } method: "GET" - path: "/bar" - query: H{ } version: "1.1" header: H{ { "some-header" "1; 2" } { "content-length" "4" } } post-data: "blah" @@ -85,14 +58,10 @@ Host: www.sex.com [ TUPLE{ request - protocol: http - port: 80 + url: TUPLE{ url protocol: "http" port: 80 host: "www.sex.com" path: "/bar" } method: "HEAD" - path: "/bar" - query: H{ } version: "1.1" header: H{ { "host" "www.sex.com" } } - host: "www.sex.com" cookies: V{ } } ] [ @@ -101,6 +70,15 @@ Host: www.sex.com ] with-string-reader ] unit-test +STRING: read-request-test-3 +GET nested HTTP/1.0 + +; + +[ read-request-test-3 [ read-request ] with-string-reader ] +[ "Bad request: URL" = ] +must-fail-with + STRING: read-response-test-1 HTTP/1.1 404 not found Content-Type: text/html; charset=UTF8 @@ -145,14 +123,14 @@ read-response-test-1' 1array [ ] unit-test ! Live-fire exercise -USING: http.server http.server.static http.server.sessions -http.server.actions http.server.auth.login http.server.db http.client +USING: http.server http.server.static furnace.sessions +furnace.actions furnace.auth.login furnace.db http.client io.server io.files io io.encodings.ascii accessors namespaces threads ; : add-quit-action - [ stop-server [ "Goodbye" write ] ] >>display + [ stop-server "Goodbye" "text/html" ] >>display "quit" add-responder ; : test-db "test.db" temp-file sqlite-db ; @@ -171,7 +149,7 @@ test-db [ "resource:extra/http/test" >>default "nested" add-responder - [ "redirect-loop" f ] >>display + [ URL" redirect-loop" ] >>display "redirect-loop" add-responder main-responder set @@ -186,16 +164,6 @@ test-db [ "http://localhost:1237/nested/foo.html" http-get = ] unit-test -! Try with a slightly malformed request -[ t ] [ - "localhost" 1237 ascii [ - "GET nested HTTP/1.0\r\n" write flush - "\r\n" write flush - read-crlf drop - read-header - ] with-client "location" swap at "/" head? -] unit-test - [ "http://localhost:1237/redirect-loop" http-get ] [ too-many-redirects? ] must-fail-with @@ -237,7 +205,7 @@ test-db [ [ ] [ [ - [ [ "Hi" write ] ] >>display + [ [ "Hi" write ] "text/plain" ] >>display "" add-responder diff --git a/extra/http/http.factor b/extra/http/http.factor index 89c8f62d5c..a4e6451044 100755 --- a/extra/http/http.factor +++ b/extra/http/http.factor @@ -7,88 +7,31 @@ strings vectors hashtables quotations arrays byte-arrays math.parser calendar calendar.format io io.streams.string io.encodings.utf8 io.encodings.string -io.sockets io.sockets.secure +io.sockets io.sockets.secure io.server unicode.case unicode.categories qualified -html.templates ; +urls html.templates ; EXCLUDE: fry => , ; IN: http -SINGLETON: http +: secure-protocol? ( protocol -- ? ) + "https" = ; -SINGLETON: https +: url-addr ( url -- addr ) + [ [ host>> ] [ port>> ] bi ] [ protocol>> ] bi + secure-protocol? [ ] when ; -GENERIC: http-port ( protocol -- port ) - -M: http http-port drop 80 ; - -M: https http-port drop 443 ; - -GENERIC: protocol>string ( protocol -- string ) - -M: http protocol>string drop "http" ; - -M: https protocol>string drop "https" ; - -: string>protocol ( string -- protocol ) +: protocol-port ( protocol -- port ) { - { "http" [ http ] } - { "https" [ https ] } - [ "Unknown protocol: " swap append throw ] + { "http" [ 80 ] } + { "https" [ 443 ] } } case ; -: absolute-url? ( url -- ? ) - [ "http://" head? ] [ "https://" head? ] bi or ; - -: url-quotable? ( ch -- ? ) - #! In a URL, can this character be used without - #! URL-encoding? - { - { [ dup letter? ] [ t ] } - { [ dup LETTER? ] [ t ] } - { [ dup digit? ] [ t ] } - { [ dup "/_-.:" member? ] [ t ] } - [ f ] - } cond nip ; foldable - -: push-utf8 ( ch -- ) - 1string utf8 encode - [ CHAR: % , >hex 2 CHAR: 0 pad-left % ] each ; - -: url-encode ( str -- str ) - [ - [ dup url-quotable? [ , ] [ push-utf8 ] if ] each - ] "" make ; - -: url-decode-hex ( index str -- ) - 2dup length 2 - >= [ - 2drop - ] [ - [ 1+ dup 2 + ] dip subseq hex> [ , ] when* - ] if ; - -: url-decode-% ( index str -- index str ) - 2dup url-decode-hex [ 3 + ] dip ; - -: url-decode-+-or-other ( index str ch -- index str ) - dup CHAR: + = [ drop CHAR: \s ] when , [ 1+ ] dip ; - -: url-decode-iter ( index str -- ) - 2dup length >= [ - 2drop - ] [ - 2dup nth dup CHAR: % = [ - drop url-decode-% - ] [ - url-decode-+-or-other - ] if url-decode-iter - ] if ; - -: url-decode ( str -- str ) - [ 0 swap url-decode-iter ] "" make utf8 decode ; +: ensure-port ( url -- url' ) + dup protocol>> '[ , protocol-port or ] change-port ; : crlf "\r\n" write ; @@ -130,6 +73,7 @@ M: https protocol>string drop "https" ; { { [ dup number? ] [ number>string ] } { [ dup timestamp? ] [ timestamp>http-string ] } + { [ dup url? ] [ url>string ] } { [ dup string? ] [ ] } { [ dup sequence? ] [ [ header-value>string ] map "; " join ] } } cond ; @@ -145,42 +89,6 @@ M: https protocol>string drop "https" ; header-value>string check-header-string write crlf ] assoc-each crlf ; -: add-query-param ( value key assoc -- ) - [ - at [ - { - { [ dup string? ] [ swap 2array ] } - { [ dup array? ] [ swap suffix ] } - { [ dup not ] [ drop ] } - } cond - ] when* - ] 2keep set-at ; - -: query>assoc ( query -- assoc ) - dup [ - "&" split H{ } clone [ - [ - [ "=" split1 [ dup [ url-decode ] when ] bi@ swap ] dip - add-query-param - ] curry each - ] keep - ] when ; - -: assoc>query ( hash -- str ) - [ - { - { [ dup number? ] [ number>string 1array ] } - { [ dup string? ] [ 1array ] } - { [ dup sequence? ] [ ] } - } cond - ] assoc-map - [ - [ - [ url-encode ] dip - [ url-encode "=" swap 3append , ] with each - ] assoc-each - ] { } make "&" join ; - TUPLE: cookie name value path domain expires max-age http-only ; : ( value name -- cookie ) @@ -236,12 +144,8 @@ TUPLE: cookie name value path domain expires max-age http-only ; [ unparse-cookie ] map concat "; " join ; TUPLE: request -protocol -host -port method -path -query +url version header post-data @@ -254,19 +158,15 @@ cookies ; : request new "1.1" >>version - http >>protocol + + "http" >>protocol + H{ } clone >>query + >>url H{ } clone >>header - H{ } clone >>query V{ } clone >>cookies "close" "connection" set-header "Factor http.client vocabulary" "user-agent" set-header ; -: query-param ( request key -- value ) - swap query>> at ; - -: set-query-param ( request value key -- request ) - pick query>> set-at ; - : chop-hostname ( str -- str' ) ":" split1 "//" ?head drop nip CHAR: / over index over length or tail @@ -284,21 +184,17 @@ cookies ; " " read-until [ "Bad request: method" throw ] unless >>method ; -: read-query ( request -- request ) - " " read-until - [ "Bad request: query params" throw ] unless - query>assoc >>query ; +: check-absolute ( url -- url ) + dup path>> "/" head? [ "Bad request: URL" throw ] unless ; inline : read-url ( request -- request ) - " ?" read-until { - { CHAR: \s [ dup empty? [ drop read-url ] [ url>path >>path ] if ] } - { CHAR: ? [ url>path >>path read-query ] } - [ "Bad request: URL" throw ] - } case ; + " " read-until [ + dup empty? [ drop read-url ] [ >url check-absolute >>url ] if + ] [ "Bad request: URL" throw ] if ; : parse-version ( string -- version ) - "HTTP/" ?head [ "Bad version" throw ] unless - dup { "1.0" "1.1" } member? [ "Bad version" throw ] unless ; + "HTTP/" ?head [ "Bad request: version" throw ] unless + dup { "1.0" "1.1" } member? [ "Bad request: version" throw ] unless ; : read-request-version ( request -- request ) read-crlf [ CHAR: \s = ] left-trim @@ -325,13 +221,11 @@ SYMBOL: max-post-request : read-post-data ( request -- request ) dup header>> content-length [ read >>post-data ] when* ; -: parse-host ( string -- host port ) - "." ?tail drop ":" split1 - dup [ string>number ] when ; - : extract-host ( request -- request ) - dup [ "host" header parse-host ] keep protocol>> http-port or - [ >>host ] [ >>port ] bi* ; + [ ] [ url>> ] [ "host" header parse-host ] tri + [ >>host ] [ >>port ] bi* + ensure-port + drop ; : extract-post-data-type ( request -- request ) dup "content-type" header >>post-data-type ; @@ -349,6 +243,9 @@ SYMBOL: max-post-request : parse-content-type ( content-type -- type encoding ) ";" split1 parse-content-type-attributes "charset" swap at ; +: detect-protocol ( request -- request ) + dup url>> remote-address get secure? "https" "http" ? >>protocol drop ; + : read-request ( -- request ) read-method @@ -356,6 +253,7 @@ SYMBOL: max-post-request read-request-version read-request-header read-post-data + detect-protocol extract-host extract-post-data-type parse-post-data @@ -364,15 +262,8 @@ SYMBOL: max-post-request : write-method ( request -- request ) dup method>> write bl ; -: (link>string) ( url query -- url' ) - [ url-encode ] [ assoc>query ] bi* - dup empty? [ drop ] [ "?" swap 3append ] if ; - -: write-url ( request -- ) - [ path>> ] [ query>> ] bi (link>string) write ; - : write-request-url ( request -- request ) - dup write-url bl ; + dup url>> relative-url url>string write bl ; : write-version ( request -- request ) "HTTP/" write dup request-version write crlf ; @@ -383,24 +274,13 @@ SYMBOL: max-post-request "application/x-www-form-urlencoded" >>post-data-type ] if ; -GENERIC: protocol-addr ( request protocol -- addr ) - -M: object protocol-addr - drop [ host>> ] [ port>> ] bi ; - -M: https protocol-addr - call-next-method ; - -: request-addr ( request -- addr ) - dup protocol>> protocol-addr ; - -: request-host ( request -- string ) - [ host>> ] [ port>> ] bi dup http http-port = +: url-host ( url -- string ) + [ host>> ] [ port>> ] bi dup "http" protocol-port = [ drop ] [ ":" swap number>string 3append ] if ; : write-request-header ( request -- request ) dup header>> >hashtable - over host>> [ over request-host "host" pick set-at ] when + over url>> host>> [ over url>> url-host "host" pick set-at ] when over post-data>> [ length "content-length" pick set-at ] when* over post-data-type>> [ "content-type" pick set-at ] when* over cookies>> f like [ unparse-cookies "cookie" pick set-at ] when* @@ -419,38 +299,8 @@ M: https protocol-addr flush drop ; -: request-with-path ( request path -- request ) - [ "/" prepend ] [ "/" ] if* - "?" split1 [ >>path ] [ dup [ query>assoc ] when >>query ] bi* ; - : request-with-url ( request url -- request ) - ":" split1 - [ string>protocol >>protocol ] - [ - "//" ?head [ "Invalid URL" throw ] unless - "/" split1 - [ - parse-host [ >>host ] [ >>port ] bi* - dup protocol>> http-port '[ , or ] change-port - ] - [ request-with-path ] - bi* - ] bi* ; - -: request-url ( request -- url ) - [ - [ - dup host>> [ - [ protocol>> protocol>string write "://" write ] - [ host>> url-encode write ":" write ] - [ [ port>> ] [ protocol>> http-port or ] bi number>string write ] - tri - ] [ drop ] if - ] - [ path>> "/" head? [ "/" write ] unless ] - [ write-url ] - tri - ] with-string-writer ; + '[ , >url derive-url ensure-port ] change-url ; GENERIC: write-response ( response -- ) diff --git a/extra/http/server/cgi/cgi.factor b/extra/http/server/cgi/cgi.factor index 20eb7318d0..a706ee6998 100755 --- a/extra/http/server/cgi/cgi.factor +++ b/extra/http/server/cgi/cgi.factor @@ -14,13 +14,12 @@ IN: http.server.cgi "HTTP/" request get version>> append "SERVER_PROTOCOL" set "Factor" "SERVER_SOFTWARE" set - dup "PATH_TRANSLATED" set - "SCRIPT_FILENAME" set + [ "PATH_TRANSLATED" set ] [ "SCRIPT_FILENAME" set ] bi - request get path>> "SCRIPT_NAME" set + request get url>> path>> "SCRIPT_NAME" set - request get host>> "SERVER_NAME" set - request get port>> number>string "SERVER_PORT" set + request get url>> host>> "SERVER_NAME" set + request get url>> port>> number>string "SERVER_PORT" set "" "PATH_INFO" set "" "REMOTE_HOST" set "" "REMOTE_ADDR" set diff --git a/extra/http/server/db/db-tests.factor b/extra/http/server/db/db-tests.factor deleted file mode 100644 index 0c34745c00..0000000000 --- a/extra/http/server/db/db-tests.factor +++ /dev/null @@ -1,4 +0,0 @@ -IN: http.server.db.tests -USING: tools.test http.server.db ; - -\ must-infer diff --git a/extra/http/server/server-tests.factor b/extra/http/server/server-tests.factor index 0aed425ade..fb1abcc6e0 100755 --- a/extra/http/server/server-tests.factor +++ b/extra/http/server/server-tests.factor @@ -1,27 +1,52 @@ USING: http.server tools.test kernel namespaces accessors -io http math sequences assocs arrays classes words ; +io http math sequences assocs arrays classes words urls ; IN: http.server.tests \ find-responder must-infer [ - http >>protocol - "www.apple.com" >>host - "/xxx/bar" >>path - { { "a" "b" } } >>query + + "http" >>protocol + "www.apple.com" >>host + "/xxx/bar" >>path + { { "a" "b" } } >>query + >>url request set [ ] link-hook set - [ "http://www.apple.com:80/xxx/bar?a=b" ] [ f f derive-url ] unit-test - [ "http://www.apple.com:80/xxx/baz?a=b" ] [ "baz" f derive-url ] unit-test - [ "http://www.apple.com:80/xxx/baz?c=d" ] [ "baz" { { "c" "d" } } derive-url ] unit-test - [ "http://www.apple.com:80/xxx/bar?c=d" ] [ f { { "c" "d" } } derive-url ] unit-test - [ "http://www.apple.com:80/flip?a=b" ] [ "/flip" f derive-url ] unit-test - [ "http://www.apple.com:80/flip?c=d" ] [ "/flip" { { "c" "d" } } derive-url ] unit-test - [ "http://www.jedit.org" ] [ "http://www.jedit.org" f derive-url ] unit-test - [ "http://www.jedit.org?a=b" ] [ "http://www.jedit.org" { { "a" "b" } } derive-url ] unit-test + [ "http://www.apple.com:80/xxx/bar" ] [ + adjust-url url>string + ] unit-test + + [ "http://www.apple.com:80/xxx/baz" ] [ + "baz" >>path adjust-url url>string + ] unit-test + + [ "http://www.apple.com:80/xxx/baz?c=d" ] [ + "baz" >>path { { "c" "d" } } >>query adjust-url url>string + ] unit-test + + [ "http://www.apple.com:80/xxx/bar?c=d" ] [ + { { "c" "d" } } >>query adjust-url url>string + ] unit-test + + [ "http://www.apple.com:80/flip" ] [ + "/flip" >>path adjust-url url>string + ] unit-test + + [ "http://www.apple.com:80/flip?c=d" ] [ + "/flip" >>path { { "c" "d" } } >>query adjust-url url>string + ] unit-test + + [ "http://www.jedit.org:80/" ] [ + "http://www.jedit.org" >url adjust-url url>string + ] unit-test + + [ "http://www.jedit.org:80/?a=b" ] [ + "http://www.jedit.org" >url { { "a" "b" } } >>query adjust-url url>string + ] unit-test ] with-scope TUPLE: mock-responder path ; @@ -31,7 +56,7 @@ C: mock-responder M: mock-responder call-responder* nip path>> on - [ ] ; + [ ] "text/plain" ; : check-dispatch ( tag path -- ? ) H{ } clone base-paths set @@ -84,7 +109,7 @@ C: path-check-responder M: path-check-responder call-responder* drop - >array ; + >array "text/plain" ; [ { "c" } ] [ H{ } clone base-paths set @@ -125,7 +150,7 @@ C: base-path-check-responder M: base-path-check-responder call-responder* 2drop "$funny-dispatcher" resolve-base-path - ; + "text/plain" ; [ ] [ diff --git a/extra/http/server/server.factor b/extra/http/server/server.factor index d68c66b829..2fd706432b 100755 --- a/extra/http/server/server.factor +++ b/extra/http/server/server.factor @@ -2,23 +2,16 @@ ! See http://factorcode.org/license.txt for BSD license. USING: assocs kernel namespaces io io.timeouts strings splitting threads sequences prettyprint io.server logging calendar http -html.streams html.elements accessors math.parser -combinators.lib tools.vocabs debugger continuations random -combinators destructors io.encodings.8-bit fry classes words -math rss json.writer ; +html.streams html.components html.elements html.templates +accessors math.parser combinators.lib tools.vocabs debugger +continuations random combinators destructors io.streams.string +io.encodings.8-bit fry classes words math urls +arrays vocabs.loader ; IN: http.server ! path is a sequence of path component strings - GENERIC: call-responder* ( path responder -- response ) -: request-params ( request -- assoc ) - dup method>> { - { "GET" [ query>> ] } - { "HEAD" [ query>> ] } - { "POST" [ post-data>> ] } - } case ; - : ( body content-type -- response ) 200 >>code @@ -26,21 +19,6 @@ GENERIC: call-responder* ( path responder -- response ) swap >>content-type swap >>body ; -: ( body -- response ) - "text/plain" ; - -: ( body -- response ) - "text/html" ; - -: ( body -- response ) - "text/xml" ; - -: ( feed -- response ) - '[ , feed>xml ] "text/xml" ; - -: ( obj -- response ) - '[ , >json ] "application/json" ; - TUPLE: trivial-responder response ; C: trivial-responder @@ -55,7 +33,8 @@ M: trivial-responder call-responder* nip response>> call ; ; : ( code message -- response ) - 2dup '[ , , trivial-response-body ] + 2dup [ trivial-response-body ] with-string-writer + "text/html" swap >>message swap >>code ; @@ -69,7 +48,7 @@ SYMBOL: 404-responder [ <404> ] 404-responder set-global -SYMBOL: base-paths +SYMBOL: responder-nesting : invert-slice ( slice -- slice' ) dup slice? [ @@ -78,86 +57,81 @@ SYMBOL: base-paths drop { } ] if ; -: add-base-path ( path dispatcher -- ) - [ invert-slice ] [ class word-name ] bi* - base-paths get set-at ; +: vocab-path ( vocab -- path ) + dup vocab-dir vocab-append-path ; + +: vocab-path-of ( dispatcher -- path ) + class word-vocabulary vocab-path ; + +: add-responder-path ( path dispatcher -- ) + [ [ invert-slice ] [ [ vocab-path-of ] keep ] bi* 3array ] + [ nip class word-name ] 2bi + responder-nesting get set-at ; : call-responder ( path responder -- response ) - [ add-base-path ] [ call-responder* ] 2bi ; + [ add-responder-path ] [ call-responder* ] 2bi ; -SYMBOL: link-hook +: nested-responders ( -- seq ) + responder-nesting get assocs:values [ third ] map ; -: add-link-hook ( quot -- ) - link-hook [ compose ] change ; inline +: each-responder ( quot -- ) + nested-responders swap each ; inline -: modify-query ( query -- query ) - link-hook get call ; - -: base-path ( string -- path ) - dup base-paths get at +: responder-path ( string -- pair ) + dup responder-nesting get at [ ] [ "No such responder: " swap append throw ] ?if ; -: resolve-base-path ( string -- string' ) - "$" ?head [ +: base-path ( string -- path ) + responder-path first ; + +: template-path ( string -- path ) + responder-path second ; + +: resolve-responder-path ( string quot -- string' ) + [ "$" ?head ] dip '[ [ - "/" split1 [ base-path [ "/" % % ] each "/" % ] dip % + "/" split1 [ @ [ "/" % % ] each "/" % ] dip % ] "" make - ] when ; + ] when ; inline -: link>string ( url query -- url' ) - [ resolve-base-path ] [ modify-query ] bi* (link>string) ; +: resolve-base-path ( string -- string' ) + [ base-path ] resolve-responder-path ; -: write-link ( url query -- ) - link>string write ; +: resolve-template-path ( string -- string' ) + [ template-path ] resolve-responder-path ; -SYMBOL: form-hook +GENERIC: modify-query ( query responder -- query' ) -: add-form-hook ( quot -- ) - form-hook [ compose ] change ; +M: object modify-query drop ; -: hidden-form-field ( -- ) - form-hook get call ; +: adjust-url ( url -- url' ) + clone + [ dup [ modify-query ] each-responder ] change-query + [ resolve-base-path ] change-path + request get url>> + clone + f >>query + swap derive-url ensure-port ; -: absolute-redirect ( to query -- url ) - #! Same host. - request get clone - swap [ >>query ] when* - swap url-encode >>path - [ modify-query ] change-query - request-url ; +: ( url code message -- response ) + + swap dup url? [ adjust-url ] when + "location" set-header ; -: replace-last-component ( path with -- path' ) - [ "/" last-split1 drop "/" ] dip 3append ; - -: relative-redirect ( to query -- url ) - request get clone - swap [ >>query ] when* - swap [ '[ , replace-last-component ] change-path ] when* - [ modify-query ] change-query - request-url ; - -: derive-url ( to query -- url ) - { - { [ over "http://" head? ] [ link>string ] } - { [ over "/" head? ] [ absolute-redirect ] } - { [ over "$" head? ] [ [ resolve-base-path ] dip derive-url ] } - [ relative-redirect ] - } cond ; - -: ( to query code message -- response ) - -rot derive-url "location" set-header ; - -\ DEBUG add-input-logging +\ DEBUG add-input-logging : ( to query -- response ) - 301 "Moved Permanently" ; + 301 "Moved Permanently" ; : ( to query -- response ) - 307 "Temporary Redirect" ; + 307 "Temporary Redirect" ; -: ( to query -- response ) - request get method>> "POST" = - [ ] [ ] if ; +: ( to query -- response ) + request get method>> { + { "GET" [ ] } + { "HEAD" [ ] } + { "POST" [ ] } + } case ; TUPLE: dispatcher default responders ; @@ -187,7 +161,7 @@ TUPLE: vhost-dispatcher default responders ; 404-responder get H{ } clone vhost-dispatcher boa ; : find-vhost ( dispatcher -- responder ) - request get host>> over responders>> at* + request get url>> host>> over responders>> at* [ nip ] [ drop default>> ] if ; M: vhost-dispatcher call-responder* ( path dispatcher -- response ) @@ -242,35 +216,28 @@ SYMBOL: development-mode LOG: httpd-hit NOTICE : log-request ( request -- ) - { method>> host>> path>> } map-exec-with httpd-hit ; - -SYMBOL: exit-continuation - -: exit-with exit-continuation get continue-with ; - -: with-exit-continuation ( quot -- ) - '[ exit-continuation set @ ] callcc1 exit-continuation off ; + [ method>> ] [ url>> [ host>> ] [ path>> ] bi ] bi 3array httpd-hit ; : split-path ( string -- path ) "/" split harvest ; -: init-request ( -- ) - H{ } clone base-paths set +: init-request ( request -- ) + request set + H{ } clone responder-nesting set [ ] link-hook set [ ] form-hook set ; +: dispatch-request ( request -- response ) + url>> path>> split-path main-responder get call-responder ; + : do-request ( request -- response ) [ - init-request - [ request set ] + [ init-request ] [ log-request ] - [ path>> split-path main-responder get call-responder ] tri - [ <404> ] unless* - ] [ - [ \ do-request log-error ] - [ <500> ] - bi - ] recover ; + [ dispatch-request ] tri + ] + [ [ \ do-request log-error ] [ <500> ] bi ] + recover ; : ?refresh-all ( -- ) development-mode get-global diff --git a/extra/http/server/static/static.factor b/extra/http/server/static/static.factor index 8814004589..d64268d68e 100755 --- a/extra/http/server/static/static.factor +++ b/extra/http/server/static/static.factor @@ -4,7 +4,7 @@ USING: calendar io io.files kernel math math.order math.parser http http.server namespaces parser sequences strings assocs hashtables debugger http.mime sorting html.elements html.templates.fhtml logging calendar.format accessors -io.encodings.binary fry xml.entities destructors ; +io.encodings.binary fry xml.entities destructors urls ; IN: http.server.static ! special maps mime types to quots with effect ( path -- ) @@ -71,7 +71,7 @@ TUPLE: file-responder root hook special allow-listings ; : list-directory ( directory -- response ) file-responder get allow-listings>> [ - '[ , directory. ] + '[ , directory. ] "text/html" ] [ drop <403> ] if ; @@ -85,7 +85,7 @@ TUPLE: file-responder root hook special allow-listings ; find-index [ serve-file ] [ list-directory ] ?if ] [ drop - request get path>> "/" append f + request get url>> clone [ "/" append ] change-path ] if ; : serve-object ( filename -- response ) @@ -101,6 +101,6 @@ M: file-responder call-responder* ( path responder -- response ) ! file responder integration : enable-fhtml ( responder -- responder ) - [ ] + [ "text/html" ] "application/x-factor-server-page" pick special>> set-at ; diff --git a/extra/io/pools/pools.factor b/extra/io/pools/pools.factor index 7ee14e03e5..033ba3cbfb 100644 --- a/extra/io/pools/pools.factor +++ b/extra/io/pools/pools.factor @@ -1,13 +1,22 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: accessors kernel arrays namespaces sequences continuations -destructors io.sockets ; +destructors io.sockets alien alien.syntax ; IN: io.pools -TUPLE: pool connections disposed ; +TUPLE: pool connections disposed expired ; + +: check-pool ( pool -- ) + dup check-disposed + dup expired>> expired? [ + ALIEN: 31337 >>expired + connections>> [ delete-all ] [ dispose-each ] bi + ] [ drop ] if ; : ( class -- pool ) - new V{ } clone >>connections ; inline + new V{ } clone + >>connections + dup check-pool ; inline M: pool dispose* connections>> dispose-each ; @@ -17,15 +26,14 @@ M: pool dispose* connections>> dispose-each ; TUPLE: return-connection conn pool ; : return-connection ( conn pool -- ) - dup check-disposed connections>> push ; + dup check-pool connections>> push ; GENERIC: make-connection ( pool -- conn ) : new-connection ( pool -- ) - [ make-connection ] keep return-connection ; + dup check-pool [ make-connection ] keep return-connection ; : acquire-connection ( pool -- conn ) - dup check-disposed [ dup connections>> empty? ] [ dup new-connection ] [ ] while connections>> pop ; diff --git a/extra/lcs/diff2html/diff2html.factor b/extra/lcs/diff2html/diff2html.factor index a8f649e2c9..754e69a476 100644 --- a/extra/lcs/diff2html/diff2html.factor +++ b/extra/lcs/diff2html/diff2html.factor @@ -38,7 +38,7 @@ M: delete diff-line ; : htmlize-diff ( diff -- ) - +
[ diff-line ] each
"Old" write "New" write
; diff --git a/extra/rss/rss.factor b/extra/rss/rss.factor index 364c24b91f..5183af5145 100644 --- a/extra/rss/rss.factor +++ b/extra/rss/rss.factor @@ -4,7 +4,7 @@ USING: xml.utilities kernel assocs xml.generator math.order strings sequences xml.data xml.writer io.streams.string combinators xml xml.entities io.files io http.client namespaces xml.generator hashtables - calendar.format accessors continuations ; + calendar.format accessors continuations urls ; IN: rss : any-tag-named ( tag names -- tag-inside ) @@ -103,18 +103,15 @@ C: entry : entry, ( entry -- ) "entry" [ - dup entry-title "title" { { "type" "html" } } simple-tag*, - "link" over entry-link "href" associate contained*, - dup entry-pub-date timestamp>rfc3339 "published" simple-tag, - entry-description [ "content" { { "type" "html" } } simple-tag*, ] when* + dup title>> "title" { { "type" "html" } } simple-tag*, + "link" over link>> dup url? [ url>string ] when "href" associate contained*, + dup pub-date>> timestamp>rfc3339 "published" simple-tag, + description>> [ "content" { { "type" "html" } } simple-tag*, ] when* ] tag, ; : feed>xml ( feed -- xml ) "feed" { { "xmlns" "http://www.w3.org/2005/Atom" } } [ - dup feed-title "title" simple-tag, - "link" over feed-link "href" associate contained*, - feed-entries [ entry, ] each + dup title>> "title" simple-tag, + "link" over link>> dup url? [ url>string ] when "href" associate contained*, + entries>> [ entry, ] each ] make-xml* ; - -: write-feed ( feed -- ) - feed>xml write-xml ; diff --git a/extra/tangle/tangle.factor b/extra/tangle/tangle.factor index 8a4c6146de..f020724d31 100644 --- a/extra/tangle/tangle.factor +++ b/extra/tangle/tangle.factor @@ -1,6 +1,6 @@ ! Copyright (C) 2008 Alex Chapman ! See http://factorcode.org/license.txt for BSD license. -USING: accessors assocs db db.sqlite db.postgresql http http.server http.server.actions http.server.static io io.files json.writer kernel math.parser namespaces semantic-db sequences strings tangle.path ; +USING: accessors assocs db db.sqlite db.postgresql http http.server furnace.actions http.server.static io io.files json.writer kernel math.parser namespaces semantic-db sequences strings tangle.path ; IN: tangle GENERIC: render* ( content templater -- output ) @@ -20,7 +20,7 @@ C: tangle [ [ db>> ] [ seq>> ] bi ] dip with-db ; : node-response ( id -- response ) - load-node [ node-content ] [ <404> ] if* ; + load-node [ node-content "text/plain" ] [ <404> ] if* ; : display-node ( params -- response ) [ @@ -36,7 +36,7 @@ C: tangle : submit-node ( params -- response ) [ "node_content" swap at* [ - create-node id>> number>string + create-node id>> number>string "text/plain" ] [ drop <400> ] if @@ -52,7 +52,7 @@ TUPLE: path-responder ; C: path-responder M: path-responder call-responder* ( path responder -- response ) - drop path>file [ node-content ] [ <404> ] if* ; + drop path>file [ node-content "text/plain" ] [ <404> ] if* ; TUPLE: tangle-dispatcher < dispatcher tangle ; diff --git a/extra/urls/urls-tests.factor b/extra/urls/urls-tests.factor index e28816fdb3..e64ef283c5 100644 --- a/extra/urls/urls-tests.factor +++ b/extra/urls/urls-tests.factor @@ -77,10 +77,17 @@ USING: urls tools.test tuple-syntax arrays kernel assocs ; } "a/relative/path" } + { + TUPLE{ url + path: "bar" + query: H{ { "a" "b" } } + } + "bar?a=b" + } } ; urls [ - [ 1array ] [ [ string>url ] curry ] bi* unit-test + [ 1array ] [ [ >url ] curry ] bi* unit-test ] assoc-each urls [ @@ -192,3 +199,7 @@ urls [ derive-url ] unit-test + +[ "a" ] [ + "a" "b" set-query-param "b" query-param +] unit-test diff --git a/extra/urls/urls.factor b/extra/urls/urls.factor index e20df65656..472eead0f2 100644 --- a/extra/urls/urls.factor +++ b/extra/urls/urls.factor @@ -1,9 +1,9 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: kernel unicode.categories combinators sequences splitting -fry namespaces assocs arrays strings mirrors -io.encodings.string io.encodings.utf8 -math math.parser accessors namespaces.lib ; +fry namespaces assocs arrays strings io.encodings.string +io.encodings.utf8 math math.parser accessors mirrors parser +prettyprint.backend hashtables ; IN: urls : url-quotable? ( ch -- ? ) @@ -91,11 +91,13 @@ IN: urls TUPLE: url protocol host port path query anchor ; +: ( -- url ) url new ; + : query-param ( request key -- value ) swap query>> at ; : set-query-param ( request value key -- request ) - pick query>> set-at ; + '[ , , _ ?set-at ] change-query ; : parse-host ( string -- host port ) ":" split1 [ url-decode ] [ @@ -105,40 +107,44 @@ TUPLE: url protocol host port path query anchor ; ] when ] bi* ; -: parse-host-part ( protocol rest -- string' ) - [ "protocol" set ] [ +: parse-host-part ( url protocol rest -- url string' ) + [ >>protocol ] [ "//" ?head [ "Invalid URL" throw ] unless "/" split1 [ - parse-host [ "host" set ] [ "port" set ] bi* + parse-host [ >>host ] [ >>port ] bi* ] [ "/" prepend ] bi* ] bi* ; -: string>url ( string -- url ) - [ - ":" split1 [ parse-host-part ] when* - "#" split1 [ - "?" split1 [ query>assoc "query" set ] when* - url-decode "path" set - ] [ - url-decode "anchor" set - ] bi* - ] url make-object ; +GENERIC: >url ( obj -- url ) -: unparse-host-part ( protocol -- ) +M: url >url ; + +M: string >url + swap + ":" split1 [ parse-host-part ] when* + "#" split1 [ + "?" split1 + [ url-decode >>path ] + [ [ query>assoc >>query ] when* ] bi* + ] + [ url-decode >>anchor ] bi* ; + +: unparse-host-part ( url protocol -- ) % "://" % - "host" get url-encode % - "port" get [ ":" % # ] when* - "path" get "/" head? [ "Invalid URL" throw ] unless ; + [ host>> url-encode % ] + [ port>> [ ":" % # ] when* ] + [ path>> "/" head? [ "/" % ] unless ] + tri ; : url>string ( url -- string ) [ - [ - "protocol" get [ unparse-host-part ] when* - "path" get url-encode % - "query" get [ "?" % assoc>query % ] when* - "anchor" get [ "#" % url-encode % ] when* - ] bind + { + [ dup protocol>> dup [ unparse-host-part ] [ 2drop ] if ] + [ path>> url-encode % ] + [ query>> dup assoc-empty? [ drop ] [ "?" % assoc>query % ] if ] + [ anchor>> [ "#" % url-encode % ] when* ] + } cleave ] "" make ; : url-append-path ( path1 path2 -- path ) @@ -158,3 +164,7 @@ TUPLE: url protocol host port path query anchor ; : relative-url ( url -- url' ) clone f >>protocol f >>host f >>port ; + +: URL" lexer get skip-blank parse-string >url parsed ; parsing + +M: url pprint* dup url>string "URL\" " "\"" pprint-string ; diff --git a/extra/webapps/counter/counter.factor b/extra/webapps/counter/counter.factor index 04194adb29..29ce3f0e7c 100644 --- a/extra/webapps/counter/counter.factor +++ b/extra/webapps/counter/counter.factor @@ -1,6 +1,6 @@ -USING: math kernel accessors html.components -http.server http.server.actions -http.server.sessions html.templates.chloe fry ; +USING: math kernel accessors html.components http.server +furnace.actions furnace.sessions html.templates.chloe +fry urls ; IN: webapps.counter SYMBOL: count @@ -11,15 +11,15 @@ M: counter-app init-session* drop 0 count sset ; : ( quot -- action ) - swap '[ count , schange "" f ] >>submit ; - -: counter-template ( -- template ) - "resource:extra/webapps/counter/counter.xml" ; + swap '[ + count , schange + URL" $counter-app" + ] >>submit ; : ( -- action ) [ count sget "counter" set-value ] >>init - counter-template >>template ; + "$counter-app/counter" >>template ; : ( -- responder ) counter-app new-dispatcher diff --git a/extra/webapps/factor-website/factor-website.factor b/extra/webapps/factor-website/factor-website.factor index 9ad4a05492..5565625a9c 100644 --- a/extra/webapps/factor-website/factor-website.factor +++ b/extra/webapps/factor-website/factor-website.factor @@ -4,13 +4,12 @@ USING: accessors kernel sequences assocs io.files io.sockets io.server namespaces db db.sqlite smtp http.server -http.server.db -http.server.flows -http.server.sessions -http.server.auth.login -http.server.auth.providers.db -http.server.boilerplate -html.templates.chloe +furnace.db +furnace.flows +furnace.sessions +furnace.auth.login +furnace.auth.providers.db +furnace.boilerplate webapps.pastebin webapps.planet webapps.todo @@ -20,9 +19,6 @@ IN: webapps.factor-website : test-db "resource:test.db" sqlite-db ; -: factor-template ( path -- template ) - "resource:extra/webapps/factor-website/" swap ".xml" 3append ; - : init-factor-db ( -- ) test-db [ init-users-table @@ -40,8 +36,10 @@ IN: webapps.factor-website init-revisions-table ] with-db ; +TUPLE: factor-website < dispatcher ; + : ( -- responder ) - + factor-website new-dispatcher "todo" add-responder "pastebin" add-responder "planet" add-responder @@ -53,7 +51,7 @@ IN: webapps.factor-website allow-password-recovery allow-edit-profile - "page" factor-template >>template + "$factor-website/page" >>template test-db ; diff --git a/extra/webapps/factor-website/page.xml b/extra/webapps/factor-website/page.xml index f7080643b4..32e1223c58 100644 --- a/extra/webapps/factor-website/page.xml +++ b/extra/webapps/factor-website/page.xml @@ -15,6 +15,8 @@ + + diff --git a/extra/webapps/pastebin/paste.xml b/extra/webapps/pastebin/paste.xml index 57c2fdb7c2..9f35d83fd8 100644 --- a/extra/webapps/pastebin/paste.xml +++ b/extra/webapps/pastebin/paste.xml @@ -2,7 +2,7 @@ - + Paste: @@ -12,15 +12,13 @@ Date: -
+
Delete Paste - | - Annotate - + -

Annotation:

+

Annotation:

@@ -32,9 +30,9 @@ Delete Annotation - + - +

New Annotation

@@ -55,6 +53,6 @@ -
+ diff --git a/extra/webapps/pastebin/pastebin-common.xml b/extra/webapps/pastebin/pastebin-common.xml index f785fceb6b..a86404d451 100644 --- a/extra/webapps/pastebin/pastebin-common.xml +++ b/extra/webapps/pastebin/pastebin-common.xml @@ -2,6 +2,8 @@ + +
Author:
@@ -11,13 +9,13 @@ - + - +
Paste by: Date:
diff --git a/extra/webapps/planet/admin.xml b/extra/webapps/planet/admin.xml index 4711ca4716..26a3e6f206 100644 --- a/extra/webapps/planet/admin.xml +++ b/extra/webapps/planet/admin.xml @@ -5,13 +5,13 @@ Planet Factor Administration
    - +
  • -
    +

diff --git a/extra/webapps/planet/mini-planet.xml b/extra/webapps/planet/mini-planet.xml index 1338463bcf..7c5269b8d9 100644 --- a/extra/webapps/planet/mini-planet.xml +++ b/extra/webapps/planet/mini-planet.xml @@ -2,13 +2,13 @@ - +


Read More...

- +
diff --git a/extra/webapps/planet/planet.factor b/extra/webapps/planet/planet.factor index 414a59f3b2..39539441ce 100755 --- a/extra/webapps/planet/planet.factor +++ b/extra/webapps/planet/planet.factor @@ -3,19 +3,16 @@ USING: kernel accessors sequences sorting math math.order calendar alarms logging concurrency.combinators namespaces sequences.lib db.types db.tuples db fry locals hashtables -html.components html.templates.chloe -rss xml.writer +html.components +rss urls xml.writer validators http.server -http.server.actions -http.server.boilerplate -http.server.auth.login -http.server.auth ; +furnace.actions +furnace.boilerplate +furnace.auth.login +furnace.auth ; IN: webapps.planet -: planet-template ( name -- template ) - "resource:extra/webapps/planet/" swap ".xml" 3append ; - TUPLE: blog id name www-url feed-url ; M: blog link-title name>> ; @@ -61,7 +58,7 @@ posting "POSTINGS" : ( -- action ) [ blogroll "blogroll" set-value ] >>init - "admin" planet-template >>template ; + "$planet-factor/admin" >>template ; : ( -- action ) @@ -70,7 +67,7 @@ posting "POSTINGS" postings "postings" set-value ] >>init - "planet" planet-template >>template ; + "$planet-factor/planet" >>template ; : planet-feed ( -- feed ) feed new @@ -110,7 +107,7 @@ posting "POSTINGS" [ update-cached-postings - "" f + URL" $planet-factor/admin" ] >>submit ; : ( -- action ) @@ -119,7 +116,7 @@ posting "POSTINGS" [ "id" value delete-tuples - "$planet-factor/admin" f + URL" $planet-factor/admin" ] >>submit ; : validate-blog ( -- ) @@ -129,15 +126,12 @@ posting "POSTINGS" { "feed-url" [ v-url ] } } validate-params ; -: ( id next -- response ) - swap "id" associate ; - : deposit-blog-slots ( blog -- ) { "name" "www-url" "feed-url" } deposit-slots ; : ( -- action ) - "new-blog" planet-template >>template + "$planet-factor/new-blog" >>template [ validate-blog ] >>validate @@ -145,7 +139,12 @@ posting "POSTINGS" f [ deposit-blog-slots ] [ insert-tuple ] - [ id>> "$planet-factor/admin/edit-blog" ] + [ + + "$planet-factor/admin/edit-blog" >>path + swap id>> "id" set-query-param + + ] tri ] >>submit ; @@ -153,10 +152,10 @@ posting "POSTINGS" [ validate-integer-id - "id" value select-tuple from-tuple + "id" value select-tuple from-object ] >>init - "edit-blog" planet-template >>template + "$planet-factor/edit-blog" >>template [ validate-integer-id @@ -167,7 +166,12 @@ posting "POSTINGS" f [ deposit-blog-slots ] [ update-tuple ] - [ id>> "$planet-factor/admin" ] + [ + + "$planet-factor/admin" >>path + swap id>> "id" set-query-param + + ] tri ] >>submit ; @@ -193,7 +197,7 @@ TUPLE: planet-factor < dispatcher ; "feed.xml" add-responder { can-administer-planet-factor? } "admin" add-responder - "planet-common" planet-template >>template ; + "$planet-factor/planet-common" >>template ; : start-update-task ( db params -- ) '[ , , [ update-cached-postings ] with-db ] 10 minutes every drop ; diff --git a/extra/webapps/planet/planet.xml b/extra/webapps/planet/planet.xml index 526a9b306b..4ee1c171e2 100644 --- a/extra/webapps/planet/planet.xml +++ b/extra/webapps/planet/planet.xml @@ -8,7 +8,7 @@ - +

@@ -22,7 +22,7 @@

- + @@ -31,7 +31,7 @@

Blogroll

    - +
  • diff --git a/extra/webapps/todo/edit-todo.xml b/extra/webapps/todo/edit-todo.xml index 0974c8ce1b..6bae6e705e 100644 --- a/extra/webapps/todo/edit-todo.xml +++ b/extra/webapps/todo/edit-todo.xml @@ -14,12 +14,8 @@ - - - View - | - Delete - - + View + | + Delete diff --git a/extra/webapps/todo/new-todo.xml b/extra/webapps/todo/new-todo.xml new file mode 100644 index 0000000000..f557d5307b --- /dev/null +++ b/extra/webapps/todo/new-todo.xml @@ -0,0 +1,17 @@ + + + + + New Item + + + + + + +
    Summary:
    Priority:
    Description:
    + + +
    + +
    diff --git a/extra/webapps/todo/todo-list.xml b/extra/webapps/todo/todo-list.xml index 845c38dbf7..036c590306 100644 --- a/extra/webapps/todo/todo-list.xml +++ b/extra/webapps/todo/todo-list.xml @@ -13,7 +13,7 @@ Edit - + @@ -30,7 +30,7 @@ - + diff --git a/extra/webapps/todo/todo.factor b/extra/webapps/todo/todo.factor index e3b174eaea..063c8515f7 100755 --- a/extra/webapps/todo/todo.factor +++ b/extra/webapps/todo/todo.factor @@ -1,15 +1,15 @@ ! Copyright (c) 2008 Slava Pestov ! See http://factorcode.org/license.txt for BSD license. USING: accessors kernel sequences namespaces -db db.types db.tuples validators hashtables +db db.types db.tuples validators hashtables urls html.components html.templates.chloe -http.server.sessions -http.server.boilerplate -http.server.auth -http.server.actions -http.server.db -http.server.auth.login +furnace.sessions +furnace.boilerplate +furnace.auth +furnace.actions +furnace.db +furnace.auth.login http.server ; IN: webapps.todo @@ -31,20 +31,14 @@ todo "TODO" swap >>id uid >>uid ; -: todo-template ( name -- template ) - "resource:extra/webapps/todo/" swap ".xml" 3append ; - : ( -- action ) [ validate-integer-id - "id" value select-tuple from-tuple + "id" value select-tuple from-object ] >>init - "view-todo" todo-template >>template ; - -: ( id next -- response ) - swap "id" associate ; + "$todo-list/view-todo" >>template ; : validate-todo ( -- ) { @@ -57,15 +51,20 @@ todo "TODO" [ 0 "priority" set-value ] >>init - "edit-todo" todo-template >>template + "$todo-list/new-todo" >>template [ validate-todo ] >>validate [ f - dup { "summary" "description" } deposit-slots + dup { "summary" "priority" "description" } deposit-slots [ insert-tuple ] - [ id>> "$todo-list/view" ] + [ + + "$todo-list/view" >>path + swap id>> "id" set-query-param + + ] bi ] >>submit ; @@ -73,10 +72,10 @@ todo "TODO" [ validate-integer-id - "id" value select-tuple from-tuple + "id" value select-tuple from-object ] >>init - "edit-todo" todo-template >>template + "$todo-list/edit-todo" >>template [ validate-integer-id @@ -87,7 +86,12 @@ todo "TODO" f dup { "id" "summary" "priority" "description" } deposit-slots [ update-tuple ] - [ id>> "$todo-list/view" ] + [ + + "$todo-list/view" >>path + swap id>> "id" set-query-param + + ] bi ] >>submit ; @@ -97,13 +101,13 @@ todo "TODO" [ "id" get delete-tuples - "$todo-list/list" f + URL" $todo-list/list" ] >>submit ; : ( -- action ) [ f select-tuples "items" set-value ] >>init - "todo-list" todo-template >>template ; + "$todo-list/todo-list" >>template ; TUPLE: todo-list < dispatcher ; @@ -115,5 +119,5 @@ TUPLE: todo-list < dispatcher ; "edit" add-responder "delete" add-responder - "todo" todo-template >>template + "$todo-list/todo" >>template f ; diff --git a/extra/webapps/todo/todo.xml b/extra/webapps/todo/todo.xml index 39ab5cda8b..e892137932 100644 --- a/extra/webapps/todo/todo.xml +++ b/extra/webapps/todo/todo.xml @@ -6,7 +6,7 @@ +

    This revision created on by .

    + diff --git a/extra/webapps/wiki/wiki.factor b/extra/webapps/wiki/wiki.factor index 7444f1012e..31b5a12c41 100644 --- a/extra/webapps/wiki/wiki.factor +++ b/extra/webapps/wiki/wiki.factor @@ -184,7 +184,10 @@ revision "REVISIONS" { "old-id" "new-id" [ value select-tuple ] bi@ - [ [ "old" set-value ] [ "new" set-value ] bi* ] + [ + [ [ title>> "title" set-value ] [ "old" set-value ] bi ] + [ "new" set-value ] bi* + ] [ [ content>> string-lines ] bi@ diff "diff" set-value ] 2bi ] >>init From 52df2a2b47d85adcbb8364d25c203361124f0e47 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 2 Jun 2008 15:38:44 -0500 Subject: [PATCH 12/19] Load fixes --- extra/tangle/tangle.factor | 6 +++++- extra/webapps/counter/counter.factor | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/extra/tangle/tangle.factor b/extra/tangle/tangle.factor index f020724d31..1f567a5f0d 100644 --- a/extra/tangle/tangle.factor +++ b/extra/tangle/tangle.factor @@ -1,6 +1,10 @@ ! Copyright (C) 2008 Alex Chapman ! See http://factorcode.org/license.txt for BSD license. -USING: accessors assocs db db.sqlite db.postgresql http http.server furnace.actions http.server.static io io.files json.writer kernel math.parser namespaces semantic-db sequences strings tangle.path ; +USING: accessors assocs db db.sqlite db.postgresql +http http.server http.server.dispatchers http.server.responses +http.server.static furnace.actions furnace.json +io io.files json.writer kernel math.parser namespaces +semantic-db sequences strings tangle.path ; IN: tangle GENERIC: render* ( content templater -- output ) diff --git a/extra/webapps/counter/counter.factor b/extra/webapps/counter/counter.factor index 1f80a71647..9ac70f452a 100644 --- a/extra/webapps/counter/counter.factor +++ b/extra/webapps/counter/counter.factor @@ -1,5 +1,6 @@ -USING: math kernel accessors html.components http.server -furnace.actions furnace.sessions html.templates.chloe +USING: math kernel accessors http.server http.server.dispatchers +furnace.actions furnace.sessions +html.components html.templates.chloe fry urls ; IN: webapps.counter From 94eebc747b5acf2cca6047e8172f6695d79be814 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 2 Jun 2008 15:50:15 -0500 Subject: [PATCH 13/19] Fix diff --- extra/webapps/wiki/wiki.css | 1 + 1 file changed, 1 insertion(+) diff --git a/extra/webapps/wiki/wiki.css b/extra/webapps/wiki/wiki.css index 4825839ab3..83ec918e3b 100644 --- a/extra/webapps/wiki/wiki.css +++ b/extra/webapps/wiki/wiki.css @@ -2,6 +2,7 @@ border-width: 1px; border-color: #666; border-style: solid; + width: 50%; } .comparison table { From d35f25f334a87a17175b8a16418e68ac6fa911a9 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 2 Jun 2008 17:51:06 -0500 Subject: [PATCH 14/19] Fix load errors --- extra/furnace/auth/basic/basic.factor | 6 +++--- extra/html/components/components-tests.factor | 2 +- extra/html/parser/analyzer/analyzer.factor | 2 +- extra/html/templates/chloe/chloe-tests.factor | 8 ++++---- extra/http/server/cgi/cgi.factor | 4 ++-- extra/http/server/server.factor | 3 ++- extra/webapps/counter/counter.factor | 2 +- extra/webapps/wiki/diff.xml | 11 +---------- extra/webapps/wiki/edit.xml | 6 ------ extra/webapps/wiki/page-common.xml | 14 ++++++++++++++ extra/webapps/wiki/revisions.xml | 9 --------- extra/webapps/wiki/view.xml | 7 ------- extra/webapps/wiki/wiki.factor | 16 ++++++++++------ extra/xmode/code2html/responder/responder.factor | 4 ++-- extra/yahoo/yahoo.factor | 3 ++- 15 files changed, 43 insertions(+), 54 deletions(-) create mode 100644 extra/webapps/wiki/page-common.xml diff --git a/extra/furnace/auth/basic/basic.factor b/extra/furnace/auth/basic/basic.factor index c57f78b315..c8d542c219 100755 --- a/extra/furnace/auth/basic/basic.factor +++ b/extra/furnace/auth/basic/basic.factor @@ -1,9 +1,9 @@ ! Copyright (c) 2007 Chris Double. ! See http://factorcode.org/license.txt for BSD license. USING: accessors quotations assocs kernel splitting -base64 html.elements io combinators http.server -furnace.auth.providers furnace.auth.login -http sequences ; +base64 html.elements io combinators sequences +http http.server.filters http.server.responses http.server +furnace.auth.providers furnace.auth.login ; IN: furnace.auth.basic TUPLE: basic-auth < filter-responder realm provider ; diff --git a/extra/html/components/components-tests.factor b/extra/html/components/components-tests.factor index 90dc156ea6..1f77768115 100644 --- a/extra/html/components/components-tests.factor +++ b/extra/html/components/components-tests.factor @@ -1,7 +1,7 @@ IN: html.components.tests USING: tools.test kernel io.streams.string io.streams.null accessors inspector html.streams -html.components namespaces ; +html.elements html.components namespaces ; [ ] [ blank-values ] unit-test diff --git a/extra/html/parser/analyzer/analyzer.factor b/extra/html/parser/analyzer/analyzer.factor index 9ce45b5c47..47d352b6b8 100755 --- a/extra/html/parser/analyzer/analyzer.factor +++ b/extra/html/parser/analyzer/analyzer.factor @@ -1,6 +1,6 @@ USING: assocs html.parser kernel math sequences strings ascii arrays shuffle unicode.case namespaces splitting http -sequences.lib accessors io combinators http.client ; +sequences.lib accessors io combinators http.client urls ; IN: html.parser.analyzer TUPLE: link attributes clickable ; diff --git a/extra/html/templates/chloe/chloe-tests.factor b/extra/html/templates/chloe/chloe-tests.factor index 3a2cd10494..d4c02061b2 100644 --- a/extra/html/templates/chloe/chloe-tests.factor +++ b/extra/html/templates/chloe/chloe-tests.factor @@ -1,7 +1,7 @@ USING: html.templates html.templates.chloe tools.test io.streams.string kernel sequences ascii boxes namespaces xml html.components -splitting unicode.categories ; +splitting unicode.categories furnace ; IN: html.templates.chloe.tests [ f ] [ f parse-query-attr ] unit-test @@ -49,7 +49,7 @@ IN: html.templates.chloe.tests [ [ "test2" test-template call-template - ] [ "test3" test-template ] with-boilerplate + ] "test3" test-template with-boilerplate ] run-template ] unit-test @@ -137,7 +137,7 @@ TUPLE: person first-name last-name ; [ "
    RBaxterUnknown
    DougColeman
    " ] [ [ - "test9" test-template call-template + "test8" test-template call-template ] run-template [ blank? not ] filter ] unit-test @@ -145,6 +145,6 @@ TUPLE: person first-name last-name ; [ "Hello" ] [ [ - "test10" test-template call-template + "test9" test-template call-template ] run-template ] unit-test diff --git a/extra/http/server/cgi/cgi.factor b/extra/http/server/cgi/cgi.factor index a706ee6998..cf8a35f141 100755 --- a/extra/http/server/cgi/cgi.factor +++ b/extra/http/server/cgi/cgi.factor @@ -2,7 +2,7 @@ ! See http://factorcode.org/license.txt for BSD license. USING: namespaces kernel assocs io.files io.streams.duplex combinators arrays io.launcher io http.server.static http.server -http accessors sequences strings math.parser fry ; +http accessors sequences strings math.parser fry urls ; IN: http.server.cgi : post? request get method>> "POST" = ; @@ -28,7 +28,7 @@ IN: http.server.cgi "" "REMOTE_IDENT" set request get method>> "REQUEST_METHOD" set - request get query>> assoc>query "QUERY_STRING" set + request get url>> query>> assoc>query "QUERY_STRING" set request get "cookie" header "HTTP_COOKIE" set request get "user-agent" header "HTTP_USER_AGENT" set diff --git a/extra/http/server/server.factor b/extra/http/server/server.factor index 68baeb28aa..02424ef974 100755 --- a/extra/http/server/server.factor +++ b/extra/http/server/server.factor @@ -63,7 +63,8 @@ LOG: httpd-hit NOTICE url>> path>> split-path main-responder get call-responder ; : do-request ( request -- response ) - [ + '[ + , [ init-request ] [ log-request ] [ dispatch-request ] tri diff --git a/extra/webapps/counter/counter.factor b/extra/webapps/counter/counter.factor index 9ac70f452a..da646fb76f 100644 --- a/extra/webapps/counter/counter.factor +++ b/extra/webapps/counter/counter.factor @@ -1,5 +1,5 @@ USING: math kernel accessors http.server http.server.dispatchers -furnace.actions furnace.sessions +furnace furnace.actions furnace.sessions html.components html.templates.chloe fry urls ; IN: webapps.counter diff --git a/extra/webapps/wiki/diff.xml b/extra/webapps/wiki/diff.xml index 55f3ef0b23..35afe51b66 100644 --- a/extra/webapps/wiki/diff.xml +++ b/extra/webapps/wiki/diff.xml @@ -2,9 +2,7 @@ - - Diff: - + Diff: @@ -23,11 +21,4 @@ - - diff --git a/extra/webapps/wiki/edit.xml b/extra/webapps/wiki/edit.xml index 37cc6d9a5b..057b7f8f71 100644 --- a/extra/webapps/wiki/edit.xml +++ b/extra/webapps/wiki/edit.xml @@ -16,10 +16,4 @@ - diff --git a/extra/webapps/wiki/page-common.xml b/extra/webapps/wiki/page-common.xml new file mode 100644 index 0000000000..1d4b507320 --- /dev/null +++ b/extra/webapps/wiki/page-common.xml @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/extra/webapps/wiki/revisions.xml b/extra/webapps/wiki/revisions.xml index 0a0de8e470..2a909e6ab3 100644 --- a/extra/webapps/wiki/revisions.xml +++ b/extra/webapps/wiki/revisions.xml @@ -53,13 +53,4 @@ -
    - - - diff --git a/extra/webapps/wiki/view.xml b/extra/webapps/wiki/view.xml index 0e1f0f7478..30dfb71270 100644 --- a/extra/webapps/wiki/view.xml +++ b/extra/webapps/wiki/view.xml @@ -10,11 +10,4 @@

    This revision created on by .

    - - diff --git a/extra/webapps/wiki/wiki.factor b/extra/webapps/wiki/wiki.factor index 31b5a12c41..6dcf89e208 100644 --- a/extra/webapps/wiki/wiki.factor +++ b/extra/webapps/wiki/wiki.factor @@ -216,16 +216,20 @@ revision "REVISIONS" { : ( -- dispatcher ) wiki new-dispatcher - "" add-responder - "view" add-responder - "revision" add-responder - "revisions" add-responder + + "" add-responder + "view" add-responder + "revision" add-responder + "revisions" add-responder + "diff" add-responder + { } "edit" add-responder + + { wiki "page-common" } >>template + >>default "rollback" add-responder "user-edits" add-responder - "diff" add-responder "articles" add-responder "changes" add-responder - { } "edit" add-responder { } "delete" add-responder { wiki "wiki-common" } >>template ; diff --git a/extra/xmode/code2html/responder/responder.factor b/extra/xmode/code2html/responder/responder.factor index 67cb60f8a0..2bc766dbc6 100755 --- a/extra/xmode/code2html/responder/responder.factor +++ b/extra/xmode/code2html/responder/responder.factor @@ -1,8 +1,8 @@ ! Copyright (C) 2007, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: io io.files io.encodings.utf8 namespaces http.server -http.server.static http xmode.code2html kernel sequences -accessors fry ; +http.server.responses http.server.static http xmode.code2html +kernel sequences accessors fry ; IN: xmode.code2html.responder : ( root -- responder ) diff --git a/extra/yahoo/yahoo.factor b/extra/yahoo/yahoo.factor index dd7ce962c2..c17de206c4 100755 --- a/extra/yahoo/yahoo.factor +++ b/extra/yahoo/yahoo.factor @@ -1,7 +1,8 @@ ! Copyright (C) 2006 Daniel Ehrenberg, Walton Chan ! See http://factorcode.org/license.txt for BSD license. USING: http.client xml xml.utilities kernel sequences -namespaces http math.parser help math.order locals accessors ; +namespaces http math.parser help math.order locals +urls accessors ; IN: yahoo TUPLE: result title url summary ; From 5127a587ea862a52ee3fa1c770a4db260e02969f Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 2 Jun 2008 18:04:21 -0500 Subject: [PATCH 15/19] Yahoo uses URLs now --- extra/yahoo/yahoo-tests.factor | 4 +-- extra/yahoo/yahoo.factor | 47 ++++++++++++++++------------------ 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/extra/yahoo/yahoo-tests.factor b/extra/yahoo/yahoo-tests.factor index 3776715c7b..827d6ecfd0 100644 --- a/extra/yahoo/yahoo-tests.factor +++ b/extra/yahoo/yahoo-tests.factor @@ -1,4 +1,4 @@ -USING: tools.test yahoo kernel io.files xml sequences accessors ; +USING: tools.test yahoo kernel io.files xml sequences accessors urls ; [ T{ result @@ -8,4 +8,4 @@ USING: tools.test yahoo kernel io.files xml sequences accessors ; "Official site with news, tour dates, discography, store, community, and more." } ] [ "resource:extra/yahoo/test-results.xml" file>xml parse-yahoo first ] unit-test -[ "http://search.yahooapis.com/WebSearchService/V1/webSearch?appid=Factor-search&query=hi&results=2&similar_ok=1" ] [ "hi" "Factor-search" >>appid 2 >>results t >>similar-ok query ] unit-test +[ URL" http://search.yahooapis.com/WebSearchService/V1/webSearch?appid=Factor-search&query=hi&results=2&similar_ok=1" ] [ "hi" "Factor-search" >>appid 2 >>results t >>similar-ok query ] unit-test diff --git a/extra/yahoo/yahoo.factor b/extra/yahoo/yahoo.factor index c17de206c4..c47b8be15c 100755 --- a/extra/yahoo/yahoo.factor +++ b/extra/yahoo/yahoo.factor @@ -1,14 +1,13 @@ ! Copyright (C) 2006 Daniel Ehrenberg, Walton Chan ! See http://factorcode.org/license.txt for BSD license. USING: http.client xml xml.utilities kernel sequences -namespaces http math.parser help math.order locals -urls accessors ; +math.parser urls accessors locals ; IN: yahoo TUPLE: result title url summary ; C: result - + TUPLE: search query results adult-ok start appid region type format similar-ok language country site subscription license ; @@ -20,11 +19,11 @@ format similar-ok language country site subscription license ; ] map ; : yahoo-url ( -- str ) - "http://search.yahooapis.com/WebSearchService/V1/webSearch" ; + URL" http://search.yahooapis.com/WebSearchService/V1/webSearch" ; -: param ( search str quot -- search ) - >r over r> call [ url-encode [ % ] bi@ ] [ drop ] if* ; - inline +:: param ( search url name quot -- search url ) + search url search quot call + [ name set-query-param ] when* ; inline : num-param ( search str quot -- search ) [ dup [ number>string ] when ] compose param ; inline @@ -33,24 +32,22 @@ format similar-ok language country site subscription license ; [ "1" and ] compose param ; inline : query ( search -- url ) - [ - yahoo-url % - "?appid=" [ appid>> ] param - "&query=" [ query>> ] param - "®ion=" [ region>> ] param - "&type=" [ type>> ] param - "&format=" [ format>> ] param - "&language=" [ language>> ] param - "&country=" [ country>> ] param - "&site=" [ site>> ] param - "&subscription=" [ subscription>> ] param - "&license=" [ license>> ] param - "&results=" [ results>> ] num-param - "&start=" [ start>> ] num-param - "&adult_ok=" [ adult-ok>> ] bool-param - "&similar_ok=" [ similar-ok>> ] bool-param - drop - ] "" make ; + yahoo-url clone + "appid" [ appid>> ] param + "query" [ query>> ] param + "region" [ region>> ] param + "type" [ type>> ] param + "format" [ format>> ] param + "language" [ language>> ] param + "country" [ country>> ] param + "site" [ site>> ] param + "subscription" [ subscription>> ] param + "license" [ license>> ] param + "results" [ results>> ] num-param + "start" [ start>> ] num-param + "adult_ok" [ adult-ok>> ] bool-param + "similar_ok" [ similar-ok>> ] bool-param + nip ; : factor-id "fRrVAKzV34GDyeRw6bUHDhEWHRedwfOC7e61wwXZLgGF80E67spxdQXuugBe2pgIevMmKwA-" ; From b5279bde62b4e7b82016a19e9a81432ef8f2fed8 Mon Sep 17 00:00:00 2001 From: Matthew Willis Date: Mon, 2 Jun 2008 16:11:41 -0700 Subject: [PATCH 16/19] implemented texture caching for pango-gadgets --- extra/cairo/gadgets/gadgets.factor | 6 +- extra/opengl/gadgets/gadgets.factor | 8 ++- extra/pango/cairo/cairo.factor | 3 + extra/pango/cairo/gadgets/gadgets.factor | 72 ++++++++++++++++-------- extra/pango/cairo/samples/samples.factor | 23 ++++++++ 5 files changed, 85 insertions(+), 27 deletions(-) create mode 100644 extra/pango/cairo/samples/samples.factor diff --git a/extra/cairo/gadgets/gadgets.factor b/extra/cairo/gadgets/gadgets.factor index 69252f8303..b42c47d79b 100644 --- a/extra/cairo/gadgets/gadgets.factor +++ b/extra/cairo/gadgets/gadgets.factor @@ -22,8 +22,10 @@ TUPLE: cairo-gadget < texture-gadget quot ; swap >>quot swap >>dim ; -M: cairo-gadget graft* ( gadget -- ) - GL_BGRA >>format dup +M: cairo-gadget format>> drop GL_BGRA ; + +M: cairo-gadget render* ( gadget -- ) + dup [ dim>> 2^-bounds ] [ quot>> copy-cairo ] bi >>bytes call-next-method ; diff --git a/extra/opengl/gadgets/gadgets.factor b/extra/opengl/gadgets/gadgets.factor index 1a15283048..de37969220 100644 --- a/extra/opengl/gadgets/gadgets.factor +++ b/extra/opengl/gadgets/gadgets.factor @@ -19,7 +19,9 @@ TUPLE: texture-gadget bytes format dim tex ; swap >>format swap >>bytes ; -:: render ( gadget -- ) +GENERIC: render* ( texture-gadget -- ) + +M:: texture-gadget render* ( gadget -- ) GL_ENABLE_BIT [ GL_TEXTURE_2D glEnable GL_TEXTURE_2D gadget tex>> glBindTexture @@ -63,8 +65,8 @@ M: texture-gadget draw-gadget* ( gadget -- ) ] with-translation ; M: texture-gadget graft* ( gadget -- ) - gen-texture >>tex [ render ] - [ f >>bytes f >>format drop ] bi ; + gen-texture >>tex [ render* ] + [ f >>bytes drop ] bi ; M: texture-gadget ungraft* ( gadget -- ) tex>> delete-texture ; diff --git a/extra/pango/cairo/cairo.factor b/extra/pango/cairo/cairo.factor index 907233a335..d1b536d9bc 100644 --- a/extra/pango/cairo/cairo.factor +++ b/extra/pango/cairo/cairo.factor @@ -130,5 +130,8 @@ MEMO: dummy-cairo ( -- cr ) : layout-text ( str -- ) layout swap -1 pango_layout_set_text ; +: show-layout ( -- ) + cr layout pango_cairo_show_layout ; + : families ( -- families ) pango_cairo_font_map_get_default list-families ; diff --git a/extra/pango/cairo/gadgets/gadgets.factor b/extra/pango/cairo/gadgets/gadgets.factor index 9e8a99515e..fb021e9320 100644 --- a/extra/pango/cairo/gadgets/gadgets.factor +++ b/extra/pango/cairo/gadgets/gadgets.factor @@ -1,30 +1,58 @@ ! Copyright (C) 2008 Matthew Willis. ! See http://factorcode.org/license.txt for BSD license. -USING: pango.cairo cairo cairo.ffi cairo.gadgets +USING: pango.cairo cairo cairo.ffi +cairo.gadgets namespaces arrays +fry accessors ui.gadgets assocs +sequences shuffle opengl opengl.gadgets alien.c-types kernel math ; IN: pango.cairo.gadgets -: (pango-gadget) ( setup show -- gadget ) - [ drop layout-size ] - [ compose [ with-pango ] curry ] 2bi ; +SYMBOL: textures +SYMBOL: dims +SYMBOL: refcounts -: ( quot -- gadget ) - [ cr layout pango_cairo_show_layout ] (pango-gadget) ; +: init-cache ( symbol -- ) + dup get [ drop ] [ H{ } clone swap set-global ] if ; -USING: prettyprint sequences ui.gadgets.panes -threads io.backend io.encodings.utf8 io.files ; -: hello-pango ( -- ) - 50 [ 6 + ] map [ - "Sans " swap unparse append - [ - cr 0 1 0.2 0.6 cairo_set_source_rgba - layout-font "今日は、 Pango!" layout-text - ] curry - gadget. yield - ] each - [ - "resource:extra/pango/cairo/gadgets/gadgets.factor" - normalize-path utf8 file-contents layout-text - ] gadget. ; +textures init-cache +dims init-cache +refcounts init-cache -MAIN: hello-pango +TUPLE: pango-gadget < cairo-gadget text font ; + +: cache-key ( gadget -- key ) + [ font>> ] [ text>> ] bi 2array ; + +: refcount-change ( gadget quot -- ) + >r cache-key refcounts get + [ [ 0 ] unless* ] r> compose change-at ; + +: ( font text -- gadget ) + pango-gadget construct-gadget + swap >>text + swap >>font ; + +: setup-layout ( {font,text} -- quot ) + first2 '[ , layout-font , layout-text ] ; + +M: pango-gadget quot>> ( gadget -- quot ) + cache-key setup-layout [ show-layout ] compose + [ with-pango ] curry ; + +M: pango-gadget dim>> ( gadget -- dim ) + cache-key dims get [ setup-layout layout-size ] cache ; + +M: pango-gadget graft* ( gadget -- ) [ 1+ ] refcount-change ; + +M: pango-gadget ungraft* ( gadget -- ) [ 1- ] refcount-change ; + +M: pango-gadget render* ( gadget -- ) + [ gen-texture ] [ cache-key textures get set-at ] + [ call-next-method ] tri ; + +M: pango-gadget tex>> ( gadget -- texture ) + dup cache-key textures get at + [ ] [ render* tex>> ] ?if ; + +USE: ui.gadgets.panes +: hello "Sans 50" "hello" gadget. ; diff --git a/extra/pango/cairo/samples/samples.factor b/extra/pango/cairo/samples/samples.factor new file mode 100644 index 0000000000..644d731d70 --- /dev/null +++ b/extra/pango/cairo/samples/samples.factor @@ -0,0 +1,23 @@ +! Copyright (C) 2008 Matthew Willis. +! See http://factorcode.org/license.txt for BSD license. +USING: prettyprint sequences ui.gadgets.panes +pango.cairo.gadgets math kernel cairo cairo.ffi +pango.cairo tools.time namespaces assocs +threads io.backend io.encodings.utf8 io.files ; + +IN: pango.cairo.samples + +: hello-pango ( -- ) + "monospace 10" "resource:extra/pango/cairo/gadgets/gadgets.factor" + normalize-path utf8 file-contents + gadget. ; + +: time-pango ( -- ) + [ hello-pango ] time ; + +! clear the caches, for testing. +: clear-pango ( -- ) + dims get clear-assoc + textures get clear-assoc ; + +MAIN: time-pango From 79a120d770a928b52a330c461054f75abfe6aca8 Mon Sep 17 00:00:00 2001 From: Matthew Willis Date: Mon, 2 Jun 2008 16:31:32 -0700 Subject: [PATCH 17/19] fix bugs and also destroy textures whose refcounts are 0 on ungraft* --- extra/pango/cairo/gadgets/gadgets.factor | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/extra/pango/cairo/gadgets/gadgets.factor b/extra/pango/cairo/gadgets/gadgets.factor index fb021e9320..4c46b4e501 100644 --- a/extra/pango/cairo/gadgets/gadgets.factor +++ b/extra/pango/cairo/gadgets/gadgets.factor @@ -44,15 +44,21 @@ M: pango-gadget dim>> ( gadget -- dim ) M: pango-gadget graft* ( gadget -- ) [ 1+ ] refcount-change ; -M: pango-gadget ungraft* ( gadget -- ) [ 1- ] refcount-change ; +: release-texture ( gadget -- ) + cache-key textures get delete-at* [ delete-texture ] [ drop ] if ; + +M: pango-gadget ungraft* ( gadget -- ) + dup [ 1- ] refcount-change + dup cache-key refcounts get at + zero? [ release-texture ] [ drop ] if ; M: pango-gadget render* ( gadget -- ) - [ gen-texture ] [ cache-key textures get set-at ] - [ call-next-method ] tri ; + [ gen-texture ] [ cache-key textures get set-at ] bi + call-next-method ; M: pango-gadget tex>> ( gadget -- texture ) dup cache-key textures get at - [ ] [ render* tex>> ] ?if ; + [ nip ] [ dup render* tex>> ] if* ; USE: ui.gadgets.panes : hello "Sans 50" "hello" gadget. ; From d0edbccf67335762fcbca7b24d2feeba591787e3 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 2 Jun 2008 21:59:23 -0500 Subject: [PATCH 18/19] Fix default main responder --- extra/http/server/server.factor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/http/server/server.factor b/extra/http/server/server.factor index 02424ef974..756a0de0ff 100755 --- a/extra/http/server/server.factor +++ b/extra/http/server/server.factor @@ -22,7 +22,7 @@ C: trivial-responder M: trivial-responder call-responder* nip response>> clone ; -main-responder global [ <404> get-global or ] change-at +main-responder global [ <404> or ] change-at : invert-slice ( slice -- slice' ) dup slice? [ [ seq>> ] [ from>> ] bi head-slice ] [ drop { } ] if ; From 180c7d317878c0d3f7c7b8f2f411e7854d4142c7 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 4 Jun 2008 19:14:20 -0500 Subject: [PATCH 19/19] Fix doublec's http.client bugs --- extra/http/client/client.factor | 9 ++++----- extra/openssl/openssl.factor | 8 ++++++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/extra/http/client/client.factor b/extra/http/client/client.factor index e6c8791e20..7b48bf93af 100755 --- a/extra/http/client/client.factor +++ b/extra/http/client/client.factor @@ -22,7 +22,7 @@ DEFER: http-request SYMBOL: redirects : redirect-url ( request url -- request ) - '[ , >url derive-url ensure-port ] change-url ; + '[ , >url ensure-port derive-url ensure-port ] change-url ; : do-redirect ( response data -- response data ) over code>> 300 399 between? [ @@ -100,12 +100,11 @@ M: download-failed error. : download ( url -- ) dup download-name download-to ; -: ( content-type content url -- request ) +: ( post-data url -- request ) "POST" >>method swap >url ensure-port >>url - swap >>post-data - swap >>post-data-type ; + swap >>post-data ; -: http-post ( content-type content url -- response data ) +: http-post ( post-data url -- response data ) http-request ; diff --git a/extra/openssl/openssl.factor b/extra/openssl/openssl.factor index 03343820db..28fa49dfce 100755 --- a/extra/openssl/openssl.factor +++ b/extra/openssl/openssl.factor @@ -2,7 +2,7 @@ ! See http://factorcode.org/license.txt for BSD license. USING: accessors byte-arrays kernel debugger sequences namespaces math math.order combinators init alien alien.c-types alien.strings libc -continuations destructors debugger inspector +continuations destructors debugger inspector splitting locals unicode.case openssl.libcrypto openssl.libssl io.backend io.ports io.files io.encodings.8-bit io.sockets.secure @@ -188,8 +188,12 @@ M: ssl-handle dispose* [ 256 X509_NAME_get_text_by_NID ] keep swap -1 = [ drop f ] [ latin1 alien>string ] if ; +: common-names-match? ( expected actual -- ? ) + [ >lower ] bi@ "*." ?head [ tail? ] [ = ] if ; + : check-common-name ( host ssl-handle -- ) - SSL_get_peer_certificate common-name 2dup [ >lower ] bi@ = + SSL_get_peer_certificate common-name + 2dup common-names-match? [ 2drop ] [ common-name-verify-error ] if ; M: openssl check-certificate ( host ssl -- )