src/freenet/boardlistrequester.cpp\r
src/freenet/boardlistxml.cpp\r
src/freenet/fcpv2.cpp\r
+src/freenet/fileinserter.cpp\r
src/freenet/freenetmasterthread.cpp\r
src/freenet/freenetssk.cpp\r
src/freenet/identityinserter.cpp\r
src/http/pages/createidentitypage.cpp\r
src/http/pages/execquerypage.cpp\r
src/http/pages/homepage.cpp\r
+src/http/pages/insertedfilespage.cpp\r
src/http/pages/localidentitiespage.cpp\r
src/http/pages/optionspage.cpp\r
src/http/pages/peerdetailspage.cpp\r
--- /dev/null
+#ifndef _fileinserter_\r
+#define _fileinserter_\r
+\r
+#include "iindexinserter.h"\r
+\r
+class FileInserter:public IIndexInserter<long>\r
+{\r
+public:\r
+ FileInserter();\r
+ FileInserter(FCPv2 *fcp);\r
+\r
+private:\r
+ void Initialize();\r
+ const bool HandlePutSuccessful(FCPMessage &message);\r
+ const bool HandlePutFailed(FCPMessage &message);\r
+ void StartInsert(const long &fileinsertid);\r
+ void CheckForNeededInsert();\r
+\r
+};\r
+\r
+#endif // _fileinserter_\r
std::string GetXML();\r
const bool ParseXML(const std::string &xml);\r
\r
- std::string GetDate() { return m_date; }\r
- std::string GetTime() { return m_time; }\r
- std::string GetSubject() { return m_subject; }\r
- std::string GetMessageID() { return m_messageid; }\r
- std::string GetReplyBoard() { return m_replyboard; }\r
- std::string GetBody() { return m_body; }\r
- std::vector<std::string> GetBoards() { return m_boards; }\r
- std::map<long,std::string> GetInReplyTo() { return m_inreplyto; }\r
+ struct fileattachment\r
+ {\r
+ fileattachment(const std::string &key, const int size):m_key(key),m_size(size) {}\r
+ std::string m_key;\r
+ int m_size;\r
+ };\r
+\r
+ std::string GetDate() { return m_date; }\r
+ std::string GetTime() { return m_time; }\r
+ std::string GetSubject() { return m_subject; }\r
+ std::string GetMessageID() { return m_messageid; }\r
+ std::string GetReplyBoard() { return m_replyboard; }\r
+ std::string GetBody() { return m_body; }\r
+ std::vector<std::string> GetBoards() { return m_boards; }\r
+ std::map<long,std::string> GetInReplyTo() { return m_inreplyto; }\r
+ std::vector<fileattachment> GetFileAttachments() { return m_fileattachments; }\r
\r
void SetDate(const std::string &date) { m_date=date; }\r
void SetTime(const std::string &time) { m_time=time; }\r
void SetBody(const std::string &body) { m_body=body; }\r
void AddBoard(const std::string &board) { m_boards.push_back(board); }\r
void AddInReplyTo(const long index, const std::string &messageid) { m_inreplyto[index]=messageid; }\r
+ void AddFileAttachment(const std::string &key, const int size) { m_fileattachments.push_back(fileattachment(key,size)); }\r
\r
private:\r
void Initialize();\r
std::vector<std::string> m_boards;\r
std::string m_replyboard;\r
std::map<long,std::string> m_inreplyto;\r
+ std::vector<fileattachment> m_fileattachments;\r
std::string m_body;\r
\r
};\r
#include <vector>\r
#include "pthreadwrapper/thread.h"\r
\r
-#define FMS_VERSION "0.2.10"\r
+#define FMS_VERSION "0.2.11"\r
\r
// opens database and creates tables and initial inserts if necessary\r
void SetupDB();\r
void ConvertDB0105To0106();\r
void ConvertDB0106To0107();\r
void ConvertDB0107To0108();\r
+void ConvertDB0108To0109();\r
// inserts default options into the database\r
void SetupDefaultOptions();\r
// opens logfile and sets it up\r
--- /dev/null
+#ifndef _insertedfilespage_\r
+#define _insertedfilespage_\r
+\r
+#include "../ipagehandler.h"\r
+#include "../../idatabase.h"\r
+\r
+class InsertedFilesPage:public IPageHandler,public IDatabase\r
+{\r
+public:\r
+ InsertedFilesPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
+\r
+private:\r
+ const bool WillHandleURI(const std::string &uri);\r
+ const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
+\r
+};\r
+\r
+#endif // _insertedfilespage_\r
void StripAdministrationBoards(); // removes administration boards from boards vector\r
const int FindLocalIdentityID(const std::string &name);\r
\r
+ struct fileattachment\r
+ {\r
+ fileattachment(const std::string &filename, const std::vector<unsigned char> &data):m_filename(filename),m_data(data) {}\r
+ std::string m_filename;\r
+ std::vector<unsigned char> m_data;\r
+ };\r
+\r
long m_messageid;\r
bool m_addnewpostfromidentities;\r
std::string m_messageuuid;\r
std::string m_fromname;\r
std::vector<std::string> m_boards;\r
std::map<long,std::string> m_inreplyto;\r
+ std::vector<fileattachment> m_fileattachments;\r
long m_changemessagetrustonreply;\r
long m_minlocalmessagetrust;\r
long m_minlocaltrustlisttrust;\r
COMPILING\r
---------\r
-Compiling FMS requires CMake, and pthreads. Other required libraries are\r
-bundled with FMS.\r
+Compiling FMS requires CMake, pthreads and iconv if you want to do charset\r
+conversion. Other required libraries are bundled with FMS.\r
\r
To compile, run these commands from the source directory:\r
cmake .\r
\r
POSTING MESSAGES\r
----------------\r
-Use must set your newsreader to use UTF-8 when posting messages. Any non-text\r
-attachment to the message will be stripped. Text attachments will be inlined\r
-with the message body. Cross posting is fine, but remember that each identity\r
-can set a limit to the number of boards each message may be cross posted to.\r
+You must set your newsreader to use UTF-8 when posting messages. Any non-text\r
+attachment to the message will be inserted as a regular file and the key added\r
+to the body of the message when received. Keep the attachments small, as the\r
+message can't be inserted until all attachments are inserted. Text attachments\r
+will be inlined with the message body. Cross posting is fine, but remember\r
+that each identity can set a limit to the number of boards each message may be\r
+cross posted to.\r
\r
CONTROL BOARDS\r
--------------\r
posts and your trust list if you are publishing it. The site will be inserted\r
to a USK accessible via: USK@yourpublickey.../fms/0/\r
\r
+You may add extra files to your Freesite by creating a file called identityname-\r
+files.txt that contains a list of files to add to the Freesite. There should\r
+be one file per line, and the path to each file may be absolute or relative to\r
+the working directory, but you MUST use / as the path separator. Files cannot\r
+be named index.htm, trustlist.htm, or files.htm.\r
+\r
TRUST\r
-----\r
Trust is the most important element of FMS. It determines which identities you\r
{\r
//ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
//PThread::Guard g(DB::Instance()->m_mutex);\r
- data=(void *)sqlite3_column_blob(m_statement,column);\r
- length=sqlite3_column_bytes(m_statement,column);\r
+ int bloblength=sqlite3_column_bytes(m_statement,column);\r
+ if(bloblength>length)\r
+ {\r
+ bloblength=length;\r
+ }\r
+ if(bloblength<length)\r
+ {\r
+ length=bloblength;\r
+ }\r
+ const void *blobptr=sqlite3_column_blob(m_statement,column);\r
+ if(blobptr)\r
+ {\r
+ std::copy((unsigned char *)blobptr,(unsigned char *)blobptr+bloblength,(unsigned char *)data);\r
+ }\r
+ else\r
+ {\r
+ length=0;\r
+ }\r
return true;\r
}\r
else\r
for(std::vector<board>::iterator i=m_boards.begin(); i!=m_boards.end(); i++)\r
{\r
std::string boardname=(*i).m_name;\r
- StringFunctions::Convert(boardname,boardname);\r
+ StringFunctions::LowerCase(boardname,boardname);\r
TiXmlElement *tr=new TiXmlElement("Board");\r
tid->LinkEndChild(tr);\r
tr->LinkEndChild(XMLCreateCDATAElement("Name",boardname));\r
--- /dev/null
+#include "../../include/freenet/fileinserter.h"\r
+\r
+#ifdef XMEM\r
+ #include <xmem.h>\r
+#endif\r
+\r
+FileInserter::FileInserter()\r
+{\r
+ Initialize();\r
+}\r
+\r
+FileInserter::FileInserter(FCPv2 *fcp):IIndexInserter<long>(fcp)\r
+{\r
+ Initialize();\r
+}\r
+\r
+void FileInserter::CheckForNeededInsert()\r
+{\r
+ // only do 1 insert at a time\r
+ if(m_inserting.size()==0)\r
+ {\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT FileInsertID FROM tblFileInserts WHERE Key IS NULL;");\r
+ st.Step();\r
+ if(st.RowReturned())\r
+ {\r
+ int id=-1;\r
+ st.ResultInt(0,id);\r
+ StartInsert(id);\r
+ }\r
+ }\r
+}\r
+\r
+const bool FileInserter::HandlePutFailed(FCPMessage &message)\r
+{\r
+ std::vector<std::string> idparts;\r
+ long fileinsertid;\r
+\r
+ StringFunctions::Split(message["Identifier"],"|",idparts);\r
+ StringFunctions::Convert(idparts[1],fileinsertid);\r
+\r
+ RemoveFromInsertList(fileinsertid);\r
+\r
+ m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"FileInserter::HandlePutFailed failed to insert "+message["Identifier"]);\r
+\r
+ return true;\r
+\r
+}\r
+\r
+const bool FileInserter::HandlePutSuccessful(FCPMessage &message)\r
+{\r
+ std::vector<std::string> idparts;\r
+ long fileinsertid;\r
+\r
+ StringFunctions::Split(message["Identifier"],"|",idparts);\r
+ StringFunctions::Convert(idparts[1],fileinsertid);\r
+\r
+ SQLite3DB::Statement st=m_db->Prepare("UPDATE tblFileInserts SET Key=?, Data=NULL WHERE FileInsertID=?;");\r
+ st.Bind(0,message["URI"]);\r
+ st.Bind(1,fileinsertid);\r
+ st.Step();\r
+\r
+ RemoveFromInsertList(fileinsertid);\r
+\r
+ return true;\r
+}\r
+\r
+void FileInserter::Initialize()\r
+{\r
+ m_fcpuniquename="FileInserter";\r
+}\r
+\r
+void FileInserter::StartInsert(const long &fileinsertid)\r
+{\r
+ FCPMessage message;\r
+ std::string fileinsertidstr="";\r
+ std::string sizestr="";\r
+ std::string filename="";\r
+ int datalen=-1;\r
+ std::vector<char> data;\r
+\r
+ StringFunctions::Convert(fileinsertid,fileinsertidstr);\r
+\r
+\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT FileName,Size,Data FROM tblFileInserts WHERE FileInsertID=?;");\r
+ st.Bind(0,fileinsertid);\r
+ st.Step();\r
+\r
+ st.ResultText(0,filename);\r
+ st.ResultInt(1,datalen);\r
+ data.resize(datalen,0);\r
+ st.ResultBlob(2,&data[0],datalen);\r
+ data.resize(datalen);\r
+\r
+ StringFunctions::Convert(data.size(),sizestr);\r
+\r
+ message.SetName("ClientPut");\r
+ message["URI"]="CHK@";\r
+ message["TargetFilename"]=filename;\r
+ message["Identifier"]=m_fcpuniquename+"|"+fileinsertidstr;\r
+ message["UploadFrom"]="direct";\r
+ message["DataLength"]=sizestr;\r
+ m_fcp->SendMessage(message);\r
+ m_fcp->SendRaw(&data[0],data.size());\r
+\r
+ m_inserting.push_back(fileinsertid);\r
+}\r
#include "../../include/freenet/boardlistinserter.h"\r
#include "../../include/freenet/boardlistrequester.h"\r
#include "../../include/freenet/siteinserter.h"\r
+#include "../../include/freenet/fileinserter.h"\r
\r
#include "../../include/pthreadwrapper/thread.h"\r
\r
m_registrables.push_back(new BoardListInserter(&m_fcp));\r
m_registrables.push_back(new BoardListRequester(&m_fcp));\r
m_registrables.push_back(new SiteInserter(&m_fcp));\r
+ m_registrables.push_back(new FileInserter(&m_fcp));\r
m_registrables.push_back(new PeriodicDBMaintenance());\r
\r
for(std::vector<IFreenetRegistrable *>::iterator i=m_registrables.begin(); i!=m_registrables.end(); i++)\r
\r
void MessageInserter::CheckForNeededInsert()\r
{\r
+ bool didinsert=false;\r
// only do 1 insert at a time\r
if(m_inserting.size()==0)\r
{\r
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';");\r
st.Step();\r
\r
- if(st.RowReturned())\r
+ while(st.RowReturned() && m_inserting.size()==0)\r
{\r
- std::string messageuuid;\r
+ std::string messageuuid="";\r
st.ResultText(0,messageuuid);\r
- StartInsert(messageuuid);\r
+\r
+ // make sure there are no uninserted files attached to this message\r
+ SQLite3DB::Statement st2=m_db->Prepare("SELECT FileInsertID FROM tblFileInserts WHERE Key IS NULL AND MessageUUID=?;");\r
+ st2.Bind(0,messageuuid);\r
+ st2.Step();\r
+\r
+ if(st2.RowReturned()==false)\r
+ {\r
+ StartInsert(messageuuid);\r
+ }\r
+\r
+ st.Step();\r
}\r
}\r
}\r
int localidentityid;\r
int index;\r
std::vector<std::string> idparts;\r
+\r
StringFunctions::Split(message["Identifier"],"|",idparts);\r
StringFunctions::Convert(idparts[3],index);\r
StringFunctions::Convert(idparts[2],localidentityid);\r
st2.Bind(1,xml.GetXML());\r
st2.Bind(2,idparts[1]);\r
st2.Step();\r
+\r
+ //update file insert MessageUUID as well\r
+ st2=m_db->Prepare("UPDATE tblFileInserts SET MessageUUID=? WHERE MessageUUID=?;");\r
+ st2.Bind(0,idparts[4]);\r
+ st2.Bind(1,idparts[1]);\r
+ st2.Step();\r
}\r
\r
RemoveFromInsertList(idparts[1]);\r
}\r
StringFunctions::Convert(index,indexstr);\r
\r
+ xmlfile.ParseXML(xml);\r
+\r
+ // add file attachments to xml - must do this before we change UUID\r
+ st=m_db->Prepare("SELECT Key, Size FROM tblFileInserts WHERE MessageUUID=?;");\r
+ st.Bind(0,xmlfile.GetMessageID());\r
+ st.Step();\r
+ while(st.RowReturned())\r
+ {\r
+ std::string key="";\r
+ int size;\r
+ \r
+ st.ResultText(0,key);\r
+ st.ResultInt(1,size);\r
+\r
+ xmlfile.AddFileAttachment(key,size);\r
+\r
+ st.Step();\r
+ }\r
+\r
// recreate messageuuid in xml - UUID of message will not match entry in MessageInserts table until we successfully insert it\r
// see HandlePutSuccessful\r
- xmlfile.ParseXML(xml);\r
// if we don't already have an @sskpart - add it\r
if(xmlfile.GetMessageID().find("@")==std::string::npos)\r
{\r
\r
if(validmessage && savetoboardcount>0)\r
{\r
+ std::string nntpbody="";\r
+ nntpbody=xml.GetBody();\r
+\r
+ //add file keys/sizes to body\r
+ std::vector<MessageXML::fileattachment> fileattachments=xml.GetFileAttachments();\r
+ if(fileattachments.size()>0)\r
+ {\r
+ nntpbody+="\r\nAttachments";\r
+ }\r
+ for(std::vector<MessageXML::fileattachment>::iterator i=fileattachments.begin(); i!=fileattachments.end(); i++)\r
+ {\r
+ std::string sizestr="0";\r
+ StringFunctions::Convert((*i).m_size,sizestr);\r
+\r
+ nntpbody+="\r\n"+(*i).m_key;\r
+ nntpbody+="\r\n"+sizestr+" bytes";\r
+ nntpbody+="\r\n";\r
+ }\r
+\r
st=m_db->Prepare("INSERT INTO tblMessage(IdentityID,FromName,MessageDate,MessageTime,Subject,MessageUUID,ReplyBoardID,Body,MessageIndex) VALUES(?,?,?,?,?,?,?,?,?);");\r
st.Bind(0,identityid);\r
st.Bind(1,GetIdentityName(identityid));\r
st.Bind(4,xml.GetSubject());\r
st.Bind(5,xml.GetMessageID());\r
st.Bind(6,GetBoardID(xml.GetReplyBoard(),GetIdentityName(identityid)));\r
- st.Bind(7,xml.GetBody());\r
+ st.Bind(7,nntpbody);\r
st.Bind(8,index);\r
inserted=st.Step(true);\r
int messageid=st.GetLastInsertRowID();\r
}\r
}\r
\r
+ // add attachemnt node if we have attachments\r
+ if(m_fileattachments.size()>0)\r
+ {\r
+ TiXmlElement *attachments=new TiXmlElement("Attachments");\r
+ tid->LinkEndChild(attachments);\r
+ for(std::vector<fileattachment>::iterator j=m_fileattachments.begin(); j!=m_fileattachments.end(); j++)\r
+ {\r
+ TiXmlElement *f=new TiXmlElement("File");\r
+ attachments->LinkEndChild(f);\r
+ f->LinkEndChild(XMLCreateCDATAElement("Key",(*j).m_key));\r
+ f->LinkEndChild(XMLCreateTextElement("Size",(*j).m_size));\r
+ }\r
+ }\r
+\r
td.Accept(&tp);\r
return std::string(tp.CStr());\r
}\r
m_replyboard="";\r
m_inreplyto.clear();\r
m_body="";\r
+ m_fileattachments.clear();\r
}\r
\r
const bool MessageXML::ParseXML(const std::string &xml)\r
node2=node2->NextSibling("Message");\r
}\r
\r
+ node2=hnd.FirstChild("Message").FirstChild("Attachments").FirstChild("File").ToNode();\r
+ while(node2)\r
+ {\r
+ std::string key="";\r
+ std::string sizestr="-1";\r
+ int size=-1;\r
+\r
+ TiXmlHandle hnd2(node2);\r
+\r
+ txt=hnd2.FirstChild("Key").FirstChild().ToText();\r
+ if(txt)\r
+ {\r
+ key=txt->ValueStr();\r
+ }\r
+\r
+ txt=hnd2.FirstChild("Size").FirstChild().ToText();\r
+ if(txt)\r
+ {\r
+ sizestr=txt->ValueStr();\r
+ StringFunctions::Convert(sizestr,size);\r
+ }\r
+\r
+ if(key!="" && size>0)\r
+ {\r
+ m_fileattachments.push_back(fileattachment(key,size));\r
+ }\r
+\r
+ node2=node2->NextSibling("File");\r
+ }\r
+\r
return true;\r
}\r
else\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
+ SQLite3DB::Statement st=m_db->Prepare("SELECT Name, PrivateKey, PublishTrustList, PublishBoardList, FreesiteEdition FROM tblLocalIdentity WHERE LocalIdentityID=?;");\r
st.Bind(0,localidentityid);\r
st.Step();\r
\r
LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_ERROR,"SiteInserter::GeneratePages unable to open "+filename+" or site-template.htm.");\r
}\r
\r
+ // get extra files that the user wants to add to the Freesite\r
+ filename=name+"-files.txt";\r
+ infile=fopen(filename.c_str(),"r+b");\r
+ if(infile)\r
+ {\r
+ std::vector<std::string> files;\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
+ // split on \r and \n - on systems with \r\n line endings there will be blank entries, but we'll just skip those\r
+ std::string filecontent(data.begin(),data.end());\r
+ StringFunctions::SplitMultiple(filecontent,"\r\n",files);\r
+\r
+ for(std::vector<std::string>::iterator i=files.begin(); i!=files.end(); i++)\r
+ {\r
+ if((*i)!="" && (*i).find("index.htm")==std::string::npos && (*i).find("trustlist.htm")==std::string::npos && (*i).find("files.htm")==std::string::npos)\r
+ {\r
+ filename=(*i);\r
+ infile=fopen(filename.c_str(),"r+b");\r
+ if(infile)\r
+ {\r
+ fseek(infile,0,SEEK_END);\r
+ len=ftell(infile);\r
+ fseek(infile,0,SEEK_SET);\r
+\r
+ data.resize(len);\r
+ fread(&data[0],1,data.size(),infile);\r
+ fclose(infile);\r
+\r
+ filecontent="";\r
+ filecontent.append(data.begin(),data.end());\r
+\r
+ // strip off path from filename\r
+ while(filename.find_first_of("/")!=std::string::npos)\r
+ {\r
+ filename.erase(0,filename.find_first_of("/")+1);\r
+ }\r
+\r
+ if(filecontent.size()>0)\r
+ {\r
+ pages[filename]=filecontent;\r
+ }\r
+\r
+ }\r
+ else\r
+ {\r
+ m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"SiteInserter::GeneratePages could not include user file "+(*i));\r
+ }\r
+ }\r
+ }\r
+\r
+ }\r
+\r
}\r
}\r
\r
\r
RemoveFromInsertList(localidentityid);\r
\r
+ m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"SiteInserter::HandlePutFailed failed to insert Freesite, Freenet error code : "+message["Code"]);\r
+\r
return true;\r
}\r
\r
major=1;\r
minor=8;\r
}\r
+ if(major==1 && minor==8)\r
+ {\r
+ ConvertDB0108To0109();\r
+ major=1;\r
+ minor=9;\r
+ }\r
}\r
else\r
{\r
- db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,8);");\r
+ db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,9);");\r
}\r
\r
- db->Execute("UPDATE tblDBVersion SET Major=1, Minor=8;");\r
+ db->Execute("UPDATE tblDBVersion SET Major=1, Minor=9;");\r
\r
db->Execute("CREATE TABLE IF NOT EXISTS tblOption(\\r
Option TEXT UNIQUE,\\r
Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\\r
);");\r
\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblFileInserts(\\r
+ FileInsertID INTEGER PRIMARY KEY,\\r
+ MessageUUID TEXT,\\r
+ FileName TEXT,\\r
+ Key TEXT,\\r
+ Size INTEGER,\\r
+ Data BLOB\\r
+ );");\r
+\r
db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListInserts(\\r
LocalIdentityID INTEGER,\\r
Day DATE,\\r
db->Execute("UPDATE tblDBVersion SET Major=1, Minor=8;");\r
}\r
\r
+void ConvertDB0108To0109()\r
+{\r
+ SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblFileInserts(\\r
+ FileInsertID INTEGER PRIMARY KEY,\\r
+ MessageUUID TEXT,\\r
+ FileName TEXT,\\r
+ Key TEXT,\\r
+ Size INTEGER,\\r
+ Data BLOB\\r
+ );");\r
+ db->Execute("UPDATE tblDBVersion SET Major=1, Minor=9;");\r
+}\r
+\r
void SetupDefaultOptions()\r
{\r
// 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\r
#include "../../include/http/pages/peermaintenancepage.h"\r
#include "../../include/http/pages/execquerypage.h"\r
#include "../../include/http/pages/boardspage.h"\r
+#include "../../include/http/pages/insertedfilespage.h"\r
\r
#include <iostream>\r
\r
m_pagehandlers.push_back(new PeerMaintenancePage(templatestr));\r
m_pagehandlers.push_back(new ExecQueryPage(templatestr));\r
m_pagehandlers.push_back(new BoardsPage(templatestr));\r
+ m_pagehandlers.push_back(new InsertedFilesPage(templatestr));\r
// homepage must be last - catch all page handler\r
m_pagehandlers.push_back(new HomePage(templatestr));\r
\r
--- /dev/null
+#include "../../../include/http/pages/insertedfilespage.h"\r
+#include "../../../include/stringfunctions.h"\r
+#include "../../../include/option.h"\r
+\r
+#ifdef XMEM\r
+ #include <xmem.h>\r
+#endif\r
+\r
+const std::string InsertedFilesPage::GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars)\r
+{\r
+ std::string content="<h2>Inserted Files</h2>";\r
+\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT Key,FileName,Size FROM tblFileInserts WHERE Key IS NOT NULL ORDER BY FileName");\r
+ st.Step();\r
+\r
+ std::string node="localhost";\r
+ Option::Instance()->Get("FCPHost",node);\r
+\r
+ while(st.RowReturned())\r
+ {\r
+ std::string key="";\r
+ std::string filename="";\r
+ std::string sizestr="";\r
+\r
+ st.ResultText(0,key);\r
+ st.ResultText(1,filename);\r
+ st.ResultText(2,sizestr);\r
+\r
+ content+="<a href=\"http://"+node+":8888/"+StringFunctions::UriEncode(key)+"\">"+SanitizeOutput(filename)+"</a> - "+sizestr+" bytes";\r
+ content+="<br>";\r
+\r
+ st.Step();\r
+ }\r
+\r
+ return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"+StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+}\r
+\r
+const bool InsertedFilesPage::WillHandleURI(const std::string &uri)\r
+{\r
+ if(uri.find("insertedfiles.")!=std::string::npos)\r
+ {\r
+ return true;\r
+ }\r
+ else\r
+ {\r
+ return false;\r
+ }\r
+}\r
m_fromname="";\r
m_boards.clear();\r
m_inreplyto.clear();\r
+ m_fileattachments.clear();\r
m_changemessagetrustonreply=0;\r
Option::Instance()->Get("ChangeMessageTrustOnReply",tempval);\r
StringFunctions::Convert(tempval,m_changemessagetrustonreply);\r
#endif\r
m_body+=bodypart;\r
}\r
+ // add a binary file attachment\r
+ else if((*i)->GetName()!="" && (*i)->GetLength()>0 && (*i)->GetContent())\r
+ {\r
+ std::vector<unsigned char> data((*i)->GetContent(),(*i)->GetContent()+(*i)->GetContentLength());\r
+ m_fileattachments.push_back(fileattachment((*i)->GetName(),data));\r
+ }\r
}\r
\r
return true;\r
st.Bind(2,xml.GetXML());\r
st.Step();\r
\r
+ // insert file attachments into database\r
+ st=m_db->Prepare("INSERT INTO tblFileInserts(MessageUUID,FileName,Size,Data) VALUES(?,?,?,?);");\r
+ for(std::vector<fileattachment>::iterator i=m_fileattachments.begin(); i!=m_fileattachments.end(); i++)\r
+ {\r
+ st.Bind(0,m_messageuuid);\r
+ st.Bind(1,(*i).m_filename);\r
+ st.Bind(2,(long)(*i).m_data.size());\r
+ st.Bind(3,&((*i).m_data[0]),(*i).m_data.size());\r
+ st.Step();\r
+ st.Reset();\r
+ }\r
+\r
HandleChangeTrust();\r
\r
return true;\r
<li><a href="peertrust.htm">Peer Trust</a></li>\r
<li><a href="boards.htm">Boards</a></li>\r
<li><a href="controlboard.htm">Control Boards</a></li>\r
+ <li><a href="insertedfiles.htm">Inserted Files</a></li>\r
</ul>\r
</div>\r
\r