void Initialize();\r
void PopulateIDList();\r
void StartRequest(const long &id);\r
+ void StartRedirectRequest(FCPMessage &message);\r
const bool HandleAllData(FCPMessage &message);\r
const bool HandleGetFailed(FCPMessage &message);\r
\r
#include <vector>\r
#include "pthreadwrapper/thread.h"\r
\r
-#define FMS_VERSION "0.2.17"\r
+#define FMS_VERSION "0.2.18"\r
\r
// opens database and creates tables and initial inserts if necessary\r
void SetupDB();\r
}\r
return false;\r
}\r
+\r
+ const std::string SanitizeSingleString(const std::string &text)\r
+ {\r
+ std::string returntext=text;\r
+ // remove bogus chars from text string\r
+ for(char i=1; i<32; i++)\r
+ {\r
+ returntext=StringFunctions::Replace(returntext,std::string(1,i),"");\r
+ }\r
+ return returntext;\r
+ }\r
\r
};\r
\r
\r
const bool GetMessageTrust(const std::string &nntpname, int &trust);\r
const bool GetTrustListTrust(const std::string &nntpname, int &trust);\r
+ const bool GetPeerMessageTrust(const std::string &nntpname, int &trust);\r
+ const bool GetPeerTrustListTrust(const std::string &nntpname, int &trust);\r
\r
const bool SetMessageTrust(const std::string &nntpname, const int trust);\r
const bool SetTrustListTrust(const std::string &nntpname, const int trust);\r
\r
XGETTRUST MESSAGE userid@keypart\r
XGETTRUST TRUSTLIST userid@keypart\r
+XGETTRUST PEERMESSAGE userid@keypart\r
+XGETTRUST PEERTRUSTLIST userid@keypart\r
\r
Responses:\r
2xx val\r
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">\r
<head>\r
-<title>FMS : Freenet Message System</title>\r
+<title>FMS Site of [IDENTITYNAME]</title>\r
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />\r
+<meta name="description" content="The FMS-generated homepage of [IDENTITYNAME]."/>\r
+<meta name="category" content="flog-fms"/>\r
<style type="text/css">\r
body {\r
background-color: #FFF;\r
txt=hnd.FirstChild("IdentityIntroduction").FirstChild("Identity").FirstChild().ToText();\r
if(txt)\r
{\r
- m_identity=txt->ValueStr();\r
+ m_identity=SanitizeSingleString(txt->ValueStr());\r
}\r
ssk.SetPublicKey(m_identity);\r
if(ssk.ValidPublicKey()==false)\r
txt=hnd.FirstChild("Identity").FirstChild("FreesiteEdition").FirstChild().ToText();\r
if(txt)\r
{\r
- std::string editionstr=txt->ValueStr();\r
+ std::string editionstr=SanitizeSingleString(txt->ValueStr());\r
StringFunctions::Convert(editionstr,m_freesiteedition);\r
}\r
\r
txt=hnd.FirstChild("IntroductionPuzzle").FirstChild("Type").FirstChild().ToText();\r
if(txt)\r
{\r
- m_type=txt->ValueStr();\r
+ m_type=SanitizeSingleString(txt->ValueStr());\r
}\r
\r
txt=hnd.FirstChild("IntroductionPuzzle").FirstChild("UUID").FirstChild().ToText();\r
if(txt)\r
{\r
- m_uuid=txt->ValueStr();\r
+ m_uuid=SanitizeSingleString(txt->ValueStr());\r
}\r
\r
txt=hnd.FirstChild("IntroductionPuzzle").FirstChild("MimeType").FirstChild().ToText();\r
if(txt)\r
{\r
- m_mimetype=txt->ValueStr();\r
+ m_mimetype=SanitizeSingleString(txt->ValueStr());\r
}\r
\r
txt=hnd.FirstChild("IntroductionPuzzle").FirstChild("PuzzleData").FirstChild().ToText();\r
// insert external message indexes\r
for(long i=0; i<xml.ExternalMessageCount(); i++)\r
{\r
- spk.Bind(0,xml.GetExternalIdentity(i));\r
- spk.Step();\r
- if(spk.RowReturned())\r
+ if(xml.GetExternalType(i)=="Keyed")\r
{\r
- int thisidentityid=0;\r
- spk.ResultInt(0,thisidentityid);\r
- mst.Bind(0,thisidentityid);\r
- mst.Bind(1,xml.GetExternalDate(i));\r
- mst.Bind(2,xml.GetExternalIndex(i));\r
- mst.Step();\r
- mst.Reset();\r
+ spk.Bind(0,xml.GetExternalIdentity(i));\r
+ spk.Step();\r
+ if(spk.RowReturned())\r
+ {\r
+ int thisidentityid=0;\r
+ spk.ResultInt(0,thisidentityid);\r
+ mst.Bind(0,thisidentityid);\r
+ mst.Bind(1,xml.GetExternalDate(i));\r
+ mst.Bind(2,xml.GetExternalIndex(i));\r
+ mst.Step();\r
+ mst.Reset();\r
+ }\r
+ spk.Reset();\r
}\r
- spk.Reset();\r
}\r
\r
st=m_db->Prepare("INSERT INTO tblMessageListRequests(IdentityID,Day,RequestIndex,Found) VALUES(?,?,?,'true');");\r
StringFunctions::Convert(idparts[1],identityid);\r
StringFunctions::Convert(idparts[2],index); \r
\r
+ // code 27 - permanent redirect\r
+ if(message["Code"]=="27")\r
+ {\r
+ StartRedirectRequest(message);\r
+ return true;\r
+ }\r
+\r
// if this is a fatal error - insert index into database so we won't try to download this index again\r
if(message["Fatal"]=="true")\r
{\r
}\r
}\r
\r
+void MessageListRequester::StartRedirectRequest(FCPMessage &message)\r
+{\r
+ std::vector<std::string> parts;\r
+ std::string indexstr="";\r
+ std::string identityidstr="";\r
+ std::string datestr="";\r
+ FCPMessage newmessage;\r
+\r
+ // get the new edition #\r
+ StringFunctions::Split(message["RedirectURI"],"/",parts);\r
+ //edition # is 2nd to last part\r
+ if(parts.size()>2)\r
+ {\r
+ indexstr=parts[parts.size()-2];\r
+ }\r
+\r
+ // get identityid\r
+ parts.clear();\r
+ StringFunctions::Split(message["Identifier"],"|",parts);\r
+ if(parts.size()>1)\r
+ {\r
+ identityidstr=parts[1];\r
+ }\r
+ if(parts.size()>4)\r
+ {\r
+ datestr=parts[4];\r
+ }\r
+\r
+ newmessage.SetName("ClientGet");\r
+ newmessage["URI"]=StringFunctions::UriDecode(message["RedirectURI"]);\r
+ newmessage["Identifier"]=m_fcpuniquename+"|"+identityidstr+"|"+indexstr+"|_|"+datestr+"|"+newmessage["URI"];\r
+ newmessage["ReturnType"]="direct";\r
+ newmessage["MaxSize"]="1000000";\r
+\r
+ m_fcp->SendMessage(newmessage);\r
+\r
+}\r
+\r
void MessageListRequester::StartRequest(const long &id)\r
{\r
DateTime now;\r
FCPMessage message;\r
std::string publickey;\r
- int index;\r
+ int index=0;\r
std::string indexstr;\r
std::string identityidstr;\r
\r
StringFunctions::Convert(id,identityidstr);\r
\r
message.SetName("ClientGet");\r
- message["URI"]=publickey+m_messagebase+"|"+now.Format("%Y-%m-%d")+"|MessageList|"+indexstr+".xml";\r
- message["Identifier"]=m_fcpuniquename+"|"+identityidstr+"|"+indexstr+"|"+message["URI"];\r
+ message["URI"]="USK"+publickey.substr(3)+m_messagebase+"|"+now.Format("%Y.%m.%d")+"|MessageList/"+indexstr+"/MessageList.xml";\r
+ message["Identifier"]=m_fcpuniquename+"|"+identityidstr+"|"+indexstr+"|_|"+now.Format("%Y-%m-%d")+"|"+message["URI"];\r
message["ReturnType"]="direct";\r
- message["MaxSize"]="1000000"; // 1 MB\r
+ message["MaxSize"]="1000000";\r
\r
m_fcp->SendMessage(message);\r
\r
txt=hnd2.FirstChild("Date").FirstChild().ToText();\r
if(txt)\r
{\r
- date=txt->ValueStr();\r
+ date=SanitizeSingleString(txt->ValueStr());\r
}\r
txt=hnd2.FirstChild("Index").FirstChild().ToText();\r
if(txt)\r
{\r
- tempstr=txt->ValueStr();\r
+ tempstr=SanitizeSingleString(txt->ValueStr());\r
StringFunctions::Convert(tempstr,index);\r
}\r
node2=hnd2.FirstChild("Boards").FirstChild("Board").ToNode();\r
{\r
if(node2->FirstChild())\r
{\r
- std::string boardname=node2->FirstChild()->ValueStr();\r
+ std::string boardname=SanitizeSingleString(node2->FirstChild()->ValueStr());\r
StringFunctions::LowerCase(boardname,boardname);\r
boards.push_back(boardname);\r
}\r
node=node->NextSibling("Message");\r
}\r
\r
+ node=hnd.FirstChild("MessageList").FirstChild("ExternalMessage").ToNode();\r
+ while(node)\r
+ {\r
+ std::string type="";\r
+ std::string identity="";\r
+ date="";\r
+ index=-1;\r
+ boards.clear();\r
+\r
+ TiXmlHandle hnd2(node);\r
+ txt=hnd2.FirstChild("Type").FirstChild().ToText();\r
+ if(txt)\r
+ {\r
+ type=SanitizeSingleString(txt->ValueStr());\r
+ }\r
+\r
+ if(type=="Keyed")\r
+ {\r
+ txt=hnd2.FirstChild("Identity").FirstChild().ToText();\r
+ if(txt)\r
+ {\r
+ identity=SanitizeSingleString(txt->ValueStr());\r
+ }\r
+ txt=hnd2.FirstChild("Date").FirstChild().ToText();\r
+ if(txt)\r
+ {\r
+ date=SanitizeSingleString(txt->ValueStr());\r
+ }\r
+ txt=hnd2.FirstChild("Index").FirstChild().ToText();\r
+ if(txt)\r
+ {\r
+ tempstr=SanitizeSingleString(txt->ValueStr());\r
+ StringFunctions::Convert(tempstr,index);\r
+ }\r
+ node2=hnd2.FirstChild("Boards").FirstChild("Board").ToNode();\r
+ while(node2)\r
+ {\r
+ if(node2->FirstChild())\r
+ {\r
+ std::string boardname=SanitizeSingleString(node2->FirstChild()->ValueStr());\r
+ StringFunctions::LowerCase(boardname,boardname);\r
+ boards.push_back(boardname);\r
+ }\r
+ node2=node2->NextSibling("Board");\r
+ }\r
+ m_externalmessages.push_back(externalmessage("Keyed",identity,date,index,boards));\r
+ }\r
+\r
+ node=node->NextSibling("ExternalMessage");\r
+ }\r
+\r
return true;\r
}\r
else\r
txt=hnd.FirstChild("Message").FirstChild("Date").FirstChild().ToText();\r
if(txt)\r
{\r
- m_date=txt->ValueStr();\r
+ m_date=SanitizeSingleString(txt->ValueStr());\r
}\r
txt=hnd.FirstChild("Message").FirstChild("Time").FirstChild().ToText();\r
if(txt)\r
{\r
- m_time=txt->ValueStr();\r
+ m_time=SanitizeSingleString(txt->ValueStr());\r
}\r
txt=hnd.FirstChild("Message").FirstChild("Subject").FirstChild().ToText();\r
if(txt)\r
{\r
- m_subject=txt->ValueStr();\r
+ m_subject=SanitizeSingleString(txt->ValueStr());\r
}\r
txt=hnd.FirstChild("Message").FirstChild("MessageID").FirstChild().ToText();\r
if(txt)\r
{\r
- m_messageid=txt->ValueStr();\r
+ m_messageid=SanitizeSingleString(txt->ValueStr());\r
}\r
txt=hnd.FirstChild("Message").FirstChild("ReplyBoard").FirstChild().ToText();\r
if(txt)\r
{\r
- m_replyboard=txt->ValueStr();\r
+ m_replyboard=SanitizeSingleString(txt->ValueStr());\r
StringFunctions::LowerCase(m_replyboard,m_replyboard);\r
if(m_replyboard.size()>40)\r
{\r
{\r
if(node2->FirstChild())\r
{\r
- std::string boardname=node2->FirstChild()->ValueStr();\r
+ std::string boardname=SanitizeSingleString(node2->FirstChild()->ValueStr());\r
StringFunctions::LowerCase(boardname,boardname);\r
if(boardname.size()>40)\r
{\r
txt=hnd2.FirstChild("Order").FirstChild().ToText();\r
if(txt)\r
{\r
- orderstr=txt->ValueStr();\r
+ orderstr=SanitizeSingleString(txt->ValueStr());\r
StringFunctions::Convert(orderstr,order);\r
}\r
txt=hnd2.FirstChild("MessageID").FirstChild().ToText();\r
if(txt)\r
{\r
- messageid=txt->ValueStr();\r
+ messageid=SanitizeSingleString(txt->ValueStr());\r
}\r
\r
if(order!=-1 && messageid!="")\r
txt=hnd2.FirstChild("Key").FirstChild().ToText();\r
if(txt)\r
{\r
- key=txt->ValueStr();\r
+ key=SanitizeSingleString(txt->ValueStr());\r
}\r
\r
txt=hnd2.FirstChild("Size").FirstChild().ToText();\r
if(txt)\r
{\r
- sizestr=txt->ValueStr();\r
+ sizestr=SanitizeSingleString(txt->ValueStr());\r
StringFunctions::Convert(sizestr,size);\r
}\r
\r
m_db->Execute("INSERT INTO tblIdentityTrust(LocalIdentityID,IdentityID) SELECT LocalIdentityID,IdentityID FROM tblLocalIdentity,tblIdentity WHERE LocalIdentityID || '_' || IdentityID NOT IN (SELECT LocalIdentityID || '_' || IdentityID FROM tblIdentityTrust);");\r
\r
// build the xml file - we only want to add identities that we recently saw, otherwise we could be inserting a ton of identities\r
- date.Add(0,0,0,-20); // identities seen in last 20 days\r
+ date.Add(0,0,0,-15); // identities seen in last 15 days\r
//SQLite3DB::Statement st=m_db->Prepare("SELECT PublicKey, LocalMessageTrust, LocalTrustListTrust, MessageTrustComment, TrustListTrustComment FROM tblIdentity WHERE PublicKey IS NOT NULL AND PublicKey<>'' AND LastSeen>=?;");\r
// we want to order by public key so we can't do identity correllation based on the sequence of identities in the list.\r
SQLite3DB::Statement st=m_db->Prepare("SELECT PublicKey, tblIdentityTrust.LocalMessageTrust, tblIdentityTrust.LocalTrustListTrust, tblIdentityTrust.MessageTrustComment, tblIdentityTrust.TrustListTrustComment FROM tblIdentity INNER JOIN tblIdentityTrust ON tblIdentity.IdentityID=tblIdentityTrust.IdentityID WHERE PublicKey IS NOT NULL AND PublicKey<>'' AND LastSeen>=? AND tblIdentityTrust.LocalIdentityID=? ORDER BY PublicKey;");\r
txt=hnd2.FirstChild("Identity").FirstChild().ToText();\r
if(txt)\r
{\r
- identity=txt->ValueStr();\r
+ identity=SanitizeSingleString(txt->ValueStr());\r
}\r
txt=hnd2.FirstChild("MessageTrustLevel").FirstChild().ToText();\r
if(txt)\r
{\r
- messagetruststr=txt->ValueStr();\r
+ messagetruststr=SanitizeSingleString(txt->ValueStr());\r
if(messagetruststr!="")\r
{\r
StringFunctions::Convert(messagetruststr,messagetrust);\r
txt=hnd2.FirstChild("TrustListTrustLevel").FirstChild().ToText();\r
if(txt)\r
{\r
- trustlisttruststr=txt->ValueStr();\r
+ trustlisttruststr=SanitizeSingleString(txt->ValueStr());\r
if(trustlisttruststr!="")\r
{\r
StringFunctions::Convert(trustlisttruststr,trustlisttrust);\r
date.SetToGMTime();\r
// insert SomeDude's public key\r
db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,LocalTrustListTrust,AddedMethod) VALUES('SSK@NuBL7aaJ6Cn4fB7GXFb9Zfi8w1FhPyW3oKgU9TweZMw,iXez4j3qCpd596TxXiJgZyTq9o-CElEuJxm~jNNZAuA,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"',50,'Initial Identity');");\r
- // insert Shadow Panther's public key\r
- db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@~mimyB1kmH4f7Cgsd2wM2Qv2NxrZHRMM6IY8~7EWRVQ,fxTKkR0TYhgMYb-vEGAv55sMOxCGD2xhE4ZxWHxdPz4,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
+ // insert Shadow Panther's public key - haven't seen in a while - disabling for now\r
+ //db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@~mimyB1kmH4f7Cgsd2wM2Qv2NxrZHRMM6IY8~7EWRVQ,fxTKkR0TYhgMYb-vEGAv55sMOxCGD2xhE4ZxWHxdPz4,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
// insert garfield's public key\r
db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@T8l1IEGU4-PoASFzgc2GYhIgRzUvZsKdoQWeuLHuTmM,QLxAPfkGis8l5NafNpSCdbxzXhBlu9WL8svcqJw9Mpo,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
// insert alek's public key\r
m_fromname=mime.GetFieldValue("From");\r
// remove any path folding\r
m_fromname=StringFunctions::Replace(m_fromname,"\r\n","");\r
+ m_fromname=StringFunctions::Replace(m_fromname,"\t","");\r
// strip off everything between () and <> and any whitespace\r
std::string::size_type startpos=m_fromname.find("(");\r
std::string::size_type endpos;\r
std::string temp=mime.GetFieldValue("Newsgroups");\r
// remove any path folding\r
temp=StringFunctions::Replace(temp,"\r\n","");\r
+ temp=StringFunctions::Replace(temp,"\t","");\r
std::vector<std::string> parts;\r
StringFunctions::SplitMultiple(temp,", \t",parts);\r
for(std::vector<std::string>::iterator i=parts.begin(); i!=parts.end(); i++)\r
m_replyboardname=mime.GetFieldValue("Followup-To");\r
// remove any path folding\r
m_replyboardname=StringFunctions::Replace(m_replyboardname,"\r\n","");\r
+ m_replyboardname=StringFunctions::Replace(m_replyboardname,"\t","");\r
}\r
else\r
{\r
m_subject=mime.GetFieldValue("Subject");\r
// remove any path folding\r
m_subject=StringFunctions::Replace(m_subject,"\r\n","");\r
+ m_subject=StringFunctions::Replace(m_subject,"\t","");\r
#if DO_CHARSET_CONVERSION\r
if(mime.GetFieldCharset("Subject"))\r
{\r
std::string temp=mime.GetFieldValue("References");\r
// remove any path folding\r
temp=StringFunctions::Replace(temp,"\r\n","");\r
+ temp=StringFunctions::Replace(temp,"\t","");\r
std::vector<std::string> parts;\r
int count=0;\r
StringFunctions::SplitMultiple(temp,", \t",parts);\r
\r
if(keyparts.size()>1)\r
{\r
- publickey=StringFunctions::Replace(StringFunctions::Replace(keyparts[1],"~",""),"-","");\r
- if(nameparts[0]+"@"+publickey==nntpname)\r
+ if(nameparts[0]+"@"+keyparts[1]==nntpname)\r
{\r
st.ResultInt(0,id);\r
return id;\r
}\r
}\r
\r
+const bool TrustExtension::GetPeerMessageTrust(const std::string &nntpname, int &trust)\r
+{\r
+ if(m_localidentityid>=0)\r
+ {\r
+ int id=GetIdentityID(nntpname);\r
+ if(id>=0)\r
+ {\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT PeerMessageTrust FROM tblIdentity WHERE IdentityID=?;");\r
+ st.Bind(0,id);\r
+ st.Step();\r
+\r
+ if(st.RowReturned())\r
+ {\r
+ int tr=-1;\r
+ if(st.ResultNull(0)==false)\r
+ {\r
+ st.ResultInt(0,tr);\r
+ }\r
+ trust=tr;\r
+ }\r
+ else\r
+ {\r
+ trust=-1;\r
+ }\r
+ return true;\r
+ }\r
+ else\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ return false;\r
+ }\r
+}\r
+\r
+const bool TrustExtension::GetPeerTrustListTrust(const std::string &nntpname, int &trust)\r
+{\r
+ if(m_localidentityid>=0)\r
+ {\r
+ int id=GetIdentityID(nntpname);\r
+ if(id>=0)\r
+ {\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT PeerTrustListTrust FROM tblIdentity WHERE IdentityID=?;");\r
+ st.Bind(0,id);\r
+ st.Step();\r
+\r
+ if(st.RowReturned())\r
+ {\r
+ int tr=-1;\r
+ if(st.ResultNull(0)==false)\r
+ {\r
+ st.ResultInt(0,tr);\r
+ }\r
+ trust=tr;\r
+ }\r
+ else\r
+ {\r
+ trust=-1;\r
+ }\r
+ return true;\r
+ }\r
+ else\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ return false;\r
+ }\r
+}\r
+\r
const bool TrustExtension::GetTrustList(std::map<std::string,std::pair<int,int> > &trustlist)\r
{\r
if(m_localidentityid>=0)\r
StringFunctions::SplitMultiple(publickey,"@,",keyparts);\r
if(keyparts.size()>1)\r
{\r
- publickey=StringFunctions::Replace(StringFunctions::Replace(keyparts[1],"~",""),"-","");\r
- nntpname=name+"@"+publickey;\r
+ nntpname=name+"@"+keyparts[1];\r
}\r
\r
trustlist[nntpname]=std::pair<int,int>(messagetrust,trustlisttrust);\r
{\r
std::string type=command.m_arguments[0];\r
StringFunctions::UpperCase(type,type);\r
- if(type=="MESSAGE" || type=="TRUSTLIST")\r
+ if(type=="MESSAGE" || type=="TRUSTLIST" || type=="PEERMESSAGE" || type=="PEERTRUSTLIST")\r
{\r
if(m_status.m_authenticated)\r
{\r
found=true;\r
}\r
}\r
- if(type=="TRUSTLIST")\r
+ else if(type=="TRUSTLIST")\r
{\r
if(tr.GetTrustListTrust(nntpname,trust))\r
{\r
found=true;\r
}\r
}\r
+ else if(type=="PEERMESSAGE")\r
+ {\r
+ if(tr.GetPeerMessageTrust(nntpname,trust))\r
+ {\r
+ found=true;\r
+ }\r
+ }\r
+ else if(type=="PEERTRUSTLIST")\r
+ {\r
+ if(tr.GetPeerTrustListTrust(nntpname,trust))\r
+ {\r
+ found=true;\r
+ }\r
+ }\r
\r
if(trust>=0 && found)\r
{\r