This file is indexed.

/usr/share/perl5/Text/PDF/Pages.pm is in libtext-pdf-perl 0.29a-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
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
package Text::PDF::Pages;

use strict;
use vars qw(@ISA %inst);
@ISA = qw(Text::PDF::Dict);
# no warnings qw(uninitialized);

use Text::PDF::Dict;
use Text::PDF::Utils;

%inst = map {$_ => 1} qw(Parent Type);

=head1 NAME

Text::PDF::Pages - a PDF pages hierarchical element. Inherits from L<Text::PDF::Dict>

=head1 DESCRIPTION

A Pages object is the parent to other pages objects or to page objects 
themselves.

=head1 METHODS

=head2 Text::PDF::Pages->new($pdfs,$parent)

This creates a new Pages object. Notice that $parent here is not the
file context for the object but the parent pages object for this
pages. If we are using this class to create a root node, then $parent
should point to the file context, which is identified by not having a
Type of Pages.  $pdfs is the file object (or objects) in which to
create the new Pages object.

=cut

sub new
{
    my ($class, $pdfs, $parent) = @_;
    my ($self);

    $class = ref $class if ref $class;
    $self = $class->SUPER::new($pdfs, $parent);
    $self->{'Type'} = PDFName("Pages");
    $self->{'Parent'} = $parent if defined $parent;
    $self->{'Count'} = PDFNum(0);
    $self->{'Kids'} = Text::PDF::Array->new;
    $self->{' outto'} = ref $pdfs eq 'ARRAY' ? $pdfs : [$pdfs];
    $self->out_obj(1);

    $self;
}


sub init
{
    my ($self, $pdf) = @_;
    $self->{' outto'} = [$pdf];
    $self;
}

=head2 $p->out_obj($isnew)

Tells all the files that this thing is destined for that they should output this
object come time to output. If this object has no parent, then it must be the
root. So set as the root for the files in question and tell it to be output too.
If $isnew is set, then call new_obj rather than out_obj to create as a new
object in the file.

=cut

sub out_obj
{
    my ($self, $isnew) = @_;

    foreach (@{$self->{' outto'}})
    {
        if ($isnew)
        { $_->new_obj($self); }
        else
        { $_->out_obj($self); }
        
        unless (defined $self->{'Parent'})
        {
            $_->{'Root'}{'Pages'} = $self;
            $_->out_obj($_->{'Root'});
        }
    }
    $self;
}
        

=head2 $p->find_page($pnum)

Returns the given page, using the page count values in the pages tree. Pages
start at 0.

=cut

sub find_page
{
    my ($self, $pnum) = @_;
    my ($top) = $self->get_top;
    
    $top->find_page_recurse(\$pnum);
}


sub find_page_recurse
{
    my ($self, $rpnum) = @_;
    my ($res, $k);
    
    if ($self->{'Count'}->realise->val <= $$rpnum)
    { 
        $$rpnum -= $self->{'Count'}->val; 
        return undef;
    }

    foreach $k ($self->{'Kids'}->realise->elementsof)
    {
        if ($k->{'Type'}->realise->val eq 'Page')
        {
            return $k if ($$rpnum == 0);
            $$rpnum--;
        }
        elsif ($res = $k->realise->find_page_recurse($rpnum))
        { return $res; }
    }
    return undef;
}
        
=head2 $p->add_page($page, $pnum)

Inserts the page before the given $pnum. $pnum can be -ve to count from the END
of the document. -1 is after the last page. Likewise $pnum can be greater than the
number of pages currently in the document, to append.

This method only guarantees to provide a reasonable pages tree if pages are
appended or prepended to the document. Pages inserted in the middle of the
document may simply be inserted in the appropriate leaf in the pages tree without
adding any new branches or leaves. To tidy up such a mess, it is best to call
$p->rebuild_tree to rebuild the pages tree into something efficient.

=cut

