version 0.1.12
authorSomeDude <SomeDude@NuBL7aaJ6Cn4fB7GXFb9Zfi8w1FhPyW3oKgU9TweZMw>
Tue, 19 Feb 2008 17:28:00 +0000 (18:28 +0100)
committerDavid ‘Bombe’ Roden <bombe@freenetproject.org>
Tue, 19 Feb 2008 17:28:00 +0000 (18:28 +0100)
22 files changed:
CMakeLists.txt
include/db/sqlite3db/sqlite3recordset.h
include/global.h
include/http/pages/execquerypage.h [new file with mode: 0644]
include/http/pages/peertrustpage.h
include/message.h
src/freenet/boardlistxml.cpp
src/freenet/introductionpuzzleinserter.cpp
src/freenet/introductionpuzzlerequester.cpp
src/freenet/introductionpuzzlexml.cpp
src/freenet/messageinserter.cpp
src/freenet/messagerequester.cpp
src/freenet/messagexml.cpp
src/freenet/periodicdbmaintenance.cpp
src/global.cpp
src/http/httpthread.cpp
src/http/pages/execquerypage.cpp [new file with mode: 0644]
src/http/pages/peermaintenancepage.cpp
src/http/pages/peertrustpage.cpp
src/message.cpp
src/nntp/nntpconnection.cpp
template.htm

index 994d5e1..455a73d 100644 (file)
@@ -57,6 +57,7 @@ src/http/pages/addpeerpage.cpp
 src/http/pages/announceidentitypage.cpp\r
 src/http/pages/controlboardpage.cpp\r
 src/http/pages/createidentitypage.cpp\r
+src/http/pages/execquerypage.cpp\r
 src/http/pages/homepage.cpp\r
 src/http/pages/localidentitiespage.cpp\r
 src/http/pages/optionspage.cpp\r
index 69ad5e5..33d56e2 100644 (file)
@@ -19,6 +19,7 @@ public:
        virtual const int Count() { return m_rows; }\r
        virtual const bool AtBeginning() { return m_currentrow==0; }\r
        virtual const bool AtEnd() { return m_currentrow>=m_rows; }\r
+       virtual const int Cols() { return m_cols; }\r
 \r
        virtual const bool Next() { if(m_currentrow<m_rows) { m_currentrow++; return true; } else { return false; } }\r
        virtual const bool Previous() { if(m_currentrow-1>=0) { m_currentrow--; return true; } else { return false; } }\r
index be6dec6..d9a82e0 100644 (file)
@@ -5,7 +5,7 @@
 //#include <zthread/Thread.h>\r
 #include "pthreadwrapper/thread.h"\r
 \r
-#define FMS_VERSION    "0.1.11"\r
+#define FMS_VERSION    "0.1.12"\r
 \r
 // opens database and creates tables and initial inserts if necessary\r
 void SetupDB();\r
diff --git a/include/http/pages/execquerypage.h b/include/http/pages/execquerypage.h
new file mode 100644 (file)
index 0000000..4679ec2
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _execquerypage_\r
+#define _execquerypage_\r
+\r
+#include "../ipagehandler.h"\r
+#include "../../idatabase.h"\r
+\r
+class ExecQueryPage:public IPageHandler,public IDatabase\r
+{\r
+public:\r
+       ExecQueryPage(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 // _execquerypage_\r
index eb780e0..8f91446 100644 (file)
@@ -14,6 +14,8 @@ private:
        const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
 \r
        const std::string GetClassString(const std::string &trustlevel);\r
+       const std::string BuildQueryString(const long startrow, const std::string &namesearch, const std::string &sortby, const std::string &sortorder);\r
+       const std::string ReverseSort(const std::string &sortname, const std::string &currentsortby, const std::string &currentsortorder);\r
 \r
 };\r
 \r
index f30f33b..74c25d4 100644 (file)
@@ -53,6 +53,7 @@ private:
        void Initialize();\r
        // checks vector of boards for any special administration boards - if it finds one true is returned, otherwise false\r
        const bool CheckForAdministrationBoard(const std::vector<std::string> &boards);\r
+       void HandleChangeTrust();\r
 \r
        long m_messageid;\r
        std::string m_messageuuid;\r
@@ -63,6 +64,7 @@ private:
        std::string m_fromname;\r
        std::vector<std::string> m_boards;\r
        std::map<long,std::string> m_inreplyto;\r
+       long m_changemessagetrustonreply;\r
 \r
 };\r
 \r
index eb9ca8c..4307c71 100644 (file)
@@ -116,4 +116,4 @@ const bool BoardListXML::ParseXML(const std::string &xml)
        {\r
                return false;\r
        }\r
-}
\ No newline at end of file
+}\r
index fef42f1..66635bb 100644 (file)
@@ -201,7 +201,9 @@ void IntroductionPuzzleInserter::StartInsert(const long localidentityid)
        FCPMessage message;\r
        std::string xmldata;\r
        std::string xmldatasizestr;\r
-       std::string privatekey;\r
+       std::string privatekey="";\r
+       std::string publickey="";\r
+       std::string keypart="";\r
 \r
        StringFunctions::Convert(localidentityid,idstring);\r
        now.SetToGMTime();\r
