src/http/pages/addpeerpage.cpp\r
src/http/pages/announceidentitypage.cpp\r
src/http/pages/boardspage.cpp\r
-src/http/pages/browseboardspage.cpp\r
-src/http/pages/browsemessagespage.cpp\r
src/http/pages/confirmpage.cpp\r
src/http/pages/controlboardpage.cpp\r
src/http/pages/createidentitypage.cpp\r
\r
#define VERSION_MAJOR "0"\r
#define VERSION_MINOR "3"\r
-#define VERSION_RELEASE "23"\r
+#define VERSION_RELEASE "24"\r
#define FMS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_RELEASE\r
-#define FMS_FREESITE_USK "USK@0npnMrqZNKRCRoGojZV93UNHCMN-6UU3rRSAmP6jNLE,~BG-edFtdCC1cSH4O3BWdeIYa8Sw5DfyrSV-TKdO5ec,AQACAAE/fms/84/"\r
-#define FMS_VERSION_EDITION "25"\r
+#define FMS_FREESITE_USK "USK@0npnMrqZNKRCRoGojZV93UNHCMN-6UU3rRSAmP6jNLE,~BG-edFtdCC1cSH4O3BWdeIYa8Sw5DfyrSV-TKdO5ec,AQACAAE/fms/85/"\r
+#define FMS_VERSION_EDITION "26"\r
\r
typedef Poco::ScopedLock<Poco::FastMutex> Guard;\r
\r
\r
// replaces html elements with encoded characters (i.e. < becomes <)\r
const std::string SanitizeOutput(const std::string &input);\r
+ // don't replace space with , because browser might convert to unicode non breaking space character\r
+ const std::string SanitizeTextAreaOutput(const std::string &input);\r
\r
std::string m_template;\r
std::string m_pagename;\r
\r
INSTALLATION\r
------------\r
-Place the binary, any templates, and the fonts directory in a directory of your\r
-choice. Windows users may need to download the runtime DLLs available from the\r
-fms Freesite and place in the fms directory if they are not already installed\r
-on the system. On the first run, a database file will also be created in this\r
-directory. Make sure the user that runs FMS has read/write access to this\r
-directory.\r
+Place the binary, any templates, and the fonts and images directories in a\r
+directory of your choice. Windows users may need to download the runtime DLLs\r
+available from the fms Freesite and place in the fms directory if they are not\r
+already installed on the system. On the first run, a database file will also\r
+be created in this directory. Make sure the user that runs FMS has read/write\r
+access to this directory.\r
\r
RUNNING\r
-------\r
-------------\r
By default, a web interface for administration will be running at http://\r
localhost:8080. You can use the interface to configure and administer FMS.\r
+There is also a forum built into the web interface so you can read and send\r
+messages without needing to use a newsreader.\r
\r
NNTP CONFIGURATION\r
------------------\r
#include "../../include/http/pages/peertrustpage.h"\r
#include "../../include/http/pages/versioninfopage.h"\r
#include "../../include/http/pages/recentlyaddedpage.h"\r
-#include "../../include/http/pages/browseboardspage.h"\r
-#include "../../include/http/pages/browsemessagespage.h"\r
#include "../../include/http/pages/forummainpage.h"\r
#include "../../include/http/pages/showimagepage.h"\r
#include "../../include/http/pages/forumthreadspage.h"\r
m_pagehandlers.push_back(new PeerTrustPage(templatestr));\r
m_pagehandlers.push_back(new VersionInfoPage(templatestr));\r
m_pagehandlers.push_back(new RecentlyAddedPage(templatestr));\r
- m_pagehandlers.push_back(new BrowseBoardsPage(templatestr));\r
- m_pagehandlers.push_back(new BrowseMessagesPage(templatestr));\r
m_pagehandlers.push_back(new ShowImagePage());\r
m_pagehandlers.push_back(new ForumMainPage(forumtemplate));\r
m_pagehandlers.push_back(new ForumThreadsPage(forumtemplate));\r
return output;\r
}\r
\r
+const std::string IPageHandler::SanitizeTextAreaOutput(const std::string &input)\r
+{\r
+ // must do & first because all other elements have & in them!\r
+ std::string output=StringFunctions::Replace(input,"&","&");\r
+ output=StringFunctions::Replace(output,"<","<");\r
+ output=StringFunctions::Replace(output,">",">");\r
+ output=StringFunctions::Replace(output,"\"",""");\r
+ return output;\r
+}\r
+\r
const bool IPageHandler::ValidateFormPassword(const std::map<std::string,std::string> &vars)\r
{\r
Poco::DateTime date;\r
st.ResultText(1,name);\r
st.ResultText(2,pubkey);\r
\r
- rval+="<option value=\""+id+"\" title=\""+pubkey+"\">"+SanitizeOutput(CreateShortIdentityName(name,pubkey))+"</option>";\r
+ rval+="<option value=\""+id+"\" title=\""+pubkey+"\""+(selected==id?" selected":"")+">"+SanitizeOutput(CreateShortIdentityName(name,pubkey))+"</option>";\r
st.Step();\r
}\r
rval+="</select>";\r
std::string pubkey="";\r
int requestindex=0;\r
bool willshow=false;\r
+ std::string localidentityidstr="";\r
\r
if(queryvars.find("formaction")!=queryvars.end() && (*queryvars.find("formaction")).second=="announce" && ValidateFormPassword(queryvars))\r
{\r
SQLite3DB::Statement insert=m_db->Prepare("INSERT INTO tblIdentityIntroductionInserts(LocalIdentityID,Day,UUID,Solution) VALUES(?,?,?,?);");\r
- std::string localidentityidstr="";\r
int localidentityid=0;\r
std::vector<std::string> uuids;\r
std::vector<std::string> days;\r
content+="<input type=\"hidden\" name=\"formaction\" value=\"announce\">";\r
content+="<table>";\r
content+="<tr><td colspan=\"4\"><center>Select Identity : ";\r
- content+=CreateLocalIdentityDropDown("localidentityid","");\r
+ content+=CreateLocalIdentityDropDown("localidentityid",localidentityidstr);\r
content+="</td></tr>";\r
content+="<tr><td colspan=\"4\"><center>Type the answers of a few of the following puzzles. You don't need to get them all correct, but remember that they are case sensitive. Getting announced will take some time and you must assign trust to other identities to see yourself announced. DO NOT continuously solve captchas. Solve 30 at most, wait a day, and if your identity has not been announced, repeat until it is.</td></tr>";\r
content+="<tr>";\r
+++ /dev/null
-#include "../../../include/http/pages/browseboardspage.h"\r
-#include "../../../include/stringfunctions.h"\r
-\r
-#ifdef XMEM\r
- #include <xmem.h>\r
-#endif\r
-\r
-const std::string BrowseBoardsPage::BuildQueryString(const long startrow, const std::string &boardsearch, const std::string &sortby, const std::string &sortorder)\r
-{\r
- std::string returnval="";\r
- std::string tempval="";\r
-\r
- if(startrow>=0)\r
- {\r
- StringFunctions::Convert(startrow,tempval);\r
- returnval+="startrow="+tempval;\r
- }\r
-\r
- if(boardsearch!="")\r
- {\r
- if(returnval!="")\r
- {\r
- returnval+="&";\r
- }\r
- returnval+="boardsearch="+boardsearch;\r
- }\r
-\r
- if(sortby!="")\r
- {\r
- if(returnval!="")\r
- {\r
- returnval+="&";\r
- }\r
- returnval+="sortby="+sortby;\r
- if(sortorder=="ASC" || sortorder=="DESC")\r
- {\r
- if(returnval!="")\r
- {\r
- returnval+="&";\r
- }\r
- returnval+="sortorder="+sortorder;\r
- }\r
- else\r
- {\r
- if(returnval!="")\r
- {\r
- returnval+="&";\r
- }\r
- returnval+="sortorder=ASC";\r
- }\r
- }\r
-\r
- return returnval;\r
-\r
-}\r
-\r
-const std::string BrowseBoardsPage::GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars)\r
-{\r
- std::string content="";\r
- std::string sql="";\r
- std::string boardname="";\r
- int rowsperpage=25;\r
- std::string rowsperpagestr="26"; // 1 more than rowsperpage so we know if there are more boards\r
- long startrow=0;\r
- std::string startrowstr="0";\r
- int messagecount=0;\r
- std::string messagecountstr="0";\r
- std::string lastdate="";\r
- int count=0;\r
- std::string boardsearch="";\r
- std::string sortby="";\r
- std::string sortorder="";\r
-\r
- // if startrow is specified\r
- if(queryvars.find("startrow")!=queryvars.end())\r
- {\r
- startrowstr=(*queryvars.find("startrow")).second;\r
- // convert back and forth, just in case a number wasn't passed in startrow\r
- StringFunctions::Convert(startrowstr,startrow);\r
- if(startrow<0)\r
- {\r
- startrow=0;\r
- }\r
- StringFunctions::Convert(startrow,startrowstr);\r
- }\r
- if(queryvars.find("boardsearch")!=queryvars.end())\r
- {\r
- boardsearch=(*queryvars.find("boardsearch")).second;\r
- }\r
- if(queryvars.find("sortby")!=queryvars.end() && queryvars.find("sortorder")!=queryvars.end())\r
- {\r
- sortby=(*queryvars.find("sortby")).second;\r
- sortorder=(*queryvars.find("sortorder")).second;\r
- if(sortby!="BoardName" && sortby!="MessageCount" && sortby!="LastMessage")\r
- {\r
- sortby="BoardName";\r
- }\r
- if(sortorder!="ASC" && sortorder!="DESC")\r
- {\r
- sortorder="ASC";\r
- }\r
- }\r
- else\r
- {\r
- sortby="BoardName";\r
- sortorder="ASC";\r
- }\r
-\r
- content="<h2>Browse Messages</h2>";\r
- content+="<form name=\"frmfilter\" method=\"post\" action=\""+m_pagename+"\">";\r
- content+="<input type=\"text\" name=\"boardsearch\" value=\""+SanitizeOutput(boardsearch)+"\">";\r
- content+="<input type=\"submit\" value=\"Filter\">";\r
- content+="</form>";\r
-\r
- content+="<table class=\"small90\">";\r
- content+="<tr>";\r
- content+="<th><a href=\""+m_pagename+"?"+BuildQueryString(startrow,boardsearch,"BoardName",ReverseSort("BoardName",sortby,sortorder))+"\">Board</a></th>";\r
- content+="<th><a href=\""+m_pagename+"?"+BuildQueryString(startrow,boardsearch,"MessageCount",ReverseSort("MessageCount",sortby,sortorder))+"\">Message Count</a></th>";\r
- content+="<th><a href=\""+m_pagename+"?"+BuildQueryString(startrow,boardsearch,"LastMessage",ReverseSort("LastMessage",sortby,sortorder))+"\">Last Message</a></th>";\r
- content+="</tr>";\r
-\r
- sql="SELECT tblBoard.BoardID, tblBoard.BoardName, COUNT(tblMessageBoard.MessageID) AS 'MessageCount', MAX(tblMessage.MessageDate || ' ' || tblMessage.MessageTime) AS 'LastMessage'";\r
- sql+="FROM tblBoard LEFT JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID ";\r
- sql+="LEFT JOIN tblMessage ON tblMessageBoard.MessageID=tblMessage.MessageID ";\r
- sql+="WHERE (tblMessageBoard.MessageID>=0 OR tblMessageBoard.MessageID IS NULL) ";\r
- if(boardsearch!="")\r
- {\r
- sql+="AND tblBoard.BoardName LIKE '%' || ? || '%' ";\r
- }\r
- sql+="GROUP BY tblBoard.BoardID ";\r
- sql+="ORDER BY "+sortby+" COLLATE NOCASE "+sortorder+" ";\r
- sql+="LIMIT "+startrowstr+","+rowsperpagestr+";";\r
- \r
- SQLite3DB::Statement st=m_db->Prepare(sql);\r
- if(boardsearch!="")\r
- {\r
- st.Bind(0,boardsearch);\r
- }\r
- \r
- st.Step();\r
- while(st.RowReturned() && count++<rowsperpage)\r
- {\r
- boardname="";\r
- messagecount=0;\r
- lastdate="";\r
- std::string boardidstr="0";\r
- st.ResultText(0,boardidstr);\r
- st.ResultText(1,boardname);\r
- st.ResultInt(2,messagecount);\r
- st.ResultText(3,lastdate);\r
-\r
- StringFunctions::Convert(messagecount,messagecountstr);\r
-\r
- content+="<tr>";\r
- content+="<td><a href=\"browsemessages.htm?boardid="+boardidstr+"\">"+SanitizeOutput(boardname)+"</a></td>";\r
- content+="<td>"+SanitizeOutput(messagecountstr)+"</td>";\r
- content+="<td>"+SanitizeOutput(lastdate)+"</td>";\r
- content+="</tr>\r\n";\r
- st.Step();\r
- }\r
-\r
- if(startrow>0 || st.RowReturned())\r
- {\r
- content+="<tr>";\r
-\r
- if(startrow>0)\r
- {\r
- int thisstartrow=startrow-rowsperpage;\r
- if(thisstartrow<0)\r
- {\r
- thisstartrow=0;\r
- }\r
- content+="<td><a href=\"boardsbrowse.htm?"+BuildQueryString(thisstartrow,boardsearch,sortby,sortorder)+"\"><--</a></td>";\r
- }\r
- else\r
- {\r
- content+="<td></td>";\r
- }\r
-\r
- content+="<td></td>";\r
-\r
- if(st.RowReturned())\r
- {\r
- int thisstartrow=startrow+rowsperpage;\r
- content+="<td><a href=\"boardsbrowse.htm?"+BuildQueryString(thisstartrow,boardsearch,sortby,sortorder)+"\">--></a></td>";\r
- }\r
-\r
- content+="</tr>";\r
- }\r
- content+="</table>";\r
- \r
- return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
-}\r
-\r
-const std::string BrowseBoardsPage::ReverseSort(const std::string &sortname, const std::string ¤tsortby, const std::string ¤tsortorder)\r
-{\r
- if(sortname==currentsortby)\r
- {\r
- if(currentsortorder=="ASC")\r
- {\r
- return "DESC";\r
- }\r
- else\r
- {\r
- return "ASC";\r
- }\r
- }\r
- else\r
- {\r
- return currentsortorder;\r
- }\r
-}\r
+++ /dev/null
-#include "../../../include/http/pages/browsemessagespage.h"\r
-#include "../../../include/stringfunctions.h"\r
-#include "../../../include/global.h"\r
-#include "../../../include/messagethread.h"\r
-\r
-#ifdef XMEM\r
- #include <xmem.h>\r
-#endif\r
-\r
-const std::string BrowseMessagesPage::BuildQueryString(const long startrow, const std::string &boardidstr, const std::string &messageidstr)\r
-{\r
- std::string returnval="";\r
- std::string tempval="";\r
-\r
- if(startrow>=0)\r
- {\r
- StringFunctions::Convert(startrow,tempval);\r
- returnval+="startrow="+tempval;\r
- }\r
-\r
- if(boardidstr!="")\r
- {\r
- if(returnval!="")\r
- {\r
- returnval+="&";\r
- }\r
- returnval+="boardid="+boardidstr;\r
- }\r
-\r
- if(messageidstr!="")\r
- {\r
- if(returnval!="")\r
- {\r
- returnval+="&";\r
- } \r
- returnval+="messageid="+messageidstr;\r
- }\r
-\r
- return returnval;\r
-\r
-}\r
-\r
-const std::string BrowseMessagesPage::GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars)\r
-{\r
- std::string content="";\r
- long boardid=-1;\r
- std::string boardidstr="";\r
- std::string messageidstr="";\r
- int startrow=0;\r
- std::string startrowstr="0";\r
- int rowsperpage=50;\r
- std::string rowsperpagestr="51"; // one more than rowsperpage so we can know if there are more messages\r
- std::string sql="";\r
- int rowcount=0;\r
- int page=0;\r
-\r
- // if startrow is specified\r
- if(queryvars.find("startrow")!=queryvars.end())\r
- {\r
- startrowstr=(*queryvars.find("startrow")).second;\r
- // convert back and forth, just in case a number wasn't passed in startrow\r
- StringFunctions::Convert(startrowstr,startrow);\r
- if(startrow<0)\r
- {\r
- startrow=0;\r
- }\r
- StringFunctions::Convert(startrow,startrowstr);\r
- }\r
- if(queryvars.find("boardid")!=queryvars.end())\r
- {\r
- boardidstr=(*queryvars.find("boardid")).second;\r
- StringFunctions::Convert(boardidstr,boardid);\r
- }\r
- if(queryvars.find("messageid")!=queryvars.end())\r
- {\r
- messageidstr=(*queryvars.find("messageid")).second;\r
- page=1;\r
- }\r
-\r
- if(page==0)\r
- {\r
- sql="SELECT Subject, FromName, MessageDate || ' ' || MessageTime, Body, tblMessage.MessageID ";\r
- sql+="FROM tblMessage INNER JOIN tblMessageBoard ON tblMessage.MessageID=tblMessageBoard.MessageID ";\r
- if(boardidstr!="")\r
- {\r
- sql+="WHERE tblMessageBoard.BoardID=? ";\r
- }\r
- sql+="ORDER BY MessageDate || ' ' || MessageTime DESC ";\r
- sql+="LIMIT "+startrowstr+","+rowsperpagestr+";";\r
-\r
- SQLite3DB::Statement st=m_db->Prepare(sql);\r
- if(boardidstr!="")\r
- {\r
- st.Bind(0,boardidstr);\r
- }\r
- st.Step();\r
-\r
- content+="<table class=\"small90\">";\r
- content+="<tr><th>Subject</th><th>From</th><th>Date</th></tr>";\r
-\r
- rowcount=0;\r
- while(st.RowReturned() && rowcount++<rowsperpage)\r
- {\r
- std::string subject="";\r
- std::string fromname="";\r
- std::string messagedate="";\r
- std::string body="";\r
- std::string messageidstr="";\r
-\r
- st.ResultText(0,subject);\r
- st.ResultText(1,fromname);\r
- st.ResultText(2,messagedate);\r
- st.ResultText(3,body);\r
- st.ResultText(4,messageidstr);\r
-\r
- if(body.size()>400)\r
- {\r
- body.erase(400);\r
- body+="...";\r
- }\r
-\r
- content+="<tr>";\r
- content+="<td title=\""+StringFunctions::Replace(SanitizeOutput(body),"\n","\r\n")+"\"><a href=\""+m_pagename+"?"+BuildQueryString(startrow,boardidstr,messageidstr)+"\">"+SanitizeOutput(subject)+"</a></td>";\r
- content+="<td>"+fromname+"</td>";\r
- content+="<td>"+SanitizeOutput(messagedate)+"</td>";\r
- content+="</tr>\r\n";\r
-\r
- st.Step();\r
- }\r
- \r
- if(startrow>0 || st.RowReturned())\r
- {\r
- content+="<tr>";\r
-\r
- if(startrow>0)\r
- {\r
- int thisstartrow=startrow-rowsperpage;\r
- if(thisstartrow<0)\r
- {\r
- thisstartrow=0;\r
- }\r
- content+="<td><a href=\""+m_pagename+"?"+BuildQueryString(thisstartrow,boardidstr,"")+"\"><--</a></td>";\r
- }\r
- else\r
- {\r
- content+="<td></td>";\r
- }\r
-\r
- content+="<td></td>";\r
-\r
- if(st.RowReturned())\r
- {\r
- int thisstartrow=startrow+rowsperpage;\r
- content+="<td><a href=\""+m_pagename+"?"+BuildQueryString(thisstartrow,boardidstr,"")+"\">--></a></td>";\r
- }\r
- content+="</tr>";\r
- }\r
-\r
- content+="</table>";\r
- }\r
- else if(page==1)\r
- {\r
- sql="SELECT Body, FromName, MessageDate || ' ' || MessageTime, Subject FROM tblMessage WHERE MessageID=?;";\r
- SQLite3DB::Statement st=m_db->Prepare(sql);\r
- st.Bind(0,messageidstr);\r
-\r
- st.Step();\r
- if(st.RowReturned())\r
- {\r
- std::string body="";\r
- std::string fromname="";\r
- std::string messagedate="";\r
- std::string subject="";\r
- std::string boards="";\r
-\r
- st.ResultText(0,body);\r
- st.ResultText(1,fromname);\r
- st.ResultText(2,messagedate);\r
- st.ResultText(3,subject);\r
-\r
- // get boards message was posted to\r
- SQLite3DB::Statement st2=m_db->Prepare("SELECT tblBoard.BoardID, tblBoard.BoardName FROM tblBoard INNER JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID WHERE tblMessageBoard.MessageID=?;");\r
- st2.Bind(0,messageidstr);\r
- st2.Step();\r
- while(st2.RowReturned())\r
- {\r
- std::string boardname="";\r
- std::string innerboardidstr="";\r
-\r
- st2.ResultText(0,innerboardidstr);\r
- st2.ResultText(1,boardname);\r
- \r
- if(boards!="")\r
- {\r
- boards+=", ";\r
- }\r
-\r
- boards+="<a href=\""+m_pagename+"?"+BuildQueryString(0,innerboardidstr,"")+"\">"+SanitizeOutput(boardname)+"</a>";\r
-\r
- st2.Step();\r
- }\r
-\r
- content+="<div class=\"post\">";\r
- content+="<div class=\"postboards\">";\r
- content+=boards;\r
- content+="</div>";\r
- content+="<div class=\"postsubject\">";\r
- content+=SanitizeOutput(subject);\r
- content+="</div>";\r
- content+="<div class=\"postfrom\">";\r
- content+=SanitizeOutput(fromname);\r
- content+="</div>";\r
- content+="<div class=\"postdate\">";\r
- content+=SanitizeOutput(messagedate);\r
- content+="</div>";\r
- content+="<div class=\"postbody\">";\r
- content+=SanitizeOutput(body);\r
- content+="</div>";\r
- content+="</div>\r\n";\r
-\r
- long currentlevel=0;\r
- MessageThread thread;\r
- thread.Load(messageidstr,boardid);\r
-\r
- std::vector<MessageThread::threadnode> nodes=thread.GetNodes();\r
- if(nodes.size()>1)\r
- {\r
- content+="<ul class=\"messagethread\">";\r
- for(std::vector<MessageThread::threadnode>::const_iterator i=nodes.begin(); i!=nodes.end(); i++)\r
- {\r
- if((*i).m_level>currentlevel)\r
- {\r
- content+="<ul class=\"messagethread\">";\r
- }\r
- else if((*i).m_level<currentlevel)\r
- {\r
- content+="</ul>";\r
- }\r
- currentlevel=(*i).m_level;\r
-\r
- std::string tempstr="";\r
- StringFunctions::Convert((*i).m_messageid,tempstr);\r
-\r
- content+="<li>";\r
- if(tempstr!=messageidstr)\r
- {\r
- content+="<a href=\""+m_pagename+"?"+BuildQueryString(0,boardidstr,tempstr)+"\">"+SanitizeOutput((*i).m_subject)+"</a> - "+SanitizeOutput((*i).m_fromname);\r
- }\r
- else\r
- {\r
- content+=SanitizeOutput((*i).m_subject)+" - "+SanitizeOutput((*i).m_fromname);\r
- }\r
- content+="</li>\r\n";\r
- }\r
- while(currentlevel-->0)\r
- {\r
- content+="</ul>";\r
- }\r
- content+="</ul>\r\n";\r
- }\r
- }\r
- }\r
-\r
- return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
-}\r
replyst.ResultText(0,subject);\r
replyst.ResultText(1,body);\r
\r
- if(subject.size()<3 || (subject.substr(0,2)!="re:" && subject.substr(0,2)!="Re:"))\r
+ if(subject.size()<3 || (subject.substr(0,3)!="re:" && subject.substr(0,3)!="Re:"))\r
{\r
subject="Re: "+subject;\r
}\r
content+="<table class=\"createpost\">";\r
content+="<tr><td class=\"identity\">From</td><td>"+LocalIdentityDropDown("localidentityid",localidentityidstr)+"</td></tr>";\r
content+="<tr><td class=\"subject\">Subject</td><td><input type=\"text\" name=\"subject\" maxlength=\"60\" size=\"60\" value=\""+SanitizeOutput(subject)+"\"></td></tr>";\r
- content+="<tr><td class=\"body\">Message</td><td><textarea name=\"body\" cols=\"80\" rows=\"30\">"+SanitizeOutput(body)+"</textarea></td></tr>";\r
+ content+="<tr><td class=\"body\">Message</td><td><textarea name=\"body\" cols=\"80\" rows=\"30\">"+SanitizeTextAreaOutput(body)+"</textarea></td></tr>";\r
content+="<tr><td colspan=\"2\" class=\"send\"><input type=\"submit\" value=\"Send\"></td></tr>";\r
content+="</table>\r\n";\r
content+="</form>";\r
static std::string whitespace=" \t\r\n";\r
std::string output=body;\r
\r
+ output=StringFunctions::Replace(output,"\r\n","\n");\r
+\r
// put \n after 80 contiguous characters in the body\r
std::string::size_type prevpos=0;\r
std::string::size_type pos=output.find_first_of(whitespace);\r
std::string boardidstr="";\r
std::string currentpagestr="";\r
std::string boardname="";\r
+ std::string firstunreadidstr="";\r
\r
if(queryvars.find("threadid")!=queryvars.end())\r
{\r
\r
content+=CreateForumHeader();\r
\r
+ SQLite3DB::Statement firstunreadst=m_db->Prepare("SELECT tblMessage.MessageID FROM tblThreadPost INNER JOIN tblMessage ON tblThreadPost.MessageID=tblMessage.MessageID WHERE ThreadID=? AND tblMessage.Read=0;");\r
+ firstunreadst.Bind(0,threadidstr);\r
+ firstunreadst.Step();\r
+ if(firstunreadst.RowReturned())\r
+ {\r
+ firstunreadst.ResultText(0,firstunreadidstr);\r
+ }\r
+\r
SQLite3DB::Statement updateread=m_db->Prepare("UPDATE tblMessage SET Read=1 WHERE tblMessage.MessageID IN (SELECT MessageID FROM tblThreadPost WHERE ThreadID=?);");\r
updateread.Bind(0,threadidstr);\r
updateread.Step();\r
content+="<table class=\"forumheader\">";\r
content+="<tr>";\r
content+="<td> Forum : <a href=\"forumthreads.htm?boardid="+boardidstr+"¤tpage="+currentpagestr+"\">"+SanitizeOutput(boardname)+"</a></td>";\r
+ if(firstunreadidstr!="")\r
+ {\r
+ content+="<td>";\r
+ content+="<a href=\"#"+firstunreadidstr+"\">First Unread Message</a>";\r
+ content+="</td>";\r
+ }\r
content+="</tr>";\r
content+="</table>\r\n";\r
\r
\r
content+="<table class=\"trust\">";\r
content+="<tr>";\r
- content+="<td colspan=\"3\" style=\"text-align:center;\"><a href=\"peertrust.htm?namesearch="+name+"\">Trust</a></td>";\r
+ content+="<td colspan=\"3\" style=\"text-align:center;\"><a href=\"peertrust.htm?namesearch="+StringFunctions::UriEncode(name)+"\">Trust</a></td>";\r
content+="</tr>";\r
content+="<tr>";\r
content+="<td></td><td>Local</td><td>Peer</td>";\r
{\r
returnval+="&";\r
}\r
- returnval+="namesearch="+namesearch;\r
+ returnval+="namesearch="+StringFunctions::UriEncode(namesearch);\r
}\r
\r
if(sortby!="")\r
st.Bind(0,threadid);\r
st.Step();\r
\r
+ SQLite3DB::Statement deleteotherst=m_db->Prepare("DELETE FROM tblThread WHERE ThreadID IN (SELECT tblThread.ThreadID FROM tblThreadPost INNER JOIN tblThread ON tblThreadPost.ThreadID=tblThread.ThreadID WHERE tblThread.BoardID=? AND tblThreadPost.MessageID=?);");\r
+\r
count=0;\r
st=m_db->Prepare("INSERT INTO tblThreadPost(ThreadID,MessageID,PostOrder) VALUES(?,?,?);");\r
for(std::vector<MessageThread::threadnode>::const_iterator i=m_threadmessages.begin(); i!=m_threadmessages.end(); i++, count++)\r
{\r
+ deleteotherst.Bind(0,boardid);\r
+ deleteotherst.Bind(1,(*i).m_messageid);\r
+ deleteotherst.Step();\r
+ deleteotherst.Reset();\r
+\r
st.Bind(0,threadid);\r
st.Bind(1,(*i).m_messageid);\r
st.Bind(2,count);\r