PROJECT(fms)\r
\r
-OPTION(USE_BUNDLED_SQLITE "Use the bundled SQLite3 library" OFF)\r
+OPTION(USE_BUNDLED_SQLITE "Use the bundled SQLite3 library." OFF)\r
+OPTION(DO_CHARSET_CONVERSION "Do charset conversion on sent messages to UTF-8. This requires libiconv." OFF)\r
\r
SET(FMS_SRC \r
src/base64.cpp\r
src/xyssl/sha1.c\r
)\r
\r
+IF(DO_CHARSET_CONVERSION)\r
+ SET(FMS_SRC ${FMS_SRC} src/charsetconverter.cpp)\r
+ENDIF(DO_CHARSET_CONVERSION)\r
+\r
IF(WIN32)\r
SET(FMS_PLATFORM_SRC src/fmsservice.cpp)\r
ELSE(WIN32)\r
FIND_LIBRARY(TINYXML_LIBRARY NAMES tinyxml tinyxml_s)\r
FIND_LIBRARY(PTHREADS_LIBRARY NAMES pthread pthreads pthreadvc2)\r
FIND_LIBRARY(SHTTPD_LIBRARY NAMES shttpd shttpd_s)\r
+FIND_LIBRARY(ICONV_LIBRARY NAMES iconv iconv_s libiconv libiconv_s)\r
\r
IF(SQLITE3_LIBRARY)\r
TARGET_LINK_LIBRARIES(fms ${SQLITE3_LIBRARY})\r
ADD_LIBRARY(shttpd ${SHTTPD_PLATFORM_SRC} libs/shttpd/auth.c libs/shttpd/cgi.c libs/shttpd/config.c libs/shttpd/io_cgi.c libs/shttpd/io_dir.c libs/shttpd/io_emb.c libs/shttpd/io_file.c libs/shttpd/io_socket.c libs/shttpd/io_ssi.c libs/shttpd/io_ssl.c libs/shttpd/log.c libs/shttpd/md5.c libs/shttpd/shttpd.c libs/shttpd/string.c)\r
TARGET_LINK_LIBRARIES(fms shttpd)\r
ENDIF(SHTTPD_LIBRARY)\r
+\r
+IF(DO_CHARSET_CONVERSION)\r
+ ADD_DEFINITIONS(-DDO_CHARSET_CONVERSION)\r
+ IF(ICONV_LIBRARY)\r
+ TARGET_LINK_LIBRARIES(fms ${ICONV_LIBRARY})\r
+ ELSE(ICONV_LIBRARY)\r
+ IF(WIN32)\r
+ MESSAGE(FATAL ERROR "Could not find iconv library. You must set the location manually, or turn off charset conversion.")\r
+ ENDIF(WIN32)\r
+ ENDIF(ICONV_LIBRARY)\r
+ENDIF(DO_CHARSET_CONVERSION)\r
--- /dev/null
+#ifndef _charset_converter_\r
+#define _charset_converter_\r
+\r
+#include <iconv.h>\r
+#include <string>\r
+\r
+class CharsetConverter\r
+{\r
+public:\r
+ CharsetConverter();\r
+ CharsetConverter(const std::string &fromcharset, const std::string &tocharset);\r
+ ~CharsetConverter();\r
+ \r
+ const bool SetConversion(const std::string &fromcharset, const std::string &tocharset);\r
+ \r
+ const bool Convert(const std::string &input, std::string &output);\r
+\r
+private:\r
+\r
+ iconv_t m_iconv;\r
+ std::string m_fromcharset;\r
+ std::string m_tocharset;\r
+\r
+};\r
+\r
+#endif // _charset_converter_\r
// make sure variables have been initialized by the derived class\r
if(m_fcpuniquename=="")\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IIndexInserter<IDTYPE>::FCPConnected fcpuniquename not initialized correctly!");\r
+ m_log->WriteLog(LogFile::LOGLEVEL_FATAL,"IIndexInserter<IDTYPE>::FCPConnected fcpuniquename not initialized correctly!");\r
}\r
if(m_fcpuniquename.find("|")!=std::string::npos)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IIndexInserter<IDTYPE>::FCPConnected fcpuniquename contains | character! This is not a valid character!");\r
+ m_log->WriteLog(LogFile::LOGLEVEL_FATAL,"IIndexInserter<IDTYPE>::FCPConnected fcpuniquename contains | character! This is not a valid character!");\r
}\r
\r
m_inserting.clear();\r
// make sure variables have been initialized by the derived class\r
if(m_maxrequests==-1)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IIndexRequester<IDTYPE>::FCPConnected maxrequests not initialized correctly!");\r
+ m_log->WriteLog(LogFile::LOGLEVEL_FATAL,"IIndexRequester<IDTYPE>::FCPConnected maxrequests not initialized correctly!");\r
}\r
if(m_fcpuniquename=="")\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IIndexRequester<IDTYPE>::FCPConnected fcpuniquename not initialized correctly!");\r
+ m_log->WriteLog(LogFile::LOGLEVEL_FATAL,"IIndexRequester<IDTYPE>::FCPConnected fcpuniquename not initialized correctly!");\r
}\r
if(m_fcpuniquename.find("|")!=std::string::npos)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IIndexRequester<IDTYPE>::FCPConnected fcpuniquename contains | character! This is not a valid character!");\r
+ m_log->WriteLog(LogFile::LOGLEVEL_FATAL,"IIndexRequester<IDTYPE>::FCPConnected fcpuniquename contains | character! This is not a valid character!");\r
}\r
\r
m_lastreceived.SetToGMTime();\r
// if we haven't received any messages to this object in 10 minutes, clear the requests and repopulate id list\r
if(m_ids.size()>0 && m_lastreceived<(now-(1.0/144.0)))\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IIndexRequester<IDTYPE>::Process() Object has not received any messages in 10 minutes. Restarting requests.");\r
+ m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IIndexRequester<IDTYPE>::Process "+m_fcpuniquename+" Object has not received any messages in 10 minutes. Restarting requests.");\r
FCPConnected();\r
}\r
\r
#ifndef _global_\r
#define _global_\r
\r
+#include <string>\r
#include <vector>\r
#include "pthreadwrapper/thread.h"\r
\r
-#define FMS_VERSION "0.2.7"\r
+#define FMS_VERSION "0.2.8"\r
\r
// opens database and creates tables and initial inserts if necessary\r
void SetupDB();\r
make\r
\r
If you want to use the bundled SQLite3 library, add a -D USE_BUNDLED_SQLITE=ON\r
-to the cmake command.\r
+to the cmake command. To do charset conversion to UTF-8 when sending messages,\r
+add a -D DO_CHARSET_CONVERSION=ON.\r
\r
UPGRADING\r
---------\r
--- /dev/null
+#include "../include/charsetconverter.h"\r
+\r
+#include <vector>\r
+\r
+CharsetConverter::CharsetConverter()\r
+{\r
+ m_iconv=(iconv_t)-1;\r
+ m_fromcharset="";\r
+ m_tocharset=""; \r
+}\r
+\r
+CharsetConverter::CharsetConverter(const std::string &fromcharset, const std::string &tocharset)\r
+{\r
+ SetConversion(fromcharset,tocharset);\r
+}\r
+\r
+CharsetConverter::~CharsetConverter()\r
+{\r
+ if(m_iconv!=(iconv_t)-1)\r
+ {\r
+ iconv_close(m_iconv);\r
+ }\r
+}\r
+\r
+const bool CharsetConverter::SetConversion(const std::string &fromcharset, const std::string &tocharset)\r
+{\r
+ if(m_iconv!=(iconv_t)-1)\r
+ {\r
+ iconv_close(m_iconv);\r
+ m_iconv=(iconv_t)-1;\r
+ }\r
+ if((m_iconv=iconv_open(tocharset.c_str(),fromcharset.c_str()))!=(iconv_t)-1)\r
+ {\r
+ m_fromcharset=fromcharset;\r
+ m_tocharset=tocharset;\r
+ return true; \r
+ }\r
+ else\r
+ {\r
+ m_fromcharset="";\r
+ m_tocharset="";\r
+ }\r
+}\r
+\r
+const bool CharsetConverter::Convert(const std::string &input, std::string &output)\r
+{\r
+ if(m_iconv!=(iconv_t)-1)\r
+ {\r
+ std::vector<char> invec(input.begin(),input.end());\r
+ std::vector<char> outvec(invec.size()*4,0);\r
+#ifdef _WIN32\r
+ const char *inptr=&invec[0];\r
+#else\r
+ char *inptr=&invec[0];\r
+#endif\r
+ char *outptr=&outvec[0];\r
+ size_t insize=invec.size();\r
+ size_t outsize=outvec.size();\r
+ size_t rval=0;\r
+ \r
+ rval=iconv(m_iconv,&inptr,&insize,&outptr,&outsize);\r
+ \r
+ if(outsize>=0)\r
+ {\r
+ outvec.resize(outptr-&outvec[0]);\r
+ output="";\r
+ output.append(outvec.begin(),outvec.end());\r
+ }\r
+ else\r
+ {\r
+ return false;\r
+ }\r
+ \r
+ }\r
+ else\r
+ {\r
+ return false; \r
+ }\r
+}\r
st.Bind(0,date.Format("%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
+\r
}\r
\r
void PeriodicDBMaintenance::Process()\r
DELETE FROM tblMessageReplyTo WHERE tblMessageReplyTo.MessageID=old.MessageID;\\r
END;");\r
\r
+ db->Execute("DROP TRIGGER IF EXISTS trgDeleteIdentity;");\r
db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteIdentity AFTER DELETE ON tblIdentity \\r
FOR EACH ROW \\r
BEGIN \\r
DELETE FROM tblMessageRequests WHERE IdentityID=old.IdentityID;\\r
DELETE FROM tblPeerTrust WHERE IdentityID=old.IdentityID;\\r
DELETE FROM tblTrustListRequests WHERE IdentityID=old.IdentityID;\\r
+ DELETE FROM tblIdentityTrust WHERE IdentityID=old.IdentityID;\\r
END;");\r
\r
db->Execute("DROP TRIGGER IF EXISTS trgDeleteLocalIdentity;");\r
usk=publickey;\r
if(usk.find("SSK@")==0)\r
{\r
+ std::string messagebase="";\r
+ Option::Instance()->Get("MessageBase",messagebase);\r
usk.erase(0,3);\r
- usk="USK"+usk+"fms/0/";\r
+ usk="USK"+usk+messagebase+"/0/";\r
}\r
\r
content+="<tr><td>Name</td><td>"+SanitizeOutput(name)+"</td></tr>";\r
}\r
}\r
\r
- if(queryvars.find("formaction")!=queryvars.end() && (*queryvars.find("formaction")).second=="update")\r
+ if(localidentityid!=-1 && queryvars.find("formaction")!=queryvars.end() && (*queryvars.find("formaction")).second=="update")\r
{\r
std::vector<std::string> identityids;\r
std::vector<std::string> oldlmt;\r
content+="</tr>";\r
}\r
\r
- content+="<tr><td colspan=\"5\"><center><input type=\"submit\" value=\"Update Trust\"></center></td></tr>";\r
+ content+="<tr><td colspan=\"8\"><center><input type=\"submit\" value=\"Update Trust\"></center></td></tr>";\r
content+="</table>";\r
content+="</form>";\r
\r
\r
#include <algorithm>\r
\r
+#ifdef DO_CHARSET_CONVERSION\r
+ #include "../include/charsetconverter.h"\r
+#endif\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
m_subject=mime.GetFieldValue("Subject");\r
// remove any path folding\r
m_subject=StringFunctions::Replace(m_subject,"\r\n","");\r
+#if DO_CHARSET_CONVERSION\r
+ if(mime.GetFieldCharset("Subject"))\r
+ {\r
+ std::string charset=mime.GetFieldCharset("Subject");\r
+ CharsetConverter ccv;\r
+ if(charset!="" && charset!="UTF-8" && ccv.SetConversion(charset,"UTF-8"))\r
+ {\r
+ std::string output="";\r
+ ccv.Convert(m_subject,output);\r
+ m_subject=output;\r
+ }\r
+ }\r
+#endif\r
}\r
else\r
{\r
{\r
if((*i)->IsText() && (*i)->GetContent())\r
{\r
- m_body+=(char *)(*i)->GetContent();\r
+ std::string bodypart=(char *)(*i)->GetContent();\r
+#ifdef DO_CHARSET_CONVERSION\r
+ std::string charset=(*i)->GetCharset();\r
+ if(charset!="" && charset!="UTF-8")\r
+ {\r
+ CharsetConverter ccv;\r
+ if(ccv.SetConversion(charset,"UTF-8"))\r
+ {\r
+ std::string output="";\r
+ ccv.Convert(bodypart,output);\r
+ bodypart=output;\r
+ }\r
+ }\r
+#endif\r
+ m_body+=bodypart;\r
}\r
}\r
\r
xml.AddInReplyTo((*j).first,(*j).second);\r
}\r
\r
-\r
- // find identity to insert with\r
- /*\r
- SQLite3DB::Statement st=m_db->Prepare("SELECT LocalIdentityID FROM tblLocalIdentity WHERE Name=?;");\r
- st.Bind(0,m_fromname);\r
- st.Step();\r
-\r
- // couldn't find identity with this name - insert a new identity\r
- if(!st.RowReturned())\r
- {\r
- if(m_addnewpostfromidentities==true)\r
- {\r
- DateTime now;\r
- now.SetToGMTime();\r
- st=m_db->Prepare("INSERT INTO tblLocalIdentity(Name) VALUES(?);");\r
- st.Bind(0,m_fromname);\r
- st.Step(true);\r
- localidentityid=st.GetLastInsertRowID();\r
- }\r
- else\r
- {\r
- return false;\r
- }\r
- }\r
- else\r
- {\r
- st.ResultInt(0,localidentityid);\r
- }\r
- */\r
localidentityid=FindLocalIdentityID(m_fromname);\r
if(localidentityid==-1)\r
{\r