From: SomeDude Date: Sun, 27 Apr 2008 12:14:00 +0000 (+0200) Subject: version 0.2.11 X-Git-Url: https://git.pterodactylus.net/?a=commitdiff_plain;h=63376b2a82c3f6cdf2df56b1f134bd7df0aaab3a;p=fms.git version 0.2.11 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 3758251..ebff758 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ src/freenet/boardlistinserter.cpp src/freenet/boardlistrequester.cpp src/freenet/boardlistxml.cpp src/freenet/fcpv2.cpp +src/freenet/fileinserter.cpp src/freenet/freenetmasterthread.cpp src/freenet/freenetssk.cpp src/freenet/identityinserter.cpp @@ -65,6 +66,7 @@ src/http/pages/controlboardpage.cpp src/http/pages/createidentitypage.cpp src/http/pages/execquerypage.cpp src/http/pages/homepage.cpp +src/http/pages/insertedfilespage.cpp src/http/pages/localidentitiespage.cpp src/http/pages/optionspage.cpp src/http/pages/peerdetailspage.cpp diff --git a/include/freenet/fileinserter.h b/include/freenet/fileinserter.h new file mode 100644 index 0000000..efc105a --- /dev/null +++ b/include/freenet/fileinserter.h @@ -0,0 +1,21 @@ +#ifndef _fileinserter_ +#define _fileinserter_ + +#include "iindexinserter.h" + +class FileInserter:public IIndexInserter +{ +public: + FileInserter(); + FileInserter(FCPv2 *fcp); + +private: + void Initialize(); + const bool HandlePutSuccessful(FCPMessage &message); + const bool HandlePutFailed(FCPMessage &message); + void StartInsert(const long &fileinsertid); + void CheckForNeededInsert(); + +}; + +#endif // _fileinserter_ diff --git a/include/freenet/messagexml.h b/include/freenet/messagexml.h index 7daa842..71e6e65 100644 --- a/include/freenet/messagexml.h +++ b/include/freenet/messagexml.h @@ -15,14 +15,22 @@ public: std::string GetXML(); const bool ParseXML(const std::string &xml); - std::string GetDate() { return m_date; } - std::string GetTime() { return m_time; } - std::string GetSubject() { return m_subject; } - std::string GetMessageID() { return m_messageid; } - std::string GetReplyBoard() { return m_replyboard; } - std::string GetBody() { return m_body; } - std::vector GetBoards() { return m_boards; } - std::map GetInReplyTo() { return m_inreplyto; } + struct fileattachment + { + fileattachment(const std::string &key, const int size):m_key(key),m_size(size) {} + std::string m_key; + int m_size; + }; + + std::string GetDate() { return m_date; } + std::string GetTime() { return m_time; } + std::string GetSubject() { return m_subject; } + std::string GetMessageID() { return m_messageid; } + std::string GetReplyBoard() { return m_replyboard; } + std::string GetBody() { return m_body; } + std::vector GetBoards() { return m_boards; } + std::map GetInReplyTo() { return m_inreplyto; } + std::vector GetFileAttachments() { return m_fileattachments; } void SetDate(const std::string &date) { m_date=date; } void SetTime(const std::string &time) { m_time=time; } @@ -32,6 +40,7 @@ public: void SetBody(const std::string &body) { m_body=body; } void AddBoard(const std::string &board) { m_boards.push_back(board); } void AddInReplyTo(const long index, const std::string &messageid) { m_inreplyto[index]=messageid; } + void AddFileAttachment(const std::string &key, const int size) { m_fileattachments.push_back(fileattachment(key,size)); } private: void Initialize(); @@ -43,6 +52,7 @@ private: std::vector m_boards; std::string m_replyboard; std::map m_inreplyto; + std::vector m_fileattachments; std::string m_body; }; diff --git a/include/global.h b/include/global.h index 6db0d86..59d9dd2 100644 --- a/include/global.h +++ b/include/global.h @@ -5,7 +5,7 @@ #include #include "pthreadwrapper/thread.h" -#define FMS_VERSION "0.2.10" +#define FMS_VERSION "0.2.11" // opens database and creates tables and initial inserts if necessary void SetupDB(); @@ -16,6 +16,7 @@ void ConvertDB0104To0105(); void ConvertDB0105To0106(); void ConvertDB0106To0107(); void ConvertDB0107To0108(); +void ConvertDB0108To0109(); // inserts default options into the database void SetupDefaultOptions(); // opens logfile and sets it up diff --git a/include/http/pages/insertedfilespage.h b/include/http/pages/insertedfilespage.h new file mode 100644 index 0000000..c09e638 --- /dev/null +++ b/include/http/pages/insertedfilespage.h @@ -0,0 +1,18 @@ +#ifndef _insertedfilespage_ +#define _insertedfilespage_ + +#include "../ipagehandler.h" +#include "../../idatabase.h" + +class InsertedFilesPage:public IPageHandler,public IDatabase +{ +public: + InsertedFilesPage(const std::string &templatestr):IPageHandler(templatestr) {} + +private: + const bool WillHandleURI(const std::string &uri); + const std::string GeneratePage(const std::string &method, const std::map &queryvars); + +}; + +#endif // _insertedfilespage_ diff --git a/include/message.h b/include/message.h index 5aed3ed..625aa22 100644 --- a/include/message.h +++ b/include/message.h @@ -59,6 +59,13 @@ private: void StripAdministrationBoards(); // removes administration boards from boards vector const int FindLocalIdentityID(const std::string &name); + struct fileattachment + { + fileattachment(const std::string &filename, const std::vector &data):m_filename(filename),m_data(data) {} + std::string m_filename; + std::vector m_data; + }; + long m_messageid; bool m_addnewpostfromidentities; std::string m_messageuuid; @@ -69,6 +76,7 @@ private: std::string m_fromname; std::vector m_boards; std::map m_inreplyto; + std::vector m_fileattachments; long m_changemessagetrustonreply; long m_minlocalmessagetrust; long m_minlocaltrustlisttrust; diff --git a/readme.txt b/readme.txt index be55508..133a0aa 100644 --- a/readme.txt +++ b/readme.txt @@ -1,7 +1,7 @@ COMPILING --------- -Compiling FMS requires CMake, and pthreads. Other required libraries are -bundled with FMS. +Compiling FMS requires CMake, pthreads and iconv if you want to do charset +conversion. Other required libraries are bundled with FMS. To compile, run these commands from the source directory: cmake . @@ -51,10 +51,13 @@ is discarded when posting messages. POSTING MESSAGES ---------------- -Use must set your newsreader to use UTF-8 when posting messages. Any non-text -attachment to the message will be stripped. Text attachments will be inlined -with the message body. Cross posting is fine, but remember that each identity -can set a limit to the number of boards each message may be cross posted to. +You must set your newsreader to use UTF-8 when posting messages. Any non-text +attachment to the message will be inserted as a regular file and the key added +to the body of the message when received. Keep the attachments small, as the +message can't be inserted until all attachments are inserted. Text attachments +will be inlined with the message body. Cross posting is fine, but remember +that each identity can set a limit to the number of boards each message may be +cross posted to. CONTROL BOARDS -------------- @@ -76,6 +79,12 @@ content. The Freesite will be inserted once a day and contain your last 10 posts and your trust list if you are publishing it. The site will be inserted to a USK accessible via: USK@yourpublickey.../fms/0/ +You may add extra files to your Freesite by creating a file called identityname- +files.txt that contains a list of files to add to the Freesite. There should +be one file per line, and the path to each file may be absolute or relative to +the working directory, but you MUST use / as the path separator. Files cannot +be named index.htm, trustlist.htm, or files.htm. + TRUST ----- Trust is the most important element of FMS. It determines which identities you diff --git a/src/db/sqlite3statement.cpp b/src/db/sqlite3statement.cpp index 81df27a..fea3d76 100644 --- a/src/db/sqlite3statement.cpp +++ b/src/db/sqlite3statement.cpp @@ -229,8 +229,24 @@ const bool Statement::ResultBlob(const int column, void *data, int &length) { //ZThread::Guard g(DB::instance()->m_mutex); //PThread::Guard g(DB::Instance()->m_mutex); - data=(void *)sqlite3_column_blob(m_statement,column); - length=sqlite3_column_bytes(m_statement,column); + int bloblength=sqlite3_column_bytes(m_statement,column); + if(bloblength>length) + { + bloblength=length; + } + if(bloblength::iterator i=m_boards.begin(); i!=m_boards.end(); i++) { std::string boardname=(*i).m_name; - StringFunctions::Convert(boardname,boardname); + StringFunctions::LowerCase(boardname,boardname); TiXmlElement *tr=new TiXmlElement("Board"); tid->LinkEndChild(tr); tr->LinkEndChild(XMLCreateCDATAElement("Name",boardname)); diff --git a/src/freenet/fileinserter.cpp b/src/freenet/fileinserter.cpp new file mode 100644 index 0000000..d8d2721 --- /dev/null +++ b/src/freenet/fileinserter.cpp @@ -0,0 +1,106 @@ +#include "../../include/freenet/fileinserter.h" + +#ifdef XMEM + #include +#endif + +FileInserter::FileInserter() +{ + Initialize(); +} + +FileInserter::FileInserter(FCPv2 *fcp):IIndexInserter(fcp) +{ + Initialize(); +} + +void FileInserter::CheckForNeededInsert() +{ + // only do 1 insert at a time + if(m_inserting.size()==0) + { + SQLite3DB::Statement st=m_db->Prepare("SELECT FileInsertID FROM tblFileInserts WHERE Key IS NULL;"); + st.Step(); + if(st.RowReturned()) + { + int id=-1; + st.ResultInt(0,id); + StartInsert(id); + } + } +} + +const bool FileInserter::HandlePutFailed(FCPMessage &message) +{ + std::vector idparts; + long fileinsertid; + + StringFunctions::Split(message["Identifier"],"|",idparts); + StringFunctions::Convert(idparts[1],fileinsertid); + + RemoveFromInsertList(fileinsertid); + + m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"FileInserter::HandlePutFailed failed to insert "+message["Identifier"]); + + return true; + +} + +const bool FileInserter::HandlePutSuccessful(FCPMessage &message) +{ + std::vector idparts; + long fileinsertid; + + StringFunctions::Split(message["Identifier"],"|",idparts); + StringFunctions::Convert(idparts[1],fileinsertid); + + SQLite3DB::Statement st=m_db->Prepare("UPDATE tblFileInserts SET Key=?, Data=NULL WHERE FileInsertID=?;"); + st.Bind(0,message["URI"]); + st.Bind(1,fileinsertid); + st.Step(); + + RemoveFromInsertList(fileinsertid); + + return true; +} + +void FileInserter::Initialize() +{ + m_fcpuniquename="FileInserter"; +} + +void FileInserter::StartInsert(const long &fileinsertid) +{ + FCPMessage message; + std::string fileinsertidstr=""; + std::string sizestr=""; + std::string filename=""; + int datalen=-1; + std::vector data; + + StringFunctions::Convert(fileinsertid,fileinsertidstr); + + + SQLite3DB::Statement st=m_db->Prepare("SELECT FileName,Size,Data FROM tblFileInserts WHERE FileInsertID=?;"); + st.Bind(0,fileinsertid); + st.Step(); + + st.ResultText(0,filename); + st.ResultInt(1,datalen); + data.resize(datalen,0); + st.ResultBlob(2,&data[0],datalen); + data.resize(datalen); + + StringFunctions::Convert(data.size(),sizestr); + + message.SetName("ClientPut"); + message["URI"]="CHK@"; + message["TargetFilename"]=filename; + message["Identifier"]=m_fcpuniquename+"|"+fileinsertidstr; + message["UploadFrom"]="direct"; + message["DataLength"]=sizestr; + m_fcp->SendMessage(message); + m_fcp->SendRaw(&data[0],data.size()); + + m_inserting.push_back(fileinsertid); +} diff --git a/src/freenet/freenetmasterthread.cpp b/src/freenet/freenetmasterthread.cpp index db72906..73d26b6 100644 --- a/src/freenet/freenetmasterthread.cpp +++ b/src/freenet/freenetmasterthread.cpp @@ -19,6 +19,7 @@ #include "../../include/freenet/boardlistinserter.h" #include "../../include/freenet/boardlistrequester.h" #include "../../include/freenet/siteinserter.h" +#include "../../include/freenet/fileinserter.h" #include "../../include/pthreadwrapper/thread.h" @@ -281,6 +282,7 @@ void FreenetMasterThread::Setup() m_registrables.push_back(new BoardListInserter(&m_fcp)); m_registrables.push_back(new BoardListRequester(&m_fcp)); m_registrables.push_back(new SiteInserter(&m_fcp)); + m_registrables.push_back(new FileInserter(&m_fcp)); m_registrables.push_back(new PeriodicDBMaintenance()); for(std::vector::iterator i=m_registrables.begin(); i!=m_registrables.end(); i++) diff --git a/src/freenet/messageinserter.cpp b/src/freenet/messageinserter.cpp index 3d5af9a..b4e1ce4 100644 --- a/src/freenet/messageinserter.cpp +++ b/src/freenet/messageinserter.cpp @@ -13,17 +13,29 @@ MessageInserter::MessageInserter(FCPv2 *fcp):IIndexInserter(fcp) void MessageInserter::CheckForNeededInsert() { + bool didinsert=false; // only do 1 insert at a time if(m_inserting.size()==0) { SQLite3DB::Statement st=m_db->Prepare("SELECT MessageUUID FROM tblMessageInserts INNER JOIN tblLocalIdentity ON tblMessageInserts.LocalIdentityID=tblLocalIdentity.LocalIdentityID WHERE tblLocalIdentity.PrivateKey IS NOT NULL AND tblLocalIdentity.PrivateKey <> '' AND tblMessageInserts.Inserted='false';"); st.Step(); - if(st.RowReturned()) + while(st.RowReturned() && m_inserting.size()==0) { - std::string messageuuid; + std::string messageuuid=""; st.ResultText(0,messageuuid); - StartInsert(messageuuid); + + // make sure there are no uninserted files attached to this message + SQLite3DB::Statement st2=m_db->Prepare("SELECT FileInsertID FROM tblFileInserts WHERE Key IS NULL AND MessageUUID=?;"); + st2.Bind(0,messageuuid); + st2.Step(); + + if(st2.RowReturned()==false) + { + StartInsert(messageuuid); + } + + st.Step(); } } } @@ -59,6 +71,7 @@ const bool MessageInserter::HandlePutSuccessful(FCPMessage &message) int localidentityid; int index; std::vector idparts; + StringFunctions::Split(message["Identifier"],"|",idparts); StringFunctions::Convert(idparts[3],index); StringFunctions::Convert(idparts[2],localidentityid); @@ -92,6 +105,12 @@ const bool MessageInserter::HandlePutSuccessful(FCPMessage &message) st2.Bind(1,xml.GetXML()); st2.Bind(2,idparts[1]); st2.Step(); + + //update file insert MessageUUID as well + st2=m_db->Prepare("UPDATE tblFileInserts SET MessageUUID=? WHERE MessageUUID=?;"); + st2.Bind(0,idparts[4]); + st2.Bind(1,idparts[1]); + st2.Step(); } RemoveFromInsertList(idparts[1]); @@ -145,9 +164,27 @@ void MessageInserter::StartInsert(const std::string &messageuuid) } StringFunctions::Convert(index,indexstr); + xmlfile.ParseXML(xml); + + // add file attachments to xml - must do this before we change UUID + st=m_db->Prepare("SELECT Key, Size FROM tblFileInserts WHERE MessageUUID=?;"); + st.Bind(0,xmlfile.GetMessageID()); + st.Step(); + while(st.RowReturned()) + { + std::string key=""; + int size; + + st.ResultText(0,key); + st.ResultInt(1,size); + + xmlfile.AddFileAttachment(key,size); + + st.Step(); + } + // recreate messageuuid in xml - UUID of message will not match entry in MessageInserts table until we successfully insert it // see HandlePutSuccessful - xmlfile.ParseXML(xml); // if we don't already have an @sskpart - add it if(xmlfile.GetMessageID().find("@")==std::string::npos) { diff --git a/src/freenet/messagerequester.cpp b/src/freenet/messagerequester.cpp index c9b78bb..836d402 100644 --- a/src/freenet/messagerequester.cpp +++ b/src/freenet/messagerequester.cpp @@ -206,6 +206,25 @@ const bool MessageRequester::HandleAllData(FCPMessage &message) if(validmessage && savetoboardcount>0) { + std::string nntpbody=""; + nntpbody=xml.GetBody(); + + //add file keys/sizes to body + std::vector fileattachments=xml.GetFileAttachments(); + if(fileattachments.size()>0) + { + nntpbody+="\r\nAttachments"; + } + for(std::vector::iterator i=fileattachments.begin(); i!=fileattachments.end(); i++) + { + std::string sizestr="0"; + StringFunctions::Convert((*i).m_size,sizestr); + + nntpbody+="\r\n"+(*i).m_key; + nntpbody+="\r\n"+sizestr+" bytes"; + nntpbody+="\r\n"; + } + st=m_db->Prepare("INSERT INTO tblMessage(IdentityID,FromName,MessageDate,MessageTime,Subject,MessageUUID,ReplyBoardID,Body,MessageIndex) VALUES(?,?,?,?,?,?,?,?,?);"); st.Bind(0,identityid); st.Bind(1,GetIdentityName(identityid)); @@ -214,7 +233,7 @@ const bool MessageRequester::HandleAllData(FCPMessage &message) st.Bind(4,xml.GetSubject()); st.Bind(5,xml.GetMessageID()); st.Bind(6,GetBoardID(xml.GetReplyBoard(),GetIdentityName(identityid))); - st.Bind(7,xml.GetBody()); + st.Bind(7,nntpbody); st.Bind(8,index); inserted=st.Step(true); int messageid=st.GetLastInsertRowID(); diff --git a/src/freenet/messagexml.cpp b/src/freenet/messagexml.cpp index ec5946e..9652c76 100644 --- a/src/freenet/messagexml.cpp +++ b/src/freenet/messagexml.cpp @@ -51,6 +51,20 @@ std::string MessageXML::GetXML() } } + // add attachemnt node if we have attachments + if(m_fileattachments.size()>0) + { + TiXmlElement *attachments=new TiXmlElement("Attachments"); + tid->LinkEndChild(attachments); + for(std::vector::iterator j=m_fileattachments.begin(); j!=m_fileattachments.end(); j++) + { + TiXmlElement *f=new TiXmlElement("File"); + attachments->LinkEndChild(f); + f->LinkEndChild(XMLCreateCDATAElement("Key",(*j).m_key)); + f->LinkEndChild(XMLCreateTextElement("Size",(*j).m_size)); + } + } + td.Accept(&tp); return std::string(tp.CStr()); } @@ -64,6 +78,7 @@ void MessageXML::Initialize() m_replyboard=""; m_inreplyto.clear(); m_body=""; + m_fileattachments.clear(); } const bool MessageXML::ParseXML(const std::string &xml) @@ -158,6 +173,36 @@ const bool MessageXML::ParseXML(const std::string &xml) node2=node2->NextSibling("Message"); } + node2=hnd.FirstChild("Message").FirstChild("Attachments").FirstChild("File").ToNode(); + while(node2) + { + std::string key=""; + std::string sizestr="-1"; + int size=-1; + + TiXmlHandle hnd2(node2); + + txt=hnd2.FirstChild("Key").FirstChild().ToText(); + if(txt) + { + key=txt->ValueStr(); + } + + txt=hnd2.FirstChild("Size").FirstChild().ToText(); + if(txt) + { + sizestr=txt->ValueStr(); + StringFunctions::Convert(sizestr,size); + } + + if(key!="" && size>0) + { + m_fileattachments.push_back(fileattachment(key,size)); + } + + node2=node2->NextSibling("File"); + } + return true; } else diff --git a/src/freenet/siteinserter.cpp b/src/freenet/siteinserter.cpp index 9db9651..9ee3019 100644 --- a/src/freenet/siteinserter.cpp +++ b/src/freenet/siteinserter.cpp @@ -113,7 +113,7 @@ std::string SiteInserter::GenerateLinks(const bool publishtrustlist, const bool void SiteInserter::GeneratePages(const long localidentityid, std::string &uskkey, std::map &pages) { - SQLite3DB::Statement st=m_db->Prepare("SELECT Name, PrivateKey, PublishTrustList, PublishBoardList FROM tblLocalIdentity WHERE LocalIdentityID=?;"); + SQLite3DB::Statement st=m_db->Prepare("SELECT Name, PrivateKey, PublishTrustList, PublishBoardList, FreesiteEdition FROM tblLocalIdentity WHERE LocalIdentityID=?;"); st.Bind(0,localidentityid); st.Step(); @@ -182,6 +182,66 @@ void SiteInserter::GeneratePages(const long localidentityid, std::string &uskkey LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_ERROR,"SiteInserter::GeneratePages unable to open "+filename+" or site-template.htm."); } + // get extra files that the user wants to add to the Freesite + filename=name+"-files.txt"; + infile=fopen(filename.c_str(),"r+b"); + if(infile) + { + std::vector files; + + fseek(infile,0,SEEK_END); + long len=ftell(infile); + fseek(infile,0,SEEK_SET); + + std::vector data; + data.resize(len); + fread(&data[0],1,data.size(),infile); + fclose(infile); + + // split on \r and \n - on systems with \r\n line endings there will be blank entries, but we'll just skip those + std::string filecontent(data.begin(),data.end()); + StringFunctions::SplitMultiple(filecontent,"\r\n",files); + + for(std::vector::iterator i=files.begin(); i!=files.end(); i++) + { + if((*i)!="" && (*i).find("index.htm")==std::string::npos && (*i).find("trustlist.htm")==std::string::npos && (*i).find("files.htm")==std::string::npos) + { + filename=(*i); + infile=fopen(filename.c_str(),"r+b"); + if(infile) + { + fseek(infile,0,SEEK_END); + len=ftell(infile); + fseek(infile,0,SEEK_SET); + + data.resize(len); + fread(&data[0],1,data.size(),infile); + fclose(infile); + + filecontent=""; + filecontent.append(data.begin(),data.end()); + + // strip off path from filename + while(filename.find_first_of("/")!=std::string::npos) + { + filename.erase(0,filename.find_first_of("/")+1); + } + + if(filecontent.size()>0) + { + pages[filename]=filecontent; + } + + } + else + { + m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"SiteInserter::GeneratePages could not include user file "+(*i)); + } + } + } + + } + } } @@ -285,6 +345,8 @@ const bool SiteInserter::HandlePutFailed(FCPMessage &message) RemoveFromInsertList(localidentityid); + m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"SiteInserter::HandlePutFailed failed to insert Freesite, Freenet error code : "+message["Code"]); + return true; } diff --git a/src/global.cpp b/src/global.cpp index 2dea27b..7e6d842 100644 --- a/src/global.cpp +++ b/src/global.cpp @@ -101,13 +101,19 @@ void SetupDB() major=1; minor=8; } + if(major==1 && minor==8) + { + ConvertDB0108To0109(); + major=1; + minor=9; + } } else { - db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,8);"); + db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,9);"); } - db->Execute("UPDATE tblDBVersion SET Major=1, Minor=8;"); + db->Execute("UPDATE tblDBVersion SET Major=1, Minor=9;"); db->Execute("CREATE TABLE IF NOT EXISTS tblOption(\ Option TEXT UNIQUE,\ @@ -328,6 +334,15 @@ void SetupDB() Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\ );"); + db->Execute("CREATE TABLE IF NOT EXISTS tblFileInserts(\ + FileInsertID INTEGER PRIMARY KEY,\ + MessageUUID TEXT,\ + FileName TEXT,\ + Key TEXT,\ + Size INTEGER,\ + Data BLOB\ + );"); + db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListInserts(\ LocalIdentityID INTEGER,\ Day DATE,\ @@ -598,6 +613,20 @@ void ConvertDB0107To0108() db->Execute("UPDATE tblDBVersion SET Major=1, Minor=8;"); } +void ConvertDB0108To0109() +{ + SQLite3DB::DB *db=SQLite3DB::DB::Instance(); + db->Execute("CREATE TABLE IF NOT EXISTS tblFileInserts(\ + FileInsertID INTEGER PRIMARY KEY,\ + MessageUUID TEXT,\ + FileName TEXT,\ + Key TEXT,\ + Size INTEGER,\ + Data BLOB\ + );"); + db->Execute("UPDATE tblDBVersion SET Major=1, Minor=9;"); +} + void SetupDefaultOptions() { // OptionValue should always be inserted as a string, even if the option really isn't a string - just to keep the field data type consistent diff --git a/src/http/httpthread.cpp b/src/http/httpthread.cpp index 22fc930..4760f80 100644 --- a/src/http/httpthread.cpp +++ b/src/http/httpthread.cpp @@ -14,6 +14,7 @@ #include "../../include/http/pages/peermaintenancepage.h" #include "../../include/http/pages/execquerypage.h" #include "../../include/http/pages/boardspage.h" +#include "../../include/http/pages/insertedfilespage.h" #include @@ -63,6 +64,7 @@ HTTPThread::HTTPThread() m_pagehandlers.push_back(new PeerMaintenancePage(templatestr)); m_pagehandlers.push_back(new ExecQueryPage(templatestr)); m_pagehandlers.push_back(new BoardsPage(templatestr)); + m_pagehandlers.push_back(new InsertedFilesPage(templatestr)); // homepage must be last - catch all page handler m_pagehandlers.push_back(new HomePage(templatestr)); diff --git a/src/http/pages/insertedfilespage.cpp b/src/http/pages/insertedfilespage.cpp new file mode 100644 index 0000000..13abc3d --- /dev/null +++ b/src/http/pages/insertedfilespage.cpp @@ -0,0 +1,48 @@ +#include "../../../include/http/pages/insertedfilespage.h" +#include "../../../include/stringfunctions.h" +#include "../../../include/option.h" + +#ifdef XMEM + #include +#endif + +const std::string InsertedFilesPage::GeneratePage(const std::string &method, const std::map &queryvars) +{ + std::string content="

