⚝
One Hat Cyber Team
⚝
Your IP:
216.73.216.19
Server IP:
178.33.27.10
Server:
Linux cpanel.dev-unit.com 3.10.0-1160.108.1.el7.x86_64 #1 SMP Thu Jan 25 16:17:31 UTC 2024 x86_64
Server Software:
Apache/2.4.57 (Unix) OpenSSL/1.0.2k-fips
PHP Version:
8.2.11
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
usr
/
lib64
/
cbpolicyd-2.1
/
awitpt
/
db
/
View File Name :
dblayer.pm
# Common database layer module # Copyright (C) 2009-2011, AllWorldIT # Copyright (C) 2008, LinuxRulz # Copyright (C) 2005-2007 Nigel Kukard <nkukard@lbsd.net> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ## @class awitpt::db::dblayer # Database layer module which makes life a bit esier package awitpt::db::dblayer; use strict; use warnings; # Exporter stuff require Exporter; our (@ISA,@EXPORT); @ISA = qw(Exporter); @EXPORT = qw( DBConnect DBSelect DBDo DBLastInsertID DBBegin DBCommit DBRollback DBQuote DBFreeRes DBSelectNumResults DBSelectSearch hashifyLCtoMC ); use POSIX qw( strftime ); use Date::Parse; use awitpt::db::dbilayer; # Database handle my $dbh = undef; # Our current error message my $error = ""; ## @internal # @fn setError($err) # This function is used to set the last error for this class # # @param err Error message sub setError { my $err = shift; my ($package,$filename,$line) = caller; my (undef,undef,undef,$subroutine) = caller(1); # Set error $error = "$subroutine($line): $err"; } ## @internal # @fn Error # Return current error message # # @return Last error message sub Error { my $err = $error; # Reset error $error = ""; # Return error return $err; } ## @fn setHandle($handle) # Initialize database handle # # @param handle Set internal database handle we use sub setHandle { my $handle = shift; $dbh = $handle; } ## @fn DBSelect($query,@params) # Return database selection results... # # @param query Query to run # # @return DBI statement handle, undef on error sub DBSelect { my ($query,@params) = @_; my $table_prefix = $dbh->table_prefix(); # Replace table prefix macro $query =~ s/\@TP\@/$table_prefix/g; # Prepare query my $sth; if (!($sth = $dbh->select($query,@params))) { setError("Error executing select: ".$dbh->Error()); return undef; } return $sth; } ## @fn DBDo($command) # Perform a command # # @param command Command to run # # @return DBI statement handle, undef on error sub DBDo { my (@params) = @_; my $table_prefix = $dbh->table_prefix(); # Check type of params we have if (ref($params[0]) eq 'HASH') { my $queryHash = $params[0]; my $dbType = $dbh->type(); # Check DB type is defined, if not use * if (defined($queryHash->{$dbType})) { @params = @{$queryHash->{$dbType}}; } elsif (defined($queryHash->{'*'})) { @params = @{$queryHash->{'*'}}; } else { setError("Error executing, database type in query not fund and no '*' query found"); return undef; } } # Grab command and data my $command = shift(@params); my @data = @params; # Replace table prefix macro $command =~ s/\@TP\@/$table_prefix/g; # Prepare query my $sth; if (!($sth = $dbh->do($command,@data))) { setError("Error executing command '$command': ".$dbh->Error()); return undef; } return $sth; } ## @fn DBLastInsertID($table,$column) # Function to get last insert id # # @param table Table to check # @param column Column to get last insert on # # @return Last insert ID or undef on error sub DBLastInsertID { my ($table,$column) = @_; my $res; if (!($res = $dbh->lastInsertID(undef,undef,$table,$column))) { setError("Error getting last inserted id: ".$dbh->Error()); return undef; } return $res; } ## @fn DBBegin # Function to begin a transaction # # @return 1 on success, undef on error sub DBBegin { my $res; if (!($res = $dbh->begin())) { setError("Error beginning transaction: ".$dbh->Error()); return undef; } return $res; } ## @fn DBCommit # Function to commit a transaction # # @return 1 on success, undef on error sub DBCommit { my $res; if (!($res = $dbh->commit())) { setError("Error committing transaction: ".$dbh->Error()); return undef; } return $res; } ## @fn DBRollback # Function to rollback a transaction # # @return 1 on success, undef on error sub DBRollback { my $res; if (!($res = $dbh->rollback())) { setError("Error rolling back transaction: ".$dbh->Error()); return undef; } return $res; } ## @fn DBQuote($variable) # Function to quote a database variable # # @param variable Variable to quote # # @return Quoted variable sub DBQuote { my $variable = shift; return $dbh->quote($variable); } ## @fn DBFreeRes($sth) # Function to cleanup DB query # # @param sth Statement handle to cleanup sub DBFreeRes { my $sth = shift; if ($sth) { $sth->finish(); } } # Function to get table prefix sub DBTablePrefix { return $dbh->table_prefix(); } # # Value Added Functions # ## @fn DBSelectNumResults($query) # Return how many results came up from the specific SELECT query # # @param query Query to perform, minus "SELECT COUNT(*) AS num_results" # # @return Number of results, undef on error sub DBSelectNumResults { my $query = shift; # Prepare query my $sth; if (!($sth = $dbh->select("SELECT COUNT(*) AS num_results $query"))) { setError("Error executing select: ".$dbh->Error()); return undef; } # Grab row my $row = $sth->fetchrow_hashref(); if (!defined($row)) { setError("Failed to get results from a select: ".$dbh->Error()); return undef; } # Pull number my $num_results = $row->{'num_results'}; $sth->finish(); return $num_results; } ## @fn DBSelectSearch($query,$search,$filters,$sorts) # Select results from database and return the total number aswell # # @param query Base query # # @param search Search hash ref # @li Filter - Filter based on this... # [filter] => Array ( # [0] => Array ( # [field] => Name # [data] => Array ( # [type] => string # [value] => hi there # ) # ) # ) # { 'data' => { 'comparison' => 'gt', 'value' => '5', 'type' => 'numeric' }, 'field' => 'ID' } # @li Start - Start item number, indexed from 0 onwards # @li Limit - Limit number of results # @li Sort - Sort by this item # @li SortDirection - Sort in this direction, either ASC or DESC # # @param filters Filter hash ref # Hash: 'Column' -> 'Table.DBColumn' # # @param sorts Hash ref of valid sort criteria, indexed by what we get, pointing to the DB column in the query # Hash: 'Column' -> 'Table.DBColumn' # # @return Number of results, undef on error sub DBSelectSearch { my ($query,$search,$filters,$sorts) = @_; # Stuff we need to add to the SQL query my @where; # Where clauses my $sqlWhere = ""; my $sqlLimit = ""; my $sqlOffset = ""; my $sqlOrderBy = ""; my $sqlOrderByDirection = ""; # Check if we're searching if (defined($search) && ref($search)) { # Check it is a hash if (ref($search) ne "HASH") { setError("Parameter 'search' is not a hashtable"); return (undef,-1); } # Check if we need to filter if (defined($search->{'Filter'})) { # We need filters in order to use filtering if (!defined($filters)) { setError("Parameter 'search' element 'Filter' requires 'filters' to be defined"); return (undef,-1); } # Check type of Filter if (ref($search->{'Filter'}) ne "ARRAY") { setError("Parameter 'search' element 'Filter' is of invalid type, it must be an ARRAY'"); return (undef,-1); } # Loop with filters foreach my $item (@{$search->{'Filter'}}) { my $data = $item->{'data'}; # value, type, comparison my $field = $item->{'field'}; my $column = $filters->{$field}; # Check if field is in our allowed filters if (!defined($filters->{$field})) { setError("Parameter 'search' element 'Filter' has invalid field item '$field' according to 'filters'"); return (undef,-1); } # Check data if (!defined($data->{'type'})) { setError("Parameter 'search' element 'Filter' requires field data element 'type' for field '$field'"); return (undef,-1); } if (!defined($data->{'value'})) { setError("Parameter 'search' element 'Filter' requires field data element 'value' for field '$field'"); return (undef,-1); } # match =, LIKE, IN ( # matchEnd '' or ) my $match; my $matchEnd = ""; # value is the DBQuote()'d value my $value; # Check what type of comparison if ($data->{'type'} eq "boolean") { $match = '='; $value = DBQuote($data->{'value'}); } elsif ($data->{'type'} eq "date") { # The comparison type must be defined if (!defined($data->{'comparison'})) { setError("Parameter 'search' element 'Filter' requires field data element 'comparison' for date field '$field'"); return (undef,-1); } # Check comparison type if ($data->{'comparison'} eq "gt") { $match = ">"; } elsif ($data->{'comparison'} eq "lt") { $match = "<"; } elsif ($data->{'comparison'} eq "eq") { $match = "="; } elsif ($data->{'comparison'} eq "ge") { $match = ">="; } elsif ($data->{'comparison'} eq "le") { $match = "<="; } # Convert to ISO format my $unixtime = str2time($data->{'value'}); my @d = localtime($unixtime); $value = DBQuote(sprintf("%4d-%02d-%02d", $d[5]+1900, $d[4]+1, $d[3])); } elsif ($data->{'type'} eq "list") { # Quote all values my @valueList; foreach my $i (split(/,/,$data->{'value'})) { push(@valueList,DBQuote($i)); } $match = "IN ("; # Join up 'xx','yy','zz' $value = join(',',@valueList); $matchEnd = ")"; } elsif ($data->{'type'} eq "numeric") { # The comparison type must be defined if (!defined($data->{'comparison'})) { setError("Parameter 'search' element 'Filter' requires field data element 'comparison' for numeric field '$field'"); return (undef,-1); } # Check comparison type if ($data->{'comparison'} eq "gt") { $match = ">"; } elsif ($data->{'comparison'} eq "lt") { $match = "<"; } elsif ($data->{'comparison'} eq "eq") { $match = "="; } elsif ($data->{'comparison'} eq "ge") { $match = ">="; } elsif ($data->{'comparison'} eq "le") { $match = "<="; } $value = DBQuote($data->{'value'}); } elsif ($data->{'type'} eq "string") { $match = "LIKE"; $value = DBQuote("%".$data->{'value'}."%"); } # Add to list push(@where,"$column $match $value $matchEnd"); } # Check if we have any WHERE clauses to add ... if (@where > 0) { # Check if we have WHERE clauses in the query if ($query =~ /\sWHERE\s/i) { # If so start off with AND $sqlWhere .= "AND "; } else { $sqlWhere = "WHERE "; } $sqlWhere .= join(" AND ",@where); } } # Check if we starting at an OFFSET if (defined($search->{'Start'})) { # Check if Start is valid if ($search->{'Start'} < 0) { setError("Parameter 'search' element 'Start' invalid value '".$search->{'Start'}."'"); return (undef,-1); } $sqlOffset = sprintf("OFFSET %i",$search->{'Start'}); } # Check if results will be LIMIT'd if (defined($search->{'Limit'})) { # Check if Limit is valid if ($search->{'Limit'} < 1) { setError("Parameter 'search' element 'Limit' invalid value '".$search->{'Limit'}."'"); return (undef,-1); } $sqlLimit = sprintf("LIMIT %i",$search->{'Limit'}); } # Check if we going to be sorting if (defined($search->{'Sort'})) { # We need sorts in order to use sorting if (!defined($sorts)) { setError("Parameter 'search' element 'Filter' requires 'filters' to be defined"); return (undef,-1); } # Check if sort is defined if (!defined($sorts->{$search->{'Sort'}})) { setError("Parameter 'search' element 'Sort' invalid item '".$search->{'Sort'}."' according to 'sorts'"); return (undef,-1); } # Build ORDER By $sqlOrderBy = "ORDER BY ".$sorts->{$search->{'Sort'}}; # Check for sort ORDER if (defined($search->{'SortDirection'})) { # Check for valid directions if (lc($search->{'SortDirection'}) eq "asc") { $sqlOrderByDirection = "ASC"; } elsif (lc($search->{'SortDirection'}) eq "desc") { $sqlOrderByDirection = "DESC"; } else { setError("Parameter 'search' element 'SortDirection' invalid value '".$search->{'SortDirection'}."'"); return (undef,-1); } } } } # Select row count, pull out "SELECT .... " as we replace this in the NumResults query (my $queryCount = $query) =~ s/^\s*SELECT\s.*\sFROM/FROM/is; my $numResults = DBSelectNumResults("$queryCount $sqlWhere"); if (!defined($numResults)) { return undef; } # Add Start, Limit, Sort, Direction my $sth = DBSelect("$query $sqlWhere $sqlOrderBy $sqlOrderByDirection $sqlLimit $sqlOffset"); if (!defined($sth)) { return undef; } return ($sth,$numResults); } # Convert a lower case array to mixed case sub hashifyLCtoMC { my ($record,@entries) = @_; # If we undefined, return return undef if (!defined($record)); my $res; # Loop with each item, assign from lowecase database record to our result foreach my $entry (@entries) { $res->{$entry} = $record->{lc($entry)}; } return $res; } 1; # vim: ts=4