| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Net::Amazon::S3::Bucket; | 
| 2 |  |  |  |  |  |  | # ABSTRACT: convenience object for working with Amazon S3 buckets | 
| 3 |  |  |  |  |  |  | $Net::Amazon::S3::Bucket::VERSION = '0.98'; | 
| 4 | 96 |  |  | 96 |  | 731 | use Moose 0.85; | 
|  | 96 |  |  |  |  | 2219 |  | 
|  | 96 |  |  |  |  | 802 |  | 
| 5 | 96 |  |  | 96 |  | 666610 | use MooseX::StrictConstructor 0.16; | 
|  | 96 |  |  |  |  | 2318 |  | 
|  | 96 |  |  |  |  | 652 |  | 
| 6 | 96 |  |  | 96 |  | 319984 | use Carp; | 
|  | 96 |  |  |  |  | 296 |  | 
|  | 96 |  |  |  |  | 6469 |  | 
| 7 | 96 |  |  | 96 |  | 59330 | use File::stat; | 
|  | 96 |  |  |  |  | 683590 |  | 
|  | 96 |  |  |  |  | 504 |  | 
| 8 | 96 |  |  | 96 |  | 59095 | use IO::File 1.14; | 
|  | 96 |  |  |  |  | 859620 |  | 
|  | 96 |  |  |  |  | 257269 |  | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | has 'account' => ( | 
| 11 |  |  |  |  |  |  | is => 'ro', | 
| 12 |  |  |  |  |  |  | isa => 'Net::Amazon::S3', | 
| 13 |  |  |  |  |  |  | required => 1, | 
| 14 |  |  |  |  |  |  | handles => [qw[ err errstr ]], | 
| 15 |  |  |  |  |  |  | ); | 
| 16 |  |  |  |  |  |  | has 'bucket'  => ( is => 'ro', isa => 'Str',             required => 1 ); | 
| 17 |  |  |  |  |  |  | has 'creation_date' => ( is => 'ro', isa => 'Maybe[Str]', required => 0 ); | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | has 'region' => ( | 
| 20 |  |  |  |  |  |  | is => 'ro', | 
| 21 |  |  |  |  |  |  | lazy => 1, | 
| 22 |  |  |  |  |  |  | predicate => 'has_region', | 
| 23 |  |  |  |  |  |  | default => sub { | 
| 24 |  |  |  |  |  |  | return $_[0]->account->vendor->guess_bucket_region ($_[0]); | 
| 25 |  |  |  |  |  |  | }, | 
| 26 |  |  |  |  |  |  | ); | 
| 27 |  |  |  |  |  |  |  | 
| 28 |  |  |  |  |  |  | __PACKAGE__->meta->make_immutable; | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  | # returns bool | 
| 31 |  |  |  |  |  |  | sub add_key { | 
| 32 | 17 |  |  | 17 | 1 | 35 | my $self = shift; | 
| 33 | 17 |  |  |  |  | 112 | my %args = Net::Amazon::S3::Utils->parse_arguments (\@_, ['key', 'value']); | 
| 34 |  |  |  |  |  |  |  | 
| 35 | 17 |  |  |  |  | 66 | my $key = delete $args{key}; | 
| 36 | 17 |  |  |  |  | 29 | my $value = delete $args{value}; | 
| 37 |  |  |  |  |  |  |  | 
| 38 | 17 | 100 |  |  |  | 47 | if ( ref($value) eq 'SCALAR' ) { | 
| 39 | 3 |  | 33 |  |  | 90 | $args{'Content-Length'} ||= -s $$value; | 
| 40 | 3 |  |  |  |  | 11 | $value = _content_sub($$value); | 
| 41 |  |  |  |  |  |  | } else { | 
| 42 | 14 |  | 33 |  |  | 57 | $args{'Content-Length'} ||= length $value; | 
| 43 |  |  |  |  |  |  | } | 
| 44 |  |  |  |  |  |  |  | 
| 45 | 17 |  |  |  |  | 25 | my $acl; | 
| 46 | 17 | 100 |  |  |  | 44 | $acl = delete $args{acl_short} if exists $args{acl_short}; | 
| 47 | 17 | 100 |  |  |  | 39 | $acl = delete $args{acl}       if exists $args{acl}; | 
| 48 |  |  |  |  |  |  |  | 
| 49 | 17 |  |  |  |  | 32 | my $encryption = delete $args{encryption}; | 
| 50 | 17 |  |  |  |  | 57 | my %headers = %args; | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | # we may get a 307 redirect; ask server to signal 100 Continue | 
| 53 |  |  |  |  |  |  | # before reading the content from CODE reference (_content_sub) | 
| 54 | 17 | 100 |  |  |  | 42 | $headers{expect} = '100-continue' if ref $value; | 
| 55 |  |  |  |  |  |  |  | 
| 56 | 17 |  |  |  |  | 77 | my $response = $self->_perform_operation ( | 
| 57 |  |  |  |  |  |  | 'Net::Amazon::S3::Operation::Object::Add', | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | key       => $key, | 
| 60 |  |  |  |  |  |  | value     => $value, | 
| 61 |  |  |  |  |  |  | (acl      => $acl) x!! defined $acl, | 
| 62 |  |  |  |  |  |  | ((encryption => $encryption) x!! defined $encryption), | 
| 63 |  |  |  |  |  |  | headers   => \%headers, | 
| 64 |  |  |  |  |  |  | ); | 
| 65 |  |  |  |  |  |  |  | 
| 66 | 10 |  |  |  |  | 281 | return $response->is_success; | 
| 67 |  |  |  |  |  |  | } | 
| 68 |  |  |  |  |  |  |  | 
| 69 |  |  |  |  |  |  | sub add_key_filename { | 
| 70 | 2 |  |  | 2 | 1 | 5 | my $self = shift; | 
| 71 | 2 |  |  |  |  | 16 | my %args = Net::Amazon::S3::Utils->parse_arguments (\@_, ['key', 'value']); | 
| 72 | 2 |  |  |  |  | 7 | $args{value} = \ delete $args{value}; | 
| 73 |  |  |  |  |  |  |  | 
| 74 | 2 |  |  |  |  | 8 | return $self->add_key (%args); | 
| 75 |  |  |  |  |  |  | } | 
| 76 |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  | sub copy_key { | 
| 78 | 6 |  |  | 6 | 1 | 11 | my $self = shift; | 
| 79 | 6 |  |  |  |  | 39 | my %args = Net::Amazon::S3::Utils->parse_arguments (\@_, ['key', 'source' ]); | 
| 80 |  |  |  |  |  |  |  | 
| 81 | 6 |  |  |  |  | 23 | my $key = delete $args{key}; | 
| 82 | 6 |  |  |  |  | 11 | my $source = delete $args{source}; | 
| 83 |  |  |  |  |  |  |  | 
| 84 | 6 |  |  |  |  | 11 | my $acl_short; | 
| 85 | 6 | 50 |  |  |  | 14 | if (%args) { | 
| 86 | 6 | 50 |  |  |  | 14 | if ( $args{acl_short} ) { | 
| 87 | 6 |  |  |  |  | 10 | $acl_short = $args{acl_short}; | 
| 88 | 6 |  |  |  |  | 11 | delete $args{acl_short}; | 
| 89 |  |  |  |  |  |  | } | 
| 90 | 6 |  | 50 |  |  | 39 | $args{Net::Amazon::S3::Constants->HEADER_METADATA_DIRECTIVE} ||= 'REPLACE'; | 
| 91 |  |  |  |  |  |  | } | 
| 92 |  |  |  |  |  |  |  | 
| 93 | 6 |  |  |  |  | 18 | $args{Net::Amazon::S3::Constants->HEADER_COPY_SOURCE} = $source; | 
| 94 |  |  |  |  |  |  |  | 
| 95 | 6 |  |  |  |  | 21 | my $encryption = delete $args{encryption}; | 
| 96 |  |  |  |  |  |  |  | 
| 97 | 6 |  |  |  |  | 201 | my $acct    = $self->account; | 
| 98 | 6 |  |  |  |  | 26 | my $response = $self->_perform_operation ( | 
| 99 |  |  |  |  |  |  | 'Net::Amazon::S3::Operation::Object::Add', | 
| 100 |  |  |  |  |  |  |  | 
| 101 |  |  |  |  |  |  | value     => '', | 
| 102 |  |  |  |  |  |  | key       => $key, | 
| 103 |  |  |  |  |  |  | acl_short => $acl_short, | 
| 104 |  |  |  |  |  |  | (encryption => $encryption) x!! defined $encryption, | 
| 105 |  |  |  |  |  |  | headers   => \%args, | 
| 106 |  |  |  |  |  |  | ); | 
| 107 |  |  |  |  |  |  |  | 
| 108 | 0 | 0 |  |  |  | 0 | return unless $response->is_success; | 
| 109 |  |  |  |  |  |  | } | 
| 110 |  |  |  |  |  |  |  | 
| 111 |  |  |  |  |  |  | sub edit_metadata { | 
| 112 | 2 |  |  | 2 | 1 | 5 | my $self = shift; | 
| 113 | 2 |  |  |  |  | 12 | my %args = Net::Amazon::S3::Utils->parse_arguments_with_object (\@_); | 
| 114 |  |  |  |  |  |  |  | 
| 115 | 2 |  |  |  |  | 10 | my $key = delete $args{key}; | 
| 116 | 2 | 50 |  |  |  | 5 | croak "Need some metadata to change" unless %args; | 
| 117 |  |  |  |  |  |  |  | 
| 118 | 2 |  |  |  |  | 66 | return $self->copy_key ( | 
| 119 |  |  |  |  |  |  | key    => $key, | 
| 120 |  |  |  |  |  |  | source => "/" . $self->bucket . "/" . $key, | 
| 121 |  |  |  |  |  |  | %args, | 
| 122 |  |  |  |  |  |  | ); | 
| 123 |  |  |  |  |  |  | } | 
| 124 |  |  |  |  |  |  |  | 
| 125 |  |  |  |  |  |  | sub head_key { | 
| 126 | 9 |  |  | 9 | 1 | 22 | my $self = shift; | 
| 127 | 9 |  |  |  |  | 68 | my %args = Net::Amazon::S3::Utils->parse_arguments_with_object (\@_); | 
| 128 |  |  |  |  |  |  |  | 
| 129 | 9 |  |  |  |  | 54 | return $self->get_key (%args, method => 'HEAD', filename => undef); | 
| 130 |  |  |  |  |  |  | } | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | sub query_string_authentication_uri { | 
| 133 | 4 |  |  | 4 | 1 | 10 | my $self = shift; | 
| 134 | 4 |  |  |  |  | 42 | my %args = Net::Amazon::S3::Utils->parse_arguments (\@_, ['key', 'expires_at']); | 
| 135 |  |  |  |  |  |  |  | 
| 136 | 4 | 100 |  |  |  | 29 | $args{method} = 'GET' unless exists $args{method}; | 
| 137 |  |  |  |  |  |  |  | 
| 138 |  |  |  |  |  |  | my $request = Net::Amazon::S3::Operation::Object::Fetch::Request->new ( | 
| 139 |  |  |  |  |  |  | s3     => $self->account, | 
| 140 |  |  |  |  |  |  | bucket => $self, | 
| 141 |  |  |  |  |  |  | key    => $args{key}, | 
| 142 |  |  |  |  |  |  | method => $args{method}, | 
| 143 | 4 |  |  |  |  | 159 | ); | 
| 144 |  |  |  |  |  |  |  | 
| 145 | 4 |  |  |  |  | 82 | return $request->query_string_authentication_uri ($args{expires_at}); | 
| 146 |  |  |  |  |  |  | } | 
| 147 |  |  |  |  |  |  |  | 
| 148 |  |  |  |  |  |  | sub get_key { | 
| 149 | 22 |  |  | 22 | 1 | 53 | my $self = shift; | 
| 150 | 22 |  |  |  |  | 137 | my %args = Net::Amazon::S3::Utils->parse_arguments (\@_, ['key', 'method', 'filename']); | 
| 151 |  |  |  |  |  |  |  | 
| 152 | 3 |  |  |  |  | 10 | $args{filename} = ${ delete $args{filename} } | 
| 153 | 22 | 100 |  |  |  | 89 | if ref $args{filename}; | 
| 154 |  |  |  |  |  |  |  | 
| 155 | 22 |  | 50 |  |  | 71 | $args{method} ||= 'GET'; | 
| 156 |  |  |  |  |  |  |  | 
| 157 |  |  |  |  |  |  | my $response = $self->_perform_operation ( | 
| 158 |  |  |  |  |  |  | 'Net::Amazon::S3::Operation::Object::Fetch', | 
| 159 |  |  |  |  |  |  |  | 
| 160 |  |  |  |  |  |  | filename => $args{filename}, | 
| 161 |  |  |  |  |  |  |  | 
| 162 |  |  |  |  |  |  | key    => $args{key}, | 
| 163 |  |  |  |  |  |  | method => $args{method}, | 
| 164 | 22 |  |  |  |  | 102 | ); | 
| 165 |  |  |  |  |  |  |  | 
| 166 | 6 | 100 |  |  |  | 40 | return unless $response->is_success; | 
| 167 | 2 |  |  |  |  | 58 | my $etag = $response->etag; | 
| 168 |  |  |  |  |  |  |  | 
| 169 | 2 |  |  |  |  | 5 | my $return; | 
| 170 | 2 |  |  |  |  | 25 | foreach my $header ($response->headers->header_field_names) { | 
| 171 | 12 |  |  |  |  | 614 | $return->{ lc $header } = $response->header ($header); | 
| 172 |  |  |  |  |  |  | } | 
| 173 | 2 |  | 50 |  |  | 120 | $return->{content_length} = $response->content_length || 0; | 
| 174 | 2 |  |  |  |  | 78 | $return->{content_type}   = $response->content_type; | 
| 175 | 2 |  |  |  |  | 63 | $return->{etag}           = $etag; | 
| 176 | 2 |  |  |  |  | 19 | $return->{value}          = $response->content; | 
| 177 |  |  |  |  |  |  |  | 
| 178 | 2 |  |  |  |  | 57 | return $return; | 
| 179 |  |  |  |  |  |  |  | 
| 180 |  |  |  |  |  |  | } | 
| 181 |  |  |  |  |  |  |  | 
| 182 |  |  |  |  |  |  | sub get_key_filename { | 
| 183 | 1 |  |  | 1 | 1 | 3 | my $self = shift; | 
| 184 | 1 |  |  |  |  | 8 | my %args = Net::Amazon::S3::Utils->parse_arguments (\@_, ['key', 'method', 'filename']); | 
| 185 |  |  |  |  |  |  |  | 
| 186 | 1 |  |  |  |  | 5 | $args{filename} = \ delete $args{filename}; | 
| 187 | 1 |  |  |  |  | 6 | return $self->get_key (%args); | 
| 188 |  |  |  |  |  |  | } | 
| 189 |  |  |  |  |  |  |  | 
| 190 |  |  |  |  |  |  | # returns bool | 
| 191 |  |  |  |  |  |  | sub delete_multi_object { | 
| 192 | 5 |  |  | 5 | 0 | 22 | my $self = shift; | 
| 193 | 5 |  |  |  |  | 20 | my @objects = @_; | 
| 194 | 5 | 50 |  |  |  | 27 | return unless( scalar(@objects) ); | 
| 195 |  |  |  |  |  |  |  | 
| 196 |  |  |  |  |  |  | # Since delete can handle up to 1000 requests, be a little bit nicer | 
| 197 |  |  |  |  |  |  | # and slice up requests and also allow keys to be strings | 
| 198 |  |  |  |  |  |  | # rather than only objects. | 
| 199 | 5 |  |  |  |  | 13 | my $last_result; | 
| 200 | 5 |  |  |  |  | 21 | while (scalar(@objects) > 0) { | 
| 201 |  |  |  |  |  |  | my $response = $self->_perform_operation ( | 
| 202 |  |  |  |  |  |  | 'Net::Amazon::S3::Operation::Objects::Delete', | 
| 203 |  |  |  |  |  |  |  | 
| 204 |  |  |  |  |  |  | keys    => [ | 
| 205 | 5 | 50 |  |  |  | 29 | map { ref ($_) ? $_->key : $_ } | 
|  | 11 | 50 |  |  |  | 56 |  | 
| 206 |  |  |  |  |  |  | splice @objects, 0, ((scalar(@objects) > 1000) ? 1000 : scalar(@objects)) | 
| 207 |  |  |  |  |  |  | ] | 
| 208 |  |  |  |  |  |  | ); | 
| 209 |  |  |  |  |  |  |  | 
| 210 | 4 | 100 |  |  |  | 43 | return unless $response->is_success; | 
| 211 |  |  |  |  |  |  | } | 
| 212 |  |  |  |  |  |  |  | 
| 213 | 1 |  |  |  |  | 208 | return 1; | 
| 214 |  |  |  |  |  |  | } | 
| 215 |  |  |  |  |  |  |  | 
| 216 |  |  |  |  |  |  | sub delete_key { | 
| 217 | 9 |  |  | 9 | 1 | 24 | my $self = shift; | 
| 218 | 9 |  |  |  |  | 94 | my %args = Net::Amazon::S3::Utils->parse_arguments_with_object (\@_); | 
| 219 |  |  |  |  |  |  |  | 
| 220 | 9 | 50 | 33 |  |  | 63 | croak 'must specify key' unless defined $args{key} && length $args{key}; | 
| 221 |  |  |  |  |  |  |  | 
| 222 | 9 |  |  |  |  | 44 | my $response = $self->_perform_operation ( | 
| 223 |  |  |  |  |  |  | 'Net::Amazon::S3::Operation::Object::Delete', | 
| 224 |  |  |  |  |  |  | %args, | 
| 225 |  |  |  |  |  |  | ); | 
| 226 |  |  |  |  |  |  |  | 
| 227 | 5 |  |  |  |  | 51 | return $response->is_success; | 
| 228 |  |  |  |  |  |  | } | 
| 229 |  |  |  |  |  |  |  | 
| 230 |  |  |  |  |  |  | sub delete_bucket { | 
| 231 | 1 |  |  | 1 | 1 | 2 | my $self = shift; | 
| 232 | 1 |  |  |  |  | 48 | return $self->account->delete_bucket (bucket => $self, @_); | 
| 233 |  |  |  |  |  |  | } | 
| 234 |  |  |  |  |  |  |  | 
| 235 |  |  |  |  |  |  | sub list { | 
| 236 | 2 |  |  | 2 | 1 | 5 | my $self = shift; | 
| 237 | 2 |  |  |  |  | 17 | my %args = Net::Amazon::S3::Utils->parse_arguments (\@_); | 
| 238 |  |  |  |  |  |  |  | 
| 239 | 2 |  |  |  |  | 80 | return $self->account->list_bucket ($self, %args); | 
| 240 |  |  |  |  |  |  | } | 
| 241 |  |  |  |  |  |  |  | 
| 242 |  |  |  |  |  |  | sub list_all { | 
| 243 | 2 |  |  | 2 | 1 | 4 | my $self = shift; | 
| 244 | 2 |  |  |  |  | 12 | my %args = Net::Amazon::S3::Utils->parse_arguments (\@_); | 
| 245 |  |  |  |  |  |  |  | 
| 246 | 2 |  |  |  |  | 65 | return $self->account->list_bucket_all ($self, %args); | 
| 247 |  |  |  |  |  |  | } | 
| 248 |  |  |  |  |  |  |  | 
| 249 |  |  |  |  |  |  | sub get_acl { | 
| 250 | 14 |  |  | 14 | 1 | 40 | my $self = shift; | 
| 251 | 14 |  |  |  |  | 159 | my %args = Net::Amazon::S3::Utils->parse_arguments_with_object (\@_); | 
| 252 |  |  |  |  |  |  |  | 
| 253 | 14 |  |  |  |  | 47 | my $response; | 
| 254 | 14 | 100 |  |  |  | 60 | if (defined $args{key}) { | 
| 255 | 8 |  |  |  |  | 45 | $response = $self->_perform_operation ( | 
| 256 |  |  |  |  |  |  | 'Net::Amazon::S3::Operation::Object::Acl::Fetch', | 
| 257 |  |  |  |  |  |  | %args, | 
| 258 |  |  |  |  |  |  | ); | 
| 259 |  |  |  |  |  |  | } else { | 
| 260 | 6 |  |  |  |  | 16 | delete $args{key}; | 
| 261 | 6 |  |  |  |  | 31 | $response = $self->_perform_operation ( | 
| 262 |  |  |  |  |  |  | 'Net::Amazon::S3::Operation::Bucket::Acl::Fetch', | 
| 263 |  |  |  |  |  |  | %args, | 
| 264 |  |  |  |  |  |  | ); | 
| 265 |  |  |  |  |  |  | } | 
| 266 |  |  |  |  |  |  |  | 
| 267 | 5 | 100 |  |  |  | 54 | return unless $response->is_success; | 
| 268 | 2 |  |  |  |  | 73 | return $response->content; | 
| 269 |  |  |  |  |  |  | } | 
| 270 |  |  |  |  |  |  |  | 
| 271 |  |  |  |  |  |  | sub set_acl { | 
| 272 | 24 |  |  | 24 | 1 | 57 | my $self = shift; | 
| 273 | 24 |  |  |  |  | 193 | my %args = Net::Amazon::S3::Utils->parse_arguments_with_object (\@_); | 
| 274 |  |  |  |  |  |  |  | 
| 275 | 24 |  |  |  |  | 101 | my $response; | 
| 276 | 24 | 100 |  |  |  | 87 | if (defined $args{key}) { | 
| 277 | 13 |  |  |  |  | 51 | $response = $self->_perform_operation ( | 
| 278 |  |  |  |  |  |  | 'Net::Amazon::S3::Operation::Object::Acl::Set', | 
| 279 |  |  |  |  |  |  | %args, | 
| 280 |  |  |  |  |  |  | ); | 
| 281 |  |  |  |  |  |  | } else { | 
| 282 | 11 |  |  |  |  | 24 | delete $args{key}; | 
| 283 | 11 |  |  |  |  | 43 | $response = $self->_perform_operation ( | 
| 284 |  |  |  |  |  |  | 'Net::Amazon::S3::Operation::Bucket::Acl::Set', | 
| 285 |  |  |  |  |  |  | %args, | 
| 286 |  |  |  |  |  |  | ); | 
| 287 |  |  |  |  |  |  | } | 
| 288 |  |  |  |  |  |  |  | 
| 289 | 18 | 100 |  |  |  | 1523 | return unless $response->is_success; | 
| 290 | 11 |  |  |  |  | 248 | return 1; | 
| 291 |  |  |  |  |  |  | } | 
| 292 |  |  |  |  |  |  |  | 
| 293 |  |  |  |  |  |  | sub get_location_constraint { | 
| 294 | 2 |  |  | 2 | 1 | 4 | my $self = shift; | 
| 295 | 2 |  |  |  |  | 19 | my %args = Net::Amazon::S3::Utils->parse_arguments (\@_); | 
| 296 |  |  |  |  |  |  |  | 
| 297 | 2 |  |  |  |  | 11 | my $response = $self->_perform_operation ( | 
| 298 |  |  |  |  |  |  | 'Net::Amazon::S3::Operation::Bucket::Location', | 
| 299 |  |  |  |  |  |  | %args, | 
| 300 |  |  |  |  |  |  | ); | 
| 301 |  |  |  |  |  |  |  | 
| 302 | 0 | 0 |  |  |  | 0 | return unless $response->is_success; | 
| 303 | 0 |  |  |  |  | 0 | return $response->location; | 
| 304 |  |  |  |  |  |  | } | 
| 305 |  |  |  |  |  |  |  | 
| 306 |  |  |  |  |  |  | sub add_tags { | 
| 307 | 14 |  |  | 14 | 1 | 40 | my $self = shift; | 
| 308 | 14 | 100 |  |  |  | 65 | my %args = @_ == 1 ? %{ $_[0] } : @_; | 
|  | 11 |  |  |  |  | 132 |  | 
| 309 |  |  |  |  |  |  |  | 
| 310 | 14 |  |  |  |  | 31 | my $response; | 
| 311 | 14 | 100 |  |  |  | 50 | if (defined $args{key}) { | 
| 312 | 8 |  |  |  |  | 52 | $response = $self->_perform_operation ( | 
| 313 |  |  |  |  |  |  | 'Net::Amazon::S3::Operation::Object::Tags::Add', | 
| 314 |  |  |  |  |  |  | %args, | 
| 315 |  |  |  |  |  |  | ); | 
| 316 |  |  |  |  |  |  | } else { | 
| 317 | 6 |  |  |  |  | 13 | delete $args{key}; | 
| 318 | 6 |  |  |  |  | 21 | $response = $self->_perform_operation ( | 
| 319 |  |  |  |  |  |  | 'Net::Amazon::S3::Operation::Bucket::Tags::Add', | 
| 320 |  |  |  |  |  |  | %args, | 
| 321 |  |  |  |  |  |  | ); | 
| 322 |  |  |  |  |  |  | } | 
| 323 |  |  |  |  |  |  |  | 
| 324 | 8 |  |  |  |  | 53 | return $response->is_success; | 
| 325 |  |  |  |  |  |  | } | 
| 326 |  |  |  |  |  |  |  | 
| 327 |  |  |  |  |  |  | sub delete_tags { | 
| 328 | 15 |  |  | 15 | 1 | 42 | my $self = shift; | 
| 329 | 15 |  |  |  |  | 141 | my %args = Net::Amazon::S3::Utils->parse_arguments_with_object (\@_); | 
| 330 |  |  |  |  |  |  |  | 
| 331 | 15 |  |  |  |  | 57 | my $response; | 
| 332 | 15 | 100 |  |  |  | 52 | if (defined $args{key}) { | 
| 333 | 9 |  |  |  |  | 51 | $response = $self->_perform_operation ( | 
| 334 |  |  |  |  |  |  | 'Net::Amazon::S3::Operation::Object::Tags::Delete', | 
| 335 |  |  |  |  |  |  | %args, | 
| 336 |  |  |  |  |  |  | ); | 
| 337 |  |  |  |  |  |  | } else { | 
| 338 | 6 |  |  |  |  | 17 | delete $args{key}; | 
| 339 | 6 |  |  |  |  | 29 | $response = $self->_perform_operation ( | 
| 340 |  |  |  |  |  |  | 'Net::Amazon::S3::Operation::Bucket::Tags::Delete', | 
| 341 |  |  |  |  |  |  | %args, | 
| 342 |  |  |  |  |  |  | ); | 
| 343 |  |  |  |  |  |  | } | 
| 344 |  |  |  |  |  |  |  | 
| 345 | 9 |  |  |  |  | 115 | return $response->is_success; | 
| 346 |  |  |  |  |  |  | } | 
| 347 |  |  |  |  |  |  |  | 
| 348 |  |  |  |  |  |  | sub _content_sub { | 
| 349 | 3 |  |  | 3 |  | 7 | my $filename  = shift; | 
| 350 | 3 |  |  |  |  | 16 | my $stat      = stat($filename); | 
| 351 | 3 |  |  |  |  | 512 | my $remaining = $stat->size; | 
| 352 | 3 |  | 50 |  |  | 49 | my $blksize   = $stat->blksize || 4096; | 
| 353 |  |  |  |  |  |  |  | 
| 354 | 3 | 50 | 33 |  |  | 81 | croak "$filename not a readable file with fixed size" | 
|  |  |  | 33 |  |  |  |  | 
| 355 |  |  |  |  |  |  | unless -r $filename and ( -f _ || $remaining ); | 
| 356 | 3 | 50 |  |  |  | 26 | my $fh = IO::File->new( $filename, 'r' ) | 
| 357 |  |  |  |  |  |  | or croak "Could not open $filename: $!"; | 
| 358 | 3 |  |  |  |  | 357 | $fh->binmode; | 
| 359 |  |  |  |  |  |  |  | 
| 360 |  |  |  |  |  |  | return sub { | 
| 361 | 0 |  |  | 0 |  | 0 | my $buffer; | 
| 362 |  |  |  |  |  |  |  | 
| 363 |  |  |  |  |  |  | # upon retries the file is closed and we must reopen it | 
| 364 | 0 | 0 |  |  |  | 0 | unless ( $fh->opened ) { | 
| 365 | 0 | 0 |  |  |  | 0 | $fh = IO::File->new( $filename, 'r' ) | 
| 366 |  |  |  |  |  |  | or croak "Could not open $filename: $!"; | 
| 367 | 0 |  |  |  |  | 0 | $fh->binmode; | 
| 368 | 0 |  |  |  |  | 0 | $remaining = $stat->size; | 
| 369 |  |  |  |  |  |  | } | 
| 370 |  |  |  |  |  |  |  | 
| 371 |  |  |  |  |  |  | # warn "read remaining $remaining"; | 
| 372 | 0 | 0 |  |  |  | 0 | unless ( my $read = $fh->read( $buffer, $blksize ) ) { | 
| 373 |  |  |  |  |  |  |  | 
| 374 |  |  |  |  |  |  | #                       warn "read $read buffer $buffer remaining $remaining"; | 
| 375 | 0 | 0 | 0 |  |  | 0 | croak | 
| 376 |  |  |  |  |  |  | "Error while reading upload content $filename ($remaining remaining) $!" | 
| 377 |  |  |  |  |  |  | if $! and $remaining; | 
| 378 |  |  |  |  |  |  |  | 
| 379 |  |  |  |  |  |  | # otherwise, we found EOF | 
| 380 | 0 | 0 |  |  |  | 0 | $fh->close | 
| 381 |  |  |  |  |  |  | or croak "close of upload content $filename failed: $!"; | 
| 382 | 0 |  | 0 |  |  | 0 | $buffer ||= '' | 
| 383 |  |  |  |  |  |  | ;    # LWP expects an emptry string on finish, read returns 0 | 
| 384 |  |  |  |  |  |  | } | 
| 385 | 0 |  |  |  |  | 0 | $remaining -= length($buffer); | 
| 386 | 0 |  |  |  |  | 0 | return $buffer; | 
| 387 | 3 |  |  |  |  | 41 | }; | 
| 388 |  |  |  |  |  |  | } | 
| 389 |  |  |  |  |  |  |  | 
| 390 |  |  |  |  |  |  | sub _head_region { | 
| 391 | 1 |  |  | 1 |  | 5 | my ($self) = @_; | 
| 392 |  |  |  |  |  |  |  | 
| 393 | 1 | 50 |  |  |  | 29 | my $protocol = $self->account->secure ? 'https' : 'http'; | 
| 394 | 1 |  |  |  |  | 27 | my $host = $self->account->host; | 
| 395 | 1 |  |  |  |  | 48 | my $path = $self->bucket; | 
| 396 | 1 |  |  |  |  | 7 | my @retry = (1, 2, (4) x 8); | 
| 397 |  |  |  |  |  |  |  | 
| 398 | 1 | 50 |  |  |  | 46 | if ($self->account->use_virtual_host) { | 
| 399 | 1 |  |  |  |  | 6 | $host = "$path.$host"; | 
| 400 | 1 |  |  |  |  | 3 | $path = ''; | 
| 401 |  |  |  |  |  |  | } | 
| 402 |  |  |  |  |  |  |  | 
| 403 | 1 |  |  |  |  | 5 | my $request_uri = "${protocol}://${host}/$path"; | 
| 404 | 1 |  |  |  |  | 4 | while (@retry) { | 
| 405 | 1 |  |  |  |  | 14 | my $request = HTTP::Request->new (HEAD => $request_uri); | 
| 406 |  |  |  |  |  |  |  | 
| 407 |  |  |  |  |  |  | # Disable redirects | 
| 408 | 1 |  |  |  |  | 9508 | my $requests_redirectable = $self->account->ua->requests_redirectable; | 
| 409 | 1 |  |  |  |  | 56 | $self->account->ua->requests_redirectable( [] ); | 
| 410 |  |  |  |  |  |  |  | 
| 411 | 1 |  |  |  |  | 48 | my $response = $self->account->ua->request ($request); | 
| 412 |  |  |  |  |  |  |  | 
| 413 | 1 |  |  |  |  | 1721 | $self->account->ua->requests_redirectable( $requests_redirectable ); | 
| 414 |  |  |  |  |  |  |  | 
| 415 | 1 | 50 |  |  |  | 29 | return $response->header (Net::Amazon::S3::Constants->HEADER_BUCKET_REGION) | 
| 416 |  |  |  |  |  |  | if $response->header (Net::Amazon::S3::Constants->HEADER_BUCKET_REGION); | 
| 417 |  |  |  |  |  |  |  | 
| 418 | 0 |  |  |  |  | 0 | print STDERR "Invalid bucket head response; $request_uri\n"; | 
| 419 | 0 |  |  |  |  | 0 | print STDERR $response->as_string; | 
| 420 |  |  |  |  |  |  |  | 
| 421 | 0 |  |  |  |  | 0 | sleep shift @retry; | 
| 422 |  |  |  |  |  |  | } | 
| 423 |  |  |  |  |  |  |  | 
| 424 | 0 |  |  |  |  | 0 | die "Cannot determine bucket region; bucket=${\ $self->bucket }"; | 
|  | 0 |  |  |  |  | 0 |  | 
| 425 |  |  |  |  |  |  | } | 
| 426 |  |  |  |  |  |  |  | 
| 427 |  |  |  |  |  |  | sub _perform_operation { | 
| 428 | 128 |  |  | 128 |  | 521 | my ($self, $operation, %params) = @_; | 
| 429 |  |  |  |  |  |  |  | 
| 430 | 128 |  |  |  |  | 4547 | $self->account->_perform_operation ($operation => ( | 
| 431 |  |  |  |  |  |  | bucket => $self, | 
| 432 |  |  |  |  |  |  | %params, | 
| 433 |  |  |  |  |  |  | )); | 
| 434 |  |  |  |  |  |  | } | 
| 435 |  |  |  |  |  |  |  | 
| 436 |  |  |  |  |  |  | 1; | 
| 437 |  |  |  |  |  |  |  | 
| 438 |  |  |  |  |  |  | __END__ | 
| 439 |  |  |  |  |  |  |  | 
| 440 |  |  |  |  |  |  | =pod | 
| 441 |  |  |  |  |  |  |  | 
| 442 |  |  |  |  |  |  | =encoding UTF-8 | 
| 443 |  |  |  |  |  |  |  | 
| 444 |  |  |  |  |  |  | =head1 NAME | 
| 445 |  |  |  |  |  |  |  | 
| 446 |  |  |  |  |  |  | Net::Amazon::S3::Bucket - convenience object for working with Amazon S3 buckets | 
| 447 |  |  |  |  |  |  |  | 
| 448 |  |  |  |  |  |  | =head1 VERSION | 
| 449 |  |  |  |  |  |  |  | 
| 450 |  |  |  |  |  |  | version 0.98 | 
| 451 |  |  |  |  |  |  |  | 
| 452 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 453 |  |  |  |  |  |  |  | 
| 454 |  |  |  |  |  |  | use Net::Amazon::S3; | 
| 455 |  |  |  |  |  |  |  | 
| 456 |  |  |  |  |  |  | my $bucket = $s3->bucket("foo"); | 
| 457 |  |  |  |  |  |  |  | 
| 458 |  |  |  |  |  |  | ok($bucket->add_key("key", "data")); | 
| 459 |  |  |  |  |  |  | ok($bucket->add_key("key", "data", { | 
| 460 |  |  |  |  |  |  | content_type => "text/html", | 
| 461 |  |  |  |  |  |  | 'x-amz-meta-colour' => 'orange', | 
| 462 |  |  |  |  |  |  | })); | 
| 463 |  |  |  |  |  |  |  | 
| 464 |  |  |  |  |  |  | # Enable server-side encryption | 
| 465 |  |  |  |  |  |  | ok($bucket->add_key("key", "data", { | 
| 466 |  |  |  |  |  |  | encryption => 'AES256', | 
| 467 |  |  |  |  |  |  | })); | 
| 468 |  |  |  |  |  |  |  | 
| 469 |  |  |  |  |  |  | # the err and errstr methods just proxy up to the Net::Amazon::S3's | 
| 470 |  |  |  |  |  |  | # objects err/errstr methods. | 
| 471 |  |  |  |  |  |  | $bucket->add_key("bar", "baz") or | 
| 472 |  |  |  |  |  |  | die $bucket->err . $bucket->errstr; | 
| 473 |  |  |  |  |  |  |  | 
| 474 |  |  |  |  |  |  | # fetch a key | 
| 475 |  |  |  |  |  |  | $val = $bucket->get_key("key"); | 
| 476 |  |  |  |  |  |  | is( $val->{value},               'data' ); | 
| 477 |  |  |  |  |  |  | is( $val->{content_type},        'text/html' ); | 
| 478 |  |  |  |  |  |  | is( $val->{etag},                'b9ece18c950afbfa6b0fdbfa4ff731d3' ); | 
| 479 |  |  |  |  |  |  | is( $val->{'x-amz-meta-colour'}, 'orange' ); | 
| 480 |  |  |  |  |  |  |  | 
| 481 |  |  |  |  |  |  | # returns undef on missing or on error (check $bucket->err) | 
| 482 |  |  |  |  |  |  | is(undef, $bucket->get_key("non-existing-key")); | 
| 483 |  |  |  |  |  |  | die $bucket->errstr if $bucket->err; | 
| 484 |  |  |  |  |  |  |  | 
| 485 |  |  |  |  |  |  | # fetch a key's metadata | 
| 486 |  |  |  |  |  |  | $val = $bucket->head_key("key"); | 
| 487 |  |  |  |  |  |  | is( $val->{value},               '' ); | 
| 488 |  |  |  |  |  |  | is( $val->{content_type},        'text/html' ); | 
| 489 |  |  |  |  |  |  | is( $val->{etag},                'b9ece18c950afbfa6b0fdbfa4ff731d3' ); | 
| 490 |  |  |  |  |  |  | is( $val->{'x-amz-meta-colour'}, 'orange' ); | 
| 491 |  |  |  |  |  |  |  | 
| 492 |  |  |  |  |  |  | # delete a key | 
| 493 |  |  |  |  |  |  | ok($bucket->delete_key($key_name)); | 
| 494 |  |  |  |  |  |  | ok(! $bucket->delete_key("non-exist-key")); | 
| 495 |  |  |  |  |  |  |  | 
| 496 |  |  |  |  |  |  | # delete the entire bucket (Amazon requires it first be empty) | 
| 497 |  |  |  |  |  |  | $bucket->delete_bucket; | 
| 498 |  |  |  |  |  |  |  | 
| 499 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 500 |  |  |  |  |  |  |  | 
| 501 |  |  |  |  |  |  | This module represents an S3 bucket.  You get a bucket object | 
| 502 |  |  |  |  |  |  | from the Net::Amazon::S3 object. | 
| 503 |  |  |  |  |  |  |  | 
| 504 |  |  |  |  |  |  | =head1 METHODS | 
| 505 |  |  |  |  |  |  |  | 
| 506 |  |  |  |  |  |  | =head2 new | 
| 507 |  |  |  |  |  |  |  | 
| 508 |  |  |  |  |  |  | Create a new bucket object. Expects a hash containing these two arguments: | 
| 509 |  |  |  |  |  |  |  | 
| 510 |  |  |  |  |  |  | =over | 
| 511 |  |  |  |  |  |  |  | 
| 512 |  |  |  |  |  |  | =item bucket | 
| 513 |  |  |  |  |  |  |  | 
| 514 |  |  |  |  |  |  | =item account | 
| 515 |  |  |  |  |  |  |  | 
| 516 |  |  |  |  |  |  | =back | 
| 517 |  |  |  |  |  |  |  | 
| 518 |  |  |  |  |  |  | =head2 add_key | 
| 519 |  |  |  |  |  |  |  | 
| 520 |  |  |  |  |  |  | Takes three positional parameters: | 
| 521 |  |  |  |  |  |  |  | 
| 522 |  |  |  |  |  |  | =over | 
| 523 |  |  |  |  |  |  |  | 
| 524 |  |  |  |  |  |  | =item key | 
| 525 |  |  |  |  |  |  |  | 
| 526 |  |  |  |  |  |  | =item value | 
| 527 |  |  |  |  |  |  |  | 
| 528 |  |  |  |  |  |  | =item configuration | 
| 529 |  |  |  |  |  |  |  | 
| 530 |  |  |  |  |  |  | A hash of configuration data for this key. | 
| 531 |  |  |  |  |  |  |  | 
| 532 |  |  |  |  |  |  | =over | 
| 533 |  |  |  |  |  |  |  | 
| 534 |  |  |  |  |  |  | =item acl | 
| 535 |  |  |  |  |  |  |  | 
| 536 |  |  |  |  |  |  | =item encryption | 
| 537 |  |  |  |  |  |  |  | 
| 538 |  |  |  |  |  |  | =item any additional HTTP header | 
| 539 |  |  |  |  |  |  |  | 
| 540 |  |  |  |  |  |  | =back | 
| 541 |  |  |  |  |  |  |  | 
| 542 |  |  |  |  |  |  | See L<Net::Amazon::S3::Operation::Object::Add::Request> for details | 
| 543 |  |  |  |  |  |  |  | 
| 544 |  |  |  |  |  |  | =back | 
| 545 |  |  |  |  |  |  |  | 
| 546 |  |  |  |  |  |  | Returns a boolean. | 
| 547 |  |  |  |  |  |  |  | 
| 548 |  |  |  |  |  |  | =head2 add_key_filename | 
| 549 |  |  |  |  |  |  |  | 
| 550 |  |  |  |  |  |  | Use this to upload a large file to S3. Takes three positional parameters: | 
| 551 |  |  |  |  |  |  |  | 
| 552 |  |  |  |  |  |  | =over | 
| 553 |  |  |  |  |  |  |  | 
| 554 |  |  |  |  |  |  | =item key | 
| 555 |  |  |  |  |  |  |  | 
| 556 |  |  |  |  |  |  | =item filename | 
| 557 |  |  |  |  |  |  |  | 
| 558 |  |  |  |  |  |  | =item configuration | 
| 559 |  |  |  |  |  |  |  | 
| 560 |  |  |  |  |  |  | A hash of configuration data for this key. (See synopsis); | 
| 561 |  |  |  |  |  |  |  | 
| 562 |  |  |  |  |  |  | =back | 
| 563 |  |  |  |  |  |  |  | 
| 564 |  |  |  |  |  |  | Returns a boolean. | 
| 565 |  |  |  |  |  |  |  | 
| 566 |  |  |  |  |  |  | =head2 copy_key | 
| 567 |  |  |  |  |  |  |  | 
| 568 |  |  |  |  |  |  | Creates (or replaces) a key, copying its contents from another key elsewhere in S3. | 
| 569 |  |  |  |  |  |  | Takes the following parameters: | 
| 570 |  |  |  |  |  |  |  | 
| 571 |  |  |  |  |  |  | =over | 
| 572 |  |  |  |  |  |  |  | 
| 573 |  |  |  |  |  |  | =item key | 
| 574 |  |  |  |  |  |  |  | 
| 575 |  |  |  |  |  |  | The key to (over)write | 
| 576 |  |  |  |  |  |  |  | 
| 577 |  |  |  |  |  |  | =item source | 
| 578 |  |  |  |  |  |  |  | 
| 579 |  |  |  |  |  |  | Where to copy the key from. Should be in the form C</I<bucketname>/I<keyname>>/. | 
| 580 |  |  |  |  |  |  |  | 
| 581 |  |  |  |  |  |  | =item conf | 
| 582 |  |  |  |  |  |  |  | 
| 583 |  |  |  |  |  |  | Optional configuration hash. If present and defined, the configuration (ACL | 
| 584 |  |  |  |  |  |  | and headers) there will be used for the new key; otherwise it will be copied | 
| 585 |  |  |  |  |  |  | from the source key. | 
| 586 |  |  |  |  |  |  |  | 
| 587 |  |  |  |  |  |  | =back | 
| 588 |  |  |  |  |  |  |  | 
| 589 |  |  |  |  |  |  | =head2 edit_metadata | 
| 590 |  |  |  |  |  |  |  | 
| 591 |  |  |  |  |  |  | Changes the metadata associated with an existing key. Arguments: | 
| 592 |  |  |  |  |  |  |  | 
| 593 |  |  |  |  |  |  | =over | 
| 594 |  |  |  |  |  |  |  | 
| 595 |  |  |  |  |  |  | =item key | 
| 596 |  |  |  |  |  |  |  | 
| 597 |  |  |  |  |  |  | The key to edit | 
| 598 |  |  |  |  |  |  |  | 
| 599 |  |  |  |  |  |  | =item conf | 
| 600 |  |  |  |  |  |  |  | 
| 601 |  |  |  |  |  |  | The new configuration hash to use | 
| 602 |  |  |  |  |  |  |  | 
| 603 |  |  |  |  |  |  | =back | 
| 604 |  |  |  |  |  |  |  | 
| 605 |  |  |  |  |  |  | =head2 head_key KEY | 
| 606 |  |  |  |  |  |  |  | 
| 607 |  |  |  |  |  |  | Takes the name of a key in this bucket and returns its configuration hash | 
| 608 |  |  |  |  |  |  |  | 
| 609 |  |  |  |  |  |  | =head2 query_string_authentication_uri KEY, EXPIRES_AT | 
| 610 |  |  |  |  |  |  |  | 
| 611 |  |  |  |  |  |  | my $uri = $bucket->query_string_authentication_uri ( | 
| 612 |  |  |  |  |  |  | key => 'foo', | 
| 613 |  |  |  |  |  |  | expires_at => time + 3_600, # valid for one hour | 
| 614 |  |  |  |  |  |  | ); | 
| 615 |  |  |  |  |  |  |  | 
| 616 |  |  |  |  |  |  | my $uri = $bucket->query_string_authentication_uri ( | 
| 617 |  |  |  |  |  |  | key => 'foo', | 
| 618 |  |  |  |  |  |  | expires_at => time + 3_600, | 
| 619 |  |  |  |  |  |  | method => 'PUT', | 
| 620 |  |  |  |  |  |  | ); | 
| 621 |  |  |  |  |  |  |  | 
| 622 |  |  |  |  |  |  | Returns uri presigned with your credentials. | 
| 623 |  |  |  |  |  |  |  | 
| 624 |  |  |  |  |  |  | When used with Signature V4 you have to specify also HTTP method this | 
| 625 |  |  |  |  |  |  | presigned uri will be used for (default: C<GET>) | 
| 626 |  |  |  |  |  |  |  | 
| 627 |  |  |  |  |  |  | Method provides authenticated uri only for direct object operations. | 
| 628 |  |  |  |  |  |  |  | 
| 629 |  |  |  |  |  |  | Method follows API's L</"CALLING CONVENTION">. | 
| 630 |  |  |  |  |  |  |  | 
| 631 |  |  |  |  |  |  | Recognized positional arguments (mandatory). | 
| 632 |  |  |  |  |  |  |  | 
| 633 |  |  |  |  |  |  | =over | 
| 634 |  |  |  |  |  |  |  | 
| 635 |  |  |  |  |  |  | =item key | 
| 636 |  |  |  |  |  |  |  | 
| 637 |  |  |  |  |  |  | =item expires_at | 
| 638 |  |  |  |  |  |  |  | 
| 639 |  |  |  |  |  |  | Expiration time (epoch time). | 
| 640 |  |  |  |  |  |  |  | 
| 641 |  |  |  |  |  |  | =back | 
| 642 |  |  |  |  |  |  |  | 
| 643 |  |  |  |  |  |  | Optional arguments | 
| 644 |  |  |  |  |  |  |  | 
| 645 |  |  |  |  |  |  | =over | 
| 646 |  |  |  |  |  |  |  | 
| 647 |  |  |  |  |  |  | =item method | 
| 648 |  |  |  |  |  |  |  | 
| 649 |  |  |  |  |  |  | Default: C<GET> | 
| 650 |  |  |  |  |  |  |  | 
| 651 |  |  |  |  |  |  | Intended HTTP method this uri will be presigned for. | 
| 652 |  |  |  |  |  |  |  | 
| 653 |  |  |  |  |  |  | Signature V2 doesn't use it but Signature V4 does. | 
| 654 |  |  |  |  |  |  |  | 
| 655 |  |  |  |  |  |  | See L<https://docs.aws.amazon.com/AmazonS3/latest/dev/PresignedUrlUploadObject.html> | 
| 656 |  |  |  |  |  |  |  | 
| 657 |  |  |  |  |  |  | =back | 
| 658 |  |  |  |  |  |  |  | 
| 659 |  |  |  |  |  |  | =head2 get_key $key_name [$method] | 
| 660 |  |  |  |  |  |  |  | 
| 661 |  |  |  |  |  |  | Takes a key name and an optional HTTP method (which defaults to C<GET>. | 
| 662 |  |  |  |  |  |  | Fetches the key from AWS. | 
| 663 |  |  |  |  |  |  |  | 
| 664 |  |  |  |  |  |  | On failure: | 
| 665 |  |  |  |  |  |  |  | 
| 666 |  |  |  |  |  |  | Returns undef on missing content, throws an exception (dies) on server errors. | 
| 667 |  |  |  |  |  |  |  | 
| 668 |  |  |  |  |  |  | On success: | 
| 669 |  |  |  |  |  |  |  | 
| 670 |  |  |  |  |  |  | Returns a hashref of { content_type, etag, value, @meta } on success. Other | 
| 671 |  |  |  |  |  |  | values from the server are there too, with the key being lowercased. | 
| 672 |  |  |  |  |  |  |  | 
| 673 |  |  |  |  |  |  | =head2 get_key_filename $key_name $method $filename | 
| 674 |  |  |  |  |  |  |  | 
| 675 |  |  |  |  |  |  | Use this to download large files from S3. Takes a key name and an optional | 
| 676 |  |  |  |  |  |  | HTTP method (which defaults to C<GET>. Fetches the key from AWS and writes | 
| 677 |  |  |  |  |  |  | it to the filename. THe value returned will be empty. | 
| 678 |  |  |  |  |  |  |  | 
| 679 |  |  |  |  |  |  | On failure: | 
| 680 |  |  |  |  |  |  |  | 
| 681 |  |  |  |  |  |  | Returns undef on missing content, throws an exception (dies) on server errors. | 
| 682 |  |  |  |  |  |  |  | 
| 683 |  |  |  |  |  |  | On success: | 
| 684 |  |  |  |  |  |  |  | 
| 685 |  |  |  |  |  |  | Returns a hashref of { content_type, etag, value, @meta } on success | 
| 686 |  |  |  |  |  |  |  | 
| 687 |  |  |  |  |  |  | =head2 delete_key $key_name | 
| 688 |  |  |  |  |  |  |  | 
| 689 |  |  |  |  |  |  | Removes C<$key> from the bucket. Forever. It's gone after this. | 
| 690 |  |  |  |  |  |  |  | 
| 691 |  |  |  |  |  |  | Returns true on success and false on failure | 
| 692 |  |  |  |  |  |  |  | 
| 693 |  |  |  |  |  |  | =head2 delete_bucket | 
| 694 |  |  |  |  |  |  |  | 
| 695 |  |  |  |  |  |  | Delete the current bucket object from the server. Takes no arguments. | 
| 696 |  |  |  |  |  |  |  | 
| 697 |  |  |  |  |  |  | Fails if the bucket has anything in it. | 
| 698 |  |  |  |  |  |  |  | 
| 699 |  |  |  |  |  |  | This is an alias for C<< $s3->delete_bucket($bucket) >> | 
| 700 |  |  |  |  |  |  |  | 
| 701 |  |  |  |  |  |  | =head2 list | 
| 702 |  |  |  |  |  |  |  | 
| 703 |  |  |  |  |  |  | List all keys in this bucket. | 
| 704 |  |  |  |  |  |  |  | 
| 705 |  |  |  |  |  |  | see L<Net::Amazon::S3/list_bucket> for documentation of this method. | 
| 706 |  |  |  |  |  |  |  | 
| 707 |  |  |  |  |  |  | =head2 list_all | 
| 708 |  |  |  |  |  |  |  | 
| 709 |  |  |  |  |  |  | List all keys in this bucket without having to worry about | 
| 710 |  |  |  |  |  |  | 'marker'. This may make multiple requests to S3 under the hood. | 
| 711 |  |  |  |  |  |  |  | 
| 712 |  |  |  |  |  |  | see L<Net::Amazon::S3/list_bucket_all> for documentation of this method. | 
| 713 |  |  |  |  |  |  |  | 
| 714 |  |  |  |  |  |  | =head2 get_acl | 
| 715 |  |  |  |  |  |  |  | 
| 716 |  |  |  |  |  |  | Takes one optional positional parameter | 
| 717 |  |  |  |  |  |  |  | 
| 718 |  |  |  |  |  |  | =over | 
| 719 |  |  |  |  |  |  |  | 
| 720 |  |  |  |  |  |  | =item key (optional) | 
| 721 |  |  |  |  |  |  |  | 
| 722 |  |  |  |  |  |  | If no key is specified, it returns the acl for the bucket. | 
| 723 |  |  |  |  |  |  |  | 
| 724 |  |  |  |  |  |  | =back | 
| 725 |  |  |  |  |  |  |  | 
| 726 |  |  |  |  |  |  | Returns an acl in XML format. | 
| 727 |  |  |  |  |  |  |  | 
| 728 |  |  |  |  |  |  | =head2 set_acl | 
| 729 |  |  |  |  |  |  |  | 
| 730 |  |  |  |  |  |  | Takes a configuration hash_ref containing: | 
| 731 |  |  |  |  |  |  |  | 
| 732 |  |  |  |  |  |  | =over | 
| 733 |  |  |  |  |  |  |  | 
| 734 |  |  |  |  |  |  | =item acl_xml (cannot be used in conjunction with acl_short) | 
| 735 |  |  |  |  |  |  |  | 
| 736 |  |  |  |  |  |  | An XML string which contains access control information which matches | 
| 737 |  |  |  |  |  |  | Amazon's published schema.  There is an example of one of these XML strings | 
| 738 |  |  |  |  |  |  | in the tests for this module. | 
| 739 |  |  |  |  |  |  |  | 
| 740 |  |  |  |  |  |  | =item acl_short (cannot be used in conjunction with acl_xml) | 
| 741 |  |  |  |  |  |  |  | 
| 742 |  |  |  |  |  |  | You can use the shorthand notation instead of specifying XML for | 
| 743 |  |  |  |  |  |  | certain 'canned' types of acls. | 
| 744 |  |  |  |  |  |  |  | 
| 745 |  |  |  |  |  |  | (from the Amazon API documentation) | 
| 746 |  |  |  |  |  |  |  | 
| 747 |  |  |  |  |  |  | private: Owner gets FULL_CONTROL. No one else has any access rights. | 
| 748 |  |  |  |  |  |  | This is the default. | 
| 749 |  |  |  |  |  |  |  | 
| 750 |  |  |  |  |  |  | public-read:Owner gets FULL_CONTROL and the anonymous principal is granted | 
| 751 |  |  |  |  |  |  | READ access. If this policy is used on an object, it can be read from a | 
| 752 |  |  |  |  |  |  | browser with no authentication. | 
| 753 |  |  |  |  |  |  |  | 
| 754 |  |  |  |  |  |  | public-read-write:Owner gets FULL_CONTROL, the anonymous principal is | 
| 755 |  |  |  |  |  |  | granted READ and WRITE access. This is a useful policy to apply to a bucket, | 
| 756 |  |  |  |  |  |  | if you intend for any anonymous user to PUT objects into the bucket. | 
| 757 |  |  |  |  |  |  |  | 
| 758 |  |  |  |  |  |  | authenticated-read:Owner gets FULL_CONTROL, and any principal authenticated | 
| 759 |  |  |  |  |  |  | as a registered Amazon S3 user is granted READ access. | 
| 760 |  |  |  |  |  |  |  | 
| 761 |  |  |  |  |  |  | =item key (optional) | 
| 762 |  |  |  |  |  |  |  | 
| 763 |  |  |  |  |  |  | If the key is not set, it will apply the acl to the bucket. | 
| 764 |  |  |  |  |  |  |  | 
| 765 |  |  |  |  |  |  | =back | 
| 766 |  |  |  |  |  |  |  | 
| 767 |  |  |  |  |  |  | Returns a boolean. | 
| 768 |  |  |  |  |  |  |  | 
| 769 |  |  |  |  |  |  | =head2 get_location_constraint | 
| 770 |  |  |  |  |  |  |  | 
| 771 |  |  |  |  |  |  | Retrieves the location constraint set when the bucket was created. Returns a | 
| 772 |  |  |  |  |  |  | string (eg, 'EU'), or undef if no location constraint was set. | 
| 773 |  |  |  |  |  |  |  | 
| 774 |  |  |  |  |  |  | =head2 err | 
| 775 |  |  |  |  |  |  |  | 
| 776 |  |  |  |  |  |  | The S3 error code for the last error the object ran into | 
| 777 |  |  |  |  |  |  |  | 
| 778 |  |  |  |  |  |  | =head2 errstr | 
| 779 |  |  |  |  |  |  |  | 
| 780 |  |  |  |  |  |  | A human readable error string for the last error the object ran into | 
| 781 |  |  |  |  |  |  |  | 
| 782 |  |  |  |  |  |  | =head2 add_tags | 
| 783 |  |  |  |  |  |  |  | 
| 784 |  |  |  |  |  |  | # Add tags for a bucket | 
| 785 |  |  |  |  |  |  | $s3->add_tags ({ | 
| 786 |  |  |  |  |  |  | bucket => 'bucket-name', | 
| 787 |  |  |  |  |  |  | tags   => { tag1 => 'value-1', tag2 => 'value-2' }, | 
| 788 |  |  |  |  |  |  | }); | 
| 789 |  |  |  |  |  |  |  | 
| 790 |  |  |  |  |  |  | # Add tags for an object | 
| 791 |  |  |  |  |  |  | $s3->add_tags ({ | 
| 792 |  |  |  |  |  |  | bucket => 'bucket-name', | 
| 793 |  |  |  |  |  |  | key    => 'key', | 
| 794 |  |  |  |  |  |  | tags   => { tag1 => 'value-1', tag2 => 'value-2' }, | 
| 795 |  |  |  |  |  |  | }); | 
| 796 |  |  |  |  |  |  |  | 
| 797 |  |  |  |  |  |  | Takes configuration parameters | 
| 798 |  |  |  |  |  |  |  | 
| 799 |  |  |  |  |  |  | =over | 
| 800 |  |  |  |  |  |  |  | 
| 801 |  |  |  |  |  |  | =item key (optional, scalar) | 
| 802 |  |  |  |  |  |  |  | 
| 803 |  |  |  |  |  |  | If key is specified, add tag(s) to object, otherwise on bucket. | 
| 804 |  |  |  |  |  |  |  | 
| 805 |  |  |  |  |  |  | =item tags (mandatory, hashref) | 
| 806 |  |  |  |  |  |  |  | 
| 807 |  |  |  |  |  |  | Set specified tags and their respective values. | 
| 808 |  |  |  |  |  |  |  | 
| 809 |  |  |  |  |  |  | =item version_id (optional) | 
| 810 |  |  |  |  |  |  |  | 
| 811 |  |  |  |  |  |  | Is specified (in conjunction with C<key>) add tag(s) to versioned object. | 
| 812 |  |  |  |  |  |  |  | 
| 813 |  |  |  |  |  |  | =back | 
| 814 |  |  |  |  |  |  |  | 
| 815 |  |  |  |  |  |  | Returns C<true> on success. | 
| 816 |  |  |  |  |  |  |  | 
| 817 |  |  |  |  |  |  | Returns C<false> and sets C<err>/C<errstr> otherwise. | 
| 818 |  |  |  |  |  |  |  | 
| 819 |  |  |  |  |  |  | =head2 delete_tags | 
| 820 |  |  |  |  |  |  |  | 
| 821 |  |  |  |  |  |  | # Add tags for a bucket | 
| 822 |  |  |  |  |  |  | $s3->delete_tags ({ | 
| 823 |  |  |  |  |  |  | bucket => 'bucket-name', | 
| 824 |  |  |  |  |  |  | }); | 
| 825 |  |  |  |  |  |  |  | 
| 826 |  |  |  |  |  |  | # Add tags for an object | 
| 827 |  |  |  |  |  |  | $s3->delete_tags ({ | 
| 828 |  |  |  |  |  |  | bucket     => 'bucket-name', | 
| 829 |  |  |  |  |  |  | key        => 'key', | 
| 830 |  |  |  |  |  |  | version_id => $version_id, | 
| 831 |  |  |  |  |  |  | }); | 
| 832 |  |  |  |  |  |  |  | 
| 833 |  |  |  |  |  |  | Takes configuration parameters | 
| 834 |  |  |  |  |  |  |  | 
| 835 |  |  |  |  |  |  | =over | 
| 836 |  |  |  |  |  |  |  | 
| 837 |  |  |  |  |  |  | =item key (optional, scalar) | 
| 838 |  |  |  |  |  |  |  | 
| 839 |  |  |  |  |  |  | If key is specified, add tag(s) to object, otherwise on bucket. | 
| 840 |  |  |  |  |  |  |  | 
| 841 |  |  |  |  |  |  | =item version_id (optional) | 
| 842 |  |  |  |  |  |  |  | 
| 843 |  |  |  |  |  |  | Is specified (in conjunction with C<key>) add tag(s) to versioned object. | 
| 844 |  |  |  |  |  |  |  | 
| 845 |  |  |  |  |  |  | =back | 
| 846 |  |  |  |  |  |  |  | 
| 847 |  |  |  |  |  |  | Returns C<true> on success. | 
| 848 |  |  |  |  |  |  |  | 
| 849 |  |  |  |  |  |  | Returns C<false> and sets C<err>/C<errstr> otherwise. | 
| 850 |  |  |  |  |  |  |  | 
| 851 |  |  |  |  |  |  | =head1 SEE ALSO | 
| 852 |  |  |  |  |  |  |  | 
| 853 |  |  |  |  |  |  | L<Net::Amazon::S3> | 
| 854 |  |  |  |  |  |  |  | 
| 855 |  |  |  |  |  |  | =head1 AUTHOR | 
| 856 |  |  |  |  |  |  |  | 
| 857 |  |  |  |  |  |  | Branislav Zahradník <barney@cpan.org> | 
| 858 |  |  |  |  |  |  |  | 
| 859 |  |  |  |  |  |  | =head1 COPYRIGHT AND LICENSE | 
| 860 |  |  |  |  |  |  |  | 
| 861 |  |  |  |  |  |  | This software is copyright (c) 2021 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. | 
| 862 |  |  |  |  |  |  |  | 
| 863 |  |  |  |  |  |  | This is free software; you can redistribute it and/or modify it under | 
| 864 |  |  |  |  |  |  | the same terms as the Perl 5 programming language system itself. | 
| 865 |  |  |  |  |  |  |  | 
| 866 |  |  |  |  |  |  | =cut |