# -*- Perl -*-
#
# Copyright (C) 1996 Craig Ruefenacht <ruefenac@cs.utah.edu> and the
#                    University of Utah Computer Science Department
#
# $Id: Rust_Query.pm,v 1.26 1997/04/16 20:18:56 ruefenac Exp $
#
# This is part of RUST-1.0 Beta 6
#
# Abstract: This library contains Rust module functions which
#           perform queries on Rust queues.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with the source distribution of RUST, in the license
# directory. If you don't have a copy of it, write to: 
#
# Free Software Foundation, Inc.
# 675 Mass Ave
# Cambridge, MA 02139, USA.

{
package Rust_Query;

use Rust_Configs;
use Rust_Data;
use Rust_Lib;
use Rust_Exit;
use Rust_Debug;

require Exporter;
@ISA = qw(Exporter);
@EXPORT =
    (
     # name                       brief description
     # --------------------------------------------------------     
     'init_query',		# Initialize this library
     'get_headers',		# Return header info on Rust tickets
     'get_ticket_log',		# Return contents of ticket logfile
     'get_section_headers',	# Return info on each section of a logfile
     'get_section',		# Return array containing specified section 
     'print_ticket_stdout',	# Print a ticket file to stdout
     'create_nice_date'		# Create a nice looking date string
     );

 
#-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
sub init_query {
    #
    # Type: Can be called by external scripts
    #
    # Abstract: Initialize this library by adding the $global
    #           hash to this object.
    
    $globals = &Rust_Configs::get_globals;
}

#-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
sub get_headers {
    #
    # Type: Can be called by external scripts
    #
    # Abstract: Retreive header information for a specified
    #           set of ticket headers.
    #
    #           This returns a 2 dimentional array, size Nx13, where
    #           N is the number of tickets contained in the
    #           array.  The array is structred as follows:
    #
    #                   idx  What info it contains
    #                   -------------------------------
    #                   0,0    Error code              # 0 if success, error# if an error
    #                   0,1    Number of headers in array
    #                   1,0    ticket number(s)       # if merged, numbers are comma seperated
    #	                1,1    queue index where ticket is
    #                   1,2    How old the ticket is  # a string, like "5 min, "1 day" etc...
    #                   1,3    Last update             # "    "    "      "
    #                   1,4    Date of notification 
    #                   1,5    ticket category        # work ticket, user ticket
    #                   1,6    ticket accounting info # Who's gonna pay for the time
    #                   1,7    ticket hours worked    # Sum of minutes worked.  a number
    #                   1,8    ticket owner
    #                   1,9    ticket user(s)         # if more than one user, comma seperated
    #                   1,10   ticket priority
    #                   1,11   ticket status
    #                   1,12   ticket eta
    #                   1,13   ticket subjec
    #                   1,14   ticket email list
    #                   1,15   ticket other queue list
    #
    # The pattern is then repeated for [2][], [3][], [4][]....
    #
    # There must be the exact number of args to this function.  If you
    # want some omitted, then pass in () for the argument.

    Rust_Debug::ddebug("Entering Rust_Query::get_headers\n");

    my ($caller, $opt_realuser, $user, $owner, $unowned, $type, $status, $priority,
	$category, $subject, $sort, $limit, $queue_index) = @_;

    my (@file_list, @return_array, $okay, $count, $rust_owner, $rust_user, 
	$rust_status, $rust_priority, $rust_category, $rust_subject, $all_queues,
	$do_queue, $current_alias, $moved_ticket);

    my ($rust_info) = new Rust_Data;

    $all_queues = 0;
    $all_queues = 1 if ($queue_index == -1);
    $do_queue = 1;
    $count = 0;
	

    # If "--status resolved" or "--status archived" then make that be
    # "--type resolved" or "--type archived" respectively

    if (($status eq "resolved") || ($status eq "archived")) {
	$type = $status;
	$status = "";
    }
      
    while ($do_queue) {
	    
	if ($all_queues) {
	    $queue_index++;
	}

	# Don't want to do this if the queue the ticket is in is private
	if ((($opt_realuser) && (Rust_Configs::extract_element('public_queue',$queue_index))) ||
	    (!$opt_realuser)) {

	    $current_alias = Rust_Configs::extract_element('alias_name',$queue_index);

	    
	    Rust_Debug::debug("Checking $caller authorization for $current_alias RUST queue\n");
	    
	    # Check to see if the caller can look at $queue_index RUST queue
	    if (Rust_Lib::check_caller($caller, "", $queue_index)) {
		
		# Extract the list of filenames 
		
		@file_list = (sort {$b <=> $a} &get_ticket_list($type, $queue_index)) if ($sort == 0);
		@file_list = (sort {$a <=> $b} &get_ticket_list($type, $queue_index)) if ($sort == 1);
		
		if (@file_list) {
		    
		    $specific_count = 0;
		    
		    foreach $each (@file_list) {
			
			$okay = 1; 
			$moved_ticket = 0;
			
			# We don't need to worry about locking the file
			# because we are only going to do a read.  Shouldn't
			# write AT ALL to any files (except logs of usage)
			
			@errors = $rust_info->init($each, $queue_index);
			$rust_info->read_header_file;
			
			if ($errors[2] != $queue_index) {
			    $moved_ticket = 1;
			} 
			
			$match = 1;

			# Need to check the real user against the user who made the
			# ticket.  In the user interface, some sites may not want
			# user to be able to look at every ticket.  $opt_realuser should
			# *always* be true if this is called by a user interface.
			
			if ($opt_realuser) {
			    
			  Rust_Debug::debug("I think a user interface called me...\n");
			    
			    if (!($rust_info->get_value('access') eq 'private')) {
				if (!(Rust_Configs::extract_element('user_see_all',$queue_index))) {
				  Rust_Debug::debug("User isn't allowed to see all tickets\n");
				    $user = $opt_realuser;
				}
			    } else {
				$okay = 0;
				&debug("Ticket ",$rust_info->get_value('number')," is private, users cannot see it.\n");
			    }
			}
			
			# user filter - There should *always* be a valid rust_user!!!
			$match = 0;
			
			if ($user) {
			    $rust_user = $rust_info->get_value('user');
			    foreach $each_user (split(',',$user)) {
				foreach $each_rust_user (split(',',$rust_user)) {
				    $each_rust_user = (split('@',$each_rust_user))[0];
				    if ($each_user eq $each_rust_user) {
					&debug("$each_user and $each_rust_user MATCHED\n");
					$match = 1;
				    }
				}
			    }
			}
			if ((!$match) && ($user)) {
			    $okay = 0;
			    &debug("USER MATCHED FAILED!\n");
			}
			
			# owner filter 
			$match = 0;
			if ((($owner) || ($unowned)) && ($okay)) {
			    $rust_owner = $rust_info->get_value('owner');
			    if (($owner eq 'unowned') || ($unowned)) {
				$match = 1 if (!($rust_owner));
			    }
			    if ($owner) {
				if ($owner eq $rust_owner) {
				    $match = 1;
				} else {  
				    foreach $each_rust_owner (Mail::Address->parse($rust_owner)) {
					if ($owner eq $each_rust_owner->address()) {
					    $match = 1;
					}
				    }
				}
			    } else {
				$okay = 0 if (!($match));
			    }
			}
			if ((!$match) && ($owner)) {
			    $okay = 0;
			    &debug("OWNER MATCH FAILED!\n");
			}
			
			# status filter - Assume that the given status is okay.
			$match = 0;
			if (($status) && ($okay)) {
			    $rust_status = $rust_info->get_value('status');
			    if ($status eq $rust_status) {
				$match = 1;
			    }
			}
			if ((!$match) && ($status)) {
			    $okay = 0;
			    &debug("STATUS MATCH FAILED!\n");
			}
			
			# priority filter - assume $priority is "low","normal","high"
			$match = 0;
			if (($priority) && ($okay)) {
			    $rust_priority = $rust_info->get_value('priority');
			    if ($priority eq $rust_priority) {
				$match = 1;
			    }
			}
			if ((!$match) && ($priority)) {
			    $okay = 0;
			    &debug("PRIORITY MATCH FAILED!\n");
			}
			
			# category filter - assume $category is "user","work"
			$match = 0;
			if (($category) && ($okay)) {
			    $rust_category = $rust_info->get_value('category');
			    if ($category eq $rust_category) {
				$match = 1;
			    }
			}
			if ((!$match) && ($category)) {
			    $okay = 0;
			    &debug("CATEGORY MATCH FAILED!\n");
			}
			
			# subject filter - Do a reg exp to check for subject
			$match = 0;
			if (($subject) && ($okay)) {
			    $rust_subject = $rust_info->get_value('subject');
			    if ($subject =~ /($rust_subject)/) {
				$match = 1;
			    }
			}
			if ((!$match) && ($subject)) {
			    $okay = 0;
			    &debug("SUBJECT MATCH FAILED!\n");
			}
			
			# If the RUST system is in the process of making a ticket
			# and the process isn't done yet, we don't want it to
			# show up in the list of tickets.  This can be found by
			# checking to see if the "user" and "owner" headers have
			# valid data.  Other headers could be used as well...
			
			if (($rust_info->get_value('user') eq 'unknown') &&
			    ($rust_info->get_value('owner') eq 'unknown')) {
			    $okay = 0;
			    &debug("TICKET IS TOO NEW TO LOOK AT!\n");
			}
			
			# Don't want to include moved tickets....
			if (($okay) && (!$moved_ticket)) {
			    
			    &debug("THE TICKET IS GOOD TO GO...\n");
			    $count++;
			    $specific_count++;
			    
			    $return_array[$count][0] = $each;
			    $return_array[$count][1] = $queue_index;
			    $return_array[$count][2] = &create_nice_date($rust_info->get_value('created'));
			    $return_array[$count][3] = &create_nice_date($rust_info->get_value('updated'));
			    $return_array[$count][4] = &create_nice_date($rust_info->get_value('notified'));
			    $return_array[$count][5] = $rust_info->get_value('category');
			    $return_array[$count][6] = $rust_info->get_value('accounting');
			    $return_array[$count][7] = $rust_info->get_value('hours');
			    if ($rust_info->get_value('owner')) {
				$return_array[$count][8] = $rust_info->get_value('owner');
			    } else {
				$return_array[$count][8] = "";
			    }
			    $return_array[$count][9] = $rust_info->get_value('user');
			    $return_array[$count][10] = $rust_info->get_value('priority');
			    if ($moved_ticket) {
				$return_array[$count][11] = "MOVED";
			    } else {
				$return_array[$count][11] = $rust_info->get_value('status');
			    }
			    $return_array[$count][12] = $rust_info->get_value('eta');
			    $return_array[$count][13] = $rust_info->get_value('subject');
			    $return_array[$count][14] = $rust_info->get_value('email');
			    $return_array[$count][15] = $rust_info->get_value('other_queues');
			}
			
			last if (($specific_count == $limit) && ($limit));
		    }
		} 
		
	    }	
	}

	$do_queue = 0 if ($queue_index == ($globals->{'number_of_queues'} - 1));
	$do_queue = 0 if (!($all_queues));
    }

     if (!$count) {
         Rust_Debug::ddebug("Leaving Rust_Query::get_headers\n");
	 $return_array[0][0] = 17;
	 return @return_array;
     }
  
    Rust_Debug::ddebug("Leaving Rust_Query::get_headers\n");
    $return_array[0][0] = 0;
    $return_array[0][1] = $count;
    return @return_array;
}

#-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
sub get_ticket_log {
    #
    # Type: Can be called by external scripts
    #
    # Abstract: Read a specified ticket logfile and return it as
    #           an array.  This puts the header information for the
    #           ticket at the top of the array!!!
    #
    #           The array is structed as follows:
    #
    # 	            0   Error code		# 0 if success, error# if error
    #               1   Ticket queue that ticket is in
    #               2   Ticket number
    #               3   Ticket creation date
    #               4   Ticket updated date
    #               5   Ticket notified date
    #               6   Ticket category (either user or work)
    #               7   Ticket subject
    #               8   Ticket type
    #               9   Ticket user(s)
    #               10  Ticket owner
    #               11  Ticket status
    #               12  Ticket priority
    #               13  Ticket ETA
    #               14  Ticket email
    #               15  Ticket other queues
    #               16  Ticket access flag
    #               17+ Logfile of the ticket

    Rust_Debug::ddebug("Entering Rust_Query::get_ticket_log\n");

    my ($caller, $opt_realuser, $opt_num, $queue_index) = @_;
    
    my ($rust_info, @file_list, @return_array, $okay, $count, $rust_owner, $rust_user,
	$rust_status, $rust_user, $rust_priority, $rust_category, $rust_subject);

    # Don't want to do this if the queue the ticket is in is private
    if ((($opt_realuser) && (Rust_Configs::extract_element('public_queue',$queue_index))) ||
	(!$opt_realuser)) {

	# Check to see if the caller can look at $queue_index RUST queue
	if (Rust_Lib::check_caller($caller, "", $queue_index)) {

	    # create the ticket object
	    
	    @errors = Rust_Lib::read_file($caller, "", "", $opt_num, $queue_index);
	    return $errors[0] if ($errors[0] == 13);
	    
	    $rust_info = $errors[1];
	    $queue_index = $rust_info->get_value('queue_index');
	    $opt_num = $rust_info->get_value('number');
	    $rust_user = $rust_info->get_value('user');
	    
	    # Now check various things to see if we should allow
	    # this ticket to be seen

	    $match = 1;

	    # Need to check the real user against the user who made the
	    # ticket.  In the user interface, some sites may not want
	    # user to be able to look at every ticket.  $opt_realuser should
	    # *always* be true if this is called by a user interface.

	    if ($opt_realuser) {
		
	      Rust_Debug::debug("I think a user interface called me...\n");

		$match = 0;

		if (!($rust_info->get_value('access') eq 'private')) {
		    if (!(Rust_Configs::extract_element('user_see_all',$queue_index))) {
			foreach $each_rust_user (Mail::Address->parse($rust_user)) {
			    if (($opt_realuser eq $each_rust_user->address()) ||
				($opt_realuser eq $rust_user)) {
				$match = 1;
			    } 
			}

		    } else {
			$match = 1;
		    }
		}
	    }

	    if (!$match) {
	      Rust_Debug::debug("User isn't allowed to see the ticket\n");
		return 21;
	    }
	    
	    $return_array[0] = 0;
	    $return_array[1] = Rust_Configs::extract_element('alias_name',$queue_index);
	    $return_array[2] = $rust_info->get_value('number');
	    $return_array[3] = $rust_info->get_value('created');
	    $return_array[4] = $rust_info->get_value('updated');
	    $return_array[5] = $rust_info->get_value('notified');
	    $return_array[6] = $rust_info->get_value('category');
	    $return_array[7] = $rust_info->get_value('subject');
	    $return_array[8] = $rust_info->get_value('type');
	    $return_array[9] = $rust_info->get_value('user');
	    
	    if (!$rust_info->get_value('owner')) {
		$return_array[10] = "";
	    } else {
		$return_array[10] = $rust_info->get_value('owner');
	    }
	    
	    $return_array[11] = $rust_info->get_value('status');
	    $return_array[12] = $rust_info->get_value('priority');
	    $return_array[13] = $rust_info->get_value('eta');
	    $return_array[14] = $rust_info->get_value('email');
	    $return_array[15] = $rust_info->get_value('other_queues');
	    $return_array[16] = $rust_info->get_value('access');
    
	    @body = Rust_Lib::read_rust_log((split(',',$opt_num))[0], $queue_index, $rust_info);
	    
	    if ($body[0] == 13) {
		$return_array[0] = 13;
	    } else {
		
		foreach $each (@body) {
		    push(@return_array, $each);
		}
	    }
	}
    } else {
      Rust_Debug::ddebug("Leaving Rust_Query::get_ticket_log\n");
	return 1;
    }
  
    Rust_Debug::ddebug("Leaving Rust_Query::get_ticket_log\n");
    return @return_array;
}

#-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
sub get_section_headers {
    #
    # Type: Can be called by external scripts
    #
    # Abstract: Read a specified ticket logfile and return info
    #           about each "section" in the logfile.  This info
    #           is returned as an two dimentional array.
    #
    #           The array is structed as follows:
    #
    #               0,0 Error code          # 0 if success, error# if error
    #               0,1 Number of sections, is the M in the NxM array
    #
    #               1,0 Date of the section
    #               1,1 User who created section
    #
    #               2,0 Date of the section
    #               2,1 User who created section
    #
    #               etc...

    Rust_Debug::ddebug("Entering Rust_Query::get_section_headers\n");

    my ($caller, $opt_realuser, $opt_num, $queue_index) = @_;
    
    my ($rust_info, @return_array, $rust_owner, $rust_user,
	$rust_type);

    # Don't want to do this if the queue the ticket is in is private
    if ((($opt_realuser) && (Rust_Configs::extract_element('public_queue',$queue_index))) ||
	(!$opt_realuser)) {

	# Check to see if the caller can look at $queue_index RUST queue
	if (Rust_Lib::check_caller($caller, "", $queue_index)) {

	    # create the ticket object
	    
	    @errors = Rust_Lib::read_file($caller, "", "", $opt_num, $queue_index);
	    return $errors[0] if ($errors[0] == 13);
	    
	    $rust_info = $errors[1];
	    $queue_index = $rust_info->get_value('queue_index');
	    $opt_num = $rust_info->get_value('number');
	    $rust_user = $rust_info->get_value('user');
	    $rust_type = $rust_info->get_value('type');
	    
	    # Need to check the real user against the user who made the
	    # ticket.  In the user interface, some sites may not want
	    # user to be able to look at every ticket.  $opt_realuser should
	    # *always* be true if this is called by a user interface.
	    
	    if ((!(Rust_Configs::extract_element('user_see_all',$queue_index))) &&
		($opt_realuser)) {
		foreach $each_rust_user (Mail::Address->parse($rust_user)) {
		    if (($opt_realuser eq $each_rust_user->address()) ||
			($opt_realuser eq $rust_user)) {
			$match = 1;	   
		    } 
		}
		if (!$match) {
		  Rust_Debug::debug("User isn't allowed to see the ticket\n");
		    return 21;
		}
	    }
	    
	    
	    $queue_name = Rust_Configs::extract_element('alias_name',$queue_index);
	    
	    $rust_file = Rust_Lib::get_ticket_filename($queue_name, $opt_num,
							$rust_type);
	    
	    $message_number = -1;
	    for ( Mail::Util::read_mbox ( $rust_file ) ) {
		$message_number++;
	      Rust_Debug::debug("Reading in message number $message_number\n");
		$mail_message = Mail::Internet->new( $_ );
		
		$return_array[$message_number+1][0] = $mail_message->get('Date:');
		$return_array[$message_number+1][1] = $mail_message->get('From:');
		chomp($return_array[$message_number+1][0]);
		chomp($return_array[$message_number+1][1]);
	    }
	    
	    $return_array[0][0] = 0;
	    $return_array[0][1] = $message_number;
	}
    }
      
    Rust_Debug::ddebug("Leaving Rust_Query::get_section_headers\n");
    return @return_array;
}

#-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
sub get_section {
    #
    # Type: Can be called by external scripts
    #
    # Abstract: Read a specified ticket logfile and return the
    #           contents of the section as an array

    Rust_Debug::ddebug("Entering Rust_Query::get_section\n");

    my ($caller, $opt_realuser, $opt_num, $opt_section, $queue_index) = @_;
    
    my ($rust_info, @return_array, $rust_owner, $rust_user, $rust_type);

    # Don't want to do this if the queue the ticket is in is private
    if ((($opt_realuser) && (Rust_Configs::extract_element('public_queue',$queue_index))) ||
	(!$opt_realuser)) {

	# Check to see if the caller can look at $queue_index RUST queue
	if (Rust_Lib::check_caller($caller, "", $queue_index)) {
	    
	    # create the ticket object
	    
	    @errors = Rust_Lib::read_file($caller, "", "", $opt_num, $queue_index);
	    return $errors[0] if ($errors[0] == 13);
	    
	    $rust_info = $errors[1];
	    $queue_index = $rust_info->get_value('queue_index');
	    $opt_num = $rust_info->get_value('number');
	    $rust_user = $rust_info->get_value('user');
	    $rust_type = $rust_info->get_value('type');
	    
	    # Need to check the real user against the user who made the
	    # ticket.  In the user interface, some sites may not want
	    # user to be able to look at every ticket.  $opt_realuser should
	    # *always* be true if this is called by a user interface.
	    
	    if ((!(Rust_Configs::extract_element('user_see_all',$queue_index))) &&
		($opt_realuser)) {
		foreach $each_rust_user (Mail::Address->parse($rust_user)) {
		    if (($opt_realuser eq $each_rust_user->address()) ||
			($opt_realuser eq $rust_user)) {
			$match = 1;	   
		    } 
		}
		if (!$match) {
		  Rust_Debug::debug("User isn't allowed to see the ticket\n");
		    return 21;
		}
	    }
	    
	    
	    $queue_name = Rust_Configs::extract_element('alias_name',$queue_index);
	    
	    $rust_file = Rust_Lib::get_ticket_filename($queue_name, $opt_num,
							$rust_type);
	    
	    @return_array = ();
	    push(@return_array, 0);
	    $message_number = -1;
	    for ( Mail::Util::read_mbox ( $rust_file ) ) {
		$message_number++;
	      Rust_Debug::debug("Reading in message number $message_number\n");
		$mail_message = Mail::Internet->new( $_ );
		if ($message_number == ($opt_section - 1)) {
		    $message_headers = $mail_message->header();
		    $message_body = $mail_message->body();
		    foreach $each (@{$message_headers}) {
			chomp($each);
			push(@return_array, $each);
		    }
		    foreach $each (@{$message_body}) {
			chomp($each);
			push(@return_array, $each);
		    }
		    
		    $return_array[0][0] = 0;
		    return @return_array;
		}
	    }
	    return 30;
	}
    }

    Rust_Debug::ddebug("Leaving Rust_Query::get_section\n");
    return 1;
}

#-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
sub print_ticket_stdout {
    #
    # Type: Can be called by external scripts
    #
    # Abstract: Print a ticket to stdout
    #

    my ($caller, $opt_realuser, $opt_show, $queue_index) = @_;

    my ($count, @m_b);

    # Don't want to do this if the queue the ticket is in is private
    if ((($opt_realuser) && (Rust_Configs::extract_element('public_queue',$queue_index))) ||
	(!$opt_realuser)) {

	@m_b = &get_ticket_log($caller, $opt_realuser, $opt_show, $queue_index);

	if ($m_b[0] == 13) {
	    print "Couldn't find ticket number $opt_show\n";
	} elsif ($m_b[0] == 21) {
	    print "You can't look at ticket number $opt_show\n";
	} elsif ($m_b[0] == 1) {
	    print "You are not authroized to look at tickets in the specified queue!\n";
	} else { 
	    
	    $count = 0;
	
	    while ($count <= $#m_b) {
	    
		if ($count == 0) {
		    print "=" x 75, "\n";
		    print "TICKET INFORMATION\n";
		    print "=" x 75, "\n";
		} elsif (($count > 0) && ($count < 11)) {
		    print 'Ticket Queue: ',$m_b[1],"\n";
		    print 'Ticket Number: ', $m_b[2],"\n";
		    print 'Ticket Creation: ', $m_b[3],"\n";
		    print 'Ticket Updated: ', $m_b[4],"\n";
		    print 'Ticket Notification: ', $m_b[5],"\n";
		    print 'Ticket Category: ', $m_b[6],"\n";
		    print 'Ticket Subject: ', $m_b[7],"\n";
		    print 'Ticket Type: ', $m_b[8],"\n";
		    print 'Ticket User(s): ', $m_b[9],"\n";
		    print 'Ticket Owner: ', $m_b[10],"\n";
		    print 'Ticket Status: ', $m_b[11],"\n";
		    print 'Ticket Priority: ', $m_b[12],"\n";
		    print 'Ticket ETA: ', $m_b[13],"\n";
		    print 'Ticket Email:', $m_b[14],"\n";
		    print 'Ticket Other Queues:', $m_b[15],"\n";
		    print 'Ticket Access Flag:', $m_b[16],"\n";
		    $count = 16;
		} elsif ($count ==17) {
		    print "=" x 75, "\n";
		    print "TICKET LOGFILE\n";
		    print "=" x 75, "\n";
		    print $m_b[17];
		} else {
		    print $m_b[$count];
		}
		
		$count++;
	    }
	}
    }
}

#-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
sub create_nice_date {
    #
    # Type: Can be called by external scripts
    #
    # Abstract: Take a date, which is assumed to be
    #           in the format "Mon June 3 1995   (83832824)".
    #           The number in parens represents the number
    #           of seconds that has elapsed since the beginning
    #           of UNIX time. 
    #
    #           Extract the seconds from the passed-in date, and
    #           compare it with the current date.  Find the difference
    #           and create a nice looking date string

    my ($date_to_parse) = @_;

    my ($elapsed_seconds);
    my ($seconds) = 0;
    my ($current_seconds) = time();

    if ($date_to_parse =~ /\((\d+)\)/) {
	$seconds = $1;
    }

    if ($seconds) {

	$elapsed_seconds = $current_seconds - $seconds;
	       
	return join(' ',$elapsed_seconds, 'sec') 
	    if ($elapsed_seconds < 60);
	return join(' ',int($elapsed_seconds/60), 'min') 
	    if ($elapsed_seconds < (60*60));
	return join(' ',int($elapsed_seconds/(60*60)), 'hr')
	    if ($elapsed_seconds < (60*60*24));
	return join(' ',int($elapsed_seconds/(60*60*24)), 'day')
	    if ($elapsed_seconds < (60*60*24*7));
	return join(' ',int($elapsed_seconds/(60*60*24*7)), 'wk')
	    if ($elapsed_seconds < (60*60*24*7*4));
	return join(' ',int($elapsed_seconds/(60*60*24*7*4)), 'mth')
	    if ($elapsed_seconds < (60*60*24*7*4*356));
	return join(' ',int($elapsed_seconds/(60*60*24*7*4*356)), 'yr');
    }
    return "";
}

}
1;
