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