Inserted Files

"; + + SQLite3DB::Statement st=m_db->Prepare("SELECT Key,FileName,Size FROM tblFileInserts WHERE Key IS NOT NULL ORDER BY FileName"); + st.Step(); + + std::string node="localhost"; + Option::Instance()->Get("FCPHost",node); + + while(st.RowReturned()) + { + std::string key=""; + std::string filename=""; + std::string sizestr=""; + + st.ResultText(0,key); + st.ResultText(1,filename); + st.ResultText(2,sizestr); + + content+=""+SanitizeOutput(filename)+" - "+sizestr+" bytes"; + content+="
"; + + st.Step(); + } + + return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"+StringFunctions::Replace(m_template,"[CONTENT]",content); +} + +const bool InsertedFilesPage::WillHandleURI(const std::string &uri) +{ + if(uri.find("insertedfiles.")!=std::string::npos) + { + return true; + } + else + { + return false; + } +} diff --git a/src/message.cpp b/src/message.cpp index d2693f5..5905021 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -325,6 +325,7 @@ void Message::Initialize() m_fromname=""; m_boards.clear(); m_inreplyto.clear(); + m_fileattachments.clear(); m_changemessagetrustonreply=0; Option::Instance()->Get("ChangeMessageTrustOnReply",tempval); StringFunctions::Convert(tempval,m_changemessagetrustonreply); @@ -694,6 +695,12 @@ const bool Message::ParseNNTPMessage(const std::string &nntpmessage) #endif m_body+=bodypart; } + // add a binary file attachment + else if((*i)->GetName()!="" && (*i)->GetLength()>0 && (*i)->GetContent()) + { + std::vector data((*i)->GetContent(),(*i)->GetContent()+(*i)->GetContentLength()); + m_fileattachments.push_back(fileattachment((*i)->GetName(),data)); + } } return true; @@ -735,6 +742,18 @@ const bool Message::StartFreenetInsert() st.Bind(2,xml.GetXML()); st.Step(); + // insert file attachments into database + st=m_db->Prepare("INSERT INTO tblFileInserts(MessageUUID,FileName,Size,Data) VALUES(?,?,?,?);"); + for(std::vector::iterator i=m_fileattachments.begin(); i!=m_fileattachments.end(); i++) + { + st.Bind(0,m_messageuuid); + st.Bind(1,(*i).m_filename); + st.Bind(2,(long)(*i).m_data.size()); + st.Bind(3,&((*i).m_data[0]),(*i).m_data.size()); + st.Step(); + st.Reset(); + } + HandleChangeTrust(); return true; diff --git a/template.htm b/template.htm index c35813c..7509afd 100644 --- a/template.htm +++ b/template.htm @@ -238,6 +238,7 @@ td { padding-left:5px; padding-right:5px; }
  • Peer Trust
  • Boards
  • Control Boards
  • +
  • Inserted Files