version 0.2.4
[fms.git] / src / freenet / siteinserter.cpp
diff --git a/src/freenet/siteinserter.cpp b/src/freenet/siteinserter.cpp
new file mode 100644 (file)
index 0000000..f943f56
--- /dev/null
@@ -0,0 +1,366 @@
+#include "../../include/freenet/siteinserter.h"\r
+\r
+#ifdef XMEM\r
+       #include <xmem.h>\r
+#endif\r
+\r
+SiteInserter::SiteInserter()\r
+{\r
+       Initialize();\r
+}\r
+\r
+SiteInserter::SiteInserter(FCPv2 *fcp):IIndexInserter<long>(fcp)\r
+{\r
+       Initialize();\r
+}\r
+\r
+void SiteInserter::CheckForNeededInsert()\r
+{\r
+       // only do 1 insert at a time\r
+       if(m_inserting.size()==0)\r
+       {\r
+               DateTime date;\r
+               date.SetToGMTime();\r
+\r
+               SQLite3DB::Statement st=m_db->Prepare("SELECT LocalIdentityID FROM tblLocalIdentity WHERE PublishFreesite='true' AND (LastInsertedFreesite IS NULL OR LastInsertedFreesite<?);");\r
+               st.Bind(0,date.Format("%Y-%m-%d"));\r
+\r
+               st.Step();\r
+               if(st.RowReturned())\r
+               {\r
+                       int localidentityid=0;\r
+                       st.ResultInt(0,localidentityid);\r
+                       StartInsert(localidentityid);\r
+               }\r
+       }\r
+}\r
+\r
+std::string SiteInserter::GenerateIndex(const std::string &htmltemplate, const long localidentityid, const std::string &name)\r
+{\r
+       std::string content="";\r
+\r
+       content="<h2>FMS site of "+SanitizeOutput(name)+"</h2>";\r
+\r
+       content+="<h3>My last few posts</h3>";\r
+\r
+       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
+       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
+       st.Bind(0,localidentityid);\r
+       st.Step();\r
+\r
+       while(st.RowReturned())\r
+       {\r
+               std::string post="";\r
+               std::string subject="";\r
+               std::string boards="";\r
+               int messageid=0;\r
+\r
+               st.ResultText(0,post);\r
+               st.ResultText(1,subject);\r
+               st.ResultInt(2,messageid);\r
+\r
+               boardst.Bind(0,messageid);\r
+               boardst.Step();\r
+               while(boardst.RowReturned())\r
+               {\r
+                       std::string board="";\r
+                       boardst.ResultText(0,board);\r
+                       if(boards!="")\r
+                       {\r
+                               boards+=",";\r
+                       }\r
+                       boards+=board;\r
+                       boardst.Step();\r
+               }\r
+               boardst.Reset();\r
+\r
+               content+="<div class=\"post\">";\r
+               content+="<div class=\"postboards\">";\r
+               content+=SanitizeOutput(boards);\r
+               content+="</div>";\r
+               content+="<div class=\"postsubject\">";\r
+               content+=SanitizeOutput(subject);\r
+               content+="</div>";\r
+               content+="<div class=\"postbody\">";\r
+               content+=SanitizeOutput(post);\r
+               content+="</div>";\r
+               content+="</div>";\r
+\r
+               st.Step();\r
+       }\r
+\r
+       return StringFunctions::Replace(htmltemplate,"[CONTENT]",content);\r
+\r
+}\r
+\r
+std::string SiteInserter::GenerateLinks(const bool publishtrustlist, const bool publishboardlist)\r
+{\r
+       std::string links="";\r
+       links+="<ul>";\r
+       links+="<li><a href=\"index.htm\">Home</a></li>";\r
+       if(publishtrustlist)\r
+       {\r
+               links+="<li><a href=\"trustlist.htm\">Trust List</a></li>";\r
+       }\r
+       if(publishboardlist)\r
+       {\r
+//             links+="<li><a href=\"boardlist.htm\">Board List</a></li>";\r
+       }\r
+       links+="</ul>";\r
+       return links;\r
+}\r
+\r
+void SiteInserter::GeneratePages(const long localidentityid, std::string &uskkey, std::map<std::string,std::string> &pages)\r
+{\r
+       SQLite3DB::Statement st=m_db->Prepare("SELECT Name, PrivateKey, PublishTrustList, PublishBoardList FROM tblLocalIdentity WHERE LocalIdentityID=?;");\r
+       st.Bind(0,localidentityid);\r
+       st.Step();\r
+\r
+       if(st.RowReturned())\r
+       {\r
+               std::string htmltemplate="";\r
+               std::string filename="";\r
+               std::string name="";\r
+               std::string key="";\r
+               std::string publishtrustliststr="";\r
+               std::string publishboardliststr="";\r
+               bool publishtrustlist=false;\r
+               bool publishboardlist=false;\r
+\r
+               st.ResultText(0,name);\r
+               st.ResultText(1,key);\r
+               st.ResultText(2,publishtrustliststr);\r
+               st.ResultText(3,publishboardliststr);\r
+\r
+               publishtrustliststr=="true" ? publishtrustlist=true : publishtrustlist=false;\r
+               publishboardliststr=="true" ? publishboardlist=true : publishboardlist=false;\r
+\r
+               filename=name+"-template.htm";\r
+               FILE *infile=fopen(filename.c_str(),"r+b");\r
+               if(!infile)\r
+               {\r
+                       infile=fopen("site-template.htm","r+b");\r
+               }\r
+               if(infile)\r
+               {\r
+                       fseek(infile,0,SEEK_END);\r
+                       long len=ftell(infile);\r
+                       fseek(infile,0,SEEK_SET);\r
+\r
+                       std::vector<unsigned char> data;\r
+                       data.resize(len);\r
+                       fread(&data[0],1,data.size(),infile);\r
+                       fclose(infile);\r
+\r
+                       htmltemplate.append(data.begin(),data.end());\r
+\r
+                       htmltemplate=StringFunctions::Replace(htmltemplate,"[LINKS]",GenerateLinks(publishtrustlist,publishboardlist));\r
+\r
+                       pages["index.htm"]=GenerateIndex(htmltemplate,localidentityid,name);\r
+                       if(publishtrustlist)\r
+                       {\r
+                               pages["trustlist.htm"]=GenerateTrustList(htmltemplate,localidentityid,name);\r
+                       }\r
+                       if(publishboardlist)\r
+                       {\r
+//                             pages["boardlist.htm"]=GenerateBoardList(htmltemplate,localidentityid,name);\r
+                       }\r
+\r
+                       // make SSK a USK\r
+                       if(key.find("SSK@")==0)\r
+                       {\r
+                               key.erase(0,3);\r
+                               key="USK"+key;\r
+                       }\r
+                       key+=m_messagebase+"/0/";\r
+                       uskkey=key;\r
+\r
+               }\r
+               else\r
+               {\r
+                       LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_ERROR,"SiteInserter::GeneratePages unable to open "+filename+" or site-template.htm.");\r
+               }\r
+\r
+       }\r
+}\r
+\r
+std::string SiteInserter::GenerateTrustList(const std::string &htmltemplate, const long localidentityid, const std::string &name)\r
+{\r
+       std::string content="";\r
+       DateTime date;\r
+\r
+       date.SetToGMTime();\r
+       date.Add(0,0,0,-20);\r
+       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
+       st.Bind(0,date.Format("%Y-%m-%d %H:%M:%S"));\r
+       st.Step();\r
+\r
+       content+="<table>";\r
+       content+="<tr><th colspan=\"5\">";\r
+       content+="Trust List of "+SanitizeOutput(name);\r
+       content+="</th></tr>";\r
+       content+="<tr><td></td><th>Message Trust</th><th>Message Comment</th><th>Trust List Trust</th><th>Trust Comment</th></tr>";\r
+       while(st.RowReturned())\r
+       {\r
+               std::string idname="";\r
+               std::string thisid="";\r
+               std::string messagetrustcomment="";\r
+               std::string trustlisttrustcomment="";\r
+               std::string messagetrust="";\r
+               std::string trustlisttrust="";\r
+               std::string publickey="";\r
+               std::string keypart="";\r
+               std::string uskkey="";\r
+\r
+               st.ResultText(0,idname);\r
+               st.ResultText(1,publickey);\r
+               st.ResultText(2,messagetrust);\r
+               st.ResultText(3,trustlisttrust);\r
+               st.ResultText(4,thisid);\r
+               st.ResultText(5,messagetrustcomment);\r
+               st.ResultText(6,trustlisttrustcomment);\r
+\r
+               if(publickey.size()>8)\r
+               {\r
+                       keypart=publickey.substr(3,5);\r
+               }\r
+\r
+               if(publickey.find("SSK@")==0)\r
+               {\r
+                       uskkey=publickey;\r
+                       uskkey.erase(0,3);\r
+                       uskkey="USK"+uskkey;\r
+                       uskkey+=m_messagebase+"/0/";\r
+               }\r
+\r
+               content+="<tr>";\r
+               content+="<td><a href=\""+uskkey+"\">"+SanitizeOutput(idname+keypart)+"...</a></td>";\r
+               content+="<td "+GetClassString(messagetrust)+">"+messagetrust+"</td>";\r
+               content+="<td>"+SanitizeOutput(messagetrustcomment)+"</td>";\r
+               content+="<td "+GetClassString(trustlisttrust)+">"+trustlisttrust+"</td>";\r
+               content+="<td>"+SanitizeOutput(trustlisttrustcomment)+"</td>";\r
+               content+="</tr>\r\n";\r
+\r
+               st.Step();\r
+       }\r
+\r
+       return StringFunctions::Replace(htmltemplate,"[CONTENT]",content);\r
+\r
+}\r
+\r
+const std::string SiteInserter::GetClassString(const std::string &trustlevel)\r
+{\r
+       int tempint=0;\r
+       std::string tempstr;\r
+\r
+       StringFunctions::Convert(trustlevel,tempint);\r
+       tempint/=10;\r
+       StringFunctions::Convert(tempint,tempstr);\r
+\r
+       if(trustlevel!="")\r
+       {\r
+               return "class=\"trust"+tempstr+"\"";\r
+       }\r
+       else\r
+       {\r
+               return "";\r
+       }\r
+}\r
+\r
+const bool SiteInserter::HandlePutFailed(FCPMessage &message)\r
+{\r
+       std::vector<std::string> idparts;\r
+       long localidentityid;\r
+\r
+       StringFunctions::Split(message["Identifier"],"|",idparts);\r
+       StringFunctions::Convert(idparts[1],localidentityid);\r
+\r
+       RemoveFromInsertList(localidentityid);\r
+\r
+       return true;\r
+}\r
+\r
+const bool SiteInserter::HandlePutSuccessful(FCPMessage &message)\r
+{\r
+       std::vector<std::string> idparts;\r
+       long localidentityid;\r
+       DateTime now;\r
+\r
+       now.SetToGMTime();\r
+\r
+       StringFunctions::Split(message["Identifier"],"|",idparts);\r
+       StringFunctions::Convert(idparts[1],localidentityid);\r
+\r
+       SQLite3DB::Statement st=m_db->Prepare("UPDATE tblLocalIdentity SET LastInsertedFreesite=? WHERE LocalIdentityID=?;");\r
+       st.Bind(0,now.Format("%Y-%m-%d %H:%M:%S"));\r
+       st.Bind(1,localidentityid);\r
+       st.Step();\r
+\r
+       m_log->WriteLog(LogFile::LOGLEVEL_INFO,"SiteInserter::HandlePutSuccessful successfully inserted Freesite.");\r
+\r
+       RemoveFromInsertList(localidentityid);\r
+\r
+       return true;\r
+}\r
+\r
+void SiteInserter::Initialize()\r
+{\r
+       m_fcpuniquename="SiteInserter";\r
+}\r
+\r
+const std::string SiteInserter::SanitizeOutput(const std::string &input)\r
+{\r
+       // must do & first because all other elements have & in them!\r
+       std::string output=StringFunctions::Replace(input,"&","&amp;");\r
+       output=StringFunctions::Replace(output,"<","&lt;");\r
+       output=StringFunctions::Replace(output,">","&gt;");\r
+       output=StringFunctions::Replace(output,"\"","&quot;");\r
+       output=StringFunctions::Replace(output," ","&nbsp;");\r
+       return output;\r
+}\r
+\r
+void SiteInserter::StartInsert(const long &localidentityid)\r
+{\r
+       FCPMessage message;\r
+       std::string localidentityidstr="";\r
+       std::string sizestr="";\r
+       std::string uskkey="";\r
+       std::map<std::string,std::string> pages;\r
+       int filenum=0;\r
+\r
+       StringFunctions::Convert(localidentityid,localidentityidstr);\r
+\r
+       GeneratePages(localidentityid,uskkey,pages);\r
+\r
+       message.SetName("ClientPutComplexDir");\r
+       message["URI"]=uskkey;\r
+       message["Identifier"]=m_fcpuniquename+"|"+localidentityidstr+"|"+message["URI"];\r
+       message["DefaultName"]="index.htm";\r
+\r
+       // add each page to the message\r
+       for(std::map<std::string,std::string>::iterator pagei=pages.begin(); pagei!=pages.end(); pagei++)\r
+       {\r
+               std::string filenumstr;\r
+               StringFunctions::Convert(filenum,filenumstr);\r
+\r
+               sizestr="0";\r
+               StringFunctions::Convert((*pagei).second.size(),sizestr);\r
+\r
+               message["Files."+filenumstr+".Name"]=(*pagei).first;\r
+               message["Files."+filenumstr+".UploadFrom"]="direct";\r
+               message["Files."+filenumstr+".DataLength"]=sizestr;\r
+\r
+               filenum++;\r
+       }\r
+\r
+       m_fcp->SendMessage(message);\r
+\r
+       // send data of each page\r
+       for(std::map<std::string,std::string>::iterator pagei=pages.begin(); pagei!=pages.end(); pagei++)\r
+       {\r
+               m_fcp->SendRaw(&(*pagei).second[0],(*pagei).second.size());\r
+       }\r
+\r
+       m_inserting.push_back(localidentityid);\r
+\r
+}\r