diff --git a/config/vufind/Summon.ini b/config/vufind/Summon.ini
index b3cd8a2565e41883c406c0b94abfa595ae4bbd85..91312983d8580a3d95f282e3ca12681006dbe67b 100644
--- a/config/vufind/Summon.ini
+++ b/config/vufind/Summon.ini
@@ -162,13 +162,20 @@ facet_limit      = 100      ; how many values should we show for each facet?
 ; Some facet types don't lend themselves to this format, and they can be turned on
 ; by inclusion in the comma-separated list below, or turned off by being excluded.
 ; Supported values:
+; checkboxes - displays a list of checkbox facets as specified in the
+;      [CheckboxFacets] section above. You can specify the config file/section
+;      with colon-separated parameters following the checkboxes setting; e.g.
+;      checkboxes:facets:myCustomCheckboxes will load from the myCustomCheckboxes
+;      section of facets.ini. You can prefix the section name with a tilde (~)
+;      to reverse processing of the section to label => filter format (useful if your
+;      filters contain values that are illegal in configuration keys -- e.g. []).
 ; daterange - for the range controls specified by the dateRange setting under
 ;      [Special_Facets] above; if multiple fields are specified above but you
 ;      only want certain ones on the advanced screen, you can filter with a
 ;      colon separated list; e.g. "daterange:field1:field2:field3"
 ; genericrange - just like daterange above, but for genericRange[] fields.
 ; numericrange - just like daterange above, but for numericRange[] fields.
-special_facets      = daterange
+special_facets = "daterange,checkboxes:Summon"
 ; Should we OR together facets rather than ANDing them? Set to * for
 ; all facets, use a comma-separated list to apply to some of the facets, set
 ; to false or omit to disable ORed facets.
diff --git a/config/vufind/facets.ini b/config/vufind/facets.ini
index ca6ad3793b067bc279d5c26f1245a6efc6415cc9..2a8e848bb477b3aecc9ce0bf94354cbe68c702bc 100644
--- a/config/vufind/facets.ini
+++ b/config/vufind/facets.ini
@@ -90,6 +90,13 @@ orFacets = *
 ; Some facet types don't lend themselves to this format, and they can be turned on
 ; by inclusion in the comma-separated list below, or turned off by being excluded.
 ; Supported values:
+; checkboxes - displays a list of checkbox facets as specified in the
+;      [CheckboxFacets] section above. You can specify the config file/section
+;      with colon-separated parameters following the checkboxes setting; e.g.
+;      checkboxes:facets:myCustomCheckboxes will load from the myCustomCheckboxes
+;      section of facets.ini. You can prefix the section name with a tilde (~)
+;      to reverse processing of the section to label => filter format (useful if your
+;      filters contain values that are illegal in configuration keys -- e.g. []).
 ; daterange - for the range controls specified by the dateRange setting under
 ;      [Special_Facets] above; if multiple fields are specified above but you
 ;      only want certain ones on the advanced screen, you can filter with a
@@ -99,10 +106,10 @@ orFacets = *
 ; numericrange - just like daterange above, but for numericRange[] fields.
 special_facets   = "illustrated,daterange"
 
-; Any facets named in the list below will have their values run through the 
+; Any facets named in the list below will have their values run through the
 ; translation code; unlisted facets will displayed as-is without translation.  For
 ; translated facets, be sure that all of the necessary strings are included in the
-; language files found in the web/lang directory.  By default, no facets are 
+; language files found in the web/lang directory.  By default, no facets are
 ; translated -- uncomment or add lines below to turn on this feature.
 ;translated_facets[] = institution
 ;translated_facets[] = building
