From f2545574af789b63fc655decfe31a3d9f1b30504 Mon Sep 17 00:00:00 2001 From: SomeDude Date: Sun, 7 Dec 2008 12:41:00 +0100 Subject: [PATCH] version 0.3.24 --- CMakeLists.txt | 2 - include/global.h | 6 +- include/http/ipagehandler.h | 2 + readme.txt | 14 +- src/http/fmshttprequesthandlerfactory.cpp | 4 - src/http/ipagehandler.cpp | 10 ++ src/http/pages/announceidentitypage.cpp | 6 +- src/http/pages/browseboardspage.cpp | 212 ------------------------ src/http/pages/browsemessagespage.cpp | 265 ------------------------------ src/http/pages/forumcreatepostpage.cpp | 4 +- src/http/pages/forumviewthreadpage.cpp | 19 ++- src/http/pages/peertrustpage.cpp | 2 +- src/threadbuilder.cpp | 7 + 13 files changed, 54 insertions(+), 499 deletions(-) delete mode 100644 src/http/pages/browseboardspage.cpp delete mode 100644 src/http/pages/browsemessagespage.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a5aef9e..4585bbc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,8 +79,6 @@ src/http/multipartparser.cpp src/http/pages/addpeerpage.cpp src/http/pages/announceidentitypage.cpp src/http/pages/boardspage.cpp -src/http/pages/browseboardspage.cpp -src/http/pages/browsemessagespage.cpp src/http/pages/confirmpage.cpp src/http/pages/controlboardpage.cpp src/http/pages/createidentitypage.cpp diff --git a/include/global.h b/include/global.h index aff023f..eb9d33d 100644 --- a/include/global.h +++ b/include/global.h @@ -7,10 +7,10 @@ #define VERSION_MAJOR "0" #define VERSION_MINOR "3" -#define VERSION_RELEASE "23" +#define VERSION_RELEASE "24" #define FMS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_RELEASE -#define FMS_FREESITE_USK "USK@0npnMrqZNKRCRoGojZV93UNHCMN-6UU3rRSAmP6jNLE,~BG-edFtdCC1cSH4O3BWdeIYa8Sw5DfyrSV-TKdO5ec,AQACAAE/fms/84/" -#define FMS_VERSION_EDITION "25" +#define FMS_FREESITE_USK "USK@0npnMrqZNKRCRoGojZV93UNHCMN-6UU3rRSAmP6jNLE,~BG-edFtdCC1cSH4O3BWdeIYa8Sw5DfyrSV-TKdO5ec,AQACAAE/fms/85/" +#define FMS_VERSION_EDITION "26" typedef Poco::ScopedLock Guard; diff --git a/include/http/ipagehandler.h b/include/http/ipagehandler.h index 16afb7c..f6f2cc0 100644 --- a/include/http/ipagehandler.h +++ b/include/http/ipagehandler.h @@ -39,6 +39,8 @@ protected: // replaces html elements with encoded characters (i.e. < becomes <) const std::string SanitizeOutput(const std::string &input); + // don't replace space with  , because browser might convert to unicode non breaking space character + const std::string SanitizeTextAreaOutput(const std::string &input); std::string m_template; std::string m_pagename; diff --git a/readme.txt b/readme.txt index caaf69d..a919c4d 100644 --- a/readme.txt +++ b/readme.txt @@ -24,12 +24,12 @@ keep the same database unless otherwise noted in the release information. INSTALLATION ------------ -Place the binary, any templates, and the fonts directory in a directory of your -choice. Windows users may need to download the runtime DLLs available from the -fms Freesite and place in the fms directory if they are not already installed -on the system. On the first run, a database file will also be created in this -directory. Make sure the user that runs FMS has read/write access to this -directory. +Place the binary, any templates, and the fonts and images directories in a +directory of your choice. Windows users may need to download the runtime DLLs +available from the fms Freesite and place in the fms directory if they are not +already installed on the system. On the first run, a database file will also +be created in this directory. Make sure the user that runs FMS has read/write +access to this directory. RUNNING ------- @@ -64,6 +64,8 @@ WEB INTERFACE ------------- By default, a web interface for administration will be running at http:// localhost:8080. You can use the interface to configure and administer FMS. +There is also a forum built into the web interface so you can read and send +messages without needing to use a newsreader. NNTP CONFIGURATION ------------------ diff --git a/src/http/fmshttprequesthandlerfactory.cpp b/src/http/fmshttprequesthandlerfactory.cpp index c4606c0..84952d2 100644 --- a/src/http/fmshttprequesthandlerfactory.cpp +++ b/src/http/fmshttprequesthandlerfactory.cpp @@ -18,8 +18,6 @@ #include "../../include/http/pages/peertrustpage.h" #include "../../include/http/pages/versioninfopage.h" #include "../../include/http/pages/recentlyaddedpage.h" -#include "../../include/http/pages/browseboardspage.h" -#include "../../include/http/pages/browsemessagespage.h" #include "../../include/http/pages/forummainpage.h" #include "../../include/http/pages/showimagepage.h" #include "../../include/http/pages/forumthreadspage.h" @@ -81,8 +79,6 @@ FMSHTTPRequestHandlerFactory::FMSHTTPRequestHandlerFactory() m_pagehandlers.push_back(new PeerTrustPage(templatestr)); m_pagehandlers.push_back(new VersionInfoPage(templatestr)); m_pagehandlers.push_back(new RecentlyAddedPage(templatestr)); - m_pagehandlers.push_back(new BrowseBoardsPage(templatestr)); - m_pagehandlers.push_back(new BrowseMessagesPage(templatestr)); m_pagehandlers.push_back(new ShowImagePage()); m_pagehandlers.push_back(new ForumMainPage(forumtemplate)); m_pagehandlers.push_back(new ForumThreadsPage(forumtemplate)); diff --git a/src/http/ipagehandler.cpp b/src/http/ipagehandler.cpp index 52e96f6..560c912 100644 --- a/src/http/ipagehandler.cpp +++ b/src/http/ipagehandler.cpp @@ -152,6 +152,16 @@ const std::string IPageHandler::SanitizeOutput(const std::string &input) return output; } +const std::string IPageHandler::SanitizeTextAreaOutput(const std::string &input) +{ + // must do & first because all other elements have & in them! + std::string output=StringFunctions::Replace(input,"&","&"); + output=StringFunctions::Replace(output,"<","<"); + output=StringFunctions::Replace(output,">",">"); + output=StringFunctions::Replace(output,"\"","""); + return output; +} + const bool IPageHandler::ValidateFormPassword(const std::map &vars) { Poco::DateTime date; diff --git a/src/http/pages/announceidentitypage.cpp b/src/http/pages/announceidentitypage.cpp index e8f7fd4..bf95295 100644 --- a/src/http/pages/announceidentitypage.cpp +++ b/src/http/pages/announceidentitypage.cpp @@ -26,7 +26,7 @@ const std::string AnnounceIdentityPage::CreateLocalIdentityDropDown(const std::s st.ResultText(1,name); st.ResultText(2,pubkey); - rval+=""; + rval+=""; st.Step(); } rval+=""; @@ -47,11 +47,11 @@ const std::string AnnounceIdentityPage::GeneratePage(const std::string &method, std::string pubkey=""; int requestindex=0; bool willshow=false; + std::string localidentityidstr=""; if(queryvars.find("formaction")!=queryvars.end() && (*queryvars.find("formaction")).second=="announce" && ValidateFormPassword(queryvars)) { SQLite3DB::Statement insert=m_db->Prepare("INSERT INTO tblIdentityIntroductionInserts(LocalIdentityID,Day,UUID,Solution) VALUES(?,?,?,?);"); - std::string localidentityidstr=""; int localidentityid=0; std::vector uuids; std::vector days; @@ -87,7 +87,7 @@ const std::string AnnounceIdentityPage::GeneratePage(const std::string &method, content+=""; content+=""; content+=""; content+=""; content+=""; diff --git a/src/http/pages/browseboardspage.cpp b/src/http/pages/browseboardspage.cpp deleted file mode 100644 index e759cd6..0000000 --- a/src/http/pages/browseboardspage.cpp +++ /dev/null @@ -1,212 +0,0 @@ -#include "../../../include/http/pages/browseboardspage.h" -#include "../../../include/stringfunctions.h" - -#ifdef XMEM - #include -#endif - -const std::string BrowseBoardsPage::BuildQueryString(const long startrow, const std::string &boardsearch, const std::string &sortby, const std::string &sortorder) -{ - std::string returnval=""; - std::string tempval=""; - - if(startrow>=0) - { - StringFunctions::Convert(startrow,tempval); - returnval+="startrow="+tempval; - } - - if(boardsearch!="") - { - if(returnval!="") - { - returnval+="&"; - } - returnval+="boardsearch="+boardsearch; - } - - if(sortby!="") - { - if(returnval!="") - { - returnval+="&"; - } - returnval+="sortby="+sortby; - if(sortorder=="ASC" || sortorder=="DESC") - { - if(returnval!="") - { - returnval+="&"; - } - returnval+="sortorder="+sortorder; - } - else - { - if(returnval!="") - { - returnval+="&"; - } - returnval+="sortorder=ASC"; - } - } - - return returnval; - -} - -const std::string BrowseBoardsPage::GeneratePage(const std::string &method, const std::map &queryvars) -{ - std::string content=""; - std::string sql=""; - std::string boardname=""; - int rowsperpage=25; - std::string rowsperpagestr="26"; // 1 more than rowsperpage so we know if there are more boards - long startrow=0; - std::string startrowstr="0"; - int messagecount=0; - std::string messagecountstr="0"; - std::string lastdate=""; - int count=0; - std::string boardsearch=""; - std::string sortby=""; - std::string sortorder=""; - - // if startrow is specified - if(queryvars.find("startrow")!=queryvars.end()) - { - startrowstr=(*queryvars.find("startrow")).second; - // convert back and forth, just in case a number wasn't passed in startrow - StringFunctions::Convert(startrowstr,startrow); - if(startrow<0) - { - startrow=0; - } - StringFunctions::Convert(startrow,startrowstr); - } - if(queryvars.find("boardsearch")!=queryvars.end()) - { - boardsearch=(*queryvars.find("boardsearch")).second; - } - if(queryvars.find("sortby")!=queryvars.end() && queryvars.find("sortorder")!=queryvars.end()) - { - sortby=(*queryvars.find("sortby")).second; - sortorder=(*queryvars.find("sortorder")).second; - if(sortby!="BoardName" && sortby!="MessageCount" && sortby!="LastMessage") - { - sortby="BoardName"; - } - if(sortorder!="ASC" && sortorder!="DESC") - { - sortorder="ASC"; - } - } - else - { - sortby="BoardName"; - sortorder="ASC"; - } - - content="

