#!/usr/bin/perl # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # # This Source Code Form is "Incompatible With Secondary Licenses", as # defined by the Mozilla Public License, v. 2.0. use strict; use warnings; use 5.10.1; use File::Basename; use File::Spec; BEGIN { require lib; my $dir = File::Spec->rel2abs(File::Spec->catdir(dirname(__FILE__), '..')); lib->import( $dir, File::Spec->catdir($dir, 'lib'), File::Spec->catdir($dir, qw(local lib perl5)) ); } use Bugzilla; use Bugzilla::Constants; use Bugzilla::Attachment; use Bugzilla::Attachment::Archive; use Getopt::Long; use Pod::Usage; BEGIN { Bugzilla->extensions } # set Bugzilla usage mode to USAGE_MODE_CMDLINE Bugzilla->usage_mode(USAGE_MODE_CMDLINE); my ($help, $file); GetOptions('help|h' => \$help, 'file|f=s' => \$file,); pod2usage(1) if $help || !$file; my $archive = Bugzilla::Attachment::Archive->new(file => $file); my $cmd = shift @ARGV; if ($cmd eq 'export') { while (my $attach_id = ) { chomp $attach_id; my $attachment = Bugzilla::Attachment->new($attach_id); unless ($attachment) { warn "No attachment: $attach_id\n"; next; } warn "writing $attach_id\n"; $archive->write_attachment($attachment); } $archive->write_checksum; } elsif ($cmd eq 'import') { while (my $mem = $archive->read_member) { warn "read $mem->{attach_id}\n"; my $attachment = Bugzilla::Attachment->new($mem->{attach_id}); next unless $mem->{data_len}; next unless check_attachment($attachment, $mem->{bug_id}, $mem->{data_len}); Bugzilla::Attachment::current_storage()->store($attachment->id, $mem->{data}); } } elsif ($cmd eq 'check') { while (my $mem = $archive->read_member()) { warn "checking $mem->{attach_id}\n"; my $attachment = Bugzilla::Attachment->new($mem->{attach_id}); next unless $mem->{data_len}; die "bad attachment\n" unless check_attachment($attachment, $mem->{bug_id}, $mem->{data_len}); } } elsif ($cmd eq 'remove') { my %remove_ok; while (my $mem = $archive->read_member) { warn "checking $mem->{attach_id}\n"; my $attachment = Bugzilla::Attachment->new($mem->{attach_id}); die "bad attachment\n" unless check_attachment($attachment, $mem->{bug_id}, $mem->{data_len}); $remove_ok{$mem->{attach_id}} = 1; } while (my $attach_id = ) { chomp $attach_id; if ($remove_ok{$attach_id}) { warn "removing $attach_id\n"; Bugzilla::Attachment::current_storage()->remove($attach_id); } else { warn "Unable to remove $attach_id, as it did not occur in the archive.\n"; } } } sub check_attachment { my ($attachment, $bug_id, $data_len) = @_; unless ($attachment) { warn "No attachment found. Skipping record.\n"; return 0; } unless ($attachment->bug_id == $bug_id) { warn 'Wrong bug id (should be ' . $attachment->bug_id . ")\n"; return 0; } unless ($attachment->datasize == $data_len) { warn 'Wrong size (should be ' . $attachment->datasize . ")\n"; return 0; } return 1; } __DATA__ =head1 NAME attachment-data.pl - import, export, and purge attachment data =head1 SYNOPSIS ./scripts/attachment-data.pl export -f attachments.dat < attachment-ids.txt ./scripts/attachment-data.pl remove -f attachments.dat < attachment-ids.txt ./scripts/attachment-data.pl import -f attachments.dat =head1 SEE ALSO L<./scripts/attachment-export.pl>