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 <zthread/Thread.h>
\r
16 NNTPConnection::NNTPConnection(SOCKET sock)
\r
18 std::string tempval;
\r
21 m_tempbuffer.resize(32768);
\r
23 m_status.m_isposting=false;
\r
24 m_status.m_allowpost=false;
\r
25 m_status.m_boardid=-1;
\r
26 m_status.m_messageid=-1;
\r
27 m_status.m_mode=MODE_NONE;
\r
29 Option::instance()->Get("NNTPAllowPost",tempval);
\r
32 m_status.m_allowpost=true;
\r
37 NNTPConnection::~NNTPConnection()
\r
42 void NNTPConnection::Disconnect()
\r
44 if(m_socket!=INVALID_SOCKET)
\r
47 closesocket(m_socket);
\r
51 m_socket=INVALID_SOCKET;
\r
55 std::vector<char>::iterator NNTPConnection::Find(std::vector<char> &buffer, const std::string &val)
\r
57 return std::search(buffer.begin(),buffer.end(),val.begin(),val.end());
\r
60 const bool NNTPConnection::HandleArticleCommand(const NNTPCommand &command)
\r
63 SendArticleParts(command);
\r
68 const bool NNTPConnection::HandleBodyCommand(const NNTPCommand &command)
\r
70 SendArticleParts(command);
\r
75 const bool NNTPConnection::HandleCapabilitiesCommand(const NNTPCommand &command)
\r
78 SendBufferedLine("101 Capability list :");
\r
79 SendBufferedLine("VERSION 2");
\r
80 SendBufferedLine("MODE-READER");
\r
81 SendBufferedLine("READER");
\r
82 SendBufferedLine("LIST OVERVIEW.FMT");
\r
83 SendBufferedLine("OVER MSGID");
\r
84 if(m_status.m_allowpost==true)
\r
86 SendBufferedLine("POST");
\r
88 SendBufferedLine(".");
\r
93 const bool NNTPConnection::HandleCommand(const NNTPCommand &command)
\r
95 if(command.m_command=="QUIT")
\r
97 return HandleQuitCommand(command);
\r
99 if(command.m_command=="MODE")
\r
101 return HandleModeCommand(command);
\r
103 if(command.m_command=="CAPABILITIES")
\r
105 return HandleCapabilitiesCommand(command);
\r
107 if(command.m_command=="HELP")
\r
109 return HandleHelpCommand(command);
\r
111 if(command.m_command=="DATE")
\r
113 return HandleDateCommand(command);
\r
115 if(command.m_command=="LIST")
\r
117 return HandleListCommand(command);
\r
119 if(command.m_command=="GROUP")
\r
121 return HandleGroupCommand(command);
\r
123 if(command.m_command=="LISTGROUP")
\r
125 return HandleListGroupCommand(command);
\r
127 if(command.m_command=="LAST")
\r
129 return HandleLastCommand(command);
\r
131 if(command.m_command=="NEXT")
\r
133 return HandleNextCommand(command);
\r
135 if(command.m_command=="ARTICLE")
\r
137 return HandleArticleCommand(command);
\r
139 if(command.m_command=="HEAD")
\r
141 return HandleHeadCommand(command);
\r
143 if(command.m_command=="BODY")
\r
145 return HandleBodyCommand(command);
\r
147 if(command.m_command=="STAT")
\r
149 return HandleStatCommand(command);
\r
151 if(command.m_command=="NEWGROUPS")
\r
153 return HandleNewGroupsCommand(command);
\r
155 if(command.m_command=="POST")
\r
157 return HandlePostCommand(command);
\r
159 if(command.m_command=="OVER" || command.m_command=="XOVER")
\r
161 return HandleOverCommand(command);
\r
167 const bool NNTPConnection::HandleDateCommand(const NNTPCommand &command)
\r
171 SendBufferedLine("111 "+now.Format("%Y%m%d%H%M%S"));
\r
175 const bool NNTPConnection::HandleGroupCommand(const NNTPCommand &command)
\r
177 if(command.m_arguments.size()==1)
\r
180 if(board.Load(command.m_arguments[0])==true)
\r
182 std::ostringstream tempstr;
\r
184 tempstr << "211 " << board.GetMessageCount() << " " << board.GetLowMessageID() << " " << board.GetHighMessageID() << " " << board.GetBoardName();
\r
186 SendBufferedLine(tempstr.str());
\r
188 // set the current boardid to this one
\r
189 m_status.m_boardid=board.GetBoardID();
\r
190 //set the first message id, -1 if there are no messages
\r
191 board.GetLowMessageID()!=0 ? m_status.m_messageid=board.GetLowMessageID() : m_status.m_messageid=-1;
\r
196 SendBufferedLine("411 No such newsgroup");
\r
201 SendBufferedLine("501 Syntax error");
\r
202 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleGroupCommand syntax error");
\r
208 const bool NNTPConnection::HandleHeadCommand(const NNTPCommand &command)
\r
211 SendArticleParts(command);
\r
216 const bool NNTPConnection::HandleHelpCommand(const NNTPCommand &command)
\r
218 SendBufferedLine("100 Help text follows");
\r
219 SendBufferedLine("There is no help text");
\r
220 SendBufferedLine(".");
\r
225 const bool NNTPConnection::HandleLastCommand(const NNTPCommand &command)
\r
227 if(m_status.m_boardid!=-1)
\r
229 if(m_status.m_messageid!=-1)
\r
233 if(mess.Load(m_status.m_messageid,m_status.m_boardid))
\r
235 std::ostringstream tempstr;
\r
237 m_status.m_messageid=mess.GetMessageID();
\r
239 tempstr << "223 " << mess.GetMessageID() << " " << mess.GetNNTPArticleID();
\r
241 SendBufferedLine(tempstr.str());
\r
246 SendBufferedLine("422 No previous article in this group");
\r
251 SendBufferedLine("420 Current article number is invalid");
\r
256 SendBufferedLine("412 No newsgroup selected");
\r
262 const bool NNTPConnection::HandleListCommand(const NNTPCommand &command)
\r
265 int type=1; // default LIST type is active
\r
266 std::string arg1="";
\r
267 std::string arg2="";
\r
270 if(command.m_arguments.size()>0)
\r
272 StringFunctions::UpperCase(command.m_arguments[0],arg1);
\r
277 else if(arg1=="NEWSGROUPS")
\r
281 else if(arg1=="OVERVIEW.FMT")
\r
291 if(command.m_arguments.size()>1)
\r
293 arg2=command.m_arguments[1];
\r
296 // LIST ACTIVE [wildmat]
\r
300 std::ostringstream tempstr;
\r
304 SendBufferedLine("215 list of newsgroups follows");
\r
306 for(BoardList::iterator i=bl.begin(); i!=bl.end(); i++)
\r
311 // check wilmat match
\r
314 show=uwildmat((*i).GetBoardName().c_str(),arg2.c_str());
\r
319 tempstr << (*i).GetBoardName() << "\t" << (*i).GetHighMessageID() << "\t" << (*i).GetLowMessageID() << "\t" << (m_status.m_allowpost ? "y" : "n");
\r
320 SendBufferedLine(tempstr.str());
\r
324 SendBufferedLine(".");
\r
331 std::ostringstream tempstr;
\r
335 SendBufferedLine("215 list of newsgroups follows");
\r
337 for(BoardList::iterator i=bl.begin(); i!=bl.end(); i++)
\r
342 // check wilmat match
\r
345 show=uwildmat((*i).GetBoardName().c_str(),arg2.c_str());
\r
350 tempstr << (*i).GetBoardName() << "\t" << (*i).GetBoardDescription();
\r
351 SendBufferedLine(tempstr.str());
\r
355 SendBufferedLine(".");
\r
358 // LIST OVERVIEW.FMT
\r
361 SendBufferedLine("215 Order of fields in overview database.");
\r
362 SendBufferedLine("Subject:");
\r
363 SendBufferedLine("From:");
\r
364 SendBufferedLine("Date:");
\r
365 SendBufferedLine("Message-ID:");
\r
366 SendBufferedLine("References:");
\r
367 SendBufferedLine(":bytes");
\r
368 SendBufferedLine(":lines");
\r
369 SendBufferedLine(".");
\r
374 SendBufferedLine("501 Syntax error");
\r
375 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleListCommand unhandled LIST variant");
\r
381 const bool NNTPConnection::HandleListGroupCommand(const NNTPCommand &command)
\r
384 std::ostringstream tempstr;
\r
386 bool validgroup=false;
\r
391 // no args and invalid boardid
\r
392 if(command.m_arguments.size()==0 && m_status.m_boardid==-1)
\r
394 SendBufferedLine("412 No newsgroup selected");
\r
396 else if(command.m_arguments.size()==0)
\r
398 validgroup=board.Load(m_status.m_boardid);
\r
400 else if(command.m_arguments.size()==1)
\r
402 validgroup=board.Load(command.m_arguments[0]);
\r
405 lownum=board.GetLowMessageID();
\r
406 highnum=board.GetHighMessageID();
\r
410 SendBufferedLine("411 No such newsgroup");
\r
413 else if(command.m_arguments.size()==2)
\r
415 validgroup=board.Load(command.m_arguments[0]);
\r
416 std::vector<std::string> rangeparts;
\r
417 StringFunctions::Split(command.m_arguments[1],"-",rangeparts);
\r
419 if(rangeparts.size()>0)
\r
421 StringFunctions::Convert(rangeparts[0],lownum);
\r
423 if(rangeparts.size()>1)
\r
425 StringFunctions::Convert(rangeparts[1],highnum);
\r
432 SendBufferedLine("501 Syntax error");
\r
433 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleListGroupCommand unknown arguments");
\r
439 // set boardid and messageid
\r
440 m_status.m_boardid=board.GetBoardID();
\r
441 board.GetLowMessageID()!=0 ? m_status.m_messageid=board.GetLowMessageID() : m_status.m_messageid=-1;
\r
445 lownum=board.GetLowMessageID();
\r
449 highnum=board.GetHighMessageID();
\r
452 tempstr << "211 " << board.GetMessageCount() << " " << board.GetLowMessageID() << " " << board.GetHighMessageID() << " " << board.GetBoardName();
\r
453 SendBufferedLine(tempstr.str());
\r
456 ml.LoadRange(lownum,highnum,board.GetBoardID());
\r
458 for(std::vector<Message>::iterator i=ml.begin(); i!=ml.end(); i++)
\r
461 tempstr << (*i).GetMessageID();
\r
463 SendBufferedLine(tempstr.str());
\r
466 // end of multi-line response
\r
467 SendBufferedLine(".");
\r
474 const bool NNTPConnection::HandleModeCommand(const NNTPCommand &command)
\r
476 if(command.m_arguments.size()>0)
\r
478 std::string arg=command.m_arguments[0];
\r
479 StringFunctions::UpperCase(arg,arg);
\r
482 m_status.m_mode=MODE_READER;
\r
483 if(m_status.m_allowpost==true)
\r
485 SendBufferedLine("200 Posting allowed");
\r
489 SendBufferedLine("201 Posting prohibited");
\r
492 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleModeCommand set mode to reader");
\r
496 SendBufferedLine("501 Syntax error");
\r
497 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleModeCommand unknown MODE argument : "+arg);
\r
502 SendBufferedLine("501 Syntax error");
\r
503 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleModeCommand no argument supplied for MODE");
\r
509 const bool NNTPConnection::HandleNewGroupsCommand(const NNTPCommand &command)
\r
511 if(command.m_arguments.size()>=2)
\r
515 if(command.m_arguments[0].size()==8)
\r
517 StringFunctions::Convert(command.m_arguments[0].substr(0,4),tempint);
\r
518 date.SetYear(tempint);
\r
519 StringFunctions::Convert(command.m_arguments[0].substr(4,2),tempint);
\r
520 date.SetMonth(tempint);
\r
521 StringFunctions::Convert(command.m_arguments[0].substr(6,2),tempint);
\r
522 date.SetDay(tempint);
\r
528 If the first two digits of the year are not specified
\r
529 (this is supported only for backward compatibility), the year is to
\r
530 be taken from the current century if yy is smaller than or equal to
\r
531 the current year, and the previous century otherwise.
\r
536 century=now.GetYear()-(now.GetYear()%100);
\r
538 StringFunctions::Convert(command.m_arguments[0].substr(0,2),tempint);
\r
539 tempint<=now.GetYear()-century ? tempint+=century : tempint+=(century-100);
\r
541 //tempint > 50 ? tempint+=1900 : tempint+=2000;
\r
543 date.SetYear(tempint);
\r
544 StringFunctions::Convert(command.m_arguments[0].substr(2,2),tempint);
\r
545 date.SetMonth(tempint);
\r
546 StringFunctions::Convert(command.m_arguments[0].substr(4,2),tempint);
\r
547 date.SetDay(tempint);
\r
554 bl.LoadNew(date.Format("%Y-%m-%d %H:%M:%S"));
\r
556 SendBufferedLine("231 List of new newsgroups follows");
\r
558 for(BoardList::iterator i=bl.begin(); i!=bl.end(); i++)
\r
560 std::ostringstream tempstr;
\r
561 tempstr << (*i).GetBoardName() << " " << (*i).GetHighMessageID() << " " << (*i).GetLowMessageID() << " " << m_status.m_allowpost ? "y" : "n";
\r
562 SendBufferedLine(tempstr.str());
\r
565 SendBufferedLine(".");
\r
570 SendBufferedLine("501 Syntax error");
\r
571 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleNewGroupsCommand syntax error");
\r
578 const bool NNTPConnection::HandleNextCommand(const NNTPCommand &command)
\r
580 if(m_status.m_boardid!=-1)
\r
582 if(m_status.m_messageid!=-1)
\r
586 if(mess.Load(m_status.m_messageid,m_status.m_boardid))
\r
588 std::ostringstream tempstr;
\r
590 m_status.m_messageid=mess.GetMessageID();
\r
592 tempstr << "223 " << mess.GetMessageID() << " " << mess.GetNNTPArticleID();
\r
594 SendBufferedLine(tempstr.str());
\r
599 SendBufferedLine("421 No next article in this group");
\r
604 SendBufferedLine("420 Current article number is invalid");
\r
609 SendBufferedLine("412 No newsgroup selected");
\r
616 const bool NNTPConnection::HandleOverCommand(const NNTPCommand &command)
\r
618 long lowmessageid,highmessageid;
\r
619 std::string messageuuid="";
\r
621 lowmessageid=highmessageid=-2;
\r
623 if(command.m_arguments.size()==0)
\r
625 lowmessageid=m_status.m_messageid;
\r
626 highmessageid=m_status.m_messageid;
\r
631 if(command.m_arguments.size()>0 && command.m_arguments[0].find("<")==0 && command.m_arguments[0].find(">")>0)
\r
633 messageuuid=command.m_arguments[0];
\r
634 messageuuid=StringFunctions::Replace(messageuuid,"<","");
\r
635 messageuuid=StringFunctions::Replace(messageuuid,">","");
\r
637 // single article or range
\r
641 if(command.m_arguments[0].find("-")!=std::string::npos)
\r
643 std::vector<std::string> rangeparts;
\r
644 StringFunctions::Split(command.m_arguments[0],"-",rangeparts);
\r
646 if(rangeparts.size()>0)
\r
648 StringFunctions::Convert(rangeparts[0],lowmessageid);
\r
652 else if(rangeparts.size()>1)
\r
654 StringFunctions::Convert(rangeparts[1],highmessageid);
\r
660 StringFunctions::Convert(command.m_arguments[0],lowmessageid);
\r
665 if(messageuuid!="")
\r
668 if(mess.Load(messageuuid))
\r
670 SendBufferedLine("224 Overview information follows");
\r
671 SendArticleOverInfo(mess);
\r
672 SendBufferedLine(".");
\r
676 SendBufferedLine("423 No such article");
\r
682 if(m_status.m_boardid!=-1 && bd.Load(m_status.m_boardid))
\r
685 if(highmessageid==-2)
\r
688 if(mess.Load(lowmessageid,m_status.m_boardid))
\r
690 SendBufferedLine("224 Overview information follows");
\r
691 SendArticleOverInfo(mess);
\r
692 SendBufferedLine(".");
\r
696 SendBufferedLine("423 No such article in this group");
\r
699 // range with no upper bound
\r
700 else if(highmessageid==-1)
\r
703 ml.LoadRange(lowmessageid,bd.GetHighMessageID(),m_status.m_boardid);
\r
706 SendBufferedLine("224 Overview information follows");
\r
707 for(MessageList::iterator i=ml.begin(); i!=ml.end(); i++)
\r
709 SendArticleOverInfo((*i));
\r
711 SendBufferedLine(".");
\r
715 SendBufferedLine("423 Empty range");
\r
718 // range with upper and lower bound
\r
719 else if(highmessageid>=lowmessageid)
\r
722 ml.LoadRange(lowmessageid,highmessageid,m_status.m_boardid);
\r
725 SendBufferedLine("224 Overview information follows");
\r
726 for(MessageList::iterator i=ml.begin(); i!=ml.end(); i++)
\r
728 SendArticleOverInfo((*i));
\r
730 SendBufferedLine(".");
\r
734 SendBufferedLine("423 Empty range");
\r
740 SendBufferedLine("423 Empty range");
\r
745 SendBufferedLine("423 No newsgroup selected");
\r
753 const bool NNTPConnection::HandlePostCommand(const NNTPCommand &command)
\r
755 if(m_status.m_allowpost==true)
\r
757 SendBufferedLine("340 Send article to be posted");
\r
758 m_status.m_isposting=true;
\r
762 SendBufferedLine("440 Posting not permitted");
\r
768 void NNTPConnection::HandlePostedMessage(const std::string &message)
\r
772 if(mess.ParseNNTPMessage(message))
\r
774 mess.StartFreenetInsert();
\r
775 SendBufferedLine("240 Article received OK");
\r
779 SendBufferedLine("441 Posting failed");
\r
783 void NNTPConnection::HandleReceivedData()
\r
785 if(m_status.m_isposting==false)
\r
787 // get end of command line
\r
788 std::vector<char>::iterator endpos=Find(m_receivebuffer,"\r\n");
\r
790 // we got a command
\r
791 if(endpos!=m_receivebuffer.end())
\r
793 NNTPCommand command;
\r
794 std::string commandline(m_receivebuffer.begin(),endpos);
\r
796 // remove command from receive buffer
\r
797 m_receivebuffer.erase(m_receivebuffer.begin(),endpos+2);
\r
799 // remove any leading/trailing whitespace
\r
800 commandline=StringFunctions::TrimWhitespace(commandline);
\r
802 // split out command and arguments separated by space or tab
\r
803 StringFunctions::SplitMultiple(commandline," \t",command.m_arguments);
\r
805 // command is first element in argument vector
\r
806 command.m_command=command.m_arguments[0];
\r
807 // erase command from argument vector and make it upper case
\r
808 command.m_arguments.erase(command.m_arguments.begin());
\r
809 StringFunctions::UpperCase(command.m_command,command.m_command);
\r
811 if(HandleCommand(command)==true)
\r
817 SendBufferedLine("500 Unknown command");
\r
819 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleReceivedData received unhandled NNTP command : "+commandline);
\r
827 // check for end of post
\r
828 std::vector<char>::iterator endpos=Find(m_receivebuffer,"\r\n.\r\n");
\r
830 if(endpos!=m_receivebuffer.end())
\r
833 std::string message(m_receivebuffer.begin(),endpos);
\r
834 // remove from receive buffer
\r
835 m_receivebuffer.erase(m_receivebuffer.begin(),endpos+5);
\r
837 // get rid of dot stuffing ( 2 dots on start of a line - used to prevent premature message end in NNTP)
\r
838 message=StringFunctions::Replace(message,"\r\n..","\r\n.");
\r
840 HandlePostedMessage(message);
\r
842 // message was received, so posting is completed
\r
843 m_status.m_isposting=false;
\r
849 const bool NNTPConnection::HandleStatCommand(const NNTPCommand &command)
\r
851 SendArticleParts(command);
\r
856 const bool NNTPConnection::HandleQuitCommand(const NNTPCommand &command)
\r
858 SendBufferedLine("205 Connection Closing");
\r
861 m_log->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPConnection::HandleQuitCommand client closed connection");
\r
865 void NNTPConnection::run()
\r
868 fd_set writefs,readfs;
\r
871 // seed random number generater for this thread
\r
874 if(m_status.m_allowpost==true)
\r
876 SendBufferedLine("200 Service available, posting allowed");
\r
880 SendBufferedLine("201 Service available, posting prohibited");
\r
888 FD_SET(m_socket,&readfs);
\r
889 if(m_sendbuffer.size()>0)
\r
891 FD_SET(m_socket,&writefs);
\r
897 rval=select(m_socket+1,&readfs,&writefs,0,&tv);
\r
901 if(FD_ISSET(m_socket,&readfs))
\r
904 HandleReceivedData();
\r
906 if(m_socket!=INVALID_SOCKET && FD_ISSET(m_socket,&writefs))
\r
913 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::run select returned -1 : "+GetSocketErrorMessage());
\r
916 }while(!Disconnected() && !ZThread::Thread::interrupted());
\r
922 void NNTPConnection::SendArticleOverInfo(Message &message)
\r
924 std::string tempval;
\r
926 std::map<long,std::string> references;
\r
928 StringFunctions::Convert(message.GetMessageID(),tempval);
\r
930 line+=message.GetSubject()+"\t";
\r
931 line+=message.GetFromName()+"\t";
\r
932 line+=message.GetDateTime().Format("%a, %d %b %y %H:%M:%S -0000")+"\t";
\r
933 line+=message.GetNNTPArticleID()+"\t";
\r
934 references=message.GetInReplyTo();
\r
935 if(references.size()>0)
\r
937 for(std::map<long,std::string>::reverse_iterator i=references.rbegin(); i!=references.rend(); i++)
\r
939 if(i!=references.rbegin())
\r
943 line+="<"+(*i).second+">";
\r
953 SendBufferedLine(line);
\r
956 void NNTPConnection::SendArticleParts(const NNTPConnection::NNTPCommand &command)
\r
958 bool sendheaders,sendbody;
\r
959 std::string successcode;
\r
961 if(command.m_command=="ARTICLE")
\r
967 else if(command.m_command=="HEAD")
\r
973 else if(command.m_command=="BODY")
\r
979 else if(command.m_command=="STAT")
\r
987 int messageid=m_status.m_messageid;
\r
988 std::string articleid="";
\r
989 int type=0; // default to current messageid, 1=messageid, 2=articleid
\r
991 if(command.m_arguments.size()==1 && command.m_arguments[0].size()>0)
\r
993 if(command.m_arguments[0].find("<")==std::string::npos)
\r
995 StringFunctions::Convert(command.m_arguments[0],messageid);
\r
996 message.Load(messageid,m_status.m_boardid);
\r
997 m_status.m_messageid=message.GetMessageID();
\r
1002 articleid=command.m_arguments[0];
\r
1003 message.Load(articleid);
\r
1009 message.Load(m_status.m_messageid,m_status.m_boardid);
\r
1015 if(m_status.m_boardid!=-1)
\r
1017 if(m_status.m_messageid!=-1)
\r
1019 std::ostringstream tempstr;
\r
1020 std::string article;
\r
1021 if(sendheaders&&sendbody)
\r
1023 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1025 else if(sendheaders && !sendbody)
\r
1027 article=message.GetNNTPHeaders();
\r
1028 // strip off final \r\n from headers
\r
1029 if(article.rfind("\r\n")==article.size()-2)
\r
1031 article.erase(article.size()-2);
\r
1036 article=message.GetNNTPBody();
\r
1038 // dot stuff article
\r
1039 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1041 tempstr << successcode << " " << message.GetMessageID() << " " << message.GetNNTPArticleID();
\r
1043 SendBufferedLine(tempstr.str());
\r
1044 if(sendheaders || sendbody)
\r
1046 SendBufferedLine(article);
\r
1047 SendBufferedLine(".");
\r
1053 SendBufferedLine("420 Current article number is invalid");
\r
1058 SendBufferedLine("412 No newsgroup selected");
\r
1062 if(m_status.m_boardid!=-1)
\r
1064 if(message.GetMessageID()!=-1)
\r
1066 std::ostringstream tempstr;
\r
1067 std::string article;
\r
1068 if(sendheaders&&sendbody)
\r
1070 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1072 else if(sendheaders && !sendbody)
\r
1074 article=message.GetNNTPHeaders();
\r
1075 // strip off final \r\n from headers
\r
1076 if(article.rfind("\r\n")==article.size()-2)
\r
1078 article.erase(article.size()-2);
\r
1083 article=message.GetNNTPBody();
\r
1085 // dot stuff article
\r
1086 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1088 tempstr << successcode << " " << message.GetMessageID() << " " << message.GetNNTPArticleID();
\r
1090 SendBufferedLine(tempstr.str());
\r
1091 if(sendheaders || sendbody)
\r
1093 SendBufferedLine(article);
\r
1094 SendBufferedLine(".");
\r
1099 SendBufferedLine("423 No article with that number");
\r
1104 SendBufferedLine("412 No newsgroup selected");
\r
1108 if(message.GetMessageID()!=-1)
\r
1110 std::string article;
\r
1111 if(sendheaders&&sendbody)
\r
1113 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1115 else if(sendheaders && !sendbody)
\r
1117 article=message.GetNNTPHeaders();
\r
1118 // strip off final \r\n from headers
\r
1119 if(article.rfind("\r\n")==article.size()-2)
\r
1121 article.erase(article.size()-2);
\r
1126 article=message.GetNNTPBody();
\r
1128 // dot stuff article
\r
1129 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1131 SendBufferedLine(successcode+" 0 "+message.GetNNTPArticleID());
\r
1132 if(sendheaders || sendbody)
\r
1134 SendBufferedLine(article);
\r
1135 SendBufferedLine(".");
\r
1140 SendBufferedLine("430 No article with that message-id");
\r
1147 void NNTPConnection::SendBuffered(const std::string &data)
\r
1149 m_sendbuffer.insert(m_sendbuffer.end(),data.begin(),data.end());
\r
1152 void NNTPConnection::SocketReceive()
\r
1154 int rval=recv(m_socket,&m_tempbuffer[0],m_tempbuffer.size(),0);
\r
1157 m_receivebuffer.insert(m_receivebuffer.end(),m_tempbuffer.begin(),m_tempbuffer.begin()+rval);
\r
1162 m_log->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPConnection::SocketReceive remote host closed connection");
\r
1166 // error on receive - close the connection
\r
1168 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::SocketReceive recv returned -1 : "+GetSocketErrorMessage());
\r
1172 void NNTPConnection::SocketSend()
\r
1174 if(m_sendbuffer.size()>0 && m_socket!=INVALID_SOCKET)
\r
1176 int rval=send(m_socket,&m_sendbuffer[0],m_sendbuffer.size(),0);
\r
1179 m_sendbuffer.erase(m_sendbuffer.begin(),m_sendbuffer.begin()+rval);
\r
1183 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::SocketSend returned -1 : "+GetSocketErrorMessage());
\r