sub add_page
{
    my ($self, $page, $pnum) = @_;
    my ($top) = $self->get_top;
    my ($ppage, $ppages, $pindex, $ppnum);
    
    $pnum = -1 unless (defined $pnum && $pnum <= $top->{'Count'}->val);
    if ($pnum == -1)
    { $ppage = $top->find_page($top->{'Count'}->val - 1); }
    else
    {
        $pnum = $top->{'Count'}->val + $pnum + 1 if ($pnum < 0);
        $ppage = $top->find_page($pnum);
    }
    
    if (defined $ppage->{'Parent'})
    { $ppages = $ppage->{'Parent'}->realise; }
    else
    { $ppages = $self; }
    
    $ppnum = scalar $ppages->{'Kids'}->realise->elementsof;
    
    if ($pnum == -1)
    { $pindex = -1; }
    else
    {
        for ($pindex = 0; $pindex < $ppnum; $pindex++)
        { last if ($ppages->{'Kids'}{' val'}[$pindex] eq $ppage); }
        $pindex = -1 if ($pindex == $ppnum);
    }
    
    $ppages->add_page_recurse($page->realise, $pindex);
    for ($ppages = $page->{'Parent'}; defined $ppages->{'Parent'}; $ppages = $ppages->{'Parent'}->realise)
    { $ppages->out_obj->{'Count'}->realise->{'val'}++; }
    $ppages->out_obj->{'Count'}->realise->{'val'}++;
    $page;
}    


sub add_page_recurse
{
    my ($self, $page, $index) = @_;
    my ($newpages, $ppages, $pindex, $ppnum);
    
    if (scalar $self->{'Kids'}->elementsof >= 8 && $self->{'Parent'} && $index < 1)
    {
        $ppages = $self->{'Parent'}->realise;
        $newpages = $self->new($self->{' outto'}, $ppages);
        if ($ppages)
        {
            $ppnum = scalar $ppages->{'Kids'}->realise->elementsof;
            for ($pindex = 0; $pindex < $ppnum; $pindex++)
            { last if ($ppages->{'Kids'}{' val'}[$pindex] eq $self); }
            $pindex = -1 if ($pindex == $ppnum);
            $ppages->add_page_recurse($newpages, $pindex);
        }
    }
    else
    { $newpages = $self->out_obj; }
    
    if ($index < 0)
    { push (@{$newpages->{'Kids'}->realise->{' val'}}, $page); }
    else
    { splice (@{$newpages->{'Kids'}{' val'}}, $index, 0, $page); }
    $page->{'Parent'} = $newpages;
}


=head2 $root_pages = $p->rebuild_tree([@pglist])

Rebuilds the pages tree to make a nice balanced tree that conforms to Adobe
recommendations. If passed a pglist then the tree is built for that list of
pages. No check is made of whether the pglist contains pages.  

Returns the top of the tree for insertion in the root object.

=cut

sub rebuild_tree
{
    my ($self, @pglist) = @_;
}


=head2 @pglist = $p->get_pages

Returns a list of page objects in the document in page order

=cut

sub get_pages
{
    my ($self) = @_;
    
    return $self->get_top->get_kids;
}


# only call this on the top level or anything you want pages below
sub get_kids
{
    my ($self) = @_;
    my ($pgref, @pglist);

    foreach $pgref ($self->{'Kids'}->elementsof)
    {
        $pgref->realise;
        if ($pgref->{'Type'}->val =~ m/^Pages$/oi)
        { push (@pglist, $pgref->get_kids()); }
        else
        { push (@pglist, $pgref); }
    }
    @pglist;
}

=head2 $p->find_prop($key)

Searches up through the inheritance tree to find a property.

=cut

sub find_prop
{
    my ($self, $prop) = @_;

    if (defined $self->{$prop})
    {
        if (ref $self->{$prop} && $self->{$prop}->isa("Text::PDF::Objind"))
        { return $self->{$prop}->realise; }
        else
        { return $self->{$prop}; }
    } elsif (defined $self->{'Parent'})
    { return $self->{'Parent'}->find_prop($prop); }
}

