version 0.1.11
authorSomeDude <SomeDude@NuBL7aaJ6Cn4fB7GXFb9Zfi8w1FhPyW3oKgU9TweZMw>
Sat, 16 Feb 2008 08:13:00 +0000 (09:13 +0100)
committerDavid ‘Bombe’ Roden <bombe@freenetproject.org>
Sat, 16 Feb 2008 08:13:00 +0000 (09:13 +0100)
34 files changed:
CMakeLists.txt
include/db/sqlite3db/sqlite3db.h
include/freenet/boardlistinserter.h [new file with mode: 0644]
include/freenet/boardlistrequester.h [new file with mode: 0644]
include/freenet/boardlistxml.h [new file with mode: 0644]
include/freenet/ifreenetregistrable.h
include/freenet/iindexinserter.h
include/freenet/iindexrequester.h
include/freenet/messagerequester.h
include/freenet/messagexml.h
include/global.h
include/http/pages/peermaintenancepage.h [new file with mode: 0644]
include/ifmsxmldocument.h
include/logfile.h
include/pthreadwrapper.h
include/pthreadwrapper/noncopyable.h
include/pthreadwrapper/thread.h
src/db/sqlite3db.cpp
src/freenet/boardlistinserter.cpp [new file with mode: 0644]
src/freenet/boardlistrequester.cpp [new file with mode: 0644]
src/freenet/boardlistxml.cpp [new file with mode: 0644]
src/freenet/freenetmasterthread.cpp
src/freenet/messagerequester.cpp
src/freenet/periodicdbmaintenance.cpp
src/global.cpp
src/http/httpthread.cpp
src/http/identityexportxml.cpp
src/http/pages/announceidentitypage.cpp
src/http/pages/controlboardpage.cpp
src/http/pages/localidentitiespage.cpp
src/http/pages/peermaintenancepage.cpp [new file with mode: 0644]
src/main.cpp
src/pthreadwrapper/thread.cpp
template.htm

index 024be6a..994d5e1 100644 (file)
@@ -20,6 +20,9 @@ src/uuidgenerator.cpp
 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
@@ -58,6 +61,7 @@ src/http/pages/homepage.cpp
 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
index f0aac60..b41f3b8 100644 (file)
@@ -5,11 +5,11 @@
 //#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
diff --git a/include/freenet/boardlistinserter.h b/include/freenet/boardlistinserter.h
new file mode 100644 (file)
index 0000000..54b5e80
--- /dev/null
@@ -0,0 +1,20 @@
+#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
diff --git a/include/freenet/boardlistrequester.h b/include/freenet/boardlistrequester.h
new file mode 100644 (file)
index 0000000..a920e60
--- /dev/null
@@ -0,0 +1,20 @@
+#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
diff --git a/include/freenet/boardlistxml.h b/include/freenet/boardlistxml.h
new file mode 100644 (file)
index 0000000..53460df
--- /dev/null
@@ -0,0 +1,34 @@
+#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
index 78e4508..955e4ea 100644 (file)
@@ -9,6 +9,8 @@ class FreenetMasterThread;
 class IFreenetRegistrable\r
 {\r
 public:\r
+       IFreenetRegistrable()                   {}\r
+       virtual ~IFreenetRegistrable()  {}\r
 \r
        virtual void RegisterWithThread(FreenetMasterThread *thread)=0;\r
        \r
index fc1a6bc..050aa3d 100644 (file)
 #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
index 7f02763..35c16c1 100644 (file)
 #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
index c4cdb92..353de7e 100644 (file)
@@ -21,6 +21,7 @@ private:
 \r
        long m_maxdaysbackward;\r
        long m_maxpeermessages;\r
+       long m_maxboardspermessage;\r
        \r
 };\r
 \r
index 04f97e2..7daa842 100644 (file)
@@ -1,10 +1,11 @@
 #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
index cb75d5a..be6dec6 100644 (file)
@@ -5,7 +5,7 @@
 //#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
