[Rt-commit] rt branch, ip-customfields, updated. rt-3.8.8-668-ge24a55b

? sunnavy sunnavy at bestpractical.com
Wed Sep 15 01:05:34 EDT 2010


The branch, ip-customfields has been updated
       via  e24a55bbde5802e34006044dad7f067d31f9448e (commit)
       via  1e5673be23115ee6fd2c17c7f8980e9d405ffdde (commit)
       via  ccdbeba431253e26f03a5f37483ee99c98a7c7c7 (commit)
      from  32afb860c09e726b06505c730a106cc0a5b0b23b (commit)

Summary of changes:
 lib/RT/ObjectCustomFieldValue_Overlay.pm |   58 +++++++-
 lib/RT/Tickets_Overlay.pm                |   13 +-
 sbin/rt-test-dependencies.in             |    1 +
 share/html/Elements/ValidateCustomFields |    3 +-
 t/customfields/ip.t                      |   30 ++--
 t/customfields/ipv6.t                    |  250 ++++++++++++++++++++++++++++++
 6 files changed, 329 insertions(+), 26 deletions(-)
 create mode 100644 t/customfields/ipv6.t

- Log -----------------------------------------------------------------
commit ccdbeba431253e26f03a5f37483ee99c98a7c7c7
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Wed Sep 15 13:06:49 2010 +0800

    ipv6 support for IPAddress

diff --git a/lib/RT/ObjectCustomFieldValue_Overlay.pm b/lib/RT/ObjectCustomFieldValue_Overlay.pm
index 54970d3..e0b356c 100644
--- a/lib/RT/ObjectCustomFieldValue_Overlay.pm
+++ b/lib/RT/ObjectCustomFieldValue_Overlay.pm
@@ -52,6 +52,7 @@ use strict;
 use warnings;
 use RT::Interface::Web;
 use Regexp::Common qw(RE_net_IPv4);
+use Regexp::IPv6 qw($IPv6_re);
 use Regexp::Common::net::CIDR;
 require Net::CIDR;
 
