nexus: Rollup update for nexus

nexus: Change field separator from : to ' '

Signed-off-by: San Mehat <san@google.com>

nexus: Add some prototypes for stuff to come

Signed-off-by: San Mehat <san@google.com>

nexus: Add some TODOs

Signed-off-by: San Mehat <san@google.com>

libsysutils: Put a proper token parser into the FrameworkListener which
supports minimal \ escapes and quotes

Signed-off-by: San Mehat <san@google.com>

nexus: Fix a lot of bugs

Signed-off-by: San Mehat <san@google.com>

libsysutils: Remove some debugging
Signed-off-by: San Mehat <san@google.com>

nexus: Send broadcasts for supplicant state changes

Signed-off-by: San Mehat <san@google.com>

nexus: Plumb DHCP listener state changes to NetworkManager

Signed-off-by: San Mehat <san@google.com>

nexus: Make the SupplicantState strings more parsable

Signed-off-by: San Mehat <san@google.com>

nexus: Broadcast a message when dhcp state changes.

Signed-off-by: San Mehat <san@google.com>

nexus: Add a few new response codes

Signed-off-by: San Mehat <san@google.com>

nexus: Rename ErrorCode -> ResponseCode

Signed-off-by: San Mehat <san@google.com>

nexus: Add DHCP event broadcasting. Also adds the framework for
tracking supplicant 'searching-for-AP' state

Signed-off-by: San Mehat <san@google.com>

nexus: REmove WifiScanner

Signed-off-by: San Mehat <san@google.com>

nexus: Change the way scanning works. scanmode can now be selected
independantly of triggering a scan. Also adds rxfilter support

Signed-off-by: San Mehat <san@google.com>

nexus: Add support for configuring bluetooth coexistence scanning and modes

Signed-off-by: San Mehat <san@google.com>

nexus: use case insensitive match for property names

Signed-off-by: San Mehat <san@google.com>

nexus: Rollup of a bunch of stuff:
    - 'list' command now takes an argument to match against
    - InterfaceConfig has been moved into the Controller base (for now)
    - DhcpClient now has some rudimentry locking
    - process 'ADDRINFO' messages from dhcpcd
    - Drop tertiary dns

Signed-off-by: San Mehat <san@google.com>

nexus: Clean up some of the supplicant variable parsing and add 'wifi.current'

Signed-off-by: San Mehat <san@google.com>

nexus: Add driver-stop/start, initial suspend support

Signed-off-by: San Mehat <san@google.com>

nexus: Add Controller suspend/resume callbacks, as well as locking

Signed-off-by: San Mehat <san@google.com>

nexus: Make ARP probing configurable for DhcpClient

Signed-off-by: San Mehat <san@google.com>

nexus: Add linkspeed / rssi retrieval

Signed-off-by: San Mehat <san@google.com>

nexus: Add WifiStatusPoller to track RSSI/linkspeed when associated

Signed-off-by: San Mehat <san@google.com>

nexus: Disable some debugging and add 'wifi.netcount' property

Signed-off-by: San Mehat <san@google.com>

nexus: Replace the hackish property system with something more flexible with namespaces

Signed-off-by: San Mehat <san@google.com>

libsysutils: Fix a few bugs in SocketListener

Signed-off-by: San Mehat <san@google.com>

nexus: PropertyManager: Add array support

Signed-off-by: San Mehat <san@google.com>

nexus: Clean up properties
Signed-off-by: San Mehat <san@google.com>

nexus: WifiController: Change name of 'CurrentNetwork' property

Signed-off-by: San Mehat <san@google.com>
diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp
index e9ca897..4c74765 100644
--- a/libsysutils/src/FrameworkListener.cpp
+++ b/libsysutils/src/FrameworkListener.cpp
@@ -56,24 +56,73 @@
 }
 
 void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) {
-    int argc;
+    FrameworkCommandCollection::iterator i;
+    int argc = 0;
     char *argv[FrameworkListener::CMD_ARGS_MAX];
+    char tmp[255];
+    char *p = data;
+    char *q = tmp;
+    bool esc = false;
+    bool quote = false;
+    int k;
 
-    if (!index(data, '"')) {
-        char *next = data;
-        char *field;
-        int i;
+    memset(argv, 0, sizeof(argv));
+    memset(tmp, 0, sizeof(tmp));
+    while(*p) {
+        if (*p == '\\') {
+            if (esc) {
+                *q++ = '\\';
+                esc = false;
+            } else
+                esc = true;
+            p++;
+            continue;
+        } else if (esc) {
+            if (*p == '"')
+                *q++ = '"';
+            else if (*p == '\\')
+                *q++ = '\\';
+            else {
+                cli->sendMsg(500, "Unsupported escape sequence", false);
+                goto out;
+            }
+            p++;
+            esc = false;
+            continue;
+        }
 
-        for (i = 0; (i < FrameworkListener::CMD_ARGS_MAX) &&
-                    (argv[i] = strsep(&next, " ")); i++);
-        argc = i+1;
-    } else {
-        LOGD("blehhh not supported");
-        return;
+        if (*p == '"') {
+            if (quote)
+                quote = false;
+            else
+                quote = true;
+            p++;
+            continue;
+        }
+
+        *q = *p++;
+        if (!quote && *q == ' ') {
+            *q = '\0';
+            argv[argc++] = strdup(tmp);
+            memset(tmp, 0, sizeof(tmp));
+            q = tmp;
+            continue;
+        }
+        q++;
     }
 
-    FrameworkCommandCollection::iterator i;
+    argv[argc++] = strdup(tmp);
+#if 0
+    for (k = 0; k < argc; k++) {
+        LOGD("arg[%d] = '%s'", k, argv[k]);
+    }
+#endif
 
+    if (quote) {
+        cli->sendMsg(500, "Unclosed quotes error", false);
+        goto out;
+    }
+    
     for (i = mCommands->begin(); i != mCommands->end(); ++i) {
         FrameworkCommand *c = *i;
 
@@ -81,10 +130,14 @@
             if (c->runCommand(cli, argc, argv)) {
                 LOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno));
             }
-            return;
+            goto out;
         }
     }
 
     cli->sendMsg(500, "Command not recognized", false);
+out:
+    int j;
+    for (j = 0; j < argc; j++)
+        free(argv[j]);
     return;
 }