+sub _FillInTemplateURL {
+ my $self = shift;
+ my $url = shift;
+
+ return undef unless defined $url && length $url;
+
+ # special case, whole value should be an URL
+ if ( $url =~ /^__CustomField__/ ) {
+ my $value = $self->Content;
+ # protect from potentially malicious URLs
+ if ( $value =~ /^\s*(?:javascript|data):/i ) {
+ my $object = $self->Object;
+ $RT::Logger->error(
+ "Potentially dangerous URL type in custom field '". $self->CustomFieldObj->Name ."'"
+ ." on ". ref($object) ." #". $object->id
+ );
+ return undef;
+ }
+ $url =~ s/^__CustomField__/$value/;
+ }
+
+ # default value, uri-escape
+ for my $key (keys %placeholders) {
+ $url =~ s{__${key}__}{
+ my $value = $placeholders{$key}{'value'}->( $self );
+ $value = '' if !defined($value);
+ RT::Interface::Web::EscapeURI(\$value) if $placeholders{$key}{'escape'};
+ $value
+ }gxe;
+ }
+
+ return $url;
+} }
+
+
+=head2 ValueLinkURL
+
+Returns a filled in URL template for this ObjectCustomFieldValue, suitable for
+constructing a hyperlink in RT's webui. Returns undef if this custom field doesn't have
+a LinkValueTo
+
+=cut
+
+sub LinkValueTo {
+ my $self = shift;
+ return $self->_FillInTemplateURL($self->CustomFieldObj->LinkValueTo);
+}
+
+
+
+=head2 ValueIncludeURL
+
+Returns a filled in URL template for this ObjectCustomFieldValue, suitable for
+constructing a hyperlink in RT's webui. Returns undef if this custom field doesn't have
+a IncludeContentForValue
+
+=cut
+
+sub IncludeContentForValue {
+ my $self = shift;
+ return $self->_FillInTemplateURL($self->CustomFieldObj->IncludeContentForValue);
+}
+
+
+sub ParseIPRange {
+ my $self = shift;
+ my $value = shift or return;
+ $value = lc $value;
+ $value =~ s!^\s+!!;
+ $value =~ s!\s+$!!;
+
+ if ( $value =~ /^$RE{net}{CIDR}{IPv4}{-keep}$/go ) {
+ my $cidr = join( '.', map $_||0, (split /\./, $1)[0..3] ) ."/$2";
+ $value = (Net::CIDR::cidr2range( $cidr ))[0] || $value;
+ }
+ elsif ( $value =~ /^$IPv6_re(?:\/\d+)?$/o ) {
+ $value = (Net::CIDR::cidr2range( $value ))[0] || $value;
+ }
+
+ my ($sIP, $eIP);
+ if ( $value =~ /^($RE{net}{IPv4})$/o ) {
+ $sIP = $eIP = sprintf "%03d.%03d.%03d.%03d", split /\./, $1;
+ }
+ elsif ( $value =~ /^($RE{net}{IPv4})-($RE{net}{IPv4})$/o ) {
+ $sIP = sprintf "%03d.%03d.%03d.%03d", split /\./, $1;
+ $eIP = sprintf "%03d.%03d.%03d.%03d", split /\./, $2;
+ }
+ elsif ( $value =~ /^($IPv6_re)$/o ) {
+ $sIP = $self->ParseIP( $1 );
+ $eIP = $sIP;
+ }
+ elsif ( $value =~ /^($IPv6_re)-($IPv6_re)$/o ) {
+ ($sIP, $eIP) = ( $1, $2 );
+ $sIP = $self->ParseIP( $sIP );
+ $eIP = $self->ParseIP( $eIP );
+ }
+ else {
+ return;
+ }
+
+ ($sIP, $eIP) = ($eIP, $sIP) if $sIP gt $eIP;
+
+ return $sIP, $eIP;