Gheek.net

October 13, 2011

HTML Input type hidden has extra space when POST/GET methods sends

Filed under: html — lancevermilion @ 3:45 pm

Apparently some browsers interrupt INPUT types of hidden differently.
For example if you have a newlines, tables, or spaces between the space between is considered.

<INPUT NAME="A1" TYPE="hidden"/> <INPUT NAME="A2" TYPE="hidden"/>

The solution is to use a DIV with a STYLE of display:none and change your TYPE to “text”.

<DIV STYLE="display;none;"><INPUT NAME="A1" TYPE="text"/> <INPUT NAME="A2" TYPE="text"/></DIV>

This is a nice discovery, but very frustrating.

Advertisement

Perl to Microsoft SQL Server 2008 Standard via ODBC using FreeTDS Drivers

Filed under: microsoft, ODBC, perl, sql — lancevermilion @ 2:30 pm

Perl to Microsoft SQL Server 2008 Standard via ODBC using FreeTDS

Today I had a need to have a perl script (running on CentOS 5.4) connect to a MSSQL Server 2008 Std server so i had to do a little research and playing around. The solution to getting everything working with “Free/OpenSource” stuff was not difficult if you don’t follow everything that everyone publishes.

I have provided the steps I used below to get everything working.

Updated step 5 on Sep 11, 2012 with a note that reflects the findings of  user xtruthx.

Pre-requisites

Before you start you need to ensure you know how to satisfy all the RPMs in the pre-requisites.
Location from where you can get the RPMs is listed in parentheses ().

  1. RPMs Needed/used:
    perl - 5.8.8-10 (Yum)
    perl-DBI - 1.52-1 (Yum)
    freetds - 0.64-11 (Yum)
    unixODBC-devel - 2.2.11.7.1 (Yum)
    unixODBC - 2.2.11.7.1 (Yum)
    perl-DBD-ODBC - 1.23-1 (http://pkgs.repoforge.org/perl-DBD-ODBC/perl-DBD-ODBC-1.23-1.el5.rf.i386.rpm)
    

Steps to get MSSQL,ODBC and Perl working as one happy product.

  1. How did I get ODBC setup?
    Install freetds, unixODBC, unixODBC-devel via Yum

    sudo yum install freetds unixODBC unixODBC-devel
    

    Then install the perl, perl-DBI if you don’t have them installed already.

    sudo yum install perl perl-DBI
    

    If you haven’t downloaded the perl-DBD-ODBC module you can do so using wget/curl/etc. I prefer wget.
    Then install the perl, perl-DBI if you don’t have them installed already.

    wget http://pkgs.repoforge.org/perl-DBD-ODBC/perl-DBD-ODBC-1.23-1.el5.rf.i386.rpm
    

    Then install the perl-DBD-ODBC module. I am assuming the perl-DBD-ODBC is in the same directory you are working in. If not you will need to provide a complete path to the rpm.

    sudo rpm -ivh perl-DBD-ODBC
    
  2. DBD::ODBC We used DBD::ODBC. You can use similar methods as above to determine if DBD::ODBC is installed and to see what version you have:To check you have the DBD::ODBC module installed:
    perl -e 'use DBD::ODBC;'
    

    If you have not got DBD::ODBC installed you can build it via CPAN or download the RPM and go from there. I just downloaded it, see the RPM list at the top of the article.To show the DBD::ODBC version:

    perl -MDBD::ODBC -e 'print $DBD::ODBC::VERSION;'
    

    e.g.

    perl -MDBD::ODBC -e 'print $DBD::ODBC::VERSION;'
    1.23
    

    To show all drivers DBI knows about and their versions:

    perl -MDBI -e 'DBI->installed_versions;'
    

    e.g.

    perl -MDBI -e 'DBI->installed_versions;'
      Perl            : 5.008008    (i386-linux-thread-multi)
      OS              : linux       (2.6.9-42.0.3.elsmp)
      DBI             : 1.52
      DBD::Sponge     : 11.10
      DBD::Proxy      : install_driver(Proxy) failed: Can't locate RPC/PlClient.pm in @INC
      DBD::ODBC       : 1.23
      DBD::File       : 0.35
      DBD::ExampleP   : 11.12
      DBD::DBM        : 0.03
    
  3. What ODBC drivers have I got?
    You can find out what ODBC drivers are installed under unixODBC with:

    odbcinst -q -d
    

    e.g.

    odbcinst -q -d
    [PostgreSQL]
    

    For unixODBC, drivers are installed in the odbcinst.ini file. You can find out which odbcinst.ini file unixODBC is using with:

    odbcinst -j
    

    e.g.

    odbcinst -j
    unixODBC 2.2.11
    DRIVERS............: /etc/odbcinst.ini
    SYSTEM DATA SOURCES: /etc/odbc.ini
    
  4. Here, /etc/odbcinst.ini defines the ODBC drivers. Configure unixODBC to use FreeTDS as the Driver for the MSSQL connection.
    First we need to locate the driver file.

    sudo updatedb
    locate libtdso
    

    e.g.

    sudo updatedb
    locate libtdso
    /usr/lib/libtdsodbc.so.0
    /usr/lib/libtdsodbc.so.0.0.0
    

    Now we know where the source files are so lets create a driver template to use for driver installation.
    You can use vi if you want, but to make sure people can copy/paste as much as possible I have provided an echo command below.
    Adjust the path and possibly filename for “/usr/lib/libtdsodbc.so.0”.
    Note: Only use the driver that has a single 0 if there is more than one returned like my example.

    echo "[FreeTDS]
    Driver = /usr/lib/libtdsodbc.so.0" >> tds.driver.template
    

    Now lets install the driver from the template. This will install the driver so anyone can use this driver.

    sudo odbcinst -i -d -f tds.driver.template
    

    e.g.

    sudo odbcinst -i -d -f tds.driver.template
    odbcinst: Driver installed. Usage count increased to 1.
        Target directory is /etc
    

    If you check to see what drivers are available to ODBC you will now see “FreeTDS” has been added.

    odbcinst -q -d
    

    e.g.

    odbcinst -q -d
    [PostgreSQL]
    [FreeTDS]
    
  5. Configure ODBC with MSSQL parameters.
    To do this we need to modify the /etc/odbc.ini file.
    Your odbc.ini file could be in a different location. use odbcinst -j to location your ini file.
    You need to adjust the values accordingly for the echo command to work for your install.
    You will want to be root to do the file modification. I jump to root by way of sudo su -.
    Note:You will need a SQL user account setup in MSSQL to allow you to connect remotely with the way I am showing you.Note: A user (xtruthx) has reported that “TDS Version” needed an underscore in order to work for his setup. The user used “TDS_Version = 8.0” instead of what is in the example below.

    sudo su -
    echo "[MSSQL]
    Driver = FreeTDS
    Address = IPADDRESSOFMSSQL
    Port = 1433
    TDS Version = 8.0
    Database = MYDATABASENAME" >> /etc/odbc.ini
    

    e.g.

    sudo su -
    echo "[MSSQL]
    Driver = FreeTDS
    Address = 192.168.10.1
    Port = 1433
    TDS Version = 8.0
    Database = Northwind" >> /etc/odbc.ini
    
  6. Test the ODBCconnect to your MSSQL database.
    isql -v -s MSSQL SQLUSERNAME SQLUSERPASSWORD
    +---------------------------------------+
    | Connected!                            |
    |                                       |
    | sql-statement                         |
    | help [tablename]                      |
    | quit                                  |
    |                                       |
    +---------------------------------------+
    SQL>
    
  7. If the step above was successful then lets try using a Perl script.
    Note: Below I specify DSN=MSSQL, that should match the name in [ ] in your odbc.ini file.
    You will also want to change SQLUSERNAME and SQLUSERNAMEPASSWORD to your username/password needed to connect to MSSQL using SQL username/password.
    This is NOT windows authentication.

    #!/usr/bin/perl
    use DBI;
    use strict;
    use DBI;
    my @dsns = DBI->data_sources('ODBC');
    foreach my $d (@dsns)
    {
      print "$d\n";
    }
      my $dbh = DBI-> connect('dbi:ODBC:DSN=MSSQL;UID=SQLUSERNAME;PWD=SQLUSERPASSWORD') or die "CONNECT ERROR! :: $DBI::err $DBI::errstr $DBI::state $!\n";
    if ($dbh)
    {
      print "There is a connection\n";
      my $sql = q/SELECT * FROM dbo.users/;
      my $sth = $dbh->prepare($sql);
      $sth->execute();
      my @row;
      while (@row = $sth->fetchrow_array) {  # retrieve one row at a time
        print join(", ", @row), "\n";
      }
      $dbh->disconnect;
    }
    

External Reference links used to get everything working.

http://www.unixodbc.org/doc/FreeTDS.html
http://www.martin-evans.me.uk/node/20
http://www.easysoft.com/developer/languages/perl/dbi_dbd_odbc.html
http://www.easysoft.com/developer/languages/perl/dbd_odbc_tutorial_part_1.html
http://www.easysoft.com/developer/languages/perl/dbd_odbc_tutorial_part_2.html
http://www.easysoft.com/developer/languages/perl/sql_server_unix_tutorial.html
http://www.easysoft.com/developer/languages/perl/tutorial_data_web.html
http://www.easysoft.com/developer/languages/perl/dbi-debugging.html

October 3, 2011

REDCOM DCT Translation Tester using net.db (100% offline)

Filed under: perl, REDCOM — lancevermilion @ 2:23 pm

The other day I shared my script on how to parse Dial Code Tables (DCT) if took the time to convert them to CSV. Well after thinking about it this morning I made a quick change to my code to read in the net.db file (ascii copy of the database) and process routing that way.

Update: I found some coding errors, removed the utilization of external shell commands, and added strict usage.

Redcom version 4.0 R1P1

The Code:

#!/usr/bin/perl
# Author:  Lance Vermilion
# Purpose: Walk through Redcom Dial Code Tables and determine
#          what entry the digits would hit if it was ran
#          through a Redcom.
# Script:  dct.pl
# Date:    10/4/2011
# Rev:     0.4
# Syntax:  dct.pl
# Example: dct.pl dct0 4352348763
#################################################################

#################################################################
# Instructions:
# Downlaod the binary configuration to a ascii format on the
# Redcom.
# rsh /tmp> xld downl;over=yes;downl;exit;log
# Cat the net.db and copy/paste this in a local net.db file in the
# same folder as dct.pl
# cat /sys/net.db
# dct.pl will parse net.db and preform all the work needed just
# as if it was being processed through the Redcom.
#################################################################

#################################################################
# Not supported yet
# TYPE (other than dct, rte, int, stn, sup)
# SC
# PRE  (does support any variation of ac- ac+)
# POS  (does support any variation of ac- ac+)
# MARK (does support any variation of ac- ac+)
# Next (Only jumps to that dct)
# SB
# SST
# TID
#
# Pattern that uses a # in the pattern
#################################################################

use strict;
use Carp;
use Data::Dumper;

my $dctnumber = "$ARGV[0]";
my $dialeddigits = "$ARGV[1]";
my $file = "net.db";

# DCT to be used that is passed by commandline
my $hash_ref = {};
print "Reading \"$file\" file: ";
if ( -f "$file" )
{
  print "[OK]\n";
}
else
{
  print "[FAILED]\n";
  croak "File: \"$file\" does not exist. :: $!\n";
}

# File net.db exists slurp it to an array
open(FH, "$file" ) or die "Could not open $file\n";
my @netdbarr = ;

sub help()
{
  print "Syntax:  dct.pl  \n";
  print "Example: dct.pl dct0 4352348763\n";
  exit;
}

if ( scalar(@ARGV) ne 2 )
{
  print "You didn't provide enough variables\n"
  &help();
}

&buildDCThash();
&processDCThash($dctnumber,$dialeddigits,0,0,0);

# Sub-routine to print DCT
sub printdct ($$$$$$$$)
{
  my $printent  = shift;
  my $printpatt = shift;
  my $printsc   = shift;
  my $printtype = shift;
  my $printval  = shift;
  my $printpre  = shift;
  my $printpos  = shift;
  my $printmark = shift;
  my $printnext = shift;
  my $printsb = shift;
  my $printsst = shift;
  my $printtid = shift;

  print "ENTRY PATTERN         SC TYPE VAL PRE POS MARK NEXT SB/SNU  SST/NST  TID    \n";
format DCTREPORT =
@<<<< @<<<<<<<<<<<<<< @< @<<< @<< @<< @<< @<<< @<<< @<<<<<  @<<<<<<  @<< $printent $printpatt $printsc $printtype $printval $printpre $printpos $printmark $printnext $printsb $printsst $printtid .   $~ = 'DCTREPORT';   write; } # Sub-routine to build our hash sub buildDCThash() {   my $curdct = '';   my $curgrp = '';   my $currte = '';   for my $netdbline (@netdbarr)   {     if ( $netdbline =~ /^_dcta\[ (\d+) \] = (.*)/ )     {       $curdct = "dct$1";       my ($dctname, $dctqty, undef, undef, undef, undef, $dcttoneable, undef, $dctdialtimer) = split(/,/, $2);       $hash_ref->{'dct'}->{$curdct}->{'name'} = $dctname;
      $hash_ref->{'dct'}->{$curdct}->{'qty'} = $dctqty;
      $hash_ref->{'dct'}->{$curdct}->{'tonable'} = $dcttoneable;
      $hash_ref->{'dct'}->{$curdct}->{'dtimer'} = $dctdialtimer;
    }

    $netdbline =~ s/,252,/,,/g if $netdbline =~ /^_dctm/; #252 equals blank
    $netdbline =~ s/220/ac/g if $netdbline =~ /^_dctm/;   #220 equals ac
    if ( $netdbline =~ /^_dctm\[ (\d+) \] = (.*)/ )
    {
      my $ent=$1;
      my ($patt, $type, $val, $next, $sc, $pre, $pos, $mark, $sb, undef, $sst, undef, $tid) = split(/,/, $2);
      $patt = '-default-' if $ent eq 0;  # net.db stored a blank entry for entry 0 aka -default- so we hard set the value.
      $hash_ref->{'dct'}->{$curdct}->{'entries'}->{$ent}->{'origpatt'} = $patt;
      $patt = 'NULL_PATTERN' if $patt eq '';
      $patt =~ s/n/[2-9]/g;
      $patt =~ s/x/[0-9]/g;
      $patt =~ s/q/[0-4]/g;
      $patt =~ s/Q/[5-9]/g;
      $patt =~ s/X/[2-8]/g;
      $patt =~ s/\~/\\d+/g;
      $patt =~ s/\*/\\*/g;
      $patt =~ s/\#/\\#/g;
      $patt =~ s/\?/[0-9]/g;
      $patt =~ s/w//g;
      $hash_ref->{'dct'}->{$curdct}->{'entries'}->{$ent}->{'patt'} = $patt;
      $hash_ref->{'dct'}->{$curdct}->{'entries'}->{$ent}->{'sc'}   = $sc;
      $hash_ref->{'dct'}->{$curdct}->{'entries'}->{$ent}->{'type'} = $type;
      $hash_ref->{'dct'}->{$curdct}->{'entries'}->{$ent}->{'val'}  = $val;
      $hash_ref->{'dct'}->{$curdct}->{'entries'}->{$ent}->{'pre'}  = $pre;
      $hash_ref->{'dct'}->{$curdct}->{'entries'}->{$ent}->{'pos'}  = $pos;
      $hash_ref->{'dct'}->{$curdct}->{'entries'}->{$ent}->{'mark'} = $mark;
      $hash_ref->{'dct'}->{$curdct}->{'entries'}->{$ent}->{'next'} = $next;
      $hash_ref->{'dct'}->{$curdct}->{'entries'}->{$ent}->{'sb'} = $sb;
      $hash_ref->{'dct'}->{$curdct}->{'entries'}->{$ent}->{'sst'} = $sst;
      $tid =~ s/65535//;   # similar to VAL, except that the final value 65535 would be reserved for the "blank" case)
      $hash_ref->{'dct'}->{$curdct}->{'entries'}->{$ent}->{'tid'} = $tid;
    }

    #
    # INCLUDE ROUTE AND GROUP INFORMATION
    #
    if ( $netdbline =~ /^_grpatt\[ (\d+), 1 \] = (.*)/ )
    {
      $curgrp = $1;
      my ( $type1,undef,undef,$grpname,undef,undef,undef ) = split(/,/, $2);
      #print "$group $type1 $grpname\n";
      $hash_ref->{'grp'}->{$curgrp}->{'group'} = $curgrp;
      $hash_ref->{'grp'}->{$curgrp}->{'type1'} = $type1;
      $hash_ref->{'grp'}->{$curgrp}->{'grpname'} = $grpname;
    }

    if ( $netdbline =~ /^_grpatt\[ (\d+), 3 \] = (.*)/ )
    {
      if ( $curgrp eq $1 )
     {
        my ( $type3,$grptype,undef,undef,undef,undef,undef,undef,undef) = split(/,/, $2);
        #print "$group,$type3,$grptype\n";
        $hash_ref->{'grp'}->{$curgrp}->{'type3'} = $type3;
        $hash_ref->{'grp'}->{$curgrp}->{'grptype'} = $grptype;
      }
    }

    my $currte = '';
    if ( $netdbline =~ /^route\[ (\d+), 1 \] = (.*)/ )
    {
      $currte = "rte$1";
      my ( $prefix_digits,undef,undef,undef,$rtename,$alt1,$alt2,$alt3,undef,undef,undef,undef,$catid,undef,undef,undef,undef,undef,undef,undef,$comp,undef,undef,undef,undef,$groupnum,undef,undef,undef,undef,undef,undef,undef ) = split(/,/, $2);
      $comp =~ s/0x0/off/g;
      $comp =~ s/0x40/on/g;
      #print "$route,$prefix_digits,$rtename,$alt1,$alt2,$alt3,$comp,$groupnum\n";
      $hash_ref->{'rte'}->{$currte}->{'prefix_digits'} = $prefix_digits;
      $hash_ref->{'rte'}->{$currte}->{'rtename'} = $rtename;
      $hash_ref->{'rte'}->{$currte}->{'alt1'} = $alt1;
      $hash_ref->{'rte'}->{$currte}->{'alt2'} = $alt2;
      $hash_ref->{'rte'}->{$currte}->{'alt3'} = $alt3;
      $hash_ref->{'rte'}->{$currte}->{'comp'} = $comp;
      $hash_ref->{'rte'}->{$currte}->{'groupnum'} = $groupnum;
    }
  }
}

# Sub-routine to process the hash
sub processDCThash($$$$$)
{
# TYPE (DCT type and val (ie. dct6)
# Digits (digits to be processed)
# Pre (digits to delete from begining of the digit string)
# Pos (digits to delete from end of the digit string)
# Mark (pass all digits, but read from n place in the digit string)

  # TYPE from DCT
  my $TYPE = shift;

  # Since we wrap back on our self to walk DCTs we need to make sure we exit on types of int,etc
  if ( $TYPE =~ /^(int|int\d+)/ )
  {
    print "User will be sent to an intercept message\n";
    print "#" x 73 . "\n";
    exit;
  }
  elsif ( $TYPE =~ /^(rte|rte\d+)/ )
  {
    my $tempTYPE = $TYPE;
    $tempTYPE =~ s/rte//g;
    print "Digits will be sent to:\n";
    print "  Primary Route: Route $tempTYPE $hash_ref->{'rte'}->{$TYPE}->{'rtename'}\n";
    print "    Group $hash_ref->{'rte'}->{$TYPE}->{'groupnum'} $hash_ref->{'grp'}->{$hash_ref->{'rte'}->{$TYPE}->{'groupnum'}}->{'grpname'} Type: $hash_ref->{'grp'}->{$hash_ref->{'rte'}->{$TYPE}->{'groupnum'}}->{'type1'},$hash_ref->{'grp'}->{$hash_ref->{'rte'}->{$TYPE}->{'groupnum'}}->{'type3'}\n";
    print "    Inserted Prefix Digits: $hash_ref->{'rte'}->{$TYPE}->{'prefix_digits'}\n" if $hash_ref->{'rte'}->{$TYPE}->{'prefix_digits'} ne '';
    if ( $hash_ref->{'rte'}->{$TYPE}->{'alt1'} ne 0 )
    {
      my $tmpalt1rte = "rte" . $hash_ref->{'rte'}->{$TYPE}->{'alt1'};
      my $tmpalt1grp = $hash_ref->{'rte'}->{$tmpalt1rte}->{'groupnum'};
      print "  Alternate Route #1: Route $hash_ref->{'rte'}->{$TYPE}->{'alt1'} $hash_ref->{'rte'}->{$tmpalt1rte}->{'rtename'}\n";
      print "    Group $tmpalt1grp $hash_ref->{'grp'}->{$tmpalt1grp}->{'grpname'} Type: $hash_ref->{'grp'}->{$tmpalt1grp}->{'type1'},$hash_ref->{'grp'}->{$tmpalt1grp}->{'type3'}\n";
      print "    Inserted Prefix Digits: $hash_ref->{'rte'}->{$tmpalt1rte}->{'prefix_digits'}\n" if $hash_ref->{'rte'}->{$tmpalt1rte}->{'prefix_digits'} ne '';
    }
    if ( $hash_ref->{'rte'}->{$TYPE}->{'alt2'} ne 0 )
    {
      my $tmpalt2rte = "rte" . $hash_ref->{'rte'}->{$TYPE}->{'alt2'};
      my $tmpalt2grp = $hash_ref->{'rte'}->{$tmpalt2rte}->{'groupnum'};
      print "  Alternate Route #2: Route $hash_ref->{'rte'}->{$TYPE}->{'alt2'} $hash_ref->{'rte'}->{$tmpalt2rte}->{'rtename'}\n";
      print "    Group $tmpalt2grp $hash_ref->{'grp'}->{$tmpalt2grp}->{'grpname'} Type: $hash_ref->{'grp'}->{$tmpalt2grp}->{'type1'},$hash_ref->{'grp'}->{$tmpalt2grp}->{'type3'}\n";
      print "    Inserted Prefix Digits: $hash_ref->{'rte'}->{$tmpalt2rte}->{'prefix_digits'}\n" if $hash_ref->{'rte'}->{$tmpalt2rte}->{'prefix_digits'} ne '';
    }
    if ( $hash_ref->{'rte'}->{$TYPE}->{'alt3'} ne 0 )
    {
      my $tmpalt3rte = "rte" . $hash_ref->{'rte'}->{$TYPE}->{'alt3'};
      my $tmpalt3grp = $hash_ref->{'rte'}->{$tmpalt3rte}->{'groupnum'};
      print "  Alternate Route #3: Route $hash_ref->{'rte'}->{$TYPE}->{'alt3'} $hash_ref->{'rte'}->{$tmpalt3rte}->{'rtename'}\n";
      print "    Group $tmpalt3grp $hash_ref->{'grp'}->{$tmpalt3grp}->{'grpname'} Type: $hash_ref->{'grp'}->{$tmpalt3grp}->{'type1'},$hash_ref->{'grp'}->{$tmpalt3grp}->{'type3'}\n";
      print "    Inserted Prefix Digits: $hash_ref->{'rte'}->{$tmpalt3rte}->{'prefix_digits'}\n" if $hash_ref->{'rte'}->{$tmpalt3rte}->{'prefix_digits'} ne '';
    }
    print "#" x 73 . "\n";
    exit;
  }
  elsif ( $TYPE =~ /^(stn|stn\d+)/ )
  {
    print "Digits will be sent to a local station.\n";
    print "#" x 73 . "\n";
    exit;
  }

  # Account for the fact the user may not provide dct6 and may provide something else.
  if ( $TYPE !~ /^dct\d+$/ )
  {
    print "Error: The Dial Code Table (DCT) you want to start at must be in this format.\n";
    print "       dct\n";
    print "       Example: dct0\n";
    my $loop = 0;
    until ( $TYPE =~ /^dct\d+$/ )
    {
      print "Re-Enter your DCT: ";
      chomp($TYPE = );
      $loop++;
      if ($loop >= 3)
      {
        print "Exiting!!! You failed to enter the DCT correctly 3 times.\n";
        exit;
      }
    }
  }

  # numbers dialed
  my $digits = shift;
  chomp($digits);

  # Adjust digits based on pre, pos, and mark
  my $pre = shift;
  my $pos = shift;
  my $mark = shift;
  $digits = substr($digits, $pre)  if ( $pre > 0 );
  $digits = substr($digits, -$pos) if ( $pos > 0 );
  $digits = substr($digits, $mark)  if ( $mark > 0 );

  my $curdct = '';

  # Create a pattern hash keyed by pattern with entry and value
  my $patt_ref = {};
  for my $key ( sort keys %{$hash_ref->{'dct'}->{$TYPE}->{'entries'}} )
  {
    $patt_ref->{$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$key}->{'origpatt'}} = $key;
  }

  print "\n" . "#" x 73 . "\n";
  print "Processing " . length($digits) . " Digit Dialed Number \"$digits\"\n";

  my $charcnt = 0;

  # Print DCT in really short form
  my $tmpTYPE = $TYPE;
  $tmpTYPE =~ s/dct//g;
  print "DCT Number = $tmpTYPE\n";
  print "DCT Name = $hash_ref->{'dct'}->{$TYPE}->{'name'}\n";
  print "DCT Entry Quantity = $hash_ref->{'dct'}->{$TYPE}->{'qty'}\n";
  print "DCT Toneable = $hash_ref->{'dct'}->{$TYPE}->{'tonable'}\n";
  print "DCT Dial Timer = " . $hash_ref->{'dct'}->{$TYPE}->{'dtimer'}/100 . " seconds\n";
  print "=" x 73 . "\n";
  print "ENTRY PATTERN        PATTERN (as seen by Perl)\n";
  for my $key ( sort { $a  $b } keys %{$hash_ref->{'dct'}->{$TYPE}->{'entries'}} )
  {
    printf ("%-5s %-14s %s\n", $key,$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$key}->{'origpatt'},($hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$key}->{'patt'}));
  }
  print "=" x 73 . "\n";

  # Check for an exact match first
  for my $patt_orig (sort keys %$patt_ref)
  {
    my $dctentry = $patt_ref->{$patt_orig};
    my $patt = $hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'patt'};
    if ( $dctentry eq 0 )
    {
      next;
    }
    if ( $digits =~ /^$patt$/ )
    {
      print " * Found exact match!\n";
      &printdct($dctentry,$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'origpatt'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'sc'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'type'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'val'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'pre'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'pos'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'mark'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'next'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'sb'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'sst'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'tid'});
      print "#" x 73 . "\n";
      if ( $hash_ref->{'dct'}->{$dctentry}->{'type'} eq 'sup' )
      {
        print "User will be sent to a DCT equal to the Next field with Supervision\n";
        print "#" x 73 . "\n";
        $hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'type'} = 'dct';
        $hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'val'} = $hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'next'}
      }
      &processDCThash("$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'type'}$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'val'}",$digits,$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'pre'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'pos'},length($patt));
    }
    else
    {
      if ( substr($digits, 0, length($hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'origpatt'})) =~ /^$patt$/ )
      {
        print " * Found DbyD exact match!\n";
        &printdct($dctentry,$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'origpatt'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'sc'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'type'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'val'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'pre'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'pos'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'mark'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'next'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'sb'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'sst'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'tid'});
        print "#" x 73 . "\n";
        if ( $hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'type'} eq 'sup' )
        {
          print "User will be sent to a DCT equal to the Next field with Supervision\n";
          print "#" x 73 . "\n";
          $hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'type'} = 'dct';
          $hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'val'} = $hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'next'}
        }
        &processDCThash("$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'type'}$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'val'}",$digits,$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'pre'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{$dctentry}->{'pos'},length($patt));
      }
    }
  }

  print " * No match using Default.\n";
  &printdct(0,$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{'0'}->{'origpatt'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{'0'}->{'sc'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{'0'}->{'type'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{'0'}->{'val'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{'0'}->{'pre'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{'0'}->{'pos'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{'0'}->{'mark'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{'0'}->{'next'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{'0'}->{'sb'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{'0'}->{'sst'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{'0'}->{'tid'});
  print "#" x 73 . "\n";
  if ( $hash_ref->{'dct'}->{'0'}->{'type'} eq 'sup' )
  {
    print "User will be sent to a DCT equal to the Next field with Supervision\n";
    print "#" x 73 . "\n";
    $hash_ref->{'dct'}->{$TYPE}->{'entries'}->{'0'}->{'type'} = 'dct';
    $hash_ref->{'dct'}->{$TYPE}->{'entries'}->{'0'}->{'val'} = $hash_ref->{'dct'}->{$TYPE}->{'entries'}->{'0'}->{'next'}
  }
  &processDCThash("$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{'0'}->{'type'}$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{'0'}->{'val'}",$digits,$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{'0'}->{'pre'},$hash_ref->{'dct'}->{$TYPE}->{'entries'}->{'0'}->{'pos'},0);
}

# make sure we exit incase we don't make it into the subroutines
exit;

Sample output: Traffic routes to a local station.

Reading "net.db" file: [OK]

#########################################################################
Processing 10 Digit Dialed Number "6235951206"
DCT Number = 0
DCT Name = "Loop Originate"
DCT Entry Quantity = 10
DCT Toneable = dial
DCT Dial Timer = 7 seconds
=========================================================================
ENTRY PATTERN        PATTERN (as seen by Perl)
0     -default-      -default-
1     *              \*
2     #              \#
3     911            911
4     zxxxx          z[0-9][0-9][0-9][0-9]
5     1nxxnxxxxxx    1[2-9][0-9][0-9][2-9][0-9][0-9][0-9][0-9][0-9][0-9]
6     011~w          011\d+
7     011~#          011\d+\#
8     1800nxxxxxx    1800[2-9][0-9][0-9][0-9][0-9][0-9][0-9]
9                    NULL_PATTERN
=========================================================================
 * No match using Default.
ENTRY PATTERN         SC TYPE VAL PRE POS MARK NEXT SB/SNU  SST/NST  TID
0     -default-       0  dct  6   0   0   0         0       0
#########################################################################

#########################################################################
Processing 10 Digit Dialed Number "6235951206"
DCT Number = 6
DCT Name = "NPA Check"
DCT Entry Quantity = 10
DCT Toneable = sil
DCT Dial Timer = 7 seconds
=========================================================================
ENTRY PATTERN        PATTERN (as seen by Perl)
0     -default-      -default-
1     623            623
2     480            480
3     xxx            [0-9][0-9][0-9]
4                    NULL_PATTERN
5                    NULL_PATTERN
6                    NULL_PATTERN
7                    NULL_PATTERN
=========================================================================
 * Found DbyD exact match!
ENTRY PATTERN         SC TYPE VAL PRE POS MARK NEXT SB/SNU  SST/NST  TID
1     623             0  dct  7   0   0   ac        0       0
#########################################################################

#########################################################################
Processing 7 Digit Dialed Number "5951206"
DCT Number = 7
DCT Name = "Switch Code Check"
DCT Entry Quantity = 7
DCT Toneable = sil
DCT Dial Timer = 7 seconds
=========================================================================
ENTRY PATTERN        PATTERN (as seen by Perl)
0     -default-      -default-
1     959            959
2     595            432
3     738            738
4     525            525
5     nxxxxxx        [2-9][0-9][0-9][0-9][0-9][0-9][0-9]
=========================================================================
 * Found DbyD exact match!
ENTRY PATTERN         SC TYPE VAL PRE POS MARK NEXT SB/SNU  SST/NST  TID
2     595             0  dct  8   0   0   ac        0       0
#########################################################################

#########################################################################
Processing 4 Digit Dialed Number "1206"
DCT Number = 8
DCT Name = "Local Numbers"
DCT Entry Quantity = 20
DCT Toneable = sil
DCT Dial Timer = 7 seconds
=========================================================================
ENTRY PATTERN        PATTERN (as seen by Perl)
0     -default-      -default-
1     1155           1155
2     11xx           11[0-9][0-9]
3     12xx           12[0-9][0-9]
4     25xx           25[0-9][0-9]
5     26xx           26[0-9][0-9]
6     93xx           93[0-9][0-9]
7     94xx           94[0-9][0-9]
8     95xx           95[0-9][0-9]
9     xxxx           [0-9][0-9][0-9][0-9]
=========================================================================
 * Found exact match!
ENTRY PATTERN         SC TYPE VAL PRE POS MARK NEXT SB/SNU  SST/NST  TID
3     12xx            0  stn  0   0   0   ac        0       0
#########################################################################
Digits will be sent to a local station.
#########################################################################

Sample Output: Traffic goes out a Trunk to PSTN

Reading "net.db" file: [OK]

#########################################################################
Processing 11 Digit Dialed Number "16134321209"
DCT Number = 0
DCT Name = "Loop Originate"
DCT Entry Quantity = 15
DCT Toneable = dial
DCT Dial Timer = 7 seconds
=========================================================================
ENTRY PATTERN        PATTERN (as seen by Perl)
0     -default-      -default-
1     *              \*
2     #              \#
3     911            911
4     zxxxx          z[0-9][0-9][0-9][0-9]
5     1480nxxxxxx    1480[2-9][0-9][0-9][0-9][0-9][0-9][0-9]
6     1602nxxxxxx    1602[2-9][0-9][0-9][0-9][0-9][0-9][0-9]
7     1623nxxxxxx    1623[2-9][0-9][0-9][0-9][0-9][0-9][0-9]
8     1nxxnxxxxxx    1[2-9][0-9][0-9][2-9][0-9][0-9][0-9][0-9][0-9][0-9]
9     011~w          011\d+
10    011~#          011\d+\#
11    1800nxxxxxx    1800[2-9][0-9][0-9][0-9][0-9][0-9][0-9]
12                   NULL_PATTERN
=========================================================================
 * Found exact match!
ENTRY PATTERN         SC TYPE VAL PRE POS MARK NEXT SB/SNU  SST/NST  TID
8     1nxxnxxxxxx     0  rte  1   0   0   0         0       0
#########################################################################
Digits will be sent to:
  Primary Route: Route 1 "Primary PSTN"
    Group 8 "PRI Span 1/0" Type: trk,trk
  Alternate Route #1: Route 7 "Secondary PSTN"
    Group 6 "PRI Span 1/1" Type: trk,trk
#########################################################################

Blog at WordPress.com.