Files
interactive/gms/LG/httpd/wwwroot/tts/TTXTicket.pm
2026-08-07 17:38:18 +09:00

1376 lines
47 KiB
Perl

package TTXTicket;
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2002-2006, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 287 $
# $Date: 2006-10-17 16:00:49 +0400 (Tue, 17 Oct 2006) $
#
$TTXTicket::VERSION='2.22';
BEGIN {
$TTXTicket::REVISION = '$Revision: 287 $';
if ($TTXTicket::REVISION =~ /(\d+)/) {
$TTXTicket::REVISION = $1;
}
};
use strict;
use TTXCommon;
require TTXUser;
use TTXTickets;
require TTXMail;
require TTXMarkup;
require TTXDictionary;
my $useGD;
# =================================================================== invenabled
my $_invenabled = undef;
sub invenabled {
if ($_invenabled eq undef) {
eval 'use TTXInvMod';
if ($@ eq undef) {
$_invenabled = 1;
} else {
$_invenabled = 0;
}
}
return $_invenabled;
}
# ====================================================================== company
sub company {
my ($cfg, $ticket) = @_;
my $cid = $cfg->get('customcompany');
my $title;
if ($cid ne undef && $cid =~ /(\d+)/) {
$cid = $1;
$title = $ticket->{"c$cid"};
}
if ($title eq undef) {
$title = $cfg->get('company');
}
return $title;
}
# =================================================================== usernotify
sub usernotify {
my $cfg = $_[0]->{cfg};
my $ticket = $_[0]->{ticket};
my $email = $ticket->{'email'};
my $name = $ticket->{'name'};
my %macros;
$name = '[%Customer%]' if $name eq undef;
my $subject;
my $messages = $ticket->{messages};
my $tmpl;
if (@{$messages} == 1) {
$tmpl = 'newticket';
if ($cfg->get('validate') ne undef) {
$tmpl .= 'validate';
$macros{ENV_HTTP_HOST} = $ENV{HTTP_HOST};
$macros{VALIDATIONCODE} = $_[0]->{validationcode};
} else {
return if $cfg->get('_USER') eq undef && $cfg->get('notikcfrm');
}
} else {
return if $cfg->get('_USER') eq undef && $cfg->get('nomsgcfrm');
$tmpl = 'newmessage';
}
if (open(TMPL, $cfg->get('basedir')."/templates/$tmpl.txt")) {
my @buff = <TMPL>;
close TMPL;
$tmpl = join('', @buff);
}
$macros{TICKETID} = $ticket->{id};
$macros{TICKETSTATE} = TTXDictionary::translate(TTXCommon::status($ticket->{status}));
$macros{UNAME} = $name;
$macros{COMPANYNAME} = company($cfg, $ticket);
$macros{UEMAIL} = $email;
$macros{OPERATORNAME} = '-';
$macros{FROM} = $_[0]->{from};
$macros{GROUP} = ($ticket->{grp} ne undef) ? $cfg->get($ticket->{grp}) : '-';
my $oper;
if ($cfg->get('_USER') ne undef) {
$oper = $cfg->get('_USER');
} elsif ($ticket->{oper} ne undef) {
$oper = TTXUser->new($ticket->{oper});
}
if ($oper ne undef) {
$macros{OPERATORNAME} = $oper->{fname}.' '.$oper->{lname};
}
my $respondername;
if ($cfg->get('askforname') ne undef) {
my $nm = $name;
$nm =~ s/[="'&><]//g;
$nm =~ s/\s/+/g;
$respondername = "&respondername=$nm";
}
$macros{TICKETURL} = '[url'." http://$ENV{HTTP_HOST}$ENV{SCRIPT_NAME}?cmd=ticket&key=".$ticket->{key}.$respondername.
'][b]Ticket '.$macros{TICKETID}.'[/b][/url]'."\n\nACCESS KEY: ".$ticket->{key};
my $msg = $messages->[@{$messages} - 1];
my @msgparts = split(/\n\n/, $msg);
shift @msgparts;
my $body = join("\n\n", @msgparts);
# $body =~s/\[b]//g;
# $body =~s/:\[\/b]/:/g;
$macros{MESSAGE} = $body;
my $cnt = TTXCommon::cfldcnt();
for (my $i = 0; $i < $cnt; ++$i) { $macros{"C$i"} = $ticket->{"c$i"}; }
my $tmplcc = $tmpl;
$tmpl =~ s/\(%\s*([A-Z0-9_]+)\s*%\)/$macros{$1}/g;
$tmpl =~ s/\[%%\]//g;
$tmpl =~ s/\[%([^]]+)%\]/TTXDictionary::translate($1)/ge;
$subject = TTXDictionary::translate('Ticket').' '.$ticket->{id};
$subject .= ", ".$ticket->{subject} if $ticket->{subject} ne undef;
TTXMail::sendmail(
{
to => $email,
from => "\"".company($cfg, $ticket)."\" <".$cfg->get('email').">",
# from => "\"".$cfg->get('company')."\" <" . (($cfg->get('_USER') ne undef && $cfg->get('_USER')->{email} ne undef)? $cfg->get('_USER')->{email}:$cfg->get('email')) . ">",
subject => $subject,
msg => $tmpl
}
);
if ($cfg->get('emaillist') ne undef) {
my $tmplname;
if (@{$messages} == 1) {
$tmplname = 'newticket';
$tmplname = 'newccticket' if -f $cfg->get('basedir')."/templates/newccticket.txt";
} else {
$tmplname = 'newmessage';
$tmplname = 'newccmessage' if -f $cfg->get('basedir')."/templates/newccmessage.txt";;
}
if (open(TMPL, $cfg->get('basedir')."/templates/$tmplname.txt")) {
my @buff = <TMPL>;
close TMPL;
$tmplcc = join('', @buff);
}
$macros{TICKETURL} = '[url '."http://$ENV{HTTP_HOST}$ENV{SCRIPT_NAME}?cmd=ticket&key=".$ticket->{key}.
'][b]Ticket '.$macros{TICKETID}.'[/b][/url]'."\n\nACCESS KEY: ".$ticket->{key};
my $n = $cfg->get('emaillist');
if ($n =~ /^\d\d?$/) {
my @addrlist = split(/,/, $ticket->{"c$n"});
$macros{UNAME} = '[%Customer%]';
foreach my $addr (@addrlist) {
$addr =~ s/\s//g;
$macros{UEMAIL} = $addr;
my $tmpltmp = $tmplcc;
$tmpltmp =~ s/\(%\s*([A-Z0-9_]+)\s*%\)/$macros{$1}/g;
$tmpltmp =~ s/\[%%\]//g;
$tmpltmp =~ s/\[%([^]]+)%\]/TTXDictionary::translate($1)/ge;
TTXMail::sendmail(
{
to => $addr,
from => "\"".company($cfg, $ticket)."\" <".$cfg->get('email').">",
subject => $subject,
msg => $tmpltmp
}
);
}
}
}
}
# ================================================================= buildadrlist
sub buildadrlist {
my @adrlist;
foreach my $oper (@{$_[0]}) {
my $u = TTXUser->new($oper);
if ($u ne undef && $u->{email} ne undef) {
push @adrlist, $u->{email};
}
}
return @adrlist;
}
# =============================================================== transfernotice
sub transfernotice {
my $cfg = $_[0]->{cfg};
my $ticket = $_[0]->{ticket};
my $o = $cfg->get('_USER');
return if $o eq undef;
my $u = TTXUser->new($ticket->{oper});
return if $u eq undef || $u->{email} eq undef;
my $quicklink;
if ($cfg->get('quicklink')) {
$quicklink = '&o='.$ticket->{oper};
my $salt = $ticket->{id} % 100;
$salt = "0$salt" if $salt < 10;
my $p = crypt($u->{passwd}.$ticket->{id}, $salt);
$p =~ s/^\d\d//;
$quicklink .= "&p=$p";
}
TTXMail::sendmail(
{
to => $u->{email},
from => "\"".company($cfg, $ticket)."\" <".$cfg->get('email').">",
subject => TTXDictionary::translate('Ticket transfer notice'),
msg => '[b]'.TTXDictionary::translate('Ticket ID').':[/b] '.$ticket->{id}."\n".
'[b]'.TTXDictionary::translate('Subject').':[/b] '.$ticket->{subject}."\n".
'[b]'.TTXDictionary::translate('Transferred by').':[/b] '.$o->{fname}.' '.$o->{lname}.' ('.$o->{login}.") \n".
'[b]'.TTXDictionary::translate('Access link').':[/b] '.
'[url http://'.$ENV{HTTP_HOST}.$ENV{SCRIPT_NAME}.'?cmd=helpdesk&tk='.$ticket->{key}.$quicklink.']'.
TTXDictionary::translate('Ticket').' '.$ticket->{id}.'[/url]'."\n\n"
# msg => "Hello ".$u->{fname}.",\n\n".$o->{fname}." ".$o->{lname}." (".$o->{login}.") has transferred ".
# "trouble ticket #".$ticket->{id}." to you. In order to access the ticket use this link:\n\n".
# "http://$ENV{HTTP_HOST}$ENV{SCRIPT_NAME}?cmd=helpdesk&tk=".$ticket->{key}."$quicklink\n\n"
}
);
}
# =================================================================== opernotify
sub opernotify {
my $cfg = $_[0]->{cfg};
return if $cfg->get('silent');
my $ticket = $_[0]->{ticket};
my @adrlist;
if ($cfg->get('usegrpsel') && $ticket->{status} eq 'PND' && ! exists $_[0]->{notifylist}) {
my $grp;
if ($ticket->{grp} eq undef) {
$grp = $cfg->get('defaultgrp');
} else {
$grp = $ticket->{grp};
}
my @list = split(/;/, $cfg->get("mbr-$grp"));
$_[0]->{notifylist} = \@list;
}
if (exists $_[0]->{notifylist}) {
@adrlist = buildadrlist($_[0]->{notifylist});
} elsif ($ticket->{oper} ne undef) {
my @operlist = split(/,/, $ticket->{oper});
push @operlist, $cfg->get('supervisor') if $cfg->get('supervisor') ne undef;
@adrlist = buildadrlist(\@operlist);
} else {
@adrlist = TTXUser::listemail();
}
my $email = $ticket->{'email'};
my $name = $ticket->{'name'};
my %macros;
$name = '[%Customer%]' if $name eq undef;
my $messages = $ticket->{messages};
my $tmpl;
if (@{$messages} == 1) {
$tmpl = 'onewticket';
} else {
$tmpl = 'onewmessage';
}
if (open(TMPL, $cfg->get('basedir')."/templates/$tmpl.txt")) {
my @buff = <TMPL>;
close TMPL;
$tmpl = join('', @buff);
}
$macros{TICKETID} = $ticket->{id};
if (invenabled()) {
my $items = TTXInvMod::getitems($ticket->{item});
my $val = undef;
foreach my $item (@{$items}) {
$val .= ', ' if $val ne undef;
$val .= $item->{title};
}
$val = 'none' if $val eq undef;
$macros{ITEMLBL} = $cfg->get('inventory.label') || 'Item';
$macros{ITEM} = $val;
$macros{ITEMLINE} = "\n[b]$macros{ITEMLBL}:[/b] $macros{ITEM}";
}
$macros{GROUP} = ($ticket->{grp} ne undef) ? $cfg->get($ticket->{grp}) : '-';
$macros{TICKETSTATE} = TTXDictionary::translate(TTXCommon::status($ticket->{status}));
$macros{UNAME} = $name;
$macros{COMPANYNAME} = company($cfg, $ticket);
$macros{UEMAIL} = $email;
$macros{TICKETURL} = '[url '."http://$ENV{HTTP_HOST}".$cfg->get('scriptname')."?cmd=helpdesk&tk=".$ticket->{key}.
'][b]Ticket '.$macros{TICKETID}.'[/b][/url]';
my $msg = $messages->[@{$messages} - 1];
my @msgparts = split(/\n\n/, $msg);
shift @msgparts;
my $body = join("\n\n", @msgparts);
# $body =~s/\[b]//g;
# $body =~s/:\[\/b]/:/g;
$macros{MESSAGE} = $body;
my $cnt = TTXCommon::cfldcnt();
for (my $i = 0; $i < $cnt; ++$i) { $macros{"C$i"} = $ticket->{"c$i"}; }
my $tmplcpy;
if (!$cfg->get('quicklink')) {
$tmpl =~ s/\(%\s*([A-Z0-9_]+)\s*%\)/$macros{$1}/g;
$tmpl =~ s/\[%%\]//g;
$tmpl =~ s/\[%([^]]+)%\]/TTXDictionary::translate($1)/ge;
} else {
$tmplcpy = $tmpl;
}
my @oplist; # got to think about this...
if (exists $_[0]->{notifylist}) {
@oplist = @{$_[0]->{notifylist}};
} elsif ($ticket->{oper} ne undef) {
@oplist = split(/,/, $ticket->{oper});
push @oplist, $cfg->get('supervisor') if $cfg->get('supervisor') ne undef;
} else {
@oplist = TTXUser::list();
}
foreach my $adr (@adrlist) {
my $oper = shift @oplist;
if ($oper ne undef) { # just to make sure
my $u = TTXUser->new($oper);
if ($u ne undef && $u->{email} ne undef) {
if ($cfg->get('quicklink')) {
my $tmp = $macros{TICKETURL};
$macros{TICKETURL} .= '&o='.$oper;
my $salt = $ticket->{id} % 100;
$salt = "0$salt" if $salt < 10;
my $p = crypt($u->{passwd}.$ticket->{id}, $salt);
$p =~ s/^\d\d//;
$macros{TICKETURL} .= "&p=$p";
$tmpl = $tmplcpy;
$tmpl =~ s/\(%\s*([A-Z0-9_]+)\s*%\)/$macros{$1}/g;
$tmpl =~ s/\[%%\]//g;
$tmpl =~ s/\[%([^]]+)%\]/TTXDictionary::translate($1)/ge;
$macros{TICKETURL} = $tmp;
}
my $subject = TTXDictionary::translate('Ticket').' '.$ticket->{id};
if ($u->{usemail}) {
$ticket->{key} =~ /Z(\w\w\w\w)/;
$subject .= ' ('.$u->{snum}."-$1)";
}
$subject .= ", ".$ticket->{subject} if $ticket->{subject} ne undef;
TTXMail::sendmail(
{
to => $adr,
from => "\"".company($cfg, $ticket)."\" <".$cfg->get('email').">",
subject => $subject,
msg => $tmpl
}
);
} else {
next;
}
} else {
last;
}
}
}
# ====================================================================== keyform
sub keyform {
my ($cfg, $query, $data) = @_;
$data->{PAGEHEADING} = '[%Access Key%]';
$data->{MESSAGE} = '[%Forgot the key? We will send it to your email address.%]';
return undef if !$query->param('do');
$query->param(-name => 'do', -value => '');
if ($query->param('cancel') ne undef) {
if ($cfg->get('_USER') ne undef) { return 'helpdesk'; }
else { return 'newticket'; }
}
if ($query->param('cmd') eq 'keyform') {
my $key = TTXCommon::cleanit($query, 'key');
if ($key eq undef) {
$data->{ERROR_MESSAGE} = '[%Missing access key%]';
return undef;
}
if ($cfg->get('shortkey')) {
if ($key !~ /^\d+$/) {
$data->{ERROR_MESSAGE} = '[%Invalid access key%]';
return undef;
}
} elsif ($key !~ /^\d+Z\d+$/) {
$data->{ERROR_MESSAGE} = '[%Invalid access key%]';
return undef;
}
return 'ticket';
}
# keyfinder code
my $email = TTXCommon::cleanit($query, 'email');
if ($email eq undef) {
$data->{ERROR_MESSAGE} = '[%Missing email address%]';
return undef;
}
if ($email !~ /^[0-9A-Za-z._-]+@[0-9A-Za-z_-]+\.[0-9A-Za-z._-]+$/) {
$data->{ERROR_MESSAGE} = '[%Invalid email address%]';
return undef;
}
my $tickets = TTXCommon::dbtik();
if ($tickets eq undef || $tickets->error() ne undef) {
$data->{ERROR_MESSAGE} = $tickets->errortext();
return undef;
}
my @filter;
my $f;
$f->{col} = 'email';
$f->{expr} = "^$email\$";
push @filter, $f;
my $browser = $tickets->list(0, 999, 'id', 'A', \@filter);
my $list = $browser->{list};
if (@{$list} < 1) {
$data->{ERROR_MESSAGE} = '[%No tickets found%]';
} else {
my $body;
foreach my $id (@{$list}) {
my $t = $tickets->ticket($id);
$body .= "#".$id." (".$t->{subject}.") KEY: ".$t->{key}."\n";
}
$tickets = undef;
$body = TTXDictionary::translate('Dear customer,')."\n\n".
TTXDictionary::translate('This is a list of all service tickets associated '.
'with your email address')."\n\n$body\n";
$body .= TTXDictionary::translate('Use the following link to access your tickets')."\n".
"[url http://$ENV{HTTP_HOST}$ENV{SCRIPT_NAME}?cmd=ticket]Show Ticket[/url]\n\n".
TTXDictionary::translate('Kind Regards')."\n".$cfg->get('company')."\n";
TTXMail::sendmail(
{
to => $email,
from => "\"".$cfg->get('company')."\" <".$cfg->get('email').">",
subject => TTXDictionary::translate('Access key(s)'),
msg => $body
}
);
$data->{MESSAGE} = '<b>[%Access keys were sent to your email address.%]</b>';
}
return undef;
}
# ================================================================== checkgroups
my $groupsenabled;
sub checkgroups {
if ($groupsenabled eq undef) {
eval "use TTXGroups";
if (!$@) {
$groupsenabled = 1;
} else {
$groupsenabled = 0;
if ($_[0]->get('usegrpsel')) {
$_[0]->set('usegrpsel', 0);
$_[0]->save();
}
}
}
}
# ========================================================================== kid
sub kid {
my ($cfg, $query, $data, $useold) = @_;
eval "use GD" if !$useGD;
if ($useGD || $@ eq undef) {
$useGD = 1;
my $datadir = $cfg->get('basedir');
my $keyid;
my $oldid = TTXCommon::cleanit($query, 'kid');
if ($oldid ne undef && $oldid !~ /^\d+-\d+$/) {
$oldid = undef;
$query->param(-name => 'kid', -value => '');
}
if ($oldid ne undef && $useold && (-f "$datadir/keys/$oldid.cgi")) {
$keyid = $oldid;
} else {
$query->param(-name => 'kid', -value => '');
if (-f "$datadir/keys/$oldid.cgi") {
unlink "$datadir/keys/$oldid.cgi";
}
$keyid = time(). "-$$";
$useold = 0;
}
if (! -d "$datadir/keys") {
mkdir("$datadir/keys", 0777);
}
if (-d "$datadir/keys") {
if (!$useold && open(KF, ">$datadir/keys/$keyid.cgi")) {
my $key = 999 + int rand(9000);
print KF "$key\n";
close KF;
}
$data->{KID} = $keyid;
my $keycode;
if ($useold && $oldid ne undef) {
$keycode = TTXCommon::cleanit($query, 'keycode');
$keycode =~ s/"/&quot;/g;
}
$data->{KIDVAL} = <<EOT;
<input type=text name=keycode size=6 value="$keycode">
<input type=hidden name=kid value="$keyid">
EOT
$data->{KIDIMG} = "<img src=\"key.cgi?$keyid\" width=50 height=20 />";
$data->{KIDFORM} = <<EOT;
<tr>
<td align=right><b>[%Access code%]</b></td>
<td align=left>
<table>
<tr>
<td><img src="key.cgi?$keyid" width=50 height=20 /></td>
<td>[%Copy the code here%]: </td>
<td><input type=text name=keycode size=6 value="$keycode">
<input type=hidden name=kid value="$keyid"></td>
</tr>
</table>
</td>
</tr>
EOT
}
}
}
# ==================================================================== newticket
sub newticket {
my ($cfg, $query, $data) = @_;
my $cfn; # captcha code file name
$data->{PAGEHEADING} = '[%Contact Customer Service%]';
if (TTXData::get('ISPRO')) {
$data->{FILEFORMS} = TTXFile::fileforms();
}
if ($cfg->get('_USER') ne undef) {
$data->{INTERNALCHECKBOX} = '<input type=checkbox name=internal value=1' .
($query->param('internal') ? ' checked':''). '> <span class=lbl>[%Internal%]</span>';
} else {
$data->{INTERNALCHECKBOX} = '&nbsp;';
}
checkgroups($cfg);
if ($cfg->get('usegrpsel')) {
TTXGroups::selector($cfg, $query, $data);
}
if ($cfg->get('inventory.show') && invenabled()) {
TTXInvMod::selector($cfg, $query, $data);
}
if ($cfg->get('useopersel')) {
eval "use TTXOpers";
if (!$@) {
TTXOpers::selector($cfg, $query, $data);
} else {
$cfg->set('useopersel', 0);
}
}
eval "use TTXLayout";
if (!$@) {
my $ldver;
eval '$ldver = $TTXLayout::VERSION';
if ($ldver >= '2.22') {
my $cfldcnt = TTXCommon::cfldcnt();
for (my $i = 0; $i < $cfldcnt; ++$i) {
$data->{"CUSTOM$i"} = TTXLayout::cfld($query, $i);
$data->{"CUSTOMROW$i"} = TTXLayout::cfldrow($query, $i);
$data->{"CUSTOMVARS"} .= $data->{"CUSTOMROW$i"};
}
}
}
if (!$query->param('do')) {
foreach my $input ('email', 'name') {
if ($query->param($input) eq undef) {
$query->param(-name => $input, -value => $cfg->get("_GLOBAL_newticket_$input"));
}
}
kid($cfg, $query, $data, 0) if $cfg->get('useaccesscode');
return undef;
}
$query->param(-name => 'do', -value => '');
if ($query->param('cancel') ne undef) {
$query->param(-name => 'cancel', -value => '');
if ($cfg->get('_USER') ne undef) {
$query->param(-name => 'tid', -value=> '');
return 'helpdesk';
} else {
return undef;
}
}
my $ticket;
$ticket->{grp} = TTXCommon::cleanit($query, 'grp');
$ticket->{name} = TTXCommon::cleanit($query, 'name');
$ticket->{email} = TTXCommon::cleanit($query, 'email');
$ticket->{subject} = TTXCommon::cleanit($query, 'subject');
if (invenabled()) {
my @items = $query->param('item');
if (grep(/^-$/, @items) || !int(@items)) {
@items = ('-');
$ticket->{item} = '';
} else {
$ticket->{item} = ';'.join(';', @items).';';
}
}
my $error;
if ($ticket->{name} eq undef) {
$error .= '[%Missing Name%]<br>';
}
$ticket->{lname} = $ticket->{name};
$ticket->{name} =~ /\s(\w+)$/;
$ticket->{lname} = $1 if $1 ne undef;
if ($ticket->{email} eq undef) {
$error .= '[%Missing Email%]<br>'."\n";
} elsif ($ticket->{email} !~ /^[0-9A-Za-z'._-]+@[0-9A-Za-z_-]+\.[0-9A-Za-z._-]+$/) {
$error .= "Invalid Email<br>";
}
if ($ticket->{grp} eq undef && $cfg->get('usegrpsel')) {
$error .= TTXDictionary::translate('Missing').' '.($cfg->get('grpsellbl') || '[%Department%]')."<br>";
}
if ($ticket->{subject} eq undef) {
$error .= '[%Missing Subject%]<br>';
}
my $useold = 0;
if ($cfg->get('useaccesscode')) {
eval "use GD" if !$useGD;
if ($useGD || $@ eq undef) {
$useGD = 1;
my $kid = TTXCommon::cleanit($query, 'kid');
if ($kid !~ /^\d+-\d+$/) {
$error .= '[%Corrupted access code%]<br>';
} else {
$cfn = $cfg->get('basedir')."/keys/$kid.cgi";
my $key = TTXCommon::cleanit($query, 'keycode');
if ($key eq undef) {
$error .= '[%Missing access code%]<br>';
} else {
if (!open(KF, $cfn)) {
$error .= '[%Expired access code%]<br>';
} else {
my $k = <KF>;
close KF;
chomp $k;
if ($k ne $key) {
$error .= '[%Invalid access code%]<br>';
} else {
$useold = 1;
}
}
}
}
}
}
if ($cfg->get('useopersel') && $query->param('oper') eq undef) {
$error .= '[%Missing Operator%] (<i>[%to assign the ticket to%]</i>)<br>';
}
my $custom;
my @inputs = sort $query->param();
my @mandatory = split(/\s*,\s*/,$query->param('mandatory'));
my $cfldcnt = TTXCommon::cfldcnt();
foreach my $input (@inputs) {
next if $input !~ /^x./;
next if $query->param($input) eq undef;
@mandatory = grep { $_ ne $input } @mandatory;
my $val = $query->param($input);
my $cidx;
if ($cfg->get($input) ne undef) {
$cidx = int ($cfg->get($input));
if ($cidx >= 0 && $cidx < $cfldcnt) {
if ($cfg->get("c$cidx.type") eq 'list') {
my @vals = $query->param($input);
my @allow = split(/;/, $cfg->get("dropdown$cidx"));
my @accept;
foreach my $v (@vals) {
push @accept, $v if grep(/^$v$/, @allow);
}
$val = join(';', @accept);
$ticket->{"c$cidx"} = ";$val;" if $val ne undef;
} else {
$ticket->{"c$cidx"} = $val;
}
}
}
$input =~ s/^x//;
$custom .= "[b]$input:[/b] $val\n";
}
$custom .= "\n" if $custom ne undef;
foreach my $mid (@mandatory) {
$mid =~ s/^x//;
$error .= '[%Missing%]'." $mid<br>\n";
}
if ($error ne undef) {
$error =~ s/<br>$//;
$data->{ERROR_MESSAGE} = $error;
kid($cfg, $query, $data, $useold) if $cfg->get('useaccesscode');
return undef;
}
foreach my $input ('email', 'name') {
$cfg->set("_GLOBAL_newticket_$input", $query->param($input));
}
TTXCommon::cleanit($query, 'problem');
my $tickets = TTXCommon::dbtik();
if ($tickets->error() ne undef || !$tickets->addticket($ticket)) {
$data->{ERROR_MESSAGE} = $tickets->errortext();
kid($cfg, $query, $data, $useold) if $cfg->get('useaccesscode');
return undef;
}
if ($cfg->get('validate') ne undef) {
my $n = $cfg->get('validate');
if ($n =~ /^\d\d?$/) {
$ticket->{"c$n"} = 'N';
srand($ticket->{open});
my $k = int (rand(999999));
$data->{VALIDATIONCODE} = $ticket->{id}."Z$k";
}
}
my @messages;
$messages[0] = "From: ".$ticket->{name}."\nDate: ".time()."\nIP: $ENV{REMOTE_ADDR}\n";
if ($query->param('internal')) {
$messages[0] .= "Operator: 1\nInternal: Yes\n";
}
if (TTXData::get('ISPRO')) {
for (my $i = 1; $i < 4; ++$i) {
next if $query->param("f$i") eq undef;
$messages[0] .= TTXFile::addfile($query, "f$i", "fname$i", $ticket->{id});
}
}
my $autoassignmsg;
if ($cfg->get('useopersel') && $query->param('oper') ne undef && $query->param('oper') ne '-') {
my $u = TTXUser->new($query->param('oper'));
if ($u ne undef) {
$ticket->{oper} = $u->{login};
$ticket->{status} = 'OPN';
$autoassignmsg = '[%The ticket is assigned to%] '.$u->{fname}.' '.$u->{lname}."\n\n";
}
}
$messages[0] .= "\n$custom$autoassignmsg".substr($query->param('problem'),0,32*1024);
$ticket->{messages} = \@messages;
if (!$tickets->save()) {
$data->{ERROR_MESSAGE} = $tickets->errortext();
kid($cfg, $query, $data, $useold) if $cfg->get('useaccesscode');
return undef;
}
unlink $cfn if $cfn ne undef && -f $cfn;
$tickets = undef;
$data->{TICKETID} = $ticket->{id};
$data->{TICKETKEY} = $ticket->{key};
usernotify({cfg => $cfg, ticket => $ticket, validationcode => $data->{VALIDATIONCODE}})
if !$query->param('internal');
if ($cfg->get('validate') eq undef) {
my $opernotifydata = {cfg => $cfg, ticket => $ticket};
if ($cfg->get('supervisor') ne undef) {
my @list = ($cfg->get('supervisor'));
$opernotifydata->{notifylist} = \@list;
} elsif ($cfg->get('usegrpsel')) {
my @list = split(/;/, $cfg->get("mbr-".$ticket->{grp}));
$opernotifydata->{notifylist} = \@list;
} elsif ($cfg->get('routex') ne undef) {
eval "use TTXCustomRoute";
if ($@ eq undef) {
my @list = TTXCustomRoute::routelist($cfg, $ticket);
$opernotifydata->{notifylist} = \@list;
}
}
opernotify($opernotifydata);
}
if ($cfg->get('report')) {
eval "use TTXEReport";
if ($@ eq undef) {
TTXEReport::reportopen($cfg, $ticket);
}
}
if ($cfg->get('internaldesk')) {
$query->param(-name => 'reset', -value => 1);
return 'helpdesk';
}
if ($query->param('noconfirmation')) {
$query->param(-name => 'reset', -value => 1);
return 'helpdesk';
}
return 'confirmnew';
}
# =================================================================== confirmnew
sub confirmnew {
my ($cfg, $query, $data) = @_;
return undef;
}
# ==================================================================== fid2title
my $_f2t;
sub fid2title {
if ($_f2t eq undef) {
eval 'use TTXData';
my $cfg;
eval '$cfg = TTXData::get'."('CONFIG')";
return $_[0] if $cfg eq undef;
my @xflds = grep(/^x/, $cfg->vars());
foreach my $xfld (@xflds) {
my $t = $xfld;
$t =~ s/^x//;
$_f2t->{'c'.$cfg->get($xfld)} = $t;
}
}
return $_f2t->{$_[0]} || $_[0];
}
# ======================================================================= wanted
sub wanted {
my ($cfg, $query, $ticket) = @_;
my $buff;
if ($cfg->get('mandatoryfields') ne undef) {
my @mflist = split(/;/, $cfg->get('mandatoryfields'));
foreach my $fid (@mflist) {
next if $fid !~ /^c\d+$/;
my $title = fid2title($fid);
$title =~ s/</&lt;/g;
$buff .= "<tr>\n<td align=left class=lbl>$title</td>\n<td align=left>";
my $id = $fid; $id =~ s/^c//;
if ($cfg->get("dropdown$id") ne undef) {
$buff .= "<select name=wanted$id>\n";
if ($ticket->{$fid} eq undef) {
if ($query->param("wanted$id") eq undef) {
$buff .= "<option></option>\n";
}
} elsif ($query->param("wanted$id") eq undef) {
$query->param(-name => "wanted$id", -value => $ticket->{$fid});
}
my @options = split(/;/, $cfg->get("dropdown$id"));
foreach my $option (@options) {
my $safeoption1 = $option;
my $safeoption2 = $option;
$safeoption1 =~ s/"/&quot/g;
$safeoption2 =~ s/</&lt;/g;
$buff .= "<option value=\"$safeoption1\"";
if ($option eq $query->param("wanted$id")) {
$buff .= ' selected';
}
$buff .= ">$safeoption2</option>\n";
}
$buff .= "</select>\n";
} else {
my $val = $query->param('do') ? $query->param("wanted$id") : $ticket->{$fid};
$val =~ s/"/&quot;/g;
$buff .= "<input type=text size=25 name=wanted$id value=\"$val\">\n";
}
$buff .= "</td>\n</tr>\n";
}
if ($buff ne undef) {
$buff = "<table width=".$cfg->get('HTMLBASEWIDTH')."cellspacing=0 cellpadding=0 bgcolor=\"#CFDCE8\">\n".
"<tr>\n<td align=center>\n".
"<table cellpadding=3>$buff</table>\n".
"</td>\n</tr>\n".
"</table>\n";
}
}
return $buff;
}
# ======================================================================= lockdb
my $lockcnt;
sub lockdb {
return ++$lockcnt if $lockcnt;
my $cfg = TTXData::get('CONFIG');
return 1 if $cfg->get('dbmode') !~ /sql/;
my $lockfile = $cfg->get('basedir')."/lockdb.ttx";
if (! -f $lockfile) {
if (!open(LOCK, ">$lockfile")) {
return 0;
}
} elsif (!open(LOCK,"+<$lockfile")) {
return 0;
}
flock(LOCK, 2);
$lockcnt = 1;
return 1;
}
# ===================================================================== unlockdb
sub unlockdb {
return if !$lockcnt;
my $cfg = TTXData::get('CONFIG');
return if $cfg->get('dbmode') !~ /sql/;
--$lockcnt;
if (!$lockcnt) {
flock(LOCK, 8);
close LOCK;
}
}
# ======================================================================== claim
sub claim {
my ($cfg, $query, $data) = @_;
if ($query->param('cancel') ne undef) {
$query->param(-name => 'tid', -value=> '');
$query->param(-name => 'do', -value => '');
return 'helpdesk';
}
return undef if !$query->param('do');
$query->param(-name => 'do', -value => '');
lockdb();
my $tickets = TTXCommon::dbtik();
if ($tickets eq undef || $tickets->error() ne undef) {
$data->{ERROR_MESSAGE} = $tickets->errortext();
unlockdb();
return undef;
}
my $t = $tickets->ticketbykey(TTXCommon::cleanit($query, 'key'));
if ($t eq undef) {
$data->{ERROR_MESSAGE} = '[%Invalid access key%]';
$query->param(-name => 'tid', -value=> '');
unlockdb();
return 'helpdesk';
}
if ($t->{oper} ne undef) {
$data->{ERROR_MESSAGE} = '[%The ticket is already assigned to%] '.$t->{oper};
} else {
if ($cfg->get('mandatoryfields') ne undef && $query->param('delete') eq undef) {
my @mflist = split(/;/, $cfg->get('mandatoryfields'));
my $err;
foreach my $fid (@mflist) {
next if $fid !~ /^c\d+$/;
my $id = $fid; $id =~ s/^c//;
if ($query->param("wanted$id") ne undef) {
$t->{$fid} = $query->param("wanted$id");
} elsif ($t->{$fid} eq undef) {
$err .= '[%Missing%] '.fid2title($fid)."<br>";
}
}
if ($err ne undef) {
$data->{ERROR_MESSAGE} = $err;
$data->{WANTED} = wanted($cfg, $query, $t);
unlockdb();
return 'ticket';
}
}
$t->{oper} = $cfg->get('_USER')->get('login');
$t->{status} = 'OPN';
if ($cfg->get('claimtime') ne undef) {
my $totaltm = int ((time() - $t->{open})/60);
my $totaltmm = $totaltm % 60;
my $totaltmh = int(($totaltm - $totaltmm) / 60);
$totaltmm = "0$totaltmm" if $totaltmm < 10;
$totaltmh = "0$totaltmh" if $totaltmh < 10;
$t->{'c'.$cfg->get('claimtime')} = $totaltmh.':'.$totaltmm;
}
$tickets->save();
TTXCommon::logit("CLAIM|".$t->{oper}."|".$t->{id});
if ($query->param('delete') ne undef) {
my $oper = $cfg->get('_USER')->get('login');
if (!($cfg->get('demo') && $oper ne 'admin') &&
($cfg->get('grant.delete') eq undef || grep(/^$oper$/, split(/,/, $cfg->get('grant.delete'))))) {
$tickets->deltik($t->{id});
$tickets->save();
}
$query->param(-name => 'tid', -value=> '');
unlockdb();
return 'helpdesk';
}
}
unlockdb();
return 'ticket';
}
# ======================================================================= ticket
sub ticket {
my ($cfg, $query, $data) = @_;
checkgroups($cfg);
TTXCommon::tickedvars($cfg, $data);
if ($query->param('cancel') ne undef) {
if ($query->param('sid') ne undef) {
$query->param(-name => 'tid', -value=> '');
$query->param(-name => 'do', -value=> '');
return 'helpdesk';
} else {
if ($query->param('emailkey') ne undef) {
return 'mytickets';
} else {
return 'newticket';
}
}
}
if ($query->param('key') eq undef) {
return 'keyform';
}
my $tickets = TTXCommon::dbtik();
if ($tickets eq undef || $tickets->error() ne undef) {
$data->{ERROR_MESSAGE} = $tickets->errortext();
return undef;
}
my $t = $tickets->ticketbykey(TTXCommon::cleanit($query, 'key'));
if ($t eq undef) {
$data->{ERROR_MESSAGE} = $cfg->get('shortkey') ? '[%Ticket does not exist%]':'[%Invalid access key%]';
return 'keyform';
}
$query->param(-name => 'tid', -value=> $t->{id});
my $cmd;
my $isoper = 0;
my $readonly;
if ($cfg->get('_USER') ne undef) {
$readonly = $cfg->get('_USER')->get('ro') ? 1:0;
if (!$readonly) {
my $oper = $cfg->get('_USER')->get('login');
my $candel;
if (!($cfg->get('demo') && $oper ne 'admin') &&
($cfg->get('grant.delete') eq undef || grep(/^$oper$/, split(/,/, $cfg->get('grant.delete'))))) {
$candel = 1;
}
if ($t->{oper} eq undef) {
$cmd = 'claim';
$data->{WANTED} = wanted($cfg, $query, $t);
if ($candel) {
$data->{DELTICKET} = '&nbsp;&nbsp;<input type=submit onsubmit name=delete onclick="return confirmdel()" value="[%Delete ticket%]">';
}
} else {
if ($candel) {
$data->{DELTICKET} = '<input type=submit onsubmit name=delete onclick="return confirmdel()" value="[%Delete ticket%]">';
}
}
$data->{TICKEDOPEN} = "<a href=# onClick=\"return ticked('".$query->param('tid')."')\">";
$data->{TICKEDCLOSE} = '</a>';
$data->{ANSWERLIB} = '&nbsp;&nbsp;&nbsp;&nbsp;<a href=#teditor onClick="return answerlib()">[%Answer library%]</a>';
}
$isoper = 1;
}
if ($query->param('do') && $t->{status} eq 'CLS' && !$isoper) {
$query->param(-name => 'email', -value => $t->{email});
$query->param(-name => 'name', -value => $t->{name});
$query->param(-name => 'subject', -value => $t->{subject});
$query->param(-name => 'problem', -value => TTXDictionary::translate('Posted as a followup to the solved ticket').' #'.$t->{id}.
".\n\n".$query->param('problem'));
return 'newticket';
}
if ($t->{status} =~ /OPN|WFR/ && !$readonly) {
$data->{PREVIEW} .= '&nbsp;&nbsp;<a href=#teditor onClick="return preview()">[%Preview%]</a>';
}
my $notify;
my $xupdate = 0;
my @inputs = $query->param();
@inputs = grep(/^x/, @inputs);
my $cfldcnt = TTXCommon::cfldcnt();
foreach my $input (@inputs) {
my $val = TTXCommon::cleanit($query, $input);
my $n = $cfg->get($input);
next if $n eq undef || $n =~ /[^0-9]/ || $n < 0 || $n >= $cfldcnt;
if ($val ne $t->{"c$n"}) {
$t->{"c$n"} = $val;
$xupdate = 1;
}
}
if ($cmd eq undef && $query->param('do')) {
if ($readonly) {
$query->param(-name => 'do', -value=> '');
$query->param(-name => 'tid', -value=> '');
return 'helpdesk';
}
if ($isoper && $query->param('delete') ne undef) {
my $oper = $cfg->get('_USER')->get('login');
if (!($cfg->get('demo') && $oper ne 'admin') &&
($cfg->get('grant.delete') eq undef || grep(/^$oper$/, split(/,/, $cfg->get('grant.delete'))))) {
$tickets->deltik($t->{id});
$tickets->save();
}
$query->param(-name => 'do', -value=> '');
$query->param(-name => 'tid', -value=> '');
return 'helpdesk';
}
my $attachment;
if (TTXData::get('ISPRO')) {
for (my $i = 1; $i < 4; ++$i) {
next if $query->param("f$i") eq undef;
$attachment .= TTXFile::addfile($query, "f$i", "fname$i", $t->{id});
}
}
if ($query->param('problem') eq undef && $attachment ne undef) {
$query->param(-name => 'problem', -value => 'See attachment');
}
if ($query->param('problem') eq undef && $query->param('newstatus') eq 'CLS') {
$query->param(-name => 'problem', -value => TTXDictionary::translate('Ticket closed'));
}
if ($query->param('problem') eq undef &&
($query->param('newstatus') eq undef || $t->{status} eq $query->param('newstatus')) &&
($query->param('transfer') eq undef || $t->{oper} eq $query->param('transfer')) &&
!$xupdate) {
$data->{ERROR_MESSAGE} = '[%Missing message%]';
} elsif (!$isoper && $cfg->get('askforname') && TTXCommon::cleanit($query, 'respondername') eq undef) {
$data->{ERROR_MESSAGE} = '[%Missing name%]';
} else {
if ($isoper && $cfg->get('tracktime') ne undef) {
my $ttx = $cfg->get('tracktime');
if ($ttx ne undef && $ttx !~ /[^0-9]/ && $ttx >= 0 && $ttx < $cfldcnt) {
my $tth = int(TTXCommon::cleanit($query, 'tracktimeh'));
my $ttm = int(TTXCommon::cleanit($query, 'tracktimem'));
$query->param(-name => 'tracktimeh', -value => '');
$query->param(-name => 'tracktimem', -value => '');
my ($totaltmh, $totaltmm) = split(/:/, $t->{"c$ttx"});
my $totaltm = $totaltmh * 60 + $totaltmm;
$totaltm += $tth * 60 + $ttm;
$totaltmm = $totaltm % 60;
$totaltmh = int(($totaltm - $totaltmm) / 60);
$totaltmm = "0$totaltmm" if $totaltmm < 10;
$totaltmh = "0$totaltmh" if $totaltmh < 10;
$t->{"c$ttx"} = $totaltmh.':'.$totaltmm;
}
}
if ($query->param('newstatus') ne undef) {
$t->{status} = $query->param('newstatus');
} else {
if ($t->{status} eq 'OPN' && $isoper && !$query->param('internal')) { $t->{status} = 'WFR'; }
if ($t->{status} eq 'WFR' && !$isoper) { $t->{status} = 'OPN'; }
}
if ($query->param('problem') ne undef || $attachment ne undef) {
my $unm = $t->{name};
if ($cfg->get('askforname')) {
$unm = $query->param('respondername');
}
my $msg = "From: ".($isoper ? $cfg->get('_USER')->get('login') : $unm)."\nDate: ".time()."\nOperator: $isoper\n";
if ($isoper && $query->param('internal')) {
$msg .= "Internal: Yes\n";
}
$msg .= "IP: $ENV{REMOTE_ADDR}\n";
$msg .= "$attachment\n".substr($query->param('problem'),0,32*1024);
push @{$t->{messages}}, $msg;
$query->param(-name => 'problem', -value => '');
$notify = 1;
if ($isoper) {
TTXCommon::logit("RESPOND|".$t->{oper}."|".$t->{id});
}
}
if ($isoper && $query->param('transfer') ne undef && $query->param('transfer') ne $t->{oper}) {
TTXCommon::logit("TRANSFER|".$t->{oper}."|".$t->{id}."|".$query->param('transfer'));
if ($query->param('transfer') !~ /^\+/) {
$t->{oper} = $query->param('transfer');
$t->{status} = 'OPN' if $cfg->get('transferopens');
transfernotice({cfg => $cfg, ticket => $t});
} elsif($cfg->get('usegrpsel')) {
$t->{grp} = $query->param('transfer');
TTXGroups::grptransfer({cfg => $cfg, ticket => $t});
}
}
$t->{updated} = time();
if ($t->{status} eq 'CLS') {
$t->{closed} = $t->{updated};
if ($isoper) {
TTXCommon::logit("CLOSE|".$t->{oper}."|".$t->{id});
if ($cfg->get('report') ne undef) {
eval "use TTXEReport";
if ($@ eq undef) {
TTXEReport::reportclose($cfg, $t);
}
}
}
}
$tickets->save();
if ($t->{status} eq 'PND' && $isoper) {
$query->param(-name => 'do', -value => '');
# $query->param(-name => 'tid', -value => $t->{id});
my $oper = $cfg->get('_USER')->get('login');
if (!($cfg->get('demo') && $oper ne 'admin') &&
($cfg->get('grant.delete') eq undef || grep(/^$oper$/, split(/,/, $cfg->get('grant.delete'))))) {
$data->{DELTICKET} = '&nbsp;&nbsp;<input type=submit onsubmit name=delete onclick="return confirmdel()" value="[%Delete ticket%]">';
}
# usernotify({cfg => $cfg, ticket => $t}) if $notify && !($isoper && $query->param('internal'));
$cmd = 'claim';
}
}
}
$tickets = undef;
if ($isoper && invenabled()) {
$data->{INVENTORYROW} = TTXInvMod::invrow($cfg, $data, $t);
}
if (($t->{status} eq 'WFR' || $t->{status} eq 'CLS') && $isoper) {
$data->{NEWSTATUS} = "<input type=radio name=newstatus value=OPN";
if ($query->param('newstatus') eq 'OPN') { $data->{NEWSTATUS} .= ' checked'; }
$data->{NEWSTATUS} .= '> [%Open%]<br>'."\n";
}
if ($t->{status} eq 'OPN') {
$data->{NEWSTATUS} .= "<input type=radio name=newstatus value=WFR";
if ($query->param('newstatus') eq 'WFR') { $data->{NEWSTATUS} .= ' checked'; }
$data->{NEWSTATUS} .= '> [%Responded%]<br>'."\n";
}
if ($t->{status} ne 'CLS') {
$data->{NEWSTATUS} .= "<input type=radio name=newstatus value=CLS";
if ($query->param('newstatus') eq 'CLS') { $data->{NEWSTATUS} .= ' checked'; }
$data->{NEWSTATUS} .= '> [%Closed%]<br>'."\n";
}
if ($isoper) {
$data->{NEWSTATUS} .= '<br><input type=checkbox name=internal value=1';
if ($query->param('internal')) {
$data->{NEWSTATUS} .= ' checked';
}
$data->{NEWSTATUS} .= '> <span class=lbl>[%Internal%]</span><br>';
}
my $userid = $cfg->get('_USER')->{login} if $isoper;
if ($isoper && ($userid eq $t->{oper} || grep(/^$userid$/, split(/,/, $cfg->get('grant.assign'))))) {
my @operlist = TTXUser::list();
# if ($cfg->get('usegrpsel') && $cfg->get('accessctrl')) {
if ($cfg->get('usegrpsel')) {
my $rev;
eval '$rev = $TTXGroups::REVISION';
# if ($@ eq undef && $rev > 213) {
if ($@ eq undef && $rev > 231) {
TTXGroups::cleanoperlist($cfg, \@operlist, $t->{grp});
}
}
if (@operlist > 1) {
$data->{NEWSTATUS} .= '<br><table cellpadding=0 cellspacing=0><tr><td align=right><span class=lbl>[%Transfer to%]</span></td></tr>'."\n".
"<tr><td align=right><br class=tiny><select name=transfer>\n";
$data->{NEWSTATUS} .= "<option></option>\n";
foreach my $oper (sort @operlist) {
next if $oper eq $t->{oper};
$data->{NEWSTATUS} .= "<option value=$oper";
if ($query->param('transfer') eq $oper) {
$data->{NEWSTATUS} .= " selected";
}
$data->{NEWSTATUS} .= ">$oper</option>\n";
}
if ($cfg->get('usegrpsel')) {
TTXGroups::trselector($cfg, $data);
}
$data->{NEWSTATUS} .= "</select></td></tr></table>\n";
}
}
$data->{PAGEHEADING} = '[%Ticket%] #'.$t->{id};
$data->{TICKET_status} = TTXCommon::status($t->{status});
$data->{TICKET_subject} = $t->{subject};
$data->{TICKET_email} = $t->{email};
$data->{TICKET_name} = $t->{name};
$data->{TICKET_key} = $t->{key};
$data->{TICKET_open} = TTXCommon::tmtxt($t->{open});
$data->{TICKET_GROUP} = $cfg->get($t->{grp}) || '-';
$data->{TICKET_closed} = $t->{status} eq 'CLS' ? TTXCommon::tmtxt($t->{closed}):'-';
$data->{TICKET_oper} = $isoper ? $t->{oper}:(($t->{oper} eq undef) ? '[%not assigned%]':'[%assigned%]');
my @xvars = $cfg->vars();
@xvars = grep(/^x/, @xvars);
foreach my $xvar (@xvars) {
$data->{'TICKET_c'.$cfg->get($xvar)} = $t->{'c'.$cfg->get($xvar)};
if ($query->param('do') eq undef) {
$query->param(-name => $xvar, -value => $t->{'c'.$cfg->get($xvar)});
}
}
if ($cfg->get('tracktime') ne undef && $isoper) {
my $ttx = $cfg->get('tracktime');
if ($ttx !~ /[^0-9]/ && $ttx >= 0 && $ttx < $cfldcnt) {
my $tth = TTXCommon::cleanit($query, 'tracktimeh');
my $ttm = TTXCommon::cleanit($query, 'tracktimem');
$tth =~ s/"/&quot;/g; $ttm =~ s/"/&quot;/g;
$data->{TRACKTIME} = '<b>[%Time spent on preparing the response (hh:mm)%]</b>'."\n".
"<input type=text size=2 name=tracktimeh value=\"$tth\">:".
"<input type=text size=2 name=tracktimem value=\"$ttm\"><br><br class=tiny>";
}
}
if (!$isoper && $cfg->get('askforname')) {
if ($query->param('emailkey') ne undef && $query->param('emailkey') eq $t->{email}) {
if ($query->param('respondername') eq undef) {
$query->param(-name => 'respondername', -value => $t->{name});
}
}
my $nm = $query->param('respondername');
$nm =~ s/"/&quot;/g;
$data->{TRACKTIME} .= '<b>[%Your name%]:</b>&nbsp;&nbsp;'.
"\n<input type=text size=25 name=respondername value=\"$nm\"><br><br class=tiny>";
}
my %images;
my %names;
my $editlink;
if ($isoper) {
my $uid = $cfg->get('_USER')->get('login');
if ($cfg->get('grand.edit') eq undef || grep(/^$uid$/, split(/,/, $cfg->get('grand.edit')))) {
eval 'use TTXMsgEdit';
if ($@ eq undef) {
$editlink = 1;
}
}
}
my $mid = 0;
foreach my $msg (@{$t->{messages}}) {
my @msgparts = split(/\n\n/, $msg);
my $rawheader = shift @msgparts;
my $body = join("\n\n", @msgparts);
my @headerlines = split(/\n/, $rawheader);
chomp @headerlines;
my %header;
foreach my $line (@headerlines) {
if ($line =~ /^([a-zA-Z][a-zA-Z0-9-]*):\s*(.*)$/) {
$header{uc $1} = $2;
}
}
next if $header{OPERATOR} && $header{INTERNAL} =~ /Yes/ && !$isoper;
my $style;
if ($header{OPERATOR}) {
if ($header{INTERNAL} =~ /Yes/) {
$style = 'imsg';
} else {
$style = 'omsg'
}
} else {
$style = 'cmsg';
}
my $imgtag;
my $fromtag;
if ($header{OPERATOR}) {
if (!exists $images{$header{FROM}}) {
my $u = TTXUser->new($header{FROM});
if ($u eq undef) {
$images{$header{FROM}} = undef;
$names{$header{FROM}} = undef;
} else {
$images{$header{FROM}} = $u->{image};
$names{$header{FROM}} = $u->{fname}.' '.$u->{lname};
}
}
if ($images{$header{FROM}} ne undef) {
$imgtag = "<br><br class=sm><center><nobr>&nbsp;<img src=\"$images{$header{FROM}}\">&nbsp;</nobr></center><br class=sm>\n";
}
$fromtag = $names{$header{FROM}};
if ($isoper) { $fromtag .= " ($header{FROM})"; }
}
$fromtag = $header{FROM} if $fromtag eq undef;
$fromtag =~ s/</&lt;/g;
if ($isoper) {
if ($header{IP} ne undef) {
$fromtag .= "<br>[$header{IP}]";
}
}
if ($editlink ne undef) {
$editlink = "<br>".TTXMsgEdit::link($cfg, $t, $mid);
++$mid;
}
$data->{MESSAGES} .= "<tr>\n<td width=20% align=left valign=top class=$style>$fromtag<br>".TTXCommon::tmtxt($header{DATE})."$editlink$imgtag</td>\n";
$body =~ s/</&lt;/g;
$body = TTXMarkup::html($body);
$body =~ s/\n/<br>\n/g;
my $firstfile = 1;
for (my $i=1; $i < 4; ++$i) {
if ($header{"FILE$i"} ne undef) {
if ($firstfile) {
$body .= '<br class=sm><br class=sm>[%Attachments%]:<br>'."\n";
$firstfile = 0;
}
$header{"FILE$i"} =~ s/CGIURL/$ENV{SCRIPT_NAME}/;
$body .= $header{"FILE$i"} . "<br>\n";
}
}
$data->{MESSAGES} .= "<td align=left valign=top class=$style>$body</td>\n</tr>\n";
}
if (TTXData::get('ISPRO')) {
$data->{FILEFORMS} = TTXFile::fileforms();
}
if ($notify) {
if (!($isoper && $query->param('internal'))) {
usernotify({cfg => $cfg, ticket => $t,
from => $isoper ?
$cfg->get('_USER')->{fname}.' '.$cfg->get('_USER')->{lname} :
$query->param('respondername')});
if ($cfg->get('askforsurvey') && $t->{status} eq 'CLS') {
eval "use TTXSurvey";
TTXSurvey::ask($cfg, $t);
}
}
if (!$isoper) {
if ($t->{status} eq 'PND') {
if ($cfg->get('validate') eq undef || $t->{'c'.$cfg->get('validate')} eq 'Y') {
my $opernotifydata = {cfg => $cfg, ticket => $t};
if ($cfg->get('supervisor') ne undef) {
my @list = ($cfg->get('supervisor'));
$opernotifydata->{notifylist} = \@list;
} elsif ($cfg->get('usegrpsel')) {
my @list = split(/;/, $cfg->get("mbr-".$t->{grp}));
$opernotifydata->{notifylist} = \@list;
} elsif ($cfg->get('routex') ne undef) {
eval "use TTXCustomRoute";
if ($@ eq undef) {
my @list = TTXCustomRoute::routelist($cfg, $t);
$opernotifydata->{notifylist} = \@list;
}
}
opernotify($opernotifydata);
}
} else {
opernotify({cfg => $cfg, ticket => $t});
}
} elsif ($t->{oper} ne undef && $cfg->get('_USER')->{login} ne $t->{oper}) {
opernotify({cfg => $cfg, ticket => $t});
}
}
return $cmd;
}
1;
#