diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..922b314
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*.o
+*.ppu
+*~
diff --git a/Logger.HandlerInterface.pp b/Logger.HandlerInterface.pp
new file mode 100644
index 0000000..a23e66d
--- /dev/null
+++ b/Logger.HandlerInterface.pp
@@ -0,0 +1,56 @@
+{*******************************************************}
+
+{ Renegade BBS }
+
+{ Copyright (c) 1990-2013 The Renegade Dev Team }
+{ Copyleft (ↄ) 2016-2017 Renegade BBS }
+
+{ This file is part of Renegade BBS }
+
+{ Renegade 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 3 of the License, or }
+{ (at your option) any later version. }
+
+{ Renegade 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 Renegade. If not, see }
+{ . }
+
+{*******************************************************}
+{ _______ __ }
+{ | _ .-----.-----.-----.-----.---.-.--| .-----. }
+{ |. l | -__| | -__| _ | _ | _ | -__| }
+{ |. _ |_____|__|__|_____|___ |___._|_____|_____| }
+{ |: | | |_____| }
+{ |::.|:. | }
+{ `--- ---' }
+{*******************************************************}
+{$mode objfpc}
+{$interfaces corba}
+{$codepage utf8}
+{$h+}
+unit Logger.HandlerInterface;
+
+interface
+
+uses
+ Classes;
+
+type
+ LoggingHandlerInterface = interface
+ ['{C6E95830-5B13-4A51-BC03-757A3A1C779F}']
+ function Open(Identifier: UTF8String): boolean;
+ function Close(): boolean;
+ function Write(const LogData: UTF8String): boolean;
+ end;
+
+implementation
+
+end.
diff --git a/Logger.LoggerInterface.pp b/Logger.LoggerInterface.pp
new file mode 100644
index 0000000..e9605a3
--- /dev/null
+++ b/Logger.LoggerInterface.pp
@@ -0,0 +1,81 @@
+{*******************************************************}
+
+{ Renegade BBS }
+
+{ Copyright (c) 1990-2013 The Renegade Dev Team }
+{ Copyleft (ↄ) 2016-2017 Renegade BBS }
+
+{ This file is part of Renegade BBS }
+
+{ Renegade 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 3 of the License, or }
+{ (at your option) any later version. }
+
+{ Renegade 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 Renegade. If not, see }
+{ . }
+
+{*******************************************************}
+{ _______ __ }
+{ | _ .-----.-----.-----.-----.---.-.--| .-----. }
+{ |. l | -__| | -__| _ | _ | _ | -__| }
+{ |. _ |_____|__|__|_____|___ |___._|_____|_____| }
+{ |: | | |_____| }
+{ |::.|:. | }
+{ `--- ---' }
+{*******************************************************}
+{$mode objfpc}
+{$interfaces corba}
+{$codepage utf8}
+{$h+}
+{ namespace Renegade.Logger }
+unit Logger.LoggerInterface;
+
+interface
+
+uses
+ Classes,
+ Logger.HandlerInterface;
+
+type
+ LogLevels = (
+ LOG_EMERG,
+ LOG_ALERT,
+ LOG_CRIT,
+ LOG_ERR,
+ LOG_WARNING,
+ LOG_NOTICE,
+ LOG_INFO,
+ LOG_DEBUG);
+
+const
+ LOG_PRIMASK = $07; // Internal Unix Use;
+
+type
+ LoggerInterface = interface
+ ['{3220524c-fae0-11e6-8b70-9c5c8e742ab6}']
+ procedure SetHandler(Handler: LoggingHandlerInterface);
+ procedure Emergency(Message: UTF8String; Context: array of const);
+ procedure Alert(Message: UTF8String; Context: array of const);
+ procedure Critical(Message: UTF8String; Context: array of const);
+ procedure Error(Message: UTF8String; Context: array of const);
+ procedure Warning(Message: UTF8String; Context: array of const);
+ procedure Notice(Message: UTF8String; Context: array of const);
+ procedure Info(Message: UTF8String; Context: array of const);
+ procedure Debug(Message: UTF8String; Context: array of const);
+ procedure Log(LogLevel: LogLevels; Message: UTF8String;
+ Context: array of const);
+ property LoggingHandler: LoggingHandlerInterface write SetHandler;
+ end;
+
+implementation
+
+end.
diff --git a/Logger.LoggerTrait.pp b/Logger.LoggerTrait.pp
new file mode 100644
index 0000000..00238a4
--- /dev/null
+++ b/Logger.LoggerTrait.pp
@@ -0,0 +1,148 @@
+{*******************************************************}
+{ }
+{ Renegade BBS }
+{ }
+{ Copyright (c) 1990-2013 The Renegade Dev Team }
+{ Copyleft (ↄ) 2016-2017 Renegade BBS }
+{ }
+{ This file is part of Renegade BBS }
+{ }
+{ Renegade 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 3 of the License, or }
+{ (at your option) any later version. }
+{ }
+{ Renegade 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 Renegade. If not, see }
+{ . }
+{ }
+{*******************************************************}
+{ _______ __ }
+{ | _ .-----.-----.-----.-----.---.-.--| .-----. }
+{ |. l | -__| | -__| _ | _ | _ | -__| }
+{ |. _ |_____|__|__|_____|___ |___._|_____|_____| }
+{ |: | | |_____| }
+{ |::.|:. | }
+{ `--- ---' }
+{*******************************************************}
+{$mode objfpc}
+{$codepage utf8}
+{$h+}
+{ namespace Renegade.Logger }
+Unit Logger.LoggerTrait;
+
+interface
+
+uses
+ Classes,
+ SysUtils,
+ Math,
+ Logger.LoggerInterface,
+ Logger.HandlerInterface,
+ Logger.SysLogHandler;
+
+Type LoggerTrait = class(TObject, LoggerInterface)
+ Private
+ FLoggingHandler : LoggingHandlerInterface;
+ procedure SetHandler( LoggingHandler : LoggingHandlerInterface );
+ Public
+ constructor Create(LoggingHandler : LoggingHandlerInterface);
+ destructor Destroy; override;
+ procedure Emergency(Message : UTF8String; Context : array of const);
+ procedure Alert(Message : UTF8String; Context : array of const);
+ procedure Critical(Message : UTF8String; Context : array of const);
+ procedure Error(Message : UTF8String; Context : array of const);
+ procedure Warning(Message : UTF8String; Context : array of const);
+ procedure Notice(Message : UTF8String; Context : array of const);
+ procedure Info(Message : UTF8String; Context : array of const);
+ procedure Debug(Message : UTF8String; Context : array of const);
+ function ConvertLogErrorToString(LogLevel : LogLevels) : AnsiString;
+ procedure Log(LogLevel : LogLevels; Message :UTF8String; Context : array of const);virtual;
+ Published
+ property LoggingHandler : LoggingHandlerInterface read FLoggingHandler write SetHandler;
+end;
+
+
+implementation
+function LoggerTrait.ConvertLogErrorToString(LogLevel : LogLevels) : AnsiString;
+begin
+ Case LogLevel of
+ LOG_EMERG : Result := 'Emergency';
+ LOG_ALERT : Result := 'Alert';
+ LOG_CRIT : Result := 'Critical';
+ LOG_ERR : Result := 'Error';
+ LOG_WARNING : Result := 'Warning';
+ LOG_NOTICE : Result := 'Notice';
+ LOG_INFO : Result := 'Info';
+ LOG_DEBUG : Result := 'Debug';
+ end;
+end;
+
+procedure LoggerTrait.SetHandler( LoggingHandler : LoggingHandlerInterface );
+begin
+ FLoggingHandler := LoggingHandler;
+end;
+
+constructor LoggerTrait.Create(LoggingHandler :LoggingHandlerInterface);
+begin
+ FLoggingHandler := LoggingHandler;
+end;
+
+destructor LoggerTrait.Destroy;
+begin
+ inherited Destroy;
+end;
+procedure LoggerTrait.Emergency(Message : UTF8String; Context : array of const);
+begin
+ Log(LOG_EMERG, Message, Context);
+end;
+
+procedure LoggerTrait.Alert(Message : UTF8String; Context : array of const);
+begin
+ Log(LOG_ALERT, Message, Context);
+end;
+procedure LoggerTrait.Critical(Message : UTF8String; Context : array of const);
+begin
+ Log(LOG_CRIT, Message, Context);
+end;
+procedure LoggerTrait.Error(Message : UTF8String; Context : array of const);
+begin
+ Log(LOG_ERR, Message, Context);
+end;
+procedure LoggerTrait.Warning(Message : UTF8String; Context : array of const);
+begin
+ Log(LOG_WARNING, Message, Context);
+end;
+
+procedure LoggerTrait.Notice(Message : UTF8String; Context : array of const);
+begin
+ Log(LOG_NOTICE, Message, Context);
+end;
+
+procedure LoggerTrait.Info(Message : UTF8String; Context : array of const);
+begin
+ Log(LOG_INFO, Message, Context);
+end;
+
+procedure LoggerTrait.Debug(Message : UTF8String; Context : array of const);
+begin
+ Log(LOG_DEBUG, Message, Context);
+end;
+procedure LoggerTrait.Log(LogLevel : LogLevels; Message :UTF8String; Context : array of const);
+begin
+
+ raise Exception.Create(
+ Format(#10#13' You need override the LoggerInterface.Log method in your class.'#10#13 +
+ ' Implemented class was %s.%s.'#10#13,
+ [self.UnitName, self.ClassName])) at
+ get_caller_addr(get_frame),
+ get_caller_frame(get_frame);
+end;
+end.
diff --git a/Logger.SysLogHandler.pp b/Logger.SysLogHandler.pp
new file mode 100644
index 0000000..a1d7b6b
--- /dev/null
+++ b/Logger.SysLogHandler.pp
@@ -0,0 +1,129 @@
+{*******************************************************}
+
+{ Renegade BBS }
+
+{ Copyright (c) 1990-2013 The Renegade Dev Team }
+{ Copyleft (ↄ) 2016-2017 Renegade BBS }
+
+{ This file is part of Renegade BBS }
+
+{ Renegade 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 3 of the License, or }
+{ (at your option) any later version. }
+
+{ Renegade 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 Renegade. If not, see }
+{ . }
+
+{*******************************************************}
+{ _______ __ }
+{ | _ .-----.-----.-----.-----.---.-.--| .-----. }
+{ |. l | -__| | -__| _ | _ | _ | -__| }
+{ |. _ |_____|__|__|_____|___ |___._|_____|_____| }
+{ |: | | |_____| }
+{ |::.|:. | }
+{ `--- ---' }
+{*******************************************************}
+{$mode objfpc}
+{$interfaces corba}
+{$linklib c}
+{$codepage utf8}
+{$h+}
+
+unit Logger.SysLogHandler;
+
+interface
+
+uses
+ Classes,
+ FPJson,
+ Logger.HandlerInterface;
+
+const
+ LOG_PID = $01; // log the pid with each message
+ LOG_CONS = $02; // log on the console if errors in sending
+ LOG_ODELAY = $04; // delay open until first syslog() (default)
+ LOG_NDELAY = $08; // don't delay open
+ LOG_NOWAIT = $10; // don't wait for console forks; (DEPRECATED)
+ LOG_PERROR = $20; // log to stderr as well
+
+ LOG_KERN = 0 shl 3; // kernel messages
+ LOG_USER = 1 shl 3; // random user-level messages
+ LOG_MAIL = 2 shl 3; // mail system
+ LOG_DAEMON = 3 shl 3; // system daemons
+ LOG_AUTH = 4 shl 3; // security/authorization messages
+ LOG_SYSLOG = 5 shl 3; // messages generated internally by syslogd
+ LOG_LPR = 6 shl 3; // line printer subsystem
+ LOG_NEWS = 7 shl 3; // network news subsystem
+ LOG_UUCP = 8 shl 3; // UUCP subsystem
+ LOG_CRON = 9 shl 3; // clock daemon
+ LOG_AUTHPRIV = 10 shl 3; // security/authorization messages (private)
+
+var
+ UnixFacility: longint;
+
+type
+ SysLogHandler = class(TObject, LoggingHandlerInterface)
+ private
+ FUnixFacility: longint;
+ procedure SetFacility(const UnixFacility: longint);
+ public
+ constructor Create(const LoggingFacility: longint);
+
+ function Open(Identifier: UTF8String): boolean;
+ function Close(): boolean;
+ function Write(const LogData: UTF8String): boolean;
+ published
+ property UnixFacility: longint read FUnixFacility write SetFacility;
+ end;
+
+procedure closelog; cdecl; external;
+procedure openlog(__ident: PChar; __option: longint; __facilit: longint); cdecl; external;
+function setlogmask(__mask: longint): longint; cdecl; external;
+procedure syslog(__pri: longint; __fmt: PChar; args: array of const); cdecl; external;
+
+implementation
+
+constructor SysLogHandler.Create(const LoggingFacility: longint);
+begin
+ FUnixFacility := LoggingFacility;
+end;
+
+procedure SysLogHandler.SetFacility(const UnixFacility: longint);
+begin
+ FUnixFacility := UnixFacility;
+end;
+
+function SysLogHandler.Open(Identifier: UTF8String): boolean;
+var
+ SysLogIdentifier: PAnsiChar;
+begin
+ SysLogIdentifier := PAnsiChar(Identifier);
+ openlog(SysLogIdentifier, LOG_PID xor LOG_CONS xor LOG_NDELAY, FUnixFacility);
+ Result := True;
+end;
+
+function SysLogHandler.Close(): boolean;
+begin
+ closelog;
+ Result := True;
+end;
+
+function SysLogHandler.Write(const LogData: UTF8String): boolean;
+var
+ SysLogData: PAnsiChar;
+begin
+ SysLogData := PAnsiChar(LogData);
+ syslog(FUnixFacility, SysLogData, []);
+ Result := True;
+end;
+
+end.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ce60e74
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# Renegade Logger Class
+
diff --git a/Renegade.Logger.pp b/Renegade.Logger.pp
new file mode 100644
index 0000000..283f40e
--- /dev/null
+++ b/Renegade.Logger.pp
@@ -0,0 +1,104 @@
+{*******************************************************}
+
+{ Renegade BBS }
+
+{ Copyright (c) 1990-2013 The Renegade Dev Team }
+{ Copyleft (ↄ) 2016-2017 Renegade BBS }
+
+{ This file is part of Renegade BBS }
+
+{ Renegade 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 3 of the License, or }
+{ (at your option) any later version. }
+
+{ Renegade 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 Renegade. If not, see }
+{ . }
+
+{*******************************************************}
+{ _______ __ }
+{ | _ .-----.-----.-----.-----.---.-.--| .-----. }
+{ |. l | -__| | -__| _ | _ | _ | -__| }
+{ |. _ |_____|__|__|_____|___ |___._|_____|_____| }
+{ |: | | |_____| }
+{ |::.|:. | }
+{ `--- ---' }
+{*******************************************************}
+{$mode objfpc}
+{$codepage utf8}
+{$h+}
+{ namespace Renegade.Logger }
+unit Renegade.Logger;
+
+interface
+
+uses
+ Classes,
+ SysUtils,
+ FPJson,
+ Logger.HandlerInterface,
+ Logger.LoggerInterface,
+ Logger.LoggerTrait;
+
+type
+ RTLogger = class(LoggerTrait, LoggerInterface)
+ public
+ constructor Create(Handler: LoggingHandlerInterface);
+ procedure Log(LogLevel: LogLevels; Message: UTF8String;
+ Context: array of const); override;
+ end;
+
+implementation
+
+constructor RTLogger.Create(Handler: LoggingHandlerInterface);
+begin
+ LoggingHandler := Handler;
+end;
+
+procedure RTLogger.Log(LogLevel: LogLevels; Message: UTF8String;
+ Context: array of const);
+var
+ JsonObject, JsonObjectContext: TJsonObject;
+ JsonArray: TJsonArray;
+begin
+
+ if Length(Context) <> 0 then
+ begin
+
+ try
+ JsonObjectContext := TJsonObject.Create(Context);
+ JsonObject := TJsonObject.Create();
+ JsonArray := TJsonArray.Create();
+ JsonArray.Add(JsonObjectContext);
+ JsonObject.Add('Context', JsonObjectContext);
+ JsonObject.CompressedJSON := True;
+ except
+ On e: Exception do
+ begin
+ Writeln(e.Message);
+ end;
+ end;
+ end;
+ LoggingHandler.Open('renegade');
+ if Length(Context) <> 0 then
+ begin
+ LoggingHandler.Write(Format('[%s] %s [%s]',
+ [ConvertLogErrorToString(LogLevel), Message, JsonObject.AsJSON]));
+ end
+ else
+ begin
+ LoggingHandler.Write(Format('[%s] %s',
+ [ConvertLogErrorToString(LogLevel), Message]));
+ end;
+ LoggingHandler.Close();
+end;
+
+end.
diff --git a/tests/LoggerTest.pp b/tests/LoggerTest.pp
new file mode 100644
index 0000000..d0cb1d0
--- /dev/null
+++ b/tests/LoggerTest.pp
@@ -0,0 +1,55 @@
+{*******************************************************}
+
+{ Renegade BBS }
+
+{ Copyright (c) 1990-2013 The Renegade Dev Team }
+{ Copyleft (ↄ) 2016-2017 Renegade BBS }
+
+{ This file is part of Renegade BBS }
+
+{ Renegade 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 3 of the License, or }
+{ (at your option) any later version. }
+
+{ Renegade 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 Renegade. If not, see }
+{ . }
+
+{*******************************************************}
+{ _______ __ }
+{ | _ .-----.-----.-----.-----.---.-.--| .-----. }
+{ |. l | -__| | -__| _ | _ | _ | -__| }
+{ |. _ |_____|__|__|_____|___ |___._|_____|_____| }
+{ |: | | |_____| }
+{ |::.|:. | }
+{ `--- ---' }
+{*******************************************************}
+{$mode objfpc}
+{$codepage utf8}
+{$h+}
+
+program LoggerTest;
+
+uses
+ Classes,
+ Renegade.Logger,
+ Logger.SysLogHandler;
+
+var
+ LogHandler: SysLogHandler;
+ Log: RTLogger;
+begin
+ LogHandler := SysLogHandler.Create(LOG_DAEMON);
+ Log := RTLogger.Create(LogHandler);
+ Log.Info('Testing', ['File', True, 'Error', True, 'Extended', 'Extend']);
+ Log.Debug('Debugging', []);
+ Log.Error('Error', []);
+end.