diff --git a/include/ajax.forms.php b/include/ajax.forms.php
index e61ddec81fd5eb0bed60c2a024272acd10ad5300..8dc11185cdfae713947d745e245c2764c27824db 100644
--- a/include/ajax.forms.php
+++ b/include/ajax.forms.php
@@ -50,6 +50,7 @@ class DynamicFormsAjaxAPI extends AjaxController {
     }
 
     function saveFieldConfiguration($field_id) {
+
         if (!($field = DynamicFormField::lookup($field_id)))
             Http::response(404, 'No such field');
 
@@ -75,13 +76,12 @@ class DynamicFormsAjaxAPI extends AjaxController {
             function($a, $b) { return $a | $b; }, 0);
         $field->flags = $flags | $preserve;
 
-        if (!$field->setConfiguration()) {
-            include STAFFINC_DIR . 'templates/dynamic-field-config.tmpl.php';
-            return;
-        }
-        else
+        if ($field->setConfiguration($_POST)) {
             $field->save();
-        Http::response(201, 'Field successfully updated');
+            Http::response(201, 'Field successfully updated');
+        }
+
+        include STAFFINC_DIR . 'templates/dynamic-field-config.tmpl.php';
     }
 
     function deleteAnswer($entry_id, $field_id) {
@@ -175,7 +175,7 @@ class DynamicFormsAjaxAPI extends AjaxController {
         $icon = ($list->get('sort_mode') == 'SortCol')
             ? '<i class="icon-sort"></i>&nbsp;' : '';
 
-        if (!$valid || !$item->setConfiguration()) {
+        if (!$valid || !$item->setConfiguration($_POST)) {
             include STAFFINC_DIR . 'templates/list-item-properties.tmpl.php';
             return;
         }
diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php
index d9d51ef8871661ecd702edc2a53e6fac238a2323..d97e4b348683f47c6a1f6c9ac71668d303b9261c 100644
--- a/include/class.dynamic_forms.php
+++ b/include/class.dynamic_forms.php
@@ -562,6 +562,7 @@ class DynamicFormField extends VerySimpleModel {
      * configuration of this field
      *
      * Parameters:
+     * vars - POST request / data
      * errors - (OUT array) receives validation errors of the parsed
      *      configuration form
      *
@@ -570,15 +571,17 @@ class DynamicFormField extends VerySimpleModel {
      * errors. If false, the errors were written into the received errors
      * array.
      */
-    function setConfiguration(&$errors=array()) {
+    function setConfiguration($vars, &$errors=array()) {
         $config = array();
-        foreach ($this->getConfigurationForm($_POST)->getFields() as $name=>$field) {
+        foreach ($this->getConfigurationForm($vars)->getFields() as $name=>$field) {
             $config[$name] = $field->to_php($field->getClean());
             $errors = array_merge($errors, $field->errors());
         }
         if (count($errors) === 0)
             $this->set('configuration', JsonDataEncoder::encode($config));
-        $this->set('hint', Format::sanitize($_POST['hint']));
+
+        $this->set('hint', Format::sanitize($vars['hint']));
+
         return count($errors) === 0;
     }
 
@@ -1323,12 +1326,20 @@ class SelectionField extends FormField {
         $config = $this->getConfiguration();
         $choices = $this->getChoices();
         $selection = array();
+
+        if ($value && !is_array($value))
+            $value = array($value);
+
         if ($value && is_array($value)) {
             foreach ($value as $k=>$v) {
-                if (($i=$list->getItem((int) $k)))
+                if ($k && ($i=$list->getItem((int) $k)))
                     $selection[$i->getId()] = $i->getValue();
                 elseif (isset($choices[$k]))
                     $selection[$k] = $choices[$k];
+                elseif (isset($choices[$v]))
+                    $selection[$v] = $choices[$v];
+                elseif (($i=$list->getItem($v, true)))
+                    $selection[$i->getId()] = $i->getValue();
             }
         } elseif($value) {
             //Assume invalid textbox input to be validated
@@ -1656,6 +1667,11 @@ class TypeaheadSelectionWidget extends ChoicesWidget {
         $data = $this->field->getSource();
         if (isset($data[$this->name]))
             return $data[$this->name];
+
+        $name = $this->field->get('name');
+        if (isset($data[$name]))
+           return $data[$name];
+
         return parent::getValue();
     }
 
@@ -1665,7 +1681,10 @@ class TypeaheadSelectionWidget extends ChoicesWidget {
         if (isset($data[$this->name.'_name'])) {
             // Drop the extra part, if any
             $v = $data[$this->name.'_name'];
-            $v = substr($v, 0, strrpos($v, ' — '));
+            $pos = strrpos($v, ' — ');
+            if ($pos !== false)
+                $v = substr($v, 0, $pos);
+
             return trim($v);
         }
         return parent::getValue();
diff --git a/include/class.list.php b/include/class.list.php
index a228ab06f2bf04c0eb31f12dc827d37e5d585eaf..12d2a85565a4062c4f8c24aca91ada5378bfd404 100644
--- a/include/class.list.php
+++ b/include/class.list.php
@@ -227,23 +227,27 @@ class DynamicList extends VerySimpleModel implements CustomList {
         return $this->_items;
     }
 
-
-
-    function getItem($val) {
+    function getItem($val, $extra=false) {
 
         $items = DynamicListItem::objects()->filter(
                 array('list_id' => $this->getId()));
 
         if (is_int($val))
             $items->filter(array('id' => $val));
+        elseif ($extra)
+            $items->filter(array('extra' => $val));
         else
-            $items->filter(Q::any(array('value'=>$val, 'extra' => $val)));
+            $items->filter(array('value' => $val));
+
 
         return $items->first();
     }
 
     function addItem($vars, &$errors) {
 
+        if (($item=$this->getItem($vars['value'])))
+            return $item;
+
         $item = DynamicListItem::create(array(
             'status' => 1,
             'list_id' => $this->getId(),
@@ -513,7 +517,7 @@ class DynamicList extends VerySimpleModel implements CustomList {
             }
         }
 
-        // 'name' and 'email' MUST be in the headers
+        // 'value' MUST be in the headers
         if (!isset($headers['value']))
             return __('CSV file must include `value` column');
 
@@ -565,11 +569,11 @@ class DynamicList extends VerySimpleModel implements CustomList {
             $items[] = $data;
         }
 
-        $errors = array();
         foreach ($items as $u) {
             $vars = array_combine($keys, $u);
-            $item = $this->addItem($vars);
-            if (!$item || !$item->setConfiguration($errors, $vars))
+            $errors = array();
+            $item = $this->addItem($vars, $errors);
+            if (!$item || !$item->setConfiguration($vars, $errors))
                 return sprintf(__('Unable to import item: %s'),
                     print_r($vars, true));
         }
@@ -698,16 +702,19 @@ class DynamicListItem extends VerySimpleModel implements CustomListItem {
         return $this->_config;
     }
 
-    function setConfiguration(&$errors=array(), $source=false) {
+    function setConfiguration($vars, &$errors=array()) {
         $config = array();
-        foreach ($this->getConfigurationForm($source ?: $_POST)->getFields() as $field) {
+        foreach ($this->getConfigurationForm($vars)->getFields() as $field) {
             $config[$field->get('id')] = $field->to_php($field->getClean());
             $errors = array_merge($errors, $field->errors());
         }
-        if (count($errors) === 0)
-            $this->set('properties', JsonDataEncoder::encode($config));
 
-        return count($errors) === 0;
+        if ($errors)
+            return false;
+
+        $this->set('properties', JsonDataEncoder::encode($config));
+
+        return $this->save();
     }
 
     function getConfigurationForm($source=null) {
@@ -1228,9 +1235,9 @@ class TicketStatus  extends VerySimpleModel implements CustomListItem {
         return $this->_settings;
     }
 
-    function setConfiguration(&$errors=array()) {
+    function setConfiguration($vars, &$errors=array()) {
         $properties = array();
-        foreach ($this->getConfigurationForm($_POST)->getFields() as $f) {
+        foreach ($this->getConfigurationForm($vars)->getFields() as $f) {
             if ($this->isInternal() //Item is internal.
                     && !$f->isEditable())
                 continue;
diff --git a/setup/cli/modules/list.php b/setup/cli/modules/list.php
new file mode 100644
index 0000000000000000000000000000000000000000..33867acba77236c8cb61a6f1752cfcb310f6f4b3
--- /dev/null
+++ b/setup/cli/modules/list.php
@@ -0,0 +1,89 @@
+<?php
+require_once dirname(__file__) . "/class.module.php";
+require_once dirname(__file__) . "/../cli.inc.php";
+include_once INCLUDE_DIR .'class.translation.php';
+
+
+class ListManager extends Module {
+    var $prologue = 'CLI list manager';
+    var $arguments = array(
+        'action' => array(
+            'help' => 'Action to be performed',
+            'options' => array(
+                'import' => 'Import list items to the system',
+                'export' => 'Export list items from the system',
+                'show' => 'Show the lists',
+            ),
+        ),
+    );
+
+
+    var $options = array(
+        'file' => array('-f', '--file', 'metavar'=>'path',
+            'help' => 'File or stream to process'),
+        'id' => array('-ID', '--id', 'metavar'=>'id',
+            'help' => 'List ID'),
+        );
+
+    var $stream;
+
+    function run($args, $options) {
+
+        Bootstrap::connect();
+
+        $list = null;
+        if ($options['id'])
+            $list = DynamicList::lookup($options['id']);
+
+        switch ($args['action']) {
+            case 'import':
+                if (!$list)
+                    $this->fail("List ID required for items import");
+
+                // Properly detect Macintosh style line endings
+                ini_set('auto_detect_line_endings', true);
+                if (!$options['file'])
+                    $this->fail('CSV file to import list items from is required!');
+                elseif (!($this->stream = fopen($options['file'], 'rb')))
+                    $this->fail("Unable to open input file [{$options['file']}]");
+
+                $extras = array();
+                $status = $list->importCsv($this->stream, $extras);
+                if (is_numeric($status))
+                    $this->stderr->write("Successfully imported $status list items\n");
+                else
+                    $this->fail($status);
+                break;
+            case 'export':
+
+                if (!$list)
+                    $this->fail("List ID required for export");
+
+                $stream = $options['file'] ?: 'php://stdout';
+                if (!($this->stream = fopen($stream, 'c')))
+                    $this->fail("Unable to open output file [{$options['file']}]");
+
+                fputcsv($this->stream, array('Value', 'Abbrev'));
+                foreach ($list->getItems() as $item)
+                    fputcsv($this->stream, array(
+                                (string) $item->getValue(),
+                                $item->getAbbrev()));
+                break;
+            case 'show':
+                $lists = DynamicList::objects()->order_by('-type', 'name');
+                foreach ($lists as $list) {
+                    $this->stdout->write(sprintf("%d %s \n",
+                                $list->getId(),
+                                $list->getName(),
+                                $list->getPluralName() ?: $list->getName()
+                                ));
+                }
+                break;
+            default:
+                $this->stderr->write('Unknown action!');
+        }
+        @fclose($this->stream);
+    }
+}
+Module::register('list', 'ListManager');
+?>