diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php
index b99ce62eb1608137cab54d1b73d2f8d79a264469..32df6570adab84fca394d7ed7bf476a5e7b884ae 100644
--- a/include/class.dynamic_forms.php
+++ b/include/class.dynamic_forms.php
@@ -998,7 +998,13 @@ class DynamicFormEntry extends VerySimpleModel {
             // Set the entry ID here so that $field->getClean() can use the
             // entry-id if necessary
             $a->set('entry_id', $this->get('id'));
-            $val = $field->to_database($field->getClean());
+            try {
+                $val = $field->to_database($field->getClean());
+            }
+            catch (FieldUnchanged $e) {
+                // Don't update the answer.
+                continue;
+            }
             if (is_array($val)) {
                 $a->set('value', $val[0]);
                 $a->set('value_id', $val[1]);
diff --git a/include/class.forms.php b/include/class.forms.php
index b535d4739576dd17ef36e5236181d4b453b1a4d4..646a98035cee622934e7258eb3f69d2fcd03ec29 100644
--- a/include/class.forms.php
+++ b/include/class.forms.php
@@ -752,12 +752,20 @@ class TextboxField extends FormField {
 class PasswordField extends TextboxField {
     static $widget = 'PasswordWidget';
 
+    function parse($value) {
+        // Don't trim the value
+        return $value;
+    }
+
     function to_database($value) {
-        return Crypto::encrypt($value, SECRET_SALT, $this->getFormName());
+        // If not set in UI, don't save the empty value
+        if (!$value)
+            throw new FieldUnchanged();
+        return Crypto::encrypt($value, SECRET_SALT, 'pwfield');
     }
 
     function to_php($value) {
-        return Crypto::decrypt($value, SECRET_SALT, $this->getFormName());
+        return Crypto::decrypt($value, SECRET_SALT, 'pwfield');
     }
 }
 
@@ -1740,8 +1748,13 @@ class Widget {
 class TextboxWidget extends Widget {
     static $input_type = 'text';
 
-    function render($mode=false) {
+    function render($mode=false, $extraConfig=false) {
         $config = $this->field->getConfiguration();
+        if (is_array($extraConfig)) {
+            foreach ($extraConfig as $k=>$v)
+                if (!isset($config[$k]) || !$config[$k])
+                    $config[$k] = $v;
+        }
         if (isset($config['size']))
             $size = "size=\"{$config['size']}\"";
         if (isset($config['length']) && $config['length'])
@@ -1769,12 +1782,19 @@ class TextboxWidget extends Widget {
 class PasswordWidget extends TextboxWidget {
     static $input_type = 'password';
 
+    function render($mode=false, $extra=false) {
+        $extra = array();
+        if ($this->field->value) {
+            $extra['placeholder'] = '••••••••••••';
+        }
+        return parent::render($mode, $extra);
+    }
+
     function parseValue() {
+        parent::parseValue();
         // Show empty box unless failed POST
-        if ($_SERVER['REQUEST_METHOD'] == 'POST'
-                && $this->field->getForm()->isValid())
-            parent::parseValue();
-        else
+        if ($_SERVER['REQUEST_METHOD'] != 'POST'
+                || $this->field->getForm()->isValid())
             $this->value = '';
     }
 }
@@ -2396,4 +2416,11 @@ class Q {
     }
 }
 
+/**
+ * FieldUnchanged
+ *
+ * Thrown in the to_database() method to indicate the value should not be
+ * saved in the database (it wasn't changed in the request)
+ */
+class FieldUnchanged extends Exception {}
 ?>
diff --git a/include/class.plugin.php b/include/class.plugin.php
index a6b653697e1b8ac5e3d60cc7ee96d8e5e59ad43b..240fbbc02559c7688181edbda0bc3c1c9e49b4c6 100644
--- a/include/class.plugin.php
+++ b/include/class.plugin.php
@@ -81,7 +81,13 @@ class PluginConfig extends Config {
             $dbready = array();
             foreach ($config as $name => $val) {
                 $field = $f->getField($name);
-                $dbready[$name] = $field->to_database($val);
+                try {
+                    $dbready[$name] = $field->to_database($val);
+                }
+                catch (FieldUnchanged $e) {
+                    // Don't save the field value
+                    continue;
+                }
             }
             if ($this->updateAll($dbready)) {
                 if (!$msg)