@@ -77,17 +78,16 @@ sub Create {
     $cf_as_sys->Load($args{'CustomField'});
 
     if($cf_as_sys->Type eq 'IPAddress') {
+        if ( $args{'Content'} ) {
+            $args{'Content'} = $self->ParseIP( $args{'Content'} );
+        }
+
         unless ( defined $args{'Content'} ) {
             return
               wantarray
               ? ( 0, $self->loc("Content can't be empty for IPAddress") )
               : 0;
         }
-
-        if ( $args{'Content'} =~ /^\s*$RE{net}{IPv4}\s*$/o ) {
-            $args{'Content'} = sprintf "%03d.%03d.%03d.%03d", split /\./,
-              $args{'Content'};
-        }
     }
 
     if($cf_as_sys->Type eq 'IPAddressRange') {
@@ -423,4 +423,52 @@ sub ParseIPRange {
     return $sIP, $eIP;
 }
 
+sub ParseIP {
+    my $self = shift;
+    my $value = shift or return;
+    $value = lc $value;
+    $value =~ s!^\s+!!;
+    $value =~ s!\s+$!!;
+
+    if ( $value =~ /^($RE{net}{IPv4})$/o ) {
+        return sprintf "%03d.%03d.%03d.%03d", split /\./, $1;
+    }
+    elsif ( $value =~ /^$IPv6_re$/ ) {
+
+        # up_fields are before '::'
+        # low_fields are after '::' but without v4
+        # v4_fields are the v4
+        my ( @up_fields, @low_fields, @v4_fields );
+        my $v6;
+        if ( $value =~ /(.*:)(\d+\..*)/ ) {
+            ( $v6, my $v4 ) = ( $1, $2 );
+            chop $v6 unless $v6 =~ /::$/;
+            while ( $v4 =~ /(\d+)\.(\d+)/g ) {
+                push @v4_fields, sprintf '%.2x%.2x', $1, $2;
+            }
+        }
+        else {
+            $v6 = $value;
+        }
+
+        my ( $up, $low );
+        if ( $v6 =~ /::/ ) {
+            ( $up, $low ) = split /::/, $v6;
+        }
+        else {
+            $up = $v6;
+        }
+
+        @up_fields = split /:/, $up;
+        @low_fields = split /:/, $low if $low;
+
+        my @zero_fields =
+          ('0000') x ( 8 - @v4_fields - @up_fields - @low_fields );
+        my @fields = ( @up_fields, @zero_fields, @low_fields, @v4_fields );
+
+        return join ':', map { sprintf "%.4x", hex "0x$_" } @fields;
+    }
+    return;
+}
+
 1;
diff --git a/lib/RT/Tickets_Overlay.pm b/lib/RT/Tickets_Overlay.pm
index 58b6e4d..738892c 100755
--- a/lib/RT/Tickets_Overlay.pm
+++ b/lib/RT/Tickets_Overlay.pm
@@ -1380,11 +1380,14 @@ sub _CustomFieldLimit {
         return $op;
     };
 
-    if (   $cf
-        && $cf->Type eq 'IPAddress'
-        && $value =~ /^\s*$RE{net}{IPv4}\s*$/o )
-    {
-        $value = sprintf "%03d.%03d.%03d.%03d", split /\./, $value;
+    if ( $cf && $cf->Type eq 'IPAddress' ) {
+        my $parsed = RT::ObjectCustomFieldValue->ParseIP($value);
+        if ($parsed) {
+            $value = $parsed;
+        }
+        else {
+            $RT::Logger->warn("$value is not a valid IPAddress");
+        }
     }
 
     if (   $cf
diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index 7fb4dcb..f9a9a39 100755
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -207,6 +207,7 @@ Devel::StackTrace 1.19
 Text::Password::Pronounceable
 Net::CIDR
 Regexp::Common::net::CIDR
+Regexp::IPv6
 .
 
 $deps{'MASON'} = [ text_to_hash( << '.') ];
diff --git a/share/html/Elements/ValidateCustomFields b/share/html/Elements/ValidateCustomFields
index 15b14e5..17f0d0e 100644
--- a/share/html/Elements/ValidateCustomFields
+++ b/share/html/Elements/ValidateCustomFields
@@ -85,7 +85,8 @@ while ( my $CF = $CustomFields->Next ) {
         if ($value) {
             if ( $CF->Type eq 'IPAddress' ) {
                 use Regexp::Common qw(RE_net_IPv4);
-                unless ( $value =~ /^$RE{net}{IPv4}$/ ) {
+                my $ip = RT::ObjectCustomFieldValue->ParseIP( $value );
+                unless ( $ip ) {
                     my $msg =
                       loc( "Input can not be parsed to " . loc( $CF->Type ) );
                     $m->notes( ( 'InvalidField-' . $CF->Id ) => $msg );

commit 1e5673be23115ee6fd2c17c7f8980e9d405ffdde
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Wed Sep 15 13:07:03 2010 +0800

    ipv6.t

diff --git a/t/customfields/ipv6.t b/t/customfields/ipv6.t
new file mode 100644
index 0000000..e64dd28
--- /dev/null
+++ b/t/customfields/ipv6.t
@@ -0,0 +1,250 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use RT::Test tests => 186;
+
+my ( $baseurl, $agent ) = RT::Test->started_ok;
+ok( $agent->login, 'log in' );
+
+my $q = RT::Queue->new($RT::SystemUser);
+$q->Load('General');
+my $ip_cf = RT::CustomField->new($RT::SystemUser);
+
+my ( $val, $msg ) = $ip_cf->Create(
+    Name       => 'IP',
+    Type       => 'IPAddress',
+    LookupType => 'RT::Queue-RT::Ticket'
+);
+ok( $val, $msg );
+my $cf_id = $val;
+$ip_cf->AddToObject($q);
+use_ok('RT');
+
+my $cf;
+diag "load and check basic properties of the IP CF" if $ENV{'TEST_VERBOSE'};
+{
+    my $cfs = RT::CustomFields->new($RT::SystemUser);
+    $cfs->Limit( FIELD => 'Name', VALUE => 'IP' );
+    is( $cfs->Count, 1, "found one CF with name 'IP'" );
+
+    $cf = $cfs->First;
+    is( $cf->Type,       'IPAddress',            'type check' );
+    is( $cf->LookupType, 'RT::Queue-RT::Ticket', 'lookup type check' );
+    ok( !$cf->MaxValues, "unlimited number of values" );
+    ok( !$cf->Disabled,  "not disabled" );
+}
+
+diag "check that CF applies to queue General" if $ENV{'TEST_VERBOSE'};
+{
+    my $cfs = $q->TicketCustomFields;
+    $cfs->Limit( FIELD => 'id', VALUE => $cf->id, ENTRYAGGREGATOR => 'AND' );
+    is( $cfs->Count, 1, 'field applies to queue' );
+}
+
+my %valid = (
+    'abcd:' x 7 . 'abcd' => 'abcd:' x 7 . 'abcd',
+    '034:' x 7 . '034'   => '0034:' x 7 . '0034',
+    'abcd::'             => 'abcd:' . '0000:' x 6 . '0000',
+    '::abcd'             => '0000:' x 7 . 'abcd',
+    'abcd::034'          => 'abcd:' . '0000:' x 6 . '0034',
+    'abcd::192.168.1.1'  => 'abcd:' . '0000:' x 5 . 'c0a8:0101',
+    '::192.168.1.1'      => '0000:' x 6 . 'c0a8:0101',
+);
+
+diag "create a ticket via web and set IP" if $ENV{'TEST_VERBOSE'};
+{
+    for my $ip ( keys %valid ) {
+        ok $agent->goto_create_ticket($q), "go to create ticket";
+        my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
+        $agent->submit_form(
+            form_name => 'TicketCreate',
+            fields    => {
+                Subject   => 'test ip',
+                $cf_field => $ip,
+            }
+        );
+
+        $agent->content_like( qr/$valid{$ip}/, "IP on the page" );
+        my ($id) = $agent->content =~ /Ticket (\d+) created/;
+        ok( $id, "created ticket $id" );
+
+        my $ticket = RT::Ticket->new($RT::SystemUser);
+        $ticket->Load($id);
+        ok( $ticket->id, 'loaded ticket' );
+        is( $ticket->FirstCustomFieldValue('IP'), $valid{$ip},
+            'correct value' );
+    }
+}
+
+diag "create a ticket and edit IP field using Edit page"
+  if $ENV{'TEST_VERBOSE'};
+
+{
+    for my $ip ( keys %valid ) {
+        ok $agent->goto_create_ticket($q), "go to create ticket";
+        $agent->submit_form(
+            form_name => 'TicketCreate',
+            fields    => { Subject => 'test ip', }
+        );
+
+        my ($id) = $agent->content =~ /Ticket (\d+) created/;
+        ok( $id, "created ticket $id" );
+        my $cf_field = "Object-RT::Ticket-$id-CustomField-$cf_id-Values";
+
+        $agent->follow_link_ok( { text => 'Basics', n => "1" },
+            "Followed 'Basics' link" );
+        $agent->form_number(3);
+
+        like( $agent->value($cf_field), qr/^\s*$/, 'IP is empty' );
+        $agent->field( $cf_field => $valid{$ip} );
+        $agent->click('SubmitTicket');
+
+        $agent->content_like( qr/$valid{$ip}/, "IP on the page" );
+
+        my $ticket = RT::Ticket->new($RT::SystemUser);
+        $ticket->Load($id);
+        ok( $ticket->id, 'loaded ticket' );
+        my $values = $ticket->CustomFieldValues('IP');
+        is( $ticket->FirstCustomFieldValue('IP'), $valid{$ip},
+            'correct value' );
+
+        diag "set IP with spaces around" if $ENV{'TEST_VERBOSE'};
+        my $new_ip = '::3141';
+        my $new_value = '0000:' x 7 . '3141';
+
+        $agent->follow_link_ok( { text => 'Basics', n => "1" },
+            "Followed 'Basics' link" );
+        $agent->form_number(3);
+        like( $agent->value($cf_field),
+            qr/^$valid{$ip}$/, 'IP is in input box' );
+        $agent->field( $cf_field => $new_ip );
+        $agent->click('SubmitTicket');
+
+        $agent->content_like( qr/$new_value/, "IP on the page" );
+
+        $ticket = RT::Ticket->new($RT::SystemUser);
+        $ticket->Load($id);
+        ok( $ticket->id, 'loaded ticket' );
+        is( $ticket->FirstCustomFieldValue('IP'), $new_value, 'correct value' );
+    }
+}
+
+diag "check that we parse correct IPs only" if $ENV{'TEST_VERBOSE'};
+{
+
+    my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
+    my @invalid =
+      ( '::', 'abcd:', 'efgh', 'abcd:' x 8 . 'abcd', 'abcd::abcd::abcd' );
+    for my $invalid (@invalid) {
+        ok $agent->goto_create_ticket($q), "go to create ticket";
+        $agent->submit_form(
+            form_name => 'TicketCreate',
+            fields    => {
+                Subject   => 'test ip',
+                $cf_field => $invalid,
+            }
+        );
+
+        $agent->content_like( qr/can not be parsed to IPAddress/,
+            'ticket fails to create' );
+    }
+}
+
+diag "search tickets by IP" if $ENV{'TEST_VERBOSE'};
+{
+    for my $ip ( keys %valid ) {
+        ok $agent->goto_create_ticket($q), "go to create ticket";
+        my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
+        $agent->submit_form(
+            form_name => 'TicketCreate',
+            fields    => {
+                Subject   => 'test ip',
+                $cf_field => $ip,
+            }
+        );
+
+        my ($id) = $agent->content =~ /Ticket (\d+) created/;
+        ok( $id, "created ticket $id" );
+
+        my $ticket = RT::Ticket->new($RT::SystemUser);
+        $ticket->Load($id);
+        ok( $ticket->id, 'loaded ticket' );
+
+        my $tickets = RT::Tickets->new($RT::SystemUser);
+        $tickets->FromSQL("id = $id AND CF.{IP} = '$ip'");
+        ok( $tickets->Count, "found tickets" );
+    }
+}
+
+diag "create two tickets with different IPs and check several searches"
+  if $ENV{'TEST_VERBOSE'};
+{
+    ok $agent->goto_create_ticket($q), "go to create ticket";
+    my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
+    $agent->submit_form(
+        form_name => 'TicketCreate',
+        fields    => {
+            Subject   => 'test ip',
+            $cf_field => 'abcd::',
+        }
+    );
+
+    my ($id1) = $agent->content =~ /Ticket (\d+) created/;
+    ok( $id1, "created first ticket $id1" );
+
+    ok $agent->goto_create_ticket($q), "go to create ticket";
+    $agent->submit_form(
+        form_name => 'TicketCreate',
+        fields    => {
+            Subject   => 'test ip',
+            $cf_field => 'bbcd::',
+        }
+    );
+
+    my ($id2) = $agent->content =~ /Ticket (\d+) created/;
+    ok( $id2, "created second ticket $id2" );
+
+    my $tickets = RT::Tickets->new($RT::SystemUser);
+    $tickets->FromSQL("id = $id1 OR id = $id2");
+    is( $tickets->Count, 2, "found both tickets by 'id = x OR y'" );
+
+    # IP
+    $tickets = RT::Tickets->new($RT::SystemUser);
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'abcd::'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->FirstCustomFieldValue('IP'),
+        'abcd' . ':0000' x 7, "correct value" );
+    $tickets = RT::Tickets->new($RT::SystemUser);
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'bbcd::'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->FirstCustomFieldValue('IP'),
+        'bbcd' . ':0000' x 7, "correct value" );
+
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} <= 'abcd::'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->FirstCustomFieldValue('IP'),
+        'abcd' . ':0000' x 7, "correct value" );
+    $tickets = RT::Tickets->new($RT::SystemUser);
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} >= 'bbcd::'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->FirstCustomFieldValue('IP'),
+        'bbcd' . ':0000' x 7, "correct value" );
+
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} > 'bbcd::'");
+    is( $tickets->Count, 0, "no tickets found" );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} < 'abcd::'");
+    is( $tickets->Count, 0, "no tickets found" );
+
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} < 'bbcd::'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->FirstCustomFieldValue('IP'),
+        'abcd' . ':0000' x 7, "correct value" );
+
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} > 'abcd::'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->FirstCustomFieldValue('IP'),
+        'bbcd' . ':0000' x 7, "correct value" );
+}
+