diff --git a/include/http/pages/peermaintenancepage.h b/include/http/pages/peermaintenancepage.h
new file mode 100644 (file)
index 0000000..80f74f1
--- /dev/null
@@ -0,0 +1,18 @@
+#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
index f444af5..8e04c3c 100644 (file)
@@ -6,6 +6,10 @@
 #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
index 3008caa..92ab17f 100644 (file)
@@ -3,9 +3,9 @@
 \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
index 76a9f09..5bad5b5 100644 (file)
@@ -24,7 +24,7 @@ namespace PThread
 #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
index e6ebb8a..9e61701 100644 (file)
@@ -7,8 +7,8 @@ namespace PThread
 class NonCopyable\r
 {\r
 protected:\r
-       NonCopyable()   {}\r
-       ~NonCopyable()  {}\r
+       NonCopyable()                   {}\r
+       virtual ~NonCopyable()  {}\r
 \r
 private:\r
        // restrict copy and assignment\r
index 6e51f73..7b5f386 100644 (file)
@@ -35,6 +35,7 @@ private:
        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
index 1b63715..edf2e8b 100644 (file)
@@ -129,7 +129,7 @@ const bool DB::IsOpen()
 \r
 const bool DB::Open(const std::string &filename)\r
 {\r
-       if(IsOpen()==false)\r
+       if(IsOpen()==true)\r
        {\r
                Close();        \r
        }\r
diff --git a/src/freenet/boardlistinserter.cpp b/src/freenet/boardlistinserter.cpp
new file mode 100644 (file)
index 0000000..92ed0b7
--- /dev/null
@@ -0,0 +1,181 @@
+#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
diff --git a/src/freenet/boardlistrequester.cpp b/src/freenet/boardlistrequester.cpp
new file mode 100644 (file)
index 0000000..6b52a46
--- /dev/null
@@ -0,0 +1,243 @@
+#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
diff --git a/src/freenet/boardlistxml.cpp b/src/freenet/boardlistxml.cpp
new file mode 100644 (file)
index 0000000..eb9ca8c
--- /dev/null
@@ -0,0 +1,119 @@
+#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
index a9f2391..f30cbf1 100644 (file)
@@ -16,6 +16,8 @@
 #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
@@ -167,6 +169,8 @@ void FreenetMasterThread::RegisterPeriodicProcessor(IPeriodicProcessor *obj)
 void FreenetMasterThread::Run()\r
 {\r
 \r
+       DateTime lastreceivedmessage;\r
+       DateTime now;\r
        FCPMessage message;\r
        bool done=false;\r
 \r
@@ -199,6 +203,10 @@ void FreenetMasterThread::Run()
                                        Sleep(1000);\r
                                }\r
                        }\r
+                       else\r
+                       {\r
+                               lastreceivedmessage.SetToGMTime();\r
+                       }\r
                }\r
                // fcp is connected\r
                else\r
@@ -214,6 +222,7 @@ void FreenetMasterThread::Run()
                                if(message.GetName()!="")\r
                                {\r
                                        HandleMessage(message);\r
+                                       lastreceivedmessage.SetToGMTime();\r
                                }\r
                        }\r
 \r
@@ -223,6 +232,14 @@ void FreenetMasterThread::Run()
                                (*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
@@ -250,10 +267,12 @@ void FreenetMasterThread::Setup()
        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
index d58494b..07faaf9 100644 (file)
@@ -1,6 +1,8 @@
 #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
@@ -113,6 +115,10 @@ const bool MessageRequester::HandleAllData(FCPMessage &message)
        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
@@ -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"]);\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
@@ -252,6 +264,17 @@ void MessageRequester::Initialize()
        {\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
index 0febbbd..01a76c7 100644 (file)
@@ -13,8 +13,9 @@ PeriodicDBMaintenance::PeriodicDBMaintenance()
        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
@@ -83,7 +84,10 @@ void PeriodicDBMaintenance::Do1DayMaintenance()
        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
index 42a4726..7f63579 100644 (file)
@@ -49,6 +49,8 @@ void SetupDB()
                if(major==1 && minor==0)\r
                {\r
                        ConvertDB0100To0101();\r
+                       major=1;\r
+                       minor=1;\r
                }\r
        }\r
        else\r
@@ -56,6 +58,8 @@ void SetupDB()
                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
@@ -168,10 +172,10 @@ void SetupDB()
                                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
@@ -233,6 +237,20 @@ void SetupDB()
                                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
@@ -535,6 +553,18 @@ void SetupDefaultOptions()
        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
index a1f51c7..5bb9988 100644 (file)
@@ -11,6 +11,7 @@
 #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
@@ -54,6 +55,7 @@ HTTPThread::HTTPThread()
        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
index b2609bf..1f87e85 100644 (file)
@@ -182,4 +182,4 @@ const bool IdentityExportXML::ParseXML(const std::string &xml)
        {\r
                return false;\r
        }\r
-}
\ No newline at end of file
+}\r
index b67f16f..81fad96 100644 (file)
@@ -46,6 +46,8 @@ const std::string AnnounceIdentityPage::GeneratePage(const std::string &method,
        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
@@ -90,11 +92,10 @@ const std::string AnnounceIdentityPage::GeneratePage(const std::string &method,
        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
@@ -107,8 +108,25 @@ const std::string AnnounceIdentityPage::GeneratePage(const std::string &method,
                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
@@ -121,7 +139,7 @@ const std::string AnnounceIdentityPage::GeneratePage(const std::string &method,
                        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
index c50a37f..c685ca4 100644 (file)
@@ -68,7 +68,7 @@ const std::string ControlBoardPage::GeneratePage(const std::string &method, cons
 \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
index 84c28b3..95649d7 100644 (file)
@@ -40,14 +40,16 @@ const std::string LocalIdentitiesPage::GeneratePage(const std::string &method, c
                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
@@ -55,7 +57,8 @@ const std::string LocalIdentitiesPage::GeneratePage(const std::string &method, c
                                        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
@@ -180,9 +183,11 @@ const std::string LocalIdentitiesPage::GeneratePage(const std::string &method, c
        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
@@ -191,18 +196,20 @@ const std::string LocalIdentitiesPage::GeneratePage(const std::string &method, c
        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
@@ -214,6 +221,7 @@ const std::string LocalIdentitiesPage::GeneratePage(const std::string &method, c
                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
@@ -227,7 +235,7 @@ const std::string LocalIdentitiesPage::GeneratePage(const std::string &method, c
                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
diff --git a/src/http/pages/peermaintenancepage.cpp b/src/http/pages/peermaintenancepage.cpp
new file mode 100644 (file)
index 0000000..f794600
--- /dev/null
@@ -0,0 +1,150 @@
+#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
index 17d6b67..9fefa8f 100644 (file)
@@ -18,6 +18,7 @@
 \r
 int main(int argc, char *argv[])\r
 {\r
+       bool daemon=false;\r
 \r
        #ifdef XMEM\r
                xmem_disable_print();\r
@@ -30,6 +31,7 @@ int main(int argc, char *argv[])
                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
@@ -91,15 +93,18 @@ int main(int argc, char *argv[])
        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
index d08cf33..07cb689 100644 (file)
@@ -27,6 +27,9 @@ void Sleep(const long ms)
        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
@@ -35,6 +38,7 @@ Thread::Thread()
        m_cancelled=false;\r
        m_runnable=0;\r
        m_threadnum=0;\r
+       m_threadcleaned=true;\r
 }\r
 \r
 Thread::Thread(Runnable *runnable)\r
@@ -43,6 +47,7 @@ Thread::Thread(Runnable *runnable)
        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
@@ -54,6 +59,10 @@ Thread::~Thread()
 {\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
@@ -85,6 +94,7 @@ void Thread::Join()
        if(m_running)\r
        {\r
                pthread_join(m_thread,NULL);\r
+               m_threadcleaned=true;\r
        }\r
 }\r
 \r
@@ -108,12 +118,16 @@ void Thread::Sleep(const long ms)
                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
index e064576..2ed3403 100644 (file)
@@ -219,6 +219,7 @@ form        { display:inline; }
                        <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