This commit is contained in:
biosvos
2026-08-07 17:38:18 +09:00
commit 873193a243
9613 changed files with 2755992 additions and 0 deletions
+558
View File
@@ -0,0 +1,558 @@
###
# $Id: CSV.pm,v 1.10 2001/08/19 01:42:33 christopher Exp $
#
# Distributed under the GNU Lesser General Public License v2.1. See the
# accompanying lgpl.txt file for the license text; if the file was missing
# you may always obtain a copy from http://www.fsf.org/.
#
# 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.
#
# Copyright (c)2001 Christopher Rath <Christopher@Rath.ca> and
# Mark Mielke <Mark@Mielke.cc>
###
###
# POD starts.
#
=head1 NAME
CSV.pm - a module providing manipulation routines for comma separated value (CSV) records
=head1 SYNOPSIS
use CSV;
%fieldLayout = CSVinit($firstRecord);
if (! CSVvalidate(%CSVfields, I<field list>)) {
die "Fields missing."};
}
while (<INPUT>) {
@record = CSVsplit($_);
I<process the records>;
}
=head1 LICENSE
Copyright (c)2001 Christopher Rath <C<Christopher@Rath.ca>> and Mark Mielke
<C<Mark@Mielke.cc>>.
Distributed under the GNU Lesser General Public License v2.1. See the
accompanying C<lgpl.txt> file for the license text; if the file was missing you
may always obtain a copy from C<http://www.fsf.org/>.
=head1 WARRANTY
This program is distributed in the hope that it will be useful, but B<without
any warranty>; without even the implied warranty of B<merchantability> or
B<fitness for a particular purpose>. See the GNU General Public License for
more details.
=head1 DESCRIPTION
This module defines some functions for reading comma separated value (CSV)
files (e.g., Remedy-ARS generated files). The module also allows some a
delimiter other than a comma to be used, or a selection of delimiters to be
used (e.g., comma and semicolon).
The B<CSVinit(>I<$firstRecord>B<)> function is used to parse the initial record
of a CSV file; which by definition will contain the field names for each field
in the CSV records which follow in the file. This initial record is itself a
CSV record.
The B<CSVvalidate(>I<\%output_from_CSVinit>B<,> <I<field_list>>B<)> function
is used to verify that the incoming file contains the full list of fields
specified in the I<field_list> provided to the function.
The B<CSVsplit(>I<$rawRecord>B<)> function splits a line, passed as
I<$rawRecord> (a CSV record), and returns it split into fields; sort-of like
B<split()>.
The B<$CSV::Delimiters> variable can be set to specify an alternate, or set of
alternate, field delimiters. In general, it should be specified as a B<local>.
The B<CSVjoin(>I<@fields_to_join>B<)> function takes an array of fields and
turns them into a comma separated value record. If B<$CSV::Delimiters> has
been used to specify multiple delimiters then B<CSVjoin()> will use the first
delimiter of the set for creation of CSV records.
=head1 USAGE
A sample application (Demo_App) of this module has been provided in order to
demonstrate how it can be used. Some additional usage notes follow.
=head2 CSV::Delimiters
local $CSV::Delimiters = ",;";
%fieldLayout = CSVinit($firstRecord);
@Fields = CSVsplit($aRawRecord);
This will cause either of 'B<,>' or 'B<;>' to be valid delimiters, even if
mixed. B<local()> is used to temporarily override the value, instead of
permanently overriding the value.
B<CSVjoin()> will prefer the first character in the Delimiters string, or the old
behaviour of a ',' if the Delimiters string is not defined.
If you peek at the code, it actually implements the split core twice. The
first with B<$CSV::Delimiters>, and the second with 'B<,>' hard-coded. This is
to maintain efficiency for code that does not make use of a dynamic set of
delimiter characters.
=head2 CSVinit()
B<CSVinit()> is used to initialize the data structures for further CSV parsing.
The function scans the input record passed to it. If it contains data, then
that data is used to define the field titles. If no data is passed then some
default column data is used instead. The function returns an associative array
containing field names and the corresponding field number.
=head3 Parameters
[1] $rawRecord - Record defining field layouts.
=head3 Returns
Returns an associative array of field layout.
=head2 CSVvalidate()
B<CSVvalidate()> is used to validate a set of field names. A list of fields is
validated against the associative array previously built by a call to
CSVinit(). Returns true or false.
=head3 Parameters
[1] \%fields - the fields as built by CSVinit(). (reference)
[?] $... - a list of field names to check.
=head3 Returns
Returns 0 if any single field is not found in %fields; otherwise 1.
=head2 CSVjoin()
B<CSVjoin()> is used to join CSV data.
=head3 Parameters
Context 1:
[1] \@fields - An array of fields to join into a CSV.
[2] "minimum"|"quoteall" - Defaults to "minimum", define
whether fields must be quoted when not req'd.
Context 2:
[?] $... - An array of fields to join into
a CSV.
=head3 Returns
Returns a string which may be "un"join'ed using CSVsplit().
except in the case of a newline contained within a field)
=head2 CSVsplit()
B<CSVsplit> is used to split CSV data, just like Perl's own split() does.
=head3 Parameters
[1] $rawRecord - the record to split.
=head3 Returns
Returns an array of values split out of $rawRecord.
=head1 TESTING
Put the following lines into a file to test the comma-based parsing of this
module:
#!/usr/bin/perl -w
use CSV;
while (<DATA>) {
print join(":", CSVsplit($_)), "\n";
}
__DATA__
"One from FAQ will do","sec""ond"
"But, not","3rd""","or","""fifth"
"don't","forget","fourth"",""","and" , """,""sixth".
"Of course, it doesn't solve",everything,8,N,1
"Is there a new emacs perl-mode?"
"Tom","tom@fiction.org"
Empty fields needed,,"and "wanted
Some,"",boundary ",cases"", ,too
Grok this\, Spok!
"Didn't you notice\! in it \{the spec\}"
"Multi-
line",test
This will produce the following output:
One from FAQ will do:sec"ond
But, not:3rd":or:"fifth
don't:forget:fourth",":"and" : """:""sixth".
Of course, it doesn't solve:everything:8:N:1
Is there a new emacs perl-mode?
Tom:tom@fiction.org
Empty fields needed::"and "wanted
Some::boundary ":cases"": :too
Grok this\: Spok!
Didn't you notice\! in it \{the spec\}
"Multi-
line":test
=head1 CSV SPECIFICATION
This section attempts to define CSV records and files in a fairly rigorous
fashion. The point behind this is to make this module usable without having to
read and understand the source code.
=head2 CSV Records
The basic idea behind a CSV record is this: literal field values are
delimited by commas. The immediate complication that arises is, of
course, ``What should be done when a comma must appear within a
field?'' Within the bounds of current practice, there are two
immediate solutions to this complication:
=over 4
=item 1.
Use a predefined escape character to tag commas which appear within fields.
=item 2.
Allow quotation marks to enclose a field and _protect_ a comma appearing within
a field.
=back
As with all work-arounds, these "immediate solutions" have complications of
their own (these secondary complications are numbered the same as their primary
counterparts):
=over 4
=item 1.
Escape characters must themselves be escaped in order to appear as a value
within a field (e.g., if a literal comma is expressed as ``\,'', then a literal
backslash must appear as ``\\'').
=item 2.
Quotation marks must somehow be protected if they are to appear as a literal
character within a field.
=back
Given that the essence of CSV files is simplicity, I have decided to reject
I<all> escape and escaped characters with the exception of quoation marks
appearing within quotation marks. That is, the case of the escaped comma has
been rejected from this specification.
Within the context of Perl, the L<string(3)> library and the UNIX shells, an
additional level of complexity is added to this equation when we begin to ask,
``What is the meaning or significance of whitespace within a CSV record?'' The
meaning of whitespace is a key technical detail which must be accounted for in
both the specification and its implementation; otherwise, everyone's
implementation will produce semi-random results based upon that implementors
opinion regarding whitespace.
=head2 Semi-Formal CSV Record Specification
This specification uses the syntax described in S<Appendix A> of the first
edition of O'Reilly's Programming Perl book (i.e., the S<Perl 4> camel book).
CSV_RECORD ::= (* FIELD DELIM *) FIELD REC_SEP
FIELD ::= QUOTED_TEXT | TEXT
DELIM ::= `,'
REC_SEP ::= `\n'
TEXT ::= LIT_STR | ["] LIT_STR [^"] | [^"] LIT_STR ["]
LIT_STR ::= (* LITERAL_CHAR *)
LITERAL_CHAR ::= NOT_COMMA_NL
NOT_COMMA_NL ::= [^,\n]
QUOTED_TEXT ::= ["] (* NOT_A_QUOTE *) ["]
NOT_A_QUOTE ::= [^"] | ESCAPED_QUOTE
ESCAPED_QUOTE ::= `""'
=head2 Notes
This specification does not grant any special status to whitespace characters.
This means that B<I<all whitespace is part of some field value.>>
The B<TEXT> non-terminal is attempting to express the cases where quotation
marks exist but do not completely encapsulate the field value; in cases like
this, the quotation marks should be treated as literal characters making up
part of the field value.
One ambiguity exist in this specification that I have been unable to properly
express. The case of a field with the value ,abc""de,. Should the double
quotation marks be treated as an escaped quotation mark or as two quotation
marks? I believe that occurences of "" should be treated as escaped quotation
marks I<only> within a quoted string.
The B<LITERAL_CHAR> non-terminal exists partially as a place-holder. Escaped
characters may be easily accomadated by this specification at a later date by
OR-ing them to the right side of B<LITERAL_CHAR>.
Some of the non-terminals exist solely as documentation/reading aids. The
B<NOT_A_COMMA_NL> is one example of this case; its name helps express the
meaning of the regex (which should assist other readers of this document to
detect errors in the specification).
The B<ESCAPED_QUOTE> non-terminal includes the PASCAL-like case of ``""'' and
excludes the more traditional UNIX ``\\"''. This is not my preference; I have
included it here because I know there exists at least one commercial tool that
produces CSV records containing the PASCAL-like construct and not the UNIX-like
one.
=head1 AUTHORS
Christopher Rath (C<christopher@rath.ca>) wrote the CSV specification and
everything in the module except the essential snippet of code that actually
does the work :).
Mark Mielke (C<mark@mielke.cc>) took the specification and wrote the essential
piece of code that actually breaks the CSV records into its constituent fields.
He also took the initial .pl version and .pm'ed it (this only makes sense,
since this module is only usable in perl5).
=head1 BUGS
=head2 Not Thread-Safe
This module, and hence B<CSVinit()>/B<CSVsplit()>, is not thread-safe or
re-entrant.
=head2 Fields Spanning Lines
This module currently fails in one of the test-cases, although the test output
listed herein, above, has been constructed to show the actual output of this
module, as opposed to the correct output:
"Multi-
line",test
This is due to the fact that perl is reading one line at a time with:
while (<DATA>) { ... }
So the first line is read ("Multi-) and evaluated. The _second_ time around the
loop the second line (line",test) is read and evaluated. There is no
workaround available, this is simply a limitation of the module.
=head1 VERSION
The RCS identifier for this module is
S<$Id: CSV.pm,v 1.10 2001/08/19 01:42:33 christopher Exp $>.
=cut
#
# End of POD.
###
package CSV;
require 5.000;
require Exporter;
$VERSION = 2.00;
@ISA = qw(Exporter);
@EXPORT = qw(CSVinit CSVvalidate CSVjoin CSVsplit);
use strict;
$CSV::Delimiters = undef;
###
# Setup Variables.
#
# CSVDefaultColumnMapping - this contains a dummy record; just in case the
# user calls us with nothing.
#
my(%CSVDefaultColumnMapping) = ("" => -1);
###
# CSVinit() - initialize data structures for further CSV parsing.
#
# This function scans the input record passed to it. If it contains data, then
# that data is used to define the field titles. If no data is passed then some
# default column data is used instead. The function returns an associative
# array containing field names and the corresponding field number.
#
# Parameters;
# [1] $rawRecord - Record defining field layouts.
#
# Returns:
# Associative array of field layout.
###
sub CSVinit
{
my @fields = CSVsplit(@_);
my %columns;
my $i = 0;
if ($#fields >= 0) {
# Build associative array with field -> column_number mapping.
map { $columns{$_} = $i++ } @fields;
%columns;
} else {
%CSVDefaultColumnMapping;
}
}
###
# CSVvalidate() - validate the field names passed in.
#
# A list of fields is validated against the associative array previously built
# by a call to CSVinit(). Returns true or false.
#
# Parameters:
# [1] \%fields - the fields as built by CSVinit(). (reference)
# [?] $... - a list of field names to check.
#
# Returns:
# 0 if any single field is not found in %fields; otherwise 1.
###
sub CSVvalidate
{
my $fields = shift; # pass by reference!
my $field;
foreach $field (@_) {
exists $fields->{$field} || return 0;
}
1;
}
###
# CSVjoin() - join CSV data.
#
# Parameters:
# Context 1:
# [1] \@fields - An array of fields to join into a CSV.
# [2] "minimum"|"quoteall" - Defaults to "minimum", defines
# whether fields must be quoted when not req'd.
# Context 2:
# [?] $... - An array of fields to join into a CSV.
#
# Returns:
# returns a string which may be "un"join'ed using CSVsplit().
# (except in the case of a newline contained within a field)
###
sub CSVjoin
{
my($fields, $mode) = ref($_[0]) ? @_ : \@_;
my($quoteall, @quotedfields, $quotedfield);
local $_;
$mode = 'minimum' if !defined($mode);
$quoteall = ($mode eq 'quoteall') ? 1 : 0;
foreach (@$fields) {
if ($quoteall || /[\",\n]/) {
($quotedfield = $_) =~ s/\"/""/g;
push(@quotedfields, qq{"$quotedfield"});
} else {
push(@quotedfields, $_);
}
}
join((defined($CSV::Delimiters) ? substr($CSV::Delimiters,0,1) : ','),
@quotedfields);
}
###
# CSVsplit() - split CSV data, just like Perl's own split() does.
#
# See description of record layout at top of this module.
#
# Parameters:
# [1] $rawRecord - the record to split.
#
# Returns:
# An array of values split out of $rawRecord.
###
sub CSVsplit
{
local $_ = $_[0];
my(@fields, $t);
# According to the specs, a new-line is a field terminator not a field
# delimiter. This only becomes an issue at the end of a string where
# a new-line implies end of field, not a field delimiter. By stripping
# the last optional new-line we allow all remaining new-lines to be
# considered field delimiters.
chomp;
###
# Only build the array if at least one field exists. (if at least one
# character exists, by definition, at least one field exists)
#
if (length($_) > 0) {
###
# Break the record into fields.
# Field Delimiter == /[,\n]/ (See comment above: According...)
my $expecting;
if (defined $CSV::Delimiters) {
while (m`(?=.)((?:"((?:""|[^"]+)*)")?([^$CSV::Delimiters]*))([$CSV::Delimiters]?)`sg) {
$expecting = $4;
if (defined($2) && !length($3)) {
($t = $2) =~ s/""/\"/g;
push(@fields, $t);
} else {
push(@fields, $1);
}
}
} else {
while (m`(?=.)((?:"((?:""|[^"]+)*)")?([^,]*))(,?)`sg) {
$expecting = $4;
if (defined($2) && !length($3)) {
($t = $2) =~ s/""/\"/g;
push(@fields, $t);
} else {
push(@fields, $1);
}
}
}
push(@fields, '') if $expecting;
}
@fields;
}
1;
###
# End of package.
###
# Local Variables:
# fill-column: 79
# End:
File diff suppressed because it is too large Load Diff
+192
View File
@@ -0,0 +1,192 @@
package TTXBarChart;
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2005, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 186 $
# $Date: 2006-06-21 07:47:49 -0400 (Wed, 21 Jun 2006) $
#
$TTXBarChart::VERSION='2.22';
BEGIN {
$TTXBarChart::REVISION = '$Revision: 186 $';
if ($TTXBarChart::REVISION =~ /(\d+)/) {
$TTXBarChart::REVISION = $1;
}
};
use strict;
use TTXData;
my %defaults = (
barwidth => 20,
barheight => 15,
chartwidth => 200,
chartheight => 100,
barcolor => 'blue',
fontratio => 0.4
);
# ========================================================================= vbar
sub vbar {
my ($data, $barwidth, $chartheight, $barcolor, $fratio) = @_;
my $buff;
my $cfg = TTXData::get('CONFIG');
my $img = $cfg->get('imgurl')."/dot.gif";
if (!$barwidth || $barwidth =~ /\D/) {
$barwidth = $defaults{barwidth};
}
if (!$chartheight || $chartheight =~ /\D/) {
$chartheight = $defaults{chartheight};
}
if ($barcolor eq undef) {
$barcolor = $defaults{barcolor}
}
if ($fratio eq undef) {
$fratio = $defaults{fontratio}
}
my $lblstyle = "style=\"font-size: ".(int ($barwidth*$fratio))."px\"";
my $valstyle = "style=\"font-size: ".(int ($barwidth*$fratio) - 1)."px;font-family:serif\"";
$buff =<<EOT;
<table cellpadding=0 cellspacing=1>
<tr>
EOT
my $max = 0;
for (my $i = 0; $i < @{$data}; ++$i) {
if ($data->[$i]->{val} eq undef || $data->[$i]->{val} < 0) {
$data->[$i]->{val} = 0;
}
if ($data->[$i]->{val} > $max) {
$max = $data->[$i]->{val};
}
}
for (my $i = 0; $i < @{$data}; ++$i) {
my $h=1;
if ($max) {
$h = int (($data->[$i]->{val} / $max) * $chartheight);
}
my $alt = $data->[$i]->{val};
my $v = $alt;
if ($v > 9999) {
if ($v < 1000000) {
$v = (int ($v/1000)).'K';
} else {
$v = (int ($v/1000000)).'M';
}
}
$buff .= <<EOT;
<td valign=bottom>
<table cellpadding=0 cellspacing=0>
<tr>
<td align=center $valstyle>$v</td>
</tr>
<tr bgcolor="$barcolor">
<td><img src="$img" width=$barwidth height=$h alt=$alt /></td>
</tr>
</table>
</td>
EOT
}
$buff .= "</tr>\n<tr>";
for (my $i = 0; $i < @{$data}; ++$i) {
my $lbl = $data->[$i]->{lbl};
if ($lbl =~ /^(..?.?)/) {
$lbl = $1;
} else {
$lbl = '&nbsp;';
}
$buff .= "<td valign=top align=center $lblstyle>$lbl</td>\n";
}
$buff .=<<EOT;
</tr>
</table>
EOT
return $buff;
}
# ========================================================================= hbar
sub hbar {
my ($data, $barheight, $chartwidth, $barcolor, $fratio, $percentage) = @_;
my $buff;
my $cfg = TTXData::get('CONFIG');
my $img = $cfg->get('imgurl')."/dot.gif";
if (!$barheight || $barheight =~ /\D/) {
$barheight = $defaults{barheight};
}
if (!$chartwidth || $chartwidth =~ /\D/) {
$chartwidth = $defaults{chartwidth};
}
if ($barcolor eq undef) {
$barcolor = $defaults{barcolor}
}
if ($fratio eq undef) {
$fratio = $defaults{fontratio}
}
my $lblstyle = "style=\"font-size: ".(int ($barheight*$fratio))."px\"";
my $valstyle = "style=\"font-size: ".(int ($barheight*$fratio) - 1)."px;font-family:serif\"";
$buff =<<EOT;
<table cellpadding=0 cellspacing=1>
EOT
my $max = 0;
my $total;
for (my $i = 0; $i < @{$data}; ++$i) {
if ($data->[$i]->{val} eq undef || $data->[$i]->{val} < 0) {
$data->[$i]->{val} = 0;
}
if ($data->[$i]->{val} > $max) {
$max = $data->[$i]->{val};
}
$total += $data->[$i]->{val};
}
for (my $i = 0; $i < @{$data}; ++$i) {
my $w=1;
if ($max) {
$w = int (($data->[$i]->{val} / $max) * $chartwidth);
}
my $alt = $data->[$i]->{val};
my $v = $alt;
if ($v > 9999) {
if ($v < 1000000) {
$v = (int ($v/1000)).'K';
} else {
$v = (int ($v/1000000)).'M';
}
}
my $lbl = $data->[$i]->{lbl};
if ($lbl eq undef) {
$lbl = '&nbsp;';
}
if ($percentage && $total) {
$v .= ' &nbsp;('.(int (100 * $alt / $total)).'%)';
}
$buff .= <<EOT;
<tr>
<td valign=middle align=right $lblstyle>$lbl</td>
<td valign=middle align=left>
<table cellpadding=0 cellspacing=0>
<tr>
<td align=left valign=middle>
<table cellpadding=0 cellspacing=0>
<tr bgcolor="$barcolor">
<td><img src="$img" width=$w height=$barheight alt=$alt /></td>
</tr>
</table>
</td>
<td align=left valign=middle>
<span $valstyle>&nbsp;$v</span>
</td>
</tr>
</table>
</td>
</tr>
EOT
}
$buff .= "</table>\n";
return $buff;
}
1;
#
+190
View File
@@ -0,0 +1,190 @@
package TTXCache;
#
# This is an optional Cache module for
# Trouble Ticket Express help desk package.
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2005, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 156 $
# $Date: 2006-05-05 03:02:47 -0400 (Fri, 05 May 2006) $
#
$TTXCache::VERSION='2.22';
BEGIN {
$TTXCache::REVISION = '$Revision: 156 $';
if ($TTXCache::REVISION =~ /(\d+)/) {
$TTXCache::REVISION = $1;
}
};
use strict;
use TTXCommon;
use TTXData;
use Digest::MD5 qw(md5_hex);
my $useencode = 0;
#
# constants
#
my $cacheidxfn = 'cache.cgi';
my $cachedir = 'cache';
my $maxage = 180; # seconds
my $nolog = 1;
my $serial;
# ==================================================================== signature
sub signature {
my $query = $_[0];
my $str;
foreach my $key (sort $query->param) {
$str .= $key.'='.$query->param($key);
}
if (!$useencode) {
eval "use Encode";
$useencode = 1 if $@ eq undef;
}
if ($useencode) {
return md5_hex(Encode::encode_utf8($str));
}
my $sig = '-';
eval '$sig = md5_hex($str)';
return $sig if $@ eq undef && $sig ne '-';
return undef;
}
# ======================================================================== store
sub store {
my ($cfg, $query, $pg, $pgsig) = @_;
my $pgsid = $query->param('sid');
$pgsid = 0 if $pgsid eq undef;
my $pgcmd = $query->param('cmd');
my $idxfn = $cfg->get('basedir')."/$cacheidxfn";
if (! -e $idxfn) {
if (open(IDX, ">$idxfn")) {
flock(IDX,2);
print IDX "0\n";
$serial = 0;
close IDX;
} else {
return;
}
}
if (! -d $cfg->get('basedir')."/$cachedir") {
mkdir $cfg->get('basedir')."/$cachedir", 0777;
}
if (open(IDX, "+<$idxfn")) {
flock IDX,2;
my @pages;
my @buff = <IDX>;
chomp @buff;
my $curtm = time();
my $purgetm = $curtm - $maxage;
my $sn = shift @buff;
if ($sn ne undef && $serial ne undef && $sn ne $serial) {
close IDX;
return;
}
foreach my $line (@buff) {
my ($tm, $cmd, $sid, $sig, $n) = split(/-/, $line);
if ($tm < $purgetm || "$cmd-$sid-$sig" eq "$pgcmd-$pgsid-$pgsig") {
unlink $cfg->get('basedir')."/$cachedir/$tm-$n.cgi";
next;
}
push (@pages, "$tm-$cmd-$sid-$sig-$n");
}
my $n = 0;
while (-e $cfg->get('basedir')."/$cachedir/$curtm-$n.cgi") {
++$n;
return if $n > 100; # endless loop control, just to make sure
}
push (@pages, "$curtm-$pgcmd-$pgsid-$pgsig-$n");
if (!open(PG, ">".$cfg->get('basedir')."/$cachedir/$curtm-$n.cgi")) {
close IDX;
return;
}
seek IDX,0,0;
print IDX "$serial\n";
foreach my $p (@pages) {
print IDX "$p\n";
}
truncate(IDX, tell (IDX));
close IDX;
print PG $pg;
close PG;
}
}
# ========================================================================== hit
sub hit {
my ($cfg, $query) = @_;
my $pgsig = signature($query);
my $pgsid = $query->param('sid');
$pgsid = 0 if $pgsid eq undef;
my $pgcmd = $query->param('cmd');
my $idxfn = $cfg->get('basedir')."/$cacheidxfn";
if (open(IDX, "$idxfn")) {
my @buff = <IDX>;
close IDX;
chomp @buff;
my $curtm = time();
my $purgetm = $curtm - $maxage;
$serial = shift @buff;
foreach my $line (@buff) {
my ($tm, $cmd, $sid, $sig, $n) = split(/-/, $line);
next if $tm < $purgetm || "$cmd-$sid-$sig" ne "$pgcmd-$pgsid-$pgsig";
return "$tm-$n";
}
}
return 0;
}
# ========================================================================= page
sub page {
my ($cfg, $pgid) = @_;
if (open(PG, $cfg->get('basedir')."/$cachedir/$pgid.cgi")) {
my @buff = <PG>;
close PG;
return join('', @buff);
}
return undef;
}
# ======================================================================== purge
sub purge {
my $cfg = TTXData::get('CONFIG');
my $idxfn = $cfg->get('basedir')."/$cacheidxfn";
if (open(IDX, "+<$idxfn")) {
flock IDX,2;
my @buff = <IDX>;
chomp @buff;
foreach my $line (@buff) {
my ($tm, $cmd, $sid, $sig, $n) = split(/-/, $line);
unlink $cfg->get('basedir')."/$cachedir/$tm-$n.cgi";
}
seek IDX,0,0;
++$serial;
print IDX "$serial\n";
truncate(IDX, tell (IDX));
close IDX;
}
logit('P');
}
# ======================================================================== logit
sub logit {
return if $nolog;
my $cfg = TTXData::get('CONFIG');
my $fn = $cfg->get('basedir')."/ttxcachelog.txt";
if (open(CACHELOG, ">>$fn")) {
flock(CACHELOG,2);
seek(CACHELOG, 0, 2);
print CACHELOG time()."|$_[0]\n";
close CACHELOG;
}
}
1;
#
+282
View File
@@ -0,0 +1,282 @@
package TTXCommon;
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2002-2005, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 286 $
# $Date: 2006-10-17 11:52:21 +0400 (Tue, 17 Oct 2006) $
#
$TTXCommon::VERSION='2.22';
BEGIN {
$TTXCommon::REVISION = '$Revision: 286 $';
if ($TTXCommon::REVISION =~ /(\d+)/) {
$TTXCommon::REVISION = $1;
}
};
use strict;
require TTXData;
require TTXDictionary;
my %id2name = (
PND => 'Pending',
OPN => 'Open',
WFR => 'Responded',
'(OPN|WFR)' => 'Active',
'(PND|OPN|WFR)' => 'Not solved',
'(OPN|PND)' => 'Hot',
CLS => 'Solved'
);
my @week = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
# ====================================================================== cfldcnt
sub cfldcnt {
my $cnt = 10;
my $cfg = TTXData::get('CONFIG');
if ($cfg ne undef) {
my $n = int ($cfg->get('cfldcnt'));
if ($n > 10 && $n <= 100) {
$cnt = $n;
}
}
return $cnt;
}
# ======================================================================== logit
sub logit {
my $cfg = TTXData::get('CONFIG');
my $fn = $cfg->get('basedir')."/ttxlog.txt";
if (open(TTXLOG, ">>$fn")) {
flock(TTXLOG,2);
seek(TTXLOG, 0, 2);
print TTXLOG time()."|$_[0]\n";
close TTXLOG;
}
}
# ======================================================================== tmtxt
sub tmtxt {
return "-" if !$_[0];
my $cfg = TTXData::get('CONFIG');
my $tz = $cfg->get('timezone') * 60;
my $tm = $_[0] + $tz;
my ($sec,$min,$hour,$mday,$mon,$year, $wday) = gmtime($tm);
my ($sec1,$min1,$hour1,$mday1,$mon1,$year1) = gmtime(time() + $tz);
my $date;
my $wkday;
if ($cfg->get('time.weekday')) {
$wkday = TTXDictionary::translate($week[$wday]).' ';
}
if ($year != $year1 || $cfg->get('time.long')) {
$year += 1900; $year =~ s/^\d\d//;
$mon++; $mon = "0$mon" if $mon < 10;
$mday = "0$mday" if $mday < 10;
$date = $wkday . ($cfg->get('etime') ? "$mday/$mon/$year" : "$mon/$mday/$year");
} elsif ($mon != $mon1 || $mday != $mday1) {
$mon++; $mon = "0$mon" if $mon < 10;
$mday = "0$mday" if $mday < 10;
$date = $wkday . ($cfg->get('etime') ? "$mday/$mon" : "$mon/$mday");
}
$date .= " " if $date ne undef;
$hour = "0$hour" if $hour < 10;
$min = "0$min" if $min < 10;
$date .= "$hour:$min";
return $date;
}
# ======================================================================== dbtik
sub dbtik {
my $cfg = TTXData::get('CONFIG');
return undef if $cfg eq undef;
if ($cfg->get('dbmode') eq undef || $cfg->get('dbmode') eq 'plaintext') {
eval "use TTXFileTickets";
return TTXFileTickets->new();
} elsif ($cfg->get('dbmode') eq 'mysql') {
eval "use TTXMySQLTickets";
return TTXMySQLTickets->new();
} elsif ($cfg->get('dbmode') eq 'mssql') {
eval "use TTXMSSQLTickets";
return TTXMSSQLTickets->new() if !$@;
}
return TTXTickets->new();
}
# ======================================================================= status
sub status {
return $id2name{$_[0]};
}
# ====================================================================== cleanit
sub cleanit {
my ($query, $input) = @_;
my $val = $query->param($input);
$val =~ s/^\s+//;
$val =~ s/\s+$//;
$query->param(-name => $input, -value => $val);
return $val;
}
# ======================================================================== blank
sub blank {
my ($cfg, $query, $data) = @_;
return undef;
}
# ===================================================================== cfldscnt
sub cfldscnt {
my @list = grep(/^x/, $_[0]->vars());
my @editable = split(/;/, $_[0]->get('editablefields'));
my $cnt = 0;
foreach my $id (@list) {
my $cid = $_[0]->get($id);
next if $cid !~ /^\d\d?$/;
$cid = "c$cid";
++$cnt if grep(/^$cid$/, @editable);
}
return $cnt;
}
# =================================================================== tickedvars
sub tickedvars {
my ($cfg, $data) = @_;
$data->{TICKEDHEIGHT} = 250 + cfldscnt($cfg) * 30;
if ($cfg->get('editclosedate')) {
$data->{TICKEDHEIGHT} += 50;
}
if ($data->{TICKEDHEIGHT} > 600) {
$data->{TICKEDHEIGHT} = 600;
}
}
my @months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
# ===================================================================== pickdate
sub pickdate {
my ($query, $pref, $start) = @_;
my $buff;
my $year = $query->param($pref.'year');
my $mon = $query->param($pref.'mon');
my $day = $query->param($pref.'day');
if ($year =~ /\D/ || $year > 137) {
$year = '';
}
if ($mon =~ /\D/ || $mon > 11) {
$mon = '';
}
if ($day =~ /\D/ || $day > 31) {
$day = '';
}
if ($year eq '') {
$mon = '';
$day = '';
} else {
if ($mon eq '') {
$mon = $start ? 0:11;
$day = $start ? 1:31;
} elsif ($day eq '') {
if ($start) {
$day = 1;
} else {
my @daysmo = (31, ($year % 4) ? 28:29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
$day = $daysmo[$mon];
}
}
}
$query->param(-name => $pref.'year', -value => $year);
$query->param(-name => $pref.'mon', -value => $mon);
$query->param(-name => $pref.'day', -value => $day);
$buff .= "<select name=$pref"."day>\n<option></option>\n";
for (my $i = 1; $i < 32; ++$i) {
$buff .= '<option';
$buff .= ' selected' if $day == $i;
$buff .= ">$i</option>\n";
}
$buff .= "</select>\n<select name=$pref"."mon>\n<option></option>\n";
for (my $i = 0; $i < 12; ++$i) {
$buff .= "<option value=$i";
$buff .= ' selected' if $mon ne '' && $mon == $i;
$buff .= '>[%'.$months[$i]."%]</option>\n";
}
$buff .= "</select>\n<select name=$pref"."year>\n<option></option>\n";
my $baseyr = $year;
my $thisyr = (gmtime())[5];
if ($baseyr eq '') {
$baseyr = $thisyr;
}
my $cfg = TTXData::get('CONFIG');
my $yrsback;
if ($cfg->get('startyear') ne undef) {
$yrsback = $baseyr - $cfg->get('startyear');
}
$yrsback = 5 if $yrsback eq undef;
for (my $i = $baseyr-$yrsback; $i <= $thisyr; ++$i) {
my $yr = $i;
next if $yr < 0;
$buff .= "<option value=$yr";
$buff .= ' selected' if $year ne '' && $year == $yr;
$buff .= '>'.($yr+1900)."</option>\n";
}
$buff .= "</select>\n";
return $buff;
}
# ================================================================== checkdrange
sub checkdrange {
my ($query, $start, $end) = @_;
my $year = $query->param($start.'year');
return if $year eq undef;
my $mon = $query->param($start.'mon');
my $day = $query->param($start.'day');
my $year1 = $query->param($end.'year');
my $mon1 = $query->param($end.'mon');
my $day1 = $query->param($end.'day');
if ($mon eq undef || $mon =~ /\D/ || $mon > 11) {
$mon = 0;
$day = 1;
} elsif ($day =~ /\D/ || !$day) {
$day = 1;
} else {
my @daysmo = (31, ($year % 4) ? 28:29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
$day = $daysmo[$mon] if $day > $daysmo[$mon];
}
if ($year1 eq undef || $year1 =~ /\D/) {
$year1 = $year;
}
if ($mon1 eq undef || $mon1 =~ /\D/ || $mon1 > 11) {
$mon1 = 11;
$day1 = 31;
} else {
if ($day1 =~ /\D/ || !$day1) {
$day1 = 31;
}
my @daysmo = (31, ($year1 % 4) ? 28:29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
$day1 = $daysmo[$mon1] if $day1 > $daysmo[$mon1];
}
eval "use Time::Local";
if ($@ eq undef) {
my $stm = Time::Local::timegm(0,0,0,$day,$mon,$year);
my $etm = Time::Local::timegm(59,59,23,$day1,$mon1,$year1);
if ($etm < $stm) {
$etm = $stm + 24*3600;
}
($day, $mon, $year) = (gmtime($stm))[3,4,5];
($day1, $mon1, $year1) = (gmtime($etm))[3,4,5];
}
$query->param(-name => $start.'year', -value => $year);
$query->param(-name => $start.'mon', -value => $mon);
$query->param(-name => $start.'day', -value => $day);
$query->param(-name => $end.'year', -value => $year1);
$query->param(-name => $end.'mon', -value => $mon1);
$query->param(-name => $end.'day', -value => $day1);
}
1;
#
+192
View File
@@ -0,0 +1,192 @@
package TTXConfig;
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2002-2005, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 198 $
# $Date: 2006-07-14 08:41:19 -0400 (Fri, 14 Jul 2006) $
#
$TTXConfig::VERSION='2.22';
BEGIN {
$TTXConfig::REVISION = '$Revision: 198 $';
if ($TTXConfig::REVISION =~ /(\d+)/) {
$TTXConfig::REVISION = $1;
}
};
use strict;
my %errmsgs = (
NOFILENAME => 'Missing file name',
NOFILE => 'File does not exist',
OPENERR => 'Error reading file',
WRERR => 'Error writing file'
);
my %defaults = (
userdb => 'users.cgi',
ticketdb => 'tickets.cgi',
ticketid => 'ticketid.txt'
);
# ========================================================================== new
sub new {
my $class = shift;
my $self = {};
bless($self, $class);
if ($_[0] ne undef) {
$self->load($_[0]);
}
return $self;
}
# ========================================================================== get
sub get {
my $self = shift;
my $name = shift;
return $self->{$name};
}
# ========================================================================== set
sub set {
my $self = shift;
my $name = shift;
my $value = shift;
$value =~ s/\n//g;
my $old = $self->{$name};
$self->{$name} = $value;
return $old
}
# ========================================================================= load
sub load {
my $self = shift;
my $fname = shift;
if ($fname eq undef) {
$self->{_ERROR_CODE} = 'NOFNAME';
return 0;
}
if (! -f $fname) {
$self->{_ERROR_CODE} = 'NOFILE';
return 0;
}
if (!open(CFG, $fname)) {
$self->{_ERROR_CODE} = 'OPENERR';
return 0;
}
my @buff = <CFG>;
close CFG;
chomp @buff;
foreach my $line (@buff) {
$line =~ s/^\s+//;
$line =~ s/\s+$//;
my @parts = split(/=/, $line);
my $name = shift @parts;
my $value = join('=', @parts);
$name =~ s/\s+$//;
$value =~ s/^\s+//;
$value =~ /(.*)/;
$self->{$name} = $1;
}
$fname =~ /(.*)/;
$self->{_CFG_FILE} = $1;
return 1;
}
# ========================================================================= save
sub save {
my $self = shift;
if ($self->{_CFG_FILE} eq undef) {
$self->{_ERROR_CODE} = 'NOFNAME';
return 0;
}
if ($self->{_CFG_FILE} eq undef) {
$self->{_ERROR_CODE} = 'NOFILE';
return 0;
}
foreach my $key (keys %defaults) {
if ($self->{$key} eq undef) {
$self->{$key} = $self->{basedir} . "/$defaults{$key}";
}
}
$self->{imgurl} = '.' if $self->{imgurl} eq undef;
my $cfgfn = $self->{_CFG_FILE};
$cfgfn =~ /(.*)/; $cfgfn = $1;
if (! -e $cfgfn) {
if (open(CFG, ">$cfgfn")) {
close CFG;
}
}
if (!open(CFG, "+<$cfgfn")) {
$self->{_ERROR_CODE} = 'WRERR';
return 0;
}
flock CFG, 2;
seek(CFG, 0, 0);
my $vars = $self->ashash();
foreach my $key (sort keys %{$vars}) {
next if $key =~ /^_/;
next if $vars->{$key} eq undef;
print CFG "$key=".$vars->{$key}."\n";
}
truncate(CFG, tell(CFG));
close CFG;
umask(0);
chmod(0777, $cfgfn);
if ($self->{usecache}) {
eval "use TTXCache";
TTXCache::purge() if $@ eq undef;
}
return 1;
}
# ========================================================================= file
sub file {
my $self = shift;
return $self->{_CFG_FILE} if $_[0] eq undef;
my $fn = shift;
my $old = $self->{_CFG_FILE};
$self->{_CFG_FILE} = $fn;
return $old
}
# ======================================================================== error
sub error {
my $self = shift;
return $self->{_ERROR_CODE};
}
# ==================================================================== errortext
sub errortext {
my $self = shift;
return $errmsgs{$self->{_ERROR_CODE}}." [config]";
}
# ========================================================================= vars
sub vars {
my $self = shift;
my @list;
foreach my $key (sort keys %$self) {
next if $key =~ /^_/;
@list = (@list, $key);
}
return @list;
}
# ======================================================================= ashash
sub ashash {
my $self = shift;
my $hash = {};
foreach my $key (keys %{$self}) {
$hash->{$key} = $self->{$key};
}
return $hash;
}
1;
#
+45
View File
@@ -0,0 +1,45 @@
package TTXData;
#
# Application wide globals
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2003-2005, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 156 $
# $Date$
#
$TTXData::VERSION='2.22';
BEGIN {
$TTXData::REVISION = '$Revision: 156 $';
if ($TTXData::REVISION =~ /(\d+)/) {
$TTXData::REVISION = $1;
}
};
use strict;
# ====================================================================== GLOBALS
my $globals = {};
# ========================================================================== get
sub get {
return $globals->{$_[0]};
}
# ========================================================================== set
sub set {
my $name = shift;
my $value = shift;
my $old = $globals->{$name};
$globals->{$name} = $value;
return $old
}
1;
#
+734
View File
@@ -0,0 +1,734 @@
package TTXDesk;
#
# 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: 248 $
# $Date: 2006-08-15 07:22:26 -0400 (Tue, 15 Aug 2006) $
#
$TTXDesk::VERSION='2.22';
BEGIN {
$TTXDesk::REVISION = '$Revision: 248 $';
if ($TTXDesk::REVISION =~ /(\d+)/) {
$TTXDesk::REVISION = $1;
}
};
use strict;
use TTXCommon;
use TTXUser;
use TTXTickets;
require TTXMarkup;
my @brcols = ('id', 'name', 'email', 'subject', 'oper', 'status', 'open', 'updated');
my %c2t = (
id => 'id',
name => 'name',
email => 'email',
subject => 'subject',
oper => 'operator',
status => 'status',
updated => 'updated',
open => 'created',
grp => 'group'
);
my %c2T = (
id => 'Ticket #',
tid => 'Ticket #',
name => 'Name',
email => 'Email',
fltrsubj => 'Subject',
oper => 'Operator',
status => 'Status',
lname => 'Name',
grp => 'Group'
);
my @rclr = ('#F0F0E1', '#E8E8CF');
my @rcls = ('orow', 'erow');
# =================================================================== invenabled
my $_invenabled = undef;
sub invenabled {
if ($_invenabled eq undef) {
eval 'use TTXInvMod';
if ($@ eq undef) {
$_invenabled = 1;
} else {
$_invenabled = 0;
}
}
return $_invenabled;
}
# ================================================================== buildfilter
sub buildfilter {
my ($cfg, $query, $data) = @_;
my $width = $cfg->get('HTMLBASEWIDTH') || 700;
my $buff = "<table cellspacing=0 collspacing=0 width=$width>\n";
if ($cfg->get('fltrcols') eq undef) {
$cfg->set('fltrcols', 'text|subject|oper|status|id');
$cfg->save();
}
my $cfldcnt = TTXCommon::cfldcnt();
foreach my $var ($cfg->vars()) {
next if $var !~ /^x/;
my $pos = $cfg->get($var);
next if $pos < 0 || $pos >= $cfldcnt;
$var =~ s/^x//;
$var =~ /^(.{1,15})(.*)/;
$var = $1;
# $val .= '...' if $2 ne undef;
$c2T{"c$pos"} = $var;
}
my $colcnt = 0;
my @fltrcols = split(/\|/, $cfg->get('fltrcols'));
if (grep(/^subject$/, @fltrcols)) {
@fltrcols = grep(!/^subject$/, @fltrcols);
@fltrcols = ('subject', @fltrcols);
}
if (grep(/^text$/, @fltrcols)) {
@fltrcols = grep(!/^text$/, @fltrcols);
@fltrcols = ('text', @fltrcols);
}
if (grep(/^drange$/, @fltrcols)) {
@fltrcols = grep(!/^drange$/, @fltrcols);
@fltrcols = (@fltrcols, 'drange');
}
foreach my $fld (@fltrcols) {
$fld = 'fltrsubj' if $fld eq 'subject';
$fld = 'tid' if $fld eq 'id';
if ($colcnt > 2) { $buff .= "</tr>\n"; $colcnt = 0; }
if (!$colcnt) { $buff .= "<tr>\n"; }
++$colcnt;
if ($fld eq 'text') {
$buff .= '<td align=right class=lbl>[%Text%]</td>'."\n<td colspan=3 align=left>&nbsp;";
++$colcnt; # text is always first element
} elsif ($fld eq 'drange') {
if ($colcnt > 1) {
while ($colcnt <= 2) {
$buff .= "<td>&nbsp;</td><td>&nbsp;</td>\n";
++$colcnt;
}
$buff .= "</tr>\n<tr>\n";
}
$buff .= '<td align=right class=lbl>[%Date Range%]</td>'."\n".
"<td colspan=5 align=left>\n&nbsp;<select name=drfld>\n<option></option>\n";
foreach my $drfld ('created', 'updated', 'solved') {
$buff .= '<option';
$buff .= ' selected' if $query->param('drfld') eq $drfld;
$buff .= ">$drfld</option>\n";
}
if ($query->param('drfld') eq undef) {
$query->param(-name => 'drsyear', -value => '');
$query->param(-name => 'dreyear', -value => '');
} else {
if ($query->param('drsyear') eq undef) {
my $tz = $cfg->get('timezone') * 60;
my ($mday,$mon,$year) = (gmtime(time() + $tz - 24*3600*30))[3,4,5];
$query->param(-name => 'drsyear', -value => $year);
$query->param(-name => 'drsmon', -value => $mon);
$query->param(-name => 'drsday', -value => $mday);
}
if ($query->param('dreyear') eq undef) {
my $tz = $cfg->get('timezone') * 60;
my ($mday,$mon,$year) = (gmtime(time() + $tz))[3,4,5];
$query->param(-name => 'dreyear', -value => $year);
$query->param(-name => 'dremon', -value => $mon);
$query->param(-name => 'dreday', -value => $mday);
}
}
TTXCommon::checkdrange($query, 'drs', 'dre');
$buff .= "</select>\n&nbsp;&nbsp;".TTXCommon::pickdate($query, 'drs', 1).
"&nbsp;-&nbsp;".TTXCommon::pickdate($query, 'dre', 0)."</td>\n";
} else {
$buff .= '<td align=right class=lbl>[%'.$c2T{$fld}.'%]</td>'."\n".'<td align=left>&nbsp;';
}
if ($fld eq 'oper') {
$buff .= $data->{OPERSELBOX};
} elsif ($fld eq 'item') {
if (invenabled()) {
$buff .= TTXInvMod::selbox($cfg, $query, 0);
} else {
$buff .= '&nbsp;';
}
} elsif ($fld eq 'status') {
$buff .= $data->{STATUSSELBOX};
} elsif ($fld eq 'grp') {
$buff .= $data->{GRPSELBOX};
} elsif ($fld ne 'drange'){
my $val = $query->param($fld);
$fld =~ /^c(\d+)$/;
if ($1 ne undef && $cfg->get("dropdown$1") ne undef) {
my @options = split(/;/, $cfg->get("dropdown$1"));
$buff .= "<select name=$fld>\n";
if ($val eq undef) {
$buff .= "<option value=\"\"></option>\n";
}
foreach my $option (@options) {
my $selected = " selected" if $option eq $val;
my $v = $option;
$v =~ s/"/&quot;/g;
my $h = $option;
$h =~ s/</&lt/g;
my $dots = '...';
$h =~ /^(.{1,15})(.*)/;
$h = $1;
$h .= '...' if $2 ne undef;
$buff .= "<option value=\"$v\"$selected>$h</option>\n";
}
if ($val ne undef) {
$buff .= '<option value="">-- [%any%] --</option>'."\n";
}
$buff .= "</select>\n";
} else {
$val =~ s/&/&amp;/g;
$val =~ s/</&lt/g;
$val =~ s/"/&quot;/g;
$buff .= "<input type=text name=$fld size=".($fld eq 'text' ? 48:20)." value=\"$val\"";
}
}
$buff .= "</td>\n";
}
if ($colcnt) {
while ($colcnt < 3) { $buff .= "<td>&nbsp;</td>\n"; ++$colcnt; }
$buff .= "</tr>\n";
}
$buff .= "</table>";
$data->{TICKETFILTER} = $buff;
}
# ===================================================================== helpdesk
sub helpdesk {
my ($cfg, $query, $data) = @_;
my $browsetxt = 0;
$data->{PAGEHEADING} = '[%Help Desk%]';
TTXCommon::tickedvars($cfg, $data);
$c2T{item} = $cfg->get('inventory.label') || 'Item';
$c2t{item} = lc $cfg->get('inventory.label') || 'item';
my $cfldcnt = TTXCommon::cfldcnt();
if ($query->param('tk') ne undef) {
$query->param(-name => 'key', -value => $query->param('tk'));
return 'ticket';
}
my $user = $cfg->get('_USER');
my $session;
my $readonly;
if ($user ne undef) {
$session = $user->get('session');
$readonly = $user->get('ro') ? 1:0;
}
if (!$query->param('do')) {
$session->qexpand($query, 'helpdesk') if $session ne undef;
if ($query->param('status') eq undef) {
$query->param(-name => 'status', -value => $cfg->get('defaultstatus'));
}
} elsif ($session ne undef) {
my @fldlist = ('text', 'oper', 'tid', 'status', 'lname', 'name', 'email', 'fltrsubj', 'grp',
'qwindow', 'qsort', 'qsortorder',
'drfld', 'drsday', 'drsmon', 'drsyear', 'dreday', 'dremon', 'dreyear', 'item');
for (my $i = 0; $i < $cfldcnt; ++$i) {
push @fldlist, "c$i";
}
foreach my $id (@fldlist) {
if ($query->param($id) ne $session->get("helpdesk.$id")) {
$query->param(-name => 'qoffset', -value => '');
last;
}
}
}
if ($query->param('reset') ne undef) {
foreach my $fld ('text', 'oper', 'tid', 'status', 'lname', 'name', 'email', 'fltrsubj', 'grp', 'qoffset', 'drfld', 'item') {
$query->param(-name => $fld, -value => '');
}
for (my $i = 0; $i < $cfldcnt; ++$i) {
$query->param(-name => "c$i", -value => '');
}
foreach my $pref ('drs', 'dre') {
foreach my $fld ('day', 'mon', 'year') {
$query->param(-name => $pref.$fld, -value => '');
}
}
}
if ($cfg->get('brcols') eq undef) {
$cfg->set('brcols', 'id|name|email|subject|oper|status|open|updated');
$cfg->save();
}
if ($cfg->get('brcols') ne undef) {
@brcols = split(/\|/, $cfg->get('brcols'));
my @cfgvars = $cfg->vars();
foreach my $var (@cfgvars) {
next if $var !~ /^x/;
my $cidx = int ($cfg->get($var));
next if ($cidx < 0 || $cidx >= $cfldcnt);
$var =~ s/^x//;
$c2t{"c$cidx"} = $var;
}
}
if ($query->param('abstract')) {
$browsetxt = 1;
$data->{CHECKABSTRACT} = ' checked';
}
$data->{GRPSELBOX} = "<select name=grp>\n";
if ($query->param('grp') eq undef) {
$data->{GRPSELBOX} .= "<option></option>\n";
}
my @grplist = sort {uc($cfg->get($a)) cmp uc($cfg->get($b))} grep(/^group\d+$/, $cfg->vars());
foreach my $id (@grplist) {
my $grpname = $cfg->get($id);
next if $grpname eq undef || $grpname eq '';
$grpname =~ s/</&quot;/g;
$data->{GRPSELBOX} .= "<option value=$id";
$data->{GRPSELBOX} .= ' selected' if $query->param('grp') eq $id;
$data->{GRPSELBOX} .= ">$grpname</option>\n";
}
if ($query->param('grp') ne undef) {
$data->{GRPSELBOX} .= '<option value="">-- [%any%] --</option>'."\n";
}
$data->{GRPSELBOX} .= '<option value="-"';
if ($query->param('grp') eq '-') {
$data->{GRPSELBOX} .= " selected";
}
$data->{GRPSELBOX} .= '>-- [%none%] --</option>'."\n</select>\n";
my @operlist = TTXUser::list();
$data->{OPERSELBOX} = "<select name=oper>\n";
if ($query->param('oper') eq undef) {
$data->{OPERSELBOX} .= "<option></option>\n";
}
foreach my $oper (@operlist) {
$data->{OPERSELBOX} .= "<option value=$oper";
if ($query->param('oper') eq $oper) {
$data->{OPERSELBOX} .= " selected";
}
$data->{OPERSELBOX} .= ">$oper</option>\n";
}
if ($query->param('oper') ne undef) {
$data->{OPERSELBOX} .= '<option value="">-- [%any%] --</option>'."\n";
}
$data->{OPERSELBOX} .= "<option value=\"-\"";
if ($query->param('oper') eq '-') {
$data->{OPERSELBOX} .= " selected";
}
$data->{OPERSELBOX} .= '>-- [%none%] --</option>'."\n</select>\n";
$data->{STATUSSELBOX} = "<select name=status>\n";
if ($query->param('status') eq undef) {
$data->{STATUSSELBOX} .= "<option></option>\n";
}
foreach my $status ('(OPN|PND)', 'PND', 'OPN', 'WFR', '(OPN|WFR)', 'CLS', '(PND|OPN|WFR)') {
$data->{STATUSSELBOX} .= "<option value=$status";
if ($query->param('status') eq $status) {
$data->{STATUSSELBOX} .= " selected";
}
$data->{STATUSSELBOX} .= '>[%'.TTXCommon::status($status)."%]</option>\n";
}
if ($query->param('status') ne undef) {
$data->{STATUSSELBOX} .= '<option value="">-- [%any%] --</option>'."\n";
}
$data->{STATUSSELBOX} .= "</select>\n";
buildfilter($cfg, $query, $data);
my $tickets = TTXCommon::dbtik();
if ($tickets eq undef || $tickets->error() ne undef) {
$data->{ERROR_MESSAGE} = $tickets->errortext();
return undef;
}
my @filter;
if ($query->param('oper') ne undef) {
my $f;
$f->{col} = 'oper';
if ($query->param('oper') ne '-') {
$f->{expr} = "^".$query->param('oper')."\$";
} else {
$f->{expr} = "^\$";
}
push @filter, $f;
}
if ($query->param('grp') ne undef) {
my $f;
$f->{col} = 'grp';
if ($query->param('grp') ne '-') {
$f->{expr} = "^".$query->param('grp')."\$";
} else {
$f->{expr} = "^\$";
}
push @filter, $f;
}
if ($query->param('item') ne undef) {
my $f;
$f->{col} = 'item';
if ($query->param('item') ne '-') {
$f->{expr} = "^.*;".$query->param('item').";.*\$";
} else {
$f->{expr} = "^\$";
}
push @filter, $f;
}
if ($cfg->get('accessctrl') && $cfg->get('routex') ne undef) {
my $n = $cfg->get('routex');
if ($n =~ /^\d$/) {
eval "use TTXCustomRoute";
if ($@ eq undef) {
my @list = TTXCustomRoute::grouplist($cfg);
if (@list > 0) {
my $f;
$f->{col} = "c$n";
$f->{expr} = '^('.join('|', @list).')$';
push @filter, $f;
}
}
}
}
if ($cfg->get('accessctrl') && $cfg->get('_USER') ne undef) {
eval "use TTXGroups";
if (!$@) {
my @list = TTXGroups::grouplist($cfg, $cfg->get('_USER')->{login});
my $f;
$f->{col} = '-grp-';
$f->{groups} = \@list;
$f->{oper} = $cfg->get('_USER')->{login};
push @filter, $f;
}
}
if ($query->param('status') ne undef) {
my $f;
$f->{col} = 'status';
$f->{expr} = "^".$query->param('status')."\$";
push @filter, $f;
}
my $hideoldsolved;
if ($query->param('text') ne undef) {
my $f;
$f->{col} = 'text';
$f->{expr} = $query->param('text');
$browsetxt = 2;
push @filter, $f;
$hideoldsolved = $cfg->set('hideoldsolved', '');
}
if ($query->param('cmd') eq 'mytickets') {
my $f;
$f->{col} = 'email';
my $emailkey = $query->param('emailkey');
$emailkey =~ s/\*//g;
$f->{expr} = "^$emailkey\$";
push @filter, $f;
}
if ($query->param('tid') ne undef) {
my $f;
$f->{col} = 'id';
$f->{expr} = "^".$query->param('tid')."\$";
$f->{expr} =~ s/\*/.*/g;
push @filter, $f;
}
my @fields = ('name', 'lname', 'fltrsubj', 'email');
for (my $i = 0; $i < $cfldcnt; ++$i) { push @fields, "c$i"; }
foreach my $fld (@fields) {
if ($query->param($fld) ne undef) {
my $f;
if ($fld eq 'fltrsubj') { $f->{col} = 'subject'; }
else { $f->{col} = $fld; }
my ($wc, $wc1);
if ($fld =~ /^c\d+$/ && $cfg->get("$fld.type") eq 'list') {
$wc = '*;';
$wc1 = ';*';
}
$f->{expr} = "^$wc".$query->param($fld)."$wc1\$";
$f->{expr} =~ s/\*/.*/g;
push @filter, $f;
}
}
if ($query->param('qoffset') eq undef) {
$query->param(-name => 'qoffset', -value => 0);
}
if ($query->param('qwindow') eq undef) {
$query->param(-name => 'qwindow', -value => 20);
}
if ($query->param('qsort') eq undef) {
$query->param(-name => 'qsort', -value => 'updated');
}
if ($query->param('qsortorder') eq undef) {
$query->param(-name => 'qsortorder', -value => 'D');
}
my %drange;
if ($query->param('drfld') ne undef) {
eval "use Time::Local";
if ($@ eq undef) {
$query->param('drfld') =~ /^(created|updated|solved)$/;
if ($1 ne undef) {
$drange{fld} = $1;
$drange{stm} = Time::Local::timegm(0,0,0,$query->param('drsday'),$query->param('drsmon'),$query->param('drsyear')) - $cfg->get('timezone') * 60;
$drange{etm} = Time::Local::timegm(59,59,23,$query->param('dreday'),$query->param('dremon'),$query->param('dreyear')) - $cfg->get('timezone') * 60;
}
}
}
my $browser = $tickets->list($query->param('qoffset'), $query->param('qwindow'),
$query->param('qsort'), $query->param('qsortorder'), \@filter, \%drange);
if ($query->param('text') ne undef) {
$cfg->set('hideoldsolved', $hideoldsolved);
}
my $list = $browser->{list};
if (@{$list} < 1) {
$data->{TICKETLIST} = '<tr><td align=center><b>[%There are no tickets matching your query%]</b></td></tr>';
} else {
my $ccnt = scalar @brcols;
++$ccnt if $query->param('cmd') ne 'mytickets' && !$readonly;
my $lspan = int($ccnt / 2);
my $rspan = $ccnt - $lspan;
if ($query->param('cmd') ne 'mytickets') {
$data->{TICKETLIST} .= "<form method=post action=\"$ENV{SCRIPT_NAME}\">\n".
"<input type=hidden name=cmd value=groupcommand>\n".
"<input type=hidden name=style value=".$query->param('style').">\n".
"<input type=hidden name=sid value=".$query->param('sid').">\n";
}
$data->{TICKETLIST} .= "<tr><td colspan=$lspan align=left><b><span class=sm>".'[%Tickets%] '.
($browser->{first} + 1)." - ".$browser->{last}.' [%out of%] '.
$browser->{total}."</b></span></td>".
"<td align=right colspan=$rspan><span class=sm><b>";
if ($browser->{first} > 0) {
$data->{TICKETLIST} .= "<a href=# onClick=\"return scroll('0','".$query->param('qwindow')."')".'">[%first%]</a> ';
} else {
$data->{TICKETLIST} .= '<font color="#BBBBBB">[%first%]</font> ';
}
if ($browser->{first} > 0) {
my $back = $browser->{first} - $query->param('qwindow');
$back = 0 if $back < 0;
$data->{TICKETLIST} .= "<a href=# onClick=\"return scroll('$back','".$query->param('qwindow')."')\">".'[%prev%]</a> ';
} else {
$data->{TICKETLIST} .= '<font color="#BBBBBB">[%prev%]</font> ';
}
if ($browser->{last} < $browser->{total}) {
my $frw = $browser->{first} + $query->param('qwindow');
$data->{TICKETLIST} .= "<a href=# onClick=\"return scroll('$frw','".$query->param('qwindow')."')\">".'[%next%]</a> ';
} else {
$data->{TICKETLIST} .= '<font color="#BBBBBB">[%next%]</font> ';
}
if ($browser->{last} < $browser->{total}) {
my $frw = $browser->{total} - $query->param('qwindow');
$data->{TICKETLIST} .= "<a href=# onClick=\"return scroll('$frw','".$query->param('qwindow')."')\">".'[%last%]</a> ';
} else {
$data->{TICKETLIST} .= '<font color="#BBBBBB">[%last%]</font> ';
}
$data->{TICKETLIST} .= "</b></span></tr>\n";
$data->{TICKETLIST} .= "<tr><td colspan=$ccnt><img src=\"".TTXData::get('CONFIG')->get('imgurl')."/dot.gif\" height=2></td></tr>";
$data->{TICKETLIST} .= "<tr>\n";
if ($query->param('cmd') ne 'mytickets' && !$readonly) {
$data->{TICKETLIST} .= '<td class=trow align=center>[%sel%]</td>'."\n";
}
foreach my $col (@brcols) {
my $order = 'A';
if ($query->param('qsort') eq $col) {
if ($query->param('qsortorder') eq 'A') {
$order = 'D';
}
} else {
$order = $query->param('qsortorder');
}
$data->{TICKETLIST} .= "<td class=trow align=center><a href=# onClick=\"return setsort('$col', '$order')\">".'[%'.$c2t{$col}.'%]'."</a></td>\n";
}
$data->{TICKETLIST} .= "</tr>\n";
my $i = 0;
my $j = 0;
my %colormatrix = (PND => 'green', WFR => 'blue', OPN => 'orange', CLS => 'red', LATE => 'red');
my $now = time();
foreach my $id (@{$list}) {
my ($fcopen, $fcclose);
my $clr = $rclr[$i];
my $cl = $rcls[$i];
++$i;
++$j;
$i = 0 if $i > 1;
my $t = $tickets->ticket($id);
if ($cfg->get('colortickets')) {
$fcopen = "<font color=".$colormatrix{$t->{status}}.">";
$fcclose = "</font>";
}
if ($cfg->get('claimtime') &&
(($t->{status} eq 'PND' && ($now - $t->{open} > 24*60*60) && !$cfg->get('ignorepending') ) ||
$t->{status} ne 'PND' && $t->{'c'.$cfg->get('claimtime')} > 23)) {
$fcopen = "<font color=".$colormatrix{LATE}.">";
$fcclose = "</font>";
}
$data->{TICKETLIST} .= "<tr bgcolor=\"$clr\" onmouseover=\"rowhl($j, 1);\" onmouseout=\"rowhl($j, 0);\" id=\"tr$j\">\n";
if ($query->param('cmd') ne 'mytickets' && !$readonly) {
$data->{TICKETLIST} .= "<td align=center valign=middle class=$cl><input type=checkbox name=tid value=".$t->{id}."></td>\n";
}
foreach my $col (@brcols) {
my $val = $t->{$col};
my $align = 'right';
if (grep(/^$col$/, ('open', 'updated', 'closed'))) {
$val = "<nobr>$fcopen".TTXCommon::tmtxt($val)."$fcclose</nobr>";
} elsif ($col eq 'status') {
$val = $fcopen.'[%'.TTXCommon::status($val).'%]'.$fcclose;
} elsif ($col eq 'id') {
$val = "$fcopen$val$fcclose";
if (!$readonly) {
$val = "<a href=# onClick=\"return ticked('$val')\">$val</a>";
}
} elsif ($col eq 'grp') {
$val = $fcopen.($cfg->get($val) || '-').$fcclose;
} elsif ($col eq 'subject') {
$align = 'left';
my $dots = '...';
$val =~ s/\b([^\s]{15,15})([^\s])*/$1.$dots/ge;
$val =~ /^(.{1,30})(.*)/;
$val = $1;
$val .= '...' if $2 ne undef;
$val =~ s/</&lt;/g;
my $emailkey;
if ($query->param('cmd') eq 'mytickets') {
$emailkey = "&emailkey=".$query->param('emailkey');
}
$val = "<a href=\"$ENV{SCRIPT_NAME}?cmd=ticket&sid=".$query->param('sid')."&key=".$t->{key}.$emailkey.
"&qsort=".$query->param('qsort')."&qsortorder=".$query->param('qsortorder').
"&qoffset=".$query->param('qoffset')."&qwindow=".$query->param('qwindow').
"&oper=".$query->param('oper')."&status=".$query->param('status')."&style=".$query->param('style').
"&lname=".$query->param('lname')."&c0=".$query->param('c0')."&fltrsubj=".$query->param('fltrsubj').
"\">$fcopen$val$fcclose</a>";
} elsif ($col eq 'name') {
$align = 'left';
$val = $fcopen.$val.$fcclose;
} elsif ($col eq 'item') {
if (invenabled()) {
my $items = TTXInvMod::getitems($val);
$val = undef;
foreach my $item (@{$items}) {
my $lbl = $item->{title};
my $dots = '...';
$lbl =~ s/\b([^\s]{15,15})([^\s])*/$1.$dots/ge;
$lbl =~ s/</&lt;/g;
$val .= ', ' if $val ne undef;
$val .= "<a href=# onClick=\"return showitem('".$item->{id}."')\">$lbl</a>";
}
if ($val eq undef) {
$val = '-';
}
$val = $fcopen.$val.$fcclose;
} else {
$val = $fcopen."???".$fcclose;
}
} elsif ($col eq 'email') {
my $dots = '...';
my $adr = $val;
$val =~ s/\b([^\s]{15,15})([^\s])*/$1.$dots/ge;
$val = "<a href=\"mailto:$adr\">$fcopen$val$fcclose</a>";
} else {
if ($val ne undef) {
if ($col =~ /^c\d+/ && $cfg->get("$col.type") eq 'list') {
$val =~ s/^;//; $val =~ s/;$//;
}
} else {
$val = "-";
}
$val =~ s/</&lt;/g;
$val =~ s/>/&gt;/g;
$val =~ s/(\d\d\d\d-\d\d-\d\d)/'<nobr>'.$1.'<\/nobr>'/eg;
$val = $fcopen.$val.$fcclose;
}
# $val = "-" if $val eq undef;
if ($query->param('qsort') eq $col) { $val = "<b>$val</b>"; }
$data->{TICKETLIST} .= "<td align=$align valign=top class=$cl>$val</td>\n";
}
$data->{TICKETLIST} .= "</tr>\n";
if ($browsetxt) {
my $body;
if ($browsetxt < 2) {
my $msg = shift (@{$t->{messages}});
my @msgparts = split(/\n\n/, $msg);
shift @msgparts;
$body = join("\n\n", @msgparts);
$body =~ s/</&lt;/g;
$body = TTXMarkup::html($body);
} else {
$body = $browser->{abstract}->{$t->{id}};
}
$body =~ s/^\s+//s;
if ($body =~ /^(.{1,340})/s) {
$body = $1;
}
$data->{TICKETLIST} .= "<tr>\n<td class=txt>&nbsp;</td>\n";
$data->{TICKETLIST} .= "<td colspan=".(int(@brcols - 1))." class=txt>$body</td>\n";
$data->{TICKETLIST} .= "</tr>\n";
}
}
$data->{TICKETLIST} .= "<tr><td colspan=$ccnt><img src=\"".TTXData::get('CONFIG')->get('imgurl')."/dot.gif\" height=2></td></tr>".
"<tr><td align=left colspan=$ccnt>\n".
"<table cellpadding=0 cellspacing=0 width=\"100%\"><tr>\n";
if ($query->param('cmd') ne 'mytickets' && !$readonly) {
my $operselbox;
my $userid = $cfg->get('_USER')->{login};
if ($cfg->get('grant.assign') eq undef || grep(/^$userid$/, split(/,/, $cfg->get('grant.assign')))) {
$operselbox = "<select name=to class=sm>\n".
"<option></option>\n";
foreach my $oper (@operlist) {
my $user = TTXUser->new($oper);
if ($user ne undef && !$user->{ro}) {
$operselbox .= "<option value=$oper>$oper</option>\n";
}
}
if ($cfg->get('usegrpsel')) {
eval "use TTXGroups";
if ($@ eq undef) {
my $tmp = $data->{NEWSTATUS};
TTXGroups::trselector($cfg, $data);
$operselbox .= $data->{NEWSTATUS};
$data->{NEWSTATUS} = $tmp;
}
}
$operselbox .= "</select>\n";
$operselbox = "<input type=submit name=assign value=\"".'[%Assign to%]'."\" class=sm>\n$operselbox";
}
$data->{TICKETLIST} .= "<td align=left><input type=submit name=close value=\"".'[%Close selected%]'."\" ".
"onclick=\"return confirm('".'[%This will close selected tickets. Please confirm.%]'."')\");\" class=sm>\n";
if (!($cfg->get('demo') && $userid ne 'admin') &&
($cfg->get('grant.delete') eq undef || grep(/^$userid$/, split(/,/, $cfg->get('grant.delete'))))) {
$data->{TICKETLIST} .= '<input type=submit name=del value="[%Delete selected%]" '.
"onclick=\"return confirm('".'[%This will delete selected tickets. Please confirm.%]'."')\");\" class=sm>\n";
}
$data->{TICKETLIST} .= "$operselbox</form></td>\n";
}
$data->{TICKETLIST} .= "<td align=right><span class=sm><b>";
if ($browser->{first} > 0) {
$data->{TICKETLIST} .= "<a href=# onClick=\"return scroll('0','".$query->param('qwindow')."')\">".'[%first%]'."</a> ";
} else {
$data->{TICKETLIST} .= '<font color="#BBBBBB">[%first%]</font> ';
}
if ($browser->{first} > 0) {
my $back = $browser->{first} - $query->param('qwindow');
$back = 0 if $back < 0;
$data->{TICKETLIST} .= "<a href=# onClick=\"return scroll('$back','".$query->param('qwindow')."')\">".'[%prev%]'."</a> ";
} else {
$data->{TICKETLIST} .= '<font color="#BBBBBB">[%prev%]</font> ';
}
if ($browser->{last} < $browser->{total}) {
my $frw = $browser->{first} + $query->param('qwindow');
$data->{TICKETLIST} .= "<a href=# onClick=\"return scroll('$frw','".$query->param('qwindow')."')\">".'[%next%]'."</a> ";
} else {
$data->{TICKETLIST} .= '<font color="#BBBBBB">[%next%]</font> ';
}
if ($browser->{last} < $browser->{total}) {
my $frw = $browser->{total} - $query->param('qwindow');
$data->{TICKETLIST} .= "<a href=# onClick=\"return scroll('$frw','".$query->param('qwindow')."')\">".'[%last%]'."</a> ";
} else {
$data->{TICKETLIST} .= '<font color="#BBBBBB">[%last%]</font> ';
}
$data->{TICKETLIST} .= "</b></span></td></tr></table>\n</td></tr>";
$data->{TICKETLIST} .= "<tr>\n";
}
if ($session ne undef) {
my @savelist = ('text', 'oper', 'tid', 'status', 'lname', 'name', 'email', 'fltrsubj', 'grp',
'qwindow', 'qoffset', 'qsort', 'qsortorder', 'abstract',
'drfld', 'drsday', 'drsmon', 'drsyear', 'dreday', 'dremon', 'dreyear');
for (my $i = 0; $i < $cfldcnt; ++$i) {
$query->param(-name => "c$i", -value => '');
}
$session->qsave($query, 'helpdesk', \@savelist);
}
return undef;
}
1;
#
@@ -0,0 +1,66 @@
package TTXDictionary;
#
# 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: 253 $
# $Date: 2006-08-15 09:11:26 -0400 (Tue, 15 Aug 2006) $
#
$TTXDictionary::VERSION='2.22';
BEGIN {
$TTXDictionary::REVISION = '$Revision: 253 $';
if ($TTXDictionary::REVISION =~ /(\d+)/) {
$TTXDictionary::REVISION = $1;
}
};
use strict;
use CSV;
my %dictionary;
my $isLoaded;
my $uselang;
# ========================================================================= lang
sub lang {
my $uselang = $_[0];
}
# ========================================================================= load
sub load {
return 1 if $isLoaded;
my $cfg = TTXData::get('CONFIG');
my $dictname = 'dict'.(($uselang ne undef) ? "-$uselang":'').'.csv';
my $fn = $cfg->get('basedir')."/$dictname";
if (open(CSV, $fn)) {
foreach (my $line = <CSV>; $line ne undef; $line = <CSV>) {
chomp($line);
$line =~ s/(\r|\n)+$//;
my ($en, $trans) = CSVsplit($line);
$dictionary{$en} = $trans;
}
close CSV;
}
if ($dictionary{CHARSET} eq undef) {
$dictionary{CHARSET} = 'windows-1252';
}
$isLoaded = 1;
return 1;
}
# ==================================================================== translate
sub translate {
my $txt = $_[0];
load();
if (defined $dictionary{$txt}) {
$txt = $dictionary{$txt};
}
return $txt;
}
1;
#
@@ -0,0 +1,392 @@
package TTXFileTickets;
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2002-2005, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 290 $
# $Date: 2006-10-19 14:09:29 +0400 (Thu, 19 Oct 2006) $
#
$TTXFileTickets::VERSION='2.22';
BEGIN {
$TTXFileTickets::REVISION = '$Revision: 290 $';
if ($TTXFileTickets::REVISION =~ /(\d+)/) {
$TTXFileTickets::REVISION = $1;
}
};
use strict;
use vars qw(@ISA);
require TTXTickets;
@ISA = qw(TTXTickets);
use TTXData;
require TTXSearch;
require TTXMarkup;
my %errmsgs = (
NOUSER => 'User does not exist',
OPENERR => 'Error reading tickets database',
WRERR => 'Error writing file',
LOCKWRERR => 'Error acquiring lock (failed to create lock file)',
LOCKOPNERR => 'Error acquiring lock (failed to open lock file)',
LOCKERR => 'Error acquiring lock (flock() failed on lock file)',
);
my $boundary = '-----------asdjhfKJS12869nmboiu7826318---';
# ========================================================================== new
sub new {
my $class = shift;
my $self = $class->SUPER::new(@_);
$self->{_LOCK_CNT} = 0;
$self->load();
return $self;
}
# ====================================================================== DESTROY
sub DESTROY {
my $self = shift;
if ($self->{_LOCK_CNT}) {
$self->{_LOCK_CNT} = 1;
$self->unlockdb();
}
}
# ========================================================================= load
sub load {
my $self = shift;
return 0 if !$self->lockdb();
my $fn = TTXData::get('CONFIG')->get('ticketdb');
return 1 if ! -f $fn;
if (!open(DB, $fn)) {
$self->{_ERROR_CODE} = 'OPENERR';
$self->unlockdb();
return 0;
}
my @buff = <DB>;
close DB;
chomp @buff;
foreach my $line (@buff) {
my @fields = split(/\|/, $line);
my $tik;
foreach my $fld ($self->_fields()) {
$tik->{$fld} = shift @fields;
}
$self->{TICKETS}->{$tik->{id}} = $tik;
}
return 1;
}
# ======================================================================= lockdb
sub lockdb {
my $self = shift;
if ($self->{_LOCK_CNT}) {
++$self->{_LOCK_CNT};
return 1;
}
my $lockfile = TTXData::get('CONFIG')->get('basedir')."/lockdb.ttx";
if (! -f $lockfile) {
if (!open(LOCK, ">$lockfile")) {
$self->{_ERROR_CODE} = 'LOCKWRERR';
return 0;
}
} elsif (!open(LOCK,"+<$lockfile")) {
$self->{_ERROR_CODE} = 'LOCKOPNERR';
return 0;
}
flock(LOCK, 2);
$self->{_LOCK_CNT} = 1;
return 1;
}
# ===================================================================== unlockdb
sub unlockdb {
my $self = shift;
return if !$self->{_LOCK_CNT};
--$self->{_LOCK_CNT};
if (!$self->{_LOCK_CNT}) {
flock(LOCK, 8);
close LOCK;
}
}
# ========================================================================= save
sub save {
my $self = shift;
return 0 if !$self->lockdb();
#
# Build temporary file
#
my $tmpfn = TTXData::get('CONFIG')->get('ticketdb').'.tmp';
if (!open(TMPDB, ">$tmpfn")) {
$self->{_ERROR_CODE} = 'WRERR';
$self->unlockdb();
return 0;
}
flock(TMPDB, 2);
foreach my $id (keys %{$self->{TICKETS}}) {
my $line;
my $tik = $self->{TICKETS}->{$id};
foreach my $fld ($self->_fields()) {
my $val = $tik->{$fld};
$val =~ s/\|/!/g;
$val =~ s/\r//g;
$val =~ s/\n/ /g;
$line .= "$val|";
}
print TMPDB "$line\n";
if ($tik->{messages} ne undef) {
my $fn = TTXData::get('CONFIG')->get('basedir')."/tickets/$id.cgi";
if (open(MSG, ">$fn")) {
flock(MSG, 2);
foreach my $msg (@{$tik->{messages}}) {
print MSG "$msg\n$boundary\n";
}
truncate(MSG, tell(MSG));
close MSG;
umask(0);
chmod(0777, $fn);
}
}
}
close(TMPDB);
umask(0);
chmod(0777, $tmpfn);
#
# Check if the ticket database exists, create if none.
#
my $fn = TTXData::get('CONFIG')->get('ticketdb');
if (! -f $fn) {
if (!open(DB, ">$fn")) {
$self->{_ERROR_CODE} = 'WRERR';
$self->unlockdb();
return 0;
}
close DB;
}
#
# Check if it's time for backup
#
my $backupfq = TTXData::get('CONFIG')->get('backupfq');
$backupfq = 7 * 24 * 60 * 60; # default is weekly
my $tmext = time();
$tmext = $tmext - ($tmext % $backupfq);
my $backupdir = TTXData::get('CONFIG')->get('basedir').'/backup';
my $backupfn = $backupdir."/tickets$tmext.cgi";
if (! -f $backupfn) {
if (! -d $backupdir) {
umask(0);
if (!mkdir($backupdir, 0777)) {
warn "Failed to create directory '$backupdir'";
}
}
if (-d $backupdir) {
rename $fn, $backupfn;
}
}
#
# Replace ticket DB
#
if (!rename($tmpfn,$fn)) {
umask 0;
chmod(0777, $fn);
if (!rename($tmpfn,$fn)) {
warn "Failed to 'rename($tmpfn,$fn), make sure the $fn is NOT read-only.";
$self->{_ERROR_CODE} = 'WRERR';
$self->unlockdb();
return 0;
}
}
$self->unlockdb();
if (TTXData::get('_USECACHE')) {
eval "use TTXCache";
TTXCache::purge() if $@ eq undef;
}
return 1;
}
# ======================================================================= deltik
sub deltik {
my $self = shift;
my $id = shift;
my $fn = TTXData::get('CONFIG')->get('basedir')."/tickets/$id.cgi";
$fn =~ /(.*)/; $fn = $1;
unlink $fn if -f $fn;
if (TTXData::get('ISPRO')) {
TTXFile::delfiles($id);
}
delete $self->{TICKETS}->{$id};
}
# ================================================================== ticketbykey
sub ticketbykey {
my $self = shift;
my $key = shift;
my $id = $key;
$id =~ s/Z.*$//;
if (TTXData::get('CONFIG')->get('shortkey') || $self->{TICKETS}->{$id}->{key} eq $key) {
return $self->ticket($id);
}
return undef;
}
# ======================================================================= ticket
sub ticket {
my ($self, $id, $nomsg) = @_;
my $tik = $self->{TICKETS}->{$id};
if ($tik ne undef && $tik->{message} eq undef && !$nomsg) {
my $fn = TTXData::get('CONFIG')->get('basedir')."/tickets/$id.cgi";
if (-f $fn && open(MSG, $fn)) {
my $rawmsg;
read(MSG, $rawmsg, 64*1024);
close MSG;
my @messages = split(/\n$boundary\n/, $rawmsg);
$tik->{messages} = \@messages;
}
}
return $tik;
}
# ==================================================================== addticket
sub addticket {
my $self = shift;
my $tik = shift;
my $fn = TTXData::get('CONFIG')->get('ticketid');
if (! -f $fn) {
if (!open(ID, ">$fn")) {
$self->{_ERROR_CODE} = 'WRERR';
return 0;
}
print ID "0\n";
close ID;
}
if (!open(ID,"+<$fn")) {
$self->{_ERROR_CODE} = 'WRERR';
return 0;
}
flock(ID, 2);
my $id = <ID>;
chomp $id;
++$id;
seek(ID, 0, 0);
print ID "$id\n";
close ID;
umask(0);
chmod(0777, $fn);
$tik->{open} = time() if $tik->{open} eq undef;
$tik->{updated} = $tik->{open};
$tik->{status} = 'PND';
$tik->{id} = $id;
$tik->{key} = "$id";
if (!TTXData::get('CONFIG')->get('shortkey')) {
$tik->{key} .= "Z$$".int(1000000 + rand(9000000)).int(1000000 + rand(9000000));
}
$self->{TICKETS}->{$id} = $tik;
return $id;
}
# ========================================================================= list
sub list {
my ($self, $off, $win, $col, $ord, $filter, $drange) = @_;
my @list = keys %{$self->{TICKETS}};
my $tickets = $self->{TICKETS};
my $byid;
my $ftxt;
my $abstract = {};
if ($filter ne undef) {
foreach my $f (@{$filter}) {
my $expr = $f->{expr};
my $c = $f->{col};
if ($c eq 'text') {
$ftxt = $f;
} elsif ($c eq '-grp-') {
my $oper = $f->{oper};
my $grps = join('|', @{$f->{groups}});
if ($grps ne undef) {
@list = grep {$tickets->{$_}->{oper} eq $oper || $tickets->{$_}->{grp} =~ /^$grps$/} @list;
} else {
@list = grep {$tickets->{$_}->{oper} eq $oper} @list;
}
} else {
$byid = 1 if $c eq 'id';
@list = grep {$tickets->{$_}->{$c} =~ /$expr/i} @list;
}
}
}
if (!$byid && TTXData::get('CONFIG')->get('hideoldsolved')) {
my $oldis = int(TTXData::get('CONFIG')->get('hideoldsolved'));
$oldis = time() - $oldis * 3600 * 24;
@list = grep {$tickets->{$_}->{status} ne 'CLS' || $tickets->{$_}->{closed} > $oldis} @list;
}
if ($drange->{fld} ne undef) {
my %fldmap = ( created => 'open', updated => 'updated', solved => 'closed' );
my $fld = $fldmap{$drange->{fld}};
my $stm = $drange->{stm};
my $etm = $drange->{etm};
@list = grep {$tickets->{$_}->{$fld} >= $stm && $tickets->{$_}->{$fld} <= $etm} @list;
}
if ($ftxt ne undef) {
my @l1;
my $tokens = TTXSearch::tokenize($ftxt->{expr});
my $match;
my $body;
my $token;
foreach my $id (@list) {
my $t = $self->ticket($id);
next if $t eq undef;
foreach my $msg (@{$t->{messages}}) {
$msg =~ s/^.+\n\n//s;
$body = TTXMarkup::strip($msg);
$match = 1;
foreach $token (@{$tokens}) {
if ($body !~ /\b$token\b/i) {
$match = 0;
last;
}
}
if ($match) {
$abstract->{$id} = TTXSearch::abstract($body, $tokens);
push @l1, $id;
last;
}
}
}
@list = @l1;
}
if (grep(/^$col$/, ('open', 'closed', 'updated', 'id'))) {
if ($ord eq 'A') {
@list = sort {$tickets->{$a}->{$col} <=> $tickets->{$b}->{$col}} @list;
} else {
@list = sort {$tickets->{$b}->{$col} <=> $tickets->{$a}->{$col}} @list;
}
} else {
if ($ord eq 'A') {
@list = sort {$tickets->{$a}->{$col} cmp $tickets->{$b}->{$col}} @list;
} else {
@list = sort {$tickets->{$b}->{$col} cmp $tickets->{$a}->{$col}} @list;
}
}
$off = 0 if $off < 0 || $off > @list;
$win = 20 if $win < 1;
$win = @list - $off if ($off + $win) > @list;
my $browser;
$browser->{abstract} = $abstract;
$browser->{total} = int(@list);
@{$browser->{list}} = splice @list, $off, $win;
$browser->{first} = $off;
$browser->{last} = $off + @{$browser->{list}};
return $browser;
}
# ==================================================================== errortext
sub errortext {
my $self = shift;
return $errmsgs{$self->{_ERROR_CODE}};
}
1;
#
+146
View File
@@ -0,0 +1,146 @@
package TTXGrpCmd;
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2006, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 216 $
# $Date: 2006-07-21 05:19:45 -0400 (Fri, 21 Jul 2006) $
#
$TTXGrpCmd::VERSION='2.22';
BEGIN {
$TTXGrpCmd::REVISION = '$Revision: 216 $';
if ($TTXGrpCmd::REVISION =~ /(\d+)/) {
$TTXGrpCmd::REVISION = $1;
}
};
use strict;
use TTXCommon;
require TTXUser;
use TTXTickets;
require TTXMail;
require TTXMarkup;
require TTXTicket;
# ================================================================== 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();
}
}
}
}
# ======================================================================= 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;
}
}
# =========================================================================== do
sub do {
my ($cfg, $query, $data) = @_;
checkgroups($cfg);
lockdb();
my $tickets = TTXCommon::dbtik();
if ($tickets eq undef || $tickets->error() ne undef) {
$data->{ERROR_MESSAGE} = $tickets->errortext();
return undef;
}
my $update = 0;
my @tidlist = $query->param('tid');
my $user = $cfg->get('_USER');
my $userid = $user->{login};
my $readonly = $user->get('ro') ? 1:0;
if (!$readonly) {
foreach my $tid (@tidlist) {
if ($query->param('del') ne undef) {
if (!($cfg->get('demo') && $userid ne 'admin') &&
($cfg->get('grant.delete') eq undef || grep(/^$userid$/, split(/,/, $cfg->get('grant.delete'))))) {
$tickets->deltik($tid);
$update = 1;
}
} elsif ($query->param('close') ne undef) {
my $t = $tickets->ticket($tid);
next if $t eq undef;
if ($t->{status} ne 'CLS') {
if ($t->{oper} eq undef) {
$t->{oper} = $userid;
}
$t->{status} = 'CLS';
$t->{updated} = time();
$t->{closed} = $t->{updated};
TTXCommon::logit("CLOSE|$userid|".$t->{id});
$update = 1;
}
} elsif ($query->param('assign') ne undef) {
my $t = $tickets->ticket($tid);
next if $t eq undef;
my $to = TTXCommon::cleanit($query, 'to');
next if $to eq undef;
if ($to !~ /^\+/ && $t->{oper} ne $to) {
my $user = TTXUser->new($to);
next if ($user eq undef || $user->get('login') eq undef);
$t->{oper} = $to;
$t->{status} = 'OPN' if $cfg->get('transferopens') || $t->{status} eq 'PND';
$update = 1;
$t->{updated} = time();
TTXCommon::logit("TRANSFER|$userid|".$t->{id}."|$to");
TTXTicket::transfernotice({cfg => $cfg, ticket => $t});
} elsif($cfg->get('usegrpsel')) {
next if $t->{grp} eq "+$to";
$t->{grp} = $to;
TTXGroups::grptransfer({cfg => $cfg, ticket => $t});
$update = 1;
$t->{updated} = time();
}
}
}
}
$tickets->save() if $update;
unlockdb();
$query->param(-name => 'tid', -value => '');
$query->param(-name => 'del', -value => '');
$query->param(-name => 'close', -value => '');
$query->param(-name => 'assign', -value => '');
return 'helpdesk'
}
1;
#
+388
View File
@@ -0,0 +1,388 @@
package TTXInventory;
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2006, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 257 $
# $Date: 2006-08-16 05:47:08 -0400 (Wed, 16 Aug 2006) $
#
$TTXInventory::VERSION='2.22';
BEGIN {
$TTXInventory::REVISION = '$Revision: 257 $';
if ($TTXInventory::REVISION =~ /(\d+)/) {
$TTXInventory::REVISION = $1;
}
};
use strict;
use TTXData;
my $idb = undef;
my $states = undef;
my $lasterror;
my @itemfields = ('id', 'title', 'status', 'img');
my @statefields = ('id', 'title', 'img');
# ====================================================================== notesfn
sub notesfn {
my $cfg = TTXData::get('CONFIG');
my $dn = $cfg->get('basedir').'/inventory';
return "$dn/$_[0].cgi";
}
# ======================================================================== idbfn
sub idbfn {
my $cfg = TTXData::get('CONFIG');
my $dn = $cfg->get('basedir').'/inventory';
my $fn = "$dn/index.cgi";
if (! -d $dn) {
if (!mkdir($dn, 0777)) {
$lasterror = "Failed to create inventory database directory";
return undef;
}
}
if (! -f $fn) {
open(IDB, ">$fn");
close(IDB);
if (! -f $fn) {
$lasterror = "Failed to create inventory database";
return undef;
}
}
return $fn;
}
# ==================================================================== line2item
sub line2item {
chomp($_[0]);
my @fields = split(/\|/, $_[0]);
my %item;
foreach my $key (@itemfields) {
$item{$key} = shift @fields;
$item{key} =~ s/^\s+//;
$item{key} =~ s/\s+$//;
}
return %item;
}
# ==================================================================== item2line
sub item2line {
my $item = $_[0];
my @vals;
foreach my $key (@itemfields) {
my $val = $item->{$key};
$val =~ s/\|/!/g;
push @vals, $val;
}
return join('|', @vals);
}
# ========================================================================= load
sub load {
if ($idb eq undef) {
my $fn = idbfn();
return 0 if $fn eq undef;
lockdb();
if (!open(IDB, $fn)) {
$lasterror = "Failed to open inventory database file";
return 0;
}
flock(IDB,2);
for (my $line = <IDB>; $line ne undef; $line = <IDB>) {
my %item = line2item($line);
next if $item{id} !~ /^\d+$/;
my $nfn = notesfn($item{id});
if (-f $nfn) {
if (open(NOTES, $nfn)) {
$item{notes} = join('', <NOTES>);
close(NOTES);
}
}
$idb->{$item{id}} = \%item;
}
close(IDB);
unlockdb();
}
return 1;
}
# ========================================================================= list
sub list {
return keys %{$idb} if load();
my @empty;
return @empty;
}
# ====================================================================== getitem
sub getitem {
return undef if !load();
if (! exists $idb->{$_[0]}) {
$lasterror = "Item $_[0] does not exist";
return undef;
}
return $idb->{$_[0]};
}
# ======================================================================= savedb
sub savedb {
return 1 if $idb eq undef;
my $fn = idbfn();
return 0 if $fn eq undef;
return 0 if !lockdb();
if (!open(IDB, ">$fn")) {
$lasterror = "Failed to open inventory database file";
unlockdb();
return 0;
}
flock(IDB,2);
foreach my $id (sort {$a <=> $b} keys %{$idb}) {
next if $id !~ /^\d+$/;
print IDB item2line($idb->{$id})."\n";
my $nfn = notesfn($id);
if ($idb->{$id}->{notes} ne undef) {
if (open(NOTES, ">$nfn")) {
print NOTES $idb->{$id}->{notes};
close(NOTES);
}
} elsif (-f $nfn) {
unlink $nfn;
}
}
close(IDB);
unlockdb();
if (TTXData::get('_USECACHE')) {
eval "use TTXCache";
TTXCache::purge() if $@ eq undef;
}
return 1;
}
# ========================================================================== add
sub add {
my $item = $_[0];
my $fn = idbfn();
return undef if $fn eq undef;
return undef if !lockdb();
if (!load()) {
unlockdb();
return undef;
}
my @lst = sort {$a <=> $b } list();
my $cnt = int(@lst);
if (!$cnt) {
$item->{id} = 1;
} else {
$item->{id} = int($lst[$cnt - 1]) + 1;
}
if (!open(IDB, ">>$fn")) {
$lasterror = "Failed to open inventory database file";
unlockdb();
return undef;
}
flock(IDB,2);
seek(IDB,0,2);
print IDB item2line($item)."\n";
close(IDB);
if ($item->{notes} ne undef) {
my $nfn = notesfn($item->{id});
if (open(NOTES, ">$nfn")) {
print NOTES $item->{notes};
close(NOTES);
}
}
unlockdb();
if (TTXData::get('_USECACHE')) {
eval "use TTXCache";
TTXCache::purge() if $@ eq undef;
}
$idb->{$item->{id}} = $item;
return $item->{id};
}
# ======================================================================= lockdb
my $_lockcnt = 0;
sub lockdb {
if ($_lockcnt) {
++$_lockcnt;
return 1;
}
my $lockfile = TTXData::get('CONFIG')->get('basedir')."/lockidb.ttx";
if (! -f $lockfile) {
if (!open(LOCK, ">$lockfile")) {
$lasterror = 'LOCKWRERR';
return 0;
}
} elsif (!open(LOCK,"+<$lockfile")) {
$lasterror = 'LOCKOPNERR';
return 0;
}
flock(LOCK, 2);
$_lockcnt = 1;
return 1;
}
# ===================================================================== unlockdb
sub unlockdb {
return if !$_lockcnt;
--$_lockcnt;
if (!$_lockcnt) {
flock(LOCK, 8);
close LOCK;
}
}
# ========================================================================== del
sub del {
my $id = $_[0];
return 0 if !lockdb();
if (!load()) {
unlockdb();
return 0;
}
if (!exists $idb->{$id}) {
unlockdb();
return 1;
}
my $nfn = notesfn($id);
unlink $nfn if -f $nfn;
delete $idb->{$id};
my $ccode = 1;
if ($_lockcnt == 1) {
$ccode = savedb();
}
unlockdb();
return $ccode;
}
# ======================================================================== sdbfn
sub sdbfn {
my $cfg = TTXData::get('CONFIG');
my $dn = $cfg->get('basedir').'/inventory';
my $fn = "$dn/states.cgi";
if (! -d $dn) {
if (!mkdir($dn, 0777)) {
$lasterror = "Failed to create inventory database directory";
return undef;
}
}
if (! -f $fn) {
open(IDB, ">$fn");
close(IDB);
if (! -f $fn) {
$lasterror = "Failed to create status database";
return undef;
}
}
return $fn;
}
# =================================================================== line2state
sub line2state {
chomp($_[0]);
my @fields = split(/\|/, $_[0]);
my %state;
foreach my $key (@statefields) {
$state{$key} = shift @fields;
$state{key} =~ s/^\s+//;
$state{key} =~ s/\s+$//;
}
return %state;
}
# =================================================================== state2line
sub state2line {
my $state = $_[0];
my @vals;
foreach my $key (@statefields) {
my $val = $state->{$key};
$val =~ s/\|/!/g;
push @vals, $val;
}
return join('|', @vals);
}
# =================================================================== loadstates
sub loadstates {
if ($states eq undef) {
$states = {};
my $fn = sdbfn();
return undef if $fn eq undef;
if (!open(SDB, $fn)) {
$lasterror = "Failed to open status database file";
return undef;
}
flock(SDB,2);
for (my $line = <SDB>; $line ne undef; $line = <SDB>) {
my %state = line2state($line);
next if $state{id} !~ /^\d+$/;
$states->{$state{id}} = \%state;
}
close(SDB);
}
return $states;
}
# ===================================================================== addstate
sub addstate {
my $state = $_[0];
my $fn = sdbfn();
return undef if $fn eq undef;
return undef if !lockdb();
if (loadstates() eq undef) {
unlockdb();
return undef;
}
my @lst = sort {$a <=> $b } keys %{$states};
my $cnt = int(@lst);
if (!$cnt) {
$state->{id} = 1;
} else {
$state->{id} = int($lst[$cnt - 1]) + 1;
}
if (!open(SDB, ">>$fn")) {
$lasterror = "Failed to open status database file";
unlockdb();
return undef;
}
flock(SDB,2);
seek(SDB,0,2);
print SDB state2line($state)."\n";
close(SDB);
unlockdb();
$states->{$state->{id}} = $state;
return $state->{id};
}
# =================================================================== savestates
sub savestates {
return 1 if $states eq undef;
my $fn = sdbfn();
return 0 if $fn eq undef;
return 0 if !lockdb();
if (!open(SDB, ">$fn")) {
$lasterror = "Failed to open status database file";
unlockdb();
return 0;
}
flock(SDB,2);
foreach my $id (sort {$a <=> $b} keys %{$states}) {
next if $id !~ /^\d+$/;
print SDB state2line($states->{$id})."\n";
}
close(SDB);
unlockdb();
return 1;
}
# ======================================================================== error
sub error {
return $lasterror;
}
1;
#
+59
View File
@@ -0,0 +1,59 @@
package TTXLogin;
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2002-2005, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 224 $
# $Date: 2006-07-24 11:32:24 -0400 (Mon, 24 Jul 2006) $
#
$TTXLogin::VERSION='2.22';
BEGIN {
$TTXLogin::REVISION = '$Revision: 224 $';
if ($TTXLogin::REVISION =~ /(\d+)/) {
$TTXLogin::REVISION = $1;
}
};
use strict;
use TTXCommon;
require TTXUser;
require TTXSession;
# ======================================================================== login
sub login {
my ($cfg, $query, $data) = @_;
$data->{PAGEHEADING} = '[%Login%]';
return undef if !$query->param('dologin');
if (TTXCommon::cleanit($query, 'login') eq undef) {
$data->{ERROR_MESSAGE} = '[%Missing User ID%]';
return undef;
}
if (TTXCommon::cleanit($query, 'passwd') eq undef) {
$data->{ERROR_MESSAGE} = '[%Missing Password%]';
return undef;
}
my $user = TTXUser->new($query->param('login'));
if ($user eq undef || ($user->get('passwd') eq undef) || ($user->get('passwd') ne $query->param('passwd'))) {
$data->{ERROR_MESSAGE} = '[%Wrong User ID or Password%]';
return undef;
}
$cfg->set('_USER', $user);
my $session = TTXSession->new();
$session->login($query->param('login'));
$user->set('session', $session);
$query->param(-name => 'checkupdate', -value => '1');
$query->param(-name => 'sid', -value => $session->sid());
if ($query->param('nextcmd') ne undef) {
$query->param(-name => 'cmd', -value => $query->param('nextcmd'));
return $query->param('nextcmd');
}
return 'helpdesk';
}
1;
#
+472
View File
@@ -0,0 +1,472 @@
package TTXMSSQLSetup;
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2005-2006, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 203 $
# $Date: 2006-07-18 00:28:33 -0400 (Tue, 18 Jul 2006) $
#
$TTXMSSQLSetup::VERSION='2.22';
BEGIN {
$TTXMSSQLSetup::REVISION = '$Revision: 203 $';
if ($TTXMSSQLSetup::REVISION =~ /(\d+)/) {
$TTXMSSQLSetup::REVISION = $1;
}
};
use TTXConfig;
require TTXUser;
require TTXTickets;
use strict;
my $cfg = {};
my $query = {};
my $newdb;
my $doimport;
my $pwd;
# ======================================================================= setup1
sub setup1 {
$cfg = $_[0];
$query = $_[1];
my $error;
$pwd = cleanit($query, 'pwd');
my $dsn = cleanit($query, 'dbdsn1') || cleanit($query, 'dbdsn') || $cfg->get('dbdsn');
my $user = cleanit($query, 'user') || $cfg->get('dbuser');
my $pass = cleanit($query, 'pass') || $cfg->get('dbpass');
my $prefix = cleanit($query, 'prefix');
$prefix = $cfg->get('dbpref') if !$query->param('do');
my $imgurl = $cfg->get('imgurl');
#
# Check if DBI module installed
#
eval "use DBI";
if ($@ ne undef) {
$error = <<EOT;
The DBI Perl library was not found on this server.<br>
Please install DBI library prior to running this program.<br>
<table cellpadding=5><tr><td align=left><font color=black>Try this:<br>
EOT
if ($^O eq 'MSWin32') {
$error .= <<EOT;
<b>&nbsp;&nbsp;&nbsp;C:\></b><i>ppm.bat</i><br>
<b>&nbsp;&nbsp;&nbsp;ppm></b> <i>install DBI</i><br>
EOT
} else {
$error .= <<EOT;
<b>#</b><i>perl -MCPAN -e shell</i><br>
<b><u>cpan></u></b> <i>install DBI</i><br>
EOT
}
$error .= <<EOT;
</font></td></tr></table>
EOT
}
#
# Check if ODBC DBD driver installed
#
if ($error eq undef) {
my @drivers = DBI->available_drivers(1);
if (!grep(/ODBC/, @drivers)) {
$error = <<EOT;
The ODBC DBD driver was not found on this server.<br>
Please install ODBC DBD driver prior to running this program.<br>
<table cellpadding=5><tr><td align=left><font color=black>Try this:<br>
EOT
my $drv = 'DBD::ODBC';
if ($^O eq 'MSWin32') {
$error .= <<EOT;
<b>&nbsp;&nbsp;&nbsp;C:\></b><i>ppm.bat</i><br>
<b>&nbsp;&nbsp;&nbsp;ppm></b> <i>install $drv</i><br>
EOT
} else {
$error .= <<EOT;
<b>#</b><i>perl -MCPAN -e shell</i><br>
<b><u>cpan></u></b> <i>install $drv</i><br>
EOT
}
$error .= <<EOT;
</font></td></tr></table>
EOT
}
}
#
# Check if any ODBC DSNs defined
#
my @dsns;
if ($error eq undef) {
@dsns = grep {s/^DBI:ODBC://} DBI->data_sources('ODBC');
$error = "No ODBC DSN records found on this server.<br>Please configure DSN prior to running this program."
if !@dsns;
}
# foreach my $d (@dsns) {
# print "$d<br>\n";
# }
if ($error eq undef && $query->param('do')) {
$cfg->set('dbdsn', $dsn);
$cfg->set('dbuser', $user);
$cfg->set('dbpass', $pass);
$cfg->set('dbpref', $prefix);
$doimport = 1 if $cfg->get('dbmode') ne 'mssql';
$error = build($cfg);
if ($error eq undef) {
eval "use TTXMSSQLTickets";
if ($@) {
$cfg->set('dbmode', 'plaintext');
} else {
$cfg->set('dbmode', 'mssql');
$cfg->set('dbschema', '2.22');
}
$cfg->save();
}
}
if ($query->param('do') && $error eq undef ) {
ok();
return;
}
my $warning;
if ($cfg->get('dbmode') eq 'mssql') {
$warning = "YOU HAVE ALREADY ENABLED SQL SERVER MODE<br>\n".
"THIS SCRIPT WILL RESET YOUR TICKETS DATABASE<br>\n".
"ALL TICKETS SUBMITTED USING SQL MODE WILL BE LOST!";
}
$error = "<br><b><font color=red>Error: $error</font></b><br><br>" if $error ne undef;
$warning = "\n<br><b><font color=red>$warning</font></b><br><br>" if $warning ne undef;
print <<EOT;
<center><b>Microsoft SQL Server Module Setup</b><br>
<span class=sm>(go to <a href="setup.cgi?cmd=setup4&pwd=$pwd">Main Setup Utility</a> form)</span>
<br>$error$warning
<form action=$ENV{SCRIPT_NAME} method=post id=mainform>
<input type=hidden name=cmd value=setup1>
<input type=hidden name=do value=1>
<input type=hidden name=pwd value=$pwd>
<table border=0 cellpadding=0 cellspacing=0>
<tr height=1><td colspan=2 align=center height=1 bgcolor="#9b9b9b"><img
src="$imgurl/dot.gif" height=1></td></tr>
<tr><td colspan=2><br>
SQL Server database access info. Please contact your hosting provider or system admin if not sure.
<br><br>
A Data Source Name (DSN) is the logical name that is used by Open Database Connectivity (ODBC)
to refer to the drive and other information that is required to access data. The name is used by
Trouble Ticket Express for a connection to an ODBC data source, such as a Microsoft
SQL Server database. To set this name, use the ODBC tool in Control Panel.<br><br>
</td></tr>
<tr><td align=right><b>DSN:</b></td>
<td>&nbsp;&nbsp;<select name=dbdsn1 onChange="document.forms['mainform'].dbdsn.value='';"><option></option>
EOT
my $dsnval = $dsn;
$dsnval = s/"/&quot;/g;
foreach my $d (@dsns) {
my $quotedsn = $d; $quotedsn =~ s/"/&quot;/g;
my $quotedsn1 = $d; $quotedsn =~ s/</&lt;/g;
print "<option value=\"$quotedsn\"";
if ($d eq $dsn) {
print " selected";
$dsnval = undef;
}
print ">$quotedsn1</option>\n";
}
print <<EOT;
</select>
other: <input type=text name=dbdsn value="$dsnval" onChange="document.forms['mainform'].dbdsn1.options[0].selected=true;">
</td></tr>
<tr><td align=right><b>User:</b></td><td>&nbsp;&nbsp;<input type=text name=user value="$user"></td></tr>
<tr><td align=right><b>Password:</b></td><td>&nbsp;&nbsp;<input type=password name=pass value="$pass"></td></tr>
<tr><td colspan=2 align=center>&nbsp;</td></tr>
<tr height=1><td colspan=2 align=center height=1 bgcolor="#9b9b9b"><img
src="$imgurl/dot.gif" height=1></td></tr>
<tr><td colspan=2><br>
If you have access to a single database or would like to use existing database, you may
provide a prefix, which will be added to the names of all the Trouble
Ticket Express tables.<br><br>
</td></tr>
<tr><td align=right><b>Table prefix</b> (optional)<b>:</b></td><td>&nbsp;&nbsp;<input type=text name=prefix value="$prefix"></td></tr>
<tr><td colspan=2 align=center>
<br><input type=submit value="Save Settings">
<br><br>
The import procedure may take several minutes to complete.<br><b>Do not click twice!</b>
</td></tr>
</form>
</table>
<br>
<br>Login to <a href="ttx.cgi?cmd=login"><b>Trouble Ticket Express</b></a>
</center>
EOT
}
# =========================================================================== ok
sub ok {
print "<center><table width=600><tr><td align=left><center><b>Congratulations!</b></center><br><br>\n";
if ($newdb) {
print "You have created Trouble Ticket Express database and imported existing tickets.\n"
} elsif ($doimport) {
print "You have imported existing tickets into Trouble Ticket Express database.\n"
} else {
print "You are proud owner of the Trouble Ticket Express Microsoft SQL Server Edition.\n".
"Please <b>do not</b> run database setup utility unless you want to make changes to the database settings.\n"
}
print "<br><br>\n";
if ($cfg->get('dbmode') ne 'mssql') {
print <<EOT;
<b>IMPORTANT</b>
Trouble Ticket Express still uses plain text database.
Neither new tickets, nor follow-up messages to existing tickets will be added to the SQL Server database.
In order to enable SQL Server features you must install a SQL Server add-on module to your web server.
The module may be ordered on-line at our web site. After uploading the SQL Server add-on module to your web server,
please run this script once more - it will update your SQL Server database to ensure it includes
recent data from your plain text database and will switch Trouble Ticket Express into SQL Server mode.
<br><br>
<center>
<a href="http://www.troubleticketexpress.com/mssql.html"><b>Order MS SQL add-on module</b></a>
</center>
<br><br>
EOT
} else {
print "Trouble Ticket Express now uses SQL Server database.<br><br>\n";
}
print "<center><a href=\"setup.cgi?cmd=setup4&pwd=$pwd\"><b>Main Setup Utility</b></a><br>".
"<a href=\"ttx.cgi?cmd=login\"><b>Trouble Ticket Express</b></a></center>\n";
print "</td></tr></table></center>\n";
}
# ====================================================================== cleanit
sub cleanit {
my ($query, $input) = @_;
my $val = $query->param($input);
$val =~ s/^\s+//;
$val =~ s/\s+$//;
$query->param(-name => $input, -value => $val);
return $val;
}
# ======================================================================== build
sub build {
my $cfg = $_[0];
$newdb = 0;
my @manda = ('dbdsn', 'dbuser', 'dbpass');
my $id2name = {
dbdsn => 'DSN',
dbuser => 'User ID',
dbpass => 'User Password'
};
my $error;
foreach my $fld (@manda) {
my $val = $cfg->get($fld);
if ($val eq undef) {
$error .= "Missing ".$id2name->{$fld}."<br>\n";
}
}
#
# Step one - connect to ms sql database engine
#
# my $dsn = "DBI:mysql:database=".$cfg->get('dbid').";host=".$cfg->get('dbhost').";port=".$cfg->get('dbport');
my $dbh = DBI->connect('DBI:ODBC:'.$cfg->get('dbdsn'), $cfg->get('dbuser'), $cfg->get('dbpass'),
{RaiseError => 0, AutoCommit => 1});
if (!$dbh) {
return "Error connecting to a database. $DBI::errstr";
}
#
# Still alive? Good. Try to create tables now.
#
my $sth = $dbh->prepare("EXECUTE sp_tables");
$sth->execute();
my %tables;
while (my @row = $sth->fetchrow_array()) {
$tables{$row[2]} = 1;
}
if (!$tables{$cfg->get('dbpref')."tickets"} && !$tables{$cfg->get('dbpref')."messages"}) {
$doimport = 1;
} elsif ($doimport) {
$dbh->do("DROP TABLE ".$cfg->get('dbpref')."tickets") if $tables{$cfg->get('dbpref')."tickets"};
$dbh->do("DROP TABLE ".$cfg->get('dbpref')."messages") if $tables{$cfg->get('dbpref')."messages"};
$tables{$cfg->get('dbpref')."tickets"} = 0;
$tables{$cfg->get('dbpref')."messages"} = 0;
}
foreach my $table ('tickets', 'messages') {
if (!$tables{$cfg->get('dbpref').$table}) {
$error = addtable($dbh, $cfg, $table);
return $error if $error ne undef;
}
}
#
# Import data if needed
#
if ($doimport) {
my @tickfields = TTXTickets::_fields();
my %fldlen = (
email => 128,
name => 128,
oper => 32,
subject => 255,
lname => 50,
grp => 10,
status => 3,
key => 64,
item => 255
);
my $boundary = TTXTickets::_boundary();
my $fn = $cfg->get('ticketdb');
return undef if ! -f $fn;
return "Database import failed: error reading ticket database" if !open(DB, $fn);
my @buff = <DB>;
close DB;
chomp @buff;
$| = 1;
foreach my $line (@buff) {
print "\n";
my @fields = split(/\|/, $line);
my %tik;
my $sql = "INSERT INTO ".$cfg->get('dbpref')."tickets VALUES(";
my $values;
foreach my $fld (@tickfields) {
$tik{$fld} = shift @fields;
$tik{$fld} = '' if $tik{$fld} eq undef;
$values .= ',' if $values ne undef;
if ($fld =~ /^(open|updated|closed)$/) {
$values .= $dbh->quote(gmt($tik{$fld}));
} elsif ($fld eq 'id') {
$values .= $dbh->quote($tik{$fld});
} elsif ($fld =~ /^c\d+$/) {
$values .= $dbh->quote(substr($tik{$fld},0,255));
} else {
$values .= $dbh->quote(substr($tik{$fld},0,$fldlen{$fld}));
}
}
$sql .= "$values)";
if (!$dbh->do($sql)) {
$error = "Error importing ticket #"."$tik{id}. ".$dbh->errstr;
last;
}
my $msgfn = $cfg->get('basedir')."/tickets/$tik{id}.cgi";
if (-f $msgfn && open(MSG, $msgfn)) {
my $rawmsg;
read(MSG, $rawmsg, 64*1024);
close MSG;
my @messages = split(/\n$boundary\n/, $rawmsg);
foreach my $msg (@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;
}
}
my $author = substr($header{FROM},0,32);
my $date = gmt($header{DATE});
my $internal = $header{INTERNAL} ? '1':'0';
my $isoper = $header{OPERATOR} ? '1':'0';
$rawheader = '';
foreach my $hdrkey (sort keys %header) {
next if grep(/^$hdrkey$/, ('FROM', 'DATE', 'INTERNAL', 'BODY', 'OPERATOR'));
$rawheader .= "$hdrkey: $header{$hdrkey}\n";
}
if (!$dbh->do("INSERT INTO ".$cfg->get('dbpref')."messages (TID, AUTHOR, DATE, ISOPER, INTERNAL, HEADERS, MSG) VALUES ".
"('$tik{id}',".$dbh->quote($author).",'$date','$isoper','$internal',".
$dbh->quote($rawheader).','.$dbh->quote($body).')')) {
return "Error importing messages of ticket #"."$tik{id}. ".$dbh->errstr;
}
}
}
}
}
return $error;
}
# ========================================================================== gmt
sub gmt {
my $tm;
if ($_[0] ne undef) { $tm = $_[0]; }
else { $tm = time(); }
my ($s, $min, $h, $d, $m, $y) = (gmtime($tm));
$y += 1900;
++$m;
$m = "0$m" if $m < 10;
$d = "0$d" if $d < 10;
$h = "0$h" if $h < 10;
$min = "0$min" if $min < 10;
$s = "0$s" if $s < 10;
return "$y-$m-$d $h:$min:$s";
}
# ===================================================================== addtable
sub addtable {
my ($dbh, $cfg, $table) = @_;
my $tablename = $cfg->get('dbpref').$table;
my $sql;
if ($table eq 'tickets') {
$sql = <<EOT;
CREATE TABLE $tablename (
ID bigint UNIQUE DEFAULT '' NOT NULL,
ACCESSKEY varchar(64) DEFAULT '' NOT NULL ,
OPENED datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
UPDATED datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
CLOSED datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
STATUS char(3) DEFAULT '' NOT NULL,
OPER varchar(32) DEFAULT '' NOT NULL,
EMAIL varchar(128) DEFAULT '' NOT NULL,
NAME varchar(128) DEFAULT '' NOT NULL,
SUBJECT varchar(255) DEFAULT '' NOT NULL,
LNAME varchar(50) DEFAULT '' NOT NULL,
C0 varchar(255) DEFAULT '' NOT NULL,
C1 varchar(255) DEFAULT '' NOT NULL,
C2 varchar(255) DEFAULT '' NOT NULL,
C3 varchar(255) DEFAULT '' NOT NULL,
C4 varchar(255) DEFAULT '' NOT NULL,
C5 varchar(255) DEFAULT '' NOT NULL,
C6 varchar(255) DEFAULT '' NOT NULL,
C7 varchar(255) DEFAULT '' NOT NULL,
C8 varchar(255) DEFAULT '' NOT NULL,
C9 varchar(255) DEFAULT '' NOT NULL,
GRP varchar(10) DEFAULT '' NOT NULL,
EOT
my $cnt = int ($cfg->get('cfldcnt'));
if (!$cfg->get('itemidx')) {
$cfg->set('itemidx', ($cnt > 10) ? $cnt:10);
$cfg->save();
}
if ($cnt > 10) {
my $i;
for ($i = 10; $i < $cnt; ++$i) {
$sql .= "ITEM varchar(255) DEFAULT '' NOT NULL,\n" if $i == $cfg->get('itemidx');
$sql .= "C$i varchar(255) DEFAULT '' NOT NULL,\n";
}
$sql .= "ITEM varchar(255) DEFAULT '' NOT NULL,\n" if $i == $cfg->get('itemidx');
} else {
$sql .= "ITEM varchar(255) DEFAULT '' NOT NULL,\n";
}
$sql .= "PRIMARY KEY (ID))\n";
} elsif ($table eq 'messages') {
$sql = <<EOT;
CREATE TABLE $tablename (
MID BIGINT IDENTITY PRIMARY KEY,
TID BIGINT NOT NULL DEFAULT '0',
AUTHOR VARCHAR(32) DEFAULT '' NOT NULL ,
DATE DATETIME DEFAULT '0000-00-00 00:00:00' NOT NULL ,
INTERNAL CHAR(1) DEFAULT '0' NOT NULL ,
ISOPER CHAR(1) DEFAULT '0' NOT NULL ,
HEADERS TEXT DEFAULT '' NOT NULL,
MSG TEXT DEFAULT '' NOT NULL
)
EOT
}
$sql =~ s/\n/ /g;
if (!$dbh->do($sql)) {
return "Error creating table $tablename, ".$dbh->errstr;
}
if ($table eq 'messages') {
$dbh->do("CREATE INDEX TID ON $tablename (TID)");
}
return undef;
}
1;
#
+326
View File
@@ -0,0 +1,326 @@
package TTXMail;
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2003-2005, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 189 $
# $Date: 2006-07-11 07:23:08 -0400 (Tue, 11 Jul 2006) $
#
$TTXMail::VERSION='2.22';
BEGIN {
$TTXMail::REVISION = '$Revision: 189 $';
if ($TTXMail::REVISION =~ /(\d+)/) {
$TTXMail::REVISION = $1;
}
};
use strict;
use TTXData;
use TTXMarkup;
my $hasb64 = 1;
$hasb64 = 0 unless eval "require MIME::Base64";
my $mailer;
my $smtphost;
my $usesmtp;
my $CRLF = "\015\012";
my $doemailfix = 0;
# ====================================================================== charset
my $_charset;
sub charset {
if ($_charset eq undef) {
$_charset = TTXData::get('CONFIG')->get('charset') || 'ISO-8859-1';
}
return $_charset;
}
# ======================================================================= encode
sub encode {
return $_[0] if $_[0] !~ /[^a-zA-Z0-9 ()[\]_!\/\\{}"';:?<>@#\$%&*\n\r.,-]/;
return "=?".charset()."?B?".base64($_[0], "")."?=" if !$_[1];
my $adr = $_[0];
$adr =~ s/"[^"]*"//;
$adr =~ s/^[^<]*<//g;
$adr =~ s/>[^>]*$//g;
$adr =~ s/^\s+//;
$adr =~ s/\s+$//;
my $name = $_[0];
$name =~ s/<[^>]*>//g;
$name =~ s/"//g;
$name =~ s/[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+//g;
$name =~ s/^\s+//;
$name =~ s/\s+$//;
$name =~ s/\s\s+/ /;
$name = "=?".charset()."?B?".base64($name, "")."?=" if $name ne undef;
$name =~ s/\r?\n\r?\s+/ /g;
my $str;
if ($name ne undef) {
$str = "\"$name\" ";
}
$str .= "<$adr>";
return $str;
}
# ========================================================================= smtp
sub smtp {
if ($usesmtp eq undef) {
if ($mailer ne undef && -x $mailer) {
$usesmtp = 0;
} else {
$usesmtp = 1;
unless (eval "require Net::SMTP") { $usesmtp = 0; }
}
}
return $usesmtp;
}
# ===================================================================== sendmail
sub sendmail {
my $cfg = TTXData::get('CONFIG');
$doemailfix = $cfg->get('emailfix');
if ($cfg->get('broadcast') ne undef) {
$_[0]->{bcc} = $cfg->get('broadcast');
}
$mailer = $cfg->get('mailer');
$smtphost = $cfg->get('smtp');
my $html = $_[0]->{msg};
my $msg = TTXMarkup::strip($html);
srand($$);
my $rnd;
for(my $i = 0; $i < 20; $i++) { $rnd .= int rand 10; }
my $boundary = "------------$rnd";
my $txtboundary = $boundary;
# my $contenttype = "MIME-Version: 1.0\nContent-Type: text/plain; charset=\"".charset()."\"\nContent-Transfer-Encoding: quoted-printable";
my $contenttype = "MIME-Version: 1.0\nContent-Type: multipart/alternative;\n boundary=\"$boundary\"";
my $datetag;
if ($cfg->get('maildatetag')) {
my ($sec,$min,$hour,$mday,$mon,$year,$wday) = gmtime(time());
$year += 1900;
my @mabbr = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
my @wabbr = qw(Sun Mon Tue Wed Thu Fri Sat);
$datetag = "Date: $wabbr[$wday], $mday $mabbr[$mon] $year ".
sprintf("%02u:%02u:%02u", $hour, $min, $sec).
" +0000\n";
}
if (!smtp()) {
return 0 if !open(MAIL, "|$mailer -t");
my $bcc = "Bcc: ".$_[0]->{bcc}."\n" if $_[0]->{bcc} ne undef;
print MAIL "To: ".$_[0]->{to}."\nFrom: ".encode($_[0]->{from}, 1)."\n".$bcc.
"Subject: ".encode($_[0]->{subject}, 0).
"\n$datetag$contenttype\n\n".
"This is a multi-part message in MIME format\n\n".
"--$txtboundary\nContent-type: text/plain; charset=\"".charset()."\"\n".
"Content-Transfer-Encoding: quoted-printable\n\n".
quoteit($msg)."\n\n";
print MAIL "\n\n--$txtboundary\nContent-type: text/html; charset=\"".charset()."\"\n".
"Content-Transfer-Encoding: base64\n\n";
print MAIL base64(htmlpage($html));
print MAIL "\n--$txtboundary--\n";
close MAIL;
} else {
my $to = $_[0]->{to};
$to =~ s/"[^"]*"//;
$to =~ s/^[^<]*<//g;
$to =~ s/>[^>]*$//g;
$to =~ s/^\s+//;
$to =~ s/\s+$//;
my $from = $_[0]->{from};
$from =~ s/"[^"]*"//;
$from =~ s/^[^<]*<//g;
$from =~ s/>[^>]*$//g;
$from =~ s/^\s+//;
$from =~ s/\s+$//;
if ($cfg->get('smtptrace')) {
# save original STDERR destination
open SAVERR, ">&STDERR";
# redirect STDERR handle to a file
open STDERR, '>>'.$cfg->get('basedir').'/smtptrace.txt';
my $oldfh = select STDERR; $| = 1; select($oldfh); # make unbuffered
}
my $s = Net::SMTP->new($smtphost, Debug => $cfg->get('smtptrace') ? 1:0);
if ($s ne undef) {
if ($cfg->get('smtplogin') ne undef) {
my $trypop3 = 0;
if ($s->can('auth')) {
eval 'use Authen::SASL';
if ($@ ne undef) {
if ($cfg->get('smtptrace')) {
warn $@;
warn "No SASL";
$trypop3 = 1;
}
} else {
my $authcode;
eval "\$authcode = \$s->auth(\$cfg->get('smtplogin'), \$cfg->get('smtppwd'));";
if ($@ ne undef) {
$trypop3 = 1;
if ($cfg->get('smtptrace')) {
warn $@;
}
} elsif (!$authcode) {
$trypop3 = 1;
if ($cfg->get('smtptrace')) {
warn "auth(login, passwd) failed";
}
}
}
} else {
$trypop3 = 1;
if ($cfg->get('smtptrace')) {
warn "No auth() method";
}
}
if ($trypop3) {
if ($cfg->get('smtptrace')) {
warn 'Trying Net::POP3';
}
eval "use Net::POP3;";
if ($@ ne undef) {
if ($cfg->get('smtptrace')) {
warn $@;
}
} else {
my $pop = Net::POP3->new($smtphost);
if (!$pop) { warn "Can't open connection to pop3 server: $!"; }
elsif (!defined ($pop->login($cfg->get('smtplogin'), $cfg->get('smtppwd')))) {
warn "Can't authenticate: $!";
} else {
my $messages = $pop->list();
$pop->quit();
}
}
}
}
$s->mail($from);
if ($_[0]->{bcc} ne undef) {
$s->to($to, $_[0]->{bcc});
} else {
$s->to($to);
}
$s->data();
$s->datasend("To: ".$_[0]->{to}."\n");
$s->datasend("From: ".encode($_[0]->{from}, 1)."\n");
$s->datasend("Subject: ".encode($_[0]->{subject}, 0).
"\n$datetag$contenttype\n\nThis is a multi-part message in MIME format\n\n");
$s->datasend( "--$txtboundary\nContent-type: text/plain; charset=\"".charset()."\"\n".
"Content-Transfer-Encoding: quoted-printable\n\n".
quoteit($msg)."\n\n");
$s->datasend("--$txtboundary\nContent-type: text/html; charset=\"".charset()."\"\n".
"Content-Transfer-Encoding: base64\n\n");
$s->datasend(base64(htmlpage($html)));
$s->datasend("\n--$txtboundary--\n\n");
$s->dataend();
$s->quit();
if ($cfg->get('smtptrace')) {
# restore original STDERR destination
open STDERR, ">&SAVERR";
}
}
}
return 1;
}
# ====================================================================== quoteit
sub quoteit {
my $in = shift;
my $out;
local $_;
$in =~ s/\015?\012/\n/g;
while (1) {
$in =~ s/^(.*?(?:(?:\n)|\Z))//m;
$_ = $1;
(defined and length) or last;
s/([^ \t\n!-<>-~])/sprintf("=%02X", ord($1))/eg;
s/([ \t]+)$/join('', map { sprintf("=%02X", ord($_)) } split('', $1))/egm;
my $brokenlines = "";
$brokenlines .= "$1=\n"
while s/(.*?^[^\n]{73} (?:
[^=\n]{2} (?! [^=\n]{0,1} $)
|[^=\n] (?! [^=\n]{0,2} $)
| (?! [^=\n]{0,3} $)
))//xsm;
$_ = "$brokenlines$_";
if (length($_) < 74) {
s/^\.$/=2E/g;
s/^From /=46rom /g;
}
s/\015?\012/$CRLF/g;
$out .= $_;
(defined($in) and length($in)) or last;
}
$out =~ s/\015//g if $doemailfix;
return $out;
}
# ======================================================================= base64
sub base64 {
my $in = $_[0];
my $out;
my $eol = $_[1];
$eol = "\n" unless defined $eol;
while (1) {
my ($buf, $b64);
last unless length $in;
$buf = substr($in, 0, 45);
substr($in, 0, 45) = '';
if ($hasb64) {
$b64 = MIME::Base64::encode_base64($buf, $eol);
} else {
$b64 = _b64($buf, $eol);
}
$b64 =~ s/\015?\012/$CRLF/g;
$b64 .= $CRLF if length $eol && $b64 !~ /$CRLF\Z/;
$out .= $b64;
}
return $out;
}
# ========================================================================= _b64
sub _b64 {
my $out = "";
my $eol = $_[1];
$eol = "\n" unless defined $eol;
pos($_[0]) = 0;
while ($_[0] =~ /(.{1,45})/gs) {
$out .= substr(pack('u', $1), 1);
chop($out);
}
$out =~ tr|` -_|AA-Za-z0-9+/|;
my $padding = (3 - length($_[0]) % 3) % 3;
$out =~ s/.{$padding}$/'=' x $padding/e if $padding;
if (length $eol) {
$out =~ s/(.{1,76})/$1$eol/g;
}
return $out;
}
# ===================================================================== htmlpage
sub htmlpage {
my $pg = $_[0];
$pg =~ s/\r//g;
$pg =~ s/\n/<br \/>\n/g;
$pg = TTXMarkup::html($pg);
my $buff = <<EOT;
<html>
<head>
<style type="text/css">
.dummy {}
body, td {font-family: verdana,arial,helvetica,sans-serif;font-size: 10pt;color: #000000;}
</style>
</head>
<body>
$pg
</body>
</html>
EOT
return $buff;
}
1;
#
+55
View File
@@ -0,0 +1,55 @@
package TTXMarkup;
#
# Markup language pack/upack routines
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2004-2005, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 156 $
# $Date: 2006-05-05 03:02:47 -0400 (Fri, 05 May 2006) $
#
#
$TTXMarkup::VERSION='2.22';
BEGIN {
$TTXMarkup::REVISION = '$Revision: 156 $';
if ($TTXMarkup::REVISION =~ /(\d+)/) {
$TTXMarkup::REVISION = $1;
}
};
use strict;
# ========================================================================= html
sub html {
my $buff = shift;
$buff =~ s/\[(\/?)(u|b|i|code)]/<$1$2>/gi; # [b] [i] [u] [code]
$buff =~ s/\[\(]/[/g; # [[]
$buff =~ s/\[url\s+([^]\s]+)\s*]/<a href="$1" target=_blank>/gi;
$buff =~ s/\[\/url\s*]/<\/a>/gi;
$buff =~ s/\[(image|img)\s+([^]\s]+)\s*]/<img src="$2">/gi;
$buff =~ s/\[\/(image|img)\s*]/<\/img>/gi;
$buff =~ s/ /&nbsp; /g;
return $buff;
}
# ========================================================================= help
sub help {
return undef;
}
# ======================================================================== strip
sub strip {
my $buff = shift;
$buff =~ s/\[(\/?)(u|b|i|code)]//gi; # [b] [i] [u] [code]
$buff =~ s/\[\(]/[/g; # [[]
$buff =~ s/\[url\s+([^]\s]+)\s*]/$1 /gi;
$buff =~ s/\[\/url\s*]/ /gi;
$buff =~ s/\[(image|img)\s+([^]\s]+)\s*]/$2 /gi;
$buff =~ s/\[\/(image|img)\s*]//gi;
return $buff;
}
1;
#
+429
View File
@@ -0,0 +1,429 @@
package TTXMySQLSetup;
#
# 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: 203 $
# $Date: 2006-07-18 00:28:33 -0400 (Tue, 18 Jul 2006) $
#
$TTXMySQLSetup::VERSION='2.22';
BEGIN {
$TTXMySQLSetup::REVISION = '$Revision: 203 $';
if ($TTXMySQLSetup::REVISION =~ /(\d+)/) {
$TTXMySQLSetup::REVISION = $1;
}
};
use TTXConfig;
require TTXUser;
require TTXTickets;
use strict;
my $cfg = {};
my $query = {};
my $newdb;
my $doimport;
my $pwd;
# ======================================================================= setup1
sub setup1 {
$cfg = $_[0];
$query = $_[1];
my $error;
$pwd = cleanit($query, 'pwd');
my $dbid = cleanit($query, 'dbid') || $cfg->get('dbid');
my $host = cleanit($query, 'host') || $cfg->get('dbhost') || 'localhost';
my $port = cleanit($query, 'port') || $cfg->get('dbport') || 3306;
my $user = cleanit($query, 'user') || $cfg->get('dbuser');
my $pass = cleanit($query, 'pass') || $cfg->get('dbpass');
my $prefix = cleanit($query, 'prefix');
$prefix = $cfg->get('dbpref') if !$query->param('do');
my $imgurl = $cfg->get('imgurl');
#
# Check if DBI module installed
#
eval "use DBI";
$error = "The DBI Perl library was not found on this server.<br>Please install DBI library prior to running this program." if $@;
#
# Check if MySQL DBD driver installed
#
if ($error eq undef) {
my @drivers = DBI->available_drivers(1);
$error = "The MySQL DBD driver was not found on this server.<br>Please install MySQL DBD driver prior to running this program."
if !grep(/mysql/, @drivers);
}
if ($error eq undef && $query->param('do')) {
$cfg->set('dbid', $dbid);
$cfg->set('dbhost', $host);
$cfg->set('dbport', $port);
$cfg->set('dbuser', $user);
$cfg->set('dbpass', $pass);
$cfg->set('dbpref', $prefix);
$doimport = 1 if $cfg->get('dbmode') ne 'mysql';
$error = build($cfg);
if ($error eq undef) {
eval "use TTXMySQLTickets";
if ($@) {
$cfg->set('dbmode', 'plaintext');
} else {
$cfg->set('dbmode', 'mysql');
$cfg->set('dbschema', '2.22');
}
$cfg->save();
}
}
if ($query->param('do') && $error eq undef ) {
ok();
return;
}
my $warning;
if ($cfg->get('dbmode') eq 'mysql') {
$warning = "YOU HAVE ALREADY ENABLED MYSQL MODE<br>\n".
"THIS SCRIPT WILL RESET YOUR TICKETS DATABASE<br>\n".
"ALL TICKETS SUBMITTED USING MYSQL MODE WILL BE LOST!";
}
$error = "<br><b><font color=red>Error: $error</font></b><br><br>" if $error ne undef;
$warning = "\n<br><b><font color=red>$warning</font></b><br><br>" if $warning ne undef;
print <<EOT;
<center><b>MySQL Module Setup</b><br>
<span class=sm>(go to <a href="setup.cgi?cmd=setup4&pwd=$pwd">Main Setup Utility</a> form)</span>
<br>$error$warning
<form action=$ENV{SCRIPT_NAME} method=post>
<input type=hidden name=cmd value=setup1>
<input type=hidden name=do value=1>
<input type=hidden name=pwd value=$pwd>
<table border=0 cellpadding=0 cellspacing=0>
<tr height=1><td colspan=2 align=center height=1 bgcolor="#9b9b9b"><img
src="$imgurl/dot.gif" height=1></td></tr>
<tr><td colspan=2><br>
MySQL database access info. Please contact your hosting provider or system admin if not sure.<br><br>
</td></tr>
<tr><td align=right><b>MySQL Host:</b></td><td>&nbsp;&nbsp;<input type=text name=host value="$host"></td></tr>
<tr><td align=right><b>MySQL Port:</b></td><td>&nbsp;&nbsp;<input type=text name=port value="$port"></td></tr>
<tr><td align=right><b>Database ID:</b></td><td>&nbsp;&nbsp;<input type=text name=dbid value="$dbid"></td></tr>
<tr><td align=right><b>MySQL User:</b></td><td>&nbsp;&nbsp;<input type=text name=user value="$user"></td></tr>
<tr><td align=right><b>MySQL Password:</b></td><td>&nbsp;&nbsp;<input type=password name=pass value="$pass"></td></tr>
<tr><td colspan=2 align=center>&nbsp;</td></tr>
<tr height=1><td colspan=2 align=center height=1 bgcolor="#9b9b9b"><img
src="$imgurl/dot.gif" height=1></td></tr>
<tr><td colspan=2><br>
If you have access to a single database or would like to use existing database, you may
provide a prefix, which will be added to the names of all the Trouble
Ticket Express tables.<br><br>
</td></tr>
<tr><td align=right><b>Table prefix</b> (optional)<b>:</b></td><td>&nbsp;&nbsp;<input type=text name=prefix value="$prefix"></td></tr>
<tr><td colspan=2 align=center>
<br><input type=submit value="Save Settings">
</td></tr>
</form>
</table>
<br>
<br>Login to <a href="ttx.cgi?cmd=login"><b>Trouble Ticket Express</b></a>
</center>
EOT
}
# =========================================================================== ok
sub ok {
print "<center><table width=600><tr><td align=left><center><b>Congratulations!</b></center><br><br>\n";
if ($newdb) {
print "You have created Trouble Ticket Express database and imported existing tickets.\n"
} elsif ($doimport) {
print "You have imported existing tickets into Trouble Ticket Express database.\n"
} else {
print "You are proud owner of the Trouble Ticket Express MySQL Edition.\n".
"Please do not run database setup utility unless you want to make changes to the database settings.\n"
}
print "<br><br>\n";
if ($cfg->get('dbmode') ne 'mysql') {
print <<EOT;
<b>IMPORTANT</b>
Trouble Ticket Express still uses plain text database.
Neither new tickets, nor follow-up messages to existing tickets will be added to the MySQL database.
In order to enable MySQL features you must install a MySQL add-on module to your web server.
The module may be ordered on-line at our web site. After uploading the MySQL add-on module to your web server,
please run this script once more - it will update your MySQL database to ensure it includes
recent data from your plain text database and will switch Trouble Ticket Express into MySQL mode.
<br><br>
<center>
<a href="http://www.troubleticketexpress.com/mysql.html"><b>Order MySQL add-on module</b></a>
</center>
<br><br>
EOT
} else {
print "Trouble Ticket Express now uses MySQL database.<br><br>\n";
}
print "<center><a href=\"setup.cgi?cmd=setup4&pwd=$pwd\"><b>Main Setup Utility</b></a><br>".
"<a href=\"ttx.cgi?cmd=login\"><b>Trouble Ticket Express</b></a></center>\n";
print "</td></tr></table></center>\n";
}
# ====================================================================== cleanit
sub cleanit {
my ($query, $input) = @_;
my $val = $query->param($input);
$val =~ s/^\s+//;
$val =~ s/\s+$//;
$query->param(-name => $input, -value => $val);
return $val;
}
# ======================================================================== build
sub build {
my $cfg = $_[0];
$newdb = 0;
my @manda = ('dbid', 'dbuser', 'dbpass');
my $id2name = {
dbid => 'Database ID',
dbuser => 'MySQL User ID',
dbpass => 'MySQL User Password'
};
my $error;
foreach my $fld (@manda) {
my $val = $cfg->get($fld);
if ($val eq undef) {
$error .= "Missing ".$id2name->{$fld}."<br>\n";
}
}
#
# Step one - connect to mysql database engine
#
my $dsn = "DBI:mysql:database=".$cfg->get('dbid').";host=".$cfg->get('dbhost').";port=".$cfg->get('dbport');
my $dbh = DBI->connect($dsn, $cfg->get('dbuser'), $cfg->get('dbpass'),
{RaiseError => 0, AutoCommit => 1});
if (!$dbh) {
# got to check as to why
if ($DBI::err !~ /\b1049\b/) {
$error = "Error connecting to a database. $DBI::errstr";
return $error;
} else {
# Well, we are allowed to connect but database does not exist.
# Will try to create...
my $drh = DBI->install_driver('mysql');
if (!$drh) {
$error = "Error loading mysql DBD driver. $DBI::errstr";
return $error;
}
my $rc = $drh->func('createdb',
$cfg->get('dbid'),
$cfg->get('dbhost'),
$cfg->get('dbuser'),
$cfg->get('dbpass'),
'admin');
if (!$rc) {
$error = "Failed to create database '".$cfg->get('dbid')."'";
return $error;
}
$newdb = 1;
$dbh = DBI->connect($dsn, $cfg->get('dbuser'), $cfg->get('dbpass'),
{RaiseError => 0, AutoCommit => 1});
if (!$dbh) {
$error = "Error connecting to a database. $DBI::errstr";
return $error;
}
}
}
#
# Still alive? Good. Try to create tables now.
#
my $sth = $dbh->prepare("SHOW TABLES");
$sth->execute();
my %tables;
while (my @row = $sth->fetchrow_array()) {
$tables{$row[0]} = 1;
}
if (!$tables{$cfg->get('dbpref')."tickets"} && !$tables{$cfg->get('dbpref')."messages"}) {
$doimport = 1;
} elsif ($doimport) {
$dbh->do("DROP TABLE ".$cfg->get('dbpref')."tickets") if $tables{$cfg->get('dbpref')."tickets"};
$dbh->do("DROP TABLE ".$cfg->get('dbpref')."messages") if $tables{$cfg->get('dbpref')."messages"};
$tables{$cfg->get('dbpref')."tickets"} = 0;
$tables{$cfg->get('dbpref')."messages"} = 0;
}
foreach my $table ('tickets', 'messages') {
if (!$tables{$cfg->get('dbpref').$table}) {
$error = addtable($dbh, $cfg, $table);
return $error if $error ne undef;
}
}
#
# Import data if needed
#
if ($doimport) {
my @tickfields = TTXTickets::_fields();
my $boundary = TTXTickets::_boundary();
my $fn = $cfg->get('ticketdb');
return undef if ! -f $fn;
return "Database import failed: error reading ticket database" if !open(DB, $fn);
my @buff = <DB>;
close DB;
chomp @buff;
$| = 1;
$dbh->do("SET AUTOCOMMIT=0;");
my $cmtcnt = 0;
foreach my $line (@buff) {
print "\n";
++$cmtcnt;
if ($cmtcnt > 99) {
$dbh->do("COMMIT;");
$cmtcnt = 0;
}
my @fields = split(/\|/, $line);
my %tik;
my $sql = "INSERT IGNORE INTO ".$cfg->get('dbpref')."tickets VALUES(";
my $values;
foreach my $fld (@tickfields) {
$tik{$fld} = shift @fields;
$tik{$fld} = '' if $tik{$fld} eq undef;
$values .= ',' if $values ne undef;
if ($fld =~ /^(open|updated|closed)$/) {
$values .= $dbh->quote(gmt($tik{$fld}));
} else {
$values .= $dbh->quote($tik{$fld});
}
}
$sql .= "$values)";
if (!$dbh->do($sql)) {
$error = "Error importing ticket #"."$tik{id}. ".$dbh->errstr;
last;
}
my $msgfn = $cfg->get('basedir')."/tickets/$tik{id}.cgi";
if (-f $msgfn && open(MSG, $msgfn)) {
my $rawmsg;
read(MSG, $rawmsg, 64*1024);
close MSG;
my @messages = split(/\n$boundary\n/, $rawmsg);
foreach my $msg (@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;
}
}
my $author = $header{FROM} || '-';
my $date = gmt($header{DATE});
my $internal = $header{INTERNAL} ? '1':'0';
my $isoper = $header{OPERATOR} ? '1':'0';
$rawheader = '';
foreach my $hdrkey (sort keys %header) {
next if grep(/^$hdrkey$/, ('FROM', 'DATE', 'INTERNAL', 'BODY', 'OPERATOR'));
$rawheader .= "$hdrkey: $header{$hdrkey}\n";
}
if (!$dbh->do("INSERT IGNORE INTO ".$cfg->get('dbpref')."messages (TID, AUTHOR, DATE, ISOPER, INTERNAL, HEADERS, MSG) VALUES ".
"('$tik{id}',".$dbh->quote($author).",'$date','$isoper','$internal',".
$dbh->quote($rawheader).','.$dbh->quote($body).')')) {
return "Error importing messages of ticket #"."$tik{id}. ".$dbh->errstr;
}
}
}
}
$dbh->do("COMMIT");
}
return $error;
}
# ========================================================================== gmt
sub gmt {
my $tm;
if ($_[0] ne undef) { $tm = $_[0]; }
else { $tm = time(); }
my ($s, $min, $h, $d, $m, $y) = (gmtime($tm));
$y += 1900;
++$m;
$m = "0$m" if $m < 10;
$d = "0$d" if $d < 10;
$h = "0$h" if $h < 10;
$min = "0$min" if $min < 10;
$s = "0$s" if $s < 10;
return "$y-$m-$d $h:$min:$s";
}
# ===================================================================== addtable
sub addtable {
my ($dbh, $cfg, $table) = @_;
my $tablename = $cfg->get('dbpref').$table;
my $sql;
if ($table eq 'tickets') {
$sql = <<EOT;
CREATE TABLE $tablename (
ID bigint(20) DEFAULT '0' NOT NULL ,
ACCESSKEY varchar(64) DEFAULT '' NOT NULL ,
OPEN datetime DEFAULT '0000-00-00 00:00:00' NOT NULL ,
UPDATED datetime DEFAULT '0000-00-00 00:00:00' NOT NULL ,
CLOSED datetime DEFAULT '0000-00-00 00:00:00' NOT NULL ,
STATUS char(3) DEFAULT '' NOT NULL ,
OPER varchar(32) DEFAULT '' NOT NULL ,
EMAIL varchar(128) DEFAULT '' NOT NULL ,
NAME varchar(128) DEFAULT '' NOT NULL ,
SUBJECT varchar(255) DEFAULT '' NOT NULL ,
LNAME varchar(50) DEFAULT '' NOT NULL ,
C0 varchar(255) DEFAULT '' NOT NULL ,
C1 varchar(255) DEFAULT '' NOT NULL ,
C2 varchar(255) DEFAULT '' NOT NULL ,
C3 varchar(255) DEFAULT '' NOT NULL ,
C4 varchar(255) DEFAULT '' NOT NULL ,
C5 varchar(255) DEFAULT '' NOT NULL ,
C6 varchar(255) DEFAULT '' NOT NULL ,
C7 varchar(255) DEFAULT '' NOT NULL ,
C8 varchar(255) DEFAULT '' NOT NULL ,
C9 varchar(255) DEFAULT '' NOT NULL ,
GRP varchar(10) DEFAULT '' NOT NULL ,
EOT
my $cnt = int ($cfg->get('cfldcnt'));
if (!$cfg->get('itemidx')) {
$cfg->set('itemidx', ($cnt > 10) ? $cnt:10);
$cfg->save();
}
if ($cnt > 10) {
my $i;
for ($i = 10; $i < $cnt; ++$i) {
$sql .= "ITEM varchar(255) DEFAULT '' NOT NULL,\n" if $i == $cfg->get('itemidx');
$sql .= "C$i varchar(255) DEFAULT '' NOT NULL,\n";
}
$sql .= "ITEM varchar(255) DEFAULT '' NOT NULL,\n" if $i == $cfg->get('itemidx');
} else {
$sql .= "ITEM varchar(255) DEFAULT '' NOT NULL,\n";
}
$sql .= <<EOT;
PRIMARY KEY (ID),
UNIQUE ID (ID),
KEY ID_2 (ID)
)
EOT
} elsif ($table eq 'messages') {
$sql = <<EOT;
CREATE TABLE $tablename (
MID BIGINT AUTO_INCREMENT NOT NULL,
TID BIGINT NOT NULL DEFAULT '0',
AUTHOR VARCHAR(32) DEFAULT '' NOT NULL ,
DATE DATETIME DEFAULT '0000-00-00 00:00:00' NOT NULL ,
INTERNAL CHAR(1) DEFAULT '0' NOT NULL ,
ISOPER CHAR(1) DEFAULT '0' NOT NULL ,
HEADERS TEXT DEFAULT '' NOT NULL,
MSG TEXT DEFAULT '' NOT NULL,
PRIMARY KEY (MID),
UNIQUE ID (MID),
KEY TID (TID)
)
EOT
}
$sql =~ s/\n/ /g;
if (!$dbh->do($sql)) {
return "Error creating table $tablename, ".$dbh->errstr;
}
return undef;
}
1;
#
+53
View File
@@ -0,0 +1,53 @@
package TTXOpers;
#
# 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: 224 $
# $Date: 2006-07-24 11:32:24 -0400 (Mon, 24 Jul 2006) $
#
$TTXOpers::VERSION='2.22';
BEGIN {
$TTXOpers::REVISION = '$Revision: 224 $';
if ($TTXOpers::REVISION =~ /(\d+)/) {
$TTXOpers::REVISION = $1;
}
};
use strict;
use TTXUser;
# ===================================================================== selector
sub selector {
my ($cfg, $query, $data) = @_;
$data->{OPERSELSTD} = '<tr><td align=right class=lbl>[%Assign to%]</td>'."\n<td align=left>";
$data->{OPERSEL} = "<select name=oper>\n".'<option value="">-- [%please select%] --</option>'."\n".
"<option value=\"-\"";
$data->{OPERSEL} .= ' selected' if $query->param('oper') eq '-';
$data->{OPERSEL} .= '>-- [%any operator%] --</option>'."\n";
my @operlist = TTXUser::list();
my %operinfo;
foreach my $id (@operlist) {
my $u = TTXUser->new($id);
next if $u eq undef;
$operinfo{$id} = $u;
}
foreach my $id (sort {uc($operinfo{$a}->{lname}) cmp uc($operinfo{$b}->{lname})} keys %operinfo) {
my $oper = $operinfo{$id}->{fname}.' '.$operinfo{$id}->{lname};
next if $oper eq undef || $oper eq '';
$oper =~ s/</&quot;/g;
$data->{OPERSEL} .= "<option value=\"$id\"";
$data->{OPERSEL} .= ' selected' if $query->param('oper') eq $id;
$data->{OPERSEL} .= ">$oper</option>\n";
}
$data->{OPERSEL} .= '</select>';
$data->{OPERSELSTD} .= $data->{OPERSEL} . "</td></tr>\n";
}
1;
#
+9
View File
@@ -0,0 +1,9 @@
package TTXOrder;
use strict;
# ==================================================================== answerlib
sub answerlib {
}
1;
#
+79
View File
@@ -0,0 +1,79 @@
package TTXPickTime;
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2002-2005, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 126 $
# $Date: 2006-02-06 05:47:42 -0500 (Mon, 06 Feb 2006) $
#
$TTXPickTime::VERSION='2.22';
BEGIN {
$TTXPickTime::REVISION = '$Revision: 126 $';
if ($TTXPickTime::REVISION =~ /(\d+)/) {
$TTXPickTime::REVISION = $1;
}
};
use strict;
# ===================================================================== picktime
sub picktime {
my ($query, $pref, $start) = @_;
my $buff;
my $sec = $query->param($pref.'sec');
my $min = $query->param($pref.'min');
my $hour = $query->param($pref.'hour');
if ($sec =~ /\D/ || $sec > 59) {
$sec = '';
}
if ($min =~ /\D/ || $min > 59) {
$min = '';
}
if ($hour =~ /\D/ || $hour > 23) {
$hour = '';
}
if ($hour eq '') {
$min = '';
$sec = '';
} else {
if ($min eq '') {
$min = $start ? 0:59;
$sec = $start ? 0:59;
} elsif ($sec eq '') {
$sec = $start ? 0:59;
}
}
$query->param(-name => $pref.'sec', -value => $sec);
$query->param(-name => $pref.'min', -value => $min);
$query->param(-name => $pref.'hour', -value => $hour);
$buff .= "<select name=$pref"."hour>\n<option></option>\n";
for (my $i = 0; $i < 24; ++$i) {
$buff .= '<option';
$buff .= ' selected' if $hour == $i;
$buff .= ">$i</option>\n";
}
$buff .= "</select>\n<select name=$pref"."min>\n<option></option>\n";
for (my $i = 0; $i < 60; $i += 5) {
if ($min < $i && $min > ($i - 5)) {
my $j = $min;
if ($j =~ /^\d$/) { $j = "0$j"; }
$buff .= "<option value=$min selected>$j</option>\n";
}
$buff .= "<option value=$i";
$buff .= ' selected' if $min ne '' && $min == $i;
my $j = $i;
if ($j =~ /^\d$/) { $j = "0$j"; }
$buff .= ">$j</option>\n";
}
$buff .= "</select>\n<input type=hidden name=$pref"."sec value=$sec>\n";
return $buff;
}
1;
#
+36
View File
@@ -0,0 +1,36 @@
package TTXPreview;
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2006, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 224 $
# $Date: 2006-07-24 11:32:24 -0400 (Mon, 24 Jul 2006) $
#
$TTXPreview::VERSION='2.22';
BEGIN {
$TTXPreview::REVISION = '$Revision: 224 $';
if ($TTXPreview::REVISION =~ /(\d+)/) {
$TTXPreview::REVISION = $1;
}
};
use strict;
use TTXCommon;
require TTXMarkup;
# ======================================================================== print
sub preview {
my ($cfg, $query, $data) = @_;
$data->{PAGEHEADING} = '[%Message Preview%]';
my $body = TTXCommon::cleanit($query, 'msg');
$body =~ s/</&lt;/g;
$body = TTXMarkup::html($body);
$body =~ s/\n/<br>\n/g;
$data->{MESSAGE} = $body;
return undef;
}
1;
#
+840
View File
@@ -0,0 +1,840 @@
package TTXReports;
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2002-2005, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 224 $
# $Date: 2006-07-24 11:32:24 -0400 (Mon, 24 Jul 2006) $
#
$TTXReports::VERSION='2.22';
BEGIN {
$TTXReports::REVISION = '$Revision: 224 $';
if ($TTXReports::REVISION =~ /(\d+)/) {
$TTXReports::REVISION = $1;
}
};
use strict;
use TTXCommon;
use TTXConfig;
require TTXUser;
require TTXBarChart;
require TTXDictionary;
my @months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
# =================================================================== checkpoint
sub checkpoint {
my $cfg = $_[0];
my $grantlist = $cfg->get('grant.reports');
if ($grantlist ne undef) {
my $uid = $cfg->get('_USER')->get('login');
if (!grep(/^$uid$/, split(/,/,$grantlist))) {
return 0;
}
}
return 1;
}
# ========================================================================= main
sub main {
my ($cfg, $query, $data) = @_;
return 'helpdesk' if !checkpoint($cfg);
for (my $i = 0; $i < 12; ++$i) {
$months[$i] = TTXDictionary::translate($months[$i]);
}
my $basewidth = $cfg->get('HTMLBASEWIDTH') || 700;
my %rtitle = (
overview => 'Overview',
operperf => 'Operator Performance',
aging360 => 'Ticket Aging',
aging => 'Hot Tickets',
slevel => 'Service Level'
);
$data->{PAGEHEADING} = '[%Reports%]';
$data->{REPORTQUERY} =<<EOT;
<table cellpadding=5>
<tr>
<td align=left>
<select name=rtype size=1>
EOT
if ($query->param('rtype') eq undef) {
$data->{REPORTQUERY} .= '<option value="">-- [%Select Report%] --</option>';
}
foreach my $rtype ('overview', 'operperf', 'aging360', 'aging', 'slevel') {
next if $rtype eq 'slevel' && !$cfg->get('opersla');
$data->{REPORTQUERY} .= "<option value=$rtype";
$data->{REPORTQUERY} .= ' selected' if $query->param('rtype') eq $rtype;
$data->{REPORTQUERY} .= '>[%'.$rtitle{$rtype}.'%]</option>'."\n";
}
$data->{REPORTQUERY} .=<<EOT;
</select>
</td>
</tr>
</table>
EOT
return undef if !$query->param('do');
$query->param(-name => 'do', -value => '');
my $rtype = TTXCommon::cleanit($query, 'rtype');
if ($rtype eq undef) {
$data->{REPORT} = "<center><b>[%No report selected%]</b><br><br></center>\n";
} elsif ($rtype eq 'overview') {
$cfg->set('_NOCOOKIE',1);
overview($cfg, $query, $data);
} elsif ($rtype eq 'operperf') {
$cfg->set('_NOCOOKIE',1);
operperf($cfg, $query, $data);
} elsif ($rtype eq 'aging360') {
$cfg->set('_NOCOOKIE',1);
aging360($cfg, $query, $data);
} elsif ($rtype eq 'aging') {
$cfg->set('_NOCOOKIE',1);
aging($cfg, $query, $data);
} elsif ($rtype eq 'slevel') {
$cfg->set('_NOCOOKIE',1);
slevel($cfg, $query, $data);
} else {
$data->{REPORT} = '<center><b>[%Unknown report requested%]</b><br><br></center>'."\n";
}
$data->{REPORT} = "<tr><td align=left>\n".$data->{REPORT}."</td></tr>\n";
return undef;
}
# ===================================================================== overview
sub overview {
my ($cfg, $query, $data) = @_;
my $tmcuts = cuttimes($cfg);
my $img = $cfg->get('imgurl')."/dot.gif";
my @fltr;
my %drange = (
fld => 'created',
stm => $tmcuts->{trail}->{months12}->{start},
etm => $tmcuts->{today}->{stop}
);
$| = 1;
my $tickets = TTXCommon::dbtik();
my $tmp = $cfg->set('hideoldsolved', '');
my $browser = $tickets->list(0, 999999, 'open', 'A', \@fltr, \%drange);
$cfg->set('hideoldsolved', $tmp);
$tmcuts->{total}->{cnt} = $browser->{total};
my $m12stop = $tmcuts->{trail}->{months12}->{stop};
my $m12idx = 0;
my $m12idxstop = $tmcuts->{trail}->{months12}->{0}->{stop};
my $m12m = $tmcuts->{trail}->{months12}->{0};
my $w12stop = $tmcuts->{trail}->{weeks12}->{stop};
my $w12start = $tmcuts->{trail}->{weeks12}->{start};
my $w12idx = 0;
my $w12idxstop = $tmcuts->{trail}->{weeks12}->{start} + 7*24*3600;
my $w12bars = [];
$w12bars->[0]->{stop} = $w12idxstop;
my $d30stop = $tmcuts->{trail}->{days30}->{stop};
my $d30start = $tmcuts->{trail}->{days30}->{start};
my $d30idx = 0;
my $d30idxstop = $tmcuts->{trail}->{days30}->{start} + 24*3600;
my $d30bars = [];
$d30bars->[0]->{stop} = $d30idxstop;
foreach my $tid (@{$browser->{list}}) {
my $t = $tickets->ticket($tid, 1);
next if $t eq undef;
my $tm = $t->{open};
if ($tm < $m12stop) {
while ($tm >= $m12idxstop) {
++$m12idx;
$m12idxstop = $tmcuts->{trail}->{months12}->{$m12idx}->{stop};
$m12m = $tmcuts->{trail}->{months12}->{$m12idx};
print "\n"; #keep browser alive
}
++$m12m->{cnt};
} else {
++$tmcuts->{thismonth}->{cnt};
}
if ($tm >= $w12start) {
while ($tm >= $w12idxstop && $w12idx < 12) {
++$w12idx;
last if $w12idx > 11;
$w12idxstop += 7*24*3600;
$w12bars->[$w12idx]->{stop} = $w12idxstop;
}
if ($w12idx < 12) {
++$w12bars->[$w12idx]->{val};
} else {
++$tmcuts->{thisweek}->{cnt};
}
}
if ($tm >= $d30start) {
while ($tm >= $d30idxstop && $d30idx < 30) {
++$d30idx;
last if $d30idx > 29;
$d30idxstop += 24*3600;
$d30bars->[$d30idx]->{stop} = $d30idxstop;
}
if ($d30idx < 30) {
++$d30bars->[$d30idx]->{val};
} else {
++$tmcuts->{today}->{cnt};
}
}
#
# Purge ticket out of memory
# This is pretty safe if using SQL Edition (both MySQL and SQL Server).
# If using Standard (palin text database) Edition the consequent
# $tickets->save would destroy the database.
#
delete $tickets->{TICKETS}->{$tid};
}
while ($w12idx < 12) {
++$w12idx;
last if $w12idx > 11;
$w12idxstop += 7*24*3600;
$w12bars->[$w12idx]->{stop} = $w12idxstop;
}
while ($d30idx < 30) {
++$d30idx;
last if $d30idx > 29;
$d30idxstop += 24*3600;
$d30bars->[$d30idx]->{stop} = $d30idxstop;
}
my $bars = [];
for (my $i=0; $i < 12; ++$i) {
$bars->[$i]->{lbl} = $months[$tmcuts->{trail}->{months12}->{$i}->{idx}];
$bars->[$i]->{val} = $tmcuts->{trail}->{months12}->{$i}->{cnt};
}
my $chart = TTXBarChart::vbar($bars, 25, 125, 'red');
for (my $i=0; $i < 12; ++$i) {
$w12bars->[$i]->{lbl} = $months[(gmtime($w12bars->[$i]->{stop} - 6*3600 + 60 * int($cfg->get('timezone'))))[4]];
}
for (my $i=11; $i > 0; --$i) {
if ($w12bars->[$i]->{lbl} eq $w12bars->[$i-1]->{lbl}) {
$w12bars->[$i]->{lbl} = '';
}
}
my $chart1 = TTXBarChart::vbar($w12bars, 25, 125, 'blue');
for (my $i=0; $i < 30; ++$i) {
$d30bars->[$i]->{lbl} = (gmtime($d30bars->[$i]->{stop} - 3600+ 60 * int($cfg->get('timezone'))))[3];
}
my $chartd30 = TTXBarChart::vbar($d30bars, 22, 125, 'green', 0.5);
my $newtoday = int $tmcuts->{today}->{cnt};
my $newthisweek = int $tmcuts->{thisweek}->{cnt};
my $newthismonth = int $tmcuts->{thismonth}->{cnt};
$data->{REPORT} .=<<EOT;
<table cellpadding=0 cellspacing=0>
<tr>
<td align=left colspan=3>
<b>[%New tickets%]</b>
<table cellpadding=0 cellspacing=1>
<tr>
<td align=left><font color=gray><b>[%Today%]</b></font></td>
<td align=right><font color=green><b>$newtoday</b></font></td>
</tr>
<tr>
<td align=left><font color=gray><b>[%This Week%]</b></font></td>
<td align=right><font color=blue><b>$newthisweek</b></font></td>
</tr>
<tr>
<td align=left><font color=gray><b>[%This Month%]&nbsp;&nbsp;</b></font></td>
<td align=right><font color=red><b>$newthismonth</b></font></td>
</tr>
</table>
<br />
</td>
</tr>
<tr>
<td align=center valign=top>
<table cellpadding=10 style="border-style:solid;border-color:gray;border-width:1px;">
<tr>
<td align=center>
<b>[%New tickets, last 12 months%]</b>
<br><br>
$chart
</td>
</tr>
</table>
</td>
<td><img src="$img" width=17 height=1 /></td>
<td align=center valign=top>
<table cellpadding=10 style="border-style:solid;border-color:gray;border-width:1px;">
<tr>
<td align=center>
<b>[%New tickets, last 12 weeks%]</b>
<br><br>
$chart1
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td colspan=3><img src="$img" width=1 height=10 /></td>
</tr>
<tr>
<td align=center valign=top colspan=3>
<table cellpadding=1 cellspacing=0 style="border-style:solid;border-color:gray;border-width:1px;">
<tr>
<td align=center>
<br class=tiny>
<b>[%New tickets, last 30 days%]</b>
<br><br>
$chartd30
<br><br class=tiny>
</td>
</tr>
</table>
</td>
</tr>
</table>
EOT
}
# ===================================================================== operperf
sub operperf {
my ($cfg, $query, $data) = @_;
my $tmcuts = cuttimes($cfg);
my $img = $cfg->get('imgurl')."/dot.gif";
my @fltr = ({col => 'status', expr => '^(CLS|WFR)$'});
my %drange = (
fld => 'updated',
stm => $tmcuts->{trail}->{months12}->{start},
etm => $tmcuts->{today}->{stop}
);
$| = 1;
my $tickets = TTXCommon::dbtik();
my $tmp = $cfg->set('hideoldsolved', '');
my $browser = $tickets->list(0, 999999, 'open', 'A', \@fltr, \%drange);
$cfg->set('hideoldsolved', $tmp);
$tmcuts->{total}->{cnt} = $browser->{total};
my $opercnts = {};
my $m12stop = $tmcuts->{trail}->{months12}->{stop};
my $w12stop = $tmcuts->{trail}->{weeks12}->{stop};
my $w12start = $tmcuts->{trail}->{weeks12}->{start};
my $d30stop = $tmcuts->{trail}->{days30}->{stop};
my $d30start = $tmcuts->{trail}->{days30}->{start};
my $tcnt = 0;
foreach my $tid (@{$browser->{list}}) {
if (!$tcnt) {
print "\n";
$tcnt = 100;
}
--$tcnt;
my $t = $tickets->ticket($tid, 1);
next if $t eq undef;
my $oper = $t->{oper};
next if $oper eq undef;
my $tm = $t->{updated};
if ($tm < $m12stop) {
++$opercnts->{$oper}->{m12};
} else {
++$opercnts->{$oper}->{thismonth};
}
if ($tm >= $w12start) {
if ($tm < $w12stop) {
++$opercnts->{$oper}->{w12};
} else {
++$opercnts->{$oper}->{thisweek};
}
}
if ($tm >= $d30start) {
if ($tm < $d30stop) {
++$opercnts->{$oper}->{d30};
} else {
++$opercnts->{$oper}->{today};
}
}
#
# Purge ticket out of memory
# This is pretty safe if using SQL Edition (both MySQL and SQL Server).
# If using Standard (palin text database) Edition the consequent
# $tickets->save would destroy the database.
#
delete $tickets->{TICKETS}->{$tid};
}
my $bars = [];
my @operlist = TTXUser::list();
@operlist = sort @operlist;
my $i = 0;
foreach my $oper (@operlist) {
$bars->[$i]->{lbl} = $oper;
$bars->[$i]->{val} = 0;
if ($opercnts->{$oper} ne undef) {
$bars->[$i]->{val} = $opercnts->{$oper}->{m12};
}
++$i;
}
my $chart = TTXBarChart::hbar($bars, 18, 125, 'red', 0.8);
$i = 0;
foreach my $oper (@operlist) {
$bars->[$i]->{lbl} = $oper;
$bars->[$i]->{val} = 0;
if ($opercnts->{$oper} ne undef) {
$bars->[$i]->{val} = $opercnts->{$oper}->{w12};
}
++$i;
}
my $chart1 = TTXBarChart::hbar($bars, 18, 125, 'blue', 0.8);
$i = 0;
foreach my $oper (@operlist) {
$bars->[$i]->{lbl} = $oper;
$bars->[$i]->{val} = 0;
if ($opercnts->{$oper} ne undef) {
$bars->[$i]->{val} = $opercnts->{$oper}->{d30};
}
++$i;
}
my $chartd30 = TTXBarChart::hbar($bars, 18, 125, 'green', 0.8);
$i = 0;
foreach my $oper (@operlist) {
$bars->[$i]->{lbl} = $oper;
$bars->[$i]->{val} = 0;
if ($opercnts->{$oper} ne undef) {
$bars->[$i]->{val} = $opercnts->{$oper}->{today};
}
++$i;
}
my $charttoday = TTXBarChart::hbar($bars, 18, 125, 'green', 0.8);
$i = 0;
foreach my $oper (@operlist) {
$bars->[$i]->{lbl} = $oper;
$bars->[$i]->{val} = 0;
if ($opercnts->{$oper} ne undef) {
$bars->[$i]->{val} = $opercnts->{$oper}->{thisweek};
}
++$i;
}
my $chartthisweek = TTXBarChart::hbar($bars, 18, 125, 'blue', 0.8);
$i = 0;
foreach my $oper (@operlist) {
$bars->[$i]->{lbl} = $oper;
$bars->[$i]->{val} = 0;
if ($opercnts->{$oper} ne undef) {
$bars->[$i]->{val} = $opercnts->{$oper}->{thismonth};
}
++$i;
}
my $chartthismonth = TTXBarChart::hbar($bars, 18, 125, 'red', 0.8);
$data->{REPORT} .=<<EOT;
<br>
<table cellpadding=0 cellspacing=0>
<tr>
<td align=center valign=top>
<table width="100%" cellpadding=10 style="border-style:solid;border-color:gray;border-width:1px;">
<tr>
<td align=left>
<center><b>[%Answers, this month%]</b></center>
<br>
$chartthismonth
</td>
</tr>
</table>
</td>
<td><img src="$img" width=17 height=1 /></td>
<td align=center valign=top>
<table width="100%" cellpadding=10 style="border-style:solid;border-color:gray;border-width:1px;">
<tr>
<td align=left>
<center><b>[%Answers, this week%]</b></center>
<br>
$chartthisweek
</td>
</tr>
</table>
</td>
<td><img src="$img" width=17 height=1 /></td>
<td align=center valign=top>
<table width="100%" cellpadding=10 style="border-style:solid;border-color:gray;border-width:1px;">
<tr>
<td align=left>
<center><b>[%Answers, today%]</b></center>
<br>
$charttoday
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td colspan=5><img src="$img" width=1 height=10 /></td>
</tr>
<tr>
<td align=center valign=top>
<table width="100%" cellpadding=10 style="border-style:solid;border-color:gray;border-width:1px;">
<tr>
<td align=left>
<center><b>[%Answers, last 12 months%]</b></center>
<br>
$chart
</td>
</tr>
</table>
</td>
<td><img src="$img" width=17 height=1 /></td>
<td align=center valign=top>
<table width="100%" cellpadding=10 style="border-style:solid;border-color:gray;border-width:1px;">
<tr>
<td align=left>
<center><b>[%Answers, last 12 weeks%]</b></center>
<br>
$chart1
</td>
</tr>
</table>
</td>
<td><img src="$img" width=17 height=1 /></td>
<td align=center valign=top>
<table width="100%" cellpadding=10 style="border-style:solid;border-color:gray;border-width:1px;">
<tr>
<td align=left>
<center><b>[%Answers, last 30 days%]</b></center>
<br>
$chartd30
</td>
</tr>
</table>
</td>
</tr>
</table>
<br class=tiny />
EOT
}
# ======================================================================= slevel
sub slevel {
my ($cfg, $query, $data) = @_;
my $tmcuts = cuttimes($cfg);
my $img = $cfg->get('imgurl')."/dot.gif";
my @fltr = ({col => 'status', expr => '^CLS$'});
my %drange = (
fld => 'solved',
stm => $tmcuts->{trail}->{months12}->{11}->{start},
etm => $tmcuts->{trail}->{months12}->{11}->{stop},
# etm => $tmcuts->{lastweek}->{stop}
);
$| = 1;
my $tickets = TTXCommon::dbtik();
my $tmp = $cfg->set('hideoldsolved', '');
my $browser = $tickets->list(0, 999999, 'open', 'A', \@fltr, \%drange);
my $opercnts = {};
my $tcnt = 0;
foreach my $tid (@{$browser->{list}}) {
if (!$tcnt) {
print "\n";
$tcnt = 100;
}
--$tcnt;
my $t = $tickets->ticket($tid, 1);
next if $t eq undef;
my $oper = $t->{oper};
next if $oper eq undef; # just to make sure
if (!defined $opercnts->{$oper}) {
my $u = TTXUser->new($oper);
next if $u eq undef;
$opercnts->{$oper}->{sla} = int($u->{sla}) * 3600;
}
++$opercnts->{$oper}->{lm}->{total};
++$opercnts->{$oper}->{lm}->{jit} if $opercnts->{$oper}->{sla} > ($t->{closed} - $t->{open});
#
# Purge ticket out of memory
# This is pretty safe if using SQL Edition (both MySQL and SQL Server).
# If using Standard (palin text database) Edition the consequent
# $tickets->save would destroy the database.
#
delete $tickets->{TICKETS}->{$tid};
}
%drange = (
fld => 'solved',
stm => $tmcuts->{lastweek}->{start},
etm => $tmcuts->{lastweek}->{stop},
);
$browser = $tickets->list(0, 999999, 'open', 'A', \@fltr, \%drange);
$cfg->set('hideoldsolved', $tmp);
foreach my $tid (@{$browser->{list}}) {
if (!$tcnt) {
print "\n";
$tcnt = 100;
}
--$tcnt;
my $t = $tickets->ticket($tid, 1);
next if $t eq undef;
my $oper = $t->{oper};
next if $oper eq undef; # just to make sure
if (!defined $opercnts->{$oper}) {
my $u = TTXUser->new($oper);
next if $u eq undef;
$opercnts->{$oper}->{sla} = int($u->{sla}) * 3600;
}
++$opercnts->{$oper}->{lw}->{total};
++$opercnts->{$oper}->{lw}->{jit} if $opercnts->{$oper}->{sla} > ($t->{closed} - $t->{open});
#
# Purge ticket out of memory
# This is pretty safe if using SQL Edition (both MySQL and SQL Server).
# If using Standard (palin text database) Edition the consequent
# $tickets->save would destroy the database.
#
delete $tickets->{TICKETS}->{$tid};
}
$data->{REPORT} .=<<EOT;
<center>
<b>[%Service Level Report%]</b><br>
<span class=sm>([%percentage of tickets solved within SLA time%])</span>
<br><br>
<table cellpadding=3 style="border-style:solid;border-color:gray;border-width:1px;">
<tr>
<td align=center>
<b>[%Operator%]</b>
</td>
<td align=center>
<b>[%Last Week%]</b>
</td>
<td align=center>
<b>[%Last Month%]</b>
</td>
</tr>
EOT
foreach my $oper (sort keys %{$opercnts}) {
$data->{REPORT} .= "<tr>\n<td align=left>$oper</td><td align=right>".
($opercnts->{$oper}->{lw}->{total} ?
int(100*$opercnts->{$oper}->{lw}->{jit}/$opercnts->{$oper}->{lw}->{total}).'%':'-' ).
"</td>\n<td align=right>".
($opercnts->{$oper}->{lm}->{total} ?
int(100*$opercnts->{$oper}->{lm}->{jit}/$opercnts->{$oper}->{lm}->{total}).'%':'-' ).
"</td>\n</tr>\n";
}
$data->{REPORT} .=<<EOT;
</table>
</center>
<br class=tiny />
EOT
}
# ===================================================================== aging360
sub aging360 {
my ($cfg, $query, $data) = @_;
my @tmlst = (
'0-24 [%hrs%]',
'24-48 [%hrs%]',
'2-7 [%days%]',
'7-30 [%days%]',
'30+ [%days%]'
);
my %tmcuts = (
$tmlst[0] => 24*3600,
$tmlst[1] => 48*3600,
$tmlst[2] => 168*3600,
$tmlst[3] => 720*3600,
$tmlst[4] => 0
);
my $img = $cfg->get('imgurl')."/dot.gif";
my @fltr = (
{ 'col' => 'status', 'expr' => '^CLS$' }
);
my $now = time();
my %drange = (
fld => 'created',
stm => int ($now - 365*24*3600),
etm => $now
);
$| = 1;
my $tickets = TTXCommon::dbtik();
my $tmp = $cfg->set('hideoldsolved', '');
my $browser = $tickets->list(0, 999999, 'open', 'A', \@fltr, \%drange);
$cfg->set('hideoldsolved', $tmp);
my @bardata;
my $heartbeat = 0;
foreach my $tid (@{$browser->{list}}) {
my $t = $tickets->ticket($tid, 1);
next if $t eq undef;
my $tm = $t->{closed} - $t->{open};
my $i = 0;
foreach my $cut (@tmlst) {
last if $tm < $tmcuts{$cut} || !$tmcuts{$cut};
++$i;
}
++$bardata[$i]->{val};
++$heartbeat;
if ($heartbeat > 100) {
print "\n"; #keep browser alive
$heartbeat = 0;
}
#
# Purge ticket out of memory
# This is pretty safe if using SQL Edition (both MySQL and SQL Server).
# If using Standard (palin text database) Edition the consequent
# $tickets->save would destroy the database.
#
delete $tickets->{TICKETS}->{$tid};
}
my $i = 0;
foreach my $cut (@tmlst) {
$bardata[$i]->{lbl} = $cut;
++$i;
}
my $chart = TTXBarChart::hbar(\@bardata, 18, 125, 'red', 0.8, 1);
$data->{REPORT} .=<<EOT;
<table cellpadding=0 cellspacing=0 width="100%">
<tr>
<td align=center>
<b>[%Breakdown of time to close a ticket%]</b><br />
<span class=sm>([%tickets submitted during last 365 days%])</span>
<br /><br />
$chart
<br /><br />
</td>
</tr>
</table>
EOT
}
# ======================================================================== aging
sub aging {
my ($cfg, $query, $data) = @_;
my @tmlst = (
'0-24 [%hrs%]',
'24-48 [%hrs%]',
'2-7 [%days%]',
'7-30 [%days%]',
'30+ [%days%]'
);
my %tmcuts = (
$tmlst[0] => 24*3600,
$tmlst[1] => 48*3600,
$tmlst[2] => 168*3600,
$tmlst[3] => 720*3600,
$tmlst[4] => 0
);
my $img = $cfg->get('imgurl')."/dot.gif";
my @fltr = (
{ 'col' => 'status', 'expr' => '^(PND|OPN)$' }
);
my $now = time();
my %drange = (
fld => 'created',
stm => int ($now - 365*24*3600),
etm => $now
);
$| = 1;
my $tickets = TTXCommon::dbtik();
my $tmp = $cfg->set('hideoldsolved', '');
my $browser = $tickets->list(0, 999999, 'open', 'A', \@fltr, \%drange);
$cfg->set('hideoldsolved', $tmp);
my @bardata;
my $heartbeat = 0;
foreach my $tid (@{$browser->{list}}) {
my $t = $tickets->ticket($tid, 1);
next if $t eq undef;
my $tm = $now - $t->{open};
my $i = 0;
foreach my $cut (@tmlst) {
last if $tm < $tmcuts{$cut} || !$tmcuts{$cut};
++$i;
}
++$bardata[$i]->{val};
++$heartbeat;
if ($heartbeat > 100) {
print "\n"; #keep browser alive
$heartbeat = 0;
}
#
# Purge ticket out of memory
# This is pretty safe if using SQL Edition (both MySQL and SQL Server).
# If using Standard (palin text database) Edition the consequent
# $tickets->save would destroy the database.
#
delete $tickets->{TICKETS}->{$tid};
}
my $i = 0;
foreach my $cut (@tmlst) {
$bardata[$i]->{lbl} = $cut;
++$i;
}
my $chart = TTXBarChart::hbar(\@bardata, 18, 125, 'red', 0.8, 1);
$data->{REPORT} .=<<EOT;
<table cellpadding=0 cellspacing=0 width="100%">
<tr>
<td align=center>
<b>[%Hot Tickets%]</b><br />
<span class=sm>([%tickets in open or pending state%])</span>
<br /><br />
$chart
<br /><br />
</td>
</tr>
</table>
EOT
}
# ===================================================================== cuttimes
sub cuttimes {
my $cfg = $_[0];
my $cuts;
my $now = time() + 60 * int($cfg->get('timezone'));
$cuts->{total}->{start} = 0;
$cuts->{total}->{stop} = $now;
$cuts->{yesterday}->{stop} = $now - ($now % (3600 * 24));
$cuts->{yesterday}->{start} = $cuts->{yesterday}->{stop} - (3600 * 24);
my ($sec,$min,$hour,$mday,$mon,$year, $wday) = gmtime($now);
--$wday;
$wday = 6 if $wday < 0; # Sunday is last week day
# $wdaytoday = $wday;
$cuts->{lastweek}->{stop} = $cuts->{yesterday}->{stop} - $wday * (3600 * 24);
$cuts->{lastweek}->{start} = $cuts->{lastweek}->{stop} - (7 * 3600 * 24);
$cuts->{thisweek}->{start} = $cuts->{lastweek}->{stop}; # current week
$cuts->{thisweek}->{stop} = $now;
$cuts->{lastmonth}->{stop} = $cuts->{yesterday}->{stop} - ($mday - 1) * (3600 * 24);
$cuts->{thismonth}->{start} = $cuts->{lastmonth}->{stop};
$cuts->{thismonth}->{stop} = $now;
$cuts->{today}->{start} = $cuts->{yesterday}->{stop};
$cuts->{today}->{stop} = $cuts->{today}->{start} + (3600 * 24);
my ($sec1,$min1,$hour1,$mday1,$mon1,$year1, $wday1) = gmtime($cuts->{month}->{stop} - 3600);
$cuts->{lastmonth}->{start} = $cuts->{lastmonth}->{stop} - $mday1 * (3600 * 24);
foreach my $col ('today', 'yesterday', 'lastweek', 'lastmonth', 'thismonth', 'thisweek') {
$cuts->{$col}->{start} -= 60 * int($cfg->get('timezone'));
$cuts->{$col}->{stop} -= 60 * int($cfg->get('timezone'));
}
$cuts->{Mon}->{start} = $cuts->{lastweek}->{stop};
$cuts->{Mon}->{stop} = $cuts->{Mon}->{start} + (3600 * 24);
my $priorday = 'Mon';
foreach my $day ('Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun') {
$cuts->{$day}->{stop} = $cuts->{$priorday}->{stop} + (3600 * 24);
$cuts->{$day}->{start} = $cuts->{$day}->{stop} - (3600 * 24);
$priorday = $day;
}
#
# Trailings
#
# 30 Days
#
$cuts->{trail}->{days30}->{stop} = $cuts->{yesterday}->{stop};
$cuts->{trail}->{days30}->{start} = $cuts->{trail}->{days30}->{stop} - 30 * 24 * 3600;
#
# 12 weeks
#
$cuts->{trail}->{weeks12}->{stop} = $cuts->{lastweek}->{stop};
$cuts->{trail}->{weeks12}->{start} = $cuts->{trail}->{weeks12}->{stop} - 12 * 7 * 24 * 3600;
#
# 12 months
#
$cuts->{trail}->{months12}->{stop} = $cuts->{lastmonth}->{stop};
for (my $i=11; $i >= 0; --$i) {
if ($i == 11) {
$cuts->{trail}->{months12}->{11}->{stop} = $cuts->{trail}->{months12}->{stop};
} else {
$cuts->{trail}->{months12}->{$i}->{stop} = $cuts->{trail}->{months12}->{($i+1)}->{start};
}
my ($md,$mn) = (gmtime($cuts->{trail}->{months12}->{$i}->{stop} - 3600 + 60 * int($cfg->get('timezone'))))[3,4];
$cuts->{trail}->{months12}->{$i}->{start} = $cuts->{trail}->{months12}->{$i}->{stop} - $md * 3600 * 24;
$cuts->{trail}->{months12}->{$i}->{idx} = $mn;
}
$cuts->{trail}->{months12}->{start} = $cuts->{trail}->{months12}->{0}->{start};
return $cuts;
}
1;
#
+114
View File
@@ -0,0 +1,114 @@
package TTXSearch;
#
# Common search functions
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2005, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 156 $
# $Date: 2006-05-05 03:02:47 -0400 (Fri, 05 May 2006) $
#
$TTXSearch::VERSION='2.22';
BEGIN {
$TTXSearch::REVISION = '$Revision: 156 $';
if ($TTXSearch::REVISION =~ /(\d+)/) {
$TTXSearch::REVISION = $1;
}
};
use strict;
# ===================================================================== tokenize
sub tokenize {
my $s = $_[0];
$s =~ s /\*/\\\*/g;
$s =~ s /\?/\\\?/g;
$s =~ s /\+/\\\+/g;
$s =~ s /\{/\\\{/g;
my @tokens;
while ($s =~ /"([^"]*)"/) {
my $t = $1;
push @tokens, $t;
$s =~ s/"[^"]*"//;
}
push @tokens, split(/ /, $s);
my @cleantokens;
foreach my $token (@tokens) {
$token =~ s/\s+/ /g;
$token =~ s/^\s//;
$token =~ s/\s+$//;
next if $token eq undef;
next if grep(/^$token$/i, @cleantokens);
push @cleantokens, $token;
}
return \@cleantokens;
}
# ===================================================================== abstract
sub abstract {
my ($text, $tokens) = @_;
$text =~ s/<([^>]*)>/&lt;$1&gt;/g;
#
# mark tokens
#
foreach my $token (@{$tokens}) {
$token =~ s/ /(\\s+|\\s+<b>|<\/b>\\s+)/g;
$text =~ s/\b($token)\b/<b>$1<\/b>/gi;
}
#
# remove enclosed token marks
#
$text =~ s/(<b>[^<]*)<b>/$1/g;
$text =~ s/<\/b>([^<]*<\/b>)/$1/g;
#
# remove extra text
#
$text =~ /^([^<]*)<b>/;
my @plain = split(/<b>[^<]*<\/b>/, $text);
if (@plain < 1) {
push @plain, '';
}
$text = "</b>$text<b>";
my @bold = split(/<\/b>[^<]*<b>/, $text);
my $i = 1;
my $out;
my $wcnt = 10;
foreach (@plain) {
my $pt = $_;
$pt =~ s/^\s+//;
$pt =~ s/\s+$//;
my @words = split(/\s+/, $pt);
if ($i == 1 && @bold > 0) {
if (@words > 5) {
$out = "... ".join(" ", splice(@words, -5));
} else {
$out = join(" ", @words);
}
} elsif ($bold[$i] eq undef) {
$wcnt *= 8 if @bold == 0;
if (@words > $wcnt / 2) {
$out .= join(" ", splice(@words, 0, $wcnt / 2))." ...";
} else {
$out .= join(" ", @words);
}
} else {
if (@words <= $wcnt) {
$out .= join(" ", @words);
} else {
$out .= join(" ", splice(@words, 0, $wcnt / 2)).
" ... ".
join(" ", splice(@words, $wcnt / (-2)));
}
}
$out .= " <b>$bold[$i]</b> " if $bold[$i] ne undef;
$i++;
}
return $out;
}
1;
#
+160
View File
@@ -0,0 +1,160 @@
package TTXSession;
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2002-2005, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 182 $
# $Date: 2006-06-07 02:46:21 -0400 (Wed, 07 Jun 2006) $
#
$TTXSession::VERSION='2.22';
BEGIN {
$TTXSession::REVISION = '$Revision: 182 $';
if ($TTXSession::REVISION =~ /(\d+)/) {
$TTXSession::REVISION = $1;
}
};
use strict;
use TTXConfig;
use TTXData;
use vars qw(@ISA);
@ISA = qw(TTXConfig);
my %errmsgs = (
NOFILENAME => 'Missing file name',
NOFILE => 'File does not exist',
OPENERR => 'Error reading file',
WRERR => 'Error writing file'
);
# ========================================================================== new
sub new {
my $class = $_[0];
my $self = $class->SUPER::new();
if ($_[1] ne undef && $self->load(TTXData::get('CONFIG')->get('basedir')."/sid/$_[1].cgi")) {
$self->{_SID} = $_[1];
}
return $self;
}
# ====================================================================== refresh
sub refresh {
my $self = shift;
my $exptime = TTXData::get('CONFIG')->get('exptime');
$exptime = 3600 * 10 if !$exptime;
$self->{expires} = time() + $exptime;
$self->save();
}
# ====================================================================== expired
sub expired {
my $self = shift;
return 1 if $self->{login} ne undef && $self->{expires} < time();
return 0;
}
# ======================================================================= logout
sub logout {
my $self = shift;
if ($self->{login} ne undef) {
my $fn = TTXData::get('CONFIG')->get('basedir')."/sid/".$self->sid().".cgi";
$fn =~ /(.*)/; $fn = $1;
unlink($fn);
}
}
# ========================================================================== sid
sub sid {
my $self = shift;
return $self->{_SID};
}
# ==================================================================== errortext
sub errortext {
my $self = shift;
return $errmsgs{$self->{_ERROR_CODE}}." [session]";
}
# ====================================================================== cleanup
sub cleanup {
if (opendir(DIR, TTXData::get('CONFIG')->get('basedir')."/sid")) {
my @dirlist = readdir(DIR);
closedir(DIR);
my $killtm = time() - 3600 * 24 * 7; # one week ago
foreach my $file (@dirlist) { # quick and dirty cleanup
next if $file !~ /^\d+Z\d+\.cgi$/;
my ($tm) = split(/Z/, $file);
if ($tm < $killtm) {
$file =~ /(.*)/; $file = $1;
unlink TTXData::get('CONFIG')->get('basedir')."/sid/$file";
}
}
}
}
# ======================================================================== login
sub login {
my $self = shift;
my $uid = shift;
if ($uid eq undef) {
warn "uid eq undef";
return 0;
}
cleanup();
my $sid = time()."Z".$$.int(rand(900000) + 100000);
$self->file(TTXData::get('CONFIG')->get('basedir')."/sid/$sid.cgi");
$self->set('login', $uid);
my $exptime = TTXData::get('CONFIG')->get('exptime');
$exptime = 3600 * 10 if !$exptime;
$self->set('expires', time() + $exptime);
if ($self->save()) {
$self->{_SID} = $sid;
return 1;
} else {
return 0;
}
}
# ====================================================================== qexpand
sub qexpand {
my ($self, $query, $cmd) = @_;
my @vars = $self->vars();
foreach my $id (@vars) {
next if $id !~ /^$cmd\.(\w+)$/;
my $var = $1;
if ($query->param($var) eq undef && $self->get("$id") ne undef) {
$query->param(-name => $var, -value => $self->get("$id"));
}
}
}
# ======================================================================== qsave
sub qsave {
my ($self, $query, $cmd, $list) = @_;
my $dosave = 0;
foreach my $id (@{$list}) {
if ($self->get("$cmd.$id") ne $query->param($id)) {
$self->set("$cmd.$id", $query->param($id));
$dosave = 1;
}
}
if ($dosave) {
$self->save() ;
if (TTXData::get('_USECACHE')) {
eval "use TTXCache";
TTXCache::purge() if $@ eq undef;
}
}
}
1;
#
File diff suppressed because it is too large Load Diff
+236
View File
@@ -0,0 +1,236 @@
package TTXTickEd;
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2005, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 224 $
# $Date: 2006-07-24 11:32:24 -0400 (Mon, 24 Jul 2006) $
#
$TTXTickEd::VERSION='2.22';
BEGIN {
$TTXTickEd::REVISION = '$Revision: 224 $';
if ($TTXTickEd::REVISION =~ /(\d+)/) {
$TTXTickEd::REVISION = $1;
}
};
use strict;
use TTXCommon;
# =================================================================== invenabled
my $_invenabled = undef;
sub invenabled {
if ($_invenabled eq undef) {
eval 'use TTXInvMod';
if ($@ eq undef) {
$_invenabled = 1;
} else {
$_invenabled = 0;
}
}
return $_invenabled;
}
# ===================================================================== ticketed
sub ticketed {
my ($cfg, $query, $data) = @_;
my $user = $cfg->get('_USER');
if ($query->param('isticket')) {
$query->param(-name => 'isticket', value => '1');
} else {
$query->param(-name => 'isticket', value => '0');
}
if ($user ne undef && $user->get('ro')) {
$data->{ERROR_MESSAGE} = '[%Access denied%]';
return undef;
}
my $tickets = TTXCommon::dbtik();
if ($tickets eq undef || $tickets->error() ne undef) {
$data->{ERROR_MESSAGE} = $tickets->errortext();
return undef;
}
my $t = $tickets->ticket(TTXCommon::cleanit($query, 'tid'));
if ($t eq undef) {
$data->{ERROR_MESSAGE} = '[%Ticket does not exist%]';
return undef;
}
if (!$query->param('do')) {
if (invenabled()) {
my $iline = $t->{item};
$iline =~ s/^;//; $iline =~ s/;$//;
my @ilist = split(/;/, $iline);
$query->param(-name => 'item', -values => \@ilist);
}
}
if ($query->param('do')) {
my $val = TTXCommon::cleanit($query, 'email');
if ($val !~ /^[0-9A-Za-z.'_-]+@[0-9A-Za-z_-]+\.[0-9A-Za-z._-]+$/) {
$data->{ERROR_MESSAGE} .= '[%Invalid email address%]';
} else {
$t->{email} = $val;
}
if ($cfg->get('editopendate')) {
eval "use Time::Local";
if ($@ eq undef) {
my $tz = $cfg->get('timezone') * 60;
$t->{open} = Time::Local::timegm($query->param('sec'),$query->param('min'),$query->param('hour'),
$query->param('day'),$query->param('mon'),
$query->param('year')) - $tz;
}
}
if ($cfg->get('editclosedate') && $t->{status} eq 'CLS') {
eval "use Time::Local";
if ($@ eq undef) {
my $tz = $cfg->get('timezone') * 60;
$t->{closed} = Time::Local::timegm($query->param('clssec'),$query->param('clsmin'),$query->param('clshour'),
$query->param('clsday'),$query->param('clsmon'),
$query->param('clsyear')) - $tz;
if ($t->{closed} < $t->{open}) {
$t->{closed} = $t->{open};
}
$t->{updated} = $t->{closed};
}
}
$val = TTXCommon::cleanit($query, 'name');
$t->{name} = $val if $val ne undef;
$val = TTXCommon::cleanit($query, 'subject');
$t->{subject} = $val if $val ne undef;
my @items = $query->param('item');
if (grep(/^-$/, @items)) {
@items = ('-');
$t->{item} = '';
} else {
$t->{item} = ';'.join(';', @items).';';
}
foreach my $cfld (sort grep(/^c\d\d?$/, $query->param())) {
if ($cfg->get("$cfld.type") eq 'list') {
my $n = $cfld;
$n =~ s/^c//;
my @allow = split(/;/, $cfg->get("dropdown$n"));
my @qlist = $query->param($cfld);
my @vlist;
foreach my $v (@qlist) {
$v =~ s/\n//g; $v =~ s/\r//g;
$v =~ s/\s+//; $v =~ s/\s+$//g;
push @vlist, $v if grep(/^$v$/, @allow);
}
$t->{$cfld} = ';'.join(';', @vlist).';';
} else{
$t->{$cfld} = TTXCommon::cleanit($query, $cfld);
}
}
if ($data->{ERROR_MESSAGE} eq undef) {
$tickets->save();
$data->{MESSAGE} = '[%Ticket updated%]';
}
}
$data->{TICKET_subject} = $t->{subject};
$data->{TICKET_email} = $t->{email};
$data->{TICKET_name} = $t->{name};
$data->{TICKET_key} = $t->{key};
my @list = grep(/^x/, $cfg->vars());
my @editable = split(/;/, $cfg->get('editablefields'));
my %cflds;
foreach my $id (@list) {
my $cid = $cfg->get($id);
next if $cid !~ /^\d\d?$/;
$cid = "c$cid";
if (grep(/^$cid$/, @editable)) {
$cflds{$cid} = $id;
$cflds{$cid} =~ s/^x//;
}
}
if (invenabled()) {
my $lbl = $cfg->get('inventory.label') || '[%Item%]';
$lbl =~ s/</&lt;/g;
$data->{CUSTOMFIELDS} .= "<tr><td align=right><b>$lbl</b></td><td align=left>".
TTXInvMod::selbox($cfg, $query, 1)."</td></tr>\n";
}
if ($cfg->get('editopendate')) {
$data->{CUSTOMFIELDS} .= '<tr><td align=right><b>[%Submitted%]</b></td>'."\n".
"<td align=left>";
my $tz = $cfg->get('timezone') * 60;
my ($sec, $min, $hour, $mday,$mon,$year) = (gmtime($t->{open} + $tz))[0,1,2,3,4,5];
$query->param(-name => 'sec', -value => $sec);
$query->param(-name => 'min', -value => $min);
$query->param(-name => 'hour', -value => $hour);
$query->param(-name => 'year', -value => $year);
$query->param(-name => 'mon', -value => $mon);
$query->param(-name => 'day', -value => $mday);
$data->{CUSTOMFIELDS} .= TTXCommon::pickdate($query, '');
eval "use TTXPickTime";
if (!$@) {
$data->{CUSTOMFIELDS} .= TTXPickTime::picktime($query, '');
}
$data->{CUSTOMFIELDS} .= "</td></tr>\n";
}
if ($cfg->get('editclosedate') && $t->{status} eq 'CLS') {
$data->{CUSTOMFIELDS} .= '<tr><td align=right><b>[%Solved%]</b></td>'."\n".
"<td align=left>";
my $tz = $cfg->get('timezone') * 60;
my ($sec, $min, $hour, $mday,$mon,$year) = (gmtime($t->{closed} + $tz))[0,1,2,3,4,5];
$query->param(-name => 'clssec', -value => $sec);
$query->param(-name => 'clsmin', -value => $min);
$query->param(-name => 'clshour', -value => $hour);
$query->param(-name => 'clsyear', -value => $year);
$query->param(-name => 'clsmon', -value => $mon);
$query->param(-name => 'clsday', -value => $mday);
$data->{CUSTOMFIELDS} .= TTXCommon::pickdate($query, 'cls');
eval "use TTXPickTime";
if (!$@) {
$data->{CUSTOMFIELDS} .= TTXPickTime::picktime($query, 'cls');
}
$data->{CUSTOMFIELDS} .= "</td></tr>\n";
}
foreach my $id (sort keys %cflds) {
$data->{CUSTOMFIELDS} .= "<tr><td align=right><b>$cflds{$id}</b></td>\n".
"<td align=left>";
my $n = $id;
$n =~ s/^c//;
my @options = split(/;/, $cfg->get("dropdown$n"));
if (@options > 0) {
my @qlist;
my $multi;
if ($cfg->get("$id.type") eq 'list') {
my $cnt = int @options;
$cnt = 3 if $cnt > 3;
$multi = " multiple size=3";
if ($query->param('do')) {
@qlist = $query->param($id);
} else {
@qlist = split(/;/, $t->{$id});
}
} else {
if ($query->param('do')) {
$qlist[0] = $query->param($id);
} else {
$qlist[0] = $t->{$id};
}
}
$data->{CUSTOMFIELDS} .= "<select$multi name=$id>\n";
foreach my $opt (@options) {
my $val = $opt; $val =~ s/"/&quot;/g;
$data->{CUSTOMFIELDS} .= "<option value=\"$val\"";
if (grep(/^$opt$/, @qlist)) {
$data->{CUSTOMFIELDS} .= ' selected';
}
$opt =~ s/</&lt;/g;
$data->{CUSTOMFIELDS} .= ">$opt</option>\n";
}
$data->{CUSTOMFIELDS} .= "</select>\n";
} else {
my $val = $query->param('do') ? $query->param($id) : $t->{$id};
$val =~ s/"/&quot;/g;
$data->{CUSTOMFIELDS} .= "<input type=text size=30 name=$id value=\"$val\">";
}
$data->{CUSTOMFIELDS} .= "</td></tr>\n";
}
return undef;
}
1;
#
File diff suppressed because it is too large Load Diff
+132
View File
@@ -0,0 +1,132 @@
package TTXTickets;
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2002-2005, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 202 $
# $Date: 2006-07-17 11:27:36 -0400 (Mon, 17 Jul 2006) $
#
$TTXTickets::VERSION='2.22';
BEGIN {
$TTXTickets::REVISION = '$Revision: 202 $';
if ($TTXTickets::REVISION =~ /(\d+)/) {
$TTXTickets::REVISION = $1;
}
};
use strict;
use TTXData;
my @tickfields = ('id', 'key', 'open', 'updated', 'closed', 'status', 'oper', 'email', 'name', 'subject',
'lname', 'c0', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9','grp');
my $fldsexpanded = 0;
my $boundary = '-----------asdjhfKJS12869nmboiu7826318---';
# ====================================================================== _fields
sub _fields {
if (!$fldsexpanded) {
my $cfg = TTXData::get('CONFIG');
if ($cfg ne undef) {
my $cnt = int ($cfg->get('cfldcnt'));
if (!$cfg->get('itemidx')) {
$cfg->set('itemidx', ($cnt > 10) ? $cnt:10);
$cfg->save();
}
if ($cnt > 10) {
for (my $i = 10; $i < $cnt; ++$i) {
push @tickfields, 'item' if $i eq $cfg->get('itemidx');
push @tickfields, "c$i";
}
push @tickfields, 'item' if $cnt eq $cfg->get('itemidx');
} else {
push @tickfields, 'item';
}
$fldsexpanded = 1;
}
}
return @tickfields;
}
# ==================================================================== _boundary
sub _boundary {
return $boundary;
}
# ========================================================================== new
sub new {
my $class = shift;
my $self = {};
bless($self, $class);
return $self;
}
# ========================================================================= save
sub save {
warn 'Pure virtual method TTXTickets::save() called';
return 0;
}
# ======================================================================= deltik
sub deltik {
warn 'Pure virtual method TTXTickets::deltik() called';
}
# ================================================================== ticketbykey
sub ticketbykey {
warn 'Pure virtual method TTXTickets::ticketbykey() called';
return undef;
}
# ======================================================================= ticket
sub ticket {
warn 'Pure virtual method TTXTickets::ticket() called';
return undef;
}
# ==================================================================== addticket
sub addticket {
warn 'Pure virtual method TTXTickets::addticket() called';
return 0;
}
# ========================================================================= list
sub list {
warn 'Pure virtual method TTXTickets::list() called';
my $browser;
return $browser;
}
# ==================================================================== errortext
sub errortext {
warn "Pure virtual method TTXTickets::errortext() called";
return 'Pure virtual method TTXTickets::errortext() called';
}
# ======================================================================== error
sub error {
my $self = shift;
return $self->{_ERROR_CODE};
}
# ====================================================================== raw2msg
sub raw2msg {
my $msg = {};
my @msgparts = split(/\n\n/, $_[0]);
my $rawheader = shift @msgparts;
$msg->{BODY} = join("\n\n", @msgparts);
my @headerlines = split(/\n/, $rawheader);
chomp @headerlines;
foreach my $line (@headerlines) {
if ($line =~ /^([a-zA-Z][a-zA-Z0-9-]*):\s*(.*)$/) {
$msg->{uc $1} = $2;
}
}
return $msg;
}
1;
#
+339
View File
@@ -0,0 +1,339 @@
package TTXUpgrade;
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2005-2006, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 181 $
# $Date: 2006-06-07 02:20:54 -0400 (Wed, 07 Jun 2006) $
#
$TTXUpgrade::VERSION='2.22';
BEGIN {
$TTXUpgrade::REVISION = '$Revision: 181 $';
if ($TTXUpgrade::REVISION =~ /(\d+)/) {
$TTXUpgrade::REVISION = $1;
}
};
use strict;
require TTXSetup;
my %upgradepath = (
'2.182' => { ver => '2.19', code => \&upgrade219 },
'2.19' => { ver => '2.191', code => \&upgrade2191 },
'2.191' => { ver => '2.20', code => \&upgrade220 },
'2.20' => { ver => '2.21', code => \&upgrade221 },
'2.21' => { ver => '2.22', code => \&upgrade222 },
);
# ====================================================================== upgrade
sub upgrade {
my $cfg = $_[0];
my $v = $cfg->get('ttx.version');
if ($v eq undef) {
if (-f $cfg->get('basedir'). "/templates/ticketed.html") {
$v = '2.182';
}
}
for (my $ver = $upgradepath{$v}; $ver ne undef ; $ver = $upgradepath{$ver->{ver}}) {
my $err = &{$ver->{code}}($cfg);
if ($err ne undef) {
return $err;
}
$cfg->set('ttx.version', $ver->{ver});
$cfg->save();
}
return undef;
}
# =================================================================== upgrade219
sub upgrade219 {
my $cfg = $_[0];
my $fn = $cfg->get('basedir'). "/templates/header.shtml";
return "File $fn does not exist" if ! -f $fn;
return "File $fn is not writable" if ! -w $fn;
return "Can't open file $fn" if !open(F, "+<$fn");
flock(F,2);
my $buff = join('', <F>);
if ($buff !~ /\btd\.txt\s+\{/) {
my $addthis = <<EOT;
td.txt {
padding-right: 4pt;
padding-left: 4pt;
padding-top: 2pt;
padding-bottom: 1pt;
border-width:1px;
border-style:solid;
border-top-width:0;
border-bottom-width:0;
border-right-width:0;
font-size : 8pt;
border-color: #FFF;
color: #666;
text-align: left;
}
EOT
$buff =~ s/<\/style>/$addthis\n<\/style>/;
seek(F,0,0);
print F $buff;
truncate(F, tell(F));
}
close(F);
$fn = $cfg->get('basedir'). "/templates/helpdesk.html";
return "File $fn does not exist" if ! -f $fn;
return "File $fn is not writable" if ! -w $fn;
return "Can't open file $fn" if !open(F, "+<$fn");
flock(F,2);
$buff = join('', <F>);
if ($buff =~ /<\s*input\s+type="?hidden"?\s+name="?qwindow"?\s+value="?\(%INPUT_qwindow%\)"?\s*>/) {
$buff =~ s/<\s*input\s+type="?hidden"?\s+name="?qwindow"?\s+value="?\(%INPUT_qwindow%\)"?\s*>//;
my $addthis = <<EOT;
<tr>
<td align=left>
<span class=sm>
Show <input type=text size=3 class=sm name=qwindow value=(%INPUT_qwindow%)> tickets per page.
Include abstracts <input type=checkbox class=sm name=abstract value=1(%CHECKABSTRACT%)>
</span>
</td>
<td align=right>
<input type=submit value=Search>&nbsp;<input type=submit name=reset value="Show all">
</td>
</tr>
EOT
my $findthis = '<tr>\s*<td[^>]*><input\s+type="?submit"?[^>]*>[^<]*<input\s+type="?submit"?[^>]*>[^<]*</td>[^<]*</tr>';
$buff =~ s/$findthis/$addthis\n/i;
seek(F,0,0);
print F $buff;
truncate(F, tell(F));
}
close(F);
$fn = $cfg->get('basedir'). "/templates/ticket.html";
return "File $fn does not exist" if ! -f $fn;
return "File $fn is not writable" if ! -w $fn;
return "Can't open file $fn" if !open(F, "+<$fn");
flock(F,2);
$buff = join('', <F>);
if ($buff =~ /width=700,\s*height=300,\s*resizable/) {
$buff =~ s/width=700,\s*height=300,\s*resizable/width=700,height=360,resizable/;
seek(F,0,0);
print F $buff;
truncate(F, tell(F));
}
close(F);
$fn = $cfg->get('basedir'). "/templates/answerlib.html";
return "File $fn does not exist" if ! -f $fn;
return "File $fn is not writable" if ! -w $fn;
return "Can't open file $fn" if !open(F, "+<$fn");
flock(F,2);
$buff = join('', <F>);
if ($buff !~ /showcat/) {
$buff =~ s/-->\s*<\/style>/.lbl { font-size: 9pt; font-weight: 700;}-->\n<\/style>/;
my $addthis = <<EOT;
<script language=Javascript>
<!--
function showcat(id) {
location.href='(%ENV_SCRIPT_NAME%)?cmd=answerlib&sid=(%INPUT_sid%)&style=(%INPUT_style%)&cat='+escape(id);
return false;
}
// -->
</script>
</head>
EOT
$buff =~ s/<\/head>/$addthis/i;
$buff =~ s/\(%ANSWERLIBMSG%\)\s*<br>/(%ANSWERLIBMSG%)\n/;
$addthis = <<EOT;
<table cellpadding=1 cellspacing=1>
<tr>
<td>
<select name=cat size=1 OnChange="return showcat(this[this.selectedIndex].value);">
(%CATSELECTOR%)
</select>
</td>
</tr>
<tr>
<td>
<select name=answer size=10 OnChange="return showanswer(this[this.selectedIndex].value);">
(%ANSWERSELECTOR%)
</select>
</td>
</tr>
</table>
EOT
$buff =~ s/<select\s+name="?answer"?[^<]*<\/select>/$addthis/i;
seek(F,0,0);
print F $buff;
truncate(F, tell(F));
}
close(F);
$fn = $cfg->get('basedir'). "/templates/newanswer.html";
return "File $fn does not exist" if ! -f $fn;
return "File $fn is not writable" if ! -w $fn;
return "Can't open file $fn" if !open(F, "+<$fn");
flock(F,2);
$buff = join('', <F>);
if ($buff !~ /CATSELECTOR/) {
$buff =~ s/-->\s*<\/style>/.lbl { font-size: 9pt; font-weight: 700;}-->\n<\/style>/;
my $addthis = <<EOT;
<td colspan=2></td>
</tr>
<tr>
<td colspan=2></td>
</tr>
<tr>
<td align=left class=lbl>Select existing category</td>
<td align=left>
<select name=cat OnChange="if (this[this.selectedIndex].value) {document.editor.catnew.value = ''}; return false;">
(%CATSELECTOR%)
</select>
</td>
</tr>
<tr>
<td align=left class=lbl>or define new one: </td>
<td align=left><input type=text size=30 name=catnew value="(%INPUT_catnew%)"></td>
</tr>
<tr>
<td colspan=2 valign=top class=lbl>Answer</td>
EOT
$buff =~ s/<td[^<>]*>\s*Answer\s*<\/td>/$addthis/i;
seek(F,0,0);
print F $buff;
truncate(F, tell(F));
}
close(F);
$fn = $cfg->get('basedir'). "/templates/delanswer.html";
return "File $fn does not exist" if ! -f $fn;
return "File $fn is not writable" if ! -w $fn;
return "Can't open file $fn" if !open(F, "+<$fn");
flock(F,2);
$buff = join('', <F>);
if ($buff !~ /\.lbl/) {
$buff =~ s/-->\s*<\/style>/.lbl { font-size: 9pt; font-weight: 700;}-->\n<\/style>/;
seek(F,0,0);
print F $buff;
truncate(F, tell(F));
}
close(F);
eval "use TTXLayout";
if ($@ ne undef) {
$cfg->set('fltrcols', 'text|subject|oper|status|id');
$cfg->save();
} else {
$cfg->set('fltrcols', 'text|'.$cfg->get('fltrcols'));
}
return undef;
}
# =================================================================== upgrade219
sub upgrade2191 {
my $cfg = $_[0];
my $fn = $cfg->get('basedir'). "/templates/helpdesk.html";
return "File $fn does not exist" if ! -f $fn;
return "File $fn is not writable" if ! -w $fn;
return "Can't open file $fn" if !open(F, "+<$fn");
flock(F,2);
my $buff = join('', <F>);
if ($buff =~ /<\s*input\s+type="?hidden"?\s+name="?qwindow"?\s+value="?\(%INPUT_qwindow%\)"?\s*>/) {
$buff =~ s/<\s*input\s+type="?hidden"?\s+name="?qwindow"?\s+value="?\(%INPUT_qwindow%\)"?\s*>//;
seek(F,0,0);
print F $buff;
truncate(F, tell(F));
}
close(F);
return undef;
}
# =================================================================== upgrade220
sub upgrade220 {
my $cfg = $_[0];
# Disabled in 2.22. Default is do not use cache. Just to avoid problems while
# editing templates.
# $cfg->set('usecache', 1);
eval "use TTXSetup";
if ($@ ne undef) {
return "Error loading TTXSetup: $@";
}
my $v;
eval '$v = $TTXSetup::VERSION';
if ($@ ne undef) {
return "Error reading TTXSetup version: $@";
}
if ($v eq undef || $v < 2.20) {
return "Error: Version mismatch: TTXSetup $v, TTXUpgrade ".$TTXUpgrade::VERSION;
}
return TTXSetup::tmplreset($cfg, 'reports.html');
}
# =================================================================== upgrade221
sub upgrade221 {
return undef;
}
# =================================================================== upgrade222
sub upgrade222 {
my $cfg = $_[0];
for my $f ('header.shtml', 'ticketed.html', 'newanswer.html', 'answerlib.html', 'delanswer.html') {
my $fn = $cfg->get('basedir'). "/templates/$f";
next if ! -f $fn;
return "File $fn is not writable" if ! -w $fn;
return "Can't open file $fn" if !open(F, "+<$fn");
flock(F,2);
my $buff = join('', <F>);
if ($buff !~ /\(%HTML_CHARSET%\)/) {
$buff =~ s/<head>/<head>\n(%HTML_CHARSET%)/i;
seek(F,0,0);
print F $buff;
truncate(F, tell(F));
}
close(F);
}
my $fn = $cfg->get('basedir'). "/templates/ticket.html";
if (-f $fn) {
return "File $fn is not writable" if ! -w $fn;
return "Can't open file $fn" if !open(F, "+<$fn");
flock(F,2);
my $buff = join('', <F>);
if ($buff !~ /function preview\(\)/) {
my $addthis = <<EOT;
<script language="JavaScript"><!--
function preview(){
hwstring="scrollbars=yes,width=600,height=500,resizable=yes,toolbar=no,menubar=no";
var newwin = window.open('', 'winpreview', hwstring);
newwin.focus();
document.forms['preview'].msg.value = document.forms['newticket'].problem.value;
document.forms['preview'].submit();
return false;
}
//--></script>
EOT
$buff =~ s/<table\s/$addthis<table /i;
}
if ($buff !~ /\(%PREVIEW%\)/) {
$buff =~ s/\(%ANSWERLIB%\)/(%ANSWERLIB%)(%PREVIEW%)/i;
}
seek(F,0,0);
print F $buff;
if ($buff !~ /value=preview/) {
print F <<EOT;
<form method="post" action="(%ENV_SCRIPT_NAME%)" id="preview" target="winpreview" >
<input type=hidden name=cmd value=preview>
<input type=hidden name=style value="(%INPUT_style%)">
<input type=hidden name=sid value=(%INPUT_sid%)>
<input type=hidden name=key value=(%INPUT_key%)>
<input type=hidden name=msg>
</form>
EOT
}
truncate(F, tell(F));
close(F);
}
my $ccode = TTXSetup::tmplreset($cfg, 'preview.html');
return $ccode if $ccode ne undef;
return TTXSetup::tmplreset($cfg, 'roticket.html');
}
1;
#
+251
View File
@@ -0,0 +1,251 @@
package TTXUser;
#
# This module is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2003-2005, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 185 $
# $Date: 2006-06-20 08:14:46 -0400 (Tue, 20 Jun 2006) $
#
$TTXUser::VERSION='2.22';
BEGIN {
$TTXUser::REVISION = '$Revision: 185 $';
if ($TTXUser::REVISION =~ /(\d+)/) {
$TTXUser::REVISION = $1;
}
};
use strict;
use TTXData;
my %errmsgs = (
NOUSER => 'User does not exist',
OPENERR => 'Error reading file',
WRERR => 'Error writing file'
);
my $delim;
my $redelim;
# ========================================================================== new
sub new {
my $class = shift;
my $self = {};
bless($self, $class);
$delim = TTXData::get('CONFIG')->get('delim');
$delim = ':' if $delim eq undef;
if ($delim eq '|') {
$redelim = '\|';
} else {
$redelim = $delim;
}
if ($_[0] ne undef) {
$self->load($_[0]);
}
return $self;
}
# ========================================================================== get
sub get {
my $self = shift;
my $name = shift;
return $self->{$name};
}
# ========================================================================== set
sub set {
my $self = shift;
my $name = shift;
my $value = shift;
my $old = $self->{$name};
$self->{$name} = $value;
return $old
}
# ==================================================================== listemail
sub listemail {
$delim = TTXData::get('CONFIG')->get('delim');
$delim = ':' if $delim eq undef;
if ($delim eq '|') {
$redelim = '\|';
} else {
$redelim = $delim;
}
my $fn = TTXData::get('CONFIG')->get('userdb');
if (! -f $fn) {
return undef;
}
if (!open(USRDB, $fn)) {
return undef;
}
my @buff = <USRDB>;
close USRDB;
chomp @buff;
my @list;
foreach my $line (@buff) {
my @parts = split(/$redelim/, $line);
push @list, $parts[4];
}
return @list;
}
# ========================================================================= list
sub list {
$delim = TTXData::get('CONFIG')->get('delim');
$delim = ':' if $delim eq undef;
if ($delim eq '|') {
$redelim = '\|';
} else {
$redelim = $delim;
}
my $fn = TTXData::get('CONFIG')->get('userdb');
if (! -f $fn) {
return undef;
}
if (!open(USRDB, $fn)) {
return undef;
}
my @buff = <USRDB>;
close USRDB;
chomp @buff;
my @list;
foreach my $line (@buff) {
$line =~ s/$redelim.*$//;
push @list, $line;
}
return @list;
}
# ===================================================================== userbysn
sub userbysn {
my $sn = shift;
my @lst = list();
foreach my $uid (@lst) {
my $u = TTXUser->new($uid);
next if $u eq undef || $u->{snum} ne $sn;
return $u;
}
return undef;
}
# ========================================================================= load
sub load {
my $self = shift;
my $login = shift;
my $fn = TTXData::get('CONFIG')->get('userdb');
if (! -f $fn) {
$self->{_ERROR_CODE} = 'NOUSER';
return 0;
}
if (!open(USRDB, $fn)) {
$self->{_ERROR_CODE} = 'OPENERR';
return 0;
}
my @buff = <USRDB>;
close USRDB;
chomp @buff;
foreach my $line (@buff) {
next if $line !~ /^$login$redelim/;
my ($login, $passwd, $fname, $lname, $email, $image, $usemail, $snum, $ro, $sla) = split(/$redelim/, $line);
$self->{login} = $login;
$self->{passwd} = $passwd;
$self->{fname} = $fname;
$self->{lname} = $lname;
$self->{email} = $email;
$self->{image} = $image;
$self->{usemail} = $usemail;
$self->{ro} = $ro;
$self->{snum} = $snum;
$self->{sla} = $sla;
return 1;
}
$self->{_ERROR_CODE} = 'NOUSER';
return 0;
}
# ==================================================================== errortext
sub errortext {
my $self = shift;
return $errmsgs{$self->{_ERROR_CODE}};
}
# ======================================================================= delete
sub delete {
my $self = shift;
my $fn = TTXData::get('CONFIG')->get('userdb');
if (! -f $fn || $self->{login} eq undef) {
$self->{_ERROR_CODE} = 'NOUSER';
return 0;
}
if (open(USRDB,"+<$fn")) {
flock(USRDB, 2);
my @users = <USRDB>;
my $id = $self->{login};
@users = grep(!/^$id$redelim/, @users);
seek(USRDB, 0, 0);
foreach (@users) { print USRDB $_; }
truncate(USRDB, tell(USRDB));
close(USRDB);
} else {
$self->{_ERROR_CODE} = 'WRERR';
return 0;
}
return 1;
}
# ========================================================================= save
sub save {
my $self = shift;
my $fn = TTXData::get('CONFIG')->get('userdb');
if ($self->{login} eq undef) {
$self->{_ERROR_CODE} = 'NOUSER';
return 0;
}
if (! -f $fn) {
open(USRDB, ">$fn");
close USRDB;
umask(0);
chmod(0777, $fn);
}
if (open(USRDB,"+<$fn")) {
flock(USRDB, 2);
my @users = <USRDB>;
my $id = $self->{login};
@users = grep(!/^$id$redelim/, @users);
seek(USRDB, 0, 0);
if ($delim eq ':') {
TTXData::get('CONFIG')->set('delim', '|');
TTXData::get('CONFIG')->save();
$delim = '|';
$redelim = '\|';
foreach my $u (@users) { $u =~ s/:/|/g; print USRDB $u; }
} else {
foreach (@users) { print USRDB $_; }
}
print USRDB $self->{login}.$delim.$self->{passwd}.$delim.$self->{fname}.
$delim.$self->{lname}.$delim.$self->{email}.$delim.$self->{image}.
$delim.$self->{usemail}.$delim.$self->{snum}.$delim.$self->{ro}.$delim.$self->{sla}."\n";
truncate(USRDB, tell(USRDB));
close(USRDB);
} else {
$self->{_ERROR_CODE} = 'WRERR';
return 0;
}
return 1;
}
# ========================================================================= hash
sub hash {
my $self = shift;
my $h = {};
foreach my $key ($self->vars()) {
$h->{$key} = $self->{$key};
}
return $h;
}
1;
#
@@ -0,0 +1,3 @@
4|4Z8987721738407954867|1161676971|1161676971||PND||uphsu@netomi.co.kr|uphsu|&#53580;&#49828;&#53944;|TTXTicket|||||||||||||
1|1Z8887383590727458998|1161675767|1161675767||PND||whatisnet@netomi.co.kr|whatisnet|kakaka|TTXTicket|||||||||||||
2|2Z8974078920432262177|1161676242|1161676456|1161676456|CLS|whatisnet|uphsu@netomi.co.kr|uphsu|uphsu_test|TTXTicket|||||||||||||
+219
View File
@@ -0,0 +1,219 @@
CHARSET,windows-1252
Subject,Subject
Created,Created
Solved,Solved
Customer,Customer
Logged as,Logged as
Home,Home
Tickets,Tickets
Ticket,Ticket
Contact us,Contact us
Login,Login
Logout,Logout
User ID,User ID
Password,Password
Missing User ID,Missing User ID
Missing Password,Missing Password
Wrong User ID or Password,Wrong User ID or Password
Ticket does not exist,Ticket does not exist
Invalid access key,Invalid access key
Add message,Add message
No changes,No changes
Delete ticket,Delete ticket
Please confirm ticket removal,Please confirm ticket removal
Answer library,Answer library
Markup help,Markup help
New status,New status
Posted as a followup to the solved ticket,Posted as a followup to the solved ticket
See attachment,See attachment
Ticket closed,Ticket closed
Missing message,Missing message
Open,Open
Responded,Responded
Closed,Closed
Internal,Internal
Transfer to,Transfer to
Attachments,Attachments
Contact Customer Service,Contact Customer Service
Department,Department
please select,please select
Missing Name,Missing Name
Missing Email,Missing Email
Missing email address,Missing email address
Invalid Email,Invalid Email
Invalid email address,Invalid email address
Missing,Missing
Missing Subject,Missing Subject
The ticket is already assigned to,The ticket is already assigned to
Please be patient. Submission is in progress...,Please be patient. Submission is in progress...
Name,Name
Email,Email
Problem,Problem
Submit,Submit
File,File
Access Key,Access Key
Please select,Please select
Other,Other
Help Desk,Help Desk
id,id
Ticket #,Ticket #
name,name
Name,Name
email,email
subject,subject
operator,operator
Operator,Operator
status,status
Status,Status
updated,updated
created,created
Hot,Hot
Pending,Pending
Open,Open
Active,Active
Not solved,Not solved
group,group
Group,Group
Any,Any
any,any
none,none
There are no tickets matching your query,There are no tickets matching your query
Tickets,Tickets
out of,out of
first,first
prev,prev
next,next
last,last
Search,Search
Show all,Show all
Ticket updated,Ticket updated
Ticket Editor,Ticket Editor
Ticket ID,Ticket ID
Update Ticket,Update Ticket
Close Window,Close Window
Solution,Solution
Use This Answer,Use This Answer
Forgot the key? We will send it to your email address.,Forgot the key? We will send it to your email address.
Email address,Email address
Access keys were sent to your email address.,Access keys were sent to your email address.
Missing access key,Missing access key
No tickets found,No tickets found
Enter,Enter
Cancel,Cancel
"Dear customer,","Dear customer,"
This is a list of all service tickets associated with your email address,This is a list of all service tickets associated with your email address
Use the following link to access your tickets,Use the following link to access your tickets
Kind Regards,Kind Regards
You were logged out,You were logged out
Your session expired,Your session expired
This command is available to operator only. Please login.,This command is available to operator only. Please login.
Select,Select
Preview,Preview
Copy,Copy
Use,Use
New,New
Edit,Edit
Delete,Delete
Close,Close
Notes,Notes
Answer not found,Answer not found
Access denied. You may change your own answers only.,Access denied. You may change your own answers only.
Answer deleted,Answer deleted
Common,Common
available to all operators,available to all operators
Missing Title,Missing Title
Missing Category,Missing Category
Missing Answer,Missing Answer
Answer Updated,Answer Updated
Answer Saved,Answer Saved
No answers defined,No answers defined
All,All
Title,Title
Select existing category,Select existing category
or define new one,or define new one
Answer,Answer
Update,Update
Exit,Exit
Assign to,Assign to
any operator,any operator
Access code,Access code
Copy the code here,Copy the code here
preview,preview
"too big, not saved","too big, not saved"
max size,max size
Missing access code,Missing access code
Missing Operator,Missing Operator
to assign the ticket to,to assign the ticket to
Invalid access code,Invalid access code
Message Preview,Message Preview
Dashboard,Dashboard
Reports,Reports
Date Range,Date Range
Text,Text
Jan,Jan
Feb,Feb
Mar,Mar
Apr,Apr
May,May
Jun,Jun
Jul,Jul
Aug,Aug
Sep,Sep
Oct,Oct
Nov,Nov
Dec,Dec
Close selected,Close selected
Delete selected,Delete selected
sel,sel
Show,Show
tickets per page.,tickets per page.
Include abstracts,Include abstracts
Groups,Groups
Claim ownership,Claim ownership
Done,Done
Deleting answer,Deleting answer
Are you sure?,Are you sure?
Yes,Yes
No,No
Submitted,Submitted
Select Report,Select Report
Overview,Overview
Operator Performance,Operator Performance
Ticket Aging,Ticket Aging
Hot Tickets,Hot Tickets
Service Level,Service Level
Build Report,Build Report
No report selected,No report selected
Unknown report requested,Unknown report requested
New tickets,New tickets
Today,Today
This Week,This Week
This Month,This Month
"New tickets, last 12 months","New tickets, last 12 months"
"New tickets, last 12 weeks","New tickets, last 12 weeks"
"New tickets, last 30 days","New tickets, last 30 days"
"Answers, this month","Answers, this month"
"Answers, this week","Answers, this week"
"Answers, today","Answers, today"
"Answers, last 12 months","Answers, last 12 months"
"Answers, last 12 weeks","Answers, last 12 weeks"
"Answers, last 30 days","Answers, last 30 days"
Service Level Report,Service Level Report
percentage of tickets solved within SLA time,percentage of tickets solved within SLA time
Last Week,Last Week
Last Month,Last Month
Breakdown of time to close a ticket,Breakdown of time to close a ticket
tickets submitted during last 365 days,tickets submitted during last 365 days
tickets in open or pending state,tickets in open or pending state
Markup Quick Guide,Markup Quick Guide
hrs,hrs
days,days
add notes,add notes
Item,Item
Posted by,Posted by
on,on
Date,Date
Ticket transfer notice,Ticket transfer notice
Transferred by,Transferred by
Access link,Access link
Access key,Access key
1 CHARSET windows-1252
2 Subject Subject
3 Created Created
4 Solved Solved
5 Customer Customer
6 Logged as Logged as
7 Home Home
8 Tickets Tickets
9 Ticket Ticket
10 Contact us Contact us
11 Login Login
12 Logout Logout
13 User ID User ID
14 Password Password
15 Missing User ID Missing User ID
16 Missing Password Missing Password
17 Wrong User ID or Password Wrong User ID or Password
18 Ticket does not exist Ticket does not exist
19 Invalid access key Invalid access key
20 Add message Add message
21 No changes No changes
22 Delete ticket Delete ticket
23 Please confirm ticket removal Please confirm ticket removal
24 Answer library Answer library
25 Markup help Markup help
26 New status New status
27 Posted as a followup to the solved ticket Posted as a followup to the solved ticket
28 See attachment See attachment
29 Ticket closed Ticket closed
30 Missing message Missing message
31 Open Open
32 Responded Responded
33 Closed Closed
34 Internal Internal
35 Transfer to Transfer to
36 Attachments Attachments
37 Contact Customer Service Contact Customer Service
38 Department Department
39 please select please select
40 Missing Name Missing Name
41 Missing Email Missing Email
42 Missing email address Missing email address
43 Invalid Email Invalid Email
44 Invalid email address Invalid email address
45 Missing Missing
46 Missing Subject Missing Subject
47 The ticket is already assigned to The ticket is already assigned to
48 Please be patient. Submission is in progress... Please be patient. Submission is in progress...
49 Name Name
50 Email Email
51 Problem Problem
52 Submit Submit
53 File File
54 Access Key Access Key
55 Please select Please select
56 Other Other
57 Help Desk Help Desk
58 id id
59 Ticket # Ticket #
60 name name
61 Name Name
62 email email
63 subject subject
64 operator operator
65 Operator Operator
66 status status
67 Status Status
68 updated updated
69 created created
70 Hot Hot
71 Pending Pending
72 Open Open
73 Active Active
74 Not solved Not solved
75 group group
76 Group Group
77 Any Any
78 any any
79 none none
80 There are no tickets matching your query There are no tickets matching your query
81 Tickets Tickets
82 out of out of
83 first first
84 prev prev
85 next next
86 last last
87 Search Search
88 Show all Show all
89 Ticket updated Ticket updated
90 Ticket Editor Ticket Editor
91 Ticket ID Ticket ID
92 Update Ticket Update Ticket
93 Close Window Close Window
94 Solution Solution
95 Use This Answer Use This Answer
96 Forgot the key? We will send it to your email address. Forgot the key? We will send it to your email address.
97 Email address Email address
98 Access keys were sent to your email address. Access keys were sent to your email address.
99 Missing access key Missing access key
100 No tickets found No tickets found
101 Enter Enter
102 Cancel Cancel
103 Dear customer, Dear customer,
104 This is a list of all service tickets associated with your email address This is a list of all service tickets associated with your email address
105 Use the following link to access your tickets Use the following link to access your tickets
106 Kind Regards Kind Regards
107 You were logged out You were logged out
108 Your session expired Your session expired
109 This command is available to operator only. Please login. This command is available to operator only. Please login.
110 Select Select
111 Preview Preview
112 Copy Copy
113 Use Use
114 New New
115 Edit Edit
116 Delete Delete
117 Close Close
118 Notes Notes
119 Answer not found Answer not found
120 Access denied. You may change your own answers only. Access denied. You may change your own answers only.
121 Answer deleted Answer deleted
122 Common Common
123 available to all operators available to all operators
124 Missing Title Missing Title
125 Missing Category Missing Category
126 Missing Answer Missing Answer
127 Answer Updated Answer Updated
128 Answer Saved Answer Saved
129 No answers defined No answers defined
130 All All
131 Title Title
132 Select existing category Select existing category
133 or define new one or define new one
134 Answer Answer
135 Update Update
136 Exit Exit
137 Assign to Assign to
138 any operator any operator
139 Access code Access code
140 Copy the code here Copy the code here
141 preview preview
142 too big, not saved too big, not saved
143 max size max size
144 Missing access code Missing access code
145 Missing Operator Missing Operator
146 to assign the ticket to to assign the ticket to
147 Invalid access code Invalid access code
148 Message Preview Message Preview
149 Dashboard Dashboard
150 Reports Reports
151 Date Range Date Range
152 Text Text
153 Jan Jan
154 Feb Feb
155 Mar Mar
156 Apr Apr
157 May May
158 Jun Jun
159 Jul Jul
160 Aug Aug
161 Sep Sep
162 Oct Oct
163 Nov Nov
164 Dec Dec
165 Close selected Close selected
166 Delete selected Delete selected
167 sel sel
168 Show Show
169 tickets per page. tickets per page.
170 Include abstracts Include abstracts
171 Groups Groups
172 Claim ownership Claim ownership
173 Done Done
174 Deleting answer Deleting answer
175 Are you sure? Are you sure?
176 Yes Yes
177 No No
178 Submitted Submitted
179 Select Report Select Report
180 Overview Overview
181 Operator Performance Operator Performance
182 Ticket Aging Ticket Aging
183 Hot Tickets Hot Tickets
184 Service Level Service Level
185 Build Report Build Report
186 No report selected No report selected
187 Unknown report requested Unknown report requested
188 New tickets New tickets
189 Today Today
190 This Week This Week
191 This Month This Month
192 New tickets, last 12 months New tickets, last 12 months
193 New tickets, last 12 weeks New tickets, last 12 weeks
194 New tickets, last 30 days New tickets, last 30 days
195 Answers, this month Answers, this month
196 Answers, this week Answers, this week
197 Answers, today Answers, today
198 Answers, last 12 months Answers, last 12 months
199 Answers, last 12 weeks Answers, last 12 weeks
200 Answers, last 30 days Answers, last 30 days
201 Service Level Report Service Level Report
202 percentage of tickets solved within SLA time percentage of tickets solved within SLA time
203 Last Week Last Week
204 Last Month Last Month
205 Breakdown of time to close a ticket Breakdown of time to close a ticket
206 tickets submitted during last 365 days tickets submitted during last 365 days
207 tickets in open or pending state tickets in open or pending state
208 Markup Quick Guide Markup Quick Guide
209 hrs hrs
210 days days
211 add notes add notes
212 Item Item
213 Posted by Posted by
214 on on
215 Date Date
216 Ticket transfer notice Ticket transfer notice
217 Transferred by Transferred by
218 Access link Access link
219 Access key Access key
Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

+6
View File
@@ -0,0 +1,6 @@
<HTML>
<HEAD>
<META http-equiv="Refresh" content="0;url=http://tts.0x31.com/ttx.cgi?cmd=login">
</HEAD>
<BODY><BODY>
</HTML>
+123
View File
@@ -0,0 +1,123 @@
#!/usr/bin/perl
#
# This script is a part of Trouble Ticket Express package
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2002-2006, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 274 $
# $Date: 2006-09-20 00:03:43 +0400 (Wed, 20 Sep 2006) $
#
#
# please feel free to uncomment the following line in order to get rid of
# bogus "usage of uninitialized variable" in your error log file, but
# make sure your Perl supports the 'no warnings' pragma
#
# no warnings 'uninitialized';
# ==== NOTHING TO EDIT BELOW THIS LINE. PLS DO NOT CROSS IF NOT SURE ===========
BEGIN {
my $sd = _findsd() || '.';
$sd =~ /(.*)/;
$sd = $1;
eval "use lib '$sd'";
if ($@) {
_fatalbegin($@);
exit 0;
}
if ($sd ne '.') {
chdir $sd;
}
sub _fatalbegin {
print <<EOT;
Content-type: text/html
<html>
<body>
<br><br>
<font color=red><b>Fatal error:</b></font>
$_[0]
<br><br>
<a href="http://ttx.helpdeskconnect.com"><b>Trouble Ticket Express Help Desk</b></a>
</body>
</html>
EOT
}
sub _findsd {
my $dir;
$dir = $ENV{'SCRIPT_FILENAME'};
$dir = $ENV{'PATH_TRANSLATED'} if $ENV{'PATH_TRANSLATED'} ne undef;
$dir = $ENV{'pathTranslated'} if $ENV{'pathTranslated'} ne undef;
return $ENV{'PWD'} if $dir eq undef;
my @path = split(/\/|\\/, $dir);
pop(@path);
$dir = join("\/", @path);
return $dir;
}
}
use strict;
use TTXConfig;
eval 'use GD';
if ($@ ne undef) {
print <<EOT;
Content-type: text/html
<html>
<body>
Error loading GD.pm
<br>
$@
</body>
</html>
EOT
exit 0;
}
#
# Read config
#
my $configfile = "ttxcfg.cgi";
my $cfg = TTXConfig->new($configfile);
if ($cfg->error()) {
print "Content-type: text/html\n\n<html><body>Fatal error: ".$cfg->errortext()."</body></html>\n";
exit 0;
}
if ($cfg->get('cfgref') ne undef) {
if (!$cfg->load($cfg->get('cfgref'))) {
print "Content-type: text/html\n\n<html><body>Fatal error: ".$cfg->errortext()."</body></html>\n";
exit 0;
}
}
my $im = new GD::Image(50,20);
my $white = $im->colorAllocate(255,255,255);
my $black = $im->colorAllocate(0,0,0);
$im->fill(0,0,$white);
$im->rectangle(0,0,49,19,$black);
my $keyfn = $ENV{QUERY_STRING};
$keyfn =~ /([0-9-]+)$/;
$keyfn = $1;
if ($keyfn =~ /^\d+-\d+$/) {
if (open(KF, $cfg->get('basedir')."/keys/$keyfn.cgi")) {
my $key = <KF>;
close KF;
chomp $key;
$im->string(GD::gdGiantFont(), 6, 3, $key, $black);
}
}
print "Content-type: image/gif\nExpires: Wed, 13-Dec-1995 16:28:32 GMT\n\n";
binmode STDOUT;
print $im->gif();
my $tm = time();
$tm -= 24*3600;
my $dir = $cfg->get('basedir').'/keys';
if (opendir(KEYDIR, $dir)) {
my @files = grep { /^\d+-\d+\.cgi/ && -f "$dir/$_" } readdir(KEYDIR);
closedir KEYDIR;
foreach my $f (@files) {
$f =~ /^(\d+)/;
next if $1 > $tm;
unlink "$dir/$f";
}
}
@@ -0,0 +1 @@
1120
@@ -0,0 +1 @@
8070
@@ -0,0 +1 @@
9873
@@ -0,0 +1 @@
9022
+199
View File
@@ -0,0 +1,199 @@
#!/usr/bin/perl
#
# This script is a part of
# Trouble Ticket Express package.
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2005, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 199 $
# $Date: 2006-07-16 03:12:21 -0400 (Sun, 16 Jul 2006) $
#
my $configfile;
my $VERSION = '2.22';
my $REVISION;
# ==== NOTHING TO EDIT BELOW THIS LINE. PLS DO NOT CROSS =======================
BEGIN {
if ($^O eq 'MSWin32') {
eval "use FindBin";
eval "use lib $FindBin::Bin";
chdir($FindBin::Bin);
}
$REVISION = '$Revision: 199 $';
if ($REVISION =~ /(\d+)/) {
$REVISION = $1;
}
}
use strict;
use CGI;
use TTXConfig;
use TTXMSSQLSetup;
use TTXData;
#
# Global vars
#
my $cfg;
my $query;
my %data;
print "Content-type: text/html\n\n";
header();
#
# Read config
#
$configfile = 'ttxcfg.cgi' if $configfile eq undef;
$cfg = TTXConfig->new($configfile);
runsetup() if $cfg eq undef || $cfg->error() ne undef;
if ($cfg->get('cfgref') ne undef) {
my $regcfg = TTXConfig->new($cfg->get('cfgref'));
$cfg = $regcfg;
runsetup() if $cfg->error() ne undef;
}
TTXData::set('CONFIG', $cfg);
#
# Parse input
#
$query = new CGI;
#
# Validate user if id provided
#
if ($query->param('pwd') ne undef) {
if ($cfg->get('admpwd') ne $query->param('pwd')) {
login();
}
} elsif ($cfg->get('admpwd') ne undef) {
login();
} else {
runsetup(); # Just to make sure.
}
#
# Execute command
#
my $cmd = $query->param('cmd');
$cmd = 'setup1' if $cmd eq undef;
if ($cmd eq 'setup1') {
TTXMSSQLSetup::setup1($cfg, $query);
} elsif ($cmd eq 'login') {
dologin();
}
footer();
#======================================================================= dologin
sub dologin {
my $error;
if ($query->param('do')) {
if ($query->param('passwd') eq undef || $query->param('passwd') ne $cfg->get('admpwd')) {
$error = "Invalid password";
} else {
$query->param(-name => 'pwd', -value => $query->param('passwd'));
$query->param(-name => 'do', -value => '');
TTXMSSQLSetup::setup1($cfg, $query);
return;
}
}
$error = "<br><font color=red><b>Error: $error</b></font><br><br>" if $error ne undef;
print <<EOT;
<center><b>Please login</b>
<br><br>$error
<table cellpadding=3>
<form action=$ENV{SCRIPT_NAME} method=post>
<input type=hidden name=cmd value=login>
<input type=hidden name=do value=1>
<tr>
<td align=left class=lbl>Administrator password</td>
<td align=left><input type=password name=passwd></td>
</tr>
<tr>
<td colspan=2 align=right>
<input type=submit>
</td>
</tr>
</form>
</table>
</center>
EOT
}
#========================================================================= login
sub login {
$query->param(-name => 'pwd', -value => '');
$query->param(-name => 'cmd', -value => 'login');
}
#====================================================================== runsetup
sub runsetup {
print <<EOT;
<html>
<head><title>Trouble Ticket Express</title></head>
<body>
<br><br><center>
<b><font color=red>Error reading configuration file.</font></b>
<br><br>
Please execute <a href=setup.cgi><b>Main Setup Utility</b></a> first.
</center>
</body>
</html>
EOT
exit;
}
#==================================================================== fatalerror
sub fatalerror {
print <<EOT;
<html>
<head><title>Trouble Ticket Express</title></head>
<body>
<br><center><h1>Fatal Error: $_[0]</h1>
</body>
</html>
EOT
exit;
}
sub header {
print <<EOT;
<html>
<head>
<title>
Trouble Ticket Express - MS SQL Server Module Setup
</title>
<style type="text/css">
body, td { font-family: Verdana, Helvetica, sans-serif; font-size: 10pt;}
A { color : #2E3197; text-decoration : none; }
A:Hover { color : #C00; text-decoration : underline;}
.sm {font-size: 8pt;}
.tiny {font-size: 4pt;}
.heading {font-size: 13pt;font-weight: 700; color: #2E3197;}
.lbl {font-size: 9pt;font-weight: 700;}
</style>
</head>
<body>
<center>
<table width=700>
<tr>
<td align=left>
EOT
}
# ======================================================================= footer
sub footer {
print <<EOT;
</td></tr>
</table>
<br><br>
rev. $VERSION.$REVISION
</center>
</body>
</html>
EOT
}
+353
View File
@@ -0,0 +1,353 @@
#!/usr/bin/perl
#
# This script is a part of
# Trouble Ticket Express package.
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2002-2005, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 196 $
# $Date: 2006-07-12 10:48:30 -0400 (Wed, 12 Jul 2006) $
#
#
my $configfile;
my $VERSION = '2.22';
my $REVISION;
# ==== NOTHING TO EDIT BELOW THIS LINE. PLS DO NOT CROSS =======================
BEGIN {
$REVISION = '$Revision: 196 $';
if ($REVISION =~ /(\d+)/) {
$REVISION = $1;
}
my $sd = _findsd() || '.';
$sd =~ /(.*)/;
$sd = $1;
eval "use lib '$sd'";
if ($@) {
_fatalbegin($@);
exit 0;
}
if ($sd ne '.') {
chdir $sd;
}
eval "use TTXConfig";
if ($@) {
if (-f "$sd/TTXConfig.pm") {
_fatalbegin($@);
} else {
_fatalbegin("Incomplete package. Please upload all *.cgi and *.pm files to your web server");
}
exit 0;
}
sub _fatalbegin {
print <<EOT;
Content-type: text/html
<html>
<body>
<br><br>
<font color=red><b>Fatal error:</b></font>
$_[0]
<br><br>
<a href="ttx.helpdeskconnect.com"><b>Trouble Ticket Express Help Desk</b></a><br />
EOT
print "<br /><strong>SDir:</strong> $sd<br />\n";
foreach my $key (sort keys %ENV) {
print "<strong>$key:</strong> $ENV{$key}<br />\n";
}
print "</body>\n</html>\n";
}
sub _findsd {
my $dir = $ENV{'SCRIPT_FILENAME'};
$dir = $ENV{'PATH_TRANSLATED'} if $ENV{'PATH_TRANSLATED'} ne undef;
$dir = $ENV{'pathTranslated'} if $ENV{'pathTranslated'} ne undef;
return $ENV{'PWD'} if $dir eq undef;
my @path = split(/\/|\\/, $dir);
pop(@path);
$dir = join("\/", @path);
return $dir;
}
}
use strict;
use CGI;
use TTXConfig;
use TTXSetup;
use TTXData;
#
# Global vars
#
my $cfg;
my $query;
my %data;
print "Content-type: text/html\n\n";
#
# Read config
#
$configfile = 'ttxcfg.cgi' if $configfile eq undef;
$cfg = TTXConfig->new($configfile);
TTXData::set('CONFIG', $cfg);
my $freshsetup = 1 if $cfg->error() ne undef;
if ($cfg->get('cfgref') ne undef) {
my $regcfg = TTXConfig->new($cfg->get('cfgref'));
$cfg = $regcfg;
$freshsetup = 1 if $cfg->error() ne undef;
TTXData::set('CONFIG', $cfg);
}
#
# Parse input
#
$query = new CGI;
#
# Validate user if not fresh setup and id provided
#
if (!$freshsetup && $query->param('cmd') ne 'logout') {
if ($query->param('pwd') ne undef) {
if ($cfg->get('admpwd') eq $query->param('pwd')) {
my $seed = join ('', ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64]);
$cfg->set('admpwdseed', $seed);
$cfg->save();
my $cpwd = crypt($cfg->get('admpwd'), $seed);
$cpwd =~ s/^..//;
$query->param(-name => 'pwd', value => $cpwd);
}
if (crypt($cfg->get('admpwd'), $cfg->get('admpwdseed')) ne $cfg->get('admpwdseed').$query->param('pwd')) {
login();
} else {
my $seed = join ('', ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64]);
$cfg->set('admpwdseed', $seed);
$cfg->save();
my $cpwd = crypt($cfg->get('admpwd'), $seed);
$cpwd =~ s/^..//;
$query->param(-name => 'pwd', value => $cpwd);
}
} elsif ($cfg->get('admpwd') ne undef) {
login();
} else {
$query->param(-name => 'cmd', -value => 'setup3');
}
}
header();
#
# Execute command
#
my $cmd = $query->param('cmd');
$cmd = 'setup1' if $cmd eq undef;
if ($cmd eq 'setup1') {
TTXSetup::setup1($cfg, $query);
} elsif ($cmd eq 'setup2') {
TTXSetup::setup2($cfg, $query);
} elsif ($cmd eq 'setup3') {
TTXSetup::setup3($cfg, $query);
} elsif ($cmd eq 'setup4') {
TTXSetup::setup4($cfg, $query);
} elsif ($cmd eq 'setup5') {
TTXSetup::setup5($cfg, $query);
} elsif ($cmd eq 'grps') {
TTXSetup::grps($cfg, $query);
} elsif ($cmd eq 'inventory') {
TTXSetup::inventory($cfg, $query);
} elsif ($cmd eq 'logout') {
if (!$freshsetup) {
$cfg->set('admpwdseed', '');
$cfg->save();
}
dologin();
} elsif ($cmd eq 'login') {
dologin();
} elsif ($cmd eq 'smtplog') {
smtplog();
} elsif ($cmd eq 'sysinfo') {
TTXSetup::sysinfo($cfg, $query);
}
footer($ENV{'QUERY_STRING'} !~ /pwd=/ ? 1:0);
#======================================================================= dologin
sub dologin {
my $error;
if ($query->param('do')) {
if ($query->param('passwd') eq undef || $query->param('passwd') ne $cfg->get('admpwd')) {
$error = "Invalid password";
} else {
my $seed = join ('', ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64]);
$cfg->set('admpwdseed', $seed);
$cfg->save();
my $cpwd = crypt($cfg->get('admpwd'), $seed);
$cpwd =~ s/^..//;
$query->param(-name => 'pwd', value => $cpwd);
$query->param(-name => 'do', -value => '');
TTXSetup::setup4($cfg, $query);
return;
}
}
$error = "<br><font color=red><b>Error: $error</b></font><br><br>" if $error ne undef;
print <<EOT;
<center><b>Please login</b>
<br><br>$error
<table cellpadding=3>
<form action=$ENV{SCRIPT_NAME} method=post>
<input type=hidden name=cmd value=login>
<input type=hidden name=do value=1>
<tr>
<td align=left class=lbl>Administrator password</td>
<td align=left><input type=password name=passwd></td>
</tr>
<tr>
<td colspan=2 align=right>
<input type=submit>
</td>
</tr>
</form>
</table>
<br><br>
Subscribe to <a href="http://www.unitedwebcoders.com">United Web Coders</a> news.
<br>
Stay tuned for new software releases and yet to be documented features.
<br>
<br>
<table>
<tr>
<td>
<a href="http://feeds.feedburner.com/uwc"
title="Subscribe to United Web Coders News Feed"
rel="alternate"
type="application/rss+xml">
<img src="http://www.unitedwebcoders.com/i/feed-icon16x16.png" alt="" style="border:0"/></a>
</td><td alig=left>
<a href="http://feeds.feedburner.com/uwc"
rel="alternate"
type="application/rss+xml">
Use RSS news feed.
</a>
</td>
</tr>
</table>
<form
action="http://www.feedburner.com/fb/a/emailverify" method="post"
target="popupwindow"
onsubmit="window.open('http://www.feedburner.com', 'popupwindow', 'scrollbars=yes,width=550,height=520');return true">
<b>or</b>
Subscribe to our mail list
<small><br><br></small>
<span class=lbl>Email: </span><input type="text" style="width:140px" name="email"/>
<input type="hidden" value="http://feeds.feedburner.com/~e?ffid=373254" name="url"/>
<input type="hidden" value="United Web Coders" name="title"/>
<input type="submit" value="Subscribe" />
<small><br><br></small>
<small>Delivered by <a href="http://www.feedburner.com/" target="_blank">FeedBurner</a></small></form></center>
EOT
}
# ====================================================================== smtplog
sub smtplog {
my $smtplog = $cfg->get('basedir').'/smtptrace.txt';
my $pwd = $query->param('pwd');
if (! -f $smtplog) {
print "<br><center><b>SMTP log file does not exist</b></center><br>\n";
} elsif (!open(LOG, $smtplog)) {
print "<br><center><b><font color=red>Error opening SMTP log file.</font></b></center><br>\n";
} else {
print <<EOT;
<center>
<br><br>
<form action=$ENV{SCRIPT_NAME} method=post>
<input type=hidden name=cmd value=setup4>
<input type=hidden name=pwd value=$pwd>
<input type=submit value="System Setup Form">
</form>
</center>
EOT
my @buff = <LOG>;
close LOG;
foreach my $line (@buff) {
$line =~ s/</&lt;/g;
print "$line<br>";
}
}
print <<EOT;
<center>
<br><br>
<form action=$ENV{SCRIPT_NAME} method=post>
<input type=hidden name=cmd value=setup4>
<input type=hidden name=pwd value=$pwd>
<input type=submit value="System Setup Form">
</form>
</center>
EOT
}
#========================================================================= login
sub login {
$query->param(-name => 'pwd', -value => '');
$query->param(-name => 'cmd', -value => 'login');
}
#==================================================================== fatalerror
sub fatalerror {
print <<EOT;
<html>
<head><title>Trouble Ticket Express</title></head>
<body>
<br><center><h1>Fatal Error: $_[0]</h1>
</body>
</html>
EOT
exit;
}
sub header {
my $logout;
if (!$freshsetup) {
$logout = "<table width=600><tr><td align=right>".
"<a href=\"$ENV{SCRIPT_NAME}?cmd=logout\">".
"<span class=sm><b>logout</b></span></a></td></tr></table>\n";
}
print <<EOT;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<title>
Trouble Ticket Express Setup
</title>
<style type="text/css">
body, td { font-family: Verdana, Helvetica, sans-serif; font-size: 10pt;}
A { color : #2E3197; text-decoration : none; }
A:Hover { color : #C00; text-decoration : underline;}
.sm {font-size: 8pt;}
.tiny {font-size: 4pt;}
.heading {font-size: 13pt;font-weight: 700; color: #2E3197;}
.lbl {font-size: 9pt;font-weight: 700;}
</style>
</head>
<body>
<center>
<table width=700>
<tr>
<td align=left>$logout
EOT
}
# ======================================================================= footer
sub footer {
print <<EOT;
</td></tr>
</table>
<br><br>
rev. $VERSION.$REVISION
</center>
</body>
</html>
EOT
}
@@ -0,0 +1,10 @@
expires=1175711850
helpdesk.qoffset=0
helpdesk.qsort=updated
helpdesk.qsortorder=D
helpdesk.qwindow=20
imgurl=.
login=tael
ticketdb=/tickets.cgi
ticketid=/ticketid.txt
userdb=/users.cgi
+199
View File
@@ -0,0 +1,199 @@
#!/usr/bin/perl
#
# This script is a part of
# Trouble Ticket Express package.
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2002-2006, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 203 $
# $Date: 2006-07-18 00:28:33 -0400 (Tue, 18 Jul 2006) $
#
my $configfile;
my $VERSION = '2.22';
my $REVISION;
# ==== NOTHING TO EDIT BELOW THIS LINE. PLS DO NOT CROSS =======================
BEGIN {
if ($^O eq 'MSWin32') {
eval "use FindBin";
eval "use lib $FindBin::Bin";
chdir($FindBin::Bin);
}
$REVISION = '$Revision: 203 $';
if ($REVISION =~ /(\d+)/) {
$REVISION = $1;
}
}
use strict;
use CGI;
use TTXConfig;
use TTXMySQLSetup;
use TTXData;
#
# Global vars
#
my $cfg;
my $query;
my %data;
print "Content-type: text/html\n\n";
header();
#
# Read config
#
$configfile = 'ttxcfg.cgi' if $configfile eq undef;
$cfg = TTXConfig->new($configfile);
runsetup() if $cfg eq undef || $cfg->error() ne undef;
if ($cfg->get('cfgref') ne undef) {
my $regcfg = TTXConfig->new($cfg->get('cfgref'));
$cfg = $regcfg;
runsetup() if $cfg->error() ne undef;
}
TTXData::set('CONFIG', $cfg);
#
# Parse input
#
$query = new CGI;
#
# Validate user if id provided
#
if ($query->param('pwd') ne undef) {
if ($cfg->get('admpwd') ne $query->param('pwd')) {
login();
}
} elsif ($cfg->get('admpwd') ne undef) {
login();
} else {
runsetup(); # Just to make sure.
}
#
# Execute command
#
my $cmd = $query->param('cmd');
$cmd = 'setup1' if $cmd eq undef;
if ($cmd eq 'setup1') {
TTXMySQLSetup::setup1($cfg, $query);
} elsif ($cmd eq 'login') {
dologin();
}
footer();
#======================================================================= dologin
sub dologin {
my $error;
if ($query->param('do')) {
if ($query->param('passwd') eq undef || $query->param('passwd') ne $cfg->get('admpwd')) {
$error = "Invalid password";
} else {
$query->param(-name => 'pwd', -value => $query->param('passwd'));
$query->param(-name => 'do', -value => '');
TTXMySQLSetup::setup1($cfg, $query);
return;
}
}
$error = "<br><font color=red><b>Error: $error</b></font><br><br>" if $error ne undef;
print <<EOT;
<center><b>Please login</b>
<br><br>$error
<table cellpadding=3>
<form action=$ENV{SCRIPT_NAME} method=post>
<input type=hidden name=cmd value=login>
<input type=hidden name=do value=1>
<tr>
<td align=left class=lbl>Administrator password</td>
<td align=left><input type=password name=passwd></td>
</tr>
<tr>
<td colspan=2 align=right>
<input type=submit>
</td>
</tr>
</form>
</table>
</center>
EOT
}
#========================================================================= login
sub login {
$query->param(-name => 'pwd', -value => '');
$query->param(-name => 'cmd', -value => 'login');
}
#====================================================================== runsetup
sub runsetup {
print <<EOT;
<html>
<head><title>Trouble Ticket Express</title></head>
<body>
<br><br><center>
<b><font color=red>Error reading configuration file.</font></b>
<br><br>
Please execute <a href=setup.cgi><b>Main Setup Utility</b></a> first.
</center>
</body>
</html>
EOT
exit;
}
#==================================================================== fatalerror
sub fatalerror {
print <<EOT;
<html>
<head><title>Trouble Ticket Express</title></head>
<body>
<br><center><h1>Fatal Error: $_[0]</h1>
</body>
</html>
EOT
exit;
}
sub header {
print <<EOT;
<html>
<head>
<title>
Trouble Ticket Express - MySQL Module Setup
</title>
<style type="text/css">
body, td { font-family: Verdana, Helvetica, sans-serif; font-size: 10pt;}
A { color : #2E3197; text-decoration : none; }
A:Hover { color : #C00; text-decoration : underline;}
.sm {font-size: 8pt;}
.tiny {font-size: 4pt;}
.heading {font-size: 13pt;font-weight: 700; color: #2E3197;}
.lbl {font-size: 9pt;font-weight: 700;}
</style>
</head>
<body>
<center>
<table width=700>
<tr>
<td align=left>
EOT
}
# ======================================================================= footer
sub footer {
print <<EOT;
</td></tr>
</table>
<br><br>
rev. $VERSION.$REVISION
</center>
</body>
</html>
EOT
}
+591
View File
@@ -0,0 +1,591 @@
#!/usr/bin/perl
#
# This script is a part of
# Trouble Ticket Express package.
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2002-2005, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 92 $
# $Date: 2005-12-02 06:17:59 -0500 (Fri, 02 Dec 2005) $
#
my $configfile;
# ==== NOTHING TO EDIT BELOW THIS LINE. PLS DO NOT CROSS =======================
BEGIN {
if ($^O eq 'MSWin32') {
eval "use FindBin";
eval "use lib $FindBin::Bin";
chdir($FindBin::Bin);
}
}
use strict;
use CGI;
use TTXConfig;
use TTXCommon;
use TTXData;
#
# Global vars
#
my $cfg;
my $query;
my $version = '2.21';
my %data;
print "Content-type: text/html\n\n";
header();
#
# Read config
#
if ($configfile eq undef) {
$configfile = 'ttxcfg.cgi';
my $sd = scriptdir();
$configfile = "$sd/ttxcfg.cgi" if $sd ne undef;
}
$cfg = TTXConfig->new($configfile);
runsetup() if $cfg eq undef || $cfg->error() ne undef;
if ($cfg->get('cfgref') ne undef) {
my $regcfg = TTXConfig->new($cfg->get('cfgref'));
$cfg = $regcfg;
runsetup() if $cfg->error() ne undef;
}
TTXData::set('CONFIG', $cfg);
#
# Parse input
#
$query = new CGI;
#
# Validate user if id provided
#
if ($query->param('pwd') ne undef) {
if ($cfg->get('admpwd') ne $query->param('pwd')) {
login();
}
} elsif ($cfg->get('admpwd') ne undef) {
login();
} else {
runsetup(); # Just to make sure.
}
#
# Execute command
#
my $cmd = $query->param('cmd');
$cmd = 'setup1' if $cmd eq undef;
if ($cmd eq 'setup1') {
setup1($cfg, $query);
} elsif ($cmd eq 'setup2') {
setup2($cfg, $query);
} elsif ($cmd eq 'login') {
dologin();
}
footer();
#========================================================================== stop
sub stop {
print <<EOT;
<center>
<br>
<table width=500>
<tr>
<td align=left>
$_[0]
</tr>
</td>
</table>
</center>
EOT
}
#===================================================================== foolproof
sub foolproof {
my ($cfg) = @_;
my $dbmode = $cfg->get('dbmode');
if ($dbmode !~ /sql/) {
stop("SQL mode is not activated yet. Please use".
" either <a href=\"sqlsetup.cgi\"><b><nobr>MySQL setup</nobr></b><a> or".
" <a href=\"mssqlsetup.cgi\"><b><nobr>SQL Server setup</nobr></b><a> utility".
" to configure SQL mode.");
} elsif($cfg->get('dbschema') > 2.18) {
stop("You have already upgraded your database");
} else {
#
# Check if updated SQL module installed
#
if ($cfg->get('dbmode') eq 'mysql') {
eval "use TTXMySQLTickets";
if ($@ ne undef) {
stop("<b>Error loading TTXMySQLTickets, $@</b>");
return 0;
}
my $modver;
eval '$modver = $TTXMySQLTickets::VERSION';
if ($@ ne undef) {
stop("<b>Error querying TTXMySQLTickets, $@</b>");
return 0;
}
if ($modver < 2.19) {
stop("<b>Please install latest (2.19) version of TTXMySQLTickets.pm<br><br>\n".
"<center><a href=\"http://www.troubleticketexpress.com/mysql.html\">Order/Download instructions</a></center></b>");
return 0;
}
} else {
eval "use TTXMSSQLTickets";
if ($@ ne undef) {
stop("<b>Error loading TTXMSSQLTickets, $@</b>");
return 0;
}
my $modver;
eval '$modver = $TTXMSSQLTickets::VERSION';
if ($@ ne undef) {
stop("<b>Error querying TTXMSSQLTickets, $@</b>");
return 0;
}
if ($modver < 2.19) {
stop("<b>Please install latest (2.19) version of TTXMSSQLTickets.pm<br><br>\n".
"<center><a href=\"http://www.troubleticketexpress.com/mssql.html\">Order/Download instructions</a></center></b>");
return 0;
}
}
return 1;
}
return 0;
}
#======================================================================== setup2
sub setup2 {
my ($cfg, $query, $msg) = @_;
my $pwd = TTXCommon::cleanit($query, 'pwd');
return if !foolproof($cfg);
my $tickets = TTXCommon::dbtik();
if ($tickets eq undef) {
stop("Fatal error: can't access tickets database");
return;
}
my $dbh = $tickets->{DBH};
if ($dbh eq undef) {
stop("Fatal error: can't obtain database handle");
return;
}
my $msgtable = TTXCommon::cleanit($query, 'dbmessages');
$msgtable = $cfg->get('dbmessages') if $msgtable eq undef;
$msgtable = $cfg->get('dbpref').'messages' if $msgtable eq undef;
$msgtable =~ /^([a-zA-Z][a-zA-Z0-9_]+)$/;
my $tmp = $1;
if ($tmp eq undef) {
setup1($cfg, $query, "Invalid table name: $tmp");
return;
}
$msgtable = $tmp;
if (texists($cfg, $dbh, $msgtable)) {
if (!isttxtable($cfg, $dbh, $msgtable)) {
setup1($cfg, $query, "Table <i>$msgtable</i> exist");
return;
}
if (!$dbh->do("DROP TABLE $msgtable")) {
stop("Fatal error: Unable to delete table $msgtable, ".$dbh->errstr);
return;
}
}
my $sql = "CREATE TABLE $msgtable (\n";
if ($cfg->get('dbmode') eq 'mysql') {
$sql .= "MID BIGINT UNIQUE AUTO_INCREMENT NOT NULL PRIMARY KEY,\n";
} else {
$sql .= "MID BIGINT IDENTITY PRIMARY KEY,\n";
}
$sql .= <<EOT;
TID BIGINT NOT NULL DEFAULT '0',
AUTHOR VARCHAR(32) DEFAULT '' NOT NULL ,
DATE DATETIME DEFAULT '0000-00-00 00:00:00' NOT NULL ,
INTERNAL CHAR(1) DEFAULT '0' NOT NULL ,
ISOPER CHAR(1) DEFAULT '0' NOT NULL ,
HEADERS TEXT DEFAULT '' NOT NULL ,
MSG TEXT DEFAULT '' NOT NULL
EOT
if ($cfg->get('dbmode') eq 'mysql') {
$sql .= ",\nKEY TID (TID)";
}
$sql .= "\n)";
if (!$dbh->do($sql)) {
setup1($cfg, $query, "Unable to create table $msgtable, ".$dbh->errstr);
return;
}
if ($cfg->get('dbmode') eq 'mssql') {
$dbh->do("CREATE INDEX TID ON $msgtable (TID)");
}
if ($msgtable ne $cfg->get('dbpref').'messages') {
$cfg->set('dbmessages', $msgtable);
$cfg->save();
}
#
# Stop Trouble Ticket Express
#
my $tm = time();
$cfg->set('dbupdate', $tm);
$cfg->save();
my $cnt = 0;
my $sth = $dbh->prepare('SELECT ID FROM '.$cfg->get('dbpref').'tickets');
if ($sth eq undef) {
stop("Fatal error: Unable to build SQL statement, ".$dbh->errstr);
return;
}
if (!$sth->execute()) {
stop("Fatal error: Unable to query tickets table, ".$dbh->errstr);
return;
}
$| = 1;
my $boundary = $tickets->_boundary();
my @tiklist;
for (my @row = $sth->fetchrow_array(); @row; @row = $sth->fetchrow_array()) {
my $t = time();
if (($t - $tm) > 10) {
$tm = $t;
$cfg->set('dbupdate', $tm);
$cfg->save();
print "\n"; # keep browser connection alive
}
push @tiklist, $row[0];
}
$sth->finish();
foreach my $id (@tiklist) {
my $t = time();
if (($t - $tm) > 10) {
$tm = $t;
$cfg->set('dbupdate', $tm);
$cfg->save();
}
print "\n"; # keep browser connection alive
$sth = $dbh->prepare('SELECT MSG FROM '.$cfg->get('dbpref')."tickets WHERE ID='$id'");
if ($sth eq undef) {
stop("Fatal error: Unable to build SQL statement, ".$dbh->errstr);
return;
}
if (!$sth->execute()) {
stop("Fatal error: Unable to query tickets table, ".$dbh->errstr);
return;
}
my @row = $sth->fetchrow_array();
$sth->finish();
my @messages = split(/\n$boundary\n/, $row[0]);
foreach my $msg (@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;
}
}
my $author = $header{FROM};
my $date = gmt($header{DATE});
my $internal = $header{INTERNAL} ? '1':'0';
my $isoper = $header{OPERATOR} ? '1':'0';
$rawheader = '';
foreach my $hdrkey (sort keys %header) {
next if grep(/^$hdrkey$/, ('FROM', 'DATE', 'INTERNAL', 'BODY', 'OPERATOR'));
$rawheader .= "$hdrkey: $header{$hdrkey}\n";
}
if (!$dbh->do("INSERT INTO $msgtable (TID, AUTHOR, DATE, ISOPER, INTERNAL, HEADERS, MSG) VALUES ".
"('$id',".$dbh->quote(substr($author,0,32)).",'$date','$isoper','$internal',".
$dbh->quote($rawheader).','.$dbh->quote($body).')')) {
$cfg->set('dbupdate', '');
$cfg->save();
stop("Fatal error: Unable to insert message record, ".$dbh->errstr);
return;
}
}
}
$cfg->set('dbupdate', '');
$cfg->set('dbschema', '2.19');
$cfg->save();
print <<EOT;
<center>
<br>
<table width=500>
<tr>
<td align=center>
Your database has been upgraded.
<br><br>
The full text search feature is availble now.
<br><br>
<a href="ttx.cgi?cmd=login"><b>Login to Trouble Ticket Express</b></a>
</td>
</tr>
</table>
EOT
}
# ========================================================================== gmt
sub gmt {
my $tm;
if ($_[0] ne undef) { $tm = $_[0]; }
else { $tm = time(); }
my ($s, $min, $h, $d, $m, $y) = (gmtime($tm));
$y += 1900;
++$m;
$m = "0$m" if $m < 10;
$d = "0$d" if $d < 10;
$h = "0$h" if $h < 10;
$min = "0$min" if $min < 10;
$s = "0$s" if $s < 10;
return "$y-$m-$d $h:$min:$s";
}
#======================================================================== setup1
sub setup1 {
my ($cfg, $query, $msg) = @_;
my $pwd = TTXCommon::cleanit($query, 'pwd');
if (foolproof($cfg)) {
my $tickets = TTXCommon::dbtik();
if ($tickets eq undef) {
stop("Fatal error: can't access tickets database");
return;
}
my $dbh = $tickets->{DBH};
if ($dbh eq undef) {
stop("Fatal error: can't obtain database handle");
return;
}
my $msgtable = TTXCommon::cleanit($query, 'dbmessages');
my $qmtbl = $msgtable;
$msgtable = $cfg->get('dbmessages') if $msgtable eq undef;
$msgtable = $cfg->get('dbpref').'messages' if $msgtable eq undef;
$msgtable =~ /^([a-zA-Z][a-zA-Z0-9_]+)$/;
my $tmp = $1;
if ($tmp eq undef) {
$msg .= "\nInvalid table name: $tmp";
}
$msgtable = $tmp;
print <<EOT;
<center>
<br>
<table width=500>
<tr>
<td align=left>
In order to support full text search feature introduced in rel 2.19 your database
needs to be upgraded. The upgrade will not affect existing data. The upgrade script
will do the following:
<br><br>
1) A new table will be created. The table will store all messages
(each trouble ticket consists of one or more messages).
<br><br>
2) Existing messages will be copied into the new table. This will not
destroy your existing data.
<br><br>
<b>IMPORTANT</b> During upgrade process the Trouble Ticket Express
will not be available. It will show the following message: "The help desk system
is temporary unavailable due to scheduled maintenance. We will resume operations
within next 5 minutes."
</td>
</tr>
</table>
EOT
if ($msg ne undef) {
print <<EOT;
<br>
<table width=500>
<tr>
<td align=center>
<b><font color=red>$msg</font></b>
</td>
</tr>
</table>
EOT
}
print <<EOT;
<br>
<form action="$ENV{SCRIPT_NAME}" method=post>
<input type=hidden name=cmd value=setup2>
<input type=hidden name=pwd value=$pwd>
<table width=500>
EOT
if (texists($cfg, $dbh, $msgtable) && !isttxtable($cfg, $dbh, $msgtable)) {
print <<EOT;
<tr>
<td align=left>
Please specify name of the table to use for storing messages. The name must be a valid table name
(please refer to your database server manuals for a definition of valid table names) and the
table may not exist.<br><br>
<b>Message table:</b> <input type=text name=dbmessages value="$qmtbl">
</td>
</tr>
EOT
}
print <<EOT;
<tr>
<td align=center>
<input type=submit value="Upgrade database">
</form>
</td>
</tr>
</table>
EOT
}
}
#======================================================================= texists
sub texists {
my ($cfg, $dbh, $msgtable) = @_;
my $sth;
if ($cfg->get('dbmode') eq 'mysql') {
$sth = $dbh->prepare('SHOW TABLES LIKE '.$dbh->quote($msgtable));
} else {
$sth = $dbh->prepare('EXECUTE sp_tables '.$dbh->quote($msgtable));
}
$sth->execute();
my @row = $sth->fetchrow_array();
return (@row > 0) ? 1:0;
}
# =================================================================== isttxtable
sub isttxtable {
my ($cfg, $dbh, $msgtable) = @_;
my $sth;
my @musthave = ('MID', 'TID', 'AUTHOR', 'INTERNAL', 'DATE', 'ISOPER', 'MSG');
if ($cfg->get('dbmode') eq 'mysql') {
$sth = $dbh->prepare("DESCRIBE $msgtable");
} else {
$sth = $dbh->prepare("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '$msgtable'");
}
$sth->execute();
my $hitcnt = 0;
for (my @row = $sth->fetchrow_array(); @row; @row = $sth->fetchrow_array()) {
my $id = $row[0];
if (grep(/^$id$/i, @musthave)) { ++$hitcnt; }
else { return 0; }
}
return ($hitcnt == int @musthave) ? 1:0;
}
#======================================================================= dologin
sub dologin {
my $error;
if ($query->param('do')) {
if ($query->param('passwd') eq undef || $query->param('passwd') ne $cfg->get('admpwd')) {
$error = "Invalid password";
} else {
$query->param(-name => 'pwd', -value => $query->param('passwd'));
$query->param(-name => 'do', -value => '');
setup1($cfg, $query);
return;
}
}
$error = "<br><font color=red><b>Error: $error</b></font><br><br>" if $error ne undef;
print <<EOT;
<center><b>Please login</b>
<br><br>$error
<table cellpadding=3>
<form action=$ENV{SCRIPT_NAME} method=post>
<input type=hidden name=cmd value=login>
<input type=hidden name=do value=1>
<tr>
<td align=left class=lbl>Administrator password</td>
<td align=left><input type=password name=passwd></td>
</tr>
<tr>
<td colspan=2 align=right>
<input type=submit>
</td>
</tr>
</form>
</table>
</center>
EOT
}
#========================================================================= login
sub login {
$query->param(-name => 'pwd', -value => '');
$query->param(-name => 'cmd', -value => 'login');
}
#====================================================================== runsetup
sub runsetup {
print <<EOT;
<html>
<head><title>Trouble Ticket Express</title></head>
<body>
<br><br><center>
<b><font color=red>Error reading configuration file.</font></b>
<br><br>
Please execute <a href=setup.cgi><b>Main Setup Utility</b></a> first.
</center>
</body>
</html>
EOT
exit;
}
#==================================================================== fatalerror
sub fatalerror {
print <<EOT;
<html>
<head><title>Trouble Ticket Express</title></head>
<body>
<br><center><h1>Fatal Error: $_[0]</h1>
</body>
</html>
EOT
exit;
}
sub header {
print <<EOT;
<html>
<head>
<title>
Trouble Ticket Express - Database upgrade
</title>
<style type="text/css">
body, td { font-family: Verdana, Helvetica, sans-serif; font-size: 10pt;}
A { color : #2E3197; text-decoration : none; }
A:Hover { color : #C00; text-decoration : underline;}
.sm {font-size: 8pt;}
.tiny {font-size: 4pt;}
.heading {font-size: 13pt;font-weight: 700; color: #2E3197;}
.lbl {font-size: 9pt;font-weight: 700;}
</style>
</head>
<body>
<center>
<table width=700>
<tr>
<td align=left>
EOT
}
# ======================================================================= footer
sub footer {
print <<EOT;
</td></tr>
</table>
<br><br>
rev. $version
</center>
</body>
</html>
EOT
# ==================================================================== scriptdir
sub scriptdir {
my $dir = $ENV{'SCRIPT_FILENAME'};
$dir = $ENV{'PATH_TRANSLATED'} if $ENV{'PATH_TRANSLATED'} ne undef;
$dir = $ENV{'pathTranslated'} if $ENV{'pathTranslated'} ne undef;
return $ENV{'PWD'} if $dir eq undef;
my @path = split(/\/|\\/, $dir);
pop(@path);
$dir = join("\/", @path);
return $dir;
}
}
@@ -0,0 +1,411 @@
#!/usr/bin/perl
#
# This script is a part of
# Trouble Ticket Express package.
# http://www.troubleticketexpress.com
#
# COPYRIGHT: 2002-2006, United Web Coders
# http://www.unitedwebcoders.com
#
# $Revision: 230 $
# $Date: 2006-08-08 02:35:34 -0400 (Tue, 08 Aug 2006) $
#
my $configfile;
# ==== NOTHING TO EDIT BELOW THIS LINE. PLS DO NOT CROSS =======================
BEGIN {
if ($^O eq 'MSWin32') {
eval "use FindBin";
eval "use lib $FindBin::Bin";
chdir($FindBin::Bin);
}
}
use strict;
use CGI;
use TTXConfig;
use TTXCommon;
use TTXData;
#
# Global vars
#
my $cfg;
my $query;
my $version = '2.22';
my %data;
print "Content-type: text/html\n\n";
header();
#
# Read config
#
if ($configfile eq undef) {
$configfile = 'ttxcfg.cgi';
my $sd = scriptdir();
$configfile = "$sd/ttxcfg.cgi" if $sd ne undef;
}
$cfg = TTXConfig->new($configfile);
runsetup() if $cfg eq undef || $cfg->error() ne undef;
if ($cfg->get('cfgref') ne undef) {
my $regcfg = TTXConfig->new($cfg->get('cfgref'));
$cfg = $regcfg;
runsetup() if $cfg->error() ne undef;
}
TTXData::set('CONFIG', $cfg);
#
# Parse input
#
$query = new CGI;
#
# Validate user if id provided
#
if ($query->param('pwd') ne undef) {
if ($cfg->get('admpwd') ne $query->param('pwd')) {
login();
}
} elsif ($cfg->get('admpwd') ne undef) {
login();
} else {
runsetup(); # Just to make sure.
}
#
# Execute command
#
my $cmd = $query->param('cmd');
$cmd = 'setup1' if $cmd eq undef;
if ($cmd eq 'setup1') {
setup1($cfg, $query);
} elsif ($cmd eq 'setup2') {
setup2($cfg, $query);
} elsif ($cmd eq 'login') {
dologin();
}
footer();
#========================================================================== stop
sub stop {
print <<EOT;
<center>
<br>
<table width=500>
<tr>
<td align=left>
$_[0]
</tr>
</td>
</table>
</center>
EOT
}
#===================================================================== foolproof
sub foolproof {
my ($cfg) = @_;
my $dbmode = $cfg->get('dbmode');
if ($dbmode !~ /sql/) {
stop("SQL mode is not activated yet. Please use".
" either <a href=\"sqlsetup.cgi\"><b><nobr>MySQL setup</nobr></b><a> or".
" <a href=\"mssqlsetup.cgi\"><b><nobr>SQL Server setup</nobr></b><a> utility".
" to configure SQL mode.");
} elsif($cfg->get('dbschema') < 2.19) {
stop("Please use this <a href=\"sqlupgrade.cgi\">upgrade script</a> first.");
} elsif($cfg->get('dbschema') >= 2.22) {
stop("You have already upgraded your database");
} else {
#
# Check if updated SQL module installed
#
if ($cfg->get('dbmode') eq 'mysql') {
eval "use TTXMySQLTickets";
if ($@ ne undef) {
stop("<b>Error loading TTXMySQLTickets, $@</b>");
return 0;
}
my $modver;
eval '$modver = $TTXMySQLTickets::VERSION';
if ($@ ne undef) {
stop("<b>Error querying TTXMySQLTickets, $@</b>");
return 0;
}
if ($modver < 2.22) {
stop("<b>Please install latest (2.22) version of TTXMySQLTickets.pm<br><br>\n".
"<center><a href=\"http://www.troubleticketexpress.com/mysql.html\">Order/Download instructions</a></center></b>");
return 0;
}
} else {
eval "use TTXMSSQLTickets";
if ($@ ne undef) {
stop("<b>Error loading TTXMSSQLTickets, $@</b>");
return 0;
}
my $modver;
eval '$modver = $TTXMSSQLTickets::VERSION';
if ($@ ne undef) {
stop("<b>Error querying TTXMSSQLTickets, $@</b>");
return 0;
}
if ($modver < 2.22) {
stop("<b>Please install latest (2.22) version of TTXMSSQLTickets.pm<br><br>\n".
"<center><a href=\"http://www.troubleticketexpress.com/mssql.html\">Order/Download instructions</a></center></b>");
return 0;
}
}
return 1;
}
return 0;
}
#======================================================================== setup2
sub setup2 {
my ($cfg, $query, $msg) = @_;
my $pwd = TTXCommon::cleanit($query, 'pwd');
return if !foolproof($cfg);
my $tickets = TTXCommon::dbtik();
if ($tickets eq undef) {
stop("Fatal error: can't access tickets database");
return;
}
my $dbh = $tickets->{DBH};
if ($dbh eq undef) {
stop("Fatal error: can't obtain database handle");
return;
}
my $table = $cfg->get('dbpref').'tickets';
my $cnt = int ($cfg->get('cfldcnt'));
my $itemidx = ($cnt > 10) ? $cnt:10;
my $sql;
if ($cfg->get('dbmode') eq 'mysql') {
$sql = "ALTER TABLE $table ADD COLUMN ITEM varchar(255) DEFAULT '' NOT NULL";
} else {
$sql = "ALTER TABLE $table ADD ITEM varchar(255) DEFAULT '' NOT NULL";
}
if (!$dbh->do($sql)) {
setup1($cfg, $query, "Unable to upgrade table $table, ".$dbh->errstr);
return;
}
$cfg->set('itemidx', $itemidx);
$cfg->set('dbschema', '2.22');
$cfg->save();
print <<EOT;
<center>
<br>
<table width=500>
<tr>
<td align=center>
Your database has been upgraded.
<br><br>
The database supports Inventory Module now.
<br><br>
<a href="ttx.cgi?cmd=login"><b>Login to Trouble Ticket Express</b></a>
</td>
</tr>
</table>
EOT
}
# ========================================================================== gmt
sub gmt {
my $tm;
if ($_[0] ne undef) { $tm = $_[0]; }
else { $tm = time(); }
my ($s, $min, $h, $d, $m, $y) = (gmtime($tm));
$y += 1900;
++$m;
$m = "0$m" if $m < 10;
$d = "0$d" if $d < 10;
$h = "0$h" if $h < 10;
$min = "0$min" if $min < 10;
$s = "0$s" if $s < 10;
return "$y-$m-$d $h:$min:$s";
}
#======================================================================== setup1
sub setup1 {
my ($cfg, $query, $msg) = @_;
my $pwd = TTXCommon::cleanit($query, 'pwd');
if (foolproof($cfg)) {
my $tickets = TTXCommon::dbtik();
if ($tickets eq undef) {
stop("Fatal error: can't access tickets database");
return;
}
my $dbh = $tickets->{DBH};
if ($dbh eq undef) {
stop("Fatal error: can't obtain database handle");
return;
}
print <<EOT;
<center>
<br>
<table width=500>
<tr>
<td align=left>
In order to support Inventory Module introduced in rel 2.22 your database
needs to be upgraded. The upgrade will not affect existing data. The upgrade script
will do the following:
<br><br>
1) A new column 'ITEMS' will be added to the tickets table.
</td>
</tr>
</table>
EOT
if ($msg ne undef) {
print <<EOT;
<br>
<table width=500>
<tr>
<td align=center>
<b><font color=red>$msg</font></b>
</td>
</tr>
</table>
EOT
}
print <<EOT;
<br>
<form action="$ENV{SCRIPT_NAME}" method=post>
<input type=hidden name=cmd value=setup2>
<input type=hidden name=pwd value=$pwd>
<table width=500>
EOT
print <<EOT;
<tr>
<td align=center>
<input type=submit value="Upgrade database">
</form>
</td>
</tr>
</table>
EOT
}
}
#======================================================================= dologin
sub dologin {
my $error;
if ($query->param('do')) {
if ($query->param('passwd') eq undef || $query->param('passwd') ne $cfg->get('admpwd')) {
$error = "Invalid password";
} else {
$query->param(-name => 'pwd', -value => $query->param('passwd'));
$query->param(-name => 'do', -value => '');
setup1($cfg, $query);
return;
}
}
$error = "<br><font color=red><b>Error: $error</b></font><br><br>" if $error ne undef;
print <<EOT;
<center><b>Please login</b>
<br><br>$error
<table cellpadding=3>
<form action=$ENV{SCRIPT_NAME} method=post>
<input type=hidden name=cmd value=login>
<input type=hidden name=do value=1>
<tr>
<td align=left class=lbl>Administrator password</td>
<td align=left><input type=password name=passwd></td>
</tr>
<tr>
<td colspan=2 align=right>
<input type=submit>
</td>
</tr>
</form>
</table>
</center>
EOT
}
#========================================================================= login
sub login {
$query->param(-name => 'pwd', -value => '');
$query->param(-name => 'cmd', -value => 'login');
}
#====================================================================== runsetup
sub runsetup {
print <<EOT;
<html>
<head><title>Trouble Ticket Express</title></head>
<body>
<br><br><center>
<b><font color=red>Error reading configuration file.</font></b>
<br><br>
Please execute <a href=setup.cgi><b>Main Setup Utility</b></a> first.
</center>
</body>
</html>
EOT
exit;
}
#==================================================================== fatalerror
sub fatalerror {
print <<EOT;
<html>
<head><title>Trouble Ticket Express</title></head>
<body>
<br><center><h1>Fatal Error: $_[0]</h1>
</body>
</html>
EOT
exit;
}
sub header {
print <<EOT;
<html>
<head>
<title>
Trouble Ticket Express - Database upgrade
</title>
<style type="text/css">
body, td { font-family: Verdana, Helvetica, sans-serif; font-size: 10pt;}
A { color : #2E3197; text-decoration : none; }
A:Hover { color : #C00; text-decoration : underline;}
.sm {font-size: 8pt;}
.tiny {font-size: 4pt;}
.heading {font-size: 13pt;font-weight: 700; color: #2E3197;}
.lbl {font-size: 9pt;font-weight: 700;}
</style>
</head>
<body>
<center>
<table width=700>
<tr>
<td align=left>
EOT
}
# ======================================================================= footer
sub footer {
print <<EOT;
</td></tr>
</table>
<br><br>
rev. $version
</center>
</body>
</html>
EOT
# ==================================================================== scriptdir
sub scriptdir {
my $dir = $ENV{'SCRIPT_FILENAME'};
$dir = $ENV{'PATH_TRANSLATED'} if $ENV{'PATH_TRANSLATED'} ne undef;
$dir = $ENV{'pathTranslated'} if $ENV{'pathTranslated'} ne undef;
return $ENV{'PWD'} if $dir eq undef;
my @path = split(/\/|\\/, $dir);
pop(@path);
$dir = join("\/", @path);
return $dir;
}
}
@@ -0,0 +1,104 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=[%CHARSET%]">
<title>[%Answer library%]</title>
<style type="text/css">
<!--
body, td, p { font-family: Verdana, Helvetica, sans-serif; font-size: 10pt;}
.lbl { font-size: 9pt; font-weight: 700;}
-->
</style>
<script language=Javascript>
<!--
function postanswer(jopa)
{
window.opener.document.newticket.problem.value += jopa;
return false;
}
// -->
</script>
(%INITANSWERS%)
<script language=Javascript>
<!--
function showanswer(id) {
for (i = 0; i < ANSWERS.length; i++) {
if (ANSWERS[i][0] == id) {
document.ansform.ananswer.value = ANSWERS[i][1];
document.ctrl.aid.value = id;
return false;
}
}
ananswer.value = ' ';
return false;
}
// -->
</script>
<script language=Javascript>
<!--
function showcat(id) {
location.href='(%ENV_SCRIPT_NAME%)?cmd=answerlib&sid=(%INPUT_sid%)&style=(%INPUT_style%)&cat='+escape(id);
return false;
}
// -->
</script>
</head>
<body onload="initanswers()">
<center>
(%ANSWERLIBERROR%)
(%ANSWERLIBMSG%)
<table cellpadding=0 cellspacing=0>
<tr>
<td valign=top align=left>
<span class=lbl>1. [%Select%]</span><br><br class=tiny>
<table cellpadding=1 cellspacing=1>
<tr>
<td>
<select name=cat size=1 OnChange="return showcat(this[this.selectedIndex].value);">
(%CATSELECTOR%)
</select>
</td>
</tr>
<tr>
<td>
<select name=answer size=10 OnChange="return showanswer(this[this.selectedIndex].value);">
(%ANSWERSELECTOR%)
</select>
</td>
</tr>
</table>
</td>
<td><nobr>&nbsp;&nbsp;&nbsp;&nbsp;</nobr></td>
<form name=ansform>
<td valign=top align=left>
<span class=lbl>2. [%Preview%]</span><br><br class=tiny>
<textarea readonly name=ananswer cols=50 rows=(%ROWS%)></textarea></td>
</form>
</tr>
<form action="(%ENV_SCRIPT_NAME%)" name=ctrl method=post>
<input type=hidden name=cmd value=answerlib>
<input type=hidden name=style value="(%INPUT_style%)">
<input type=hidden name=do value=1>
<input type=hidden name=aid value="">
<input type=hidden name=sid value="(%INPUT_sid%)">
<tr>
<td colspan align=left><span class=lbl><nobr>3. [%Copy%] =></nobr></span><td>
<td colspan align=left>
<br class=tiny>
<input type=submit value="[%Use%]" OnClick="return postanswer(document.ansform.ananswer.value)">
&nbsp;&nbsp;<input type=submit name=new value="[%New%]">
<input type=submit name=edit value="[%Edit%]">
<input type=submit name=del value="[%Delete%]">
&nbsp;&nbsp;<input type=submit value="[%Close%]" OnClick="window.close(); return false;">
<td>
</tr>
</form>
</table>
</center>
</body>
</html>
@@ -0,0 +1,74 @@
<script language="JavaScript"><!--
function confirmdel()
{
return confirm("[%Please confirm ticket removal%]");
}
//--></script>
<table width=(%HTMLBASEWIDTH%) cellspacing=0 cellpadding=0 bgcolor="#C6D7CF" style="padding-left: 5px">
<form method=post action="(%ENV_SCRIPT_NAME%)">
<input type=hidden name=cmd value=claim>
<input type=hidden name=style value="(%INPUT_style%)">
<input type=hidden name=sid value=(%INPUT_sid%)>
<input type=hidden name=do value=1>
<input type=hidden name=tid value=(%INPUT_tid%)>
<input type=hidden name=key value=(%INPUT_key%)>
<input type=hidden name=qsort value="(%INPUT_qsort%)">
<input type=hidden name=qsortorder value="(%INPUT_qsortorder%)">
<input type=hidden name=qoffset value=(%INPUT_qoffset%)>
<input type=hidden name=qwindow value=(%INPUT_qwindow%)>
<input type=hidden name=oper value=(%INPUT_oper%)>
<input type=hidden name=status value=(%INPUT_status%)>
<input type=hidden name=lname value=(%INPUT_lname%)>
<input type=hidden name=c0 value="(%INPUT_c0%)">
<input type=hidden name=c1 value="(%INPUT_c1%)">
<input type=hidden name=c2 value="(%INPUT_c2%)">
<input type=hidden name=c3 value="(%INPUT_c3%)">
<input type=hidden name=c4 value="(%INPUT_c4%)">
<input type=hidden name=c5 value="(%INPUT_c5%)">
<input type=hidden name=c6 value="(%INPUT_c6%)">
<input type=hidden name=c7 value="(%INPUT_c7%)">
<input type=hidden name=c8 value="(%INPUT_c8%)">
<input type=hidden name=c9 value="(%INPUT_c9%)">
<input type=hidden name=fltrsubj value="(%INPUT_fltrsubj%)">
<tr>
<td colspan=3 class=tiny>&nbsp</td>
</tr>
<tr>
<td align=left class=lbl>[%Status%]</td>
<td>&nbsp;&nbsp;</td>
<td align=left>[%(%TICKET_status%)%]</td>
</tr>
<tr>
<td align=left class=lbl>[%Subject%]</td>
<td>&nbsp;&nbsp;</td>
<td width=90% align=left>(%TICKET_subject%)</td>
</tr>
<tr>
<td align=left class=lbl>[%Group%]</td>
<td>&nbsp;&nbsp;</td>
<td width=90% align=left>(%TICKET_GROUP%)</td>
</tr>
<tr>
<td align=left class=lbl>[%Created%]</td>
<td>&nbsp;&nbsp;</td>
<td align=left>(%TICKET_open%)</td>
</tr>
<tr>
<td colspan=3 class=tiny>&nbsp</td>
</tr>
</table>
<br class=tiny>
<table width=(%HTMLBASEWIDTH%) cellspacing=0 cellpadding=0>
(%MESSAGES%)
</table>
<br class=tiny>(%WANTED%)
<table width=(%HTMLBASEWIDTH%) cellspacing=0 cellpadding=0 bgcolor="#CFDCE8">
<tr>
<td align=center>
<br class=tiny><br class=tiny>
<input type=submit value="[%Claim ownership%]">(%DELTICKET%)&nbsp;&nbsp;<input type=submit name=cancel value="[%Cancel%]">
<br><br class=tiny><br class=tiny>
</td>
</tr>
</form>
</table>
@@ -0,0 +1,30 @@
<br class=tiny>
<table width=(%HTMLBASEWIDTH%) cellspacing=0 cellpadding=0>
<tr>
<td width=50>&nbsp;</td>
<td align=left>
We have received your message and created <nobr>a service ticket #<font color=red><b>(%TICKETID%)</b></font>.</nobr>
Please refer to this number in all follow-up communications relating to this specific issue.
<br><br>
<span class=sm><b>Note:</b> We have sent a confirmation email to <b>(%INPUT_email%)</b> including instructions
for tracking status of your ticket. If you did not receive the confirmation shortly after submission of your inquiry,
there is something wrong with the email address you provided. Please be advised that if we cannot deliver a confirmation,
we cannot deliver an answer as well. In an event of email delivery problems please use our online system in order to
fetch an answer.</span>
<br><br>
In order to access your service request via our online system, please use the following access key:
<br><br>
<center><b><font color=red>(%TICKETKEY%)</font></b>
<br></br>
or follow this link
<br><br>
<a href="(%ENV_SCRIPT_NAME%)?cmd=ticket&key=(%TICKETKEY%)"><b>Ticket #(%TICKETID%)</b></a> (do not forget to bookmark it)
<br><br>
</center>
(both key and link have been sent to your email address <b>(%INPUT_email%)</b> as well)
<br><br>
</td>
<td width=50>&nbsp;</td>
</tr>
</table>
<br class=tiny>
@@ -0,0 +1,56 @@
<script language="JavaScript"><!--
function showitem(ID){ hwstring="scrollbars=yes,width=650,height=350,resizable=yes,toolbar=no,menubar=no"; var newwin = window.open("(%ENV_SCRIPT_NAME%)?cmd=showitem&id=" + ID + "&sid=(%INPUT_sid%)&style=(%INPUT_style%)&update=1", "ItemInfo", hwstring); return false; }
//--></script>
<script language="JavaScript"><!--
function rowhl(id, inrow) {
var row = document.getElementById('tr'+id);
var odd = id % 2;
var c = (odd) ? '#EEEEEE' : '#CCCCCC';
row.style.backgroundColor = (inrow) ? '#FFFFD9' : c;
}
//--></script>
<style type="text/css">
td.top {
border-style:solid;
border-color: #CCC;
border-bottom-width:0px;
border-right-width:0px;
border-left-width:0px;
border-top-width:1px;
}
td.topr {
border-style:solid;
border-color: #CCC;
border-bottom-width:0px;
border-right-width:1px;
border-left-width:0px;
border-top-width:1px;
}
td.topl {
border-style:solid;
border-color: #CCC;
border-bottom-width:0px;
border-right-width:0px;
border-left-width:1px;
border-top-width:1px;
}
td.r {
border-style:solid;
border-color: #CCC;
border-bottom-width:0px;
border-right-width:1px;
border-left-width:0px;
border-top-width:0px;
}
td.btmrl {
border-style:solid;
border-color: #CCC;
border-bottom-width:1px;
border-right-width:1px;
border-left-width:1px;
border-top-width:0px;
}
</style>
<table width=(%HTMLBASEWIDTH%) cellspacing=0 cellpadding=5>
(%ITEMLIST%)
</table>
@@ -0,0 +1,36 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=[%CHARSET%]">
<title>[%Deleting answer%]</title>
<style type="text/css">
<!--
body, td, p { font-family: Verdana, Helvetica, sans-serif; font-size: 10pt;}
.lbl { font-size: 9pt; font-weight: 700;}
-->
</style>
</head>
<body>
<br><br>
<center>
(%ANSWERLIBERROR%)
(%ANSWERLIBMSG%)
<form action="(%ENV_SCRIPT_NAME%)" method=post>
<input type=hidden name=cmd value=delanswer>
<input type=hidden name=style value="(%INPUT_style%)">
<input type=hidden name=do value=1>
<input type=hidden name=aid value="(%INPUT_aid%)">
<input type=hidden name=sid value="(%INPUT_sid%)">
<b><font color=red>[%Deleting answer%]</font></b>
<br><br>
<b>(%ANSWERTITLE%)</b>
<br><br>
[%Are you sure?%]
<br><br>
<input type=submit value="[%Yes%]">
<input type=submit name=cancel value="[%No%]">
</form>
</center>
</body>
</html>
@@ -0,0 +1,15 @@
<table width=(%HTMLBASEWIDTH%) cellpadding=0 cellspacing=0>
<tr>
<td style="background-color: #CCC;"><img src="(%CONFIG_IMGURL%)/dot.gif" width=(%HTMLBASEWIDTH%) height=2></td>
</tr>
<tr>
<td><img src="(%CONFIG_IMGURL%)/dot.gif" width=(%HTMLBASEWIDTH%) height=2></td>
</tr>
<tr>
<td align=left class=sm><font color="777777">Powered by <a href="http://www.troubleticketexpress.com"
style="color : #777;">Trouble Ticket Express</a> rev. (%VERSION%) (%ISPRO%)</font> (%CHECKUPDATE%)</td>
</tr>
</table>
</center>
</body>
</html>
@@ -0,0 +1,134 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=[%CHARSET%]">
<style type="text/css">
body, td { font-family: Verdana, Helvetica, sans-serif; font-size: 10pt;}
A { color : #2E3197; text-decoration : none; }
A:Hover { color : #C00; text-decoration : underline;}
.sm {font-size: 8pt;}
.tiny {font-size: 4pt;}
.heading {font-size: 13pt;font-weight: 700; color: #2E3197;}
.lbl { font-size: 9pt; font-weight: 700;}
td.error {
background-color: #FFC;
padding-right: 5pt;
padding-left: 5pt;
padding-top: 3pt;
padding-bottom: 3pt;
border-width:1px;
border-style:solid;
border-color: #996;
font-weight: 700;
color: #F00;
}
td.trow {
padding-right: 2pt;
padding-left: 2pt;
border-style:solid;
border-bottom-width:2px;
border-right-width: 0px;
border-left-width:1px;
border-top-width:0;
border-color: #FFF;
background-color: #CCC;
text-align: center;
font-size : 8pt;
font-weight: 700;
}
td.orow {
padding-right: 4pt;
padding-left: 4pt;
padding-top: 2pt;
padding-bottom: 1pt;
border-width:1px;
border-style:solid;
border-top-width:0;
border-bottom-width:0;
border-right-width:0;
font-size : 8pt;
border-color: #FFF;
}
td.erow {
padding-right: 4pt;
padding-left: 4pt;
padding-top: 2pt;
padding-bottom: 1pt;
border-width:1px;
border-style:solid;
border-top-width:0;
border-bottom-width:0;
border-right-width:0;
font-size : 8pt;
border-color: #FFF;
}
td.txt {
padding-right: 4pt;
padding-left: 4pt;
padding-top: 2pt;
padding-bottom: 1pt;
border-width:1px;
border-style:solid;
border-top-width:0;
border-bottom-width:0;
border-right-width:0;
font-size : 8pt;
border-color: #FFF;
color: #666;
text-align: left;
}
td.omsg {
background-color: #E8E8CF;
padding-right: 3pt;
padding-left: 3pt;
padding-top: 2pt;
padding-bottom: 2pt;
border-width:1px;
border-style:solid;
border-color: #FFF;
}
td.imsg {
background-color: #E8E8E8;
padding-right: 3pt;
padding-left: 3pt;
padding-top: 2pt;
padding-bottom: 2pt;
border-width:1px;
border-style:solid;
border-color: #FFF;
}
td.cmsg {
background-color: #E8DCCF;
padding-right: 3pt;
padding-left: 3pt;
padding-top: 2pt;
padding-bottom: 2pt;
border-width:1px;
border-style:solid;
border-color: #FFF;
}
</style>
<title>(%CONFIG_COMPANY%)</title>
</head>
<body>
<center>
<table width=(%HTMLBASEWIDTH%) cellpadding=0 cellspacing=0>
<tr>
<td align=left><span class=sm><font color="#AAAAAA"><b>(%LOGGEDAS%)</b></font></span></td>
<td align=right class=sm>
(%HOMELINK%) (%DASHBOARDLINK%) <a href="(%ENV_SCRIPT_NAME%)?cmd=(%HELPDESKCMD%)&sid=(%INPUT_sid%)&style=(%INPUT_style%)">[%Tickets%]</a> | <a href="(%ENV_SCRIPT_NAME%)?cmd=newticket&sid=(%INPUT_sid%)&style=(%INPUT_style%)">[%Contact us%]</a> | (%LOGINLOGOUT%)
</td>
</table>
<table width=(%HTMLBASEWIDTH%) cellpadding=0 cellspacing=0>
<tr>
<td class=heading align=left nowrap>(%PAGEHEADING%)</td>
</tr>
</table>
<br class=tiny>
<table width=(%HTMLBASEWIDTH%) cellpadding=0 cellspacing=0>
<tr>
<td style="background-color: #CCC;"><img src="(%CONFIG_IMGURL%)/dot.gif" width=(%HTMLBASEWIDTH%) height=2></td>
</tr>
</table>
(%ERROR_BOX%)
@@ -0,0 +1,81 @@
<script language="JavaScript"><!--
function ticked(ID){ hwstring="scrollbars=yes,width=450,height=(%TICKEDHEIGHT%),resizable=yes,toolbar=no,menubar=no"; var newwin = window.open("(%ENV_SCRIPT_NAME%)?cmd=ticketed&tid=" + ID + "&sid=(%INPUT_sid%)", "TicketEditor", hwstring); }
//--></script>
<script language="JavaScript"><!--
function showitem(ID){ hwstring="scrollbars=yes,width=650,height=350,resizable=yes,toolbar=no,menubar=no"; var newwin = window.open("(%ENV_SCRIPT_NAME%)?cmd=showitem&id=" + ID + "&sid=(%INPUT_sid%)&style=(%INPUT_style%)&isticket=0", "ItemInfo", hwstring); return false; }
//--></script>
<script language="JavaScript"><!--
function setsort(orderby, direction)
{
document.forms['hd'].qoffset.value='0';
document.forms['hd'].qsort.value=orderby;
document.forms['hd'].qsortorder.value=direction;
document.forms['hd'].submit();
return false;
}
//--></script>
<script language=Javascript> <!--
function update()
{
document.forms['hd'].submit();
return false;
}
//-->
</script>
<script language="JavaScript"><!--
function scroll(off, win)
{
document.forms['hd'].qoffset.value=off;
document.forms['hd'].qwindow.value=win;
document.forms['hd'].submit();
return false;
}
//--></script>
<script language="JavaScript"><!--
function rowhl(id, inrow) {
var row = document.getElementById('tr'+id);
var odd = id % 2;
var c = (odd) ? '#F0F0E1' : '#E8E8CF';
row.style.backgroundColor = (inrow) ? '#FFFFD9' : c;
}
//--></script>
<table width=(%HTMLBASEWIDTH%) cellspacing=0 cellpadding=0 bgcolor="#C6D7CF">
<form method=post action="(%ENV_SCRIPT_NAME%)" name=hd>
<input type=hidden name=cmd value=(%INPUT_cmd%)>
<input type=hidden name=style value="(%INPUT_style%)">
<input type=hidden name=sid value=(%INPUT_sid%)>
<input type=hidden name=do value=1>
<input type=hidden name=emailkey value=(%INPUT_emailkey%)>
<input type=hidden name=qsort value="(%INPUT_qsort%)">
<input type=hidden name=qsortorder value="(%INPUT_qsortorder%)">
<input type=hidden name=qoffset value=(%INPUT_qoffset%)>
<tr>
<td class=tiny>&nbsp</td>
</tr>
<tr>
<td>(%TICKETFILTER%)</td>
</tr>
<tr>
<td class=tiny>&nbsp</td>
</tr>
</table>
<br class=tiny>
<table width=(%HTMLBASEWIDTH%) cellspacing=0 cellpadding=0>
<tr>
<td align=left>
<span class=sm>
[%Show%] <input type=text size=3 class=sm name=qwindow value=(%INPUT_qwindow%)> [%tickets per page.%]
[%Include abstracts%] <input type=checkbox class=sm name=abstract value=1(%CHECKABSTRACT%)>
</span>
</td>
<td align=right>
<input type=submit value="[%Search%]">&nbsp;<input type=submit name=reset value="[%Show all%]">
</td>
</tr>
</form>
</table>
<br class=tiny>
<table width=(%HTMLBASEWIDTH%) cellspacing=0 cellpadding=0 >
(%TICKETLIST%)
</table>
<br class=tiny>
@@ -0,0 +1,65 @@
<table width=(%HTMLBASEWIDTH%) cellspacing=0 cellpadding=0 bgcolor="#CFDCE8">
<form method=post action="(%ENV_SCRIPT_NAME%)">
<input type=hidden name=cmd value=keyform>
<input type=hidden name=style value="(%INPUT_style%)">
<input type=hidden name=sid value=(%INPUT_sid%)>
<input type=hidden name=do value=1>
<input type=hidden name=qsort value="(%INPUT_qsort%)">
<input type=hidden name=qsortorder value="(%INPUT_qsortorder%)">
<input type=hidden name=qoffset value=(%INPUT_qoffset%)>
<input type=hidden name=qwindow value=(%INPUT_qwindow%)>
<tr>
<td align=center>
<table cellpadding=3>
<tr>
<td>
<br class=tiny><br class=tiny>
<span class=lbl>[%Access Key%]</span>
<input type=text name=key size=35 value="(%INPUT_key%)">
</td>
</tr>
<tr>
<td align=right>
<input type=submit value="[%Enter%]"> <input type=submit name=cancel value="[%Cancel%]">
</form>
<br><br class=tiny><br class=tiny>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td align=center>
(%MESSAGE%)
</td>
</tr>
<form method=post action="(%ENV_SCRIPT_NAME%)">
<input type=hidden name=cmd value=keyfinder>
<input type=hidden name=style value="(%INPUT_style%)">
<input type=hidden name=sid value=(%INPUT_sid%)>
<input type=hidden name=do value=1>
<input type=hidden name=qsort value="(%INPUT_qsort%)">
<input type=hidden name=qsortorder value="(%INPUT_qsortorder%)">
<input type=hidden name=qoffset value=(%INPUT_qoffset%)>
<input type=hidden name=qwindow value=(%INPUT_qwindow%)>
<tr>
<td align=center>
<table cellpadding=3>
<tr>
<td>
<br class=tiny><br class=tiny>
<span class=lbl>[%Email address%]</span>
<input type=text name=email size=34 value="(%INPUT_email%)">
</td>
</tr>
<tr>
<td align=right>
<input type=submit value="[%Enter%]"> <input type=submit name=cancel value="[%Cancel%]">
<br><br class=tiny><br class=tiny>
</td>
</tr>
</table>
</td>
</tr>
</form>
</table>
@@ -0,0 +1,27 @@
<table width=(%HTMLBASEWIDTH%) cellspacing=0 cellpadding=0 bgcolor="#CFDCE8">
<tr>
<td align=center>
<br><b>(%INPUT_loginmsg%)</b><br class=tiny><br class=tiny>
<table cellpadding=3 cellspacing=0>
<form method=post action="(%ENV_SCRIPT_NAME%)">
<input type=hidden name=cmd value=login>
<input type=hidden name=dologin value=1>
<input type=hidden name=nextcmd value="(%INPUT_nextcmd%)">
<input type=hidden name=style value="(%INPUT_style%)">
<input type=hidden name=tk value="(%INPUT_tk%)">
<tr>
<td align=right class=lbl>[%User ID%]</td>
<td align=left><input type=text style="font-family: Verdana, Geneva, Helvetica, sans-serif; font-size: 10pt;" name=login value="(%INPUT_login%)"></td>
</tr>
<tr>
<td align=right class=lbl>[%Password%]</td>
<td align=left><input type=password style="font-family: Verdana, Geneva, Helvetica, sans-serif; font-size: 10pt;" name=passwd value="(%INPUT_passwd%)"></td>
</tr>
<tr>
<td colspan=2 align=right><input type=submit class=button value="[%Login%]"><br class=tiny><br class=tiny></td>
</tr>
</form>
</table>
</td>
</tr>
</table>
@@ -0,0 +1,78 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=[%CHARSET%]">
<title>[%Markup Quick Guide%]</title>
<style type="text/css">
<!--
body, td, p {
font-family: Verdana, Helvetica, sans-serif;
font-size: 10pt;
}
-->
</style>
</head>
<body>
<center>
<table cellspacing=0 cellpadding=6 style="border-style:solid; border-width:1px; border-color: #CCC;">
<tr>
<td style="border-style:solid; border-width:1px; border-color: #CCC;">
[b] Sample text [/b]
</td>
<td style="border-style:solid; border-width:1px; border-color: #CCC;">
<b> Sample text </b>
</td>
</tr>
<tr>
<td style="border-style:solid; border-width:1px; border-color: #CCC;">
[i] Sample text [/i]
</td>
<td style="border-style:solid; border-width:1px; border-color: #CCC;">
<i> Sample text </i>
</td>
</tr>
<tr>
<td style="border-style:solid; border-width:1px; border-color: #CCC;">
[u] Sample text [/u]
</td>
<td style="border-style:solid; border-width:1px; border-color: #CCC;">
<u> Sample text </u>
</td>
</tr>
<tr>
<td style="border-style:solid; border-width:1px; border-color: #CCC;">
[code] Sample text [/code]
</td>
<td style="border-style:solid; border-width:1px; border-color: #CCC;">
<code> Sample text </code>
</td>
</tr>
<tr>
<td style="border-style:solid; border-width:1px; border-color: #CCC;">
[url http://www.troubleticketexpress.com]Trouble Ticket Express[/url]
</td>
<td style="border-style:solid; border-width:1px; border-color: #CCC;">
<a href="http://www.troubleticketexpress.com" target=_blank>Trouble Ticket Express</a>
</td>
</tr>
<tr>
<td style="border-style:solid; border-width:1px; border-color: #CCC;">
[img http://www.helpdeskconnect.com/i/sml.gif]
</td>
<td style="border-style:solid; border-width:1px; border-color: #CCC;">
<img src="http://www.helpdeskconnect.com/i/sml.gif">
</td>
</tr>
<tr>
<td style="border-style:solid; border-width:1px; border-color: #CCC;">
[(]
</td>
<td style="border-style:solid; border-width:1px; border-color: #CCC;">
[
</td>
</tr>
</table>
</center>
</body>
</html>
@@ -0,0 +1,51 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=[%CHARSET%]">
<title>[%Message Editor%]</title>
<style type="text/css">
<!--
body, td, p { font-family: Verdana, Helvetica, sans-serif; font-size: 10pt;}
-->
</style>
<script language=Javascript>
<!--
function closeme()
{
msg = window.opener.document.newticket.problem.value;
window.opener.location.href = "(%ENV_SCRIPT_NAME%)?cmd=ticket&sid=(%INPUT_sid%)&key=(%KEY%)&style=(%INPUT_style%)&problem="+escape(msg);
window.close();
return false;
}
//-->
</script>
</head>
<body>
<center>
<font color=red><b>(%ERROR_MESSAGE%)</b></font><font color=blue><b>(%MESSAGE%)</b></font>
<form action="(%ENV_SCRIPT_NAME%)" method=post>
<input type=hidden name=sid value="(%INPUT_sid%)">
<input type=hidden name=cmd value=msgedit>
<input type=hidden name=style value="(%INPUT_style%)">
<input type=hidden name=mid value="(%INPUT_mid%)">
<input type=hidden name=tid value="(%INPUT_tid%)">
<input type=hidden name=do value=1>
<br>
<textarea name=msg wrap=virtual cols=60 rows=20>(%MSG%)</textarea>
<br>
<table cellpadding=5>
<tr>
<td width="50%" align=right>
<input type=submit class=boldcontent value="[%Update Message%]">
</td>
</form>
<td width="50%" align=left>
<input type=submit class=button onClick="return closeme()" value="[%Close Window%]">
</td>
</tr>
</table>
</center>
</body>
</html>
@@ -0,0 +1,72 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=[%CHARSET%]">
<title>[%Answer editor%]</title>
<style type="text/css">
<!--
body, td, p { font-family: Verdana, Helvetica, sans-serif; font-size: 10pt;}
.lbl { font-size: 9pt; font-weight: 700;}
-->
</style>
</head>
<body>
<center>
(%ANSWERLIBERROR%)
(%ANSWERLIBMSG%)
<table cellpadding=3 cellspacing=0>
<form action="(%ENV_SCRIPT_NAME%)" method=post>
<input type=hidden name=cmd value="(%INPUT_cmd%)">
<input type=hidden name=do value=1>
<input type=hidden name=style value="(%INPUT_style%)">
<input type=hidden name=aid value="(%INPUT_aid%)">
<input type=hidden name=sid value="(%INPUT_sid%)">
<tr>
<td align=left class=lbl>[%Title%]</td>
<td align=left><input type=text size=30 name=title value="(%TITLE%)"></td>
</tr>
<tr>
<td colspan=2></td>
</tr>
<tr>
<td colspan=2></td>
</tr>
<tr>
<td align=left class=lbl>[%Select existing category%]</td>
<td align=left>
<select name=cat OnChange="if (this[this.selectedIndex].value) {document.editor.catnew.value = ''}; return false;">
(%CATSELECTOR%)
</select>
</td>
</tr>
<tr>
<td align=left class=lbl>[%or define new one%]: </td>
<td align=left><input type=text size=30 name=catnew value="(%INPUT_catnew%)"></td>
</tr>
<tr>
<td colspan=2 valign=top class=lbl>[%Answer%]</td>
</tr>
<tr>
<td colspan=2><textarea name=answer cols=50 rows=9 wrap=virtual>(%ANSWER%)</textarea>
</tr>
<tr>
<td colspan=2>
<table width="100%" cellpadding=0 cellspacing=0>
<tr>
<td align=left>
(%COMMONCHECKBOX%)
</td>
<td align=right>
<input type=submit value="[%Update%]">
<input type=submit name=cancel value="[%Done%]">
</td>
</tr>
</table>
</td>
</tr>
</form>
</table>
</center>
</body>
</html>
@@ -0,0 +1,13 @@
[b]Re:[/b] Ticket (%TICKETID%), (%TICKETSTATE%)
Dear (%UNAME%)
A new message has been added to the service request #(%TICKETID%).
(%MESSAGE%)
You can view and update your inquiry here:
(%TICKETURL%)
(%OPERATORNAME%)
(%COMPANYNAME%) Help Desk
@@ -0,0 +1,81 @@
<script language="javascript"><!--
numberoftimes = 0;
function onlyonce() {
numberoftimes += 1;
if (numberoftimes > 1) {
var themessage = "[%Please be patient. Submission is in progress...%]";
alert(themessage);
return false;
} else {
return true;
}
}
// -->
</script>
<script language="JavaScript"><!--
function preview(){
hwstring="scrollbars=yes,width=600,height=500,resizable=yes,toolbar=no,menubar=no";
var newwin = window.open('', 'winpreview', hwstring);
newwin.focus();
document.forms['preview'].msg.value = document.forms['newticket'].problem.value;
document.forms['preview'].submit();
return false;
}
//--></script>
<table width=(%HTMLBASEWIDTH%) cellspacing=0 cellpadding=0 bgcolor="#CFDCE8">
<tr>
<td align=center><br class=tiny>
<form method=post action="(%ENV_SCRIPT_NAME%)" name=newticket enctype="multipart/form-data" onsubmit="return onlyonce()">
<input type=hidden name=cmd value=newticket>
<input type=hidden name=style value="(%INPUT_style%)">
<input type=hidden name=sid value=(%INPUT_sid%)>
<input type=hidden name=do value=1>
<input type=hidden name=tid value=(%INPUT_tid%)>
<input type=hidden name=form value=(%INPUT_form%)>
<table cellspacing=0 cellpadding=3>
<tr>
<td align=right class=lbl>[%Name%]<font color=red><sup>*</sup></font></td>
<td align=left><input type=text size=25 name=name value="(%INPUT_name%)"></td>
</tr>
<tr>
<td align=right class=lbl>[%Email%]<font color=red><sup>*</sup></font></td>
<td align=left><input type=text size=25 name=email value="(%INPUT_email%)"></td>
</tr>
(%CUSTOMVARS%)
(%ITEMSELSTD%)
(%OPERSELSTD%)
(%GROUPSELSTD%)
<tr>
<td align=right class=lbl>[%Subject%]<font color=red><sup>*</sup></font></td>
<td align=left><input type=text size=40 name=subject value="(%INPUT_subject%)"></td>
</tr>
(%KIDFORM%)
<tr>
<td colspan=2 align=center>
<table cellspacing=0 cellpadding=0>
<tr>
<td align=left>
<span class=lbl>[%Problem%]</span>&nbsp;&nbsp;&nbsp;<a href=#teditor onClick="return preview()">[%preview%]</a><br class=tiny>
<textarea name=problem wrap=virtual cols=50 rows=10>(%INPUT_problem%)</textarea>
</td>
</tr>
</table>
</td>
</tr>
<tr><td colspan=2 align=left>(%FILEFORMS%)</td></tr>
<tr>
<td align=left>(%INTERNALCHECKBOX%)</td>
<td align=right><input type=submit value="[%Submit%]"><br><br class=tiny></td>
</tr>
</form>
</table>
</td>
</tr>
</table>
<form method="post" action="(%ENV_SCRIPT_NAME%)" id="preview" target="winpreview" >
<input type=hidden name=cmd value=preview>
<input type=hidden name=style value="(%INPUT_style%)">
<input type=hidden name=sid value=(%INPUT_sid%)>
<input type=hidden name=key value=(%INPUT_key%)>
<input type=hidden name=msg>
</form>
@@ -0,0 +1,12 @@
Dear (%UNAME%)
Thank you for contacting (%COMPANYNAME%) Help Desk. This message is to confirm that we received a service request with tracking # (%TICKETID%) from you.
(%MESSAGE%)
You can view and update your service request here:
(%TICKETURL%)
Sincerely,
(%COMPANYNAME%) Help Desk
@@ -0,0 +1,8 @@
[b]Re:[/b] Ticket (%TICKETID%), (%TICKETSTATE%)
[b]Customer:[/b] (%UNAME%) ((%UEMAIL%))
Followup message:
(%MESSAGE%)
(%TICKETURL%)
@@ -0,0 +1,6 @@
New ticket #(%TICKETID%) from (%UNAME%) ((%UEMAIL%)),
(%ITEMLINE%)
(%MESSAGE%)
(%TICKETURL%)
@@ -0,0 +1,27 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<title>Answer library</title>
<style type="text/css">
<!--
body, td, p { font-family: Verdana, Helvetica, sans-serif; font-size: 10pt;}
-->
</style>
</head>
<body>
<br>
<b>Answer Library</b> module is not installed on your server.
<br><br>
The module allows organizing answers to common questions. Your staff can quickly access canned
answers for instant solutions that save problem-resolution time. New staff members will benefit
from the canned answer library for training, enabling them to hit the ground running and be
productive right from their first day.
<br><br>
You may see the Answer Library module in action through our
<a href="http://www.troubleticketexpress.com/trouble-ticket-demo.html" target=_blank><b><nobr>demo help desk</nobr></b></a>.
<br><br>
For more detailed description and ordering info please refer to
<a href="http://www.troubleticketexpress.com/canned-answers.html" target=_blank><b><nobr>Answer Library page</nobr></b></a>.
</body>
</html>
@@ -0,0 +1,151 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=[%CHARSET%]">
<style type="text/css">
body, td { font-family: Verdana, Helvetica, sans-serif; font-size: 10pt;}
A { color : #2E3197; text-decoration : none; }
A:Hover { color : #C00; text-decoration : underline;}
.sm {font-size: 8pt;}
.tiny {font-size: 4pt;}
.heading {font-size: 13pt;font-weight: 700; color: #2E3197;}
.lbl { font-size: 9pt; font-weight: 700;}
td.error {
background-color: #FFC;
padding-right: 5pt;
padding-left: 5pt;
padding-top: 3pt;
padding-bottom: 3pt;
border-width:1px;
border-style:solid;
border-color: #996;
font-weight: 700;
color: #F00;
}
td.trow {
padding-right: 2pt;
padding-left: 2pt;
border-style:solid;
border-bottom-width:2px;
border-right-width: 0px;
border-left-width:1px;
border-top-width:0;
border-color: #FFF;
background-color: #CCC;
text-align: center;
font-size : 8pt;
font-weight: 700;
}
td.orow {
padding-right: 4pt;
padding-left: 4pt;
padding-top: 2pt;
padding-bottom: 1pt;
border-width:1px;
border-style:solid;
border-top-width:0;
border-bottom-width:0;
border-right-width:0;
font-size : 8pt;
border-color: #FFF;
}
td.erow {
padding-right: 4pt;
padding-left: 4pt;
padding-top: 2pt;
padding-bottom: 1pt;
border-width:1px;
border-style:solid;
border-top-width:0;
border-bottom-width:0;
border-right-width:0;
font-size : 8pt;
border-color: #FFF;
}
td.txt {
padding-right: 4pt;
padding-left: 4pt;
padding-top: 2pt;
padding-bottom: 1pt;
border-width:1px;
border-style:solid;
border-top-width:0;
border-bottom-width:0;
border-right-width:0;
font-size : 8pt;
border-color: #FFF;
color: #666;
text-align: left;
}
td.omsg {
background-color: #EEE;
padding-right: 3pt;
padding-left: 3pt;
padding-top: 2pt;
padding-bottom: 2pt;
border-width:1px;
border-style:solid;
border-color: #FFF;
}
td.imsg {
background-color: #EEE;
padding-right: 3pt;
padding-left: 3pt;
padding-top: 2pt;
padding-bottom: 2pt;
border-width:1px;
border-style:solid;
border-color: #FFF;
}
td.cmsg {
background-color: #D0D0D0;
padding-right: 3pt;
padding-left: 3pt;
padding-top: 2pt;
padding-bottom: 2pt;
border-width:1px;
border-style:solid;
border-color: #FFF;
}
</style>
<title>[%Message Preview%]</title>
</head>
<body>
<center>
<table width="90%" cellpadding=0 cellspacing=0>
<tr>
<td class=heading align=left nowrap>(%PAGEHEADING%)</td>
</tr>
</table>
<br class=tiny>
<table width="90%" cellpadding=0 cellspacing=0>
<tr>
<td style="background-color: #CCC;"><img src="(%CONFIG_IMGURL%)/dot.gif" width="100%" height=2></td>
</tr>
</table>
<table width="90%" cellspacing=0 cellpadding=0 bgcolor="#CFDCE8" style="padding-left: 5px; padding-right: 5px">
<tr>
<td align=left>
<br class=tiny>
(%MESSAGE%)
<br class=tiny>
<br class=tiny>
</td>
</tr>
</table>
<table width="90%" cellpadding=0 cellspacing=0>
<tr>
<td style="background-color: #CCC;"><img src="(%CONFIG_IMGURL%)/dot.gif" width="100%" height=2></td>
</tr>
</table>
<br class=tiny>
<table width="90%" cellpadding=0 cellspacing=0>
<tr>
<td align=right><input type=submit value="[%Close Window%]" onclick="window.close()" />
</td>
</tr>
</table>
</center>
</body>
</html>
@@ -0,0 +1,30 @@
<table width=(%HTMLBASEWIDTH%) cellspacing=0 cellpadding=0 bgcolor="#C6D7CF">
<form method=post action="(%ENV_SCRIPT_NAME%)">
<input type=hidden name=cmd value=(%INPUT_cmd%)>
<input type=hidden name=style value="(%INPUT_style%)">
<input type=hidden name=sid value=(%INPUT_sid%)>
<input type=hidden name=do value=1>
<tr>
<td class=tiny>&nbsp</td>
</tr>
<tr>
<td>(%REPORTQUERY%)</td>
</tr>
<tr>
<td class=tiny>&nbsp</td>
</tr>
</table>
<br class=tiny>
<table width=(%HTMLBASEWIDTH%) cellspacing=0 cellpadding=0>
<tr>
<td align=right>
<input type=submit value="[%Build Report%]">
</td>
</tr>
</form>
</table>
<br class=tiny>
<table width=(%HTMLBASEWIDTH%) cellspacing=0 cellpadding=0 >
(%REPORT%)
</table>
<br class=tiny>
@@ -0,0 +1,44 @@
<table width=(%HTMLBASEWIDTH%) cellspacing=0 cellpadding=0 bgcolor="#C6D7CF" style="padding-left: 5px; padding-right: 5px">
<!-- <tr>
<td align=right colspan=6 class=sm><a href="(%ENV_SCRIPT_NAME%)?cmd=annotate&sid=(%INPUT_sid%)&key=(%INPUT_key%)" target="_blank">printable version</a></td>
</tr> -->
<tr>
<td align=left class=lbl>[%Subject%]</td>
<td>&nbsp;&nbsp;</td>
<td align=left>(%TICKEDOPEN%)(%TICKET_subject%)(%TICKEDCLOSE%)</td>
<td align=left class=lbl>[%Group%]</td>
<td>&nbsp;&nbsp;</td>
<td align=left>(%TICKET_GROUP%)</td>
</tr>
<tr>
<td align=left class=lbl>[%Status%]</td>
<td>&nbsp;&nbsp;</td>
<td align=left width=90%>(%TICKET_status%)</td>
<td align=left class=lbl>[%Operator%]</td>
<td>&nbsp;&nbsp;</td>
<td align=left>(%TICKET_oper%)</td>
</tr>
<tr>
<td align=left class=lbl>[%Created%]</td>
<td>&nbsp;&nbsp;</td>
<td align=left>(%TICKET_open%)</td>
<td align=left class=lbl>[%Customer%]</td>
<td>&nbsp;&nbsp;</td>
<td align=left><nobr>(%TICKET_name%) (<a href="mailto:(%TICKET_email%)">(%TICKET_email%)</a>)</nobr></td>
</tr>
<tr>
<td align=left class=lbl>[%Solved%]</td>
<td>&nbsp;&nbsp;</td>
<td align=left>(%TICKET_closed%)</td>
<td align=left class=lbl><nobr>[%Access key%]</nobr></td>
<td>&nbsp;&nbsp;</td>
<td align=left>(%TICKET_key%)</td>
</tr>
<tr>
<td colspan=6 class=tiny>&nbsp;</td>
</tr>
</table>
<br class=tiny>
<table width=(%HTMLBASEWIDTH%) cellspacing=0 cellpadding=0>
(%MESSAGES%)
</table>
@@ -0,0 +1,73 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=[%CHARSET%]">
<title>(%ITEMLABEL%) (%ITEM_TITLE%)</title>
<style type="text/css">
<!--
body, td, p { font-family: Verdana, Helvetica, sans-serif; font-size: 10pt;}
-->
</style>
<script language=Javascript>
<!--
function closeme()
{
//parentisticket = (%INPUT_isticket%);
//if (parentisticket) {
// msg = opener.newticket.problem.value;
// opener.location.href = "(%ENV_SCRIPT_NAME%)?cmd=ticket&sid=(%INPUT_sid%)&key=(%TICKET_key%)&problem="+escape(msg);
// }
// else {
// opener.update();
// }
window.close();
return false;
}
//-->
</script>
</head>
<body>
<center>
<font color=red><b>(%ERROR_MESSAGE%)</b></font><font color=blue><b>(%MESSAGE%)</b></font>
<form action="(%ENV_SCRIPT_NAME%)" method=post>
<input type=hidden name=sid value="(%INPUT_sid%)">
<input type=hidden name=isticket value="(%INPUT_isticket%)">
<input type=hidden name=cmd value=showitem>
<input type=hidden name=style value="(%INPUT_style%)">
<input type=hidden name=id value="(%INPUT_id%)">
<input type=hidden name=do value=1>
<table cellspacing=0 cellpadding=5>
<td colspan=3 align=left>
<b><font size="+1">(%ITEM_TITLE%)</font></b>
</td>
</tr>
<tr>
<td align=center><img src="(%ITEM_IMG%)"></td>
<td align=left><nobr><b>[%Status%]:</b> <img src="(%ITEM_STATUS_IMG%)"> (%STATUS_SELBOX%)</nobr></td>
<td align=right><input type=submit value="[%Update%]">
<input type=submit class=button onClick="return closeme()" value="[%Close Window%]"></td>
</tr>
<tr>
<td colspan=3 align=left>
<b>[%Notes%]</b><br>
(%ITEM_QNOTES%)
</td>
</tr>
<tr>
<td colspan=3 align=left>
<b><small>[%add notes%]</small></b><br>
<textarea wrap=virtual cols=70 name=notes rows=6>(%QNOTES%)</textarea>
</td>
</tr>
<tr>
<td colspan=3 align=center>
<input type=submit value="[%Update%]">
<input type=submit class=button onClick="return closeme()" value="[%Close Window%]">
</td>
</tr>
</table>
</form>
</center>
</body>
</html>
@@ -0,0 +1,166 @@
<script language="javascript"><!--
numberoftimes = 0;
function onlyonce() {
numberoftimes += 1;
if (numberoftimes > 1) {
var themessage = "[%Please be patient. Submission is in progress...%]";
alert(themessage);
return false;
} else {
return true;
}
}
// -->
</script>
<script language="JavaScript"><!--
function msgedit(TID, MID){ hwstring="scrollbars=yes,width=600,height=450,resizable=yes,toolbar=no,menubar=no"; var newwin = window.open("(%ENV_SCRIPT_NAME%)?cmd=msgedit&tid=" + TID + "&mid=" + MID + "&sid=(%INPUT_sid%)&style=(%INPUT_style%)", "TTXMsgEditor", hwstring); }
//--></script>
<script language="JavaScript"><!--
function msgdel(TID, MID){
if (confirm("[%Please confirm message deletion%]")) {
msg = document.newticket.problem.value;
window.location.href = "(%ENV_SCRIPT_NAME%)?cmd=msgdel&sid=(%INPUT_sid%)&tid="+ TID + "&mid=" + MID + "&style=(%INPUT_style%)&problem="+escape(msg);
}
}
//--></script>
<script language="JavaScript"><!--
function ticked(ID){ hwstring="scrollbars=yes,width=450,height=(%TICKEDHEIGHT%),resizable=yes,toolbar=no,menubar=no"; var newwin = window.open("(%ENV_SCRIPT_NAME%)?cmd=ticketed&tid=" + ID + "&sid=(%INPUT_sid%)&style=(%INPUT_style%)&isticket=1", "TicketEditor", hwstring); }
//--></script>
<script language="JavaScript"><!--
function showitem(ID){ hwstring="scrollbars=yes,width=650,height=350,resizable=yes,toolbar=no,menubar=no"; var newwin = window.open("(%ENV_SCRIPT_NAME%)?cmd=showitem&id=" + ID + "&sid=(%INPUT_sid%)&style=(%INPUT_style%)&isticket=1", "ItemInfo", hwstring); return false; }
//--></script>
<script language="JavaScript"><!--
function confirmdel()
{
return confirm("[%Please confirm ticket removal%]");
}
//--></script>
<script language="JavaScript"><!--
function answerlib(){
hwstring="scrollbars=yes,width=700,height=360,resizable=yes,toolbar=no,menubar=no";
var newwin = window.open("(%ENV_SCRIPT_NAME%)?cmd=answerlib&sid=(%INPUT_sid%)&style=(%INPUT_style%)", 'TTXAnswerLib', hwstring);
newwin.focus();
return false;
}
//--></script>
<script language="JavaScript"><!--
function preview(){
hwstring="scrollbars=yes,width=600,height=500,resizable=yes,toolbar=no,menubar=no";
var newwin = window.open('', 'winpreview', hwstring);
newwin.focus();
document.forms['preview'].msg.value = document.forms['newticket'].problem.value;
document.forms['preview'].submit();
return false;
}
//--></script>
<script language="JavaScript"><!--
function markuphelp(){
hwstring="scrollbars=yes,width=650,height=300,resizable=yes,toolbar=no,menubar=no";
var newwin = window.open("(%ENV_SCRIPT_NAME%)?cmd=markuphelp", 'TTXQuickHelp', hwstring);
return false;
}
//--></script>
<table width=(%HTMLBASEWIDTH%) cellspacing=0 cellpadding=0 bgcolor="#C6D7CF" style="padding-left: 5px; padding-right: 5px">
<form method=post action="(%ENV_SCRIPT_NAME%)" name=newticket id=newticket enctype="multipart/form-data" onsubmit="return onlyonce()">
<input type=hidden name=cmd value=ticket>
<input type=hidden name=style value="(%INPUT_style%)">
<input type=hidden name=sid value=(%INPUT_sid%)>
<input type=hidden name=do value=1>
<input type=hidden name=tid value=(%INPUT_tid%)>
<input type=hidden name=key value=(%INPUT_key%)>
<input type=hidden name=qsort value="(%INPUT_qsort%)">
<input type=hidden name=qsortorder value="(%INPUT_qsortorder%)">
<input type=hidden name=qoffset value=(%INPUT_qoffset%)>
<input type=hidden name=qwindow value=(%INPUT_qwindow%)>
<input type=hidden name=oper value=(%INPUT_oper%)>
<input type=hidden name=status value=(%INPUT_status%)>
<input type=hidden name=lname value=(%INPUT_lname%)>
<input type=hidden name=emailkey value=(%INPUT_emailkey%)>
<input type=hidden name=c0 value="(%INPUT_c0%)">
<input type=hidden name=c1 value="(%INPUT_c1%)">
<input type=hidden name=c2 value="(%INPUT_c2%)">
<input type=hidden name=c3 value="(%INPUT_c3%)">
<input type=hidden name=c4 value="(%INPUT_c4%)">
<input type=hidden name=c5 value="(%INPUT_c5%)">
<input type=hidden name=c6 value="(%INPUT_c6%)">
<input type=hidden name=c7 value="(%INPUT_c7%)">
<input type=hidden name=c8 value="(%INPUT_c8%)">
<input type=hidden name=c9 value="(%INPUT_c9%)">
<input type=hidden name=fltrsubj value="(%INPUT_fltrsubj%)">
<tr>
<td colspan=6 class=tiny>&nbsp</td>
</tr>
(%INVENTORYROW%)
<tr>
<td align=left class=lbl>[%Subject%]</td>
<td>&nbsp;&nbsp;</td>
<td align=left>(%TICKEDOPEN%)(%TICKET_subject%)(%TICKEDCLOSE%)</td>
<td align=left class=lbl>[%Group%]</td>
<td>&nbsp;&nbsp;</td>
<td align=left>(%TICKET_GROUP%)</td>
</tr>
<tr>
<td align=left class=lbl>[%Status%]</td>
<td>&nbsp;&nbsp;</td>
<td align=left width=90%>[%(%TICKET_status%)%]</td>
<td align=left class=lbl>[%Operator%]</td>
<td>&nbsp;&nbsp;</td>
<td align=left>(%TICKET_oper%)</td>
</tr>
<tr>
<td align=left class=lbl>[%Created%]</td>
<td>&nbsp;&nbsp;</td>
<td align=left>(%TICKET_open%)</td>
<td align=left class=lbl>[%Customer%]</td>
<td>&nbsp;&nbsp;</td>
<td align=left><nobr>(%TICKET_name%) (<a href="mailto:(%TICKET_email%)">(%TICKET_email%)</a>)</nobr></td>
</tr>
<tr>
<td align=left class=lbl>[%Solved%]</td>
<td>&nbsp;&nbsp;</td>
<td align=left>(%TICKET_closed%)</td>
<td align=left class=lbl><nobr>[%Access key%]</nobr></td>
<td>&nbsp;&nbsp;</td>
<td align=left>(%TICKET_key%)</td>
</tr>
<tr>
<td colspan=6 class=tiny>&nbsp</td>
</tr>
</table>
<br class=tiny>
<table width=(%HTMLBASEWIDTH%) cellspacing=0 cellpadding=0>
(%MESSAGES%)
<tr>
<td colspan=2 class=tiny>&nbsp</td>
</tr>
<tr>
<td valign=top align=left bgcolor="#CFDCE8" style="padding-left: 5px">
<br><span class=lbl>[%New status%]</span><br class=tiny>
(%NEWSTATUS%)
</td>
<td valign=top align=left bgcolor="#CFDCE8" style="padding-left: 5px"><br><span class=lbl>&nbsp;[%Message%]</span>(%ANSWERLIB%)(%PREVIEW%)
&nbsp;&nbsp;<a href=# onClick="return markuphelp()">[%Markup help%]</a><br class=tiny>
<table>
<tr>
<td align=right>
<textarea name=problem wrap=virtual cols=60 rows=10>(%INPUT_problem%)</textarea><br class=tiny>
(%FILEFORMS%)<br class=tiny>(%TRACKTIME%)
<input type=submit value="[%Add message%]">
<input type=submit name=cancel value="[%No changes%]">
(%DELTICKET%)<br><br class=tiny>
</td>
</tr>
</table>
</td>
</tr>
</form>
</table>
<form method="post" action="(%ENV_SCRIPT_NAME%)" id="preview" target="winpreview" >
<input type=hidden name=cmd value=preview>
<input type=hidden name=style value="(%INPUT_style%)">
<input type=hidden name=sid value=(%INPUT_sid%)>
<input type=hidden name=key value=(%INPUT_key%)>
<input type=hidden name=msg>
</form>
@@ -0,0 +1,75 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=[%CHARSET%]">
<title>[%Ticket Editor%]</title>
<style type="text/css">
<!--
body, td, p { font-family: Verdana, Helvetica, sans-serif; font-size: 10pt;}
-->
</style>
<script language=Javascript>
<!--
function closeme()
{
parentisticket = (%INPUT_isticket%);
if (parentisticket) {
msg = window.opener.document.newticket.problem.value;
opener.location.href = "(%ENV_SCRIPT_NAME%)?cmd=ticket&sid=(%INPUT_sid%)&key=(%TICKET_key%)&problem="+escape(msg);
} else {
opener.update();
}
window.close();
return false;
}
//-->
</script>
</head>
<body>
<center>
<font color=red><b>(%ERROR_MESSAGE%)</b></font><font color=blue><b>(%MESSAGE%)</b></font>
<table cellspacing=0 cellpadding=4>
<form action="(%ENV_SCRIPT_NAME%)" method=post>
<input type=hidden name=sid value="(%INPUT_sid%)">
<input type=hidden name=isticket value="(%INPUT_isticket%)">
<input type=hidden name=cmd value=ticketed>
<input type=hidden name=style value="(%INPUT_style%)">
<input type=hidden name=tid value="(%INPUT_tid%)">
<input type=hidden name=do value=1>
<tr>
<td align=right><b>[%Ticket ID%]</b></td>
<td align=left><b>(%INPUT_tid%)</b></td>
</tr>
<tr>
<td align=right><b>[%Email%]</b></td>
<td align=left><input type=text name=email size=30 value="(%TICKET_email%)"></td>
</tr>
<tr>
<td align=right><b>[%Name%]</b></td>
<td align=left><input type=text name=name size=30 value="(%TICKET_name%)"></td>
</tr>
<tr>
<td align=right><b>[%Subject%]</b></td>
<td align=left><input type=text name=subject size=30 value="(%TICKET_subject%)"></td>
</tr>
(%CUSTOMFIELDS%)
<tr>
<td colspan=2>
<table width="100%">
<tr>
<td width="50%" align=center>
<input type=submit class=boldcontent value="[%Update Ticket%]">
</td>
</form>
<td width="50%" align=center>
<input type=submit class=button onClick="return closeme()" value="[%Close Window%]">
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
+85
View File
@@ -0,0 +1,85 @@
#!/usr/bin/perl
use strict;
use CGI;
#use GD;
my $query = new CGI;
if ($query->param('generateimage')) {
generateImage();
} else {
# We weren't asked for the image,
# so let's return a simple web page
# that contains the image
my $gderror;
eval 'use GD';
if ($@ ne undef) {
$gderror = "<br><br>The following error occured when trying to load GD.pm<br><br>\n<b>$@</b>\n";
}
print $query->header;
print <<EOM
<html>
<body>
<br><br>
<center><b>GD Library Test
<br><br>
<table cellpadding="5" cellspacing="5">
<tr>
<td width="50%" align="center"><b><nobr>Remote image</nobr></b></td>
<td width="50%" align="center"><b><nobr>Local image</nobr></b></td>
</tr>
<tr>
<td align=center>
<img src="http://www.troubleticketexpress.com/testgd.gif">
</td>
<td align=center>
<img src="$ENV{SCRIPT_NAME}?generateimage=1">
</td>
</tr>
</table>
<br>
<table width="450">
<tr>
<td align=left>
If Local image is the same as (or similar to) the Remote image, both the GD Library
and GD.pm module are installed on your server.
<br><br>
If you do not see the Local image, either GD Library or GD.pm module are not available.
<a href="http://www.troubleticketexpress.com/gdlibrary.html"><nobr>Click here</nobr></a> for more info.
<br><br>
If you do not see the Remote image, either our web site is not available at the moment
or you have Internet connectivity problems. Anyway, make sure you see the Local image
(red square inside of black square).
$gderror
</td>
</tr>
</table>
</center>
<body>
</html>
EOM
;
}
sub generateImage {
eval 'use GD';
return if $@ ne undef;
# We MUST do this on Windows or the
# image will be garbled, and it
# doesn't hurt on Unix/Linux/etc
binmode STDOUT;
# Output the right content type
# for a PNG-format image
print $query->header("image/gif");
# Draw an image with a red rectangle
# in the middle
my $image = new GD::Image(100, 100);
my $black = $image->colorAllocate(
0, 0, 0);
my $red = $image->colorAllocate(
255, 0, 0);
$image->filledRectangle(
25, 25, 75, 75, $red);
# Output the image to the browser
print $image->gif;
}
+1
View File
@@ -0,0 +1 @@
5
+3
View File
@@ -0,0 +1,3 @@
1|1Z8887383590727458998|1161675767|1161675767||PND||whatisnet@netomi.co.kr|whatisnet|kakaka|TTXTicket|||||||||||||
4|4Z8987721738407954867|1161676971|1174885533|1174885533|CLS|sean|uphsu@netomi.co.kr|uphsu|&#53580;&#49828;&#53944;|TTXTicket|||||||||||||
2|2Z8974078920432262177|1161676242|1161676456|1161676456|CLS|whatisnet|uphsu@netomi.co.kr|uphsu|uphsu_test|TTXTicket|||||||||||||
+15
View File
@@ -0,0 +1,15 @@
From: whatisnet
Date: 1161675767
IP: 59.11.89.77
sdfs
df
d
d
d
d
a
d
d
-----------asdjhfKJS12869nmboiu7826318---
+20
View File
@@ -0,0 +1,20 @@
From: uphsu
Date: 1161676242
IP: 59.11.89.77
uphsu_mail test
-----------asdjhfKJS12869nmboiu7826318---
From: whatisnet
Date: 1161676346
Operator: 1
IP: 59.11.89.77
&#53580;&#49828;&#53944; &#50756;&#47308;.... ^^
-----------asdjhfKJS12869nmboiu7826318---
From: whatisnet
Date: 1161676456
Operator: 1
IP: 59.11.89.77
&#53580;&#49828;&#53944; &#50756;&#47308;.. &#51652;&#51676;..
-----------asdjhfKJS12869nmboiu7826318---
+20
View File
@@ -0,0 +1,20 @@
From: uphsu
Date: 1161676971
IP: 59.11.89.77
&#53580;&#49828;&#53944;
-----------asdjhfKJS12869nmboiu7826318---
From: tael
Date: 1174885504
Operator: 1
IP: 211.38.137.33
Ticket closed
-----------asdjhfKJS12869nmboiu7826318---
From: tael
Date: 1174885533
Operator: 1
IP: 211.38.137.33
&#53580;&#49828;&#53944; &#54644;&#44208;&#46120;.
-----------asdjhfKJS12869nmboiu7826318---
+652
View File
@@ -0,0 +1,652 @@
#!/usr/bin/perl
#
# Visit the Trouble Ticket Express home page for release notes and setup info
# 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) $
#
my $configfile;
my $defaultcmd = 'newticket';
# ==== NOTHING TO EDIT BELOW THIS LINE. PLS DO NOT CROSS =======================
my $version = '2.22';
my $REVISION;
BEGIN {
$REVISION = '$Revision: 287 $';
if ($REVISION =~ /(\d+)/) {
$REVISION = $1;
}
my $sd = _findsd() || '.';
$sd =~ /(.*)/;
$sd = $1;
my $path = $ENV{PATH};
$path =~ /(.*)/;
$ENV{PATH} = $1;
eval "use lib '$sd'";
if ($@) {
_fatalbegin($@);
exit 0;
}
if ($sd ne '.') {
chdir $sd;
}
eval "use TTXConfig";
if ($@) {
if (-f "$sd/TTXConfig.pm") {
_fatalbegin($@);
} else {
_fatalbegin("Incomplete package. Please upload all *.cgi and *.pm files to your web server");
}
exit 0;
}
sub _fatalbegin {
print <<EOT;
Content-type: text/html
<html>
<body>
<br><br>
<font color=red><b>Fatal error:</b></font>
$_[0]
<br><br>
<a href="http://ttx.helpdeskconnect.com"><b>Trouble Ticket Express Help Desk</b></a>
</body>
</html>
EOT
}
sub _findsd {
my $dir = $ENV{'SCRIPT_FILENAME'};
$dir = $ENV{'PATH_TRANSLATED'} if $ENV{'PATH_TRANSLATED'} ne undef;
$dir = $ENV{'pathTranslated'} if $ENV{'pathTranslated'} ne undef;
return $ENV{'PWD'} if $dir eq undef;
my @path = split(/\/|\\/, $dir);
pop(@path);
$dir = join("\/", @path);
return $dir;
}
}
use strict;
use CGI;
use TTXConfig;
use TTXData;
require TTXSession;
require TTXUser;
require TTXDictionary;
eval "require TTXFile";
TTXData::set('ISPRO', 1) if $@ eq undef;
# please feel free to uncomment the following line in order to get rid of
# bogus "usage of uninitialized variable" in your error log file, but
# make sure your Perl supports the 'no warnings' pragma
# no warnings 'uninitialized';
#
# Global vars
#
my $cfg;
my $query;
my $user;
my %data;
my $usecache = 0;
my $originalcookie;
my $cmddef = {
login => { action => 'TTXLogin::login', access => 0 },
ticket => { action => 'TTXTicket::ticket', access => 0 },
claim => { action => 'TTXTicket::claim', access => 1 },
keyfinder => { action => 'TTXTicket::keyform', access => 0, template => 'keyform.html' },
keyform => { action => 'TTXTicket::keyform', access => 0 },
newticket => { action => 'TTXTicket::newticket', access => 0 },
confirmnew => { action => 'TTXTicket::confirmnew', access => 0 },
markuphelp => { action => 'TTXMarkup::help', access => 0, noheader => 1, template => 'markuphelp.html' },
answerlib => { action => 'TTXOrder::answerlib', access => 1, noheader => 1, template => 'orderalib.html' },
newanswer => { action => 'TTXAnswerLib::newanswer', access => 1, noheader => 1 },
delanswer => { action => 'TTXAnswerLib::delanswer', access => 1, noheader => 1 },
editanswer => { action => 'TTXAnswerLib::editanswer', access => 1, noheader => 1, template => 'newanswer.html' },
ticketed => { action => 'TTXTickEd::ticketed', access => 1, noheader => 1, template => 'ticketed.html' },
helpdesk => { action => 'TTXDesk::helpdesk', access => 1 },
reports => { action => 'TTXReports::main', access => 1 },
survey => { action => 'TTXSurvey::survey', access => 0 },
cfrmsurvey => { action => 'TTXSurvey::confirm', access => 0 },
annotate => { action => 'TTXPrint::annotate', access => 0, noheader => 1 },
'print' => { action => 'TTXPrint::print', access => 0, noheader => 1 },
preview => { action => 'TTXPreview::preview', access => 0, noheader => 1 },
groupcommand => { action => 'TTXGrpCmd::do', access => 1 },
msgedit => { action => 'TTXMsgEdit::edit', access => 1, noheader => 1 },
msgdel => { action => 'TTXMsgEdit::del', access => 1, noheader => 1 },
};
eval "require TTXAnswerLib";
if ($@ eq undef) {
$cmddef->{answerlib}->{action} = 'TTXAnswerLib::answerlib';
$cmddef->{answerlib}->{template} = 'answerlib.html';
}
eval "use TTXMyTickets";
if ($@ eq undef) {
$cmddef->{mytickets}->{action} = 'TTXMyTickets::mytickets';
$cmddef->{mytickets}->{template} = 'helpdesk.html';
}
eval "require TTXDashBoard";
if ($@ eq undef) {
$cmddef->{showitem}->{action} = 'TTXDashBoard::showitem';
$cmddef->{showitem}->{noheader} = 1;
$cmddef->{showitem}->{access} = 1;
$cmddef->{dashboard}->{action} = 'TTXDashBoard::dashboard';
$cmddef->{dashboard}->{access} = 1;
}
#
# Read config
#
if ($configfile eq undef) {
$configfile = 'ttxcfg.cgi';
my $sd = scriptdir();
$configfile = "$sd/ttxcfg.cgi" if $sd ne undef;
}
$cfg = TTXConfig->new($configfile);
if ($cfg->error()) {
print "Content-type: text/html\n\n";
fatalerror($cfg->errortext())
}
if ($cfg->get('cfgref') ne undef) {
if (!$cfg->load($cfg->get('cfgref'))) {
print "Content-type: text/html\n\n";
fatalerror($cfg->errortext());
}
}
if ($cfg->get('order1256')) {
$cmddef->{ticket}->{template} = 'ticket1256.html';
}
if ($cfg->get('validate') ne undef) {
$cmddef->{confirmnew}->{template} = 'confirmnewvalidate.html';
}
TTXData::set('CONFIG', $cfg);
if ($cfg->get('cookiename') eq undef) {
$cfg->set('cookiename', 'TTXPRESS');
}
readglobals();
if ($cfg->get('httphost') ne $ENV{HTTP_HOST} || $cfg->get('scriptname') ne $ENV{SCRIPT_NAME}) {
$cfg->set('httphost', $ENV{HTTP_HOST});
$cfg->set('scriptname', $ENV{SCRIPT_NAME});
$cfg->save();
}
if ($cfg->get('ttx.version') eq undef || $cfg->get('ttx.version') < $version) {
eval 'use TTXUpgrade';
if ($@ ne undef) {
print "Content-type: text/html\n\n";
fatalerror('TTXUpgrade.pm not found. Please upload the file to the scripts directory.');
}
my $err = TTXUpgrade::upgrade($cfg);
if ($err ne undef) {
print "Content-type: text/html\n\n";
fatalerror("Error during upgrade: $err");
}
}
if ($cfg->get('internaldesk')) {
$cmddef->{newticket}->{access} = 1;
$defaultcmd = 'helpdesk';
}
#
# Stop here if database upgrade is in progress
#
if ($cfg->get('dbupdate') > 0) {
if ((time() - $cfg->get('dbupdate')) > 120) {
# the upgrade process died
$cfg->set('dbupdate', '');
$cfg->save();
} else {
print "Content-type: text/html\n\n";
upgrademsg();
exit;
}
}
#
# Parse input
#
my $tmpdir = $cfg->get('basedir').'/tmp';
if (! -d $tmpdir) {
mkdir($tmpdir, 0777);
}
if (-d $tmpdir && -w $tmpdir) {
$ENV{TMPDIR} = $tmpdir if $ENV{TMPDIR} eq undef || ! -d $ENV{TMPDIR} || ! -w $ENV{TMPDIR};
}
eval '$query = new CGI';
if ($@ ne undef) {
warn "New CGI failed, error: $@";
print <<EOT;
Content-type: text/html
<html>
<body>
<br><br><br><br>
<center>
<b><font color=red>The file you are trying to upload is too big</font>
<br><br>
Please use your browser 'Back' button to return to previous page.
</center>
</body>
</html>
EOT
exit;
}
if ($query eq undef) {
print "Content-type: text/html\n\n";
exit;
}
if ($query->param('cmd') eq 'file' && TTXData::get('ISPRO')) {
TTXFile::download($query->param('fid'), $query->param('fn'));
exit;
}
if ($query->param('cmd') eq 'img') {
eval "use TTXImage";
if (!$@) {
TTXImage::show($query->param('fid'), $query->param('fid'));
}
exit;
}
#
# Create User object if session id provided
#
print "Content-type: text/html\n"; # Single new-line, as more headers may follow
my $savestate = $|;
$|=1;
$|=$savestate;
if ($query->param('sid') ne undef) {
my $session = TTXSession->new($query->param('sid'));
if ($session ne undef && $session->get('login') ne undef) {
if ($session->expired()) {
$session->logout();
$query->param(-name => 'sid', -value => '');
$query->param(-name => 'cmd', -value => 'helpdesk');
login('[%Your session expired%]');
} else {
$session->refresh();
$user = TTXUser->new($session->get('login'));
if ($user eq undef || $user->get('login') eq undef) {
$query->param(-name => 'sid', -value => '');
$user = undef;
} elsif ($query->param('cmd') eq 'logout') {
$session->logout();
$query->param(-name => 'sid', -value => '');
$query->param(-name => 'cmd', -value => '');
login('[%You were logged out%]');
$user = undef;
} else {
$user->set('session', $session);
}
}
} else {
$query->param(-name => 'sid', -value => '');
}
} else {
if ($cfg->get('quicklink') && $query->param('cmd') eq 'helpdesk') {
my $oper = $query->param('o');
my $tk = $query->param('tk');
my $p = $query->param('p');
if ($oper ne undef && $tk =~ /^\d+Z/ && $p ne undef) {
my $u = TTXUser->new($oper);
if ($u ne undef && $u->{passwd} ne undef) {
$tk =~ s/Z.*//;
my $salt = $tk;
$salt = $salt % 100;
$salt = "0$salt" if $salt < 10;
$p = "$salt$p";
if ($p eq crypt($u->{passwd}.$tk, $p)) {
$query->param(-name => 'cmd', -value => 'login');
$query->param(-name => 'nextcmd', -value => 'helpdesk');
$query->param(-name => 'login', -value => $oper);
$query->param(-name => 'passwd', -value => $u->{passwd});
$query->param(-name => 'dologin', -value => 1);
}
}
}
}
}
if ($query->param('cmd') eq 'logout') {
$query->param(-name => 'cmd', -value => '');
login("You were logged out");
}
if ($user ne undef) {
$cfg->set('_USER', $user);
$data{USERID} = $user->{login};
if ($user->get('ro')) {
$cmddef->{ticket}->{template} = 'roticket.html';
}
}
if ($cfg->get('HTMLBASEWIDTH') eq undef) {
$cfg->set('HTMLBASEWIDTH', 700);
$cfg->save();
}
my $charset = TTXDictionary::translate('CHARSET');
if ($charset ne undef && $charset ne 'CHARSET' && $charset ne $cfg->get('charset')) {
$cfg->set('charset', $charset);
$cfg->save();
}
if ($query->param('cmd') eq undef) {
$query->param(-name => 'cmd', -value => $defaultcmd);
}
#
# Consult cache
#
my $pagesignature;
if ($cfg->get('usecache')) {
eval "use TTXCache";
if ($@ eq undef) {
$usecache = 1;
TTXData::set('_USECACHE', 1);
my $pgid = TTXCache::hit($cfg, $query);
$pagesignature = TTXCache::signature($query);
my $sessig;
if ($query->param('sid') ne undef) {
my $session = TTXSession->new($query->param('sid'));
if ($session ne undef && $user ne undef &&
$session->get('login') ne undef &&
$user->{login} eq $session->get('login')) {
$sessig = $session->get('signature');
$session->set('signature', $pagesignature);
$session->save();
}
}
if ($pgid) {
my $pgout = TTXCache::page($cfg, $pgid);
if ($pgout ne undef) {
print "\n$pgout";
TTXCache::logit('H|'.$query->param('cmd').'|'.length($pgout));
exit;
}
} else {
TTXCache::logit('M|'.$query->param('cmd'));
}
}
}
#
# Execute command
#
command($query->param('cmd'));
my $cfgvars = $cfg->ashash();
foreach my $key (keys %{$cfgvars}) {
$data{"CONFIG_".uc $key} = $cfgvars->{$key};
}
foreach my $key (keys %ENV) {
$data{"ENV_".uc $key} = $ENV{$key};
}
foreach my $key ($query->param) {
$data{"INPUT_".$key} = $query->param($key);
if ($key ne 'problem') {
$data{"INPUT_".$key} =~ s/"/&quot;/g;
} else {
$data{"INPUT_".$key} =~ s/</&lt;/g;
}
}
if (defined $cmddef->{dashboard} && $cfg->get('_USER') ne undef) {
$data{DASHBOARDLINK} = "<a href=\"$ENV{SCRIPT_NAME}?cmd=dashboard&sid=".$query->param('sid').
"&style=".$query->param('style').'">[%Dashboard%]</a> |';
}
if ($query->param('checkupdate')) {
$data{CHECKUPDATE} = "<a href=\"http://www.troubleticketexpress.com\"><img border=0 src=\"http://www.troubleticketexpress.com/cgi-bin/ttx/checkupdate.cgi?$version\"></a>";
}
$data{VERSION} = "$version.$REVISION";
if ($cfg->get('dbmode') eq 'mysql') {
$data{ISPRO} .= 'MySQL Edition';
} elsif ($cfg->get('dbmode') eq 'mssql') {
$data{ISPRO} .= 'SQL Server Edition';
} else {
$data{ISPRO} .= 'Standard Edition';
my $u = $cfg->get('_USER');
# if ($u ne undef && $u->{login} eq 'admin') {
$data{ISPRO} .= ', upgrade to <a href="sqlsetup.cgi">MySQL</a> or '.
'<a href="mssqlsetup.cgi">SQL Server</a> edition.'
# }
}
$data{HTMLBASEWIDTH} = $cfg->get('HTMLBASEWIDTH');
$data{HELPDESKCMD} = ($cfg->get('_USER') ne undef) ? 'helpdesk':'ticket';
if ($query->param('cmd') eq 'mytickets' ||
($query->param('cmd') eq 'ticket' && $query->param('emailkey') ne undef && $query->param('sid') eq undef)) {
$data{HELPDESKCMD} = 'mytickets&emailkey=' . $query->param('emailkey');
}
if ($cfg->get('_USER') ne undef) {
my $u = $cfg->get('_USER');
$data{USERID} = $u->{login};
$data{USERFNAME} = $u->{fname};
$data{USERLNAME} = $u->{lname};
$data{LOGGEDAS} = TTXDictionary::translate('Logged as').' '.$u->{fname}.' '.$u->{lname};
if ($cfg->get('dbmode') =~ /sql/ && $cfg->get('dbschema') < 2.19) {
$data{ISPRO} .= ' <font color=red><b>NOTE:</b></font> <a href="sqlupgrade.cgi"><b>Database upgrade required.</b></a>';
} elsif ($cfg->get('dbmode') =~ /sql/ && $cfg->get('dbschema') < 2.22) {
$data{ISPRO} .= ' <font color=red><b>NOTE:</b></font> <a href="sqlupgrade222.cgi"><b>Database upgrade required.</b></a>';
}
}
if ($cfg->get('_USER') ne undef) {
my $uid = $cfg->get('_USER')->get('login');
if ($cfg->get('grant.reports') eq undef || grep(/^$uid$/, split(/,/,$cfg->get('grant.reports')))) {
$data{LOGINLOGOUT} .= "<a href=\"$ENV{SCRIPT_NAME}?cmd=reports&sid=".
$query->param('sid')."&style=".$query->param('style').'">[%Reports%]</a> | ';
}
}
if (!$cfg->get('nologinlink')) {
$data{LOGINLOGOUT} .= "<a href=\"$ENV{SCRIPT_NAME}?cmd=".(($cfg->get('_USER') ne undef) ? 'logout':'login').
"&sid=".$query->param('sid')."&style=".$query->param('style')."\">".(($cfg->get('_USER') ne undef) ? '[%Logout%]':'[%Login%]').
"</a>";
}
if ($cfg->get('home') ne undef) {
$data{HOMELINK} .= '<a href="'.$cfg->get('home').'">[%Home%]</a> |';
}
if ($data{ERROR_MESSAGE} ne undef) {
$data{ERROR_BOX} =<<EOT;
<table width=$data{HTMLBASEWIDTH} cellpadding=0 cellspacing=0>
<tr>
<td align=center bgcolor="#CFDCE8">
<br>
<table width=500 cellpadding=0 cellspacing=0>
<tr>
<td class=error align=center>$data{ERROR_MESSAGE}</td>
</tr>
</table>
<br>
</td>
</tr>
</table>
EOT
}
my $template = loadtemplate();
$template =~ s/\(%\s*([a-zA-Z0-9_]+)\s*%\)/$data{$1}/g;
$template =~ s/\[%%\]//g;
$template =~ s/\[%([^]]+)%\]/TTXDictionary::translate($1)/ge;
print preparecookie()."\n$template";
#
# Update cache
#
if ($usecache) {
TTXCache::store($cfg, $query, $template, $pagesignature);
}
exit;
#================================================================== loadtemplate
sub loadtemplate {
my ($t, $style);
if ($query->param('cmd') eq 'newticket' && $query->param('form') ne undef) {
my @parts = split(/\/|\\/, $query->param('form'));
$t = pop @parts;
$t .= '.html';
# } elsif ($query->param('cmd') eq 'keyfinder') {
# $t = 'keyform.html';
}
if ($t eq undef) {
$t = $cmddef->{$query->param('cmd')}->{template};
$t = $query->param('cmd').".html" if $t eq undef;
}
my $fn = $cfg->get('basedir')."/templates";
if ($query->param('style') ne undef) {
my @parts = split(/\/|\\/, $query->param('style'));
$style = pop @parts;
}
if ($style ne undef) {
if ((! -f "$fn/$style/$t" || !open(TMPL, "$fn/$style/$t")) &&
(! -f "$fn/$t" || !open(TMPL, "$fn/$t"))) {
fatalerror("Missing template $t");
}
} elsif (! -f "$fn/$t" || !open(TMPL, "$fn/$t")) {
fatalerror("Missing template $t");
}
my @buff = <TMPL>;
close TMPL;
my $template = join('', @buff);
if (!($cmddef->{$query->param('cmd')}->{noheader} || $query->param('noheader'))) {
if (($style ne undef && open(TMPL, "$fn/$style/header.shtml")) || open(TMPL, "$fn/header.shtml")) {
my @hdr = <TMPL>;
close TMPL;
$template = join('', @hdr) . $template;
}
if (($style ne undef && open(TMPL, "$fn/$style/footer.shtml")) || open(TMPL, "$fn/footer.shtml")) {
my @ftr = <TMPL>;
close TMPL;
$template .= join('', @ftr);
}
}
return $template;
}
#======================================================================= command
sub command {
my $cmd = $_[0];
if (!defined $cmddef->{$cmd}) {
fatalerror("Unknown command [$cmd]");
}
if ($cmddef->{$cmd}->{access}) {
if ($cfg->get('_USER') eq undef) {
$cmd = 'login';
login('[%This command is available to operator only. Please login.%]');
}
}
my @action_path = split(/::/, $cmddef->{$cmd}->{action});
my $func = pop @action_path;
my $module = join("::", @action_path);
if ($module eq undef) {
fatalerror("No module defined for [$cmd] action");
}
if ($func eq undef) {
fatalerror("No function defined for [$cmd] action");
}
$module =~ /(.*)/; $module = $1;
eval "use $module";
fatalerror("Unable to load module $module<br><br>$@<br><br>SD:".scriptdir()) if $@;
my $markcmd = $cmd;
{
no strict 'refs';
$cmd = ($cmddef->{$cmd}->{action})->($cfg, $query, \%data);
}
fatalerror("Recursive call to $cmd") if $cmd eq $markcmd;
if ($cmd ne undef) {
$query->param(-name => 'cmd', -value => $cmd);
command($cmd);
}
return undef;
}
#========================================================================= login
sub login {
$query->param(-name => 'nextcmd', -value => $query->param('cmd'));
$query->param(-name => 'loginmsg', -value => $_[0]);
$query->param(-name => 'cmd', -value => 'login');
$query->param(-name => 'form', -value => '');
}
#==================================================================== fatalerror
sub fatalerror {
print <<EOT;
Content-type: text/html
<html>
<head><title>Trouble Ticket Express</title></head>
<body>
<br><center><h1>Fatal Error: $_[0]</h1>
</body>
</html>
EOT
exit;
}
# ==================================================================== scriptdir
sub scriptdir {
my $dir = $ENV{'SCRIPT_FILENAME'};
$dir = $ENV{'PATH_TRANSLATED'} if $ENV{'PATH_TRANSLATED'} ne undef;
$dir = $ENV{'pathTranslated'} if $ENV{'pathTranslated'} ne undef;
return $ENV{'PWD'} if $dir eq undef;
my @path = split(/\/|\\/, $dir);
pop(@path);
$dir = join("\/", @path);
return $dir;
}
# =================================================================== upgrademsg
sub upgrademsg {
print <<EOT;
<html>
<body>
<br><br>
<center>
The help desk system is temporary unavailable due to scheduled maintenance.
<br><br>
We will resume operations within next 5 minutes.
<br><br>
</center>
</body>
</html>
EOT
}
#=================================================================== readglobals
sub readglobals {
my @http_cookie = split(/; /,$ENV{'HTTP_COOKIE'});
my %cookies;
foreach (@http_cookie) {
my @parts = split('=',$_);
my $n = shift @parts;
my $v = join('=', @parts);
$cookies{$n}=$v;
}
my $cookiename = $cfg->get('cookiename');
if ($cookies{$cookiename} ne undef) {
$originalcookie = $cookies{$cookiename};
my @globals = split (/&/, $cookies{$cookiename});
foreach (@globals) {
my @parts = split('=',$_);
my $n = shift @parts;
my $v = join('=', @parts);
$v =~ s/%0D%0A/\n/g;
$v =~ s/%0A%0D/\n/g;
$v =~ tr/+/ /;
$v =~ s/%([A-Fa-f0-9]{2})/pack("c",hex($1))/ge;
$cfg->set("_GLOBAL_$n", $v);
}
}
}
#================================================================= preparecookie
sub preparecookie {
return undef if $cfg->get('_NOCOOKIE');
my $cookie;
foreach my $global (keys %{$cfg}) {
next if $global !~ /^_GLOBAL_/;
my $name = $global;
$name =~ s/^_GLOBAL_//;
my $value = $cfg->get($global);
next if $value eq undef;
$value =~ s/([^a-zA-Z0-9_])/sprintf("%%%X", ord($1))/eg;
$cookie .= '&' if $cookie ne undef;
$cookie .= "$name=$value";
}
return undef if $cookie eq $originalcookie;
return "Set-Cookie: ".$cfg->get('cookiename')."=$cookie; path=/; expires=Mon, 28-Dec-2037 00:00:00 GMT\n";
}
# end of file
+30
View File
@@ -0,0 +1,30 @@
HTMLBASEWIDTH=700
admpwd=alfkzmf!?{}qrwe
admpwdseed=mI
basedir=/user2/wwwroot/tts
brcols=id|name|email|subject|oper|status|open|updated
charset=windows-1252
company=(ÁÖ)³×Åä¹Ì
cookiename=TTXPRESS
delim=|
email=bs@netomi.co.kr
emailfix=0
fltrcols=text|subject|oper|status|id
grpsellbl=Department
hideoldsolved=365
home=http://www.netomi.co.kr
httphost=tts.0x31.com
imgurl=.
itemidx=10
mailer=/usr/sbin/sendmail
nomsgcfrm=0
notikcfrm=0
savecnt=7
scriptname=/ttx.cgi
smtptrace=0
ticketdb=/user2/wwwroot/tts/tickets.cgi
ticketid=/user2/wwwroot/tts/ticketid.txt
timezone=540
ttx.version=2.22
useaccesscode=1
userdb=/user2/wwwroot/tts/users.cgi
+14
View File
@@ -0,0 +1,14 @@
1161676316|CLAIM|whatisnet|2
1161676346|RESPOND|whatisnet|2
1161676456|RESPOND|whatisnet|2
1161676456|CLOSE|whatisnet|2
1161676612|CLAIM|whatisnet|3
1161677357|CLAIM|whatisnet|5
1161677366|RESPOND|whatisnet|5
1161677366|CLOSE|whatisnet|5
1174885422|CLOSE|tael|4
1174885450|TRANSFER|tael|4|sean
1174885504|RESPOND|sean|4
1174885504|CLOSE|sean|4
1174885533|RESPOND|sean|4
1174885533|CLOSE|sean|4
+4
View File
@@ -0,0 +1,4 @@
sean|qrwe1423|SEAN|KIM|sean@netomi.co.kr||1|17||
taeha|wagner|박태하|.|taeha@netomi.co.kr||1|25||
whatisnet|spxhal|강명균|kang|whatisnet@netomi.co.kr|||41||
tael|1212|Taeil|Kim|tael@netomi.co.kr||1|51||