1 #include "../../include/nntp/nntpconnection.h"
\r
2 #include "../../include/nntp/uwildmat.h"
\r
3 #include "../../include/stringfunctions.h"
\r
4 #include "../../include/datetime.h"
\r
5 #include "../../include/boardlist.h"
\r
6 #include "../../include/message.h"
\r
7 #include "../../include/messagelist.h"
\r
8 #include "../../include/option.h"
\r
10 #include <algorithm>
\r
12 //#include <zthread/Thread.h>
\r
13 #include "../../include/pthreadwrapper/thread.h"
\r
19 NNTPConnection::NNTPConnection(SOCKET sock)
\r
21 std::string tempval;
\r
24 m_tempbuffer.resize(32768);
\r
26 m_status.m_isposting=false;
\r
27 m_status.m_allowpost=false;
\r
28 m_status.m_boardid=-1;
\r
29 m_status.m_messageid=-1;
\r
30 m_status.m_mode=MODE_NONE;
\r
32 Option::Instance()->Get("NNTPAllowPost",tempval);
\r
35 m_status.m_allowpost=true;
\r
40 NNTPConnection::~NNTPConnection()
\r
45 void NNTPConnection::Disconnect()
\r
47 if(m_socket!=INVALID_SOCKET)
\r
50 closesocket(m_socket);
\r
54 m_socket=INVALID_SOCKET;
\r
58 std::vector<char>::iterator NNTPConnection::Find(std::vector<char> &buffer, const std::string &val)
\r
60 return std::search(buffer.begin(),buffer.end(),val.begin(),val.end());
\r
63 const bool NNTPConnection::HandleArticleCommand(const NNTPCommand &command)
\r
66 SendArticleParts(command);
\r
71 const bool NNTPConnection::HandleBodyCommand(const NNTPCommand &command)
\r
73 SendArticleParts(command);
\r
78 const bool NNTPConnection::HandleCapabilitiesCommand(const NNTPCommand &command)
\r
81 SendBufferedLine("101 Capability list :");
\r
82 SendBufferedLine("VERSION 2");
\r
83 SendBufferedLine("MODE-READER");
\r
84 SendBufferedLine("READER");
\r
85 SendBufferedLine("LIST OVERVIEW.FMT");
\r
86 SendBufferedLine("OVER MSGID");
\r
87 if(m_status.m_allowpost==true)
\r
89 SendBufferedLine("POST");
\r
91 SendBufferedLine(".");
\r
96 const bool NNTPConnection::HandleCommand(const NNTPCommand &command)
\r
98 if(command.m_command=="QUIT")
\r
100 return HandleQuitCommand(command);
\r
102 if(command.m_command=="MODE")
\r
104 return HandleModeCommand(command);
\r
106 if(command.m_command=="CAPABILITIES")
\r
108 return HandleCapabilitiesCommand(command);
\r
110 if(command.m_command=="HELP")
\r
112 return HandleHelpCommand(command);
\r
114 if(command.m_command=="DATE")
\r
116 return HandleDateCommand(command);
\r
118 if(command.m_command=="LIST")
\r
120 return HandleListCommand(command);
\r
122 if(command.m_command=="GROUP")
\r
124 return HandleGroupCommand(command);
\r
126 if(command.m_command=="LISTGROUP")
\r
128 return HandleListGroupCommand(command);
\r
130 if(command.m_command=="LAST")
\r
132 return HandleLastCommand(command);
\r
134 if(command.m_command=="NEXT")
\r
136 return HandleNextCommand(command);
\r
138 if(command.m_command=="ARTICLE")
\r
140 return HandleArticleCommand(command);
\r
142 if(command.m_command=="HEAD")
\r
144 return HandleHeadCommand(command);
\r
146 if(command.m_command=="BODY")
\r
148 return HandleBodyCommand(command);
\r
150 if(command.m_command=="STAT")
\r
152 return HandleStatCommand(command);
\r
154 if(command.m_command=="NEWGROUPS")
\r
156 return HandleNewGroupsCommand(command);
\r
158 if(command.m_command=="POST")
\r
160 return HandlePostCommand(command);
\r
162 if(command.m_command=="OVER" || command.m_command=="XOVER")
\r
164 return HandleOverCommand(command);
\r
170 const bool NNTPConnection::HandleDateCommand(const NNTPCommand &command)
\r
174 SendBufferedLine("111 "+now.Format("%Y%m%d%H%M%S"));
\r
178 const bool NNTPConnection::HandleGroupCommand(const NNTPCommand &command)
\r
180 if(command.m_arguments.size()==1)
\r
183 if(board.Load(command.m_arguments[0])==true)
\r
185 std::ostringstream tempstr;
\r
187 tempstr << "211 " << board.GetMessageCount() << " " << board.GetLowMessageID() << " " << board.GetHighMessageID() << " " << board.GetBoardName();
\r
189 SendBufferedLine(tempstr.str());
\r
191 // set the current boardid to this one
\r
192 m_status.m_boardid=board.GetBoardID();
\r
193 //set the first message id, -1 if there are no messages
\r
194 board.GetLowMessageID()!=0 ? m_status.m_messageid=board.GetLowMessageID() : m_status.m_messageid=-1;
\r
199 SendBufferedLine("411 No such newsgroup");
\r
204 SendBufferedLine("501 Syntax error");
\r
205 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleGroupCommand syntax error");
\r
211 const bool NNTPConnection::HandleHeadCommand(const NNTPCommand &command)
\r
214 SendArticleParts(command);
\r
219 const bool NNTPConnection::HandleHelpCommand(const NNTPCommand &command)
\r
221 SendBufferedLine("100 Help text follows");
\r
222 SendBufferedLine("There is no help text");
\r
223 SendBufferedLine(".");
\r
228 const bool NNTPConnection::HandleLastCommand(const NNTPCommand &command)
\r
230 if(m_status.m_boardid!=-1)
\r
232 if(m_status.m_messageid!=-1)
\r
236 if(mess.LoadPrevious(m_status.m_messageid,m_status.m_boardid))
\r
238 std::ostringstream tempstr;
\r
240 m_status.m_messageid=mess.GetMessageID();
\r
242 tempstr << "223 " << mess.GetMessageID() << " " << mess.GetNNTPArticleID();
\r
244 SendBufferedLine(tempstr.str());
\r
249 SendBufferedLine("422 No previous article in this group");
\r
254 SendBufferedLine("420 Current article number is invalid");
\r
259 SendBufferedLine("412 No newsgroup selected");
\r
265 const bool NNTPConnection::HandleListCommand(const NNTPCommand &command)
\r
268 int type=1; // default LIST type is active
\r
269 std::string arg1="";
\r
270 std::string arg2="";
\r
273 if(command.m_arguments.size()>0)
\r
275 StringFunctions::UpperCase(command.m_arguments[0],arg1);
\r
280 else if(arg1=="NEWSGROUPS")
\r
284 else if(arg1=="OVERVIEW.FMT")
\r
294 if(command.m_arguments.size()>1)
\r
296 arg2=command.m_arguments[1];
\r
299 // LIST ACTIVE [wildmat]
\r
303 std::ostringstream tempstr;
\r
307 SendBufferedLine("215 list of newsgroups follows");
\r
309 for(BoardList::iterator i=bl.begin(); i!=bl.end(); i++)
\r
314 // check wilmat match
\r
317 show=uwildmat((*i).GetBoardName().c_str(),arg2.c_str());
\r
322 tempstr << (*i).GetBoardName() << " " << (*i).GetHighMessageID() << " " << (*i).GetLowMessageID() << " " << (m_status.m_allowpost ? "y" : "n");
\r
323 SendBufferedLine(tempstr.str());
\r
327 SendBufferedLine(".");
\r
334 std::ostringstream tempstr;
\r
338 SendBufferedLine("215 list of newsgroups follows");
\r
340 for(BoardList::iterator i=bl.begin(); i!=bl.end(); i++)
\r
345 // check wilmat match
\r
348 show=uwildmat((*i).GetBoardName().c_str(),arg2.c_str());
\r
353 tempstr << (*i).GetBoardName() << "\t" << (*i).GetBoardDescription();
\r
354 SendBufferedLine(tempstr.str());
\r
358 SendBufferedLine(".");
\r
361 // LIST OVERVIEW.FMT
\r
364 SendBufferedLine("215 Order of fields in overview database.");
\r
365 SendBufferedLine("Subject:");
\r
366 SendBufferedLine("From:");
\r
367 SendBufferedLine("Date:");
\r
368 SendBufferedLine("Message-ID:");
\r
369 SendBufferedLine("References:");
\r
370 SendBufferedLine(":bytes");
\r
371 SendBufferedLine(":lines");
\r
372 SendBufferedLine(".");
\r
377 SendBufferedLine("501 Syntax error");
\r
378 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleListCommand unhandled LIST variant");
\r
384 const bool NNTPConnection::HandleListGroupCommand(const NNTPCommand &command)
\r
387 std::ostringstream tempstr;
\r
389 bool validgroup=false;
\r
393 // no args and invalid boardid
\r
394 if(command.m_arguments.size()==0 && m_status.m_boardid==-1)
\r
396 SendBufferedLine("412 No newsgroup selected");
\r
398 else if(command.m_arguments.size()==0)
\r
400 validgroup=board.Load(m_status.m_boardid);
\r
402 else if(command.m_arguments.size()==1)
\r
404 validgroup=board.Load(command.m_arguments[0]);
\r
407 lownum=board.GetLowMessageID();
\r
408 highnum=board.GetHighMessageID();
\r
412 SendBufferedLine("411 No such newsgroup");
\r
415 else if(command.m_arguments.size()==2)
\r
417 validgroup=board.Load(command.m_arguments[0]);
\r
418 std::vector<std::string> rangeparts;
\r
419 StringFunctions::Split(command.m_arguments[1],"-",rangeparts);
\r
421 if(rangeparts.size()>0)
\r
423 StringFunctions::Convert(rangeparts[0],lownum);
\r
425 if(rangeparts.size()>1)
\r
427 StringFunctions::Convert(rangeparts[1],highnum);
\r
434 SendBufferedLine("501 Syntax error");
\r
435 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleListGroupCommand unknown arguments");
\r
441 // set boardid and messageid
\r
442 m_status.m_boardid=board.GetBoardID();
\r
443 board.GetLowMessageID()!=0 ? m_status.m_messageid=board.GetLowMessageID() : m_status.m_messageid=-1;
\r
447 lownum=board.GetLowMessageID();
\r
451 highnum=board.GetHighMessageID();
\r
454 tempstr << "211 " << board.GetMessageCount() << " " << board.GetLowMessageID() << " " << board.GetHighMessageID() << " " << board.GetBoardName();
\r
455 SendBufferedLine(tempstr.str());
\r
458 ml.LoadRange(lownum,highnum,board.GetBoardID());
\r
460 for(std::vector<Message>::iterator i=ml.begin(); i!=ml.end(); i++)
\r
463 tempstr << (*i).GetMessageID();
\r
465 SendBufferedLine(tempstr.str());
\r
468 // end of multi-line response
\r
469 SendBufferedLine(".");
\r
476 const bool NNTPConnection::HandleModeCommand(const NNTPCommand &command)
\r
478 if(command.m_arguments.size()>0)
\r
480 std::string arg=command.m_arguments[0];
\r
481 StringFunctions::UpperCase(arg,arg);
\r
484 m_status.m_mode=MODE_READER;
\r
485 if(m_status.m_allowpost==true)
\r
487 SendBufferedLine("200 Posting allowed");
\r
491 SendBufferedLine("201 Posting prohibited");
\r
494 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleModeCommand set mode to reader");
\r
498 SendBufferedLine("501 Syntax error");
\r
499 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleModeCommand unknown MODE argument : "+arg);
\r
504 SendBufferedLine("501 Syntax error");
\r
505 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleModeCommand no argument supplied for MODE");
\r
511 const bool NNTPConnection::HandleNewGroupsCommand(const NNTPCommand &command)
\r
513 if(command.m_arguments.size()>=2)
\r
517 if(command.m_arguments[0].size()==8)
\r
519 StringFunctions::Convert(command.m_arguments[0].substr(0,4),tempint);
\r
520 date.SetYear(tempint);
\r
521 StringFunctions::Convert(command.m_arguments[0].substr(4,2),tempint);
\r
522 date.SetMonth(tempint);
\r
523 StringFunctions::Convert(command.m_arguments[0].substr(6,2),tempint);
\r
524 date.SetDay(tempint);
\r
530 If the first two digits of the year are not specified
\r
531 (this is supported only for backward compatibility), the year is to
\r
532 be taken from the current century if yy is smaller than or equal to
\r
533 the current year, and the previous century otherwise.
\r
538 century=now.GetYear()-(now.GetYear()%100);
\r
540 StringFunctions::Convert(command.m_arguments[0].substr(0,2),tempint);
\r
541 tempint<=now.GetYear()-century ? tempint+=century : tempint+=(century-100);
\r
543 //tempint > 50 ? tempint+=1900 : tempint+=2000;
\r
545 date.SetYear(tempint);
\r
546 StringFunctions::Convert(command.m_arguments[0].substr(2,2),tempint);
\r
547 date.SetMonth(tempint);
\r
548 StringFunctions::Convert(command.m_arguments[0].substr(4,2),tempint);
\r
549 date.SetDay(tempint);
\r
556 bl.LoadNew(date.Format("%Y-%m-%d %H:%M:%S"));
\r
558 SendBufferedLine("231 List of new newsgroups follows");
\r
560 for(BoardList::iterator i=bl.begin(); i!=bl.end(); i++)
\r
562 std::ostringstream tempstr;
\r
563 tempstr << (*i).GetBoardName() << " " << (*i).GetHighMessageID() << " " << (*i).GetLowMessageID() << " " << m_status.m_allowpost ? "y" : "n";
\r
564 SendBufferedLine(tempstr.str());
\r
567 SendBufferedLine(".");
\r
572 SendBufferedLine("501 Syntax error");
\r
573 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleNewGroupsCommand syntax error");
\r
580 const bool NNTPConnection::HandleNextCommand(const NNTPCommand &command)
\r
582 if(m_status.m_boardid!=-1)
\r
584 if(m_status.m_messageid!=-1)
\r
588 if(mess.LoadNext(m_status.m_messageid,m_status.m_boardid))
\r
590 std::ostringstream tempstr;
\r
592 m_status.m_messageid=mess.GetMessageID();
\r
594 tempstr << "223 " << mess.GetMessageID() << " " << mess.GetNNTPArticleID();
\r
596 SendBufferedLine(tempstr.str());
\r
601 SendBufferedLine("421 No next article in this group");
\r
606 SendBufferedLine("420 Current article number is invalid");
\r
611 SendBufferedLine("412 No newsgroup selected");
\r
618 const bool NNTPConnection::HandleOverCommand(const NNTPCommand &command)
\r
620 long lowmessageid,highmessageid;
\r
621 std::string messageuuid="";
\r
623 lowmessageid=highmessageid=-2;
\r
625 if(command.m_arguments.size()==0)
\r
627 lowmessageid=m_status.m_messageid;
\r
628 highmessageid=m_status.m_messageid;
\r
633 if(command.m_arguments.size()>0 && command.m_arguments[0].find("<")==0 && command.m_arguments[0].find(">")>0)
\r
635 messageuuid=command.m_arguments[0];
\r
636 messageuuid=StringFunctions::Replace(messageuuid,"<","");
\r
637 messageuuid=StringFunctions::Replace(messageuuid,">","");
\r
638 // get rid of @ and everything after
\r
639 if(messageuuid.find("@")!=std::string::npos)
\r
641 messageuuid.erase(messageuuid.find("@"));
\r
644 // single article or range
\r
648 if(command.m_arguments[0].find("-")!=std::string::npos)
\r
650 std::vector<std::string> rangeparts;
\r
651 StringFunctions::Split(command.m_arguments[0],"-",rangeparts);
\r
653 if(rangeparts.size()>0)
\r
655 StringFunctions::Convert(rangeparts[0],lowmessageid);
\r
659 else if(rangeparts.size()>1)
\r
661 StringFunctions::Convert(rangeparts[1],highmessageid);
\r
667 StringFunctions::Convert(command.m_arguments[0],lowmessageid);
\r
672 if(messageuuid!="")
\r
675 if(mess.Load(messageuuid))
\r
677 SendBufferedLine("224 Overview information follows");
\r
678 SendArticleOverInfo(mess);
\r
679 SendBufferedLine(".");
\r
683 SendBufferedLine("423 No such article");
\r
689 if(m_status.m_boardid!=-1 && bd.Load(m_status.m_boardid))
\r
692 if(highmessageid==-2)
\r
695 if(mess.Load(lowmessageid,m_status.m_boardid))
\r
697 SendBufferedLine("224 Overview information follows");
\r
698 SendArticleOverInfo(mess);
\r
699 SendBufferedLine(".");
\r
703 SendBufferedLine("423 No such article in this group");
\r
706 // range with no upper bound
\r
707 else if(highmessageid==-1)
\r
710 ml.LoadRange(lowmessageid,bd.GetHighMessageID(),m_status.m_boardid);
\r
713 SendBufferedLine("224 Overview information follows");
\r
714 for(MessageList::iterator i=ml.begin(); i!=ml.end(); i++)
\r
716 SendArticleOverInfo((*i));
\r
718 SendBufferedLine(".");
\r
722 SendBufferedLine("423 Empty range");
\r
725 // range with upper and lower bound
\r
726 else if(highmessageid>=lowmessageid)
\r
729 ml.LoadRange(lowmessageid,highmessageid,m_status.m_boardid);
\r
732 SendBufferedLine("224 Overview information follows");
\r
733 for(MessageList::iterator i=ml.begin(); i!=ml.end(); i++)
\r
735 SendArticleOverInfo((*i));
\r
737 SendBufferedLine(".");
\r
741 SendBufferedLine("423 Empty range");
\r
747 SendBufferedLine("423 Empty range");
\r
752 SendBufferedLine("423 No newsgroup selected");
\r
760 const bool NNTPConnection::HandlePostCommand(const NNTPCommand &command)
\r
762 if(m_status.m_allowpost==true)
\r
764 SendBufferedLine("340 Send article to be posted");
\r
765 m_status.m_isposting=true;
\r
769 SendBufferedLine("440 Posting not permitted");
\r
775 void NNTPConnection::HandlePostedMessage(const std::string &message)
\r
779 if(mess.ParseNNTPMessage(message))
\r
781 if(mess.PostedToAdministrationBoard()==true)
\r
783 mess.HandleAdministrationMessage();
\r
787 mess.StartFreenetInsert();
\r
789 SendBufferedLine("240 Article received OK");
\r
793 SendBufferedLine("441 Posting failed");
\r
797 void NNTPConnection::HandleReceivedData()
\r
799 if(m_status.m_isposting==false)
\r
801 // get end of command line
\r
802 std::vector<char>::iterator endpos=Find(m_receivebuffer,"\r\n");
\r
804 // we got a command
\r
805 if(endpos!=m_receivebuffer.end())
\r
807 NNTPCommand command;
\r
808 std::string commandline(m_receivebuffer.begin(),endpos);
\r
810 // remove command from receive buffer
\r
811 m_receivebuffer.erase(m_receivebuffer.begin(),endpos+2);
\r
813 // remove any leading/trailing whitespace
\r
814 commandline=StringFunctions::TrimWhitespace(commandline);
\r
816 // split out command and arguments separated by space or tab
\r
817 StringFunctions::SplitMultiple(commandline," \t",command.m_arguments);
\r
819 // command is first element in argument vector
\r
820 command.m_command=command.m_arguments[0];
\r
821 // erase command from argument vector and make it upper case
\r
822 command.m_arguments.erase(command.m_arguments.begin());
\r
823 StringFunctions::UpperCase(command.m_command,command.m_command);
\r
825 if(HandleCommand(command)==true)
\r
831 SendBufferedLine("500 Unknown command");
\r
833 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleReceivedData received unhandled NNTP command : "+commandline);
\r
841 // check for end of post
\r
842 std::vector<char>::iterator endpos=Find(m_receivebuffer,"\r\n.\r\n");
\r
844 if(endpos!=m_receivebuffer.end())
\r
847 std::string message(m_receivebuffer.begin(),endpos);
\r
848 // remove from receive buffer
\r
849 m_receivebuffer.erase(m_receivebuffer.begin(),endpos+5);
\r
851 // get rid of dot stuffing ( 2 dots on start of a line - used to prevent premature message end in NNTP)
\r
852 message=StringFunctions::Replace(message,"\r\n..","\r\n.");
\r
854 HandlePostedMessage(message);
\r
856 // message was received, so posting is completed
\r
857 m_status.m_isposting=false;
\r
863 const bool NNTPConnection::HandleStatCommand(const NNTPCommand &command)
\r
865 SendArticleParts(command);
\r
870 const bool NNTPConnection::HandleQuitCommand(const NNTPCommand &command)
\r
872 SendBufferedLine("205 Connection Closing");
\r
875 m_log->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPConnection::HandleQuitCommand client closed connection");
\r
879 void NNTPConnection::Run()
\r
882 fd_set writefs,readfs;
\r
885 // seed random number generater for this thread
\r
888 if(m_status.m_allowpost==true)
\r
890 SendBufferedLine("200 Service available, posting allowed");
\r
894 SendBufferedLine("201 Service available, posting prohibited");
\r
902 FD_SET(m_socket,&readfs);
\r
903 if(m_sendbuffer.size()>0)
\r
905 FD_SET(m_socket,&writefs);
\r
911 rval=select(m_socket+1,&readfs,&writefs,0,&tv);
\r
915 if(FD_ISSET(m_socket,&readfs))
\r
918 HandleReceivedData();
\r
920 if(m_socket!=INVALID_SOCKET && FD_ISSET(m_socket,&writefs))
\r
925 else if(rval==SOCKET_ERROR)
\r
927 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::run select returned -1 : "+GetSocketErrorMessage());
\r
930 // }while(!Disconnected() && !ZThread::Thread::interrupted());
\r
931 }while(!Disconnected() && !IsCancelled());
\r
937 void NNTPConnection::SendArticleOverInfo(Message &message)
\r
939 std::string tempval;
\r
941 std::map<long,std::string> references;
\r
943 StringFunctions::Convert(message.GetMessageID(),tempval);
\r
945 line+=message.GetSubject()+"\t";
\r
946 line+=message.GetFromName()+"\t";
\r
947 line+=message.GetDateTime().Format("%a, %d %b %y %H:%M:%S -0000")+"\t";
\r
948 line+=message.GetNNTPArticleID()+"\t";
\r
949 references=message.GetInReplyTo();
\r
950 if(references.size()>0)
\r
952 for(std::map<long,std::string>::reverse_iterator i=references.rbegin(); i!=references.rend(); i++)
\r
954 if(i!=references.rbegin())
\r
958 line+="<"+(*i).second+"@freenetproject.org>";
\r
968 SendBufferedLine(line);
\r
971 void NNTPConnection::SendArticleParts(const NNTPConnection::NNTPCommand &command)
\r
973 bool sendheaders,sendbody;
\r
974 std::string successcode;
\r
976 if(command.m_command=="ARTICLE")
\r
982 else if(command.m_command=="HEAD")
\r
988 else if(command.m_command=="BODY")
\r
994 else if(command.m_command=="STAT")
\r
1002 int messageid=m_status.m_messageid;
\r
1003 std::string articleid="";
\r
1004 int type=0; // default to current messageid, 1=messageid, 2=articleid
\r
1006 if(command.m_arguments.size()==1 && command.m_arguments[0].size()>0)
\r
1008 if(command.m_arguments[0].find("<")==std::string::npos)
\r
1010 StringFunctions::Convert(command.m_arguments[0],messageid);
\r
1011 message.Load(messageid,m_status.m_boardid);
\r
1012 m_status.m_messageid=message.GetMessageID();
\r
1017 articleid=command.m_arguments[0];
\r
1018 message.Load(articleid);
\r
1024 message.Load(m_status.m_messageid,m_status.m_boardid);
\r
1030 if(m_status.m_boardid!=-1)
\r
1032 if(m_status.m_messageid!=-1)
\r
1034 std::ostringstream tempstr;
\r
1035 std::string article;
\r
1036 if(sendheaders&&sendbody)
\r
1038 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1040 else if(sendheaders && !sendbody)
\r
1042 article=message.GetNNTPHeaders();
\r
1043 // strip off final \r\n from headers
\r
1044 if(article.rfind("\r\n")==article.size()-2)
\r
1046 article.erase(article.size()-2);
\r
1051 article=message.GetNNTPBody();
\r
1053 // dot stuff article
\r
1054 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1056 tempstr << successcode << " " << message.GetMessageID() << " " << message.GetNNTPArticleID();
\r
1058 SendBufferedLine(tempstr.str());
\r
1059 if(sendheaders || sendbody)
\r
1061 SendBufferedLine(article);
\r
1062 SendBufferedLine(".");
\r
1068 SendBufferedLine("420 Current article number is invalid");
\r
1073 SendBufferedLine("412 No newsgroup selected");
\r
1077 if(m_status.m_boardid!=-1)
\r
1079 if(message.GetMessageID()!=-1)
\r
1081 std::ostringstream tempstr;
\r
1082 std::string article;
\r
1083 if(sendheaders&&sendbody)
\r
1085 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1087 else if(sendheaders && !sendbody)
\r
1089 article=message.GetNNTPHeaders();
\r
1090 // strip off final \r\n from headers
\r
1091 if(article.rfind("\r\n")==article.size()-2)
\r
1093 article.erase(article.size()-2);
\r
1098 article=message.GetNNTPBody();
\r
1100 // dot stuff article
\r
1101 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1103 tempstr << successcode << " " << message.GetMessageID() << " " << message.GetNNTPArticleID();
\r
1105 SendBufferedLine(tempstr.str());
\r
1106 if(sendheaders || sendbody)
\r
1108 SendBufferedLine(article);
\r
1109 SendBufferedLine(".");
\r
1114 SendBufferedLine("423 No article with that number");
\r
1119 SendBufferedLine("412 No newsgroup selected");
\r
1123 if(message.GetMessageID()!=-1)
\r
1125 std::string article;
\r
1126 if(sendheaders&&sendbody)
\r
1128 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1130 else if(sendheaders && !sendbody)
\r
1132 article=message.GetNNTPHeaders();
\r
1133 // strip off final \r\n from headers
\r
1134 if(article.rfind("\r\n")==article.size()-2)
\r
1136 article.erase(article.size()-2);
\r
1141 article=message.GetNNTPBody();
\r
1143 // dot stuff article
\r
1144 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1146 SendBufferedLine(successcode+" 0 "+message.GetNNTPArticleID());
\r
1147 if(sendheaders || sendbody)
\r
1149 SendBufferedLine(article);
\r
1150 SendBufferedLine(".");
\r
1155 SendBufferedLine("430 No article with that message-id");
\r
1162 void NNTPConnection::SendBuffered(const std::string &data)
\r
1164 m_sendbuffer.insert(m_sendbuffer.end(),data.begin(),data.end());
\r
1167 void NNTPConnection::SocketReceive()
\r
1169 int rval=recv(m_socket,&m_tempbuffer[0],m_tempbuffer.size(),0);
\r
1172 m_receivebuffer.insert(m_receivebuffer.end(),m_tempbuffer.begin(),m_tempbuffer.begin()+rval);
\r
1177 m_log->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPConnection::SocketReceive remote host closed connection");
\r
1181 std::string errnostr;
\r
1182 StringFunctions::Convert(GetSocketErrorNumber(),errnostr);
\r
1183 // error on receive - close the connection
\r
1185 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::SocketReceive recv returned -1 : "+errnostr+" - "+GetSocketErrorMessage());
\r
1189 void NNTPConnection::SocketSend()
\r
1191 if(m_sendbuffer.size()>0 && m_socket!=INVALID_SOCKET)
\r
1193 int rval=send(m_socket,&m_sendbuffer[0],m_sendbuffer.size(),0);
\r
1196 m_sendbuffer.erase(m_sendbuffer.begin(),m_sendbuffer.begin()+rval);
\r
1200 std::string errnostr;
\r
1201 StringFunctions::Convert(GetSocketErrorNumber(),errnostr);
\r
1202 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::SocketSend returned -1 : "+errnostr+" - "+GetSocketErrorMessage());
\r