📄 idnntpserver.pas
字号:
if LAccept then
begin
ASender.Reply.SetReply(335,'News to me! <CRLF.CRLF> to end.'); {do not localize}
ASender.SendReply;
LErrorText := '';
OnPost(TIdNNTPContext(ASender.Context), LAccept, LErrorText);
ASender.Reply.SetReply(iif(LAccept, 235, 436), LErrorText);
end
else
begin
ASender.Reply.NumericCode := 435;
end;
end;
end else ASender.Reply.NumericCode := 500;
end;
procedure TIdNNTPServer.CommandLast(ASender: TIdCommand);
var
LMsgNo: Integer;
LThread: TIdNNTPContext;
LMsgID : String;
begin
if Assigned(OnPrevArticle) then begin
if SecLayerOk(ASender) then
begin
Exit;
end;
if not AuthOk(ASender) then begin
LThread := TIdNNTPContext(ASender.Context);
//we do this in a round about way in case there is no previous article at all
LMsgNo := LThread.CurrentArticle;
LMsgID := RawNavigate(LThread,OnPrevArticle);
if LMsgID<>'' then begin
ASender.Reply.SetReply(223, IntToStr(LMsgNo) + ' ' + LMsgID +
' article retrieved - request text separately'); {do not localize}
end else begin
ASender.Reply.NumericCode := 430;
end;
end;
end else ASender.Reply.NumericCode := 500;
end;
(*
3.6. The LIST command
3.6.1. LIST
LIST
Returns a list of valid newsgroups and associated information. Each
newsgroup is sent as a line of text in the following format:
group last first p
where <group> is the name of the newsgroup, <last> is the number of
the last known article currently in that newsgroup, <first> is the
number of the first article currently in the newsgroup, and <p> is
either 'y' or 'n' indicating whether posting to this newsgroup is
allowed ('y') or prohibited ('n').
The <first> and <last> fields will always be numeric. They may have
leading zeros. If the <last> field evaluates to less than the
<first> field, there are no articles currently on file in the
newsgroup.
Note that posting may still be prohibited to a client even though the
LIST command indicates that posting is permitted to a particular
newsgroup. See the POST command for an explanation of client
prohibitions. The posting flag exists for each newsgroup because
some newsgroups are moderated or are digests, and therefore cannot be
posted to; that is, articles posted to them must be mailed to a
moderator who will post them for the submitter. This is independent
of the posting permission granted to a client by the NNTP server.
Please note that an empty list (i.e., the text body returned by this
command consists only of the terminating period) is a possible valid
response, and indicates that there are currently no valid newsgroups.
3.6.2. Responses
215 list of newsgroups follows
*)
procedure TIdNNTPServer.CommandList(ASender: TIdCommand);
begin
if SecLayerOk(ASender) then
begin
Exit;
end;
if not AuthOk(ASender) then begin
ASender.SendReply;
DoListGroups(TIdNNTPContext(ASender.Context));
ASender.Context.Connection.IOHandler.WriteLn('.');
end;
end;
procedure TIdNNTPServer.CommandListGroup(ASender: TIdCommand);
var LThrd : TIdNNTPContext;
LGroup : String;
LFirstIdx : Integer;
LCanJoin : Boolean;
begin
if Assigned(FOnCheckListGroup) and Assigned(FOnListGroup) then begin
if SecLayerOk(ASender) then
begin
Exit;
end;
if AuthOk(ASender)=False then begin
ASender.Reply.NumericCode := 502;
end;
LThrd := TIdNNTPContext ( ASender.Context );
LGroup := Trim(ASender.UnparsedParams);
if Length(LGroup)>0 then
begin
LGroup := LThrd.CurrentGroup;
end;
FOnCheckListGroup(LThrd,LGroup,LCanJoin,LFirstIdx);
if LCanJoin then
begin
LThrd.FCurrentGroup := LGroup;
LThrd.FCurrentArticle := LFirstIdx;
ASender.SendReply;
FOnListGroup(LThrd);
ASender.Context.Connection.IOHandler.WriteLn('.');
end
else
begin
ASender.Reply.SetReply(412,'Not currently in newsgroup'); {do not localize}
end;
end else ASender.Reply.NumericCode := 500;
end;
procedure TIdNNTPServer.CommandModeReader(ASender: TIdCommand);
(*
2.3 MODE READER
MODE READER is used by the client to indicate to the server that it
is a news reading client. Some implementations make use of this
information to reconfigure themselves for better performance in
responding to news reader commands. This command can be contrasted
with the SLAVE command in RFC 977, which was not widely implemented.
MODE READER was first available in INN.
2.3.1 Responses
200 Hello, you can post
201 Hello, you can't post
*)
begin
if SecLayerOk(ASender) then
begin
Exit;
end;
TIdNNTPContext(ASender.Context).FModeReader := True;
ASender.Reply.NumericCode := 200;
end;
(*
3.7. The NEWGROUPS command
3.7.1. NEWGROUPS
NEWGROUPS date time [GMT] [<distributions>]
A list of newsgroups created since <date and time> will be listed in
the same format as the LIST command.
The date is sent as 6 digits in the format YYMMDD, where YY is the
last two digits of the year, MM is the two digits of the month (with
leading zero, if appropriate), and DD is the day of the month (with
leading zero, if appropriate). The closest century is assumed as
part of the year (i.e., 86 specifies 1986, 30 specifies 2030, 99 is
1999, 00 is 2000).
Time must also be specified. It must be as 6 digits HHMMSS with HH
being hours on the 24-hour clock, MM minutes 00-59, and SS seconds
00-59. The time is assumed to be in the server's timezone unless the
token "GMT" appears, in which case both time and date are evaluated
at the 0 meridian.
The optional parameter "distributions" is a list of distribution
groups, enclosed in angle brackets. If specified, the distribution
portion of a new newsgroup (e.g, 'net' in 'net.wombat') will be
examined for a match with the distribution categories listed, and
only those new newsgroups which match will be listed. If more than
one distribution group is to be listed, they must be separated by
commas within the angle brackets.
Please note that an empty list (i.e., the text body returned by this
command consists only of the terminating period) is a possible valid
response, and indicates that there are currently no new newsgroups.
3.7.2. Responses
231 list of new newsgroups follows
*)
procedure TIdNNTPServer.CommandNewGroups(ASender: TIdCommand);
var LDate : TDateTime;
LDist : String;
begin
if SecLayerOk(ASender) then
begin
Exit;
end;
if AuthOk(ASender) then begin
Exit;
end;
if (ASender.Params.Count > 1) and (Assigned(FOnListNewGroups)) then
begin
LDist := '';
LDate := NNTPDateTimeToDateTime( ASender.Params[0] );
LDate := LDate + NNTPTimeToTime( ASender.Params[1] );
if ASender.Params.Count > 2 then
begin
if (UpperCase(ASender.Params[2]) = 'GMT') then {Do not translate}
begin
LDate := LDate + OffSetFromUTC;
if (ASender.Params.Count > 3) then
begin
LDist := ASender.Params[3];
end;
end
else
begin
LDist := ASender.Params[2];
end;
end;
ASender.SendReply;
FOnListNewGroups(TIdNNTPContext(ASender.Context), LDate, LDist);
ASender.Context.Connection.IOHandler.WriteLn('.');
end else ASender.Reply.NumericCode := 500;
end;
procedure TIdNNTPServer.CommandNewNews(ASender: TIdCommand);
var LDate : TDateTime;
LDist : String;
begin
if SecLayerOk(ASender) then
begin
Exit;
end;
if AuthOk(ASender) then begin
Exit;
end;
if (ASender.Params.Count > 2) and (Assigned(FOnNewNews)) then
begin
//0 - newsgroup
//1 - date
//2 - time
//3 - GMT or distributions
//4 - distributions if 3 was GMT
LDist := '';
LDate := NNTPDateTimeToDateTime( ASender.Params[1] );
LDate := LDate + NNTPTimeToTime( ASender.Params[2] );
if (ASender.Params.Count > 3) then
begin
if (UpperCase(ASender.Params[3]) = 'GMT') then {Do not translate}
begin
LDate := LDate + OffSetFromUTC;
if (ASender.Params.Count > 4) then
begin
LDist := ASender.Params[4];
end;
end
else
begin
LDist := ASender.Params[3];
end;
end;
ASender.SendReply;
FOnNewNews( TIdNNTPContext(ASender.Context), ASender.Params[0], LDate, LDist );
ASender.Context.Connection.IOHandler.WriteLn('.');
end else ASender.Reply.NumericCode := 500;
end;
procedure TIdNNTPServer.CommandNext(ASender: TIdCommand);
var
LMsgNo: Integer;
LThread: TIdNNTPContext;
LMsgID : String;
begin
if Assigned(OnPrevArticle) then begin
if SecLayerOk(ASender) then
begin
Exit;
end;
if AuthOk(ASender) then begin
Exit;
end;
LThread := TIdNNTPContext(ASender.Context);
//we do this in a round about way in case there is no previous article at all
LMsgNo := LThread.CurrentArticle;
LMsgID := RawNavigate(LThread,OnPrevArticle);
if LMsgID<>'' then begin
ASender.Reply.SetReply(223, IntToStr(LMsgNo) + ' ' + LMsgID +
' article retrieved - request text separately'); {do not localize}
end else begin
ASender.Reply.NumericCode := 430;
end;
end;
end;
(*
3.10. The POST command
3.10.1. POST
POST
If posting is allowed, response code 340 is returned to indicate that
the article to be posted should be sent. Response code 440 indicates
that posting is prohibited for some installation-dependent reason.
If posting is permitted, the article should be presented in the
format specified by RFC850, and should include all required header
lines. After the article's header and body have been completely sent
by the client to the server, a further response code will be returned
to indicate success or failure of the posting attempt.
The text forming the header and body of the message to be posted
should be sent by the client using the conventions for text received
from the news server: A single period (".") on a line indicates the
end of the text, with lines starting with a period in the original
text having that period doubled during transmission.
No attempt shall be made by the server to filter characters, fold or
limit lines, or otherwise process incoming text. It is our intent
that the server just pass the incoming message to be posted to the
server installation's news posting software, which is separate from
this specification. See RFC850 for more details.
Since most installations will want the client news program to allow
the user to prepare his message using some sort of text editor, and
transmit it to the server for posting only after it is composed, the
client program should take note of the herald message that greeted it
when the connection was first established. This message indicates
whether postings from that client are permitted or not, and can be
used to caution the user that his access is read-only if that is the
case. This will prevent the user from wasting a good deal of time
composing a message only to find posting of the message was denied.
The method and determination of which clients and hosts may post is
installation dependent and is not covered by this specification.
3.10.2. Responses
240 article posted ok
340 send article to be posted. End with <CR-LF>.<CR-LF>
440 posting not allowed
441 posting failed
(for reference, one of the following codes will be sent upon initial
connection; the client program should determine whether posting is
generally permitted from these:) 200 server ready - posting allowed
201 server ready - no posting allowed
*)
procedure TIdNNTPServer.CommandPost(ASender: TIdCommand);
var
LCanPost: Boolean;
LErrorText: string;
LPostOk: Boolean;
LReply: TIdReplyRFC;
begin
if SecLayerOk(ASender) then begin
Exit;
end;
if AuthOk(ASender) then begin
Exit;
end;
LCanPost := Assigned(OnPost);
LReply := TIdReplyRFC.Create(nil);
try
LReply.NumericCode := iif(LCanPost, 340, 440);
ReplyTexts.UpdateText(LReply);
ASender.Context.Connection.IOHandler.Write(LReply.FormattedReply);
finally
FreeAndNil(LReply);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -