[freeside-commits] branch FREESIDE_4_BRANCH updated. a7d14a749e808369e22aa1b0026af5bc74225961

Mitch Jackson mitch at freeside.biz
Fri Oct 19 17:00:19 PDT 2018


The branch, FREESIDE_4_BRANCH has been updated
       via  a7d14a749e808369e22aa1b0026af5bc74225961 (commit)
       via  1b4b7af57df5a6b9bbf7c27a63119a431ca4f847 (commit)
       via  f56debe7d5703435e6a3cdd4c4c90b9de2527ae7 (commit)
      from  966183ff11dd1a0b21eac2905118f478b84102c5 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit a7d14a749e808369e22aa1b0026af5bc74225961
Author: Mitch Jackson <mitch at freeside.biz>
Date:   Tue Jul 10 23:30:48 2018 -0500

    RT# 80555 freeside_upgrade for invalid ip addresses

diff --git a/FS/FS/Misc/FixIPFormat.pm b/FS/FS/Misc/FixIPFormat.pm
new file mode 100644
index 000000000..3f9a19bba
--- /dev/null
+++ b/FS/FS/Misc/FixIPFormat.pm
@@ -0,0 +1,124 @@
+package FS::Misc::FixIPFormat;
+use strict;
+use warnings;
+use FS::Record qw(dbh qsearchs);
+use FS::upgrade_journal;
+
+=head1 NAME
+
+FS::Misc::FixIPFormat - Functions to repair bad IP address input
+
+=head1 DESCRIPTION
+
+Provides functions for freeside_upgrade to check IP address storage for
+user-entered leading 0's in IP addresses.  When read from database, NetAddr::IP
+would treat the number as octal isntead of decimal.  If a user entered
+10.0.0.052, this may get invisibly translated to 10.0.0.42 when exported.
+Base8:52 = Base0:42
+
+Tied to freeside_upgrade with journal name TABLE__fixipformat
+
+see: RT# 80555
+
+=head1 SYNOPSIS
+
+Usage:
+
+    # require, not use - this module is only run once
+    require FS::Misc::FixIPFormat;
+
+    my $error = FS::Misc::FixIPFormat::fix_bad_addresses_in_table(
+      'svc_broadband', 'svcnum', 'ip_addr'
+    );
+    die "oh no!" if $error;
+
+=head2 fix_bad_addresses_in_table TABLE, ID_COLUMN, IP_COLUMN
+
+$error = fix_bad_addresses_in_table( 'svc_broadband', 'svcnum', 'ip_addr' );
+
+=cut
+
+sub fix_bad_addresses_in_table {
+  my ( $table ) = @_;
+  return if FS::upgrade_journal->is_done("${table}__fixipformat");
+  for my $id ( find_bad_addresses_in_table( @_ )) {
+    if ( my $error = fix_ip_for_record( $id, @_ )) {
+      die "fix_bad_addresses_in_table(): $error";
+    }
+  }
+  FS::upgrade_journal->set_done("${table}__fixipformat");
+  0;
+}
+
+=head2 find_bad_addresses_in_table TABLE, ID_COLUMN, IP_COLUMN
+
+ at id = find_bad_addresses_in_table( 'svc_broadband', 'svcnum', 'ip_addr' );
+
+=cut
+
+sub find_bad_addresses_in_table {
+  my ( $table, $id_col, $ip_col ) = @_;
+  my @fix_ids;
+
+  # using DBI directly for performance
+  my $sql_statement = "
+    SELECT $id_col, $ip_col
+    FROM $table
+    WHERE $ip_col IS NOT NULL
+  ";
+  my $sth = dbh->prepare( $sql_statement ) || die "SQL ERROR ".dbh->errstr;
+  $sth->execute || die "SQL ERROR ".dbh->errstr;
+  while ( my $row = $sth->fetchrow_hashref ) {
+    push @fix_ids, $row->{ $id_col }
+      if $row->{ $ip_col } =~ /[\.^]0\d/;
+  }
+  @fix_ids;
+}
+
+=head2 fix_ip_for_record ID, TABLE, ID_COLUMN, IP_COLUMN
+
+Attempt to strip the leading 0 from a stored IP address record.  If
+the corrected IP address would be a duplicate of another record in the
+same table, thow an exception.
+
+$error = fix_ip_for_record( 1001, 'svc_broadband', 'svcnum', 'ip_addr', );
+
+=cut
+
+sub fix_ip_for_record {
+  my ( $id, $table, $id_col, $ip_col ) = @_;
+
+  my $row = qsearchs($table, {$id_col => $id})
+    || die "Error finding $table record for id $id";
+
+  my $ip = $row->getfield( $ip_col );
+  my $fixed_ip = join( '.',
+    map{ int($_) }
+    split( /\./, $ip )
+  );
+
+  return undef unless $ip ne $fixed_ip;
+
+  if ( my $dupe_row = qsearchs( $table, {$ip_col => $fixed_ip} )) {
+    if ( $dupe_row->getfield( $id_col ) != $row->getfield( $id_col )) {
+      # Another record in the table has this IP address
+      # Eg one ip is provisioned as 10.0.0.51 and another is
+      # provisioned as 10.0.0.051.  Cannot auto-correct by simply
+      # trimming leading 0.  Die, let support decide how to fix.
+
+      die "Invalid IP address could not be auto-corrected - ".
+          "($table - $id_col = $id, $ip_col = $ip) ".
+           "colission with another reocrd - ".
+           "($table - $id_col = ".$dupe_row->getfield( $id_col )." ".
+           "$ip_col = ",$dupe_row->getfield( $ip_col )." ) - ".
+         "The entry must be corrected to continue";
+    }
+  }
+
+  warn "Autocorrecting IP address problem for ".
+       "($table - $id_col = $id, $ip_col = $ip) $fixed_ip\n";
+  $row->setfield( $ip_col, $fixed_ip );
+  $row->replace;
+}
+
+1;