@@ -217,10 +219,19 @@ void IntroductionPuzzleInserter::StartInsert(const long localidentityid)
        }\r
        StringFunctions::Convert(index,indexstr);\r
 \r
-       SQLite3DB::Recordset rs2=m_db->Query("SELECT PrivateKey FROM tblLocalIdentity WHERE LocalIdentityID="+idstring+";");\r
+       SQLite3DB::Recordset rs2=m_db->Query("SELECT PrivateKey,PublicKey FROM tblLocalIdentity WHERE LocalIdentityID="+idstring+";");\r
        if(rs2.Empty()==false && rs2.GetField(0)!=NULL)\r
        {\r
                privatekey=rs2.GetField(0);\r
+               if(rs2.GetField(1))\r
+               {\r
+                       publickey=rs2.GetField(1);\r
+               }\r
+               if(publickey.size()>=50)\r
+               {\r
+                       // remove - and ~\r
+                       keypart=StringFunctions::Replace(StringFunctions::Replace(publickey.substr(4,43),"-",""),"~","");\r
+               }\r
        }\r
 \r
        Option::Instance()->Get("MessageBase",messagebase);\r
@@ -228,7 +239,7 @@ void IntroductionPuzzleInserter::StartInsert(const long localidentityid)
        GenerateCaptcha(encodedpuzzle,solutionstring);\r
 \r
        xml.SetType("captcha");\r
-       xml.SetUUID(uuid.Generate());\r
+       xml.SetUUID(uuid.Generate()+"@"+keypart);\r
        xml.SetPuzzleData(encodedpuzzle);\r
        xml.SetMimeType("image/bmp");\r
 \r
