diff --git a/doku.php b/doku.php
index 52e8e6b8e9597db80a96ad2a6fa37389b2867089..052e18be9acef8d7a2cc639a3c30e790448ee5d4 100644
--- a/doku.php
+++ b/doku.php
@@ -61,7 +61,7 @@ if($conf['allowdebug'] && $ACT == 'debug'){
 //send 404 for missing pages if configured or ID has special meaning to bots
 if(!$INFO['exists'] &&
   ($conf['send404'] || preg_match('/^(robots\.txt|sitemap\.xml(\.gz)?|favicon\.ico|crossdomain\.xml)$/',$ID)) &&
-  ($ACT == 'show' || substr($ACT,0,7) == 'export_') ){
+  ($ACT == 'show' || (!is_array($ACT) && substr($ACT,0,7) == 'export_')) ){
     header('HTTP/1.0 404 Not Found');
 }
 
diff --git a/inc/auth/ldap.class.php b/inc/auth/ldap.class.php
index c519241357c711cd869470669525fa479d2b1721..fc1a7ddb63c722bc7e53e83b5595c092e1d60d88 100644
--- a/inc/auth/ldap.class.php
+++ b/inc/auth/ldap.class.php
@@ -27,7 +27,9 @@ class auth_ldap extends auth_basic {
             return;
         }
 
-        if(empty($this->cnf['groupkey'])) $this->cnf['groupkey'] = 'cn';
+        if(empty($this->cnf['groupkey']))   $this->cnf['groupkey']   = 'cn';
+        if(empty($this->cnf['userscope']))  $this->cnf['userscope']  = 'sub';
+        if(empty($this->cnf['groupscope'])) $this->cnf['groupscope'] = 'sub';
 
         // auth_ldap currently just handles authentication, so no
         // capabilities are set
@@ -171,7 +173,7 @@ class auth_ldap extends auth_basic {
             $filter = "(ObjectClass=*)";
         }
 
-        $sr     = @ldap_search($this->con, $base, $filter);
+        $sr     = $this->_ldapsearch($this->con, $base, $filter, $this->cnf['userscope']);
         $result = @ldap_get_entries($this->con, $sr);
         if($this->cnf['debug']){
             msg('LDAP user search: '.htmlspecialchars(ldap_error($this->con)),0,__LINE__,__FILE__);
@@ -219,7 +221,7 @@ class auth_ldap extends auth_basic {
         if ($this->cnf['grouptree'] && $this->cnf['groupfilter']) {
             $base   = $this->_makeFilter($this->cnf['grouptree'], $user_result);
             $filter = $this->_makeFilter($this->cnf['groupfilter'], $user_result);
-            $sr = @ldap_search($this->con, $base, $filter, array($this->cnf['groupkey']));
+            $sr = $this->_ldapsearch($this->con, $base, $filter, $this->cnf['groupscope'], array($this->cnf['groupkey']));
             if(!$sr){
                 msg("LDAP: Reading group memberships failed",-1);
                 if($this->cnf['debug']){
@@ -352,6 +354,28 @@ class auth_ldap extends auth_basic {
 
         return true;
     }
+
+    /**
+     * Wraps around ldap_search, ldap_list or ldap_read depending on $scope
+     *
+     * @param  $scope string - can be 'base', 'one' or 'sub'
+     * @author Andreas Gohr <andi@splitbrain.org>
+     */
+    function _ldapsearch($link_identifier, $base_dn, $filter, $scope='sub', $attributes=null,
+                         $attrsonly=0, $sizelimit=0, $timelimit=0, $deref=LDAP_DEREF_NEVER){
+        if(is_null($attributes)) $attributes = array();
+
+        if($scope == 'base'){
+            return @ldap_read($link_identifier, $base_dn, $filter, $attributes,
+                             $attrsonly, $sizelimit, $timelimit, $deref);
+        }elseif($scope == 'one'){
+            return @ldap_list($link_identifier, $base_dn, $filter, $attributes,
+                             $attrsonly, $sizelimit, $timelimit, $deref);
+        }else{
+            return @ldap_search($link_identifier, $base_dn, $filter, $attributes,
+                                $attrsonly, $sizelimit, $timelimit, $deref);
+        }
+    }
 }
 
 //Setup VIM: ex: et ts=4 enc=utf-8 :
diff --git a/inc/lang/de-informal/lang.php b/inc/lang/de-informal/lang.php
index 2060e1769342b00a48ec64543ff52bdc5743bd8a..a42ecc0ab1f3bedb47505fead04e131dd71f26d2 100644
--- a/inc/lang/de-informal/lang.php
+++ b/inc/lang/de-informal/lang.php
@@ -105,7 +105,7 @@ $lang['txt_overwrt']           = 'Bestehende Datei überschreiben';
 $lang['lockedby']              = 'Momentan gesperrt von';
 $lang['lockexpire']            = 'Sperre läuft ab am';
 $lang['willexpire']            = 'Die Sperre zur Bearbeitung dieser Seite läuft in einer Minute ab.\nUm Bearbeitungskonflikte zu vermeiden, solltest du sie durch einen Klick auf den Vorschau-Knopf verlängern.';
-$lang['js']['notsavedyet']     = "Nicht gespeicherte Änderungen gehen verloren!\nWeitermachen?";
+$lang['js']['notsavedyet']     = "Nicht gespeicherte Änderungen gehen verloren!";
 $lang['rssfailed']             = 'Es ist ein Fehler beim Laden des Feeds aufgetreten: ';
 $lang['nothingfound']          = 'Nichts gefunden.';
 $lang['mediaselect']           = 'Dateiauswahl';
diff --git a/inc/lang/de/lang.php b/inc/lang/de/lang.php
index 91bdcab0aa59c80485c1e0302995bb2c184169ba..290c069a4b8ecbd58a6ab164ae9b02c9ed53c3c3 100644
--- a/inc/lang/de/lang.php
+++ b/inc/lang/de/lang.php
@@ -103,8 +103,7 @@ $lang['txt_overwrt']           = 'Bestehende Datei überschreiben';
 $lang['lockedby']              = 'Momentan gesperrt von';
 $lang['lockexpire']            = 'Sperre läuft ab am';
 $lang['willexpire']            = 'Die Sperre zur Bearbeitung dieser Seite läuft in einer Minute ab.\nUm Bearbeitungskonflikte zu vermeiden, sollten Sie sie durch einen Klick auf den Vorschau-Knopf verlängern.';
-$lang['js']['notsavedyet']     = 'Nicht gespeicherte Änderungen gehen verloren!
-Weitermachen?';
+$lang['js']['notsavedyet']     = 'Nicht gespeicherte Änderungen gehen verloren!';
 $lang['js']['searchmedia']     = 'Suche Dateien';
 $lang['js']['keepopen']        = 'Fenster nach Auswahl nicht schließen';
 $lang['js']['hidedetails']     = 'Details ausblenden';
diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php
index 0dd6fd548aa13ac1f03383c496ceba286dcfc30c..1fddfe7278b5eab8d8c503855f28271a226bbffc 100644
--- a/inc/lang/en/lang.php
+++ b/inc/lang/en/lang.php
@@ -100,7 +100,7 @@ $lang['lockedby']     = 'Currently locked by';
 $lang['lockexpire']   = 'Lock expires at';
 $lang['willexpire']   = 'Your lock for editing this page is about to expire in a minute.\nTo avoid conflicts use the preview button to reset the locktimer.';
 
-$lang['js']['notsavedyet'] = "Unsaved changes will be lost.\nReally continue?";
+$lang['js']['notsavedyet'] = "Unsaved changes will be lost.";
 $lang['rssfailed']   = 'An error occurred while fetching this feed: ';
 $lang['nothingfound']= 'Nothing was found.';
 
diff --git a/inc/lang/it/lang.php b/inc/lang/it/lang.php
index 8e476816e01739cb0bb3bfb54eb388b919106bbf..c8e51f3e9ab7c8fab55d22a698b80659fad86c47 100644
--- a/inc/lang/it/lang.php
+++ b/inc/lang/it/lang.php
@@ -99,7 +99,7 @@ $lang['txt_overwrt']           = 'Sovrascrivi file esistente';
 $lang['lockedby']              = 'Attualmente bloccato da';
 $lang['lockexpire']            = 'Il blocco scade alle';
 $lang['willexpire']            = 'Il tuo blocco su questa pagina scadrà tra circa un minuto.\nPer evitare incongruenze usa il pulsante di anteprima per prolungare il periodo di blocco.';
-$lang['js']['notsavedyet']     = "Le modifiche non salvate andranno perse.\nContinuare?";
+$lang['js']['notsavedyet']     = "Le modifiche non salvate andranno perse.";
 $lang['rssfailed']             = 'Si è verificato un errore cercando questo feed: ';
 $lang['nothingfound']          = 'Nessun risultato trovato.';
 $lang['mediaselect']           = 'Selezione dei file';
diff --git a/lib/exe/ajax.php b/lib/exe/ajax.php
index 8b03bb07cc6ef34e95f6f8dc25e7f070d6bc1d5b..582be90e590e8e58e66b2a3412f8e7c38047c959 100644
--- a/lib/exe/ajax.php
+++ b/lib/exe/ajax.php
@@ -156,7 +156,7 @@ function ajax_lock(){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function ajax_draftdel(){
-  $id = cleanID($_POST['id']);
+  $id = cleanID($_REQUEST['id']);
   if(empty($id)) return;
 
   $client = $_SERVER['REMOTE_USER'];
diff --git a/lib/scripts/edit.js b/lib/scripts/edit.js
index e66154f8377fac472d952a35ab90e406acf48fef..5178dba4ce934a7383cc7fb481be735cba82ed83 100644
--- a/lib/scripts/edit.js
+++ b/lib/scripts/edit.js
@@ -258,35 +258,30 @@ function currentHeadlineLevel(textboxId){
 var textChanged = false;
 
 /**
- * Check for changes before leaving the page
+ * Delete the draft before leaving the page
  */
-function changeCheck(){
-  if(textChanged){
-    var ok = confirm(LANG.notsavedyet);
-    if(ok){
-        // remove a possibly saved draft using ajax
-        var dwform = $('dw__editform');
-        if(dwform){
-            var params = 'call=draftdel';
-            params += '&id='+encodeURIComponent(dwform.elements.id.value);
-
-            var sackobj = new sack(DOKU_BASE + 'lib/exe/ajax.php');
-            sackobj.AjaxFailedAlert = '';
-            sackobj.encodeURIString = false;
-            sackobj.runAJAX(params);
-            // we send this request blind without waiting for
-            // and handling the returned data
-        }
+function deleteDraft() {
+    if (is_opera) return;
+
+    // remove a possibly saved draft using ajax
+    var dwform = $('dw__editform');
+    if(dwform){
+        var params = 'call=draftdel';
+        params += '&id='+encodeURIComponent(dwform.elements.id.value);
+
+        var sackobj = new sack(DOKU_BASE + 'lib/exe/ajax.php');
+        // this needs to be synchronous and GET to not be aborted upon page unload
+        sackobj.asynchronous = false;
+        sackobj.method = 'GET';
+        sackobj.AjaxFailedAlert = '';
+        sackobj.encodeURIString = false;
+        sackobj.runAJAX(params);
     }
-    return ok;
-  }else{
-    return true;
-  }
 }
 
 /**
- * Add changeCheck to all Links and Forms (except those with a
- * JSnocheck class), add handlers to monitor changes
+ * Activate "not saved" dialog, add draft deletion to page unload,
+ * add handlers to monitor changes
  *
  * Sets focus to the editbox as well
  */
@@ -309,20 +304,12 @@ addInitEvent(function (){
     addEvent(editform, 'change', checkfunc);
     addEvent(editform, 'keydown', checkfunc);
 
-    // add change check for links
-    var links = document.getElementsByTagName('a');
-    for(var i=0; i < links.length; i++){
-        if(links[i].className.indexOf('JSnocheck') == -1){
-            addEvent(links[i], 'click', changeCheck);
-        }
-    }
-    // add change check for forms
-    var forms = document.forms;
-    for(i=0; i < forms.length; i++){
-        if(forms[i].className.indexOf('JSnocheck') == -1){
-            addEvent(forms[i], 'submit', changeCheck);
+    window.onbeforeunload = function(){
+        if(textChanged) {
+            return LANG.notsavedyet;
         }
     }
+    window.onunload = deleteDraft;
 
     // reset change memory var on submit
     addEvent($('edbtn__save'), 'click', function(){ textChanged = false; });
diff --git a/lib/scripts/tw-sack.js b/lib/scripts/tw-sack.js
index cfcbe0ea9d3d19d1485e7ddf70ef7eb7a87ab88f..b5a5c88616b86b1365a58a1d1dc6a3aeadb53359 100644
--- a/lib/scripts/tw-sack.js
+++ b/lib/scripts/tw-sack.js
@@ -10,6 +10,7 @@ function sack(file){
   this.URLString = "";
   this.encodeURIString = true;
   this.execute = false;
+  this.asynchronous = true;
 
   this.onLoading = function() { };
   this.onLoaded = function() { };
@@ -86,9 +87,9 @@ function sack(file){
         var self = this;
         if (this.method == "GET") {
           var totalurlstring = this.requestFile + "?" + this.URLString;
-          this.xmlhttp.open(this.method, totalurlstring, true);
+          this.xmlhttp.open(this.method, totalurlstring, this.asynchronous);
         } else {
-          this.xmlhttp.open(this.method, this.requestFile, true);
+          this.xmlhttp.open(this.method, this.requestFile, this.asynchronous);
         }
         if (this.method == "POST"){
           try {