Yaws wiki adapted to ERDialog

This Wiki was originally based on Joe Armstrongs wiki implementation. It has been ported to yaws and hacked quite a bit in general by Johan Bevemyr.

It is possible to have several Wiki instances on the same server. Just install the wiki/* files in the directory where you want a Wiki instance. This is easily done by running the updateWiki script and give a new directory as argument.

To edit the wiki preferences go to the wiki page WikiPreferences (for example by clicking on the "All Pages" or "Zombies" icon) and replace the gifs with our own favorites.

The password to the WikiPreferences page is ForgetMe.

Getting started --------------- WIKIINSTALLDIR is where the wiki is located. It must be part of your docroot. After installation, browse to the wiki directory. You will be asked to create a 'home' page, which will be the first wiki page. To find out about the special wiki formatting rules, go to WikiFormattingRules (e.g. from "All Pages"). To create a new page, just create a link to it by clicking EditMe on the home page (use the ~ character: "my new page ~TestPage"), and save the home page. The new link will show up as: "my new page TestPage???". The question marks means that the node TestPage doens't exist. Click on the question marks to create the the page.

Look and feel -------------

The layout of the Wiki pages is to a large extent controlled by two templates in WikiPreferences.files called template.html and template_info.html. There is an alternative look and feel bundled, just copy template2.html to template.html and template_info2.html to template_info.html.

To maintain


There are a number of useful scripts in the script directory.

updateWiki - takes a number of wiki directories and updates the .yaws files etc

getPassword - takes a path to a wob file as argument. Will print the password associated with that node.

importFiles - takes a path to a wob file as argument. Will add any files in the corresponding .files directory to the page. Useful when you want to import many files without going through the WEB GUI. Just copy the files to the .files directory and run the importFiles command.

Version Updated for the ERDialog version to 0.7

Version 1.0 Refactored the directory structure to work as an applet for ERDialog version 0.5Next file: Emakefile

Next file: Readme.erdwiki

Next file: ERDawiki-1.0.hweb

Next file: docroot/html/erdwiki/putPassword.yaws

Next file: docroot/html/erdwiki/thumbIndex.yaws

Next file: docroot/html/erdwiki/storePage.yaws

Next file: docroot/html/erdwiki/changePassword2.yaws

Next file: docroot/html/erdwiki/previewTagged.yaws

Next file: docroot/html/erdwiki/sendMeThePassword.yaws

Next file: docroot/html/erdwiki/lastEdited.yaws

Next file: docroot/html/erdwiki/storeNewPage.yaws

Next file: docroot/html/erdwiki/copyFiles.yaws

Next file: docroot/html/erdwiki/allPages.yaws

Next file: docroot/html/erdwiki/previewNewPage.yaws

Next file: docroot/html/erdwiki/WikiPreferences.files/template_info.html

Next file: docroot/html/erdwiki/WikiPreferences.files/template_info2.html

Next file: docroot/html/erdwiki/WikiPreferences.files/template2.html

Next file: docroot/html/erdwiki/WikiPreferences.files/custom.css

Next file: docroot/html/erdwiki/WikiPreferences.files/template.html

Next file: docroot/html/erdwiki/addFile.yaws

Next file: docroot/html/erdwiki/editFiles.yaws

Next file: docroot/html/erdwiki/getThumb.yaws

Next file: docroot/html/erdwiki/editTag.yaws

Next file: docroot/html/erdwiki/getMidSize.yaws

Next file: docroot/html/erdwiki/home.wob

Next file: docroot/html/erdwiki/showPage.yaws

Next file: docroot/html/erdwiki/editPage.yaws

Next file: docroot/html/erdwiki/allRefsToMe.yaws

Next file: docroot/html/erdwiki/slideShow.yaws

Next file: docroot/html/erdwiki/storeFiles.yaws

Next file: docroot/html/erdwiki/index.yaws

Next file: docroot/html/erdwiki/showOldPage.yaws

Next file: docroot/html/erdwiki/searchPage.yaws

Next file: docroot/html/erdwiki/wikiZombies.yaws

Next file: docroot/html/erdwiki/createNewPage.yaws

Next file: docroot/html/erdwiki/storeTagged.yaws

Next file: docroot/html/erdwiki/finalDeletePage.yaws

Next file: docroot/html/erdwiki/previewPage.yaws

Next file: docroot/html/erdwiki/changePassword.yaws

Next file: docroot/html/erdwiki/importFiles.yaws

Next file: docroot/html/erdwiki/deleteFiles.yaws

Next file: docroot/html/erdwiki/showHistory.yaws

Next file: docroot/html/erdwiki/doc/utils.html

Next file: docroot/html/erdwiki/doc/edoc-info

Next file: docroot/html/erdwiki/doc/wiki_utils.html

Next file: docroot/html/erdwiki/doc/modules-frame.html

Next file: docroot/html/erdwiki/doc/wiki_to_html.html

Next file: docroot/html/erdwiki/doc/wiki_diff.html

Next file: docroot/html/erdwiki/doc/wiki_yaws.html

Next file: docroot/html/erdwiki/doc/wiki.html

Next file: docroot/html/erdwiki/doc/wiki_plugin_dummy.html

Next file: docroot/html/erdwiki/doc/packages-frame.html

Next file: docroot/html/erdwiki/doc/wiki_plugin_menu.html

Next file: docroot/html/erdwiki/doc/wiki_plugin_backlinks.html

Next file: docroot/html/erdwiki/doc/wiki_format_txt.html

Next file: docroot/html/erdwiki/doc/overview.edoc

Next file: docroot/html/erdwiki/doc/wiki_split.html

Next file: docroot/html/erdwiki/doc/index.html

Next file: docroot/html/erdwiki/doc/overview-summary.html

Next file: docroot/html/erdwiki/doc/wiki_templates.html

Next file: docroot/html/erdwiki/doc/stylesheet.css

Next file: docroot/html/erdwiki/doc/wiki_vsn.html

Next file: priv/makedist-erdwiki.sh

Next file: priv/yaws-conf/erdwiki.yawsconf

Next file: priv/shared/makedocerdwiki.sh

Next file: priv/cleancnf.sh

Next file: priv/erdwiki/updateWiki.src

Next file: priv/erdwiki/importFiles

Next file: priv/erdwiki/getPassword.src

Next file: priv/erdwiki/addFile

Next file: priv/erdwiki/importFiles.src

Next file: priv/erdwiki/makedist.sh

Next file: priv/erdwiki/addFile.src

Next file: priv/erdwiki/cleancnf.sh

Next file: priv/erdwiki/getPassword

Next file: priv/erdwiki/updateWiki

Next file: priv/erdwiki/Makefile

Next file: priv/main-menus/erdwiki-menu.txt

Next file: priv/makefiles/Emakefile.erdwiki

Next file: ebin/erdwiki/erdawikisrc.txt

Next file: src/erdwiki/utils.erl

Next file: src/erdwiki/wiki_plugin_dummy.erl

Next file: src/erdwiki/wiki_plugin_menu.erl

Next file: src/erdwiki/wiki_utils.erl

Next file: src/erdwiki/wiki_to_html.erl

Next file: src/erdwiki/wiki_diff.erl

Next file: src/erdwiki/wiki_split.erl

Next file: src/erdwiki/wiki_vsn.erl

Next file: src/erdwiki/wiki.erl
\n"]. textarea(Name, Row, Cols, Txt) -> ["\n"]. h1(X) -> ["


"]. b(X) -> ["",X,""]. p() -> "

". p(X) -> ["

", X, "

\n"]. br() -> ["
\n"]. hr() -> ["
\n"]. body(X) -> [""]. pre(X) -> ["
"]. i2s(I) -> integer_to_list(I). initial_page_content() -> "\nEnter your text here\n". bgcolor(C) -> ["\n"]. top_header(Page) -> F1 = add_blanks_nicely(Page), ["


\n"]. add_blanks_nicely([H1,H2|T]) -> case {little_letter(H1), big_letter(H2)} of {true,true} -> [H1,$ ,H2|add_blanks_nicely(T)]; _ -> [H1|add_blanks_nicely([H2|T])] end; add_blanks_nicely([H|T]) -> [H|add_blanks_nicely(T)]; add_blanks_nicely([]) -> []. big_letter(H) when $A =< H, H =< $Z -> true; big_letter($) -> true; big_letter($) -> true; big_letter($) -> true; big_letter(_) -> false. little_letter(H) when $a =< H, H =< $z -> true; little_letter($) -> true; little_letter($) -> true; little_letter($) -> true; little_letter(_) -> false. show({bad_password, Page}, Root) -> template2(Root, "Error", "Incorrect password", [p("You have supplied an incorrect password"), p("To find out the the password fill " "in your email address and click on " "Show password. If you are " "the registered owner of this page " "then I will tell you the password."), form("POST", "sendMeThePassword.yaws", [input("hidden", "node", Page), "email address:", input("text", "email", ""), input("submit", "send", "Show password")]) ], false); show({illegal_filename, FileName, Reason}, Root) -> template2(Root, "Error", "Illegal filename", [p("You have supplied an illegal filename: " ++ FileName ++ "."), p(Reason)], false); show(X, Root) -> {html, [body("white"),"
"]}. show_error(Str) -> {html, [body("white"),"
","Error: ",Str,"
"]}. quote_lt([$<|T]) -> "<" ++ quote_lt(T); quote_lt([H|T]) -> [H|quote_lt(T)]; quote_lt([]) -> []. %%---------------------------- %% Utilities %% Notes on the encoding of URI's %% This comes from secition 8.2.1 of RFC1866 %% The default encoding for all forms is `application/x-www-form-urlencoded'. %% A form data set is represented in this media type as follows: %% %% 1. The form field names and values are escaped: space characters are %% replaced by `+', and then reserved characters are escaped as per [URL]; %% that is, non-alphanumeric characters are replaced by `%HH', a percent %% sign and two hexadecimal digits representing the ASCII code of the %% character. Line breaks, as in multi-line text field values, are %% represented as CR LF pairs, i.e. `%0D%0A'. %% %% 2. The fields are listed in the order they appear in the document with the %% name separated from the value by `=' and the pairs separated from each %% other by `&'. Fields with null values may be omitted. In particular, %% unselected radio buttons and checkboxes should not appear in the %% encoded data, but hidden fields with VALUE attributes present should. %% str2fileencoded([$_|T]) -> [$_|str2fileencoded(T)]; str2fileencoded([$ |T]) -> [$ |str2fileencoded(T)]; str2fileencoded([$.|T]) -> [$.|str2fileencoded(T)]; str2fileencoded([H|T]) -> case is_alphanum(H) of true -> [H|str2fileencoded(T)]; false -> {Hi,Lo} = byte2hex(H), [$%,Hi,Lo|str2fileencoded(T)] end; str2fileencoded([]) -> []. fileencoded2str(Str) -> urlencoded2str(Str). str2urlencoded([$\n|T]) -> "%0D%0A" ++ str2urlencoded(T); str2urlencoded([$.|T]) -> "." ++ str2urlencoded(T); str2urlencoded([H|T]) -> case is_alphanum(H) of true -> [H|str2urlencoded(T)]; false -> {Hi,Lo} = byte2hex(H), [$%,Hi,Lo|str2urlencoded(T)] end; str2urlencoded([]) -> []. str2formencoded([$ |T]) -> [$+|str2formencoded(T)]; str2formencoded([$.|T]) -> [$.|str2formencoded(T)]; str2formencoded([$\n|T]) -> "%0D%0A" ++ str2formencoded(T); str2formencoded([H|T]) -> case is_alphanum(H) of true -> [H|str2formencoded(T)]; false -> {Hi,Lo} = byte2hex(H), [$%,Hi,Lo|str2formencoded(T)] end; str2formencoded([]) -> []. byte2hex(X) -> {nibble2hex(X bsr 4), nibble2hex(X band 15)}. nibble2hex(X) when X < 10 -> $0 + X; nibble2hex(X) -> $A + X - 10. is_alphanum(X) when $0 =< X, X =< $9 -> true; is_alphanum(X) when $a =< X, X =< $z -> true; is_alphanum(X) when $A =< X, X =< $Z -> true; is_alphanum(_) -> false. urlencoded2str([$%,Hi,Lo|T]) -> [decode_hex(Hi, Lo)|urlencoded2str(T)]; urlencoded2str([$+|T]) -> [$ |urlencoded2str(T)]; urlencoded2str([H|T]) -> [H|urlencoded2str(T)]; urlencoded2str([]) -> []. %% decode_hex %% decode_hex(Hex1, Hex2) -> hex2dec(Hex1)*16 + hex2dec(Hex2). hex2dec(X) when X >=$0, X =<$9 -> X-$0; hex2dec($A) -> 10; hex2dec($B) -> 11; hex2dec($C) -> 12; hex2dec($D) -> 13; hex2dec($E) -> 14; hex2dec($F) -> 15; hex2dec($a) -> 10; hex2dec($b) -> 11; hex2dec($c) -> 12; hex2dec($d) -> 13; hex2dec($e) -> 14; hex2dec($f) -> 15. %% %% MR: Is this really necessary ? %% We can now use filelib:fold_files/5 files(Dir, Re) -> Re1 = regexp:sh_to_awk(Re), find_files(Dir, Re1, []). find_files(Dir, Re, L) -> case file:list_dir(Dir) of {ok, Files} -> find_files(Files, Dir, Re, L); {error, _} -> L end. find_files([File|T], Dir, Re, L) -> FullName = Dir ++ [$/|File], case file_type(FullName) of regular -> case regexp:match(FullName, Re) of {match, _, _} -> find_files(T, Dir, Re, [FullName|L]); _ -> find_files(T, Dir, Re, L) end; _ -> find_files(T, Dir, Re, L) end; find_files([], _, _, L) -> L. file_type(File) -> case file:read_file_info(File) of {ok, Facts} -> case element(3, Facts) of regular -> regular; directory -> directory; _ -> error end; _ -> error end. %% read_page(Page, Root) -> {File,FileDir} = page2filename(Page, Root), %% io:format("Reading:~p~n",[Page]), case file:read_file(File) of {ok, Bin} -> {wik002,_Pwd,_Email,_Time,_Who,OldTxt,_Files,_Patches} = bin_to_wik002(Bin), {ok, OldTxt}; _ -> error end. %% mime_type(Name) -> case lists:reverse(Name) of "cod."++_ -> "application/octet-stream"; "piz."++_ -> "application/x-zip"; "lmth."++_ -> "text/html"; "mth."++_ -> "text/html"; "fdp."++_ -> "application/pdf"; _ -> "application/octet-stream" end. %% %% Applies the Funs in the list to the Args. Return the value of the %% first Fun that returns a non-ok value, otherwise ok. check_precon([],_Args) -> ok; check_precon([F|Fs], Args) -> case apply(F,Args) of ok -> check_precon(Fs, Args); NotOk -> NotOk end. %% getopt(Key, KeyList) -> getopt(Key, KeyList, undefined). % getopt(Key, KeyList, Default) when atom (Key) -> % getopt(atom_to_list(Key), KeyList, Default); getopt(Key, KeyList, Default) -> case lists:keysearch(Key, 1, KeyList) of false -> Default; {value, Tuple} -> Val = element(2,Tuple), if Val == undefined -> Default; true -> Val end end. getopt_options(Key, KeyList) when atom(Key) -> getopt_options(atom_to_list(Key), KeyList); getopt_options(Key, KeyList) -> case lists:keysearch(Key, 1, KeyList) of {value, Tuple} when size(Tuple) >= 3 -> element(3,Tuple); _ -> undefined end. % basename(FilePath) -> case string:rchr(FilePath, $\\) of 0 -> %% probably not a DOS name filename:basename(FilePath); N -> %% probably a DOS name, remove everything after last \ basename(string:substr(FilePath, N+1)) end. % getPassword([File]) -> case file:read_file(File) of {ok, Bin} -> {wik002,Pwd,Email,Time,Who,OldTxt,Files,Patches} = bin_to_wik002(Bin), io:format("Password is: '~s'\n", [Pwd]), halt(); _ -> io:format("Error - failed to open ~s\n", [File]), halt() end. %% tostring(A) when atom(A) -> atom_to_list(A); tostring(S) -> S. % wobfile_to_filedir(Wob) -> WobFile = tostring(Wob), string:substr(WobFile, 1, length(WobFile)-3)++"files". %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% forms(Method, Action, Args) -> ["", Args, "
\n"]. %% --> searchPara([Para|Paralist]) -> case Para of {"search", undefined, []} -> []; {"search", Search, []} -> case regexp:parse(Search) of {ok, RE} -> Search; {error, Error} -> {error, Error} end; _Other -> searchPara(Paralist) end; searchPara([]) -> []. searchPages(SearchPost, Root, Prefix) -> case searchPara(SearchPost) of [] -> S0 = [forms("POST", "searchPage.yaws", [input("submit", "searchstart", "Search"), input("text", "search", "")])], template2(Root,"Search", "Wiki page search", [S0, "
", h1("Nothing to find")], false); {error, Error} -> S0 = [forms("POST", "searchPage.yaws", [input("submit", "searchstart", "Search"), input("text", "search", "")])], template2(Root,"Search", "Wiki page search", [S0, "
", h1(io_lib:format("Error in the regular " "expression \"~p\"", [Error]))], false); Search -> Files = sort(files(Root, "*.wob")), {Sres, _S} = lists:mapfoldl(fun(F, S) -> {searchPage(F, S), S} end, Search, Files), Sres_sort = reverse(sort(Sres)), S1 = lists:map(fun({Matches, Fx}) -> [p(),i2s(Matches)," ", wiki_to_html:format_link( filename:basename(Fx, ".wob"), Root), "

"] end, Sres_sort), S0 = [forms("POST", "searchPage.yaws", [input("submit", "searchstart", "Search"), input("text", "search", Search)])], template2(Root,"Search", "Wiki page search", [S0, "
", h1("Number of matches found per page"), S1], false) end. searchPage(File, Search) -> case file:read_file(File) of {ok, Bin} -> {wik002,_Pwd,_Email,_Time,_Who,Txt,_Files,_Patches} = bin_to_wik002(Bin), {match, Matches} = regexp:matches(Txt, Search), {length(Matches), File}; _ -> io:format("Error - failed to open ~s\n", [File]), {-1, File} end.

Next file: src/erdwiki/wiki_plugin_backlinks.erl

Next file: src/erdwiki/wiki_yaws.erl

Next file: src/erdwiki/wiki_format_txt.erl

Next file: src/erdwiki/wiki_templates.erl

Next file: src/erdwiki/Makefile

Next file: src/erdwiki/doc/overview.edoc