diff --git a/include/ajax.tasks.php b/include/ajax.tasks.php
index 88b11bee010075c07b8293d260ec09f284569891..4cc99a0d614f569e06ff1f43c6ae84303f3abe40 100644
--- a/include/ajax.tasks.php
+++ b/include/ajax.tasks.php
@@ -84,8 +84,10 @@ class TasksAjaxAPI extends AjaxController {
     function add($tid=0, $vars=array()) {
         global $thisstaff;
 
-        if ($tid)
-          $originalTask = Task::lookup($tid);
+        if ($tid) {
+            $vars = array_merge($_SESSION[':form-data'], $vars);
+            $originalTask = Task::lookup($tid);
+        }
         else
           unset($_SESSION[':form-data']);
 
diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php
index 4f5e7a62bcc55939dd2c788b86ee880a4fe37489..a529c193862912a97be84195e512f1bbaa320710 100644
--- a/include/ajax.tickets.php
+++ b/include/ajax.tickets.php
@@ -1382,7 +1382,7 @@ function refer($tid, $target=null) {
                 && ($f=$iform->getField('duedate'))) {
             $f->configure('max', Misc::db2gmtime($ticket->getEstDueDate()));
         }
-
+        $vars = array_merge($_SESSION[':form-data'], $vars);
 
         if ($_POST) {
             Draft::deleteForNamespace(
diff --git a/include/class.attachment.php b/include/class.attachment.php
index bcda6d08af5d757c01b691b78a29b28f03def623..9c6cd7c40b6e980b1e387e341b135ca9840f0082 100644
--- a/include/class.attachment.php
+++ b/include/class.attachment.php
@@ -108,16 +108,15 @@ extends InstrumentedList {
      */
     function keepOnlyFileIds($ids, $inline=false, $lang=false) {
         if (!$ids) $ids = array();
-        $new = array_flip($ids);
         foreach ($this as $A) {
-            if (!isset($new[$A->file_id]) && $A->lang == $lang && $A->inline == $inline)
+            if (!isset($ids[$A->file_id]) && $A->lang == $lang && $A->inline == $inline)
                 // Not in the $ids list, delete
                 $this->remove($A);
-            unset($new[$A->file_id]);
+            unset($ids[$A->file_id]);
         }
         $attachments = array();
         // Format $new for upload() with new name
-        foreach ($new as $id=>$name) {
+        foreach ($ids as $id=>$name) {
             $attachments[] = array(
                     'id' => $id,
                     'name' => $name
@@ -134,7 +133,7 @@ extends InstrumentedList {
         foreach ($files as $file) {
             if (is_numeric($file))
                 $fileId = $file;
-            elseif (is_array($file) && isset($file['id']))
+            elseif (is_array($file) && isset($file['id']) && $file['id'] != 0)
                 $fileId = $file['id'];
             elseif (isset($file['tmp_name']) && ($F = AttachmentFile::upload($file)))
                 $fileId = $F->getId();
diff --git a/include/class.forms.php b/include/class.forms.php
index 980f67c56ea9b991e67de2cc7c9cfaf5afb3539b..86c6cd9d163db45bb34aa72f10f6d7e171ea53bc 100644
--- a/include/class.forms.php
+++ b/include/class.forms.php
@@ -3268,7 +3268,7 @@ class FileUploadField extends FormField {
         $id = $F->getId();
 
         // This file is allowed for attachment in this session
-        $_SESSION[':uploadedFiles'][$id] = 1;
+        $_SESSION[':uploadedFiles'][$id] = $F->getName();
 
         return $id;
     }
@@ -4400,13 +4400,7 @@ class FileUploadWidget extends Widget {
         );
         $maxfilesize = ($config['size'] ?: 1048576) / 1048576;
         $files = array();
-        $new = array_flip($this->field->getClean());
-
-        //get file ids stored in session when creating tickets/tasks from thread
-        //XXX: This shouldn't be here!!
-        if (!$new && is_array($_SESSION[':form-data'])
-                  && array_key_exists($this->field->get('name'), $_SESSION[':form-data']))
-          $new = $_SESSION[':form-data'][$this->field->get('name')];
+        $new = $this->field->getClean();
 
         foreach ($this->field->getAttachments() as $att) {
             unset($new[$att->file_id]);
@@ -4484,41 +4478,40 @@ class FileUploadWidget extends Widget {
         // identified in the session
         //
         // If no value was sent, assume an empty list
-        if (!($files = parent::getValue()))
+        if (!($_files = parent::getValue()))
             return array();
 
+        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
+            foreach ($_files as $info) {
+                if (@list($id,$name) = explode(',', $info, 2))
+                    $files[$id] = $name;
+            }
+        }
+        else
+          $files = $_files;
+
         $allowed = array();
         // Files already attached to the field are allowed
         foreach ($this->field->getFiles() as $F) {
             // FIXME: This will need special porting in v1.10
-            $allowed[$F->id] = 1;
+            $allowed[$F->id] = $F->getName();
         }
 
         // New files uploaded in this session are allowed
         if (isset($_SESSION[':uploadedFiles']))
             $allowed += $_SESSION[':uploadedFiles'];
 
-        // Files attached to threads where we are creating tasks/tickets are allowed
-        if (isset($_SESSION[':form-data'][$this->field->get('name')])) {
-          foreach ($_SESSION[':form-data'][$this->field->get('name')] as $key => $value)
-            $allowed[$key] = $value;
-        }
-
         // Canned attachments initiated by this session
         if (isset($_SESSION[':cannedFiles']))
            $allowed += $_SESSION[':cannedFiles'];
 
         // Parse the files and make sure it's allowed.
-        foreach ($files as $info) {
-            @list($id, $name) = explode(',', $info, 2);
+        foreach ($files as $id => $name) {
             if (!isset($allowed[$id]))
                 continue;
 
             // Keep the values as the IDs
-            if ($name)
-                $ids[$name] = $id;
-            else
-                $ids[] = $id;
+            $ids[$id] = $name ?: $allowed[$id] ?: $id;
         }
 
         return $ids;
diff --git a/include/class.thread.php b/include/class.thread.php
index b499b95ed59c497d37d70955079f9501e3b58e80..59d864060708003ca72a0439fef703752551fc62 100644
--- a/include/class.thread.php
+++ b/include/class.thread.php
@@ -1082,21 +1082,21 @@ implements TemplateVariable {
             $files = array($files);
 
         $ids = array();
-        foreach ($files as $name => $file) {
-            $F = array('inline' => is_array($file) && @$file['inline']);
-
-            if (is_numeric($file))
-                $fileId = $file;
-            elseif ($file instanceof AttachmentFile)
-                $fileId = $file->getId();
-            elseif (is_array($file) && isset($file['id']))
-                $fileId = $file['id'];
-            elseif ($AF = AttachmentFile::create($file))
+        foreach ($files as $id => $info) {
+            $F = array('inline' => is_array($info) && @$info['inline']);
+
+            if (is_numeric($id) && $id != 0)
+                $fileId = $id;
+            elseif ($info instanceof AttachmentFile)
+                $fileId = $info->getId();
+            elseif (is_array($info) && isset($info['id']))
+                $fileId = $info['id'];
+            elseif ($AF = AttachmentFile::create($info))
                 $fileId = $AF->getId();
             elseif ($add_error) {
-                $error = $file['error']
+                $error = $info['error']
                     ?: sprintf(_S('Unable to import attachment - %s'),
-                        $name ?: $file['name']);
+                        $id ?: $info['name']);
                 if (is_numeric($error) && isset($error_descriptions[$error])) {
                     $error = sprintf(_S('Error #%1$d: %2$s'), $error,
                         _S($error_descriptions[$error]));
@@ -1119,15 +1119,15 @@ implements TemplateVariable {
 
             $F['id'] = $fileId;
 
-            if (is_string($name))
-                $F['name'] = $name;
+            if (is_string($info))
+                $F['name'] = $info;
             if (isset($AF))
                 $F['file'] = $AF;
 
             // Add things like the `key` field, but don't change current
             // keys of the file array
-            if (is_array($file))
-                $F += $file;
+            if (is_array($info))
+                $F += $info;
 
             // Key is required for CID rewriting in the body
             if (!isset($F['key']) && ($AF = AttachmentFile::lookup($F['id'])))
diff --git a/include/class.thread_actions.php b/include/class.thread_actions.php
index 2bccfd311586643492e48b0b987f6d33c0a95d2d..54a2821c996b9fa4c3ef64ce8546aea735076825 100644
--- a/include/class.thread_actions.php
+++ b/include/class.thread_actions.php
@@ -525,6 +525,7 @@ JS
               foreach ($this->entry->getAttachments() as $a)
                   if (!$a->inline && $a->file) {
                     $_SESSION[':form-data'][$k][$a->file->getId()] = $a->getFilename();
+                    $_SESSION[':uploadedFiles'][$a->file->getId()] = $a->getFilename();
                   }
         }
 
diff --git a/include/staff/ticket-open.inc.php b/include/staff/ticket-open.inc.php
index 62a0c60fc0f0c30833e05b6f5619ac3d2717245f..09bcfb21fdf95ee2a05366724b6ee921c63eaf48 100644
--- a/include/staff/ticket-open.inc.php
+++ b/include/staff/ticket-open.inc.php
@@ -31,6 +31,7 @@ if (!$user && $_GET['tid'] && ($entry = ThreadEntry::lookup($_GET['tid']))) {
         foreach ($entry->getAttachments() as $a) {
           if (!$a->inline && $a->file) {
             $_SESSION[':form-data'][$k][$a->file->getId()] = $a->getFilename();
+            $_SESSION[':uploadedFiles'][$a->file->getId()] = $a->getFilename();
           }
         }
      }
diff --git a/scp/tasks.php b/scp/tasks.php
index 63e4b87ca1b35831e54f6bfcde6ce0efe07620db..aa8fc88793d858957ede515d756eac951e094c36 100644
--- a/scp/tasks.php
+++ b/scp/tasks.php
@@ -48,9 +48,7 @@ if($_POST && !$errors):
         switch(strtolower($_POST['a'])):
         case 'postnote': /* Post Internal Note */
             $vars = $_POST;
-            $attachments = $note_attachments_form->getField('attachments')->getClean();
-            $vars['cannedattachments'] = array_merge(
-                $vars['cannedattachments'] ?: array(), $attachments);
+            $vars['cannedattachments'] = $note_attachments_form->getField('attachments')->getClean();
 
             $wasOpen = ($task->isOpen());
             if(($note=$task->postNote($vars, $errors, $thisstaff))) {
@@ -78,9 +76,7 @@ if($_POST && !$errors):
             break;
         case 'postreply': /* Post an update */
             $vars = $_POST;
-            $attachments = $reply_attachments_form->getField('attachments')->getClean();
-            $vars['cannedattachments'] = array_merge(
-                $vars['cannedattachments'] ?: array(), $attachments);
+            $vars['cannedattachments'] = $reply_attachments_form->getField('attachments')->getClean();
 
             $wasOpen = ($task->isOpen());
             if (($response=$task->postReply($vars, $errors))) {
diff --git a/scp/tickets.php b/scp/tickets.php
index 4851b4169d257b259671e525d12b0917be428b46..299f83336686ab49afbb20d422ed2f78d85c7cd8 100644
--- a/scp/tickets.php
+++ b/scp/tickets.php
@@ -211,9 +211,7 @@ if($_POST && !$errors):
             break;
         case 'postnote': /* Post Internal Note */
             $vars = $_POST;
-            $attachments = $note_form->getField('attachments')->getClean();
-            $vars['cannedattachments'] = array_merge(
-                $vars['cannedattachments'] ?: array(), $attachments);
+            $vars['cannedattachments'] = $note_form->getField('attachments')->getClean();
             $vars['note'] = ThreadEntryBody::clean($vars['note']);
 
             if ($cfg->isTicketLockEnabled()) {
@@ -418,6 +416,10 @@ if($_POST && !$errors):
                         $response_form->getField('attachments')->reset();
                         $_SESSION[':form-data'] = null;
                     } elseif(!$errors['err']) {
+                        // ensure that we retain the tid if ticket is created from thread
+                        if ($_SESSION[':form-data']['ticketId'] || $_SESSION[':form-data']['taskId'])
+                            $_GET['tid'] = $_SESSION[':form-data']['ticketId'] ?: $_SESSION[':form-data']['taskId'];
+
                         $errors['err']=sprintf('%s %s',
                             __('Unable to create the ticket.'),
                             __('Correct any errors below and try again.'));