This file is indexed.

/usr/share/perl5/Mail/MtPolicyd/Request.pm is in mtpolicyd 2.02-3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
package Mail::MtPolicyd::Request;

use Moose;
use namespace::autoclean;

use Mail::MtPolicyd::Plugin::Result;

our $VERSION = '2.02'; # VERSION
# ABSTRACT: the request object


has 'attributes' => (
	is => 'ro', isa => 'HashRef', required => 1,
	traits => [ 'Hash' ],
	handles => { 'attr' => 'get' },
);


# gets attached later
has 'session' => ( is => 'rw', isa => 'Maybe[HashRef]' );


has 'server' => (
	is => 'ro', isa => 'Net::Server', required => 1,
	handles => {
		'log' => 'log',
	}
);


has 'type' => (
	is => 'ro',
	isa => 'Str',
	lazy => 1,
	default => sub {
		my $self = shift;
		return( $self->attr('request') );
	}
);


has 'use_caching' => ( is => 'rw', isa => 'Bool', default => 1 );


sub dump_attr {
	my $self = shift;
	my $attr = $self->attributes;
	return( join(', ', map { $_.'='.$attr->{$_} } keys %$attr ) );
}


sub get {
  my ( $self, $value ) = @_;
  my ($scope, $name);

  if( ! defined $value || $value eq '' ) { return; }

  my @params = split(':', $value, 2);
  if( scalar(@params) == 2 ) {
    ( $scope, $name ) = @params;
  } elsif( scalar(@params) == 1) {
    ( $scope, $name ) = ( 'request', @params );
  }

  if( $scope eq 'session' || $scope eq 's' ) {
    if( ! defined $self->session ) {
      return;
    }
    return $self->session->{$name};
  } elsif( $scope eq 'request' || $scope eq 'r' ) {
    return $self->attr( $name );
  }

  die("unknown scope $scope while retrieving variable for $value");

  return;
}


sub new_from_fh {
	my ( $class, $fh ) = ( shift, shift );
	my $attr = {};
	my $complete = 0;
	my $line;
	while( defined( $line = $fh->getline ) ) {
		$line =~ s/\r?\n$//;
		if( $line eq '') { $complete = 1 ; last; }
		my ( $name, $value ) = split('=', $line, 2);
		if( ! defined $value ) {
			die('error parsing request');
		}
		$attr->{$name} = $value;
	}
	if( $fh->error ) {
		die('while reading request: '.$fh->error);
	}
	if( ! defined $line && ! $complete ) {
		die('connection closed by peer');
	}
	if( ! $complete ) {
		die('could not parse request');
	}
	my $obj = $class->new(
		'attributes' => $attr,
		@_
	);
	return $obj;
}


sub do_cached {
	my ( $self, $key, $call ) = @_;
	my $session = $self->session;

	# we cant cache a result without session
	if( ! defined $session || ! $self->use_caching ) {
		return( $call->() );
	}
	if( ! defined $session->{$key} ) {
		$session->{$key} = [ $call->() ];
	}
	return( @{$session->{$key}} );
}


sub is_already_done {
	my ( $self, $key ) = @_;
	my $session = $self->session;

	# we cant cache a result without session
	if( ! defined $session || ! $self->use_caching ) {
		return 0;
	}
	if( defined $session->{$key} ) {
		return(1);
	}
	$session->{$key} = 1;
	return 0;
}


sub is_attr_defined {
    my ( $self, @fields ) = @_;
    my $a = $self->attributes;

    foreach my $field ( @fields ) {
        if( ! defined $a->{$field}
                || $a->{$field} eq ''
                || $a->{$field} =~ /^\s+$/ ) {
            return 0;
        }
    }

    return 1;
}

__PACKAGE__->meta->make_immutable;

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

Mail::MtPolicyd::Request - the request object

=head1 VERSION

version 2.02

=head1 ATTRIBUTES

=head2 attributes

Contains an HashRef with all attributes of the request.

To retrieve a single attribute the attr method could be used:

  $obj->attr('sender');

=head2 session

Contains a HashRef with all values stored in the session.

mtpolicyd will persist the content of this HashRef across requests with the same instance_id.

=head2 server

Contains the Net::Server object of mtpolicyd.

=head2 type

The type of the request. Postfix will always use 'smtpd_access_policy'.

=head2 use_caching

Could be used to disable caching. Only used within the unit tests.

=head1 METHODS

=head2 dump_attr

Returns an string to dump the content of a request.

=head2 get($variable_name)

Retrieve value of a session or request variable.

The format for the variable name is

  (<scope>:)?<variable>

If no scope is given it default to the request scope.

Valid scopes are:

=over

=item session, s

Session variables.

=item request, r

Request attributes.

=back

For example:

  $r->get('request:sender'); # retrieve sender from request
  $r->get('r:sender');       # short format
  $r->get('sender');         # scope defaults to request

  $r->get('session:user_policy'); # retrieve session variable user_policy
  $r->get('s:user_policy');       # the same

=head2 new_from_fh($fh)

An object constructor for creating an request object with the content read
for the supplied filehandle $fh.

Will die if am error ocours:

=over

=item error parsing request

A line in the request could not be parsed.

=item while reading request: <io-error>

The filehandle had an error while reading the request.

=item connection closed by peer

Connection has been closed while reading the request.

=item could not parse request

The client did not send a complete request.

=back

=head2 do_cached( $key, $sub )

This method will execute the function reference give in $sub and store
the return values in $key within the session.
If there is already a cached result stored within $key of the session
it will return the content instead of calling the reference again.

Returns an Array with the return values of the function call.

Example:

  my ( $ip_result, $info ) = $r->do_cached('rbl-'.$self->name.'-result',
    sub { $self->_rbl->check( $ip ) } );

=head2 is_already_done( $key )

This function will raise an flag with name of $key within the session and return true if the
flag is already set. False otherwise.

This could be used to prevent scores or headers from being applied a second time.

Example:

  if( defined $self->score && ! $r->is_already_done('rbl-'.$self->name.'-score') ) {
    $self->add_score($r, $self->name => $self->score);
  }

=head2 is_attr_defined

Returns true if all given attribute names are defined and non-empty.

=head1 AUTHOR

Markus Benning <ich@markusbenning.de>

=head1 COPYRIGHT AND LICENSE

This software is Copyright (c) 2014 by Markus Benning <ich@markusbenning.de>.

This is free software, licensed under:

  The GNU General Public License, Version 2, June 1991

=cut