commit e24a55bbde5802e34006044dad7f067d31f9448e
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Wed Sep 15 13:07:26 2010 +0800

    tweak ip.t a little bit

diff --git a/t/customfields/ip.t b/t/customfields/ip.t
index 5781634..c96db8f 100644
--- a/t/customfields/ip.t
+++ b/t/customfields/ip.t
@@ -93,11 +93,7 @@ diag "create a ticket and edit IP field using Edit page"
     my $ticket = RT::Ticket->new($RT::SystemUser);
     $ticket->Load($id);
     ok( $ticket->id, 'loaded ticket' );
-    my $values = $ticket->CustomFieldValues('IP');
-    my %has = map { $_->Content => 1 } @{ $values->ItemsArrayRef };
-    is( scalar values %has, 1, "one IP were added" );
-    ok( $has{$val}, "has value" )
-      or diag "but has values " . join ", ", keys %has;
+    is( $ticket->FirstCustomFieldValue('IP'), '172.16.0.1' );
 
     diag "set IP with spaces around" if $ENV{'TEST_VERBOSE'};
     $val = "  172.16.0.2  \n  ";
@@ -114,11 +110,8 @@ diag "create a ticket and edit IP field using Edit page"
     $ticket = RT::Ticket->new($RT::SystemUser);
     $ticket->Load($id);
     ok( $ticket->id, 'loaded ticket' );
