eb95e918ebdcc6074c083371d62a4527074f1b77
[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         m_fcp->ReceiveRaw(&data[0],datalength);\r
85 \r
86         // parse file into xml and update the database\r
87         if(xml.ParseXML(std::string(data.begin(),data.end()))==true)\r
88         {\r
89 \r
90                 SQLite3DB::Statement brd=m_db->Prepare("SELECT BoardID,BoardName,BoardDescription FROM tblBoard WHERE BoardName=?;");\r
91                 SQLite3DB::Statement ins=m_db->Prepare("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,SaveReceivedMessages,AddedMethod) VALUES(?,?,?,?,?);");\r
92                 SQLite3DB::Statement upd=m_db->Prepare("UPDATE tblBoard SET BoardDescription=? WHERE BoardID=?;");\r
93                 for(long i=0; i<xml.GetCount(); i++)\r
94                 {\r
95                         int boardid;\r
96                         std::string name="";\r
97                         std::string description="";\r
98 \r
99                         brd.Bind(0,xml.GetName(i));\r
100                         brd.Step();\r
101                         \r
102                         if(brd.RowReturned())\r
103                         {\r
104                                 brd.ResultInt(0,boardid);\r
105                                 brd.ResultText(2,description);\r
106                                 if(description=="" && xml.GetDescription(i)!="")\r
107                                 {\r
108                                         upd.Bind(0,xml.GetDescription(i));\r
109                                         upd.Bind(1,boardid);\r
110                                         upd.Step();\r
111                                         upd.Reset();\r
112                                 }\r
113                         }\r
114                         else\r
115                         {\r
116                                 ins.Bind(0,xml.GetName(i));\r
117                                 ins.Bind(1,xml.GetDescription(i));\r
118                                 ins.Bind(2,Poco::DateTimeFormatter::format(now,"%Y-%m-%d %H:%M:%S"));\r
119                                 if(m_savemessagesfromnewboards)\r
120                                 {\r
121                                         ins.Bind(3,"true");\r
122                                 }\r
123                                 else\r
124                                 {\r
125                                         ins.Bind(3,"false");\r
126                                 }\r
127                                 ins.Bind(4,"Board List of "+identityname);\r
128                                 ins.Step();\r
129                                 ins.Reset();\r
130                         }\r
131                         brd.Reset();\r
132                 }\r
133 \r
134                 st=m_db->Prepare("INSERT INTO tblBoardListRequests(IdentityID,Day,RequestIndex,Found) VALUES(?,?,?,'true');");\r
135                 st.Bind(0,identityid);\r
136                 st.Bind(1,idparts[4]);\r
137                 st.Bind(2,index);\r
138                 st.Step();\r
139                 st.Finalize();\r
140 \r
141                 m_log->debug("BoardListRequester::HandleAllData parsed BoardList XML file : "+message["Identifier"]);\r
142         }\r
143         else\r
144         {\r
145                 // bad data - mark index\r
146                 st=m_db->Prepare("INSERT INTO tblBoardListRequests(IdentityID,Day,RequestIndex,Found) VALUES(?,?,?,'false');");\r
147                 st.Bind(0,identityid);\r
148                 st.Bind(1,idparts[4]);\r
149                 st.Bind(2,index);\r
150                 st.Step();\r
151                 st.Finalize();\r
152 \r
153                 m_log->error("BoardListRequester::HandleAllData error parsing BoardList XML file : "+message["Identifier"]);\r
154         }\r
155 \r
156         // remove this identityid from request list\r
157         RemoveFromRequestList(identityid);\r
158 \r
159         return true;\r
160 \r
161 }\r
162 \r
163 const bool BoardListRequester::HandleGetFailed(FCPMessage &message)\r
164 {\r
165         SQLite3DB::Statement st;\r
166         std::vector<std::string> idparts;\r
167         long identityid;\r
168         long index;\r
169 \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->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()->GetInt("MaxBoardListRequests",m_maxrequests);\r
201         if(m_maxrequests<0)\r
202         {\r
203                 m_maxrequests=0;\r
204                 m_log->error("Option MaxBoardListRequests is currently set at "+tempval+".  It must be 0 or greater.");\r
205         }\r
206         if(m_maxrequests>100)\r
207         {\r
208                 m_log->warning("Option MaxBoardListRequests is currently set at "+tempval+".  This value might be incorrectly configured.");\r
209         }\r
210 \r
211         Option::Instance()->Get("SaveMessagesFromNewBoards",tempval);\r
212         if(tempval=="true")\r
213         {\r
214                 m_savemessagesfromnewboards=true;\r
215         }\r
216         else\r
217         {\r
218                 m_savemessagesfromnewboards=false;\r
219         }\r
220 \r
221         Option::Instance()->Get("LocalTrustOverridesPeerTrust",tempval);\r
222         if(tempval=="true")\r
223         {\r
224                 m_localtrustoverrides=true;\r
225         }\r
226         else\r
227         {\r
228                 m_localtrustoverrides=false;\r
229         }\r
230 \r
231 }\r
232 \r
233 void BoardListRequester::PopulateIDList()\r
234 {\r
235         int id;\r
236         Poco::DateTime today;\r
237 \r
238         SQLite3DB::Statement st;\r
239 \r
240         if(m_localtrustoverrides==false)\r
241         {\r
242                 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
243         }\r
244         else\r
245         {\r
246                 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
247         }\r
248         st.Step();\r
249 \r
250         m_ids.clear();\r
251 \r
252         while(st.RowReturned())\r
253         {\r
254                 st.ResultInt(0,id);\r
255                 m_ids[id]=false;\r
256                 st.Step();\r
257         }\r
258 \r
259 }\r
260 \r
261 void BoardListRequester::StartRequest(const long &identityid)\r
262 {\r
263         Poco::DateTime now;\r
264         FCPMessage message;\r
265         std::string publickey;\r
266         std::string indexstr;\r
267         int index;\r
268         std::string identityidstr;\r
269 \r
270         SQLite3DB::Statement st=m_db->Prepare("SELECT PublicKey FROM tblIdentity WHERE identityid=?;");\r
271         st.Bind(0,identityid);\r
272         st.Step();\r
273 \r
274         if(st.RowReturned())\r
275         {\r
276                 st.ResultText(0,publickey);\r
277 \r
278                 SQLite3DB::Statement st2=m_db->Prepare("SELECT MAX(RequestIndex) FROM tblBoardListRequests WHERE Day=? AND IdentityID=?;");\r
279                 st2.Bind(0,Poco::DateTimeFormatter::format(now,"%Y-%m-%d"));\r
280                 st2.Bind(1,identityid);\r
281                 st2.Step();\r
282 \r
283                 index=0;\r
284                 if(st2.RowReturned())\r
285                 {\r
286                         if(st2.ResultNull(0)==false)\r
287                         {\r
288                                 st2.ResultInt(0,index);\r
289                                 index++;\r
290                         }\r
291                 }\r
292                 st2.Finalize();\r
293 \r
294                 StringFunctions::Convert(index,indexstr);\r
295                 StringFunctions::Convert(identityid,identityidstr);\r
296 \r
297                 message.SetName("ClientGet");\r
298                 message["URI"]=publickey+m_messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"|BoardList|"+indexstr+".xml";\r
299                 message["Identifier"]=m_fcpuniquename+"|"+identityidstr+"|"+indexstr+"|"+message["URI"];\r
300                 message["ReturnType"]="direct";\r
301                 message["MaxSize"]="100000";                    // 100 KB\r
302 \r
303                 m_fcp->SendMessage(message);\r
304 \r
305                 m_requesting.push_back(identityid);\r
306 \r
307         }\r
308         st.Finalize();\r
309 \r
310         m_ids[identityid]=true;\r
311 \r
312 }\r