1 #include "../../include/freenet/introductionpuzzleinserter.h"
\r
2 #include "../../include/freenet/introductionpuzzlexml.h"
\r
3 #include "../../include/stringfunctions.h"
\r
4 #include "../../include/option.h"
\r
5 #include "../../include/freenet/captcha/simplecaptcha.h"
\r
6 #include "../../include/uuidgenerator.h"
\r
7 #include "../../include/base64.h"
\r
13 IntroductionPuzzleInserter::IntroductionPuzzleInserter()
\r
18 IntroductionPuzzleInserter::IntroductionPuzzleInserter(FCPv2 *fcp):IFCPConnected(fcp)
\r
23 void IntroductionPuzzleInserter::CheckForNeededInsert()
\r
25 // select all local ids that aren't single use and that aren't currently inserting a puzzle
\r
26 SQLite3DB::Recordset rs=m_db->Query("SELECT LocalIdentityID FROM tblLocalIdentity WHERE SingleUse='false' AND InsertingPuzzle='false' AND PrivateKey IS NOT NULL AND PrivateKey <> '' ORDER BY LastInsertedPuzzle;");
\r
33 // if this identity has any non-solved puzzles for today, we don't need to insert a new puzzle
\r
34 SQLite3DB::Recordset rs2=m_db->Query("SELECT UUID FROM tblIntroductionPuzzleInserts WHERE Day='"+now.Format("%Y-%m-%d")+"' AND FoundSolution='false';");
\r
36 // identity doesn't have any non-solved puzzles for today - start a new insert
\r
37 if(rs2.Empty()==true)
\r
39 StartInsert(rs.GetInt(0));
\r
46 void IntroductionPuzzleInserter::FCPConnected()
\r
48 m_db->Execute("UPDATE tblLocalIdentity SET InsertingPuzzle='false';");
\r
51 void IntroductionPuzzleInserter::FCPDisconnected()
\r
56 void IntroductionPuzzleInserter::GenerateCaptcha(std::string &encodeddata, std::string &solution)
\r
58 SimpleCaptcha captcha;
\r
59 std::vector<unsigned char> puzzle;
\r
60 std::vector<unsigned char> puzzlesolution;
\r
63 captcha.GetPuzzle(puzzle);
\r
64 captcha.GetSolution(puzzlesolution);
\r
66 encodeddata.clear();
\r
69 Base64::Encode(puzzle,encodeddata);
\r
70 solution.insert(solution.begin(),puzzlesolution.begin(),puzzlesolution.end());
\r
74 const bool IntroductionPuzzleInserter::HandleMessage(FCPMessage &message)
\r
77 if(message["Identifier"].find("IntroductionPuzzleInserter")==0)
\r
80 // ignore URIGenerated message
\r
81 if(message.GetName()=="URIGenerated")
\r
86 if(message.GetName()=="PutSuccessful")
\r
88 return HandlePutSuccessful(message);
\r
91 if(message.GetName()=="PutFailed")
\r
93 return HandlePutFailed(message);
\r
101 const bool IntroductionPuzzleInserter::HandlePutFailed(FCPMessage &message)
\r
103 SQLite3DB::Statement st;
\r
104 std::vector<std::string> idparts;
\r
105 long localidentityid;
\r
107 StringFunctions::Split(message["Identifier"],"|",idparts);
\r
108 StringFunctions::Convert(idparts[1],localidentityid);
\r
110 st=m_db->Prepare("UPDATE tblLocalIdentity SET InsertingPuzzle='false' WHERE LocalIdentityID=?;");
\r
111 st.Bind(0,localidentityid);
\r
115 // if fatal error or collision - mark index
\r
116 if(message["Fatal"]=="true" || message["Code"]=="9")
\r
118 m_db->Execute("UPDATE tblIntroductionPuzzleInserts SET Day='"+idparts[5]+"', InsertIndex="+idparts[2]+", FoundSolution='true' WHERE UUID='"+idparts[3]+"';");
\r
121 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IntroductionPuzzleInserter::HandlePutFailed failed to insert puzzle "+idparts[3]);
\r
126 const bool IntroductionPuzzleInserter::HandlePutSuccessful(FCPMessage &message)
\r
129 SQLite3DB::Statement st;
\r
130 std::vector<std::string> idparts;
\r
131 long localidentityid;
\r
135 StringFunctions::Split(message["Identifier"],"|",idparts);
\r
136 StringFunctions::Convert(idparts[1],localidentityid);
\r
137 StringFunctions::Convert(idparts[2],insertindex);
\r
139 st=m_db->Prepare("UPDATE tblIntroductionPuzzleInserts SET Day=?, InsertIndex=? WHERE UUID=?;");
\r
140 st.Bind(0,idparts[5]);
\r
141 st.Bind(1,insertindex);
\r
142 st.Bind(2,idparts[3]);
\r
146 st=m_db->Prepare("UPDATE tblLocalIdentity SET InsertingPuzzle='false', LastInsertedPuzzle=? WHERE LocalIdentityID=?;");
\r
147 st.Bind(0,now.Format("%Y-%m-%d %H:%M:%S"));
\r
148 st.Bind(1,localidentityid);
\r
152 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IntroductionPuzzleInserter::HandlePutSuccessful inserted puzzle "+idparts[3]);
\r
157 void IntroductionPuzzleInserter::Initialize()
\r
159 m_lastchecked.SetToGMTime();
\r
162 void IntroductionPuzzleInserter::Process()
\r
169 if(m_lastchecked<(now-(1.0/1440.0)))
\r
171 CheckForNeededInsert();
\r
177 void IntroductionPuzzleInserter::RegisterWithThread(FreenetMasterThread *thread)
\r
179 thread->RegisterFCPConnected(this);
\r
180 thread->RegisterFCPMessageHandler(this);
\r
181 thread->RegisterPeriodicProcessor(this);
\r
184 void IntroductionPuzzleInserter::StartInsert(const long localidentityid)
\r
187 std::string idstring;
\r
189 std::string indexstr;
\r
190 UUIDGenerator uuid;
\r
191 std::string messagebase;
\r
192 IntroductionPuzzleXML xml;
\r
193 std::string encodedpuzzle;
\r
194 std::string solutionstring;
\r
195 FCPMessage message;
\r
196 std::string xmldata;
\r
197 std::string xmldatasizestr;
\r
198 std::string privatekey;
\r
200 StringFunctions::Convert(localidentityid,idstring);
\r
202 SQLite3DB::Recordset rs=m_db->Query("SELECT MAX(InsertIndex) FROM tblIntroductionPuzzleInserts WHERE Day='"+now.Format("%Y-%m-%d")+"' AND LocalIdentityID="+idstring+";");
\r
204 if(rs.Empty() || rs.GetField(0)==NULL)
\r
210 index=rs.GetInt(0)+1;
\r
212 StringFunctions::Convert(index,indexstr);
\r
214 SQLite3DB::Recordset rs2=m_db->Query("SELECT PrivateKey FROM tblLocalIdentity WHERE LocalIdentityID="+idstring+";");
\r
215 if(rs2.Empty()==false && rs2.GetField(0)!=NULL)
\r
217 privatekey=rs2.GetField(0);
\r
220 Option::instance()->Get("MessageBase",messagebase);
\r
222 GenerateCaptcha(encodedpuzzle,solutionstring);
\r
224 xml.SetType("captcha");
\r
225 xml.SetUUID(uuid.Generate());
\r
226 xml.SetPuzzleData(encodedpuzzle);
\r
227 xml.SetMimeType("bitmap/image");
\r
229 xmldata=xml.GetXML();
\r
230 StringFunctions::Convert(xmldata.size(),xmldatasizestr);
\r
232 message.SetName("ClientPut");
\r
233 message["URI"]=privatekey+messagebase+"|"+now.Format("%Y-%m-%d")+"|IntroductionPuzzle|"+indexstr+".xml";
\r
234 message["Identifier"]="IntroductionPuzzleInserter|"+idstring+"|"+indexstr+"|"+xml.GetUUID()+"|"+message["URI"];
\r
235 message["UploadFrom"]="direct";
\r
236 message["DataLength"]=xmldatasizestr;
\r
237 m_fcp->SendMessage(message);
\r
238 m_fcp->SendRaw(xmldata.c_str(),xmldata.size());
\r
240 m_db->Execute("UPDATE tblLocalIdentity SET InsertingPuzzle='true' WHERE LocalIdentityID="+idstring+";");
\r
241 m_db->Execute("INSERT INTO tblIntroductionPuzzleInserts(UUID,Type,MimeType,LocalIdentityID,PuzzleData,PuzzleSolution) VALUES('"+xml.GetUUID()+"','captcha','image/bmp',"+idstring+",'"+encodedpuzzle+"','"+solutionstring+"');");
\r
243 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IntroductionPuzzleInserter::StartInsert started insert for id "+idstring);
\r