/usr/share/perl5/Net/Trac/TicketAttachment.pm is in libnet-trac-perl 0.16-1.
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 | use strict;
use warnings;
package Net::Trac::TicketAttachment;
use Any::Moose;
use URI::Escape qw(uri_escape);
=head1 NAME
Net::Trac::TicketAttachment - Represents a single attachment for a Trac ticket
=head1 DESCRIPTION
This class represents a single attachment for a Trac ticket. You do not want
to deal with instantiating this class yourself. Instead let L<Net::Trac::Ticket>
do the work.
=head1 ACCESSORS
=head2 connection
Returns the L<Net::Trac::Connection> used by this class.
=head2 ticket
Returns the ID of the ticket to which this attachment belongs.
=head2 filename
=head2 description
=head2 url
Relative to the remote Trac instance URL as set in the L<Net::Trac::Connection>.
=head2 content
returns the content of the attachment
=head2 content_type
returns the content_type of the attachment
=head2 size
In bytes.
=head2 author
=head2 date
Returns a L<DateTime> object.
=cut
has connection => ( isa => 'Net::Trac::Connection', is => 'ro' );
has ticket => ( isa => 'Int', is => 'ro' );
has date => ( isa => 'DateTime', is => 'rw' );
has filename => ( isa => 'Str', is => 'rw' );
has description => ( isa => 'Str', is => 'rw' );
has url => ( isa => 'Str', is => 'rw' );
has author => ( isa => 'Str', is => 'rw' );
has size => ( isa => 'Int', is => 'rw' );
has content => (
isa => 'Str',
is => 'rw',
lazy => 1,
default => sub { ($_[0]->_load)[0] },
);
has content_type => (
isa => 'Str',
is => 'rw',
lazy => 1,
default => sub { ($_[0]->_load)[1] },
);
=head1 PRIVATE METHODS
=head2 _parse_html_chunk STRING
Parses a specific chunk of HTML (as extracted by L<Net::Trac::Ticket>) into
the various fields.
=cut
sub _parse_html_chunk {
my $self = shift;
my $html = shift;
# <a href="/trac/attachment/ticket/1/xl0A1UDD4i" title="View attachment">xl0A1UDD4i</a>
# (<span title="27 bytes">27 bytes</span>) - added by <em>hiro</em>
# <a class="timeline" href="/trac/timeline?from=2008-12-30T15%3A45%3A24Z-0500&precision=second" title="2008-12-30T15:45:24Z-0500 in Timeline">0 seconds</a> ago.
# </dt>
# <dd>
# Test description
# </dd>
# for individual attachment page, the html is like:
#
# <div id="content" class="attachment">
# <h1><a href="/xx/ticket/2">Ticket #2</a>: test.2.txt</h1>
# <table id="info" summary="Description">
# <tbody>
# <tr>
# <th scope="col">
# File test.2.txt, <span title="5 bytes">5 bytes</span>
# (added by sunnavy, <a class="timeline" href="/xx/timeline?from=2009-05-27T14%3A31%3A02Z%2B0800&precision=second" title="2009-05-27T14:31:02Z+0800 in Timeline">13 seconds</a> ago)
# </th>
# </tr>
# <tr>
# <td class="message searchable">
# <p>
#blalba
#</p>
#
# </td>
# </tr>
# </tbody>
# </table>
# </div>
$self->filename($1) if $html =~ qr{<a (?:.+?) title="View attachment">(.+?)</a>};
$self->url( "/raw-attachment/ticket/"
. $self->ticket . "/"
. uri_escape( $self->filename ) )
if defined $self->filename;
$self->size($1) if $html =~ qr{<span title="(\d+) bytes">};
$self->author($1) if $html =~ qr{added by (?:<em>)?\s*(\w+)};
if ( $html =~ qr{<a (?:.+?) title="(.+?) in Timeline">} ) {
my $scalar_date = $1;
$self->date( Net::Trac::Ticket->timestamp_to_datetime($scalar_date) );
}
$self->description($1) if $html =~ qr{(?:<dd>|<p>)\s*(.*?)\s*(?:</dd>|</p>)}s;
return 1;
}
sub _load {
my $self = shift;
my $content = $self->connection->_fetch( $self->url );
my $content_type;
my $type_header = $self->connection->mech->response->header('Content-Type');
if ( $type_header =~ /(\S+?);/ ) {
$content_type = $1;
}
$self->content( $content );
$self->content_type( $content_type );
return $content, $content_type;
}
=head1 LICENSE
Copyright 2008-2009 Best Practical Solutions.
This package is licensed under the same terms as Perl 5.8.8.
=cut
__PACKAGE__->meta->make_immutable;
no Any::Moose;
1;
|