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 = < Please install DBI library prior to running this program.
Try this:
EOT if ($^O eq 'MSWin32') { $error .= <   C:\>ppm.bat
   ppm> install DBI
EOT } else { $error .= <#perl -MCPAN -e shell
cpan> install DBI
EOT } $error .= <
EOT } # # Check if ODBC DBD driver installed # if ($error eq undef) { my @drivers = DBI->available_drivers(1); if (!grep(/ODBC/, @drivers)) { $error = < Please install ODBC DBD driver prior to running this program.
Try this:
EOT my $drv = 'DBD::ODBC'; if ($^O eq 'MSWin32') { $error .= <   C:\>ppm.bat
   ppm> install $drv
EOT } else { $error .= <#perl -MCPAN -e shell
cpan> install $drv
EOT } $error .= <
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.
Please configure DSN prior to running this program." if !@dsns; } # foreach my $d (@dsns) { # print "$d
\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
\n". "THIS SCRIPT WILL RESET YOUR TICKETS DATABASE
\n". "ALL TICKETS SUBMITTED USING SQL MODE WILL BE LOST!"; } $error = "
Error: $error

" if $error ne undef; $warning = "\n
$warning

" if $warning ne undef; print <Microsoft SQL Server Module Setup
(go to Main Setup Utility form)
$error$warning

SQL Server database access info. Please contact your hosting provider or system admin if not sure.

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.

DSN:   
User:  
Password:  
 

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.

Table prefix (optional):  



The import procedure may take several minutes to complete.
Do not click twice!


Login to Trouble Ticket Express EOT } # =========================================================================== ok sub ok { print "
Congratulations!


\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 do not run database setup utility unless you want to make changes to the database settings.\n" } print "

\n"; if ($cfg->get('dbmode') ne 'mssql') { print <IMPORTANT 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.

Order MS SQL add-on module


EOT } else { print "Trouble Ticket Express now uses SQL Server database.

\n"; } print "
Main Setup Utility
". "Trouble Ticket Express
\n"; print "
\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}."
\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 = ; 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 = <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 = <do($sql)) { return "Error creating table $tablename, ".$dbh->errstr; } if ($table eq 'messages') { $dbh->do("CREATE INDEX TID ON $tablename (TID)"); } return undef; } 1; #