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() << "\t" << (*i).GetHighMessageID() << "\t" << (*i).GetLowMessageID() << "\t" << (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
394 // no args and invalid boardid
\r
395 if(command.m_arguments.size()==0 && m_status.m_boardid==-1)
\r
397 SendBufferedLine("412 No newsgroup selected");
\r
399 else if(command.m_arguments.size()==0)
\r
401 validgroup=board.Load(m_status.m_boardid);
\r
403 else if(command.m_arguments.size()==1)
\r
405 validgroup=board.Load(command.m_arguments[0]);
\r
408 lownum=board.GetLowMessageID();
\r
409 highnum=board.GetHighMessageID();
\r
413 SendBufferedLine("411 No such newsgroup");
\r
416 else if(command.m_arguments.size()==2)
\r
418 validgroup=board.Load(command.m_arguments[0]);
\r
419 std::vector<std::string> rangeparts;
\r
420 StringFunctions::Split(command.m_arguments[1],"-",rangeparts);
\r
422 if(rangeparts.size()>0)
\r
424 StringFunctions::Convert(rangeparts[0],lownum);
\r
426 if(rangeparts.size()>1)
\r
428 StringFunctions::Convert(rangeparts[1],highnum);
\r
435 SendBufferedLine("501 Syntax error");
\r
436 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleListGroupCommand unknown arguments");
\r
442 // set boardid and messageid
\r
443 m_status.m_boardid=board.GetBoardID();
\r
444 board.GetLowMessageID()!=0 ? m_status.m_messageid=board.GetLowMessageID() : m_status.m_messageid=-1;
\r
448 lownum=board.GetLowMessageID();
\r
452 highnum=board.GetHighMessageID();
\r
455 tempstr << "211 " << board.GetMessageCount() << " " << board.GetLowMessageID() << " " << board.GetHighMessageID() << " " << board.GetBoardName();
\r
456 SendBufferedLine(tempstr.str());
\r
459 ml.LoadRange(lownum,highnum,board.GetBoardID());
\r
461 for(std::vector<Message>::iterator i=ml.begin(); i!=ml.end(); i++)
\r
464 tempstr << (*i).GetMessageID();
\r
466 SendBufferedLine(tempstr.str());
\r
469 // end of multi-line response
\r
470 SendBufferedLine(".");
\r
477 const bool NNTPConnection::HandleModeCommand(const NNTPCommand &command)
\r
479 if(command.m_arguments.size()>0)
\r
481 std::string arg=command.m_arguments[0];
\r
482 StringFunctions::UpperCase(arg,arg);
\r
485 m_status.m_mode=MODE_READER;
\r
486 if(m_status.m_allowpost==true)
\r
488 SendBufferedLine("200 Posting allowed");
\r
492 SendBufferedLine("201 Posting prohibited");
\r
495 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleModeCommand set mode to reader");
\r
499 SendBufferedLine("501 Syntax error");
\r
500 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleModeCommand unknown MODE argument : "+arg);
\r
505 SendBufferedLine("501 Syntax error");
\r
506 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleModeCommand no argument supplied for MODE");
\r
512 const bool NNTPConnection::HandleNewGroupsCommand(const NNTPCommand &command)
\r
514 if(command.m_arguments.size()>=2)
\r
518 if(command.m_arguments[0].size()==8)
\r
520 StringFunctions::Convert(command.m_arguments[0].substr(0,4),tempint);
\r
521 date.SetYear(tempint);
\r
522 StringFunctions::Convert(command.m_arguments[0].substr(4,2),tempint);
\r
523 date.SetMonth(tempint);
\r
524 StringFunctions::Convert(command.m_arguments[0].substr(6,2),tempint);
\r
525 date.SetDay(tempint);
\r
531 If the first two digits of the year are not specified
\r
532 (this is supported only for backward compatibility), the year is to
\r
533 be taken from the current century if yy is smaller than or equal to
\r
534 the current year, and the previous century otherwise.
\r
539 century=now.GetYear()-(now.GetYear()%100);
\r
541 StringFunctions::Convert(command.m_arguments[0].substr(0,2),tempint);
\r
542 tempint<=now.GetYear()-century ? tempint+=century : tempint+=(century-100);
\r
544 //tempint > 50 ? tempint+=1900 : tempint+=2000;
\r
546 date.SetYear(tempint);
\r
547 StringFunctions::Convert(command.m_arguments[0].substr(2,2),tempint);
\r
548 date.SetMonth(tempint);
\r
549 StringFunctions::Convert(command.m_arguments[0].substr(4,2),tempint);
\r
550 date.SetDay(tempint);
\r
557 bl.LoadNew(date.Format("%Y-%m-%d %H:%M:%S"));
\r
559 SendBufferedLine("231 List of new newsgroups follows");
\r
561 for(BoardList::iterator i=bl.begin(); i!=bl.end(); i++)
\r
563 std::ostringstream tempstr;
\r
564 tempstr << (*i).GetBoardName() << " " << (*i).GetHighMessageID() << " " << (*i).GetLowMessageID() << " " << m_status.m_allowpost ? "y" : "n";
\r
565 SendBufferedLine(tempstr.str());
\r
568 SendBufferedLine(".");
\r
573 SendBufferedLine("501 Syntax error");
\r
574 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleNewGroupsCommand syntax error");
\r
581 const bool NNTPConnection::HandleNextCommand(const NNTPCommand &command)
\r
583 if(m_status.m_boardid!=-1)
\r
585 if(m_status.m_messageid!=-1)
\r
589 if(mess.LoadNext(m_status.m_messageid,m_status.m_boardid))
\r
591 std::ostringstream tempstr;
\r
593 m_status.m_messageid=mess.GetMessageID();
\r
595 tempstr << "223 " << mess.GetMessageID() << " " << mess.GetNNTPArticleID();
\r
597 SendBufferedLine(tempstr.str());
\r
602 SendBufferedLine("421 No next article in this group");
\r
607 SendBufferedLine("420 Current article number is invalid");
\r
612 SendBufferedLine("412 No newsgroup selected");
\r
619 const bool NNTPConnection::HandleOverCommand(const NNTPCommand &command)
\r
621 long lowmessageid,highmessageid;
\r
622 std::string messageuuid="";
\r
624 lowmessageid=highmessageid=-2;
\r
626 if(command.m_arguments.size()==0)
\r
628 lowmessageid=m_status.m_messageid;
\r
629 highmessageid=m_status.m_messageid;
\r
634 if(command.m_arguments.size()>0 && command.m_arguments[0].find("<")==0 && command.m_arguments[0].find(">")>0)
\r
636 messageuuid=command.m_arguments[0];
\r
637 messageuuid=StringFunctions::Replace(messageuuid,"<","");
\r
638 messageuuid=StringFunctions::Replace(messageuuid,">","");
\r
640 // single article or range
\r
644 if(command.m_arguments[0].find("-")!=std::string::npos)
\r
646 std::vector<std::string> rangeparts;
\r
647 StringFunctions::Split(command.m_arguments[0],"-",rangeparts);
\r
649 if(rangeparts.size()>0)
\r
651 StringFunctions::Convert(rangeparts[0],lowmessageid);
\r
655 else if(rangeparts.size()>1)
\r
657 StringFunctions::Convert(rangeparts[1],highmessageid);
\r
663 StringFunctions::Convert(command.m_arguments[0],lowmessageid);
\r
668 if(messageuuid!="")
\r
671 if(mess.Load(messageuuid))
\r
673 SendBufferedLine("224 Overview information follows");
\r
674 SendArticleOverInfo(mess);
\r
675 SendBufferedLine(".");
\r
679 SendBufferedLine("423 No such article");
\r
685 if(m_status.m_boardid!=-1 && bd.Load(m_status.m_boardid))
\r
688 if(highmessageid==-2)
\r
691 if(mess.Load(lowmessageid,m_status.m_boardid))
\r
693 SendBufferedLine("224 Overview information follows");
\r
694 SendArticleOverInfo(mess);
\r
695 SendBufferedLine(".");
\r
699 SendBufferedLine("423 No such article in this group");
\r
702 // range with no upper bound
\r
703 else if(highmessageid==-1)
\r
706 ml.LoadRange(lowmessageid,bd.GetHighMessageID(),m_status.m_boardid);
\r
709 SendBufferedLine("224 Overview information follows");
\r
710 for(MessageList::iterator i=ml.begin(); i!=ml.end(); i++)
\r
712 SendArticleOverInfo((*i));
\r
714 SendBufferedLine(".");
\r
718 SendBufferedLine("423 Empty range");
\r
721 // range with upper and lower bound
\r
722 else if(highmessageid>=lowmessageid)
\r
725 ml.LoadRange(lowmessageid,highmessageid,m_status.m_boardid);
\r
728 SendBufferedLine("224 Overview information follows");
\r
729 for(MessageList::iterator i=ml.begin(); i!=ml.end(); i++)
\r
731 SendArticleOverInfo((*i));
\r
733 SendBufferedLine(".");
\r
737 SendBufferedLine("423 Empty range");
\r
743 SendBufferedLine("423 Empty range");
\r
748 SendBufferedLine("423 No newsgroup selected");
\r
756 const bool NNTPConnection::HandlePostCommand(const NNTPCommand &command)
\r
758 if(m_status.m_allowpost==true)
\r
760 SendBufferedLine("340 Send article to be posted");
\r
761 m_status.m_isposting=true;
\r
765 SendBufferedLine("440 Posting not permitted");
\r
771 void NNTPConnection::HandlePostedMessage(const std::string &message)
\r
775 if(mess.ParseNNTPMessage(message))
\r
777 mess.StartFreenetInsert();
\r
778 SendBufferedLine("240 Article received OK");
\r
782 SendBufferedLine("441 Posting failed");
\r
786 void NNTPConnection::HandleReceivedData()
\r
788 if(m_status.m_isposting==false)
\r
790 // get end of command line
\r
791 std::vector<char>::iterator endpos=Find(m_receivebuffer,"\r\n");
\r
793 // we got a command
\r
794 if(endpos!=m_receivebuffer.end())
\r
796 NNTPCommand command;
\r
797 std::string commandline(m_receivebuffer.begin(),endpos);
\r
799 // remove command from receive buffer
\r
800 m_receivebuffer.erase(m_receivebuffer.begin(),endpos+2);
\r
802 // remove any leading/trailing whitespace
\r
803 commandline=StringFunctions::TrimWhitespace(commandline);
\r
805 // split out command and arguments separated by space or tab
\r
806 StringFunctions::SplitMultiple(commandline," \t",command.m_arguments);
\r
808 // command is first element in argument vector
\r
809 command.m_command=command.m_arguments[0];
\r
810 // erase command from argument vector and make it upper case
\r
811 command.m_arguments.erase(command.m_arguments.begin());
\r
812 StringFunctions::UpperCase(command.m_command,command.m_command);
\r
814 if(HandleCommand(command)==true)
\r
820 SendBufferedLine("500 Unknown command");
\r
822 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleReceivedData received unhandled NNTP command : "+commandline);
\r
830 // check for end of post
\r
831 std::vector<char>::iterator endpos=Find(m_receivebuffer,"\r\n.\r\n");
\r
833 if(endpos!=m_receivebuffer.end())
\r
836 std::string message(m_receivebuffer.begin(),endpos);
\r
837 // remove from receive buffer
\r
838 m_receivebuffer.erase(m_receivebuffer.begin(),endpos+5);
\r
840 // get rid of dot stuffing ( 2 dots on start of a line - used to prevent premature message end in NNTP)
\r
841 message=StringFunctions::Replace(message,"\r\n..","\r\n.");
\r
843 HandlePostedMessage(message);
\r
845 // message was received, so posting is completed
\r
846 m_status.m_isposting=false;
\r
852 const bool NNTPConnection::HandleStatCommand(const NNTPCommand &command)
\r
854 SendArticleParts(command);
\r
859 const bool NNTPConnection::HandleQuitCommand(const NNTPCommand &command)
\r
861 SendBufferedLine("205 Connection Closing");
\r
864 m_log->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPConnection::HandleQuitCommand client closed connection");
\r
868 void NNTPConnection::Run()
\r
871 fd_set writefs,readfs;
\r
874 // seed random number generater for this thread
\r
877 if(m_status.m_allowpost==true)
\r
879 SendBufferedLine("200 Service available, posting allowed");
\r
883 SendBufferedLine("201 Service available, posting prohibited");
\r
891 FD_SET(m_socket,&readfs);
\r
892 if(m_sendbuffer.size()>0)
\r
894 FD_SET(m_socket,&writefs);
\r
900 rval=select(m_socket+1,&readfs,&writefs,0,&tv);
\r
904 if(FD_ISSET(m_socket,&readfs))
\r
907 HandleReceivedData();
\r
909 if(m_socket!=INVALID_SOCKET && FD_ISSET(m_socket,&writefs))
\r
914 else if(rval==SOCKET_ERROR)
\r
916 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::run select returned -1 : "+GetSocketErrorMessage());
\r
919 // }while(!Disconnected() && !ZThread::Thread::interrupted());
\r
920 }while(!Disconnected() && !IsCancelled());
\r
926 void NNTPConnection::SendArticleOverInfo(Message &message)
\r
928 std::string tempval;
\r
930 std::map<long,std::string> references;
\r
932 StringFunctions::Convert(message.GetMessageID(),tempval);
\r
934 line+=message.GetSubject()+"\t";
\r
935 line+=message.GetFromName()+"\t";
\r
936 line+=message.GetDateTime().Format("%a, %d %b %y %H:%M:%S -0000")+"\t";
\r
937 line+=message.GetNNTPArticleID()+"\t";
\r
938 references=message.GetInReplyTo();
\r
939 if(references.size()>0)
\r
941 for(std::map<long,std::string>::reverse_iterator i=references.rbegin(); i!=references.rend(); i++)
\r
943 if(i!=references.rbegin())
\r
947 line+="<"+(*i).second+">";
\r
957 SendBufferedLine(line);
\r
960 void NNTPConnection::SendArticleParts(const NNTPConnection::NNTPCommand &command)
\r
962 bool sendheaders,sendbody;
\r
963 std::string successcode;
\r
965 if(command.m_command=="ARTICLE")
\r
971 else if(command.m_command=="HEAD")
\r
977 else if(command.m_command=="BODY")
\r
983 else if(command.m_command=="STAT")
\r
991 int messageid=m_status.m_messageid;
\r
992 std::string articleid="";
\r
993 int type=0; // default to current messageid, 1=messageid, 2=articleid
\r
995 if(command.m_arguments.size()==1 && command.m_arguments[0].size()>0)
\r
997 if(command.m_arguments[0].find("<")==std::string::npos)
\r
999 StringFunctions::Convert(command.m_arguments[0],messageid);
\r
1000 message.Load(messageid,m_status.m_boardid);
\r
1001 m_status.m_messageid=message.GetMessageID();
\r
1006 articleid=command.m_arguments[0];
\r
1007 message.Load(articleid);
\r
1013 message.Load(m_status.m_messageid,m_status.m_boardid);
\r
1019 if(m_status.m_boardid!=-1)
\r
1021 if(m_status.m_messageid!=-1)
\r
1023 std::ostringstream tempstr;
\r
1024 std::string article;
\r
1025 if(sendheaders&&sendbody)
\r
1027 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1029 else if(sendheaders && !sendbody)
\r
1031 article=message.GetNNTPHeaders();
\r
1032 // strip off final \r\n from headers
\r
1033 if(article.rfind("\r\n")==article.size()-2)
\r
1035 article.erase(article.size()-2);
\r
1040 article=message.GetNNTPBody();
\r
1042 // dot stuff article
\r
1043 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1045 tempstr << successcode << " " << message.GetMessageID() << " " << message.GetNNTPArticleID();
\r
1047 SendBufferedLine(tempstr.str());
\r
1048 if(sendheaders || sendbody)
\r
1050 SendBufferedLine(article);
\r
1051 SendBufferedLine(".");
\r
1057 SendBufferedLine("420 Current article number is invalid");
\r
1062 SendBufferedLine("412 No newsgroup selected");
\r
1066 if(m_status.m_boardid!=-1)
\r
1068 if(message.GetMessageID()!=-1)
\r
1070 std::ostringstream tempstr;
\r
1071 std::string article;
\r
1072 if(sendheaders&&sendbody)
\r
1074 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1076 else if(sendheaders && !sendbody)
\r
1078 article=message.GetNNTPHeaders();
\r
1079 // strip off final \r\n from headers
\r
1080 if(article.rfind("\r\n")==article.size()-2)
\r
1082 article.erase(article.size()-2);
\r
1087 article=message.GetNNTPBody();
\r
1089 // dot stuff article
\r
1090 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1092 tempstr << successcode << " " << message.GetMessageID() << " " << message.GetNNTPArticleID();
\r
1094 SendBufferedLine(tempstr.str());
\r
1095 if(sendheaders || sendbody)
\r
1097 SendBufferedLine(article);
\r
1098 SendBufferedLine(".");
\r
1103 SendBufferedLine("423 No article with that number");
\r
1108 SendBufferedLine("412 No newsgroup selected");
\r
1112 if(message.GetMessageID()!=-1)
\r
1114 std::string article;
\r
1115 if(sendheaders&&sendbody)
\r
1117 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1119 else if(sendheaders && !sendbody)
\r
1121 article=message.GetNNTPHeaders();
\r
1122 // strip off final \r\n from headers
\r
1123 if(article.rfind("\r\n")==article.size()-2)
\r
1125 article.erase(article.size()-2);
\r
1130 article=message.GetNNTPBody();
\r
1132 // dot stuff article
\r
1133 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1135 SendBufferedLine(successcode+" 0 "+message.GetNNTPArticleID());
\r
1136 if(sendheaders || sendbody)
\r
1138 SendBufferedLine(article);
\r
1139 SendBufferedLine(".");
\r
1144 SendBufferedLine("430 No article with that message-id");
\r
1151 void NNTPConnection::SendBuffered(const std::string &data)
\r
1153 m_sendbuffer.insert(m_sendbuffer.end(),data.begin(),data.end());
\r
1156 void NNTPConnection::SocketReceive()
\r
1158 int rval=recv(m_socket,&m_tempbuffer[0],m_tempbuffer.size(),0);
\r
1161 m_receivebuffer.insert(m_receivebuffer.end(),m_tempbuffer.begin(),m_tempbuffer.begin()+rval);
\r
1166 m_log->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPConnection::SocketReceive remote host closed connection");
\r
1170 std::string errnostr;
\r
1171 StringFunctions::Convert(GetSocketErrorNumber(),errnostr);
\r
1172 // error on receive - close the connection
\r
1174 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::SocketReceive recv returned -1 : "+errnostr+" - "+GetSocketErrorMessage());
\r
1178 void NNTPConnection::SocketSend()
\r
1180 if(m_sendbuffer.size()>0 && m_socket!=INVALID_SOCKET)
\r
1182 int rval=send(m_socket,&m_sendbuffer[0],m_sendbuffer.size(),0);
\r
1185 m_sendbuffer.erase(m_sendbuffer.begin(),m_sendbuffer.begin()+rval);
\r
1189 std::string errnostr;
\r
1190 StringFunctions::Convert(GetSocketErrorNumber(),errnostr);
\r
1191 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::SocketSend returned -1 : "+errnostr+" - "+GetSocketErrorMessage());
\r