diff --git a/module/VuFind/config/module.config.php b/module/VuFind/config/module.config.php
index 9b0b83fa2428352a0d938b05a6e84deaafcdc4cd..b1754b8be65279dbcd651cec2f82ac59736e9e9a 100644
--- a/module/VuFind/config/module.config.php
+++ b/module/VuFind/config/module.config.php
@@ -591,7 +591,8 @@ $staticRoutes = array(
     'MyResearch/ILLRequests', 'MyResearch/Logout',
     'MyResearch/NewPassword', 'MyResearch/Profile',
     'MyResearch/Recover', 'MyResearch/SaveSearch',
-    'MyResearch/StorageRetrievalRequests', 'MyResearch/Verify',
+    'MyResearch/StorageRetrievalRequests', 'MyResearch/UserLogin',
+    'MyResearch/Verify',
     'Primo/Advanced', 'Primo/Home', 'Primo/Search',
     'QRCode/Show', 'QRCode/Unavailable',
     'OAI/Server', 'Pazpar2/Home', 'Pazpar2/Search', 'Records/Home',
diff --git a/module/VuFind/src/VuFind/Auth/ChoiceAuth.php b/module/VuFind/src/VuFind/Auth/ChoiceAuth.php
index 6c7af73027defe59f64ba29702c79dc7a8b7068c..83c1c20efa7b8a8f89093b9353e59a2f47a1526e 100644
--- a/module/VuFind/src/VuFind/Auth/ChoiceAuth.php
+++ b/module/VuFind/src/VuFind/Auth/ChoiceAuth.php
@@ -45,18 +45,18 @@ use VuFind\Exception\Auth as AuthException;
 class ChoiceAuth extends AbstractBase
 {
     /**
-     * Authentication methods to present
+     * Authentication strategies to present
      *
      * @var array
      */
-    protected $methods = array();
+    protected $strategies = array();
 
     /** 
-     * Auth method selected by user
+     * Auth strategy selected by user
      *
      * @var string
      */
-    protected $method;
+    protected $strategy;
 
     /**
      * Username input
@@ -79,6 +79,21 @@ class ChoiceAuth extends AbstractBase
      */
     protected $manager;
 
+    /**
+     * Session container
+     *
+     * @var \Zend\Session\Container
+     */
+    protected $session;
+
+    /**
+     * Constructor
+     */
+    public function __construct() 
+    {
+        $this->session = new \Zend\Session\Container('ChoiceAuth');
+    }
+
     /**
      * Validate configuration parameters.  This is a support method for getConfig(),
      * so the configuration MUST be accessed using $this->config; do not call
@@ -111,7 +126,7 @@ class ChoiceAuth extends AbstractBase
     public function setConfig($config)
     {
         parent::setConfig($config);
-        $this->methods = array_map(
+        $this->strategies = array_map(
             'trim', explode(',', $config->ChoiceAuth->choice_order)
         );
     }
@@ -129,10 +144,14 @@ class ChoiceAuth extends AbstractBase
     {
         $this->username = trim($request->getPost()->get('username'));
         $this->password = trim($request->getPost()->get('password'));
-        $this->method = trim($request->getPost()->get('auth_method'));
+        $this->strategy = trim($request->getPost()->get('auth_method'));
 
-        if ($this->method == '') {
-            throw new AuthException('authentication_error_technical');
+        if ($this->strategy == '') {
+            if (isset($this->session->auth_method)) {
+                $this->strategy = $this->session->auth_method;
+            } else {
+                throw new AuthException('authentication_error_technical');
+            }
         }
 
         // Do the actual authentication work:
@@ -151,11 +170,11 @@ class ChoiceAuth extends AbstractBase
      */
     protected function authUser($request)
     {
-        $manager = $this->getPluginManager();
-        $authenticator = $manager->get($this->method);
-        $authenticator->setConfig($this->getConfig());
         try {
-            $user = $authenticator->authenticate($request);
+            $user = $this->proxyAuthMethod('authenticate', func_get_args());
+            if ($user) {
+                $this->session->auth_method = $this->strategy;
+            }
         } catch (AuthException $exception) {
             throw $exception;
         }
@@ -167,7 +186,6 @@ class ChoiceAuth extends AbstractBase
         }
     }
 
-
     /**
      * Set the manager for loading other authentication plugins.
      *
@@ -195,17 +213,77 @@ class ChoiceAuth extends AbstractBase
     }
 
     /**
-     * Does the class allow for authentication from more than one method?
-     * If so return an array that lists the classes for the methods allowed.
+     * Does the class allow for authentication from more than one strategy?
+     * If so return an array that lists the classes for the strategies allowed.
      *
      * @return array | bool
      */
     public function getClasses()
     {
         $classes = array();
-        foreach ($this->methods as $method) {
-            $classes[] = get_class($this->manager->get($method));
+        foreach ($this->strategies as $strategy) {
+            $classes[] = get_class($this->manager->get($strategy));
         }
         return $classes;
     }
+    /**
+     * Perform cleanup at logout time.
+     *
+     * @param string $url URL to redirect user to after logging out.
+     *
+     * @return string     Redirect URL (usually same as $url, but modified in
+     * some authentication modules).
+     */
+    public function logout($url)
+    {
+        // clear user's login choice
+        if (isset($this->session->auth_method)) {
+            $this->strategy = $this->session->auth_method;
+            unset($this->session->auth_method);
+            return $this->proxyAuthMethod('logout', func_get_args());
+        }
+        // No special cleanup or URL modification needed by default.
+        return $url;
+    }
+
+    /**
+     * Get the URL to establish a session (needed when the internal VuFind login
+     * form is inadequate).  Returns false when no session initiator is needed.
+     *
+     * @param string $target Full URL where external authentication strategy should
+     * send user after login (some drivers may override this).
+     *
+     * @return bool|string
+     */
+    public function getSessionInitiator($target)
+    {
+        if (isset($this->session->auth_method)) {
+            // if user has chosen and logged in; use that auth's method
+            $this->strategy = $this->session->auth_method;
+            return $this->proxyAuthMethod('getSessionInitiator', func_get_args());
+        }
+        return false;
+    }
+
+    /**
+     * Proxy auth method; a helper function to be called like:
+     *   return $this->proxyAuthMethod(METHOD, func_get_args());
+     *
+     * @param string $method the method to proxy
+     * @param array  $params array of params to pass
+     *
+     * @throws AuthException
+     * @return mixed
+     */
+    protected function proxyAuthMethod($method, $params)
+    {
+        $manager = $this->getPluginManager();
+        $authenticator = $manager->get($this->strategy);
+        $authenticator->setConfig($this->getConfig());
+        if (!is_callable(array($authenticator, $method))) {
+            throw new AuthException($this->strategy . "has no method $method");
+        }
+        return call_user_func_array(array($authenticator, $method), $params);
+    }
+
 }
diff --git a/module/VuFind/src/VuFind/Config/Upgrade.php b/module/VuFind/src/VuFind/Config/Upgrade.php
index 282ff5bcecf87d3628cf879ab997374cbe664e4e..c97adc07b756fbaf501b2d99b2b7519cbec79bd4 100644
--- a/module/VuFind/src/VuFind/Config/Upgrade.php
+++ b/module/VuFind/src/VuFind/Config/Upgrade.php
@@ -744,6 +744,17 @@ class Upgrade
         );
         $this->applyOldSettings('Summon.ini', $groups);
 
+        // Turn on advanced checkbox facets if we're upgrading from a version
+        // prior to 2.3.
+        if ((float)$this->from < 2.3) {
+            $cfg = & $this->newConfigs['Summon.ini']['Advanced_Facet_Settings'];
+            if (!isset($cfg['special_facets']) || empty($cfg['special_facets'])) {
+                $cfg['special_facets'] = 'checkboxes:Summon';
+            } else if (false === strpos('checkboxes', $cfg['special_facets'])) {
+                $cfg['special_facets'] .= ',checkboxes:Summon';
+            }
+        }
+
         // save the file
         $this->saveModifiedConfig('Summon.ini');
     }
diff --git a/module/VuFind/src/VuFind/Controller/AbstractBase.php b/module/VuFind/src/VuFind/Controller/AbstractBase.php
index 17fb41a55ef9c84e730fe337f18eb9e9ec59b398..acf9804ce14eda9bb922e30cb1b6a178ad57f5ae 100644
--- a/module/VuFind/src/VuFind/Controller/AbstractBase.php
+++ b/module/VuFind/src/VuFind/Controller/AbstractBase.php
@@ -268,13 +268,15 @@ class AbstractBase extends AbstractActionController
         // lightbox (since lightboxes use a different followup mechanism).
         if (!$this->inLightbox()) {
             $this->followup()->store($extras);
-        } elseif ($this->getAuthManager()->getSessionInitiator()) {
+        } else {
             // If we're in a lightbox and using an authentication method
             // with a session initiator, the user will be redirected outside
             // of VuFind and then redirected back. Thus, we need to store a
             // followup URL to avoid losing context, but we don't want to
             // store the AJAX request URL that populated the lightbox. The
             // delightboxURL() routine will remap the URL appropriately.
+            // We can set this whether or not there's a session initiator
+            // because it will be cleared when needed.
             $url = $this->delightboxURL($this->getServerUrl());
             $this->followup()->store($extras, $url);
         }
