\r
#include <algorithm>\r
\r
+#include <Poco/DateTime.h>\r
+#include <Poco/DateTimeFormatter.h>\r
+#include <Poco/Timespan.h>\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
Initialize();\r
}\r
\r
-const long MessageRequester::GetBoardID(const std::string &boardname)\r
+const long MessageRequester::GetBoardID(const std::string &boardname, const std::string &identityname)\r
{\r
+ std::string lowerboard=boardname;\r
+ StringFunctions::LowerCase(lowerboard,lowerboard);\r
SQLite3DB::Statement st=m_db->Prepare("SELECT BoardID FROM tblBoard WHERE BoardName=?;");\r
- st.Bind(0,boardname);\r
+ st.Bind(0,lowerboard);\r
st.Step();\r
\r
if(st.RowReturned())\r
}\r
else\r
{\r
- DateTime now;\r
- now.SetToGMTime();\r
- st=m_db->Prepare("INSERT INTO tblBoard(BoardName,DateAdded) VALUES(?,?);");\r
+ Poco::DateTime now;\r
+ st=m_db->Prepare("INSERT INTO tblBoard(BoardName,DateAdded,SaveReceivedMessages,AddedMethod) VALUES(?,?,?,?);");\r
st.Bind(0,boardname);\r
- st.Bind(1,now.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(1,Poco::DateTimeFormatter::format(now,"%Y-%m-%d %H:%M:%S"));\r
+ if(m_savemessagesfromnewboards)\r
+ {\r
+ st.Bind(2,"true");\r
+ }\r
+ else\r
+ {\r
+ st.Bind(2,"false");\r
+ }\r
+ st.Bind(3,"Message from "+identityname);\r
st.Step(true);\r
return st.GetLastInsertRowID();\r
} \r
long identityid;\r
long index;\r
bool inserted=false;\r
+ bool validmessage=true;\r
+ long savetoboardcount=0;\r
\r
StringFunctions::Split(message["Identifier"],"|",idparts);\r
StringFunctions::Convert(message["DataLength"],datalength);\r
if(xml.ParseXML(std::string(data.begin(),data.end()))==true)\r
{\r
std::vector<std::string> boards=xml.GetBoards();\r
+ std::map<long,std::string> replyto=xml.GetInReplyTo();\r
+\r
if(boards.size()>m_maxboardspermessage)\r
{\r
boards.resize(m_maxboardspermessage);\r
\r
if(boards.size()<=0)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"MessageRequester::HandleAllData Message XML did not contain any boards! "+message["Identifier"]);\r
+ m_log->error("MessageRequester::HandleAllData Message XML did not contain any boards! "+message["Identifier"]);\r
+ // remove this identityid from request list\r
+ RemoveFromRequestList(idparts[1]); \r
return true;\r
}\r
if(xml.GetReplyBoard()=="")\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"MessageRequester::HandleAllData Message XML did not contain a reply board! "+message["Identifier"]);\r
+ m_log->error("MessageRequester::HandleAllData Message XML did not contain a reply board! "+message["Identifier"]);\r
+ // remove this identityid from request list\r
+ RemoveFromRequestList(idparts[1]); \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
+\r
+ // make sure the reply board is on the board list we are saving - if not, replace the last element of boards with 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
- // TODO make sure domain of message id match 43 characters of public key of identity (remove - and ~) - if not, discard message\r
+ // 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=m_db->Prepare("SELECT PublicKey FROM tblIdentity WHERE IdentityID=?;");\r
st.Bind(0,identityid);\r
- st.Bind(1,GetIdentityName(identityid));\r
- st.Bind(2,xml.GetDate());\r
- st.Bind(3,xml.GetTime());\r
- st.Bind(4,xml.GetSubject());\r
- st.Bind(5,xml.GetMessageID());\r
- st.Bind(6,GetBoardID(xml.GetReplyBoard()));\r
- st.Bind(7,xml.GetBody());\r
- inserted=st.Step(true);\r
- int messageid=st.GetLastInsertRowID();\r
-\r
- if(inserted==true)\r
+ st.Step();\r
+ if(st.RowReturned())\r
{\r
+ std::vector<std::string> uuidparts;\r
+ std::vector<std::string> keyparts;\r
+ std::string keypart="";\r
+ std::string publickey="";\r
+\r
+ st.ResultText(0,publickey);\r
+\r
+ StringFunctions::SplitMultiple(publickey,"@,",keyparts);\r
+ StringFunctions::SplitMultiple(xml.GetMessageID(),"@",uuidparts);\r
\r
- st=m_db->Prepare("INSERT INTO tblMessageBoard(MessageID,BoardID) VALUES(?,?);");\r
- for(std::vector<std::string>::iterator i=boards.begin(); i!=boards.end(); i++)\r
+ if(uuidparts.size()>1 && keyparts.size()>1)\r
{\r
- st.Bind(0,messageid);\r
- st.Bind(1,GetBoardID((*i)));\r
- st.Step();\r
- st.Reset();\r
+ keypart=StringFunctions::Replace(StringFunctions::Replace(keyparts[1],"-",""),"~","");\r
+ if(keypart!=uuidparts[1])\r
+ {\r
+ m_log->error("MessageRequester::HandleAllData MessageID in Message doesn't match public key of identity : "+message["Identifier"]);\r
+ validmessage=false;\r
+ }\r
}\r
- st.Finalize();\r
-\r
- st=m_db->Prepare("INSERT INTO tblMessageReplyTo(MessageID,ReplyToMessageUUID,ReplyOrder) VALUES(?,?,?);");\r
- std::map<long,std::string> replyto=xml.GetInReplyTo();\r
- for(std::map<long,std::string>::iterator j=replyto.begin(); j!=replyto.end(); j++)\r
+ else\r
{\r
- st.Bind(0,messageid);\r
- st.Bind(1,(*j).second);\r
- st.Bind(2,(*j).first);\r
- st.Step();\r
- st.Reset();\r
+ m_log->error("MessageRequester::HandleAllData Error with identity's public key or Message ID : "+message["Identifier"]);\r
+ validmessage=false;\r
}\r
- st.Finalize();\r
-\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"MessageRequester::HandleAllData parsed Message XML file : "+message["Identifier"]);\r
-\r
}\r
- else // couldn't insert - was already in database\r
+ else\r
+ {\r
+ m_log->error("MessageRequester::HandleAllData Error couldn't find identity : "+message["Identifier"]);\r
+ validmessage=false;\r
+ }\r
+\r
+ // make sure we will at least save to 1 board before inserting message\r
+ savetoboardcount=0;\r
+ for(std::vector<std::string>::iterator bi=boards.begin(); bi!=boards.end(); bi++)\r
{\r
- //m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"MessageRequester::HandleAddData could not insert message into database. "+message["Identifier"]);\r
+ if(SaveToBoard((*bi)))\r
+ {\r
+ savetoboardcount++;\r
+ }\r
}\r
\r
+ if(validmessage && savetoboardcount>0)\r
+ {\r
+ std::string nntpbody="";\r
+ nntpbody=xml.GetBody();\r
+\r
+ //add file keys/sizes to body\r
+ std::vector<MessageXML::fileattachment> fileattachments=xml.GetFileAttachments();\r
+ if(fileattachments.size()>0)\r
+ {\r
+ nntpbody+="\r\nAttachments";\r
+ }\r
+ for(std::vector<MessageXML::fileattachment>::iterator i=fileattachments.begin(); i!=fileattachments.end(); i++)\r
+ {\r
+ std::string sizestr="0";\r
+ StringFunctions::Convert((*i).m_size,sizestr);\r
+\r
+ nntpbody+="\r\n"+(*i).m_key;\r
+ nntpbody+="\r\n"+sizestr+" bytes";\r
+ nntpbody+="\r\n";\r
+ }\r
+\r
+ st=m_db->Prepare("INSERT INTO tblMessage(IdentityID,FromName,MessageDate,MessageTime,Subject,MessageUUID,ReplyBoardID,Body,MessageIndex) VALUES(?,?,?,?,?,?,?,?,?);");\r
+ st.Bind(0,identityid);\r
+ st.Bind(1,GetIdentityName(identityid));\r
+ st.Bind(2,xml.GetDate());\r
+ st.Bind(3,xml.GetTime());\r
+ st.Bind(4,xml.GetSubject());\r
+ st.Bind(5,xml.GetMessageID());\r
+ st.Bind(6,GetBoardID(xml.GetReplyBoard(),GetIdentityName(identityid)));\r
+ st.Bind(7,nntpbody);\r
+ st.Bind(8,index);\r
+ inserted=st.Step(true);\r
+ int messageid=st.GetLastInsertRowID();\r
+\r
+ if(inserted==true)\r
+ {\r
+\r
+ st=m_db->Prepare("INSERT INTO tblMessageBoard(MessageID,BoardID) VALUES(?,?);");\r
+ for(std::vector<std::string>::iterator i=boards.begin(); i!=boards.end(); i++)\r
+ {\r
+ if(SaveToBoard((*i)))\r
+ {\r
+ st.Bind(0,messageid);\r
+ st.Bind(1,GetBoardID((*i),GetIdentityName(identityid)));\r
+ st.Step();\r
+ st.Reset();\r
+ }\r
+ }\r
+ st.Finalize();\r
+\r
+ st=m_db->Prepare("INSERT INTO tblMessageReplyTo(MessageID,ReplyToMessageUUID,ReplyOrder) VALUES(?,?,?);");\r
+ for(std::map<long,std::string>::iterator j=replyto.begin(); j!=replyto.end(); j++)\r
+ {\r
+ st.Bind(0,messageid);\r
+ st.Bind(1,(*j).second);\r
+ st.Bind(2,(*j).first);\r
+ st.Step();\r
+ st.Reset();\r
+ }\r
+ st.Finalize();\r
+\r
+ m_log->debug("MessageRequester::HandleAllData parsed Message XML file : "+message["Identifier"]);\r
+\r
+ }\r
+ else // couldn't insert - was already in database\r
+ {\r
+ //m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"MessageRequester::HandleAddData could not insert message into database. "+message["Identifier"]);\r
+ }\r
+\r
+ } // if validmessage\r
}\r
else\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"MessageRequester::HandleAllData error parsing Message XML file : "+message["Identifier"]);\r
+ m_log->error("MessageRequester::HandleAllData error parsing Message XML file : "+message["Identifier"]);\r
}\r
\r
RemoveFromRequestList(idparts[1]);\r
\r
const bool MessageRequester::HandleGetFailed(FCPMessage &message)\r
{\r
- DateTime now;\r
SQLite3DB::Statement st;\r
std::vector<std::string> idparts;\r
std::string requestid;\r
long index;\r
long identityid;\r
\r
- now.SetToGMTime();\r
StringFunctions::Split(message["Identifier"],"|",idparts);\r
requestid=idparts[1];\r
StringFunctions::Convert(idparts[2],identityid);\r
st.Step();\r
st.Finalize();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"MessageRequester::HandleGetFailed fatal error requesting "+message["Identifier"]);\r
+ m_log->error("MessageRequester::HandleGetFailed fatal error requesting "+message["Identifier"]);\r
}\r
\r
// remove this identityid from request list\r
if(m_maxrequests<1)\r
{\r
m_maxrequests=1;\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"Option MaxMessageRequests is currently set at "+tempval+". It must be 1 or greater.");\r
+ m_log->error("Option MaxMessageRequests is currently set at "+tempval+". It must be 1 or greater.");\r
}\r
if(m_maxrequests>100)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_WARNING,"Option MaxMessageRequests is currently set at "+tempval+". This value might be incorrectly configured.");\r
+ m_log->warning("Option MaxMessageRequests is currently set at "+tempval+". This value might be incorrectly configured.");\r
}\r
Option::Instance()->Get("MessageDownloadMaxDaysBackward",tempval);\r
StringFunctions::Convert(tempval,m_maxdaysbackward);\r
if(m_maxdaysbackward<0)\r
{\r
m_maxdaysbackward=0;\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"Option MessageDownloadMaxDaysBackward is currently set at "+tempval+". It must be 0 or greater.");\r
+ m_log->error("Option MessageDownloadMaxDaysBackward is currently set at "+tempval+". It must be 0 or greater.");\r
}\r
if(m_maxdaysbackward>30)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_WARNING,"Option MessageDownloadMaxDaysBackward is currently set at "+tempval+". This value might be incorrectly configured.");\r
+ m_log->warning("Option MessageDownloadMaxDaysBackward is currently set at "+tempval+". This value might be incorrectly configured.");\r
}\r
Option::Instance()->Get("MaxPeerMessagesPerDay",tempval);\r
StringFunctions::Convert(tempval,m_maxpeermessages);\r
if(m_maxpeermessages<1)\r
{\r
m_maxpeermessages=1;\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"Option MaxPeerMessagesPerDay is currently set at "+tempval+". It must be 1 or greater.");\r
+ m_log->error("Option MaxPeerMessagesPerDay is currently set at "+tempval+". It must be 1 or greater.");\r
}\r
if(m_maxpeermessages<20 || m_maxpeermessages>1000)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_WARNING,"Option MaxPeerMessagesPerDay is currently set at "+tempval+". This value might be incorrectly configured. The suggested value is 200.");\r
+ m_log->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
+ m_log->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
+ m_log->warning("Option MaxBoardsPerMessage is currently set at "+tempval+". This value might be incorrectly configured.");\r
+ }\r
+\r
+ Option::Instance()->Get("SaveMessagesFromNewBoards",tempval);\r
+ if(tempval=="true")\r
+ {\r
+ m_savemessagesfromnewboards=true;\r
+ }\r
+ else\r
+ {\r
+ m_savemessagesfromnewboards=false;\r
+ }\r
+\r
+ Option::Instance()->Get("LocalTrustOverridesPeerTrust",tempval);\r
+ if(tempval=="true")\r
+ {\r
+ m_localtrustoverrides=true;\r
+ }\r
+ else\r
+ {\r
+ m_localtrustoverrides=false;\r
}\r
+\r
}\r
\r
void MessageRequester::PopulateIDList()\r
{\r
- DateTime date;\r
+ Poco::DateTime date;\r
std::string val1;\r
std::string val2;\r
std::string val3;\r
std::string sql;\r
long requestindex;\r
\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-m_maxdaysbackward);\r
+ date-=Poco::Timespan(m_maxdaysbackward,0,0,0,0);\r
\r
sql="SELECT tblIdentity.IdentityID,Day,RequestIndex ";\r
sql+="FROM tblMessageRequests INNER JOIN tblIdentity ON tblMessageRequests.IdentityID=tblIdentity.IdentityID ";\r
- sql+="WHERE tblIdentity.LocalMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalMessageTrust') AND FromMessageList='true' AND Found='false' AND Day>='"+date.Format("%Y-%m-%d")+"' ";\r
- sql+="AND (tblIdentity.PeerMessageTrust IS NULL OR tblIdentity.PeerMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerMessageTrust')) ";\r
+ sql+="WHERE FromMessageList='true' AND Found='false' AND Day>='"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"' ";\r
+ if(m_localtrustoverrides==false)\r
+ {\r
+ sql+="AND (tblIdentity.LocalMessageTrust IS NULL OR tblIdentity.LocalMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalMessageTrust')) ";\r
+ sql+="AND (tblIdentity.PeerMessageTrust IS NULL OR tblIdentity.PeerMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerMessageTrust')) ";\r
+ }\r
+ else\r
+ {\r
+ sql+="AND (tblIdentity.LocalMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalMessageTrust') OR (tblIdentity.LocalMessageTrust IS NULL AND (tblIdentity.PeerMessageTrust IS NULL OR tblIdentity.PeerMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerMessageTrust')))) ";\r
+ }\r
+ sql+="AND tblIdentity.Name <> '' ";\r
+ // sort by day descending - in case there is a bunch of messages on a day that keep timing out, we will eventually get to the next day and hopefully find messages there\r
+ // secondary ascending sort on tries\r
+ // tertiary sort on request index (so we get low indexes first)\r
+ sql+="ORDER BY tblMessageRequests.Day DESC, tblMessageRequests.Tries ASC, tblMessageRequests.RequestIndex ASC ";\r
sql+=";";\r
\r
SQLite3DB::Statement st=m_db->Prepare(sql);\r
\r
}\r
\r
+const bool MessageRequester::SaveToBoard(const std::string &boardname)\r
+{\r
+ bool save=true;\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT SaveReceivedMessages FROM tblBoard WHERE BoardName=?;");\r
+ st.Bind(0,boardname);\r
+ st.Step();\r
+ if(st.RowReturned())\r
+ {\r
+ std::string val="";\r
+ st.ResultText(0,val);\r
+ if(val=="true")\r
+ {\r
+ save=true;\r
+ }\r
+ else\r
+ {\r
+ save=false;\r
+ }\r
+ }\r
+ return save;\r
+}\r
+\r
void MessageRequester::StartRequest(const std::string &requestid)\r
{\r
FCPMessage message;\r
message["Identifier"]=m_fcpuniquename+"|"+requestid+"|"+parts[0]+"|"+parts[1]+"|"+parts[2]+"|"+message["URI"];\r
message["ReturnType"]="direct";\r
message["MaxSize"]="1000000"; // 1 MB\r
- message["MaxRetries"]="-1"; // use new ULPR since we are fairly sure message exists since the author says it does\r
+ message["MaxRetries"]="-1"; // use ULPR since we are fairly sure message exists since the author says it does\r
\r
m_fcp->SendMessage(message);\r
\r
m_requesting.push_back(requestid);\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"MessageRequester::StartRequest requesting "+message["Identifier"]);\r
+ // update tries\r
+ st=m_db->Prepare("UPDATE tblMessageRequests SET Tries=Tries+1 WHERE IdentityID=? AND Day=? AND RequestIndex=?;");\r
+ st.Bind(0,identityid);\r
+ st.Bind(1,date);\r
+ st.Bind(2,indexstr);\r
+ st.Step();\r
+\r
+ m_log->debug("MessageRequester::StartRequest requesting "+message["Identifier"]);\r
}\r
\r
m_ids[requestid]=true;\r