src/bitmapvalidator.cpp\r
src/board.cpp\r
src/boardlist.cpp\r
-src/db\r
src/dbconversions.cpp\r
src/dbmaintenancethread.cpp\r
src/dbsetup.cpp\r
src/fmsapp.cpp\r
-src/freenet\r
src/global.cpp\r
src/hex.cpp\r
-src/http\r
src/ipaddressacl.cpp\r
src/localidentity.cpp\r
src/main.cpp\r
src/message.cpp\r
src/messagelist.cpp\r
-src/nntp\r
+src/messagethread.cpp\r
src/option.cpp\r
src/optionssetup.cpp\r
src/socketdefines.cpp\r
src/stringfunctions.cpp\r
-src/threadwrapper\r
+src/threadbuilder.cpp\r
src/db/sqlite3db.cpp\r
src/db/sqlite3recordset.cpp\r
src/db/sqlite3statement.cpp\r
src/freenet/boardlistinserter.cpp\r
src/freenet/boardlistrequester.cpp\r
src/freenet/boardlistxml.cpp\r
-src/freenet/captcha\r
src/freenet/fcpv2.cpp\r
src/freenet/fileinserter.cpp\r
src/freenet/fmsversionrequester.cpp\r
src/freenet/trustlistrequester.cpp\r
src/freenet/trustlistxml.cpp\r
src/freenet/unkeyedidcreator.cpp\r
-src/freenet/captcha/easybmp\r
src/freenet/captcha/simplecaptcha.cpp\r
src/freenet/captcha/easybmp/EasyBMP.cpp\r
src/freenet/captcha/easybmp/EasyBMP_Font.cpp\r
src/http/identityexportxml.cpp\r
src/http/ipagehandler.cpp\r
src/http/multipartparser.cpp\r
-src/http/pages\r
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
src/http/pages/execquerypage.cpp\r
+src/http/pages/forumcreatepostpage.cpp\r
+src/http/pages/forummainpage.cpp\r
+src/http/pages/forumthreadspage.cpp\r
+src/http/pages/forumviewthreadpage.cpp\r
src/http/pages/homepage.cpp\r
src/http/pages/insertedfilespage.cpp\r
src/http/pages/localidentitiespage.cpp\r
src/http/pages/peertrustpage.cpp\r
src/http/pages/recentlyaddedpage.cpp\r
src/http/pages/showcaptchapage.cpp\r
+src/http/pages/showimagepage.cpp\r
src/http/pages/versioninfopage.cpp\r
src/nntp/extensiontrust.cpp\r
-src/nntp/mime\r
src/nntp/nntpconnection.cpp\r
src/nntp/nntplistener.cpp\r
src/nntp/uwildmat.cpp\r
ENDIF(NOT WIN32)\r
\r
IF(SQLITE3_LIBRARY)\r
+ MESSAGE(STATUS "Linking against system SQLite3 library.")\r
TARGET_LINK_LIBRARIES(fms ${SQLITE3_LIBRARY})\r
ELSE(SQLITE3_LIBRARY)\r
IF(NOT USE_BUNDLED_SQLITE)\r
--- /dev/null
+<html>\r
+<head>\r
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />\r
+<style>\r
+body {\r
+ margin:0px;\r
+ padding:10px;\r
+ font-family:Helvetica,Arial;\r
+ font-size:12px;\r
+ }\r
+ \r
+table {\r
+ margin:0px;\r
+ padding:0px;\r
+ font-size:12px;\r
+ }\r
+ \r
+table td {\r
+ margin:0px;\r
+ padding:0px;\r
+ background-color:#ddeeff;\r
+ }\r
+ \r
+table th {\r
+ background-color:#003366;\r
+ color:#ffffff;\r
+ }\r
+\r
+#outercontainer {\r
+ padding:0px;\r
+ margin:0px;\r
+ }\r
+ \r
+.error {\r
+ padding-left:5px;\r
+ padding-right:5px;\r
+ color:#ff0000;\r
+ font-weight:bolder;\r
+ }\r
+ \r
+table.header {\r
+ width:100%;\r
+ }\r
+\r
+table.header td {\r
+ text-align:center;\r
+ padding:5px;\r
+ font-size:1.2em;\r
+ font-weight:bolder;\r
+ }\r
+\r
+table.foruminfo {\r
+ width:100%;\r
+ }\r
+ \r
+table.foruminfo td {\r
+ padding-left:5px;\r
+ padding-right:5px;\r
+ padding-top:2px;\r
+ padding-bottom:2px;\r
+ }\r
+\r
+table.foruminfo td.newposts {\r
+ width:32px;\r
+ }\r
+ \r
+table.foruminfo td.forumname {\r
+ font-size:1.2em;\r
+ font-weight:bolder;\r
+ }\r
+\r
+table.foruminfo td.forumname .description {\r
+ font-weight:normal;\r
+ font-size:0.7em;\r
+ }\r
+ \r
+table.foruminfo td.postcount {\r
+ width:80px;\r
+ }\r
+ \r
+table.foruminfo td.lastpost {\r
+ width:340px;\r
+ font-size:0.9em;\r
+ }\r
+\r
+table.forumheader {\r
+ width:100%;\r
+ }\r
+ \r
+table.forumheader td {\r
+ font-size:1.1em;\r
+ font-weight:bolder;\r
+ padding-left:5px;\r
+ padding-right:5px;\r
+ padding-top:2px;\r
+ padding-bottom:2px;\r
+ }\r
+\r
+table.threadinfo {\r
+ width:100%;\r
+ }\r
+ \r
+table.threadinfo td {\r
+ padding-left:5px;\r
+ padding-right:5px;\r
+ padding-top:2px;\r
+ padding-bottom:2px;\r
+ }\r
+\r
+table.threadinfo td.newposts {\r
+ width:32px;\r
+ text-align:center;\r
+ }\r
+\r
+table.threadinfo td.threadauthor {\r
+ width:150px;\r
+ }\r
+ \r
+table.threadinfo td.threadreplies {\r
+ width:60px;\r
+ }\r
+\r
+table.threadinfo td.threadlastpost {\r
+ width:220px;\r
+ font-size:0.9em;\r
+ }\r
+\r
+table.threadinfo td.pages {\r
+ font-weight:bolder;\r
+ }\r
+\r
+table.threadinfo td.pages form {\r
+ margin-left:10px;\r
+ display:inline;\r
+ }\r
+\r
+table.threadinfo td.pages input {\r
+ width:30px;\r
+ text-align:center;\r
+ }\r
+ \r
+table.thread {\r
+ width:100%;\r
+ }\r
+ \r
+table.thread td {\r
+ padding:5px;\r
+ }\r
+ \r
+table.thread td.from {\r
+ vertical-align:top;\r
+ font-weight:bolder;\r
+ }\r
+ \r
+table.thread td.subject {\r
+ font-size:1.1em;\r
+ font-weight:bolder;\r
+ height:20px;\r
+ }\r
+\r
+table.thread td.body {\r
+ vertical-align:top;\r
+ overflow:auto;\r
+ }\r
+table.createpost td {\r
+ padding-left:5px;\r
+ padding-right:5px;\r
+ padding-top:2px;\r
+ padding-bottom:2px;\r
+ }\r
+\r
+table.createpost td.identity {\r
+ font-weight:bolder;\r
+ text-align:right;\r
+ }\r
+\r
+table.createpost td.subject {\r
+ font-weight:bolder;\r
+ text-align:right;\r
+ }\r
+\r
+table.createpost td.body {\r
+ font-weight:bolder;\r
+ text-align:right;\r
+ vertical-align:top;\r
+ }\r
+\r
+table.createpost td.send {\r
+ text-align:center;\r
+ }\r
+\r
+table.trust {\r
+ margin-top:10px;\r
+ margin-left:5px;\r
+ border-style:solid;\r
+ border-width:1px;\r
+ }\r
+ \r
+table.trust td {\r
+ padding-left:5px;\r
+ padding-right:5px;\r
+ padding-top:2px;\r
+ padding-bottom:2px;\r
+ }\r
+\r
+</style>\r
+</head>\r
+<body>\r
+\r
+<div id="outercontainer">\r
+\r
+ [CONTENT]\r
+\r
+</div>\r
+\r
+</body>\r
+</html>\r
{\r
public:\r
DB();\r
- DB(std::string filename);\r
+ DB(const std::string &filename);\r
~DB();\r
\r
const bool Open(const std::string &filename);\r
virtual ~Recordset();\r
\r
virtual void Free() { if(m_rs) { sqlite3_free_table(m_rs); m_rs=NULL; } }\r
- virtual const bool Empty() { return (m_rs==NULL || m_rows==0) ? true : false ; }\r
+ virtual const bool Empty() const { return (m_rs==NULL || m_rows==0) ? true : false ; }\r
\r
- virtual const int Count() { return m_rows; }\r
- virtual const bool AtBeginning() { return m_currentrow==0; }\r
- virtual const bool AtEnd() { return m_currentrow>=m_rows; }\r
- virtual const int Cols() { return m_cols; }\r
+ virtual const int Count() const { return m_rows; }\r
+ virtual const bool AtBeginning() const { return m_currentrow==0; }\r
+ virtual const bool AtEnd() const { return m_currentrow>=m_rows; }\r
+ virtual const int Cols() const { return m_cols; }\r
\r
virtual const bool Next() { if(m_currentrow<m_rows) { m_currentrow++; return true; } else { return false; } }\r
virtual const bool Previous() { if(m_currentrow-1>=0) { m_currentrow--; return true; } else { return false; } }\r
long m_lastinsertrowid;\r
\r
static std::map<sqlite3_stmt *, long> m_statementcount;\r
- //std::vector<char *> textptrs;\r
- //std::vector<std::vector<char> > m_boundtext;\r
\r
}; //class\r
\r
void ConvertDB0110To0111();\r
void ConvertDB0111To0112();\r
void ConvertDB0112To0113();\r
+void ConvertDB0113To0114();\r
\r
// TODO remove sometime after 0.1.17\r
void FixCapitalBoardNames();\r
}\r
if(m_fcpuniquename.find("|")!=std::string::npos)\r
{\r
- m_log->fatal("IIndexInserter<IDTYPE>::FCPConnected fcpuniquename contains | character! This is not a valid character!");\r
+ m_log->fatal("IIndexInserter<IDTYPE>::FCPConnected fcpuniquename : "+m_fcpuniquename+" contains | character! This is not a valid character!");\r
}\r
\r
m_inserting.clear();\r
\r
if(message["Identifier"].find(m_fcpuniquename)==0)\r
{\r
+ m_log->trace("IIndexInserter<IDTYPE>::HandleMessage "+m_fcpuniquename+" received "+message.GetName()+" ID="+message["Identifier"]+" URI="+message["URI"]);\r
+\r
if(message.GetName()=="URIGenerated")\r
{\r
return true;\r
#include <Poco/Timestamp.h>\r
#include <Poco/Timespan.h>\r
\r
+#include <algorithm>\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
}\r
if(m_fcpuniquename.find("|")!=std::string::npos)\r
{\r
- m_log->fatal("IIndexRequester<IDTYPE>::FCPConnected fcpuniquename contains | character! This is not a valid character!");\r
+ m_log->fatal("IIndexRequester<IDTYPE>::FCPConnected fcpuniquename "+m_fcpuniquename+" contains | character! This is not a valid character!");\r
}\r
\r
m_lastreceived=Poco::Timestamp();\r
template <class IDTYPE>\r
void IIndexRequester<IDTYPE>::RemoveFromRequestList(const IDTYPE id)\r
{\r
+/*\r
typename std::vector<IDTYPE>::iterator i=m_requesting.begin();\r
while(i!=m_requesting.end() && (*i)!=id)\r
{\r
i++;\r
}\r
+*/\r
+ // better\r
+ typename std::vector<IDTYPE>::iterator i=std::find(m_requesting.begin(),m_requesting.end(),id);\r
+\r
if(i!=m_requesting.end())\r
{\r
m_requesting.erase(i);\r
IntroductionPuzzleRequester();\r
IntroductionPuzzleRequester(FCPv2 *fcp);\r
\r
- void FCPDisconnected();\r
- void FCPConnected();\r
-\r
private:\r
void Initialize();\r
void StartRequest(const long &identityid);\r
\r
#define VERSION_MAJOR "0"\r
#define VERSION_MINOR "3"\r
-#define VERSION_RELEASE "22"\r
+#define VERSION_RELEASE "23"\r
#define FMS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_RELEASE\r
-#define FMS_FREESITE_USK "USK@0npnMrqZNKRCRoGojZV93UNHCMN-6UU3rRSAmP6jNLE,~BG-edFtdCC1cSH4O3BWdeIYa8Sw5DfyrSV-TKdO5ec,AQACAAE/fms/82/"\r
-#define FMS_VERSION_EDITION "24"\r
+#define FMS_FREESITE_USK "USK@0npnMrqZNKRCRoGojZV93UNHCMN-6UU3rRSAmP6jNLE,~BG-edFtdCC1cSH4O3BWdeIYa8Sw5DfyrSV-TKdO5ec,AQACAAE/fms/84/"\r
+#define FMS_VERSION_EDITION "25"\r
\r
typedef Poco::ScopedLock<Poco::FastMutex> Guard;\r
\r
{\r
public:\r
IPageHandler() {}\r
- IPageHandler(const std::string &templatestr) { m_template=templatestr; }\r
+ IPageHandler(const std::string &templatestr, const std::string &pagename):m_template(templatestr),m_pagename(pagename) { }\r
virtual ~IPageHandler() {}\r
- virtual const bool WillHandleURI(const std::string &uri)=0;\r
+ virtual const bool WillHandleURI(const std::string &uri);\r
\r
virtual IPageHandler *New()=0; // returns a new instance of the object\r
\r
const std::string SanitizeOutput(const std::string &input);\r
\r
std::string m_template;\r
+ std::string m_pagename;\r
\r
};\r
\r
class AddPeerPage:public IPageHandler,public IDatabase\r
{\r
public:\r
- AddPeerPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
+ AddPeerPage(const std::string &templatestr):IPageHandler(templatestr,"addpeer.htm") {}\r
\r
IPageHandler *New() { return new AddPeerPage(m_template); }\r
\r
class AnnounceIdentityPage:public IPageHandler,public IDatabase\r
{\r
public:\r
- AnnounceIdentityPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
+ AnnounceIdentityPage(const std::string &templatestr):IPageHandler(templatestr,"announceidentity.htm") {}\r
\r
IPageHandler *New() { return new AnnounceIdentityPage(m_template); }\r
\r
class BoardsPage:public IPageHandler,public IDatabase\r
{\r
public:\r
- BoardsPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
+ BoardsPage(const std::string &templatestr):IPageHandler(templatestr,"boards.htm") {}\r
\r
IPageHandler *New() { return new BoardsPage(m_template); }\r
\r
--- /dev/null
+#ifndef _browseboardspage_\r
+#define _browseboardspage_\r
+\r
+#include "../ipagehandler.h"\r
+#include "../../idatabase.h"\r
+\r
+class BrowseBoardsPage:public IPageHandler,public IDatabase\r
+{\r
+public:\r
+ BrowseBoardsPage(const std::string &templatestr):IPageHandler(templatestr,"boardsbrowse.htm") {}\r
+ \r
+ IPageHandler *New() { return new BrowseBoardsPage(m_template); }\r
+ \r
+private:\r
+ const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
+\r
+ const std::string BuildQueryString(const long startrow, const std::string &boardsearch, const std::string &sortby, const std::string &sortorder);\r
+ const std::string ReverseSort(const std::string &sortname, const std::string ¤tsortby, const std::string ¤tsortorder);\r
+};\r
+\r
+#endif // _browseboardspage_\r
--- /dev/null
+#ifndef _browsemessagespage_\r
+#define _browsemessagespage_\r
+\r
+#include "../ipagehandler.h"\r
+#include "../../idatabase.h"\r
+\r
+class BrowseMessagesPage:public IPageHandler,public IDatabase\r
+{\r
+public:\r
+ BrowseMessagesPage(const std::string &templatestr):IPageHandler(templatestr,"browsemessages.htm") {}\r
+ \r
+ IPageHandler *New() { return new BrowseMessagesPage(m_template); }\r
+ \r
+private:\r
+ const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
+ const std::string BuildQueryString(const long startrow, const std::string &boardidstr, const std::string &messageidstr);\r
+};\r
+\r
+#endif // _browsemessagespage_\r
class ConfirmPage:public IPageHandler\r
{\r
public:\r
- ConfirmPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
+ ConfirmPage(const std::string &templatestr):IPageHandler(templatestr,"confirm.htm") {}\r
\r
IPageHandler *New() { return new ConfirmPage(m_template); }\r
\r
class ControlBoardPage:public IPageHandler,public IDatabase\r
{\r
public:\r
- ControlBoardPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
+ ControlBoardPage(const std::string &templatestr):IPageHandler(templatestr,"controlboard.htm") {}\r
\r
IPageHandler *New() { return new ControlBoardPage(m_template); }\r
\r
class CreateIdentityPage:public IPageHandler,public IDatabase\r
{\r
public:\r
- CreateIdentityPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
+ CreateIdentityPage(const std::string &templatestr):IPageHandler(templatestr,"createidentity.htm") {}\r
\r
IPageHandler *New() { return new CreateIdentityPage(m_template); }\r
\r
class ExecQueryPage:public IPageHandler,public IDatabase\r
{\r
public:\r
- ExecQueryPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
+ ExecQueryPage(const std::string &templatestr):IPageHandler(templatestr,"execquery.htm") {}\r
\r
IPageHandler *New() { return new ExecQueryPage(m_template); }\r
\r
--- /dev/null
+#ifndef _forumcreatepostpage_\r
+#define _forumcreatepostpage_\r
+\r
+#include "forumpage.h"\r
+\r
+class ForumCreatePostPage:public ForumPage\r
+{\r
+public:\r
+ ForumCreatePostPage(const std::string &templatestr):ForumPage(templatestr,"forumcreatepost.htm") {}\r
+\r
+ IPageHandler *New() { return new ForumCreatePostPage(m_template); }\r
+private:\r
+ const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
+\r
+ const std::string LocalIdentityDropDown(const std::string &name, const std::string &selectedid);\r
+ \r
+};\r
+\r
+#endif // _forumcreatepostpage_\r
--- /dev/null
+#ifndef _forummainpage_\r
+#define _forummainpage_\r
+\r
+#include "forumpage.h"\r
+\r
+class ForumMainPage:public ForumPage\r
+{\r
+public:\r
+ ForumMainPage(const std::string &templatestr):ForumPage(templatestr,"forummain.htm") {}\r
+\r
+ IPageHandler *New() { return new ForumMainPage(m_template); }\r
+\r
+private:\r
+ const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
+};\r
+\r
+#endif // _forummainpage_\r
--- /dev/null
+#ifndef _forumpage_\r
+#define _forumpage_\r
+\r
+#include "../ipagehandler.h"\r
+#include "../../idatabase.h"\r
+\r
+class ForumPage:public IPageHandler,public IDatabase\r
+{\r
+public:\r
+ ForumPage(const std::string &templatestr, const std::string &pagename):IPageHandler(templatestr,pagename) {}\r
+\r
+ virtual IPageHandler *New()=0; // returns a new instance of the object\r
+\r
+protected:\r
+ const std::string FixFromName(const std::string &fromname)\r
+ {\r
+ std::string tempname=fromname;\r
+ if(tempname.size()>30)\r
+ {\r
+ tempname.erase(27);\r
+ tempname+="...";\r
+ }\r
+ tempname=SanitizeOutput(tempname);\r
+ return tempname;\r
+ }\r
+\r
+ const std::string FixSubject(const std::string &subject)\r
+ {\r
+ std::string tempsubject=subject;\r
+ if(tempsubject.size()>30)\r
+ {\r
+ tempsubject.erase(27);\r
+ tempsubject+="...";\r
+ }\r
+ tempsubject=SanitizeOutput(tempsubject);\r
+ return tempsubject;\r
+ }\r
+\r
+ const std::string CreateForumHeader()\r
+ {\r
+ std::string content="<table class=\"header\">\r\n";\r
+ content+="<tr><td><a href=\"index.htm\">Home</a> | <a href=\"forummain.htm\">Browse Forums</a></td></tr>\r\n";\r
+ content+="</table>\r\n";\r
+ return content;\r
+ }\r
+\r
+private:\r
+ virtual const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars)=0;\r
+\r
+};\r
+\r
+#endif // _forumpage_\r
--- /dev/null
+#ifndef _forumthreads_page_\r
+#define _forumthreads_page_\r
+\r
+#include "forumpage.h"\r
+\r
+class ForumThreadsPage:public ForumPage\r
+{\r
+public:\r
+ ForumThreadsPage(const std::string &templatestr):ForumPage(templatestr,"forumthreads.htm") {}\r
+\r
+ IPageHandler *New() { return new ForumThreadsPage(m_template); }\r
+\r
+private:\r
+ const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
+};\r
+\r
+#endif // _forumthreads_page_\r
--- /dev/null
+#ifndef _forumviewthreadpage_\r
+#define _forumviewthreadpage_\r
+\r
+#include "forumpage.h"\r
+\r
+class ForumViewThreadPage:public ForumPage\r
+{\r
+public:\r
+ ForumViewThreadPage(const std::string &templatestr):ForumPage(templatestr,"forumviewthread.htm") {}\r
+\r
+ IPageHandler *New() { return new ForumViewThreadPage(m_template); }\r
+private:\r
+ const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
+\r
+ const std::string FixBody(const std::string &body);\r
+\r
+};\r
+\r
+#endif // _forumviewthreadpage_\r
class HomePage:public IPageHandler,public IDatabase\r
{\r
public:\r
- HomePage(const std::string &templatestr):IPageHandler(templatestr) {}\r
+ HomePage(const std::string &templatestr):IPageHandler(templatestr,"index.htm") {}\r
\r
IPageHandler *New() { return new HomePage(m_template); }\r
\r
class InsertedFilesPage:public IPageHandler,public IDatabase\r
{\r
public:\r
- InsertedFilesPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
+ InsertedFilesPage(const std::string &templatestr):IPageHandler(templatestr,"insertedfiles.htm") {}\r
\r
IPageHandler *New() { return new InsertedFilesPage(m_template); }\r
\r
class LocalIdentitiesPage:public IPageHandler,public IDatabase\r
{\r
public:\r
- LocalIdentitiesPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
+ LocalIdentitiesPage(const std::string &templatestr):IPageHandler(templatestr,"localidentities.htm") {}\r
\r
IPageHandler *New() { return new LocalIdentitiesPage(m_template); }\r
\r
class OptionsPage:public IPageHandler,public IDatabase\r
{\r
public:\r
- OptionsPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
+ OptionsPage(const std::string &templatestr):IPageHandler(templatestr,"options.htm") {}\r
\r
IPageHandler *New() { return new OptionsPage(m_template); }\r
\r
class PeerDetailsPage:public IPageHandler,public IDatabase\r
{\r
public:\r
- PeerDetailsPage(const std::string templatestr):IPageHandler(templatestr) {}\r
+ PeerDetailsPage(const std::string templatestr):IPageHandler(templatestr,"peerdetails.htm") {}\r
\r
IPageHandler *New() { return new PeerDetailsPage(m_template); }\r
\r
class PeerMaintenancePage:public IPageHandler,public IDatabase\r
{\r
public:\r
- PeerMaintenancePage(const std::string &templatestr):IPageHandler(templatestr) {}\r
+ PeerMaintenancePage(const std::string &templatestr):IPageHandler(templatestr,"peermaintenance.htm") {}\r
\r
IPageHandler *New() { return new PeerMaintenancePage(m_template); }\r
\r
class PeerTrustPage:public IPageHandler,public IDatabase\r
{\r
public:\r
- PeerTrustPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
+ PeerTrustPage(const std::string &templatestr):IPageHandler(templatestr,"peertrust.htm") {}\r
\r
IPageHandler *New() { return new PeerTrustPage(m_template); }\r
\r
private:\r
- const bool WillHandleURI(const std::string &uri);\r
const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
\r
const std::string GetClassString(const std::string &trustlevel);\r
class RecentlyAddedPage:public IPageHandler,public IDatabase\r
{\r
public:\r
- RecentlyAddedPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
+ RecentlyAddedPage(const std::string &templatestr):IPageHandler(templatestr,"recentlyadded.htm") {}\r
\r
IPageHandler *New() { return new RecentlyAddedPage(m_template); }\r
\r
private:\r
- const bool WillHandleURI(const std::string &uri);\r
const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
\r
};\r
--- /dev/null
+#ifndef _showimagepage_\r
+#define _showimagepage_\r
+\r
+#include "../ipagehandler.h"\r
+\r
+class ShowImagePage:public IPageHandler\r
+{\r
+public:\r
+\r
+ void handleRequest(Poco::Net::HTTPServerRequest &request, Poco::Net::HTTPServerResponse &response);\r
+\r
+ IPageHandler *New() { return new ShowImagePage; }\r
+\r
+private:\r
+ const bool WillHandleURI(const std::string &uri);\r
+ const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars) {return "";}\r
+\r
+ static std::map<std::string,std::vector<char> > m_imagecache;\r
+\r
+};\r
+\r
+#endif // _showcaptchapage_\r
class VersionInfoPage:public IPageHandler,public IDatabase\r
{\r
public:\r
- VersionInfoPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
+ VersionInfoPage(const std::string &templatestr):IPageHandler(templatestr,"versioninfo.htm") {}\r
\r
IPageHandler *New() { return new VersionInfoPage(m_template); }\r
\r
private:\r
- const bool WillHandleURI(const std::string &uri);\r
const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
\r
};\r
const bool Load(const std::string &messageuuid);\r
\r
const bool ParseNNTPMessage(const std::string &nntpmessage);\r
+ const bool Create(const long localidentityid, const long boardid, const std::string &subject, const std::string &body, const std::string &references);\r
\r
const bool PostedToAdministrationBoard() { return CheckForAdministrationBoard(m_boards); }\r
\r
--- /dev/null
+#ifndef _messagethread_\r
+#define _messagethread_\r
+\r
+#include "idatabase.h"\r
+\r
+class MessageThread:public IDatabase\r
+{\r
+public:\r
+ struct threadnode\r
+ {\r
+ long m_messageid;\r
+ long m_level;\r
+ std::string m_subject;\r
+ std::string m_fromname;\r
+ std::string m_date;\r
+ };\r
+ \r
+ void Clear() { m_nodes.clear(); }\r
+\r
+ const bool Load(const std::string &messageidstr, const long boardid, const bool bydate=false);\r
+ const bool Load(const long messageid, const long boardid, const bool bydate=false);\r
+ \r
+ const std::vector<threadnode> GetNodes() { return m_nodes; }\r
+ \r
+private:\r
+ const threadnode GetOriginalMessageNode(const long messageid, const long boardid);\r
+ void AddChildren(const long messageid, const long level, const long boardid);\r
+\r
+ class datecompare\r
+ {\r
+ public:\r
+ const bool operator()(const threadnode &node1, const threadnode &node2) const\r
+ {\r
+ return node1.m_date<node2.m_date;\r
+ }\r
+ };\r
+\r
+ std::vector<threadnode> m_nodes;\r
+};\r
+\r
+#endif // _messagethread_\r
--- /dev/null
+#ifndef _threadbuilder_\r
+#define _threadbuilder_\r
+\r
+#include "idatabase.h"\r
+\r
+class ThreadBuilder:public IDatabase\r
+{\r
+public:\r
+\r
+ const bool Build(const long messageid, const long boardid, const bool bydate=false);\r
+\r
+private:\r
+\r
+};\r
+\r
+#endif // _threadbuilder_\r
Initialize();\r
}\r
\r
-DB::DB(std::string filename)\r
+DB::DB(const std::string &filename)\r
{\r
Initialize();\r
Open(filename);\r
{\r
if(IsOpen())\r
{\r
- Close(); \r
+ Close();\r
}\r
}\r
\r
}\r
else\r
{\r
- return false; \r
+ return false;\r
}\r
}\r
else\r
{\r
- return false; \r
+ return false;\r
}\r
}\r
\r
}\r
else\r
{\r
- return false; \r
+ return false;\r
}\r
}\r
else\r
}\r
else\r
{\r
- return false; \r
+ return false;\r
}\r
}\r
else\r
}\r
else\r
{\r
- return SQLITE_OK; \r
+ return SQLITE_OK;\r
}\r
}\r
\r
const bool DB::IsOpen()\r
{\r
Poco::ScopedLock<Poco::FastMutex> g(m_mutex);\r
- return m_db ? true : false; \r
+ return m_db ? true : false;\r
}\r
\r
const bool DB::Open(const std::string &filename)\r
}\r
else\r
{\r
- return false; \r
+ return false;\r
}\r
}\r
else\r
{\r
- return false; \r
+ return false;\r
}\r
}\r
\r
\r
std::map<sqlite3_stmt *, long> Statement::m_statementcount;\r
\r
-Statement::Statement()\r
+Statement::Statement():m_statement(0),m_parametercount(0),m_resultcolumncount(0),m_rowreturned(false),m_lastinsertrowid(-1)\r
{\r
- m_statement=NULL;\r
- m_parametercount=0;\r
- m_resultcolumncount=0;\r
- m_rowreturned=false;\r
- m_lastinsertrowid=-1;\r
+\r
}\r
\r
-Statement::Statement(sqlite3_stmt *statement)\r
+Statement::Statement(sqlite3_stmt *statement):m_statement(statement),m_rowreturned(false),m_lastinsertrowid(-1)\r
{\r
- m_statement=statement;\r
m_parametercount=sqlite3_bind_parameter_count(m_statement);\r
m_resultcolumncount=sqlite3_column_count(m_statement);\r
- m_rowreturned=false;\r
- m_lastinsertrowid=-1;\r
- \r
+\r
if(m_statement)\r
{\r
m_statementcount[m_statement]++;\r
}\r
}\r
\r
-Statement::Statement(const Statement &rhs)\r
+Statement::Statement(const Statement &rhs):m_statement(0),m_parametercount(0),m_resultcolumncount(0),m_rowreturned(false),m_lastinsertrowid(-1)\r
{\r
- m_statement=NULL;\r
- m_parametercount=0;\r
- m_resultcolumncount=0;\r
- m_rowreturned=false;\r
- m_lastinsertrowid=-1;\r
*this=rhs;\r
}\r
\r
Statement::~Statement()\r
{\r
- \r
Finalize();\r
- \r
- /*\r
- std::vector<char *>::iterator i;\r
- for(i=textptrs.begin(); i!=textptrs.end(); i++)\r
- {\r
- if((*i))\r
- {\r
- delete [] (*i);\r
- }\r
- }\r
- */\r
-\r
}\r
\r
const bool Statement::Bind(const int column)\r
{\r
if(Valid() && column>=0 && column<m_parametercount)\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
- //PThread::Guard g(DB::Instance()->m_mutex);\r
if(sqlite3_bind_null(m_statement,column+1)==SQLITE_OK)\r
{\r
return true;\r
{\r
if(Valid() && column>=0 && column<m_parametercount)\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
- //PThread::Guard g(DB::Instance()->m_mutex);\r
if(sqlite3_bind_int(m_statement,column+1,value)==SQLITE_OK)\r
{\r
return true;\r
{\r
if(Valid() && column>=0 && column<m_parametercount)\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
- //PThread::Guard g(DB::Instance()->m_mutex);\r
if(sqlite3_bind_double(m_statement,column+1,value)==SQLITE_OK)\r
{\r
return true;\r
{\r
if(Valid() && column>=0 && column<m_parametercount)\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
- //PThread::Guard g(DB::Instance()->m_mutex);\r
if(sqlite3_bind_text(m_statement,column+1,value.c_str(),value.size(),SQLITE_TRANSIENT)==SQLITE_OK)\r
{\r
return true;\r
{\r
if(Valid() && column>=0 && column<m_parametercount)\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
- //PThread::Guard g(DB::Instance()->m_mutex);\r
if(sqlite3_bind_blob(m_statement,column+1,data,length,SQLITE_TRANSIENT)==SQLITE_OK)\r
{\r
return true;\r
m_parametercount=rhs.m_parametercount;\r
m_resultcolumncount=rhs.m_resultcolumncount;\r
m_rowreturned=rhs.m_rowreturned;\r
+ m_lastinsertrowid=rhs.m_lastinsertrowid;\r
\r
if(m_statement)\r
{\r
db->Execute("UPDATE tblDBVersion SET Major=1, Minor=13;");\r
}\r
\r
+void ConvertDB0113To0114()\r
+{\r
+ SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
+\r
+ db->Execute("ALTER TABLE tblBoard ADD COLUMN Forum TEXT CHECK(Forum IN ('true','false')) DEFAULT 'false';");\r
+ db->Execute("ALTER TABLE tblMessage ADD COLUMN Read INTEGER CHECK(Read IN (0,1)) DEFAULT 0;");\r
+\r
+ db->Execute("UPDATE tblDBVersion SET Major=1, Minor=14;");\r
+}\r
+\r
void FixCapitalBoardNames()\r
{\r
SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
#include "../include/dbmaintenancethread.h"\r
#include "../include/stringfunctions.h"\r
#include "../include/option.h"\r
+#include "../include/threadbuilder.h"\r
\r
#include <Poco/Timestamp.h>\r
#include <Poco/Timespan.h>\r
void DBMaintenanceThread::Do10MinuteMaintenance()\r
{\r
\r
+ ThreadBuilder tb;\r
+ SQLite3DB::Statement boardst=m_db->Prepare("SELECT BoardID FROM tblBoard WHERE Forum='true';");\r
+ // select messages for a board that aren't in a thread\r
+ SQLite3DB::Statement selectst=m_db->Prepare("SELECT tblMessage.MessageID FROM tblMessage \\r
+ INNER JOIN tblMessageBoard ON tblMessage.MessageID=tblMessageBoard.MessageID\\r
+ LEFT JOIN tblThreadPost ON tblMessage.MessageID=tblThreadPost.MessageID \\r
+ LEFT JOIN tblThread ON tblThreadPost.ThreadID=tblThread.ThreadID\\r
+ WHERE tblMessageBoard.BoardID=? AND tblThread.BoardID IS NULL;");\r
+\r
+ boardst.Step();\r
+ while(boardst.RowReturned())\r
+ {\r
+ int boardid=-1;\r
+\r
+ boardst.ResultInt(0,boardid);\r
+\r
+ selectst.Bind(0,boardid);\r
+ selectst.Step();\r
+\r
+ while(selectst.RowReturned())\r
+ {\r
+ int messageid=-1;\r
+\r
+ selectst.ResultInt(0,messageid);\r
+\r
+ tb.Build(messageid,boardid,true);\r
+\r
+ selectst.Step();\r
+ }\r
+ selectst.Reset();\r
+\r
+ boardst.Step();\r
+ }\r
+\r
+ // now rebuild threads where the message has been deleted\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT tblThreadPost.MessageID, tblThread.BoardID FROM tblThreadPost INNER JOIN tblThread ON tblThreadPost.ThreadID=tblThread.ThreadID LEFT JOIN tblMessage ON tblThreadPost.MessageID=tblMessage.MessageID WHERE tblMessage.MessageID IS NULL;");\r
+ st.Step();\r
+ while(st.RowReturned())\r
+ {\r
+ int messageid=-1;\r
+ int boardid=-1;\r
+\r
+ st.ResultInt(0,messageid);\r
+ st.ResultInt(1,boardid);\r
+\r
+ tb.Build(messageid,boardid,true);\r
+\r
+ st.Step();\r
+ }\r
+\r
m_log->debug("PeriodicDBMaintenance::Do10MinuteMaintenance");\r
}\r
\r
void DBMaintenanceThread::Do30MinuteMaintenance()\r
{\r
-\r
+ // UNCOMMENT method in run when code is placed here\r
m_log->debug("PeriodicDBMaintenance::Do30MinuteMaintenance");\r
}\r
\r
m_log->debug("DBMaintenanceThread::run thread started.");\r
\r
Poco::DateTime now;\r
+ int i=0;\r
\r
do\r
{\r
Do10MinuteMaintenance();\r
m_last10minute=Poco::Timestamp();\r
}\r
+ /*\r
if((m_last30minute+Poco::Timespan(0,0,30,0,0))<=now)\r
{\r
Do30MinuteMaintenance();\r
m_last30minute=Poco::Timestamp();\r
}\r
+ */\r
if((m_last1hour+Poco::Timespan(0,1,0,0,0))<=now)\r
{\r
Do1HourMaintenance();\r
m_last1day=Poco::Timestamp();\r
}\r
\r
- Poco::Thread::sleep(1000);\r
+ i=0;\r
+ while(i++<5 && !IsCancelled())\r
+ {\r
+ Poco::Thread::sleep(1000);\r
+ }\r
+\r
}while(!IsCancelled());\r
\r
m_log->debug("DBMaintenanceThread::run thread exiting.");\r
major=1;\r
minor=13;\r
}\r
+ if(major==1 && minor==13)\r
+ {\r
+ ConvertDB0113To0114();\r
+ major=1;\r
+ minor=14;\r
+ }\r
}\r
else\r
{\r
- db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,13);");\r
+ db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,14);");\r
}\r
\r
- db->Execute("UPDATE tblDBVersion SET Major=1, Minor=13;");\r
+ db->Execute("UPDATE tblDBVersion SET Major=1, Minor=14;");\r
\r
db->Execute("CREATE TABLE IF NOT EXISTS tblFMSVersion(\\r
Major INTEGER,\\r
BoardDescription TEXT,\\r
DateAdded DATETIME,\\r
SaveReceivedMessages BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true',\\r
- AddedMethod TEXT\\r
+ AddedMethod TEXT,\\r
+ Forum TEXT CHECK(Forum IN('true','false')) DEFAULT 'false'\\r
);");\r
\r
- db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('fms','Freenet Message System','2007-12-01 12:00:00','Initial Board');");\r
- db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('freenet','Discussion about Freenet','2007-12-01 12:00:00','Initial Board');");\r
- db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('public','Public discussion','2007-12-01 12:00:00','Initial Board');");\r
- db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('test','Test board','2007-12-01 12:00:00','Initial Board');");\r
+ db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod,Forum) VALUES('fms','Freenet Message System','2007-12-01 12:00:00','Initial Board','true');");\r
+ db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod,Forum) VALUES('freenet','Discussion about Freenet','2007-12-01 12:00:00','Initial Board','true');");\r
+ db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod,Forum) VALUES('public','Public discussion','2007-12-01 12:00:00','Initial Board','true');");\r
+ db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod,Forum) VALUES('test','Test board','2007-12-01 12:00:00','Initial Board','true');");\r
\r
db->Execute("CREATE TABLE IF NOT EXISTS tblMessage(\\r
MessageID INTEGER PRIMARY KEY,\\r
MessageUUID TEXT UNIQUE,\\r
ReplyBoardID INTEGER,\\r
Body TEXT,\\r
- MessageIndex INTEGER\\r
+ MessageIndex INTEGER,\\r
+ Read INTEGER CHECK(Read IN(0,1)) DEFAULT 0\\r
);");\r
\r
db->Execute("CREATE INDEX IF NOT EXISTS idxMessage_IdentityID ON tblMessage (IdentityID);");\r
);");\r
\r
db->Execute("CREATE INDEX IF NOT EXISTS idxMessageReplyTo_MessageID ON tblMessageReplyTo (MessageID);");\r
+ db->Execute("CREATE INDEX IF NOT EXISTS idxMessageReplyTo_ReplyToMessageUUID ON tblMessageReplyTo (ReplyToMessageUUID);");\r
\r
db->Execute("CREATE TABLE IF NOT EXISTS tblMessageBoard(\\r
MessageID INTEGER,\\r
Day DATE,\\r
RequestIndex INTEGER,\\r
Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
- );"); \r
+ );");\r
+\r
+ // begin thread db schema\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblThread(\\r
+ ThreadID INTEGER PRIMARY KEY,\\r
+ BoardID INTEGER,\\r
+ FirstMessageID INTEGER,\\r
+ LastMessageID INTEGER\\r
+ );");\r
+\r
+ db->Execute("CREATE INDEX IF NOT EXISTS idxThread_BoardID ON tblThread(BoardID);");\r
+ db->Execute("CREATE INDEX IF NOT EXISTS idxThread_FirstMessageID ON tblThread(FirstMessageID);");\r
+ db->Execute("CREATE INDEX IF NOT EXISTS idxThread_LastMessageID ON tblThread(LastMessageID);");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblThreadPost(\\r
+ ThreadID INTEGER,\\r
+ MessageID INTEGER,\\r
+ PostOrder INTEGER\\r
+ );");\r
+\r
+ db->Execute("CREATE INDEX IF NOT EXISTS idxThreadPost_ThreadID ON tblThreadPost(ThreadID);");\r
+ db->Execute("CREATE INDEX IF NOT EXISTS idxThreadPost_MessageID ON tblThreadPost(MessageID);");\r
+\r
+ db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteOnThread AFTER DELETE ON tblThread\\r
+ FOR EACH ROW\\r
+ BEGIN\\r
+ DELETE FROM tblThreadPost WHERE ThreadID=old.ThreadID;\\r
+ END;");\r
+ // end thread db schema\r
\r
// MessageInserter will insert a record into this temp table which the MessageListInserter will query for and insert a MessageList when needed\r
db->Execute("CREATE TEMPORARY TABLE IF NOT EXISTS tmpMessageListInsert(\\r
{\r
logger().trace("FMSApp::StartThreads starting HTTPThread");\r
m_threads.Start(new HTTPThread());\r
+ if(isInteractive())\r
+ {\r
+ std::cout << "Started HTTP Thread" << std::endl;\r
+ }\r
}\r
else\r
{\r
{\r
logger().trace("FMSApp::StartThreads starting NNTPListener");\r
m_threads.Start(new NNTPListener());\r
+ if(isInteractive())\r
+ {\r
+ std::cout << "Started NNTP Thread" << std::endl;\r
+ }\r
}\r
else\r
{\r
{\r
logger().trace("FMSApp::StartThreads starting FreenetMasterThread");\r
m_threads.Start(new FreenetMasterThread());\r
+ if(isInteractive())\r
+ {\r
+ std::cout << "Started Freenet FCP Thread" << std::endl;\r
+ }\r
}\r
else\r
{\r
Initialize();\r
}\r
\r
-void IntroductionPuzzleRequester::FCPConnected()\r
-{\r
- m_requesting.clear();\r
- PopulateIDList();\r
-}\r
-\r
-void IntroductionPuzzleRequester::FCPDisconnected()\r
-{\r
- \r
-}\r
-\r
const bool IntroductionPuzzleRequester::HandleAllData(FCPMessage &message)\r
{\r
Poco::DateTime now;\r
st.Step();\r
}\r
\r
+ m_log->trace("MessageInserter::HandlePutFailed error code "+message["Code"]+" fatal="+message["Fatal"]);\r
+\r
RemoveFromInsertList(idparts[1]);\r
\r
return true;\r
date-=Poco::Timespan(m_daysbackward,0,0,0,0);\r
StringFunctions::Convert(localidentityid,localidentityidstr);\r
\r
- SQLite3DB::Statement st=m_db->Prepare("SELECT Day, InsertIndex, MessageXML, PrivateKey FROM tblMessageInserts INNER JOIN tblLocalIdentity ON tblMessageInserts.LocalIdentityID=tblLocalIdentity.LocalIdentityID WHERE tblLocalIdentity.LocalIdentityID=? AND Day>=?;");\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT Day, InsertIndex, MessageXML, PrivateKey FROM tblMessageInserts INNER JOIN tblLocalIdentity ON tblMessageInserts.LocalIdentityID=tblLocalIdentity.LocalIdentityID WHERE tblLocalIdentity.LocalIdentityID=? AND Day>=? AND tblMessageInserts.MessageUUID IS NOT NULL;");\r
st.Bind(0,localidentityid);\r
st.Bind(1,Poco::DateTimeFormatter::format(date,"%Y-%m-%d"));\r
st.Step();\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
+#include "../../include/http/pages/forumviewthreadpage.h"\r
+#include "../../include/http/pages/forumcreatepostpage.h"\r
\r
FMSHTTPRequestHandlerFactory::FMSHTTPRequestHandlerFactory()\r
{\r
m_log->error("HTTPThread::HTTPThread could not open template.htm");\r
}\r
\r
+ // load forum template\r
+ std::string forumtemplate="<html><head></head><body><a href=\"home.htm\">Home</a><br><h1>Could not open forum-template.htm! Place in program directory and restart!</h1><br>[CONTENT]</body></html>";\r
+ infile=fopen("forum-template.htm","rb");\r
+ if(infile)\r
+ {\r
+ fseek(infile,0,SEEK_END);\r
+ long len=ftell(infile);\r
+ std::vector<char> data(len,0);\r
+ fseek(infile,0,SEEK_SET);\r
+ fread(&data[0],1,len,infile);\r
+ fclose(infile);\r
+ forumtemplate.assign(data.begin(),data.end());\r
+ }\r
+ else\r
+ {\r
+ m_log->error("HTTPThread::HTTPThread could not open forum-template.htm");\r
+ }\r
+\r
// push back page handlers\r
m_pagehandlers.push_back(new OptionsPage(templatestr));\r
m_pagehandlers.push_back(new CreateIdentityPage(templatestr));\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
+ m_pagehandlers.push_back(new ForumViewThreadPage(forumtemplate));\r
+ m_pagehandlers.push_back(new ForumCreatePostPage(forumtemplate));\r
// homepage must be last - catch all page handler\r
m_pagehandlers.push_back(new HomePage(templatestr));\r
\r
return false;\r
}\r
}\r
+\r
+const bool IPageHandler::WillHandleURI(const std::string &uri)\r
+{\r
+ if(uri.find(m_pagename)!=std::string::npos)\r
+ {\r
+ return true;\r
+ }\r
+ else\r
+ {\r
+ return false;\r
+ }\r
+}\r
content+="<tr><td colspan=\"4\"><center>Select Identity : ";\r
content+=CreateLocalIdentityDropDown("localidentityid","");\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. 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><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
\r
date-=Poco::Timespan(1,0,0,0,0);\r
\r
if(st.RowReturned()==false)\r
{\r
- content+="<td colspan=\"4\"><center>You must wait for some puzzles to be downloaded. Check back later.</td>";\r
+ content+="<td colspan=\"4\"><center>You must wait for some puzzles to be downloaded. Make sure you have assigned trust to some other identities' trust lists and check back later.</td>";\r
}\r
\r
while(st.RowReturned() && shown<20)\r
std::vector<std::string> descriptions;\r
std::vector<std::string> oldsavemessages;\r
std::vector<std::string> savemessages;\r
+ std::vector<std::string> oldforums;\r
+ std::vector<std::string> forums;\r
\r
CreateArgArray(queryvars,"boardid",boardids);\r
CreateArgArray(queryvars,"oldboarddescription",olddescriptions);\r
CreateArgArray(queryvars,"boarddescription",descriptions);\r
CreateArgArray(queryvars,"oldsavereceivedmessages",oldsavemessages);\r
CreateArgArray(queryvars,"savereceivedmessages",savemessages);\r
+ CreateArgArray(queryvars,"oldforum",oldforums);\r
+ CreateArgArray(queryvars,"forum",forums);\r
\r
olddescriptions.resize(boardids.size(),"");\r
descriptions.resize(boardids.size(),"");\r
oldsavemessages.resize(boardids.size(),"");\r
savemessages.resize(boardids.size(),"");\r
+ oldforums.resize(boardids.size(),"");\r
+ forums.resize(boardids.size(),"");\r
\r
- SQLite3DB::Statement updatest=m_db->Prepare("UPDATE tblBoard SET BoardDescription=?, SaveReceivedMessages=? WHERE BoardID=?;");\r
+ SQLite3DB::Statement updatest=m_db->Prepare("UPDATE tblBoard SET BoardDescription=?, SaveReceivedMessages=?, Forum=? WHERE BoardID=?;");\r
\r
for(int i=0; i<boardids.size(); i++)\r
{\r
- if(olddescriptions[i]!=descriptions[i] || oldsavemessages[i]!=savemessages[i])\r
+ if(olddescriptions[i]!=descriptions[i] || oldsavemessages[i]!=savemessages[i] || oldforums[i]!=forums[i])\r
{\r
updatest.Bind(0,descriptions[i]);\r
if(savemessages[i]!="true")\r
{\r
updatest.Bind(1,"true");\r
}\r
+ if(forums[i]!="true")\r
+ {\r
+ updatest.Bind(2,"false");\r
+ }\r
+ else\r
+ {\r
+ updatest.Bind(2,"true");\r
+ }\r
boardid=0;\r
StringFunctions::Convert(boardids[i],boardid);\r
- updatest.Bind(2,boardid);\r
+ updatest.Bind(3,boardid);\r
updatest.Step();\r
updatest.Reset();\r
}\r
st.Finalize();\r
\r
\r
- sql="SELECT BoardID,BoardName,BoardDescription,SaveReceivedMessages,AddedMethod FROM tblBoard WHERE BoardID NOT IN (SELECT BoardID FROM tblAdministrationBoard)";\r
+ sql="SELECT BoardID,BoardName,BoardDescription,SaveReceivedMessages,AddedMethod,Forum FROM tblBoard WHERE BoardID NOT IN (SELECT BoardID FROM tblAdministrationBoard)";\r
if(boardsearch!="")\r
{\r
sql+=" AND (BoardName LIKE '%' || ? || '%' OR BoardDescription LIKE '%' || ? || '%')";\r
}\r
st.Step();\r
\r
- content+="<table>";\r
+ content+="<table class=\"small90\">";\r
\r
content+="<tr>";\r
content+="<td colspan=\"3\"><center>";\r
\r
content+="<tr><td colspan=\"4\"><hr><form name=\"frmboards\" method=\"POST\"><input type=\"hidden\" name=\"formaction\" value=\"update\">"+CreateFormPassword()+"</td></tr>";\r
content+="<tr>";\r
- content+="<th>Name</th><th>Description</th><th>Save Received Messages *</th><th>Added Method</th>";\r
+ content+="<th>Name</th><th>Description</th><th>Save Received Messages *</th><th>Forum</th><th>Added Method</th>";\r
content+="</tr>"; \r
while(st.RowReturned() && rownum<rowsperpage)\r
{\r
std::string boarddescription="";\r
std::string savereceivedmessages="";\r
std::string addedmethod="";\r
+ std::string forum="";\r
\r
st.ResultText(0,boardidstr);\r
st.ResultText(1,boardname);\r
st.ResultText(2,boarddescription);\r
st.ResultText(3,savereceivedmessages);\r
st.ResultText(4,addedmethod);\r
+ st.ResultText(5,forum);\r
\r
StringFunctions::Convert(rownum,rownumstr);\r
\r
}\r
content+=">";\r
content+="</td>";\r
- content+="<td class=\"smaller\">"+SanitizeOutput(addedmethod)+"</td>";\r
+ content+="<td>";\r
+ content+="<input type=\"hidden\" name=\"oldforum["+rownumstr+"]\" value=\""+forum+"\">";\r
+ content+="<input type=\"checkbox\" name=\"forum["+rownumstr+"]\" value=\"true\"";\r
+ if(forum=="true")\r
+ {\r
+ content+=" CHECKED";\r
+ }\r
+ content+=">";\r
+ content+="</td>";\r
+ content+="<td>"+SanitizeOutput(addedmethod)+"</td>";\r
content+="</tr>\r\n";\r
st.Step();\r
rownum++;\r
if(startrow>0)\r
{\r
StringFunctions::Convert(startrow-rowsperpage,tempstr);\r
- content+="<td colspan=\"1\" align=\"left\"><a href=\"boards.htm?"+BuildQueryString(startrow-rowsperpage,boardsearch)+"\"><-- Previous Page</a></td>";\r
- cols+=1;\r
+ content+="<td colspan=\"2\" style=\"text-align:left;\"><a href=\"boards.htm?"+BuildQueryString(startrow-rowsperpage,boardsearch)+"\"><-- Previous Page</a></td>";\r
+ cols+=2;\r
}\r
if(startrow+rowsperpage<boardcount)\r
{\r
- while(cols<3)\r
+ while(cols<4)\r
{\r
content+="<td></td>";\r
cols++;\r
}\r
- content+="<td colspan=\"1\" align=\"right\"><a href=\"boards.htm?"+BuildQueryString(startrow+rowsperpage,boardsearch)+"\">Next Page --></a></td>";\r
+ content+="<td colspan=\"1\" style=\"text-align:left;\"><a href=\"boards.htm?"+BuildQueryString(startrow+rowsperpage,boardsearch)+"\">Next Page --></a></td>";\r
}\r
content+="</tr>";\r
}\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
--- /dev/null
+#include "../../../include/http/pages/forumcreatepostpage.h"\r
+#include "../../../include/stringfunctions.h"\r
+#include "../../../include/message.h"\r
+\r
+#ifdef XMEM\r
+ #include <xmem.h>\r
+#endif\r
+\r
+const std::string ForumCreatePostPage::GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars)\r
+{\r
+ int page=0;\r
+ std::string content="";\r
+ std::string boardidstr="";\r
+ std::string currentpagestr="";\r
+ std::string threadidstr="";\r
+ std::string replytomessageidstr="";\r
+ std::string error="";\r
+ std::string boardname="";\r
+ std::string subject="";\r
+ std::string body="";\r
+ std::string localidentityidstr="";\r
+\r
+ if(queryvars.find("boardid")!=queryvars.end())\r
+ {\r
+ boardidstr=(*queryvars.find("boardid")).second;\r
+ }\r
+ if(queryvars.find("currentpage")!=queryvars.end())\r
+ {\r
+ currentpagestr=(*queryvars.find("currentpage")).second;\r
+ }\r
+ if(queryvars.find("threadid")!=queryvars.end())\r
+ {\r
+ threadidstr=(*queryvars.find("threadid")).second;\r
+ }\r
+ if(queryvars.find("replytomessageid")!=queryvars.end())\r
+ {\r
+ replytomessageidstr=(*queryvars.find("replytomessageid")).second;\r
+ }\r
+\r
+ if(queryvars.find("formaction")!=queryvars.end() && (*queryvars.find("formaction")).second=="send")\r
+ {\r
+ if(queryvars.find("localidentityid")!=queryvars.end() && (*queryvars.find("localidentityid")).second!="")\r
+ {\r
+ localidentityidstr=(*queryvars.find("localidentityid")).second;\r
+ }\r
+ else\r
+ {\r
+ error="You must select a local identity as the sender<br />";\r
+ }\r
+\r
+ if(queryvars.find("subject")!=queryvars.end() && (*queryvars.find("subject")).second!="")\r
+ {\r
+ subject=(*queryvars.find("subject")).second;\r
+ }\r
+ else\r
+ {\r
+ error+="You must enter a subject<br />";\r
+ }\r
+\r
+ if(queryvars.find("body")!=queryvars.end() && (*queryvars.find("body")).second!="")\r
+ {\r
+ body=(*queryvars.find("body")).second;\r
+ body=StringFunctions::Replace(body,"\r\n","\n");\r
+ }\r
+ else\r
+ {\r
+ error+="You must enter a message body</br />";\r
+ }\r
+\r
+ if(error=="")\r
+ {\r
+ Message mess;\r
+ \r
+ long localidentityid=-1;\r
+ long boardid=-1;\r
+ std::string references="";\r
+\r
+ StringFunctions::Convert(localidentityidstr,localidentityid);\r
+ StringFunctions::Convert(boardidstr,boardid);\r
+\r
+ if(replytomessageidstr!="")\r
+ {\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT MessageUUID FROM tblMessage WHERE MessageID=?;");\r
+ st.Bind(0,replytomessageidstr);\r
+ st.Step();\r
+ if(st.RowReturned())\r
+ {\r
+ st.ResultText(0,references);\r
+ }\r
+ }\r
+\r
+ if(mess.Create(localidentityid,boardid,subject,body,references))\r
+ {\r
+ if(mess.PostedToAdministrationBoard()==true)\r
+ {\r
+ mess.HandleAdministrationMessage();\r
+ }\r
+ if(mess.StartFreenetInsert())\r
+ {\r
+ page=1;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ error="Could not create message";\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if(replytomessageidstr!="")\r
+ {\r
+ SQLite3DB::Statement replyst=m_db->Prepare("SELECT Subject, Body FROM tblMessage WHERE MessageID=?;");\r
+ replyst.Bind(0,replytomessageidstr);\r
+ replyst.Step();\r
+ if(replyst.RowReturned())\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
+ {\r
+ subject="Re: "+subject;\r
+ }\r
+\r
+ if(body.size()>0)\r
+ {\r
+ if(body[0]=='>')\r
+ {\r
+ body=">"+body;\r
+ }\r
+ else\r
+ {\r
+ body="> "+body;\r
+ }\r
+ std::string::size_type pos=body.find("\n");\r
+ while(pos!=std::string::npos)\r
+ {\r
+ if(pos+1<body.size() && body[pos+1]=='>')\r
+ {\r
+ body.insert(pos+1,">");\r
+ }\r
+ else\r
+ {\r
+ body.insert(pos+1,"> ");\r
+ }\r
+ pos=body.find("\n",pos+2);\r
+ }\r
+ body+="\n";\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ SQLite3DB::Statement boardnamest=m_db->Prepare("SELECT BoardName FROM tblBoard WHERE BoardID=?;");\r
+ boardnamest.Bind(0,boardidstr);\r
+ boardnamest.Step();\r
+ if(boardnamest.RowReturned())\r
+ {\r
+ boardnamest.ResultText(0,boardname);\r
+ }\r
+\r
+ content+=CreateForumHeader();\r
+\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
+ content+="</tr>";\r
+ content+="</table>\r\n";\r
+\r
+ if(error!="")\r
+ {\r
+ content+="<div class=\"error\">"+error+"</div>\r\n";\r
+ }\r
+\r
+ if(page==0)\r
+ {\r
+ content+="<form name=\"frmcreatemessage\" method=\"post\" action=\"forumcreatepost.htm\">";\r
+ content+="<input type=\"hidden\" name=\"boardid\" value=\""+boardidstr+"\">";\r
+ content+="<input type=\"hidden\" name=\"currentpage\" value=\""+currentpagestr+"\">";\r
+ content+="<input type=\"hidden\" name=\"threadid\" value=\""+threadidstr+"\">";\r
+ content+="<input type=\"hidden\" name=\"replytomessageid\" value=\""+replytomessageidstr+"\">";\r
+ content+="<input type=\"hidden\" name=\"formaction\" value=\"send\">";\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 colspan=\"2\" class=\"send\"><input type=\"submit\" value=\"Send\"></td></tr>";\r
+ content+="</table>\r\n";\r
+ content+="</form>";\r
+ }\r
+ else if(page==1)\r
+ {\r
+ content+="You have sent your message. It will show up in the thread after it has been successfully inserted and retrieved by FMS.";\r
+ }\r
+\r
+ return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+}\r
+\r
+const std::string ForumCreatePostPage::LocalIdentityDropDown(const std::string &name, const std::string &selectedid)\r
+{\r
+ std::string html="<select name=\""+name+"\">";\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT LocalIdentityID, Name FROM tblLocalIdentity ORDER BY Name COLLATE NOCASE ASC;");\r
+\r
+ if(selectedid=="")\r
+ {\r
+ html+="<option value=\"\" selected></option>";\r
+ }\r
+\r
+ st.Step();\r
+ while(st.RowReturned())\r
+ {\r
+ std::string id="";\r
+ std::string name="";\r
+ st.ResultText(0,id);\r
+ st.ResultText(1,name);\r
+ html+="<option value=\""+id+"\"";\r
+ if(id==selectedid)\r
+ {\r
+ html+=" selected";\r
+ }\r
+ html+=">"+FixFromName(name)+"</option>";\r
+ st.Step();\r
+ }\r
+ html+="</select>";\r
+ return html;\r
+}\r
--- /dev/null
+#include "../../../include/http/pages/forummainpage.h"\r
+#include "../../../include/stringfunctions.h"\r
+\r
+#ifdef XMEM\r
+ #include <xmem.h>\r
+#endif\r
+\r
+const std::string ForumMainPage::GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars)\r
+{\r
+ std::string content="";\r
+\r
+ content+=CreateForumHeader();\r
+\r
+ content+="<table class=\"foruminfo\">\r\n";\r
+ content+="<thead><tr><th>New</th><th>Forum</th><th>Posts</th><th>Last Post</th></tr></thead>\r\n";\r
+\r
+ SQLite3DB::Statement newmessagesst=m_db->Prepare("SELECT tblMessage.MessageID FROM tblMessage INNER JOIN tblMessageBoard ON tblMessage.MessageID=tblMessageBoard.MessageID INNER JOIN tblThreadPost ON tblMessage.MessageID=tblThreadPost.MessageID WHERE tblMessageBoard.BoardID=? AND tblMessage.Read=0 LIMIT 0,1;");\r
+ SQLite3DB::Statement lastmessagest=m_db->Prepare("SELECT tblMessage.MessageID, tblMessage.IdentityID, tblMessage.FromName, tblMessage.Subject, tblMessage.MessageDate || ' ' || tblMessage.MessageTime, tblThread.ThreadID FROM tblMessage INNER JOIN tblThreadPost ON tblMessage.MessageID=tblThreadPost.MessageID INNER JOIN tblThread ON tblThreadPost.ThreadID=tblThread.ThreadID WHERE tblThread.BoardID=? ORDER BY tblMessage.MessageDate || tblMessage.MessageTime DESC LIMIT 0,1;");\r
+ \r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT tblBoard.BoardID, BoardName, BoardDescription, COUNT(tblThreadPost.MessageID) FROM tblBoard LEFT JOIN tblThread ON tblBoard.BoardID=tblThread.BoardID LEFT JOIN tblThreadPost ON tblThread.ThreadID=tblThreadPost.ThreadID WHERE Forum='true' GROUP BY tblBoard.BoardID ORDER BY BoardName COLLATE NOCASE;");\r
+ st.Step();\r
+ while(st.RowReturned())\r
+ {\r
+ int boardid=-1;\r
+ std::string boardidstr="-1";\r
+ std::string boardname="";\r
+ std::string boarddescription="";\r
+ std::string postcountstr="";\r
+\r
+ st.ResultInt(0,boardid);\r
+ st.ResultText(0,boardidstr);\r
+ st.ResultText(1,boardname);\r
+ st.ResultText(2,boarddescription);\r
+ st.ResultText(3,postcountstr);\r
+\r
+ content+="<tr>";\r
+ content+="<td class=\"newposts\">";\r
+\r
+ newmessagesst.Bind(0,boardid);\r
+ newmessagesst.Step();\r
+ if(newmessagesst.RowReturned())\r
+ {\r
+ content+="<img src=\"showimage.htm?image=images/new_posts.png\" title=\"New Posts\">";\r
+ }\r
+ else\r
+ {\r
+ content+="<img src=\"showimage.htm?image=images/no_new_posts.png\" title=\"No New Posts\">";\r
+ }\r
+ newmessagesst.Reset();\r
+\r
+ content+="</td>";\r
+\r
+ content+="<td class=\"forumname\">";\r
+ content+="<a href=\"forumthreads.htm?boardid="+boardidstr+"\">"+SanitizeOutput(boardname)+"</a><br />";\r
+ content+="<span class=\"description\">"+SanitizeOutput(boarddescription)+"</span>";\r
+ content+="</td>";\r
+ content+="<td class=\"postcount\">";\r
+ content+=postcountstr+" posts";\r
+ content+="</td>";\r
+\r
+ lastmessagest.Bind(0,boardid);\r
+ lastmessagest.Step();\r
+ content+="<td class=\"lastpost\">";\r
+ if(lastmessagest.RowReturned())\r
+ {\r
+ std::string messageidstr="";\r
+ std::string identityidstr="";\r
+ std::string fromname="";\r
+ std::string messagedate="";\r
+ std::string subject="";\r
+ std::string threadidstr="";\r
+\r
+ lastmessagest.ResultText(0,messageidstr);\r
+ lastmessagest.ResultText(1,identityidstr);\r
+ lastmessagest.ResultText(2,fromname);\r
+ lastmessagest.ResultText(3,subject);\r
+ lastmessagest.ResultText(4,messagedate);\r
+ lastmessagest.ResultText(5,threadidstr);\r
+\r
+ content+="Last post on "+messagedate+" in<br />";\r
+ content+="<a href=\"forumviewthread.htm?threadid="+threadidstr+"&boardid="+boardidstr+"#"+messageidstr+"\">"+FixSubject(subject)+"</a> by <a href=\"peerdetails.htm?identityid="+identityidstr+"\" title=\""+SanitizeOutput(fromname)+"\">"+FixFromName(fromname)+"</a>";\r
+ }\r
+ content+="</td>";\r
+ lastmessagest.Reset();\r
+\r
+ content+="</tr>\r\n";\r
+ st.Step();\r
+ }\r
+\r
+ content+="</table>\r\n";\r
+\r
+ return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+}\r
--- /dev/null
+#include "../../../include/http/pages/forumthreadspage.h"\r
+#include "../../../include/stringfunctions.h"\r
+#include <cmath>\r
+\r
+const std::string ForumThreadsPage::GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars)\r
+{\r
+ int currentpage=1;\r
+ std::string currentpagestr="1";\r
+ std::string content="";\r
+ int startrow=0;\r
+ std::string startrowstr="0";\r
+ int rowsperpage=25;\r
+ std::string rowsperpagestr="25";\r
+ std::string sql="";\r
+ int boardid=-1;\r
+ std::string boardidstr="-1";\r
+ int count=0;\r
+ int threadcount=0;\r
+ SQLite3DB::Statement newthreadpostst=m_db->Prepare("SELECT tblMessage.MessageID FROM tblThreadPost INNER JOIN tblMessage ON tblThreadPost.MessageID=tblMessage.MessageID WHERE tblThreadPost.ThreadID=? AND tblMessage.Read=0 LIMIT 0,1;");\r
+ SQLite3DB::Statement replycountst=m_db->Prepare("SELECT COUNT(*)-1 FROM tblThreadPost WHERE ThreadID=?;");\r
+ SQLite3DB::Statement boardnamest=m_db->Prepare("SELECT tblBoard.BoardName FROM tblBoard WHERE BoardID=?;");\r
+ SQLite3DB::Statement threadcountst=m_db->Prepare("SELECT COUNT(*) FROM tblThread WHERE BoardID=?;");\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("currentpage")!=queryvars.end())\r
+ {\r
+ currentpagestr=(*queryvars.find("currentpage")).second;\r
+ StringFunctions::Convert(currentpagestr,currentpage);\r
+ if(currentpage<0)\r
+ {\r
+ currentpage=0;\r
+ }\r
+ StringFunctions::Convert(currentpage,currentpagestr);\r
+ }\r
+ if(queryvars.find("formaction")!=queryvars.end() && (*queryvars.find("formaction")).second=="markallread" && boardid!=-1)\r
+ {\r
+ SQLite3DB::Statement markst=m_db->Prepare("UPDATE tblMessage SET Read=1 WHERE tblMessage.Read=0 AND tblMessage.MessageID IN (SELECT MessageID FROM tblThread INNER JOIN tblThreadPost ON tblThread.ThreadID=tblThreadPost.ThreadID WHERE tblThread.BoardID=?);");\r
+ markst.Bind(0,boardid);\r
+ markst.Step();\r
+ }\r
+\r
+ startrow=(currentpage-1)*rowsperpage;\r
+ StringFunctions::Convert(startrow,startrowstr);\r
+\r
+ content+=CreateForumHeader();\r
+\r
+ content+="<table class=\"forumheader\">";\r
+ content+="<tr>";\r
+\r
+ boardnamest.Bind(0,boardid);\r
+ boardnamest.Step();\r
+ if(boardnamest.RowReturned())\r
+ {\r
+ std::string boardname="";\r
+ boardnamest.ResultText(0,boardname);\r
+ content+="<td>Forum : <a href=\"forumthreads.htm?boardid="+boardidstr+"\">"+SanitizeOutput(boardname)+"</a></td>";\r
+ }\r
+ content+="<td><a href=\"forumthreads.htm?boardid="+boardidstr+"¤tpage="+currentpagestr+"&formaction=markallread\">Mark All Read</a></td>";\r
+ content+="<td><a href=\"forumcreatepost.htm?boardid="+boardidstr+"¤tpage="+currentpagestr+"\">New Post</a></td>";\r
+ content+="</tr>";\r
+ content+="</table>\r\n";\r
+\r
+ content+="<table class=\"threadinfo\">";\r
+ content+="<thead><tr><th>New</th><th>Subject</th><th>Started By</th><th>Replies</th><th>Last Post</th></tr></thread>\r\n";\r
+ \r
+ sql="SELECT tblThread.ThreadID, tblThread.LastMessageID, tblLastMessage.FromName, tblLastMessage.MessageDate || ' ' || tblLastMessage.MessageTime, tblFirstMessage.Subject, tblFirstMessage.FromName, tblFirstMessage.IdentityID, tblLastMessage.IdentityID";\r
+ sql+=" FROM tblThread INNER JOIN tblMessage AS tblLastMessage ON tblThread.LastMessageID=tblLastMessage.MessageID INNER JOIN tblMessage AS tblFirstMessage ON tblThread.FirstMessageID=tblFirstMessage.MessageID";\r
+ sql+=" WHERE tblThread.BoardID=?";\r
+ sql+=" ORDER BY tblLastMessage.MessageDate || tblLastMessage.MessageTime DESC";\r
+ sql+=" LIMIT "+startrowstr+","+rowsperpagestr+";";\r
+\r
+ SQLite3DB::Statement threadst=m_db->Prepare(sql);\r
+ threadst.Bind(0,boardid);\r
+ threadst.Step();\r
+ count=0;\r
+ while(threadst.RowReturned() && count++<rowsperpage)\r
+ {\r
+ std::string threadidstr="";\r
+ std::string lastmessageidstr="";\r
+ std::string lastmessagefromname="";\r
+ std::string lastmessagedate="";\r
+ std::string firstmessagesubject="";\r
+ std::string firstmessagefromname="";\r
+ std::string firstmessageidentityidstr="";\r
+ std::string lastmessageidentityidstr="";\r
+\r
+ threadst.ResultText(0,threadidstr);\r
+ threadst.ResultText(1,lastmessageidstr);\r
+ threadst.ResultText(2,lastmessagefromname);\r
+ threadst.ResultText(3,lastmessagedate);\r
+ threadst.ResultText(4,firstmessagesubject);\r
+ threadst.ResultText(5,firstmessagefromname);\r
+ threadst.ResultText(6,firstmessageidentityidstr);\r
+ threadst.ResultText(7,lastmessageidentityidstr);\r
+\r
+ content+="<tr>";\r
+ content+="<td class=\"newposts\">";\r
+\r
+ newthreadpostst.Bind(0,threadidstr);\r
+ newthreadpostst.Step();\r
+ if(newthreadpostst.RowReturned())\r
+ {\r
+ content+="<img src=\"showimage.htm?image=images/new_posts.png\" title=\"New Posts\">";\r
+ }\r
+ else\r
+ {\r
+ content+="<img src=\"showimage.htm?image=images/no_new_posts.png\" title=\"No New Posts\">";\r
+ }\r
+ newthreadpostst.Reset();\r
+\r
+ content+="</td>";\r
+ content+="<td class=\"threadsubject\">";\r
+ content+="<a href=\"forumviewthread.htm?threadid="+threadidstr+"¤tpage="+currentpagestr+"&boardid="+boardidstr+"\">"+SanitizeOutput(firstmessagesubject)+"</a>";\r
+ content+="</td>";\r
+ content+="<td class=\"threadauthor\">";\r
+ content+="<a href=\"peerdetails.htm?identityid="+firstmessageidentityidstr+"\">"+FixFromName(firstmessagefromname)+"</a>";\r
+ content+="</td>";\r
+\r
+ content+="<td class=\"threadreplies\">";\r
+\r
+ replycountst.Bind(0,threadidstr);\r
+ replycountst.Step();\r
+ if(replycountst.RowReturned())\r
+ {\r
+ std::string count="0";\r
+ replycountst.ResultText(0,count);\r
+ content+=count;\r
+ }\r
+ else\r
+ {\r
+ content+="0";\r
+ }\r
+ replycountst.Reset();\r
+\r
+ content+="</td>";\r
+\r
+ content+="<td class=\"threadlastpost\">";\r
+ content+=lastmessagedate+"<br />by <a href=\"peerdetails.htm?identityid="+lastmessageidentityidstr+"\">"+FixFromName(lastmessagefromname)+"</a>";\r
+ content+="</td>";\r
+\r
+ content+="</tr>\r\n";\r
+\r
+ threadst.Step();\r
+ }\r
+\r
+ threadcountst.Bind(0,boardid);\r
+ threadcountst.Step();\r
+ if(threadcountst.RowReturned())\r
+ {\r
+ threadcountst.ResultInt(0,threadcount);\r
+ }\r
+\r
+ if(threadcount>=rowsperpage)\r
+ {\r
+ int totalpages=ceil(static_cast<float>(threadcount)/static_cast<float>(rowsperpage));\r
+ int lastwrote=0;\r
+ content+="<tr>";\r
+ \r
+ content+="<td class=\"pages\" colspan=\"7\">Pages : ";\r
+\r
+ for(int i=1; i<=totalpages; i++)\r
+ {\r
+ if(i==1 || (i>currentpage-3 && i<currentpage+3) || i==totalpages)\r
+ {\r
+ std::string pagestr="";\r
+ StringFunctions::Convert(i,pagestr);\r
+ if(lastwrote!=i-1)\r
+ {\r
+ content+=" ...";\r
+ }\r
+ if(i!=currentpage)\r
+ {\r
+ content+=" <a href=\"forumthreads.htm?boardid="+boardidstr+"¤tpage="+pagestr+"\">"+pagestr+"</a>";\r
+ }\r
+ else\r
+ {\r
+ content+=" "+pagestr;\r
+ }\r
+ lastwrote=i;\r
+ }\r
+ }\r
+\r
+ content+="<form><input type=\"hidden\" name=\"boardid\" value=\""+boardidstr+"\"><input type=\"text\" name=\"currentpage\"><input type=\"submit\" value=\"Go\"></form>";\r
+ \r
+ content+="</td>";\r
+\r
+ content+="</tr>\r\n";\r
+ }\r
+ \r
+ content+="</table>\r\n";\r
+\r
+ return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+}\r
--- /dev/null
+#include "../../../include/http/pages/forumviewthreadpage.h"\r
+#include "../../../include/stringfunctions.h"\r
+\r
+#ifdef XMEM\r
+ #include <xmem.h>\r
+#endif\r
+\r
+const std::string ForumViewThreadPage::FixBody(const std::string &body)\r
+{\r
+ static std::string whitespace=" \t\r\n";\r
+ std::string output=body;\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
+ while(pos!=std::string::npos)\r
+ {\r
+ while(pos-prevpos>80)\r
+ {\r
+ output.insert(prevpos+80,"\n");\r
+ prevpos+=81; // 81 because of the extra newline we just inserted\r
+ }\r
+ prevpos=pos;\r
+ pos=output.find_first_of(whitespace,pos+1);\r
+ }\r
+ while(output.size()-prevpos>80) // check the last line of the message (no whitespace after it)\r
+ {\r
+ output.insert(prevpos+80,"\n");\r
+ prevpos+=81;\r
+ }\r
+\r
+ output=StringFunctions::Replace(output,"<","<");\r
+ output=StringFunctions::Replace(output,">",">");\r
+ output=StringFunctions::Replace(output,"\n","<br />");\r
+ return output;\r
+}\r
+\r
+const std::string ForumViewThreadPage::GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars)\r
+{\r
+ std::string content="";\r
+ std::string threadidstr="";\r
+ std::string boardidstr="";\r
+ std::string currentpagestr="";\r
+ std::string boardname="";\r
+\r
+ if(queryvars.find("threadid")!=queryvars.end())\r
+ {\r
+ threadidstr=(*queryvars.find("threadid")).second;\r
+ }\r
+ if(queryvars.find("currentpage")!=queryvars.end())\r
+ {\r
+ currentpagestr=(*queryvars.find("currentpage")).second;\r
+ }\r
+ if(queryvars.find("boardid")!=queryvars.end())\r
+ {\r
+ boardidstr=(*queryvars.find("boardid")).second;\r
+ }\r
+\r
+ content+=CreateForumHeader();\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
+\r
+ SQLite3DB::Statement trustst=m_db->Prepare("SELECT LocalMessageTrust, LocalTrustListTrust, PeerMessageTrust, PeerTrustListTrust, Name FROM tblIdentity WHERE IdentityID=?;");\r
+\r
+ SQLite3DB::Statement boardnamest=m_db->Prepare("SELECT tblBoard.BoardName FROM tblBoard INNER JOIN tblThread ON tblBoard.BoardID=tblThread.BoardID WHERE tblThread.ThreadID=?;");\r
+ boardnamest.Bind(0,threadidstr);\r
+ boardnamest.Step();\r
+\r
+ if(boardnamest.RowReturned())\r
+ {\r
+ boardnamest.ResultText(0,boardname);\r
+ }\r
+\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
+ content+="</tr>";\r
+ content+="</table>\r\n";\r
+\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT tblMessage.MessageID, tblMessage.IdentityID, tblMessage.FromName, tblMessage.Subject, tblMessage.MessageDate || ' ' || tblMessage.MessageTime, tblMessage.Body FROM tblMessage INNER JOIN tblThreadPost ON tblMessage.MessageID=tblThreadPost.MessageID WHERE tblThreadPost.ThreadID=? ORDER BY tblThreadPost.PostOrder;");\r
+ st.Bind(0,threadidstr);\r
+\r
+ content+="<table class=\"thread\">";\r
+ st.Step();\r
+ while(st.RowReturned())\r
+ {\r
+ std::string messageidstr="";\r
+ std::string identityidstr="";\r
+ std::string fromname="";\r
+ std::string subject="";\r
+ std::string datetime="";\r
+ std::string body="";\r
+ \r
+ st.ResultText(0,messageidstr);\r
+ st.ResultText(1,identityidstr);\r
+ st.ResultText(2,fromname);\r
+ st.ResultText(3,subject);\r
+ st.ResultText(4,datetime);\r
+ st.ResultText(5,body);\r
+\r
+ content+="<tr>";\r
+ content+="<td rowspan=\"2\" class=\"from\">";\r
+ content+="<a name=\""+messageidstr+"\"></a>";\r
+ content+="<a href=\"peerdetails.htm?identityid="+identityidstr+"\">"+FixFromName(fromname)+"</a><br />";\r
+\r
+ trustst.Bind(0,identityidstr);\r
+ trustst.Step();\r
+ if(trustst.RowReturned())\r
+ {\r
+ std::string localmessagetrust="";\r
+ std::string localtrustlisttrust="";\r
+ std::string peermessagetrust="";\r
+ std::string peertrustlisttrust="";\r
+ std::string name="";\r
+\r
+ trustst.ResultText(0,localmessagetrust);\r
+ trustst.ResultText(1,localtrustlisttrust);\r
+ trustst.ResultText(2,peermessagetrust);\r
+ trustst.ResultText(3,peertrustlisttrust);\r
+ trustst.ResultText(4,name);\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+="</tr>";\r
+ content+="<tr>";\r
+ content+="<td></td><td>Local</td><td>Peer</td>";\r
+ content+="</tr>";\r
+ content+="<tr>";\r
+ content+="<td>Message</td><td>"+localmessagetrust+"</td><td>"+peermessagetrust+"</td>";\r
+ content+="</tr>";\r
+ content+="<tr>";\r
+ content+="<td>Trust List</td><td>"+localtrustlisttrust+"</td><td>"+peertrustlisttrust+"</td>";\r
+ content+="</tr>";\r
+ content+="</table>";\r
+ }\r
+\r
+ content+="</td>";\r
+ content+="<td class=\"subject\">";\r
+ content+=SanitizeOutput(subject)+" on "+datetime;\r
+ content+="</td>";\r
+ content+="<td><a href=\"forumcreatepost.htm?replytomessageid="+messageidstr+"&threadid="+threadidstr+"&boardid="+boardidstr+"¤tpage="+currentpagestr+"\">Reply</a></td>";\r
+ content+="</tr>\r\n";\r
+ content+="<tr>";\r
+ content+="<td class=\"body\" colspan=\"2\">";\r
+ content+=FixBody(body);\r
+ content+="</td>";\r
+ content+="</tr>";\r
+ trustst.Reset();\r
+\r
+ st.Step();\r
+ }\r
+ content+="</table>";\r
+\r
+ return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+}\r
content+="You can see the release info <a href=\"versioninfo.htm?Major="+majorstr+"&Minor="+minorstr+"&Release="+releasestr+"\">here</a><br>";\r
showgenericupdate=false;\r
}\r
+ else\r
+ {\r
+ content+="<a href=\"versioninfo.htm\">Release info</a><br>";\r
+ }\r
\r
}\r
\r
\r
content+="<hr>";\r
\r
- content+="<table><tr><th>Name</th><th>Single Use</th><th>Publish Trust List</th><th>Publish Board List</th><th>Publish Freesite</th><th>Min Message Delay</th><th>Max Message Delay</th><th>Announced? *</th></tr>";\r
+ content+="<table class=\"small90\"><tr><th>Name</th><th>Single Use</th><th>Publish Trust List</th><th>Publish Board List</th><th>Publish Freesite</th><th>Min Message Delay</th><th>Max Message Delay</th><th>Announced? *</th></tr>";\r
\r
SQLite3DB::Statement st=m_db->Prepare("SELECT LocalIdentityID,tblLocalIdentity.Name,tblLocalIdentity.PublicKey,tbLLocalIdentity.PublishTrustList,tblLocalIdentity.SingleUse,tblLocalIdentity.PublishBoardList,tblIdentity.IdentityID,tblLocalIdentity.PublishFreesite,tblLocalIdentity.MinMessageDelay,tblLocalIdentity.MaxMessageDelay FROM tblLocalIdentity LEFT JOIN tblIdentity ON tblLocalIdentity.PublicKey=tblIdentity.PublicKey ORDER BY tblLocalIdentity.Name;");\r
st.Step();\r
}\r
\r
content+="</table>";\r
- content+="<p class=\"paragraph\">* An identity is considered successfully announced when you have downloaded a trust list from someone that contains the identity. The number in parenthesis is how many trust lists that identity appears in.</p>";\r
+ content+="<p class=\"paragraph\">* An identity is considered successfully announced when you have downloaded a trust list from someone that contains the identity. You must trust other identities' trust lists for this to happen. The number in parenthesis is how many trust lists the identity appears in.</p>";\r
content+="<p class=\"paragraph\">Single Use Identities will automatically be deleted 7 days after creation.</p>";\r
content+="<p class=\"paragraph\">Messages that each identity sends may be delayed by a random number of minutes between min and max. Set both to 0 to send messages as soon as possible.</p>";\r
\r
\r
// search drop down\r
content+="<div style=\"text-align:center;margin-bottom:5px;\">";\r
- content+="<form name=\"frmsearch\" method=\"POST\" action=\"peertrust.htm?"+BuildQueryString(0,"","","",localidentityid)+"\">";\r
+ content+="<form name=\"frmsearch\" method=\"POST\" action=\""+m_pagename+"?"+BuildQueryString(0,"","","",localidentityid)+"\">";\r
content+="<input type=\"text\" name=\"namesearch\" value=\""+SanitizeOutput(namesearch)+"\">";\r
content+="<input type=\"submit\" value=\"Search\">";\r
content+="</form>";\r
content+="</div>";\r
\r
content+="<div style=\"text-align:center;\">";\r
- content+="<form name=\"frmlocalidentity\" method=\"POST\" action=\"peertrust.htm?"+BuildQueryString(startrow,namesearch,sortby,sortorder,-1)+"\">";\r
+ content+="<form name=\"frmlocalidentity\" method=\"POST\" action=\""+m_pagename+"?"+BuildQueryString(startrow,namesearch,sortby,sortorder,-1)+"\">";\r
content+="Load Trust List of ";\r
content+=CreateLocalIdentityDropDown("localidentityid",localidentityid);\r
content+="<input type=\"submit\" value=\"Load List\">";\r
content+="<input type=\"hidden\" name=\"namesearch\" value=\""+SanitizeOutput(namesearch)+"\">";\r
}\r
content+="<table class=\"small90\">";\r
- content+="<tr><th><a href=\"peertrust.htm?"+BuildQueryString(startrow,namesearch,"Name",ReverseSort("Name",sortby,sortorder),localidentityid)+"\">Name</a></th>";\r
- content+="<th><a href=\"peertrust.htm?"+BuildQueryString(startrow,namesearch,"tblIdentityTrust.LocalMessageTrust",ReverseSort("tblIdentityTrust.LocalMessageTrust",sortby,sortorder),localidentityid)+"\">Local Message Trust</a></th>";\r
+ content+="<tr><th><a href=\""+m_pagename+"?"+BuildQueryString(startrow,namesearch,"Name",ReverseSort("Name",sortby,sortorder),localidentityid)+"\">Name</a></th>";\r
+ content+="<th><a href=\""+m_pagename+"?"+BuildQueryString(startrow,namesearch,"tblIdentityTrust.LocalMessageTrust",ReverseSort("tblIdentityTrust.LocalMessageTrust",sortby,sortorder),localidentityid)+"\">Local Message Trust</a></th>";\r
content+="<th>Message Comment</th>";\r
- content+="<th><a href=\"peertrust.htm?"+BuildQueryString(startrow,namesearch,"PeerMessageTrust",ReverseSort("PeerMessageTrust",sortby,sortorder),localidentityid)+"\">Peer Message Trust</a></th>";\r
- content+="<th><a href=\"peertrust.htm?"+BuildQueryString(startrow,namesearch,"tblIdentityTrust.LocalTrustListTrust",ReverseSort("tblIdentityTrust.LocalTrustListTrust",sortby,sortorder),localidentityid)+"\">Local Trust List Trust</a></th>";\r
+ content+="<th><a href=\""+m_pagename+"?"+BuildQueryString(startrow,namesearch,"PeerMessageTrust",ReverseSort("PeerMessageTrust",sortby,sortorder),localidentityid)+"\">Peer Message Trust</a></th>";\r
+ content+="<th><a href=\""+m_pagename+"?"+BuildQueryString(startrow,namesearch,"tblIdentityTrust.LocalTrustListTrust",ReverseSort("tblIdentityTrust.LocalTrustListTrust",sortby,sortorder),localidentityid)+"\">Local Trust List Trust</a></th>";\r
content+="<th>Trust Comment</th>";\r
- content+="<th><a href=\"peertrust.htm?"+BuildQueryString(startrow,namesearch,"PeerTrustListTrust",ReverseSort("PeerTrustListTrust",sortby,sortorder),localidentityid)+"\">Peer Trust List Trust</a></th>";\r
- content+="<th><a href=\"peertrust.htm?"+BuildQueryString(startrow,namesearch,"MessageCount",ReverseSort("MessageCount",sortby,sortorder),localidentityid)+"\">Message Count</a></th>";\r
+ content+="<th><a href=\""+m_pagename+"?"+BuildQueryString(startrow,namesearch,"PeerTrustListTrust",ReverseSort("PeerTrustListTrust",sortby,sortorder),localidentityid)+"\">Peer Trust List Trust</a></th>";\r
+ content+="<th><a href=\""+m_pagename+"?"+BuildQueryString(startrow,namesearch,"MessageCount",ReverseSort("MessageCount",sortby,sortorder),localidentityid)+"\">Message Count</a></th>";\r
content+="</tr>\r\n";\r
\r
// get count of identities we are showing\r
if(startrow>0)\r
{\r
StringFunctions::Convert(startrow-rowsperpage,tempstr);\r
- content+="<td colspan=\"3\" align=\"left\"><a href=\"peertrust.htm?"+BuildQueryString(startrow-rowsperpage,namesearch,sortby,sortorder,localidentityid)+"\"><-- Previous Page</a></td>";\r
+ content+="<td colspan=\"3\" align=\"left\"><a href=\""+m_pagename+"?"+BuildQueryString(startrow-rowsperpage,namesearch,sortby,sortorder,localidentityid)+"\"><-- Previous Page</a></td>";\r
cols+=3;\r
}\r
if(startrow+rowsperpage<identitycount)\r
content+="<td></td>";\r
cols++;\r
}\r
- content+="<td colspan=\"3\" align=\"right\"><a href=\"peertrust.htm?"+BuildQueryString(startrow+rowsperpage,namesearch,sortby,sortorder,localidentityid)+"\">Next Page --></a></td>";\r
+ content+="<td colspan=\"3\" align=\"right\"><a href=\""+m_pagename+"?"+BuildQueryString(startrow+rowsperpage,namesearch,sortby,sortorder,localidentityid)+"\">Next Page --></a></td>";\r
}\r
content+="</tr>";\r
}\r
return currentsortorder;\r
}\r
}\r
-\r
-const bool PeerTrustPage::WillHandleURI(const std::string &uri)\r
-{\r
- if(uri.find("peertrust.")!=std::string::npos)\r
- {\r
- return true;\r
- }\r
- else\r
- {\r
- return false;\r
- }\r
-}\r
\r
return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
}\r
-\r
-const bool RecentlyAddedPage::WillHandleURI(const std::string &uri)\r
-{\r
- if(uri.find("recentlyadded.")!=std::string::npos)\r
- {\r
- return true;\r
- }\r
- else\r
- {\r
- return false;\r
- }\r
-}\r
std::map<std::string,std::string> queryvars;\r
CreateQueryVarMap(request,queryvars);\r
\r
- response.setChunkedTransferEncoding(true);\r
+ if(request.getVersion()==Poco::Net::HTTPRequest::HTTP_1_1)\r
+ {\r
+ response.setChunkedTransferEncoding(true);\r
+ }\r
\r
std::string content="";\r
if(queryvars.find("UUID")!=queryvars.end())\r
--- /dev/null
+#include "../../../include/http/pages/showimagepage.h"\r
+\r
+#ifdef XMEM\r
+ #include <xmem.h>\r
+#endif\r
+\r
+std::map<std::string,std::vector<char> > ShowImagePage::m_imagecache;\r
+\r
+void ShowImagePage::handleRequest(Poco::Net::HTTPServerRequest &request, Poco::Net::HTTPServerResponse &response)\r
+{\r
+ m_log->trace("ShowImagePage::handleRequest from "+request.clientAddress().toString());\r
+\r
+ std::map<std::string,std::string> queryvars;\r
+ CreateQueryVarMap(request,queryvars);\r
+\r
+ if(request.getVersion()==Poco::Net::HTTPRequest::HTTP_1_1)\r
+ {\r
+ response.setChunkedTransferEncoding(true);\r
+ }\r
+\r
+ std::string content="";\r
+ if(queryvars.find("image")!=queryvars.end())\r
+ {\r
+ if(m_imagecache.find((*queryvars.find("image")).second)!=m_imagecache.end())\r
+ {\r
+ content+=std::string(m_imagecache[(*queryvars.find("image")).second].begin(),m_imagecache[(*queryvars.find("image")).second].end());\r
+ }\r
+ else\r
+ {\r
+ FILE *infile=fopen((*queryvars.find("image")).second.c_str(),"rb");\r
+ if(infile)\r
+ {\r
+ fseek(infile,0,SEEK_END);\r
+ long filelen=ftell(infile);\r
+ fseek(infile,0,SEEK_SET);\r
+\r
+ if(filelen>0)\r
+ {\r
+ std::vector<char> data(filelen,0);\r
+ fread(&data[0],1,data.size(),infile);\r
+ content+=std::string(data.begin(),data.end());\r
+ m_imagecache[(*queryvars.find("image")).second]=data;\r
+ }\r
+\r
+ fclose(infile);\r
+ }\r
+ }\r
+ }\r
+\r
+ std::ostream &ostr = response.send();\r
+ ostr << content;\r
+}\r
+\r
+const bool ShowImagePage::WillHandleURI(const std::string &uri)\r
+{\r
+ if(uri.find("showimage.htm")!=std::string::npos)\r
+ {\r
+ return true;\r
+ }\r
+ else\r
+ {\r
+ return false;\r
+ }\r
+}\r
\r
#include <string>\r
\r
+#ifdef XMEM\r
+ #include <xmem.h>\r
+#endif\r
+\r
const std::string VersionInfoPage::GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars)\r
{\r
std::string content="";\r
\r
+ bool hascriteria=false;\r
std::string major=VERSION_MAJOR;\r
std::string minor=VERSION_MINOR;\r
std::string release=VERSION_RELEASE;\r
+ std::string sql="";\r
\r
if(queryvars.find("Major")!=queryvars.end())\r
{\r
major=(*queryvars.find("Major")).second;\r
+ hascriteria=true;\r
}\r
if(queryvars.find("Minor")!=queryvars.end())\r
{\r
minor=(*queryvars.find("Minor")).second;\r
+ hascriteria=true;\r
}\r
if(queryvars.find("Release")!=queryvars.end())\r
{\r
release=(*queryvars.find("Release")).second;\r
+ hascriteria=true;\r
}\r
\r
- SQLite3DB::Statement st=m_db->Prepare("SELECT Notes, Changes FROM tblFMSVersion WHERE Major=? AND Minor=? AND Release=?;");\r
- st.Bind(0,major);\r
- st.Bind(1,minor);\r
- st.Bind(2,release);\r
+ sql="SELECT Notes, Changes, Major, Minor, Release FROM tblFMSVersion ";\r
+ if(hascriteria==true)\r
+ {\r
+ sql+="WHERE Major=? AND Minor=? AND Release=? ";\r
+ }\r
+ sql+="ORDER BY Major DESC, Minor DESC, Release DESC;";\r
+ SQLite3DB::Statement st=m_db->Prepare(sql);\r
+ if(hascriteria==true)\r
+ {\r
+ st.Bind(0,major);\r
+ st.Bind(1,minor);\r
+ st.Bind(2,release);\r
+ }\r
st.Step();\r
\r
- if(st.RowReturned())\r
+ while(st.RowReturned())\r
{\r
std::string notes="";\r
std::string changes="";\r
\r
st.ResultText(0,notes);\r
st.ResultText(1,changes);\r
+ st.ResultText(2,major);\r
+ st.ResultText(3,minor);\r
+ st.ResultText(4,release);\r
\r
+ content+="<div style=\"margin-bottom:20px;\">";\r
content+="<h2>Release "+major+"."+minor+"."+release+"</h2>";\r
content+="<h3>Notes</h3>";\r
content+=StringFunctions::Replace(notes,"\n","<br>");\r
content+="<h3>Changes</h3>";\r
content+=StringFunctions::Replace(changes,"\n","<br>");\r
+ content+="</div>";\r
+ st.Step();\r
}\r
\r
return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
}\r
-\r
-const bool VersionInfoPage::WillHandleURI(const std::string &uri)\r
-{\r
- if(uri.find("versioninfo.")!=std::string::npos)\r
- {\r
- return true;\r
- }\r
- else\r
- {\r
- return false;\r
- }\r
-}\r
return false;\r
}\r
\r
+const bool Message::Create(const long localidentityid, const long boardid, const std::string &subject, const std::string &body, const std::string &references)\r
+{\r
+ Initialize();\r
+\r
+ Poco::UUIDGenerator uuidgen;\r
+ Poco::UUID uuid;\r
+\r
+ // get header info\r
+ // date is always set to now regardless of what message has\r
+ m_datetime=Poco::Timestamp();\r
+\r
+ // messageuuid is always a unique id we generate regardless of message message-id\r
+ try\r
+ {\r
+ uuid=uuidgen.createRandom();\r
+ m_messageuuid=uuid.toString();\r
+ StringFunctions::UpperCase(m_messageuuid,m_messageuuid);\r
+ }\r
+ catch(...)\r
+ {\r
+ m_log->fatal("Message::ParseNNTPMessage could not create UUID");\r
+ }\r
+ \r
+ // get from\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT Name FROM tblLocalIdentity WHERE LocalIdentityID=?;");\r
+ st.Bind(0,localidentityid);\r
+ st.Step();\r
+ if(st.RowReturned())\r
+ {\r
+ st.ResultText(0,m_fromname);\r
+ }\r
+\r
+ // get boards posted to\r
+ std::string boardname="";\r
+ SQLite3DB::Statement boardst=m_db->Prepare("SELECT BoardName FROM tblBoard WHERE BoardID=?;");\r
+ boardst.Bind(0,boardid);\r
+ boardst.Step();\r
+ if(boardst.RowReturned())\r
+ {\r
+ boardst.ResultText(0,boardname);\r
+ }\r
+\r
+ m_boards.push_back(boardname);\r
+ m_replyboardname=boardname;\r
+\r
+ m_subject=subject;\r
+\r
+ m_body=body;\r
+\r
+ if(references!="")\r
+ {\r
+ m_inreplyto[0]=references;\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
const int Message::FindLocalIdentityID(const std::string &name)\r
{\r
SQLite3DB::Statement st=m_db->Prepare("SELECT LocalIdentityID FROM tblLocalIdentity WHERE Name=?;");\r
--- /dev/null
+#include "../include/messagethread.h"\r
+#include "../include/stringfunctions.h"\r
+\r
+#include <algorithm>\r
+\r
+#ifdef XMEM\r
+ #include <xmem.h>\r
+#endif\r
+\r
+void MessageThread::AddChildren(const long messageid, const long level, const long boardid)\r
+{\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT tblMessageReplyTo.MessageID, tblMessage1.Subject, tblMessage1.FromName, tblMessage1.MessageDate || ' ' || tblMessage1.MessageTime FROM tblMessage INNER JOIN tblMessageReplyTo ON tblMessage.MessageUUID=tblMessageReplyTo.ReplyToMessageUUID INNER JOIN tblMessage AS 'tblMessage1' ON tblMessageReplyTo.MessageID=tblMessage1.MessageID INNER JOIN tblMessageBoard ON tblMessage1.MessageID=tblMessageBoard.MessageID WHERE tblMessage.MessageID=? AND tblMessageBoard.BoardID=? AND tblMessageReplyTo.ReplyOrder=0 ORDER BY tblMessage1.MessageDate || ' ' || tblMessage1.MessageTime;");\r
+ st.Bind(0,messageid);\r
+ st.Bind(1,boardid);\r
+ st.Step();\r
+ while(st.RowReturned())\r
+ {\r
+ int childid=0;\r
+ std::string subject="";\r
+ std::string fromname="";\r
+ std::string datetime="";\r
+ st.ResultInt(0,childid);\r
+ st.ResultText(1,subject);\r
+ st.ResultText(2,fromname);\r
+ st.ResultText(3,datetime);\r
+ \r
+ threadnode node;\r
+ node.m_messageid=childid;\r
+ node.m_level=level;\r
+ node.m_subject=subject;\r
+ node.m_fromname=fromname;\r
+ node.m_date=datetime;\r
+ m_nodes.push_back(node);\r
+ \r
+ AddChildren(childid,level+1,boardid);\r
+ \r
+ st.Step();\r
+ } \r
+}\r
+\r
+const MessageThread::threadnode MessageThread::GetOriginalMessageNode(const long messageid, const long boardid)\r
+{\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT tblMessage.MessageID, tblMessage.Subject, tblMessage.FromName, tblMessage.MessageDate || ' ' || tblMessage.MessageTime FROM tblMessageReplyTo INNER JOIN tblMessage ON tblMessageReplyTo.ReplyToMessageUUID=tblMessage.MessageUUID INNER JOIN tblMessageBoard ON tblMessage.MessageID=tblMessageBoard.MessageID WHERE tblMessageReplyTo.ReplyOrder=0 AND tblMessageReplyTo.MessageID=? AND tblMessageBoard.BoardID=?;");\r
+ st.Bind(0,messageid);\r
+ st.Bind(1,boardid);\r
+ st.Step();\r
+ if(st.RowReturned())\r
+ {\r
+ int id=0;\r
+ std::string subject="";\r
+ std::string fromname="";\r
+ std::string datetime="";\r
+ st.ResultInt(0,id);\r
+ st.ResultText(1,subject);\r
+ st.ResultText(2,fromname);\r
+ st.ResultText(3,datetime);\r
+\r
+ threadnode node;\r
+ node.m_messageid=id;\r
+ node.m_level=0;\r
+ node.m_subject=subject;\r
+ node.m_fromname=fromname;\r
+ node.m_date=datetime;\r
+\r
+ return GetOriginalMessageNode(node.m_messageid,boardid);\r
+ }\r
+ else\r
+ {\r
+ threadnode node;\r
+ node.m_messageid=-1;\r
+ node.m_level=0;\r
+ node.m_subject="";\r
+ node.m_fromname="";\r
+ node.m_date="";\r
+\r
+ SQLite3DB::Statement st2=m_db->Prepare("SELECT Subject, FromName, MessageDate || ' ' || MessageTime FROM tblMessage WHERE MessageID=?;");\r
+ st2.Bind(0,messageid);\r
+ st2.Step();\r
+\r
+ if(st2.RowReturned())\r
+ {\r
+ node.m_messageid=messageid;\r
+ st2.ResultText(0,node.m_subject);\r
+ st2.ResultText(1,node.m_fromname);\r
+ st2.ResultText(2,node.m_date);\r
+ }\r
+\r
+ return node;\r
+ }\r
+}\r
+\r
+const bool MessageThread::Load(const long messageid, const long boardid, const bool bydate)\r
+{\r
+ threadnode originalmessagenode=GetOriginalMessageNode(messageid,boardid);\r
+ \r
+ if(originalmessagenode.m_messageid>=0)\r
+ {\r
+ m_nodes.push_back(originalmessagenode);\r
+ \r
+ AddChildren(originalmessagenode.m_messageid,1,boardid);\r
+\r
+ if(bydate==true)\r
+ {\r
+ std::sort(m_nodes.begin(),m_nodes.end(),datecompare());\r
+ }\r
+\r
+ return true;\r
+ }\r
+ else\r
+ {\r
+ return false;\r
+ }\r
+}\r
+\r
+const bool MessageThread::Load(const std::string &messageidstr, const long boardid, const bool bydate)\r
+{\r
+ long messageid=0;\r
+ StringFunctions::Convert(messageidstr,messageid);\r
+ return Load(messageid,boardid,bydate);\r
+}\r
#include <xmem.h>\r
#endif\r
\r
-NNTPConnection::NNTPConnection(SOCKET sock)\r
+NNTPConnection::NNTPConnection(SOCKET sock):m_socket(sock)\r
{\r
- std::string tempval;\r
+ std::string tempval("");\r
\r
- m_socket=sock;\r
m_tempbuffer.resize(32768);\r
\r
m_status.m_isposting=false;\r
}\r
else\r
{\r
- m_log->error("NNTPListener::StartListen socket listen failed");\r
+ m_log->error("NNTPListener::StartListen socket listen failed on "+sa.toString());\r
#ifdef _WIN32\r
closesocket(sock);\r
#else\r
}\r
else\r
{\r
- m_log->error("NNTPListener::StartListen socket bind failed");\r
+ m_log->error("NNTPListener::StartListen socket bind failed on "+sa.toString());\r
#ifdef _WIN32\r
closesocket(sock);\r
#else\r
}\r
else\r
{\r
- m_log->error("NNTPListener::StartListen couldn't create socket");\r
+ m_log->error("NNTPListener::StartListen couldn't create socket on "+sa.toString());\r
}\r
}\r
catch(Poco::Exception &e)\r
--- /dev/null
+#include "../include/threadbuilder.h"\r
+#include "../include/messagethread.h"\r
+\r
+const bool ThreadBuilder::Build(const long messageid, const long boardid, const bool bydate)\r
+{\r
+ int count=0;\r
+ int threadid=-1;\r
+ MessageThread mt;\r
+ std::vector<MessageThread::threadnode> m_threadmessages;\r
+\r
+ mt.Load(messageid,boardid,bydate);\r
+ m_threadmessages=mt.GetNodes();\r
+\r
+ // find threadid of this thread if it already exists in a thread\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT tblThread.ThreadID FROM tblThread INNER JOIN tblThreadPost ON tblThread.ThreadID=tblThreadPost.ThreadID WHERE tblThread.BoardID=? AND tblThreadPost.MessageID=?;");\r
+ st.Bind(0,boardid);\r
+ st.Bind(1,messageid);\r
+\r
+ st.Step();\r
+ if(st.RowReturned())\r
+ {\r
+ st.ResultInt(0,threadid);\r
+ }\r
+ else\r
+ {\r
+ st.Reset();\r
+ // message doesn't exist in a thread, try to find a message in the thread that is already in a thread\r
+ for(std::vector<MessageThread::threadnode>::const_iterator i=m_threadmessages.begin(); i!=m_threadmessages.end() && threadid==-1; i++)\r
+ {\r
+ st.Bind(0,boardid);\r
+ st.Bind(1,(*i).m_messageid);\r
+ st.Step();\r
+\r
+ if(st.RowReturned())\r
+ {\r
+ st.ResultInt(0,threadid);\r
+ }\r
+\r
+ st.Reset();\r
+\r
+ }\r
+\r
+ // thread doesn't exist - create it\r
+ if(threadid==-1)\r
+ {\r
+ st=m_db->Prepare("INSERT INTO tblThread(BoardID) VALUES(?);");\r
+ st.Bind(0,boardid);\r
+ st.Step(true);\r
+ threadid=st.GetLastInsertRowID();\r
+ }\r
+ }\r
+\r
+ if(m_threadmessages.size()>0)\r
+ {\r
+ st=m_db->Prepare("UPDATE tblThread SET FirstMessageID=?, LastMessageID=? WHERE ThreadID=?;");\r
+ st.Bind(0,m_threadmessages[0].m_messageid);\r
+ st.Bind(1,m_threadmessages[m_threadmessages.size()-1].m_messageid);\r
+ st.Bind(2,threadid);\r
+ st.Step();\r
+\r
+ st=m_db->Prepare("DELETE FROM tblThreadPost WHERE ThreadID=?;");\r
+ st.Bind(0,threadid);\r
+ st.Step();\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
+ st.Bind(0,threadid);\r
+ st.Bind(1,(*i).m_messageid);\r
+ st.Bind(2,count);\r
+ st.Step();\r
+ st.Reset();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ st=m_db->Prepare("DELETE FROM tblThread WHERE ThreadID=?;");\r
+ st.Bind(0,threadid);\r
+ st.Step();\r
+ }\r
+\r
+ return true;\r
+\r
+}\r
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">\r
<head>\r
-<title>FMS : Freenet Message System</title>\r
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />\r
+<title>FMS : Freenet Message System</title>\r
<style type="text/css">\r
body {\r
background-color: #FFF;\r
.small70 {\r
font-size:70%;\r
}\r
+ \r
+.post {\r
+ margin-bottom:2em;\r
+ }\r
+ \r
+.post .postsubject {\r
+ font-size:1.2em;\r
+ font-style:bolder;\r
+ }\r
+ \r
+.post .postboards {\r
+ font-size:1.2em;\r
+ font-style:bolder;\r
+ }\r
+ \r
+.post .postbody {\r
+ font-size:0.8em;\r
+ white-space:pre;\r
+ }\r
+ \r
+.post .postfrom {\r
+ font-size:1.2em;\r
+ font-style:bolder;\r
+ }\r
+ \r
+.post .postdate {\r
+ font-size:1.2em;\r
+ font-style:bolder;\r
+ }\r
+\r
+ul.messagethread {\r
+ list-style:none;\r
+ margin-left:8px;\r
+ font-size:9pt;\r
+ }\r
\r
</style>\r
</head>\r
<li><a href="addpeer.htm">Add Peer</a></li>\r
<li><a href="peermaintenance.htm">Peer Maintenance</a></li>\r
<li><a href="peertrust.htm">Peer Trust</a></li>\r
- <li><a href="boards.htm">Boards</a></li>\r
+ <li><a href="boards.htm">Board Maintenance</a></li>\r
<li><a href="controlboard.htm">Control Boards</a></li>\r
<li><a href="insertedfiles.htm">Inserted Files</a></li>\r
+ <li><a href="forummain.htm">Browse Forums</a></li>\r
</ul>\r
</div>\r
\r