diff -urpN drupal-6.x-dev-200708221235/includes/bootstrap.inc drupal-6.x-dev-access-0.3/includes/bootstrap.inc
--- drupal-6.x-dev-200708221235/includes/bootstrap.inc	2007-08-07 16:41:24.000000000 +0800
+++ drupal-6.x-dev-access-0.3/includes/bootstrap.inc	2007-08-22 14:32:11.000000000 +0800
@@ -792,11 +792,55 @@ function drupal_get_messages($type = NUL
 }
 
 /**
+ * Initialize the access strategy.
+ */
+function _drupal_access_init() {
+  // NOTE: caching the access rules can greatly improve performance.
+  $accesses = array();
+  if ($cached = cache_get('accesses', 'cache')) {
+    $accesses = $cached->data;
+  }
+  else {
+    $result = db_query('SELECT * FROM {access}');
+
+    // Classify, group and preprocess fetched access rules.
+    // NOTE: non-regexp matches are always done first.
+    $array = array();
+    while ($rule = db_fetch_object($result)) {
+      // Phase is not starting with '^': in plain text format. Escape it 
+      // with preg_quote().
+      if (substr($rule->mask, 0, 1) != '^') {
+        $plain[$rule->type][$rule->status ? 'allow' : 'deny'][] = '^' . preg_quote($rule->mask) . '$';
+      }
+      // Phase is starting with '^': in regex expression. Use directly without
+      // additional processing.
+      else {
+        $regex[$rule->type][$rule->status ? 'allow' : 'deny'][] = $rule->mask;
+      }
+
+      // Record which type of rules are existing.
+      $array[$rule->type][$rule->status ? 'allow' : 'deny'] = TRUE;
+    }
+
+    // Build regex expression for caching.
+    foreach ($array as $type => $tmp) {
+      foreach ($tmp as $status => $mask) {
+        $accesses[$type][$status] = '/' . implode('|', array_merge((array) $plain[$type][$status], (array) $regex[$type][$status])) . '/Ds';
+      }
+    }
+
+    cache_set('accesses', $accesses);
+  }
+
+  return $accesses;
+}
+
+/**
  * Perform an access check for a given mask and rule type. Rules are usually
  * created via admin/user/rules page.
  *
- * If any allow rule matches, access is allowed. Otherwise, if any deny rule
- * matches, access is denied.  If no rule matches, access is allowed.
+ * If any deny rule matches, access is denied. By the way, if any allow rule
+ * matches, access is allowed. If no rule matches, access is allowed.
  *
  * @param $type string
  *   Type of access to check: Allowed values are:
@@ -804,25 +848,27 @@ function drupal_get_messages($type = NUL
  *     - 'mail': e-mail address
  *     - 'user': username
  * @param $mask string
- *   String or mask to test: '_' matches any character, '%' matches any
- *   number of characters.
+ *   String to test.
  * @return bool
  *   TRUE if access is denied, FALSE if access is allowed.
  */
 function drupal_is_denied($type, $mask) {
-  // Because this function is called for every page request, both cached
-  // and non-cached pages, we tried to optimize it as much as possible.
-  // We deny access if the only matching records in the {access} table have
-  // status 0. If any have status 1, or if there are no matching records,
-  // we allow access. So, select matching records in decreasing order of
-  // 'status', returning NOT(status) for the first. If any have status 1,
-  // they come first, and we return NOT(status) = 0 (allowed). Otherwise,
-  // if we have some with status 0, we return 1 (denied). If no matching
-  // records, we get no return from db_result, so we return (bool)NULL = 0
-  // (allowed).
-  // The use of ORDER BY / LIMIT is more efficient than "MAX(status) = 0"
-  // in PostgreSQL <= 8.0.
-  return (bool) db_result(db_query_range("SELECT CASE WHEN status=1 THEN 0 ELSE 1 END FROM {access} WHERE type = '%s' AND LOWER(mask) LIKE LOWER('%s') ORDER BY status DESC", $type, $mask, 0, 1));
+  global $access;
+
+  // First of all, assume access is allowed.
+  $ret = FALSE;
+
+  // Check if deny rules exists. If so, deny access if rule matches.
+  if (isset($access[$type]['deny']) && $access[$type]['deny'] && preg_match($access[$type]['deny'], $mask)) {
+    $ret = TRUE;
+  }
+
+  // Check if allow rules exists. If so, allow access if rule matches.
+  if (isset($access[$type]['allow']) && $access[$type]['allow'] && preg_match($access[$type]['allow'], $mask)) {
+    $ret = FALSE;
+  }
+
+  return $ret;
 }
 
 /**
@@ -878,7 +924,7 @@ function drupal_bootstrap($phase) {
 }
 
 function _drupal_bootstrap($phase) {
-  global $conf;
+  global $conf, $access;
 
   switch ($phase) {
 
@@ -899,6 +945,9 @@ function _drupal_bootstrap($phase) {
       break;
 
     case DRUPAL_BOOTSTRAP_ACCESS:
+      // Initialize the access strategy.
+      $access = _drupal_access_init();
+
       // Deny access to hosts which were banned - t() is not yet available.
       if (drupal_is_denied('host', ip_address())) {
         header('HTTP/1.1 403 Forbidden');
diff -urpN drupal-6.x-dev-200708221235/modules/user/user.module drupal-6.x-dev-access-0.3/modules/user/user.module
--- drupal-6.x-dev-200708221235/modules/user/user.module	2007-08-19 16:08:45.000000000 +0800
+++ drupal-6.x-dev-access-0.3/modules/user/user.module	2007-08-22 14:13:56.000000000 +0800
@@ -2007,6 +2007,7 @@ function user_admin_access_add($mask = N
     else {
       db_query("INSERT INTO {access} (aid, mask, type, status) VALUES ('%s', '%s', '%s', %d)", $aid, $edit['mask'], $edit['type'], $edit['status']);
       $aid = db_last_insert_id('access', 'aid');
+      cache_clear_all('accesses', 'cache');
       drupal_set_message(t('The access rule has been added.'));
       drupal_goto('admin/user/rules');
     }
@@ -2038,6 +2039,7 @@ function user_admin_access_delete_confir
 
 function user_admin_access_delete_confirm_submit($form, &$form_state) {
   db_query('DELETE FROM {access} WHERE aid = %d', $form_state['values']['aid']);
+  cache_clear_all('accesses', 'cache');
   drupal_set_message(t('The access rule has been deleted.'));
   $form_state['redirect'] = 'admin/user/rules';
   return;
@@ -2053,6 +2055,7 @@ function user_admin_access_edit($aid = 0
     }
     else {
       db_query("UPDATE {access} SET mask = '%s', type = '%s', status = '%s' WHERE aid = %d", $edit['mask'], $edit['type'], $edit['status'], $aid);
+      cache_clear_all('accesses', 'cache');
       drupal_set_message(t('The access rule has been saved.'));
       drupal_goto('admin/user/rules');
     }
@@ -2083,7 +2086,7 @@ function user_admin_access_form(&$form_s
     '#size' => 30,
     '#maxlength' => 64,
     '#default_value' => $edit['mask'],
-    '#description' => '%: '. t('Matches any number of characters, even zero characters') .'.<br />_: '. t('Matches exactly one character.'),
+    '#description' => t('Start the line with a ^ character to designate a regular expression match.'),
     '#required' => TRUE,
   );
   $form['submit'] = array('#type' => 'submit', '#value' => $submit);
