runWikiAW

This is a modification of the runWiki project that ships with Run BASIC. It is a work in progress and it has few features. If you want a wiki with many features, try Neal Collins's [|RunWikiNG] (the Next Generation).

See how this code looks in use:'[|RunWikiAW Online]

Please read the notes at the top of the code and fill in your own info before running the program for the first time.

code format="vbnet" 'June 18, 2009 'added parse for crlf -> 'added wikitext markup/parsing 'changed to double braces for links 'changed so page and member list displays are ordered 'added buttons to editing pages for HTML tags 'added preview ability to editing pages

'IMPORTANT: set dbname$, adminpwd$, mailuser$, server$ and mailpwd$ 'and other design and usage variables at top of code before installing. 'Password reminder and any other email features require sendemail.exe and 'sendemail.pl to be installed in the root directory of Run BASIC. 'Run Wiki AW 'Based on Run Wiki by Shoptalk Systems 'Public Domain

'Global vars global mailuser$, server$, mailpw$, navColor$, noticeColor$ global bannerImage$, dbname$, adminpwd$, wikiTitle$, totaltags, totaltags2 global currentName$, currentContent$, #editPage, #wiki, #user, #password global #login, #register, #reminder, #goHome, #pagelist, #profile, #area global #memberlist, #doNewPage, #noreminder, #createNewPage, #history global user$, userpassword$, useremail$, slash$, crlf$ '************************************* '************************************* mailuser$ = "your email address" server$ = "your email server:port" mailpwd$ = "your email password" adminpwd$ = "desired admin password" dbname$ = "desired database file name" wikiTitle$ = "Wiki Title" bannerImage$ = "/resources/your_banner.JPG" '************************************* '************************************* 'DESIGN VARIABLES navColor$ = "#FD7" noticeColor$ = "#FF9"

if Platform$ = "unix" then slash$ = "/" else slash$ = "\" end if

crlf$=chr$(13)+chr$(10) totaltags=5 dim tags$(totaltags,2) totaltags2=7 dim tags2$(totaltags2,2)

call setCSS call SetWikiTags call createDefaultUser call createHomePageRow currentName$ = "HOME"

[refresh] call loadCurrentPage call displayCurrentPage wait

sub displayCurrentPage call doNav call connect 'is page locked?, get last author, time and date #wiki execute("select * from pages where NAME = """; currentName$; """") if #wiki hasAnswer then #row = #wiki #nextrow pagelock = #row LOCKED pagedate$ = #row date$ pageuser$ = #row user$ pagetime$ = #row pagetime$ if not(pagelock) then pagelock=0 end if call disconnect

div page print "This page: "; currentName$ if (user$ <> "") then if (pagelock=0) then 'logged in users can edit unlocked pages link #editPage, "Edit", [editPage] html " " link #history, "History", [history] else html "PAGE LOCKED " end if   end if    if user$ = "admin" then 'admin can delete or lock page html " " link #deletePage, "Delete", [deletePageClick] html " " if pagelock=0 then link #lockPage, "Lock", [lockPage] else link #unlockPage, "Unlock",[unlockPage] end if  end if    print:html " " call renderPage currentContent$ end div div footer  'display last edit info at bottom of page print:print "Last edit ";pagetime$;", ";pagedate$;" by ";pageuser$ end div end sub

[deletePageClick]'admin selected member from list, can delete if desired cls div notice if upper$(currentName$)<>"HOME" then link #deletecurrentpage, "Delete page with name: "; currentName$, [deletePage]:print else html "Cannot delete HOME page. " end if   link #noreminder, "Cancel", [goHome] end div wait

[deletePage] 'admin has elected to delete a page 'delete from pages table and all copies from pages_history table call connect #wiki execute("delete from PAGES_HISTORY where NAME = '";currentName$;"'") #wiki execute("delete from PAGES where NAME = '";currentName$;"'") call disconnect goto [goHome]

[lockPage] 'LOCKED = 1 if page is locked call connect query$ = "update pages set LOCKED = 1 where NAME = """; currentName$; """" call execute query$ call disconnect goto [refresh]

[unlockPage] 'LOCKED = 0 if page is unlocked call connect query$ = "update pages set LOCKED = 0 where NAME = """; currentName$; """" call execute query$ call disconnect goto [refresh]

[goHome] 'after some actions are completed, display home page DeleteName$ = "" currentName$ = "HOME" call loadCurrentPage call displayCurrentPage wait

[memberlist] 'only admins can see memberlist. Doesn't show passwords. call doNav div lister link #closelist, "HOME", [goHome] html " " call connect #wiki execute("SELECT name, email from USERS order by name asc; ") #wiki LINK("NAME", "[userNameClick]") #wiki CAPTION("List of Members in this Wiki") render #wiki call disconnect end div wait

[userNameClick]'admin selected member from list, can delete if desired cls DeleteName$ = EventKey$ div notice if DeleteName$ <> "admin" then link #deleteuser, "Delete user with name: "; DeleteName$, [deleteUser]:print else html "Cannot delete admin account. " end if   link #noreminder, "Cancel", [goHome] end div wait

[deleteUser] 'admin has elected to delete a user call connect #wiki execute("delete from USERS where NAME = '";DeleteName$;"'") call disconnect goto [goHome]

[pagelist] call doNav div lister link #closelist, "HOME", [goHome] html " " call connect #wiki execute("SELECT NAME, DATE, PAGETIME, USER from PAGES order by NAME asc; ") if #wiki hasAnswer then #wiki LINK("NAME", "[pageNameClick]") #wiki CAPTION("List of Pages in this Wiki") 'helpfile documents the columnames method, but it doesn't appear to work '#wiki COLUMNNAMES("Page Name, Date, Time, Last Author, Locked") render #wiki end if   call disconnect end div wait

[pageNameClick]'name was chosen from page list, display it currentName$ = EventKey$ call loadCurrentPage call displayCurrentPage wait

[history] cls div notice link #closelist, "HOME", [goHome] html " " call connect #wiki execute("SELECT DATE, PAGETIME from PAGES_HISTORY where NAME = """; currentName$; """ order by DATE desc;") if #wiki hasAnswer then #wiki LINK("DATE", "[historyClick]") #wiki CAPTION("History of ";currentName$) html "Click on a date from the list to revert the page." render #wiki print:print link #noRevert, "Cancel", [cancelNewHistory] else print "There is no history for this page.":print link #nohistory, "Return to Page", [refresh] end if   call disconnect end div wait

[historyClick]'name was chosen from page list, display it   call connect #wiki execute("SELECT DATE, PAGETIME, CONTENT from PAGES_HISTORY where NAME = """; currentName$; """") for i = 0 to RowIndex if #wiki hasAnswer then #row = #wiki #nextRow hContent$ = #row CONTENT$ end if   next query$ = "update pages set DATE = """; date$("mm/dd/yy"); """ where NAME = """; currentName$; """" call execute query$ query$ = "update pages set PAGETIME = """; time$; """ where NAME = """; currentName$; """" call execute query$ query$ = "update pages set USER = """; user$;""" where NAME = """; currentName$; """" call execute query$ currentContent$ = hContent$ call disconnect [cancelNewHistory] RowIndex=-1 call displayCurrentPage wait

call disconnect

wait

[profile] cls div notice link #closelist, "HOME", [goHome] html " " call connect #wiki execute("SELECT * from USERS where NAME = """;user$;"""") if #wiki hasAnswer then #row = #wiki #nextrow profilename$ = #row name$ profileemail$ = #row email$ profilepassword$ = #row password$ #wiki execute("SELECT name, email from USERS where NAME = '";user$;"'") render #wiki print:print:print end if   call disconnect

html " Change Profile Information " html "You cannot change your username. You can change your email address and password. " html "You must enter a valid email address if you want to retrieve your password in the future. " print "New Password: "; passwordbox #p, profilepassword$, 15 : print print "New Email Address: "; textbox #e, profileemail$, 15 : print link #updateprofile, "Update Profile", [updateprofile]:print link #cancelprofile, "Cancel", [refresh]

end div wait