diff --git a/module/VuFind/src/VuFind/Controller/AbstractSearch.php b/module/VuFind/src/VuFind/Controller/AbstractSearch.php
index e8bdeb640e1dafeb15a31948f97ea9139caafd8a..44a6c152f2209754beae2967bec0adb053809f65 100644
--- a/module/VuFind/src/VuFind/Controller/AbstractSearch.php
+++ b/module/VuFind/src/VuFind/Controller/AbstractSearch.php
@@ -553,4 +553,50 @@ class AbstractSearch extends AbstractBase
         }
         return $parsed;
     }
+
+    /**
+     * Process the checkbox setting from special facets.
+     *
+     * @param array  $params      Parameters to the checkbox setting
+     * @param object $savedSearch Saved search object (false if none)
+     *
+     * @return array
+     */
+    protected function processAdvancedCheckboxes($params, $savedSearch = false)
+    {
+        // Set defaults for missing parameters:
+        $config = isset($params[0]) ? $params[0] : 'facets';
+        $section = isset($params[1]) ? $params[1] : 'CheckboxFacets';
+
+        // Load config file:
+        $config = $this->getServiceLocator()->get('VuFind\Config')->get($config);
+
+        // Process checkbox settings in config:
+        if (substr($section, 0, 1) == '~') {        // reverse flag
+            $section = substr($section, 1);
+            $flipCheckboxes = true;
+        }
+        $checkboxFacets = ($section && isset($config->$section))
+            ? $config->$section->toArray() : array();
+        if (isset($flipCheckboxes) && $flipCheckboxes) {
+            $checkboxFacets = array_flip($checkboxFacets);
+        }
+
+        // Reformat for convenience:
+        $formatted = array();
+        foreach ($checkboxFacets as $filter => $desc) {
+            $current = compact("desc", "filter");
+            $current['selected']
+                = $savedSearch && $savedSearch->getParams()->hasFilter($filter);
+            // We don't want to double-display checkboxes on advanced search, so
+            // if they are checked, we should remove them from the object to
+            // prevent display in the "other filters" area.
+            if ($current['selected']) {
+                $savedSearch->getParams()->removeFilter($filter);
+            }
+            $formatted[] = $current;
+        }
+
+        return $formatted;
+    }
 }
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Controller/CoverController.php b/module/VuFind/src/VuFind/Controller/CoverController.php
index 220f33fca16d817956c8cbf9d7f5a1da698a521b..e1fda710ba2ee5d2e5d842d9279b9033616d5bde 100644
--- a/module/VuFind/src/VuFind/Controller/CoverController.php
+++ b/module/VuFind/src/VuFind/Controller/CoverController.php
@@ -109,6 +109,22 @@ class CoverController extends AbstractBase
         $headers->addHeaderLine(
             'Content-type', $this->getLoader()->getContentType()
         );
+
+        // Send proper caching headers so that the user's browser
+        // is able to cache the cover images and not have to re-request
+        // then on each page load. Default TTL set at 14 days
+
+        $coverImageTtl = (60*60*24*14); // 14 days
+        $headers->addHeaderLine(
+            'Cache-Control', "maxage=".$coverImageTtl
+        );
+        $headers->addHeaderLine(
+            'Pragma', 'public'
+        );
+        $headers->addHeaderLine(
+            'Expires', gmdate('D, d M Y H:i:s', time()+$coverImageTtl) . ' GMT'
+        );
+
         $response->setContent($this->getLoader()->getImage());
         return $response;
     }
diff --git a/module/VuFind/src/VuFind/Controller/MyResearchController.php b/module/VuFind/src/VuFind/Controller/MyResearchController.php
index d30bc3aab1fba56f8a50c1c3428c321a9adf52d7..f2778f364c7cb59ff9c8457b0a15edbbdd81eda9 100644
--- a/module/VuFind/src/VuFind/Controller/MyResearchController.php
+++ b/module/VuFind/src/VuFind/Controller/MyResearchController.php
@@ -250,6 +250,27 @@ class MyResearchController extends AbstractBase
         return $view;
     }
 