index 830bdb3..03d4a41 100644 (file)
@@ -64,6 +64,9 @@ const bool IntroductionPuzzleRequester::HandleAllData(FCPMessage &message)
        // parse file into xml and update the database\r
        if(xml.ParseXML(std::string(data.begin(),data.end()))==true)\r
        {\r
+\r
+               // TODO - check if last part of UUID matches public key of identity who inserted it\r
+\r
                st=m_db->Prepare("INSERT INTO tblIntroductionPuzzleRequests(IdentityID,Day,RequestIndex,Found,UUID,Type,MimeType,PuzzleData) VALUES(?,?,?,?,?,?,?,?);");\r
                st.Bind(0,identityid);\r
                st.Bind(1,idparts[4]);\r
index 348b7ca..1dea038 100644 (file)
@@ -22,7 +22,7 @@ std::string IntroductionPuzzleXML::GetXML()
 \r
        tid->LinkEndChild(XMLCreateTextElement("Type",m_type));\r
 \r
-       tid->LinkEndChild(XMLCreateTextElement("UUID",m_uuid));\r
+       tid->LinkEndChild(XMLCreateCDATAElement("UUID",m_uuid));\r
 \r
        tid->LinkEndChild(XMLCreateTextElement("MimeType",m_mimetype));\r
 \r
index cc7cfd5..3d5af9a 100644 (file)
@@ -1,4 +1,5 @@
 #include "../../include/freenet/messageinserter.h"\r
+#include "../../include/freenet/messagexml.h"\r
 \r
 MessageInserter::MessageInserter()\r
 {\r
@@ -41,7 +42,7 @@ const bool MessageInserter::HandlePutFailed(FCPMessage &message)
        {\r
                SQLite3DB::Statement st=m_db->Prepare("INSERT INTO tblMessageInserts(LocalIdentityID,Day,InsertIndex,Inserted) VALUES(?,?,?,'true');");\r
                st.Bind(0,localidentityid);\r
-               st.Bind(1,idparts[5]);\r
+               st.Bind(1,idparts[6]);\r
                st.Bind(2,index);\r
                st.Step();\r
        }\r
@@ -53,6 +54,7 @@ const bool MessageInserter::HandlePutFailed(FCPMessage &message)
 \r
 const bool MessageInserter::HandlePutSuccessful(FCPMessage &message)\r
 {\r
+       MessageXML xml;\r
        DateTime date;\r
        int localidentityid;\r
        int index;\r
@@ -62,7 +64,7 @@ const bool MessageInserter::HandlePutSuccessful(FCPMessage &message)
        StringFunctions::Convert(idparts[2],localidentityid);\r
 \r
        SQLite3DB::Statement st=m_db->Prepare("UPDATE tblMessageInserts SET Day=?, InsertIndex=?, Inserted='true' WHERE MessageUUID=?;");\r
-       st.Bind(0,idparts[5]);\r
+       st.Bind(0,idparts[6]);\r
        st.Bind(1,index);\r
        st.Bind(2,idparts[1]);\r
        st.Step();\r
@@ -74,6 +76,24 @@ const bool MessageInserter::HandlePutSuccessful(FCPMessage &message)
        st.Bind(1,date.Format("%Y-%m-%d"));\r
        st.Step();\r
 \r
+       // update the messageuuid to the real messageuuid\r
+       st=m_db->Prepare("SELECT MessageXML FROM tblMessageInserts WHERE MessageUUID=?;");\r
+       st.Bind(0,idparts[1]);\r
+       st.Step();\r
+       if(st.RowReturned())\r
+       {\r
+               std::string xmldata="";\r
+               st.ResultText(0,xmldata);\r
+               xml.ParseXML(xmldata);\r
+               xml.SetMessageID(idparts[4]);\r
+\r
+               SQLite3DB::Statement st2=m_db->Prepare("UPDATE tblMessageInserts SET MessageUUID=?, MessageXML=? WHERE MessageUUID=?;");\r
+               st2.Bind(0,idparts[4]);\r
+               st2.Bind(1,xml.GetXML());\r
+               st2.Bind(2,idparts[1]);\r
+               st2.Step();\r
+       }\r
+\r
        RemoveFromInsertList(idparts[1]);\r
 \r
        m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"MessageInserter::HandlePutSuccessful successfully inserted message "+message["Identifier"]);\r
@@ -88,9 +108,10 @@ void MessageInserter::Initialize()
 \r
 void MessageInserter::StartInsert(const std::string &messageuuid)\r
 {\r
+       MessageXML xmlfile;\r
        DateTime now;\r
        now.SetToGMTime();\r
-       SQLite3DB::Statement st=m_db->Prepare("SELECT MessageXML,PrivateKey,tblLocalIdentity.LocalIdentityID FROM tblMessageInserts INNER JOIN tblLocalIdentity ON tblMessageInserts.LocalIdentityID=tblLocalIdentity.LocalIdentityID WHERE MessageUUID=?;");\r
+       SQLite3DB::Statement st=m_db->Prepare("SELECT MessageXML,PrivateKey,tblLocalIdentity.LocalIdentityID,PublicKey FROM tblMessageInserts INNER JOIN tblLocalIdentity ON tblMessageInserts.LocalIdentityID=tblLocalIdentity.LocalIdentityID WHERE MessageUUID=?;");\r
        st.Bind(0,messageuuid);\r
        st.Step();\r
 \r
@@ -101,6 +122,7 @@ void MessageInserter::StartInsert(const std::string &messageuuid)
                std::string xml;\r
                std::string xmlsizestr;\r
                std::string privatekey;\r
+               std::string publickey;\r
                FCPMessage message;\r
                std::string indexstr;\r
                int index=0;\r
@@ -108,7 +130,7 @@ void MessageInserter::StartInsert(const std::string &messageuuid)
                st.ResultText(0,xml);\r
                st.ResultText(1,privatekey);\r
                st.ResultInt(2,localidentityid);\r
-               StringFunctions::Convert(xml.size(),xmlsizestr);\r
+               st.ResultText(3,publickey);\r
                StringFunctions::Convert(localidentityid,idstr);\r
 \r
                st=m_db->Prepare("SELECT MAX(InsertIndex) FROM tblMessageInserts WHERE Day=? AND LocalIdentityID=?;");\r
@@ -123,9 +145,23 @@ void MessageInserter::StartInsert(const std::string &messageuuid)
                }\r
                StringFunctions::Convert(index,indexstr);\r
 \r
+               // recreate messageuuid in xml - UUID of message will not match entry in MessageInserts table until we successfully insert it\r
+               // see HandlePutSuccessful\r
+               xmlfile.ParseXML(xml);\r
+               // if we don't already have an @sskpart - add it\r
+               if(xmlfile.GetMessageID().find("@")==std::string::npos)\r
+               {\r
+                       // remove - and ~ from publickey part\r
+                       std::string publickeypart=StringFunctions::Replace(StringFunctions::Replace(publickey.substr(4,43),"-",""),"~","");\r
+                       xmlfile.SetMessageID(xmlfile.GetMessageID()+"@"+publickeypart);\r
+               }\r
+               xml=xmlfile.GetXML();\r
+\r
+               StringFunctions::Convert(xml.size(),xmlsizestr);\r
+\r
                message.SetName("ClientPut");\r
                message["URI"]=privatekey+m_messagebase+"|"+now.Format("%Y-%m-%d")+"|Message|"+indexstr+".xml";\r
-               message["Identifier"]=m_fcpuniquename+"|"+messageuuid+"|"+idstr+"|"+indexstr+"|"+message["URI"];\r
+               message["Identifier"]=m_fcpuniquename+"|"+messageuuid+"|"+idstr+"|"+indexstr+"|"+xmlfile.GetMessageID()+"|"+message["URI"];\r
                message["UploadFrom"]="direct";\r
                message["DataLength"]=xmlsizestr;\r
                m_fcp->SendMessage(message);\r
index 07faaf9..54b0d26 100644 (file)
@@ -137,6 +137,9 @@ const bool MessageRequester::HandleAllData(FCPMessage &message)
                        boards[boards.size()-1]=xml.GetReplyBoard();\r
                }\r
 \r
+               // TODO make sure domain of message id match 43 characters of public key of identity (remove - and ~) - if not, discard message\r
+               // implement after 0.1.12 is released\r
+\r
                st=m_db->Prepare("INSERT INTO tblMessage(IdentityID,FromName,MessageDate,MessageTime,Subject,MessageUUID,ReplyBoardID,Body) VALUES(?,?,?,?,?,?,?,?);");\r
                st.Bind(0,identityid);\r
                st.Bind(1,GetIdentityName(identityid));\r
index 8de3077..0de84c3 100644 (file)
@@ -25,7 +25,9 @@ std::string MessageXML::GetXML()
        tid->LinkEndChild(XMLCreateCDATAElement("Subject",m_subject));\r
        tid->LinkEndChild(XMLCreateCDATAElement("MessageID",m_messageid));\r
        tid->LinkEndChild(XMLCreateCDATAElement("ReplyBoard",m_replyboard));\r
-       tid->LinkEndChild(XMLCreateCDATAElement("Body",m_body));\r
+       // a little hack because TinyXML doesn't handle ]]> inside a CDATA section - manually separate into multiple CDATA sections\r
+       // TinyXML still won't be able to parse past the 1st CDATA section, but other implementations might\r
+       tid->LinkEndChild(XMLCreateCDATAElement("Body",StringFunctions::Replace(m_body,"]]>","]]]]><![CDATA[>")));\r
 \r
        TiXmlElement *brds=new TiXmlElement("Boards");\r
        tid->LinkEndChild(brds);\r
index 01a76c7..c615d60 100644 (file)
@@ -1,4 +1,5 @@
 #include "../../include/freenet/periodicdbmaintenance.h"\r
+#include "../../include/stringfunctions.h"\r
 \r
 #ifdef XMEM\r
        #include <xmem.h>\r
@@ -89,6 +90,49 @@ void PeriodicDBMaintenance::Do1DayMaintenance()
        // 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
+       // remove identityid from messages where the identity has been deleted\r
+       m_db->Execute("UPDATE tblMessage SET IdentityID=NULL WHERE IdentityID NOT IN (SELECT IdentityID FROM tblIdentity);");\r
+\r
+       // try to re-attach messages from identities that were previously deleted, but have been since re-added\r
+       // first get the names from messages that have a NULL IdentityID\r
+       SQLite3DB::Statement st=m_db->Prepare("SELECT FromName FROM tblMessage WHERE IdentityID IS NULL GROUP BY FromName;");\r
+       st.Step();\r
+       while(st.RowReturned())\r
+       {\r
+               std::string name="";\r
+               std::string publickey="";\r
+               int identityid=0;\r
+               st.ResultText(0,name);\r
+\r
+               std::vector<std::string> parts;\r
+               StringFunctions::Split(name,"@",parts);\r
+\r
+               // find identities with this name\r
+               SQLite3DB::Statement st2=m_db->Prepare("SELECT IdentityID,PublicKey FROM tblIdentity WHERE Name=?;");\r
+               st2.Bind(0,name);\r
+               st2.Step();\r
+               while(st2.RowReturned())\r
+               {\r
+                       publickey="";\r
+                       identityid=0;\r
+                       st2.ResultText(1,publickey);\r
+                       // check if public key matches 2nd part\r
+                       if(parts.size()>1 && publickey.find(parts[1])==4)\r
+                       {\r
+                               // we have the identity - so update the messages table with the identityid\r
+                               st2.ResultInt(0,identityid);\r
+\r
+                               SQLite3DB::Statement st3=m_db->Prepare("UPDATE tblMessage SET IdentityID=? WHERE Name=? AND IdentityID IS NULL;");\r
+                               st3.Bind(0,identityid);\r
+                               st3.Bind(1,name);\r
+                               st3.Step();\r
+                       }\r
+                       st2.Step();\r
+               }\r
+\r
+               st.Step();\r
+       }\r
+\r
 }\r
 \r
 void PeriodicDBMaintenance::Process()\r
