base
This commit is contained in:
@@ -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
@@ -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 = ' ';
|
||||
}
|
||||
$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 = ' ';
|
||||
}
|
||||
if ($percentage && $total) {
|
||||
$v .= ' ('.(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> $v</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
EOT
|
||||
}
|
||||
$buff .= "</table>\n";
|
||||
return $buff;
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
#
|
||||
@@ -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;
|
||||
#
|
||||
|
||||
@@ -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;
|
||||
#
|
||||
|
||||
@@ -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;
|
||||
#
|
||||
|
||||
@@ -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;
|
||||
#
|
||||
|
||||
@@ -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> ";
|
||||
++$colcnt; # text is always first element
|
||||
} elsif ($fld eq 'drange') {
|
||||
if ($colcnt > 1) {
|
||||
while ($colcnt <= 2) {
|
||||
$buff .= "<td> </td><td> </td>\n";
|
||||
++$colcnt;
|
||||
}
|
||||
$buff .= "</tr>\n<tr>\n";
|
||||
}
|
||||
$buff .= '<td align=right class=lbl>[%Date Range%]</td>'."\n".
|
||||
"<td colspan=5 align=left>\n <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 ".TTXCommon::pickdate($query, 'drs', 1).
|
||||
" - ".TTXCommon::pickdate($query, 'dre', 0)."</td>\n";
|
||||
} else {
|
||||
$buff .= '<td align=right class=lbl>[%'.$c2T{$fld}.'%]</td>'."\n".'<td align=left> ';
|
||||
}
|
||||
if ($fld eq 'oper') {
|
||||
$buff .= $data->{OPERSELBOX};
|
||||
} elsif ($fld eq 'item') {
|
||||
if (invenabled()) {
|
||||
$buff .= TTXInvMod::selbox($cfg, $query, 0);
|
||||
} else {
|
||||
$buff .= ' ';
|
||||
}
|
||||
} 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/"/"/g;
|
||||
my $h = $option;
|
||||
$h =~ s/</</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/&/&/g;
|
||||
$val =~ s/</</g;
|
||||
$val =~ s/"/"/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> </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/</"/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/</</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/</</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/</</g;
|
||||
$val =~ s/>/>/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/</</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> </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;
|
||||
#
|
||||
|
||||
@@ -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;
|
||||
#
|
||||
@@ -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;
|
||||
#
|
||||
@@ -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;
|
||||
#
|
||||
|
||||
@@ -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> C:\></b><i>ppm.bat</i><br>
|
||||
<b> 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> C:\></b><i>ppm.bat</i><br>
|
||||
<b> 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> <select name=dbdsn1 onChange="document.forms['mainform'].dbdsn.value='';"><option></option>
|
||||
EOT
|
||||
my $dsnval = $dsn;
|
||||
$dsnval = s/"/"/g;
|
||||
foreach my $d (@dsns) {
|
||||
my $quotedsn = $d; $quotedsn =~ s/"/"/g;
|
||||
my $quotedsn1 = $d; $quotedsn =~ s/</</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> <input type=text name=user value="$user"></td></tr>
|
||||
<tr><td align=right><b>Password:</b></td><td> <input type=password name=pass value="$pass"></td></tr>
|
||||
|
||||
<tr><td colspan=2 align=center> </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> <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;
|
||||
#
|
||||
@@ -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;
|
||||
#
|
||||
@@ -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/ / /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;
|
||||
#
|
||||
@@ -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> <input type=text name=host value="$host"></td></tr>
|
||||
<tr><td align=right><b>MySQL Port:</b></td><td> <input type=text name=port value="$port"></td></tr>
|
||||
<tr><td align=right><b>Database ID:</b></td><td> <input type=text name=dbid value="$dbid"></td></tr>
|
||||
<tr><td align=right><b>MySQL User:</b></td><td> <input type=text name=user value="$user"></td></tr>
|
||||
<tr><td align=right><b>MySQL Password:</b></td><td> <input type=password name=pass value="$pass"></td></tr>
|
||||
|
||||
<tr><td colspan=2 align=center> </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> <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;
|
||||
#
|
||||
|
||||
@@ -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/</"/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;
|
||||
#
|
||||
@@ -0,0 +1,9 @@
|
||||
package TTXOrder;
|
||||
use strict;
|
||||
|
||||
# ==================================================================== answerlib
|
||||
|
||||
sub answerlib {
|
||||
}
|
||||
1;
|
||||
#
|
||||
@@ -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;
|
||||
#
|
||||
|
||||
@@ -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/</</g;
|
||||
$body = TTXMarkup::html($body);
|
||||
$body =~ s/\n/<br>\n/g;
|
||||
$data->{MESSAGE} = $body;
|
||||
return undef;
|
||||
}
|
||||
1;
|
||||
#
|
||||
@@ -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%] </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;
|
||||
#
|
||||
|
||||
@@ -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/<([^>]*)>/<$1>/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;
|
||||
#
|
||||
@@ -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
@@ -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/</</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/"/"/g;
|
||||
$data->{CUSTOMFIELDS} .= "<option value=\"$val\"";
|
||||
if (grep(/^$opt$/, @qlist)) {
|
||||
$data->{CUSTOMFIELDS} .= ' selected';
|
||||
}
|
||||
$opt =~ s/</</g;
|
||||
$data->{CUSTOMFIELDS} .= ">$opt</option>\n";
|
||||
}
|
||||
$data->{CUSTOMFIELDS} .= "</select>\n";
|
||||
} else {
|
||||
my $val = $query->param('do') ? $query->param($id) : $t->{$id};
|
||||
$val =~ s/"/"/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
@@ -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;
|
||||
#
|
||||
@@ -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> <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;
|
||||
#
|
||||
|
||||
@@ -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|테스트|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|||||||||||||
|
||||
@@ -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
|
||||
|
Binary file not shown.
|
After Width: | Height: | Size: 43 B |
@@ -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>
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
@@ -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/</</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
|
||||
@@ -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
|
||||
}
|
||||
@@ -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> </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)">
|
||||
<input type=submit name=new value="[%New%]">
|
||||
<input type=submit name=edit value="[%Edit%]">
|
||||
<input type=submit name=del value="[%Delete%]">
|
||||
<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> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=left class=lbl>[%Status%]</td>
|
||||
<td> </td>
|
||||
<td align=left>[%(%TICKET_status%)%]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=left class=lbl>[%Subject%]</td>
|
||||
<td> </td>
|
||||
<td width=90% align=left>(%TICKET_subject%)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=left class=lbl>[%Group%]</td>
|
||||
<td> </td>
|
||||
<td width=90% align=left>(%TICKET_GROUP%)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=left class=lbl>[%Created%]</td>
|
||||
<td> </td>
|
||||
<td align=left>(%TICKET_open%)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=3 class=tiny> </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%) <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> </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> </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> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>(%TICKETFILTER%)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=tiny> </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%]"> <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> <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> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>(%REPORTQUERY%)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=tiny> </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> </td>
|
||||
<td align=left>(%TICKEDOPEN%)(%TICKET_subject%)(%TICKEDCLOSE%)</td>
|
||||
<td align=left class=lbl>[%Group%]</td>
|
||||
<td> </td>
|
||||
<td align=left>(%TICKET_GROUP%)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=left class=lbl>[%Status%]</td>
|
||||
<td> </td>
|
||||
<td align=left width=90%>(%TICKET_status%)</td>
|
||||
<td align=left class=lbl>[%Operator%]</td>
|
||||
<td> </td>
|
||||
<td align=left>(%TICKET_oper%)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=left class=lbl>[%Created%]</td>
|
||||
<td> </td>
|
||||
<td align=left>(%TICKET_open%)</td>
|
||||
<td align=left class=lbl>[%Customer%]</td>
|
||||
<td> </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> </td>
|
||||
<td align=left>(%TICKET_closed%)</td>
|
||||
<td align=left class=lbl><nobr>[%Access key%]</nobr></td>
|
||||
<td> </td>
|
||||
<td align=left>(%TICKET_key%)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=6 class=tiny> </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> </td>
|
||||
</tr>
|
||||
(%INVENTORYROW%)
|
||||
<tr>
|
||||
<td align=left class=lbl>[%Subject%]</td>
|
||||
<td> </td>
|
||||
<td align=left>(%TICKEDOPEN%)(%TICKET_subject%)(%TICKEDCLOSE%)</td>
|
||||
<td align=left class=lbl>[%Group%]</td>
|
||||
<td> </td>
|
||||
<td align=left>(%TICKET_GROUP%)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=left class=lbl>[%Status%]</td>
|
||||
<td> </td>
|
||||
<td align=left width=90%>[%(%TICKET_status%)%]</td>
|
||||
<td align=left class=lbl>[%Operator%]</td>
|
||||
<td> </td>
|
||||
<td align=left>(%TICKET_oper%)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=left class=lbl>[%Created%]</td>
|
||||
<td> </td>
|
||||
<td align=left>(%TICKET_open%)</td>
|
||||
<td align=left class=lbl>[%Customer%]</td>
|
||||
<td> </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> </td>
|
||||
<td align=left>(%TICKET_closed%)</td>
|
||||
<td align=left class=lbl><nobr>[%Access key%]</nobr></td>
|
||||
<td> </td>
|
||||
<td align=left>(%TICKET_key%)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=6 class=tiny> </td>
|
||||
</tr>
|
||||
</table>
|
||||
<br class=tiny>
|
||||
<table width=(%HTMLBASEWIDTH%) cellspacing=0 cellpadding=0>
|
||||
(%MESSAGES%)
|
||||
<tr>
|
||||
<td colspan=2 class=tiny> </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> [%Message%]</span>(%ANSWERLIB%)(%PREVIEW%)
|
||||
<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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
5
|
||||
@@ -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|테스트|TTXTicket|||||||||||||
|
||||
2|2Z8974078920432262177|1161676242|1161676456|1161676456|CLS|whatisnet|uphsu@netomi.co.kr|uphsu|uphsu_test|TTXTicket|||||||||||||
|
||||
@@ -0,0 +1,15 @@
|
||||
From: whatisnet
|
||||
Date: 1161675767
|
||||
IP: 59.11.89.77
|
||||
|
||||
sdfs
|
||||
df
|
||||
|
||||
d
|
||||
d
|
||||
d
|
||||
d
|
||||
a
|
||||
d
|
||||
d
|
||||
-----------asdjhfKJS12869nmboiu7826318---
|
||||
@@ -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
|
||||
|
||||
테스트 완료.... ^^
|
||||
-----------asdjhfKJS12869nmboiu7826318---
|
||||
From: whatisnet
|
||||
Date: 1161676456
|
||||
Operator: 1
|
||||
IP: 59.11.89.77
|
||||
|
||||
테스트 완료.. 진짜..
|
||||
-----------asdjhfKJS12869nmboiu7826318---
|
||||
@@ -0,0 +1,20 @@
|
||||
From: uphsu
|
||||
Date: 1161676971
|
||||
IP: 59.11.89.77
|
||||
|
||||
테스트
|
||||
-----------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
|
||||
|
||||
테스트 해결됨.
|
||||
-----------asdjhfKJS12869nmboiu7826318---
|
||||
@@ -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/"/"/g;
|
||||
} else {
|
||||
$data{"INPUT_".$key} =~ s/</</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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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||
|
||||
Reference in New Issue
Block a user