void ConvertDB0109To0110();\r
void ConvertDB0110To0111();\r
void ConvertDB0111To0112();\r
+void ConvertDB0112To0113();\r
\r
// TODO remove sometime after 0.1.17\r
void FixCapitalBoardNames();\r
\r
#include "iindexinserter.h"\r
\r
+#include <map>\r
#include <Poco/DateTime.h>\r
\r
class IntroductionPuzzleInserter:public IIndexInserter<long>\r
const bool HandlePutFailed(FCPMessage &message);\r
\r
Poco::DateTime m_lastchecked;\r
+ int m_maxpuzzleinserts;\r
+ std::map<int,Poco::DateTime> m_lastinserted;\r
\r
};\r
\r
const bool HandleAllData(FCPMessage &message);\r
const bool HandleGetFailed(FCPMessage &message);\r
void GetBoardList(std::map<std::string,bool> &boards);\r
+ const bool CheckDateNotFuture(const std::string &datestr) const;\r
\r
bool m_localtrustoverrides;\r
bool m_savetonewboards;\r
\r
#define VERSION_MAJOR "0"\r
#define VERSION_MINOR "3"\r
-#define VERSION_RELEASE "9"\r
+#define VERSION_RELEASE "10"\r
#define FMS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_RELEASE\r
\r
typedef Poco::ScopedLock<Poco::FastMutex> Guard;\r
db->Execute("UPDATE tblDBVersion SET Major=1, Minor=12;");\r
}\r
\r
+void ConvertDB0112To0113()\r
+{\r
+ // Add Tries and Key (for anonymous messages) to tblMessageRequests \r
+ SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
+\r
+ db->Execute("ALTER TABLE tblMessageRequests ADD COLUMN Tries INTEGER DEFAULT 0;");\r
+ db->Execute("ALTER TABLE tblMessageRequests ADD COLUMN Key TEXT;");\r
+\r
+ db->Execute("UPDATE tblDBVersion SET Major=1, Minor=13;");\r
+}\r
+\r
void FixCapitalBoardNames()\r
{\r
SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
st.Bind(0,Poco::DateTimeFormatter::format(date,"%Y-%m-%d"));\r
st.Step();\r
\r
+ // delete old message requests\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(90,0,0,0,0);\r
+ st=m_db->Prepare("DELETE FROM tblMessageRequests WHERE Day<?;");\r
+ st.Bind(0,Poco::DateTimeFormatter::format(date,"%Y-%m-%d"));\r
+ st.Step();\r
+\r
// delete tblIdentityTrust for local identities and identities that have been deleted\r
m_db->Execute("DELETE FROM tblIdentityTrust WHERE LocalIdentityID NOT IN (SELECT LocalIdentityID FROM tblLocalIdentity);");\r
m_db->Execute("DELETE FROM tblIdentityTrust WHERE IdentityID NOT IN (SELECT IdentityID FROM tblIdentity);");\r
major=1;\r
minor=12;\r
}\r
+ if(major==1 && minor==12)\r
+ {\r
+ ConvertDB0112To0113();\r
+ major=1;\r
+ minor=13;\r
+ }\r
}\r
else\r
{\r
- db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,12);");\r
+ db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,13);");\r
}\r
\r
- db->Execute("UPDATE tblDBVersion SET Major=1, Minor=12;");\r
+ db->Execute("UPDATE tblDBVersion SET Major=1, Minor=13;");\r
\r
db->Execute("CREATE TABLE IF NOT EXISTS tblFMSVersion(\\r
Major INTEGER,\\r
FoundSolution BOOL CHECK(FoundSolution IN('true','false')) DEFAULT 'false'\\r
);");\r
\r
+ /*\r
+ PurgeDate is not used yet\r
+ */\r
db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\\r
IdentityID INTEGER PRIMARY KEY,\\r
PublicKey TEXT UNIQUE,\\r
Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
);");\r
\r
+ /*\r
+ Key is for anonymous messages (future)\r
+ */\r
db->Execute("CREATE TABLE IF NOT EXISTS tblMessageRequests(\\r
IdentityID INTEGER,\\r
Day DATE,\\r
RequestIndex INTEGER,\\r
FromMessageList BOOL CHECK(FromMessageList IN('true','false')) DEFAULT 'false',\\r
- Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
+ Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false',\\r
+ Tries INTEGER DEFAULT 0,\\r
+ Key TEXT\\r
);");\r
\r
db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);");\r
\r
while(!rs.AtEnd())\r
{\r
- std::string localidentityidstr;\r
+ int localidentityid=0;\r
+ std::string localidentityidstr="";\r
Poco::DateTime now;\r
+ float minutesbetweeninserts=0;\r
+ minutesbetweeninserts=1440.0/(float)m_maxpuzzleinserts;\r
+ Poco::DateTime lastinsert=now;\r
+ lastinsert-=Poco::Timespan(0,0,minutesbetweeninserts,0,0);\r
\r
if(rs.GetField(0))\r
{\r
// identity doesn't have any non-solved puzzles for today - start a new insert\r
if(rs2.Empty()==true)\r
{\r
- StartInsert(rs.GetInt(0));\r
+ if(m_lastinserted.find(rs.GetInt(0))==m_lastinserted.end() || m_lastinserted[rs.GetInt(0)]<=lastinsert)\r
+ {\r
+ StartInsert(rs.GetInt(0));\r
+ m_lastinserted[rs.GetInt(0)]=now;\r
+ }\r
+ else\r
+ {\r
+ m_log->trace("IntroductionPuzzleInserter::CheckForNeededInsert waiting to insert puzzle for "+localidentityidstr);\r
+ }\r
}\r
\r
rs.Next();\r
void IntroductionPuzzleInserter::Initialize()\r
{\r
m_fcpuniquename="IntroductionPuzzleInserter";\r
+ m_maxpuzzleinserts=50;\r
}\r
\r
const bool IntroductionPuzzleInserter::StartInsert(const long &localidentityid)\r
}\r
StringFunctions::Convert(index,indexstr);\r
\r
- if(index<50)\r
+ if(index<m_maxpuzzleinserts)\r
{\r
SQLite3DB::Recordset rs2=m_db->Query("SELECT PrivateKey,PublicKey FROM tblLocalIdentity WHERE LocalIdentityID="+idstring+";");\r
if(rs2.Empty()==false && rs2.GetField(0)!=NULL)\r
}\r
else\r
{\r
- m_log->warning("IntroductionPuzzleInserter::StartInsert already inserted 50 puzzles for "+idstring);\r
+ m_log->warning("IntroductionPuzzleInserter::StartInsert already inserted max puzzles for "+idstring);\r
}\r
\r
return true;\r
Initialize();\r
}\r
\r
+const bool MessageListRequester::CheckDateNotFuture(const std::string &datestr) const\r
+{\r
+ std::vector<std::string> dateparts;\r
+ int year=0;\r
+ int month=0;\r
+ int day=0;\r
+ Poco::DateTime today;\r
+\r
+ StringFunctions::Split(datestr,"-",dateparts);\r
+ if(dateparts.size()==3)\r
+ {\r
+ StringFunctions::Convert(dateparts[0],year);\r
+ StringFunctions::Convert(dateparts[1],month);\r
+ StringFunctions::Convert(dateparts[2],day);\r
+ if(today.year()>year || (today.year()==year && today.month()>month) || (today.year()==year && today.month()==month && today.day()>=day))\r
+ {\r
+ return true;\r
+ }\r
+ else\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ return false;\r
+ }\r
+\r
+}\r
+\r
void MessageListRequester::GetBoardList(std::map<std::string,bool> &boards)\r
{\r
SQLite3DB::Statement st=m_db->Prepare("SELECT BoardName, SaveReceivedMessages FROM tblBoard;");\r
std::map<std::string,bool> boards; // list of boards and if we will save messages for that board or not\r
bool addmessage=false;\r
std::string boardsstr="";\r
+ std::string datestr="";\r
+ std::vector<std::string> dateparts;\r
\r
GetBoardList(boards);\r
\r
boardsstr+=(*j);\r
}\r
\r
+ if(CheckDateNotFuture(xml.GetDate(i))==false)\r
+ {\r
+ addmessage=false;\r
+ m_log->error("MessageListRequester::HandleAllData date for message is in future! "+xml.GetDate(i));\r
+ }\r
+\r
if(addmessage==true)\r
{\r
st.Bind(0,identityid);\r
boardsstr+=(*j);\r
}\r
\r
+ if(CheckDateNotFuture(xml.GetExternalDate(i))==false)\r
+ {\r
+ addmessage=false;\r
+ m_log->error("MessageListRequester::HandleAllData date for external message is in future! "+xml.GetExternalDate(i));\r
+ }\r
+\r
if(addmessage==true)\r
{\r
spk.Bind(0,xml.GetExternalIdentity(i));\r
}\r
sql+="AND tblIdentity.Name <> '' ";\r
// sort by day descending - in case there is a bunch of messages on a day that keep timing out, we will eventually get to the next day and hopefully find messages there\r
- sql+="ORDER BY tblMessageRequests.Day DESC ";\r
+ // secondary ascending sort on tries\r
+ // tertiary sort on request index (so we get low indexes first)\r
+ sql+="ORDER BY tblMessageRequests.Day DESC, tblMessageRequests.Tries ASC, tblMessageRequests.RequestIndex ASC ";\r
sql+=";";\r
\r
SQLite3DB::Statement st=m_db->Prepare(sql);\r
\r
m_requesting.push_back(requestid);\r
\r
+ // update tries\r
+ st=m_db->Prepare("UPDATE tblMessageRequests SET Tries=Tries+1 WHERE IdentityID=? AND Day=? AND RequestIndex=?;");\r
+ st.Bind(0,identityid);\r
+ st.Bind(1,date);\r
+ st.Bind(2,indexstr);\r
+ st.Step();\r
+\r
m_log->debug("MessageRequester::StartRequest requesting "+message["Identifier"]);\r
}\r
\r
st.Step();\r
if(st.RowReturned())\r
{\r
- std::string currentmajor=VERSION_MAJOR;\r
- std::string currentminor=VERSION_MINOR;\r
- std::string currentrelease=VERSION_RELEASE;\r
- std::string major="";\r
- std::string minor="";\r
- std::string release="";\r
+ int major=0;\r
+ int minor=0;\r
+ int release=0;\r
+ int currentmajor=0;\r
+ int currentminor=0;\r
+ int currentrelease=0;\r
std::string freesite="";\r
- st.ResultText(0,major);\r
- st.ResultText(1,minor);\r
- st.ResultText(2,release);\r
+ std::string majorstr="";\r
+ std::string minorstr="";\r
+ std::string releasestr="";\r
+\r
+ StringFunctions::Convert(VERSION_MAJOR,currentmajor);\r
+ StringFunctions::Convert(VERSION_MINOR,currentminor);\r
+ StringFunctions::Convert(VERSION_RELEASE,currentrelease);\r
+\r
+ st.ResultInt(0,major);\r
+ st.ResultInt(1,minor);\r
+ st.ResultInt(2,release);\r
st.ResultText(3,freesite);\r
\r
+ StringFunctions::Convert(major,majorstr);\r
+ StringFunctions::Convert(minor,minorstr);\r
+ StringFunctions::Convert(release,releasestr);\r
+\r
if(currentmajor<major || (currentmajor==major && currentminor<minor) || (currentmajor==major && currentminor==minor && currentrelease<release))\r
{\r
- content+="<b>You are running an old version of FMS. Please update here: <a href=\"http://"+fcphost+":"+fproxyport+"/"+freesite+"\">FMS "+major+"."+minor+"."+release+"</a></b><br>";\r
- content+="You can see the release info <a href=\"versioninfo.htm?Major="+major+"&Minor="+minor+"&Release="+release+"\">here</a><br>";\r
+ content+="<b>You are running an old version of FMS. Please update here: <a href=\"http://"+fcphost+":"+fproxyport+"/"+freesite+"\">FMS "+majorstr+"."+minorstr+"."+releasestr+"</a></b><br>";\r
+ content+="You can see the release info <a href=\"versioninfo.htm?Major="+majorstr+"&Minor="+minorstr+"&Release="+releasestr+"\">here</a><br>";\r
showgenericupdate=false;\r
}\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
+ temp=StringFunctions::Replace(temp,"\t"," ");\r
std::vector<std::string> parts;\r
int count=0;\r
StringFunctions::SplitMultiple(temp,", \t",parts);\r
for(std::vector<std::string>::reverse_iterator i=parts.rbegin(); i!=parts.rend(); i++)\r
{\r
- // get rid of < and > and any whitespace\r
- (*i)=StringFunctions::Replace((*i),"<","");\r
- (*i)=StringFunctions::Replace((*i),">","");\r
- (*i)=StringFunctions::TrimWhitespace((*i));\r
- /*\r
- // erase @ and everything after\r
- if((*i).find("@")!=std::string::npos)\r
+ if((*i).size()>2)\r
{\r
- (*i).erase((*i).find("@"));\r
- }\r
- */\r
- // only erase after @ if message is old type with @freenetproject.org\r
- if((*i).find("@freenetproject.org")!=std::string::npos)\r
- {\r
- (*i).erase((*i).find("@"));\r
- }\r
- if((*i)!="")\r
- {\r
- m_inreplyto[count++]=(*i);\r
+ // get rid of < and > and any whitespace\r
+ (*i)=StringFunctions::Replace((*i),"<","");\r
+ (*i)=StringFunctions::Replace((*i),">","");\r
+ (*i)=StringFunctions::TrimWhitespace((*i));\r
+ /*\r
+ // erase @ and everything after\r
+ if((*i).find("@")!=std::string::npos)\r
+ {\r
+ (*i).erase((*i).find("@"));\r
+ }\r
+ */\r
+ // only erase after @ if message is old type with @freenetproject.org\r
+ if((*i).find("@freenetproject.org")!=std::string::npos)\r
+ {\r
+ (*i).erase((*i).find("@"));\r
+ }\r
+ if((*i)!="")\r
+ {\r
+ m_inreplyto[count++]=(*i);\r
+ }\r
}\r
}\r
}\r
upd.Reset();\r
\r
st.Bind(0,"FMSVersionEdition");\r
- st.Bind(1,"9");\r
+ st.Bind(1,"11");\r
st.Step();\r
st.Reset();\r
upd.Bind(0,"Program");\r