commit 1b4b7af57df5a6b9bbf7c27a63119a431ca4f847
Author: Mitch Jackson <mitch at freeside.biz>
Date:   Tue Jul 10 23:09:48 2018 -0500

    RT# 80555 freeside_upgrade for invalid ip addresses

diff --git a/FS/FS/Upgrade.pm b/FS/FS/Upgrade.pm
index f998a816e..4e0e5c085 100644
--- a/FS/FS/Upgrade.pm
+++ b/FS/FS/Upgrade.pm
@@ -526,6 +526,20 @@ sub upgrade_data {
 
     #upgrade part_event_condition_option agentnum to a multiple hash value
     'part_event_condition_option' =>[],
+
+    #fix ip format
+    'svc_circuit' => [],
+
+    #fix ip format
+    'svc_hardware' => [],
+
+    #fix ip format
+    'svc_pbx' => [],
+
+    #fix ip format
+    'tower_sector' => [],
+
+
   ;
 
   \%hash;
@@ -736,4 +750,3 @@ Sure.
 =cut
 
 1;
-
diff --git a/FS/FS/svc_broadband.pm b/FS/FS/svc_broadband.pm
index 583030e1d..02136c594 100755
--- a/FS/FS/svc_broadband.pm
+++ b/FS/FS/svc_broadband.pm
@@ -515,6 +515,11 @@ sub _upgrade_data {
     #next SVC;
   }
 
+  require FS::Misc::FixIPFormat;
+  FS::Misc::FixIPFormat::fix_bad_addresses_in_table(
+      'svc_broadband', 'svcnum', 'ip_addr',
+  );
+
   '';
 }
 
diff --git a/FS/FS/svc_circuit.pm b/FS/FS/svc_circuit.pm
index 7f49715b9..7f2ef807c 100644
--- a/FS/FS/svc_circuit.pm
+++ b/FS/FS/svc_circuit.pm
@@ -236,6 +236,17 @@ sub search_sql_addl_from {
   'LEFT JOIN circuit_type USING ( typenum )';
 }
 
+sub _upgrade_data {
+
+  require FS::Misc::FixIPFormat;
+  FS::Misc::FixIPFormat::fix_bad_addresses_in_table(
+      'svc_circuit', 'svcnum', 'endpoint_ip_addr',
+  );
+
+  '';
+
+}
+
 =back
 
 =head1 SEE ALSO
@@ -245,4 +256,3 @@ L<FS::Record>
 =cut
 
 1;
-
diff --git a/FS/FS/svc_hardware.pm b/FS/FS/svc_hardware.pm
index 4bff483e1..019a5646c 100644
--- a/FS/FS/svc_hardware.pm
+++ b/FS/FS/svc_hardware.pm
@@ -245,6 +245,17 @@ sub display_hw_addr {
     join(':', $self->hw_addr =~ /../g) : $self->hw_addr)
 }
 
+sub _upgrade_data {
+
+  require FS::Misc::FixIPFormat;
+  FS::Misc::FixIPFormat::fix_bad_addresses_in_table(
+      'svc_hardware', 'svcnum', 'ip_addr',
+  );
+
+  '';
+
+}
+
 =back
 
 =head1 SEE ALSO
@@ -254,4 +265,3 @@ L<FS::Record>, L<FS::svc_Common>, schema.html from the base documentation.
 =cut
 
 1;
-
diff --git a/FS/FS/svc_pbx.pm b/FS/FS/svc_pbx.pm
index a5e181d9d..b0f6e8d98 100644
--- a/FS/FS/svc_pbx.pm
+++ b/FS/FS/svc_pbx.pm
@@ -387,6 +387,17 @@ sub sum_cdrs {
   qsearchs ( $psearch->{query} );
 }
 
+sub _upgrade_data {
+
+  require FS::Misc::FixIPFormat;
+  FS::Misc::FixIPFormat::fix_bad_addresses_in_table(
+      'svc_pbx', 'svcnum', 'ip_addr',
+  );
+
+  '';
+
+}
+
 =back
 
 =head1 BUGS
@@ -399,4 +410,3 @@ L<FS::cust_pkg>, schema.html from the base documentation.
 =cut
 
 1;
