version 0.3.20
[fms.git] / src / freenet / boardlistrequester.cpp
1 #include "../../include/freenet/boardlistrequester.h"\r
2 #include "../../include/freenet/boardlistxml.h"\r
3 \r
4 #include <Poco/DateTime.h>\r
5 #include <Poco/DateTimeFormatter.h>\r
6 \r
7 #ifdef XMEM\r
8         #include <xmem.h>\r
9 #endif\r
10 \r
11 BoardListRequester::BoardListRequester()\r
12 {\r
13         Initialize();\r
14 }\r
15 \r
16 BoardListRequester::BoardListRequester(FCPv2 *fcp):IIndexRequester<long>(fcp)\r
17 {\r
18         Initialize();\r
19 }\r
20 \r
21 std::string BoardListRequester::GetIdentityName(const long identityid)\r
22 {\r
23         SQLite3DB::Statement st=m_db->Prepare("SELECT Name,PublicKey FROM tblIdentity WHERE IdentityID=?;");\r
24         st.Bind(0,identityid);\r
25         st.Step();\r
26         if(st.RowReturned())\r
27         {\r
28                 std::vector<std::string> keyparts;\r
29                 std::string key;\r
30                 std::string name;\r
31                 st.ResultText(0,name);\r
32                 st.ResultText(1,key);\r
33                 \r
34                 StringFunctions::SplitMultiple(key,"@,",keyparts);\r
35                 \r
36                 if(keyparts.size()>1)\r
37                 {\r
38                         return name+"@"+keyparts[1];\r
39                 }\r
40                 else\r
41                 {\r
42                         return name+"@invalidpublickey";\r
43                 }\r
44         }\r
45         else\r
46         {\r
47                 return "";\r
48         }\r
49 }\r
50 \r
51 const bool BoardListRequester::HandleAllData(FCPMessage &message)\r
52 {       \r
53         Poco::DateTime now;\r
54         SQLite3DB::Statement st;\r
55         std::vector<std::string> idparts;\r
56         long datalength;\r
57         std::vector<char> data;\r
58         BoardListXML xml;\r
59         long identityid;\r
60         long index;\r
61         std::string identityname="";\r
62 \r
63         StringFunctions::Split(message["Identifier"],"|",idparts);\r
64         StringFunctions::Convert(message["DataLength"],datalength);\r
65         StringFunctions::Convert(idparts[1],identityid);\r
66         StringFunctions::Convert(idparts[2],index);\r
67 \r
68         identityname=GetIdentityName(identityid);\r
69 \r
70         // wait for all data to be received from connection\r
71         while(m_fcp->Connected() && m_fcp->ReceiveBufferSize()<datalength)\r
72         {\r
73                 m_fcp->Update(1);\r
74         }\r
75 \r
76         // if we got disconnected- return immediately\r
77         if(m_fcp->Connected()==false)\r
78         {\r
79                 return false;\r
80         }\r
81 \r
82         // receive the file\r
83         data.resize(datalength);\r
84         if(data.size()>0)\r
85         {\r
86                 m_fcp->ReceiveRaw(&data[0],datalength);\r
87         }\r
88 \r
89         // parse file into xml and update the database\r
90         if(data.size()>0 && xml.ParseXML(std::string(data.begin(),data.end()))==true)\r
91         {\r
92 \r
93                 SQLite3DB::Statement brd=m_db->Prepare("SELECT BoardID,BoardName,BoardDescription FROM tblBoard WHERE BoardName=?;");\r
94                 SQLite3DB::Statement ins=m_db->Prepare("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,SaveReceivedMessages,AddedMethod) VALUES(?,?,?,?,?);");\r
95                 SQLite3DB::Statement upd=m_db->Prepare("UPDATE tblBoard SET BoardDescription=? WHERE BoardID=?;");\r
96                 for(long i=0; i<xml.GetCount(); i++)\r
97                 {\r
98                         int boardid;\r
99                         std::string name="";\r
100                         std::string description="";\r
101 \r
102                         brd.Bind(0,xml.GetName(i));\r
103                         brd.Step();\r
104                         \r
105                         if(brd.RowReturned())\r
106                         {\r
107                                 brd.ResultInt(0,boardid);\r
108                                 brd.ResultText(2,description);\r
109                                 if(description=="" && xml.GetDescription(i)!="")\r
110                                 {\r
111                                         upd.Bind(0,xml.GetDescription(i));\r
112                                         upd.Bind(1,boardid);\r
113                                         upd.Step();\r
114                                         upd.Reset();\r
115                                 }\r
116                         }\r
117                         else\r
118                         {\r
119                                 ins.Bind(0,xml.GetName(i));\r
120                                 ins.Bind(1,xml.GetDescription(i));\r
121                                 ins.Bind(2,Poco::DateTimeFormatter::format(now,"%Y-%m-%d %H:%M:%S"));\r
122                                 if(m_savemessagesfromnewboards)\r
123                                 {\r
124                                         ins.Bind(3,"true");\r
125                                 }\r
126                                 else\r
127                                 {\r
128                                         ins.Bind(3,"false");\r
129                                 }\r
130                                 ins.Bind(4,"Board List of "+identityname);\r
131                                 ins.Step();\r
132                                 ins.Reset();\r
133                         }\r
134                         brd.Reset();\r
135                 }\r
136 \r
137                 st=m_db->Prepare("INSERT INTO tblBoardListRequests(IdentityID,Day,RequestIndex,Found) VALUES(?,?,?,'true');");\r
138                 st.Bind(0,identityid);\r
139                 st.Bind(1,idparts[4]);\r
140                 st.Bind(2,index);\r
141                 st.Step();\r
142                 st.Finalize();\r
143 \r
144                 m_log->debug("BoardListRequester::HandleAllData parsed BoardList XML file : "+message["Identifier"]);\r
145         }\r
146         else\r
147         {\r
148                 // bad data - mark index\r
149                 st=m_db->Prepare("INSERT INTO tblBoardListRequests(IdentityID,Day,RequestIndex,Found) VALUES(?,?,?,'false');");\r
150                 st.Bind(0,identityid);\r
151                 st.Bind(1,idparts[4]);\r
152                 st.Bind(2,index);\r
153                 st.Step();\r
154                 st.Finalize();\r
155 \r
156                 m_log->error("BoardListRequester::HandleAllData error parsing BoardList XML file : "+message["Identifier"]);\r
157         }\r
158 \r
159         // remove this identityid from request list\r
160         RemoveFromRequestList(identityid);\r
161 \r
162         return true;\r
163 \r
164 }\r
165 \r
166 const bool BoardListRequester::HandleGetFailed(FCPMessage &message)\r
167 {\r
168         SQLite3DB::Statement st;\r
169         std::vector<std::string> idparts;\r
170         long identityid;\r
171         long index;\r
172 \r
173         StringFunctions::Split(message["Identifier"],"|",idparts);\r
174         StringFunctions::Convert(idparts[1],identityid);\r
175         StringFunctions::Convert(idparts[2],index);     \r
176 \r
177         // if this is a fatal error - insert index into database so we won't try to download this index again\r
178         if(message["Fatal"]=="true")\r
179         {\r
180                 st=m_db->Prepare("INSERT INTO tblBoardListRequests(IdentityID,Day,RequestIndex,Found) VALUES(?,?,?,'false');");\r
181                 st.Bind(0,identityid);\r
182                 st.Bind(1,idparts[4]);\r
183                 st.Bind(2,index);\r
184                 st.Step();\r
185                 st.Finalize();\r
186 \r
187                 m_log->error("BoardListRequester::HandleGetFailed fatal error requesting "+message["Identifier"]);\r
188         }\r
189 \r
190         // remove this identityid from request list\r
191         RemoveFromRequestList(identityid);\r
192 \r
193         return true;\r
194 }\r
195 \r
196 void BoardListRequester::Initialize()\r
197 {\r
198         std::string tempval="";\r
199 \r
200         m_fcpuniquename="BoardListRequester";\r
201         m_maxrequests=0;\r
202 \r
203         Option::Instance()->GetInt("MaxBoardListRequests",m_maxrequests);\r
204         if(m_maxrequests<0)\r
205         {\r
206                 m_maxrequests=0;\r
207                 m_log->error("Option MaxBoardListRequests is currently set at "+tempval+".  It must be 0 or greater.");\r
208         }\r
209         if(m_maxrequests>100)\r
210         {\r
211                 m_log->warning("Option MaxBoardListRequests is currently set at "+tempval+".  This value might be incorrectly configured.");\r
212         }\r
213 \r
214         Option::Instance()->Get("SaveMessagesFromNewBoards",tempval);\r
215         if(tempval=="true")\r
216         {\r
217                 m_savemessagesfromnewboards=true;\r
218         }\r
219         else\r
220         {\r
221                 m_savemessagesfromnewboards=false;\r
222         }\r
223 \r
224         Option::Instance()->Get("LocalTrustOverridesPeerTrust",tempval);\r
225         if(tempval=="true")\r
226         {\r
227                 m_localtrustoverrides=true;\r
228         }\r
229         else\r
230         {\r
231                 m_localtrustoverrides=false;\r
232         }\r
233 \r
234 }\r
235 \r
236 void BoardListRequester::PopulateIDList()\r
237 {\r
238         int id;\r
239         Poco::DateTime today;\r
240 \r
241         SQLite3DB::Statement st;\r
242 \r
243         if(m_localtrustoverrides==false)\r
244         {\r
245                 st=m_db->Prepare("SELECT IdentityID FROM tblIdentity WHERE PublicKey IS NOT NULL AND PublicKey <> '' AND LastSeen>='"+Poco::DateTimeFormatter::format(today,"%Y-%m-%d")+"' AND (LocalMessageTrust IS NULL OR LocalMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalMessageTrust')) AND (PeerMessageTrust IS NULL OR PeerMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerMessageTrust')) AND PublishBoardList='true' ORDER BY LocalMessageTrust+LocalTrustListTrust DESC, LastSeen;");\r
246         }\r
247         else\r
248         {\r
249                 st=m_db->Prepare("SELECT IdentityID FROM tblIdentity WHERE PublicKey IS NOT NULL AND PublicKey <> '' AND LastSeen>='"+Poco::DateTimeFormatter::format(today,"%Y-%m-%d")+"' AND (LocalMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalMessageTrust') OR (LocalMessageTrust IS NULL AND (PeerMessageTrust IS NULL OR PeerMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerMessageTrust')))) AND PublishBoardList='true' ORDER BY LocalMessageTrust+LocalTrustListTrust DESC, LastSeen;");\r
250         }\r
251         st.Step();\r
252 \r
253         m_ids.clear();\r
254 \r
255         while(st.RowReturned())\r
256         {\r
257                 st.ResultInt(0,id);\r
258                 m_ids[id]=false;\r
259                 st.Step();\r
260         }\r
261 \r
262 }\r
263 \r
264 void BoardListRequester::StartRequest(const long &identityid)\r
265 {\r
266         Poco::DateTime now;\r
267         FCPMessage message;\r
268         std::string publickey;\r
269         std::string indexstr;\r
270         int index;\r
271         std::string identityidstr;\r
272 \r
273         SQLite3DB::Statement st=m_db->Prepare("SELECT PublicKey FROM tblIdentity WHERE identityid=?;");\r
274         st.Bind(0,identityid);\r
275         st.Step();\r
276 \r
277         if(st.RowReturned())\r
278         {\r
279                 st.ResultText(0,publickey);\r
280 \r
281                 SQLite3DB::Statement st2=m_db->Prepare("SELECT MAX(RequestIndex) FROM tblBoardListRequests WHERE Day=? AND IdentityID=?;");\r
282                 st2.Bind(0,Poco::DateTimeFormatter::format(now,"%Y-%m-%d"));\r
283                 st2.Bind(1,identityid);\r
284                 st2.Step();\r
285 \r
286                 index=0;\r
287                 if(st2.RowReturned())\r
288                 {\r
289                         if(st2.ResultNull(0)==false)\r
290                         {\r
291                                 st2.ResultInt(0,index);\r
292                                 index++;\r
293                         }\r
294                 }\r
295                 st2.Finalize();\r
296 \r
297                 StringFunctions::Convert(index,indexstr);\r
298                 StringFunctions::Convert(identityid,identityidstr);\r
299 \r
300                 message.SetName("ClientGet");\r
301                 message["URI"]=publickey+m_messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"|BoardList|"+indexstr+".xml";\r
302                 message["Identifier"]=m_fcpuniquename+"|"+identityidstr+"|"+indexstr+"|"+message["URI"];\r
303                 message["ReturnType"]="direct";\r
304                 message["MaxSize"]="100000";                    // 100 KB\r
305 \r
306                 m_fcp->SendMessage(message);\r
307 \r
308                 m_requesting.push_back(identityid);\r
309 \r
310         }\r
311         st.Finalize();\r
312 \r
313         m_ids[identityid]=true;\r
314 \r
315 }\r