version 0.3.29
[fms.git] / src / freenet / trustlistinserter.cpp
1 #include "../../include/freenet/trustlistinserter.h"\r
2 #include "../../include/option.h"\r
3 #include "../../include/freenet/trustlistxml.h"\r
4 #include "../../include/stringfunctions.h"\r
5 \r
6 #include <Poco/Timespan.h>\r
7 #include <Poco/DateTimeFormatter.h>\r
8 #include <Poco/DateTimeParser.h>\r
9 \r
10 #ifdef XMEM\r
11         #include <xmem.h>\r
12 #endif\r
13 \r
14 TrustListInserter::TrustListInserter(SQLite3DB::DB *db):IDatabase(db)\r
15 {\r
16         Initialize();\r
17 }\r
18 \r
19 TrustListInserter::TrustListInserter(SQLite3DB::DB *db, FCPv2::Connection *fcp):IDatabase(db),IFCPConnected(fcp)\r
20 {\r
21         Initialize();\r
22 }\r
23 \r
24 void TrustListInserter::CheckForNeededInsert()\r
25 {\r
26         Poco::DateTime date;\r
27         int currentday=date.day();\r
28         date-=Poco::Timespan(0,6,0,0,0);\r
29         // insert trust lists every 6 hours - if 6 hours ago was different day then set to midnight of current day to insert list today ASAP\r
30         if(currentday!=date.day())\r
31         {\r
32                 date.assign(date.year(),date.month(),currentday,0,0,0);\r
33         }\r
34         SQLite3DB::Recordset rs=m_db->Query("SELECT LocalIdentityID, PrivateKey FROM tblLocalIdentity WHERE PrivateKey IS NOT NULL AND PrivateKey <> '' AND PublishTrustList='true' AND InsertingTrustList='false' AND (LastInsertedTrustList<='"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S")+"' OR LastInsertedTrustList IS NULL);");\r
35 \r
36         if(rs.Empty()==false)\r
37         {\r
38                 StartInsert(rs.GetInt(0),rs.GetField(1));\r
39         }\r
40 }\r
41 \r
42 void TrustListInserter::FCPConnected()\r
43 {\r
44         m_db->Execute("UPDATE tblLocalIdentity SET InsertingTrustList='false';");\r
45 }\r
46 \r
47 void TrustListInserter::FCPDisconnected()\r
48 {\r
49 \r
50 }\r
51 \r
52 const bool TrustListInserter::HandleMessage(FCPv2::Message &message)\r
53 {\r
54 \r
55         if(message["Identifier"].find("TrustListInserter")==0)\r
56         {\r
57                 \r
58                 Poco::DateTime now;\r
59                 std::vector<std::string> idparts;\r
60 \r
61                 StringFunctions::Split(message["Identifier"],"|",idparts);\r
62 \r
63                 // no action for URIGenerated\r
64                 if(message.GetName()=="URIGenerated")\r
65                 {\r
66                         return true;\r
67                 }\r
68 \r
69                 // no action for IdentifierCollision\r
70                 if(message.GetName()=="IdentifierCollision")\r
71                 {\r
72                         return true;\r
73                 }\r
74 \r
75                 if(message.GetName()=="PutSuccessful")\r
76                 {\r
77                         // non USK\r
78                         if(idparts[0]=="TrustListInserter")\r
79                         {\r
80                                 m_db->Execute("UPDATE tblLocalIdentity SET InsertingTrustList='false', LastInsertedTrustList='"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d %H:%M:%S")+"' WHERE LocalIdentityID="+idparts[1]+";");\r
81                                 m_db->Execute("INSERT INTO tblTrustListInserts(LocalIdentityID,Day,InsertIndex) VALUES("+idparts[1]+",'"+idparts[4]+"',"+idparts[2]+");");\r
82                                 m_log->debug("TrustListInserter::HandleMessage inserted TrustList xml");\r
83                         }\r
84                         return true;\r
85                 }\r
86 \r
87                 if(message.GetName()=="PutFailed" && idparts[0]=="TrustListInserter")\r
88                 {\r
89                         // non USK\r
90                         if(idparts[0]=="TrustListInserter")\r
91                         {\r
92                                 m_db->Execute("UPDATE tblLocalIdentity SET InsertingTrustList='false' WHERE LocalIdentityID="+idparts[1]+";");\r
93                                 m_log->debug("TrustListInserter::HandleMessage failure inserting TrustList xml.  Code="+message["Code"]+" Description="+message["CodeDescription"]);\r
94                         \r
95                                 // if code 9 (collision), then insert index into inserted table\r
96                                 if(message["Code"]=="9")\r
97                                 {\r
98                                         m_db->Execute("INSERT INTO tblTrustListInserts(LocalIdentityID,Day,InsertIndex) VALUES("+idparts[1]+",'"+idparts[4]+"',"+idparts[2]+");");\r
99                                 }\r
100                         }\r
101                         return true;\r
102                 }\r
103 \r
104         }\r
105 \r
106         return false;\r
107 }\r
108 \r
109 void TrustListInserter::Initialize()\r
110 {\r
111         Option option(m_db);\r
112         option.Get("MessageBase",m_messagebase);\r
113         m_lastchecked=Poco::Timestamp();\r
114 }\r
115 \r
116 void TrustListInserter::Process()\r
117 {\r
118         Poco::DateTime now;\r
119 \r
120         // check every minute\r
121         if(m_lastchecked<=(now-Poco::Timespan(0,0,1,0,0)))\r
122         {\r
123                 CheckForNeededInsert();\r
124                 m_lastchecked=now;\r
125         }\r
126 }\r
127 \r
128 void TrustListInserter::RegisterWithThread(FreenetMasterThread *thread)\r
129 {\r
130         thread->RegisterFCPConnected(this);\r
131         thread->RegisterFCPMessageHandler(this);\r
132         thread->RegisterPeriodicProcessor(this);\r
133 }\r
134 \r
135 void TrustListInserter::StartInsert(const long localidentityid, const std::string &privatekey)\r
136 {\r
137         FCPv2::Message message;\r
138         TrustListXML xml;\r
139         std::string data;\r
140         std::string datasizestr;\r
141         std::string publickey;\r
142         int messagetrust;\r
143         int trustlisttrust;\r
144         Poco::DateTime now,date,dateminus30,tempdate;\r
145         int index;\r
146         std::string indexstr;\r
147         std::string localidentityidstr;\r
148         std::string messagetrustcomment="";\r
149         std::string trustlisttrustcomment="";\r
150         int identityid=-1;\r
151         int count=0;\r
152         bool add=false;\r
153         std::string dateadded="";\r
154 \r
155         dateminus30-=Poco::Timespan(30,0,0,0,0);\r
156 \r
157         // insert all identities not in trust list already\r
158         m_db->Execute("INSERT INTO tblIdentityTrust(LocalIdentityID,IdentityID) SELECT LocalIdentityID,IdentityID FROM tblLocalIdentity,tblIdentity WHERE LocalIdentityID || '_' || IdentityID NOT IN (SELECT LocalIdentityID || '_' || IdentityID FROM tblIdentityTrust);");\r
159 \r
160         // select statement for last message date for an identity\r
161         SQLite3DB::Statement countst=m_db->Prepare("SELECT COUNT(*) FROM tblMessage WHERE IdentityID=? AND MessageDate>=?;");\r
162 \r
163         // build the xml file - we only want to add identities that we recently saw, otherwise we could be inserting a ton of identities\r
164         date-=Poco::Timespan(15,0,0,0,0);       // identities seen in last 15 days - the maintenance page lets us delete identities not seen in 20 days, so this gives us a window where the identity won't be deleted and then found in a trust list and readded immediately\r
165         //SQLite3DB::Statement st=m_db->Prepare("SELECT PublicKey, LocalMessageTrust, LocalTrustListTrust, MessageTrustComment, TrustListTrustComment FROM tblIdentity WHERE PublicKey IS NOT NULL AND PublicKey<>'' AND LastSeen>=?;");\r
166         // we want to order by public key so we can't do identity correllation based on the sequence of identities in the list.\r
167         SQLite3DB::Statement st=m_db->Prepare("SELECT PublicKey, tblIdentityTrust.LocalMessageTrust, tblIdentityTrust.LocalTrustListTrust, tblIdentityTrust.MessageTrustComment, tblIdentityTrust.TrustListTrustComment, tblIdentity.IdentityID, tblIdentity.DateAdded FROM tblIdentity INNER JOIN tblIdentityTrust ON tblIdentity.IdentityID=tblIdentityTrust.IdentityID WHERE PublicKey IS NOT NULL AND PublicKey<>'' AND LastSeen>=? AND tblIdentityTrust.LocalIdentityID=? ORDER BY PublicKey;");\r
168         st.Bind(0,Poco::DateTimeFormatter::format(date,"%Y-%m-%d"));\r
169         st.Bind(1,localidentityid);\r
170         st.Step();\r
171         while(st.RowReturned())\r
172         {\r
173                 st.ResultText(0,publickey);\r
174                 if(st.ResultNull(1)==false)\r
175                 {\r
176                         st.ResultInt(1,messagetrust);\r
177                 }\r
178                 else\r
179                 {\r
180                         messagetrust=-1;\r
181                 }\r
182                 if(st.ResultNull(2)==false)\r
183                 {\r
184                         st.ResultInt(2,trustlisttrust);\r
185                 }\r
186                 else\r
187                 {\r
188                         trustlisttrust=-1;\r
189                 }\r
190                 st.ResultText(3,messagetrustcomment);\r
191                 st.ResultText(4,trustlisttrustcomment);\r
192                 identityid=-1;\r
193                 st.ResultInt(5,identityid);\r
194                 dateadded="";\r
195                 st.ResultText(6,dateadded);\r
196 \r
197                 add=false;\r
198 \r
199                 // add the identity to the trust list if they have posted a message in the last 30 days\r
200                 countst.Bind(0,identityid);\r
201                 countst.Bind(1,Poco::DateTimeFormatter::format(dateminus30,"%Y-%m-%d"));\r
202                 countst.Step();\r
203                 if(countst.RowReturned())\r
204                 {\r
205                         count=0;\r
206                         countst.ResultInt(0,count);\r
207                         if(count>0)\r
208                         {\r
209                                 add=true;\r
210                         }\r
211                 }\r
212                 countst.Reset();\r
213 \r
214                 // no messages in last 30 days - add the identity if we learned about them less than 5 days ago\r
215                 if(add==false && dateadded!="")\r
216                 {\r
217                         int tzdiff=0;\r
218                         if(Poco::DateTimeParser::tryParse(dateadded,tempdate,tzdiff)==false)\r
219                         {\r
220                                 tempdate=Poco::Timestamp();\r
221                                 m_log->fatal("TrustListInserter::StartInsert could not parse date "+dateadded);\r
222                         }\r
223                         if(tempdate>=(now-Poco::Timespan(5,0,0,0,0)))\r
224                         {\r
225                                 add=true;\r
226                         }\r
227                 }\r
228 \r
229                 if(add==true)\r
230                 {\r
231                         xml.AddTrust(publickey,messagetrust,trustlisttrust,messagetrustcomment,trustlisttrustcomment);\r
232                 }\r
233 \r
234                 st.Step();\r
235         }\r
236 \r
237         // get next insert index\r
238         st=m_db->Prepare("SELECT MAX(InsertIndex) FROM tblTrustListInserts WHERE LocalIdentityID=? AND Day=?;");\r
239         st.Bind(0,localidentityid);\r
240         st.Bind(1,Poco::DateTimeFormatter::format(now,"%Y-%m-%d"));\r
241         st.Step();\r
242 \r
243         index=0;\r
244         if(st.RowReturned() && st.ResultNull(0)==false)\r
245         {\r
246                 st.ResultInt(0,index);\r
247                 index++;\r
248         }\r
249 \r
250         StringFunctions::Convert(localidentityid,localidentityidstr);\r
251         StringFunctions::Convert(index,indexstr);\r
252 \r
253         data=xml.GetXML();\r
254         StringFunctions::Convert(data.size(),datasizestr);\r
255 \r
256         message.SetName("ClientPut");\r
257         message["URI"]=privatekey+m_messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"|TrustList|"+indexstr+".xml";\r
258         message["Identifier"]="TrustListInserter|"+localidentityidstr+"|"+indexstr+"|"+message["URI"];\r
259         message["UploadFrom"]="direct";\r
260         message["DataLength"]=datasizestr;\r
261         m_fcp->Send(message);\r
262         m_fcp->Send(std::vector<char>(data.begin(),data.end()));\r
263 \r
264         // insert to USK\r
265         message.Clear();\r
266         message.SetName("ClientPutComplexDir");\r
267         message["URI"]="USK"+privatekey.substr(3)+m_messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y.%m.%d")+"|TrustList/0/";\r
268         message["Identifier"]="TrustListInserterUSK|"+message["URI"];\r
269         message["DefaultName"]="TrustList.xml";\r
270         message["Files.0.Name"]="TrustList.xml";\r
271         message["Files.0.UplaodFrom"]="direct";\r
272         message["Files.0.DataLength"]=datasizestr;\r
273         m_fcp->Send(message);\r
274         m_fcp->Send(std::vector<char>(data.begin(),data.end()));\r
275 \r
276         m_db->Execute("UPDATE tblLocalIdentity SET InsertingTrustList='true' WHERE LocalIdentityID="+localidentityidstr+";");\r
277 \r
278 }\r