Viewing File: /usr/local/cpanel/base/backend/traceaddy.cgi
#!/usr/local/cpanel/3rdparty/bin/perl
# cpanel - base/backend/traceaddy.cgi Copyright 2022 cPanel, L.L.C.
# All rights reserved.
# copyright@cpanel.net http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited
use strict;
use Cpanel::AdminBin ();
use Cpanel::Encoder::URI ();
print "Content-type: image/png\r\n\r\n";
eval "use GD;";
my $has_gd = $@ ? 0 : 1;
if ( !$has_gd ) {
its_broken();
}
my %ROUTE;
my $startaddress;
my $addy = Cpanel::Encoder::URI::uri_decode_str( $ENV{'QUERY_STRING'} );
my $result;
if ( $> != 0 ) {
$result = Cpanel::AdminBin::adminfetchnocache( 'mailroute', '', 'TRACE', 'storable', $addy, $ENV{REMOTE_USER} );
}
else {
require Cpanel::EximTrace;
require Cpanel::Validate::EmailRFC;
$addy =~ s/%([0-9A-Fa-f]{2})/chr hex $1/eg;
$addy = Cpanel::Validate::EmailRFC::scrub($addy);
$result = Cpanel::EximTrace::generate_trace_table($addy);
}
if ( ref $result eq 'HASH' ) {
%ROUTE = %{ $result->{'route'} };
$startaddress = $result->{'startaddress'};
}
else {
its_broken();
}
my $maxheight = 1;
my $maxwidth;
my %BOTTOM;
my %SEENLIST;
my $height = 0;
_processnodes($startaddress);
my $image = new GD::Image( ( ( $maxwidth * 150 ) + 600 ), ( $maxheight * 100 ) );
my $font = '/usr/local/cpanel/share/ttf/Generic.ttf';
my $white = $image->colorAllocate( 255, 255, 255 );
my $black = $image->colorAllocate( 0, 0, 0 );
my $red = $image->colorAllocate( 255, 0, 0 );
my $green = $image->colorAllocate( 0, 220, 0 );
my $blue = $image->colorAllocate( 0, 0, 230 );
$image->transparent($white);
$image->interlaced('false');
delete @SEENLIST{ keys %SEENLIST };
$height = 0;
_processnodes( $startaddress, 0, 1 );
binmode(STDOUT);
print STDOUT $image->png;
sub _processnodes {
my $node = shift;
my $width = shift;
my $img = shift;
$SEENLIST{$node} = 1;
$width++;
if ( $width > $maxwidth ) { $maxwidth = $width; }
foreach my $rr ( @{ $ROUTE{$node} } ) {
my $value = join( ',', %{$rr} );
if ($img) {
drawBox( $node, $rr, $width, $height );
}
$height++;
if ( $height > $maxheight ) { $maxheight = $height; }
if ( ( $$rr{'result'} =~ /\@/ || $$rr{'result'} =~ /^\S+$/ )
&& !$SEENLIST{ $$rr{'result'} } ) {
_processnodes( $$rr{'result'}, $width, $img );
}
}
}
sub drawBox {
my ( $key, $rr, $depth, $curheight ) = @_;
my $val = $$rr{'router'};
if ( $$rr{'aliasfile'} ne '' ) {
$val .= " via " . $$rr{'aliasfile'};
}
elsif ( $$rr{'result'} eq 'local delivery' ) {
$val .= " to " . $$rr{'result'};
}
else {
$val .= " via " . $$rr{'result'};
}
my $x = ( ( $depth - 1 ) * 150 ) + 7;
my $y = ( $curheight * 100 ) + 4;
my $bx = ( $depth - 1 );
my $by = ($curheight);
# @bounds[0,1] Lower left corner (x,y)
# @bounds[2,3] Lower right corner (x,y)
# @bounds[4,5] Upper right corner (x,y)
# @bounds[6,7] Upper left corner (x,y)
my @boundsa = $image->stringFT( $black, $font, 12.0, 0.0, $x, $y + 15, $key );
if ($@) {
my $px = $x;
my $py = $y + 15;
$image->string( GD::Font->MediumBold, $x, $y + 15, $key, $black );
@boundsa = ( $px, $py - 8, $px + ( length($key) * 7 ), $py, $px, $py + ( length($key) + 5 ), $px, $py );
}
my @boundsb = $image->stringFT( $black, $font, 12.0, 0.0, $boundsa[0], $boundsa[1] + 20, $val );
if ($@) {
my $px = $boundsa[0];
my $py = $boundsa[1] + 10;
$image->string( GD::Font->MediumBold, $boundsa[0], $boundsa[1] + 20, $val, $black );
@boundsb = ( $px, $py, $px + ( length($val) * 7 ), $py + 20, $px, $px + ( length($val) + 5 ), $px, $py );
}
my $pngfile = '';
my $branchcolor = $black;
if ( $$rr{'error'} ) {
$branchcolor = $red;
$pngfile = '/usr/local/cpanel/share/icons/alert.red.png';
}
elsif ( $$rr{'result'} eq 'local delivery' ) {
$branchcolor = $blue;
$pngfile = '/usr/local/cpanel/share/icons/mbox.png';
}
elsif ( $$rr{'aliasfile'} ne '' ) {
$pngfile = '/usr/local/cpanel/share/icons/f.png';
}
else {
$branchcolor = $green;
$pngfile = '/usr/local/cpanel/share/icons/world2.png';
}
if ( $boundsb[2] != $boundsa[6] ) {
if ( $boundsa[2] > $boundsb[2] ) { #if the first text is longer then the second use it as the rectangle size
$image->rectangle( $boundsa[6] - 5, $boundsa[7] - 5, $boundsa[2] + 5, $boundsb[3] + 5, $branchcolor );
}
else {
$image->rectangle( $boundsa[6] - 5, $boundsa[7] - 5, $boundsb[2] + 5, $boundsb[3] + 5, $branchcolor );
}
#$mbx = ( $bx - 1 );
for ( my $i = ( $by - 1 ); $i >= 0; $i-- ) {
if ( $BOTTOM{ $bx - 1 }{$i} ne '' ) {
$image->line( ( $x - 100 ), $BOTTOM{ $bx - 1 }{$i} + 5, ( $x - 100 ), ( $y + 20 ), $black );
last;
}
}
$image->line( ( $x - 100 ), ( $y + 20 ), $x - 7, ( $y + 20 ), $branchcolor );
open( PNG, '<', $pngfile );
my $myImage = newFromPng GD::Image( \*PNG ) || die;
close PNG;
$myImage->transparent($white);
my ( $imgwidth, $imgheight ) = $myImage->getBounds();
$image->copy( $myImage, ( $x - 100 ) - ( $imgwidth / 2 ), ( $y + 20 ) - ( $imgheight / 2 ), 0, 0, $imgwidth, $imgheight );
$BOTTOM{ $bx - 1 }{$by} = ( ( ( $y + 14 ) + ($imgheight) ) - ( $imgheight / 2 ) );
$BOTTOM{$bx}{$by} = ( $boundsb[3] );
}
else {
if ( $boundsa[2] > $boundsb[2] ) { #if the first text is longer then the second use it as the rectangle size
$image->rectangle( $boundsa[6] - 2, $boundsa[7] - 2, $boundsa[2] + 5, $boundsb[3] + 5, $branchcolor );
}
else {
$image->rectangle( $boundsa[6] - 2, $boundsa[7] - 2, $boundsb[2] + 5, $boundsb[3] + 5, $branchcolor );
}
$BOTTOM{$bx}{$by} = ( $boundsb[3] - 20 );
}
}
sub its_broken {
if ( open my $image_fh, '<', '/usr/local/cpanel/whostmgr/docroot/images/broken.gif' ) {
binmode $image_fh;
while ( readline $image_fh ) {
print;
}
close $image_fh;
}
exit;
}
Back to Directory
File Manager