[Rt-commit] rt branch, 4.0/rest-attachments-on-create, created. rt-4.0.13-88-gc63c35e

Ruslan Zakirov ruz at bestpractical.com
Wed Jun 26 06:04:15 EDT 2013


The branch, 4.0/rest-attachments-on-create has been created
        at  c63c35e9a782e19bdb7c42fe9ad8ac109820adb6 (commit)

- Log -----------------------------------------------------------------
commit 7b6ddfb45a5c4c794845fc588806efdbc6daaa77
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Jun 26 12:39:52 2013 +0400

    extract attachments processing in REST into lib

diff --git a/lib/RT/Interface/REST.pm b/lib/RT/Interface/REST.pm
index 5f8ff99..3a85c2d 100644
--- a/lib/RT/Interface/REST.pm
+++ b/lib/RT/Interface/REST.pm
@@ -52,7 +52,7 @@ use warnings;
 use RT;
 
 use base 'Exporter';
-our @EXPORT = qw(expand_list form_parse form_compose vpush vsplit);
+our @EXPORT = qw(expand_list form_parse form_compose vpush vsplit process_attachments);
 
 sub custom_field_spec {
     my $self    = shift;
@@ -296,6 +296,45 @@ sub vsplit {
     return \@words;
 }
 
+sub process_attachments {
+    my $entity = shift;
+    my @list = @_;
+    return 1 unless @list;
+
+    my $m = $HTML::Mason::Commands::m;
+    my $cgi = $m->cgi_object;
+
+    my $i = 1;
+    foreach my $e ( @list ) {
+
+        my $fh = $cgi->upload("attachment_$i");
+        return (0, "No attachment for $e") unless $fh;
+
+        local $/=undef;
+
+        my $file = $e;
+        $file =~ s#^.*[\\/]##;
+
+        my ($tmp_fh, $tmp_fn) = File::Temp::tempfile( UNLINK => 1 );
+
+        my $buf;
+        while (sysread($fh, $buf, 8192)) {
+            syswrite($tmp_fh, $buf);
+        }
+
+        my $info = $cgi->uploadInfo($fh);
+        my $new_entity = $entity->attach(
+            Path => $tmp_fn,
+            Type => $info->{'Content-Type'} || guess_media_type($tmp_fn),
+            Filename => $file,
+            Disposition => "attachment",
+        );
+        $new_entity->bodyhandle->{'_dirty_hack_to_save_a_ref_tmp_fh'} = $tmp_fh;
+        $i++;
+    }
+    return (1);
+}
+
 RT::Base->_ImportOverlays();
 
 1;
diff --git a/share/html/REST/1.0/Forms/ticket/comment b/share/html/REST/1.0/Forms/ticket/comment
index b50135f..c7e8b9c 100644
--- a/share/html/REST/1.0/Forms/ticket/comment
+++ b/share/html/REST/1.0/Forms/ticket/comment
@@ -55,8 +55,6 @@ $id
 use MIME::Entity;
 use LWP::MediaTypes;
 use RT::Interface::REST;
-use File::Temp qw(tempfile);
-my @tmp_files;
 
 $RT::Logger->debug("Got ticket id=$id for comment");
 $RT::Logger->debug("Got args @{[keys(%changes)]}.");
@@ -89,44 +87,19 @@ if (!$changes{Text} && @atts == 0) {
     goto OUTPUT;
 }
 
-my $cgi = $m->cgi_object;
 my $ent = MIME::Entity->build(
     Type => "multipart/mixed",
     'X-RT-Interface' => 'REST',
 );
 $ent->attach(Data => $changes{Text}) if $changes{Text};
 
-my $i = 1;
-foreach my $att (@atts) {
-    local $/=undef;
-    my $file = $att;
-    $file =~ s#^.*[\\/]##;
-
-    my $fh = $cgi->upload("attachment_$i");
-    if ($fh) {
-        my $buf;
-        my ($w, $tmp) = tempfile();
-        my $info = $cgi->uploadInfo($fh);
-        push @tmp_files, $tmp;
-
-        while (sysread($fh, $buf, 8192)) {
-            syswrite($w, $buf);
-        }
-
-        $ent->attach(
-            Path => $tmp,
-            Type => $info->{'Content-Type'} || guess_media_type($tmp),
-            Filename => $file,
-            Disposition => "attachment"
-        );
-    }
-    else {
+{
+    my ($status, $msg) = process_attachments($ent, @atts);
+    unless ( $status ) {
         $e = 1;
-        $c = "# No attachment for $att.";
+        $c = "# $msg";
         goto OUTPUT;
     }
-
-    $i++;
 }
 
 unless ($ticket->CurrentUserHasRight('ModifyTicket') ||
@@ -154,6 +127,5 @@ if ($changes{Status}) {
 
 OUTPUT:
 
-unlink @tmp_files;
 return [ $c, $o, $k, $e ];
 </%INIT>
diff --git a/share/html/REST/1.0/ticket/comment b/share/html/REST/1.0/ticket/comment
index 475e3a8..0999024 100644
--- a/share/html/REST/1.0/ticket/comment
+++ b/share/html/REST/1.0/ticket/comment
@@ -54,8 +54,6 @@ $content
 use MIME::Entity;
 use LWP::MediaTypes;
 use RT::Interface::REST;
-use File::Temp qw(tempfile);
-my @tmp_files;
 
 my $ticket = RT::Ticket->new($session{CurrentUser});
 my $object = $r->path_info;
@@ -113,37 +111,13 @@ my $ent = MIME::Entity->build(
 );
 $ent->attach(Data => $k->{Text}) if $k->{Text};
 
-my $i = 1;
-foreach my $att (@atts) {
-    local $/=undef;
-    my $file = $att;
-    $file =~ s#^.*[\\/]##;
-
-    my $fh = $cgi->upload("attachment_$i");
-    if ($fh) {
-        my $buf;
-        my ($w, $tmp) = tempfile();
-        push @tmp_files, $tmp;
-        my $info = $cgi->uploadInfo();
-
-        while (sysread($fh, $buf, 8192)) {
-            syswrite($w, $buf);
-        }
-
-        $ent->attach(
-            Path => $tmp,
-            Type => $info->{'Content-Type'} || guess_media_type($tmp),
-            Filename => $file,
-            Disposition => "attachment"
-        );
-    }
-    else {
+{
+    my ($res, $msg) = process_attachments($ent, @atts);
+    unless ( $res ) {
         $status = "400 Bad Request";
-        $output = "No attachment for $att.\n";
+        $output = "$msg\n";
         goto OUTPUT;
     }
-
-    $i++;
 }
 
 $ticket->Load($object);
@@ -177,7 +151,6 @@ if ($k->{Status}) {
 
 OUTPUT:
 
-unlink @tmp_files;
 </%INIT>
 RT/<% $RT::VERSION %> <% $status %>
 

commit c63c35e9a782e19bdb7c42fe9ad8ac109820adb6
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Jun 26 13:28:53 2013 +0400

    REST: make it possible to attach files on create
    
    Only with command line option - no in editor support.

diff --git a/bin/rt.in b/bin/rt.in
index 4a3eada..bdb580b 100644
--- a/bin/rt.in
+++ b/bin/rt.in
@@ -471,7 +471,7 @@ sub show {
 
 sub edit {
     my ($action) = @_;
-    my (%data, $type, @objects);
+    my (%data, $type, @objects, @files);
     my ($cl, $text, $edit, $input, $output);
 
     use vars qw(%set %add %del);
@@ -503,6 +503,13 @@ sub edit {
             }
             $slurped = 1;
         }
+        elsif (/^-a$/) {
+            unless (-f $ARGV[0] && -r $ARGV[0]) {
+                whine "Cannot read attachment: '$ARGV[0]'.";
+                $bad = 1; last;
+            }
+            push @files, shift @ARGV;
+        }
         elsif (/^set$/i) {
             my $vars = 0;
 
@@ -630,6 +637,12 @@ sub edit {
                 }
                 push @$o, (keys %add, keys %set);
             }
+            if ( @files ) {
+                foreach my $form (@$forms) {
+                    push @{ $form->[1] }, 'Attachment';
+                    $form->[2]{'Attachment'} = \@files;
+                }
+            }
 
             $text = Form::compose($forms);
         }
@@ -646,6 +659,12 @@ sub edit {
                     push @forms, ["", [keys %set], \%set];
                 }
             }
+            if ( @files ) {
+                foreach my $form (@forms) {
+                    push @{ $form->[1] }, 'Attachment';
+                    $form->[2]{'Attachment'} = \@files;
+                }
+            }
             $text = Form::compose(\@forms);
         }
     }
@@ -666,6 +685,12 @@ EDIT:
         $text = ($synerr && $newtext eq $text) ? undef : $newtext;
     }
 
+    my $i = 1;
+    foreach my $file (@files) {
+        $data{"attachment_$i"} = bless([ $file ], "Attachment");
+        $i++;
+    }
+
     if ($text) {
         my $r = submit("$REST/edit", {content => $text, %data});
         if ($r->code == 409) {
@@ -2273,6 +2298,9 @@ Text:
         -S var=val
                 Submits the specified variable with the request.
         -t type Specifies object type.
+        -a <file>
+                Attach a file on create. (May be used more than once to
+                attach multiple files.)
 
     Examples:
 
diff --git a/share/html/REST/1.0/Forms/ticket/default b/share/html/REST/1.0/Forms/ticket/default
index a48876b..1eacb78 100644
--- a/share/html/REST/1.0/Forms/ticket/default
+++ b/share/html/REST/1.0/Forms/ticket/default
@@ -134,7 +134,7 @@ else {
     else {
         # We'll create a new ticket, and fall through to set fields that
         # can't be set in the call to Create().
-        my (%v, $text);
+        my (%v, $text, @atts);
 
         foreach my $k (keys %data) {
             # flexibly parse any dates
@@ -167,6 +167,9 @@ else {
             elsif (lc $k eq 'text') {
                 $text = delete $data{$k};
             }
+            elsif (lc $k eq 'attachment') {
+                push @atts, @{ vsplit(delete $data{$k}) };
+            }
             elsif ( $k !~ /^(?:id|requestors)$/i ) {
                 $e = 1;
                 push @$o, $k;
@@ -183,14 +186,21 @@ else {
         # people fields allow multiple values
         $v{$_} = vsplit($v{$_}) foreach ( grep $create{lc $_}, @people );
 
-        if ($text) {
+        if ($text || @atts) {
             $v{MIMEObj} =
                 MIME::Entity->build(
+                    Type => "multipart/mixed",
                     From => $session{CurrentUser}->EmailAddress,
                     Subject => $v{Subject},
-                    Data => $text,
                     'X-RT-Interface' => 'REST',
                 );
+            $v{MIMEObj}->attach( Data => $text ) if $text;
+            my ($status, $msg) = process_attachments($v{'MIMEObj'}, @atts);
+            unless ($status) {
+                push(@comments, "# $msg");
+                goto DONE;
+            }
+            $v{MIMEObj}->make_singlepart;
         }
 
         my($tid,$trid,$terr) = $ticket->Create(%v);    

-----------------------------------------------------------------------


More information about the Rt-commit mailing list