[updateprofile] puserpassword$ = #p contents$ puseremail$ = #e contents$ if (puserpassword$ = "") or (puseremail$ = "") then [profile] 'see if username in use call connect 'see if email in use #wiki execute("SELECT * from USERS where email = '"; puseremail$;"'") if #wiki hasanswer then #row = #wiki #nextrow tempemail$ = #row email$ if tempemail$<>profileemail$ then call disconnect goto [pnameInUse] end if end if  call disconnect query$ = "update users set PASSWORD= """; doubleQuote$(puserpassword$); """ where NAME = """; profilename$; """" call connect #wiki execute(query$) call disconnect query$ = "update users set EMAIL= """; doubleQuote$(puseremail$); """ where NAME = """; profilename$; """" call connect #wiki execute(query$) call disconnect user$ = puser$ call displayCurrentPage wait

[pnameInUse] cls div notice link #closelist, "HOME", [goHome] html " " print "The new email you've chosen is already in use by another member. Profile update cancelled." end div wait

sub doNav 'display top-title info and left navbar cls div title print wikiTitle$ div copyright print "based on Run Wiki by Shoptalk Systems" html "Visit the Run BASIC Home Page" end div end div div navigation if user$ = "" then print "Welcome, Visitor" print "User: "; textbox #user, "", 11 : print print "Password: "; passwordbox #password, "", 8 : print link #login, "Log in", [login] :print link #register, "Register", [register] : print link #reminder, "Password Reminder", [forgotpassword]: print else print "Welcome, "; user$ link #logout, "Log out", [logout] : print link #profile, "Profile", [profile] : print link #createNewPage, "New Page", [navCreateNewPage] end if

html " " link #goHome, "HOME", [goHome] : print link #pagelist, "Page List", [pagelist] : print 'admins can list and delete members if user$ = "admin" then link #memberlist, "Member List", [memberlist] end div end sub

[navCreateNewPage] 'create new page from link on navbar cls div notice print "Type a name for the new page." textbox #newpagename, "", 15 : print link #donewpage, "Create", [getName]:print link #noreminder, "Cancel", [goHome] end div wait

[getName] newPageName$ = #newpagename contents$ if newPageName$ = "" then newPageName$ = date$("dd/mm/yyyy") call doNav call createPage newPageName$ wait

[login] call connect #wiki execute("SELECT * from USERS where name = '"; #user contents$; "' and password = '"; #password contents$; "'") if #wiki hasanswer then user$ = #user contents$ call disconnect else call disconnect cls div notice print "Login failed. Bad username or password." link #retry, "Try again.", [logout] wait end div end if call displayCurrentPage wait

[logout] user$ = "" userpassword$ = "" useremail$ = "" call displayCurrentPage wait [forgotpassword] cls div notice print "Request Password by Email" print "Your email address: "; textbox #youremail, "", 15 : print link #reminder, "Send Password", [sendpassword]:print link #noreminder, "Cancel", [logout] end div wait

[sendpassword] userpw$ = "" 'reset var youremail$ = #youremail contents$ if youremail$ = "" then [logout] call connect #wiki execute("SELECT * from USERS where email = '"; youremail$;"'") if #wiki hasanswer then result$ = #wiki nextrow$(",") userpw$ = word$(result$,2,",") usern$ = word$(result$,1,",") end if call disconnect if userpw$ <> "" then subject$ = "Password Reminder" message$ = "Your wiki username is ";usern$;" . Your wiki password is ";userpw$;" ." gosub [sendemail] end if

cls div notice print "Your password had been sent.": print link #pwsentok, "Return to Wiki", [logout]:print end div wait

[register] cls div notice html " Register for Membership to this Wiki " html "You must enter a valid email address if you want to retrieve your password in the future. " print "Desired Username: "; textbox #u, "", 15 : print print "Desired Password: "; passwordbox #p, "", 15 : print print "Email Address: "; textbox #e, "", 15 : print link #newlogin, "Join Wiki", [newlogin]:print link #cancelnewlogin, "Cancel", [logout] end div wait

[nameInUse] cls div notice print "The username or email you've chosen is already in use. Try another, please." print "Desired Username: "; textbox #u, "", 15 : print print "Desired Password: "; passwordbox #p, "", 15 : print print "Email Address: "; textbox #e, "", 15 : print link #newlogin, "Join Wiki", [newlogin]:print link #cancelnewlogin, "Cancel", [logout] end div wait

