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/fcpv2.cpp\r
src/freenet/freenetmasterthread.cpp\r
src/freenet/freenetssk.cpp\r
src/http/pages/localidentitiespage.cpp\r
src/http/pages/optionspage.cpp\r
src/http/pages/peerdetailspage.cpp\r
+src/http/pages/peermaintenancepage.cpp\r
src/http/pages/peertrustpage.cpp\r
src/http/pages/showcaptchapage.cpp\r
src/nntp/nntpconnection.cpp\r
//#include <zthread/Mutex.h>\r
#include <sqlite3.h>\r
#include <string>\r
-#include "../../pthreadwrapper/singleton.h"\r
#include "../../pthreadwrapper/mutex.h"\r
-\r
#include "../sqlite3db.h"\r
\r
+#include "../../pthreadwrapper/singleton.h"\r
+\r
#if SQLITE_VERSION_NUMBER<3005000\r
#error "Your version of SQLite is too old! 3.5.0 or later is required."\r
#endif\r
--- /dev/null
+#ifndef _boardlistinserter_\r
+#define _boardlistinserter_\r
+\r
+#include "iindexinserter.h"\r
+\r
+class BoardListInserter:public IIndexInserter<long>\r
+{\r
+public:\r
+ BoardListInserter();\r
+ BoardListInserter(FCPv2 *fcp);\r
+\r
+private:\r
+ void Initialize();\r
+ const bool HandlePutSuccessful(FCPMessage &message);\r
+ const bool HandlePutFailed(FCPMessage &message);\r
+ void StartInsert(const long &localidentityid);\r
+ void CheckForNeededInsert();\r
+};\r
+\r
+#endif // _boardlistinserter_\r
--- /dev/null
+#ifndef _boardlistrequester_\r
+#define _boardlistrequester_\r
+\r
+#include "iindexrequester.h"\r
+\r
+class BoardListRequester:public IIndexRequester<long>\r
+{\r
+public:\r
+ BoardListRequester();\r
+ BoardListRequester(FCPv2 *fcp);\r
+\r
+private:\r
+ void Initialize();\r
+ void PopulateIDList();\r
+ void StartRequest(const long &identityid);\r
+ const bool HandleAllData(FCPMessage &message);\r
+ const bool HandleGetFailed(FCPMessage &message);\r
+};\r
+\r
+#endif // _boardlistrequester_\r
--- /dev/null
+#ifndef _boardlistxml_\r
+#define _boardlistxml_\r
+\r
+#include "../ifmsxmldocument.h"\r
+\r
+class BoardListXML:public IFMSXMLDocument\r
+{\r
+public:\r
+ BoardListXML();\r
+\r
+ std::string GetXML();\r
+\r
+ const bool ParseXML(const std::string &xml);\r
+\r
+ void AddBoard(const std::string &name, const std::string &description);\r
+ const long GetCount() { return m_boards.size(); }\r
+ const std::string GetName(const long index);\r
+ const std::string GetDescription(const long index);\r
+\r
+private:\r
+ struct board\r
+ {\r
+ board(const std::string &name, const std::string &description):m_name(name),m_description(description) {}\r
+ std::string m_name;\r
+ std::string m_description;\r
+ };\r
+\r
+ void Initialize();\r
+\r
+ std::vector<board> m_boards;\r
+ \r
+};\r
+\r
+#endif // _boardlistxml_\r
class IFreenetRegistrable\r
{\r
public:\r
+ IFreenetRegistrable() {}\r
+ virtual ~IFreenetRegistrable() {}\r
\r
virtual void RegisterWithThread(FreenetMasterThread *thread)=0;\r
\r
#include "ifcpmessagehandler.h"\r
#include "iperiodicprocessor.h"\r
\r
+#ifdef XMEM\r
+ #include <xmem.h>\r
+#endif\r
+\r
template <class IDTYPE>\r
class IIndexInserter:public IFreenetRegistrable,public IFCPConnected,public IFCPMessageHandler,public IPeriodicProcessor,public IDatabase,public ILogger\r
{\r
public:\r
IIndexInserter();\r
IIndexInserter(FCPv2 *fcp);\r
+ virtual ~IIndexInserter() {}\r
\r
virtual void FCPConnected();\r
virtual void FCPDisconnected();\r
#include "ifcpmessagehandler.h"\r
#include "iperiodicprocessor.h"\r
\r
+#ifdef XMEM\r
+ #include <xmem.h>\r
+#endif\r
+\r
template <class IDTYPE>\r
class IIndexRequester:public IFreenetRegistrable,public IFCPConnected,public IFCPMessageHandler,public IPeriodicProcessor,public IDatabase,public ILogger\r
{\r
public:\r
IIndexRequester();\r
IIndexRequester(FCPv2 *fcp);\r
+ virtual ~IIndexRequester() {}\r
\r
virtual void FCPConnected();\r
virtual void FCPDisconnected();\r
\r
long m_maxdaysbackward;\r
long m_maxpeermessages;\r
+ long m_maxboardspermessage;\r
\r
};\r
\r
#ifndef _messagexml_\r
#define _messagexml_\r
\r
-#include "../ifmsxmldocument.h"\r
#include <vector>\r
#include <map>\r
\r
+#include "../ifmsxmldocument.h"\r
+\r
class MessageXML:public IFMSXMLDocument\r
{\r
public:\r
//#include <zthread/Thread.h>\r
#include "pthreadwrapper/thread.h"\r
\r
-#define FMS_VERSION "0.1.10"\r
+#define FMS_VERSION "0.1.11"\r
\r
// opens database and creates tables and initial inserts if necessary\r
void SetupDB();\r
--- /dev/null
+#ifndef _peermaintenancepage_\r
+#define _peermaintenancepage_\r
+\r
+#include "../ipagehandler.h"\r
+#include "../../idatabase.h"\r
+\r
+class PeerMaintenancePage:public IPageHandler,public IDatabase\r
+{\r
+public:\r
+ PeerMaintenancePage(const std::string &templatestr):IPageHandler(templatestr) {}\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
+\r
+#endif // _peermaintenancepage_\r
#include <string>\r
#include <tinyxml.h>\r
\r
+#ifdef XMEM\r
+ #include <xmem.h>\r
+#endif\r
+\r
/**\r
\brief Interface for objects that represent an XML document\r
*/\r
\r
//#include <zthread/Singleton.h>\r
//#include <zthread/Mutex.h>\r
-#include "pthreadwrapper/singleton.h"\r
#include "pthreadwrapper/mutex.h"\r
#include <string>\r
+#include "pthreadwrapper/singleton.h"\r
\r
class LogFile:public PThread::Singleton<LogFile>\r
{\r
#include "pthreadwrapper/guard.h"\r
#include "pthreadwrapper/runnable.h"\r
#include "pthreadwrapper/thread.h"\r
-#include "pthreadwrapper/singleton.h"\r
#include "pthreadwrapper/threadedexecutor.h"\r
+#include "pthreadwrapper/singleton.h"\r
\r
#endif // _pthread_wrapper_\r
class NonCopyable\r
{\r
protected:\r
- NonCopyable() {}\r
- ~NonCopyable() {}\r
+ NonCopyable() {}\r
+ virtual ~NonCopyable() {}\r
\r
private:\r
// restrict copy and assignment\r
bool m_running; // thread (object) is currently running\r
bool m_cancelled;\r
Runnable *m_runnable; // actual object that is being run\r
+ bool m_threadcleaned;\r
\r
};\r
\r
\r
const bool DB::Open(const std::string &filename)\r
{\r
- if(IsOpen()==false)\r
+ if(IsOpen()==true)\r
{\r
Close(); \r
}\r
--- /dev/null
+#include "../../include/freenet/boardlistinserter.h"\r
+#include "../../include/freenet/boardlistxml.h"\r
+\r
+#ifdef XMEM\r
+ #include <xmem.h>\r
+#endif\r
+\r
+BoardListInserter::BoardListInserter()\r
+{\r
+ Initialize();\r
+}\r
+\r
+BoardListInserter::BoardListInserter(FCPv2 *fcp):IIndexInserter<long>(fcp)\r
+{\r
+ Initialize();\r
+}\r
+\r
+void BoardListInserter::CheckForNeededInsert()\r
+{\r
+ // only do 1 insert at a time\r
+ if(m_inserting.size()==0)\r
+ {\r
+ DateTime today;\r
+ DateTime daysback;\r
+ \r
+ today.SetToGMTime();\r
+ daysback.SetToGMTime();\r
+\r
+ // 20 days\r
+ daysback.Add(0,0,0,-20);\r
+\r
+ // get identities who posted messages to boards in the past 20 days\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT tblLocalIdentity.LocalIdentityID FROM tblLocalIdentity INNER JOIN tblMessageInserts ON tblLocalIdentity.LocalIdentityID=tblMessageInserts.LocalIdentityID WHERE tblLocalIdentity.PublishBoardList='true' AND (tblLocalIdentity.LastInsertedBoardList<? OR tblLocalIdentity.LastInsertedBoardList IS NULL) AND tblMessageInserts.Day>=? GROUP BY tblLocalIdentity.LocalIdentityID;");\r
+ st.Bind(0,today.Format("%Y-%m-%d"));\r
+ st.Bind(1,daysback.Format("%Y-%m-%d"));\r
+ st.Step();\r
+\r
+ if(st.RowReturned())\r
+ {\r
+ int localidentityid;\r
+ st.ResultInt(0,localidentityid);\r
+ StartInsert(localidentityid);\r
+ }\r
+ }\r
+}\r
+\r
+const bool BoardListInserter::HandlePutFailed(FCPMessage &message)\r
+{\r
+ std::vector<std::string> idparts;\r
+ long localidentityid;\r
+ long index;\r
+\r
+ StringFunctions::Split(message["Identifier"],"|",idparts);\r
+ StringFunctions::Convert(idparts[1],localidentityid);\r
+ StringFunctions::Convert(idparts[2],index);\r
+\r
+ if(message["Fatal"]=="true" || message["Code"]=="9")\r
+ {\r
+ SQLite3DB::Statement st=m_db->Prepare("INSERT INTO tblBoardListInserts(LocalIdentityID,Day,InsertIndex,Inserted) VALUES(?,?,?,'false');");\r
+ st.Bind(0,localidentityid);\r
+ st.Bind(1,idparts[4]);\r
+ st.Bind(2,index);\r
+ st.Step();\r
+ }\r
+\r
+ RemoveFromInsertList(localidentityid);\r
+\r
+ return true;\r
+}\r
+\r
+const bool BoardListInserter::HandlePutSuccessful(FCPMessage &message)\r
+{\r
+ DateTime now;\r
+ std::vector<std::string> idparts;\r
+ long localidentityid;\r
+ long index;\r
+\r
+ StringFunctions::Split(message["Identifier"],"|",idparts);\r
+ StringFunctions::Convert(idparts[1],localidentityid);\r
+ StringFunctions::Convert(idparts[2],index);\r
+\r
+ SQLite3DB::Statement st=m_db->Prepare("INSERT INTO tblBoardListInserts(LocalIdentityID,Day,InsertIndex,Inserted) VALUES(?,?,?,'true');");\r
+ st.Bind(0,localidentityid);\r
+ st.Bind(1,idparts[4]);\r
+ st.Bind(2,index);\r
+ st.Step();\r
+\r
+ now.SetToGMTime();\r
+ st=m_db->Prepare("UPDATE tblLocalIdentity SET LastInsertedBoardList=? WHERE LocalIdentityID=?;");\r
+ st.Bind(0,now.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(1,localidentityid);\r
+ st.Step();\r
+\r
+ RemoveFromInsertList(localidentityid);\r
+\r
+ m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"BoardListInserter::HandlePutSuccessful successfully inserted BoardList.");\r
+\r
+ return true;\r
+}\r
+\r
+void BoardListInserter::Initialize()\r
+{\r
+ m_fcpuniquename="BoardListInserter";\r
+}\r
+\r
+void BoardListInserter::StartInsert(const long &localidentityid)\r
+{\r
+ DateTime daysback;\r
+ DateTime now;\r
+ BoardListXML xml;\r
+ FCPMessage message;\r
+ std::string data;\r
+ std::string datasizestr;\r
+ std::string privatekey="";\r
+ int index;\r
+ std::string indexstr="";\r
+ std::string localidentityidstr;\r
+\r
+ now.SetToGMTime();\r
+ daysback.SetToGMTime();\r
+ daysback.Add(0,0,0,-20);\r
+\r
+ // get boards\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT BoardName,BoardDescription FROM tblBoard INNER JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID INNER JOIN tblMessage ON tblMessageBoard.MessageID=tblMessage.MessageID INNER JOIN tblMessageInserts ON tblMessage.MessageUUID=tblMessageInserts.MessageUUID WHERE tblMessageInserts.LocalIdentityID=? AND tblMessageInserts.Day>=? GROUP BY tblBoard.BoardID;");\r
+ st.Bind(0,localidentityid);\r
+ st.Bind(1,daysback.Format("%Y-%m-%d"));\r
+ st.Step();\r
+\r
+ while(st.RowReturned())\r
+ {\r
+ std::string name="";\r
+ std::string description="";\r
+\r
+ st.ResultText(0,name);\r
+ st.ResultText(1,description);\r
+\r
+ xml.AddBoard(name,description);\r
+\r
+ st.Step();\r
+ }\r
+\r
+ // get public key\r
+ st=m_db->Prepare("SELECT PrivateKey FROM tblLocalIdentity WHERE LocalIdentityID=?;");\r
+ st.Bind(0,localidentityid);\r
+ st.Step();\r
+ if(st.RowReturned())\r
+ {\r
+ st.ResultText(0,privatekey);\r
+ }\r
+\r
+ // get last index\r
+ index=0;\r
+ st=m_db->Prepare("SELECT MAX(InsertIndex) FROM tblBoardListInserts WHERE LocalIdentityID=? AND Day=?;");\r
+ st.Bind(0,localidentityid);\r
+ st.Bind(1,now.Format("%Y-%m-%d"));\r
+ st.Step();\r
+ if(st.RowReturned())\r
+ {\r
+ if(st.ResultNull(0)==false)\r
+ {\r
+ st.ResultInt(0,index);\r
+ index++;\r
+ }\r
+ }\r
+ StringFunctions::Convert(index,indexstr);\r
+\r
+ data=xml.GetXML();\r
+ StringFunctions::Convert(data.size(),datasizestr);\r
+ StringFunctions::Convert(localidentityid,localidentityidstr);\r
+\r
+ message.SetName("ClientPut");\r
+ message["URI"]=privatekey+m_messagebase+"|"+now.Format("%Y-%m-%d")+"|BoardList|"+indexstr+".xml";\r
+ message["Identifier"]=m_fcpuniquename+"|"+localidentityidstr+"|"+indexstr+"|"+message["URI"];\r
+ message["UploadFrom"]="direct";\r
+ message["DataLength"]=datasizestr;\r
+ m_fcp->SendMessage(message);\r
+ m_fcp->SendRaw(data.c_str(),data.size());\r
+\r
+ m_inserting.push_back(localidentityid);\r
+\r
+}\r
--- /dev/null
+#include "../../include/freenet/boardlistrequester.h"\r
+#include "../../include/freenet/boardlistxml.h"\r
+\r
+#ifdef XMEM\r
+ #include <xmem.h>\r
+#endif\r
+\r
+BoardListRequester::BoardListRequester()\r
+{\r
+ Initialize();\r
+}\r
+\r
+BoardListRequester::BoardListRequester(FCPv2 *fcp):IIndexRequester<long>(fcp)\r
+{\r
+ Initialize();\r
+}\r
+\r
+const bool BoardListRequester::HandleAllData(FCPMessage &message)\r
+{ \r
+ DateTime now;\r
+ SQLite3DB::Statement st;\r
+ std::vector<std::string> idparts;\r
+ long datalength;\r
+ std::vector<char> data;\r
+ BoardListXML xml;\r
+ long identityid;\r
+ long index;\r
+\r
+ now.SetToGMTime();\r
+ StringFunctions::Split(message["Identifier"],"|",idparts);\r
+ StringFunctions::Convert(message["DataLength"],datalength);\r
+ StringFunctions::Convert(idparts[1],identityid);\r
+ StringFunctions::Convert(idparts[2],index);\r
+\r
+ // wait for all data to be received from connection\r
+ while(m_fcp->Connected() && m_fcp->ReceiveBufferSize()<datalength)\r
+ {\r
+ m_fcp->Update(1);\r
+ }\r
+\r
+ // if we got disconnected- return immediately\r
+ if(m_fcp->Connected()==false)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // receive the file\r
+ data.resize(datalength);\r
+ m_fcp->ReceiveRaw(&data[0],datalength);\r
+\r
+ // parse file into xml and update the database\r
+ if(xml.ParseXML(std::string(data.begin(),data.end()))==true)\r
+ {\r
+\r
+ SQLite3DB::Statement brd=m_db->Prepare("SELECT BoardID,BoardName,BoardDescription FROM tblBoard WHERE BoardName=?;");\r
+ SQLite3DB::Statement ins=m_db->Prepare("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES(?,?,?);");\r
+ SQLite3DB::Statement upd=m_db->Prepare("UPDATE tblBoard SET BoardDescription=? WHERE BoardID=?;");\r
+ for(long i=0; i<xml.GetCount(); i++)\r
+ {\r
+ int boardid;\r
+ std::string name="";\r
+ std::string description="";\r
+\r
+ brd.Bind(0,xml.GetName(i));\r
+ brd.Step();\r
+ \r
+ if(brd.RowReturned())\r
+ {\r
+ brd.ResultInt(0,boardid);\r
+ brd.ResultText(2,description);\r
+ if(description=="" && xml.GetDescription(i)!="")\r
+ {\r
+ upd.Bind(0,xml.GetDescription(i));\r
+ upd.Step();\r
+ upd.Reset();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ ins.Bind(0,xml.GetName(i));\r
+ ins.Bind(1,xml.GetDescription(i));\r
+ ins.Bind(2,now.Format("%Y-%m-%d %H:%M:%S"));\r
+ ins.Step();\r
+ ins.Reset();\r
+ }\r
+ brd.Reset();\r
+ }\r
+\r
+ st=m_db->Prepare("INSERT INTO tblBoardListRequests(IdentityID,Day,RequestIndex,Found) VALUES(?,?,?,'true');");\r
+ st.Bind(0,identityid);\r
+ st.Bind(1,idparts[4]);\r
+ st.Bind(2,index);\r
+ st.Step();\r
+ st.Finalize();\r
+\r
+ m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"BoardListRequester::HandleAllData parsed BoardList XML file : "+message["Identifier"]);\r
+ }\r
+ else\r
+ {\r
+ // bad data - mark index\r
+ st=m_db->Prepare("INSERT INTO tblBoardListRequests(IdentityID,Day,RequestIndex,Found) VALUES(?,?,?,'false');");\r
+ st.Bind(0,identityid);\r
+ st.Bind(1,idparts[4]);\r
+ st.Bind(2,index);\r
+ st.Step();\r
+ st.Finalize();\r
+\r
+ m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"BoardListRequester::HandleAllData error parsing BoardList XML file : "+message["Identifier"]);\r
+ }\r
+\r
+ // remove this identityid from request list\r
+ RemoveFromRequestList(identityid);\r
+\r
+ return true;\r
+\r
+}\r
+\r
+const bool BoardListRequester::HandleGetFailed(FCPMessage &message)\r
+{\r
+ DateTime now;\r
+ SQLite3DB::Statement st;\r
+ std::vector<std::string> idparts;\r
+ long identityid;\r
+ long index;\r
+\r
+ now.SetToGMTime();\r
+ StringFunctions::Split(message["Identifier"],"|",idparts);\r
+ StringFunctions::Convert(idparts[1],identityid);\r
+ StringFunctions::Convert(idparts[2],index); \r
+\r
+ // if this is a fatal error - insert index into database so we won't try to download this index again\r
+ if(message["Fatal"]=="true")\r
+ {\r
+ st=m_db->Prepare("INSERT INTO tblBoardListRequests(IdentityID,Day,RequestIndex,Found) VALUES(?,?,?,'false');");\r
+ st.Bind(0,identityid);\r
+ st.Bind(1,idparts[4]);\r
+ st.Bind(2,index);\r
+ st.Step();\r
+ st.Finalize();\r
+\r
+ m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"BoardListRequester::HandleGetFailed fatal error requesting "+message["Identifier"]);\r
+ }\r
+\r
+ // remove this identityid from request list\r
+ RemoveFromRequestList(identityid);\r
+\r
+ return true;\r
+}\r
+\r
+void BoardListRequester::Initialize()\r
+{\r
+ std::string tempval="";\r
+\r
+ m_fcpuniquename="BoardListRequester";\r
+ m_maxrequests=0;\r
+\r
+ Option::Instance()->Get("MaxBoardListRequests",tempval);\r
+ StringFunctions::Convert(tempval,m_maxrequests);\r
+ if(m_maxrequests<0)\r
+ {\r
+ m_maxrequests=0;\r
+ m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"Option MaxBoardListRequests is currently set at "+tempval+". It must be 0 or greater.");\r
+ }\r
+ if(m_maxrequests>100)\r
+ {\r
+ m_log->WriteLog(LogFile::LOGLEVEL_WARNING,"Option MaxBoardListRequests is currently set at "+tempval+". This value might be incorrectly configured.");\r
+ }\r
+}\r
+\r
+void BoardListRequester::PopulateIDList()\r
+{\r
+ int id;\r
+ DateTime today;\r
+ today.SetToGMTime();\r
+\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT IdentityID FROM tblIdentity WHERE PublicKey IS NOT NULL AND PublicKey <> '' AND LastSeen>='"+today.Format("%Y-%m-%d")+"' AND LocalMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalMessageTrust') AND PublishBoardList='true' ORDER BY LocalMessageTrust+LocalTrustListTrust DESC, LastSeen;");\r
+ st.Step();\r
+\r
+ m_ids.clear();\r
+\r
+ while(st.RowReturned())\r
+ {\r
+ st.ResultInt(0,id);\r
+ m_ids[id]=false;\r
+ st.Step();\r
+ }\r
+\r
+}\r
+\r
+void BoardListRequester::StartRequest(const long &identityid)\r
+{\r
+ DateTime now;\r
+ FCPMessage message;\r
+ std::string publickey;\r
+ std::string indexstr;\r
+ int index;\r
+ std::string identityidstr;\r
+\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT PublicKey FROM tblIdentity WHERE identityid=?;");\r
+ st.Bind(0,identityid);\r
+ st.Step();\r
+\r
+ if(st.RowReturned())\r
+ {\r
+ st.ResultText(0,publickey);\r
+\r
+ now.SetToGMTime();\r
+\r
+ SQLite3DB::Statement st2=m_db->Prepare("SELECT MAX(RequestIndex) FROM tblBoardListRequests WHERE Day=? AND IdentityID=?;");\r
+ st2.Bind(0,now.Format("%Y-%m-%d"));\r
+ st2.Bind(1,identityid);\r
+ st2.Step();\r
+\r
+ index=0;\r
+ if(st2.RowReturned())\r
+ {\r
+ if(st2.ResultNull(0)==false)\r
+ {\r
+ st2.ResultInt(0,index);\r
+ index++;\r
+ }\r
+ }\r
+ st2.Finalize();\r
+\r
+ StringFunctions::Convert(index,indexstr);\r
+ StringFunctions::Convert(identityid,identityidstr);\r
+\r
+ message.SetName("ClientGet");\r
+ message["URI"]=publickey+m_messagebase+"|"+now.Format("%Y-%m-%d")+"|BoardList|"+indexstr+".xml";\r
+ message["Identifier"]=m_fcpuniquename+"|"+identityidstr+"|"+indexstr+"|"+message["URI"];\r
+ message["ReturnType"]="direct";\r
+ message["MaxSize"]="100000"; // 100 KB\r
+\r
+ m_fcp->SendMessage(message);\r
+\r
+ m_requesting.push_back(identityid);\r
+\r
+ }\r
+ st.Finalize();\r
+\r
+ m_ids[identityid]=true;\r
+\r
+}\r
--- /dev/null
+#include "../../include/freenet/boardlistxml.h"\r
+\r
+#ifdef XMEM\r
+ #include <xmem.h>\r
+#endif\r
+\r
+BoardListXML::BoardListXML()\r
+{\r
+ Initialize();\r
+}\r
+\r
+void BoardListXML::AddBoard(const std::string &name, const std::string &description)\r
+{\r
+ if(name!="" && description!="")\r
+ {\r
+ m_boards.push_back(board(name,description));\r
+ }\r
+}\r
+\r
+const std::string BoardListXML::GetDescription(const long index)\r
+{\r
+ if(index>=0 && index<GetCount())\r
+ {\r
+ return m_boards[index].m_description;\r
+ }\r
+ else\r
+ {\r
+ return "";\r
+ }\r
+}\r
+\r
+const std::string BoardListXML::GetName(const long index)\r
+{\r
+ if(index>=0 && index<GetCount())\r
+ {\r
+ return m_boards[index].m_name;\r
+ }\r
+ else\r
+ {\r
+ return "";\r
+ }\r
+}\r
+\r
+std::string BoardListXML::GetXML()\r
+{\r
+ TiXmlDocument td;\r
+ TiXmlDeclaration *tdec=new TiXmlDeclaration("1.0","UTF-8","");\r
+ TiXmlElement *tid;\r
+ TiXmlPrinter tp;\r
+\r
+ td.LinkEndChild(tdec);\r
+ tid=new TiXmlElement("BoardList");\r
+ td.LinkEndChild(tid);\r
+\r
+ for(std::vector<board>::iterator i=m_boards.begin(); i!=m_boards.end(); i++)\r
+ {\r
+ TiXmlElement *tr=new TiXmlElement("Board");\r
+ tid->LinkEndChild(tr);\r
+ tr->LinkEndChild(XMLCreateCDATAElement("Name",(*i).m_name));\r
+ tr->LinkEndChild(XMLCreateCDATAElement("Description",(*i).m_description));\r
+ }\r
+\r
+ td.Accept(&tp);\r
+ return std::string(tp.CStr());\r
+}\r
+\r
+void BoardListXML::Initialize()\r
+{\r
+ m_boards.clear();\r
+}\r
+\r
+const bool BoardListXML::ParseXML(const std::string &xml)\r
+{\r
+ std::string name;\r
+ std::string description;\r
+ TiXmlDocument td;\r
+ td.Parse(xml.c_str());\r
+\r
+ if(!td.Error())\r
+ {\r
+ TiXmlText *txt;\r
+ TiXmlHandle hnd(&td);\r
+ TiXmlNode *node;\r
+\r
+ Initialize();\r
+\r
+ node=hnd.FirstChild("BoardList").FirstChild("Board").ToElement();\r
+ while(node)\r
+ {\r
+ name="";\r
+ description="";\r
+\r
+ TiXmlHandle hnd2(node);\r
+ txt=hnd2.FirstChild("Name").FirstChild().ToText();\r
+ if(txt)\r
+ {\r
+ name=txt->ValueStr();\r
+ }\r
+ txt=hnd2.FirstChild("Description").FirstChild().ToText();\r
+ if(txt)\r
+ {\r
+ description=txt->ValueStr();\r
+ }\r
+\r
+ if(name!="" && description!="")\r
+ {\r
+ m_boards.push_back(board(name,description));\r
+ }\r
+ \r
+ node=node->NextSibling("Board");\r
+ }\r
+ return true;\r
+\r
+ }\r
+ else\r
+ {\r
+ return false;\r
+ }\r
+}
\ No newline at end of file
#include "../../include/freenet/messageinserter.h"\r
#include "../../include/freenet/messagelistinserter.h"\r
#include "../../include/freenet/periodicdbmaintenance.h"\r
+#include "../../include/freenet/boardlistinserter.h"\r
+#include "../../include/freenet/boardlistrequester.h"\r
\r
//#include <zthread/Thread.h>\r
#include "../../include/pthreadwrapper/thread.h"\r
void FreenetMasterThread::Run()\r
{\r
\r
+ DateTime lastreceivedmessage;\r
+ DateTime now;\r
FCPMessage message;\r
bool done=false;\r
\r
Sleep(1000);\r
}\r
}\r
+ else\r
+ {\r
+ lastreceivedmessage.SetToGMTime();\r
+ }\r
}\r
// fcp is connected\r
else\r
if(message.GetName()!="")\r
{\r
HandleMessage(message);\r
+ lastreceivedmessage.SetToGMTime();\r
}\r
}\r
\r
(*i)->Process();\r
}\r
\r
+ // if we haven't received any messages from the node in 10 minutes, something is wrong\r
+ now.SetToGMTime();\r
+ if(lastreceivedmessage<(now-(1.0/144.0)))\r
+ {\r
+ m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"FreenetMasterThread::Run The Freenet node has not responded in 10 minutes. Trying to reconnect.");\r
+ m_fcp.Disconnect();\r
+ }\r
+\r
}\r
// }while(!ZThread::Thread::interrupted() && done==false);\r
}while(!IsCancelled() && done==false);\r
m_registrables.push_back(new IdentityIntroductionInserter(&m_fcp));\r
m_registrables.push_back(new TrustListInserter(&m_fcp));\r
m_registrables.push_back(new TrustListRequester(&m_fcp));\r
+ m_registrables.push_back(new MessageListInserter(&m_fcp));\r
m_registrables.push_back(new MessageListRequester(&m_fcp));\r
m_registrables.push_back(new MessageRequester(&m_fcp));\r
m_registrables.push_back(new MessageInserter(&m_fcp));\r
- m_registrables.push_back(new MessageListInserter(&m_fcp));\r
+ m_registrables.push_back(new BoardListInserter(&m_fcp));\r
+ m_registrables.push_back(new BoardListRequester(&m_fcp));\r
m_registrables.push_back(new PeriodicDBMaintenance());\r
\r
for(std::vector<IFreenetRegistrable *>::iterator i=m_registrables.begin(); i!=m_registrables.end(); i++)\r
#include "../../include/freenet/messagerequester.h"\r
#include "../../include/freenet/messagexml.h"\r
\r
+#include <algorithm>\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
if(xml.ParseXML(std::string(data.begin(),data.end()))==true)\r
{\r
std::vector<std::string> boards=xml.GetBoards();\r
+ if(boards.size()>m_maxboardspermessage)\r
+ {\r
+ boards.resize(m_maxboardspermessage);\r
+ }\r
\r
if(boards.size()<=0)\r
{\r
m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"MessageRequester::HandleAllData Message XML did not contain a reply board! "+message["Identifier"]);\r
return true;\r
}\r
+ \r
+ // make sure the reply board is on the board list - if not, replace the last element of boardswith the reply board\r
+ if(xml.GetReplyBoard()!="" && std::find(boards.begin(),boards.end(),xml.GetReplyBoard())==boards.end() && boards.size()>0)\r
+ {\r
+ boards[boards.size()-1]=xml.GetReplyBoard();\r
+ }\r
\r
st=m_db->Prepare("INSERT INTO tblMessage(IdentityID,FromName,MessageDate,MessageTime,Subject,MessageUUID,ReplyBoardID,Body) VALUES(?,?,?,?,?,?,?,?);");\r
st.Bind(0,identityid);\r
{\r
m_log->WriteLog(LogFile::LOGLEVEL_WARNING,"Option MaxPeerMessagesPerDay is currently set at "+tempval+". This value might be incorrectly configured. The suggested value is 200.");\r
}\r
+ Option::Instance()->Get("MaxBoardsPerMessage",tempval);\r
+ StringFunctions::Convert(tempval,m_maxboardspermessage);\r
+ if(m_maxboardspermessage<1)\r
+ {\r
+ m_maxboardspermessage=1;\r
+ m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"Option MaxBoardsPerMessage is currently set at "+tempval+". It must be 1 or greater.");\r
+ }\r
+ if(m_maxboardspermessage>20)\r
+ {\r
+ m_log->WriteLog(LogFile::LOGLEVEL_WARNING,"Option MaxBoardsPerMessage is currently set at "+tempval+". This value might be incorrectly configured.");\r
+ }\r
}\r
\r
void MessageRequester::PopulateIDList()\r
m_check1day.SetToGMTime();\r
\r
// set back times so they will do their first maintenance soon ( within the next hour ) - stagger so not all run at once\r
- m_check1hour.Add(0,-45);\r
- m_check6hours.Add(0,0,-5);\r
+ m_check30mins.Add(0,-5);\r
+ m_check1hour.Add(0,-42);\r
+ m_check6hours.Add(0,-1,-5);\r
m_check1day.Add(0,0,-23);\r
\r
}\r
date.SetToGMTime();\r
date.Add(0,0,0,-2);\r
m_db->Execute("DELETE FROM tblTrustListInserts WHERE Day<'"+date.Format("%Y-%m-%d")+"';");\r
- m_db->Execute("DELETE FROM tblTrustListRequests WHERE Day<'"+date.Format("%Y-%m-%d")+"';"); \r
+ m_db->Execute("DELETE FROM tblTrustListRequests WHERE Day<'"+date.Format("%Y-%m-%d")+"';");\r
+\r
+ // delete trust lists from identities we aren't trusting anymore\r
+ m_db->Execute("DELETE FROM tblPeerTrust WHERE IdentityID NOT IN (SELECT IdentityID FROM tblIdentity WHERE (LocalTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalTrustListTrust')) AND (PeerTrustListTrust IS NULL OR PeerTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerTrustListTrust')));");\r
\r
}\r
\r
if(major==1 && minor==0)\r
{\r
ConvertDB0100To0101();\r
+ major=1;\r
+ minor=1;\r
}\r
}\r
else\r
db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,1);");\r
}\r
\r
+ db->Execute("UPDATE tblDBVersion SET Major=1, Minor=2;");\r
+\r
db->Execute("CREATE TABLE IF NOT EXISTS tblOption(\\r
Option TEXT UNIQUE,\\r
OptionValue TEXT NOT NULL,\\r
DateAdded DATETIME\\r
);");\r
\r
- db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('fms','Freenet Message System','2007-12-01');");\r
- db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('freenet','Discussion about Freenet','2007-12-01');");\r
- db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('public','Public discussion','2007-12-01');");\r
- db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('test','Test board','2007-12-01');");\r
+ db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('fms','Freenet Message System','2007-12-01 12:00:00');");\r
+ db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('freenet','Discussion about Freenet','2007-12-01 12:00:00');");\r
+ db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('public','Public discussion','2007-12-01 12:00:00');");\r
+ db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('test','Test board','2007-12-01 12:00:00');");\r
\r
db->Execute("CREATE TABLE IF NOT EXISTS tblMessage(\\r
MessageID INTEGER PRIMARY KEY,\\r
ModifyLocalTrustListTrust INTEGER\\r
);");\r
\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListInserts(\\r
+ LocalIdentityID INTEGER,\\r
+ Day DATE,\\r
+ InsertIndex INTEGER,\\r
+ Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\\r
+ );");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListRequests(\\r
+ IdentityID INTEGER,\\r
+ Day DATE,\\r
+ RequestIndex INTEGER,\\r
+ Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
+ );"); \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
LocalIdentityID INTEGER,\\r
st.Step();\r
st.Reset();\r
\r
+ st.Bind(0,"MaxBoardListRequests");\r
+ st.Bind(1,"5");\r
+ st.Bind(2,"The maximum number of concurrent requests for new Board Lists. Set to 0 to disable.");\r
+ st.Step();\r
+ st.Reset();\r
+\r
+ st.Bind(0,"MaxBoardsPerMessage");\r
+ st.Bind(1,"8");\r
+ st.Bind(2,"The maximum number of boards a received message may be sent to. Boards over this limit will be ignored.");\r
+ st.Step();\r
+ st.Reset();\r
+\r
}\r
\r
void SetupLogFile()\r
#include "../../include/http/pages/peertrustpage.h"\r
#include "../../include/http/pages/controlboardpage.h"\r
#include "../../include/http/pages/peerdetailspage.h"\r
+#include "../../include/http/pages/peermaintenancepage.h"\r
\r
#include <iostream>\r
\r
m_pagehandlers.push_back(new PeerTrustPage(templatestr));\r
m_pagehandlers.push_back(new ControlBoardPage(templatestr));\r
m_pagehandlers.push_back(new PeerDetailsPage(templatestr));\r
+ m_pagehandlers.push_back(new PeerMaintenancePage(templatestr));\r
// homepage must be last - catch all page handler\r
m_pagehandlers.push_back(new HomePage(templatestr));\r
\r
{\r
return false;\r
}\r
-}
\ No newline at end of file
+}\r
std::string lastid="";\r
std::string thisid="";\r
std::string day="";\r
+ int requestindex=0;\r
+ bool willshow=false;\r
\r
if(queryvars.find("formaction")!=queryvars.end() && (*queryvars.find("formaction")).second=="announce")\r
{\r
content+="<tr><td colspan=\"4\"><center>Type the answers of a few puzzles. The puzzles are case sensitive.</td></tr>";\r
content+="<tr>";\r
\r
- //TODO if we are already inserting a solution for an identity - we shouldn't select any puzzles that are older than the one we are inserting\r
\r
date.SetToGMTime();\r
date.Add(0,0,0,-1);\r
- SQLite3DB::Statement st=m_db->Prepare("SELECT UUID,Day,IdentityID FROM tblIntroductionPuzzleRequests WHERE UUID NOT IN (SELECT UUID FROM tblIdentityIntroductionInserts) AND UUID NOT IN (SELECT UUID FROM tblIntroductionPuzzleInserts) AND Day>='"+date.Format("%Y-%m-%d")+"' AND Found='true' ORDER BY IdentityID, Day DESC, RequestIndex DESC;");\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT UUID,Day,IdentityID,RequestIndex FROM tblIntroductionPuzzleRequests WHERE UUID NOT IN (SELECT UUID FROM tblIdentityIntroductionInserts) AND UUID NOT IN (SELECT UUID FROM tblIntroductionPuzzleInserts) AND Day>='"+date.Format("%Y-%m-%d")+"' AND Found='true' ORDER BY IdentityID, Day DESC, RequestIndex DESC;");\r
st.Step();\r
\r
if(st.RowReturned()==false)\r
st.ResultText(0,uuid);\r
st.ResultText(1,day);\r
st.ResultText(2,thisid);\r
+ st.ResultInt(3,requestindex);\r
+\r
+ // if we are already inserting a solution for an identity - we shouldn't show any puzzles that are older than the one we are inserting\r
+ // get the last index # we are inserting this day from this identity\r
+ // if the index here is greater than the index in the st statement, we will skip this puzzle because we are already inserting a puzzle with a greater index\r
+ willshow=true;\r
+ SQLite3DB::Statement st2=m_db->Prepare("SELECT MAX(RequestIndex) FROM tblIdentityIntroductionInserts INNER JOIN tblIntroductionPuzzleRequests ON tblIdentityIntroductionInserts.UUID=tblIntroductionPuzzleRequests.UUID WHERE tblIdentityIntroductionInserts.Day=? AND tblIdentityIntroductionInserts.UUID IN (SELECT UUID FROM tblIntroductionPuzzleRequests WHERE IdentityID=? AND Day=?) GROUP BY tblIdentityIntroductionInserts.Day;");\r
+ st2.Step();\r
+ if(st2.RowReturned()==true)\r
+ {\r
+ int index=0;\r
+ st2.ResultInt(0,index);\r
+ if(index>=requestindex)\r
+ {\r
+ willshow=false;\r
+ }\r
+ }\r
\r
- if(thisid!=lastid)\r
+ if(willshow && thisid!=lastid)\r
{\r
StringFunctions::Convert(shown,countstr);\r
if(shown>0 && shown%4==0)\r
content+="<input type=\"hidden\" name=\"day["+countstr+"]\" value=\""+day+"\">";\r
content+="<input type=\"text\" name=\"solution["+countstr+"]\">";\r
content+="</td>\r\n";\r
- thisid=lastid;\r
+ lastid=thisid;\r
shown++;\r
}\r
\r
\r
content+="<h2>Control Boards</h2>";\r
content+="<p class=\"paragraph\">";\r
- content+="These boards are special administration boards where sent messages will change the trust levels of the parent poster. These boards can not be used as regular boards, so make the name unique. The change in trust levels can be negative or positive, but keep in mind that the minimum trust level is 0 and the maximum trust level is 100. After the boards are created here, you may use your newreader to reply to a message to one or more of these boards, and the previous poster will have his trust levels changed as per the settings for that board.";\r
+ content+="These boards are special administration boards where sent messages will change the trust levels of the parent poster by ADDING these numbers to their current trust level. These boards can not be used as regular boards, so make the name unique. The change in trust levels can be negative or positive, but keep in mind that the minimum trust level is 0 and the maximum trust level is 100. After the boards are created here, you may use your newreader to reply to a message to one or more of these boards, and the previous poster will have his trust levels changed as per the settings for that board.";\r
content+="</p>";\r
\r
st=m_db->Prepare("SELECT tblBoard.BoardID,BoardName,ModifyLocalMessageTrust,ModifyLocalTrustListTrust FROM tblBoard INNER JOIN tblAdministrationBoard ON tblBoard.BoardID=tblAdministrationBoard.BoardID ORDER BY BoardName COLLATE NOCASE;");\r
std::vector<std::string> ids;\r
std::vector<std::string> singleuse;\r
std::vector<std::string> publishtrustlist;\r
+ std::vector<std::string> publishboardlist;\r
\r
CreateArgArray(queryvars,"chkidentityid",ids);\r
CreateArgArray(queryvars,"singleuse",singleuse);\r
CreateArgArray(queryvars,"publishtrustlist",publishtrustlist);\r
+ CreateArgArray(queryvars,"publishboardlist",publishboardlist);\r
\r
if((*queryvars.find("formaction")).second=="update")\r
{\r
- SQLite3DB::Statement update=m_db->Prepare("UPDATE tblLocalIdentity SET SingleUse=?, PublishTrustList=? WHERE LocalIdentityID=?;");\r
+ SQLite3DB::Statement update=m_db->Prepare("UPDATE tblLocalIdentity SET SingleUse=?, PublishTrustList=?, PublishBoardList=? WHERE LocalIdentityID=?;");\r
for(int i=0; i<ids.size(); i++)\r
{\r
if(ids[i]!="")\r
StringFunctions::Convert(ids[i],id);\r
update.Bind(0,singleuse[i]);\r
update.Bind(1,publishtrustlist[i]);\r
- update.Bind(2,id);\r
+ update.Bind(2,publishboardlist[i]);\r
+ update.Bind(3,id);\r
update.Step();\r
update.Reset();\r
}\r
content+="</form>";\r
content+="</td></tr></table>";\r
\r
+ content+="<hr>";\r
+\r
content+="<form name=\"frmlocalidentity\" method=\"POST\">";\r
content+="<input type=\"hidden\" name=\"formaction\" value=\"update\">";\r
- content+="<table><tr><td></td><th>Name</th><th>Single Use</th><th>Publish Trust List</th><th>Announced? *</th></tr>";\r
+ content+="<table><tr><td></td><th>Name</th><th>Single Use</th><th>Publish Trust List</th><th>Publish Board List</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 FROM tblLocalIdentity LEFT JOIN tblIdentity ON tblLocalIdentity.PublicKey=tblIdentity.PublicKey ORDER BY tblLocalIdentity.Name;");\r
st.Step();\r
while(st.RowReturned())\r
{\r
StringFunctions::Convert(count,countstr);\r
- std::string id;\r
- std::string name;\r
- std::string publickey;\r
- std::string publishtrustlist;\r
- std::string singleuse;\r
- std::string keypart;\r
+ std::string id="";\r
+ std::string name="";\r
+ std::string publickey="";\r
+ std::string publishtrustlist="";\r
+ std::string singleuse="";\r
+ std::string keypart="";\r
+ std::string publishboardlist="";\r
\r
st.ResultText(0,id);\r
st.ResultText(1,name);\r
st.ResultText(2,publickey);\r
st.ResultText(3,publishtrustlist);\r
st.ResultText(4,singleuse);\r
+ st.ResultText(5,publishboardlist);\r
\r
if(publickey.size()>8)\r
{\r
content+="<td title=\""+publickey+"\">"+SanitizeOutput(name+keypart)+"...</td>";\r
content+="<td>"+CreateTrueFalseDropDown("singleuse["+countstr+"]",singleuse)+"</td>";\r
content+="<td>"+CreateTrueFalseDropDown("publishtrustlist["+countstr+"]",publishtrustlist)+"</td>";\r
+ content+="<td>"+CreateTrueFalseDropDown("publishboardlist["+countstr+"]",publishboardlist)+"</td>";\r
if(st.ResultNull(6))\r
{\r
content+="<td>No</td>";\r
count++;\r
}\r
\r
- content+="<tr><td colspan=\"4\"><center><input type=\"submit\" value=\"Update Selected\"> <input type=\"submit\" value=\"Delete Selected\" onClick=\"if(confirm('Delete Selected Identities?')){frmlocalidentity.formaction.value='delete';}else{return false;}\"></td></tr>";\r
+ content+="<tr><td colspan=\"5\"><center><input type=\"submit\" value=\"Update Selected\"> <input type=\"submit\" value=\"Delete Selected\" onClick=\"if(confirm('Delete Selected Identities?')){frmlocalidentity.formaction.value='delete';}else{return false;}\"></td></tr>";\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.</p>";\r
\r
--- /dev/null
+#include "../../../include/http/pages/peermaintenancepage.h"\r
+#include "../../../include/stringfunctions.h"\r
+#include "../../../include/datetime.h"\r
+\r
+#ifdef XMEM\r
+ #include <xmem.h>\r
+#endif\r
+\r
+const std::string PeerMaintenancePage::GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars)\r
+{\r
+ std::string content="";\r
+ SQLite3DB::Statement st;\r
+ std::string tempval;\r
+ DateTime date;\r
+\r
+ if(queryvars.find("formaction")!=queryvars.end())\r
+ {\r
+ if((*queryvars.find("formaction")).second=="removenotseen")\r
+ {\r
+ m_db->Execute("DELETE FROM tblIdentity WHERE LastSeen IS NULL;");\r
+ }\r
+ else if((*queryvars.find("formaction")).second=="removelastseen20")\r
+ {\r
+ date.SetToGMTime();\r
+ date.Add(0,0,0,-20);\r
+ st=m_db->Prepare("DELETE FROM tblIdentity WHERE LastSeen<?;");\r
+ st.Bind(0,date.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Step();\r
+ }\r
+ else if((*queryvars.find("formaction")).second=="removeneversent")\r
+ {\r
+ m_db->Execute("DELETE FROM tblIdentity WHERE IdentityID NOT IN (SELECT IdentityID FROM tblMessage GROUP BY IdentityID);");\r
+ }\r
+ else if((*queryvars.find("formaction")).second=="removelastseenneversent20")\r
+ {\r
+ date.SetToGMTime();\r
+ date.Add(0,0,0,-20);\r
+ st=m_db->Prepare("DELETE FROM tblIdentity WHERE IdentityID NOT IN (SELECT IdentityID FROM tblMessage GROUP BY IdentityID) AND LastSeen<?;");\r
+ st.Bind(0,date.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Step();\r
+ }\r
+ else if((*queryvars.find("formaction")).second=="removedaysago" && queryvars.find("daysago")!=queryvars.end() && (*queryvars.find("daysago")).second!="")\r
+ {\r
+ int tempint=10000;\r
+ StringFunctions::Convert((*queryvars.find("daysago")).second,tempint);\r
+ date.SetToGMTime();\r
+ date.Add(0,0,0,-tempint);\r
+ st=m_db->Prepare("DELETE FROM tblIdentity WHERE IdentityID NOT IN (SELECT IdentityID FROM tblMessage GROUP BY IdentityID) AND LastSeen<?;");\r
+ st.Bind(0,date.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Step();\r
+ }\r
+ }\r
+\r
+ content+="<h2>Peer Maintenance</h2>";\r
+ content+="<p class=\"paragraph\">Removing a peer will not remove the messages they sent, but will remove everything else about that peer, including their trust levels.</p>";\r
+ content+="<table>";\r
+ content+="<tr><th colspan=\"3\">Stats</th></tr>";\r
+\r
+ content+="<tr>";\r
+ st=m_db->Prepare("SELECT COUNT(*) FROM tblIdentity;");\r
+ st.Step();\r
+ st.ResultText(0,tempval);\r
+ content+="<td>"+tempval+"</td>";\r
+ content+="<td>known peers</td>";\r
+ content+="</tr>";\r
+\r
+ content+="<tr>";\r
+ st=m_db->Prepare("SELECT COUNT(*) FROM tblIdentity WHERE LastSeen IS NULL;");\r
+ st.Step();\r
+ st.ResultText(0,tempval);\r
+ content+="<td>"+tempval+"</td>";\r
+ content+="<td>never seen</td>";\r
+ content+="<td>";\r
+ content+="<form name=\"frmremove\" method=\"POST\">";\r
+ content+="<input type=\"hidden\" name=\"formaction\" value=\"removenotseen\">";\r
+ content+="<input type=\"submit\" value=\"Remove\">";\r
+ content+="</form>";\r
+ content+="</td>";\r
+ content+="</tr>";\r
+\r
+ date.SetToGMTime();\r
+ date.Add(0,0,0,-20);\r
+ st=m_db->Prepare("SELECT COUNT(*) FROM tblIdentity WHERE LastSeen<?;");\r
+ st.Bind(0,date.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Step();\r
+ st.ResultText(0,tempval);\r
+ content+="<tr>";\r
+ content+="<td>"+tempval+"</td>";\r
+ content+="<td>last seen more than 20 days ago</td>";\r
+ content+="<td>";\r
+ content+="<form name=\"frmremove\" method=\"POST\">";\r
+ content+="<input type=\"hidden\" name=\"formaction\" value=\"removelastseen20\">";\r
+ content+="<input type=\"submit\" value=\"Remove\">";\r
+ content+="</form>";\r
+ content+="</td>";\r
+ content+="</tr>";\r
+\r
+ st=m_db->Prepare("SELECT COUNT(*) FROM tblIdentity LEFT JOIN tblMessage ON tblIdentity.IdentityID=tblMessage.IdentityID WHERE tblMessage.IdentityID IS NULL;");\r
+ st.Step();\r
+ st.ResultText(0,tempval);\r
+ content+="<tr>";\r
+ content+="<td>"+tempval+"</td>";\r
+ content+="<td>never sent a message</td>";\r
+ content+="<td>";\r
+ content+="<form name=\"frmremove\" method=\"POST\">";\r
+ content+="<input type=\"hidden\" name=\"formaction\" value=\"removeneversent\">";\r
+ content+="<input type=\"submit\" value=\"Remove\">";\r
+ content+="</form>";\r
+ content+="</td>";\r
+ content+="</tr>";\r
+\r
+ date.SetToGMTime();\r
+ date.Add(0,0,0,-20);\r
+ st=m_db->Prepare("SELECT COUNT(*) FROM tblIdentity LEFT JOIN tblMessage ON tblIdentity.IdentityID=tblMessage.IdentityID WHERE tblMessage.IdentityID IS NULL AND tblIdentity.LastSeen<?;");\r
+ st.Bind(0,date.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Step();\r
+ st.ResultText(0,tempval);\r
+ content+="<tr>";\r
+ content+="<td>"+tempval+"</td>";\r
+ content+="<td>last seen more than 20 days ago and never sent a message</td>";\r
+ content+="<td>";\r
+ content+="<form name=\"frmremove\" method=\"POST\">";\r
+ content+="<input type=\"hidden\" name=\"formaction\" value=\"removelastseenneversent20\">";\r
+ content+="<input type=\"submit\" value=\"Remove\">";\r
+ content+="</form>";\r
+ content+="</td>";\r
+ content+="</tr>";\r
+\r
+ content+="<tr>";\r
+ content+="<td><form name=\"frmdelete\" method=\"POST\"><input type=\"hidden\" name=\"formaction\" value=\"removedaysago\"></td>";\r
+ content+="<td>last seen <input type=\"text\" name=\"daysago\" size=\"2\"> days ago</td>";\r
+ content+="<td><input type=\"submit\" value=\"Remove\"></form></td>";\r
+ content+="</tr>";\r
+\r
+ content+="</table>";\r
+\r
+ return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"+StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+}\r
+\r
+const bool PeerMaintenancePage::WillHandleURI(const std::string &uri)\r
+{\r
+ if(uri.find("peermaintenance.")!=std::string::npos)\r
+ {\r
+ return true;\r
+ }\r
+ else\r
+ {\r
+ return false;\r
+ }\r
+}
\ No newline at end of file
\r
int main(int argc, char *argv[])\r
{\r
+ bool daemon=false;\r
\r
#ifdef XMEM\r
xmem_disable_print();\r
if(argv[1] && strncmp(argv[1],"-d",2)==0)\r
{\r
Daemonize();\r
+ daemon=true;\r
}\r
#else\r
if(argv[1] && strncmp(argv[1],"-i",2)==0)\r
signal(SIGBREAK,SigHandler);\r
#endif\r
\r
- std::cout << "FMS Running in console mode." << std::endl;\r
- std::cout << "Use the administration pages, or CTRL+C to exit" << std::endl << std::endl;\r
- std::cout << "Available command line arguments:" << std::endl;\r
-#ifdef _WIN32\r
- std::cout << "-i\tinstall service" << std::endl;\r
- std::cout << "-u\tuninstall service" << std::endl;\r
-#else\r
- std::cout << "-d\trun as daemon" << std::endl;\r
-#endif\r
+ if(daemon==false)\r
+ {\r
+ std::cout << "FMS Running in console mode." << std::endl;\r
+ std::cout << "Use the administration pages, or CTRL+C to exit" << std::endl << std::endl;\r
+ std::cout << "Available command line arguments:" << std::endl;\r
+ #ifdef _WIN32\r
+ std::cout << "-i\tinstall service" << std::endl;\r
+ std::cout << "-u\tuninstall service" << std::endl;\r
+ #else\r
+ std::cout << "-d\trun as daemon" << std::endl;\r
+ #endif\r
+ }\r
\r
MainFunction();\r
\r
pthread_mutex_lock(&m);\r
pthread_cond_timedwait(&c,&m,&t);\r
pthread_mutex_unlock(&m);\r
+\r
+ pthread_cond_destroy(&c);\r
+ pthread_mutex_destroy(&m);\r
}\r
\r
Thread::Thread()\r
m_cancelled=false;\r
m_runnable=0;\r
m_threadnum=0;\r
+ m_threadcleaned=true;\r
}\r
\r
Thread::Thread(Runnable *runnable)\r
m_cancelled=false;\r
m_runnable=runnable;\r
m_threadnum=0;\r
+ m_threadcleaned=true;\r
if(m_runnable)\r
{\r
m_runnable->m_thread=this;\r
{\r
Cancel();\r
Join();\r
+ if(m_threadcleaned==false)\r
+ {\r
+ pthread_detach(m_thread);\r
+ }\r
if(m_runnable)\r
{\r
delete m_runnable;\r
if(m_running)\r
{\r
pthread_join(m_thread,NULL);\r
+ m_threadcleaned=true;\r
}\r
}\r
\r
pthread_mutex_lock(&m);\r
pthread_cond_timedwait(&c,&m,&t);\r
pthread_mutex_unlock(&m);\r
+\r
+ pthread_cond_destroy(&c);\r
+ pthread_mutex_destroy(&m);\r
}\r
}\r
\r
void Thread::Start()\r
{\r
m_running=true;\r
+ m_threadcleaned=false;\r
m_threadnum=pthread_create(&m_thread,NULL,Thread::EntryPoint,this);\r
}\r
\r
<li><a href="localidentities.htm">Local Identities</a></li>\r
<li><a href="announceidentity.htm">Announce Identity</a></li>\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="controlboard.htm">Control Boards</a></li>\r
</ul>\r