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