[newlogin] user$ = #u contents$ userpassword$ = #p contents$ useremail$ = #e contents$ if (user$ = "") or (userpassword$ = "") or (useremail$ = "") then [logout] 'see if username in use call connect #wiki execute("SELECT * from USERS where name = '"; user$;"'") if #wiki hasanswer then call disconnect goto [nameInUse] end if 'see if email in use #wiki execute("SELECT * from USERS where email = '"; useremail$;"'") if #wiki hasanswer then call disconnect goto [nameInUse] end if     #wiki execute("SELECT * FROM sqlite_master WHERE name = 'users' and type='table'") if (#wiki hasanswer) then #wiki execute("INSERT INTO users (NAME, PASSWORD, EMAIL) VALUES('";user$;"', '";userpassword$;"','";useremail$;"')") end if   call disconnect call displayCurrentPage wait

sub renderPage content$ buffer$ = Parse$(content$) while buffer$ <> "" leftBrace = instr(buffer$, "")   if leftBrace = 0 then      html buffer$      buffer$ = ""    else      if leftBrace > 1 then        html left$(buffer$, leftBrace-1)        buffer$ = mid$(buffer$, leftBrace)      else  'leftBrace = 1        rightBrace = instr(buffer$, "") if rightBrace < 3 then html buffer$ buffer$ = "" else queryName$ = mid$(buffer$, 3, rightBrace - 3) if (pageExists(queryName$)) then link #exists, queryName$, loadPage #exists setkey(queryName$) else link #doesntExist, "?"+queryName$, createPage #doesntExist setkey(queryName$) end if         buffer$ = mid$(buffer$, rightBrace+2) end if     end if    end if  wend end sub

sub createPage name$ cls if user$<>"" then html " Create Page - "; name$; " " textarea #area, "" : print #area setid("tablet") link #accept, "Accept", [acceptNew] : print " "; #accept setkey(name$) link #cancel, "Cancel", [cancelNew]:print " "; link #previewEdit, "Preview", [previewEdit] :print:print link #acceptEdit, "Accept", [acceptEdit] :html " " link #cancelEdit, "Cancel", [cancelEdit] :html " " link #previewEdit, "Preview", [previewEdit] :print:print print "To format your text display, use wikitext or HTML tags." print "Click a button below to add tags, or type them yourself.":print button #bold, "Bold", doFormat button #italic, "Italic", doFormat button #underline, "Underline", doFormat button #head, "Heading", doFormat button #horizontalrule, "Horizontal Rule", doFormat button #unorderedlist, "Unordered List", doFormat button #orderedlist, "Ordered List", doFormat print button #wikilink, "New Page", doFormat button #color, "Colored Font", doFormat button #face, "Font Face/Size", doFormat button #pre, "Preformatted Text", doFormat print:print "Wikitext markup:" print "**bold** //italic// __underline__ ===heading=== Horizontal Rule" print "/*Unordered List *Item One *Item Two */" print "/#Ordered List #Item One #Item Two #/" else print "You must be logged in to create a new page or to edit an existing page." link #cancel, "Cancel", [cancelNew] end if end sub

sub loadPage name$ currentName$ = name$ call loadCurrentPage call displayCurrentPage end sub

[acceptNew] newContent$ = #area contents$ call connect #wiki execute("insert into pages (NAME, CONTENT, DATE, PAGETIME, USER) values ("""; EventKey$; """, """; doubleQuote$(newContent$); """, """; date$("mm/dd/yy"); """, """; time$;""", """;user$;""")") call disconnect currentName$ = EventKey$ currentContent$ = newContent$ [cancelNew] call displayCurrentPage wait

function pageExists(name$) call connect #wiki execute("SELECT * from pages where NAME="""; name$; """") pageExists = #wiki hasAnswer call disconnect end function

