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