75
75
# Determine whether to use the action specified by the user or the default.
76
76
my $action = $cgi->param('action') || 'view';
77
my $format = $cgi->param('format') || '';
78
79
# You must use the appropriate urlbase/sslbase param when doing anything
79
# but viewing an attachment.
80
if ($action ne 'view') {
80
# but viewing an attachment, or a raw diff.
82
&& (($action !~ /^(?:interdiff|diff)$/) || $format ne 'raw'))
81
84
do_ssl_redirect_if_required();
82
85
if ($cgi->url_is_attachment_base) {
83
86
$cgi->redirect_to_urlbase;
167
170
# non-natural, so use the original value from $cgi in our exception
169
172
detaint_natural($attach_id)
170
|| ThrowUserError("invalid_attach_id", { attach_id => $cgi->param($param) });
173
|| ThrowUserError("invalid_attach_id",
174
{ attach_id => scalar $cgi->param($param) });
172
176
# Make sure the attachment exists in the database.
173
177
my $attachment = new Bugzilla::Attachment($attach_id)
174
|| ThrowUserError("invalid_attach_id", { attach_id => $attach_id });
178
|| ThrowUserError("invalid_attach_id", { attach_id => $attach_id });
176
180
return $attachment if ($dont_validate_access || check_can_access($attachment));
233
################################################################################
235
################################################################################
238
# Gets the attachment object(s) generated by validateID, while ensuring
239
# attachbase and token authentication is used when required.
241
my @field_names = @_ ? @_ : qw(id);
237
# Display an attachment.
241
245
if (use_attachbase()) {
242
$attachment = validateID(undef, 1);
243
my $path = 'attachment.cgi?id=' . $attachment->id;
244
# The user is allowed to override the content type of the attachment.
245
if (defined $cgi->param('content_type')) {
246
$path .= '&content_type=' . url_quote($cgi->param('content_type'));
246
# Load each attachment, and ensure they are all from the same bug
248
foreach my $field_name (@field_names) {
249
my $attachment = validateID($field_name, 1);
251
$bug_id = $attachment->bug_id;
252
} elsif ($attachment->bug_id != $bug_id) {
253
ThrowUserError('attachment_bug_id_mismatch');
255
$attachments{$field_name} = $attachment;
257
my @args = map { $_ . '=' . $attachments{$_}->id } @field_names;
258
my $cgi_params = $cgi->canonicalise_query(@field_names, 't',
259
'Bugzilla_login', 'Bugzilla_password');
260
push(@args, $cgi_params) if $cgi_params;
261
my $path = 'attachment.cgi?' . join('&', @args);
249
263
# Make sure the attachment is served from the correct server.
250
my $bug_id = $attachment->bug_id;
251
264
if ($cgi->url_is_attachment_base($bug_id)) {
252
265
# No need to validate the token for public attachments. We cannot request
253
266
# credentials as we are on the alternate host.
254
if (!attachmentIsPublic($attachment)) {
267
if (!all_attachments_are_public(\%attachments)) {
255
268
my $token = $cgi->param('t');
256
my ($userid, undef, $token_attach_id) = Bugzilla::Token::GetTokenData($token);
258
&& detaint_natural($token_attach_id)
259
&& ($token_attach_id == $attachment->id))
269
my ($userid, undef, $token_data) = Bugzilla::Token::GetTokenData($token);
270
my %token_data = unpack_token_data($token_data);
272
foreach my $field_name (@field_names) {
273
my $token_id = $token_data{$field_name};
275
|| !detaint_natural($token_id)
276
|| $attachments{$field_name}->id != $token_id)
282
unless ($userid && $valid_token) {
261
283
# Not a valid token.
262
284
print $cgi->redirect('-location' => correct_urlbase() . $path);
283
305
# Replace %bugid% by the ID of the bug the attachment
284
306
# belongs to, if present.
285
307
$attachbase =~ s/\%bugid\%/$bug_id/;
286
if (attachmentIsPublic($attachment)) {
308
if (all_attachments_are_public(\%attachments)) {
287
309
# No need for a token; redirect to attachment base.
288
310
print $cgi->redirect(-location => $attachbase . $path);
291
313
# Make sure the user can view the attachment.
292
check_can_access($attachment);
314
foreach my $field_name (@field_names) {
315
check_can_access($attachments{$field_name});
293
317
# Create a token and redirect.
294
my $token = url_quote(issue_session_token($attachment->id));
318
my $token = url_quote(issue_session_token(pack_token_data(\%attachments)));
295
319
print $cgi->redirect(-location => $attachbase . "$path&t=$token");
300
324
do_ssl_redirect_if_required();
301
325
# No alternate host is used. Request credentials if required.
302
326
Bugzilla->login();
303
$attachment = validateID();
327
foreach my $field_name (@field_names) {
328
$attachments{$field_name} = validateID($field_name);
333
? map { $attachments{$_} } @field_names
334
: $attachments{$field_names[0]};
337
sub all_attachments_are_public {
338
my $attachments = shift;
339
foreach my $field_name (keys %$attachments) {
340
if (!attachmentIsPublic($attachments->{$field_name})) {
347
sub pack_token_data {
348
my $attachments = shift;
349
return join(' ', map { $_ . '=' . $attachments->{$_}->id } keys %$attachments);
352
sub unpack_token_data {
353
my @token_data = split(/ /, shift || '');
355
foreach my $token (@token_data) {
356
my ($field_name, $attach_id) = split('=', $token);
357
$data{$field_name} = $attach_id;
362
################################################################################
364
################################################################################
366
# Display an attachment.
368
my $attachment = get_attachment();
306
370
# At this point, Bugzilla->login has been called if it had to.
307
371
my $contenttype = $attachment->contenttype;
348
412
# Retrieve and validate parameters
349
my $old_attachment = validateID('oldid');
350
my $new_attachment = validateID('newid');
351
413
my $format = validateFormat('html', 'raw');
414
my($old_attachment, $new_attachment);
415
if ($format eq 'raw') {
416
($old_attachment, $new_attachment) = get_attachment('oldid', 'newid');
418
$old_attachment = validateID('oldid');
419
$new_attachment = validateID('newid');
352
421
my $context = validateContext();
354
423
Bugzilla::Attachment::PatchReader::process_interdiff(
359
428
# Retrieve and validate parameters
360
my $attachment = validateID();
361
429
my $format = validateFormat('html', 'raw');
430
my $attachment = $format eq 'raw' ? get_attachment() : validateID();
362
431
my $context = validateContext();
364
433
# If it is not a patch, view normally.