version 0.3.0
[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()->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->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->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         Poco::DateTime today;\r
238 \r
239         SQLite3DB::Statement st;\r
240 \r
241         if(m_localtrustoverrides==false)\r
242         {\r
243                 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
244         }\r
245         else\r
246         {\r
247                 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
248         }\r
249         st.Step();\r
250 \r
251         m_ids.clear();\r
252 \r
253         while(st.RowReturned())\r
254         {\r
255                 st.ResultInt(0,id);\r
256                 m_ids[id]=false;\r
257                 st.Step();\r
258         }\r
259 \r
260 }\r
261 \r
262 void BoardListRequester::StartRequest(const long &identityid)\r
263 {\r
264         Poco::DateTime now;\r
265         FCPMessage message;\r
266         std::string publickey;\r
267         std::string indexstr;\r
268         int index;\r
269         std::string identityidstr;\r
270 \r
271         SQLite3DB::Statement st=m_db->Prepare("SELECT PublicKey FROM tblIdentity WHERE identityid=?;");\r
272         st.Bind(0,identityid);\r
273         st.Step();\r
274 \r
275         if(st.RowReturned())\r
276         {\r
277                 st.ResultText(0,publickey);\r
278 \r
279                 SQLite3DB::Statement st2=m_db->Prepare("SELECT MAX(RequestIndex) FROM tblBoardListRequests WHERE Day=? AND IdentityID=?;");\r
280                 st2.Bind(0,Poco::DateTimeFormatter::format(now,"%Y-%m-%d"));\r
281                 st2.Bind(1,identityid);\r
282                 st2.Step();\r
283 \r
284                 index=0;\r
285                 if(st2.RowReturned())\r
286                 {\r
287                         if(st2.ResultNull(0)==false)\r
288                         {\r
289                                 st2.ResultInt(0,index);\r
290                                 index++;\r
291                         }\r
292                 }\r
293                 st2.Finalize();\r
294 \r
295                 StringFunctions::Convert(index,indexstr);\r
296                 StringFunctions::Convert(identityid,identityidstr);\r
297 \r
298                 message.SetName("ClientGet");\r
299                 message["URI"]=publickey+m_messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"|BoardList|"+indexstr+".xml";\r
300                 message["Identifier"]=m_fcpuniquename+"|"+identityidstr+"|"+indexstr+"|"+message["URI"];\r
301                 message["ReturnType"]="direct";\r
302                 message["MaxSize"]="100000";                    // 100 KB\r
303 \r
304                 m_fcp->SendMessage(message);\r
305 \r
306                 m_requesting.push_back(identityid);\r
307 \r
308         }\r
309         st.Finalize();\r
310 \r
311         m_ids[identityid]=true;\r
312 \r
313 }\r