REBOL [
Title: "Wiki"
Date: 3-Jul-2002
Name: Wiki
Version: 1.0.0
File: %Wiki.r
Author: "Andrew Martin"
Purpose: {Wiki. Creates a Wiki using Rebol, and the Xitami web server.}
Email: Al.Bri@xtra.co.nz
Web: http://valley.150m.com
Category: [util net markup 5]
]
Wiki_Directory: %/C/Rebol/Wiki/Files/ ; Where all the Wiki's .txt files are stored.
Remote: %/c/Xitami/cgi-bin/
if Remote <> what-dir [
write join Remote Rebol/script/header/File read Rebol/script/header/File
]
if not value? 'Values [
do %/C/Rebol/Values/Values.r
]
if none? Rebol/options/cgi/script-name [
browse http://localhost/cgi-bin/Wiki.r
quit
]
Forbidden: {\/:*?"<>|} ; A Wiki name cannot contain any of these characters.
Permitted: exclude Printable charset Forbidden
CGI: make object! [
Post?: "POST" = Rebol/options/cgi/request-method
Get?: "GET" = Rebol/options/cgi/request-method
Script-File: to-file Rebol/options/cgi/script-name
Script-URL: join make url! compose [
http (join Rebol/options/cgi/server-name Rebol/options/cgi/script-name)
] #"?"
Query: Rebol/options/cgi/query-string
]
Date_Rule: [
1 2 digit [#"/" | #"-"] [1 2 digit | 3 12 alpha] [#"/" | #"-"] [4 digit | 2 digit]
]
File_Rule: [some [some Permitted opt #"/"]]
See_Other: func [URL [url!]] [
print rejoin [
Rebol/options/cgi/server-protocol " Status: 303 See Other" newline
"Location: " URL newline
]
]
Deplus: func [Value [string!]] [
dehex replace/all copy Value #"+" #" "
]
Enspace: func [Value [file! string!]] [
replace/all copy Value #" " "%20"
]
Envelope: func [Title [string!] Body [block!]] [
content-type text/html
print ML compose/deep [
?xml/version/encoding "1.0" "UTF-8"
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11-frameset.dtd">
html [
head [
title (Title)
link/rel/type/href "stylesheet" "text/css" %/Stylesheet.css
]
body [(Body)]
]
]
]
Pages: make object! [
New: make object! [
Name: File: none
Rule?: does [
all [
CGI/Get?
string? CGI/Query
not empty? CGI/Query
parse/all CGI/Query [
[
Date_Rule (
error? try [
Name: to-string load deplus CGI/Query
]
)
| File_Rule (
Name: deplus CGI/Query
)
] end (
File: to-file Name
any [directory? File File: Extension File %.txt]
)
]
not exists? Wiki_Directory/:File
]
]
Execute: has [Title] [
either directory? File [
md/deep Wiki_Directory/:File
See_Other rejoin [CGI/Script-URL enspace Name]
] [
Envelope Title: join "New: " Name compose/deep [
h1 (Title)
(
Save/Html Name "Change text in Name text box to rename page." rejoin [
Name newline
head insert/dup copy "" #"*" length? Name newline
]
)
]
]
]
]
Save: make object! [
Rule?: does [
CGI/Post?
]
Execute: has [Post Length Name Text File] [
Post: make string! 2 + Length: to-integer Rebol/options/cgi/content-length
read-io Rebol/ports/input Post Length
parse/all Post [
"Name=" copy Name to #"&" skip
"Text=" copy Text to end
end
]
either none? Name [
See_Other CGI/Script-URL
] [
Name: deplus Name
File: extension to-file Name %.txt
either none? Text [
if exists? Wiki_Directory/:File [
delete Wiki_Directory/:File
]
See_Other rejoin [
CGI/Script-URL
use [Dir] [
either none? Dir: directory File [
""
] [
rejoin [
enspace directory File
]
]
]
]
] [
Text: deplus Text
make-dir/deep directory Wiki_Directory/:File
write/binary Wiki_Directory/:File Text
See_Other rejoin [CGI/Script-URL enspace Name]
]
]
]
Html: func [Name [string!] Hint [string!] Text [string!]] [
compose/deep [
form/method/action "POST" (CGI/Script-File) [
label [
"Name: " input/type/name/value "text" "Name" (Name) #" " (Hint)
] br
textarea/name/rows/cols/wrap/style "Text" 25 80 "virtual" "width:100%;" (
Text
)
div/align "right" [
input/type/value "submit" "Save"
]
]
]
]
]
Edit: make object! [
Title: "Edit"
Name: File: none
Command: join #"*" Title
Rule?: does [
all [
CGI/Get?
string? CGI/Query
not empty? CGI/Query
parse/all CGI/Query [
Command #"=" copy Name File_Rule end (
Name: deplus Name
File: extension to-file Name %.txt
)
]
exists? Wiki_Directory/:File
]
]
Execute: has [Page_Title] [
Page_Title: rejoin [Title ": " Name]
Envelope Page_Title compose/deep [
h1 (Page_Title)
(
Save/Html Name "Change text in Name text box to clone page."
read Wiki_Directory/:File
)
]
]
Html: func [Title [string!]] [
compose/deep [
form/method/action "GET" (CGI/Script-File) [
input/type/value "submit" "Edit"
input/type/name/value "hidden" (Command) (Title)
]
]
]
]
Random_Page: make object! [
random/seed now
Title: "Random"
Command: join #"*" Title
Rule?: does [
all [
CGI/Get?
string? CGI/Query
not empty? CGI/Query
parse/all CGI/Query [
Command #"=" Title end
]
]
]
Execute: has [File] [
until [
File: first random recursive-read Wiki_Directory
%.txt = extension? File
]
See_Other rejoin [CGI/Script-URL enspace copy/part File find File %.txt]
]
Html: does [
compose/deep [
form/method/action "GET" (CGI/Script-File) [
input/type/value "submit" (Title)
input/type/name/value "hidden" (Command) (Title)
]
]
]
]
Search: make object! [
Query: none
Title: "Search"
Command: join #"*" Title
Rule?: has [Rule Index] [
Rule: join Command #"="
all [
CGI/Get?
string? CGI/Query
not empty? CGI/Query
any [
all [
#"?" = last CGI/Query
any [
Query: dehex copy/part CGI/Query
find CGI/Query #"?"
]
]
all [
found? Index: find CGI/Query Rule
1 = Index: index? Index
found? Index: find/tail CGI/Query Rule
Query: deplus Index
]
]
]
]
Execute: has [Results Index Title] [
if empty? Query [
See_Other CGI/Script-URL
exit
]
Results: make block! 100
append Results [
tr [
th "Results"
th "Document"
]
]
foreach File recursive-read Wiki_Directory [
if %.txt = Extension? File [
Text: read Wiki_Directory/:File
if found? Index: find Text Query [
File: head clear extension? File
append Results compose/deep [
tr [
td [
(rejoin ["..." copy/part Index -35])
span/class "Hilight" (copy/part Index length? Query)
(append copy/part at Index 1 + length? Query 35 "...")
]
td [
a/href (rejoin [CGI/Script-File #"?" File]) (File)
]
]
]
]
]
]
Envelope Title: rejoin ["Search: " Query] compose/deep [
h1 (Title)
table/width "100%" [(Results)]
hr
table/width "100%" [
tr [
td/align "left" [(Contents/Html)]
td/align "left" [(Random_Page/Html)]
td/align "center" [(Search/Html Query)]
td/align "right" #" "
]
]
]
]
Html: func [Default [string!]] [
compose/deep [
form/method/action "GET" (CGI/Script-File) [
label [
(rejoin [Title SP Rebol/script/header/title ": "])
input/type/name/value "text" (Command) (Default)
]
input/type/value "submit" (Title)
]
]
]
]
View: make object! [
File: Name: none
Rule?: does [
all [
CGI/Get?
string? CGI/Query
not empty? CGI/Query
parse/all dehex CGI/Query [
[
copy Name Date_Rule (
error? try [
Name: to-string load Name
]
)
| copy Name File_Rule
]
end (
File: join to-file Name %.txt
)
]
exists? Wiki_Directory/:File
]
]
Execute: has [Title] [
Envelope Title: to-string filename File compose/deep [
(
eText/Wiki/Base read Wiki_Directory/:File rejoin [
CGI/Script-File #"?" any [directory File ""]
]
)
hr
table/width "100%" [
tr [
td/align "left" [(Contents/Html)]
td/align "left" [(Random_Page/Html)]
td/align "center" [(Search/Html Title)]
td/align "right" [(Edit/Html Name)]
]
]
]
]
]
Delete_Subdirectory: make object! [
Title: "Delete"
Command: join #"*" Title
Subdirectory: none
Rule?: does [
all [
CGI/Get?
string? CGI/Query
not empty? CGI/Query
parse/all CGI/Query [
Command #"=" copy Subdirectory File_Rule end (
Subdirectory: to-file deplus Subdirectory
)
]
]
]
Execute: has [Url] [
Url: CGI/Script-URL
if all [
exists? Wiki_Directory/:Subdirectory
empty? read Wiki_Directory/:Subdirectory
delete Wiki_Directory/:Subdirectory
not none? Subdirectory: directory Subdirectory
] [
Url: rejoin [CGI/Script-URL Subdirectory]
]
See_Other Url
]
Html: func [Subdirectory [file!]] [
compose/deep [
form/method/action "GET" (CGI/Script-File) [
input/type/value "submit" (Title)
input/type/name/value "hidden" (Command) (to-string Subdirectory)
]
]
]
]
Contents: make object! [
Title: "Contents"
Subdirectory: none
Rule?: does [
all [
CGI/Get?
any [
none? CGI/Query
empty? CGI/Query
all [
#"/" = last Subdirectory: dehex CGI/Query
exists? Wiki_Directory/:Subdirectory
Subdirectory: to-file Subdirectory
]
]
]
]
Execute: has [Links] [
Envelope Title compose/deep [
h1 (Title)
(all [Subdirectory compose [h2 (to-string Subdirectory)]])
(
Links: make block! 100
foreach File read either Subdirectory [
Wiki_Directory/:Subdirectory
] [
Wiki_Directory
] [
if any [
Directory? File
all [
%.txt = Extension? File
File: filename File
]
] [
append Links compose/deep [
li [
a/href (
rejoin [
CGI/Script-File #"?" either Subdirectory [
Subdirectory/:File
] [
File
]
]
) (File)
]
]
]
]
either empty? Links [
Delete_Subdirectory/Html Subdirectory
] [
compose/deep [
ul [(Links)]
]
]
)
hr
table/width "100%" [
tr [
td/align "left" [
(
either Subdirectory [Contents/Html] [""]
)
]
td/align "left" [(Random_Page/Html)]
td/align "right" [(Search/Html Title)]
]
]
]
]
Html: does [
compose/deep [
form/method/action "GET" (CGI/Script-File) [
input/type/value "submit" (Title)
]
]
]
]
]
foreach Page next first Pages [
Page: get in Pages Page
if Page/Rule? [
Page/Execute
quit
]
]
Envelope Rebol/script/header/Title compose/deep [
h1 (Rebol/script/header/Title)
p/class "Initial" (reform ["Now: " now])
pre [
"Rebol/options/cgi: " (mold Rebol/options/cgi)
]
]