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
320 if(show==true && (*i).GetSaveReceivedMessages()==true)
\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
351 if(show==true && (*i).GetSaveReceivedMessages()==true)
\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 if((*i).GetSaveReceivedMessages()==true)
\r
564 std::ostringstream tempstr;
\r
565 tempstr << (*i).GetBoardName() << " " << (*i).GetHighMessageID() << " " << (*i).GetLowMessageID() << " " << m_status.m_allowpost ? "y" : "n";
\r
566 SendBufferedLine(tempstr.str());
\r
570 SendBufferedLine(".");
\r
575 SendBufferedLine("501 Syntax error");
\r
576 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleNewGroupsCommand syntax error");
\r
583 const bool NNTPConnection::HandleNextCommand(const NNTPCommand &command)
\r
585 if(m_status.m_boardid!=-1)
\r
587 if(m_status.m_messageid!=-1)
\r
591 if(mess.LoadNext(m_status.m_messageid,m_status.m_boardid))
\r
593 std::ostringstream tempstr;
\r
595 m_status.m_messageid=mess.GetMessageID();
\r
597 tempstr << "223 " << mess.GetMessageID() << " " << mess.GetNNTPArticleID();
\r
599 SendBufferedLine(tempstr.str());
\r
604 SendBufferedLine("421 No next article in this group");
\r
609 SendBufferedLine("420 Current article number is invalid");
\r
614 SendBufferedLine("412 No newsgroup selected");
\r
621 const bool NNTPConnection::HandleOverCommand(const NNTPCommand &command)
\r
623 long lowmessageid,highmessageid;
\r
624 std::string messageuuid="";
\r
626 lowmessageid=highmessageid=-2;
\r
628 if(command.m_arguments.size()==0)
\r
630 lowmessageid=m_status.m_messageid;
\r
631 highmessageid=m_status.m_messageid;
\r
636 if(command.m_arguments.size()>0 && command.m_arguments[0].find("<")==0 && command.m_arguments[0].find(">")>0)
\r
638 messageuuid=command.m_arguments[0];
\r
639 messageuuid=StringFunctions::Replace(messageuuid,"<","");
\r
640 messageuuid=StringFunctions::Replace(messageuuid,">","");
\r
642 // get rid of @ and everything after
\r
643 if(messageuuid.find("@")!=std::string::npos)
\r
645 messageuuid.erase(messageuuid.find("@"));
\r
649 // single article or range
\r
653 if(command.m_arguments[0].find("-")!=std::string::npos)
\r
655 std::vector<std::string> rangeparts;
\r
656 StringFunctions::Split(command.m_arguments[0],"-",rangeparts);
\r
658 if(rangeparts.size()>0)
\r
660 StringFunctions::Convert(rangeparts[0],lowmessageid);
\r
664 else if(rangeparts.size()>1)
\r
666 StringFunctions::Convert(rangeparts[1],highmessageid);
\r
672 StringFunctions::Convert(command.m_arguments[0],lowmessageid);
\r
677 if(messageuuid!="")
\r
680 if(mess.Load(messageuuid))
\r
682 SendBufferedLine("224 Overview information follows");
\r
683 SendArticleOverInfo(mess);
\r
684 SendBufferedLine(".");
\r
688 SendBufferedLine("423 No such article");
\r
694 if(m_status.m_boardid!=-1 && bd.Load(m_status.m_boardid))
\r
697 if(highmessageid==-2)
\r
700 if(mess.Load(lowmessageid,m_status.m_boardid))
\r
702 SendBufferedLine("224 Overview information follows");
\r
703 SendArticleOverInfo(mess);
\r
704 SendBufferedLine(".");
\r
708 SendBufferedLine("423 No such article in this group");
\r
711 // range with no upper bound
\r
712 else if(highmessageid==-1)
\r
715 ml.LoadRange(lowmessageid,bd.GetHighMessageID(),m_status.m_boardid);
\r
718 SendBufferedLine("224 Overview information follows");
\r
719 for(MessageList::iterator i=ml.begin(); i!=ml.end(); i++)
\r
721 SendArticleOverInfo((*i));
\r
723 SendBufferedLine(".");
\r
727 SendBufferedLine("423 Empty range");
\r
730 // range with upper and lower bound
\r
731 else if(highmessageid>=lowmessageid)
\r
734 ml.LoadRange(lowmessageid,highmessageid,m_status.m_boardid);
\r
737 SendBufferedLine("224 Overview information follows");
\r
738 for(MessageList::iterator i=ml.begin(); i!=ml.end(); i++)
\r
740 SendArticleOverInfo((*i));
\r
742 SendBufferedLine(".");
\r
746 SendBufferedLine("423 Empty range");
\r
752 SendBufferedLine("423 Empty range");
\r
757 SendBufferedLine("423 No newsgroup selected");
\r
765 const bool NNTPConnection::HandlePostCommand(const NNTPCommand &command)
\r
767 if(m_status.m_allowpost==true)
\r
769 SendBufferedLine("340 Send article to be posted");
\r
770 m_status.m_isposting=true;
\r
774 SendBufferedLine("440 Posting not permitted");
\r
780 void NNTPConnection::HandlePostedMessage(const std::string &message)
\r
784 if(mess.ParseNNTPMessage(message))
\r
786 if(mess.PostedToAdministrationBoard()==true)
\r
788 mess.HandleAdministrationMessage();
\r
790 if(mess.StartFreenetInsert())
\r
792 SendBufferedLine("240 Article received OK");
\r
796 SendBufferedLine("441 Posting failed. Make sure the identity you are sending with exists!");
\r
801 SendBufferedLine("441 Posting failed");
\r
805 void NNTPConnection::HandleReceivedData()
\r
807 if(m_status.m_isposting==false)
\r
809 // get end of command line
\r
810 std::vector<char>::iterator endpos=Find(m_receivebuffer,"\r\n");
\r
812 // we got a command
\r
813 if(endpos!=m_receivebuffer.end())
\r
815 NNTPCommand command;
\r
816 std::string commandline(m_receivebuffer.begin(),endpos);
\r
818 // remove command from receive buffer
\r
819 m_receivebuffer.erase(m_receivebuffer.begin(),endpos+2);
\r
821 // remove any leading/trailing whitespace
\r
822 commandline=StringFunctions::TrimWhitespace(commandline);
\r
824 // split out command and arguments separated by space or tab
\r
825 StringFunctions::SplitMultiple(commandline," \t",command.m_arguments);
\r
827 // command is first element in argument vector
\r
828 command.m_command=command.m_arguments[0];
\r
829 // erase command from argument vector and make it upper case
\r
830 command.m_arguments.erase(command.m_arguments.begin());
\r
831 StringFunctions::UpperCase(command.m_command,command.m_command);
\r
833 if(HandleCommand(command)==true)
\r
839 SendBufferedLine("500 Unknown command");
\r
841 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleReceivedData received unhandled NNTP command : "+commandline);
\r
849 // check for end of post
\r
850 std::vector<char>::iterator endpos=Find(m_receivebuffer,"\r\n.\r\n");
\r
852 if(endpos!=m_receivebuffer.end())
\r
855 std::string message(m_receivebuffer.begin(),endpos);
\r
856 // remove from receive buffer
\r
857 m_receivebuffer.erase(m_receivebuffer.begin(),endpos+5);
\r
859 // get rid of dot stuffing ( 2 dots on start of a line - used to prevent premature message end in NNTP)
\r
860 message=StringFunctions::Replace(message,"\r\n..","\r\n.");
\r
862 HandlePostedMessage(message);
\r
864 // message was received, so posting is completed
\r
865 m_status.m_isposting=false;
\r
871 const bool NNTPConnection::HandleStatCommand(const NNTPCommand &command)
\r
873 SendArticleParts(command);
\r
878 const bool NNTPConnection::HandleQuitCommand(const NNTPCommand &command)
\r
880 SendBufferedLine("205 Connection Closing");
\r
883 m_log->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPConnection::HandleQuitCommand client closed connection");
\r
887 void NNTPConnection::Run()
\r
890 fd_set writefs,readfs;
\r
893 // seed random number generater for this thread
\r
896 if(m_status.m_allowpost==true)
\r
898 SendBufferedLine("200 Service available, posting allowed");
\r
902 SendBufferedLine("201 Service available, posting prohibited");
\r
910 FD_SET(m_socket,&readfs);
\r
911 if(m_sendbuffer.size()>0)
\r
913 FD_SET(m_socket,&writefs);
\r
919 rval=select(m_socket+1,&readfs,&writefs,0,&tv);
\r
923 if(FD_ISSET(m_socket,&readfs))
\r
926 HandleReceivedData();
\r
928 if(m_socket!=INVALID_SOCKET && FD_ISSET(m_socket,&writefs))
\r
933 else if(rval==SOCKET_ERROR)
\r
935 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::run select returned -1 : "+GetSocketErrorMessage());
\r
938 // }while(!Disconnected() && !ZThread::Thread::interrupted());
\r
939 }while(!Disconnected() && !IsCancelled());
\r
945 void NNTPConnection::SendArticleOverInfo(Message &message)
\r
947 std::string tempval;
\r
949 std::map<long,std::string> references;
\r
951 StringFunctions::Convert(message.GetMessageID(),tempval);
\r
953 line+=message.GetSubject()+"\t";
\r
954 line+=message.GetFromName()+"\t";
\r
955 line+=message.GetDateTime().Format("%a, %d %b %y %H:%M:%S -0000")+"\t";
\r
956 line+=message.GetNNTPArticleID()+"\t";
\r
957 references=message.GetInReplyTo();
\r
958 if(references.size()>0)
\r
960 for(std::map<long,std::string>::reverse_iterator i=references.rbegin(); i!=references.rend(); i++)
\r
962 if(i!=references.rbegin())
\r
966 line+="<"+(*i).second+">"; //+"@freenetproject.org>";
\r
976 SendBufferedLine(line);
\r
979 void NNTPConnection::SendArticleParts(const NNTPConnection::NNTPCommand &command)
\r
981 bool sendheaders,sendbody;
\r
982 std::string successcode;
\r
984 if(command.m_command=="ARTICLE")
\r
990 else if(command.m_command=="HEAD")
\r
996 else if(command.m_command=="BODY")
\r
1000 successcode="222";
\r
1002 else if(command.m_command=="STAT")
\r
1004 sendheaders=false;
\r
1006 successcode="223";
\r
1010 int messageid=m_status.m_messageid;
\r
1011 std::string articleid="";
\r
1012 int type=0; // default to current messageid, 1=messageid, 2=articleid
\r
1014 if(command.m_arguments.size()==1 && command.m_arguments[0].size()>0)
\r
1016 if(command.m_arguments[0].find("<")==std::string::npos)
\r
1018 StringFunctions::Convert(command.m_arguments[0],messageid);
\r
1019 message.Load(messageid,m_status.m_boardid);
\r
1020 m_status.m_messageid=message.GetMessageID();
\r
1025 articleid=command.m_arguments[0];
\r
1026 //strip off < and > and everthing after @
\r
1027 if(articleid.size()>0 && articleid[0]=='<')
\r
1029 articleid.erase(0,1);
\r
1031 if(articleid.size()>0 && articleid[articleid.size()-1]=='>')
\r
1033 articleid.erase(articleid.size()-1);
\r
1036 if(articleid.size()>0 && articleid.find('@')!=std::string::npos)
\r
1038 articleid.erase(articleid.find('@'));
\r
1041 message.Load(articleid);
\r
1047 message.Load(m_status.m_messageid,m_status.m_boardid);
\r
1053 if(m_status.m_boardid!=-1)
\r
1055 if(m_status.m_messageid!=-1)
\r
1057 std::ostringstream tempstr;
\r
1058 std::string article;
\r
1059 if(sendheaders&&sendbody)
\r
1061 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1063 else if(sendheaders && !sendbody)
\r
1065 article=message.GetNNTPHeaders();
\r
1066 // strip off final \r\n from headers
\r
1067 if(article.rfind("\r\n")==article.size()-2)
\r
1069 article.erase(article.size()-2);
\r
1074 article=message.GetNNTPBody();
\r
1076 // dot stuff article
\r
1077 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1079 tempstr << successcode << " " << message.GetMessageID() << " " << message.GetNNTPArticleID();
\r
1081 SendBufferedLine(tempstr.str());
\r
1082 if(sendheaders || sendbody)
\r
1084 SendBufferedLine(article);
\r
1085 SendBufferedLine(".");
\r
1091 SendBufferedLine("420 Current article number is invalid");
\r
1096 SendBufferedLine("412 No newsgroup selected");
\r
1100 if(m_status.m_boardid!=-1)
\r
1102 if(message.GetMessageID()!=-1)
\r
1104 std::ostringstream tempstr;
\r
1105 std::string article;
\r
1106 if(sendheaders&&sendbody)
\r
1108 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1110 else if(sendheaders && !sendbody)
\r
1112 article=message.GetNNTPHeaders();
\r
1113 // strip off final \r\n from headers
\r
1114 if(article.rfind("\r\n")==article.size()-2)
\r
1116 article.erase(article.size()-2);
\r
1121 article=message.GetNNTPBody();
\r
1123 // dot stuff article
\r
1124 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1126 tempstr << successcode << " " << message.GetMessageID() << " " << message.GetNNTPArticleID();
\r
1128 SendBufferedLine(tempstr.str());
\r
1129 if(sendheaders || sendbody)
\r
1131 SendBufferedLine(article);
\r
1132 SendBufferedLine(".");
\r
1137 SendBufferedLine("423 No article with that number");
\r
1142 SendBufferedLine("412 No newsgroup selected");
\r
1146 if(message.GetMessageID()!=-1)
\r
1148 std::string article;
\r
1149 if(sendheaders&&sendbody)
\r
1151 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1153 else if(sendheaders && !sendbody)
\r
1155 article=message.GetNNTPHeaders();
\r
1156 // strip off final \r\n from headers
\r
1157 if(article.rfind("\r\n")==article.size()-2)
\r
1159 article.erase(article.size()-2);
\r
1164 article=message.GetNNTPBody();
\r
1166 // dot stuff article
\r
1167 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1169 SendBufferedLine(successcode+" 0 "+message.GetNNTPArticleID());
\r
1170 if(sendheaders || sendbody)
\r
1172 SendBufferedLine(article);
\r
1173 SendBufferedLine(".");
\r
1178 SendBufferedLine("430 No article with that message-id");
\r
1185 void NNTPConnection::SendBuffered(const std::string &data)
\r
1187 m_sendbuffer.insert(m_sendbuffer.end(),data.begin(),data.end());
\r
1190 void NNTPConnection::SocketReceive()
\r
1192 int rval=recv(m_socket,&m_tempbuffer[0],m_tempbuffer.size(),0);
\r
1195 m_receivebuffer.insert(m_receivebuffer.end(),m_tempbuffer.begin(),m_tempbuffer.begin()+rval);
\r
1200 m_log->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPConnection::SocketReceive remote host closed connection");
\r
1204 std::string errnostr;
\r
1205 StringFunctions::Convert(GetSocketErrorNumber(),errnostr);
\r
1206 // error on receive - close the connection
\r
1208 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::SocketReceive recv returned -1 : "+errnostr+" - "+GetSocketErrorMessage());
\r
1212 void NNTPConnection::SocketSend()
\r
1214 if(m_sendbuffer.size()>0 && m_socket!=INVALID_SOCKET)
\r
1216 int rval=send(m_socket,&m_sendbuffer[0],m_sendbuffer.size(),0);
\r
1219 m_sendbuffer.erase(m_sendbuffer.begin(),m_sendbuffer.begin()+rval);
\r
1223 std::string errnostr;
\r
1224 StringFunctions::Convert(GetSocketErrorNumber(),errnostr);
\r
1225 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::SocketSend returned -1 : "+errnostr+" - "+GetSocketErrorMessage());
\r