wjl-0.26/changelog
/files/tmp/wjl-0.26/changelog.html
v0.26
- Tiny Tweaks here and there..
- $wjl->day_stats() now takes a type as the first arguement.
v0.25
- Rewrite of the Include mechanism. Use WJLCore now instead of eval files.
- Resolve namespace conflict redirect now meta_redirect.
- Resolve namespace conflict button now form_button.
- Cleanup a couple of undeclared variables.
- Improve filter to handle ` chars.
- Fix job_valid so that jobids are clean to numerics with s/([^0-9])//g.
- Asorted filtering fixes to prevent bombing out on invalud user input.
- Code tested with mod_perl, speed improvement is enormous.
- Various minor clean ups which mod_perl was pointing at.
v0.24
- Various DHTML changes.
- Fix/Remove Text Block Formatting Code fmt().
- Add alert() function using javascript to main library.
- job_list.pl uses alert($jobid) for new jobs.
- stats.pl allows filtering based on status before user seletion.
v0.23
- Fix some internal filter bugs.
- Filter time inputs on gen_elapsed and gen_date to integers.
- Order Status is now actualy connected to something in job_list.pl.
- Fix edit_user.pl, so the title is Edit User not New User.
- Add a whole bunch of bounding checks with new cut() function.
- Add -f to rm line in src/inst script.
- Fix silly $job->due() bug.
- Fix nasty bug, where two jobs can appear to have the same jobid.
- Fix db install script bug.
v0.22
- Fix formatting to do with \n\r DHTML bug.
- Add the ability to edit User and Time of comments.
- Movement from Job List now carries Filter and Order parameters when return.
- Fix Bugs in workingseconds().
- Fix $job->due(), so that it is static from initial start of a job.
- Fix departments.pl so you can't add blank departments.
- Allow Filtering to unallocated Jobs.
- Add a $wjl->list_technicians(), so that Allocation, is only to techs.
- Add a Pseudo Live status on job list, which basically means status < 64.
v0.21
- General Clean Up.
- Install Script added.
- Alter WJL.pm to allow a user to have a 0 level.
- Add $job->due(), which give estimate due date.
- Alter Job Report to provide estimated completetion via $job->due().
- Installation Documentation.
- Fix an Atomic Bug in edit_job.pl.
- Fix Bug in find_knowledge() where it doesn't match on Job Description.
v0.20
- Fix Bug where stat_graph.pl header was for gif, but output is png.
- Fix Bug where IE file names are not handled right in knowledge_add.pl.
- Make Buttons use POST, instead of GET, for security...
v0.20-PRE
- Added Statistics (uses Graphs, need GD and GD::Graph modules).
- Added Working Time, so only working hours are counted when selected.
- Added Knowledge Based, this changes the DB structure, see db_patch.
- Knowledge base needs MIME::Base64.
- Feature Freeze now in effect.
v0.12 - Internal Release
- Added Path to Cookies, they now work... Finaly. I hope.
v0.11
- Add DHTML for IE users.
- Fix remove some unintentionaly global variable.
- Add "use strict".
- Cookies/Low security now works :).
- Add Changelog.
- Add a $job->comments() function.
v0.1
- Fix Joblist Filter Bug.
- Fix Edit Job not doing atomic properly for first time users.
v0.1-PRE
- Prelimary Release.
wjl-0.26/install
/files/tmp/wjl-0.26/install.html
#!/usr/bin/perl
sub ok {
print "OK\n";
}
sub md5sum($) {
use Digest::MD5;
my $string = $_[0];
my $md5 = Digest::MD5->new;
$md5->add($string);
return($md5->hexdigest);
}
sub check_dependencies {
print "\nChecking Dependencies\n";
print "Digest::MD5\t";
use Digest::MD5;
ok();
print "Mysql\t\t";
use Mysql;
ok();
print "Time::Local\t";
use Time::Local;
ok();
print "MIME::Base64\t";
use MIME::Base64;
ok();
print "GD\t\t";
use GD;
ok();
print "GD::Graph\t";
use GD::Graph;
ok();
print "Dependency Check Complete\n";
}
sub ask($$) {
my ($question,$dpath) = @_;
print "$question [$dpath]:";
my $answer = <STDIN>;
chomp($answer);
if($answer) {
return $answer;
} else {
return $dpath;
}
}
sub where($$) {
my ($item,$dpath) = @_;
my $question = "Where is your $item";
return ask($question,$dpath);
}
sub filter_replace($$$$) {
my ($infile,$outfile,$st,$et) = @_;
my ($buffer,$data);
#print "$infile -> $outfile, s/$st/$et/g\n";
open(IN,$infile) || die $!;
while($buffer = <IN>) {
$data .= $buffer;
}
close(IN);
$data =~ s/$st/$et/g;
open(OUT,">$outfile") || die $!;
print OUT $data;
close(OUT);
}
sub clean {
print "\nCleaning Old Files, please ignore errors.\n";
unlink('db/sql_db');
unlink('src/modules/WJLCore.pm');
}
print "Web Job Logs Installer\n";
if($ARGV[0] =~ /clean/) {
clean();
exit(0);
} else {
check_dependencies();
clean();
}
print "\n";
my $cgibin = where('cgi-bin','/var/www/cgi-bin/wjl');
my $www = where('www-root','/var/www/html');
my $perllib = where('Perl modules directory','/usr/lib/perl5/5.6.0');
my $confdb = ask('Configure Database','Yes');
my ($sqlroot,$adminuser,$adminpass);
if($confdb =~ /^Y/i) {
#$sqlroot = ask('What is your MySQL Root Password','');
$adminuser = ask('What username do you want your WJL admin to have','admin');
$adminpass = ask('What password should the WJL admin user have','changeme');
$adminpass = md5sum($adminpass);
} else {
$confdb = 0;
}
my $sqluser = ask('What name should the Database user have','wjl');
my $sqlpass = ask('What password should the Database user have','changeme');
my $organisation= ask('What is the name of your organisation','noorg');
print "\nMangling Files\n";
if($confdb) {
filter_replace('db/sql_db.in','db/sql_db','your_user',$sqluser);
filter_replace('db/sql_db','db/sql_db','your_password',$sqlpass);
filter_replace('db/sql_db','db/sql_db','admin_user',$adminuser);
filter_replace('db/sql_db','db/sql_db','admin_password',$adminpass);
}
filter_replace('src/modules/WJLCore.pm.in','src/modules/WJLCore.pm','your_user',$sqluser);
filter_replace('src/modules/WJLCore.pm','src/modules/WJLCore.pm','your_password',$sqlpass);
filter_replace('src/modules/WJLCore.pm','src/modules/WJLCore.pm','your_organisation',$organisation);
if($ARGV[0] !~ /config/i) {
if($confdb) {
print "\nSetting Up MySQL Database\n";
print "You maybe asked for your root password.\n";
system('db/inst');
print "If that worked you won't see any messages\n";
}
print "\nInstalling Files\n";
system('src/inst',$cgibin,$www,$perllib);
}
print "Ok I think we are done\n";
exit(0);
wjl-0.26/db/sql_db.in
/files/tmp/wjl-0.26/db/sql_db.in.html
create database joblogs;
use joblogs;
create table job (
jobid BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
started BIGINT UNSIGNED NOT NULL,
problem_started BIGINT UNSIGNED,
caller CHAR(32) BINARY NOT NULL,
dept CHAR(32) BINARY,
priority SMALLINT UNSIGNED,
username CHAR(32) BINARY NOT NULL,
allocated_to CHAR(32) BINARY NOT NULL,
PRIMARY KEY (jobid),
UNIQUE jobid (jobid),
INDEX (allocated_to)
);
create table event (
eventid BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
jobid BIGINT UNSIGNED NOT NULL,
date BIGINT UNSIGNED NOT NULL,
username CHAR(32) BINARY NOT NULL,
type SMALLINT,
status SMALLINT,
data MEDIUMTEXT,
PRIMARY KEY (eventid),
UNIQUE eventid (eventid)
);
create table dept (
dept CHAR(32) BINARY NOT NULL,
dept_name VARCHAR(250),
hod VARCHAR(250),
phone CHAR(32) BINARY,
PRIMARY KEY (dept),
UNIQUE dept (dept)
);
create table user (
username CHAR(32) BINARY NOT NULL,
sectoken CHAR(32) BINARY NOT NULL,
initials CHAR(4) BINARY,
full_name VARCHAR(250) BINARY,
level INT NOT NULL,
PRIMARY KEY (username),
UNIQUE username (username),
INDEX (initials)
);
create table knowledge (
jobid BIGINT UNSIGNED NOT NULL,
name MEDIUMTEXT,
description MEDIUMTEXT,
data LONGBLOB
);
create table atomic (
username CHAR(32) BINARY NOT NULL,
time BIGINT UNSIGNED NOT NULL
);
use mysql;
INSERT INTO user VALUES(
'localhost',
'your_user',
Password('your_password'),
'Y','Y','Y','Y','Y','Y','Y',
'Y','Y','Y','Y','Y','Y','Y'
);
FLUSH PRIVILEGES;
GRANT ALL PRIVILEGES ON joblogs.job TO your_user@localhost IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON joblogs.event TO your_user@localhost IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON joblogs.dept TO your_user@localhost IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON joblogs.user TO your_user@localhost IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON joblogs.knowledge TO csd@localhost IDENTIFIED BY 'your_password';
FLUSH PRIVILEGES;
use joblogs;
INSERT INTO user (username,sectoken,initials,full_name,level) VALUES ('admin_user','admin_password','AD','Admin User',255);
wjl-0.26/db/inst
/files/tmp/wjl-0.26/db/inst.html
#!/bin/sh
cat db/sql_db | /usr/bin/mysql -u root -p
wjl-0.26/src/www/wjl-style.css
/files/tmp/wjl-0.26/src/www/wjl-style.css.html
BODY, TD {
background: #3664A9;
color : silver;
font-family : "Tahoma";
font-size: 14px;
text-align: left;
}
H2 {
font-size: 14pt;
}
H3 {
font-size: 15pt;
font-style: italic;
font-family: sans-serif;
}
H4 {
font-family: sans-serif;
font-size: small;
}
A , A:Visited, A:Active{
color: white;
text-decoration : none;
font-weight : bold;
}
A:Hover {
color: #DAA520;
text-decoration : none;
font-weight : bold;
}
HR {
height: 1pt;
}
wjl-0.26/src/modules/WJLCore.pm.in
/files/tmp/wjl-0.26/src/modules/WJLCore.pm.in.html
# *-* Perl *-*
# Core Functions Include File for Web Logs Software
# WJL V0.26, Version 0.3
# Carl Ritson - 2002
# Define This Package
package WJLCore;
# Library Includes
require Digest::MD5;
require MIME::Base64;
require Time::Local;
require CGI;
require strict;
use vars qw($VERSION);
$VERSION = '0.3';
# Export Functions for pages to use.
require Exporter;
@ISA = qw(Exporter);
@EXPORT = (
'organisation',
'md5sum',
'meta_redirect',
'get_user_info',
'user_valid',
'user_level',
'start_page',
'db_error',
'db_login',
'form_button',
'six_page',
'frame6_page',
'has_right',
'set_right',
'hidden_fields',
'text_field',
'n2month',
'gen_date',
'date2timestamp',
'gen_elapsed',
'select_field',
'text_area',
'submit_button',
'hash2get',
'status',
'statusl',
'priol',
'priof',
'filter',
'radio_fields',
'fmt',
'popup_redirect',
'job_valid',
'event_type',
'auth_fail_page',
'dhtml_header',
'dhtml_main',
'dhtml_wrap',
'isie',
'mime',
'carrier_encode',
'carrier_decode',
'cut',
'alert',
'set_sectoken'
);
# Start of Subs
sub organisation {
my $organisation = 'your_organisation';
return $organisation;
}
# md5sum, takes string, returns Hex Digest of it, uses Digest::MD5.
sub md5sum($) {
my $string = $_[0];
my $md5 = Digest::MD5->new;
$md5->add($string);
return($md5->hexdigest);
}
# meta_redirect, takes URL , returns Generates Meta Redirect.
# Use instead of using meta_redirect header.
sub meta_redirect($) {
my $url = $_[0];
return ('<meta http-equiv="refresh" content="0;URL='.$url.'">');
}
# center, returns html with in center tags.
sub center {
my ($html) = join('',@_);
return '<center>'.$html.'</center>';
}
# gets_user_info, requires a CGI object, returns a Hash. Sends Page Header.
sub get_user_info {
my ($page,$header_type) = @_;
my %userinfo;
if(!$header_type) {
$header_type = 'text/html';
}
if ($page->param('security') =~ /high/) {
$userinfo{username} = $page->param('username');
$userinfo{sectoken} = $page->param('sectoken');
$userinfo{security} = 'high';
print CGI::header($header_type);
} else {
%userinfo = $page->cookie('wjl');
#print header(-cookie=>$cookie);
#print STDERR "raw: ".$page->raw_cookie()."\n";
#print STDERR "cookie: $cookie\n";
#%userinfo = split(/:/,$cookie);
print CGI::header($header_type);
}
return %userinfo;
}
# user_valid, requires DBH, Username, Sectoken. Returns 1 If The User is Valid.
sub user_valid($$$) {
my ($dbh, $username, $sectoken) = @_;
my $query = "SELECT username FROM user WHERE username=\'$username\' AND sectoken=\'$sectoken\'";
my $result = $dbh->query($query);
if ($result->fetchrow()) {
return 1;
} else {
return 0;
}
}
# user_level, requires DBH, Username. Returns Users Level.
sub user_level($$) {
my ($dbh, $username) = @_;
my $query = "SELECT level FROM user WHERE username='$username'";
my $result = $dbh->query($query);
my @row = $result->fetchrow();
return $row[0];
}
# start_page, require CGI object and DBH, returns $result and %userinfo.
# $result is 1 if the user was authenticated, etc.
sub start_page($$) {
my ($page, $dbh) = @_;
my $result = 0;
my %userinfo = get_user_info($page);
if (user_valid($dbh,$userinfo{username},$userinfo{sectoken})) {
$result = 1;
}
return ($result, %userinfo);
}
# db_error, take no arguments, returns void. Print DB Error Page.
sub db_error {
print CGI::header(),
CGI::start_html("Database Error :("),
CGI::h2("Sorry a Database Error has occured, please try again later"),
CGI::end_html();
}
# db_login, take no arguments, returns an array for use with the Mysql->connect.
sub db_login {
my @login_info;
my $db_name = "joblogs";
my $db_host = "localhost";
my $db_user = "your_user";
my $db_password = "your_password";
push(@login_info,$db_host,$db_name,$db_user,$db_password);
return(@login_info);
}
# form_button, takes name, target, %parm, returns form based html button
sub form_button($$%) {
my ($name, $target, %parm) = @_;
my $html = "";
$html .= "<form action=\"$target\" METHOD=\"POST\">\n";
foreach(keys(%parm)) {
my $key = $_;
$html .= "\t".'<input type="hidden" name="'.$key.'" value="'.$parm{$key}.'">'."\n";
}
$html .= submit_button($name);
$html .= "</form>";
return $html;
}
# six_page, takes 6 strings, returns them as tabled html 3x2.
sub six_page($$$$$$) {
my ($tl,$tm,$tr,$bl,$bm,$br) = @_;
my $table = '<table BORDER="0" CELLPADDING="0" CELLSPACING="0" WIDTH="100%">';
$table .= CGI::Tr(
'<td WIDTH="5%"></td>',
'<td WIDTH="90%"></td>',
'<td WIDTH="5%"></td>'
);
return CGI::start_html(
-title => "Web Job Logs - ".organisation(),
-style => {'src' => '/wjl-style.css'},
-head => dhtml_header()
),
$table,
CGI::Tr(CGI::td(center($tl)),CGI::td(center($tm)),CGI::td(center($tr))),
CGI::Tr(CGI::td($bl),CGI::td(center($bm)),CGI::td($br)),
'</table>',
CGI::end_html();
}
# frame6_page, takes page, returns it framed using a mostly blank six_page.
sub frame6_page($) {
my $page = $_[0];
return six_page('','','','',$page,'');
}
# Two functions has_right and set_right, edit of level tokens.
# This is done to keep all the magic in one place.
# has_right, takes level, rights question. returns 1 if user has that right.
sub has_right($$) {
my ($level, $right) = @_;
# The magic..
my $new_job = 0x01;
my $edit_jobs = 0x02;
my $alloc_and_prio = 0x04;
my $setup = 0x08;
my $password = 0x10;
my $delete = 0x20;
my $stats = 0x40;
my $knowledge = 0x80;
# Use RegExps, so queries can be more fluid.
if($right =~ /job/) {
if($right =~ /new/) {
if($level & $new_job) {
return 1;
}
} elsif($right =~ /edit/) {
if($level & $edit_jobs) {
return 1;
}
}
} elsif($right =~ /password/) {
if($level & $password) {
return 1;
}
} elsif($right =~ /setup/) {
if($level & $setup) {
return 1;
}
} elsif($right =~ /allocate/ || $right =~ /set.*priority/) {
if($level & $alloc_and_prio) {
return 1;
}
} elsif($right =~ /delete/) {
if($level & $delete) {
return 1;
}
} elsif($right =~ /stat/) {
if($level & $stats) {
return 1;
}
} elsif($right =~ /know/) {
if($level & $knowledge) {
return 1;
}
}
return 0;
}
# set_right, takes level, right, boolean. returns the altered level token.
sub set_right($$$) {
my ($level, $right, $boolean) = @_;
my $mask = 0;
# The magic..
my $new_job = 0x01;
my $edit_jobs = 0x02;
my $alloc_and_prio = 0x04;
my $setup = 0x08;
my $password = 0x10;
my $delete = 0x20;
my $stats = 0x40;
my $knowledge = 0x80;
# Use RegExps, so queries can be more fluid.
if($right =~ /job/) {
if($right =~ /new/) {
$mask = $new_job;
} elsif($right =~ /edit/) {
$mask = $edit_jobs;
}
} elsif($right =~ /password/) {
$mask = $password;
} elsif($right =~ /setup/) {
$mask = $setup;
} elsif($right =~ /allocate/ || $right =~ /set.*priority/) {
$mask = $alloc_and_prio;
} elsif($right =~ /delete/) {
$mask = $delete;
} elsif($right =~ /stat/) {
$mask = $stats;
} elsif($right =~ /know/) {
$mask = $knowledge;
}
if($boolean) {
$level |= $mask;
} else {
$level &= ~$mask;
}
return $level;
}
# hidden_fields, takes %data, returns a set of html hidden fields.
sub hidden_fields {
my %data = @_;
my $html = '';
foreach(keys(%data)) {
my $key = $_;
$html .= '<input type="hidden" name="'.$key.'" value="'.$data{$key}.'">'."\n";
}
return $html;
}
# text_field, takes name, value. returns html text input field.
sub text_field($$) {
my ($name, $value) = @_;
my $size = length($value) > 20 ? length($value) : 20;
my $html = "<input type=\"text\" name=\"$name\" size=\"$size\" value=\"$value\">\n";
return $html;
}
# n2month, takes unix month number, returns 3 letter month name.
sub n2month($) {
return (qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec))[$_[0]];
}
# gen_date, takes unix timestamp, returns date+time in form "11-Oct-2002 10:20"
sub gen_date($) {
my $time = int($_[0]);
my @temp = gmtime($time);
my $month = n2month($temp[4]);
my $day = $temp[3];
my $year = $temp[5] + 1900;
my $time = $temp[2].':'.($temp[1] < 10?'0'.$temp[1]:$temp[1]);
my $text = "$day-$month-$year $time";
return $text;
}
# date2timestamp, takes a text string something like "11-Oct-2002 10:20".
# returns unix timestamp. (intelligent e.g. "20:10 12/02/2000" is also valid)
sub date2timestamp($) {
my $text = $_[0];
my @months = qw(ja fe mar ap may jun jul au se oc no de);
my ($a,$b,undef) = split(/ /,$text,3);
my ($date,$time);
# Which part is time and which is date?
if($a =~ /:/) {
$time = $a;
$date = $b;
} else {
$time = $b;
$date = $a;
}
# Clean rubbish out of time
$time =~ s/([^0-9:])//g;
# Split Time
my ($hour,$minute,undef) = split(/:/,$time);
# Split Date
$date =~ s/([^0-9A-Za-z])/ /g;
my ($day,$month,$year,undef) = split(/ /,$date);
# See if month is tex tof number.
if ($month =~ /([A-Za-z])/) {
my $count = 0;
foreach(@months) {
my $m = $_;
if($month =~ /^$m/i) {
$month = $count;
}
++$count;
}
} else {
--$month;
}
if($year >= 100) {$year -= 1900;}
#print STDERR "timelocal(0,$minute,$hour,$day,$month,$year)\n";
return Time::Local::timelocal(0,$minute,$hour,$day,$month,$year);
}
# gen_elapsed, takes seconds and returns the time elapsed as a text string.
sub gen_elapsed($) {
my $sec = int($_[0]);
my $ret = '';
my ($min,$hour,$day);
#print STDERR "gen_elapsed; in:$sec\n";
if($sec >= (60*60*24)) {
$day = int($sec / (60*60*24));
$sec -= 60*60*24*$day;
}
if($sec >= (60*60)) {
$hour = int($sec / (60*60));
$sec -= 60*60*$hour;
}
if($sec >= 60) {
$min = int($sec / 60);
$sec -= 60*$min;
}
if($day) {
$ret .= "$day Days, ";
}
if($day || $hour) {
if($hour == 0) {
$hour = '0';
}
$ret .= "$hour Hours, ";
}
if($day || $hour || $min) {
if($min == 0) {
$min = '0';
}
$ret .= "$min Minutes, ";
}
if($sec == 0) {
$sec = '0';
}
$ret .= "$sec Seconds";
#print STDERR "gen_elapsed; out:$ret\n";
return $ret;
}
# select_field, takes name, currently selected option, list of options.
# returns html select input type.
sub select_field($$@) {
my ($name, $value, @options) = @_;
my $html = '';
$html .= "<SELECT name=\"$name\">\n";
foreach(@options) {
my $option = $_;
if($value && $option =~ /^$value/) {
$html .= "\t<OPTION SELECTED>$option</OPTION>\n";
} else {
$html .= "\t<OPTION>$option</OPTION>\n";
}
}
$html .= "</SELECT>\n";
return $html;
}
# text_area, takes name, rows, cols and value. returns html textarea.
sub text_area($$$$) {
my ($name, $rows, $cols, $value) = @_;
my $html = '';
$html .= "<TEXTAREA NAME=\"$name\"";
if($rows) {
$html .= " ROWS=$rows";
}
if($cols) {
$html .= " COLS=$cols";
}
$html .= ">\n";
$html .= $value;
$html .= "</TEXTAREA>\n";
return $html;
}
# submit_button, takes label for button, returns html submit button.
sub submit_button($) {
my $label = $_[0];
return "<input type=\"submit\" name=\"submit_type\" value=\"$label\">\n";
}
# hash2get, takes a hash of arguments, returns them in a get style url.
sub hash2get(%) {
my %parm = @_;
my @keys = keys(%parm);
my $url = '';
if(@keys > 0) {
$url .= '?';
foreach(@keys) {
my $key = $_;
$url .= $key.'='.$parm{$key}.'&';
}
chop($url);
}
return $url;
}
# status, convert status number to Text and vice versa.
sub status($) {
my $status = $_[0];
# print STDERR "status: in '$status'\n";
my $out;
# Text to int, or int to Text?
if($status =~ /([A-Za-z])/) {
# Text to int..
if($status =~ /New/i) {
$out = 1;
} elsif($status =~ /Active/i) {
$out = 2;
} elsif($status =~ /Ready/i && $status =~ /User Test/i) {
$out = 4;
} elsif($status =~ /Suspend/i) {
$out = 64;
} elsif($status =~ /Closed/i) {
$out = 128;
}
} else {
# int to Text..
if($status == 1) {
$out = 'New';
} elsif($status == 2) {
$out = 'Active';
} elsif($status == 4) {
$out = 'Ready for user testing';
} elsif($status == 64) {
$out = 'Suspended';
} elsif($status == 128) {
$out = 'Closed';
}
}
# print STDERR "status: return '$out'\n";
return $out;
}
# statusl, returns a list of valid status texts.
sub statusl {
my @list;
# List of Status Codes.
my @sti = (1,2,4,64,128);
foreach(@sti) {
push(@list,status($_));
}
return @list;
}
# priol, returns a list of valid priorities.
sub priol {
return ('NA',1,2,3,4,5);
}
# priof, priority filter, converts 0 to NA, NA to 0.
sub priof($) {
my $p = $_[0];
if($p =~ /NA/) {
return 0;
} elsif($p == 0) {
return 'NA';
} else {
return $p;
}
}
# filter, takes string filters and dereferences stuff.
sub filter($) {
my $text = shift;
if($text) {
$text =~ s/"/'/g;
$text =~ s/`/'/g;
$text =~ s/'/\\'/g;
$text =~ s/([<>])/\\'/g;
}
return $text;
}
# radio_fields, takes name, currently checked and hash of value => option.
# returns html radio field.
sub radio_fields($$%) {
my ($name, $checked, %parm) = @_;
my $tab = '';
my $html = '';
foreach my $key (keys(%parm)) {
if($key =~ /$checked/ && $checked) {
$tab = ' CHECKED';
} else {
$tab = '';
}
$html .= '<br><input TYPE="radio" NAME="'.$name.'" VALUE="'.$key.'"'.$tab.'>'.$parm{$key}."\n";
}
return $html;
}
# fmt, takes columns, rows, string.
# returns the string html formated to those dimensions
sub fmt($$$) {
my ($cols, $rows, $data) = @_;
#my $chars = $cols * $rows;
#my @data = split(//,$data,($chars+1));
#my ($i,$j);
#if(length($data) > $cols) {
# $data = '';
# for ($i = 0; $i < $rows; ++$i) {
# for ($j = 0; $j < $cols; ++$j) {
# $data .= $data[($i * $cols) + $j];
# }
# $data .= "<br>\n";
# }
#}
return $data;
}
# popup_redirect, takes url, returns javascript.
# which spawns a new window and redirects it to url.
sub popup_redirect($) {
my $url = $_[0];
my $html = '';
$html .= '<script language="JavaScript">'."\n";
$html .= 'pop = window.open("","pop","");'."\n";
$html .= "pop.document.write('<head>');\n";
$html .= "pop.document.write('".meta_redirect($url)."'>);\n";
$html .= "pop.document.write('<title> </title>');\n";
$html .= "pop.document.write('</head>');\n";
$html .= "</script>\n";
return $html;
}
# job_valid, takes jobid and dbh. returns 1 if job exists.
sub job_valid($$) {
my ($jobid, $dbh) = @_;
$jobid =~ s/([^0-9])//g;
# Quite simple, if either is blank fail..
if($dbh && $jobid) {
my $query = "SELECT jobid FROM job WHERE jobid='$jobid'";
my $result = $dbh->query($query);
my @row = $result->fetchrow();
if($row[0] == $jobid) {
return 1;
} else {
return 0;
}
} else {
return 0;
}
}
# event_type, takes text type and event code. returns 1 if that code is set.
sub event_type($$) {
my ($text, $code) = @_;
# Magic..
my $comment = 0x01;
my $status_change = 0x02;
my $set_priority = 0x04;
my $allocate = 0x08;
# Vague Checking..
if($text =~ /comment/i && ($code & $comment)) {
return 1;
} elsif($text =~ /status.change/i && ($code & $status_change)) {
return 1;
} elsif($text =~ /set.priority/i && ($code & $set_priority)) {
return 1;
} elsif($text =~/allocate/i && ($code & $allocate)) {
return 1;
}
# Nope
return 0;
}
# auth_fail_page, takes username, returns redirect to the index login page, with the username.
sub auth_fail_page($) {
my $user = $_[0];
my $html = '';
$html .= meta_redirect('index.pl'.hash2get(username => $user, fail => 1));
$html .= CGI::end_html();
return $html;
}
# dhtml_header, css for dhtml, needs to be in html <head>
sub dhtml_header {
return
'
<STYLE TYPE="text/css">
<!--
.DEK {POSITION:absolute;VISIBILITY:hidden;Z-INDEX:200;}
//-->
</STYLE>
';
}
# dhtml_main, spits out the script to do DHTML message boxes.
sub dhtml_main {
return
'
<DIV ID="dek" CLASS="dek"></DIV>
<SCRIPT TYPE="text/javascript">
<!--
Width=screen.availWidth/2;
Xoffset=-(Width/2);
Yoffset= 20;
var active=0;
var nav,old,iex=(document.all);
if(navigator.appName=="Netscape"){(document.layers)?nav=true:old=true;}
if(!old){
var skn=(nav)?document.dek:dek.style;
if(nav)document.captureEvents(Event.MOUSEMOVE);
document.onmousemove=get_mouse;
}
function popup(msg,bak){
active=1;
var content="<TABLE WIDTH="+Width+" BORDER=1 BORDERCOLOR=black CELLPADDING=2 CELLSPACING=0 "+
"BGCOLOR="+bak+"><TD ALIGN=center><FONT COLOR=white face=verdana SIZE=1><b>"+msg+"</b></FONT></TD></TABLE>";
if(old){return;}
else{
if(nav){skn.document.write(content);skn.document.close();skn.visibility="visible";}
if(iex){document.all("dek").innerHTML=content;skn.visibility="visible";}
}
}
function get_mouse(e){
if(active) {
var x=(nav)?e.pageX:event.x+document.body.scrollLeft;skn.left=x+Xoffset;
var y=(nav)?e.pageY:event.y+document.body.scrollTop;skn.top=y+Yoffset;
}
}
function kill(){
if(!old){active=0;skn.visibility="hidden";}
}
//-->
</SCRIPT>';
}
# dhtml_wrap, wraps $text in DHTML so that $other pops up on mouseover.
sub dhtml_wrap($$) {
my ($text, $other) = @_;
my $html;
#$text =~ s/(["'\n\r])//g;
$other =~ s/(["'])//g;
$other =~ s/([\r\n])+/\n/g;
$other =~ s/([\n])/<br>/g;
$html .= "<a ONMOUSEOVER=\"popup('$other','#6699ff')\"; ONMOUSEOUT=\"kill()\">$text</a>\n";
return $html;
}
# isie, returns 1 if client browser is Internet Exploiter.
sub isie {
if(CGI::user_agent() =~ /MSIE/) {
return 1;
} else {
return 0;
}
}
# mime, takes a filename, returns a guess at its mime type.
sub mime($) {
my $type = shift;
my $mimetypes = '/etc/mime.types';
open(MIME,$mimetypes);
my @mime = readline *MIME;
close(MIME);
foreach my $line (@mime) {
if ($line =~ /[#].*/) {
$line='';
}
if ($line =~ /[\t\n ]$type[\t\n ]/i) {
my @buffer = split(/[\t ]/,$line);
return($buffer[0]);
}
}
return('application/octet-steam');
}
sub carrier_encode {
my @fields = @_;
my $buffer;
$buffer = join("\t",@fields);
$buffer = MIME::Base64::encode($buffer);
$buffer =~ s/\n//g;
return $buffer;
}
sub carrier_decode {
my $buffer = $_[0];
my @temp = split(//,$buffer);
my ($i,$j);
$buffer = '';
for($i = 0; $i*76 < @temp; ++$i) {
for($j = 0; $j < 76; ++$j) {
$buffer .= $temp[$i*80 + $j];
}
$buffer .= "\n";
}
return split(/\t/,MIME::Base64::decode($buffer));
}
# cut, returns $string to $len long
sub cut($$) {
my ($len, $string) = @_;
if(length($string) > $len) {
my @temp = split(//,$string,($len+1));
pop(@temp);
return join('',@temp);
} else {
return $string;
}
}
sub alert($) {
my $msg = $_[0];
return
'
<SCRIPT TYPE="text/javascript">
<!--
alert('.filter($msg).'.);
//-->
</SCRIPT>';
}
sub set_sectoken($$$) {
my ($dbh, $user, $token) = @_;
my $query = "UPDATE user SET sectoken='$token' WHERE username='$user'";
$dbh->query($query);
}
1;
wjl-0.26/src/modules/WJL.pm
/files/tmp/wjl-0.26/src/modules/WJL.pm.html
# *-* Perl *-*
# WJL - Web Job Logs Perl Module
# WJL V0.26, Module V0.21
# Carl Ritson - 2002
package WJL;
require Mysql;
require MIME::Base64;
use vars qw($VERSION);
$VERSION = '0.21';
# Hash Definitions use for Reference.
%job_info_hash = (
'jobid' => 1,
'started' => 1,
'problem_started' => 1,
'caller' => 1,
'dept' => 1,
'username' => 1,
'priority' => 1,
'allocated_to' => 1
);
%event_info_hash = (
'username' => 1,
'type' => 1,
'status' => 1,
'data' => 1,
'date' => 1
);
# The WJL new Function, spawns a new WJL Object.
sub New {
my ($dbh) = @_;
#my $dbh = Mysql->connect($db_host, $db_name, $db_user, $db_password);
my $self = {
'dbh' => $dbh
};
bless $self;
#print STDERR "Class:$class\n";
return $self;
}
# Query Function
# saves other functions from having to reference the dbh directly.
sub query {
my $self = shift;
my $query = shift;
#print STDERR "QUERY:\"$query\"\n";
my $dbh = $self->{'dbh'};
my $result = $dbh->query($query);
return $result;
}
sub no_active_jobs {
my $self = shift;
my $username = shift;
my $jobs = 0;
my $result = $self->query("SELECT jobid FROM job WHERE allocated_to='$username'");
my @row;
while(@row = $result->fetchrow()) {
my $jobid = $row[0];
my $result = $self->query("SELECT status FROM event WHERE jobid=$jobid ORDER BY date DESC LIMIT 1");
my @dat = $result->fetchrow();
if($dat[0] < 64) {
++$jobs;
}
}
return $jobs;
}
sub user_exists {
my $self = shift;
my $username = shift;
my $query = "SELECT username FROM user WHERE username=\'$username\'";
my $result = $self->query($query);
if ($result->fetchrow()) {
return 1;
} else {
return 0;
}
}
sub del_user {
my $self = shift;
my $username = shift;
my $query = "DELETE FROM user WHERE username=\'$username\'";
$self->query($query);
#print STDERR "DELETE $username\n";
}
sub _filter($) {
my $text = shift;
if($text) {
$text =~ s/"/'/g;
$text =~ s/`/'/g;
$text =~ s/'/\\'/g;
$text =~ s/([<>])/\\'/g;
}
return $text;
}
# Returns the Number of Seconds that are actualy worked between,
# two timestamps, based on 9-16.30 days, 5 day weeks...
sub workingseconds($$) {
# These two constants alter the worked day, edit these only
my $daystart = 9; # Day Start
my $dayfinish = 16.5; # Day Finish
# End Constants
my ($from, $to) = @_;
my @mdays = (31,28,31,30,31,30,31,31,30,31,30,31);
my @stat_s = localtime($from);
my @stat_e = localtime($to);
my $perday = ($dayfinish - $daystart)*60*60;
my $daysdiff = 0;
my $daysspare = 0;
my $monsdiff = 0;
my $wks = 0;
my $sec = 0;
if($stat_s[5] != $stat_e[5]) {
$monsdiff = (11 - $stat_s[4]) + $stat_e[4];
} else {
$monsdiff = $stat_e[4] - $stat_s[4];
}
if($monsdiff) {
my $j = $stat_s[4];
my $i = 0;
for($i = 0; $i < $monsdiff; ++$i) {
$daysdiff += $mdays[$j];
++$j;
if($j > 11) {
$j = 0;
}
}
}
$daysdiff -= $stat_s[3];
$daysdiff += $stat_e[3];
$wks = int($daysdiff/7);
$daysspare = $daysdiff - $wks*7;
$daysdiff = $wks * 5; # 5 Days worked each week.
if($daysspare) {
my $days = $daysspare;
if($stat_s[6] == 0) {
--$days;
}
if(($stat_s[6] + $daysspare) > 5) {
--$days;
}
if(($stat_s[6] + $daysspare) > 6) {
--$days;
}
$daysdiff += $days;
}
$sec = $daysdiff * $perday;
if($stat_s[6] == 0 || $stat_s[6] == 6) {
$stat_s[0] = 0;
$stat_s[1] = 0;
$stat_s[2] = $daystart;
}
if($stat_e[6] == 0 || $stat_e[6] == 6) {
$stat_e[0] = 0;
$stat_e[1] = 0;
$stat_e[2] = $daystart;
}
if($stat_s[2] >= $dayfinish) {
$stat_s[2] = $dayfinish;
$stat_s[1] = 0;
$stat_s[0] = 0;
}
if($stat_e[2] >= $dayfinish) {
$stat_e[2] = $dayfinish;
$stat_e[1] = 0;
$stat_e[0] = 0;
}
if($stat_e[2] < $daystart) {
$stat_e[2] = $daystart;
$stat_e[1] = 0;
$stat_e[0] = 0;
}
$sec += ((($stat_e[2] - $daystart) - ($stat_s[2] - $daystart)))*60*60;
$sec += ($stat_e[1] - $stat_s[1])*60;
$sec += $stat_e[0] - $stat_s[0];
return $sec > 0 ? $sec : 0;
}
sub timediff {
my ($start,$finish,$real) = @_;
if($real) {
return ($finish - $start);
} else {
return workingseconds($start,$finish);
}
}
sub user {
my ($self, %u) = @_;
my ($username,$sectoken,$initials,$full_name,$level);
$username = _filter($u{username});
$full_name = _filter($u{fullname});
$initials = _filter($u{initials});
$level = $u{level};
$sectoken = $u{sectoken};
if(!$full_name && !$initials && !$sectoken) {
if($self->user_exists($username)) {
my $query = "SELECT full_name,initials,sectoken,level FROM user WHERE username='$username'";
my $result = $self->query($query);
my @row = $result->fetchrow();
if(@row) {
$u{fullname} = $row[0];
$u{initials} = $row[1];
$u{sectoken} = $row[2];
$u{level} = $row[3];
return %u;
} else {
return 0;
}
}
} elsif($self->user_exists($username)) {
if($full_name) {
$self->query("UPDATE user SET full_name='$full_name' WHERE username='$username'");
}
if($initials) {
$self->query("UPDATE user SET initials='$initials' WHERE username='$username'");
}
$self->query("UPDATE user SET level=$level WHERE username='$username'");
if($sectoken) {
$self->query("UPDATE user SET sectoken='$sectoken' WHERE username='$username'");
}
} elsif($username) {
my $query = "INSERT INTO user (username,sectoken,initials,full_name,level) VALUES('$username','$sectoken','$initials','$full_name',$level)";
$self->query($query);
}
}
sub list_depts {
my $self = shift;
my $result = $self->query("SELECT dept FROM dept ORDER BY dept ASC");
my @list;
my @row;
while(@row = $result->fetchrow()) {
push(@list,$row[0]);
}
return @list;
}
sub list_users {
my $self = shift;
my $result = $self->query("SELECT initials FROM user ORDER BY initials ASC");
my @list;
my @row;
while(@row = $result->fetchrow()) {
push(@list,$row[0]);
}
return @list;
}
sub list_usernames {
my $self = shift;
my $result = $self->query("SELECT username FROM user ORDER BY initials ASC");
my @list;
my @row;
while(@row = $result->fetchrow()) {
push(@list,$row[0]);
}
return @list;
}
sub list_technicians {
my $self = shift;
my @list = $self->list_usernames();
my @techs;
foreach my $uid (@list) {
my %user = $self->user(username => $uid);
if(($user{level} & 0x02) || ($user{level} & 0x01)) {
push(@techs,$user{initials});
}
}
return @techs;
}
sub job {
my ($self, $jobid) = @_;
my $dbh = $self->{'dbh'};
my ($started,$problem_started,$caller,$dept,$priority,$username,$allocated_to);
my $new_job = 1;
if ($jobid) {
my $query = "SELECT started,problem_started,caller,dept,priority,username,allocated_to FROM job WHERE jobid='$jobid'";
my $result = $self->query($query);
($started,$problem_started,$caller,$dept,$priority,$username,$allocated_to) = $result->fetchrow();
if (!$started) {
return 0;
}
$new_job = 0;
} else {
$jobid = 0;
}
my $newself = {
"dbh" => $dbh,
"jobid" => $jobid,
"started" => $started,
"problem_started" => $problem_started,
"caller" => $caller,
"dept" => $dept,
"username" => $username,
"priority" => $priority,
"allocated_to" => $allocated_to,
"new_job" => $new_job,
"time" => 0,
"changed" => 0
};
bless $newself;
return $newself;
}
sub info {
my ($self, %info) = @_;
my %ret;
if(keys(%info) == 0) {
foreach(keys(%job_info_hash)) {
#print STDERR "INFO \$ret{$_} = ".$self->{$_}."\n";
$ret{$_} = $self->{$_};
}
return %ret;
} else {
# Delete these Keys from the hash
# to prevent them overwritting those in the object.
delete($info{jobid});
delete($info{dbh});
foreach(keys(%info)) {
#print STDERR "INFO:\$self->{$_} = ".$info{$_}."\n";
$self->{$_} = $info{$_};
}
$self->{'changed'} = 1;
}
}
# Deletes the Job and all attached events.
sub del {
my $self = shift;
my $jobid = $self->{'jobid'};
if($jobid > 0) {
$self->query("DELETE FROM event WHERE jobid=$jobid");
$self->query("DELETE FROM job WHERE jobid=$jobid");
# Make the jobid void to prevent future work on this job.
$self->{'jobid'} = -1;
}
}
sub commit {
my $self = shift;
my $jobid = $self->{'jobid'};
# The && jobid > -1, is a sanity check to prevent calls on deleted jobs.
if(($self->{'changed'} || $self->{'new_job'}) && $jobid > -1) {
my $started = $self->{'started'};
my $problem_started = $self->{'problem_started'};
my $caller = $self->{'caller'};
my $dept = $self->{'dept'};
my $priority = $self->{'priority'};
my $username = $self->{'username'};
my $allocated_to = $self->{'allocated_to'};
# Note the Lack of Error Handling
# I am assuming that the insert/update are 'assured' ;)
if($self->{'new_job'}) {
$self->query("INSERT INTO job (started,problem_started,caller,dept,priority,username,allocated_to) VALUES ($started,$problem_started,'$caller','$dept',$priority,'$username','$allocated_to')");
# Get the jobid of the new job.
my $result = $self->query("SELECT jobid FROM job WHERE started=$started AND dept='$dept' AND username='$username' ORDER BY jobid DESC LIMIT 1");
my @temp = $result->fetchrow();
$self->{'jobid'} = $temp[0];
$self->{'new_job'} = 0;
} else {
$self->query("UPDATE job SET started=$started, problem_started=$problem_started, caller='$caller', dept='$dept', priority=$priority, username='$username', allocated_to='$allocated_to' WHERE jobid=$jobid");
}
$self->{'changed'} = 0;
}
}
sub event {
my ($self, $eventid) = @_;
my $jobid = $self->{'jobid'};
# Sanity Check: Only work on Real Jobs.
if($jobid > 0) {
my $result = $self->query("SELECT username,type,status,data,date FROM event WHERE jobid=$jobid AND eventid=$eventid");
if($result) {
my @temp = $result->fetchrow();
my %info = (
eventid => $eventid,
username => $temp[0],
type => $temp[1],
status => $temp[2],
data => $temp[3],
date => $temp[4]
);
return %info;
}
}
return 0;
}
sub new_event {
my ($self, %event) = @_;
my $jobid = $self->{'jobid'};
my $eventid = 0;
# More Sanity Checking.. 4 Elements as we don't expect date.
if($jobid > -1 && keys(%event) >= 4) {
if(!defined($event{date})) {
$event{date} = time();
}
# Make sure this Job is in the DB
$self->commit();
# If this was a new Job we now know its ID.
$jobid = $self->{'jobid'};
$self->query("INSERT INTO event (username,type,status,data,date,jobid) VALUES('".$event{username}."',".$event{type}.",".$event{status}.",'".$event{data}."',".$event{date}.",$jobid)");
# Whats the chances of the same user adding 2 events at once..
# 0% Touch Wood ;)
my $result = $self->query("SELECT eventid FROM event WHERE jobid=$jobid AND username='".$event{username}."' ORDER BY date DESC LIMIT 1");
my @temp = $result->fetchrow();
$eventid = $temp[0];
}
return $eventid;
}
sub status {
my $self = shift;
my $jobid = $self->{'jobid'};
if($jobid > 0) {
my $result = $self->query("SELECT status FROM event WHERE jobid=$jobid ORDER BY date DESC LIMIT 1");
my @temp = $result->fetchrow();
return $temp[0];
}
return -1;
}
sub last_event {
my $self = shift;
my $jobid = $self->{'jobid'};
if($jobid > 0) {
my $result = $self->query("SELECT eventid FROM event WHERE jobid=$jobid ORDER BY date DESC LIMIT 1");
my @temp = $result->fetchrow();
my $eventid = $temp[0];
return $self->event($eventid);
}
}
sub first_event {
my $self = shift;
my $jobid = $self->{'jobid'};
if($jobid > 0) {
my $result = $self->query("SELECT eventid FROM event WHERE jobid=$jobid ORDER BY date ASC LIMIT 1");
my @temp = $result->fetchrow();
my $eventid = $temp[0];
return $self->event($eventid);
}
}
sub update_event {
my ($self,$eventid,$data) = @_;
my $jobid = $self->{'jobid'};
if($jobid > 0 && $eventid > 0) {
$self->query("UPDATE event SET data='$data' WHERE eventid=$eventid AND jobid=$jobid");
}
}
sub delete_event {
my ($self,$eventid) = @_;
my $jobid = $self->{'jobid'};
if($jobid > 0 && $eventid > 0) {
$self->query("DELETE FROM event WHERE eventid=$eventid AND jobid=$jobid");
}
}
sub mangle_event {
my ($self,%event) = @_;
$self->query("UPDATE event SET username='".$event{username}."', type=".$event{type}.", status=".$event{status}.", data='".$event{data}."', date=".$event{date}." WHERE eventid=".$event{eventid});
}
sub description {
my ($self, $description) = @_;
my %ev = $self->first_event();
$self->update_event($ev{eventid},$description);
}
sub list_events {
my $self = shift;
my $jobid = $self->{'jobid'};
my @ids;
if($jobid > 0) {
my @row;
my $result = $self->query("SELECT eventid FROM event WHERE jobid=$jobid ORDER BY date ASC");
while(@row = $result->fetchrow()) {
push(@ids,$row[0]);
}
}
return @ids;
}
sub user2initials {
my ($self, $user) = @_;
my $result = $self->query("SELECT initials FROM user WHERE username='$user'");
my @temp = $result->fetchrow();
return $temp[0];
}
sub initials2user {
my ($self, $initials) = @_;
my $result = $self->query("SELECT username FROM user WHERE initials='$initials'");
my @temp = $result->fetchrow();
return $temp[0];
}
sub fullname {
my ($self, $user) = @_;
my $result = $self->query("SELECT full_name FROM user WHERE username='$user'");
my @temp = $result->fetchrow();
return $temp[0];
}
sub set_realtime {
my ($job,$set) = @_;
$job->{'time'} = ~($set);
}
sub get_realtime {
my ($job) = shift;
return ~($job->{'time'});
}
sub response_time {
#print STDERR "Response Time\n";
my $job = shift;
my (%evf,%evl);
my ($i,$fc);
my @events = $job->list_events();
%evf = $job->event($events[0]);
for($i = 1; $i < @events && !$fc; ++$i) {
%evl = $job->event($events[$i]);
if($evl{type} & 0x01) { # Time of First Comment.
$fc = $evl{date};
}
}
if($fc) {
return timediff($evf{date},$fc,$job->get_realtime());
} else {
return 0;
}
}
sub elapsed_time {
my $job = shift;
my %ev;
my ($active,$i,$prev,$total);
my @events = $job->list_events();
%ev = $job->event($events[0]);
$prev = $ev{date};
if($ev{status} < 64) {
$active = 1;
}
for($i = 1; $i < @events; ++$i) {
%ev = $job->event($events[$i]);
if($ev{status} >= 64) {
if($active) {
$active = 0;
$total += timediff($prev,$ev{date},$job->get_realtime());
}
} else {
if(!$active) {
$active = 1;
$prev = $ev{date};
}
}
}
if($active) {
$total += timediff($prev,time(),$job->get_realtime());
}
return $total;
}
sub comments {
my $job = shift;
my @events = $job->list_events();
my @comments;
foreach my $event (@events) {
my %ev = $job->event($event);
if($ev{type} & 0x01) {
push(@comments,$ev{data});
}
}
return @comments;
}
# Used to prevent multiple submissions of the same job.
sub get_job_atomic {
my ($self, $user, $time) = @_;
my $result = $self->query("SELECT time FROM atomic WHERE username='$user'");
my @row = $result->fetchrow();
if($row[0] == $time) {
return 0;
} else {
return 1;
}
}
# Used to prevent multiple submissions of the same job.
sub set_job_atomic {
my ($self, $user, $time) = @_;
my $result = $self->query("SELECT time FROM atomic WHERE username='$user'");
my @row = $result->fetchrow();
if($row[0]) {
$self->query("UPDATE atomic SET time=$time WHERE username='$user'");
} else {
$self->query("INSERT INTO atomic (username,time) VALUES('$user',$time)");
}
}
# list jobs routine.
sub list_jobs {
my ($self, %parm) = @_;
my $query = "SELECT jobid FROM job";
my $filter = '';
my $order = '';
foreach(keys(%parm)) {
my $key = $_;
if($key =~ /order/) {
my $char = chop($parm{$key});
if($char =~ /([-+])/) {
if($char =~ /-/) {
$char = ' DESC';
} else {
$char = ' ASC';
}
} else {
$parm{$key} .= $char;
$char = '';
}
$order = ' ORDER BY '.$parm{$key}.$char;
} else {
$filter .= " $key='".$parm{$key}."'";
}
}
if($filter) {
$filter = ' WHERE'.$filter;
}
$query .= $filter.$order;
my $result = $self->query($query);
my @ids;
@ids = $result->fetchcol();
return @ids;
}
# add_knowledge, Base64 encode data into database
sub add_knowledge {
my ($self,%file) = @_;
$file{data} = MIME::Base64::encode($file{data});
#print STDERR "add:".length($file{data})."\n";
my $query = "INSERT INTO knowledge (jobid,name,description,data) VALUES(".$self->{'jobid'}.",'".$file{name}."','".$file{description}."','".$file{data}."')";
$self->query($query);
}
# get_knowledge, Base64 decode data out of database
sub get_knowledge {
my ($self,$name) = @_;
my $query = "SELECT data FROM knowledge WHERE name='$name'";
my $result = $self->query($query);
my @temp = $result->fetchrow();
return MIME::Base64::decode($temp[0]);
}
# list_knowledge, list the knowledge of a job, either by self reference or parm
sub list_knowledge {
my ($self,$jid) = @_;
my $jobid;
if($jid) {
$jobid = $jid;
} else {
$jobid = $self->{'jobid'};
}
my $query = "SELECT name FROM knowledge WHERE jobid=$jobid";
my $result = $self->query($query);
my (@names,@temp);
while(@temp = $result->fetchrow()) {
push(@names,$temp[0]);
}
return @names;
}
# find_knowledge, based on words..
sub find_knowledge {
my ($self, @words) = @_;
my $equery = "SELECT jobid FROM event WHERE type <= 3";
my $kquery = "SELECT jobid FROM knowledge WHERE jobid > 0";
foreach my $word (@words) {
$word = _filter($word);
$word =~ s/%/\%/g;
$word = "\%$word%";
$equery .= " AND data LIKE \"$word\"";
$kquery .= " AND description LIKE \"$word\"";
}
my $eresult = $self->query($equery);
my $kresult = $self->query($kquery);
my %jobids;
my @temp;
my @names;
while(@temp = $eresult->fetchrow()) {
$jobids{$temp[0]} = 1;
}
while(@temp = $kresult->fetchrow()) {
$jobids{$temp[0]} = 1;
}
foreach my $jobid (keys(%jobids)) {
push(@names,$self->list_knowledge($jobid));
}
return @names;
}
sub describe_knowledge {
my ($self, $name) = @_;
my $query = "SELECT description FROM knowledge WHERE name='$name'";
my $result = $self->query($query);
my @temp = $result->fetchrow();
return $temp[0];
}
sub delete_knowledge {
my ($self, $name) = @_;
if($name) {
my $query = "DELETE FROM knowledge WHERE name='$name'";
$self->query($query);
}
}
# day_stats, Returns statistics for the day beginning time
sub day_stats {
my ($self,$type,$time) = @_;
my $i;
my $st = $time;
my $et = $st + 24*60*60;
my ($query,$result);
if($type =~ /^opened$/) {
$query = "SELECT jobid FROM job WHERE started > $st AND started < $et";
$result = $self->query($query);
while($result->fetchrow()) {
++$i;
}
} elsif($type =~ /^closed$/) {
$query = "SELECT eventid FROM event WHERE date > $st AND date < $et AND status = 128";
$result = $self->query($query);
while($result->fetchrow()) {
++$i;
}
} elsif($type =~ /^comments$/) {
$query = "SELECT eventid FROM event WHERE date > $st AND date < $et AND type = 1";
$result = $self->query($query);
while($result->fetchrow()) {
++$i;
}
}
return $i;
}
# downtime, returns the downtime involved in a job
sub downtime {
my ($self) = @_;
my $prio = $self->{'priority'};
my $r = $self->get_realtime();
$self->set_realtime(0);
my $duration = $self->elapsed_time();
$self->set_realtime($r);
if($prio > 0 && $prio < 5) {
return int($duration / ($prio*$prio));
} else {
return 0;
}
}
# due, returns the timestamp of when this job is estimated to finish.
sub due {
my $job = shift;
my $now = time;
my ($query,$result);
my @temp;
# If job is suspended, or closed don't bother :)
if($job->status() >= 64) {
return -1;
}
# Don't Estimate for unallocated Jobs
if(!($job->{'allocated_to'})) {
return -1;
}
# Don't Act for Jobs with no priority
if($job->{'priority'} == 0) {
return -1;
}
# Figure out who this job was initialy allocated to
$query = "SELECT data FROM event WHERE jobid=".$job->{'jobid'}." AND type=8 ORDER BY date ASC LIMIT 1";
$result = $job->query($query);
@temp = $result->fetchrow();
my %user;
if($temp[0]) {
%user = $job->user(username => $temp[0]);
#print STDERR "picking db user:".$user{username}."\n";
} else {
%user = $job->user(username => $job->{'allocated_to'});
#print STDERR "picking job user:".$user{username}."\n";
}
my $date = $job->{'started'};
$query = "SELECT jobid FROM job WHERE allocated_to='".$user{username}."' AND started < $date";
$result = $job->query($query);
my %jobs;
while(@temp = $result->fetchrow()) {
my $jobid = $temp[0];
my $query = "SELECT status FROM event WHERE date < $date AND jobid=$jobid ORDER BY date DESC LIMIT 1";
my $result = $job->query($query);
my ($status,@rubbish) = $result->fetchrow();
if($status < 64) {
my $j = $job->job($jobid);
++$jobs{$j->{'priority'}};
#print STDERR "++jobs{".$j->{'priority'}."}\n";
}
}
# Time alloted to different priorities of jobs.
my %prio_map = (
1 => 60*60*6,
2 => 60*60*12,
3 => 60*60*24,
4 => 60*60*48,
5 => 60*60*96
);
my $time_alloted = 0;
my $i;
for($i = 1; $i <= $job->{'priority'}; ++$i) {
$time_alloted += $prio_map{$i} * $jobs{$i};
}
#print STDERR "time_alloted:$time_alloted\n";
$time_alloted += $prio_map{$job->{'priority'}};
$i = $job->get_realtime(); # Store The Present Realtime
$job->set_realtime(0); # Set Realtime Off
my $remaining = $time_alloted - $job->elapsed_time();
$job->set_realtime($i); # Restore Previous Realtime
#print STDERR "time_alloted:$time_alloted\n";
#print STDERR "remaining:$remaining\n";
# Ok this is abit of hack as I can't be bothered to write a
# reverse workingseconds at the moment...
my $due = $now;
$i = 0;
while($i <= $remaining) {
my @due = localtime($due);
$due += 60*60 - $due[0] - $due[1]*60;
$i = workingseconds($now,$due);
#print STDERR "due: $due, i: $i\n";
}
return ($due != $now ? $due : 0);
}
wjl-0.26/src/inst
/files/tmp/wjl-0.26/src/inst.html
#!/bin/sh
mkdir $1 &> /dev/null
mkdir $2 &> /dev/null
cp -a src/cgi-bin/* $1
cp -a src/www/* $2
cp -a src/modules/* $3
rm -f $3/WJLCore.pm.in
wjl-0.26/src/cgi-bin/stat_graph.pl
/files/tmp/wjl-0.26/src/cgi-bin/stat_graph.pl.html
#!/usr/bin/perl
# Statistical Graph Generator for Web Logs Software
# WJL V0.26, Page V0.11
# Carl Ritson - 2002
# Library Includes
use GD::Graph::bars;
use GD::Graph::colour qw(:colours);
use Mysql;
use CGI qw/:standard/;
use strict;
use WJL;
use WJLCore;
# Main Program Body
# CGI & DBH
my $page = new CGI;
my $dbh = Mysql->connect(db_login()) || db_error;
# Slightly different structure, as this doesn't send back HTML
if($dbh) {
my %userinfo = get_user_info($page,'image/png');
if (user_valid($dbh,$userinfo{username},$userinfo{sectoken})) {
my $level = user_level($dbh,$userinfo{username});
if(has_right($level,'stat')) {
my $wjl = WJL::New($dbh);
my $start = $page->param('start');
my $stop = $page->param('stop');
my $type = $page->param('type');
my $days = int(($stop - $start)/(24*60*60));
my $i;
my (@data,@days);
for($i = 0; $i < $days; ++$i) {
my @data = $wjl->day_stats($type,$start + $i*24*60*60);
my @temp = localtime($start + $i*24*60*60);
push(@days,$temp[3].' '.n2month($temp[4]));
}
@data = (
[@days],
[@data]
);
my $graph = GD::Graph::bars->new(400,200);
$graph->set(
#x_label => 'Days',
x_label_skip => int($days/9),
transparent => 0
#bgclr => _rgb('black')
);
binmode(STDOUT);
print STDOUT $graph->plot(\@data)->png();
}
}
}
wjl-0.26/src/cgi-bin/menu.pl
/files/tmp/wjl-0.26/src/cgi-bin/menu.pl.html
#!/usr/bin/perl
# Main Menu Page for Web Logs Software
# WJL V0.26, Page V0.2
# Carl Ritson - 2002
# Library Include
use Mysql;
use CGI qw/:standard/, 'shortcuts', 'center';
use strict;
use WJL;
use WJLCore;
# Main Program Body
# CGI & DBH
my $page = new CGI;
my $dbh = Mysql->connect(db_login()) || db_error();
# Predefine some Variables
my $user_valid = 0;
my %userinfo;
# Call Start Page Function, only if we have a DBH.
if ($dbh) {
($user_valid, %userinfo) = start_page($page,$dbh);
}
if ($user_valid) {
my $wjl = WJL::New($dbh);
my $user = $userinfo{username};
my $no_jobs = $wjl->no_active_jobs($user);
my $title = h3("Main Menu");
my $level = user_level($dbh,$user);
my %parm;
if($userinfo{security} =~ /high/) {
%parm = %userinfo;
}
$parm{src} = 'menu.pl';
my $menu = '';
# New Job, Edit Jobs, Job List, Job Report, (Setup/Password)
if(has_right($level,'new_job')) {
$menu .= form_button('New Job','new_job.pl',%parm).br();
}
if(has_right($level,'edit_jobs')) {
$menu .= form_button('Edit Job','edit_job.pl',%parm).br();
}
$menu .= form_button('Job List','job_list.pl',%parm).br();
$menu .= form_button('Job Report','job_report.pl',%parm).br();
if(has_right($level,'stat')) {
$menu .= form_button('Statistics','stats.pl',%parm).br();
}
if(has_right($level,'knowledge')) {
$menu .= form_button('Knowledge','knowledge_find.pl',%parm).br();
}
# Users get one or the other
if(has_right($level,'setup')) {
$menu .= form_button('Setup','setup_menu.pl',%parm).br();
} elsif(has_right($level,'password')) {
$menu .= form_button('Change Password','change_passwd.pl',%parm).br();
}
$menu .= form_button('Log Out','index.pl',logout => 1,security => $userinfo{security}).br();
print start_html(
-title=>"Web Job Logs - ".organisation(),
-style=>{'src'=>'/wjl-style.css'}
),
"<table border=\"0\" width=\"100%\">\n",
Tr(
'<td WIDTH="10%"></td>',
'<td WIDTH="80%"></td>',
'<td WIDTH="10%"></td>'
),
Tr(
td(center("<b>Jobs:</b> $no_jobs"),),
td(''),
td(center("<b>User:</b><br>".$wjl->fullname($user)))
),
Tr(
td(''),
td(center($title)),
td('')
),
Tr(
td(''),
td(center($menu)),
td('')
),
"</table>\n",
end_html();
} else {
# If we don't have a DBH an error page has already been printed.
if($dbh) {
print auth_fail_page($userinfo{username});
}
}
wjl-0.26/src/cgi-bin/knowledge_find.pl
/files/tmp/wjl-0.26/src/cgi-bin/knowledge_find.pl.html
#!/usr/bin/perl
# Find Knowledge Page for Web Logs Software
# WJL V0.26, Page V0.1
# Carl Ritson - 2002
# Library Include
use Mysql;
use CGI qw/:standard/, 'shortcuts', 'center';
use strict;
use WJL;
use WJLCore;
# Main Program Body
# CGI & DBH
my $page = new CGI;
my $dbh = Mysql->connect(db_login()) || db_error;
# Predefine some Variables
my $user_valid = 0;
my $level = 0;
my %userinfo;
my $src = $page->param('src'); # Where did we come from.
# Call Start Page Function, only if we have a DBH.
if ($dbh) {
($user_valid, %userinfo) = start_page($page,$dbh);
$level = user_level($dbh,$userinfo{username});
}
if ($user_valid && has_right($level,'knowledge')) {
my $wjl = WJL::New($dbh);
my $title = h3("Find Knowledge");
my %parm;
if($userinfo{security} =~ /high/) {
%parm = %userinfo;
}
$parm{src} = $src;
my $html = '';
my $phrase = $page->param('phrase');
my $message;
# Delete Knowledge, before looking for it.
if($page->param('delete')) {
my $file = filter($page->param('file'));
if($file) {
$wjl->delete_knowledge($file);
}
}
# If your looking for $html .= $title, look at the bottom
$html .= "<form>\n<table>\n";
$html .= hidden_fields(%parm);
$html .= Tr(td('Phrase:'),
td(text_field('phrase',$phrase)));
$html .= "</table>\n";
$html .= "<p>\n";
$html .= submit_button('Find Knowledge');
$html .= "</form>\n";
$html .= form_button('Cancel',$src,%parm);
$html .= "</p>\n";
if($phrase) {
$phrase = filter($phrase);
my @words = split(/ /,$phrase);
my @names = $wjl->find_knowledge(@words);
if(@names) {
$html .= '<p><table WIDTH="400" BORDER="1" CELLPADDING="2" CELLSPACING="1">';
$html .= Tr(
td(b(center('Filename'))),
td(b(center('Description'))),
td(),td()
);
foreach my $file (@names) {
my $desc = $wjl->describe_knowledge($file);
$html .= Tr(
td(center(b($file))),
td(center(fmt(40,2,$desc))),
td(center(form_button('Get',"knowledge_get.pl/$file",%parm))),
td(center(form_button('Delete','knowledge_find.pl',%parm,delete=>1,file=>$file,phrase=>$phrase)))
);
}
$html .= '</table></p>';
} else {
$message = p(b("Sorry No Knowledge Relating To '$phrase' was found."));
}
}
# Hacky Magic
$html = $title . $message . $html;
print frame6_page($html);
} else {
# If we don't have a DBH an error page has already been printed.
if($dbh) {
print auth_fail_page($userinfo{username});
}
}
wjl-0.26/src/cgi-bin/departments.pl
/files/tmp/wjl-0.26/src/cgi-bin/departments.pl.html
#!/usr/bin/perl
# Department Setup Menu Page for Web Logs Software
# WJL V0.26, Page V0.1
# Carl Ritson - 2002
# Library Include
use Mysql;
use CGI qw/:standard/, 'shortcuts', 'center';
use strict;
use WJL;
use WJLCore;
# Main Program Body
# CGI & DBH
my $page = new CGI;
my $dbh = Mysql->connect(db_login()) || db_error();
# Predefine some Variables
my $user_valid = 0;
my %userinfo;
my $level = 0;
my $src = $page->param('src'); # Where did we come from?
# Call Start Page Function, only if we have a DBH.
if ($dbh) {
($user_valid, %userinfo) = start_page($page,$dbh);
$level = user_level($dbh,$userinfo{username});
}
if ($user_valid && has_right($level,'setup')) {
my $wjl = WJL::New($dbh);
my $active = $page->param('active');
my $type = $page->param('submit_type');
my $title = h3("Departments");
my %parm;
if($userinfo{security} =~ /high/) {
%parm = %userinfo;
}
$parm{src} = 'setup_menu.pl';
# Quite a bit of database exposed in this module.
my $html = '';
# Perform any changes before displaying the page.
if($type =~ /add/i || $type =~ /update/i) {
my $dept = cut(32,filter($page->param('dept')));
my $dept_name = filter($page->param('dept_name'));
my $hod = filter($page->param('hod'));
my $phone = cut(32,filter($page->param('phone')));
if($type =~ /add/i && $dept) {
my $query = "INSERT INTO dept (dept,dept_name,hod,phone) VALUES('$dept','$dept_name','$hod','$phone')";
$dbh->query($query);
} elsif($dept) {
my $query = "UPDATE dept SET dept_name='$dept_name',hod='$hod',phone='$phone' WHERE dept='$dept'";
$dbh->query($query);
}
} elsif($type =~ /delete/i) {
my $dept = filter($page->param('dept'));
my $query = "DELETE FROM dept WHERE dept='$dept'";
$dbh->query($query);
}
$html .= $title;
$html .= hr();
$html .= "<table BORDER=\"1\">\n";
$html .= Tr(
td(center(b('Dept'))),
td(center(b('Name'))),
td(center(b('HOD'))),
td(center(b('Phone'))),
td(),td()
);
$html .= Tr(
"<form>\n",
hidden_fields(%parm),
hidden_fields(active => 1),
td(center(text_field('dept',''))),
td(center(text_field('dept_name',''))),
td(center(text_field('hod',''))),
td(center(text_field('phone',''))),
td(center(submit_button('Add'))),
"</form>\n"
);
my @depts = $wjl->list_depts();
foreach my $dept (@depts) {
my $query = "SELECT dept_name,hod,phone FROM dept WHERE dept='$dept'";
my $result = $dbh->query($query);
my ($dept_name, $hod, $phone, $rubbish) = $result->fetchrow();
$html .= Tr(
"<form>\n",
hidden_fields(%parm),
hidden_fields(active => 1, dept => $dept),
td(center(b($dept))),
td(center(text_field('dept_name',$dept_name))),
td(center(text_field('hod',$hod))),
td(center(text_field('phone',$phone))),
td(center(submit_button('Update'))),
td(center(submit_button('Delete'))),
"</form>\n"
);
}
$html .= "</table>\n";
$html .= hr();
$html .= form_button('Return',$src,%parm);
print frame6_page($html);
} else {
# If we don't have a DBH an error page has already been printed.
if($dbh) {
print auth_fail_page($userinfo{username});
}
}
wjl-0.26/src/cgi-bin/knowledge_get.pl
/files/tmp/wjl-0.26/src/cgi-bin/knowledge_get.pl.html
#!/usr/bin/perl
# Get Knowledge Linker for Web Logs Software
# WJL V0.26, Page V0.1
# Carl Ritson - 2002
# Library Include
use Mysql;
use CGI qw/:standard/;
use strict;
use WJL;
use WJLCore;
# Main Program Body
# CGI & DBH
my $page = new CGI;
my $dbh = Mysql->connect(db_login()) || db_error;
# Slightly different structure, as this doesn't send back HTML
my $file = filter($ENV{PATH_INFO});
$file =~ s/\///g;
if($file && $dbh) {
my %userinfo = get_user_info($page,mime($file));
if (user_valid($dbh,$userinfo{username},$userinfo{sectoken})) {
my $level = user_level($dbh,$userinfo{username});
if(has_right($level,'knowledge')) {
my $wjl = WJL::New($dbh);
my $data = $wjl->get_knowledge($file);
binmode(STDOUT); # Not strictly nessary for *NIX systems
print STDOUT $data;
}
}
}
wjl-0.26/src/cgi-bin/setup_menu.pl
/files/tmp/wjl-0.26/src/cgi-bin/setup_menu.pl.html
#!/usr/bin/perl
# Setup Menu Page for Web Logs Software
# WJL V0.26, Page V0.1
# Carl Ritson - 2002
# Library Include
use Mysql;
use CGI qw/:standard/, 'shortcuts', 'center';
use strict;
use WJL;
use WJLCore;
# Main Program Body
# CGI & DBH
my $page = new CGI;
my $dbh = Mysql->connect(db_login()) || db_error();
# Predefine some Variables
my $user_valid = 0;
my %userinfo;
my $level = 0;
# Call Start Page Function, only if we have a DBH.
if ($dbh) {
($user_valid, %userinfo) = start_page($page,$dbh);
$level = user_level($dbh,$userinfo{username});
}
if ($user_valid && has_right($level,'setup')) {
my $wjl = WJL::New($dbh);
my $user = $userinfo{username};
my $no_jobs = $wjl->no_active_jobs($user);
my $title = h3("Setup Menu");
my %parm;
if($userinfo{security} =~ /high/) {
%parm = %userinfo;
}
$parm{src} = 'setup_menu.pl';
my $menu = '';
# Add User, Edit User, Departments, (Password)
$menu .= form_button('New User','new_user.pl',%parm)."<BR>\n";
$menu .= form_button('Edit User','edit_user.pl',%parm)."<BR>\n";
$menu .= form_button('Departments','departments.pl',%parm)."<BR>\n";
if(has_right($level,'password')) {
$menu .= form_button('Change Password','change_passwd.pl',%parm)."<BR>\n";
}
$menu .= form_button('Main Menu','menu.pl',%parm)."<BR>\n";
print start_html(
-title=>"Web Job Logs - ".organisation(),
-style=>{'src'=>'/wjl-style.css'}
),
"<table border=\"0\" width=\"100%\">\n",
Tr(
'<td WIDTH="10%"></td>',
'<td WIDTH="80%"></td>',
'<td WIDTH="10%"></td>'
),
Tr(
td(center("<b>Jobs:</b> $no_jobs"),),
td(''),
td(center("<b>User:</b><br>".$wjl->fullname($user)))
),
Tr(
td(''),
td(center($title)),
td('')
),
Tr(
td(''),
td(center($menu)),
td('')
),
"</table>\n",
end_html();
} else {
# If we don't have a DBH an error page has already been printed.
if($dbh) {
print auth_fail_page($userinfo{username});
}
}
wjl-0.26/src/cgi-bin/index.pl
/files/tmp/wjl-0.26/src/cgi-bin/index.pl.html
#!/usr/bin/perl
# Index and Login Page for Web Logs Software
# WJL V0.26, Page V0.2
# Carl Ritson - 2002
# Global Vars
my $menu = "menu.pl"; # URL of menu
# Library Include
use Mysql;
use CGI qw/:standard/, 'shortcuts', 'center';
use strict;
use WJL;
use WJLCore;
# Main Program Body
my $page = new CGI;
my $login = $page->param('login');
my $security = $page->param('security');
my $username = $page->param('username');
my $fail = $page->param('fail');
my $logout = $page->param('logout');
# If security is set to low we put the user login info in a cookie,
# else we put the information in get headers.
# Password is at this point hashed to an MD5 checksum for both methods.
if ($login && ($security =~ /low/)) {
#print STDERR "Low Security Setting Cookie\n";
my %userinfo;
$userinfo{username} = $page->param('username');
$userinfo{sectoken} = md5sum($page->param('password'));
$userinfo{security} = 'low';
my $cookie = $page->cookie( -name => 'wjl',
-value => \%userinfo,
-expires=> '+7d',
-path => '/'
);
print header(-cookie=>$cookie),
start_html(),
meta_redirect($menu), # Redirect to Main Menu
end_html();
} elsif ($login && ($security =~ /high/)) {
my $buffer;
$buffer = $menu;
$buffer .= '?username='.$page->param('username');
$buffer .= '§oken='.md5sum($page->param('password'));
$buffer .= '&security=high';
print header(),
start_html(),
meta_redirect($buffer),
end_html();
} else {
my $display = 1;
if (($logout || $fail)
&& ($security =~ /low/ || $page->cookie('wjl'))) {
# If this is a logout invalidate low security Cookies
my $cookie = $page->cookie( -name => 'wjl',
-value => '',
-expires => 'now',
-path => '/'
);
print header(-cookie=>$cookie);
} else {
my $cookie = $page->cookie('wjl');
print header();
if($cookie && !$fail) {
$display = 0;
print start_html(),
meta_redirect($menu);
end_html();
}
}
if($display) {
# We fell through the login options so we present the user
# with a login screen instead.
print start_html(
-title=>"Web Job Logs - ".organisation(),
-style=>{'src'=>'/wjl-style.css'}
),
hr(),
center(
h3("Web Job Logs - ".organisation()),
hr(),
b("Login"),p(),
startform(),
hidden(-name=>'login',-default=>'1'),
"Username:",textfield('username',$username),p(),
"Password:",password_field('password'),p(),
"Security:",
popup_menu( -name=>'security',
-values=>['high','low']),p(),
submit("Login"),
end_form()
),
hr(),
end_html();
}
}
wjl-0.26/src/cgi-bin/knowledge_add.pl
/files/tmp/wjl-0.26/src/cgi-bin/knowledge_add.pl.html
#!/usr/bin/perl
# Add Knowledge for Web Logs Software
# WJL V0.26, Page V0.1
# Carl Ritson - 2002
# Library Include
use Mysql;
use CGI qw/:standard/, 'shortcuts', 'center';
use strict;
use WJL;
use WJLCore;
# Main Program Body
# CGI & DBH
my $page = new CGI;
my $dbh = Mysql->connect(db_login()) || db_error;
# Predefine some Variables
my $user_valid = 0;
my $level = 0;
my %userinfo;
my $src = $page->param('src'); # Where did we come from.
# Call Start Page Function, only if we have a DBH.
if ($dbh) {
($user_valid, %userinfo) = start_page($page,$dbh);
$level = user_level($dbh,$userinfo{username});
}
if ($user_valid && has_right($level,'knowledge')) {
my $wjl = WJL::New($dbh);
my $active = $page->param('active');
my $user = $userinfo{username};
my $title = h3("Add Knowledge");
my $complete = 0;
my $time = time();
my %parm;
if($userinfo{security} =~ /high/) {
%parm = %userinfo;
}
$parm{src} = $src;
my $html = '';
my $atomic;
my ($description,$file);
my $jobid = $page->param('jobid');
if($active) {
$atomic = $page->param('atomic');
$description = filter($page->param('description'));
$file = $page->param('file');
if($jobid && $description
&& $file && job_valid($jobid,$dbh)) {
$complete = 1;
}
}
if($complete && $wjl->get_job_atomic($user,$atomic)) {
my $filename = $file;
my $fh = $page->upload('file');
my $job = $wjl->job($jobid);
my ($buffer,$data);
my %file;
# Read from the filehandle that $page->upload gives us
while(read($fh,$buffer,4096)) {
$data .= $buffer;
}
my @filename = split(/([\\\/])/,$filename);
$filename = $filename[(@filename - 1)];
$filename =~ s/([^A-Za-z0-9 \-\.])//g;
$file{name} = $filename;
$file{description} = $description;
$file{data} = $data;
$job->add_knowledge(%file);
# Where to now?
# To boldy go where ever we were before
$html = meta_redirect($src.hash2get(%parm));
} else {
$html .= $title;
if($active) {
$html .= "<p><b>Please Complete All Fields.</b></p>\n";
}
if(!$atomic) {
$atomic = $time;
}
$html .= "<form METHOD=\"POST\" ENCTYPE=\"multipart/form-data\">\n<table>\n";
$html .= hidden_fields(active => 1, atomic => $atomic);
$html .= hidden_fields(%parm, jobid => $jobid);
$html .= Tr(td('Jobid:'),
td($jobid));
$html .= Tr(td('Description:'),
td(text_area('description',4,25,$description)));
$html .= Tr(td('File:'),
td(filefield('file')));
$html .= "</table>\n";
$html .= "<p>\n";
$html .= submit_button('Add Knowledge');
$html .= "</form>\n";
$html .= form_button('Cancel',$src,%parm,jobid=>$jobid);
$html .= "</p>\n";
}
print frame6_page($html);
} else {
# If we don't have a DBH an error page has already been printed.
if($dbh) {
print auth_fail_page($userinfo{username});
}
}
wjl-0.26/src/cgi-bin/edit_user.pl
/files/tmp/wjl-0.26/src/cgi-bin/edit_user.pl.html
#!/usr/bin/perl
# Edit User Page for Web Logs Software
# WJL V0.26, Page V0.1
# Carl Ritson - 2002
# Library Include
use Mysql;
use CGI qw/:standard/, 'shortcuts', 'center';
use strict;
use WJL;
use WJLCore;
# Main Program Body
# CGI & DBH
my $page = new CGI;
my $dbh = Mysql->connect(db_login()) || db_error;
# Predefine some Variables
my $user_valid = 0;
my $level = 0;
my %userinfo;
my $src = $page->param('src'); # Where did we come from.
# Call Start Page Function, only if we have a DBH.
if ($dbh) {
($user_valid, %userinfo) = start_page($page,$dbh);
$level = user_level($dbh,$userinfo{username});
}
if ($user_valid && has_right($level,'setup')) {
my $wjl = WJL::New($dbh);
my $active = $page->param('active');
my $type = $page->param('type');
my $user = $userinfo{username};
my $title = h3("Edit User");
my $errors;
my $complete = 0;
my %parm;
if($userinfo{security} =~ /high/) {
%parm = %userinfo;
}
$parm{src} = $src;
my $html = '';
my ($euser,$initials,$fullname,$passwd1,$passwd2);
my ($njob,$ejob,$alloc,$setup,$passwdright,$del,$stats,$kb);
if($active) {
# Key Details
$euser = cut(32,$page->param('euser'));
$initials = cut(4,$page->param('initials'));
$fullname = $page->param('fullname');
$passwd1 = $page->param('passwd1');
$passwd2 = $page->param('passwd2');
# Rights
$njob = $page->param('njob');
$ejob = $page->param('ejob');
$alloc = $page->param('alloc');
$setup = $page->param('setup');
$passwdright = $page->param('passwdright');
$del = $page->param('del');
$stats = $page->param('stats');
$kb = $page->param('kb');
if(!$wjl->user_exists($euser)) {
$active = 0;
$errors = "Username $euser does not exist.";
} elsif($type =~ /details/) {
if($euser && $initials && $fullname) {
$complete = 1;
} else {
$errors = 'Please fill in all fields.';
}
} elsif($type =~ /passwd/) {
if($passwd1 =~ /^$passwd2$/) {
$complete = 1;
} else {
$errors = 'Passwords don\'t match.';
}
} elsif($type =~ /delete/) {
$complete = 1;
}
}
if($complete) {
if($type =~ /details/) {
my %u = $wjl->user(username => $euser);
my $l = 0;
if($njob) {$l = set_right($l,'new_job',1);}
if($ejob) {$l = set_right($l,'edit_jobs',1);}
if($alloc) {$l = set_right($l,'allocate',1);}
if($setup) {$l = set_right($l,'setup',1);}
if($passwdright) {$l = set_right($l,'password',1);}
if($del) {$l = set_right($l,'delete',1);}
if($stats) {$l = set_right($l,'stats',1);}
if($kb) {$l = set_right($l,'knowledge',1);}
$wjl->user(
username => $euser,
initials => $initials,
fullname => $fullname,
level => $l,
);
$errors = 'User Details Updated';
$complete = 0;
} elsif($type =~ /passwd/) {
$wjl->user(
username => $euser,
sectoken => md5sum($passwd1)
);
$errors = 'Password Set';
$complete = 0;
} elsif($type =~ /delete/) {
$wjl->del_user($euser);
$html = meta_redirect($src.hash2get(%parm));
}
}
if($active && !$complete) {
# Fill in the blanks
if($active == 1) {
my %u = $wjl->user(username => $euser);
my $l = $u{level};
$fullname = $u{fullname};
$initials = $u{initials};
if(has_right($l,'new_job')) {$njob = 1;}
if(has_right($l,'edit_jobs')) {$ejob = 1;}
if(has_right($l,'allocate')) {$alloc = 1;}
if(has_right($l,'setup')) {$setup = 1;}
if(has_right($l,'password')) {$passwdright = 1;}
if(has_right($l,'delete')) {$del = 1;}
if(has_right($l,'stats')) {$stats = 1;}
if(has_right($l,'knowledge')) {$kb = 1;}
}
$html .= $title;
# Display Errors
if($errors) {
$html .= p(b($errors));
}
# The Page
$html .= "<form>\n<table>\n";
$html .= hidden_fields(active => 2, euser => $euser, type => 'details');
$html .= hidden_fields(%parm);
$html .= Tr(td('Username:'),
td(u($euser)));
$html .= Tr(td('Initials:'),
td(text_field('initials',$initials)));
$html .= Tr(td('Full Name:'),
td(text_field('fullname',$fullname)));
#$html .= Tr(td(b('Rights')),td(''));
$html .= Tr(td('Add Job'),
td(checkbox('njob',$njob,'1','')));
$html .= Tr(td('Edit Job'),
td(checkbox('ejob',$ejob,'1','')));
$html .= Tr(td('Allocate Jobs'),
td(checkbox('alloc',$alloc,'1','')));
$html .= Tr(td('Setup'),
td(checkbox('setup',$setup,'1','')));
$html .= Tr(td('Change Password'),
td(checkbox('passwdright',$passwdright,'1','')));
$html .= Tr(td('Delete Jobs'),
td(checkbox('del',$del,'1','')));
$html .= Tr(td('View Statistics'),
td(checkbox('stats',$stats,'1','')));
$html .= Tr(td('Knowledge Base'),
td(checkbox('kb',$kb,'1','')));
$html .= "</table>\n";
$html .= submit_button('Update');
$html .= "</form>\n";
#$html .= hr();
$html .= "<form>\n<table>\n";
$html .= hidden_fields(active => 2, euser => $euser, type => 'passwd');
$html .= hidden_fields(%parm);
$html .= Tr(td('Password:'),
td(password_field('passwd1')));
$html .= Tr(td('Confirm Password:'),
td(password_field('passwd2')));
$html .= "</table>\n";
$html .= submit_button('Set Password');
$html .= "</form>\n";
#$html .= hr();
$html .= "<form>\n";
$html .= hidden_fields(active => 2, euser => $euser, type => 'delete');
$html .= hidden_fields(%parm);
$html .= submit_button('Delete User');
$html .= "</form>\n";
#$html .= hr();
$html .= form_button('Return',$src,%parm);
} elsif($active == 0) {
my $title = h3("Select User");
$html .= $title;
if($errors) {
$html .= p(b($errors));
}
$html .= "<form>\n";
$html .= hidden_fields(%parm);
$html .= hidden_fields(active => 1);
$html .= "<p>Username:".select_field('euser','','',$wjl->list_usernames())."</p>\n";
$html .= "<p>\n";
$html .= submit_button('Edit');
$html .= "</form>\n";
$html .= form_button('Cancel',$src,%parm);
$html .= "</p>\n";
}
print frame6_page($html);
} else {
# If we don't have a DBH an error page has already been printed.
if($dbh) {
print auth_fail_page($userinfo{username});
}
}
wjl-0.26/src/cgi-bin/change_passwd.pl
/files/tmp/wjl-0.26/src/cgi-bin/change_passwd.pl.html
#!/usr/bin/perl
# Change Password Page for Web Logs Software
# WJL V0.26, Page V0.1
# Carl Ritson - 2002
# Library Include
use Mysql;
use CGI qw/:standard/, 'shortcuts', 'center';
use strict;
use WJL;
use WJLCore;
# Main Program Body
# CGI & DBH
my $page = new CGI;
my $dbh = Mysql->connect(db_login()) || db_error;
# Predefine some Variables
my $user_valid = 0;
my $level = 0;
my %userinfo;
my $src = $page->param('src'); # Where did we come from.
my $note = '';
my $active = $page->param('active');
# Call Start Page Function, only if we have a DBH.
if ($dbh) {
# We have to do this here as we may need to update a cookie
if($active) {
my $username = $page->param('username');
my $curpasswd = $page->param('curpasswd');
my $newpasswd = $page->param('newpasswd');
my $conpasswd = $page->param('conpasswd');
my $level = user_level($dbh,$username);
#print STDERR "user_valid($dbh,$username,".md5sum($curpasswd).":$curpasswd".");\n";
if(user_valid($dbh,$username,md5sum($curpasswd))) {
if($newpasswd =~ /^$conpasswd$/) {
my $newsectoken = md5sum($newpasswd);
if(has_right($level,'password')) {
my %userinfo;
$userinfo{username} = $username;
$userinfo{sectoken} = $newsectoken;
set_sectoken($dbh,$username,$newsectoken);
if($page->param('security') =~ /high/) {
$userinfo{security} = 'high';
$src .= hash2get(%userinfo);
print header();
} else {
$userinfo{security} = 'low';
my $cookie = $page->cookie( -name=>'wjl',
-value=>join(':',%userinfo),
-expires=>'+7d');
print header(-cookie=>$cookie);
}
print start_html(),
meta_redirect($src),
end_html();
}
} else {
$note = 'Passwords Don\'t Match';
}
} else {
$note = 'Current Password Incorrect';
}
}
if($note || !$active) {
($user_valid, %userinfo) = start_page($page,$dbh);
$level = user_level($dbh,$userinfo{username});
}
}
if ($user_valid && has_right($level,'password')) {
my $wjl = WJL::New($dbh);
my $user = $userinfo{username};
my $title = h3("Change Password");
my %parm;
if($userinfo{security} =~ /high/) {
%parm = %userinfo;
} else {
$parm{username} = $user;
}
$parm{src} = $src;
my $html = '';
$html .= $title;
if($note) {$html .= p(b($note));}
$html .= "<form method=\"POST\">\n<table>\n";
$html .= hidden_fields(active => 1);
$html .= hidden_fields(%parm);
$html .= Tr(td('Current Password:'),
td(password_field('curpasswd')));
$html .= Tr(td('New Password:'),
td(password_field('newpasswd')));
$html .= Tr(td('Confirm Password:'),
td(password_field('conpasswd')));
$html .= "</table>\n";
$html .= p(
submit('Change'),
"</form>\n",
form_button('Cancel',$src,%parm)
);
print frame6_page($html);
} else {
# If we don't have a DBH an error page has already been printed.
if($dbh && !$active) {
print auth_fail_page($userinfo{username});
}
}
wjl-0.26/src/cgi-bin/new_user.pl
/files/tmp/wjl-0.26/src/cgi-bin/new_user.pl.html
#!/usr/bin/perl
# New User Page for Web Logs Software
# WJL V0.1, Page V0.1
# Carl Ritson - 2002
# Library Include
use Mysql;
use CGI qw/:standard/, 'shortcuts', 'center';
use strict;
use WJL;
use WJLCore;
# Main Program Body
# CGI & DBH
my $page = new CGI;
my $dbh = Mysql->connect(db_login()) || db_error;
# Predefine some Variables
my $user_valid = 0;
my $level = 0;
my %userinfo;
my $src = $page->param('src'); # Where did we come from.
# Call Start Page Function, only if we have a DBH.
if ($dbh) {
($user_valid, %userinfo) = start_page($page,$dbh);
$level = user_level($dbh,$userinfo{username});
}
if ($user_valid && has_right($level,'setup')) {
my $wjl = WJL::New($dbh);
my $active = $page->param('active');
my $user = $userinfo{username};
my $title = h3("New User");
my $errors;
my $complete = 0;
my %parm;
if($userinfo{security} =~ /high/) {
%parm = %userinfo;
}
$parm{src} = $src;
my $html = '';
my ($nuser,$initials,$fullname,$passwd1,$passwd2);
my ($njob,$ejob,$alloc,$setup,$passwdright,$del,$stats,$kb);
if($active) {
# Key Details
$nuser = cut(32,$page->param('nuser'));
$initials = cut(4,$page->param('initials'));
$fullname = $page->param('fullname');
$passwd1 = $page->param('passwd1');
$passwd2 = $page->param('passwd2');
# Rights
$njob = $page->param('njob');
$ejob = $page->param('ejob');
$alloc = $page->param('alloc');
$setup = $page->param('setup');
$passwdright = $page->param('passwdright');
$del = $page->param('del');
$stats = $page->param('stats');
$kb = $page->param('kb');
if($nuser && $initials && $fullname &&
$passwd1 && $passwd2) {
if($passwd1 !~ /^$passwd2$/) {
$errors = 'Passwords don\'t match.';
} elsif($wjl->user_exists($nuser)) {
$errors = "User $nuser already exists.";
} elsif($wjl->initials2user($initials)) {
$errors = "Initials $initials already used.";
} else {
$complete = 1;
}
} else {
$errors = 'Please fill in all fields.';
}
}
if($complete) {
my $l = 0;
if($njob) {$l = set_right($l,'new_job',1);}
if($ejob) {$l = set_right($l,'edit_jobs',1);}
if($alloc) {$l = set_right($l,'allocate',1);}
if($setup) {$l = set_right($l,'setup',1);}
if($passwdright) {$l = set_right($l,'password',1);}
if($del) {$l = set_right($l,'delete',1);}
if($stats) {$l = set_right($l,'stats',1);}
if($kb) {$l = set_right($l,'knowledge',1);}
$wjl->user(
username => $nuser,
initials => $initials,
fullname => $fullname,
level => $l,
sectoken => md5sum($passwd1)
);
$html = meta_redirect($src.hash2get(%parm));
} else {
$html .= $title;
if($active) {
$html .= p(b($errors));
}
$html .= "<form>\n<table>\n";
$html .= hidden_fields(active => 1);
$html .= hidden_fields(%parm);
$html .= Tr(td('Username:'),
td(text_field('nuser',$nuser)));
$html .= Tr(td('Initials:'),
td(text_field('initials',$initials)));
$html .= Tr(td('Full Name:'),
td(text_field('fullname',$fullname)));
#$html .= Tr(td(b('Rights')),td(''));
$html .= Tr(td('Add Job'),
td(checkbox('njob',$njob,'1','')));
$html .= Tr(td('Edit Job'),
td(checkbox('ejob',$ejob,'1','')));
$html .= Tr(td('Allocate Jobs'),
td(checkbox('alloc',$alloc,'1','')));
$html .= Tr(td('Setup'),
td(checkbox('setup',$setup,'1','')));
$html .= Tr(td('Change Password'),
td(checkbox('passwdright',$passwdright,'1','')));
$html .= Tr(td('Delete Jobs'),
td(checkbox('del',$del,'1','')));
$html .= Tr(td('View Statistics'),
td(checkbox('stats',$stats,'1','')));
$html .= Tr(td('Knowledge Base'),
td(checkbox('kb',$kb,'1','')));
$html .= Tr(td('Password:'),
td(password_field('passwd1')));
$html .= Tr(td('Confirm Password:'),
td(password_field('passwd2')));
$html .= "</table>\n";
$html .= "<p>\n";
$html .= submit_button('Add User');
$html .= "</form>\n";
$html .= form_button('Cancel',$src,%parm);
$html .= "</p>\n";
}
print frame6_page($html);
} else {
# If we don't have a DBH an error page has already been printed.
if($dbh) {
print auth_fail_page($userinfo{username});
}
}
wjl-0.26/src/cgi-bin/stats.pl
/files/tmp/wjl-0.26/src/cgi-bin/stats.pl.html
#!/usr/bin/perl
# Statistics for Web Logs Software
# WJL V0.26, Page V0.12
# Carl Ritson - 2002
# Library Include
use Mysql;
use CGI qw/:standard/, 'shortcuts', 'center';
use strict;
use WJL;
use WJLCore;
# Main Program Body
# CGI & DBH
my $page = new CGI;
my $dbh = Mysql->connect(db_login()) || db_error;
# Predefine some Variables
my $user_valid = 0;
my $level = 0;
my %userinfo;
# Call Start Page Function, only if we have a DBH.
if ($dbh) {
($user_valid, %userinfo) = start_page($page,$dbh);
$level = user_level($dbh,$userinfo{username});
}
if ($user_valid && has_right($level,'stat')) {
my $wjl = WJL::New($dbh);
my $title = h3("Statistics");
my $button = '';
my $time = time;
my %parm;
if($userinfo{security} =~ /high/) {
%parm = %userinfo;
}
$parm{src} = $page->param('src');
my $html = $title;
if(isie()) {
$html .= dhtml_main();
}
# Filter Parameters
my $phase = $page->param('phase');
if(!$phase) {
$html .= p(b('Please Select The Range of Jobs to use in Statistics'));
$html .= "<form>\n";
$html .= hidden_fields(%parm,phase => 1);
# 90*24*60*60 will push $time back three months
$html .= p('Start Date:'.text_field('date_from',gen_date($time - 90*24*60*60)));
$html .= p('End Date:'.text_field('date_to',gen_date($time)));
$html .= p('Status:'.select_field('status','','All','Live','Dead'));
$html .= p(submit_button('Next'));
$html .= "</form>\n";
} elsif($phase == 1) {
my $date_from = filter($page->param('date_from'));
my $date_to = filter($page->param('date_to'));
my $status_filter = filter($page->param('status'));
if($date_from) {
$date_from = date2timestamp($date_from);
} else {
$date_from = $time;
}
if($date_to) {
$date_to = date2timestamp($date_to);
} else {
$date_to = $time;
}
$parm{date_from} = $date_from;
$parm{date_to} = $date_to;
# This really shouldn't be here...
my $query = "SELECT jobid FROM job WHERE started >= $date_from AND started <= $date_to ORDER BY started ASC";
my $result = $wjl->query($query);
my @temp;
my @jobs;
while(@temp = $result->fetchrow()) {
push(@jobs,$wjl->job($temp[0]));
}
# End of Secret Database Knowledge
$html .= "<form>\n";
$html .= hidden_fields(%parm,phase=>2);
$html .= p(
'Please Select the Jobs you want used during the statistical calculations.'.
br().
'The Job selection only affects the averages.'
);
$html .= p('Number of Machines Active During this period : '.text_field('machines',''));
$html .= p(submit_button('Continue'));
$html .= "<table WIDTH=\"100%\" BORDER=\"1\" CELLPADDING=\"1\">\n";
$html .= Tr(td('Used'),
td(center(b('JobID'))),
td(center(b('Date'))),
td(center(b('Caller'))),
td(center(b('Dept'))),
td(center(b('Description'))),
td(center(b('User'))),
td(center(b('Priority'))),
td(center(b('Allocated To'))),
td(center(b('Status')))
);
foreach my $job (@jobs) {
my %info = $job->info();
my $status = $job->status();
my %fevent = $job->first_event();
if($status_filter) {
if($status_filter =~ /Live/i && $status >= 64) {
next;
} elsif($status_filter =~ /Dead/i && $status < 64) {
next;
}
}
$html .= "<tr>";
$html .= td(checkbox('jobs',1,$info{jobid},''));
$html .= td($info{jobid});
$html .= td(gen_date($info{started}));
$html .= td($info{caller});
$html .= td($info{dept});
if(isie()) {
my @comments = $job->comments();
if(@comments) {
my $buf;
foreach(@comments) {
$buf .= filter($_).hr();
}
$html .= td(dhtml_wrap(fmt(40,2,$fevent{data}),$buf));
} else {
$html .= td(fmt(40,2,$fevent{data}));
}
} else {
$html .= td(fmt(40,2,$fevent{data}));
}
$html .= td($wjl->user2initials($info{username}));
$html .= td(priof($info{priority}));
$html .= td($info{allocated_to}?$wjl->user2initials($info{allocated_to}):'-');
$html .= td(status($status));
$html .= "</tr>\n";
}
$html .= "</table>\n";
$html .= "</form>\n";
} elsif($phase == 2) {
my @jobs = $page->param('jobs');
my $date_from = filter($page->param('date_from'));
my $date_to = filter($page->param('date_to'));
my $machines = filter($page->param('machines'));
$machines = $machines?$machines:1; # Make sure we have 1
my $no_jobs = @jobs;
my $no_closed = '0';
my $no_opened = '0';
my $avg_response = '0';
my $avg_duration = '0';
my $avg_comments = '0';
my $avg_events = '0';
my ($uptime,$downtime);
if($no_jobs) {
my ($query,$result);
foreach my $jobid (@jobs) {
# Protect ourselfs from invalid input.
$jobid =~ s/([^0-9])//g;
if($jobid) {
my $job = $wjl->job($jobid);
$job->set_realtime(1); # use real time
$avg_response += $job->response_time();
$job->set_realtime(0); # use working time
$avg_duration += $job->elapsed_time();
$avg_comments += $job->comments();
$avg_events += $job->list_events();
$downtime += $job->downtime();
}
}
$avg_response /= $no_jobs;
$avg_duration /= $no_jobs;
$avg_comments /= $no_jobs;
$avg_events /= $no_jobs;
$uptime = WJL::workingseconds($date_from,$date_to);
$uptime *= $machines;
$uptime -= $downtime;
$uptime /= ($machines * WJL::workingseconds($date_from,$date_to));
$uptime *= 100; # Its a percentage :)
# More Magic Database knowledge
$query = "SELECT status FROM event WHERE type >= 2 AND type <= 3 AND status=128 AND date >= $date_from AND date <= $date_to";
$result = $wjl->query($query);
while($result->fetchrow()) {
++$no_closed;
}
$query = "SELECT jobid FROM job WHERE started >= $date_from AND started <= $date_to";
$result = $wjl->query($query);
while($result->fetchrow()) {
++$no_opened;
}
}
$html .= p(b('For the period '.i(gen_date($date_from)).' to '.i(gen_date($date_to)).'.'));
$html .= '<table WIDTH="500" BORDER="0" CELLPADDING="2">';
$html .= Tr(td(b('Jobs Opened:')),td($no_opened));
$html .= Tr(td(b('Jobs Closed:')),td($no_closed));
$html .= Tr(td(b('Average Response Time:')),td(gen_elapsed($avg_response)));
$html .= Tr(td(b('Average Duration:')),td(gen_elapsed($avg_duration)));
$html .= Tr(td(b('Average Comments per Job:')),td($avg_comments));
$html .= Tr(td(b('Average Events per Job:')),td($avg_events));
$html .= Tr(td(b('Uptime:')),td(sprintf("%.2f%%",$uptime)));
$html .= "</table>\n";
$html .= p(
b('Comments Per Day').br().
"<img src=\"stat_graph.pl".
hash2get(%parm,type=>'comments',
start=>$date_from,stop=>$date_to
).'" BORDER="1" WIDTH="400" HEIGHT="200">'
);
$html .= p(
b('Jobs Opened Per Day').br().
"<img src=\"stat_graph.pl".
hash2get(%parm,type=>'opened',
start=>$date_from,stop=>$date_to
).'" BORDER="1" WIDTH="400" HEIGHT="200">'
);
$html .= p(
b('Jobs Closed Per Day').br().
"<img src=\"stat_graph.pl".
hash2get(%parm,type=>'closed',
start=>$date_from,stop=>$date_to
).'" BORDER="1" WIDTH="400" HEIGHT="200">'
);
}
$button = form_button('Return',$parm{src},%parm);
print six_page($button,'','','',$html,'');
} else {
# If we don't have a DBH an error page has already been printed.
if($dbh) {
print auth_fail_page($userinfo{username});
}
}
wjl-0.26/src/cgi-bin/job_list.pl
/files/tmp/wjl-0.26/src/cgi-bin/job_list.pl.html
#!/usr/bin/perl
# Job List Page for Web Logs Software
# WJL V0.26, Page V0.2
# Carl Ritson - 2002
# Library Include
use Mysql;
use CGI qw/:standard/, 'shortcuts', 'center';
use strict;
use WJL;
use WJLCore;
# Main Program Body
# CGI & DBH
my $page = new CGI;
my $dbh = Mysql->connect(db_login()) || db_error;
# Predefine some Variables
my $user_valid = 0;
my $level = 0;
my %userinfo;
# Different Display Orders
my %orders = (
1 => 'Entry',
2 => 'Date (Oldest First)',
3 => 'Date (Newest First)',
4 => 'Priority/Date',
5 => 'Date/Priority',
6 => 'Status'
);
# Call Start Page Function, only if we have a DBH.
if ($dbh) {
($user_valid, %userinfo) = start_page($page,$dbh);
$level = user_level($dbh,$userinfo{username});
}
if ($user_valid) {
my $wjl = WJL::New($dbh);
my $title = h3("Job List");
my $button = '';
my $time = time;
my %parm;
if($userinfo{security} =~ /high/) {
%parm = %userinfo;
}
$parm{src} = 'job_list.pl';
my $html = $title;
if(isie()) {
$html .= dhtml_main();
}
# Filter Parameters
my $alloc_filter = filter(cut(4,$page->param('alloc_filter')));
my $status_filter = filter($page->param('status_filter'));
my $dept_filter = filter(cut(32,$page->param('dept_filter')));
my $order = filter($page->param('order'));
my $selected = filter($page->param('selected'));
if($page->param('carrier')) {
my %data = carrier_decode($page->param('carrier'));
$alloc_filter = $data{alloc_filter};
$status_filter = $data{status_filter};
$dept_filter = $data{dept_filter};
$order = $data{order};
$selected = $data{selected};
}
if(!$order) {
$order = $orders{'Entry'};
}
# (New) Filter Parameters
my $limit = filter($page->param('limit'));
if(!$limit) {
$limit = 25;
}
my $date_from = filter($page->param('date_from'));
my $date_to = filter($page->param('date_to'));
# Page Flow Control
my $submit_type = $page->param('submit_type');
my $printable = 0;
my $redirect = 0;
my $can_edit = 0;
my $can_add = 0;
if(has_right($level,'edit_job')) {
$can_edit = 1;
}
if(has_right($level,'new_job')) {
$can_add = 1;
}
# Determine the Submit Entry Point, if not Go..
if($submit_type =~ /Printable/i) {
$printable = 1;
} elsif($submit_type =~ /Edit Job/i && $can_edit) {
$redirect = 1;
} elsif($submit_type =~ /Job Report/i) {
$redirect = 2;
} elsif($submit_type =~ /New Job/i) {
$redirect = 3;
} elsif($submit_type =~ /Main Menu/i) {
$redirect = 4;
}
# Handle the redirection to any other pages.
if($redirect) {
# Functions handle external to this form...
# Send the clients on with Meta Redirects in Javascript Popups.
# Redirect 1 is 'Edit Job'
# Redirect 2 is 'Print Job'
# Redirect 3 is 'New Job'
# Redirect 4 is 'Main Menu'
my %get = %parm;
$get{jobid} = $selected;
$get{src} = 'job_list.pl';
$get{carrier} = carrier_encode(
alloc_filter => $alloc_filter,
status_filter => $status_filter,
dept_filter => $dept_filter,
order => $order,
selected => $selected
);
if($redirect == 1) {
$html = meta_redirect('edit_job.pl'.hash2get(%get));
goto out;
} elsif($redirect == 2) {
#$html .= popup_redirect('job_report.pl'.hash2get(%get));
$html = meta_redirect('job_report.pl'.hash2get(%get));
goto out;
} elsif($redirect == 3) {
$html = meta_redirect('new_job.pl'.hash2get(%parm));
goto out;
} elsif($redirect == 4) {
$html = meta_redirect('menu.pl'.hash2get(%parm));
goto out;
}
}
# Don't Display Controls in Printable Mode
if(!$printable) {
if($page->param('new')) {
$html .= alert('JobID: '.$page->param('jobid'));
}
$html .= "<form>\n";
$html .= "<table BORDER=\"0\" CELLPADDING=\"1\" CELLSPACING=\"1\">\n";
$html .= hidden_fields(%parm);
$html .= Tr(td(center(u(b('Filtering Criteria')))),td(center(u(b('Order By')))),td(''));
$html .= "<tr>\n";
my $temp = '';
$temp .= "<table BORDER=\"0\" CELLPADDING=\"1\" CELLSPACING=\"1\">\n";
$temp .= Tr(td('Allocated To:'),td(select_field('alloc_filter',$alloc_filter,('','None',$wjl->list_technicians()))))."\n";
$temp .= Tr(td('Status:'),td(select_field('status_filter',$status_filter,('','Live',statusl()))))."\n";
$temp .= Tr(td('Dept:'),td(select_field('dept_filter',$dept_filter,('',$wjl->list_depts()))))."\n";
$temp .= Tr(td('Limit:'),td(text_field('limit',$limit)))."\n";
$temp .= Tr(td('Date From:'),td(text_field('date_from',$date_from)))."\n";
$temp .= Tr(td('Date To:'),td(text_field('date_to',$date_to)))."\n";
$temp .= "</table>\n";
$html .= td($temp);
$html .= td(radio_fields('order',$order,%orders));
$temp = "<center>\n";
$temp .= submit_button('Printable')."<br>\n";
if($can_edit) {
$temp .= submit_button('Edit Job')."<br>\n";
}
$temp .= submit_button('Job Report')."<br>\n";
$temp .= submit_button('Go')."<br>\n";
$temp .= "</center>\n";
$html .= td($temp);
$html .= "</tr>\n";
$html .= "</table>\n";
#$html .= "</form>\n";
#$html .= "<hr>\n";
$html .= "<table BORDER=\"0\" CELLPADDING=\"0\" CELLSPACING=\"0\"\n";
$html .= "<tr>\n";
if($can_add) {
$html .= td(submit_button('New Job'));
}
$html .= td(submit_button('Main Menu'));
$html .= "</tr>\n</table>\n";
$html .= "<hr>\n";
#$button = button('Main Menu','menu.pl',%parm);
} else {
$button = form_button('Return','job_list.pl',%parm);
}
my %query;
if($alloc_filter) {
if($alloc_filter =~ /None/) {
$query{allocated_to} = '';
} else {
$query{allocated_to} = $wjl->initials2user($alloc_filter);
}
}
if($dept_filter) {
$query{dept} = $dept_filter;
}
if($order == 2) {
$query{order} = "started+";
} elsif($order == 3) {
$query{order} = "started-";
} elsif($order == 4) {
$query{order} = "priority,started";
} elsif($order == 5) {
$query{order} = "started,priority";
}
my @jobids = $wjl->list_jobs(%query);
my @jobs;
my $count = 0;
foreach my $jobid (@jobids) {
# Once limit Reached Start Skipping.
if($count >= $limit) {
next;
}
# Get Job Info
my $job = $wjl->job($jobid);
my %info = $job->info();
# Check Filters not at DB Level
if($date_from) {
if($info{started} < date2timestamp($date_from)) {
next;
}
}
if($date_to) {
if($info{started} > date2timestamp($date_to)) {
next;
}
}
if($status_filter) {
my $status = $job->status();
if($status_filter =~ /Live/i) {
if($status >= 64) {
next;
}
} elsif($status != status($status_filter)) {
next;
}
}
# We made it to here, job must be good, add it to the stack.
push(@jobs,$job);
++$count;
}
# Sort the Jobs into Status Order Here
if($order == 6) {
@jobs = sort {return $a->status() <=> $b->status();} (@jobs);
}
$html .= "<table WIDTH=\"100%\" BORDER=\"1\" CELLPADDING=\"1\">\n";
$html .= Tr(td(),
td(center(b('JobID'))),
td(center(b('Date'))),
td(center(b('Caller'))),
td(center(b('Dept'))),
td(center(b('Description'))),
td(center(b('User'))),
td(center(b('Priority'))),
td(center(b('Allocated To'))),
td(center(b('Status')))
);
foreach my $job (@jobs) {
my %info = $job->info();
my $status = status($job->status());
my %fevent = $job->first_event();
$html .= "<tr>";
if(!$printable) {
my $temp = 0;
if(($info{jobid} =~ /$selected/) &&
(length($info{jobid}) == length($selected))) {
$temp = 1;
}
$html .= td("<input TYPE=\"radio\" NAME=\"selected\" VALUE=\"".$info{jobid}."\"".($temp?' CHECKED':'').">");
} else {
$html .= td('');
}
$html .= td($info{jobid});
$html .= td(gen_date($info{started}));
$html .= td($info{caller});
$html .= td($info{dept});
if(!$printable && isie()) {
my @comments = $job->comments();
if(@comments) {
my $buf;
foreach(@comments) {
$buf .= filter($_).hr();
}
$html .= td(dhtml_wrap(fmt(40,2,$fevent{data}),$buf));
} else {
$html .= td(fmt(40,2,$fevent{data}));
}
} else {
$html .= td(fmt(40,2,$fevent{data}));
}
$html .= td($wjl->user2initials($info{username}));
$html .= td(priof($info{priority}));
$html .= td($info{allocated_to}?$wjl->user2initials($info{allocated_to}):'-');
$html .= td($status);
$html .= "</tr>\n";
}
$html .= "</table>\n";
if(!$printable) {
$html .= "</form>\n";
}
out: print six_page($button,'','','',$html,''); # Note the out tag, this is where redirects jump to
} else {
# If we don't have a DBH an error page has already been printed.
if($dbh) {
print auth_fail_page($userinfo{username});
}
}
wjl-0.26/src/cgi-bin/new_job.pl
/files/tmp/wjl-0.26/src/cgi-bin/new_job.pl.html
#!/usr/bin/perl
# New Job Page for Web Logs Software
# WJL V0.26, Page V0.2
# Carl Ritson - 2002
# Library Include
use Mysql;
use CGI qw/:standard/, 'shortcuts', 'center';
use strict;
use WJL;
use WJLCore;
# Main Program Body
# CGI & DBH
my $page = new CGI;
my $dbh = Mysql->connect(db_login()) || db_error;
# Predefine some Variables
my $user_valid = 0;
my $level = 0;
my %userinfo;
my $src = $page->param('src'); # Where did we come from.
# Call Start Page Function, only if we have a DBH.
if ($dbh) {
($user_valid, %userinfo) = start_page($page,$dbh);
$level = user_level($dbh,$userinfo{username});
}
if ($user_valid && has_right($level,'new_job')) {
my $wjl = WJL::New($dbh);
my $active = $page->param('active');
my $user = $userinfo{username};
my $title = h3("New Job");
my $complete = 0;
my $time = time();
my %parm;
if($userinfo{security} =~ /high/) {
%parm = %userinfo;
}
$parm{src} = $src;
$parm{carrier} = $page->param('carrier');
my $html = '';
my $atomic;
my ($date,$started,$caller,$dept,$description,$status,$priority,$taker,$allocated_to);
if($active) {
$atomic = $page->param('atomic');
$date = $page->param('date');
$started = $page->param('started');
$taker = cut(32,$page->param('taker'));
$caller = cut(32,$page->param('caller'));
$dept = cut(32,$page->param('dept'));
$description = $page->param('description');
$status = $page->param('status');
$priority = cut(32,$page->param('priority'));
$allocated_to = $page->param('allocated_to');
if($date && $started && $taker && $caller && $dept
&& $description && $status) {
$complete = 1;
}
#print STDERR "Atomic:$atomic,Time:$time,Status:$status\n";
#print STDERR "Get Atomic:".$wjl->get_job_atomic($user,$atomic)."\n";
}
if($complete && $wjl->get_job_atomic($user,$atomic)) {
my $job = $wjl->job();
# Pack the Data Input Hashes.
my %jinfo = (
started => date2timestamp($date) + int(rand(10)), # The random is to jitter the times to make them more unique.
problem_started => date2timestamp($started),
username => $wjl->initials2user($taker),
caller => $caller,
dept => $dept,
priority => has_right($level,'allocate')?priof($priority):'NA',
allocated_to => has_right($level,'allocate')?$wjl->initials2user($allocated_to):''
);
my %ev = (
username => $wjl->initials2user($taker),
type => 0,
status => status($status),
data => filter($description),
date => date2timestamp($date)
);
$job->info(%jinfo);
$job->new_event(%ev);
$job->commit();
# Prevent this job from being entered twice.
$wjl->set_job_atomic($user,$atomic);
my $parm = hash2get(%parm,new=>1,jobid=>$job->{'jobid'});
# Meta Redirect, hard to push back on.
$html = meta_redirect('job_list.pl'.$parm);
} else {
$html .= $title;
if($active) {
$html .= "<p><b>Please Complete All Fields.</b></p>\n";
}
if(!$date) {
$date = gen_date($time);
}
if(!$started) {
$started = gen_date($time);
}
if(!$taker) {
$taker = $wjl->user2initials($user);
}
if(!$atomic) {
$atomic = $time;
}
if(!$status) {
$status = 'New';
}
$html .= "<form>\n<table>\n";
$html .= hidden_fields(active => 1, atomic => $atomic);
$html .= hidden_fields(%parm);
$html .= Tr(td('Date:'),
td(text_field('date',$date)));
$html .= Tr(td('Problem Started:'),
td(text_field('started',$started)));
$html .= Tr(td('Person Taking Call:'),
td(select_field('taker',$taker,$wjl->list_technicians)));
$html .= Tr(td('Caller:'),
td(text_field('caller',$caller)));
$html .= Tr(td('Dept:'),
td(select_field('dept',$dept,$wjl->list_depts)));
$html .= Tr(td('Description:'),
td(text_area('description',4,25,$description)));
$html .= Tr(td('Job Status:'),
td(select_field('status',$status,statusl())));
if(has_right($level,'allocate')) {
$html .= Tr(td('Priority:'),
td(select_field('priority',$priority,priol())));
$html .= Tr(td('Allocated To:'),
td(select_field('allocated_to',$allocated_to,'',$wjl->list_technicians)));
}
$html .= "</table>\n";
$html .= "<p>\n";
$html .= submit_button('Add Job');
$html .= "</form>\n";
$html .= form_button('Cancel',$src,%parm);
$html .= "</p>\n";
}
print frame6_page($html);
} else {
# If we don't have a DBH an error page has already been printed.
if($dbh) {
print auth_fail_page($userinfo{username});
}
}
wjl-0.26/src/cgi-bin/job_report.pl
/files/tmp/wjl-0.26/src/cgi-bin/job_report.pl.html
#!/usr/bin/perl
# Job Report Page for Web Logs Software
# WJL V0.26, Page V0.1
# Carl Ritson - 2002
# Library Include
use Mysql;
use CGI qw/:standard/, 'shortcuts', 'center';
use strict;
use WJL;
use WJLCore;
# Main Program Body
# CGI & DBH
my $page = new CGI;
my $dbh = Mysql->connect(db_login()) || db_error;
# Predefine some Variables
my $user_valid = 0;
my $level = 0;
my %userinfo;
# Predefine and Capture
my $jobid = $page->param('jobid');
my $jobid_clone = $jobid;
my $src = $page->param('src'); # Where did we come from.
# Call Start Page Function, only if we have a DBH.
if ($dbh) {
($user_valid, %userinfo) = start_page($page,$dbh);
$level = user_level($dbh,$userinfo{username});
if($jobid) {
# We validate JobId here as we are sure we have a dbh.
if(!job_valid($jobid,$dbh)) {
$jobid = (-1);
}
}
}
if(((!$jobid) || $jobid == (-1)) && $user_valid) {
# If no jobid selected, or jobid not valid, allow user to enter one.
my $html = '';
my %parm;
if($userinfo{security} =~ /high/) {
%parm = %userinfo;
}
my $title = h3("Select Job");
$parm{src} = $src;
$parm{carrier} = $page->param('carrier');
$html .= $title;
if($jobid == (-1)) {
$html .= "<p><b>Sorry Jobid $jobid_clone does not exist</b></p>\n";
}
$html .= "<form>\n";
$html .= hidden_fields(%parm);
$html .= "<p>JobID:<input type=\"text\" name=\"jobid\"></p>\n";
$html .= "<p>\n";
$html .= submit_button('View');
$html .= "</form>\n";
$html .= form_button('Cancel',$src,%parm);
$html .= "</p>\n";
print frame6_page($html);
} elsif ($user_valid) {
my $wjl = WJL::New($dbh);
my $user = $userinfo{username};
my $job = $wjl->job($jobid);
my %jobinfo = $job->info();
my $title = h3("Job Report");
my $button = '';
my $complete = 0;
my $time = time;
my %parm;
if($userinfo{security} =~ /high/) {
%parm = %userinfo;
}
$parm{src} = $src;
my $html = '';
my %ev = $job->first_event();
$button = form_button('Return',$src,%parm);
$html .= u($title);
$html .= hr();
$html .= "<table WIDTH=\"80%\" BORDER=\"1\">\n";
$html .= Tr(td('Job Number:'),td($jobid));
$html .= Tr(td('Date of Report:'),td(gen_date($time)));
$html .= Tr(td('Date of Job Submission:'),td(gen_date($jobinfo{started})));
$html .= Tr(td('Department Reporting Job:'),td($jobinfo{dept}));
$html .= Tr(td('Staff Initials:'),td($jobinfo{caller}));
$html .= Tr(td('Call Logged By:'),td($wjl->user2initials($jobinfo{username})));
$html .= Tr(td('Reported Fault Description:'),td(fmt(40,4,$ev{data})));
$html .= Tr(td('Job Status:'),td(status($job->status())));
$html .= Tr(td('Job Priority:'),td(priof($jobinfo{priority})));
$html .= "</table>\n";
$html .= hr();
$html .= center(u(b('Engineers Comments')));
$html .= "<table BORDER=\"1\" WIDTH=\"90%\">\n";
$html .= Tr(td(center(b('Date'))),td(center(b('User'))),td(center(b('Comments'))))."\n";
my @events = $job->list_events();
my $count = 0;
foreach my $eventid (@events) {
my %ev = $job->event($eventid);
if(event_type('comment',$ev{type})) {
$html .= Tr(
td(center(gen_date($ev{date}))),
td(center($wjl->user2initials($ev{username}))),
td(center(fmt(80,2,$ev{data}))),
);
$html .= "\n";
++$count;
}
}
if($count == 0) {
$html .= Tr(td(''),td('There are no comments.'),td(''));
}
my ($closed,$due);
if($job->status() == status('Closed')) {
my %evl = $job->last_event();
$closed = gen_date($evl{date});
} else {
$due = $job->due();
if($due >= (-1)) {
if($due > 0) {
my @temp = split(/ /,gen_date($due));
$due = $temp[0]; # Only want the date.
} else {
$due = 'Overdue';
}
} else {
$closed = 'Not Completed';
}
}
my $resp = $job->response_time();
$html .= "</table>\n";
$html .= hr();
$html .= center(b('Summary'));
$html .= "<table BORDER=\"1\" WIDTH=\"80%\">\n";
$html .= "<tr ALIGN=\"middle\">\n";
$html .= "<td WIDTH=\"65%\">\n";
$html .= "<table BORDER=\"0\" WIDTH=\"100%\">\n";
$html .= Tr(td('Problem Started:'),td(gen_date($jobinfo{problem_started})));
if($closed) {
$html .= Tr(td('Job Closed:'),td($closed));
} else {
$html .= Tr(td('Estimated Completion:'),td($due));
}
$html .= Tr(td('Job Duration:'),
td(gen_elapsed($job->elapsed_time())));
$html .= Tr(td('Response Time:'),
td($resp?gen_elapsed($resp):'No Response'));
$html .= "</table>\n</td>\n";
$html .= "<td WIDTH=\"35%\">\n";
$html .= "<table BORDER=\"0\" WIDTH=\"100%\">\n";
$html .= Tr(td('Allocated To:'),
td($jobinfo{allocated_to}?$wjl->user2initials($jobinfo{allocated_to}):'NA'));
$html .= "</table>\n</td>\n";
$html .= "</td>\n";
$html .= "</tr>\n";
$html .= "</table>\n";
print six_page($button,'','','',$html,'');
} else {
# If we don't have a DBH an error page has already been printed.
if($dbh) {
print auth_fail_page($userinfo{username});
}
}
wjl-0.26/src/cgi-bin/edit_job.pl
/files/tmp/wjl-0.26/src/cgi-bin/edit_job.pl.html
#!/usr/bin/perl
# Edit Job Page for Web Logs Software (The Monster (tm))
# WJL V0.26, Page V0.15
# Carl Ritson - 2002
# Library Include
use Mysql;
use CGI qw/:standard/, 'shortcuts', 'center';
use strict;
use WJL;
use WJLCore;
# Main Program Body
# CGI & DBH
my $page = new CGI;
my $dbh = Mysql->connect(db_login()) || db_error;
# Predefine some Variables
my $user_valid = 0;
my $level = 0;
my %userinfo;
# Predefine and Capture
my $jobid = $page->param('jobid');
my $jobid_clone = $jobid;
my $src = $page->param('src'); # Where did we come from.
# Call Start Page Function, only if we have a DBH.
if ($dbh) {
($user_valid, %userinfo) = start_page($page,$dbh);
$level = user_level($dbh,$userinfo{username});
if($jobid) {
# We validate JobId here as we are sure we have a dbh.
if(!job_valid($jobid,$dbh)) {
$jobid = (-1);
}
}
}
if(((!$jobid) || $jobid == (-1)) && $user_valid) {
# If no jobid selected, or jobid not valid, allow user to enter one.
my $html = '';
my %parm;
if($userinfo{security} =~ /high/) {
%parm = %userinfo;
}
my $title = h3("Select Job");
$parm{src} = $src;
$html .= $title;
if($jobid == (-1)) {
$html .= "<p><b>Sorry Jobid $jobid_clone does not exist</b></p>\n";
}
$html .= "<form>\n";
$html .= hidden_fields(%parm);
$html .= "<p>JobID:<input type=\"text\" name=\"jobid\"></p>\n";
$html .= "<p>\n";
$html .= submit_button('Edit');
$html .= "</form>\n";
$html .= form_button('Cancel',$src,%parm);
$html .= "</p>\n";
print frame6_page($html);
} elsif ($user_valid && has_right($level,'edit_job')) {
my $wjl = WJL::New($dbh);
my $active = $page->param('active');
my $type = $page->param('submit_type');
my $eventmode = $page->param('event');
my $genpage = 1;
my $user = $userinfo{username};
my $job = $wjl->job($jobid);
my %jobinfo = $job->info();
my $title = h3("Edit Job");
my $complete = 0;
my $time = time();
my %parm;
if($userinfo{security} =~ /high/) {
%parm = %userinfo;
}
$parm{src} = $src;
$parm{carrier} = $page->param('carrier');
my $html = '';
# Actual Inputs
my ($atomic);
my ($date,$started,$caller,$dept,$description,$status,$priority,$taker,$allocated_to);
if($active && !$eventmode) {
$atomic = $page->param('atomic');
$date = $page->param('date');
$started = $page->param('started');
$taker = cut(4,$page->param('taker'));
$caller = cut(32,$page->param('caller'));
$dept = cut(32,$page->param('dept'));
$description = $page->param('description');
$status = $page->param('status');
$priority = $page->param('priority');
$allocated_to = cut(4,$page->param('allocated_to'));
if($date && $started && $taker && $caller && $dept
&& $description && $status) {
$complete = 1;
} elsif($type =~ /Delete/i) {
$complete = 1;
}
} elsif($eventmode) {
$atomic = $page->param('atomic');
$complete = 1;
}
if($complete && $wjl->get_job_atomic($user,$atomic)) {
if($type =~ /Save/i && !$eventmode) {
# Save type we have to determine what has changed and journal it.
my $_started = date2timestamp($date);
my $_problem_started = date2timestamp($started);
my $_prio = priof($priority);
my $_status = status($status);
my $_taker = $wjl->initials2user(filter($taker));
my $_allocated_to = $wjl->initials2user($allocated_to);
my $jstatus = $job->status();
# Status Change
if($jstatus != $_status) {
my %ev = (
username => $user,
type => 0x02, # 2 Status Change
status => $_status,
data => $jstatus
);
$job->new_event(%ev);
}
if(has_right($level,'allocate')) {
# Priority Change
if($_prio != $jobinfo{priority}) {
my %ev = (
username => $user,
type => 0x04, # 4 Priority Change
status => $_status,
data => $jobinfo{priority}
);
$job->new_event(%ev);
}
# Allocation Change
my $temp = $jobinfo{allocated_to};
if($_allocated_to !~ /^$temp$/) {
my %ev = (
username => $user,
type => 0x08, # 8 Allocation Change
status => $_status,
data => $jobinfo{allocated_to}
);
$job->new_event(%ev);
}
}
# Pack Up the New Job info
my %njobinfo = (
started => $_started,
problem_started => $_problem_started,
caller => filter($caller),
dept => filter($dept),
username => $_taker,
);
if(has_right($level,'allocate')) {
$njobinfo{priority} = $_prio;
$njobinfo{allocated_to} = $_allocated_to;
}
$job->info(%njobinfo);
$job->commit();
$job->description($description);
$job->set_job_atomic($user,$atomic);
%jobinfo = $job->info(); # Replace Stale Data
$active = 0; # Invalidate Other Stale Info
$atomic = $time; # Regenerate the Atomic so the page can be used again.
} elsif($type =~ /Delete/i && !$eventmode) {
$genpage = 0;
my $confirm = $page->param('confirm');
if($confirm) {
$wjl->set_job_atomic($user,$atomic);
$job->del();
$html = meta_redirect($src.hash2get(%parm));
} else {
$html = h3('Confirm Delete');
$html .= p(b("This will delete JobID: $jobid"));
$html .= form_button('Delete','edit_job.pl',%parm, active => 1, confirm => 1, jobid => $jobid);
$html .= form_button('Cancel','edit_job.pl',%parm, jobid => $jobid);
}
} elsif($eventmode) {
my $eventid = $page->param('eventid');
my $comment = filter($page->param('comment'));
if($type =~ /Add/i && $type =~ /Close/i) {
my %ev = (
username => $page->param('nuser')?$wjl->initials2user(cut(4,$page->param('nuser'))):$user,
type => 0x03, # 3 Status Change + Comment
status => status('Closed'),
#date => $page->param('ndate')?date2timestamp($page->param('ndate')):$time,
data => $comment
);
$job->new_event(%ev);
} elsif($type =~ /Add/i) {
my %ev = (
username => $page->param('nuser')?$wjl->initials2user(cut(4,$page->param('nuser'))):$user,
type => 0x01, # 1 Comment
status => $job->status(),
#date => $page->param('ndate')?date2timestamp($page->param('ndate')):$time,
data => $comment
);
$job->new_event(%ev);
} elsif($type =~ /Delete/i && has_right($level,'delete')) {
my %ev = $job->event($eventid);
# Special Case, we don't want to lose Status Info.
if(event_type('status_change',$ev{type})) {
$ev{type} = 0x02;
$ev{data} = '';
$job->mangle_event(%ev);
} else {
$job->delete_event($eventid);
}
} elsif($type =~ /Update/i) {
my $user = filter($page->param('user'));
my $user_prev = filter($page->param('user_prev'));
my $date = filter($page->param('date'));
my $date_prev = filter($page->param('date_prev'));
if($date =~ /^$date_prev$/ && $user =~ /^$user_prev$/) {
$job->update_event($eventid,$comment);
} else {
# Special Code to handle the editing of events in time...
my %ev = $job->event($eventid);
my %evn = %ev;
$evn{data} = $comment;
$evn{username} = $wjl->initials2user($user);
if($date !~ /^$date_prev$/) {
# If changing time we need to match status
my $d = date2timestamp($date);
my $query = "SELECT status FROM event WHERE date <= $d AND jobid=".$job->{'jobid'}." ORDER BY date DESC LIMIT 1";
my $result = $job->query($query);
my @temp = $result->fetchrow();
$evn{date} = $d;
$evn{status} = $temp[0];
if($ev{type} & 0x02) {
$ev{type} = 0x02;
$evn{type} = 0x01;
$job->mangle_event(%ev);
$job->new_event(%evn);
} else {
$job->mangle_event(%evn);
}
} else {
$job->mangle_event(%evn);
}
}
}
$job->set_job_atomic($user,$atomic);
$active = 0;
$atomic = $time;
}
} #elsif(!$wjl->get_job_atomic($user,$atomic)) {
#print STDERR "Bottling Atomic : $atomic\n";
#}
if($genpage) {
$html .= $title;
if($active && !$complete) {
$html .= p(b('Please Complete All Fields'));
} else {
my %evf = $job->first_event();
$date = gen_date($jobinfo{started});
$started = gen_date($jobinfo{problem_started});
$taker = $wjl->user2initials($jobinfo{username});
$caller = $jobinfo{caller};
$dept = $jobinfo{dept};
$description = $evf{data};
$status = status($job->status());
$priority = priof($jobinfo{priority});
$allocated_to = $wjl->user2initials($jobinfo{allocated_to});
}
if(!$atomic) {
$atomic = $time;
}
$html .= "<form>\n<table>\n";
$html .= hidden_fields(
active => 1,
atomic => $atomic,
src => $src,
jobid => $jobid
);
$html .= hidden_fields(%parm);
$html .= Tr(td('JobID:'),td($jobid));
$html .= Tr(td('Date:'),
td(text_field('date',$date)));
$html .= Tr(td('Problem Started:',
td(text_field('started',$started))));
$html .= Tr(td('Person Taking Call:'),
td(select_field('taker',$taker,$wjl->list_technicians())));
$html .= Tr(td('Caller:'),
td(text_field('caller',$caller)));
$html .= Tr(td('Dept:'),
td(select_field('dept',$dept,$wjl->list_depts)));
$html .= Tr(td('Description:'),
td(text_area('description',4,25,$description)));
$html .= Tr(td('Job Status:'),
td(select_field('status',$status,statusl())));
if(has_right($level,'allocate')) {
$html .= Tr(td('Priority:'),
td(select_field('priority',$priority,priol())));
$html .= Tr(td('Allocated To:'),
td(select_field('allocated_to',$allocated_to,'',$wjl->list_technicians())));
}
$html .= Tr(
td(has_right($level,'delete')?submit_button('Delete'):''),
td(submit_button('Save'))
);
#if(has_right($level,'delete')) {$html .= Tr(td(),td(submit_button('Delete')));}
$html .= "</table>\n</form>\n";
$html .= form_button('Return',$src,%parm);
if(has_right($level,'knowledge')) {
$html .= form_button('Add Knowledge','knowledge_add.pl',%parm,jobid=>$jobid);
}
$html .= hr();
$html .= center(b('Engineers Comments'));
$html .= "<table BORDER=\"1\" WIDTH=\"90%\">\n";
$html .= Tr(td(center(b('Date'))),td(center(b('User'))),td(center(b('Comments'))),td(),td())."\n";
$html .= Tr(
"<form>",
hidden_fields(%parm),
hidden_fields(
active => 1,
event => 1,
jobid => $jobid,
atomic => $atomic
),
#td(center(text_field('ndate',gen_date($time)))),
td(center(gen_date($time))),
td(center(select_field('nuser',$wjl->user2initials($user),$wjl->list_technicians()))),
td(center(text_area('comment',2,40,''))),
td(center(submit_button('Add'))),
td(center(submit_button('Add and Close Job'))),
"</form>"
);
my @events = $job->list_events();
foreach my $eventid (@events) {
#print STDERR "Eventid:$eventid\n";
my %ev = $job->event($eventid);
if(event_type('comment',$ev{type})) {
$html .= Tr(
"<form>",
hidden_fields(%parm),
hidden_fields(
active => 1,
event => 1,
eventid => $eventid,
jobid => $jobid,
atomic => $atomic,
user_prev => $wjl->user2initials($ev{username}),
date_prev => gen_date($ev{date})
),
td(center(text_field('date',gen_date($ev{date})))),
td(center(select_field('user',$wjl->user2initials($ev{username}),$wjl->list_technicians()))),
td(center(text_area('comment',2,40,$ev{data}))),
td(center(submit_button('Update'))),
td(center(has_right($level,'delete')?submit_button('Delete'):'')),
"</form>"
);
$html .= "\n";
}
}
$html .= "</table>\n";
}
print frame6_page($html);
} else {
# If we don't have a DBH an error page has already been printed.
if($dbh) {
print auth_fail_page($userinfo{username});
}
}