📄 u_connectionnntp.pas
字号:
(*
* One Way Network Sniffer (OWNS)
* Copyright (C) 2001-2002 OWNS
*
* http://owns.sourceforge.net/
* http://www.owns.st
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)
(*
* $Id: u_ConnectionNntp.pas,v 1.4 2002/11/02 14:05:37 owns Exp $
* Represents an Nntp connection
* An Nntp connection is composed from several messages
* You can naviguate through the messages with nextMessage
*
* TConnectionNntp is easy to use :
* - create(p_Data,p_Size,p_NumConnection,p_IPSourceAddr, p_SourcePort, p_IPDestAddr, p_DestPort, p_Damaged);
* - saveMessages
* - free
*)
unit u_ConnectionNntp;
interface
uses sysutils,classes,
u_IPPacket, u_Statistics,u_Filter,u_Mimetypes,u_FileStreamCapture;
// cf RFC0977
type
TConnectionNntp = class
private
FData : PChar; // data (TCP stream) for this connection
FSize : Integer; // size of FData
FPosition : Integer;
FIPSource : IP_ADDR;
FSourcePort : Word;
FIPDest : IP_ADDR;
FDestPort : Word;
FNumConnection : LongInt;
FDamaged : Boolean;
FResponseTextBody : PChar;
FResponseTextBodyLength : Integer;
FResponse : String;
FStatusCode : Integer;
FHeadBody : PChar;
FHead : PChar;
FBody : PChar;
FHeadBodyLength : Integer;
FHeadLength : Integer;
FBodyLength : Integer;
function readLine : String;
function getStatusCode(p_Line : String) : Integer;
procedure readResponseTextBody;
function nextResponse : String;
public
constructor create(p_Data : PChar; p_Size : LongInt;p_NumConnection : LongInt;
p_IPSourceAddr : PIP_ADDR; p_SourcePort : Word;
p_IPDestAddr : PIP_ADDR; p_DestPort : Word; p_Damaged : Boolean);
procedure saveMessages;
function firstMessage : boolean;
function nextMessage : boolean;
property IPSource : IP_ADDR read FIPSource;
property SourcePort : Word read FSourcePort;
property IPDest : IP_ADDR read FIPDest;
property DestPort : Word read FDestPort;
property Head : PChar read FHead;
property Body : PChar read FBody;
property HeadBody : Pchar read FHeadBody;
property HeadLength : Integer read FHeadLength;
property BodyLength : Integer read FBodyLength;
property HeadBodyLength : Integer read FHeadBodyLength;
end;
implementation
// read a line
function TConnectionNntp.readLine : String;
begin
result := '';
while (FData[FPosition] <> #13) do
begin
result := result + FData[FPosition];
Inc(FPosition);
if (FPosition = FSize) then exit;
end;
Inc(FPosition,2); // for #13 #10 (CRLF)
end;
// return the status code of the "status response line"
// returns 0 (this code does not exist for NNTP) if p_Line is not a "status response line"
function TConnectionNntp.getStatusCode(p_Line : String) : Integer;
var
l_StatusCodeString : String;
begin
if (Length(p_Line) >= 3) then
begin
l_StatusCodeString := p_Line[1]+p_Line[2]+p_Line[3];
result := StrToIntDef(l_StatusCodeString,0);
end else
result := 0;
end;
// read "text" from a "text response"
// remark : if the text contained a period as the first character of the text
// line in the original, that first period is doubled.
// So we should replace a '..' by a '.' but we don't do that for now
procedure TConnectionNntp.readResponseTextBody;
var
l_PositionTextBody : Integer; // position du d閎ut du body
l_Line : String;
l_PositionLine : Integer;
begin
FResponseTextBody := @(FData[FPosition]);
FResponseTextBodyLength := 0;
l_PositionTextBody := FPosition;
while (FPosition < FSize) do
begin
l_PositionLine := FPosition;
l_Line := readLine;
if (l_Line = '.') then
begin
FResponseTextBodyLength := l_PositionLine-l_PositionTextBody; // on n'a pas besoin du '.'
exit;
end;
end;
end;
// return the next response
// response which are interesting are those which begin with 220, 221 and 222
function TConnectionNntp.nextResponse : String;
var
l_Line : String;
begin
FResponse := ''; // texte de la r閜onse
FStatusCode := 0; FResponseTextBody := nil; FResponseTextBodyLength := 0;
while (FPosition < FSize) do
begin
l_Line := readLine;
FStatusCode := getStatusCode(l_Line);
if (FStatusCode <> 0) then
begin
FResponse := l_Line;
result := FResponse;
readResponseTextBody;
exit;
end;
end;
result := '';
end;
// go to the first message
// return false if there is no messages
function TConnectionNntp.firstMessage : boolean;
begin
FPosition := 0;
result := nextMessage;
end;
// go to the next message
// the message is in FHeadBody or separated in two in FHead and FBody
// returns false if there is no more message
function TConnectionNntp.nextMessage : boolean;
begin
FHeadBody := nil; FHeadBodyLength := 0;
FHead := nil; FHeadLength := 0;
FBody := nil; FBodyLength := 0;
nextResponse;
while (FResponse <> '') do
begin
if (FStatusCode = 220) then
begin
FHeadBody := FResponseTextBody;
FHeadBodyLength := FResponseTextBodyLength;
result := true;
exit;
end;
if (FStatusCode = 221) then
begin
FHead := FResponseTextBody;
FHeadLength := FResponseTextBodyLength;
end;
if (FStatusCode = 222) then
begin
FBody := FResponseTextBody;
FBodyLength := FResponseTextBodyLength;
end;
if (FHead <> nil) and (Fbody <> nil) then
begin
result := true;
exit;
end;
nextResponse;
end;
// pour 関iter que l'un seulement des deux soit <> nil
FHead := nil; FHeadLength := 0;
FBody := nil; FBodyLength := 0;
result := false;
end;
// save all the messages
procedure TConnectionNntp.saveMessages;
var
l_NumMessage : Integer;
l_UniqueId : String;
l_FileStream : TFileStreamCapture;
l_FilePath : String;
l_HasMessage : Boolean;
l_MimeType : TMimeType;
begin
try
l_HasMessage := firstMessage; l_NumMessage := 0;
l_MimeType := TMimeType.create('internal/rfc822-news');
while (l_HasMessage) do
begin
l_UniqueId := IntToStr(FNumConnection)+'-'+IntToStr(l_NumMessage);
if FDamaged then l_UniqueId := l_UniqueId + ' DAMAGED ';
l_FilePath := g_Filter.getFilePath(
l_UniqueId,
l_MimeType,
@(IPSource[0]),SourcePort,
@(IPDest[0]),DestPort);
l_FileStream := TFileStreamCapture.create(l_FilePath);
if (HeadBody <> nil) then
begin
l_FileStream.write(HeadBody^,HeadBodyLength);
end
else
begin
l_FileStream.write(Head^,HeadLength);
l_FileStream.write(Body^,BodyLength);
end;
l_FileStream.free;
Inc(l_NumMessage);
l_HasMessage := nextMessage;
end;
l_MimeType.free;
except
end;
end;
constructor TConnectionNntp.create(p_Data : PChar; p_Size : LongInt;p_NumConnection : LongInt;
p_IPSourceAddr : PIP_ADDR; p_SourcePort : Word;
p_IPDestAddr : PIP_ADDR; p_DestPort : Word; p_Damaged : Boolean);
var
i : Integer;
begin
FDestPort := p_DestPort;
FSourcePort := p_SourcePort;
for i := 0 to 3 do
begin
FIPDest[i] := p_IPDestAddr[i];
FIPSource[i] := p_IPSourceAddr[i];
end;
FData := p_Data;
FSize := p_Size;
FNumConnection := p_NumConnection;
FDamaged := p_Damaged;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -