Index: includes/menu.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/menu.inc,v
retrieving revision 1.322
diff -u -p -r1.322 menu.inc
--- includes/menu.inc	25 Apr 2009 15:19:12 -0000	1.322
+++ includes/menu.inc	3 May 2009 22:36:53 -0000
@@ -2721,13 +2721,18 @@ function menu_path_is_external($path) {
 function _menu_site_is_offline() {
   // Check if site is set to maintenance mode.
   if (variable_get('site_offline', 0)) {
-    // Check if the user has administration privileges.
-    if (user_access('administer site configuration')) {
+    // Check if the user is allowed to access site in maintenance mode.
+    if (user_access('access site in maintenance mode')) {
       // Ensure that the offline message is displayed only once [allowing for
       // page redirects], and specifically suppress its display on the site
       // maintenance page.
-      if (drupal_get_normal_path($_GET['q']) != 'admin/settings/maintenance-mode') {
-        drupal_set_message(t('Operating in maintenance mode. <a href="@url">Go online.</a>', array('@url' => url('admin/settings/maintenance-mode'))), 'status', FALSE);
+      if ($_GET['q'] != 'admin/settings/maintenance-mode') {
+        if (user_access('administer site configuration')) {
+          drupal_set_message(t('Operating in maintenance mode. <a href="@url">Go online.</a>', array('@url' => url('admin/settings/maintenance-mode'))), 'status', FALSE);
+        }
+        else {
+          drupal_set_message(t('Operating in maintenance mode.'), 'status', FALSE);
+        }
       }
     }
     else {
Index: modules/system/system.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v
retrieving revision 1.140
diff -u -p -r1.140 system.admin.inc
--- modules/system/system.admin.inc	3 May 2009 07:35:37 -0000	1.140
+++ modules/system/system.admin.inc	3 May 2009 22:38:13 -0000
@@ -1706,15 +1706,12 @@ function system_date_time_lookup() {
  * @see system_settings_form()
  */
 function system_site_maintenance_mode() {
-
   $form['site_offline'] = array(
-    '#type' => 'radios',
-    '#title' => t('Site status'),
+    '#type' => 'checkbox',
+    '#title' => t('Set site offline'),
     '#default_value' => 0,
-    '#options' => array(t('Online'), t('Offline')),
-    '#description' => t('When set to "Online", all visitors will be able to browse your site normally. When set to "Offline", only users with the "administer site configuration" permission will be able to access your site to perform maintenance; all other visitors will see the site offline message configured below. Authorized users can log in during "Offline" mode directly via the <a href="@user-login">user login</a> page.', array('@user-login' => url('user'))),
+    '#description' => t('When enabled, only users with the "Access site in maintenance mode" <a href="@permissions-url">permission</a> are able to access your site to perform maintenance; all other visitors see the site offline message configured below. Authorized users can log in directly via the <a href="@user-login">user login</a> page.', array('@permissions-url' => url('admin/user/permissions'), '@user-login' => url('user'))),
   );
-
   $form['site_offline_message'] = array(
     '#type' => 'textarea',
     '#title' => t('Site offline message'),
Index: modules/system/system.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.install,v
retrieving revision 1.319
diff -u -p -r1.319 system.install
--- modules/system/system.install	30 Apr 2009 21:44:18 -0000	1.319
+++ modules/system/system.install	3 May 2009 22:40:14 -0000
@@ -3299,6 +3299,28 @@ function system_update_7021() {
 }
 
 /**
+ * Split the 'access site in maintenance mode' permission from 'administer site configuration'.
+ */
+function system_update_7022() {
+  $ret = array();
+  // Get existing roles that can 'administer site configuration'.
+  $rids = db_query("SELECT rid FROM {role_permission} WHERE permission = :perm", array(':perm' => 'administer site configuration'))->fetchCol();
+  // None found.
+  if (empty($rids)) {
+    return $ret;
+  }
+  $insert = db_insert('role_permission')->fields(array('rid', 'permission'));
+  foreach ($rids as $rid) {
+    $insert->values(array(
+      'rid' => $rid,
+      'permission' => 'access site in maintenance mode',
+    ));
+  }
+  $insert->execute();
+  return $ret;
+}
+
+/**
  * @} End of "defgroup updates-6.x-to-7.x"
  * The next series of updates should start at 8000.
  */
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.689
diff -u -p -r1.689 system.module
--- modules/system/system.module	30 Apr 2009 21:44:19 -0000	1.689
+++ modules/system/system.module	3 May 2009 22:34:57 -0000
@@ -193,6 +193,10 @@ function system_perm() {
       'title' => t('Access administration pages'),
       'description' => t('View the administration panel and browse the help system.'),
     ),
+    'access site in maintenance mode' => array(
+      'title' => t('Access site in maintenance mode'),
+      'description' => t('Log in when the site is offline.'),
+    ),
     'access site reports' => array(
       'title' => t('Access site reports'),
       'description' => t('View reports from system logs and other status information.'),
Index: modules/system/system.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.test,v
retrieving revision 1.40
diff -u -p -r1.40 system.test
--- modules/system/system.test	31 Mar 2009 01:49:54 -0000	1.40
+++ modules/system/system.test	3 May 2009 22:48:34 -0000
@@ -537,6 +537,89 @@ class PageNotFoundTestCase extends Drupa
 }
 
 /**
+ * Tests site maintenance functionality.
+ */
+class SiteMaintenanceTestCase extends DrupalWebTestCase {
+  protected $admin_user;
+
+  public static function getInfo() {
+    return array(
+      'name' => t('Site maintenance functionality'),
+      'description' => t('Test access to site while in maintenance mode.'),
+      'group' => t('System'),
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+
+    // Create an administrative user.
+    $this->user = $this->drupalCreateUser(array('access site in maintenance mode'));
+    // Create an administrative user.
+    $this->admin_user = $this->drupalCreateUser(array('administer site configuration', 'access site in maintenance mode'));
+    $this->drupalLogin($this->admin_user);
+  }
+
+  function testSiteOffline() {
+    // Set site offline.
+    $edit = array(
+      'site_offline' => 1,
+    );
+    $this->drupalPost('admin/settings/maintenance-mode', $edit, t('Save configuration'));
+
+    $admin_message = t('Operating in maintenance mode. <a href="@url">Go online.</a>', array('@url' => url('admin/settings/maintenance-mode')));
+    $user_message = t('Operating in maintenance mode.');
+    $offline_message = t('@site is currently under maintenance. We should be back shortly. Thank you for your patience.', array('@site' => variable_get('site_name', 'Drupal')));
+
+    $this->drupalGet('');
+    $this->assertRaw($admin_message, t('Found the site maintenance mode message.'));
+
+    // Logout and verify that offline message is displayed.
+    $this->drupalLogout();
+    $this->drupalGet('');
+    $this->assertText($offline_message);
+    $this->drupalGet('node');
+    $this->assertText($offline_message);
+    $this->drupalGet('user/register');
+    $this->assertText($offline_message);
+    $this->drupalGet('user/password');
+    $this->assertText($offline_message);
+
+    // Verify that user is able to log in.
+    $this->drupalGet('user');
+    $this->assertNoText($offline_message);
+    $this->drupalGet('user/login');
+    $this->assertNoText($offline_message);
+
+    // Log in user and verify that maintenance mode message is displayed
+    // directly after login.
+    $edit = array(
+      'name' => $this->user->name,
+      'pass' => $this->user->pass_raw,
+    );
+    $this->drupalPost(NULL, $edit, t('Log in'));
+    $this->assertText($user_message);
+
+    // Log in administrative user and configure a custom site offline message.
+    $this->drupalLogout();
+    $this->drupalLogin($this->admin_user);
+    $this->drupalGet('admin/settings/maintenance-mode');
+    $this->assertNoRaw($admin_message, t('Site maintenance mode message not displayed.'));
+
+    $offline_message = 'Sorry, not online.';
+    $edit = array(
+      'site_offline_message' => $offline_message,
+    );
+    $this->drupalPost(NULL, $edit, t('Save configuration'));
+
+    // Logout and verify that custom site offline message is displayed.
+    $this->drupalLogout();
+    $this->drupalGet('');
+    $this->assertRaw($offline_message, t('Found the site offline message.'));
+  }
+}
+
+/**
  * Tests generic date and time handling capabilities of Drupal.
  */
 class DateTimeFunctionalTest extends DrupalWebTestCase {
