Updated LogFiles and TextBrowser relative functions

This commit is contained in:
Valentino Orlandi 2022-06-24 19:56:34 +02:00
parent 21ac8144e3
commit 3cf93b2c3b
Signed by: elB4RTO
GPG Key ID: 1719E976DB2D4E71
12 changed files with 384 additions and 89 deletions

View File

@ -26,14 +26,13 @@ set(PROJECT_SOURCES
mainwindow.ui
tools/craplog.h
tools/craplog.cpp
utilities.h
utilities/io.h
utilities/io.cpp
utilities/strings.h
utilities/strings.cpp
utilities/rtf.h
utilities/rtf.cpp
utilities/logs.h
utilities/logs.cpp
resources/resources.qrc
${TS_FILES}
)

View File

@ -1,6 +1,8 @@
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <iostream>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
@ -51,7 +53,9 @@ void MainWindow::on_buttonRefreshList_clicked()
// clear the current tree
this->ui->listLogFiles->clear();
// iterate over elements of list
std::cout << "OOOOOOOOOOOOOOOOOK" << std::endl;
for ( const Craplog::LogFile& log_file : this->craplog.getLogsList(true) ) {
std::cout << "XXXXXXXXXXXXXXXXXXXXXXXK" << std::endl;
// new entry for the tree widget
QTreeWidgetItem * item = new QTreeWidgetItem();
// set unchecked
@ -124,10 +128,26 @@ void MainWindow::on_checkAllLogFiles_stateChanged(int arg1)
void MainWindow::on_buttonViewFile_clicked()
{
QString file_name = this->ui->listLogFiles->selectedItems().takeFirst()->text(0);
/*QString file_name = this->ui->listLogFiles->selectedItems().takeFirst()->text(0);
std::string file_path = this->craplog.getLogFilePath( file_name );
std::string content = IOutils::readFile( file_path );
this->ui->textLogFiles->setText( RichText::enrichLogs( content, this->TB_color_scheme ) );
this->ui->textLogFiles->setText( RichText::enrichLogs( content, this->TB_color_scheme ) );*/
Craplog::LogFile item = this->craplog.getLogFileItem(
this->ui->listLogFiles->selectedItems().takeFirst()->text(0) );
Craplog::LogsFormat format;
if ( item.type == Craplog::LogType::Access ) {
format = this->craplog.getAccessLogsFormat();
} else if ( item.type == Craplog::LogType::Error ) {
format = this->craplog.getErrorLogsFormat();
} else {
// this shouldn't be
// !!! PUT A DIALOG ERROR MESSAGE HERE !!!
}
this->ui->textLogFiles->setText(
RichText::enrichLogs(
IOutils::readFile( item.path ),
format,
this->TB_color_scheme ));
this->ui->textLogFiles->setFont( this->FONTS["main"] );
}

View File

@ -7,8 +7,7 @@
#include "qtreewidget.h"
#include "utilities/io.h"
#include "utilities/rtf.h"
#include "utilities.h"
#include "tools/craplog.h"
QT_BEGIN_NAMESPACE
@ -18,32 +17,32 @@ QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_buttonViewFile_clicked();
void on_checkAllLogFiles_stateChanged(int arg1);
void on_buttonRefreshList_clicked();
void on_listLogFiles_itemDoubleClicked(QTreeWidgetItem *item, int column);
void on_listLogFiles_itemChanged(QTreeWidgetItem *item, int column);
private:
Ui::MainWindow *ui;
Craplog craplog;
bool runCraplog();
std::unordered_map<std::string, QColor> COLORS;
std::unordered_map<std::string, QColor> COLORS;
std::unordered_map<std::string, QFont> FONTS;
int font_size, font_size_big, font_size_small;
int TB_color_scheme;
};
#endif // MAINWINDOW_H

View File

