The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
<%init>
# grab ticket number from URL
my ($mode,$ticket_no) = ($m->dhandler_arg =~ m/^((?:all|current))\/(\d+)\//i );

# create ticket object
my $Ticket = LoadTicket($ticket_no);

# collect individual attached files in a hash of arrays
my $AttachObj = $m->comp('/Ticket/Elements/FindAttachments', Ticket => $Ticket);
my %attached_files;
while (my $attached_name = $AttachObj->Next() ) {
  next unless ($attached_name->Filename());
  unshift( @{ $attached_files{ $attached_name->Filename } }, $attached_name );
}
my $tempdir = File::Temp->newdir( CLEANUP => 1 );
my $zip = Archive::Zip->new();
my ($zip_fh,$zip_name) = Archive::Zip::tempFile($tempdir);
</%init>
<%perl>
foreach my $name (keys %attached_files) {
  foreach my $revision (@{$attached_files{$name}}) {
    # temporary on-disk storage of files for zip
    my $tempfile_fh = File::Temp->new(DIR => $tempdir, SUFFIX => ".tmp");

    # these objects go out of scope before the zipfile is written to disk,
    # which would cause them to be deleted too early.  Let the tempdir
    # CLEANUP take care of them instead.
    $tempfile_fh->unlink_on_destroy(0);
    my $tempfile_name = $tempfile_fh->filename;
    print $tempfile_fh $revision->Content;

    # need to close the FH so that perl flushes output
    close $tempfile_fh;

    # add tempfile to zip as the original name from the attachment, with revision ID
    my $member;
    if ($mode =~ m/all/i) {
      $member = $zip->addFile($tempfile_name,sprintf('ticket_%d/%d_%s',$Ticket->Id,$revision->Id,$revision->Filename));
    } else {
      $member = $zip->addFile($tempfile_name,sprintf('ticket_%d/%s',$Ticket->Id,$revision->Filename));
    }
    $member->desiredCompressionMethod( COMPRESSION_DEFLATED );
    last if ($mode !~ m/all/i);
  }
}

if ( $zip->writeToFileHandle($zip_fh) == AZ_OK) {
  # need to close the FH so that perl flushes output
  close $zip_fh;
  $r->content_type( "application/zip" );
  $m->clear_buffer();
  $m->out($m->file($zip_name));
  $m->abort;
} else {
  close $zip_fh;
  $RT::Logger->error("write error writing zip to $zip_name");
  $r->content_type( "text/plain" );
  $m->clear_buffer();
  $m->out("Sorry, error creating zip.  Please contact your system administrator.");
  $m->abort;
}
undef $tempdir;
</%perl>
<%attr>
AutoFlush => 0
</%attr>
<%once>
use Archive::Zip qw( :ERROR_CODES :CONSTANTS);
use File::Temp qw( tempfile tempdir);
</%once>