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 .= '&sectoken='.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});
        }
}