@ -1,14 +1,31 @@
#include "craplog.h"
#include "utilities/io.h"
#include "utilities/logs.h"
#include "utilities.h"
#include <filesystem>
#include <iostream>
Craplog::Craplog()
{
this->access_logs_format = Craplog::LogsFormat::AccessCombined;
this->error_logs_format = Craplog::LogsFormat::ErrorDefault;
this->access_logs_format = Craplog::LogsFormat{
.format = Craplog::Format::Combined,
.string = "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"",
.initial = "",
.final = "\"",
.separators = {" ", " ", " ", " \"", "\" ", " ", " \"", "\" \""},
.fields = {"client","logname","user","date_time","request","response_code","http_size","referer","user_agent"}
};
this->error_logs_format = Craplog::LogsFormat{
.format = Craplog::Format::Default,
.string = "[%t] [%l] [pid %P] %F: %E: [client %a] %M",
.initial = "[",
.final = "",
.separators = {"] [", "] [pid", "] ", ": ", ": [client ", "] "},
.fields = {"date_time","error_level","pid","source_file","os_err","client:port","error_message"}
};
this->logs_path = "/var/log/apache2";
//this->readConfigs();
this->scanLogsDir();
@ -30,6 +47,20 @@ std::vector<Craplog::LogFile> Craplog::getLogsList( bool fresh )
}
// return the path of the file matching the given name
Craplog::LogFile Craplog::getLogFileItem( QString file_name )
{
LogFile logfile;
for ( const Craplog::LogFile& item : this->logs_list ) {
if ( item.name == file_name ) {
logfile = item;
break;
}
}
return logfile;
}
// return the path of the file matching the given name
std::string Craplog::getLogFilePath( QString file_name )
{
@ -69,18 +100,156 @@ void Craplog::scanLogsDir()
std::string path = dir_entry.path().string();
std::string name = dir_entry.path().filename().string();
// match only files having ".log." in their name
if ( ! dir_entry.is_regular_file()
|| LogOp::isNameValid( name ) ) {
if ( dir_entry.is_regular_file() == false
|| this->isFileNameValid( name ) == false ) {
continue;
}
auto logfile =LogFile{
.selected = false,
.size = size,
.name = QString::fromStdString( name ),
.path = path,
.type = this->defineFileType( name, IOutils::readLines( path ) )
};
if ( logfile.type == Craplog::LogType::Failed ) {
// failed to get the log type
// error message displayed while defining as failed in logOps
continue;
}
// push in the list
this->logs_list.push_back(
LogFile{
.selected = false,
.size = size,
.name = QString::fromStdString( name ),
.path = path,
.type = LogOp::defineLogType( path )
});
this->logs_list.push_back( logfile );
}
}
bool Craplog::isFileNameValid( std::string name )
{
bool valid = false;
if ( StringOps::startsWith( name, "access.log." )
|| StringOps::startsWith( name, "error.log." ) ) {
int start = name.find_last_of( ".log." )+1;
int stop = name.find( ".gz", start);
if ( stop >= name.size() ) {
stop = name.size()-1;
}
valid = true;
for ( int i=start; i<=stop; i++ ) {
if ( StringOps::isNumeric( name[i] ) == false ) {
valid = false;
break;
}
}
}
return valid;
}
Craplog::LogType Craplog::defineFileType( std::string name, std::vector<std::string> lines )
{
int n_acc=0, n_err=0;
Craplog::LogType supposed_type, real_type;
if ( StringOps::startsWith( name, "access" ) ) {
supposed_type = Craplog::LogType::Access;
} else if ( StringOps::startsWith( name, "error" ) ) {
supposed_type = Craplog::LogType::Error;
} else {
// this shouldn't be
// !!! PUT A DIALOG ERROR MESSAGE HERE !!!
}
real_type = Craplog::LogType::Failed;
for ( const std::string& line : lines ) {
std::cout << "LINE: " << line << std::endl;
if ( supposed_type == Craplog::LogType::Access ) {
if ( this->access_logs_format.initial.size() > 0 ) {
// a fixed starter char is set
if ( StringOps::startsWith( line, this->access_logs_format.initial ) == false ) {
// but wasn't found
continue;
}
}
if ( this->access_logs_format.final.empty() > 0 ) {
// a fixed starter char is set
if ( StringOps::endsWith( line, this->access_logs_format.final ) == false ) {
// but wasn't found
continue;
}
}
n_acc++;
} else {
if ( this->error_logs_format.initial.empty() == false ) {
// a fixed starter char is set
if ( StringOps::startsWith( line, this->error_logs_format.initial ) == false ) {
// but wasn't found
continue;
}
}
if ( this->error_logs_format.final.empty() == false ) {
// a fixed starter char is set
if ( StringOps::endsWith( line, this->error_logs_format.final ) == false ) {
// but wasn't found
continue;
}
}
n_err++;
}
}
std::cout << "ACC: " << n_acc << " / ERR: " << n_err << std::endl;
if ( n_acc > 0 && n_err == 0 ) {
// access logs
real_type = Craplog::LogType::Access;
} else if ( n_err > 0 && n_acc == 0 ) {
// error logs
real_type = Craplog::LogType::Error;
} else {
// something is wrong with these logs, put a warnin
if ( n_acc > 0 && n_err > 0 ) {
// both access and error types found
// !!! PUT A DIALOG ERROR MESSAGE HERE !!!
} else {
// every line was invalid
// !!! PUT A DIALOG ERROR MESSAGE HERE !!!
}
}
return real_type;
}
// get the logs format
Craplog::LogsFormat Craplog::getAccessLogsFormat()
{
return this->access_logs_format;
}
Craplog::LogsFormat Craplog::getErrorLogsFormat()
{
return this->error_logs_format;
}
// set the logs format
void Craplog::setAccessLogsFormat( std::string format_string )
{
}
void Craplog::setErrorLogsFormat( std::string format_string )
{
}
/////////////////
//// LOG OPS ////
/////////////////
Craplog::LogOps::LogOps()
{
}
std::vector<std::string> Craplog::LogOps::splitLine( std::string line, Craplog::LogType type )
{
}
std::vector<std::string> Craplog::LogOps::splitLines( std::string line, Craplog::LogType type )
{
}

