1 #include "../../include/freenet/frostmessagerequester.h"
\r
2 #include "../../include/freenet/frostidentity.h"
\r
3 #include "../../include/freenet/frostmessagexml.h"
\r
5 #include <Poco/DateTime.h>
\r
6 #include <Poco/DateTimeParser.h>
\r
7 #include <Poco/DateTimeFormatter.h>
\r
8 #include <Poco/Timespan.h>
\r
10 FrostMessageRequester::FrostMessageRequester(SQLite3DB::DB *db):IIndexRequester<std::string>(db)
\r
15 FrostMessageRequester::FrostMessageRequester(SQLite3DB::DB *db, FCPv2::Connection *fcp):IIndexRequester<std::string>(db,fcp)
\r
20 const bool FrostMessageRequester::HandleAllData(FCPv2::Message &message)
\r
22 std::vector<std::string> idparts;
\r
23 std::vector<char> data;
\r
25 FrostMessageXML xml;
\r
26 FrostIdentity frostid;
\r
27 bool validmessage=true;
\r
28 bool inserted=false;
\r
30 StringFunctions::Split(message["Identifier"],"|",idparts);
\r
31 StringFunctions::Convert(message["DataLength"],datalength);
\r
33 // wait for all data to be received from connection
\r
34 m_fcp->WaitForBytes(1000,datalength);
\r
36 // if we got disconnected- return immediately
\r
37 if(m_fcp->IsConnected()==false)
\r
43 m_fcp->Receive(data,datalength);
\r
45 // mark this index as received
\r
46 SQLite3DB::Statement st=m_db->Prepare("INSERT INTO tblFrostMessageRequests(BoardID,Day,RequestIndex,Found) VALUES(?,?,?,'true');");
\r
47 st.Bind(0,idparts[1]);
\r
48 st.Bind(1,idparts[3]);
\r
49 st.Bind(2,idparts[2]);
\r
52 if(data.size()>0 && xml.ParseXML(std::string(data.begin(),data.end()))==true)
\r
54 std::vector<std::string> boards=xml.GetBoards();
\r
55 std::map<long,std::string> replyto=xml.GetInReplyTo();
\r
57 if(xml.GetFrostAuthor()!="Anonymous" && frostid.FromPublicKey(xml.GetFrostPublicKey())==false)
\r
59 m_log->debug("FrostMessageRequester::HandleAllData error with public key "+xml.GetFrostPublicKey());
\r
63 if(validmessage && xml.GetFrostAuthor()!="Anonymous" && frostid.VerifyAuthor(xml.GetFrostAuthor())==false)
\r
65 m_log->debug("FrostMessageRequester::HandleAllData error with author "+xml.GetFrostAuthor());
\r
69 std::string contentv2=xml.GetSignableContentV2();
\r
70 if(validmessage && xml.GetFrostAuthor()!="Anonymous" && frostid.VerifySignature(std::vector<unsigned char>(contentv2.begin(),contentv2.end()),xml.GetFrostSignatureV2())==false)
\r
72 m_log->debug("FrostMessageRequester::HandleAllData error with signature "+xml.GetFrostSignatureV2());
\r
76 if(xml.GetFrostAuthor()=="Anonymous" && m_saveanonymous==false)
\r
81 if(validmessage==true)
\r
83 std::string nntpbody="";
\r
84 nntpbody=xml.GetBody();
\r
86 //add file keys/sizes to body
\r
87 std::vector<MessageXML::fileattachment> fileattachments=xml.GetFileAttachments();
\r
88 if(fileattachments.size()>0)
\r
90 nntpbody+="\r\nAttachments";
\r
92 for(std::vector<MessageXML::fileattachment>::iterator i=fileattachments.begin(); i!=fileattachments.end(); i++)
\r
94 std::string sizestr="0";
\r
95 StringFunctions::Convert((*i).m_size,sizestr);
\r
97 nntpbody+="\r\n"+(*i).m_key;
\r
98 nntpbody+="\r\n"+sizestr+" bytes";
\r
102 m_db->Execute("BEGIN;");
\r
104 st=m_db->Prepare("INSERT INTO tblMessage(FromName,MessageDate,MessageTime,Subject,MessageUUID,ReplyBoardID,Body,InsertDate,MessageIndex) VALUES(?,?,?,?,?,?,?,?,?);");
\r
105 st.Bind(0,xml.GetFrostAuthor());
\r
106 st.Bind(1,xml.GetDate());
\r
107 st.Bind(2,xml.GetTime());
\r
108 st.Bind(3,xml.GetSubject());
\r
109 st.Bind(4,xml.GetMessageID());
\r
110 st.Bind(5,idparts[1]);
\r
111 st.Bind(6,nntpbody);
\r
112 st.Bind(7,idparts[3]);
\r
113 st.Bind(8,idparts[2]);
\r
114 inserted=st.Step(true);
\r
115 long messageid=st.GetLastInsertRowID();
\r
120 st=m_db->Prepare("INSERT INTO tblMessageBoard(MessageID,BoardID) VALUES(?,?);");
\r
121 for(std::vector<std::string>::iterator i=boards.begin(); i!=boards.end(); i++)
\r
123 st.Bind(0,messageid);
\r
124 st.Bind(1,idparts[1]);
\r
130 st=m_db->Prepare("INSERT INTO tblMessageReplyTo(MessageID,ReplyToMessageUUID,ReplyOrder) VALUES(?,?,?);");
\r
131 for(std::map<long,std::string>::iterator j=replyto.begin(); j!=replyto.end(); j++)
\r
133 st.Bind(0,messageid);
\r
134 st.Bind(1,(*j).second);
\r
135 st.Bind(2,(*j).first);
\r
141 m_log->debug("MessageRequester::HandleAllData parsed Message XML file : "+message["Identifier"]);
\r
144 else // couldn't insert - was already in database
\r
146 std::string errmsg;
\r
147 m_db->GetLastError(errmsg);
\r
148 m_log->debug("FrostMessageRequester::HandleAllData could not insert message into database. SQLite error "+errmsg);
\r
152 m_db->Execute("COMMIT;");
\r
154 } // if validmessage
\r
157 m_log->debug("FrostMessageRequester::HandleAllData invalid message "+message["Identifier"]);
\r
163 m_log->error("FrostMessageRequester::HandleAllData error parsing FrostMessage XML file : "+message["Identifier"]);
\r
166 RemoveFromRequestList(idparts[0]+"|"+idparts[1]+"|"+idparts[2]);
\r
172 const bool FrostMessageRequester::HandleGetFailed(FCPv2::Message &message)
\r
174 std::vector<std::string> idparts;
\r
175 StringFunctions::Split(message["Identifier"],"|",idparts);
\r
177 if(message["Fatal"]=="true")
\r
179 // insert index so we won't try it again
\r
180 SQLite3DB::Statement st=m_db->Prepare("INSERT INTO tblFrostMessageRequests(BoardID,Day,RequestIndex,Found) VALUES(?,?,?,'true');");
\r
181 st.Bind(0,idparts[0]);
\r
182 st.Bind(1,idparts[2]);
\r
183 st.Bind(2,idparts[1]);
\r
187 m_log->debug("FrostMessageRequester::HandleGetFailed handled failure "+message["Code"]+" of "+message["Identifier"]);
\r
193 void FrostMessageRequester::Initialize()
\r
195 m_fcpuniquename="FrostMessageRequester";
\r
196 std::string tempval("");
\r
198 Option option(m_db);
\r
200 option.GetInt("FrostMaxMessageRequests",m_maxrequests);
\r
201 if(m_maxrequests<1)
\r
204 m_log->error("Option FrostMaxMessageRequests is currently set at "+tempval+". It must be 1 or greater.");
\r
206 if(m_maxrequests>100)
\r
208 m_log->warning("Option FrostMaxMessageRequests is currently set at "+tempval+". This value might be incorrectly configured.");
\r
211 m_maxdaysbackward=0;
\r
212 option.GetInt("FrostMessageMaxDaysBackward",m_maxdaysbackward);
\r
213 if(m_maxdaysbackward<0)
\r
215 m_maxdaysbackward=0;
\r
216 m_log->error("Option FrostMessageMaxDaysBackward is currently set at "+tempval+". It must be 0 or greater.");
\r
218 if(m_maxdaysbackward>30)
\r
220 m_log->warning("Option FrostMessageMaxDaysBackward is currently set at "+tempval+". This value might be incorrectly configured.");
\r
224 option.Get("FrostBoardPrefix",m_boardprefix);
\r
226 m_frostmessagebase="";
\r
227 option.Get("FrostMessageBase",m_frostmessagebase);
\r
229 m_saveanonymous=false;
\r
230 option.Get("FrostSaveAnonymousMessages",tempval);
\r
231 if(tempval=="true")
\r
233 m_saveanonymous=true;
\r
236 m_maxindexesforward=4;
\r
240 void FrostMessageRequester::PopulateIDList()
\r
243 Poco::DateTime pastdate;
\r
244 long expectedindex;
\r
245 SQLite3DB::Statement st=m_db->Prepare("SELECT BoardID, BoardName FROM tblBoard WHERE BoardName LIKE ? || '%' AND SaveReceivedMessages='true';");
\r
246 SQLite3DB::Statement st2=m_db->Prepare("SELECT Day, RequestIndex FROM tblFrostMessageRequests WHERE BoardID=? AND Day=? ORDER BY RequestIndex ASC;");
\r
248 st.Bind(0,m_boardprefix);
\r
251 while(st.RowReturned())
\r
254 std::string boardidstr="";
\r
255 std::string boardname="";
\r
257 st.ResultInt(0,boardid);
\r
258 st.ResultText(1,boardname);
\r
260 StringFunctions::Convert(boardid,boardidstr);
\r
262 for(long backdays=0; backdays<=m_maxdaysbackward; backdays++)
\r
265 pastdate=Poco::DateTime()-Poco::Timespan(backdays,0,0,0,0);
\r
266 std::string day=Poco::DateTimeFormatter::format(pastdate,"%Y-%m-%d");
\r
268 st2.Bind(0,boardid);
\r
273 while(st2.RowReturned())
\r
276 st2.ResultText(0,day);
\r
277 st2.ResultInt(1,thisindex);
\r
279 // fill in indexes we haven't downloaded yet
\r
280 if(expectedindex<thisindex)
\r
282 for(long i=expectedindex; i<thisindex; i++)
\r
284 std::string istr="";
\r
285 StringFunctions::Convert(i,istr);
\r
286 m_ids[boardidstr+"|"+istr+"|"+day]=false;
\r
290 expectedindex=thisindex+1;
\r
297 // fill in remaining indexes
\r
298 for(long i=expectedindex; i<=expectedindex+m_maxindexesforward; i++)
\r
300 std::string istr="";
\r
301 StringFunctions::Convert(i,istr);
\r
302 m_ids[boardidstr+"|"+istr+"|"+day]=false;
\r
312 void FrostMessageRequester::StartRequest(const std::string &id)
\r
314 Poco::DateTime date;
\r
316 FCPv2::Message message;
\r
317 std::vector<std::string> idparts;
\r
319 StringFunctions::Split(id,"|",idparts);
\r
321 Poco::DateTimeParser::tryParse(idparts[2],date,tz);
\r
323 SQLite3DB::Statement st=m_db->Prepare("SELECT BoardName FROM tblBoard WHERE BoardID=?;");
\r
324 st.Bind(0,idparts[0]);
\r
327 if(st.RowReturned())
\r
329 std::string boardname="";
\r
331 st.ResultText(0,boardname);
\r
332 // erase prefix from the board name
\r
333 if(m_boardprefix.size()>0)
\r
335 boardname.erase(0,m_boardprefix.size());
\r
338 message.SetName("ClientGet");
\r
339 message["URI"]="KSK@"+m_frostmessagebase+"|message|news|"+Poco::DateTimeFormatter::format(date,"%Y.%n.%e")+"-"+boardname+"-"+idparts[1]+".xml";
\r
340 message["Identifier"]=m_fcpuniquename+"|"+id+"|"+message["URI"];
\r
341 message["ReturnType"]="direct";
\r
342 message["MaxSize"]="1000000"; // 1 MB
\r
344 m_fcp->Send(message);
\r
346 m_requesting.push_back(id);
\r