#    defined $_[0]->{$_[1]} && $_[0]->{$_[1]}->realised or
#        defined $_[0]->{'Parent'} && $_[0]->{'Parent'}->find_prop($_[1]); }


=head2 $p->add_font($pdf, $font)

Creates or edits the resource dictionary at this level in the hierarchy. If
the font is already supported even through the hierarchy, then it is not added.

=cut

sub add_font
{
    my ($self, $font, $pdf) = @_;
    my ($name) = $font->{'Name'}->val;
    my ($dict) = $self->find_prop('Resources');
    my ($rdict);

    return $self if ($dict ne "" && defined $dict->{'Font'} && defined $dict->{'Font'}{$name});
    unless (defined $self->{'Resources'})
    {
        $dict = $dict ne "" ? $dict->copy($pdf) : PDFDict();
        $self->{'Resources'} = $dict;
    }
    else
    { $dict = $self->{'Resources'}; }
    $dict->{'Font'} = PDFDict() unless defined $self->{'Resources'}{'Font'};
    $rdict = $dict->{'Font'}->val;
    $rdict->{$name} = $font unless ($rdict->{$name});
    if (ref $dict ne 'HASH' && $dict->is_obj($pdf))
    { $pdf->out_obj($dict); }
    if (ref $rdict ne 'HASH' && $rdict->is_obj($pdf))
    { $pdf->out_obj($rdict); }
    $self;
}


=head2 $p->bbox($xmin, $ymin, $xmax, $ymax, [$param])

Specifies the bounding box for this and all child pages. If the values are
identical to those inherited then no change is made. $param specifies the attribute
name so that other 'bounding box'es can be set with this method.

=cut

sub bbox
{
    my ($self, @bbox) = @_;
    my ($str) = $bbox[4] || 'MediaBox';
    my ($inh) = $self->find_prop($str);
    my ($test, $i, $e);

    if ($inh ne "")
    {
        $test = 1; $i = 0;
        foreach $e ($inh->elementsof)
        { $test &&= $e->val == $bbox[$i++]; }
        return $self if $test && $i == 4;
    }

    $inh = Text::PDF::Array->new;
    foreach $e (@bbox[0..3])
    { $inh->add_elements(PDFNum($e)); }
    $self->{$str} = $inh;
    $self;
}


=head2 $p->proc_set(@entries)

Ensures that the current resource contains all the entries in the proc_sets
listed. If necessary it creates a local resource dictionary to achieve this.

=cut

sub proc_set
{
    my ($self, @entries) = @_;
    my (@temp) = @entries;
    my ($dict, $e);

    $dict = $self->find_prop('Resource');
    if ($dict ne "" && defined $dict->{'ProcSet'})
    {
        foreach $e ($dict->{'ProcSet'}->elementsof)
        { @temp = grep($_ ne $e, @temp); }
        return $self if (scalar @temp == 0);
        @entries = @temp if defined $self->{'Resources'};
    }

    unless (defined $self->{'Resources'})
    { $self->{'Resources'} = $dict ne "" ? $dict->copy : PDFDict(); }

    $self->{'Resources'}{'ProcSet'} = PDFArray() unless defined $self->{'ProcSet'};

    foreach $e (@entries)
    { $self->{'Resources'}{'ProcSet'}->add_elements(PDFName($e)); }
    $self;
}

sub empty
{
    my ($self) = @_;
    my ($parent) = $self->{'Parent'} if defined ($self->{'Parent'});

    $self->SUPER::empty;
    $self->{'Parent'} = $parent if defined $parent;
    $self;
}

sub dont_copy
{ return $inst{$_[1]} || $_[0]->SUPER::dont_copy($_[1]); }


=head2 $p->get_top

Returns the top of the pages tree

=cut

sub get_top
{
    my ($self) = @_;
    my ($p);
    
    for ($p = $self; defined $p->{'Parent'}; $p = $p->{'Parent'})
    { }
    
    $p->realise;
}


1;