-    $values = $ticket->CustomFieldValues('IP');
-    %has = map { $_->Content => 1 } @{ $values->ItemsArrayRef };
-    is( scalar values %has, 1, "one IP were added" );
-    ok( $has{'172.16.0.2'}, "has value" )
-      or diag "but has values " . join ", ", keys %has;
+    is( $ticket->FirstCustomFieldValue('IP'),
+        '172.16.0.2', 'correct value' );
 }
 
 diag "check that we parse correct IPs only" if $ENV{'TEST_VERBOSE'};
@@ -141,11 +134,8 @@ diag "check that we parse correct IPs only" if $ENV{'TEST_VERBOSE'};
         $ticket->Load($id);
         is( $ticket->id, $id, 'loaded ticket' );
 
-        my %has = ();
-        $has{ $_->Content }++
-          foreach @{ $ticket->CustomFieldValues('IP')->ItemsArrayRef };
-        is( scalar values %has, 1, "one IP was added" );
-        ok( $has{$valid}, 'correct value' );
+        is( $ticket->FirstCustomFieldValue('IP'),
+            $valid, 'correct value' );
     }
 
     for my $invalid (qw{255.255.255.256 355.255.255.255 8.13.8/8.13.0/1.0}) {
@@ -233,6 +223,16 @@ diag "create two tickets with different IPs and check several searches"
     is( $tickets->First->FirstCustomFieldValue('IP'),
         '192.168.22.10', "correct value" );
 
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} <= '192.168.21.10'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->FirstCustomFieldValue('IP'),
+        '192.168.21.10', "correct value" );
+    $tickets = RT::Tickets->new($RT::SystemUser);
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} >= '192.168.22.10'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->FirstCustomFieldValue('IP'),
+        '192.168.22.10', "correct value" );
+
     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} > '192.168.22.10'");
     is( $tickets->Count, 0, "no tickets found" );
     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} < '192.168.21.10'");

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


More information about the Rt-commit mailing list