[editPage] cls html " Edit page "; currentName$; " " textarea #area, currentContent$ : print #area setid("tablet") link #acceptEdit, "Accept", [acceptEdit] :html " " link #cancelEdit, "Cancel", [cancelEdit] :html " " link #previewEdit, "Preview", [previewEdit] :print:print print "To format your text display, use wikitext or HTML tags." print "Click a button below to add tags, or type them yourself.":print button #bold, "Bold", doFormat button #italic, "Italic", doFormat button #underline, "Underline", doFormat button #head, "Heading", doFormat button #horizontalrule, "Horizontal Rule", doFormat button #unorderedlist, "Unordered List", doFormat button #orderedlist, "Ordered List", doFormat print button #wikilink, "New Page", doFormat button #color, "Colored Font", doFormat button #face, "Font Face/Size", doFormat button #pre, "Preformatted Text", doFormat print:print "Wikitext markup:" print "**bold** //italic// __underline__ ===heading=== Horizontal Rule" print "/*Unordered List *Item One *Item Two */" print "/#Ordered List #Item One #Item Two #/" wait [previewEdit] previewContent$ = #area contents$ print:html " PREVIEW " call renderPage previewContent$ print:html "END PREVIEW " wait

sub doFormat handle$ select case handle$ case "#wikilink" #area print("new page name") case "#bold" #area print("**bold text**") case "#italic" #area print("//italic text//") case "#underline" #area print("__underlined text__") case "#color" #area print("colored text ") case "#face" #area print("text in different face and size ") case "#pre" #area print(crlf$+" preformatted text "+crlf$) case "#horizontalrule" #area print("") case "#unorderedlist" #area print(crlf$+"/*List Name *First Item *Second Item */"+crlf$) case "#orderedlist" #area print(crlf$+"/#List Name #Item One #Item Two #/"+crlf$) case "#head" #area print("==Heading Text==") end select end sub
 * 1) area print(" ")
 * 1) area print(" ")

[acceptEdit] newContent$ = #area contents$ call connect 'add page current to history: query$ = "insert into pages_history select * from pages where name = '"; doubleQuote$(currentName$); "'" call execute query$ 'change page info: query$ = "update pages set CONTENT = """; doubleQuote$(newContent$); """ where NAME = """; currentName$; """" call execute query$ query$ = "update pages set DATE = """; date$("mm/dd/yy"); """ where NAME = """; currentName$; """" call execute query$ query$ = "update pages set PAGETIME = """; time$; """ where NAME = """; currentName$; """" call execute query$ query$ = "update pages set USER = """; user$;""" where NAME = """; currentName$; """" call execute query$ 'add page current to history: query$ = "insert into pages_history select * from pages where name = '"; doubleQuote$(currentName$); "'" call execute query$ call disconnect currentContent$ = newContent$ [cancelEdit] call displayCurrentPage wait

sub loadCurrentPage call connect #wiki execute("select (CONTENT) from pages where NAME = """; currentName$; """") if #wiki hasAnswer then currentContent$ = #wiki nextRow$("") else currentContent$ = "Page named "; currentName$; " does not exist." end if call disconnect end sub

sub createDefaultUser call connect #wiki execute("SELECT * FROM sqlite_master WHERE name = 'users' and type='table'") if not(#wiki hasanswer) then #wiki execute("create table users(NAME text, PASSWORD text, EMAIL text)") #wiki execute("INSERT INTO users (NAME, PASSWORD, EMAIL) VALUES('admin', '";adminpwd$;"', '";mailuser$;"' )") end if call disconnect end sub

sub createHomePageRow call connect #wiki execute("SELECT * FROM sqlite_master WHERE name = 'pages' and type='table'") if not(#wiki hasanswer) then #wiki execute("create table pages (NAME text, CONTENT text, DATE text, PAGETIME text, USER text, LOCKED integer) ") end if #wiki execute("SELECT * FROM sqlite_master WHERE name = 'pages_history' and type='table'") if not(#wiki hasanswer) then #wiki execute("create table pages_history (NAME text, CONTENT text, DATE text, PAGETIME text, USER text, LOCKED integer) ") end if #wiki execute("select * from pages") if not(#wiki hasanswer) then content$ = "This is your initial home page for Run Wiki. Please edit this and make it your own." #wiki execute("INSERT INTO PAGES (NAME, CONTENT, DATE, PAGETIME, USER, LOCKED) VALUES ('HOME', '"; content$; "', """; date$("mm/dd/yy"); """, """; time$; """, 'admin', 0)") end if call disconnect end sub

