9db96517ed98b5378c897ea470d9651bc8d1918b
[fms.git] / src / freenet / siteinserter.cpp
1 #include "../../include/freenet/siteinserter.h"\r
2 #include "../../include/global.h"\r
3 \r
4 #ifdef XMEM\r
5         #include <xmem.h>\r
6 #endif\r
7 \r
8 SiteInserter::SiteInserter()\r
9 {\r
10         Initialize();\r
11 }\r
12 \r
13 SiteInserter::SiteInserter(FCPv2 *fcp):IIndexInserter<long>(fcp)\r
14 {\r
15         Initialize();\r
16 }\r
17 \r
18 void SiteInserter::CheckForNeededInsert()\r
19 {\r
20         // only do 1 insert at a time\r
21         if(m_inserting.size()==0)\r
22         {\r
23                 DateTime date;\r
24                 date.SetToGMTime();\r
25 \r
26                 SQLite3DB::Statement st=m_db->Prepare("SELECT LocalIdentityID FROM tblLocalIdentity WHERE PublishFreesite='true' AND (LastInsertedFreesite IS NULL OR LastInsertedFreesite<?);");\r
27                 st.Bind(0,date.Format("%Y-%m-%d"));\r
28 \r
29                 st.Step();\r
30                 if(st.RowReturned())\r
31                 {\r
32                         int localidentityid=0;\r
33                         st.ResultInt(0,localidentityid);\r
34                         StartInsert(localidentityid);\r
35                 }\r
36         }\r
37 }\r
38 \r
39 std::string SiteInserter::GenerateIndex(const std::string &htmltemplate, const long localidentityid, const std::string &name)\r
40 {\r
41         std::string content="";\r
42 \r
43         content="<h2>FMS site of "+SanitizeOutput(name)+"</h2>";\r
44 \r
45         content+="<h3>My last few posts</h3>";\r
46 \r
47         SQLite3DB::Statement boardst=m_db->Prepare("SELECT tblBoard.BoardName FROM tblBoard INNER JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID WHERE tblMessageBoard.MessageID=? ORDER BY tblBoard.BoardName COLLATE NOCASE;");\r
48         SQLite3DB::Statement st=m_db->Prepare("SELECT tblMessage.Body, tblMessage.Subject, tblMessage.MessageID FROM tblMessage INNER JOIN tblIdentity ON tblMessage.IdentityID=tblIdentity.IdentityID INNER JOIN tblLocalIdentity ON tblIdentity.PublicKey=tblLocalIdentity.PublicKey WHERE tblLocalIdentity.LocalIdentityID=? ORDER BY tblMessage.MessageDate DESC, tblMessage.MessageTime DESC LIMIT 0,10;");\r
49         st.Bind(0,localidentityid);\r
50         st.Step();\r
51 \r
52         while(st.RowReturned())\r
53         {\r
54                 std::string post="";\r
55                 std::string subject="";\r
56                 std::string boards="";\r
57                 int messageid=0;\r
58 \r
59                 st.ResultText(0,post);\r
60                 st.ResultText(1,subject);\r
61                 st.ResultInt(2,messageid);\r
62 \r
63                 boardst.Bind(0,messageid);\r
64                 boardst.Step();\r
65                 while(boardst.RowReturned())\r
66                 {\r
67                         std::string board="";\r
68                         boardst.ResultText(0,board);\r
69                         if(boards!="")\r
70                         {\r
71                                 boards+=",";\r
72                         }\r
73                         boards+=board;\r
74                         boardst.Step();\r
75                 }\r
76                 boardst.Reset();\r
77 \r
78                 content+="<div class=\"post\">";\r
79                 content+="<div class=\"postboards\">";\r
80                 content+=SanitizeOutput(boards);\r
81                 content+="</div>";\r
82                 content+="<div class=\"postsubject\">";\r
83                 content+=SanitizeOutput(subject);\r
84                 content+="</div>";\r
85                 content+="<div class=\"postbody\">";\r
86                 content+=SanitizeOutput(post);\r
87                 content+="</div>";\r
88                 content+="</div>";\r
89 \r
90                 st.Step();\r
91         }\r
92 \r
93         return StringFunctions::Replace(htmltemplate,"[CONTENT]",content);\r
94 \r
95 }\r
96 \r
97 std::string SiteInserter::GenerateLinks(const bool publishtrustlist, const bool publishboardlist)\r
98 {\r
99         std::string links="";\r
100         links+="<ul>";\r
101         links+="<li><a href=\"index.htm\">Home</a></li>";\r
102         if(publishtrustlist)\r
103         {\r
104                 links+="<li><a href=\"trustlist.htm\">Trust List</a></li>";\r
105         }\r
106         if(publishboardlist)\r
107         {\r
108 //              links+="<li><a href=\"boardlist.htm\">Board List</a></li>";\r
109         }\r
110         links+="</ul>";\r
111         return links;\r
112 }\r
113 \r
114 void SiteInserter::GeneratePages(const long localidentityid, std::string &uskkey, std::map<std::string,std::string> &pages)\r
115 {\r
116         SQLite3DB::Statement st=m_db->Prepare("SELECT Name, PrivateKey, PublishTrustList, PublishBoardList FROM tblLocalIdentity WHERE LocalIdentityID=?;");\r
117         st.Bind(0,localidentityid);\r
118         st.Step();\r
119 \r
120         if(st.RowReturned())\r
121         {\r
122                 std::string htmltemplate="";\r
123                 std::string filename="";\r
124                 std::string name="";\r
125                 std::string key="";\r
126                 std::string publishtrustliststr="";\r
127                 std::string publishboardliststr="";\r
128                 bool publishtrustlist=false;\r
129                 bool publishboardlist=false;\r
130 \r
131                 st.ResultText(0,name);\r
132                 st.ResultText(1,key);\r
133                 st.ResultText(2,publishtrustliststr);\r
134                 st.ResultText(3,publishboardliststr);\r
135 \r
136                 publishtrustliststr=="true" ? publishtrustlist=true : publishtrustlist=false;\r
137                 publishboardliststr=="true" ? publishboardlist=true : publishboardlist=false;\r
138 \r
139                 filename=name+"-template.htm";\r
140                 FILE *infile=fopen(filename.c_str(),"r+b");\r
141                 if(!infile)\r
142                 {\r
143                         infile=fopen("site-template.htm","r+b");\r
144                 }\r
145                 if(infile)\r
146                 {\r
147                         fseek(infile,0,SEEK_END);\r
148                         long len=ftell(infile);\r
149                         fseek(infile,0,SEEK_SET);\r
150 \r
151                         std::vector<unsigned char> data;\r
152                         data.resize(len);\r
153                         fread(&data[0],1,data.size(),infile);\r
154                         fclose(infile);\r
155 \r
156                         htmltemplate.append(data.begin(),data.end());\r
157 \r
158                         htmltemplate=StringFunctions::Replace(htmltemplate,"[LINKS]",GenerateLinks(publishtrustlist,publishboardlist));\r
159 \r
160                         pages["index.htm"]=GenerateIndex(htmltemplate,localidentityid,name);\r
161                         if(publishtrustlist)\r
162                         {\r
163                                 pages["trustlist.htm"]=GenerateTrustList(htmltemplate,localidentityid,name);\r
164                         }\r
165                         if(publishboardlist)\r
166                         {\r
167 //                              pages["boardlist.htm"]=GenerateBoardList(htmltemplate,localidentityid,name);\r
168                         }\r
169 \r
170                         // make SSK a USK\r
171                         if(key.find("SSK@")==0)\r
172                         {\r
173                                 key.erase(0,3);\r
174                                 key="USK"+key;\r
175                         }\r
176                         key+=m_messagebase+"/0/";\r
177                         uskkey=key;\r
178 \r
179                 }\r
180                 else\r
181                 {\r
182                         LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_ERROR,"SiteInserter::GeneratePages unable to open "+filename+" or site-template.htm.");\r
183                 }\r
184 \r
185         }\r
186 }\r
187 \r
188 std::string SiteInserter::GenerateTrustList(const std::string &htmltemplate, const long localidentityid, const std::string &name)\r
189 {\r
190         std::string content="";\r
191         DateTime date;\r
192 \r
193         date.SetToGMTime();\r
194         date.Add(0,0,0,-20);\r
195         SQLite3DB::Statement st=m_db->Prepare("SELECT Name,PublicKey,tblIdentityTrust.LocalMessageTrust,tblIdentityTrust.LocalTrustListTrust,tblIdentity.IdentityID,tblIdentityTrust.MessageTrustComment,tblIdentityTrust.TrustListTrustComment,tblIdentity.FreesiteEdition FROM tblIdentity LEFT JOIN (SELECT IdentityID,LocalMessageTrust,LocalTrustListTrust,MessageTrustComment,TrustListTrustComment FROM tblIdentityTrust WHERE LocalIdentityID=?) AS 'tblIdentityTrust' ON tblIdentity.IdentityID=tblIdentityTrust.IdentityID WHERE PublicKey IS NOT NULL AND LastSeen IS NOT NULL AND LastSeen>=? ORDER BY Name COLLATE NOCASE;");\r
196         st.Bind(0,localidentityid);\r
197         st.Bind(1,date.Format("%Y-%m-%d %H:%M:%S"));\r
198         st.Step();\r
199 \r
200         content+="<table>";\r
201         content+="<tr><th colspan=\"5\">";\r
202         content+="Trust List of "+SanitizeOutput(name);\r
203         content+="</th></tr>";\r
204         content+="<tr><td></td><th>Message Trust</th><th>Message Comment</th><th>Trust List Trust</th><th>Trust Comment</th></tr>";\r
205         while(st.RowReturned())\r
206         {\r
207                 std::string idname="";\r
208                 std::string thisid="";\r
209                 std::string messagetrustcomment="";\r
210                 std::string trustlisttrustcomment="";\r
211                 std::string messagetrust="";\r
212                 std::string trustlisttrust="";\r
213                 std::string publickey="";\r
214                 std::string uskkey="";\r
215                 std::string freesiteedition="";\r
216 \r
217                 st.ResultText(0,idname);\r
218                 st.ResultText(1,publickey);\r
219                 st.ResultText(2,messagetrust);\r
220                 st.ResultText(3,trustlisttrust);\r
221                 st.ResultText(4,thisid);\r
222                 st.ResultText(5,messagetrustcomment);\r
223                 st.ResultText(6,trustlisttrustcomment);\r
224                 st.ResultText(7,freesiteedition);\r
225 \r
226                 if(freesiteedition!="")\r
227                 {\r
228                         if(publickey.find("SSK@")==0)\r
229                         {\r
230                                 uskkey=publickey;\r
231                                 uskkey.erase(0,3);\r
232                                 uskkey="USK"+uskkey;\r
233                                 uskkey+=m_messagebase+"/"+freesiteedition+"/";\r
234                         }\r
235                 }\r
236 \r
237                 content+="<tr>";\r
238                 if(freesiteedition!="")\r
239                 {\r
240                         content+="<td><a href=\""+uskkey+"\">"+SanitizeOutput(CreateShortIdentityName(idname,publickey))+"</a></td>";\r
241                 }\r
242                 else\r
243                 {\r
244                         content+="<td>"+SanitizeOutput(CreateShortIdentityName(idname,publickey))+"</td>";\r
245                 }\r
246                 content+="<td "+GetClassString(messagetrust)+">"+messagetrust+"</td>";\r
247                 content+="<td>"+SanitizeOutput(messagetrustcomment)+"</td>";\r
248                 content+="<td "+GetClassString(trustlisttrust)+">"+trustlisttrust+"</td>";\r
249                 content+="<td>"+SanitizeOutput(trustlisttrustcomment)+"</td>";\r
250                 content+="</tr>\r\n";\r
251 \r
252                 st.Step();\r
253         }\r
254 \r
255         return StringFunctions::Replace(htmltemplate,"[CONTENT]",content);\r
256 \r
257 }\r
258 \r
259 const std::string SiteInserter::GetClassString(const std::string &trustlevel)\r
260 {\r
261         int tempint=0;\r
262         std::string tempstr;\r
263 \r
264         StringFunctions::Convert(trustlevel,tempint);\r
265         tempint/=10;\r
266         StringFunctions::Convert(tempint,tempstr);\r
267 \r
268         if(trustlevel!="")\r
269         {\r
270                 return "class=\"trust"+tempstr+"\"";\r
271         }\r
272         else\r
273         {\r
274                 return "";\r
275         }\r
276 }\r
277 \r
278 const bool SiteInserter::HandlePutFailed(FCPMessage &message)\r
279 {\r
280         std::vector<std::string> idparts;\r
281         long localidentityid;\r
282 \r
283         StringFunctions::Split(message["Identifier"],"|",idparts);\r
284         StringFunctions::Convert(idparts[1],localidentityid);\r
285 \r
286         RemoveFromInsertList(localidentityid);\r
287 \r
288         return true;\r
289 }\r
290 \r
291 const bool SiteInserter::HandlePutSuccessful(FCPMessage &message)\r
292 {\r
293         std::vector<std::string> idparts;\r
294         std::vector<std::string> uriparts;\r
295         long localidentityid;\r
296         int edition=-1;\r
297         DateTime now;\r
298 \r
299         now.SetToGMTime();\r
300 \r
301         StringFunctions::Split(message["Identifier"],"|",idparts);\r
302         StringFunctions::Convert(idparts[1],localidentityid);\r
303 \r
304         // edition is very last part of uri\r
305         StringFunctions::Split(message["URI"],"/",uriparts);\r
306         if(uriparts.size()>0)\r
307         {\r
308                 StringFunctions::Convert(uriparts[uriparts.size()-1],edition);\r
309         }\r
310 \r
311         SQLite3DB::Statement st=m_db->Prepare("UPDATE tblLocalIdentity SET LastInsertedFreesite=?, FreesiteEdition=? WHERE LocalIdentityID=?;");\r
312         st.Bind(0,now.Format("%Y-%m-%d %H:%M:%S"));\r
313         st.Bind(1,edition);\r
314         st.Bind(2,localidentityid);\r
315         st.Step();\r
316 \r
317         m_log->WriteLog(LogFile::LOGLEVEL_INFO,"SiteInserter::HandlePutSuccessful successfully inserted Freesite.");\r
318 \r
319         RemoveFromInsertList(localidentityid);\r
320 \r
321         return true;\r
322 }\r
323 \r
324 void SiteInserter::Initialize()\r
325 {\r
326         m_fcpuniquename="SiteInserter";\r
327 }\r
328 \r
329 const std::string SiteInserter::SanitizeOutput(const std::string &input)\r
330 {\r
331         // must do & first because all other elements have & in them!\r
332         std::string output=StringFunctions::Replace(input,"&","&amp;");\r
333         output=StringFunctions::Replace(output,"<","&lt;");\r
334         output=StringFunctions::Replace(output,">","&gt;");\r
335         output=StringFunctions::Replace(output,"\"","&quot;");\r
336         output=StringFunctions::Replace(output," ","&nbsp;");\r
337         return output;\r
338 }\r
339 \r
340 void SiteInserter::StartInsert(const long &localidentityid)\r
341 {\r
342         FCPMessage message;\r
343         std::string localidentityidstr="";\r
344         std::string sizestr="";\r
345         std::string uskkey="";\r
346         std::map<std::string,std::string> pages;\r
347         int filenum=0;\r
348 \r
349         StringFunctions::Convert(localidentityid,localidentityidstr);\r
350 \r
351         GeneratePages(localidentityid,uskkey,pages);\r
352 \r
353         message.SetName("ClientPutComplexDir");\r
354         message["URI"]=uskkey;\r
355         message["Identifier"]=m_fcpuniquename+"|"+localidentityidstr+"|"+message["URI"];\r
356         message["DefaultName"]="index.htm";\r
357 \r
358         // add each page to the message\r
359         for(std::map<std::string,std::string>::iterator pagei=pages.begin(); pagei!=pages.end(); pagei++)\r
360         {\r
361                 std::string filenumstr;\r
362                 StringFunctions::Convert(filenum,filenumstr);\r
363 \r
364                 sizestr="0";\r
365                 StringFunctions::Convert((*pagei).second.size(),sizestr);\r
366 \r
367                 message["Files."+filenumstr+".Name"]=(*pagei).first;\r
368                 message["Files."+filenumstr+".UploadFrom"]="direct";\r
369                 message["Files."+filenumstr+".DataLength"]=sizestr;\r
370 \r
371                 filenum++;\r
372         }\r
373 \r
374         m_fcp->SendMessage(message);\r
375 \r
376         // send data of each page\r
377         for(std::map<std::string,std::string>::iterator pagei=pages.begin(); pagei!=pages.end(); pagei++)\r
378         {\r
379                 m_fcp->SendRaw(&(*pagei).second[0],(*pagei).second.size());\r
380         }\r
381 \r
382         m_inserting.push_back(localidentityid);\r
383 \r
384 }\r