index 7f63579..0c6f913 100644 (file)
@@ -343,6 +343,12 @@ void SetupDB()
                                        DELETE FROM tblTrustListInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
                                END;");\r
 \r
+       db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteBoard AFTER DELETE ON tblBoard \\r
+                               FOR EACH ROW \\r
+                               BEGIN \\r
+                                       DELETE FROM tblMessageBoard WHERE BoardID=old.BoardID;\\r
+                               END;");\r
+\r
        // delete introduction puzzles that were half-way inserted\r
        db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day IS NULL AND InsertIndex IS NULL;");\r
 \r
@@ -565,6 +571,12 @@ void SetupDefaultOptions()
        st.Step();\r
        st.Reset();\r
 \r
+       st.Bind(0,"ChangeMessageTrustOnReply");\r
+       st.Bind(1,"0");\r
+       st.Bind(2,"How much the local message trust level of an identity should change when you reply to one of their messages.");\r
+       st.Step();\r
+       st.Reset();\r
+\r
 }\r
 \r
 void SetupLogFile()\r
index 5bb9988..6ad6ef9 100644 (file)
@@ -12,6 +12,7 @@
 #include "../../include/http/pages/controlboardpage.h"\r
 #include "../../include/http/pages/peerdetailspage.h"\r
 #include "../../include/http/pages/peermaintenancepage.h"\r
+#include "../../include/http/pages/execquerypage.h"\r
 \r
 #include <iostream>\r
 \r
@@ -28,7 +29,7 @@ HTTPThread::HTTPThread()
        StringFunctions::Convert(portstr,port);\r
 \r
        // set template\r
