15 TModeType
= (mtStream
, mtIHAVE
, mtReader
);
17 TConnectionResult
= (crCanPost
, crNoPost
, crAuthRequired
, crTempUnavailable
);
18 TModeSetResult
= (mrCanStream
, mrNoStream
, mrCanIHAVE
, mrNoIHAVE
, mrCanPost
,
21 TEventStreaming
= procedure(const AMesgID
: string; var AAccepted
: Boolean) of
23 TNewsTransportEvent
= procedure(AMsg
: PStrList
) of object;
24 TEventNewsgroupList
= procedure(const ANewsgroup
: string; const ALow
, AHigh
:
26 const AType
: string; var ACanContinue
: Boolean) of object;
28 TEventNewNewsList
= procedure(const AMsgID
: string; var ACanContinue
: Boolean)
31 TIdNNTP
= object(TIdMessageClient
)
40 FOnNewGroupsList
: TEventNewsgroupList
;
41 FOnNewNewsList
: TEventNewNewsList
;
42 fOnSendCheck
: TNewsTransportEvent
;
43 fOnSendTakethis
: TNewsTransportEvent
;
45 fConectionResult
: TConnectionResult
;
46 fModeResult
: TModeSetResult
;
47 fOnSendIHAVE
: TNewsTransportEvent
;
52 function ConvertDateTimeDist(ADate
: TDateTime
; AGMT
: boolean;
53 const ADistributions
: string): string;
54 procedure SetModeType(const AValue
: TModeType
);
55 procedure setConnectionResult(const AValue
: TConnectionResult
);
56 procedure SetModeResult(const AValue
: TModeSetResult
);
57 function Get(const ACmd
: string; const AMsgNo
: Cardinal; const AMsgID
:
59 AMsg
: TIDMessage
): Boolean;
60 function SetArticle(const ACmd
: string; const AMsgNo
: Cardinal; const
61 AMsgID
: string): Boolean;
62 procedure ProcessGroupList(const ACmd
: string; const AResponse
: integer;
63 const AListEvent
: TEventNewsgroupList
);
65 // constructor Create(AOwner: TComponent); override;
66 procedure Connect
; virtual;//override;
67 procedure Disconnect
; virtual;//override;
68 function GetArticle(const AMsgNo
: Cardinal; const AMsgID
: string; AMsg
:
70 function GetBody(const AMsgNo
: Cardinal; const AMsgID
: string; AMsg
:
72 function GetHeader(const AMsgNo
: Cardinal; const AMsgID
: string; AMsg
:
74 procedure GetNewsgroupList
; overload
;
75 procedure GetNewsgroupList(AList
: PStrList
); overload
;
76 procedure GetNewGroupsList(const ADate
: TDateTime
; const AGMT
: boolean;
77 const ADistributions
: string); overload
;
78 procedure GetNewGroupsList(const ADate
: TDateTime
; const AGMT
: boolean;
79 const ADistributions
: string; AList
: PStrList
); overload
;
80 procedure GetNewNewsList(const ANewsgroups
: string;
81 const ADate
: TDateTime
; const AGMT
: boolean; ADistributions
: string);
83 procedure GetNewNewsList(const ANewsgroups
: string; const ADate
: TDateTime
;
84 const AGMT
: boolean; ADistributions
: string; AList
: PStrList
); overload
;
85 procedure GetOverviewFMT(var AResponse
: PStrList
);
86 function Next
: Boolean;
87 function Previous
: Boolean;
88 function SelectArticle(const AMsgNo
: Cardinal): Boolean;
89 procedure SelectGroup(const AGroup
: string);
90 procedure Send(AMsg
: TidMessage
);
91 procedure SendIHAVE(AMsg
: PStrList
);
92 procedure SendCheck(AMsgID
: PStrList
; var AResponses
: PStrList
);
93 function SendCmd(const AOut
: string; const AResponse
: array of SmallInt
):
94 SmallInt
;virtual;// override;
95 function SendTakeThis(AMsg
: PStrList
): string;
96 procedure SendXHDR(const AHeader
: string; const AParam
: string; var
98 procedure SendXOVER(const AParm
: string; var AResponse
: PStrList
);
100 property MsgID
: string read fsMsgID
;
101 property MsgNo
: Cardinal read FlMsgNo
;
102 property MsgHigh
: Cardinal read FlMsgHigh
;
103 property MsgLow
: Cardinal read FlMsgLow
;
104 property GreetingResult
: TConnectionResult read fConectionResult write
106 property ModeResult
: TModeSetResult read fModeResult write SetModeResult
;
107 property MsgCount
: Cardinal read flMsgCount write flMsgCount
;
109 property NewsAgent
: string read FNewsAgent write FNewsAgent
;
110 property Mode
: TModeType read fModeType write SetModeType default mtReader
;
111 property Password
: string read fPassword write fPassword
;
112 property UserId
: string read fUserId write fUserId
;
113 property SetMode
: Boolean read FbSetMode write FbSetMode default
True;
115 property OnSendCheck
: TNewsTransportEvent read fOnSendCheck
117 property OnSendIHAVE
: TNewsTransportEvent read fOnSendIHAVE
119 property OnSendTakeThis
: TNewsTransportEvent read fOnSendTakethis
120 write fOnSendTakethis
;
121 property OnNewsgroupList
: TEventNewsgroupList read FOnNewsgroupList
122 write FOnNewsgroupList
;
123 property OnNewGroupsList
: TEventNewsGroupList read FOnNewGroupsList
124 write FOnNewGroupsList
;
125 property OnNewNewsList
: TEventNewNewsList read FOnNewNewsList
126 write FOnNewNewsList
;
127 property Port default IdPORT_NNTP
;
131 function NewIdNNTP(AOwner
: PControl
):PIdNNTP
;
134 EIdNNTPException = object(EIdException);
135 PIdNNTPException=^EIdNNTPException; type MyStupid0=DWord;
136 EIdNNTPNoOnNewGroupsList = object(EIdNNTPException);
137 PdNNTPException=^IdNNTPException; type MyStupid3137=DWord;
138 EIdNNTPNoOnNewNewsList = object(EIdNNTPException);
139 PNNTPException=^dNNTPException; type MyStupid86104=DWord;
140 EIdNNTPNoOnNewsgroupList = object(EIdNNTPException);
141 PNTPException=^NNTPException; type MyStupid20258=DWord;
142 EIdNNTPStringListNotInitialized = object(EIdNNTPException);
143 PTPException=^NTPException; type MyStupid27292=DWord;
145 EIdNNTPConnectionRefused = object(EIdProtocolReplyError);
146 PPException=^TPException; type MyStupid67165=DWord;}
148 procedure ParseXOVER(Aline
: string; var AArticleIndex
: Cardinal;
151 var ADate
: TDateTime
;
155 ALineCount
: Cardinal;
156 var AExtraData
: string);
158 procedure ParseNewsGroup(ALine
: string; var ANewsGroup
: string;
159 var AHi
, ALo
: Cardinal;
160 var AStatus
: string);
169 procedure ParseXOVER(Aline
: string; var AArticleIndex
: Cardinal;
172 var ADate
: TDateTime
;
176 ALineCount
: Cardinal;
177 var AExtraData
: string);
180 ALine
:= StringReplace(ALine
, #9#8#9, #9, [rfReplaceAll
]);
181 AArticleIndex
:= StrToCard(Fetch(ALine
, #9));
182 ASubject
:= Fetch(ALine
, #9);
183 AFrom
:= Fetch(ALine
, #9);
184 ADate
:= StrInternetToDateTime(Fetch(Aline
, #9));
185 AMsgId
:= Fetch(Aline
, #9);
186 AReferences
:= Fetch(ALine
, #9);
187 AByteCount
:= StrToCard(Fetch(ALine
, #9));
188 ALineCount
:= StrToCard(Fetch(ALine
, #9));
192 procedure ParseNewsGroup(ALine
: string; var ANewsGroup
: string;
193 var AHi
, ALo
: Cardinal;
194 var AStatus
: string);
196 ANewsgroup
:= Fetch(ALine
, ' ');
197 AHi
:= StrToCard(Fetch(Aline
, ' '));
198 ALo
:= StrToCard(Fetch(ALine
, ' '));
202 { constructor TIdNNTP.Create(AOwner: TComponent);
204 function NewIdNNTP (AOwner
: PControl
):PIdNNTP
;
206 New( Result
, Create
);
209 // inherited Create(AOwner);
212 // Port := IdPORT_NNTP;
217 function TIdNNTP
.SendCmd(const AOut
: string; const AResponse
: array of
220 Result
:= inherited SendCmd(AOut
, []);
221 if (Result
= 480) or (Result
= 450) then
223 inherited SendCmd('AuthInfo User ' + UserID
, [381]);
224 inherited SendCmd('AuthInfo Pass ' + Password
, [281]);
225 Result
:= inherited SendCmd(AOut
, AResponse
);
229 Result
:= CheckResponse(Result
, AResponse
);
233 procedure TIdNNTP
.Connect
;
239 200: GreetingResult
:= crCanPost
;
240 201: GreetingResult
:= crNoPost
;
241 400: GreetingResult
:= crTempUnavailable
;
242 // 502: raise EIdNNTPConnectionRefused.CreateError(502,
243 // RSNNTPConnectionRefused);
248 // SendCmd('mode stream');
249 if ResultNo
<> 203 then
250 ModeResult
:= mrNoStream
252 ModeResult
:= mrCanStream
;
256 // SendCmd('mode reader');
257 if ResultNo
<> 200 then
258 ModeResult
:= mrNoPost
260 ModeResult
:= mrCanPost
;
269 procedure TIdNNTP
.Disconnect
;
279 procedure TIdNNTP
.GetOverviewFMT(var AResponse
: PStrList
);
281 // SendCmd('list overview.fmt', 215);
282 // Capture(AResponse);
285 procedure TIdNNTP
.SendXOVER(const AParm
: string; var AResponse
: PStrList
);
287 // SendCmd('xover ' + AParm, 224);
288 // Capture(AResponse);
291 procedure TIdNNTP
.SendXHDR(const AHeader
: string; const AParam
: string; var
292 AResponse
: PStrList
);
294 // SendCmd('XHDR ' + AHeader + ' ' + AParam, 221);
295 // Capture(AResponse);
298 procedure TIdNNTP
.SelectGroup(const AGroup
: string);
302 SendCmd('Group ' + AGroup
, [211]);
303 s
:= Copy(CmdResult
, 5, Maxint
);
304 FlMsgCount
:= StrToCard(Fetch(s
));
305 FlMsgLow
:= StrToCard(Fetch(s
));
306 FlMsgHigh
:= StrToCard(Fetch(s
));
309 function TIdNNTP
.Get(const ACmd
: string; const AMsgNo
: Cardinal; const AMsgID
:
311 AMsg
: TidMessage
): Boolean;
313 Result
:= SetArticle(ACmd
, AMsgNo
, AMsgID
);
317 if AnsiSameText(ACmd
, 'HEAD') then
319 if ResultNo
in [220, 221] then
321 ReceiveHeader(AMsg
, '.');
326 if ResultNo
in [220, 221] then
328 ReceiveHeader(AMsg
, '');
330 if ResultNo
in [220, 222] then
336 procedure TIdNNTP
.SendIHAVE(AMsg
: PStrList
);
342 { if not Assigned(FOnSendIHAVE) then
344 for i := 0 to AMsg.Count - 1 do
345 if IndyPos('Message-ID', AMsg.Strings[i]) > 0 then
347 MsgID := AMsg.Strings[i];
348 Temp := Fetch(MsgID, ':');
351 SendCmd('IHAVE ' + MsgID, 335);
352 for i := 0 to AMsg.Count - 1 do
359 procedure TIdNNTP
.SendCheck(AMsgID
: PStrList
;
360 var AResponses
: PStrList
);
364 if not Assigned(FOnSendCheck
) then
366 // for i := 0 to AMsgID.Count - 1 do
367 // Writeln('CHECK ' + AMsgID.Strings[i]);
368 for i
:= 0 to AMsgID
.Count
- 1 do
370 { if assigned(AResponses) then
371 AResponses.Add(ReadLn)
374 EIdNNTPStringListNotInitialized.Create(RSNNTPStringListNotInitialized);}
379 function TIdNNTP
.SendTakeThis(AMsg
: PStrList
): string;
385 { if not Assigned(FOnSendTakeThis) then
387 if (Setmode) and (ModeResult = mrNoStream) then
393 for i := 0 to AMsg.Count - 1 do
394 if IndyPos('Message-ID', AMsg.Strings[i]) > 0 then
396 MsgID := AMsg.Strings[i];
397 Temp := Fetch(MsgID, ':');
401 Writeln('TAKETHIS ' + MsgID);
402 for i := 0 to AMsg.Count - 1 do
411 procedure TIdNNTP
.Send(AMsg
: TidMessage
);
413 { SendCmd('Post', 340);
415 with AMsg.ExtraHeaders do
417 Values['Lines'] := IntToStr(AMsg.Body.Count);
418 Values['X-Newsreader'] := NewsAgent;
425 procedure TIdNNTP
.ProcessGroupList(const ACmd
: string; const AResponse
: integer;
426 const AListEvent
: TEventNewsgroupList
);
428 s1
, sNewsgroup
: string;
431 CanContinue
: Boolean;
433 { BeginWork(wmRead, 0);
435 SendCmd(ACmd, AResponse);
438 while (s1 <> '.') and CanContinue do
440 ParseNewsGroup(s1, sNewsgroup, lHi, lLo, sStatus);
441 AListEvent(sNewsgroup, lLo, lHi, sStatus, CanContinue);
449 procedure TIdNNTP
.GetNewsgroupList
;
451 { if not Assigned(FOnNewsgroupList) then
452 raise EIdNNTPNoOnNewsgroupList.Create(RSNNTPNoOnNewsgroupList);
454 ProcessGroupList('List', 215, FOnNewsgroupList);}
457 procedure TIdNNTP
.GetNewGroupsList(const ADate
: TDateTime
; const AGMT
: boolean;
458 const ADistributions
: string);
460 if not Assigned(FOnNewGroupsList
) then
462 // raise EIdNNTPNoOnNewGroupsList.Create(RSNNTPNoOnNewGroupsList);
464 ProcessGroupList('Newgroups ' + ConvertDateTimeDist(ADate
, AGMT
,
469 procedure TIdNNTP
.GetNewNewsList(const ANewsgroups
: string;
470 const ADate
: TDateTime
; const AGMT
: boolean; ADistributions
: string);
473 CanContinue
: Boolean;
475 // if not Assigned(FOnNewNewsList) then
476 // raise EIdNNTPNoOnNewNewsList.Create(RSNNTPNoOnNewNewsList);
478 BeginWork(wmRead
, 0);
480 // SendCmd('Newnews ' + ANewsgroups + ' ' + ConvertDateTimeDist(ADate, AGMT,
481 // ADistributions), 230);
484 while (s1
<> '.') and CanContinue
do
486 FOnNewNewsList(s1
, CanContinue
);
494 function TIdNNTP
.GetArticle(const AMsgNo
: Cardinal; const AMsgID
: string;
495 AMsg
: TidMessage
): Boolean;
497 Result
:= Get('Article', AMsgNo
, AMsgID
, AMsg
);
500 function TIdNNTP
.GetBody(const AMsgNo
: Cardinal; const AMsgID
: string;
501 AMsg
: TidMessage
): Boolean;
503 Result
:= Get('Body', AMsgNo
, AMsgID
, AMsg
);
506 function TIdNNTP
.GetHeader(const AMsgNo
: Cardinal; const AMsgID
: string;
507 AMsg
: TidMessage
): Boolean;
509 Result
:= Get('Head', AMsgNo
, AMsgID
, AMsg
);
512 function TIdNNTP
.Next
: Boolean;
514 Result
:= SetArticle('Next', 0, '');
517 function TIdNNTP
.Previous
: Boolean;
519 Result
:= SetArticle('Last', 0, '');
522 function TIdNNTP
.SelectArticle(const AMsgNo
: Cardinal): Boolean;
524 Result
:= SetArticle('Stat', AMsgNo
, '');
527 function TIdNNTP
.SetArticle(const ACmd
: string; const AMsgNo
: Cardinal;
528 const AMsgID
: string): Boolean;
532 { if AMsgNo >= 1 then
533 SendCmd(ACmd + ' ' + IntToStr(AMsgNo))
536 SendCmd(ACmd + ' <' + AMsgID + '>')
540 if ResultNo in [220, 221, 222, 223] then
546 flMsgNo := StrToCard(Fetch(s, ' '));
552 if (ResultNo = 421) or (ResultNo = 422)
553 or (ResultNo = 423) or (ResultNo = 430) then
559 raise EidResponseError.Create(CmdResult);
563 procedure TIdNNTP
.SetModeType(const AValue
: TModeType
);
568 procedure TIdNNTP
.setConnectionResult(const AValue
: TConnectionResult
);
570 fConectionResult
:= AValue
;
573 procedure TIdNNTP
.SetModeResult(const AValue
: TModeSetResult
);
575 fModeResult
:= AValue
;
578 procedure TIdNNTP
.GetNewsgroupList(AList
: PStrList
);
580 // SendCmd('List', 215);
584 procedure TIdNNTP
.GetNewGroupsList(const ADate
: TDateTime
; const AGMT
: boolean;
585 const ADistributions
: string; AList
: PStrList
);
587 // SendCmd('Newgroups ' + ConvertDateTimeDist(ADate, AGMT, ADistributions), 231);
591 procedure TIdNNTP
.GetNewNewsList(const ANewsgroups
: string; const ADate
:
593 const AGMT
: boolean; ADistributions
: string; AList
: PStrList
);
595 // SendCmd('Newnews ' + ANewsgroups + ' ' + ConvertDateTimeDist(ADate, AGMT,
596 // ADistributions), 230);
600 function TIdNNTP
.ConvertDateTimeDist(ADate
: TDateTime
; AGMT
: boolean;
601 const ADistributions
: string): string;
603 Result
:= FormatDateTime('yymmdd hhnnss', ADate
);
606 Result
:= Result
+ ' GMT';
608 if Length(ADistributions
) > 0 then
610 Result
:= ' <' + ADistributions
+ '>';