-
diff --git a/FS/FS/tower_sector.pm b/FS/FS/tower_sector.pm
index 9f5b142a6..e2dad1b76 100644
--- a/FS/FS/tower_sector.pm
+++ b/FS/FS/tower_sector.pm
@@ -327,6 +327,17 @@ sub process_generate_coverage {
   die $error if $error;
 }
 
+sub _upgrade_data {
+
+  require FS::Misc::FixIPFormat;
+  FS::Misc::FixIPFormat::fix_bad_addresses_in_table(
+      'tower_sector', 'sectornum', 'ip_addr',
+  );
+
+  '';
+
+}
+
 =head1 BUGS
 
 =head1 SEE ALSO

commit f56debe7d5703435e6a3cdd4c4c90b9de2527ae7
Author: Mitch Jackson <mitch at freeside.biz>
Date:   Sun Jul 8 23:15:20 2018 -0500

    RT# 80555 Sanitize leading 0's from ip addr input

diff --git a/FS/FS/IP_Mixin.pm b/FS/FS/IP_Mixin.pm
index 3ec769313..0b138dd21 100644
--- a/FS/FS/IP_Mixin.pm
+++ b/FS/FS/IP_Mixin.pm
@@ -94,6 +94,15 @@ sub ip_check {
     $self->ip_addr('');
   }
 
+  # strip user-entered leading 0's from IPv4 addresses
+  # Parsers like NetAddr::IP interpret them as octal instead of decimal
+  $self->ip_addr(
+    join( '.', (
+        map{ int($_) }
+        split( /\./, $self->ip_addr )
+    ))
+  ) if $self->ip_addr =~ /\./ && $self->ip_addr =~ /[\.^]0/;
+
   if ( $self->ip_addr
        and !$self->router
        and $self->conf->exists('auto_router') ) {
diff --git a/FS/FS/Record.pm b/FS/FS/Record.pm
index c790ec01c..2a4a200fa 100644
--- a/FS/FS/Record.pm
+++ b/FS/FS/Record.pm
@@ -2882,11 +2882,9 @@ to 127.0.0.1.
 sub ut_ip {
   my( $self, $field ) = @_;
   $self->setfield($field, '127.0.0.1') if $self->getfield($field) eq '::1';
-  $self->getfield($field) =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/
-    or return "Illegal (IP address) $field: ". $self->getfield($field);
-  for ( $1, $2, $3, $4 ) { return "Illegal (IP address) $field" if $_ > 255; }
-  $self->setfield($field, "$1.$2.$3.$4");
-  '';
+  return "Illegal (IP address) $field: ".$self->getfield($field)
+    unless $self->getfield($field) =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
+  $self->ut_ip46($field);
 }
 
 =item ut_ipn COLUMN
@@ -2914,7 +2912,17 @@ Check/untaint IPv4 or IPv6 address.
 
 sub ut_ip46 {
   my( $self, $field ) = @_;
-  my $ip = NetAddr::IP->new($self->getfield($field))
+  my $ip_addr = $self->getfield( $field );
+
+  # strip user-entered leading 0's from IPv4 addresses
+  # Parsers like NetAddr::IP interpret them as octal instead of decimal
+  $ip_addr = join( '.', (
+        map{ int($_) }
+        split( /\./, $ip_addr )
+    )
+  ) if $ip_addr =~ /\./ && $ip_addr =~ /[\.^]0/;
+
+  my $ip = NetAddr::IP->new( $ip_addr )
     or return "Illegal (IP address) $field: ".$self->getfield($field);
   $self->setfield($field, lc($ip->addr));
   return '';
diff --git a/FS/FS/tower_sector.pm b/FS/FS/tower_sector.pm
index e4996f3aa..9f5b142a6 100644
--- a/FS/FS/tower_sector.pm
+++ b/FS/FS/tower_sector.pm
@@ -154,7 +154,7 @@ sub check {
     $self->ut_numbern('sectornum')
     || $self->ut_number('towernum', 'tower', 'towernum')
     || $self->ut_text('sectorname')
-    || $self->ut_textn('ip_addr')
+    || $self->ut_ip46n('ip_addr')
     || $self->ut_floatn('height')
     || $self->ut_numbern('freq_mhz')
     || $self->ut_numbern('direction')
@@ -336,4 +336,3 @@ L<FS::tower>, L<FS::Record>, schema.html from the base documentation.
 =cut
 
 1;
-

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/IP_Mixin.pm         |   9 ++++
 FS/FS/Misc/FixIPFormat.pm | 124 ++++++++++++++++++++++++++++++++++++++++++++++
 FS/FS/Record.pm           |  20 +++++---
 FS/FS/Upgrade.pm          |  15 +++++-
 FS/FS/svc_broadband.pm    |   5 ++
 FS/FS/svc_circuit.pm      |  12 ++++-
 FS/FS/svc_hardware.pm     |  12 ++++-
 FS/FS/svc_pbx.pm          |  12 ++++-
 FS/FS/tower_sector.pm     |  14 +++++-
 9 files changed, 211 insertions(+), 12 deletions(-)
 create mode 100644 FS/FS/Misc/FixIPFormat.pm




More information about the freeside-commits mailing list