Browse Messages

"; - content+="
"; - content+=""; - content+=""; - content+=""; - - content+="
Select Identity : "; - content+=CreateLocalIdentityDropDown("localidentityid",""); + content+=CreateLocalIdentityDropDown("localidentityid",localidentityidstr); content+="
Type the answers of a few of the following puzzles. You don't need to get them all correct, but remember that they are case sensitive. Getting announced will take some time and you must assign trust to other identities to see yourself announced. DO NOT continuously solve captchas. Solve 30 at most, wait a day, and if your identity has not been announced, repeat until it is.
"; - content+=""; - content+=""; - content+=""; - content+=""; - content+=""; - - sql="SELECT tblBoard.BoardID, tblBoard.BoardName, COUNT(tblMessageBoard.MessageID) AS 'MessageCount', MAX(tblMessage.MessageDate || ' ' || tblMessage.MessageTime) AS 'LastMessage'"; - sql+="FROM tblBoard LEFT JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID "; - sql+="LEFT JOIN tblMessage ON tblMessageBoard.MessageID=tblMessage.MessageID "; - sql+="WHERE (tblMessageBoard.MessageID>=0 OR tblMessageBoard.MessageID IS NULL) "; - if(boardsearch!="") - { - sql+="AND tblBoard.BoardName LIKE '%' || ? || '%' "; - } - sql+="GROUP BY tblBoard.BoardID "; - sql+="ORDER BY "+sortby+" COLLATE NOCASE "+sortorder+" "; - sql+="LIMIT "+startrowstr+","+rowsperpagestr+";"; - - SQLite3DB::Statement st=m_db->Prepare(sql); - if(boardsearch!="") - { - st.Bind(0,boardsearch); - } - - st.Step(); - while(st.RowReturned() && count++"+SanitizeOutput(boardname)+""; - content+=""; - content+=""; - content+="\r\n"; - st.Step(); - } - - if(startrow>0 || st.RowReturned()) - { - content+=""; - - if(startrow>0) - { - int thisstartrow=startrow-rowsperpage; - if(thisstartrow<0) - { - thisstartrow=0; - } - content+=""; - } - else - { - content+=""; - } - - content+=""; - - if(st.RowReturned()) - { - int thisstartrow=startrow+rowsperpage; - content+=""; - } - - content+=""; - } - content+="
BoardMessage CountLast Message
"+SanitizeOutput(messagecountstr)+""+SanitizeOutput(lastdate)+"
<---->
"; - - return StringFunctions::Replace(m_template,"[CONTENT]",content); -} - -const std::string BrowseBoardsPage::ReverseSort(const std::string &sortname, const std::string ¤tsortby, const std::string ¤tsortorder) -{ - if(sortname==currentsortby) - { - if(currentsortorder=="ASC") - { - return "DESC"; - } - else - { - return "ASC"; - } - } - else - { - return currentsortorder; - } -} diff --git a/src/http/pages/browsemessagespage.cpp b/src/http/pages/browsemessagespage.cpp deleted file mode 100644 index 9601064..0000000 --- a/src/http/pages/browsemessagespage.cpp +++ /dev/null @@ -1,265 +0,0 @@ -#include "../../../include/http/pages/browsemessagespage.h" -#include "../../../include/stringfunctions.h" -#include "../../../include/global.h" -#include "../../../include/messagethread.h" - -#ifdef XMEM - #include -#endif - -const std::string BrowseMessagesPage::BuildQueryString(const long startrow, const std::string &boardidstr, const std::string &messageidstr) -{ - std::string returnval=""; - std::string tempval=""; - - if(startrow>=0) - { - StringFunctions::Convert(startrow,tempval); - returnval+="startrow="+tempval; - } - - if(boardidstr!="") - { - if(returnval!="") - { - returnval+="&"; - } - returnval+="boardid="+boardidstr; - } - - if(messageidstr!="") - { - if(returnval!="") - { - returnval+="&"; - } - returnval+="messageid="+messageidstr; - } - - return returnval; - -} - -const std::string BrowseMessagesPage::GeneratePage(const std::string &method, const std::map &queryvars) -{ - std::string content=""; - long boardid=-1; - std::string boardidstr=""; - std::string messageidstr=""; - int startrow=0; - std::string startrowstr="0"; - int rowsperpage=50; - std::string rowsperpagestr="51"; // one more than rowsperpage so we can know if there are more messages - std::string sql=""; - int rowcount=0; - int page=0; - - // if startrow is specified - if(queryvars.find("startrow")!=queryvars.end()) - { - startrowstr=(*queryvars.find("startrow")).second; - // convert back and forth, just in case a number wasn't passed in startrow - StringFunctions::Convert(startrowstr,startrow); - if(startrow<0) - { - startrow=0; - } - StringFunctions::Convert(startrow,startrowstr); - } - if(queryvars.find("boardid")!=queryvars.end()) - { - boardidstr=(*queryvars.find("boardid")).second; - StringFunctions::Convert(boardidstr,boardid); - } - if(queryvars.find("messageid")!=queryvars.end()) - { - messageidstr=(*queryvars.find("messageid")).second; - page=1; - } - - if(page==0) - { - sql="SELECT Subject, FromName, MessageDate || ' ' || MessageTime, Body, tblMessage.MessageID "; - sql+="FROM tblMessage INNER JOIN tblMessageBoard ON tblMessage.MessageID=tblMessageBoard.MessageID "; - if(boardidstr!="") - { - sql+="WHERE tblMessageBoard.BoardID=? "; - } - sql+="ORDER BY MessageDate || ' ' || MessageTime DESC "; - sql+="LIMIT "+startrowstr+","+rowsperpagestr+";"; - - SQLite3DB::Statement st=m_db->Prepare(sql); - if(boardidstr!="") - { - st.Bind(0,boardidstr); - } - st.Step(); - - content+=""; - content+=""; - - rowcount=0; - while(st.RowReturned() && rowcount++400) - { - body.erase(400); - body+="..."; - } - - content+=""; - content+=""; - content+=""; - content+=""; - content+="\r\n"; - - st.Step(); - } - - if(startrow>0 || st.RowReturned()) - { - content+=""; - - if(startrow>0) - { - int thisstartrow=startrow-rowsperpage; - if(thisstartrow<0) - { - thisstartrow=0; - } - content+=""; - } - else - { - content+=""; - } - - content+=""; - - if(st.RowReturned()) - { - int thisstartrow=startrow+rowsperpage; - content+=""; - } - content+=""; - } - - content+="
SubjectFromDate
"+SanitizeOutput(subject)+""+fromname+""+SanitizeOutput(messagedate)+"
<---->
"; - } - else if(page==1) - { - sql="SELECT Body, FromName, MessageDate || ' ' || MessageTime, Subject FROM tblMessage WHERE MessageID=?;"; - SQLite3DB::Statement st=m_db->Prepare(sql); - st.Bind(0,messageidstr); - - st.Step(); - if(st.RowReturned()) - { - std::string body=""; - std::string fromname=""; - std::string messagedate=""; - std::string subject=""; - std::string boards=""; - - st.ResultText(0,body); - st.ResultText(1,fromname); - st.ResultText(2,messagedate); - st.ResultText(3,subject); - - // get boards message was posted to - SQLite3DB::Statement st2=m_db->Prepare("SELECT tblBoard.BoardID, tblBoard.BoardName FROM tblBoard INNER JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID WHERE tblMessageBoard.MessageID=?;"); - st2.Bind(0,messageidstr); - st2.Step(); - while(st2.RowReturned()) - { - std::string boardname=""; - std::string innerboardidstr=""; - - st2.ResultText(0,innerboardidstr); - st2.ResultText(1,boardname); - - if(boards!="") - { - boards+=", "; - } - - boards+=""+SanitizeOutput(boardname)+""; - - st2.Step(); - } - - content+="
"; - content+="
"; - content+=boards; - content+="
"; - content+="
"; - content+=SanitizeOutput(subject); - content+="
"; - content+="
"; - content+=SanitizeOutput(fromname); - content+="
"; - content+="
"; - content+=SanitizeOutput(messagedate); - content+="
"; - content+="
"; - content+=SanitizeOutput(body); - content+="
"; - content+="
\r\n"; - - long currentlevel=0; - MessageThread thread; - thread.Load(messageidstr,boardid); - - std::vector nodes=thread.GetNodes(); - if(nodes.size()>1) - { - content+="
    "; - for(std::vector::const_iterator i=nodes.begin(); i!=nodes.end(); i++) - { - if((*i).m_level>currentlevel) - { - content+="
      "; - } - else if((*i).m_level"+SanitizeOutput((*i).m_subject)+" - "+SanitizeOutput((*i).m_fromname); - } - else - { - content+=SanitizeOutput((*i).m_subject)+" - "+SanitizeOutput((*i).m_fromname); - } - content+="\r\n"; - } - while(currentlevel-->0) - { - content+="
    "; - } - content+="
\r\n"; - } - } - } - - return StringFunctions::Replace(m_template,"[CONTENT]",content); -} diff --git a/src/http/pages/forumcreatepostpage.cpp b/src/http/pages/forumcreatepostpage.cpp index ac9ed16..1896143 100644 --- a/src/http/pages/forumcreatepostpage.cpp +++ b/src/http/pages/forumcreatepostpage.cpp @@ -118,7 +118,7 @@ const std::string ForumCreatePostPage::GeneratePage(const std::string &method, c replyst.ResultText(0,subject); replyst.ResultText(1,body); - if(subject.size()<3 || (subject.substr(0,2)!="re:" && subject.substr(0,2)!="Re:")) + if(subject.size()<3 || (subject.substr(0,3)!="re:" && subject.substr(0,3)!="Re:")) { subject="Re: "+subject; } @@ -184,7 +184,7 @@ const std::string ForumCreatePostPage::GeneratePage(const std::string &method, c content+=""; content+=""; content+=""; - content+=""; + content+=""; content+=""; content+="
From"+LocalIdentityDropDown("localidentityid",localidentityidstr)+"
Subject
Message
Message
\r\n"; content+=""; diff --git a/src/http/pages/forumviewthreadpage.cpp b/src/http/pages/forumviewthreadpage.cpp index 0b69926..d99768d 100644 --- a/src/http/pages/forumviewthreadpage.cpp +++ b/src/http/pages/forumviewthreadpage.cpp @@ -10,6 +10,8 @@ const std::string ForumViewThreadPage::FixBody(const std::string &body) static std::string whitespace=" \t\r\n"; std::string output=body; + output=StringFunctions::Replace(output,"\r\n","\n"); + // put \n after 80 contiguous characters in the body std::string::size_type prevpos=0; std::string::size_type pos=output.find_first_of(whitespace); @@ -42,6 +44,7 @@ const std::string ForumViewThreadPage::GeneratePage(const std::string &method, c std::string boardidstr=""; std::string currentpagestr=""; std::string boardname=""; + std::string firstunreadidstr=""; if(queryvars.find("threadid")!=queryvars.end()) { @@ -58,6 +61,14 @@ const std::string ForumViewThreadPage::GeneratePage(const std::string &method, c content+=CreateForumHeader(); + SQLite3DB::Statement firstunreadst=m_db->Prepare("SELECT tblMessage.MessageID FROM tblThreadPost INNER JOIN tblMessage ON tblThreadPost.MessageID=tblMessage.MessageID WHERE ThreadID=? AND tblMessage.Read=0;"); + firstunreadst.Bind(0,threadidstr); + firstunreadst.Step(); + if(firstunreadst.RowReturned()) + { + firstunreadst.ResultText(0,firstunreadidstr); + } + SQLite3DB::Statement updateread=m_db->Prepare("UPDATE tblMessage SET Read=1 WHERE tblMessage.MessageID IN (SELECT MessageID FROM tblThreadPost WHERE ThreadID=?);"); updateread.Bind(0,threadidstr); updateread.Step(); @@ -76,6 +87,12 @@ const std::string ForumViewThreadPage::GeneratePage(const std::string &method, c content+=""; content+=""; content+=""; + if(firstunreadidstr!="") + { + content+=""; + } content+=""; content+="
Forum : "+SanitizeOutput(boardname)+""; + content+="First Unread Message"; + content+="
\r\n"; @@ -123,7 +140,7 @@ const std::string ForumViewThreadPage::GeneratePage(const std::string &method, c content+=""; content+=""; - content+=""; + content+=""; content+=""; content+=""; content+=""; diff --git a/src/http/pages/peertrustpage.cpp b/src/http/pages/peertrustpage.cpp index d80ae18..91d960f 100644 --- a/src/http/pages/peertrustpage.cpp +++ b/src/http/pages/peertrustpage.cpp @@ -23,7 +23,7 @@ const std::string PeerTrustPage::BuildQueryString(const long startrow, const std { returnval+="&"; } - returnval+="namesearch="+namesearch; + returnval+="namesearch="+StringFunctions::UriEncode(namesearch); } if(sortby!="") diff --git a/src/threadbuilder.cpp b/src/threadbuilder.cpp index 521cccc..175a34a 100644 --- a/src/threadbuilder.cpp +++ b/src/threadbuilder.cpp @@ -62,10 +62,17 @@ const bool ThreadBuilder::Build(const long messageid, const long boardid, const st.Bind(0,threadid); st.Step(); + SQLite3DB::Statement deleteotherst=m_db->Prepare("DELETE FROM tblThread WHERE ThreadID IN (SELECT tblThread.ThreadID FROM tblThreadPost INNER JOIN tblThread ON tblThreadPost.ThreadID=tblThread.ThreadID WHERE tblThread.BoardID=? AND tblThreadPost.MessageID=?);"); + count=0; st=m_db->Prepare("INSERT INTO tblThreadPost(ThreadID,MessageID,PostOrder) VALUES(?,?,?);"); for(std::vector::const_iterator i=m_threadmessages.begin(); i!=m_threadmessages.end(); i++, count++) { + deleteotherst.Bind(0,boardid); + deleteotherst.Bind(1,(*i).m_messageid); + deleteotherst.Step(); + deleteotherst.Reset(); + st.Bind(0,threadid); st.Bind(1,(*i).m_messageid); st.Bind(2,count); -- 2.7.4
TrustTrust
LocalPeer