+    /**
+     * User login action -- clear any previous follow-up information prior to
+     * triggering a login process. This is used for explicit login links within
+     * the UI to differentiate them from contextual login links that are triggered
+     * by attempting to access protected actions.
+     *
+     * @return mixed
+     */
+    public function userloginAction()
+    {
+        $followup = $this->followup()->retrieve();
+        if (isset($followup->url)) {
+            unset($followup->url);
+        }
+        $this->storeRefererForPostLoginRedirect();
+        if ($si = $this->getSessionInitiator()) {
+            return $this->redirect()->toUrl($si);
+        }
+        return $this->forwardTo('MyResearch', 'Login');
+    }
+
     /**
      * Logout Action
      *
diff --git a/module/VuFind/src/VuFind/Controller/SearchController.php b/module/VuFind/src/VuFind/Controller/SearchController.php
index d9253a917c1da5404baf8d360529ddad664392b2..820d27062ca758bbb9599b4027a2a0264f1e8aad 100644
--- a/module/VuFind/src/VuFind/Controller/SearchController.php
+++ b/module/VuFind/src/VuFind/Controller/SearchController.php
@@ -61,7 +61,13 @@ class SearchController extends AbstractSearch
             $view->illustratedLimit
                 = $this->getIllustrationSettings($view->saved);
         }
+        if (isset($specialFacets['checkboxes'])) {
+            $view->checkboxFacets = $this->processAdvancedCheckboxes(
+                $specialFacets['checkboxes'], $view->saved
+            );
+        }
         $view->ranges = $this->getAllRangeSettings($specialFacets, $view->saved);
+
         return $view;
     }
 
diff --git a/module/VuFind/src/VuFind/Controller/SummonController.php b/module/VuFind/src/VuFind/Controller/SummonController.php
index 888d33113bf5fb1b6726feab37570a8b84c12170..0097f11a5e9e052ee3cad6ba9807f3dc4b28e060 100644
--- a/module/VuFind/src/VuFind/Controller/SummonController.php
+++ b/module/VuFind/src/VuFind/Controller/SummonController.php
@@ -101,6 +101,11 @@ class SummonController extends AbstractSearch
         $specialFacets = $this->parseSpecialFacetsSetting(
             $view->options->getSpecialAdvancedFacets()
         );
+        if (isset($specialFacets['checkboxes'])) {
+            $view->checkboxFacets = $this->processAdvancedCheckboxes(
+                $specialFacets['checkboxes'], $view->saved
+            );
+        }
         $view->ranges = $this
             ->getAllRangeSettings($specialFacets, $view->saved, 'Summon');
 
diff --git a/module/VuFind/tests/fixtures/configs/1.1/config.ini b/module/VuFind/tests/fixtures/configs/1.1/config.ini
index 7e1aff3ce06fd0de141232dfdbce763cfb1b2e0b..66d89a7107d0d93cda74d9a6882268675f9e176e 100644
--- a/module/VuFind/tests/fixtures/configs/1.1/config.ini
+++ b/module/VuFind/tests/fixtures/configs/1.1/config.ini
@@ -241,9 +241,9 @@ pw               = "Password"
 ;side_recommend[] = CatalogResults:lookfor
 
 ; Summon is Optional.  See also the separate Summon.ini file.
-;[Summon]
-;apiId        = myAccessId
-;apiKey       = mySecretKey
+[Summon]
+apiId        = myAccessId
+apiKey       = mySecretKey
 
 ; WorldCat is Optional.  Worldcat offers extra features such as "Other Editions"
 ; and the WorldCat searching.
diff --git a/module/VuFind/tests/fixtures/configs/1.2/config.ini b/module/VuFind/tests/fixtures/configs/1.2/config.ini
index ee9c8cb5f3c42db3905571190c2bd298bdbd729b..dd0cb96afff94f7645e5b3df8ab706a66aa7a4ff 100644
--- a/module/VuFind/tests/fixtures/configs/1.2/config.ini
+++ b/module/VuFind/tests/fixtures/configs/1.2/config.ini
@@ -275,9 +275,9 @@ pw               = "Password"
 ;side_recommend[] = CatalogResults:lookfor
 
 ; Summon is Optional.  See also the separate Summon.ini file.
-;[Summon]
-;apiId        = myAccessId
-;apiKey       = mySecretKey
+[Summon]
+apiId        = myAccessId
+apiKey       = mySecretKey
 
 ; WorldCat is Optional.  Worldcat offers extra features such as "Other Editions"
 ; and the WorldCat searching.
diff --git a/module/VuFind/tests/fixtures/configs/1.3/config.ini b/module/VuFind/tests/fixtures/configs/1.3/config.ini
index da980b0ef6cd3465dd93d4ba5d4039553069ad47..1672da3ab2931dc0ab50c55f3d8c6393572878c6 100644
--- a/module/VuFind/tests/fixtures/configs/1.3/config.ini
+++ b/module/VuFind/tests/fixtures/configs/1.3/config.ini
@@ -337,9 +337,9 @@ pw               = "Password"
 ;side_recommend[] = CatalogResults:lookfor
 
 ; Summon is Optional.  See also the separate Summon.ini file.
-;[Summon]
-;apiId        = myAccessId
-;apiKey       = mySecretKey
+[Summon]
+apiId        = myAccessId
+apiKey       = mySecretKey
 
 ; WorldCat is Optional.  Worldcat offers extra features such as "Other Editions"
 ; and the WorldCat searching.
diff --git a/module/VuFind/tests/fixtures/configs/1.4/config.ini b/module/VuFind/tests/fixtures/configs/1.4/config.ini
index ae09cd7de81603ad10b682058eb34025f18a9245..abf8ebf8d954c672e0852e30d28e4a359c640ee5 100644
--- a/module/VuFind/tests/fixtures/configs/1.4/config.ini
+++ b/module/VuFind/tests/fixtures/configs/1.4/config.ini
@@ -413,9 +413,9 @@ pw               = "Password"
 ;side_recommend[] = CatalogResults:lookfor
 
 ; Summon is Optional.  See also the separate Summon.ini file.
-;[Summon]
-;apiId        = myAccessId
-;apiKey       = mySecretKey
+[Summon]
+apiId        = myAccessId
+apiKey       = mySecretKey
 
 ; WorldCat is Optional.  Worldcat offers extra features such as "Other Editions"
 ; and the WorldCat searching.
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/UpgradeTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/UpgradeTest.php
index 2158a0de2ce46dd979a78a1031e0570cccaaa4c8..83bb5029a33af732454c705374f66cfae51621a0 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/UpgradeTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/UpgradeTest.php
@@ -109,6 +109,13 @@ class UpgradeTest extends \VuFindTest\Unit\TestCase
             $this->assertEquals(0, count($warnings));
         }
 
+        // Summon should always have the checkboxes setting turned on after
+        // upgrade:
+        $this->assertEquals(
+            'daterange,checkboxes:Summon',
+            $results['Summon.ini']['Advanced_Facet_Settings']['special_facets']
+        );
+
         // Make sure the obsolete Index/local setting is removed:
         $this->assertFalse(isset($results['config.ini']['Index']['local']));
 
diff --git a/run_vufind.bat b/run_vufind.bat
index 73ba047aa56102a022e0643c68de8c0b60f21e04..59f6859e8587fe66a243a2a8aca0b9b20ea11e10 100644
--- a/run_vufind.bat
+++ b/run_vufind.bat
@@ -20,7 +20,7 @@ rem JAVA_OPTIONS
 rem   Extra options to pass to the JVM
 rem
 rem JETTY_HOME
-rem   Where Jetty is installed. If not set, the script will try to guess it based 
+rem   Where Jetty is installed. If not set, the script will try to guess it based
 rem   on the SOLR_HOME setting. The java system property "jetty.home" will be
 rem   set to this value for use by configure.xml files, f.e.:
 rem
@@ -46,7 +46,7 @@ rem
 rem JETTY_ARGS
 rem   The default arguments to pass to jetty.
 
-rem Make sure that environment edits are local and that we have access to the 
+rem Make sure that environment edits are local and that we have access to the
 rem Windows command extensions.
 setlocal enableextensions
 if not errorlevel 1 goto extensionsokay
@@ -60,6 +60,38 @@ set ACTION=%1
 shift
 
 rem Set Performance options for JETTY
+rem ========================================================================
+rem -Xms    Sets the initial heap size for when the JVM starts.
+rem -Xmx    Sets the maximum heap size.
+rem If you often get a "catalog error" or need to restart vufind you
+rem may need to increase the Xmx value if your system has the memory
+rem to support it. For example, on a system with 4GB of memory that is
+rem dedicated to running Vufind you may want to set the Xmx value to
+rem 2048m or 3,072m.
+rem
+rem IMPORTANT NOTE: You may want to skip setting the Xms value
+rem so that JAVA / Vufind will only use what it needs - potentialy
+rem leaving more memory for the rest of the system. To see the JVM memory
+rem usage visit your solr URL, possibly the same URL as your vufind,
+rem instance but appended with :8080/solr/
+rem
+rem The most important factors for determining the amount of memory
+rem that you will need to allocate are the number of records you have
+rem indexed, and how much traffic your site receives. It may also be
+rem beneficial to limit or block crawlers and robots as they can,
+rem at times, generate so many requests that your site has poor
+rem performance for your human patrons
+rem
+rem For more information on tuning vufind and java, see the
+rem vufind wiki article at https://vufind.org/wiki/performance
+rem and http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html
+rem
+rem Some example settings:
+rem JAVA_OPTIONS="-server -Xms1048576k -Xmx1048576k -XX:+UseParallelGC -XX:NewRatio=5"
+rem JAVA_OPTIONS="-server -Xmx1048576k -XX:+UseParallelGC -XX:NewRatio=5"
+rem JAVA_OPTIONS="-server -Xms1024m -Xmx1024m -XX:+UseParallelGC -XX:NewRatio=5"
+rem JAVA_OPTIONS="-server -Xmx1024m -XX:+UseParallelGC -XX:NewRatio=5"
+rem ========================================================================
 if not "!%JAVA_OPTIONS%!"=="!!" goto javaoptionsset
 set JAVA_OPTIONS=-server -Xms1024m -Xmx1024m -XX:+UseParallelGC -XX:NewRatio=5
 :javaoptionsset
diff --git a/solr/biblio/conf/solrconfig.xml b/solr/biblio/conf/solrconfig.xml
index cb00f6062aaf46b126289982ba627e388d49806f..090d9f059227ca54e1d2fc4e4f6e2bf2a3edd8b6 100644
--- a/solr/biblio/conf/solrconfig.xml
+++ b/solr/biblio/conf/solrconfig.xml
@@ -587,7 +587,6 @@
        </lst>
        -->
   </requestHandler>
-  <requestHandler name="/update/json" class="solr.JsonUpdateRequestHandler"/>
 
   <!-- Field Analysis Request Handler
 
diff --git a/solr/website/conf/solrconfig.xml b/solr/website/conf/solrconfig.xml
index c6257d239a2a2c198f879f25dd9ba60c9425ed25..e547b612722817852a5c0f208c24a8221150966d 100644
--- a/solr/website/conf/solrconfig.xml
+++ b/solr/website/conf/solrconfig.xml
@@ -522,7 +522,6 @@
        </lst>
        -->
   </requestHandler>
-  <requestHandler name="/update/json" class="solr.JsonUpdateRequestHandler"/>
 
   <!-- Field Analysis Request Handler
 
diff --git a/themes/blueprint/templates/header.phtml b/themes/blueprint/templates/header.phtml
index 3354c9ac3ace3ee026b75d279e1749222ef2ea15..556846dbfb04154a420bdc3cf9f9c79f53a7ddbb 100644
--- a/themes/blueprint/templates/header.phtml
+++ b/themes/blueprint/templates/header.phtml
@@ -14,10 +14,10 @@
         <a class="logout" href="<?=$this->url('myresearch-logout')?>"><?=$this->transEsc("Log Out")?></a>
       </div>
       <div id="loginOptions"<?=$account->isLoggedIn() ? ' class="hide"' : ''?>>
-      <? if ($sessionInitiator = $account->getSessionInitiator($this->serverUrl($this->url('myresearch-home')))): ?>
-        <a class="login" href="<?=$this->escapeHtml($sessionInitiator)?>"><?=$this->transEsc("Institutional Login")?></a>
+      <? if ($account->getSessionInitiator($this->serverUrl($this->url('myresearch-userlogin')))): ?>
+        <a class="login" href="<?=$this->url('myresearch-userlogin')?>"><?=$this->transEsc("Institutional Login")?></a>
       <? else: ?>
-        <a class="login" href="<?=$this->url('myresearch-home')?>"><?=$this->transEsc("Login")?></a>
+        <a class="login" href="<?=$this->url('myresearch-userlogin')?>"><?=$this->transEsc("Login")?></a>
       <? endif; ?>
       </div>
     <? endif; ?>
diff --git a/themes/blueprint/templates/search/advanced/checkbox-filters.phtml b/themes/blueprint/templates/search/advanced/checkbox-filters.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..1eba661ad22d9c5a0d134bf94f038c4db19aadea
--- /dev/null
+++ b/themes/blueprint/templates/search/advanced/checkbox-filters.phtml
@@ -0,0 +1,13 @@
+<? if (isset($this->checkboxFacets) && count($this->checkboxFacets) > 0): ?>
+  <div class="span-7">
+    <fieldset>
+      <? foreach ($this->checkboxFacets as $current): ?>
+        <div class="checkboxFilter">
+          <input type="checkbox" name="filter[]" value="<?=$this->escapeHtml($current['filter'])?>" id="<?=$this->escapeHtml(str_replace(' ', '', $current['desc']))?>" <? if ($current['selected']): ?>checked="checked" <? endif; ?> />
+          <label for="<?=$this->escapeHtml(str_replace(' ', '', $current['desc']))?>"><?=$this->transEsc($current['desc'])?></label>
+        </div>
+      <? endforeach; ?>
+    </fieldset>
+  </div>
+  <div class="clear"></div>
+<?endif;?>
diff --git a/themes/blueprint/templates/search/advanced/solr.phtml b/themes/blueprint/templates/search/advanced/solr.phtml
index f5d19893f0cfe914c027e3c2971d92f1043dc479..632c525c0a2a5778c1b6d272c0e7a59e9111b85f 100644
--- a/themes/blueprint/templates/search/advanced/solr.phtml
+++ b/themes/blueprint/templates/search/advanced/solr.phtml
@@ -1,5 +1,12 @@
-<? if (!empty($this->facetList)): ?>
+<? if (!empty($this->facetList) || !empty($this->checkboxFacets)): ?>
   <h3><?=$this->transEsc('Limit To')?></h3>
+<? endif; ?>
+
+<? if (!empty($this->checkboxFacets)): ?>
+  <?=$this->render('search/advanced/checkbox-filters.phtml')?>
+<? endif; ?>
+
+<? if (!empty($this->facetList)): ?>
   <? foreach ($this->facetList as $field => $list): ?>
   <div class="<?=($field=='callnumber-first')?'span-7':'span-4'?>">
     <label class="displayBlock" for="limit_<?=$this->escapeHtml(str_replace(' ', '', $field))?>"><?=$this->transEsc($list['label'])?>:</label>
diff --git a/themes/blueprint/templates/search/advanced/summon.phtml b/themes/blueprint/templates/search/advanced/summon.phtml
index 7ba27ada0a79fd4c5d4f262a89a1c796e25a08a9..9f15eda79237f85dc0900dcf0901ad0a2bfb23e0 100644
--- a/themes/blueprint/templates/search/advanced/summon.phtml
+++ b/themes/blueprint/templates/search/advanced/summon.phtml
@@ -1,5 +1,12 @@
-<? if (!empty($this->facetList)): ?>
+<? if (!empty($this->facetList) || !empty($this->checkboxFacets)): ?>
   <h3><?=$this->transEsc('Limit To')?></h3>
+<? endif; ?>
+
+<? if (!empty($this->checkboxFacets)): ?>
+  <?=$this->render('search/advanced/checkbox-filters.phtml')?>
+<? endif; ?>
+
+<? if (!empty($this->facetList)): ?>
   <? foreach ($this->facetList as $field => $list): ?>
   <div class="span-5">
     <label class="displayBlock" for="limit_<?=$this->escapeHtml(str_replace(' ', '', $field))?>"><?=$this->transEsc($list['label'])?>:</label>
diff --git a/themes/bootprint/templates/header.phtml b/themes/bootprint/templates/header.phtml
index d661c1236781118b7d93bb3416d38d51f0f74b8f..d8d3e0bce95c018ba55deeec75895f25ae0daf7b 100644
--- a/themes/bootprint/templates/header.phtml
+++ b/themes/bootprint/templates/header.phtml
@@ -23,10 +23,10 @@
       </span>
       <span id="loginOptions"<? if($account->isLoggedIn()): ?> class="hide"<? endif ?>>
         <i class="icon-signin"></i> 
-        <? if ($sessionInitiator = $account->getSessionInitiator($this->serverUrl($this->url('myresearch-home')))): ?>
-          <a href="<?=$this->escapeHtml($sessionInitiator)?>"><?=$this->transEsc("Institutional Login")?></a>
+        <? if ($account->getSessionInitiator($this->serverUrl($this->url('myresearch-userlogin')))): ?>
+          <a href="<?=$this->url('myresearch-userlogin')?>"><?=$this->transEsc("Institutional Login")?></a>
         <? else: ?>
-          <a href="<?=$this->url('myresearch-home')?>" class="modal-link" title="<?=$this->transEsc("Login")?>"><?=$this->transEsc("Login")?></a>
+          <a href="<?=$this->url('myresearch-userlogin')?>" class="modal-link" title="<?=$this->transEsc("Login")?>"><?=$this->transEsc("Login")?></a>
         <? endif; ?>
       </span>
     <? endif; ?>
diff --git a/themes/bootstrap/js/common.js b/themes/bootstrap/js/common.js
index 64b30addd3f8ebf322f789a747780120373c913d..af668b82e293ba69cf8f5946d6b2d087f56987b8 100644
--- a/themes/bootstrap/js/common.js
+++ b/themes/bootstrap/js/common.js
@@ -379,7 +379,7 @@ $(document).ready(function() {
   });
   // Login link
   $('#loginOptions a.modal-link').click(function() {
-    return Lightbox.get('MyResearch','Login',{},{'loggingin':true});
+    return Lightbox.get('MyResearch','UserLogin',{},{'loggingin':true});
   });
   // Email search link
   $('.mailSearch').click(function() {
diff --git a/themes/bootstrap/templates/header.phtml b/themes/bootstrap/templates/header.phtml
index 46152e7d0b48de1b2778d4c18d8e916281606952..7fbd146b1b81a9094cc29437c47ef60432f7d402 100644
--- a/themes/bootstrap/templates/header.phtml
+++ b/themes/bootstrap/templates/header.phtml
@@ -23,10 +23,10 @@
       </span>
       <span id="loginOptions"<? if($account->isLoggedIn()): ?> class="hide"<? endif ?>>
         <i class="icon-signin"></i> 
-        <? if ($sessionInitiator = $account->getSessionInitiator($this->serverUrl($this->url('myresearch-home')))): ?>
-          <a href="<?=$this->escapeHtml($sessionInitiator)?>"><?=$this->transEsc("Institutional Login")?></a>
+        <? if ($account->getSessionInitiator($this->serverUrl($this->url('myresearch-userlogin')))): ?>
+          <a href="<?=$this->url('myresearch-userlogin')?>"><?=$this->transEsc("Institutional Login")?></a>
         <? else: ?>
-          <a href="<?=$this->url('myresearch-home')?>" class="modal-link" title="<?=$this->transEsc("Login")?>"><?=$this->transEsc("Login")?></a>
+          <a href="<?=$this->url('myresearch-userlogin')?>" class="modal-link" title="<?=$this->transEsc("Login")?>"><?=$this->transEsc("Login")?></a>
         <? endif; ?>
       </span>
     <? endif; ?>
diff --git a/themes/bootstrap/templates/search/advanced/checkbox-filters.phtml b/themes/bootstrap/templates/search/advanced/checkbox-filters.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..cf8c22b72ccf6f496fa618128ddccb85e7b8c687
--- /dev/null
+++ b/themes/bootstrap/templates/search/advanced/checkbox-filters.phtml
@@ -0,0 +1,12 @@
+<? if (isset($this->checkboxFacets) && count($this->checkboxFacets) > 0): ?>
+  <fieldset>
+    <? foreach ($this->checkboxFacets as $current): ?>
+      <div class="checkboxFilter">
+        <label class="checkbox">
+          <input type="checkbox" name="filter[]" value="<?=$this->escapeHtml($current['filter'])?>" id="<?=$this->escapeHtml(str_replace(' ', '', $current['desc']))?>"<? if ($current['selected']): ?> checked="checked"<? endif; ?>/>
+          <?=$this->transEsc($current['desc'])?>
+        </label>
+      </div>
+    <? endforeach; ?>
+  </fieldset>
+<?endif;?>
\ No newline at end of file
diff --git a/themes/bootstrap/templates/search/advanced/solr.phtml b/themes/bootstrap/templates/search/advanced/solr.phtml
index 74b0572f8a2c8f144dc080e75444a7e5287c2a2d..e7723c85f5d427d37516258779fac264585fcf1f 100644
--- a/themes/bootstrap/templates/search/advanced/solr.phtml
+++ b/themes/bootstrap/templates/search/advanced/solr.phtml
@@ -1,5 +1,12 @@
-<? if (!empty($this->facetList)): ?>
+<? if (!empty($this->facetList) || !empty($this->checkboxFacets)): ?>
   <p class="lead"><?=$this->transEsc('Limit To')?></p>
+<? endif; ?>
+
+<? if (!empty($this->checkboxFacets)): ?>
+  <?=$this->render('search/advanced/checkbox-filters.phtml')?>
+<? endif; ?>
+
+<? if (!empty($this->facetList)): ?>
   <div class="row-fluid">
     <? foreach ($this->facetList as $field => $list): ?>
       <div class="span<?=floor(12/count($this->facetList)) ?>">
diff --git a/themes/bootstrap/templates/search/advanced/summon.phtml b/themes/bootstrap/templates/search/advanced/summon.phtml
index ce28d09242d819e1630f837fb04d2ee44f346e18..3102e37bec83a8133293ec0b3d26d651104a7e3d 100644
--- a/themes/bootstrap/templates/search/advanced/summon.phtml
+++ b/themes/bootstrap/templates/search/advanced/summon.phtml
@@ -1,19 +1,26 @@
+<? if (!empty($this->facetList) || !empty($this->checkboxFacets)): ?>
+  <p class="lead"><?=$this->transEsc('Limit To')?></p>
+<? endif; ?>
+
+<? if (!empty($this->checkboxFacets)): ?>
+  <?=$this->render('search/advanced/checkbox-filters.phtml')?>
+<? endif; ?>
+
 <? if (!empty($this->facetList)): ?>
-  <h3><?=$this->transEsc('Limit To')?></h3>
   <div class="row-fluid">
     <? foreach ($this->facetList as $field => $list): ?>
       <div class="span<?=floor(12/count($this->facetList)) ?>">
         <label class="displayBlock" for="limit_<?=$this->escapeHtml(str_replace(' ', '', $field))?>"><?=$this->transEsc($list['label'])?>:</label>
         <select class="span12" id="limit_<?=$this->escapeHtml(str_replace(' ', '', $field))?>" name="filter[]" multiple="multiple" size="10">
           <?
-              // Sort the current facet list alphabetically; we'll use this data
-              // along with the foreach below to display facet options in the
-              // correct order.
-              $sorted = array();
-              foreach ($list['list'] as $i => $value) {
-                  $sorted[$i] = $value['displayText'];
-              }
-              natcasesort($sorted);
+            // Sort the current facet list alphabetically; we'll use this data
+            // along with the foreach below to display facet options in the
+            // correct order.
+            $sorted = array();
+            foreach ($list['list'] as $i => $value) {
+              $sorted[$i] = $value['displayText'];
+            }
+            natcasesort($sorted);
           ?>
           <? foreach ($sorted as $i => $display): ?>
             <? $value = $list['list'][$i]; ?>
diff --git a/themes/jquerymobile/templates/Auth/Shibboleth/login.phtml b/themes/jquerymobile/templates/Auth/Shibboleth/login.phtml
index 94f44ef3d93574b3e3bcc672e4abbf1042b762f4..d4463c48646cadaddee5563605a680afa1c8fb55 100644
--- a/themes/jquerymobile/templates/Auth/Shibboleth/login.phtml
+++ b/themes/jquerymobile/templates/Auth/Shibboleth/login.phtml
@@ -1,3 +1,3 @@
 <? $account = $this->auth()->getManager(); ?>
 <? $sessionInitiator = $account->getSessionInitiator($this->serverUrl($this->url('myresearch-home'))); ?>
-<a href="<?=$this->escapeHtml($sessionInitiator)?>"><?=$this->transEsc("Institutional Login")?></a>
+<a rel="external" href="<?=$this->escapeHtml($sessionInitiator)?>"><?=$this->transEsc("Institutional Login")?></a>
diff --git a/themes/jquerymobile/templates/default-footer-navbar.phtml b/themes/jquerymobile/templates/default-footer-navbar.phtml
index 9229aee1e312e2ee7e4478a834d8c15953d9d7c8..a72c5bbba364ca6f11286b6a48fb9b1256d53cc3 100644
--- a/themes/jquerymobile/templates/default-footer-navbar.phtml
+++ b/themes/jquerymobile/templates/default-footer-navbar.phtml
@@ -3,7 +3,7 @@
   <ul>
     <li><a data-rel="dialog" href="#Language-dialog" data-transition="pop"><?=$this->transEsc('Language')?></a></li>
     <? if (is_object($account) && $account->loginEnabled()): // hide login/logout if unavailable ?>
-      <li><a rel="external" href="<?=$this->url('myresearch-home')?>"><?=$this->transEsc('Account')?></a></li>
+      <li><a rel="external" href="<?=$this->url((is_object($account) && $account->isLoggedIn()) ? 'myresearch-home' : 'myresearch-userlogin')?>"><?=$this->transEsc('Account')?></a></li>
     <? endif; ?>
     <? if (is_object($account) && $account->isLoggedIn()): ?>
       <li><a rel="external" href="<?=$this->url('myresearch-logout')?>"><?=$this->transEsc("Log Out")?></a></li>
diff --git a/themes/jquerymobile/templates/myresearch/newpassword.phtml b/themes/jquerymobile/templates/myresearch/newpassword.phtml
index fbd77f2512c42b8a1ab6e57ff9177764224e68df..fdece081381c81b1f03e4ac25f10525a98ecee85 100644
--- a/themes/jquerymobile/templates/myresearch/newpassword.phtml
+++ b/themes/jquerymobile/templates/myresearch/newpassword.phtml
@@ -6,7 +6,7 @@
   $extraButton = '<a rel="external" href="'
     . $this->url('myresearch-home')
     . '" data-icon="back" class="ui-btn-left">'
-    . $this->transEsc('My Profile')
+    . $this->transEsc('Account')
     . '</a>';
 ?>
 <div data-role="page" id="MyResearch-newpassword" class="newpassword">
diff --git a/themes/jquerymobile/templates/myresearch/recover.phtml b/themes/jquerymobile/templates/myresearch/recover.phtml
index 4e73da0009ce325086927d9c778740206479a2be..e9246a1767682545a8472e1d1938abbcf0a54d0b 100644
--- a/themes/jquerymobile/templates/myresearch/recover.phtml
+++ b/themes/jquerymobile/templates/myresearch/recover.phtml
@@ -4,11 +4,9 @@
 
   // Set up extra button for header:
   $extraButton = '<a rel="external" href="'
-    . $this->url('myresearch-home')
+    . $this->url('myresearch-userlogin')
     . '" data-icon="back" class="ui-btn-left">';
-  $extraButton .= $this->auth()->isLoggedIn()
-    ? $this->transEsc('My Profile')
-    : $this->transEsc('Login');
+  $extraButton .= $this->transEsc('Login');
   $extraButton .= '</a>';
 ?>
 <div data-role="page" id="MyResearch-recover" class="results-page">
@@ -24,4 +22,4 @@
     <? endif; ?>
   </div>
   <?=$this->mobileMenu()->footer() ?>
-</div>
\ No newline at end of file
+</div>
diff --git a/vufind.sh b/vufind.sh
index c79179556344d7c65753d0bfd5f8ffcb251509b1..5928c9163c96a5e4c39455cd9a88b1b8c6a92b42 100755
--- a/vufind.sh
+++ b/vufind.sh
@@ -106,7 +106,36 @@ findDirectory()
 ##################################################
 # Set Performance options for JETTY
 ##################################################
-#JAVA_OPTIONS="-server -Xms1048576k -Xmx1048576k -XX:+UseParallelGC -XX:NewRatio=5"
+# -Xms    Sets the initial heap size for when the JVM starts.
+# -Xmx    Sets the maximum heap size.
+# If you often get a "catalog error" or need to restart vufind you
+# may need to increase the Xmx value if your system has the memory
+# to support it. For example, on a system with 4GB of memory that is
+# dedicated to running Vufind you may want to set the Xmx value to
+# 2048m or 3,072m.
+#
+# IMPORTANT NOTE: You may want to skip setting the Xms value
+# so that JAVA / Vufind will only use what it needs - potentialy
+# leaving more memory for the rest of the system. To see the JVM memory
+# usage visit your solr URL, possibly the same URL as your vufind,
+# instance but appended with :8080/solr/
+#
+# The most important factors for determining the amount of memory
+# that you will need to allocate are the number of records you have
+# indexed, and how much traffic your site receives. It may also be
+# beneficial to limit or block crawlers and robots as they can,
+# at times, generate so many requests that your site has poor
+# performance for your human patrons
+#
+# For more information on tuning vufind and java, see the
+# vufind wiki article at https://vufind.org/wiki/performance
+# and http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html
+#
+# Some example settings:
+# JAVA_OPTIONS="-server -Xms1048576k -Xmx1048576k -XX:+UseParallelGC -XX:NewRatio=5"
+# JAVA_OPTIONS="-server -Xmx1048576k -XX:+UseParallelGC -XX:NewRatio=5"
+# JAVA_OPTIONS="-server -Xms1024m -Xmx1024m -XX:+UseParallelGC -XX:NewRatio=5"
+# JAVA_OPTIONS="-server -Xmx1024m -XX:+UseParallelGC -XX:NewRatio=5"
 if [ -z "$JAVA_OPTIONS" ]
 then
   JAVA_OPTIONS="-server -Xms1024m -Xmx1024m -XX:+UseParallelGC -XX:NewRatio=5"
@@ -321,14 +350,14 @@ then
         /opt/java \
         /opt/jdk \
         /opt/jre \
-    " 
+    "
     JAVA_NAMES="java jdk jre"
     for N in $JAVA_NAMES ; do
         for L in $JAVA_LOCATIONS ; do
-            [ -d $L ] || continue 
+            [ -d $L ] || continue
             find $L -name "$N" ! -type d | grep -v threads | while read J ; do
                 [ -x $J ] || continue
-                VERSION=`eval $J -version 2>&1`       
+                VERSION=`eval $J -version 2>&1`
                 [ $? = 0 ] || continue
                 VERSION=`expr "$VERSION" : '.*"\(1.[0-9\.]*\)["_]'`
                 [ "$VERSION" = "" ] && continue
@@ -435,7 +464,7 @@ case "$ACTION" in
 
         echo "STARTED VuFind `date`" >> $JETTY_CONSOLE
         echo "$RUN_CMD"
-        nohup sh -c "exec $RUN_CMD >>$JETTY_CONSOLE 2>&1" &
+        nohup sh -c "exec $RUN_CMD >>$JETTY_CONSOLE 2>&1" > /dev/null &
         echo $! > $JETTY_PID
         echo "VuFind running pid="`cat $JETTY_PID`
         ;;