sub connect sqliteconnect #wiki, dbname$ end sub

sub disconnect #wiki disconnect end sub

sub execute sqlStatement$ #wiki execute(sqlStatement$) end sub

function doubleQuote$(string$) if instr(string$, chr$(34)) then for x = 1 to len(string$) if mid$(string$, x, 1) = chr$(34) then doubleQuote$ = doubleQuote$ + chr$(34) doubleQuote$ = doubleQuote$ + mid$(string$, x, 1) next x else doubleQuote$ = string$ end if end function

sub setCSS cssid #title, "{ font-family: Tahoma; font-size: 20pt; font-weight: bold; background-repeat: no-repeat; background-image: url('";bannerImage$;"') ; height: 90px}" cssid #copyright, "{ font-size: 8pt }" cssid #navigation, "{font-family: Tahoma; padding: 4px; background: ";navColor$;"; width: 150px; ; min-height: 300px; float: left}" cssid #page, "{font-family: Tahoma; padding: 4px; margin-left: 155px; white-space: normal; min-height: 300px}" cssid #lister, "{font-family: Tahoma; padding: 4px; background: ";noticeColor$;"; margin-left: 155px}" cssid #notice, "{font-family: Tahoma; padding: 4px; background: ";noticeColor$;"}" cssid #footer, "{font-style: italic; margin-left: 155px; border-top: 1px dashed #898;}" cssid #tablet, "{ padding: 6px; border-style: solid ; border-color: black; border-width: 2px ; width: 600px; height 450px}" cssclass "td", "{ padding: 6px; border-style: solid ; border-color: black; border-width: 1px ; background-color: #DDD}" end sub

sub SetWikiTags 'tags that require closing tags: j=0 'counter variable t$ = "** b // i __ u === h3 == h2 " for i = 1 to totaltags j=j+1 tags$(i, 1) = word$(t$, j)   j=j+1 tags$(i, 2) = word$(t$, j) next

'other tags: j=0 'counter variable t$ = " hr /* ul */ /ul /# ol #/ /ol * li # li" for i = 1 to totaltags2 j=j+1 tags2$(i, 1) = word$(t$, j)   j=j+1 tags2$(i, 2) = word$(t$, j) next end sub

Function Parse$(p$) for i = 1 to totaltags 'parse tags that close w$=tags$(i,1):h$=tags$(i,2):w=len(w$) h1$="":h2$="" 'add angle brackets to tag [again] fnd = instr(p$, w$) if fnd > 0 then tstart = fnd p$=Replace$(p$,w$,h1$,tstart) 'replace first wiki tag tstop = instr(p$, w$, fnd+w) if tstop <> 0 then p$=Replace$(p$,w$,h2$,tstop) 'replace closing wiki tag goto [again] end if end if next

for i = 1 to totaltags2 'parse other tags w$=tags2$(i,1):h$=tags2$(i,2):w=len(w$) h1$="" 'add angle brackets to tag [again2] fnd = instr(p$, w$) if fnd then p$=Replace$(p$,w$,h1$,fnd) 'replace wiki tag goto [again2] end if next

fnd=instr(p$, crlf$) 'add line breaks while fnd p$=Replace$(p$,crlf$," ",fnd) fnd=instr(p$, crlf$) wend

Parse$=p$ end function

FUNCTION Replace$(string$, old$, new$, pos) r$ = left$(string$, pos-1) s$ = mid$(string$, pos+len(old$)) Replace$ = r$ + new$ + s$ end function

[sendemail] 'requires subject$, youremail$, message$ in main body of program sendmaildir$ = DefaultDir$;slash$;"sendEmail.exe" '--- path to SendEmail (relative to DefaultDir$) cmd$ = sendmaildir$;" -f ";mailuser$;" -t ";youremail$;" -s ";server$;" -xu ";mailuser$;" -xp ";mailpwd$;" -u ";subject$;" -m ";message$ cmdresult$ = shell$(cmd$) RETURN

code