From: SomeDude Date: Sat, 16 Feb 2008 08:13:00 +0000 (+0100) Subject: version 0.1.11 X-Git-Url: https://git.pterodactylus.net/?a=commitdiff_plain;h=df316253862dc50e8e5a790d9634ef90be37badb;p=fms.git version 0.1.11 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 024be6a..994d5e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,9 @@ src/uuidgenerator.cpp src/db/sqlite3db.cpp src/db/sqlite3recordset.cpp src/db/sqlite3statement.cpp +src/freenet/boardlistinserter.cpp +src/freenet/boardlistrequester.cpp +src/freenet/boardlistxml.cpp src/freenet/fcpv2.cpp src/freenet/freenetmasterthread.cpp src/freenet/freenetssk.cpp @@ -58,6 +61,7 @@ src/http/pages/homepage.cpp src/http/pages/localidentitiespage.cpp src/http/pages/optionspage.cpp src/http/pages/peerdetailspage.cpp +src/http/pages/peermaintenancepage.cpp src/http/pages/peertrustpage.cpp src/http/pages/showcaptchapage.cpp src/nntp/nntpconnection.cpp diff --git a/include/db/sqlite3db/sqlite3db.h b/include/db/sqlite3db/sqlite3db.h index f0aac60..b41f3b8 100644 --- a/include/db/sqlite3db/sqlite3db.h +++ b/include/db/sqlite3db/sqlite3db.h @@ -5,11 +5,11 @@ //#include #include #include -#include "../../pthreadwrapper/singleton.h" #include "../../pthreadwrapper/mutex.h" - #include "../sqlite3db.h" +#include "../../pthreadwrapper/singleton.h" + #if SQLITE_VERSION_NUMBER<3005000 #error "Your version of SQLite is too old! 3.5.0 or later is required." #endif diff --git a/include/freenet/boardlistinserter.h b/include/freenet/boardlistinserter.h new file mode 100644 index 0000000..54b5e80 --- /dev/null +++ b/include/freenet/boardlistinserter.h @@ -0,0 +1,20 @@ +#ifndef _boardlistinserter_ +#define _boardlistinserter_ + +#include "iindexinserter.h" + +class BoardListInserter:public IIndexInserter +{ +public: + BoardListInserter(); + BoardListInserter(FCPv2 *fcp); + +private: + void Initialize(); + const bool HandlePutSuccessful(FCPMessage &message); + const bool HandlePutFailed(FCPMessage &message); + void StartInsert(const long &localidentityid); + void CheckForNeededInsert(); +}; + +#endif // _boardlistinserter_ diff --git a/include/freenet/boardlistrequester.h b/include/freenet/boardlistrequester.h new file mode 100644 index 0000000..a920e60 --- /dev/null +++ b/include/freenet/boardlistrequester.h @@ -0,0 +1,20 @@ +#ifndef _boardlistrequester_ +#define _boardlistrequester_ + +#include "iindexrequester.h" + +class BoardListRequester:public IIndexRequester +{ +public: + BoardListRequester(); + BoardListRequester(FCPv2 *fcp); + +private: + void Initialize(); + void PopulateIDList(); + void StartRequest(const long &identityid); + const bool HandleAllData(FCPMessage &message); + const bool HandleGetFailed(FCPMessage &message); +}; + +#endif // _boardlistrequester_ diff --git a/include/freenet/boardlistxml.h b/include/freenet/boardlistxml.h new file mode 100644 index 0000000..53460df --- /dev/null +++ b/include/freenet/boardlistxml.h @@ -0,0 +1,34 @@ +#ifndef _boardlistxml_ +#define _boardlistxml_ + +#include "../ifmsxmldocument.h" + +class BoardListXML:public IFMSXMLDocument +{ +public: + BoardListXML(); + + std::string GetXML(); + + const bool ParseXML(const std::string &xml); + + void AddBoard(const std::string &name, const std::string &description); + const long GetCount() { return m_boards.size(); } + const std::string GetName(const long index); + const std::string GetDescription(const long index); + +private: + struct board + { + board(const std::string &name, const std::string &description):m_name(name),m_description(description) {} + std::string m_name; + std::string m_description; + }; + + void Initialize(); + + std::vector m_boards; + +}; + +#endif // _boardlistxml_ diff --git a/include/freenet/ifreenetregistrable.h b/include/freenet/ifreenetregistrable.h index 78e4508..955e4ea 100644 --- a/include/freenet/ifreenetregistrable.h +++ b/include/freenet/ifreenetregistrable.h @@ -9,6 +9,8 @@ class FreenetMasterThread; class IFreenetRegistrable { public: + IFreenetRegistrable() {} + virtual ~IFreenetRegistrable() {} virtual void RegisterWithThread(FreenetMasterThread *thread)=0; diff --git a/include/freenet/iindexinserter.h b/include/freenet/iindexinserter.h index fc1a6bc..050aa3d 100644 --- a/include/freenet/iindexinserter.h +++ b/include/freenet/iindexinserter.h @@ -11,12 +11,17 @@ #include "ifcpmessagehandler.h" #include "iperiodicprocessor.h" +#ifdef XMEM + #include +#endif + template class IIndexInserter:public IFreenetRegistrable,public IFCPConnected,public IFCPMessageHandler,public IPeriodicProcessor,public IDatabase,public ILogger { public: IIndexInserter(); IIndexInserter(FCPv2 *fcp); + virtual ~IIndexInserter() {} virtual void FCPConnected(); virtual void FCPDisconnected(); diff --git a/include/freenet/iindexrequester.h b/include/freenet/iindexrequester.h index 7f02763..35c16c1 100644 --- a/include/freenet/iindexrequester.h +++ b/include/freenet/iindexrequester.h @@ -11,12 +11,17 @@ #include "ifcpmessagehandler.h" #include "iperiodicprocessor.h" +#ifdef XMEM + #include +#endif + template class IIndexRequester:public IFreenetRegistrable,public IFCPConnected,public IFCPMessageHandler,public IPeriodicProcessor,public IDatabase,public ILogger { public: IIndexRequester(); IIndexRequester(FCPv2 *fcp); + virtual ~IIndexRequester() {} virtual void FCPConnected(); virtual void FCPDisconnected(); diff --git a/include/freenet/messagerequester.h b/include/freenet/messagerequester.h index c4cdb92..353de7e 100644 --- a/include/freenet/messagerequester.h +++ b/include/freenet/messagerequester.h @@ -21,6 +21,7 @@ private: long m_maxdaysbackward; long m_maxpeermessages; + long m_maxboardspermessage; }; diff --git a/include/freenet/messagexml.h b/include/freenet/messagexml.h index 04f97e2..7daa842 100644 --- a/include/freenet/messagexml.h +++ b/include/freenet/messagexml.h @@ -1,10 +1,11 @@ #ifndef _messagexml_ #define _messagexml_ -#include "../ifmsxmldocument.h" #include #include +#include "../ifmsxmldocument.h" + class MessageXML:public IFMSXMLDocument { public: diff --git a/include/global.h b/include/global.h index cb75d5a..be6dec6 100644 --- a/include/global.h +++ b/include/global.h @@ -5,7 +5,7 @@ //#include #include "pthreadwrapper/thread.h" -#define FMS_VERSION "0.1.10" +#define FMS_VERSION "0.1.11" // opens database and creates tables and initial inserts if necessary void SetupDB(); diff --git a/include/http/pages/peermaintenancepage.h b/include/http/pages/peermaintenancepage.h new file mode 100644 index 0000000..80f74f1 --- /dev/null +++ b/include/http/pages/peermaintenancepage.h @@ -0,0 +1,18 @@ +#ifndef _peermaintenancepage_ +#define _peermaintenancepage_ + +#include "../ipagehandler.h" +#include "../../idatabase.h" + +class PeerMaintenancePage:public IPageHandler,public IDatabase +{ +public: + PeerMaintenancePage(const std::string &templatestr):IPageHandler(templatestr) {} + +private: + const bool WillHandleURI(const std::string &uri); + const std::string GeneratePage(const std::string &method, const std::map &queryvars); + +}; + +#endif // _peermaintenancepage_ diff --git a/include/ifmsxmldocument.h b/include/ifmsxmldocument.h index f444af5..8e04c3c 100644 --- a/include/ifmsxmldocument.h +++ b/include/ifmsxmldocument.h @@ -6,6 +6,10 @@ #include #include +#ifdef XMEM + #include +#endif + /** \brief Interface for objects that represent an XML document */ diff --git a/include/logfile.h b/include/logfile.h index 3008caa..92ab17f 100644 --- a/include/logfile.h +++ b/include/logfile.h @@ -3,9 +3,9 @@ //#include //#include -#include "pthreadwrapper/singleton.h" #include "pthreadwrapper/mutex.h" #include +#include "pthreadwrapper/singleton.h" class LogFile:public PThread::Singleton { diff --git a/include/pthreadwrapper.h b/include/pthreadwrapper.h index 76a9f09..5bad5b5 100644 --- a/include/pthreadwrapper.h +++ b/include/pthreadwrapper.h @@ -24,7 +24,7 @@ namespace PThread #include "pthreadwrapper/guard.h" #include "pthreadwrapper/runnable.h" #include "pthreadwrapper/thread.h" -#include "pthreadwrapper/singleton.h" #include "pthreadwrapper/threadedexecutor.h" +#include "pthreadwrapper/singleton.h" #endif // _pthread_wrapper_ diff --git a/include/pthreadwrapper/noncopyable.h b/include/pthreadwrapper/noncopyable.h index e6ebb8a..9e61701 100644 --- a/include/pthreadwrapper/noncopyable.h +++ b/include/pthreadwrapper/noncopyable.h @@ -7,8 +7,8 @@ namespace PThread class NonCopyable { protected: - NonCopyable() {} - ~NonCopyable() {} + NonCopyable() {} + virtual ~NonCopyable() {} private: // restrict copy and assignment diff --git a/include/pthreadwrapper/thread.h b/include/pthreadwrapper/thread.h index 6e51f73..7b5f386 100644 --- a/include/pthreadwrapper/thread.h +++ b/include/pthreadwrapper/thread.h @@ -35,6 +35,7 @@ private: bool m_running; // thread (object) is currently running bool m_cancelled; Runnable *m_runnable; // actual object that is being run + bool m_threadcleaned; }; diff --git a/src/db/sqlite3db.cpp b/src/db/sqlite3db.cpp index 1b63715..edf2e8b 100644 --- a/src/db/sqlite3db.cpp +++ b/src/db/sqlite3db.cpp @@ -129,7 +129,7 @@ const bool DB::IsOpen() const bool DB::Open(const std::string &filename) { - if(IsOpen()==false) + if(IsOpen()==true) { Close(); } diff --git a/src/freenet/boardlistinserter.cpp b/src/freenet/boardlistinserter.cpp new file mode 100644 index 0000000..92ed0b7 --- /dev/null +++ b/src/freenet/boardlistinserter.cpp @@ -0,0 +1,181 @@ +#include "../../include/freenet/boardlistinserter.h" +#include "../../include/freenet/boardlistxml.h" + +#ifdef XMEM + #include +#endif + +BoardListInserter::BoardListInserter() +{ + Initialize(); +} + +BoardListInserter::BoardListInserter(FCPv2 *fcp):IIndexInserter(fcp) +{ + Initialize(); +} + +void BoardListInserter::CheckForNeededInsert() +{ + // only do 1 insert at a time + if(m_inserting.size()==0) + { + DateTime today; + DateTime daysback; + + today.SetToGMTime(); + daysback.SetToGMTime(); + + // 20 days + daysback.Add(0,0,0,-20); + + // get identities who posted messages to boards in the past 20 days + 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=? GROUP BY tblLocalIdentity.LocalIdentityID;"); + st.Bind(0,today.Format("%Y-%m-%d")); + st.Bind(1,daysback.Format("%Y-%m-%d")); + st.Step(); + + if(st.RowReturned()) + { + int localidentityid; + st.ResultInt(0,localidentityid); + StartInsert(localidentityid); + } + } +} + +const bool BoardListInserter::HandlePutFailed(FCPMessage &message) +{ + std::vector idparts; + long localidentityid; + long index; + + StringFunctions::Split(message["Identifier"],"|",idparts); + StringFunctions::Convert(idparts[1],localidentityid); + StringFunctions::Convert(idparts[2],index); + + if(message["Fatal"]=="true" || message["Code"]=="9") + { + SQLite3DB::Statement st=m_db->Prepare("INSERT INTO tblBoardListInserts(LocalIdentityID,Day,InsertIndex,Inserted) VALUES(?,?,?,'false');"); + st.Bind(0,localidentityid); + st.Bind(1,idparts[4]); + st.Bind(2,index); + st.Step(); + } + + RemoveFromInsertList(localidentityid); + + return true; +} + +const bool BoardListInserter::HandlePutSuccessful(FCPMessage &message) +{ + DateTime now; + std::vector idparts; + long localidentityid; + long index; + + StringFunctions::Split(message["Identifier"],"|",idparts); + StringFunctions::Convert(idparts[1],localidentityid); + StringFunctions::Convert(idparts[2],index); + + SQLite3DB::Statement st=m_db->Prepare("INSERT INTO tblBoardListInserts(LocalIdentityID,Day,InsertIndex,Inserted) VALUES(?,?,?,'true');"); + st.Bind(0,localidentityid); + st.Bind(1,idparts[4]); + st.Bind(2,index); + st.Step(); + + now.SetToGMTime(); + st=m_db->Prepare("UPDATE tblLocalIdentity SET LastInsertedBoardList=? WHERE LocalIdentityID=?;"); + st.Bind(0,now.Format("%Y-%m-%d %H:%M:%S")); + st.Bind(1,localidentityid); + st.Step(); + + RemoveFromInsertList(localidentityid); + + m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"BoardListInserter::HandlePutSuccessful successfully inserted BoardList."); + + return true; +} + +void BoardListInserter::Initialize() +{ + m_fcpuniquename="BoardListInserter"; +} + +void BoardListInserter::StartInsert(const long &localidentityid) +{ + DateTime daysback; + DateTime now; + BoardListXML xml; + FCPMessage message; + std::string data; + std::string datasizestr; + std::string privatekey=""; + int index; + std::string indexstr=""; + std::string localidentityidstr; + + now.SetToGMTime(); + daysback.SetToGMTime(); + daysback.Add(0,0,0,-20); + + // get boards + 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;"); + st.Bind(0,localidentityid); + st.Bind(1,daysback.Format("%Y-%m-%d")); + st.Step(); + + while(st.RowReturned()) + { + std::string name=""; + std::string description=""; + + st.ResultText(0,name); + st.ResultText(1,description); + + xml.AddBoard(name,description); + + st.Step(); + } + + // get public key + st=m_db->Prepare("SELECT PrivateKey FROM tblLocalIdentity WHERE LocalIdentityID=?;"); + st.Bind(0,localidentityid); + st.Step(); + if(st.RowReturned()) + { + st.ResultText(0,privatekey); + } + + // get last index + index=0; + st=m_db->Prepare("SELECT MAX(InsertIndex) FROM tblBoardListInserts WHERE LocalIdentityID=? AND Day=?;"); + st.Bind(0,localidentityid); + st.Bind(1,now.Format("%Y-%m-%d")); + st.Step(); + if(st.RowReturned()) + { + if(st.ResultNull(0)==false) + { + st.ResultInt(0,index); + index++; + } + } + StringFunctions::Convert(index,indexstr); + + data=xml.GetXML(); + StringFunctions::Convert(data.size(),datasizestr); + StringFunctions::Convert(localidentityid,localidentityidstr); + + message.SetName("ClientPut"); + message["URI"]=privatekey+m_messagebase+"|"+now.Format("%Y-%m-%d")+"|BoardList|"+indexstr+".xml"; + message["Identifier"]=m_fcpuniquename+"|"+localidentityidstr+"|"+indexstr+"|"+message["URI"]; + message["UploadFrom"]="direct"; + message["DataLength"]=datasizestr; + m_fcp->SendMessage(message); + m_fcp->SendRaw(data.c_str(),data.size()); + + m_inserting.push_back(localidentityid); + +} diff --git a/src/freenet/boardlistrequester.cpp b/src/freenet/boardlistrequester.cpp new file mode 100644 index 0000000..6b52a46 --- /dev/null +++ b/src/freenet/boardlistrequester.cpp @@ -0,0 +1,243 @@ +#include "../../include/freenet/boardlistrequester.h" +#include "../../include/freenet/boardlistxml.h" + +#ifdef XMEM + #include +#endif + +BoardListRequester::BoardListRequester() +{ + Initialize(); +} + +BoardListRequester::BoardListRequester(FCPv2 *fcp):IIndexRequester(fcp) +{ + Initialize(); +} + +const bool BoardListRequester::HandleAllData(FCPMessage &message) +{ + DateTime now; + SQLite3DB::Statement st; + std::vector idparts; + long datalength; + std::vector data; + BoardListXML xml; + long identityid; + long index; + + now.SetToGMTime(); + StringFunctions::Split(message["Identifier"],"|",idparts); + StringFunctions::Convert(message["DataLength"],datalength); + StringFunctions::Convert(idparts[1],identityid); + StringFunctions::Convert(idparts[2],index); + + // wait for all data to be received from connection + while(m_fcp->Connected() && m_fcp->ReceiveBufferSize()Update(1); + } + + // if we got disconnected- return immediately + if(m_fcp->Connected()==false) + { + return false; + } + + // receive the file + data.resize(datalength); + m_fcp->ReceiveRaw(&data[0],datalength); + + // parse file into xml and update the database + if(xml.ParseXML(std::string(data.begin(),data.end()))==true) + { + + SQLite3DB::Statement brd=m_db->Prepare("SELECT BoardID,BoardName,BoardDescription FROM tblBoard WHERE BoardName=?;"); + SQLite3DB::Statement ins=m_db->Prepare("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES(?,?,?);"); + SQLite3DB::Statement upd=m_db->Prepare("UPDATE tblBoard SET BoardDescription=? WHERE BoardID=?;"); + for(long i=0; iPrepare("INSERT INTO tblBoardListRequests(IdentityID,Day,RequestIndex,Found) VALUES(?,?,?,'true');"); + st.Bind(0,identityid); + st.Bind(1,idparts[4]); + st.Bind(2,index); + st.Step(); + st.Finalize(); + + m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"BoardListRequester::HandleAllData parsed BoardList XML file : "+message["Identifier"]); + } + else + { + // bad data - mark index + st=m_db->Prepare("INSERT INTO tblBoardListRequests(IdentityID,Day,RequestIndex,Found) VALUES(?,?,?,'false');"); + st.Bind(0,identityid); + st.Bind(1,idparts[4]); + st.Bind(2,index); + st.Step(); + st.Finalize(); + + m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"BoardListRequester::HandleAllData error parsing BoardList XML file : "+message["Identifier"]); + } + + // remove this identityid from request list + RemoveFromRequestList(identityid); + + return true; + +} + +const bool BoardListRequester::HandleGetFailed(FCPMessage &message) +{ + DateTime now; + SQLite3DB::Statement st; + std::vector idparts; + long identityid; + long index; + + now.SetToGMTime(); + StringFunctions::Split(message["Identifier"],"|",idparts); + StringFunctions::Convert(idparts[1],identityid); + StringFunctions::Convert(idparts[2],index); + + // if this is a fatal error - insert index into database so we won't try to download this index again + if(message["Fatal"]=="true") + { + st=m_db->Prepare("INSERT INTO tblBoardListRequests(IdentityID,Day,RequestIndex,Found) VALUES(?,?,?,'false');"); + st.Bind(0,identityid); + st.Bind(1,idparts[4]); + st.Bind(2,index); + st.Step(); + st.Finalize(); + + m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"BoardListRequester::HandleGetFailed fatal error requesting "+message["Identifier"]); + } + + // remove this identityid from request list + RemoveFromRequestList(identityid); + + return true; +} + +void BoardListRequester::Initialize() +{ + std::string tempval=""; + + m_fcpuniquename="BoardListRequester"; + m_maxrequests=0; + + Option::Instance()->Get("MaxBoardListRequests",tempval); + StringFunctions::Convert(tempval,m_maxrequests); + if(m_maxrequests<0) + { + m_maxrequests=0; + m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"Option MaxBoardListRequests is currently set at "+tempval+". It must be 0 or greater."); + } + if(m_maxrequests>100) + { + m_log->WriteLog(LogFile::LOGLEVEL_WARNING,"Option MaxBoardListRequests is currently set at "+tempval+". This value might be incorrectly configured."); + } +} + +void BoardListRequester::PopulateIDList() +{ + int id; + DateTime today; + today.SetToGMTime(); + + 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;"); + st.Step(); + + m_ids.clear(); + + while(st.RowReturned()) + { + st.ResultInt(0,id); + m_ids[id]=false; + st.Step(); + } + +} + +void BoardListRequester::StartRequest(const long &identityid) +{ + DateTime now; + FCPMessage message; + std::string publickey; + std::string indexstr; + int index; + std::string identityidstr; + + SQLite3DB::Statement st=m_db->Prepare("SELECT PublicKey FROM tblIdentity WHERE identityid=?;"); + st.Bind(0,identityid); + st.Step(); + + if(st.RowReturned()) + { + st.ResultText(0,publickey); + + now.SetToGMTime(); + + SQLite3DB::Statement st2=m_db->Prepare("SELECT MAX(RequestIndex) FROM tblBoardListRequests WHERE Day=? AND IdentityID=?;"); + st2.Bind(0,now.Format("%Y-%m-%d")); + st2.Bind(1,identityid); + st2.Step(); + + index=0; + if(st2.RowReturned()) + { + if(st2.ResultNull(0)==false) + { + st2.ResultInt(0,index); + index++; + } + } + st2.Finalize(); + + StringFunctions::Convert(index,indexstr); + StringFunctions::Convert(identityid,identityidstr); + + message.SetName("ClientGet"); + message["URI"]=publickey+m_messagebase+"|"+now.Format("%Y-%m-%d")+"|BoardList|"+indexstr+".xml"; + message["Identifier"]=m_fcpuniquename+"|"+identityidstr+"|"+indexstr+"|"+message["URI"]; + message["ReturnType"]="direct"; + message["MaxSize"]="100000"; // 100 KB + + m_fcp->SendMessage(message); + + m_requesting.push_back(identityid); + + } + st.Finalize(); + + m_ids[identityid]=true; + +} diff --git a/src/freenet/boardlistxml.cpp b/src/freenet/boardlistxml.cpp new file mode 100644 index 0000000..eb9ca8c --- /dev/null +++ b/src/freenet/boardlistxml.cpp @@ -0,0 +1,119 @@ +#include "../../include/freenet/boardlistxml.h" + +#ifdef XMEM + #include +#endif + +BoardListXML::BoardListXML() +{ + Initialize(); +} + +void BoardListXML::AddBoard(const std::string &name, const std::string &description) +{ + if(name!="" && description!="") + { + m_boards.push_back(board(name,description)); + } +} + +const std::string BoardListXML::GetDescription(const long index) +{ + if(index>=0 && index=0 && index::iterator i=m_boards.begin(); i!=m_boards.end(); i++) + { + TiXmlElement *tr=new TiXmlElement("Board"); + tid->LinkEndChild(tr); + tr->LinkEndChild(XMLCreateCDATAElement("Name",(*i).m_name)); + tr->LinkEndChild(XMLCreateCDATAElement("Description",(*i).m_description)); + } + + td.Accept(&tp); + return std::string(tp.CStr()); +} + +void BoardListXML::Initialize() +{ + m_boards.clear(); +} + +const bool BoardListXML::ParseXML(const std::string &xml) +{ + std::string name; + std::string description; + TiXmlDocument td; + td.Parse(xml.c_str()); + + if(!td.Error()) + { + TiXmlText *txt; + TiXmlHandle hnd(&td); + TiXmlNode *node; + + Initialize(); + + node=hnd.FirstChild("BoardList").FirstChild("Board").ToElement(); + while(node) + { + name=""; + description=""; + + TiXmlHandle hnd2(node); + txt=hnd2.FirstChild("Name").FirstChild().ToText(); + if(txt) + { + name=txt->ValueStr(); + } + txt=hnd2.FirstChild("Description").FirstChild().ToText(); + if(txt) + { + description=txt->ValueStr(); + } + + if(name!="" && description!="") + { + m_boards.push_back(board(name,description)); + } + + node=node->NextSibling("Board"); + } + return true; + + } + else + { + return false; + } +} \ No newline at end of file diff --git a/src/freenet/freenetmasterthread.cpp b/src/freenet/freenetmasterthread.cpp index a9f2391..f30cbf1 100644 --- a/src/freenet/freenetmasterthread.cpp +++ b/src/freenet/freenetmasterthread.cpp @@ -16,6 +16,8 @@ #include "../../include/freenet/messageinserter.h" #include "../../include/freenet/messagelistinserter.h" #include "../../include/freenet/periodicdbmaintenance.h" +#include "../../include/freenet/boardlistinserter.h" +#include "../../include/freenet/boardlistrequester.h" //#include #include "../../include/pthreadwrapper/thread.h" @@ -167,6 +169,8 @@ void FreenetMasterThread::RegisterPeriodicProcessor(IPeriodicProcessor *obj) void FreenetMasterThread::Run() { + DateTime lastreceivedmessage; + DateTime now; FCPMessage message; bool done=false; @@ -199,6 +203,10 @@ void FreenetMasterThread::Run() Sleep(1000); } } + else + { + lastreceivedmessage.SetToGMTime(); + } } // fcp is connected else @@ -214,6 +222,7 @@ void FreenetMasterThread::Run() if(message.GetName()!="") { HandleMessage(message); + lastreceivedmessage.SetToGMTime(); } } @@ -223,6 +232,14 @@ void FreenetMasterThread::Run() (*i)->Process(); } + // if we haven't received any messages from the node in 10 minutes, something is wrong + now.SetToGMTime(); + if(lastreceivedmessage<(now-(1.0/144.0))) + { + m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"FreenetMasterThread::Run The Freenet node has not responded in 10 minutes. Trying to reconnect."); + m_fcp.Disconnect(); + } + } // }while(!ZThread::Thread::interrupted() && done==false); }while(!IsCancelled() && done==false); @@ -250,10 +267,12 @@ void FreenetMasterThread::Setup() m_registrables.push_back(new IdentityIntroductionInserter(&m_fcp)); m_registrables.push_back(new TrustListInserter(&m_fcp)); m_registrables.push_back(new TrustListRequester(&m_fcp)); + m_registrables.push_back(new MessageListInserter(&m_fcp)); m_registrables.push_back(new MessageListRequester(&m_fcp)); m_registrables.push_back(new MessageRequester(&m_fcp)); m_registrables.push_back(new MessageInserter(&m_fcp)); - m_registrables.push_back(new MessageListInserter(&m_fcp)); + m_registrables.push_back(new BoardListInserter(&m_fcp)); + m_registrables.push_back(new BoardListRequester(&m_fcp)); m_registrables.push_back(new PeriodicDBMaintenance()); for(std::vector::iterator i=m_registrables.begin(); i!=m_registrables.end(); i++) diff --git a/src/freenet/messagerequester.cpp b/src/freenet/messagerequester.cpp index d58494b..07faaf9 100644 --- a/src/freenet/messagerequester.cpp +++ b/src/freenet/messagerequester.cpp @@ -1,6 +1,8 @@ #include "../../include/freenet/messagerequester.h" #include "../../include/freenet/messagexml.h" +#include + #ifdef XMEM #include #endif @@ -113,6 +115,10 @@ const bool MessageRequester::HandleAllData(FCPMessage &message) if(xml.ParseXML(std::string(data.begin(),data.end()))==true) { std::vector boards=xml.GetBoards(); + if(boards.size()>m_maxboardspermessage) + { + boards.resize(m_maxboardspermessage); + } if(boards.size()<=0) { @@ -124,6 +130,12 @@ const bool MessageRequester::HandleAllData(FCPMessage &message) m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"MessageRequester::HandleAllData Message XML did not contain a reply board! "+message["Identifier"]); return true; } + + // make sure the reply board is on the board list - if not, replace the last element of boardswith the reply board + if(xml.GetReplyBoard()!="" && std::find(boards.begin(),boards.end(),xml.GetReplyBoard())==boards.end() && boards.size()>0) + { + boards[boards.size()-1]=xml.GetReplyBoard(); + } st=m_db->Prepare("INSERT INTO tblMessage(IdentityID,FromName,MessageDate,MessageTime,Subject,MessageUUID,ReplyBoardID,Body) VALUES(?,?,?,?,?,?,?,?);"); st.Bind(0,identityid); @@ -252,6 +264,17 @@ void MessageRequester::Initialize() { m_log->WriteLog(LogFile::LOGLEVEL_WARNING,"Option MaxPeerMessagesPerDay is currently set at "+tempval+". This value might be incorrectly configured. The suggested value is 200."); } + Option::Instance()->Get("MaxBoardsPerMessage",tempval); + StringFunctions::Convert(tempval,m_maxboardspermessage); + if(m_maxboardspermessage<1) + { + m_maxboardspermessage=1; + m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"Option MaxBoardsPerMessage is currently set at "+tempval+". It must be 1 or greater."); + } + if(m_maxboardspermessage>20) + { + m_log->WriteLog(LogFile::LOGLEVEL_WARNING,"Option MaxBoardsPerMessage is currently set at "+tempval+". This value might be incorrectly configured."); + } } void MessageRequester::PopulateIDList() diff --git a/src/freenet/periodicdbmaintenance.cpp b/src/freenet/periodicdbmaintenance.cpp index 0febbbd..01a76c7 100644 --- a/src/freenet/periodicdbmaintenance.cpp +++ b/src/freenet/periodicdbmaintenance.cpp @@ -13,8 +13,9 @@ PeriodicDBMaintenance::PeriodicDBMaintenance() m_check1day.SetToGMTime(); // set back times so they will do their first maintenance soon ( within the next hour ) - stagger so not all run at once - m_check1hour.Add(0,-45); - m_check6hours.Add(0,0,-5); + m_check30mins.Add(0,-5); + m_check1hour.Add(0,-42); + m_check6hours.Add(0,-1,-5); m_check1day.Add(0,0,-23); } @@ -83,7 +84,10 @@ void PeriodicDBMaintenance::Do1DayMaintenance() date.SetToGMTime(); date.Add(0,0,0,-2); m_db->Execute("DELETE FROM tblTrustListInserts WHERE Day<'"+date.Format("%Y-%m-%d")+"';"); - m_db->Execute("DELETE FROM tblTrustListRequests WHERE Day<'"+date.Format("%Y-%m-%d")+"';"); + m_db->Execute("DELETE FROM tblTrustListRequests WHERE Day<'"+date.Format("%Y-%m-%d")+"';"); + + // delete trust lists from identities we aren't trusting anymore + 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')));"); } diff --git a/src/global.cpp b/src/global.cpp index 42a4726..7f63579 100644 --- a/src/global.cpp +++ b/src/global.cpp @@ -49,6 +49,8 @@ void SetupDB() if(major==1 && minor==0) { ConvertDB0100To0101(); + major=1; + minor=1; } } else @@ -56,6 +58,8 @@ void SetupDB() db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,1);"); } + db->Execute("UPDATE tblDBVersion SET Major=1, Minor=2;"); + db->Execute("CREATE TABLE IF NOT EXISTS tblOption(\ Option TEXT UNIQUE,\ OptionValue TEXT NOT NULL,\ @@ -168,10 +172,10 @@ void SetupDB() DateAdded DATETIME\ );"); - db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('fms','Freenet Message System','2007-12-01');"); - db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('freenet','Discussion about Freenet','2007-12-01');"); - db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('public','Public discussion','2007-12-01');"); - db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('test','Test board','2007-12-01');"); + db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('fms','Freenet Message System','2007-12-01 12:00:00');"); + db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('freenet','Discussion about Freenet','2007-12-01 12:00:00');"); + db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('public','Public discussion','2007-12-01 12:00:00');"); + db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('test','Test board','2007-12-01 12:00:00');"); db->Execute("CREATE TABLE IF NOT EXISTS tblMessage(\ MessageID INTEGER PRIMARY KEY,\ @@ -233,6 +237,20 @@ void SetupDB() ModifyLocalTrustListTrust INTEGER\ );"); + db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListInserts(\ + LocalIdentityID INTEGER,\ + Day DATE,\ + InsertIndex INTEGER,\ + Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\ + );"); + + db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListRequests(\ + IdentityID INTEGER,\ + Day DATE,\ + RequestIndex INTEGER,\ + Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\ + );"); + // MessageInserter will insert a record into this temp table which the MessageListInserter will query for and insert a MessageList when needed db->Execute("CREATE TEMPORARY TABLE IF NOT EXISTS tmpMessageListInsert(\ LocalIdentityID INTEGER,\ @@ -535,6 +553,18 @@ void SetupDefaultOptions() st.Step(); st.Reset(); + st.Bind(0,"MaxBoardListRequests"); + st.Bind(1,"5"); + st.Bind(2,"The maximum number of concurrent requests for new Board Lists. Set to 0 to disable."); + st.Step(); + st.Reset(); + + st.Bind(0,"MaxBoardsPerMessage"); + st.Bind(1,"8"); + st.Bind(2,"The maximum number of boards a received message may be sent to. Boards over this limit will be ignored."); + st.Step(); + st.Reset(); + } void SetupLogFile() diff --git a/src/http/httpthread.cpp b/src/http/httpthread.cpp index a1f51c7..5bb9988 100644 --- a/src/http/httpthread.cpp +++ b/src/http/httpthread.cpp @@ -11,6 +11,7 @@ #include "../../include/http/pages/peertrustpage.h" #include "../../include/http/pages/controlboardpage.h" #include "../../include/http/pages/peerdetailspage.h" +#include "../../include/http/pages/peermaintenancepage.h" #include @@ -54,6 +55,7 @@ HTTPThread::HTTPThread() m_pagehandlers.push_back(new PeerTrustPage(templatestr)); m_pagehandlers.push_back(new ControlBoardPage(templatestr)); m_pagehandlers.push_back(new PeerDetailsPage(templatestr)); + m_pagehandlers.push_back(new PeerMaintenancePage(templatestr)); // homepage must be last - catch all page handler m_pagehandlers.push_back(new HomePage(templatestr)); diff --git a/src/http/identityexportxml.cpp b/src/http/identityexportxml.cpp index b2609bf..1f87e85 100644 --- a/src/http/identityexportxml.cpp +++ b/src/http/identityexportxml.cpp @@ -182,4 +182,4 @@ const bool IdentityExportXML::ParseXML(const std::string &xml) { return false; } -} \ No newline at end of file +} diff --git a/src/http/pages/announceidentitypage.cpp b/src/http/pages/announceidentitypage.cpp index b67f16f..81fad96 100644 --- a/src/http/pages/announceidentitypage.cpp +++ b/src/http/pages/announceidentitypage.cpp @@ -46,6 +46,8 @@ const std::string AnnounceIdentityPage::GeneratePage(const std::string &method, std::string lastid=""; std::string thisid=""; std::string day=""; + int requestindex=0; + bool willshow=false; if(queryvars.find("formaction")!=queryvars.end() && (*queryvars.find("formaction")).second=="announce") { @@ -90,11 +92,10 @@ const std::string AnnounceIdentityPage::GeneratePage(const std::string &method, content+="
Type the answers of a few puzzles. The puzzles are case sensitive."; content+=""; - //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 date.SetToGMTime(); date.Add(0,0,0,-1); - 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;"); + 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;"); st.Step(); if(st.RowReturned()==false) @@ -107,8 +108,25 @@ const std::string AnnounceIdentityPage::GeneratePage(const std::string &method, st.ResultText(0,uuid); st.ResultText(1,day); st.ResultText(2,thisid); + st.ResultInt(3,requestindex); + + // 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 + // get the last index # we are inserting this day from this identity + // 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 + willshow=true; + 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;"); + st2.Step(); + if(st2.RowReturned()==true) + { + int index=0; + st2.ResultInt(0,index); + if(index>=requestindex) + { + willshow=false; + } + } - if(thisid!=lastid) + if(willshow && thisid!=lastid) { StringFunctions::Convert(shown,countstr); if(shown>0 && shown%4==0) @@ -121,7 +139,7 @@ const std::string AnnounceIdentityPage::GeneratePage(const std::string &method, content+=""; content+=""; content+="\r\n"; - thisid=lastid; + lastid=thisid; shown++; } diff --git a/src/http/pages/controlboardpage.cpp b/src/http/pages/controlboardpage.cpp index c50a37f..c685ca4 100644 --- a/src/http/pages/controlboardpage.cpp +++ b/src/http/pages/controlboardpage.cpp @@ -68,7 +68,7 @@ const std::string ControlBoardPage::GeneratePage(const std::string &method, cons content+="

Control Boards

"; content+="

"; - 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."; + 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."; content+="

"; 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;"); diff --git a/src/http/pages/localidentitiespage.cpp b/src/http/pages/localidentitiespage.cpp index 84c28b3..95649d7 100644 --- a/src/http/pages/localidentitiespage.cpp +++ b/src/http/pages/localidentitiespage.cpp @@ -40,14 +40,16 @@ const std::string LocalIdentitiesPage::GeneratePage(const std::string &method, c std::vector ids; std::vector singleuse; std::vector publishtrustlist; + std::vector publishboardlist; CreateArgArray(queryvars,"chkidentityid",ids); CreateArgArray(queryvars,"singleuse",singleuse); CreateArgArray(queryvars,"publishtrustlist",publishtrustlist); + CreateArgArray(queryvars,"publishboardlist",publishboardlist); if((*queryvars.find("formaction")).second=="update") { - SQLite3DB::Statement update=m_db->Prepare("UPDATE tblLocalIdentity SET SingleUse=?, PublishTrustList=? WHERE LocalIdentityID=?;"); + SQLite3DB::Statement update=m_db->Prepare("UPDATE tblLocalIdentity SET SingleUse=?, PublishTrustList=?, PublishBoardList=? WHERE LocalIdentityID=?;"); for(int i=0; i"; content+=""; - content+=""; + content+="
NameSingle UsePublish Trust ListAnnounced? *
"; 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;"); st.Step(); @@ -191,18 +196,20 @@ const std::string LocalIdentitiesPage::GeneratePage(const std::string &method, c while(st.RowReturned()) { StringFunctions::Convert(count,countstr); - std::string id; - std::string name; - std::string publickey; - std::string publishtrustlist; - std::string singleuse; - std::string keypart; + std::string id=""; + std::string name=""; + std::string publickey=""; + std::string publishtrustlist=""; + std::string singleuse=""; + std::string keypart=""; + std::string publishboardlist=""; st.ResultText(0,id); st.ResultText(1,name); st.ResultText(2,publickey); st.ResultText(3,publishtrustlist); st.ResultText(4,singleuse); + st.ResultText(5,publishboardlist); if(publickey.size()>8) { @@ -214,6 +221,7 @@ const std::string LocalIdentitiesPage::GeneratePage(const std::string &method, c content+=""; content+=""; content+=""; + content+=""; if(st.ResultNull(6)) { content+=""; @@ -227,7 +235,7 @@ const std::string LocalIdentitiesPage::GeneratePage(const std::string &method, c count++; } - content+=""; + content+=""; content+="
NameSingle UsePublish Trust ListPublish Board ListAnnounced? *
"+SanitizeOutput(name+keypart)+"..."+CreateTrueFalseDropDown("singleuse["+countstr+"]",singleuse)+""+CreateTrueFalseDropDown("publishtrustlist["+countstr+"]",publishtrustlist)+""+CreateTrueFalseDropDown("publishboardlist["+countstr+"]",publishboardlist)+"No
"; content+="

* An identity is considered successfully announced when you have downloaded a trust list from someone that contains the identity.

"; diff --git a/src/http/pages/peermaintenancepage.cpp b/src/http/pages/peermaintenancepage.cpp new file mode 100644 index 0000000..f794600 --- /dev/null +++ b/src/http/pages/peermaintenancepage.cpp @@ -0,0 +1,150 @@ +#include "../../../include/http/pages/peermaintenancepage.h" +#include "../../../include/stringfunctions.h" +#include "../../../include/datetime.h" + +#ifdef XMEM + #include +#endif + +const std::string PeerMaintenancePage::GeneratePage(const std::string &method, const std::map &queryvars) +{ + std::string content=""; + SQLite3DB::Statement st; + std::string tempval; + DateTime date; + + if(queryvars.find("formaction")!=queryvars.end()) + { + if((*queryvars.find("formaction")).second=="removenotseen") + { + m_db->Execute("DELETE FROM tblIdentity WHERE LastSeen IS NULL;"); + } + else if((*queryvars.find("formaction")).second=="removelastseen20") + { + date.SetToGMTime(); + date.Add(0,0,0,-20); + st=m_db->Prepare("DELETE FROM tblIdentity WHERE LastSeenExecute("DELETE FROM tblIdentity WHERE IdentityID NOT IN (SELECT IdentityID FROM tblMessage GROUP BY IdentityID);"); + } + else if((*queryvars.find("formaction")).second=="removelastseenneversent20") + { + date.SetToGMTime(); + date.Add(0,0,0,-20); + st=m_db->Prepare("DELETE FROM tblIdentity WHERE IdentityID NOT IN (SELECT IdentityID FROM tblMessage GROUP BY IdentityID) AND LastSeenPrepare("DELETE FROM tblIdentity WHERE IdentityID NOT IN (SELECT IdentityID FROM tblMessage GROUP BY IdentityID) AND LastSeenPeer Maintenance"; + content+="

Removing a peer will not remove the messages they sent, but will remove everything else about that peer, including their trust levels.

"; + content+=""; + content+=""; + + content+=""; + st=m_db->Prepare("SELECT COUNT(*) FROM tblIdentity;"); + st.Step(); + st.ResultText(0,tempval); + content+=""; + content+=""; + content+=""; + + content+=""; + st=m_db->Prepare("SELECT COUNT(*) FROM tblIdentity WHERE LastSeen IS NULL;"); + st.Step(); + st.ResultText(0,tempval); + content+=""; + content+=""; + content+=""; + content+=""; + + date.SetToGMTime(); + date.Add(0,0,0,-20); + st=m_db->Prepare("SELECT COUNT(*) FROM tblIdentity WHERE LastSeen"; + content+=""; + content+=""; + content+=""; + content+=""; + + st=m_db->Prepare("SELECT COUNT(*) FROM tblIdentity LEFT JOIN tblMessage ON tblIdentity.IdentityID=tblMessage.IdentityID WHERE tblMessage.IdentityID IS NULL;"); + st.Step(); + st.ResultText(0,tempval); + content+=""; + content+=""; + content+=""; + content+=""; + content+=""; + + date.SetToGMTime(); + date.Add(0,0,0,-20); + st=m_db->Prepare("SELECT COUNT(*) FROM tblIdentity LEFT JOIN tblMessage ON tblIdentity.IdentityID=tblMessage.IdentityID WHERE tblMessage.IdentityID IS NULL AND tblIdentity.LastSeen"; + content+=""; + content+=""; + content+=""; + content+=""; + + content+=""; + content+=""; + content+=""; + content+=""; + content+=""; + + content+="
Stats
"+tempval+"known peers
"+tempval+"never seen"; + content+="
"; + content+=""; + content+=""; + content+="
"; + content+="
"+tempval+"last seen more than 20 days ago"; + content+="
"; + content+=""; + content+=""; + content+="
"; + content+="
"+tempval+"never sent a message"; + content+="
"; + content+=""; + content+=""; + content+="
"; + content+="
"+tempval+"last seen more than 20 days ago and never sent a message"; + content+="
"; + content+=""; + content+=""; + content+="
"; + content+="
last seen days ago
"; + + return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"+StringFunctions::Replace(m_template,"[CONTENT]",content); +} + +const bool PeerMaintenancePage::WillHandleURI(const std::string &uri) +{ + if(uri.find("peermaintenance.")!=std::string::npos) + { + return true; + } + else + { + return false; + } +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 17d6b67..9fefa8f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,6 +18,7 @@ int main(int argc, char *argv[]) { + bool daemon=false; #ifdef XMEM xmem_disable_print(); @@ -30,6 +31,7 @@ int main(int argc, char *argv[]) if(argv[1] && strncmp(argv[1],"-d",2)==0) { Daemonize(); + daemon=true; } #else if(argv[1] && strncmp(argv[1],"-i",2)==0) @@ -91,15 +93,18 @@ int main(int argc, char *argv[]) signal(SIGBREAK,SigHandler); #endif - std::cout << "FMS Running in console mode." << std::endl; - std::cout << "Use the administration pages, or CTRL+C to exit" << std::endl << std::endl; - std::cout << "Available command line arguments:" << std::endl; -#ifdef _WIN32 - std::cout << "-i\tinstall service" << std::endl; - std::cout << "-u\tuninstall service" << std::endl; -#else - std::cout << "-d\trun as daemon" << std::endl; -#endif + if(daemon==false) + { + std::cout << "FMS Running in console mode." << std::endl; + std::cout << "Use the administration pages, or CTRL+C to exit" << std::endl << std::endl; + std::cout << "Available command line arguments:" << std::endl; + #ifdef _WIN32 + std::cout << "-i\tinstall service" << std::endl; + std::cout << "-u\tuninstall service" << std::endl; + #else + std::cout << "-d\trun as daemon" << std::endl; + #endif + } MainFunction(); diff --git a/src/pthreadwrapper/thread.cpp b/src/pthreadwrapper/thread.cpp index d08cf33..07cb689 100644 --- a/src/pthreadwrapper/thread.cpp +++ b/src/pthreadwrapper/thread.cpp @@ -27,6 +27,9 @@ void Sleep(const long ms) pthread_mutex_lock(&m); pthread_cond_timedwait(&c,&m,&t); pthread_mutex_unlock(&m); + + pthread_cond_destroy(&c); + pthread_mutex_destroy(&m); } Thread::Thread() @@ -35,6 +38,7 @@ Thread::Thread() m_cancelled=false; m_runnable=0; m_threadnum=0; + m_threadcleaned=true; } Thread::Thread(Runnable *runnable) @@ -43,6 +47,7 @@ Thread::Thread(Runnable *runnable) m_cancelled=false; m_runnable=runnable; m_threadnum=0; + m_threadcleaned=true; if(m_runnable) { m_runnable->m_thread=this; @@ -54,6 +59,10 @@ Thread::~Thread() { Cancel(); Join(); + if(m_threadcleaned==false) + { + pthread_detach(m_thread); + } if(m_runnable) { delete m_runnable; @@ -85,6 +94,7 @@ void Thread::Join() if(m_running) { pthread_join(m_thread,NULL); + m_threadcleaned=true; } } @@ -108,12 +118,16 @@ void Thread::Sleep(const long ms) pthread_mutex_lock(&m); pthread_cond_timedwait(&c,&m,&t); pthread_mutex_unlock(&m); + + pthread_cond_destroy(&c); + pthread_mutex_destroy(&m); } } void Thread::Start() { m_running=true; + m_threadcleaned=false; m_threadnum=pthread_create(&m_thread,NULL,Thread::EntryPoint,this); } diff --git a/template.htm b/template.htm index e064576..2ed3403 100644 --- a/template.htm +++ b/template.htm @@ -219,6 +219,7 @@ form { display:inline; }
  • Local Identities
  • Announce Identity
  • Add Peer
  • +
  • Peer Maintenance
  • Peer Trust
  • Control Boards