View File

@ -4,10 +4,6 @@
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
#include <filesystem>
#include <QMainWindow>
@ -17,13 +13,24 @@ public:
Craplog();
// logs formats
enum LogsFormat {
AccessCommon,
AccessCombined,
ErrorDefault
enum Format{
Default,
Common,
Combined,
Custom
};
LogsFormat access_logs_format;
LogsFormat error_logs_format;
struct LogsFormat {
Format format;
std::string string;
std::string initial;
std::string final;
std::vector<std::string> separators;
std::vector<std::string> fields;
};
void setAccessLogsFormat( std::string format_string );
void setErrorLogsFormat( std::string format_string );
LogsFormat getAccessLogsFormat();
LogsFormat getErrorLogsFormat();
// log file infoes
enum LogType {
@ -31,7 +38,7 @@ public:
Access,
Error
};
// log file item
struct LogFile {
bool selected;
int size;
@ -42,16 +49,40 @@ public:
// logs list related methods
std::vector<LogFile> getLogsList( bool fresh=false );
int getLogsListSize();
// log file related
LogFile getLogFileItem( QString file_name );
std::string getLogFilePath( QString file_name );
// set a file in the list as selected, to be used for the stats
int setLogFileSelected( QString file_name );
// check if a file name respects the one set
bool isFileNameValid( std::string name );
// define if really access and/or error logs
Craplog::LogType defineFileType( std::string name, std::vector<std::string> lines );
// operations on logs
class LogOps
{
public:
LogOps();
std::vector<std::string> splitLine( std::string line, Craplog::LogType type );
std::vector<std::string> splitLines( std::string line, Craplog::LogType type );
};
LogOps logOps;
private:
// logs related
std::string logs_path;
std::string default_access_logs_name = "access.log";
std::string logs_path = "/var/log/apache2";
std::vector<LogFile> logs_list;
// logs list related
void scanLogsDir();
// logs format related
LogsFormat access_logs_format;
LogsFormat error_logs_format;
void readConfigs();
void loadFileContent();

9
craplog/utilities.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef UTILITIES_H
#define UTILITIES_H
#include "utilities/io.h"
#include "utilities/rtf.h"
//#include "utilities/logs.h"
#include "utilities/strings.h"
#endif // UTILITIES_H

View File

@ -5,7 +5,7 @@
IOutils::IOutils()
{
}
@ -35,12 +35,12 @@ std::vector<std::string> IOutils::readLines( std::string path, int n_lines )
continue;
}
// succesfully catched a line
lines.push_back( StringOp::strip( line ) );
lines.push_back( StringOps::strip( line ) );
n++;
}
} catch (const std::ios_base::failure& err) {
// failed reading
std::cout << err.what() << std::endl; // !!! PUT AN DIALOG ERROR MESSAGE HERE !!!
// >> err.what() << // !!! PUT A DIALOG ERROR MESSAGE HERE !!!
}
if ( file.is_open() ) {
file.close();
@ -70,12 +70,12 @@ std::string IOutils::readFile( std::string path )
std::string buf = std::string(read_size, '\0');
while (file.read(& buf[0], read_size)) {
content.append(buf);
//content.append(buf, 0, file.gcount()); !!! REMOVE IF NOT NEEDED
//content.append(buf, 0, file.gcount()); !!! REMOVE IF NOT NEEDED !!!
}
content.append(buf, 0, file.gcount());
} catch (const std::ios_base::failure& err) {
// failed reading
std::cout << err.what() << std::endl; // !!! PUT AN DIALOG ERROR MESSAGE HERE !!!
// >> err.what() << // !!! PUT A DIALOG ERROR MESSAGE HERE !!!
}
if ( file.is_open() ) {
file.close();

View File

@ -2,16 +2,15 @@
#define IO_H
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <fstream>
class IOutils
{
public:
IOutils();
static std::vector<std::string> readLines( std::string path, int n_lines=10 );
static std::string readFile( std::string path );
};

View File

@ -2,11 +2,11 @@
RichText::RichText()
{
}
QString RichText::enrichLogs( std::string content, Craplog::LogsFormat logs_format, int color_scheme )
QString RichText::enrichLogs( std::string content, Craplog::LogsFormat format, int color_scheme )
{
QString style;
switch ( color_scheme ) {
@ -15,47 +15,113 @@ QString RichText::enrichLogs( std::string content, Craplog::LogsFormat logs_form
style = QString("<style>"
"body{background-color:#ffffff}"
"p{color:#9c9c9b}"
"span.x{color:#1f1c1b}"
"span.ip{color:#644a9b}"
"span.pt{color:#d5bc79}"
"span.date{color:#d685d6}"
"span.ua{color:#006e28}"
"span.time{color:#d685d6}"
"span.ua_src{color:#006e28}"
"span.req_err{color:#54b8ff}"
"span.res_lev{color:#d24f4f}"
"<style/>");
"/<style>");
case 2:
// monokai
style = QString("<style>"
"body{background-color:#272822}"
"p{color:#706c5a}"
"span.x{color:#d1d1cb}"
"span.ip{color:#57adbc}"
"span.pt{color:#c1b864}"
"span.date{color:#9773db}"
"span.ua{color:#a6e22e}"
"span.time{color:#9773db}"
"span.ua_src{color:#a6e22e}"
"span.req_err{color:#bebeb8}"
"span.res_lev{color:#f92672}"
"<style/>");
"</style>");
case 3:
// radical
style = QString("<style>"
"body{background-color:#141322}"
"p{color:#749295}"
"span.x{color:#7c9c9e}"
"span.ip{color:#fda8bc}"
"span.pt{color:#ff85a1}"
"span.date{color:#7c9c9e}"
"span.ua{color:#42a784}"
"span.time{color:#a8c0c2}"
"span.ua_src{color:#42a784}"
"span.req_err{color:#d5358f}"
"span.res_lev{color:#56e8e4}"
"<style/>");
"</style>");
default:
style = "";
}
QString rich_content = QString("<html><head>%1<head/><body>")
QString rich_content = QString("<!DOCTYPE html><html><head>%1</head><body>")
.arg( style );
for ( std::string& line : StringOp::splitrip( content ) ) {
if ( line[0] == '[' ) {
// error logs
QString rich_line="", class_name="";
std::string sep, fld;
int start=0, stop=0, i=0;
int line_size;
int n_sep = format.separators.size()-1;
for ( std::string& line : StringOps::splitrip( content ) ) {
i = 0;
line_size = line.size()-1;
rich_line += "<p>";
// add the initial chars
stop = format.initial.size();
rich_line += QString::fromStdString( format.initial );
while (true) {
// color fields
if ( i <= n_sep ) {
sep = format.separators[i];
} else {
sep = format.final;
}
start = stop;
stop = line.find( sep, start );
if ( stop > line_size ) {
// separator not found, skip to the next one
i++;
if ( i > n_sep+1 ) {
// break if no one left
break;
}
continue;
}
// color the fields
class_name.clear();
fld = format.fields[i];
if ( color_scheme > 0 ) {
class_name += "<span class=\"";
if ( fld == "client" ) {
class_name += "ip";
} else if ( fld == "port" ) {
class_name += "pt";
} else if ( fld == "date_time" ) {
class_name += "time";
} else if ( fld == "user_agent" || fld == "source_file" ) {
class_name += "ua_src";
} else if ( fld == "request" || fld == "error_message" ) {
class_name = "req_err";
} else if ( fld == "response_code" || fld == "error_level" ) {
class_name += "res_lev";
} else {
class_name += "x";
}
class_name += "\">";
}
// add the class name as apan
rich_line += QString::fromStdString( line.substr(start, stop-start) );
if ( color_scheme > 0 ) {
rich_line += "</span>";
}
// update the stop for the next start
stop = stop + sep.size();
if ( stop >= line_size ) {
break;
}
}
rich_line += "</p>";
rich_content.push_back( rich_line );
rich_line.clear();
}
rich_content.push_back("</body></html>");
return rich_content;
}

View File

@ -11,8 +11,8 @@ class RichText
{
public:
RichText();
static QString enrichLogs( std::string content, int color_scheme );
static QString enrichLogs( std::string content, Craplog::LogsFormat, int color_scheme );
};
#endif // RICHTEXT_H

View File

@ -1,26 +1,29 @@
#include "strings.h"
StringOp::StringOp()
StringOps::StringOps()
{
}
bool StringOp::isNumeric( std::string str )
bool StringOps::isNumeric( std::string str )
{
bool result = true;
for ( char& chr : str ) {
if ( StringOp::isNumeric( chr ) == false ) {
if ( StringOps::isNumeric( chr ) == false ) {
result = false;
}
}
return result;
}
bool StringOp::isNumeric( char chr )
bool StringOps::isNumeric( char chr )
{
if ( chr > 65 && chr < 99 ) {
if ( chr > 47 && chr < 58 ) {
return true;
} else {
return false;
@ -28,7 +31,7 @@ bool StringOp::isNumeric( char chr )
}
bool StringOp::startsWith(std::string str, std::string flag)
bool StringOps::startsWith(std::string str, std::string flag)
{
bool result = true;
for ( int i=0; i<flag.size(); i++ ) {
@ -41,7 +44,7 @@ bool StringOp::startsWith(std::string str, std::string flag)
}
bool StringOp::endsWith(std::string str, std::string flag)
bool StringOps::endsWith(std::string str, std::string flag)
{
bool result = true;
int size = str.size()-1;
@ -55,16 +58,16 @@ bool StringOp::endsWith(std::string str, std::string flag)
}
std::string StringOp::strip( std::string str, std::string chars )
std::string StringOps::strip( std::string str, std::string chars )
{
std::string stripped;
stripped = StringOp::lstrip( str, chars );
stripped = StringOp::rstrip( str, chars );
stripped = StringOps::lstrip( str, chars );
stripped = StringOps::rstrip( stripped, chars );
return stripped;
}
std::string StringOp::lstrip( std::string str, std::string chars )
std::string StringOps::lstrip( std::string str, std::string chars )
{
bool found = true;
int i = 0;
@ -90,7 +93,7 @@ std::string StringOp::lstrip( std::string str, std::string chars )
}
std::string StringOp::rstrip( std::string str, std::string chars )
std::string StringOps::rstrip( std::string str, std::string chars )
{
bool found = true;
int i = str.size() - 1;
@ -110,14 +113,14 @@ std::string StringOp::rstrip( std::string str, std::string chars )
}
std::string stripped = "";
if ( i > 0 ) {
stripped = str.substr( 0, str.size() - i );
stripped = str.substr( 0, str.size() - (str.size() - i) + 1 );
}
return stripped;
}
std::vector<std::string> StringOp::split( std::string str, std::string sep )
std::vector<std::string> StringOps::split( std::string str, std::string sep )
{
std::vector<std::string> splitted;
std::string slice;
@ -142,16 +145,16 @@ std::vector<std::string> StringOp::split( std::string str, std::string sep )
}
std::vector<std::string> StringOp::splitrip( std::string str, std::string sep, std::string chars )
std::vector<std::string> StringOps::splitrip( std::string str, std::string sep, std::string chars )
{
std::vector<std::string> splitted, aux;
str = StringOp::strip( str );
aux = StringOp::split( str );
str = StringOps::strip( str );
aux = StringOps::split( str );
for ( std::string &str : aux ) {
if ( str.empty() ) {
continue;
}
splitted.push_back( StringOp::strip( str ) );
splitted.push_back( StringOps::strip( str ) );
}
return splitted;
}

View File

@ -6,10 +6,10 @@
#include "qstring.h"
class StringOp
class StringOps
{
public:
StringOp();
StringOps();
static bool isNumeric( std::string str );
static bool isNumeric( char chr );
@ -26,4 +26,4 @@ public:
static std::vector<std::string> splitrip( std::string str, std::string sep="\n", std::string chars=" \n\t\b\r\v" );
};
#endif // STRINGOP_H
#endif // StringOps_H