]> WPIA git - cassiopeia.git/commitdiff
Merge remote-tracking branch 'origin/master' into tmp/logger
authorFelix Dörre <felix@dogcraft.de>
Sun, 2 Aug 2015 22:23:29 +0000 (00:23 +0200)
committerFelix Dörre <felix@dogcraft.de>
Sun, 2 Aug 2015 22:23:29 +0000 (00:23 +0200)
26 files changed:
Makefile
scripts/format.sh
src/apps/client.cpp
src/apps/signer.cpp
src/config.cpp
src/crypto/X509.cpp
src/crypto/remoteSigner.cpp
src/crypto/remoteSigner.h
src/crypto/simpleOpensslSigner.cpp
src/crypto/sslUtil.cpp
src/crypto/sslUtil.h
src/db/database.cpp
src/db/database.h
src/db/mysql.cpp
src/db/mysql.h
src/io/record.cpp
src/io/recordHandler.cpp
src/io/slipBio.cpp
src/io/slipBio.h
src/log/format.cpp [new file with mode: 0644]
src/log/format.hpp [new file with mode: 0644]
src/log/logger.cpp [new file with mode: 0644]
src/log/logger.hpp [new file with mode: 0644]
src/util.cpp
src/util.h
test/src/log.cpp [new file with mode: 0644]

index a22b76622ab19a14b409936c43f049387e8d7607..562abb5a503389d5c5df21d33363522f2f794bff 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -46,7 +46,7 @@ SRC_DIR=src
 OBJ_DIR=obj
 DEP_DIR=dep
 
-FS_SRC=$(wildcard ${SRC_DIR}/*.cpp) $(wildcard ${SRC_DIR}/io/*.cpp) $(wildcard ${SRC_DIR}/crypto/*.cpp) $(wildcard ${SRC_DIR}/db/*.cpp)
+FS_SRC=$(wildcard ${SRC_DIR}/*.cpp) $(wildcard ${SRC_DIR}/log/*.cpp) $(wildcard ${SRC_DIR}/io/*.cpp) $(wildcard ${SRC_DIR}/crypto/*.cpp) $(wildcard ${SRC_DIR}/db/*.cpp)
 
 FS_BIN=$(wildcard ${SRC_DIR}/app/*.cpp)
 FS_LIBS=$(wildcard lib/*/)
index 33b228687502fbc2a8f288455325960b2d7c5423..b8b7061238d3574c142010b6eeb986b31e205827 100755 (executable)
@@ -1,2 +1,2 @@
 #!/bin/sh
-astyle --style=java --add-brackets --indent-col1-comments --break-blocks --pad-oper --pad-paren-in --unpad-paren --indent-namespaces --align-pointer=type --align-reference=type --convert-tabs --lineend=linux -r "*.cpp" "*.h"
+astyle --style=java --add-brackets --indent-col1-comments --break-blocks --pad-oper --pad-paren-in --unpad-paren --indent-namespaces --align-pointer=type --align-reference=type --convert-tabs --lineend=linux -r "*.cpp" "*.h" '*.hpp'
index 5cbacdc264481a1e13515825eae6bc88fe801042..999b4532cb1cef0741e020ac835b157b3cc126e2 100644 (file)
@@ -11,6 +11,7 @@
 #include "crypto/simpleOpensslSigner.h"
 #include "crypto/remoteSigner.h"
 #include "crypto/sslUtil.h"
+#include "log/logger.hpp"
 #include "util.h"
 #include "io/bios.h"
 #include "io/slipBio.h"
