r19295: ldbbrowse: the search tab is now doing something vaguely reasonable.
authorDerrell Lipman <derrell@samba.org>
Sun, 15 Oct 2006 21:09:42 +0000 (21:09 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:21:03 +0000 (14:21 -0500)
(This used to be commit 039069b3fd10e2ea614c385c6b432b235e1c226b)

services/request.esp
services/resources.esp
services/samba/ldb.esp
swat/apps/samba/utils/ldbbrowse.html

index 982f39fcaae1a2b41a1e0d348613706e02dc44a2..970ea6b4fb759ad57c924e6109f662d401273556 100644 (file)
@@ -118,7 +118,7 @@ jsonrpc.Constant.ErrorCode.MethodNotFound        = 4;
  * This error is also used to indicate an illegal parameter value, in server
  * scripts.
  */
-jsonrpc.Constant.ErrorCode.PaameterMismatch      = 5;
+jsonrpc.Constant.ErrorCode.ParameterMismatch     = 5;
 
 /**
  * Error code, value 6: Permission Denied
@@ -337,7 +337,7 @@ var nameFirstLetter =
 if (strspn(jsonInput.method, nameChars) != strlen(jsonInput.method))
 {
     /* There's some illegal character in the service name */
-    error.setError(JsonRpcError.MethodNotFound,
+    error.setError(jsonrpc.Constant.ErrorCode.MethodNotFound,
                    "Illegal character found in method name.");
     error.Send();
     return;
@@ -364,7 +364,7 @@ if (strspn(substr(jsonInput.method, 0, 1), nameFirstLetter) != 1)
 if (strspn(jsonInput.service, "." + nameChars) != strlen(jsonInput.service))
 {
     /* There's some illegal character in the service name */
-    error.setError(JsonRpcError.IllegalService,
+    error.setError(jsonrpc.Constant.ErrorCode.IllegalService,
                    "Illegal character found in service name.");
     error.Send();
     return;
@@ -379,7 +379,7 @@ if (strspn(jsonInput.service, "." + nameChars) != strlen(jsonInput.service))
  */
 if (typeof(strstr(jsonInput.service, "..")) != "pointer")
 {
-    error.setError(JsonRpcError.IllegalService,
+    error.setError(jsonrpc.Constant.ErrorCode.IllegalService,
                    "Illegal use of two consecutive dots in service name");
     error.Send();
     return;
index d4a77f790729c64e46aefe8cbb82fb3095e3e4f2..d491ed5701c573464c90669f14870794feaf9b29 100644 (file)
@@ -28,15 +28,6 @@ function _resourcesCreate()
     /* We'll maintain our own count of the number of open resources */
     o.resourceList.count = 0;
 
-    /*
-     * Resource types
-     */
-    o.Type = new Object();
-    o.Type.ldb          = 1;    /* database handle */
-    o.Type.tid          = 2;    /* tree id */
-    o.Type.fid          = 3;    /* file id */
-    /* etc., etc., etc. */
-
 
     /*
      * Set a new saved resource.
@@ -48,7 +39,7 @@ function _resourcesCreate()
         {
             /* Yup. */
             error.setOrigin(jsonrpc.Constant.ErrorOrigin.Server);
-            error.setError(JsonRpcError_ResourceError,
+            error.setError(jsonrpc.Constant.ErrorCode.ResourceError,
                            "Session limit on resources (" +
                            RESOURCE_LIMIT +
                            ") exceeded.");
@@ -81,7 +72,7 @@ function _resourcesCreate()
     /*
      * Get a previously-saved resource
      */
-    function _get(resourceId, type, error)
+    function _get(resourceId, error)
     {
         /* Does the specified resource id exist? */
         if (! this.resourceList[resourceId])
@@ -96,21 +87,39 @@ function _resourcesCreate()
         /* Retrieve the resource */
         var r = this.resourceList[resourceId];
 
-        /* Is the specified resource the correct type? */
-        if (r.type != type)
-        {
-            /* Nope. */
-            error.setOrigin(jsonrpc.Constant.ErrorOrigin.Server);
-            error.setError(jsonrpc.Constant.ErrorCode.ResourceError,
-                           "Incorrect type for specified resource id.");
-            return error;
-        }
-
         /* Give 'em what they came for! */
         return r.resource;
     }
     o.get = _get;
 
+    /*
+     * Find a previously-saved resource
+     */
+    function _find(type, error)
+    {
+        /* Does the specified resource id exist? */
+        for (var resourceId in this.resourceList)
+        {
+            /* Retrieve the resource */
+            var r = this.resourceList[resourceId];
+
+            /* Ignore "id" and "count" integer fields */
+            if (typeof(r) == "object")
+            {
+                /* Is the specified resource the correct type? */
+                if (r.type == type)
+                {
+                    /* Yup, this is the one they want. */
+                    return resourceId;
+                }
+            }
+        }
+
+        /* It wasn't found. */
+        return undefined;
+    }
+    o.find = _find;
+
     /*
      * Release a previously-saved resource, allowing it to be freed
      */
index 2eff5ba57d02376f445451333f9bd9380b9702ef..d886d1a5665f7e677c2a146812773f34bc40ebcd 100644 (file)
@@ -39,18 +39,25 @@ function _connect(params, error)
 {
     if (params.length < 1)
     {
-        error.setError(JsonRpcError_ParameterMismatch,
+        error.setError(jsonrpc.Constant.ErrorCode.ParameterMismatch,
                        "usage: <db_name> [<option> ...]");
         return error;
     }
 
+    /* First, see if this database was already opened */
+    var resourceId = session.resources.find("ldb:" + params[0], error);
+    if (resourceId != undefined)
+    {
+        /* It was.  Give 'em the resource id */
+        return resourceId;
+    }
+
+    /* Database was not previously opened.  Connect to it. */
     ldb = ldb_init();
     var ret = ldb.connect(params[0]);
     if (ret && ldb.db)
     {
-        return session.resources.set(ldb,
-                                     session.resources.Type.ldb,
-                                     error);
+        return session.resources.set(ldb, "ldb:" + params[0], error);
     }
     else
     {
@@ -78,14 +85,12 @@ function _close(params, error)
 {
     if (params.length != 1)
     {
-        error.setError(JsonRpcError_ParameterMismatch,
+        error.setError(jsonrpc.Constant.ErrorCode.ParameterMismatch,
                        "usage: <resource_id>");
         return error;
     }
 
-    ldb = session.resources.get(params[0],
-                                session.resources.Type.ldb,
-                                error);
+    ldb = session.resources.get(params[0], error);
     if (ldb["__type"] == "_JsonRpcError")
     {
         return ldb;
@@ -121,14 +126,12 @@ function _transaction_start(params, error)
 {
     if (params.length != 1)
     {
-        error.setError(JsonRpcError_ParameterMismatch,
+        error.setError(jsonrpc.Constant.ErrorCode.ParameterMismatch,
                        "usage: <resource_id>");
         return error;
     }
 
-    ldb = session.resources.get(params[0],
-                                session.resources.Type.ldb,
-                                error);
+    ldb = session.resources.get(params[0], error);
     if (ldb["__type"] == "_JsonRpcError")
     {
         return ldb;
@@ -156,14 +159,12 @@ function _transaction_cancel(params, error)
 {
     if (params.length != 1)
     {
-        error.setError(JsonRpcError_ParameterMismatch,
+        error.setError(jsonrpc.Constant.ErrorCode.ParameterMismatch,
                        "usage: <resource_id>");
         return error;
     }
 
-    ldb = session.resources.get(params[0],
-                                session.resources.Type.ldb,
-                                error);
+    ldb = session.resources.get(params[0], error);
     if (ldb["__type"] == "_JsonRpcError")
     {
         return ldb;
@@ -191,14 +192,12 @@ function _transaction_commit(params, error)
 {
     if (params.length != 1)
     {
-        error.setError(JsonRpcError_ParameterMismatch,
+        error.setError(jsonrpc.Constant.ErrorCode.ParameterMismatch,
                        "usage: <resource_id>");
         return error;
     }
 
-    ldb = session.resources.get(params[0],
-                                session.resources.Type.ldb,
-                                error);
+    ldb = session.resources.get(params[0], error);
     if (ldb["__type"] == "_JsonRpcError")
     {
         return ldb;
@@ -243,15 +242,13 @@ function _search(params, error)
 {
     if (params.length < 2 || params.length > 5)
     {
-        error.setError(JsonRpcError_ParameterMismatch,
+        error.setError(jsonrpc.Constant.ErrorCode.ParameterMismatch,
                        "usage: " +
                        "<resource_id> <expr> [<baseDN> [<scope> [<attrs>]]]");
         return error;
     }
 
-    ldb = session.resources.get(params[0],
-                                session.resources.Type.ldb,
-                                error);
+    ldb = session.resources.get(params[0], error);
     if (ldb["__type"] == "_JsonRpcError")
     {
         return ldb;
@@ -287,12 +284,12 @@ function _search(params, error)
     }
     else
     {
-        error.setError(JsonRpcError_ParameterMismatch,
-                       "invalid scope");
+        error.setError(jsonrpc.Constant.ErrorCode.ParameterMismatch,
+                       "invalid scope: " + scope);
         return error;
     }
 
-    return ldb.transaction_search(expr, baseDN, scope, attrs);
+    return ldb.search(expr, baseDN, scope, attrs);
 }
 jsonrpc.method.search = _search;
 
@@ -317,14 +314,12 @@ function _add(params, error)
 {
     if (params.length != 2)
     {
-        error.setError(JsonRpcError_ParameterMismatch,
+        error.setError(jsonrpc.Constant.ErrorCode.ParameterMismatch,
                        "usage: <resource_id> <ldif>");
         return error;
     }
 
-    ldb = session.resources.get(params[0],
-                                session.resources.Type.ldb,
-                                error);
+    ldb = session.resources.get(params[0], error);
     if (ldb["__type"] == "_JsonRpcError")
     {
         return ldb;
@@ -355,14 +350,12 @@ function _modify(params, error)
 {
     if (params.length != 2)
     {
-        error.setError(JsonRpcError_ParameterMismatch,
+        error.setError(jsonrpc.Constant.ErrorCode.ParameterMismatch,
                        "usage: <resource_id> <ldif>");
         return error;
     }
 
-    ldb = session.resources.get(params[0],
-                                session.resources.Type.ldb,
-                                error);
+    ldb = session.resources.get(params[0], error);
     if (ldb["__type"] == "_JsonRpcError")
     {
         return ldb;
@@ -393,14 +386,12 @@ function _del(params, error)
 {
     if (params.length != 2)
     {
-        error.setError(JsonRpcError_ParameterMismatch,
+        error.setError(jsonrpc.Constant.ErrorCode.ParameterMismatch,
                        "usage: <resource_id> <dn>");
         return error;
     }
 
-    ldb = session.resources.get(params[0],
-                                session.resources.Type.ldb,
-                                error);
+    ldb = session.resources.get(params[0], error);
     if (ldb["__type"] == "_JsonRpcError")
     {
         return ldb;
@@ -434,14 +425,12 @@ function _rename(params, error)
 {
     if (params.length != 3)
     {
-        error.setError(JsonRpcError_ParameterMismatch,
+        error.setError(jsonrpc.Constant.ErrorCode.ParameterMismatch,
                        "usage: <resource_id> <old_dn> <new_dn>");
         return error;
     }
 
-    ldb = session.resources.get(params[0],
-                                session.resources.Type.ldb,
-                                error);
+    ldb = session.resources.get(params[0], error);
     if (ldb["__type"] == "_JsonRpcError")
     {
         return ldb;
@@ -472,14 +461,12 @@ function _base64encode(params, error)
 {
     if (params.length != 2)
     {
-        error.setError(JsonRpcError_ParameterMismatch,
+        error.setError(jsonrpc.Constant.ErrorCode.ParameterMismatch,
                        "usage: <resource_id> <string_to_be_encoded>");
         return error;
     }
 
-    ldb = session.resources.get(params[0],
-                                session.resources.Type.ldb,
-                                error);
+    ldb = session.resources.get(params[0], error);
     if (ldb["__type"] == "_JsonRpcError")
     {
         return ldb;
@@ -510,14 +497,12 @@ function _base64decode(params, error)
 {
     if (params.length != 2)
     {
-        error.setError(JsonRpcError_ParameterMismatch,
+        error.setError(jsonrpc.Constant.ErrorCode.ParameterMismatch,
                        "usage: <resource_id> <string_to_be_decoded>");
         return error;
     }
 
-    ldb = session.resources.get(params[0],
-                                session.resources.Type.ldb,
-                                error);
+    ldb = session.resources.get(params[0], error);
     if (ldb["__type"] == "_JsonRpcError")
     {
         return ldb;
@@ -548,14 +533,12 @@ function _base64decode(params, error)
 {
     if (params.length != 2)
     {
-        error.setError(JsonRpcError_ParameterMismatch,
+        error.setError(jsonrpc.Constant.ErrorCode.ParameterMismatch,
                        "usage: <resource_id> <string_to_be_decoded>");
         return error;
     }
 
-    ldb = session.resources.get(params[0],
-                                session.resources.Type.ldb,
-                                error);
+    ldb = session.resources.get(params[0], error);
     if (ldb["__type"] == "_JsonRpcError")
     {
         return ldb;
@@ -582,14 +565,12 @@ function _errstring(params, error)
 {
     if (params.length != 1)
     {
-        error.setError(JsonRpcError_ParameterMismatch,
+        error.setError(jsonrpc.Constant.ErrorCode.ParameterMismatch,
                        "usage: <resource_id>");
         return error;
     }
 
-    ldb = session.resources.get(params[0],
-                                session.resources.Type.ldb,
-                                error);
+    ldb = session.resources.get(params[0], error);
     if (ldb["__type"] == "_JsonRpcError")
     {
         return ldb;
index adfe78e75403112c058d9314990345379e01039e..028289e9f12e2dab395cb7f6ced0fbf4575b7b51 100644 (file)
 
 /*
 Root is as found by:
- source/bin/ldbsearch -H /usr/local/samba/private/sam.ldb -b '' \
-        -s base defaultNamingContext
+  source/bin/ldbsearch -H /usr/local/samba/private/sam.ldb -b '' \
+    -s base defaultNamingContext
+
+Schema page:
+  source/bin/ldbsearch -H /usr/local/samba/private/sam.ldb -b '' \
+    -s base subschemaSubentry
+  source/bin/ldbsearch -H /usr/local/samba/private/sam.ldb -b \
+    'CN=Aggregate,CN=Schema,CN=Configuration,DC=workgroup,DC=example,DC=com' \
+    -s base objectClasses attributeTypes matchingRules ldapSyntaxes        
 */
 
 function setAppearances()
@@ -51,7 +58,7 @@ function setAppearances()
     appearance.initial = function(vTheme)
     {
         var res = oldInitial ? oldInitial.apply(this, arguments) : {};
-        res.width = "96%";
+        res.width = "90%";
         return res;
     }
 }
@@ -185,7 +192,10 @@ function setupTabs(clientDocument)
         new qx.ui.pageview.tabview.TabViewPage(tabView_Schema);
 
     // Build the search page
-    buildPageSearch(tabViewPage_Search);
+    var searchResultsTable = buildPageSearch(tabViewPage_Search);
+
+    // Provide access to the search results table
+    tabView_.searchResultTable = searchResultsTable;
 
     // Build the browse page
     buildPageBrowse(tabViewPage_Browse);
@@ -207,51 +217,109 @@ function setupTabs(clientDocument)
 
 function buildPageSearch(page)
 {
+    // We need a horizontal layout for the combox box and "Find" button
+    var layout = new qx.ui.layout.HorizontalBoxLayout();
+    layout.setWidth("100%");
+
     // Create a combo box for entry of the search expression
     var search = new qx.ui.form.ComboBox();
     search.getField().setWidth("100%");
     search.setEditable(true);
     
-    // Add the combo box to the page
-    page.add(search);
+    // Add the combo box to the horizontal layout
+    layout.add(search);
 
-    // Create a simple table model
-    var tableModel = new qx.ui.table.SimpleTableModel();
-    tableModel.setColumns([ "Attribute", "Value" ]);
+    // Right-justify the 'Find' button
+    var spacer = new qx.ui.basic.HorizontalSpacer;
+    layout.add(spacer);
 
-    // Add some garbage data to it
-    var attributeNames =
-        [
-            [ "Nickname" ],
-            [ "Hostname" ],
-            [ "Port" ],
-            [ "Connection caching" ],
-            [ "TLS" ],
-            [ "Client-side caching" ],
-            [ "Connections so far" ],
-            [ "LDAP protocol version" ],
-            [ "Vendor Name" ],
-            [ "Vendor Version" ],
-            [ "Support LDAP Version" ],
-            [ "Supported SASL Mechanisms" ],
-            [ "Junk 1" ],
-            [ "Junk 2" ],
-            [ "Junk 3" ]
-        ];
-            
+    // Create the 'Find' button
+    var find = new qx.ui.form.Button('Find');
 
-    var rowData = [];
-    for (var row = 0; row < attributeNames.length; row++)
+    // We'll be setting url and service upon execute; no need to do it now.
+    var rpc = new qx.io.remote.Rpc();
+    rpc.setTimeout(10000);
+    var mycall = null;
+
+    find.addEventListener("execute", function()
     {
-        rowData.push([ attributeNames[row], "" + (Math.random() * 10000) ]);
-    }
-    tableModel.setData(rowData);
+        // Set the URL and Service
+        rpc.setUrl("/services/");
+        rpc.setServiceName("samba.ldb");
+        rpc.setCrossDomain(false);
+
+        find.setEnabled(false);
+//        abort.setEnabled(true);
+        mycall = rpc.callAsync(function(result, ex, id)
+        {
+            mycall = null;
+            if (ex == null)
+            {
+                var rowData = [];
+                for (var i = 0; i < result.length; i++)
+                {
+                    var o = result[i];
+                    if (typeof(o) != "object")
+                    {
+                        alert("Found unexpected result, type " +
+                              typeof(o) +
+                              ", " +
+                              o +
+                              "\n");
+                        continue;
+                    }
+                    for (var field in o)
+                    {
+                        // skip dn and distinguishedName fields;
+                        // they're shown in each row anyway.
+                        if (field == "dn" || field == "distinguishedName")
+                        {
+                            continue;
+                        }
+                        rowData.push( [
+                                          o["dn"],
+                                          field,
+                                          o[field]
+                                      ] );
+                    }
+
+                    // Tell the table to use the new data
+                    tableModel.setData(rowData);
+                }
+            }
+            else
+            {
+                alert("Async(" + id + ") exception: " + ex);
+            }
+            find.setEnabled(true);
+//            abort.setEnabled(false);
+        },
+        "search",               // method
+        db_handle,              // database handle
+        search.getValue(),      // search expression
+        "",                     // baseDN
+        "default",              // scope
+        [ "*" ]);               // attributes
+    });
+
+    // Add the button to horizontal layout
+    layout.add(find);
+
+    // Add the horizontal box layout to the page
+    page.add(layout);
+
+    // Create a simple table model
+    var tableModel = new qx.ui.table.SimpleTableModel();
+    tableModel.setColumns([ "Distinguished Name", "Attribute", "Value" ]);
+
     tableModel.setColumnEditable(0, false);
-    tableModel.setColumnEditable(1, true);
+    tableModel.setColumnEditable(1, false);
+    tableModel.setColumnEditable(2, false);
 
     // Create a table
     var table = new qx.ui.table.Table(tableModel);
-    with (table) {
+    with (table)
+    {
       set({
               top: 40,
               left: 0,
@@ -260,12 +328,15 @@ function buildPageSearch(page)
               statusBarVisible: false,
               columnVisibilityButtonVisible: false
           });
-      setColumnWidth(0, 200);
-      setColumnWidth(1, 440);
-      setMetaColumnCounts([1, -1]);
+      setColumnWidth(0, 300);
+      setColumnWidth(1, 180);
+      setColumnWidth(2, 240);
+      setMetaColumnCounts([ 1, -1 ]); // h-scroll attribute and value together
     };
 
     page.add(table);
+
+    return table;
 }
 
 function buildPageBrowse(page)
@@ -531,6 +602,23 @@ function buildPageSchema(page)
 qx.core.Init.getInstance().defineMain(
     function()
     {
+        // Enable JSON-RPC debugging
+        qx.Settings.setCustomOfClass("qx.io.Json", "enableDebug", true);
+
+        if (false)
+        {
+            // We'd like all table columns to do "live resize". Unfortunately,
+            // it's too slow.  Maybe someone wants to work on it...
+            var constructor = qx.OO.classes["qx.ui.table.TablePaneScroller"];
+            qx.Proto = constructor.prototype;
+            qx.OO.changeProperty(
+                {
+                    name         : "liveResize",
+                    type         : qx.constant.Type.BOOLEAN,
+                    defaultValue : true
+                });
+        }
+
         // Set appearances for this application
         setAppearances();
 
@@ -542,6 +630,23 @@ qx.core.Init.getInstance().defineMain(
 
         // Create the tabs and their windows, and attach to client document
         var tabView = setupTabs(clientDocument);
+
+        // Open a database connection.  Uses the dangerous sync request.
+        var rpc = new qx.io.remote.Rpc();
+        rpc.setUrl("/services/");
+        rpc.setServiceName("samba.ldb");
+        rpc.setCrossDomain(false);
+
+        try
+        {
+            // db_handle is global!!!  no 'var' is intentional.
+            db_handle = rpc.callSync("connect",
+                                     "/usr/local/samba/private/sam.ldb");
+        }
+        catch (ex)
+        {
+            alert("Sync exception: " + ex);
+        }
     });
 /*
  * Local Variables: