| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784 |
- {
- $Project$
- $Workfile$
- $Revision$
- $DateUTC$
- $Id$
- This file is part of the Indy (Internet Direct) project, and is offered
- under the dual-licensing agreement described on the Indy website.
- (http://www.indyproject.org/)
- Copyright:
- (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
- }
- {
- $Log$
- }
- {
- Rev 1.8 7/23/04 1:32:08 PM RLebeau
- Bug fix for TIdSyslogFacility where sfUUCP and sfClockDeamonOne were in the
- wrong order
- Rev 1.7 7/8/04 11:43:08 PM RLebeau
- Updated ReadFromBytes(c) to use new BytesToString() parameters
- Rev 1.6 2004.02.03 5:44:28 PM czhower
- Name changes
- Rev 1.5 1/31/2004 1:23:24 PM JPMugaas
- Eliminated Todo item.
- Rev 1.4 2004.01.22 3:23:36 PM czhower
- IsCharInSet
- Rev 1.3 1/21/2004 4:03:58 PM JPMugaas
- InitComponent
- Rev 1.2 10/24/2003 01:58:30 PM JPMugaas
- Attempt to port Syslog over to new code.
- Rev 1.1 2003.10.12 6:36:44 PM czhower
- Now compiles.
- Rev 1.0 11/13/2002 08:02:12 AM JPMugaas
- }
- unit IdSysLogMessage;
- {
- Copyright the Indy pit crew
- Original Author: Stephane Grobety ([email protected])
- Release history:
- 25/2/02; - Stephane Grobety
- - Moved Facility and Severity translation functions out of the class
- - Restored the "SendToHost" method
- - Changed the ASCII check tzo include only the PRI and HEADER part.
- - Now allow nul chars in message result (Special handeling should be required, though)
- 09/20/01; - J. Peter Mugaas
- Added more properties dealing with Msg parts of the SysLog Message
- 09/19/01; - J. Peter Mugaas
- restructured syslog classes
- 08/09/01: Dev started
- }
- interface
- {$i IdCompilerDefines.inc}
- uses
- Classes,
- IdGlobal, IdGlobalProtocols, IdBaseComponent;
- type
- // TIdSyslogSeverity = ID_SYSLOG_SEVERITY_EMERGENCY..ID_SYSLOG_SEVERITY_DEBUG;
- // TIdSyslogFacility = ID_SYSLOG_FACILITY_KERNEL..ID_SYSLOG_FACILITY_LOCAL7;
- TIdSyslogPRI = 0..191;
- TIdSyslogFacility = (sfKernel, { ID_SYSLOG_FACILITY_KERNEL}
- sfUserLevel, { ID_SYSLOG_FACILITY_USER }
- sfMailSystem, { ID_SYSLOG_FACILITY_MAIL }
- sfSystemDaemon, { ID_SYSLOG_FACILITY_SYS_DAEMON }
- sfSecurityOne, { ID_SYSLOG_FACILITY_SECURITY1 }
- sfSysLogInternal, { ID_SYSLOG_FACILITY_INTERNAL }
- sfLPR, {ID_SYSLOG_FACILITY_LPR}
- sfNNTP, { ID_SYSLOG_FACILITY_NNTP }
- sfUUCP, { ID_SYSLOG_FACILITY_UUCP }
- sfClockDaemonOne, { CILITY_CLOCK1 }
- sfSecurityTwo, { ID_SYSLOG_FACILITY_SECURITY2 }
- sfFTPDaemon, { ID_SYSLOG_FACILITY_FTP }
- sfNTP, { ID_SYSLOG_FACILITY_NTP }
- sfLogAudit, { ID_SYSLOG_FACILITY_AUDIT }
- sfLogAlert, { ID_SYSLOG_FACILITY_ALERT }
- sfClockDaemonTwo, { ID_SYSLOG_FACILITY_CLOCK2 }
- sfLocalUseZero, { ID_SYSLOG_FACILITY_LOCAL0 }
- sfLocalUseOne, { ID_SYSLOG_FACILITY_LOCAL1 }
- sfLocalUseTwo, { ID_SYSLOG_FACILITY_LOCAL2 }
- sfLocalUseThree, { ID_SYSLOG_FACILITY_LOCAL3 }
- sfLocalUseFour, { ID_SYSLOG_FACILITY_LOCAL4 }
- sfLocalUseFive, { ID_SYSLOG_FACILITY_LOCAL5 }
- sfLocalUseSix, { ID_SYSLOG_FACILITY_LOCAL6 }
- sfLocalUseSeven); { ID_SYSLOG_FACILITY_LOCAL7 }
- TIdSyslogSeverity = (slEmergency, {0 - emergency - system unusable}
- slAlert, {1 - action must be taken immediately }
- slCritical, { 2 - critical conditions }
- slError, {3 - error conditions }
- slWarning, {4 - warning conditions }
- slNotice, {5 - normal but signification condition }
- slInformational, {6 - informational }
- slDebug); {7 - debug-level messages }
- TIdSysLogMsgPart = class(TPersistent)
- protected
- FPIDAvailable: Boolean;
- FProcess: String;
- FPID: Integer;
- FContent: String;
- procedure SetPID(AValue: Integer);
- procedure SetProcess(const AValue: String);
- function GetText: String;
- procedure SetText(const AValue: String);
- public
- procedure Assign(Source: TPersistent); override;
- published
- property Text: String read GetText write SetText;
- property PIDAvailable : Boolean read FPIDAvailable write FPIDAvailable stored false;
- property Process : String read FProcess write SetProcess stored false;
- property PID : Integer read FPID write SetPID stored false;
- property Content : String read FContent write FContent stored false;
- end;
- TIdSysLogMessage = class(TIdBaseComponent)
- protected
- FMsg : TIdSysLogMsgPart;
- FFacility: TidSyslogFacility;
- FSeverity: TIdSyslogSeverity;
- FHostname: string;
- FMessage: String;
- FTimeStamp: TDateTime;
- FRawMessage: String;
- FPeer: String;
- FPri: TIdSyslogPRI;
- FUDPCliComp: TIdBaseComponent;
- procedure SetFacility(const AValue: TidSyslogFacility);
- procedure SetSeverity(const AValue: TIdSyslogSeverity);
- procedure SetHostname(const AValue: string);
- procedure SetRawMessage(const Value: string);
- procedure SetTimeStamp(const AValue: TDateTime);
- procedure SetMsg(const AValue : TIdSysLogMsgPart);
- procedure SetPri(const Value: TIdSyslogPRI);
- function GetHeader: String;
- procedure CheckASCIIRange(var Data: String); virtual;
- procedure ReadPRI(var StartPos: Integer); virtual;
- procedure ReadHeader(var StartPos: Integer); virtual;
- procedure ReadMSG(var StartPos: Integer); virtual;
- procedure Parse; virtual;
- procedure UpdatePRI; virtual;
- function DecodeTimeStamp(TimeStampString: String): TDateTime; virtual;
- procedure InitComponent; override;
- public
- procedure Assign(Source: TPersistent); override;
- destructor Destroy; override;
- function EncodeMessage: String; virtual;
- procedure ReadFromBytes(const ASrc: TIdBytes; const APeer : String); virtual;
- //
- property RawMessage: string read FRawMessage write SetRawMessage;
- procedure SendToHost(const Dest: String);
- property Peer: string read FPeer write FPeer;
- property TimeStamp: TDateTime read FTimeStamp write SetTimeStamp;
- published
- property Pri: TIdSyslogPRI read FPri write SetPri default 13;
- property Facility: TidSyslogFacility read FFacility write SetFacility stored false;
- property Severity: TIdSyslogSeverity read FSeverity write SetSeverity stored false;
- property Hostname: string read FHostname write SetHostname stored false;
- property Msg : TIdSysLogMsgPart read FMsg write SetMsg;
- end; // class
- function FacilityToString(AFac: TIdSyslogFacility): string;
- function SeverityToString(ASec: TIdsyslogSeverity): string;
- function NoToSeverity(ASev : Word) : TIdSyslogSeverity;
- function logSeverityToNo(ASev : TIdSyslogSeverity) : Word;
- function NoToFacility(AFac : Word) : TIdSyslogFacility;
- function logFacilityToNo(AFac : TIdSyslogFacility) : Word;
- implementation
- uses
- IdAssignedNumbers, IdException, IdExceptionCore, IdResourceStringsProtocols, IdStack, IdUDPClient, SysUtils;
- const
- // facility
- ID_SYSLOG_FACILITY_KERNEL = 0; // kernel messages
- ID_SYSLOG_FACILITY_USER = 1; // user-level messages
- ID_SYSLOG_FACILITY_MAIL = 2; // mail system
- ID_SYSLOG_FACILITY_SYS_DAEMON = 3; // system daemons
- ID_SYSLOG_FACILITY_SECURITY1 = 4; // security/authorization messages (1)
- ID_SYSLOG_FACILITY_INTERNAL = 5; // messages generated internally by syslogd
- ID_SYSLOG_FACILITY_LPR = 6; // line printer subsystem
- ID_SYSLOG_FACILITY_NNTP = 7; // network news subsystem
- ID_SYSLOG_FACILITY_UUCP = 8; // UUCP subsystem
- ID_SYSLOG_FACILITY_CLOCK1 = 9; // clock daemon (1)
- ID_SYSLOG_FACILITY_SECURITY2 = 10; // security/authorization messages (2)
- ID_SYSLOG_FACILITY_FTP = 11; // FTP daemon
- ID_SYSLOG_FACILITY_NTP = 12; // NTP subsystem
- ID_SYSLOG_FACILITY_AUDIT = 13; // log audit
- ID_SYSLOG_FACILITY_ALERT = 14; // log alert
- ID_SYSLOG_FACILITY_CLOCK2 = 15; // clock daemon (2)
- ID_SYSLOG_FACILITY_LOCAL0 = 16; // local use 0 (local0)
- ID_SYSLOG_FACILITY_LOCAL1 = 17; // local use 1 (local1)
- ID_SYSLOG_FACILITY_LOCAL2 = 18; // local use 2 (local2)
- ID_SYSLOG_FACILITY_LOCAL3 = 19; // local use 3 (local3)
- ID_SYSLOG_FACILITY_LOCAL4 = 20; // local use 4 (local4)
- ID_SYSLOG_FACILITY_LOCAL5 = 21; // local use 5 (local5)
- ID_SYSLOG_FACILITY_LOCAL6 = 22; // local use 6 (local6)
- ID_SYSLOG_FACILITY_LOCAL7 = 23; // local use 7 (local7)
- // Severity
- ID_SYSLOG_SEVERITY_EMERGENCY = 0; // Emergency: system is unusable
- ID_SYSLOG_SEVERITY_ALERT = 1; // Alert: action must be taken immediately
- ID_SYSLOG_SEVERITY_CRITICAL = 2; // Critical: critical conditions
- ID_SYSLOG_SEVERITY_ERROR = 3; // Error: error conditions
- ID_SYSLOG_SEVERITY_WARNING = 4; // Warning: warning conditions
- ID_SYSLOG_SEVERITY_NOTICE = 5; // Notice: normal but significant condition
- ID_SYSLOG_SEVERITY_INFORMATIONAL = 6; // Informational: informational messages
- ID_SYSLOG_SEVERITY_DEBUG = 7; // Debug: debug-level messages
- function logFacilityToNo(AFac : TIdSyslogFacility) : Word;
- begin
- case AFac of
- sfKernel : Result := ID_SYSLOG_FACILITY_KERNEL;
- sfUserLevel : Result := ID_SYSLOG_FACILITY_USER;
- sfMailSystem : Result := ID_SYSLOG_FACILITY_MAIL;
- sfSystemDaemon : Result := ID_SYSLOG_FACILITY_SYS_DAEMON;
- sfSecurityOne : Result := ID_SYSLOG_FACILITY_SECURITY1;
- sfSysLogInternal : Result := ID_SYSLOG_FACILITY_INTERNAL;
- sfLPR : Result := ID_SYSLOG_FACILITY_LPR;
- sfNNTP : Result := ID_SYSLOG_FACILITY_NNTP;
- sfClockDaemonOne : Result := ID_SYSLOG_FACILITY_CLOCK1;
- sfUUCP : Result := ID_SYSLOG_FACILITY_UUCP;
- sfSecurityTwo : Result := ID_SYSLOG_FACILITY_SECURITY2;
- sfFTPDaemon : Result := ID_SYSLOG_FACILITY_FTP;
- sfNTP : Result := ID_SYSLOG_FACILITY_NTP;
- sfLogAudit : Result := ID_SYSLOG_FACILITY_AUDIT;
- sfLogAlert : Result := ID_SYSLOG_FACILITY_ALERT;
- sfClockDaemonTwo : Result := ID_SYSLOG_FACILITY_CLOCK2;
- sfLocalUseZero : Result := ID_SYSLOG_FACILITY_LOCAL0;
- sfLocalUseOne : Result := ID_SYSLOG_FACILITY_LOCAL1;
- sfLocalUseTwo : Result := ID_SYSLOG_FACILITY_LOCAL2;
- sfLocalUseThree : Result := ID_SYSLOG_FACILITY_LOCAL3;
- sfLocalUseFour : Result := ID_SYSLOG_FACILITY_LOCAL4;
- sfLocalUseFive : Result := ID_SYSLOG_FACILITY_LOCAL5;
- sfLocalUseSix : Result := ID_SYSLOG_FACILITY_LOCAL6;
- sfLocalUseSeven : Result := ID_SYSLOG_FACILITY_LOCAL7;
- else
- Result := ID_SYSLOG_FACILITY_LOCAL7;
- end;
- end;
- function NoToFacility(AFac : Word) : TIdSyslogFacility;
- begin
- case AFac of
- ID_SYSLOG_FACILITY_KERNEL : Result := sfKernel;
- ID_SYSLOG_FACILITY_USER : Result := sfUserLevel;
- ID_SYSLOG_FACILITY_MAIL : Result := sfMailSystem;
- ID_SYSLOG_FACILITY_SYS_DAEMON : Result := sfSystemDaemon;
- ID_SYSLOG_FACILITY_SECURITY1 : Result := sfSecurityOne;
- ID_SYSLOG_FACILITY_INTERNAL : Result := sfSysLogInternal;
- ID_SYSLOG_FACILITY_LPR : Result := sfLPR;
- ID_SYSLOG_FACILITY_NNTP : Result := sfNNTP;
- ID_SYSLOG_FACILITY_CLOCK1 : Result := sfClockDaemonOne;
- ID_SYSLOG_FACILITY_UUCP : Result := sfUUCP;
- ID_SYSLOG_FACILITY_SECURITY2 : Result := sfSecurityTwo;
- ID_SYSLOG_FACILITY_FTP : Result := sfFTPDaemon;
- ID_SYSLOG_FACILITY_NTP : Result := sfNTP;
- ID_SYSLOG_FACILITY_AUDIT : Result := sfLogAudit;
- ID_SYSLOG_FACILITY_ALERT : Result := sfLogAlert;
- ID_SYSLOG_FACILITY_CLOCK2 : Result := sfClockDaemonTwo;
- ID_SYSLOG_FACILITY_LOCAL0 : Result := sfLocalUseZero;
- ID_SYSLOG_FACILITY_LOCAL1 : Result := sfLocalUseOne;
- ID_SYSLOG_FACILITY_LOCAL2 : Result := sfLocalUseTwo;
- ID_SYSLOG_FACILITY_LOCAL3 : Result := sfLocalUseThree;
- ID_SYSLOG_FACILITY_LOCAL4 : Result := sfLocalUseFour;
- ID_SYSLOG_FACILITY_LOCAL5 : Result := sfLocalUseFive;
- ID_SYSLOG_FACILITY_LOCAL6 : Result := sfLocalUseSix;
- ID_SYSLOG_FACILITY_LOCAL7 : Result := sfLocalUseSeven;
- else
- Result := sfLocalUseSeven;
- end;
- end;
- function logSeverityToNo(ASev : TIdSyslogSeverity) : Word;
- begin
- case ASev of
- slEmergency : Result := ID_SYSLOG_SEVERITY_EMERGENCY;
- slAlert : Result := ID_SYSLOG_SEVERITY_ALERT;
- slCritical : Result := ID_SYSLOG_SEVERITY_CRITICAL;
- slError : Result := ID_SYSLOG_SEVERITY_ERROR;
- slWarning : Result := ID_SYSLOG_SEVERITY_WARNING;
- slNotice : Result := ID_SYSLOG_SEVERITY_NOTICE;
- slInformational : Result := ID_SYSLOG_SEVERITY_INFORMATIONAL;
- slDebug : Result := ID_SYSLOG_SEVERITY_DEBUG;
- else
- Result := ID_SYSLOG_SEVERITY_DEBUG;
- end;
- end;
- function NoToSeverity(ASev : Word) : TIdSyslogSeverity;
- begin
- case ASev of
- ID_SYSLOG_SEVERITY_EMERGENCY : Result := slEmergency;
- ID_SYSLOG_SEVERITY_ALERT : Result := slAlert;
- ID_SYSLOG_SEVERITY_CRITICAL : Result := slCritical;
- ID_SYSLOG_SEVERITY_ERROR : Result := slError;
- ID_SYSLOG_SEVERITY_WARNING : Result := slWarning;
- ID_SYSLOG_SEVERITY_NOTICE : Result := slNotice;
- ID_SYSLOG_SEVERITY_INFORMATIONAL : Result := slInformational;
- ID_SYSLOG_SEVERITY_DEBUG : Result := slDebug;
- else
- Result := slDebug;
- end;
- end;
- function SeverityToString(ASec: TIdsyslogSeverity): string;
- begin
- case ASec of
- slEmergency: Result := STR_SYSLOG_SEVERITY_EMERGENCY;
- slAlert: Result := STR_SYSLOG_SEVERITY_ALERT;
- slCritical: Result := STR_SYSLOG_SEVERITY_CRITICAL;
- slError: Result := STR_SYSLOG_SEVERITY_ERROR;
- slWarning: Result := STR_SYSLOG_SEVERITY_WARNING;
- slNotice: Result := STR_SYSLOG_SEVERITY_NOTICE;
- slInformational: Result := STR_SYSLOG_SEVERITY_INFORMATIONAL;
- slDebug: Result := STR_SYSLOG_SEVERITY_DEBUG;
- else
- Result := STR_SYSLOG_SEVERITY_UNKNOWN;
- end;
- end;
- function FacilityToString(AFac: TIdSyslogFacility): string;
- begin
- case AFac of
- sfKernel: Result := STR_SYSLOG_FACILITY_KERNEL;
- sfUserLevel: Result := STR_SYSLOG_FACILITY_USER;
- sfMailSystem: Result := STR_SYSLOG_FACILITY_MAIL;
- sfSystemDaemon: Result := STR_SYSLOG_FACILITY_SYS_DAEMON;
- sfSecurityOne: Result := STR_SYSLOG_FACILITY_SECURITY1;
- sfSysLogInternal: Result := STR_SYSLOG_FACILITY_INTERNAL;
- sfLPR: Result := STR_SYSLOG_FACILITY_LPR;
- sfNNTP: Result := STR_SYSLOG_FACILITY_NNTP;
- sfClockDaemonOne: Result := STR_SYSLOG_FACILITY_CLOCK1;
- sfUUCP: Result := STR_SYSLOG_FACILITY_UUCP;
- sfSecurityTwo: Result := STR_SYSLOG_FACILITY_SECURITY2;
- sfFTPDaemon: Result := STR_SYSLOG_FACILITY_FTP;
- sfNTP: Result := STR_SYSLOG_FACILITY_NTP;
- sfLogAudit: Result := STR_SYSLOG_FACILITY_AUDIT;
- sfLogAlert: Result := STR_SYSLOG_FACILITY_ALERT;
- sfClockDaemonTwo: Result := STR_SYSLOG_FACILITY_CLOCK2;
- sfLocalUseZero: Result := STR_SYSLOG_FACILITY_LOCAL0;
- sfLocalUseOne: Result := STR_SYSLOG_FACILITY_LOCAL1;
- sfLocalUseTwo: Result := STR_SYSLOG_FACILITY_LOCAL2;
- sfLocalUseThree: Result := STR_SYSLOG_FACILITY_LOCAL3;
- sfLocalUseFour: Result := STR_SYSLOG_FACILITY_LOCAL4;
- sfLocalUseFive: Result := STR_SYSLOG_FACILITY_LOCAL5;
- sfLocalUseSix: Result := STR_SYSLOG_FACILITY_LOCAL6;
- sfLocalUseSeven: Result := STR_SYSLOG_FACILITY_LOCAL7;
- else
- Result := STR_SYSLOG_FACILITY_UNKNOWN;
- end;
- end;
- function ExtractAlphaNumericStr(var VString : String) : String;
- var
- i, len : Integer;
- begin
- len := 0;
- for i := 1 to IndyMin(Length(VString), 32) do begin
- //numbers or alphabet only
- if IsAlphaNumeric(VString[i]) then begin
- Inc(len);
- end else begin
- Break;
- end;
- end;
- Result := Copy(VString, 1, len);
- VString := Copy(VString, len+1, MaxInt);
- end;
- { TIdSysLogMessage }
- procedure TIdSysLogMessage.Assign(Source: TPersistent);
- var
- ms : TIdSysLogMessage;
- begin
- if Source is TIdSysLogMessage then begin
- ms := Source as TIdSysLogMessage;
- {Priority and facility properties are set with this so those assignments
- are not needed}
- Pri := Ms.Pri;
- HostName := ms.Hostname;
- FMsg.Assign(ms.Msg);
- TimeStamp := ms.TimeStamp;
- end else begin
- inherited Assign(Source);
- end;
- end;
- function TIdSysLogMessage.DecodeTimeStamp(TimeStampString: String): TDateTime;
- var
- AYear, AMonth, ADay, AHour, AMin, ASec: Word;
- LDate : TDateTime;
- begin
- // SG 25/2/02: Check the ASCII range
- CheckASCIIRange(TimeStampString);
- // Get the current date to get the current year
- LDate := Now;
- DecodeDate(LDate, AYear, AMonth, ADay);
- if Length(TimeStampString) <> 16 then begin
- raise EInvalidSyslogMessage.CreateFmt(RSInvalidSyslogTimeStamp, [TimeStampString]);
- end;
- // Month
- AMonth := StrToMonth(Copy(TimeStampString, 1, 3));
- if not (AMonth in [1..12]) then begin
- raise EInvalidSyslogMessage.CreateFmt(RSInvalidSyslogTimeStamp, [TimeStampString]);
- end;
- // day
- ADay := IndyStrToInt(Copy(TimeStampString, 5, 2), 0);
- if not (ADay in [1..31]) then begin
- raise EInvalidSyslogMessage.CreateFmt(RSInvalidSyslogTimeStamp, [TimeStampString]);
- end;
- // Time
- AHour := IndyStrToInt(Copy(TimeStampString, 8, 2), 0);
- if not (AHour in [0..23]) then begin
- raise EInvalidSyslogMessage.CreateFmt(RSInvalidSyslogTimeStamp, [TimeStampString]);
- end;
- AMin := IndyStrToInt(Copy(TimeStampString, 11, 2), 0);
- if not (AMin in [0..59]) then begin
- raise EInvalidSyslogMessage.CreateFmt(RSInvalidSyslogTimeStamp, [TimeStampString]);
- end;
- ASec := IndyStrToInt(Copy(TimeStampString, 14, 2), 0);
- if not (ASec in [0..59]) then begin
- raise EInvalidSyslogMessage.CreateFmt(RSInvalidSyslogTimeStamp, [TimeStampString]);
- end;
- if TimeStampString[16] <> ' ' then begin {Do not Localize}
- Raise EInvalidSyslogMessage.CreateFmt(RSInvalidSyslogTimeStamp, [TimeStampString]);
- end;
- Result := EncodeDate(AYear, AMonth, ADay) + EncodeTime(AHour, AMin, ASec, 0);
- end;
- procedure TIdSysLogMessage.ReadFromBytes(const ASrc: TIdBytes; const APeer : String);
- const
- MSGLEN = 1024;
- begin
- FPeer := APeer;
- RawMessage := BytesToString(ASrc, 0, MSGLEN);
- end;
- procedure TIdSysLogMessage.Parse;
- var
- APos: Integer;
- begin
- APos := 1;
- ReadPRI(APos);
- ReadHeader(APos);
- ReadMSG(APos);
- end;
- procedure TIdSysLogMessage.ReadHeader(var StartPos: Integer);
- var
- AHostNameEnd: Integer;
- begin
- // DateTimeToInternetStr and StrInternetToDateTime
- // Time stamp string is 15 char long
- try
- FTimeStamp := DecodeTimeStamp(Copy(FRawMessage, StartPos, 16));
- Inc(StartPos, 16);
- // HostName
- AHostNameEnd := StartPos;
- while (AHostNameEnd < Length(FRawMessage)) and (FRawMessage[AHostNameEnd] <> ' ') do begin {Do not Localize}
- Inc(AHostNameEnd);
- end; // while
- FHostname := Copy(FRawMessage, StartPos, AHostNameEnd - StartPos);
- if Pos(':', FHostname) <> 0 then begin // check if the hostname doesn't contain a semicolon (so it's not a process)
- FHostname := Peer;
- end else begin
- StartPos := AHostNameEnd + 1;
- end;
- // SG 25/2/02: Check the ASCII range of host name
- CheckASCIIRange(FHostname);
- except
- on e: Exception do
- begin
- FTimeStamp := Now;
- FHostname := FPeer;
- end;
- end;
- end;
- procedure TIdSysLogMessage.ReadMSG(var StartPos: Integer);
- begin
- FMessage := Copy(FRawMessage, StartPos, Length(FRawMessage));
- Msg.Text := FMessage;
- end;
- procedure TIdSysLogMessage.ReadPRI(var StartPos: Integer);
- var
- StartPosSave: Integer;
- Buffer: string;
- begin
- StartPosSave := StartPos;
- try
- // Read the PRI string
- // PRI must start with "less than" sign
- Buffer := ''; {Do not Localize}
- if not CharEquals(FRawMessage, StartPos, '<') then begin {Do not Localize}
- raise EInvalidSyslogMessage.Create(RSInvalidSyslogPRI);
- end;
- repeat
- Inc(StartPos);
- if CharEquals(FRawMessage, StartPos, '>') then begin {Do not Localize}
- Break;
- end;
- if not IsNumeric(FRawMessage, 1, StartPos) then begin {Do not Localize}
- raise EInvalidSyslogMessage.CreateFmt(RSInvalidSyslogPRINumber, [Buffer]);
- end;
- Buffer := Buffer + FRawMessage[StartPos];
- until StartPos = StartPosSave + 5;
- // PRI must end with "greater than" sign
- if not CharEquals(FRawMessage, StartPos, '>') then begin {Do not Localize}
- raise EInvalidSyslogMessage.Create(RSInvalidSyslogPRI);
- end;
- // Convert PRI to numerical value
- Inc(StartPos);
- CheckASCIIRange(Buffer);
- PRI := IndyStrToInt(Buffer, -1);
- except
- // as per RFC, on invalid/missing PRI, use value 13
- on e: Exception do
- begin
- Pri := 13;
- // Reset the position to saved value
- StartPos := StartPosSave;
- end;
- end;
- end;
- procedure TIdSysLogMessage.UpdatePRI;
- begin
- PRI := logFacilityToNo(Facility) * 8 + logSeverityToNo(Severity);
- end;
- procedure TIdSysLogMessage.SetFacility(const AValue: TidSyslogFacility);
- begin
- if FFacility <> AValue then begin
- FFacility := AValue;
- UpdatePRI;
- end;
- end;
- procedure TIdSysLogMessage.SetHostname(const AValue: string);
- begin
- if FHostname <> AValue then begin
- if Pos(' ', AValue) <> 0 then begin {Do not Localize}
- raise EInvalidSyslogMessage.CreateFmt(RSInvalidHostName, [AValue]);
- end;
- FHostname := AValue;
- end;
- end;
- procedure TIdSysLogMessage.SetSeverity(const AValue: TIdSyslogSeverity);
- begin
- if FSeverity <> AValue then begin
- FSeverity := AValue;
- UpdatePRI;
- end;
- end;
- procedure TIdSysLogMessage.SetTimeStamp(const AValue: TDateTime);
- begin
- FTimeStamp := AValue;
- end;
- function TIdSysLogMessage.GetHeader: String;
- var
- AYear, AMonth, ADay, AHour, AMin, ASec, AMSec: Word;
- function YearOf(ADate : TDateTime) : Word;
- var
- mm, dd : Word;
- begin
- DecodeDate(ADate, Result, mm, dd);
- end;
- Function DayToStr(day: Word): String;
- begin
- if Day < 10 then begin
- Result := ' ' + IntToStr(day); {Do not Localize}
- end else begin
- Result := IntToStr(day);
- end;
- end;
- begin
- // if the year of the message is not the current year, the timestamp is
- // invalid -> Create a new timestamp with the current date/time
- if YearOf(Now) <> YearOf(TimeStamp) then
- begin
- TimeStamp := Now;
- end;
- DecodeDate(TimeStamp, AYear, AMonth, ADay);
- DecodeTime(TimeStamp, AHour, AMin, ASec, AMSec);
- Result := IndyFormat('%s %s %.2d:%.2d:%.2d %s', [monthnames[AMonth], DayToStr(ADay), AHour, AMin, ASec, Hostname]); {Do not Localize}
- end;
- function TIdSysLogMessage.EncodeMessage: String;
- begin
- // Create a syslog message string
- // PRI
- Result := IndyFormat('<%d>%s %s', [PRI, GetHeader, FMsg.Text]); {Do not Localize}
- // If the message is too long, tuncate it
- if Length(result) > 1024 then
- begin
- result := Copy(result, 1, 1024);
- end;
- end;
- procedure TIdSysLogMessage.SetPri(const Value: TIdSyslogPRI);
- begin
- if FPri <> Value then begin
- if not (Value in [0..191]) then begin
- raise EInvalidSyslogMessage.CreateFmt(RSInvalidSyslogPRINumber, [IntToStr(value)]);
- end;
- FPri := Value;
- FFacility := NoToFacility(Value div 8);
- FSeverity := NoToSeverity(Value mod 8);
- end;
- end;
- procedure TIdSysLogMessage.InitComponent;
- begin
- inherited;
- PRI := 13; //default
- {This stuff is necessary to prevent an AV in the IDE if GStack does not exist}
- // RLebeau: should we really be doing this here? At the least, maybe detect
- // DFM streaming and don't do this if it will just be overriden afterwards...
- TIdStack.IncUsage;
- try
- Hostname := GStack.HostName;
- finally
- TIdStack.DecUsage;
- end;
- FMsg := TIdSysLogMsgPart.Create;
- end;
- procedure TIdSysLogMessage.CheckASCIIRange(var Data: String);
- var
- i: Integer;
- ValidChars : String;
- {$IFDEF STRING_IS_IMMUTABLE}
- LSB: TIdStringBuilder;
- {$ENDIF}
- begin
- ValidChars := CharRange(#0, #127);
- {$IFDEF STRING_IS_IMMUTABLE}
- LSB := TIdStringBuilder.Create(Data);
- for i := 0 to LSB.Length-1 do // Iterate
- begin
- if not CharIsInSet(LSB, i, ValidChars) then begin
- LSB[i] := '?'; {Do not Localize}
- end;
- end; // for
- Data := LSB.ToString;
- {$ELSE}
- for i := 1 to Length(Data) do // Iterate
- begin
- if not CharIsInSet(Data, i, ValidChars) then begin
- Data[i] := '?'; {Do not Localize}
- end;
- end; // for
- {$ENDIF}
- end;
- destructor TIdSysLogMessage.Destroy;
- begin
- FreeAndNil(FMsg);
- inherited Destroy;
- end;
- procedure TIdSysLogMessage.SetMsg(const AValue: TIdSysLogMsgPart);
- begin
- FMsg.Assign(AValue);
- end;
- procedure TIdSysLogMessage.SetRawMessage(const Value: string);
- begin
- FRawMessage := Value;
- // check that message contains only valid ASCII chars.
- // Replace Invalid entries by "?"
- // SG 25/2/02: Moved to header decoding
- Parse;
- end;
- procedure TIdSysLogMessage.SendToHost(const Dest: String);
- var
- LEncoding: IIdTextEncoding;
- begin
- if not Assigned(FUDPCliComp) then begin
- FUDPCliComp := TIdUDPClient.Create(Self);
- end;
- LEncoding := IndyTextEncoding_8Bit;
- (FUDPCliComp as TIdUDPClient).Send(Dest, IdPORT_syslog, EncodeMessage, LEncoding{$IFDEF STRING_IS_ANSI}, LEncoding{$ENDIF});
- end;
- { TIdSysLogMsgPart }
- procedure TIdSysLogMsgPart.Assign(Source: TPersistent);
- begin
- if Source is TIdSysLogMsgPart then begin
- {This sets about everything here}
- Text := (Source as TIdSysLogMsgPart).Text;
- end else begin
- inherited Assign(Source);
- end;
- end;
- procedure TIdSysLogMsgPart.SetPID(AValue: Integer);
- begin
- FPID := AValue;
- FPIDAvailable := FPID <> -1;
- end;
- procedure TIdSysLogMsgPart.SetProcess(const AValue: String);
- var
- LTmp: String;
- begin
- //we have to ensure that the TAG field will never be greater than 32 characters
- //and the program name must contain alphanumeric characters
- LTmp := AValue;
- FProcess := ExtractAlphaNumericStr(LTmp);
- end;
- function TIdSysLogMsgPart.GetText: String;
- begin
- Result := Process;
- if FPIDAvailable then begin
- Result := Result + IndyFormat('[%d]', [FPID]); {Do not Localize}
- end;
- Result := Result + ': ' + Content; {Do not Localize}
- if Result = ': ' then begin {Do not Localize}
- Result := '';
- end;
- end;
- procedure TIdSysLogMsgPart.SetText(const AValue: String);
- var
- SBuf: String;
- begin
- FProcess := ''; {Do not Localize}
- FPID := -1;
- FPIDAvailable := False;
- FContent := ''; {Do not Localize}
- SBuf := AValue;
- FProcess := ExtractAlphaNumericStr(SBuf);
- if TextStartsWith(SBuf, '[') then begin {Do not Localize}
- SBuf := Copy(SBuf, 2, MaxInt);
- FPID := IndyStrToInt(Fetch(SBuf, ']'), -1); {Do not Localize}
- FPIDAvailable := FPID <> -1;
- end;
- if TextStartsWith(SBuf, ': ') then begin {Do not Localize}
- SBuf := Copy(SBuf, 3, MaxInt);
- end
- else if TextStartsWith(SBuf, ':') or TextStartsWith(SBuf, ' ') then begin {Do not Localize}
- SBuf := Copy(SBuf, 2, MaxInt);
- end;
- FContent := SBuf;
- end;
- end.
|