-       templatestr="<html><head></head><body><a href=\"home.htm\">Home</a><br>[CONTENT]</body></html>";\r
+       templatestr="<html><head></head><body><a href=\"home.htm\">Home</a><br><h1>Could not find template.htm!  Place in program directory and restart!</h1><br>[CONTENT]</body></html>";\r
        FILE *infile=fopen("template.htm","r+b");\r
        if(infile)\r
        {\r
@@ -56,6 +57,7 @@ HTTPThread::HTTPThread()
        m_pagehandlers.push_back(new ControlBoardPage(templatestr));\r
        m_pagehandlers.push_back(new PeerDetailsPage(templatestr));\r
        m_pagehandlers.push_back(new PeerMaintenancePage(templatestr));\r
+       m_pagehandlers.push_back(new ExecQueryPage(templatestr));\r
        // homepage must be last - catch all page handler\r
        m_pagehandlers.push_back(new HomePage(templatestr));\r
 \r
diff --git a/src/http/pages/execquerypage.cpp b/src/http/pages/execquerypage.cpp
new file mode 100644 (file)
index 0000000..f86579a
--- /dev/null
@@ -0,0 +1,55 @@
+#include "../../../include/http/pages/execquerypage.h"\r
+#include "../../../include/stringfunctions.h"\r
+\r
+#ifdef XMEM\r
+       #include <xmem.h>\r
+#endif\r
+\r
+const std::string ExecQueryPage::GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars)\r
+{\r
+       std::string content="";\r
+\r
+       if(queryvars.find("formaction")!=queryvars.end() && (*queryvars.find("formaction")).second=="execute" && queryvars.find("query")!=queryvars.end() && (*queryvars.find("query")).second!="")\r
+       {\r
+               SQLite3DB::Recordset rs=m_db->Query((*queryvars.find("query")).second);\r
+\r
+               content+="<table>";\r
+               while(!rs.AtEnd())\r
+               {\r
+                       content+="<tr>";\r
+                       for(int i=0; i<rs.Cols(); i++)\r
+                       {\r
+                               content+="<td>";\r
+                               if(rs.GetField(i))\r
+                               {\r
+                                       content+=rs.GetField(i);\r
+                               }\r
+                               content+="</td>";\r
+                       }\r
+                       content+="</tr>";\r
+                       rs.Next();\r
+               }\r
+               content+="</table>";\r
+       }\r
+\r
+       content+="<h2>Execute Query</h2>";\r
+       content+="<form name=\"frmquery\" method=\"POST\">";\r
+       content+="<input type=\"hidden\" name=\"formaction\" value=\"execute\">";\r
+       content+="<textarea name=\"query\" rows=\"10\" cols=\"80\"></textarea>";\r
+       content+="<input type=\"submit\" value=\"Execute Query\">";\r
+       content+="</form>";\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 ExecQueryPage::WillHandleURI(const std::string &uri)\r
+{\r
+       if(uri.find("execquery.")!=std::string::npos)\r
+       {\r
+               return true;\r
+       }\r
+       else\r
+       {\r
+               return false;\r
+       }\r
+}\r
index f794600..f6cf386 100644 (file)
@@ -147,4 +147,4 @@ const bool PeerMaintenancePage::WillHandleURI(const std::string &uri)
        {\r
                return false;\r
        }\r
-}
\ No newline at end of file
+}\r
index 38bddbf..667595d 100644 (file)
@@ -5,6 +5,48 @@
        #include <xmem.h>\r
 #endif\r
 \r
+const std::string PeerTrustPage::BuildQueryString(const long startrow, const std::string &namesearch, const std::string &sortby, const std::string &sortorder)\r
+{\r
+       std::string returnval="";\r
+       std::string tempval="";\r
+       \r
+       if(startrow>=0)\r
+       {\r
+               StringFunctions::Convert(startrow,tempval);\r
+               returnval+="startrow="+tempval;\r
+       }\r
+\r
+       if(namesearch!="")\r
+       {\r
+               if(returnval!="")\r
+               {\r
+                       returnval+="&";\r
+               }\r
+               returnval+="namesearch="+namesearch;\r
+       }\r
+\r
+       if(sortby!="")\r
+       {\r
+               if(returnval!="")\r
+               {\r
+                       returnval+="&";\r
+               }\r
+               returnval+="sortby="+sortby;\r
+       }\r
+\r
+       if(sortorder!="")\r
+       {\r
+               if(returnval!="")\r
+               {\r
+                       returnval+="&";\r
+               }\r
+               returnval+="sortorder="+sortorder;\r
+       }\r
+\r
+       return returnval;\r
+\r
+}\r
+\r
 const std::string PeerTrustPage::GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars)\r
 {\r
        int count=0;\r
@@ -17,6 +59,8 @@ const std::string PeerTrustPage::GeneratePage(const std::string &method, const s
        std::string startrowstr="0";\r
        std::string namesearch="";\r
        std::string sql;\r
+       std::string sortby="";\r
+       std::string sortorder="";\r
 \r
        StringFunctions::Convert(rowsperpage,rowsperpagestr);\r
 \r
@@ -70,6 +114,26 @@ const std::string PeerTrustPage::GeneratePage(const std::string &method, const s
                StringFunctions::Convert(startrow,startrowstr);\r
        }\r
 \r
+       // sort by\r
+       if(queryvars.find("sortby")!=queryvars.end())\r
+       {\r
+               sortby=(*queryvars.find("sortby")).second;\r
+       }\r
+       else\r
+       {\r
+               sortby="Name";\r
+       }\r
+\r
+       // sort order\r
+       if(queryvars.find("sortorder")!=queryvars.end())\r
+       {\r
+               sortorder=(*queryvars.find("sortorder")).second;\r
+       }\r
+       else\r
+       {\r
+               sortorder="ASC";\r
+       }\r
+\r
        // if we are searching by name\r
        if(queryvars.find("namesearch")!=queryvars.end())\r
        {\r
@@ -77,7 +141,7 @@ const std::string PeerTrustPage::GeneratePage(const std::string &method, const s
        }\r
 \r
        content+="<h2>Peer Trust</h2>";\r
-       content+="Message Trust is how much you trust the identity to post good messages. Trust List Trust is how much weight you want the trust list of that identity to have when calculating the total. The local trust levels are set by you, and the peer trust levels are calculated by a weighted average using other identities trust lists.";\r
+       content+="Message Trust is how much you trust the identity to post good messages. Trust List Trust is how much weight you want the trust list of that identity to have when calculating the total. The local trust levels are set by you, and the peer trust levels are calculated by a weighted average using other identities' trust lists.";\r
        content+="<div style=\"text-align:center;\">";\r
        content+="<form name=\"frmsearch\" method=\"POST\" action=\"peertrust.htm\">";\r
        content+="<input type=\"text\" name=\"namesearch\">";\r
@@ -88,7 +152,11 @@ const std::string PeerTrustPage::GeneratePage(const std::string &method, const s
        content+="<input type=\"hidden\" name=\"formaction\" value=\"update\">";\r
        content+="<input type=\"hidden\" name=\"startrow\" value=\""+startrowstr+"\">";\r
        content+="<table>";\r
-       content+="<tr><th>Name</th><th>Local Message Trust</th><th>Peer Message Trust</th><th>Local Trust List Trust</th><th>Peer Trust List Trust</th></tr>";\r
+       content+="<tr><th><a href=\"peertrust.htm?"+BuildQueryString(startrow,namesearch,"Name",ReverseSort("Name",sortby,sortorder))+"\">Name</a></th>";\r
+       content+="<th><a href=\"peertrust.htm?"+BuildQueryString(startrow,namesearch,"LocalMessageTrust",ReverseSort("LocalMessageTrust",sortby,sortorder))+"\">Local Message Trust</a></th>";\r
+       content+="<th><a href=\"peertrust.htm?"+BuildQueryString(startrow,namesearch,"PeerMessageTrust",ReverseSort("PeerMessageTrust",sortby,sortorder))+"\">Peer Message Trust</a></th>";\r
+       content+="<th><a href=\"peertrust.htm?"+BuildQueryString(startrow,namesearch,"LocalTrustListTrust",ReverseSort("LocalTrustListTrust",sortby,sortorder))+"\">Local Trust List Trust</a></th>";\r
+       content+="<th><a href=\"peertrust.htm?"+BuildQueryString(startrow,namesearch,"PeerTrustListTrust",ReverseSort("PeerTrustListTrust",sortby,sortorder))+"\">Peer Trust List Trust</a></th></tr>";\r
        \r
        // get count of identities we are showing\r
        sql="SELECT COUNT(*) FROM tblIdentity";\r
@@ -111,7 +179,20 @@ const std::string PeerTrustPage::GeneratePage(const std::string &method, const s
        {\r
                sql+=" WHERE Name LIKE  '%' || ? || '%'";\r
        }\r
-       sql+=" ORDER BY Name COLLATE NOCASE LIMIT "+startrowstr+","+rowsperpagestr+";";\r
+       sql+=" ORDER BY";\r
+       if(sortby=="Name")\r
+       {\r
+               sql+=" Name COLLATE NOCASE";\r
+       }\r
+       else\r
+       {\r
+               sql+=" "+sortby;\r
+       }\r
+       if(sortorder!="")\r
+       {\r
+               sql+=" "+sortorder;\r
+       }\r
+       sql+=" LIMIT "+startrowstr+","+rowsperpagestr+";";\r
        st=m_db->Prepare(sql);\r
        if(namesearch!="")\r
        {\r
@@ -183,18 +264,17 @@ const std::string PeerTrustPage::GeneratePage(const std::string &method, const s
                if(startrow>0)\r
                {\r
                        StringFunctions::Convert(startrow-rowsperpage,tempstr);\r
-                       content+="<td colspan=\"2\" align=\"left\"><a href=\"peertrust.htm?startrow="+tempstr+"&namesearch="+namesearch+"\"><-- Previous Page</a></td>";\r
+                       content+="<td colspan=\"2\" align=\"left\"><a href=\"peertrust.htm?"+BuildQueryString(startrow-rowsperpage,namesearch,sortby,sortorder)+"\"><-- Previous Page</a></td>";\r
                        cols+=2;\r
                }\r
                if(startrow+rowsperpage<identitycount)\r
                {\r
-                       StringFunctions::Convert(startrow+rowsperpage,tempstr);\r
                        while(cols<3)\r
                        {\r
                                content+="<td></td>";\r
                                cols++;\r
                        }\r
-                       content+="<td colspan=\"2\" align=\"right\"><a href=\"peertrust.htm?startrow="+tempstr+"&namesearch="+namesearch+"\">Next Page --></a></td>";\r
+                       content+="<td colspan=\"2\" align=\"right\"><a href=\"peertrust.htm?"+BuildQueryString(startrow+rowsperpage,namesearch,sortby,sortorder)+"\">Next Page --></a></td>";\r
                }\r
                content+="</tr>";\r
        }\r
@@ -225,6 +305,25 @@ const std::string PeerTrustPage::GetClassString(const std::string &trustlevel)
        }\r
 }\r
 \r
+const std::string PeerTrustPage::ReverseSort(const std::string &sortname, const std::string &currentsortby, const std::string &currentsortorder)\r
+{\r
+       if(sortname==currentsortby)\r
+       {\r
+               if(currentsortorder=="ASC")\r
+               {\r
+                       return "DESC";\r
+               }\r
+               else\r
+               {\r
+                       return "ASC";\r
+               }\r
+       }\r
+       else\r
+       {\r
+               return currentsortorder;\r
+       }\r
+}\r
+\r
 const bool PeerTrustPage::WillHandleURI(const std::string &uri)\r
 {\r
        if(uri.find("peertrust.")!=std::string::npos)\r
index 123d370..41add10 100644 (file)
@@ -3,6 +3,7 @@
 #include "../include/uuidgenerator.h"\r
 #include "../include/stringfunctions.h"\r
 #include "../include/freenet/messagexml.h"\r
+#include "../include/option.h"\r
 \r
 #include <algorithm>\r
 \r
@@ -43,7 +44,15 @@ const bool Message::CheckForAdministrationBoard(const std::vector<std::string> &
 \r
 const std::string Message::GetNNTPArticleID() const\r
 {\r
-       return "<"+m_messageuuid+"@freenetproject.org>";\r
+       // old message - before 0.1.12 - doesn't have @domain so add @freenetproject.org\r
+       if(m_messageuuid.find("@")==std::string::npos)\r
+       {\r
+               return "<"+m_messageuuid+"@freenetproject.org>";\r
+       }\r
+       else\r
+       {\r
+               return "<"+m_messageuuid+">";\r
+       }\r
 }\r
 \r
 const std::string Message::GetNNTPBody() const\r
@@ -78,7 +87,15 @@ const std::string Message::GetNNTPHeaders() const
                        {\r
                                rval+=" ";\r
                        }\r
-                       rval+="<"+(*j).second+"@freenetproject.org>";\r
+                       // old message - before 0.1.12 - doesn't have @domain so add @freenetproject.org\r
+                       if((*j).second.find("@")==std::string::npos)\r
+                       {\r
+                               rval+="<"+(*j).second+"@freenetproject.org>";\r
+                       }\r
+                       else\r
+                       {\r
+                               rval+="<"+(*j).second+">";\r
+                       }\r
                }\r
                rval+="\r\n";\r
        }\r
@@ -192,8 +209,43 @@ void Message::HandleAdministrationMessage()
 \r
 }\r
 \r
+void Message::HandleChangeTrust()\r
+{\r
+       if(m_changemessagetrustonreply!=0 && m_inreplyto.size()>0)\r
+       {\r
+               SQLite3DB::Statement st=m_db->Prepare("SELECT tblIdentity.IdentityID,tblIdentity.LocalMessageTrust FROM tblIdentity INNER JOIN tblMessage ON tblIdentity.IdentityID=tblMessage.IdentityID WHERE tblMessage.MessageUUID=?;");\r
+               st.Bind(0,m_inreplyto[0]);\r
+               st.Step();\r
+               if(st.RowReturned())\r
+               {\r
+                       int identityid=0;\r
+                       int localmessagetrust=0;\r
+\r
+                       st.ResultInt(0,identityid);\r
+                       st.ResultInt(1,localmessagetrust);\r
+\r
+                       localmessagetrust+=m_changemessagetrustonreply;\r
+                       if(localmessagetrust<0)\r
+                       {\r
+                               localmessagetrust=0;\r
+                       }\r
+                       if(localmessagetrust>100)\r
+                       {\r
+                               localmessagetrust=100;\r
+                       }\r
+\r
+                       SQLite3DB::Statement st2=m_db->Prepare("UPDATE tblIdentity SET LocalMessageTrust=? WHERE IdentityID=?;");\r
+                       st2.Bind(0,localmessagetrust);\r
+                       st2.Bind(1,identityid);\r
+                       st2.Step();\r
+\r
+               }\r
+       }\r
+}\r
+\r
 void Message::Initialize()\r
 {\r
+       std::string tempval="";\r
        m_messageid=-1;\r
        m_messageuuid="";\r
        m_subject="";\r
@@ -203,6 +255,9 @@ void Message::Initialize()
        m_fromname="";\r
        m_boards.clear();\r
        m_inreplyto.clear();\r
+       m_changemessagetrustonreply=0;\r
+       Option::Instance()->Get("ChangeMessageTrustOnReply",tempval);\r
+       StringFunctions::Convert(tempval,m_changemessagetrustonreply);\r
 }\r
 \r
 const bool Message::Load(const long messageid, const long boardid)\r
@@ -286,8 +341,24 @@ const bool Message::Load(const long messageid, const long boardid)
 \r
 const bool Message::Load(const std::string &messageuuid)\r
 {\r
+\r
+       std::string uuid=messageuuid;\r
+\r
+       if(uuid.size()>0 && uuid[0]=='<')\r
+       {\r
+               uuid.erase(0,1);\r
+       }\r
+       if(uuid.size()>0 && uuid[uuid.size()-1]=='>')\r
+       {\r
+               uuid.erase(uuid.size()-1);\r
+       }\r
+       if(uuid.find("@freenetproject.org")!=std::string::npos)\r
+       {\r
+               uuid.erase(uuid.find("@freenetproject.org"));\r
+       }\r
+\r
        SQLite3DB::Statement st=m_db->Prepare("SELECT MessageID FROM tblMessage WHERE MessageUUID=?;");\r
-       st.Bind(0,messageuuid);\r
+       st.Bind(0,uuid);\r
        st.Step();\r
 \r
        if(st.RowReturned())\r
@@ -375,8 +446,10 @@ const bool Message::ParseNNTPMessage(const std::string &nntpmessage)
        // get header info\r
        // date is always set to now regardless of what message has\r
        m_datetime.SetToGMTime();\r
+\r
        // messageuuid is always a unique id we generate regardless of message message-id\r
        m_messageuuid=uuid.Generate();\r
+       \r
        // get from\r
        if(mime.GetFieldValue("From"))\r
        {\r
@@ -480,11 +553,18 @@ const bool Message::ParseNNTPMessage(const std::string &nntpmessage)
                        (*i)=StringFunctions::Replace((*i),"<","");\r
                        (*i)=StringFunctions::Replace((*i),">","");\r
                        (*i)=StringFunctions::TrimWhitespace((*i));\r
+                       /*\r
                        // erase @ and everything after\r
                        if((*i).find("@")!=std::string::npos)\r
                        {\r
                                (*i).erase((*i).find("@"));\r
                        }\r
+                       */\r
+                       // only erase after @ if message is old type with @freenetproject.org\r
+                       if((*i).find("@freenetproject.org")!=std::string::npos)\r
+                       {\r
+                               (*i).erase((*i).find("@"));\r
+                       }\r
                        if((*i)!="")\r
                        {\r
                                m_inreplyto[count++]=(*i);\r
@@ -556,4 +636,6 @@ void Message::StartFreenetInsert()
        st.Bind(2,xml.GetXML());\r
        st.Step();\r
 \r
+       HandleChangeTrust();\r
+\r
 }\r
index 3fffad7..078c1c3 100644 (file)
@@ -635,11 +635,13 @@ const bool NNTPConnection::HandleOverCommand(const NNTPCommand &command)
                        messageuuid=command.m_arguments[0];\r
                        messageuuid=StringFunctions::Replace(messageuuid,"<","");\r
                        messageuuid=StringFunctions::Replace(messageuuid,">","");\r
+                       /*\r
                        // get rid of @ and everything after\r
                        if(messageuuid.find("@")!=std::string::npos)\r
                        {\r
                                messageuuid.erase(messageuuid.find("@"));\r
                        }\r
+                       */\r
                }\r
                // single article or range\r
                else\r
@@ -955,7 +957,7 @@ void NNTPConnection::SendArticleOverInfo(Message &message)
                        {\r
                                line+=" ";\r
                        }\r
-                       line+="<"+(*i).second+"@freenetproject.org>";\r
+                       line+="<"+(*i).second+">"; //+"@freenetproject.org>";\r
                }\r
                line+="\t";\r
        }\r
@@ -1015,6 +1017,21 @@ void NNTPConnection::SendArticleParts(const NNTPConnection::NNTPCommand &command
                else\r
                {\r
                        articleid=command.m_arguments[0];\r
+                       //strip off < and > and everthing after @\r
+                       if(articleid.size()>0 && articleid[0]=='<')\r
+                       {\r
+                               articleid.erase(0,1);\r
+                       }\r
+                       if(articleid.size()>0 && articleid[articleid.size()-1]=='>')\r
+                       {\r
+                               articleid.erase(articleid.size()-1);\r
+                       }\r
+                       /*\r
+                       if(articleid.size()>0 && articleid.find('@')!=std::string::npos)\r
+                       {\r
+                               articleid.erase(articleid.find('@'));\r
+                       }\r
+                       */\r
                        message.Load(articleid);\r
                        type=2;\r
                }\r
index 2ed3403..157b1b2 100644 (file)
@@ -1,7 +1,7 @@
 <html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">\r
 <head>\r
 <title>FMS : Freenet Message System</title>\r
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />\r
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />\r
 <style type="text/css">\r
 body {\r
        background-color: #FFF;\r
@@ -198,6 +198,9 @@ h1, h2, h3, h4, h5, h6 {
 \r
 form   { display:inline; }\r
 \r
+th             { padding-left:5px; padding-right:5px; }\r
+td             { padding-left:5px; padding-right:5px; }\r
+\r
 </style>\r
 </head>\r
 \r