@@ -28,33 +29,32 @@ extern std::string serialPath;
 extern std::unordered_map<std::string, std::shared_ptr<CAConfig>> CAs;
 
 void checkCRLs( std::shared_ptr<Signer> sign ) {
-    std::cout << "Signing CRLs" << std::endl;
 
-    for( auto x : CAs ) {
-        std::cout << "Checking: " << x.first << std::endl;
+    logger::note( "Signing CRLs" );
+
+    for( auto& x : CAs ) {
+        logger::notef( "Checking: %s ...", x.first );
 
         if( !x.second->crlNeedsResign() ) {
-            std::cout << "Skipping Resigning CRL: " + x.second->name << std::endl;
+            logger::warnf( "Skipping Resigning CRL: %s ...", x.second->name );
             continue;
         }
 
-        std::cout << "Resigning CRL: " + x.second->name << std::endl;
+        logger::notef( "Resigning CRL: %s ...", x.second->name );
 
         try {
             std::vector<std::string> serials;
             std::pair<std::shared_ptr<CRL>, std::string> rev = sign->revoke( x.second, serials );
         } catch( const char* c ) {
-            std::cout << "Exception: " << c << std::endl;
+            logger::error( "Exception: ", c );
         }
     }
 }
 
 int main( int argc, const char* argv[] ) {
-    ( void ) argc;
-    ( void ) argv;
     bool once = false;
 
-    if( argc == 2 && std::string( "--once" ) == std::string( argv[1] ) ) {
+    if( argc == 2 && std::string( "--once" ) == argv[1] ) {
         once = true;
     }
 
@@ -67,11 +67,12 @@ int main( int argc, const char* argv[] ) {
 #endif
 
     if( parseConfig( path ) != 0 ) {
+        logger::fatal( "Error: Could not parse the configuration file." );
         return -1;
     }
 
     if( serialPath == "" ) {
-        std::cout << "Error: no serial device is given" << std::endl;
+        logger::fatal( "Error: no serial device is given!" );
         return -1;
     }
 
@@ -92,7 +93,7 @@ int main( int argc, const char* argv[] ) {
             // todo set good log TODO FIXME
             sign->setLog( std::shared_ptr<std::ostream>(
                 &std::cout,
-                []( std::ostream * o ) {
+                []( std::ostream* o ) {
                     ( void ) o;
                 } ) );
             checkCRLs( sign );
@@ -102,68 +103,66 @@ int main( int argc, const char* argv[] ) {
         std::shared_ptr<Job> job = jp->fetchJob();
 
         if( !job ) {
-            std::cout << "Nothing to work on" << std::endl;
+            logger::debug( "Nothing to work on." );
             sleep( 5 );
             continue;
         }
 
         std::shared_ptr<std::ofstream> logPtr = openLogfile( std::string( "logs/" ) + job->id + std::string( "_" ) + job->warning + std::string( ".log" ) );
 
-        std::ofstream& log = *( logPtr.get() );
-
         sign->setLog( logPtr );
-        log << "TASK ID: " << job->id << std::endl;
-        log << "TRY: " << job->warning << std::endl;
-        log << "TARGET: " << job->target << std::endl;
-        log << "TASK: " << job->task << std::endl << std::endl;
+        logger::note( "TASK ID: ", job->id );
+        logger::note( "TRY:     ", job->warning );
+        logger::note( "TARGET:  ", job->target );
+        logger::note( "TASK:    ", job->task );
 
         if( job->task == "sign" ) {
             try {
                 std::shared_ptr<TBSCertificate> cert = jp->fetchTBSCert( job );
                 cert->wishFrom = job->from;
                 cert->wishTo = job->to;
-                log << "INFO: message digest: " << cert->md << std::endl;
-                log << "INFO: profile id: " << cert->profile << std::endl;
+                logger::note( "INFO: Message Digest: ", cert->md );
+                logger::note( "INFO: Profile ID: ", cert->profile );
 
                 for( auto& SAN : cert->SANs ) {
-                    log << "INFO: SAN " << SAN->type << ": " << SAN->content;
+                    logger::notef( "INFO: SAN %s: %s", SAN->type, SAN->content );
                 }
 
                 for( auto& AVA : cert->AVAs ) {
-                    log << "INFO: AVA " << AVA->name << ": " << AVA->value;
+                    logger::notef( "INFO: AVA %s: %s", AVA->name, AVA->value );
                 }
 
                 if( !cert ) {
-                    std::cout << "wasn't able to load CSR" << std::endl;
+                    logger::error( "Unable to load CSR" );
                     jp->failJob( job );
                     continue;
                 }
 
-                log << "FINE: Found the CSR at '" << cert->csr << "'" << std::endl;
+                logger::notef( "FINE: Found the CSR at '%s'", cert->csr );
                 cert->csr_content = readFile( keyDir + "/../" + cert->csr );
-                log << "FINE: CSR is " << std::endl << cert->csr_content << std::endl;
+                logger::note( "FINE: CSR content:\n", cert->csr_content );
 
                 std::shared_ptr<SignedCertificate> res = sign->sign( cert );
 
                 if( !res ) {
-                    log << "ERROR: The signer failed. There was no certificate." << std::endl;
+                    logger::error( "ERROR: The signer failed. No certificate was returned." );
                     jp->failJob( job );
                     continue;
                 }
 
-                log << "FINE: CERTIFICATE LOG: " << res->log << std::endl;
-                log << "FINE: CERTIFICATE:" << std::endl << res->certificate << std::endl;
+                logger::note( "FINE: CERTIFICATE LOG:\n", res->log );
+                logger::note( "FINE: CERTIFICATE:\n", res->certificate );
                 std::string fn = writeBackFile( job->target.c_str(), res->certificate, keyDir );
 
                 if( fn.empty() ) {
-                    log << "ERROR: Writeback of the certificate failed." << std::endl;
+                    logger::error( "ERROR: Writeback of the certificate failed." );
                     jp->failJob( job );
                     continue;
                 }
 
                 res->crt_name = fn;
                 jp->writeBack( job, res ); //! \FIXME: Check return value
-                log << "FINE: signing done." << std::endl;
+                logger::note( "FINE: signing done." );
 
                 if( DAEMON ) {
                     jp->finishJob( job );
@@ -171,17 +170,17 @@ int main( int argc, const char* argv[] ) {
 
                 continue;
             } catch( const char* c ) {
-                log << "ERROR: " << c << std::endl;
+                logger::error( "ERROR: ", c );
             } catch( std::string& c ) {
-                log << "ERROR: " << c << std::endl;
+                logger::error( "ERROR: ", c );
             }
 
             try {
                 jp->failJob( job );
             } catch( const char* c ) {
-                log << "ERROR: " << c << std::endl;
+                logger::error( "ERROR: ", c );
             } catch( std::string& c ) {
-                log << "ERROR: " << c << std::endl;
+                logger::error( "ERROR: ", c );
             }
         } else if( job->task == "revoke" ) {
             try {
@@ -196,12 +195,12 @@ int main( int argc, const char* argv[] ) {
                 jp->writeBackRevocation( job, timeToString( time ) );
                 jp->finishJob( job );
             } catch( const char* c ) {
-                std::cout << "Exception: " << c << std::endl;
+                logger::error( "Exception: ", c );
             } catch( const std::string& c ) {
-                std::cout << "Exception: " << c << std::endl;
+                logger::error( "Exception: ", c );
             }
         } else {
-            log << "Unknown job type" << job->task << std::endl;
+            logger::errorf( "Unknown job type (\"%s\")", job->task );
             jp->failJob( job );
         }
 
index 0d027c0a8070a44823aec9f70adf3399fed96211..f7f61d8d2932eb26bd4b36366936cc16bd195949 100644 (file)
@@ -1,6 +1,7 @@
 #include <iostream>
 #include <fstream>
 #include <streambuf>
+#include <stdexcept>
 
 #include "db/database.h"
 #include "db/mysql.h"
@@ -10,6 +11,7 @@
 #include "io/bios.h"
 #include "io/slipBio.h"
 #include "io/recordHandler.h"
+#include "log/logger.hpp"
 #include "util.h"
 #include "config.h"
 
@@ -21,7 +23,7 @@
 
 extern std::string serialPath;
 
-int main( int argc, const char* argv[] ) {
+int main( int argc, const char* argv[] ) try {
     ( void ) argc;
     ( void ) argv;
 
@@ -34,13 +36,14 @@ int main( int argc, const char* argv[] ) {
 #endif
 
     if( parseConfig( path ) != 0 ) {
+        logger::fatal( "Could not parse configuration file." );
         return -1;
     }
 
     std::shared_ptr<int> ssl_lib = ssl_lib_ref;
 
     if( serialPath == "" ) {
-        std::cout << "Error: no serial device is given" << std::endl;
+        logger::fatal( "Error: No device for the serial connection was given." );
         return -1;
     }
 
@@ -56,11 +59,18 @@ int main( int argc, const char* argv[] ) {
             //} catch( const std::exception &ch ) {
             //std::cout << "Real exception: " << typeid(ch).name() << ", " << ch.what() << std::endl;
         } catch( const std::string& ch ) {
-            std::cout << "Exception: " << ch << std::endl;
+            logger::error( "Exception: ", ch );
         } catch( char const* ch ) {
-            std::cout << "Exception: " << ch << std::endl;
+            logger::error( "Exception: ", ch );
         }
     }
 
     return -1;
+
+} catch( std::exception& e ) {
+    logger::fatalf( "Fatal Error: %s!\n", e.what() );
+    return -1;
+} catch( ... ) {
+    logger::fatal( "Fatal Error: Unknown Exception!\n" );
+    return -1;
 }
index ad3c1375963a16602d07611b62bc7ff502e31606..495231c8a377f1c9c5c5e86ed6ce3a0bfb4411de 100644 (file)
@@ -6,6 +6,8 @@
 
 #include "crypto/sslUtil.h"
 
+#include "log/logger.hpp"
+
 std::string keyDir;
 std::unordered_map<std::string, Profile> profiles;
 std::unordered_map<std::string, std::shared_ptr<CAConfig>> CAs;
@@ -18,7 +20,7 @@ std::shared_ptr<std::unordered_map<std::string, std::string>> parseConf( std::st
     config.open( path );
 
     if( !config.is_open() ) {
-        std::cout << "Where is " << path << "?" << std::endl;
+        logger::notef( "Where is \"%s\"?", path );
         throw "Config missing";
     }
 
@@ -32,7 +34,7 @@ std::shared_ptr<std::unordered_map<std::string, std::string>> parseConf( std::st
         int splitter = line1.find( "=" );
 
         if( splitter == -1 ) {
-            std::cerr << "Ignoring malformed config line: " << line1 << std::endl;
+            logger::warn( "Ignoring malformed config line: ", line1 );
             continue;
         }
 
@@ -54,7 +56,7 @@ int parseProfiles() {
     dp = opendir( "profiles" );
 
     if( dp == NULL ) {
-        std::cerr << "Profiles not found " << std::endl;
+        logger::error( "Profiles directory not found" );
         return -1;
     }
 
@@ -68,14 +70,14 @@ int parseProfiles() {
         int splitter = profileName.find( "-" );
 
         if( splitter == -1 ) {
-            std::cerr << "Ignoring malformed profile: " << profileName << std::endl;
+            logger::warn( "Ignoring malformed profile: ", profileName );
             continue;
         }
 
         std::string id = profileName.substr( 0, splitter );
 
         if( profileName.substr( profileName.size() - 4 ) != ".cfg" ) {
-            std::cerr << "Ignoring malformed profile: " << profileName << std::endl;
+            logger::warn( "Ignoring malformed profile: ", profileName );
             continue;
         }
 
@@ -91,12 +93,14 @@ int parseProfiles() {
 
         std::string cas = map->at( "ca" );
 
-        DIR *dir;
-        struct dirent *ent;
-        if ((dir = opendir ("ca")) != NULL) {
-            while ((ent = readdir (dir)) != NULL) {
-                std::string caName = std::string(ent->d_name);
-                if( caName.find( cas ) != 0 ){
+        DIR* dir;
+        struct dirent* ent;
+
+        if( ( dir = opendir( "ca" ) ) != NULL ) {
+            while( ( ent = readdir( dir ) ) != NULL ) {
+                std::string caName = std::string( ent->d_name );
+
+                if( caName.find( cas ) != 0 ) {
                     continue;
                 }
 
@@ -106,27 +110,26 @@ int parseProfiles() {
                 }
 
                 prof.ca.push_back( CAs.at( caName ) );
-                std::cout << "Adding CA: " << caName << std::endl;
+                logger::note( "Adding CA: ", caName );
             }
-            closedir (dir);
+
+            closedir( dir );
         } else {
             throw "Directory with CAConfigs not found";
         }
 
         profiles.emplace( profileName, prof );
-        std::cout << "Profile: " << profileName << " up and running." << std::endl;
+        logger::notef( "Profile: \"%s\" up and running.", profileName );
     }
 
     ( void ) closedir( dp );
 
-
-    std::cout << profiles.size() << " profiles loaded." << std::endl;
+    logger::notef( "%s profiles loaded.", profiles.size() );
 
     return 0;
 }
 
 int parseConfig( std::string path ) {
-
     auto masterConf = parseConf( path );
 
     keyDir = masterConf->at( "key.directory" );
@@ -137,7 +140,7 @@ int parseConfig( std::string path ) {
     serialPath = masterConf->at( "serialPath" );
 
     if( keyDir == "" ) {
-        std::cerr << "Missing config property key.directory" << std::endl;
+        logger::error( "Missing config property key.directory" );
         return -1;
     }
 
index acc9dec358b528bd558e43cc5819c06e9d1bcd6d..5eed484bd24aebe0c798243303400e12cfe47623 100644 (file)
@@ -268,8 +268,8 @@ std::shared_ptr<SignedCertificate> X509Cert::sign( std::shared_ptr<EVP_PKEY> caK
 
     std::shared_ptr<char> serStr(
         BN_bn2hex( ser.get() ),
-        []( char *p ) {
-            OPENSSL_free(p);
+        []( charp ) {
+            OPENSSL_free( p );
         } ); // OPENSSL_free is a macro...
     res->serial = serStr ? std::string( serStr.get() ) : "";
 
index b6c7c317d30047cf703c4c1824bb9c8836031ba2..74368467540de8af841e24a16ec6a9b618f571fc 100644 (file)
@@ -1,4 +1,6 @@
 #include "remoteSigner.h"
+
+#include "log/logger.hpp"
 #include "util.h"
 
 #include <iostream>
@@ -17,7 +19,6 @@ void RemoteSigner::send( std::shared_ptr<OpensslBIOWrapper> bio, RecordHeader& h
     head.command_count++;
     head.totalLength = data.size();
     sendCommand( head, data, bio, log );
-
 }
 
 std::shared_ptr<SignedCertificate> RemoteSigner::sign( std::shared_ptr<TBSCertificate> cert ) {
@@ -38,7 +39,7 @@ std::shared_ptr<SignedCertificate> RemoteSigner::sign( std::shared_ptr<TBSCertif
     } else if( cert->csr_type == "SPKAC" ) {
         send( conn, head, RecordHeader::SignerCommand::SET_SPKAC, cert->csr_content );
     } else {
-        std::cout << "Unknown csr_type: " << cert->csr_type;
+        logger::error( "Unknown csr_type: ", cert->csr_type );
         return std::shared_ptr<SignedCertificate>();
     }
 
@@ -75,7 +76,7 @@ std::shared_ptr<SignedCertificate> RemoteSigner::sign( std::shared_ptr<TBSCertif
             int length = conn->read( buffer.data(), buffer.size() );
 
             if( length <= 0 ) {
-                std::cout << "Error, no response data" << std::endl;
+                logger::error( "Error, no response data" );
                 result = std::shared_ptr<SignedCertificate>();
                 break;
             }
@@ -97,11 +98,11 @@ std::shared_ptr<SignedCertificate> RemoteSigner::sign( std::shared_ptr<TBSCertif
                 break;
 
             default:
-                std::cout << "Invalid Message" << std::endl;
+                logger::error( "Invalid Message" );
                 break;
             }
         } catch( const char* msg ) {
-            std::cout << msg << std::endl;
+            logger::error( msg );
             return std::shared_ptr<SignedCertificate>();
         }
     }
@@ -141,7 +142,7 @@ std::shared_ptr<SignedCertificate> RemoteSigner::sign( std::shared_ptr<TBSCertif
     }
 
     if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) { // need to close the connection twice
-        std::cout << "SSL shutdown failed" << std::endl;
+        logger::warn( "SSL shutdown failed" );
     }
 
     return result;
@@ -199,10 +200,10 @@ std::pair<std::shared_ptr<CRL>, std::string> RemoteSigner::revoke( std::shared_p
     bool ok = crl->verify( ca );
 
     if( ok ) {
-        ( *log ) << "CRL verificated successfully" << std::endl;
+        logger::note( "CRL verificated successfully" );
         writeFile( ca->path + std::string( "/ca.crl" ), crl->toString() );
     } else {
-        ( *log ) << "CRL is broken" << std::endl;
+        logger::warn( "CRL is broken, trying to recover" );
         send( conn, head, RecordHeader::SignerCommand::GET_FULL_CRL, ca->name );
         length = conn->read( buffer.data(), buffer.size() );
 
@@ -221,17 +222,16 @@ std::pair<std::shared_ptr<CRL>, std::string> RemoteSigner::revoke( std::shared_p
 
         if( crl->verify( ca ) ) {
             writeFile( ca->path + std::string( "/ca.crl" ), crl->toString() );
-            ( *log ) << "CRL is now valid" << std::endl;
+            logger::note( "CRL is now valid again" );
         } else {
-            ( *log ) << "CRL is still broken... Please, help me" << std::endl;
+            logger::warn( "CRL is still broken... Please, help me" );
         }
-
     }
 
-    ( *log ) << "CRL: " << std::endl << crl->toString() << std::endl;
+    logger::debug( "CRL:\n", crl->toString() );
 
     if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) { // need to close the connection twice
-        std::cout << "SSL shutdown failed" << std::endl;
+        logger::warn( "SSL shutdown failed" );
     }
 
     return std::pair<std::shared_ptr<CRL>, std::string>( crl, date );
index 525bbd0123632e3eddbd48a98204a21d52dd770c..79fabae4c1bc156909fe00fbd31a66596c988d89 100644 (file)
@@ -1,4 +1,5 @@
 #pragma once
+
 #include <memory>
 #include <openssl/ssl.h>
 
index 914d26e459fff0b9c8b994d2044c4d2392e31834..7f75142f2f964330a69cf784d9140cfda10b2441 100644 (file)
@@ -10,6 +10,8 @@
 #include <openssl/engine.h>
 #include <openssl/x509v3.h>
 
+#include "log/logger.hpp"
+
 #include "X509.h"
 #include "util.h"
 #include "sslUtil.h"
@@ -71,25 +73,25 @@ std::pair<std::shared_ptr<BIGNUM>, std::string> SimpleOpensslSigner::nextSerial(
 std::shared_ptr<SignedCertificate> SimpleOpensslSigner::sign( std::shared_ptr<TBSCertificate> cert ) {
     std::stringstream signlog;
 
-    signlog << "FINE: profile is " << cert->profile << std::endl;
+    logger::note( "FINE: Profile name is: ", cert->profile );
 
     Profile& prof = profiles.at( cert->profile );
-    signlog << "FINE: Profile id is: " << prof.id << std::endl;
+    logger::note( "FINE: Profile ID is: ", prof.id );
 
     std::shared_ptr<CAConfig> ca = prof.getCA();
 
     if( !ca ) {
-        signlog << "ERROR: Signing CA specified in profile could not be loaded." << std::endl;
+        logger::error( "ERROR: Signing CA specified in profile could not be loaded." );
         throw "CA-key not found";
     }
 
-    signlog << "FINE: Key for Signing CA is correctly loaded." << std::endl;
+    logger::note( "FINE: Key for Signing CA is correctly loaded." );
 
-    signlog << "INFO: Baseline Key Usage is: " << prof.ku << std::endl;
-    signlog << "INFO: Extended Key Usage is: " << prof.eku << std::endl;
+    logger::note( "INFO: Baseline Key Usage is: ", prof.ku );
+    logger::note( "INFO: Extended Key Usage is: ", prof.eku );
 
-    signlog << "FINE: Signing is wanted by: " << cert->wishFrom << std::endl;
-    signlog << "FINE: Signing is wanted for: " << cert->wishTo << std::endl;
+    logger::note( "FINE: Signing is wanted by: ", cert->wishFrom );
+    logger::note( "FINE: Signing is wanted for: ", cert->wishTo );
 
     std::shared_ptr<X509Req> req;
 
@@ -98,8 +100,8 @@ std::shared_ptr<SignedCertificate> SimpleOpensslSigner::sign( std::shared_ptr<TB
     } else if( cert->csr_type == "CSR" ) {
         req = X509Req::parseCSR( cert->csr_content );
     } else {
-        signlog << "ERROR: Unknown type of certification in request: " << cert->csr_type << std::endl;
-        throw "Error, unknown REQ rype " + ( cert->csr_type );
+        logger::errorf( "ERROR: Unknown type (\"%s\") of certification in request.", cert->csr_type );
+        throw "Error, unknown REQ rype " + ( cert->csr_type ); //! \fixme: Pointer instead of string, please use proper exception classes
     }
 
     int i = req->verify();
@@ -109,15 +111,16 @@ std::shared_ptr<SignedCertificate> SimpleOpensslSigner::sign( std::shared_ptr<TB
     } else if( i == 0 ) {
         throw "Request contains a Signature that does not match ...";
     } else {
-        signlog << "FINE: Request contains valid self-signature." << std::endl;
+        logger::note( "FINE: Request contains valid self-signature." );
     }
 
     // Construct the Certificate
     X509Cert c = X509Cert();
 
-    signlog << "INFO: Populating RDN ..." << std::endl;
+    logger::note( "INFO: Populating RDN ..." );
+
     for( std::shared_ptr<AVA> a : cert->AVAs ) {
-        signlog << "INFO: Trying to add RDN: " << a->name << ": " << a->value << std::endl;
+        logger::notef( "INFO: Trying to add RDN: %s: %s", a->name, a->value );
 
         if( a->name == "CN" ) {
             c.addRDN( NID_commonName, a->value );
@@ -134,34 +137,34 @@ std::shared_ptr<SignedCertificate> SimpleOpensslSigner::sign( std::shared_ptr<TB
         } else if( a->name == "OU" ) {
             c.addRDN( NID_organizationalUnitName, a->value );
         } else {
-            signlog << "ERROR: Trying to add illegal RDN/AVA type: " << a->name << std::endl;
+            logger::error( "ERROR: Trying to add illegal RDN/AVA type: ", a->name );
             throw "Unhandled/Illegal AVA type";
         }
     }
 
-    signlog << "INFO: Populating Issuer ..." << std::endl;
+    logger::note( "INFO: Populating Issuer ..." );
     c.setIssuerNameFrom( ca->ca );
 
-    signlog << "INFO: Validating Public key for use in certificate" << std::endl;
-    signlog << "INFO: - Checking generic key parameters" << std::endl;
-    signlog << "FINE:   ->Public Key parameters are okay" << std::endl;
+    logger::note( "INFO: Validating Public key for use in certificate" );
+    logger::note( "INFO: - Checking generic key parameters" );
+    logger::note( "FINE:   ->Public Key parameters are okay" );
 
-    signlog << "INFO: - Checking blacklists" << std::endl;
-    signlog << "FINE:   ->Does not appear on any blacklist" << std::endl;
+    logger::note( "INFO: - Checking blacklists" );
+    logger::note( "FINE:   ->Does not appear on any blacklist" );
 
-    signlog << "INFO: - Checking trivial factorization" << std::endl;
-    signlog << "FINE:   ->Trivial factorization not possible" << std::endl;
+    logger::note( "INFO: - Checking trivial factorization" );
+    logger::note( "FINE:   ->Trivial factorization not possible" );
 
-    signlog << "INFO: - Checking astrological signs" << std::endl;
-    signlog << "FINE:   ->The stars look good for this one" << std::endl;
-    signlog << "FINE: Public key is fine for use in certificate" << std::endl;
+    logger::note( "INFO: - Checking astrological signs" );
+    logger::note( "FINE:   ->The stars look good for this one" );
+    logger::note( "FINE: Public key is fine for use in certificate" );
 
-    signlog << "INFO: Copying Public Key from Request ..." << std::endl;
+    logger::note( "INFO: Copying Public Key from Request ..." );
     c.setPubkeyFrom( req );
-    signlog << "FINE: Public Key successfully copied from Request." << std::endl;
+    logger::note( "FINE: Public Key successfully copied from Request." );
 
     {
-        signlog << "INFO: Determining Validity Period ..." << std::endl;
+        logger::note( "INFO: Determining Validity Period ..." );
         std::time_t from, to;
         std::time_t now = time( 0 );
         std::pair<bool, std::time_t> parsed;
@@ -176,7 +179,7 @@ std::shared_ptr<SignedCertificate> SimpleOpensslSigner::sign( std::shared_ptr<TB
             from = now;
         }
 
-        if( ((from - now) > /* 2 Weeks */ (2 * 7 * 24 * 60 * 60)) || ((now - from) >= 0) ) {
+        if( ( ( from - now ) > /* 2 Weeks */ ( 2 * 7 * 24 * 60 * 60 ) ) || ( ( now - from ) >= 0 ) ) {
             from = now;
         }
 
@@ -196,57 +199,57 @@ std::shared_ptr<SignedCertificate> SimpleOpensslSigner::sign( std::shared_ptr<TB
 
         time_t limit = prof.maxValidity;
 
-        if( (to - from > limit) || (to - from < 0) ) {
+        if( ( to - from > limit ) || ( to - from < 0 ) ) {
             to = from + limit;
         }
 
         c.setTimes( from, to );
-        signlog << "FINE: Setting validity period successful:" << std::endl;
+        logger::note( "FINE: Setting validity period successful:" );
         {
             struct tm* timeobj;
             std::vector<char> timebuf;
 
-            timeobj = gmtime(&from);
-            timebuf.resize(128);
-            timebuf.resize(std::strftime(const_cast<char *>(timebuf.data()), timebuf.size(), "%F %T %Z", timeobj));
-            signlog << "FINE: - Valid not before: " << std::string(timebuf.cbegin(), timebuf.cend()) << std::endl;
+            timeobj = gmtime( &from );
+            timebuf.resize( 128 );
+            timebuf.resize( std::strftime( const_cast<char*>( timebuf.data() ), timebuf.size(), "%F %T %Z", timeobj ) );
+            logger::note( "FINE: - Valid not before: ", std::string( timebuf.cbegin(), timebuf.cend() ) );
 
-            timeobj = gmtime(&to);
-            timebuf.resize(128);
-            timebuf.resize(std::strftime(const_cast<char *>(timebuf.data()), timebuf.size(), "%F %T %Z", timeobj));
-            signlog << "FINE: - Valid not after:  " << std::string(timebuf.cbegin(), timebuf.cend()) << std::endl;
+            timeobj = gmtime( &to );
+            timebuf.resize( 128 );
+            timebuf.resize( std::strftime( const_cast<char*>( timebuf.data() ), timebuf.size(), "%F %T %Z", timeobj ) );
+            logger::note( "FINE: - Valid not after:  ", std::string( timebuf.cbegin(), timebuf.cend() ) );
         }
     }
 
-    signlog << "INFO: Setting extensions:" << std::endl;
+    logger::note( "INFO: Setting extensions:" );
     c.setExtensions( ca->ca, cert->SANs, prof );
-    signlog << "FINE: Setting extensions successful." << std::endl;
+    logger::note( "FINE: Setting extensions successful." );
 
-    signlog << "INFO: Generating next Serial Number ..." << std::endl;
+    logger::note( "INFO: Generating next Serial Number ..." );
     std::shared_ptr<BIGNUM> ser;
     std::string num;
     std::tie( ser, num ) = nextSerial( prof, ca );
     c.setSerialNumber( ser.get() );
-    signlog << "FINE: Certificate Serial Number set to:" << num << std::endl;
+    logger::note( "FINE: Certificate Serial Number set to: ", num );
 
     {
-        signlog << "INFO: Trying to sign Certificate:" << std::endl;
+        logger::note( "INFO: Trying to sign Certificate:" );
         std::shared_ptr<SignedCertificate> output = c.sign( ca->caKey, cert->md );
-        signlog << "INFO: Writing certificate to local file." << std::endl;
+        logger::note( "INFO: Writing certificate to local file." );
         std::string fn = writeBackFile( num, output->certificate, ca->path );
 
         if( fn.empty() ) {
-            signlog << "ERROR: failed to get filename for storage of signed certificate." << std::endl;
+            logger::error( "ERROR: failed to get filename for storage of signed certificate." );
             throw "Storage location could not be determined";
         }
-        signlog << "FINE: Certificate signed successfully." << std::endl;
-        signlog << "FINE: - Certificate written to: " << fn << std::endl;
+
+        logger::note( "FINE: Certificate signed successfully." );
+        logger::note( "FINE: - Certificate written to: ", fn );
 
         output->ca_name = ca->name;
         output->log = signlog.str();
         return output;
     }
-
 }
 
 std::pair<std::shared_ptr<CRL>, std::string> SimpleOpensslSigner::revoke( std::shared_ptr<CAConfig> ca, std::vector<std::string> serials ) {
index d0df60c9d7a3f5171b093e8bf1421ede90a6bee9..d4f55da86b33247c6d9a228f7ab04f416bd4d291 100644 (file)
@@ -7,6 +7,7 @@
 #include <iostream>
 
 #include "crypto/CRL.h"
+#include "log/logger.hpp"
 
 std::shared_ptr<int> ssl_lib_ref(
     new int( SSL_library_init() ),
@@ -32,17 +33,19 @@ std::shared_ptr<X509> loadX509FromFile( const std::string& filename ) {
 
     return std::shared_ptr<X509>(
         key,
-        []( X509 * ref ) {
+        []( X509* ref ) {
             X509_free( ref );
         } );
 }
 
 std::shared_ptr<EVP_PKEY> loadPkeyFromFile( const std::string& filename ) {
-    std::shared_ptr<FILE> f( fopen( filename.c_str(), "r" ), []( FILE * ptr ) {
-        if( ptr ) {
-            fclose( ptr );
-        }
-    } );
+    std::shared_ptr<FILE> f(
+        fopen( filename.c_str(), "r" ),
+        []( FILE* ptr ) {
+            if( ptr ) {
+                fclose( ptr );
+            }
+        } );
 
     if( !f ) {
         return std::shared_ptr<EVP_PKEY>();
@@ -56,7 +59,7 @@ std::shared_ptr<EVP_PKEY> loadPkeyFromFile( const std::string& filename ) {
 
     return std::shared_ptr<EVP_PKEY>(
         key,
-        []( EVP_PKEY * ref ) {
+        []( EVP_PKEY* ref ) {
             EVP_PKEY_free( ref );
         } );
 }
@@ -65,7 +68,9 @@ int gencb( int a, int b, BN_GENCB* g ) {
     ( void ) a;
     ( void ) b;
     ( void ) g;
+
     std::cout << ( a == 0 ? "." : "+" ) << std::flush;
+
     return 1;
 }
 
@@ -76,7 +81,7 @@ static int verify_callback( int preverify_ok, X509_STORE_CTX* ctx ) {
         //X509_print_ex(o, cert, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
         //BIO_free(o);
 
-        std::cout << "Verification failed: " << preverify_ok << " because " << X509_STORE_CTX_get_error( ctx ) << std::endl;
+        logger::errorf( "Verification failed: %s because %s", preverify_ok, X509_STORE_CTX_get_error( ctx ) );
     }
 
     return preverify_ok;
@@ -85,9 +90,11 @@ static int verify_callback( int preverify_ok, X509_STORE_CTX* ctx ) {
 static std::shared_ptr<DH> dh_param;
 
 std::shared_ptr<SSL_CTX> generateSSLContext( bool server ) {
-    std::shared_ptr<SSL_CTX> ctx = std::shared_ptr<SSL_CTX>( SSL_CTX_new( TLSv1_2_method() ), []( SSL_CTX * p ) {
-        SSL_CTX_free( p );
-    } );
+    std::shared_ptr<SSL_CTX> ctx = std::shared_ptr<SSL_CTX>(
+        SSL_CTX_new( TLSv1_2_method() ),
+        []( SSL_CTX* p ) {
+            SSL_CTX_free( p );
+        } );
 
     if( !SSL_CTX_set_cipher_list( ctx.get(), "HIGH:+CAMELLIA256:!eNull:!aNULL:!ADH:!MD5:-RSA+AES+SHA1:!RC4:!DES:!3DES:!SEED:!EXP:!AES128:!CAMELLIA128" ) ) {
         throw "Cannot set cipher list. Your source is broken.";
@@ -117,7 +124,7 @@ std::shared_ptr<SSL_CTX> generateSSLContext( bool server ) {
                 dh_param = std::shared_ptr<DH>( PEM_read_DHparams( paramfile.get(), NULL, NULL, NULL ), DH_free );
             } else {
                 dh_param = std::shared_ptr<DH>( DH_new(), DH_free );
-                std::cout << "Generating DH params" << std::endl;
+                logger::note( "Generating DH params" );
                 BN_GENCB cb;
                 cb.ver = 2;
                 cb.arg = 0;
@@ -169,7 +176,7 @@ std::shared_ptr<BIO> openSerial( const std::string& name ) {
     std::shared_ptr<FILE> f( fopen( name.c_str(), "r+" ), fclose );
 
     if( !f ) {
-        std::cout << "Opening serial device failed" << std::endl;
+        logger::error( "Opening serial device failed." );
         return std::shared_ptr<BIO>();
     }
 
@@ -177,7 +184,7 @@ std::shared_ptr<BIO> openSerial( const std::string& name ) {
     return std::shared_ptr<BIO>(
         BIO_new_fd( fileno( f.get() ), 0 ),
         [f]( BIO* b ) {
-            BIO_free(b);
+            BIO_free( b );
         } );
 }
 
index 1327a17bd47367dd0113ce8dec984e1ca93ccb27..6ecb536cd5cac1ca479239da1411d042595d5925 100644 (file)
 
 #include "db/database.h"
 
-class CAConfig {
-public:
+struct CAConfig {
     std::string path;
     std::string name;
 
     std::shared_ptr<X509> ca;
     std::shared_ptr<EVP_PKEY> caKey;
     std::shared_ptr<ASN1_TIME> notBefore;
+
     CAConfig( const std::string& name );
+
     bool crlNeedsResign();
 };
 
@@ -49,4 +50,5 @@ std::shared_ptr<EVP_PKEY> loadPkeyFromFile( const std::string& filename );
 std::shared_ptr<SSL_CTX> generateSSLContext( bool server );
 std::shared_ptr<BIO> openSerial( const std::string& name );
 std::string timeToString( std::shared_ptr<ASN1_TIME> time );
+
 void extractTimes( std::shared_ptr<X509> source, std::shared_ptr<SignedCertificate> cert );
index 7eabc17d9d99b30c31a2725883ee97cc2db6a81d..4bb12b292c98b402348fd4868d0b05261b78ecdf 100644 (file)
@@ -1 +1 @@
-#include "database.h"
+#include "db/database.h"
index 132d8ef22b1b521760c6015701a369648a9962c9..31687b13ce43242e68ab14babba87ae25e2908f6 100644 (file)
@@ -26,6 +26,7 @@ struct AVA {
 struct TBSCertificate {
     std::string md;
     std::string profile;
+
     /**
      * CSR path
      */
@@ -39,7 +40,6 @@ struct TBSCertificate {
     std::string wishTo;
 };
 
-
 struct SignedCertificate {
     std::string certificate;
     std::string serial;
@@ -54,6 +54,7 @@ struct SignedCertificate {
 
 class JobProvider {
 public:
+    virtual ~JobProvider() = default;
     virtual std::shared_ptr<Job> fetchJob() = 0;
     virtual void finishJob( std::shared_ptr<Job> job ) = 0;
     virtual void failJob( std::shared_ptr<Job> job ) = 0;
index fe5bdc9998025dfe22a8905b2658edb70eb60a9d..51cfdcbcfa486d0211d51dce2b5a118c4077e015 100644 (file)
@@ -10,6 +10,7 @@
 std::shared_ptr<int> MySQLJobProvider::lib_ref(
     //Initializer: Store the return code as a pointer to an integer
     new int( mysql_library_init( 0, NULL, NULL ) ),
+
     //Finalizer: Check the pointer and free resources
     []( int* ref ) {
         if( !ref ) {
@@ -36,19 +37,8 @@ MySQLJobProvider::MySQLJobProvider( const std::string& server, const std::string
     connect( server, user, password, database );
 }
 
-MySQLJobProvider::~MySQLJobProvider() {
-    disconnect();
-}
-
 bool MySQLJobProvider::connect( const std::string& server, const std::string& user, const std::string& password, const std::string& database ) {
-    if( conn ) {
-        if( !disconnect() ) {
-            return false;
-        }
-
-        conn.reset();
-    }
-
+    disconnect();
     conn = _connect( server, user, password, database );
 
     return !!conn;
@@ -58,13 +48,13 @@ std::shared_ptr<MYSQL> MySQLJobProvider::_connect( const std::string& server, co
     MYSQL* tmp( mysql_init( NULL ) );
 
     if( !tmp ) {
-        return std::shared_ptr<MYSQL>();
+        return nullptr;
     }
 
     tmp = mysql_real_connect( tmp, server.c_str(), user.c_str(), password.c_str(), database.c_str(), 3306, NULL, CLIENT_COMPRESS );
 
     if( !tmp ) {
-        return std::shared_ptr<MYSQL>();
+        return nullptr;
     }
 
     auto l = lib_ref;
@@ -121,7 +111,7 @@ std::shared_ptr<Job> MySQLJobProvider::fetchJob() {
     std::tie( err, res ) = query( q );
 
     if( err ) {
-        return std::shared_ptr<Job>();
+        return nullptr;
     }
 
     unsigned int num = mysql_num_fields( res.get() );
@@ -129,15 +119,15 @@ std::shared_ptr<Job> MySQLJobProvider::fetchJob() {
     MYSQL_ROW row = mysql_fetch_row( res.get() );
 
     if( !row ) {
-        return std::shared_ptr<Job>();
+        return nullptr;
     }
 
-    std::shared_ptr<Job> job( new Job() );
+    auto job = std::make_shared<Job>();
 
     unsigned long* l = mysql_fetch_lengths( res.get() );
 
     if( !l ) {
-        return std::shared_ptr<Job>();
+        return nullptr;
     }
 
     job->id = std::string( row[0], row[0] + l[0] );
@@ -182,7 +172,6 @@ void MySQLJobProvider::finishJob( std::shared_ptr<Job> job ) {
     if( query( q ).first ) {
         throw "No database entry found.";
     }
-
 }
 
 void MySQLJobProvider::failJob( std::shared_ptr<Job> job ) {
@@ -198,7 +187,7 @@ void MySQLJobProvider::failJob( std::shared_ptr<Job> job ) {
 }
 
 std::shared_ptr<TBSCertificate> MySQLJobProvider::fetchTBSCert( std::shared_ptr<Job> job ) {
-    std::shared_ptr<TBSCertificate> cert = std::shared_ptr<TBSCertificate>( new TBSCertificate() );
+    auto cert = std::make_shared<TBSCertificate>();
     std::string q = "SELECT md, profile, csr_name, csr_type, keyname FROM certs INNER JOIN profiles ON profiles.id = certs.profile WHERE certs.id='" + this->escape_string( job->target ) + "'";
 
     int err = 0;
@@ -208,19 +197,19 @@ std::shared_ptr<TBSCertificate> MySQLJobProvider::fetchTBSCert( std::shared_ptr<
     std::tie( err, res ) = query( q );
 
     if( err ) {
-        return std::shared_ptr<TBSCertificate>();
+        return nullptr;
     }
 
     MYSQL_ROW row = mysql_fetch_row( res.get() );
 
     if( !row ) {
-        return std::shared_ptr<TBSCertificate>();
+        return nullptr;
     }
 
     unsigned long* l = mysql_fetch_lengths( res.get() );
 
     if( !l ) {
-        return std::shared_ptr<TBSCertificate>();
+        return nullptr;
     }
 
     std::string profileName = std::string( row[4], row[4] + l[4] );
@@ -244,7 +233,7 @@ std::shared_ptr<TBSCertificate> MySQLJobProvider::fetchTBSCert( std::shared_ptr<
 
     if( err ) {
         std::cout << mysql_error( this->conn.get() );
-        return std::shared_ptr<TBSCertificate>();
+        return nullptr;
     }
 
     std::cout << "Fetching SANs" << std::endl;
@@ -253,7 +242,7 @@ std::shared_ptr<TBSCertificate> MySQLJobProvider::fetchTBSCert( std::shared_ptr<
         unsigned long* l = mysql_fetch_lengths( res.get() );
 
         if( !l ) {
-            return std::shared_ptr<TBSCertificate>();
+            return nullptr;
         }
 
         std::shared_ptr<SAN> nSAN = std::shared_ptr<SAN>( new SAN() );
@@ -267,7 +256,7 @@ std::shared_ptr<TBSCertificate> MySQLJobProvider::fetchTBSCert( std::shared_ptr<
 
     if( err ) {
         std::cout << mysql_error( this->conn.get() );
-        return std::shared_ptr<TBSCertificate>();
+        return nullptr;
 
     }
 
@@ -275,7 +264,7 @@ std::shared_ptr<TBSCertificate> MySQLJobProvider::fetchTBSCert( std::shared_ptr<
         unsigned long* l = mysql_fetch_lengths( res.get() );
 
         if( !l ) {
-            return std::shared_ptr<TBSCertificate>();
+            return nullptr;
         }
 
         std::shared_ptr<AVA> nAVA = std::shared_ptr<AVA>( new AVA() );
index a6b6a363c948e7cb70f69c363109c1bf978f6b52..5559244bd3f5f6892be597c76a87af2356d2e5a1 100644 (file)
@@ -19,7 +19,6 @@ private:
 
 public:
     MySQLJobProvider( const std::string& server, const std::string& user, const std::string& password, const std::string& database );
-    ~MySQLJobProvider();
 
 public:
     bool connect( const std::string& server, const std::string& user, const std::string& password, const std::string& database );
index bd0cc1b8d1e965636575c4c122244bd5f50a076b..c8fda58c98dd942c6e7d41b11efb97cf13c28b26 100644 (file)
@@ -5,8 +5,9 @@
 #include <memory>
 #include <sstream>
 
-#include "bios.h"
-#include "opensslBIO.h"
+#include "io/bios.h"
+#include "io/opensslBIO.h"
+#include "log/logger.hpp"
 
 std::string toHexAndChecksum( const std::string& src ) {
     char checksum = 0;
@@ -32,7 +33,7 @@ void sendCommand( RecordHeader& head, const std::string& data, std::shared_ptr<O
     std::string res = toHexAndChecksum( s );
 
     if( log ) {
-        ( *log.get() ) << "FINE: RECORD output: " << res << std::endl;
+        logger::debug( "FINE: RECORD output: ", res );
     }
 
     bio->write( res.data(), res.size() );
@@ -54,7 +55,7 @@ int32_t fromHexDigit( char c ) {
 
 std::string parseCommand( RecordHeader& head, const std::string& input, std::shared_ptr<std::ostream> log ) {
     if( log ) {
-        ( *log.get() ) << "FINE: RECORD input: " << input << std::endl;
+        logger::debug( "FINE: RECORD input: ", input );
     }
 
     int32_t dlen = ( input.size() - 2 ) / 2;
@@ -62,7 +63,7 @@ std::string parseCommand( RecordHeader& head, const std::string& input, std::sha
     bool error = false;
 
     std::string str( std::max( dlen, RECORD_HEADER_SIZE ), 0 );
-    str.append( 0, dlen );
+    str.append( dlen, '\0' );
 
     for( int i = 0; i < dlen; i++ ) {
         int32_t digit;
index b55317b1d26b8b6a7f2f89159195c4dbc65e51ab..a1d7b47d1e7b0853bd04de66ebc1a807357d26d6 100644 (file)
 #include "db/database.h"
 #include "crypto/remoteSigner.h"
 #include "crypto/sslUtil.h"
-
 #include "crypto/simpleOpensslSigner.h"
 
+#include "log/logger.hpp"
+
 extern std::vector<Profile> profiles;
 extern std::unordered_map<std::string, std::shared_ptr<CAConfig>> CAs;
 
@@ -78,7 +79,7 @@ public:
         int res = io->read( buffer.data(), buffer.capacity() );
 
         if( res <= 0 ) {
-            ( *log ) << "Stream error, resetting SSL" << std::endl;
+            logger::error( "Stream error, resetting SSL" );
             parent->reset();
             return;
         }
@@ -91,7 +92,7 @@ public:
             execute( head, payload );
         } catch( const char* msg ) {
             if( log ) {
-                ( *log ) << "ERROR: " << msg << std::endl;
+                logger::error( "ERROR: ", msg );
             }
 
             parent->reset();
@@ -108,13 +109,13 @@ public:
         case RecordHeader::SignerCommand::SET_CSR:
             tbs->csr_content = data;
             tbs->csr_type = "CSR";
-            ( *log ) << "INFO: CSR read: " << tbs->csr_content << std::endl;
+            logger::note( "INFO: CSR read:\n", tbs->csr_content );
             break;
 
         case RecordHeader::SignerCommand::SET_SPKAC:
             tbs->csr_content = data;
             tbs->csr_type = "SPKAC";
-            ( *log ) << "INFO: SPKAC read: " << tbs->csr_content << std::endl;
+            logger::note( "INFO: SPKAC read:\n", tbs->csr_content );
             break;
 
         case RecordHeader::SignerCommand::SET_SIGNATURE_TYPE:
@@ -134,41 +135,43 @@ public:
             tbs->wishTo = data;
             break;
 
-        case RecordHeader::SignerCommand::ADD_SAN: {
-            size_t pos = data.find( "," );
-
-            if( pos == std::string::npos ) {
-                // error
-            } else {
-                std::shared_ptr<SAN> san( new SAN() );
-                san->type = data.substr( 0, pos );
-                san->content = data.substr( pos + 1 );
-                tbs->SANs.push_back( san );
+        case RecordHeader::SignerCommand::ADD_SAN:
+            {
+                size_t pos = data.find( "," );
+
+                if( pos == std::string::npos ) {
+                    // error
+                } else {
+                    std::shared_ptr<SAN> san( new SAN() );
+                    san->type = data.substr( 0, pos );
+                    san->content = data.substr( pos + 1 );
+                    tbs->SANs.push_back( san );
+                }
             }
-        }
-        break;
-
-        case RecordHeader::SignerCommand::ADD_AVA: {
-            size_t pos = data.find( "," );
-
-            if( pos == std::string::npos ) {
-                // error
-            } else {
-                std::shared_ptr<AVA> ava( new AVA() );
-                ava->name = data.substr( 0, pos );
-                ava->value = data.substr( pos + 1 );
-                tbs->AVAs.push_back( ava );
+            break;
+
+        case RecordHeader::SignerCommand::ADD_AVA:
+            {
+                size_t pos = data.find( "," );
+
+                if( pos == std::string::npos ) {
+                    // error
+                } else {
+                    std::shared_ptr<AVA> ava( new AVA() );
+                    ava->name = data.substr( 0, pos );
+                    ava->value = data.substr( pos + 1 );
+                    tbs->AVAs.push_back( ava );
+                }
             }
-        }
-        break;
+            break;
 
         case RecordHeader::SignerCommand::ADD_PROOF_LINE:
             break;
 
         case RecordHeader::SignerCommand::SIGN:
             result = signer->sign( tbs );
-            ( *log ) << "INFO: signlog: " << result->log << std::endl;
-            ( *log ) << "INFO: res: " << result->certificate << std::endl;
+            logger::note( "INFO: signlog:\n", result->log );
+            logger::note( "INFO: res:\n", result->certificate );
             respondCommand( RecordHeader::SignerResult::SAVE_LOG, result->log );
             break;
 
@@ -179,8 +182,9 @@ public:
             }
 
             if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) {
-                ( *log ) << "ERROR: SSL close failed" << std::endl;
+                logger::warn( "ERROR: SSL shutdown failed." );
             }
+
             parent->reset(); // Connection ended
 
             break;
@@ -189,30 +193,32 @@ public:
             serials.push_back( data );
             break;
 
-        case RecordHeader::SignerCommand::REVOKE: {
-            std::string ca = data;
-            auto reqCA = CAs.at( ca );
-            ( *log ) << "CA found" << std::endl;
-            std::shared_ptr<CRL> crl;
-            std::string date;
-            std::tie<std::shared_ptr<CRL>, std::string>( crl, date ) = signer->revoke( reqCA, serials );
-
-            respondCommand( RecordHeader::SignerResult::REVOKED, date + crl->getSignature() );
+        case RecordHeader::SignerCommand::REVOKE:
+            {
+                std::string ca = data;
+                auto reqCA = CAs.at( ca );
+                logger::note( "CA found" );
+                std::shared_ptr<CRL> crl;
+                std::string date;
+                std::tie<std::shared_ptr<CRL>, std::string>( crl, date ) = signer->revoke( reqCA, serials );
 
+                respondCommand( RecordHeader::SignerResult::REVOKED, date + crl->getSignature() );
+            }
             break;
-        }
 
-        case RecordHeader::SignerCommand::GET_FULL_CRL: {
-            auto ca = CAs.at( data );
-            CRL c( ca->path + "/ca.crl" );
-            respondCommand( RecordHeader::SignerResult::FULL_CRL, c.toString() );
+        case RecordHeader::SignerCommand::GET_FULL_CRL:
+            {
+                auto ca = CAs.at( data );
+                CRL c( ca->path + "/ca.crl" );
+                respondCommand( RecordHeader::SignerResult::FULL_CRL, c.toString() );
 
-            if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) {
-                ( *log ) << "ERROR: SSL close failed" << std::endl;
+                if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) {
+                    logger::error( "ERROR: SSL shutdown failed." );
+                }
+
+                parent->reset(); // Connection ended
             }
-            parent->reset(); // Connection ended
             break;
-        }
 
         default:
             throw "Unimplemented";
@@ -220,8 +226,8 @@ public:
     }
 };
 
-DefaultRecordHandler::DefaultRecordHandler( std::shared_ptr<Signer> signer, std::shared_ptr<BIO> bio )
-    bio( bio ), ctx( generateSSLContext( true ) ), signer( signer ), currentSession() {
+DefaultRecordHandler::DefaultRecordHandler( std::shared_ptr<Signer> signer, std::shared_ptr<BIO> bio ) :
+    bio( bio ), ctx( generateSSLContext( true ) ), signer( signer ), currentSession() {
 }
 
 void DefaultRecordHandler::reset() {
@@ -230,7 +236,7 @@ void DefaultRecordHandler::reset() {
 
 void DefaultRecordHandler::handle() {
     if( !currentSession ) {
-        std::cout << "session allocated" << std::endl;
+        logger::note( "New session allocated." );
         currentSession = std::shared_ptr<RecordHandlerSession>( new RecordHandlerSession( this, signer, ctx, bio ) );
     }
 
index fb3f6c1925cbde5cb499008b1edfcb656fe1883d..4d0653e27b14f221cb25ff9d007cdd28721f6da4 100644 (file)
@@ -4,6 +4,8 @@
 
 #include <iostream>
 
+#include "log/logger.hpp"
+
 #define BUFFER_SIZE 8192
 
 #define SLIP_ESCAPE_CHAR ( (char) 0xDB)
@@ -51,7 +53,7 @@ SlipBIO::~SlipBIO() {}
 
 int SlipBIO::write( const char* buf, int num ) {
 #ifdef SLIP_IO_DEBUG
-    std::cout << "Out: " << toHex( buf, num ) << std::endl;
+    logger::debug( "Out: " << toHex( buf, num ) );
 #endif
 
     int badOnes = 0;
@@ -145,7 +147,7 @@ int SlipBIO::read( char* buf, int size ) {
     }
 
 #ifdef SLIP_IO_DEBUG
-    std::cout << "in: " << toHex( buf, len ) << std::endl;
+    logger::debug( "in: " << toHex( buf, len ) );
 #endif
 
     return len;
@@ -162,7 +164,7 @@ long SlipBIO::ctrl( int cmod, long arg1, void* arg2 ) {
         decodePos = 0;
         decodeTarget = 0;
         rawPos = 0;
-        std::cout << "resetting SLIP" << std::endl;
+        logger::note( "Resetting SLIP layer" );
         return 0;
     }
 
index 26de30aefa75f6dad29b3fa1d91d80ba98e05dda..27bfadb7950d2e452146a33614ddc59860759667 100644 (file)
@@ -3,7 +3,7 @@
 #include <memory>
 #include <vector>
 
-#include "bios.h"
+#include "io/bios.h"
 
 class SlipBIO : public OpensslBIO {
 private:
diff --git a/src/log/format.cpp b/src/log/format.cpp
new file mode 100644 (file)
index 0000000..1edd6a0
--- /dev/null
@@ -0,0 +1,107 @@
+#include "log/format.hpp"
+
+#include <algorithm>
+#include <cctype>
+#include <tuple>
+
+namespace logger {
+
+    namespace format {
+
+        inline namespace literals {
+
+            format_data operator"" _fmt( const char* it, std::size_t len ) {
+                const auto end = it + len;
+                auto retval = format_data {};
+
+                if( it == end ) {
+                    return retval;
+                }
+
+                if( *it == '0' or !std::isalnum( *it ) ) {
+                    retval.fill = *it;
+                    ++it;
+                }
+
+                if( it == end ) {
+                    return retval;
+                }
+
+                if( std::isdigit( *it ) ) {
+                    const auto w_end = std::find_if_not( it, end,
+                        []( char c ) {
+                            return std::isdigit( c );
+                        } );
+                    retval.width = std::stoul( std::string{it, w_end} );
+                    it = w_end;
+                }
+
+                if( it == end ) {
+                    return retval;
+                }
+
+                switch( *it ) {
+                case 's':
+                    break;
+
+                case 'd':
+                    retval.base = 10;
+                    break;
+
+                case 'x':
+                    retval.base = 16;
+                    break;
+
+                case 'o':
+                    retval.base = 8;
+                    break;
+
+                case 'l':
+                    retval.align_right = false;
+                    break;
+
+                case 'r':
+                    retval.align_right = true;
+                    break;
+
+                default:
+                    throw std::invalid_argument{"invalid format_data-string"};
+                }
+
+                ++it;
+
+                if( it != end ) {
+                    throw std::invalid_argument{"invalid format_data-string"};
+                }
+
+                return retval;
+            }
+
+        } // inline namespace literals
+
+    } // namespace format
+
+    namespace conv {
+
+        std::string to_string( const format::formated_string& arg ) {
+            if( arg.value.size() >= arg.width ) {
+                return arg.value;
+            }
+
+            auto str = std::string {};
+            str.reserve( arg.width );
+
+            if( arg.align_right ) {
+                str.append( arg.width - arg.value.size(), arg.fill );
+                str.append( arg.value );
+            } else {
+                str.append( arg.value );
+                str.append( arg.width - arg.value.size(), arg.fill );
+            }
+
+            return str;
+        }
+
+    } // namespace conv
+
+} // namespace logger
diff --git a/src/log/format.hpp b/src/log/format.hpp
new file mode 100644 (file)
index 0000000..827f7ea
--- /dev/null
@@ -0,0 +1,130 @@
+#pragma once
+
+#include <string>
+#include <sstream>
+#include <iomanip>
+#include <initializer_list>
+#include <tuple>
+
+namespace logger {
+
+    namespace format {
+
+        template <typename Integer>
+        struct formated_integer;
+        struct formated_string;
+
+        struct width_t {
+            explicit width_t( unsigned v ): value{v} {}
+            unsigned value = 0u;
+        };
+        struct base_t {
+            explicit base_t( unsigned v ): value{v} {}
+            unsigned value = 10u;
+        };
+        struct fill_t {
+            explicit fill_t( char v ): value{v} {}
+            char value = ' ';
+        };
+        enum class align_t {
+            left, right
+        };
+
+        inline namespace literals {
+            inline width_t operator"" _w( unsigned long long value ) {
+                return width_t{static_cast<unsigned>( value )};
+            }
+            inline base_t operator"" _b( unsigned long long value ) {
+                return base_t{static_cast<unsigned>( value )};
+            }
+            inline fill_t operator"" _f( char c ) {
+                return fill_t{c};
+            }
+        }
+
+        struct format_data {
+            unsigned width = 0;
+            std::uint8_t base = 10;
+            char fill = ' ';
+            bool align_right = false;
+
+            void set( width_t w ) {
+                width = w.value;
+            }
+            void set( base_t b ) {
+                base = b.value;
+            }
+            void set( fill_t f ) {
+                fill = f.value;
+            }
+            void set( align_t a ) {
+                align_right = ( a == align_t::right );
+            }
+
+            formated_string operator()( const std::string& str ) const;
+
+            template <typename Integer,
+                      typename = typename std::enable_if<std::is_integral<Integer>::value>::type>
+            formated_integer<Integer> operator()( Integer i ) const;
+        };
+
+        template <typename Integer>
+        struct formated_integer : public format_data {
+            formated_integer( Integer i, format_data f ) : format_data( f ), value {i} {}
+            Integer value;
+        };
+
+        struct formated_string : public format_data {
+            formated_string( const std::string& s, format_data f ) :
+                format_data( f ), value( std::move( s ) ) {}
+
+            const std::string& value;
+        };
+
+        inline formated_string format_data::operator()( const std::string& str ) const {
+            return {str, *this};
+        }
+
+        template <typename Integer, typename>
+        inline formated_integer<Integer> format_data::operator()( Integer i ) const {
+            return {i, *this};
+        }
+
+        template <typename... Args>
+        formated_string fmt( const std::string& str, const Args& ... args ) {
+            auto format = format_data{};
+            std::ignore = std::initializer_list<int>{( format.set( args ), 0 )...};
+            return format( str );
+        }
+
+        template <typename Integer, typename... Args>
+        formated_integer<Integer> fmt( const Integer i, const Args& ... args ) {
+            auto format = format_data{};
+            std::ignore = std::initializer_list<int>{( format.set( args ), 0 )...};
+            return format( i );
+        }
+
+        inline namespace literals {
+            format_data operator"" _fmt( const char*, std::size_t );
+        }
+
+    } // namespace format
+
+    namespace conv {
+
+        template <typename Integer>
+        inline std::string to_string( const format::formated_integer<Integer>& arg ) {
+            std::ostringstream stream;
+            stream <<
+                std::setbase( arg.base ) <<
+                std::setw( arg.width ) <<
+                std::setfill( arg.fill ) <<
+                arg.value;
+            return stream.str();
+        }
+
+        std::string to_string( const format::formated_string& arg );
+
+    } // namespace conf
+
+} // namespace logger
diff --git a/src/log/logger.cpp b/src/log/logger.cpp
new file mode 100644 (file)
index 0000000..aee4d29
--- /dev/null
@@ -0,0 +1,274 @@
+#include "log/logger.hpp"
+
+#include <cassert>
+#include <iterator>
+#include <algorithm>
+#include <chrono>
+#include <cstring>
+#include <ostream>
+#include <iterator>
+
+namespace logger {
+
+    namespace impl {
+
+        /**
+         * Manages the standard-logger and the logger-stack.
+         *
+         * CAREFULL: THIS FUNCTION CONTAINS GLOBAL STATE!
+         */
+        std::vector<logger_set*>& logger_stack() {
+            static auto stack = std::vector<logger_set*> {};
+            // To avoid infinite recursion, the base-logger must
+            // not auto-register but be added manually
+            static auto std_logger = logger_set {{std::cout}, auto_register::off};
+            // in order to avoid use-after-free bugs, the logger must be created after
+            // the stack, to avoid that it's destructor tries to access
+            // parts of the destroyed stack
+
+            static auto dummy = [&] {
+                stack.push_back( &std_logger );
+                return 0;
+            }();
+
+            ( void ) dummy;
+            return stack;
+        }
+
+        void reassign_stack_pointer( logger_set*& ptr ) {
+            const auto old_ptr = ptr;
+
+            if( ptr ) {
+                ptr->m_stackpointer = &ptr;
+            }
+
+            ( void ) old_ptr;
+            assert( ptr == old_ptr );
+        }
+
+        void register_logger( logger_set& set ) {
+            auto& stack = logger_stack();
+
+            // we need to reassign everything if the vector reallocated:
+            const auto old_capacity = stack.capacity();
+            stack.push_back( &set );
+
+            if( stack.capacity() == old_capacity ) {
+                reassign_stack_pointer( stack.back() );
+            } else {
+                for( auto& ptr : stack ) {
+                    reassign_stack_pointer( ptr );
+                }
+            }
+        }
+
+        /**
+         * Pops loggers from the stack until the last one is not a nullptr
+         */
+        void pop_loggers() {
+            auto& stack = logger_stack();
+
+            while( !stack.empty() and stack.back() == nullptr ) {
+                stack.pop_back();
+            }
+
+            assert( stack.empty() or stack.back() != nullptr );
+        }
+
+        logger_set& active_logger() {
+            const auto result = logger_stack().back();
+            assert( result != nullptr );
+            return *result;
+        }
+
+    } // namespace impl
+
+    logger_set::logger_set( std::initializer_list<log_target> lst, auto_register r ):
+        m_loggers{lst}, m_min_level{default_level} {
+        if( lst.size() > 0 ) {
+            m_min_level = std::min_element( lst.begin(), lst.end(),
+                []( const log_target& l, const log_target& r ) {
+                    return l.min_level < r.min_level;
+                } )->min_level;
+        }
+
+        if( r == auto_register::on ) {
+            impl::register_logger( *this );
+        }
+    }
+
+    logger_set::~logger_set() {
+        if( m_stackpointer ) {
+            *m_stackpointer = nullptr;
+            impl::pop_loggers();
+        }
+    }
+
+    logger_set::logger_set( logger_set&& other ) noexcept :
+        m_loggers{std::move( other.m_loggers )}, m_stackpointer{other.m_stackpointer}, m_min_level{other.m_min_level} {
+        other.m_stackpointer = nullptr;
+
+        if( m_stackpointer ) {
+            *m_stackpointer = this;
+        }
+    }
+
+    logger_set& logger_set::operator=( logger_set && other ) noexcept {
+        if( m_stackpointer ) {
+            *m_stackpointer = nullptr;
+            impl::pop_loggers();
+        }
+
+        m_loggers = std::move( other.m_loggers );
+        m_stackpointer = other.m_stackpointer;
+        m_min_level = other.m_min_level;
+        other.m_stackpointer = nullptr;
+
+        if( m_stackpointer ) {
+            *m_stackpointer = this;
+        }
+
+        return *this;
+    }
+
+    void logger_set::log_impl( level l, const std::string& msg ) {
+        for( auto& logger : m_loggers ) {
+            if( l >= logger.min_level ) {
+                *logger.stream << msg << std::flush;
+            }
+        }
+    }
+
+    logger_set current_logger_extended( std::initializer_list<log_target> further_targets ) {
+        auto& active = impl::active_logger();
+        auto returnvalue = logger_set{further_targets};
+        returnvalue.m_loggers.insert( returnvalue.m_loggers.end(), active.m_loggers.begin(), active.m_loggers.end() );
+        returnvalue.m_min_level = active.m_min_level;
+        return returnvalue;
+    }
+
+    namespace {
+
+        std::string make_prefix( level l ) {
+            auto prefix = std::string {};
+
+            switch( l ) {
+            case level::debug:
+                prefix = "[debug][";
+                break;
+
+            case level::note:
+                prefix = "[note ][";
+                break;
+
+            case level::warn:
+                prefix = "[warn ][";
+                break;
+
+            case level::error:
+                prefix = "[error][";
+                break;
+
+            case level::fatal:
+                prefix = "[fatal][";
+                break;
+            }
+
+            using clock = std::chrono::system_clock;
+            const auto now = clock::to_time_t( clock::now() );
+            // ctime appends a newline, we don't want that here:
+            auto time_str = std::ctime( &now );
+            prefix.append( time_str, time_str + std::strlen( time_str ) - 1 );
+            prefix += "]: ";
+            return prefix;
+        }
+
+    } // anonymous namespace
+
+    namespace impl {
+
+        std::string replace_newlines( const std::string& str, std::size_t length ) {
+            auto returnstring = std::string {};
+            auto it = str.begin();
+            const auto end = str.end();
+            auto nl_it = it;
+
+            while( ( nl_it = std::find( it, end, '\n' ) ) != end ) {
+                ++nl_it;
+                returnstring.append( it, nl_it );
+                returnstring.append( length, ' ' );
+                it = nl_it;
+            }
+
+            returnstring.append( it, end );
+            return returnstring;
+        }
+
+
+        std::string concat_msg( level l, const std::vector<std::string>& args ) {
+            auto msg = make_prefix( l );
+            const auto prefix_length = msg.length();
+
+            for( const auto& arg : args ) {
+                msg += replace_newlines( arg, prefix_length );
+            }
+
+            msg += '\n';
+            return msg;
+        }
+
+        std::string format_msg( level l, const std::string& format, std::vector<std::string> args ) {
+            const auto prefix = make_prefix( l );
+            const auto length = prefix.length();
+            const auto fmt = replace_newlines( format, length );
+            std::transform( args.begin(), args.end(), args.begin(),
+                [length]( const std::string & str ) {
+                    return replace_newlines( str, length );
+                } );
+
+            auto msg = prefix;
+            auto arg_index = std::size_t {0};
+            auto it = fmt.begin();
+            const auto end = fmt.end();
+
+            while( it != end ) {
+                auto pos = std::find( it, end, '%' );
+                msg.append( it, pos );
+
+                if( pos == end ) {
+                    break;
+                }
+
+                ++pos;
+
+                if( pos == end ) {
+                    throw std::invalid_argument {"Invalid formatstring (ends on single '%')"};
+                }
+
+                switch( *pos ) {
+                case '%':
+                    msg.push_back( '%' );
+                    break;
+
+                case 's':
+                    if( arg_index >= args.size() ) {
+                        throw std::invalid_argument {"Invalid formatstring (not enough arguments)"};
+                    }
+
+                    msg.append( args[arg_index++] );
+                    break;
+
+                default:
+                    throw std::invalid_argument {"Invalid formatstring (unknown format-character)"};
+                }
+
+                it = std::next( pos );
+            }
+
+            msg.push_back( '\n' );
+            return msg;
+        }
+
+    } //  namespace impl
+
+} // namespace logger
diff --git a/src/log/logger.hpp b/src/log/logger.hpp
new file mode 100644 (file)
index 0000000..aabbb67
--- /dev/null
@@ -0,0 +1,241 @@
+#pragma once
+
+#include <algorithm>
+#include <iomanip>
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <fstream>
+#include <stdexcept>
+
+namespace logger {
+
+    /**
+     * conv::to_string will be used to convert whatever argument is send
+     * to the logger to a string. If another type shall be supported,
+     * just add the appropriate overload and you can start using it right
+     * away. The default conversion will use a stringstream.
+     */
+    namespace conv {
+        template <typename T>
+        inline std::string to_string( const T& arg ) {
+            std::ostringstream stream;
+            stream << arg;
+            return stream.str();
+        }
+        inline std::string to_string( std::string&& arg ) {
+            return arg;
+        }
+        inline std::string to_string( const std::string& arg ) {
+            return arg;
+        }
+        inline std::string to_string( const char* arg ) {
+            return arg;
+        }
+
+    } // namespace conv
+
+    enum class level {
+        debug, note, warn, error, fatal
+    };
+
+    const auto default_level = level::note;
+
+    struct log_target {
+        log_target( std::ostream& stream, level min_level = default_level ):
+            stream {&stream}, min_level {min_level} {}
+        log_target( std::ofstream& stream, level min_level = default_level ):
+            stream {&stream}, min_level {min_level} {
+            if( !stream.is_open() ) {
+                throw std::runtime_error {"logfile not open"};
+            }
+        }
+        std::ostream* stream;
+        level min_level;
+    };
+
+    class logger_set;
+    namespace impl {
+        void reassign_stack_pointer( logger_set*& ptr );
+    }
+
+    /**
+     * Provides controll over wether a logger should automatically register itself
+     */
+    enum class auto_register {
+        on, off
+    };
+
+    class logger_set {
+    public:
+        logger_set( std::initializer_list<log_target> lst, auto_register = auto_register::on );
+
+        logger_set( logger_set&& ) noexcept;
+        logger_set& operator=( logger_set && ) noexcept;
+        ~logger_set();
+
+        template<typename... Args>
+        void log( level l, Args&& ... args );
+        template<typename... Args>
+        void logf( level l, const std::string& format, Args&& ... args );
+
+        template<typename... Args>
+        void debug( Args&& ... args );
+        template<typename... Args>
+        void debugf( const std::string& format, Args&& ... args );
+
+        template<typename... Args>
+        void note( Args&& ... args );
+        template<typename... Args>
+        void notef( const std::string& format, Args&& ... args );
+
+        template<typename... Args>
+        void warn( Args&& ... args );
+        template<typename... Args>
+        void warnf( const std::string& format, Args&& ... args );
+
+        template<typename... Args>
+        void error( Args&& ... args );
+        template<typename... Args>
+        void errorf( const std::string& format, Args&& ... args );
+
+        template<typename... Args>
+        void fatal( Args&& ... args );
+        template<typename... Args>
+        void fatalf( const std::string& format, Args&& ... args );
+
+        friend void impl::reassign_stack_pointer( logger_set*& ptr );
+        friend logger_set current_logger_extended( std::initializer_list<log_target> further_targets );
+    private:
+        void log_impl( level l, const std::string& msg );
+
+        std::vector<log_target> m_loggers;
+        logger_set** m_stackpointer = nullptr;
+        level m_min_level;
+    };
+
+    logger_set current_logger_extended( std::initializer_list<log_target> further_targets );
+
+    namespace impl {
+        std::string concat_msg( level l, const std::vector<std::string>& args );
+        std::string format_msg( level l, const std::string&, std::vector<std::string> args );
+        logger_set& active_logger();
+    }
+
+    template <typename... Args>
+    void logger_set::log( level l, Args&& ... data ) {
+        if( l < m_min_level ) {
+            return;
+        }
+
+        log_impl( l, impl::concat_msg( l, {conv::to_string( std::forward<Args>( data ) )...} ) );
+    }
+
+    template <typename... Args>
+    void logger_set::logf( level l, const std::string& format, Args&& ... data ) {
+        if( l < m_min_level ) {
+            return;
+        }
+
+        log_impl( l, impl::format_msg( l, format, {conv::to_string( std::forward<Args>( data ) )...} ) );
+    }
+
+    template <typename... Args>
+    void log( level l, Args&& ... args ) {
+        impl::active_logger().log( l, std::forward<Args>( args )... );
+    }
+    template <typename... Args>
+    void logf( level l, const std::string& format, Args&& ... args ) {
+        impl::active_logger().logf( l, format, std::forward<Args>( args )... );
+    }
+
+    // concat-based methods
+    template <typename... Args>
+    void logger_set::debug( Args&& ... args ) {
+        log( level::debug, std::forward<Args>( args )... );
+    }
+    template <typename... Args>
+    void logger_set::note( Args&& ... args ) {
+        log( level::note, std::forward<Args>( args )... );
+    }
+    template <typename... Args>
+    void logger_set::warn( Args&& ... args ) {
+        log( level::warn, std::forward<Args>( args )... );
+    }
+    template <typename... Args>
+    void logger_set::error( Args&& ... args ) {
+        log( level::error, std::forward<Args>( args )... );
+    }
+    template <typename... Args>
+    void logger_set::fatal( Args&& ... args ) {
+        log( level::fatal, std::forward<Args>( args )... );
+    }
+
+    // format-based methods
+    template <typename... Args>
+    void logger_set::debugf( const std::string& fmt, Args&& ... args ) {
+        logf( level::debug, fmt, std::forward<Args>( args )... );
+    }
+    template <typename... Args>
+    void logger_set::notef( const std::string& fmt, Args&& ... args ) {
+        logf( level::note, fmt, std::forward<Args>( args )... );
+    }
+    template <typename... Args>
+    void logger_set::warnf( const std::string& fmt, Args&& ... args ) {
+        logf( level::warn, fmt, std::forward<Args>( args )... );
+    }
+    template <typename... Args>
+    void logger_set::errorf( const std::string& fmt, Args&& ... args ) {
+        logf( level::error, fmt, std::forward<Args>( args )... );
+    }
+    template <typename... Args>
+    void logger_set::fatalf( const std::string& fmt, Args&& ... args ) {
+        logf( level::fatal, fmt, std::forward<Args>( args )... );
+    }
+
+    // global concat-based
+    template <typename... Args>
+    void debug( Args&& ... args ) {
+        log( level::debug, std::forward<Args>( args )... );
+    }
+    template <typename... Args>
+    void note( Args&& ... args ) {
+        log( level::note, std::forward<Args>( args )... );
+    }
+    template <typename... Args>
+    void warn( Args&& ... args ) {
+        log( level::warn, std::forward<Args>( args )... );
+    }
+    template <typename... Args>
+    void error( Args&& ... args ) {
+        log( level::error, std::forward<Args>( args )... );
+    }
+    template <typename... Args>
+    void fatal( Args&& ... args ) {
+        log( level::fatal, std::forward<Args>( args )... );
+    }
+
+    // global format-based
+    template <typename... Args>
+    void debugf( const std::string& fmt, Args&& ... args ) {
+        logf( level::debug, fmt, std::forward<Args>( args )... );
+    }
+    template <typename... Args>
+    void notef( const std::string& fmt, Args&& ... args ) {
+        logf( level::note, fmt, std::forward<Args>( args )... );
+    }
+    template <typename... Args>
+    void warnf( const std::string& fmt, Args&& ... args ) {
+        logf( level::warn, fmt, std::forward<Args>( args )... );
+    }
+    template <typename... Args>
+    void errorf( const std::string& fmt, Args&& ... args ) {
+        logf( level::error, fmt, std::forward<Args>( args )... );
+    }
+    template <typename... Args>
+    void fatalf( const std::string& fmt, Args&& ... args ) {
+        logf( level::fatal, fmt, std::forward<Args>( args )... );
+    }
+
+}
index c16ba1c6c8d541164fc5ff7fd540aadb74d1e7fa..9e24b378d834c6e3ad6a356b3f9a48b533fb1751 100644 (file)
@@ -138,7 +138,6 @@ std::pair<bool, time_t> addMonths( std::time_t t, int32_t count ) {
     }
 
     return std::pair<bool, time_t>( true, res );
-
 }
 
 std::pair<bool, time_t> parseMonthInterval( std::time_t t, const std::string& date ) {
@@ -161,6 +160,7 @@ std::pair<bool, time_t> parseMonthInterval( std::time_t t, const std::string& da
         return std::pair<bool, time_t>( false, 0 );
     }
 }
+
 std::pair<bool, time_t> parseYearInterval( std::time_t t, const std::string& date ) {
     if( date[date.size() - 1] != 'y' ) {
         return  std::pair<bool, time_t>( false, 0 );
@@ -182,20 +182,24 @@ std::pair<bool, time_t> parseYearInterval( std::time_t t, const std::string& dat
     }
 }
 
-std::shared_ptr<std::ofstream> openLogfile( const std::string name) {
+std::shared_ptr<std::ofstream> openLogfile( const std::string name ) {
     struct stat buffer;
     std::string tname = name;
     int ctr = 2;
-    while(stat (tname.c_str(), &buffer) == 0) {
-        tname = name + "_" + std::to_string(ctr++);
+
+    while( stat( tname.c_str(), &buffer ) == 0 ) {
+        tname = name + "_" + std::to_string( ctr++ );
     }
-    auto res = std::shared_ptr<std::ofstream>(new std::ofstream( tname ),
-        [](std::ofstream *p){
+
+    auto res = std::shared_ptr<std::ofstream>( new std::ofstream( tname ),
+        []( std::ofstream * p ) {
             p->close();
             delete p;
-        });
-    if(! res->good() ){
-        throw std::string("Failed to open file for logging: ") + name;
+        } );
+
+    if( ! res->good() ) {
+        throw std::string( "Failed to open file for logging: " ) + name;
     }
+
     return res;
 }
index d59991042c1c00ed1fedf63c43073732581a2997..04448d402d6ccfb6bd87b721d11c9962931e0ecc 100644 (file)
@@ -13,5 +13,4 @@ std::pair<bool, std::time_t> parseDate( const std::string& date );
 std::pair<bool, std::time_t> parseMonthInterval( std::time_t t, const std::string& date );
 std::pair<bool, std::time_t> parseYearInterval( std::time_t t, const std::string& date );
 
-
-std::shared_ptr<std::ofstream> openLogfile( const std::string name);
+std::shared_ptr<std::ofstream> openLogfile( const std::string name );
diff --git a/test/src/log.cpp b/test/src/log.cpp
new file mode 100644 (file)
index 0000000..c95df53
--- /dev/null
@@ -0,0 +1,392 @@
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+
+#include <boost/test/unit_test.hpp>
+
+#include "log/logger.hpp"
+#include "log/format.hpp"
+
+BOOST_AUTO_TEST_SUITE( TestLogger )
+
+static inline bool head_and_tail_equal( const std::string& str, const std::string& head, const std::string& tail ) {
+    return str.size() >= head.size() + tail.size()
+            and std::equal( head.begin(), head.end(), str.begin() )
+            and std::equal( tail.rbegin(), tail.rend(), str.rbegin() )
+            ;
+}
+
+BOOST_AUTO_TEST_CASE( basic_log ) {
+    std::ostringstream stream{};
+    auto logger = logger::logger_set{stream};
+
+    logger.log( logger::level::note, "foo", " bar ", 23, ' ', 42.0, " baz" );
+
+    BOOST_CHECK( head_and_tail_equal( stream.str(), "[note ][", "]: foo bar 23 42 baz\n" ) );
+}
+
+BOOST_AUTO_TEST_CASE( basic_logf ) {
+    std::ostringstream stream{};
+    auto logger = logger::logger_set{stream};
+
+    logger.logf( logger::level::note, "bla%sblub%s%%", "foo", 42 );
+
+    BOOST_CHECK( head_and_tail_equal( stream.str(), "[note ][", "]: blafooblub42%\n" ) );
+}
+
+BOOST_AUTO_TEST_CASE( log_hiding ) {
+    std::ostringstream stream1{};
+    auto logger1 = logger::logger_set{stream1};
+
+    std::ostringstream stream2{};
+    auto logger2 = logger::logger_set{stream2};
+
+    logger::note( "foobar" );
+
+    BOOST_CHECK( stream1.str().empty() );
+    BOOST_CHECK( head_and_tail_equal( stream2.str(), "[note ][", "]: foobar\n" ) );
+}
+
+BOOST_AUTO_TEST_CASE( log_restoration ) {
+    std::ostringstream stream1{};
+    auto logger1 = logger::logger_set{stream1};
+
+    {
+        std::ostringstream stream2{};
+        auto logger2 = logger::logger_set{stream2};
+    }
+
+    logger::note( "foobar" );
+
+    BOOST_CHECK( head_and_tail_equal( stream1.str(), "[note ][", "]: foobar\n" ) );
+}
+
+BOOST_AUTO_TEST_CASE( non_global_log ) {
+    std::ostringstream stream1{};
+    auto logger1 = logger::logger_set{stream1};
+
+    std::ostringstream stream2{};
+    auto logger2 = logger::logger_set{{stream2}, logger::auto_register::off};
+
+    logger::note( "foobar" );
+
+    BOOST_CHECK( head_and_tail_equal( stream1.str(), "[note ][", "]: foobar\n" ) );
+    BOOST_CHECK( stream2.str().empty() );
+}
+
+BOOST_AUTO_TEST_CASE( concat_alias_methods ) {
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{{stream, logger::level::debug}};
+
+        logger.debug( "foo" );
+
+        BOOST_CHECK( head_and_tail_equal( stream.str(), "[debug][", "]: foo\n" ) );
+    }
+
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{{stream, logger::level::note}};
+
+        logger.note( "foo" );
+
+        BOOST_CHECK( head_and_tail_equal( stream.str(), "[note ][", "]: foo\n" ) );
+    }
+
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{{stream, logger::level::warn}};
+
+        logger.warn( "foo" );
+
+        BOOST_CHECK( head_and_tail_equal( stream.str(), "[warn ][", "]: foo\n" ) );
+    }
+
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{{stream, logger::level::error}};
+
+        logger.error( "foo" );
+
+        BOOST_CHECK( head_and_tail_equal( stream.str(), "[error][", "]: foo\n" ) );
+    }
+
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{{stream, logger::level::fatal}};
+
+        logger.fatal( "foo" );
+
+        BOOST_CHECK( head_and_tail_equal( stream.str(), "[fatal][", "]: foo\n" ) );
+    }
+}
+
+BOOST_AUTO_TEST_CASE( format_alias_methods ) {
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{{stream, logger::level::debug}};
+
+        logger.debugf( "foo" );
+
+        BOOST_CHECK( head_and_tail_equal( stream.str(), "[debug][", "]: foo\n" ) );
+    }
+
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{{stream, logger::level::note}};
+
+        logger.notef( "foo" );
+
+        BOOST_CHECK( head_and_tail_equal( stream.str(), "[note ][", "]: foo\n" ) );
+    }
+
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{{stream, logger::level::warn}};
+
+        logger.warnf( "foo" );
+
+        BOOST_CHECK( head_and_tail_equal( stream.str(), "[warn ][", "]: foo\n" ) );
+    }
+
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{{stream, logger::level::error}};
+
+        logger.errorf( "foo" );
+
+        BOOST_CHECK( head_and_tail_equal( stream.str(), "[error][", "]: foo\n" ) );
+    }
+
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{{stream, logger::level::fatal}};
+
+        logger.fatalf( "foo" );
+
+        BOOST_CHECK( head_and_tail_equal( stream.str(), "[fatal][", "]: foo\n" ) );
+    }
+}
+
+BOOST_AUTO_TEST_CASE( concat_alias_functions ) {
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{{stream, logger::level::debug}};
+
+        logger::debug( "foo" );
+
+        BOOST_CHECK( head_and_tail_equal( stream.str(), "[debug][", "]: foo\n" ) );
+    }
+
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{{stream, logger::level::note}};
+
+        logger::note( "foo" );
+
+        BOOST_CHECK( head_and_tail_equal( stream.str(), "[note ][", "]: foo\n" ) );
+    }
+
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{{stream, logger::level::warn}};
+
+        logger::warn( "foo" );
+
+        BOOST_CHECK( head_and_tail_equal( stream.str(), "[warn ][", "]: foo\n" ) );
+    }
+
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{{stream, logger::level::error}};
+
+        logger::error( "foo" );
+
+        BOOST_CHECK( head_and_tail_equal( stream.str(), "[error][", "]: foo\n" ) );
+    }
+
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{{stream, logger::level::fatal}};
+
+        logger::fatal( "foo" );
+
+        BOOST_CHECK( head_and_tail_equal( stream.str(), "[fatal][", "]: foo\n" ) );
+    }
+}
+
+BOOST_AUTO_TEST_CASE( format_alias_functions ) {
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{{stream, logger::level::debug}};
+
+        logger::debugf( "foo" );
+
+        BOOST_CHECK( head_and_tail_equal( stream.str(), "[debug][", "]: foo\n" ) );
+    }
+
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{{stream, logger::level::note}};
+
+        logger::notef( "foo" );
+
+        BOOST_CHECK( head_and_tail_equal( stream.str(), "[note ][", "]: foo\n" ) );
+    }
+
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{{stream, logger::level::warn}};
+
+        logger::warnf( "foo" );
+
+        BOOST_CHECK( head_and_tail_equal( stream.str(), "[warn ][", "]: foo\n" ) );
+    }
+
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{{stream, logger::level::error}};
+
+        logger::errorf( "foo" );
+
+        BOOST_CHECK( head_and_tail_equal( stream.str(), "[error][", "]: foo\n" ) );
+    }
+
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{{stream, logger::level::fatal}};
+
+        logger::fatalf( "foo" );
+
+        BOOST_CHECK( head_and_tail_equal( stream.str(), "[fatal][", "]: foo\n" ) );
+    }
+}
+
+BOOST_AUTO_TEST_CASE( formatting_exceptions ) {
+    std::ostringstream stream{};
+    auto logger = logger::logger_set{stream};
+
+    BOOST_CHECK_THROW( logger.notef( "%" ), std::invalid_argument );
+    BOOST_CHECK_THROW( logger.notef( "%s" ), std::invalid_argument );
+    BOOST_CHECK_THROW( logger.notef( "%e" ), std::invalid_argument );
+}
+
+BOOST_AUTO_TEST_CASE( multiple_calls ) {
+    std::ostringstream stream{};
+    auto logger = logger::logger_set{stream};
+
+    logger::note( "foo1" );
+    logger::debug( "foo2" );
+    logger::warn( "foo3" );
+    logger::note( "foo4" );
+
+    const auto result = stream.str();
+
+    const auto foo1 = result.find( "foo1" );
+    const auto foo2 = result.find( "foo2" );
+    const auto foo3 = result.find( "foo3" );
+    const auto foo4 = result.find( "foo4" );
+
+    BOOST_CHECK_LT( foo1, foo3 );
+    BOOST_CHECK_LT( foo3, foo4 );
+    BOOST_CHECK_NE( foo4, std::string::npos );
+    BOOST_CHECK_EQUAL( foo2, std::string::npos );
+}
+
+BOOST_AUTO_TEST_CASE( multiple_calls_nested ) {
+    std::ostringstream stream{};
+    auto logger = logger::logger_set{stream};
+
+    logger::note( "foo1" );
+
+    {
+        std::ostringstream stream{};
+        auto logger = logger::logger_set{stream};
+
+        logger::note( "foo2" );
+    }
+
+    logger::note( "foo3" );
+
+    const auto result = stream.str();
+    const auto foo1 = result.find( "foo1" );
+    const auto foo2 = result.find( "foo2" );
+    const auto foo3 = result.find( "foo3" );
+
+    BOOST_CHECK_LT( foo1, foo3 );
+    BOOST_CHECK_NE( foo3, std::string::npos );
+    BOOST_CHECK_EQUAL( foo2, std::string::npos );
+}
+
+BOOST_AUTO_TEST_CASE( extending_current_logger ) {
+    std::ostringstream stream1{};
+    auto logger1 = logger::logger_set{stream1};
+
+    std::ostringstream stream2{};
+    {
+        auto logger2 = logger::current_logger_extended( {stream2} );
+        logger::note( "foo1" );
+    }
+
+    BOOST_CHECK( head_and_tail_equal( stream1.str(), "[note ][", "]: foo1\n" ) );
+    BOOST_CHECK( head_and_tail_equal( stream2.str(), "[note ][", "]: foo1\n" ) );
+
+    stream1.str( "" );
+    stream2.str( "" );
+
+    logger::note( "foo2" );
+
+    BOOST_CHECK( head_and_tail_equal( stream1.str(), "[note ][", "]: foo2\n" ) );
+    BOOST_CHECK( stream2.str().empty() );
+}
+
+BOOST_AUTO_TEST_CASE( closed_filestream_exception ) {
+    std::ofstream stream;
+
+    BOOST_CHECK_THROW( logger::logger_set {stream}, std::runtime_error );
+}
+
+BOOST_AUTO_TEST_CASE( formated_strings ) {
+    using namespace logger::format::literals;
+    using logger::conv::to_string;
+
+    BOOST_CHECK_EQUAL( to_string( ""_fmt( "foo" ) ), "foo" );
+    BOOST_CHECK_EQUAL( to_string( "_3"_fmt( "foo" ) ), "foo" );
+    BOOST_CHECK_EQUAL( to_string( "_6"_fmt( "foo" ) ), "foo___" );
+    BOOST_CHECK_EQUAL( to_string( "_10l"_fmt( "foo" ) ), "foo_______" );
+    BOOST_CHECK_EQUAL( to_string( "_10r"_fmt( "foo" ) ), "_______foo" );
+}
+
+BOOST_AUTO_TEST_CASE( formated_ints ) {
+    using namespace logger::format::literals;
+    using logger::conv::to_string;
+
+    BOOST_CHECK_EQUAL( to_string( ""_fmt( 3 ) ), "3" );
+    BOOST_CHECK_EQUAL( to_string( "03"_fmt( 3 ) ), "003" );
+    BOOST_CHECK_EQUAL( to_string( "03"_fmt( 13 ) ), "013" );
+    BOOST_CHECK_EQUAL( to_string( "03x"_fmt( 13 ) ), "00d" );
+    BOOST_CHECK_EQUAL( to_string( "03o"_fmt( 13 ) ), "015" );
+    BOOST_CHECK_EQUAL( to_string( "03d"_fmt( 13 ) ), "013" );
+    BOOST_CHECK_EQUAL( to_string( "03s"_fmt( 13 ) ), "013" );
+}
+
+BOOST_AUTO_TEST_CASE( formated_ints_variadic_api ) {
+    using logger::conv::to_string;
+    using logger::format::fmt;
+
+    BOOST_CHECK_EQUAL( to_string( fmt( 3 ) ), "3" );
+    BOOST_CHECK_EQUAL( to_string( fmt( 3, logger::format::width_t {3} ) ), "  3" );
+}
+
+BOOST_AUTO_TEST_CASE( formated_ints_variadic_api_literals ) {
+    using logger::conv::to_string;
+    using logger::format::fmt;
+
+    using namespace logger::format::literals;
+
+    BOOST_CHECK_EQUAL( to_string( fmt( 3 ) ), "3" );
+    BOOST_CHECK_EQUAL( to_string( fmt( 3, 3_w ) ), "  3" );
+    BOOST_CHECK_EQUAL( to_string( fmt( 10, 3_w, 8_b, 'x'_f ) ), "x12" );
+}
+
+BOOST_AUTO_TEST_SUITE_END()