s4:wmic - Output enhancements
authorDmitry Karasik <dmitry@karasik.eu.org>
Mon, 7 Sep 2009 12:08:16 +0000 (14:08 +0200)
committerMatthias Dieter Wallnöfer <mwallnoefer@yahoo.de>
Mon, 7 Sep 2009 12:16:09 +0000 (14:16 +0200)
Outputs shouldn't clash with metadata characters (|,()), special characters
should be escaped, "NULL" values should be reported as "(null)" string.

For the full explaination look at bug #6076.

source4/lib/wmi/tools/wmic.c

index bbfe5ed3341a1c7c582baa40724ec7ce41cf2b28..d37e22d44f77269df889240c8d3e67855fcbdf93 100644 (file)
 #include "lib/wmi/wmi.h"
 
 struct program_args {
-    char *hostname;
-    char *query;
-    char *ns;
+       char *hostname;
+       char *query;
+       char *ns;
 };
 
 static void parse_args(int argc, char *argv[], struct program_args *pmyargs)
 {
-    poptContext pc;
-    int opt, i;
-
-    int argc_new;
-    char **argv_new;
-
-    struct poptOption long_options[] = {
-       POPT_AUTOHELP
-       POPT_COMMON_SAMBA
-       POPT_COMMON_CONNECTION
-       POPT_COMMON_CREDENTIALS
-       POPT_COMMON_VERSION
-       {"namespace", 0, POPT_ARG_STRING, &pmyargs->ns, 0,
-        "WMI namespace, default to root\\cimv2", 0},
-       POPT_TABLEEND
-    };
-
-    pc = poptGetContext("wmi", argc, (const char **) argv,
-               long_options, POPT_CONTEXT_KEEP_FIRST);
-
-    poptSetOtherOptionHelp(pc, "//host query\n\nExample: wmic -U [domain/]adminuser%password //host \"select * from Win32_ComputerSystem\"");
-
-    while ((opt = poptGetNextOpt(pc)) != -1) {
-       poptPrintUsage(pc, stdout, 0);
-       poptFreeContext(pc);
-       exit(1);
-    }
+       poptContext pc;
+       int opt, i;
+
+       int argc_new;
+       char **argv_new;
+
+       struct poptOption long_options[] = {
+               POPT_AUTOHELP
+               POPT_COMMON_SAMBA
+               POPT_COMMON_CONNECTION
+               POPT_COMMON_CREDENTIALS
+               POPT_COMMON_VERSION
+               {"namespace", 0, POPT_ARG_STRING, &pmyargs->ns, 0,
+                "WMI namespace, default to root\\cimv2", 0},
+               POPT_TABLEEND
+       };
+
+       pc = poptGetContext("wmi", argc, (const char **) argv,
+               long_options, POPT_CONTEXT_KEEP_FIRST);
+
+       poptSetOtherOptionHelp(pc, "//host query\n\nExample: wmic -U [domain/]adminuser%password //host \"select * from Win32_ComputerSystem\"");
+
+       while ((opt = poptGetNextOpt(pc)) != -1) {
+               poptPrintUsage(pc, stdout, 0);
+               poptFreeContext(pc);
+               exit(1);
+       }
+
+       argv_new = discard_const_p(char *, poptGetArgs(pc));
 
-    argv_new = discard_const_p(char *, poptGetArgs(pc));
+       argc_new = argc;
+       for (i = 0; i < argc; i++) {
+               if (argv_new[i] == NULL) {
+                       argc_new = i;
+                       break;
+               }
+       }
 
-    argc_new = argc;
-    for (i = 0; i < argc; i++) {
-       if (argv_new[i] == NULL) {
-           argc_new = i;
-           break;
+       if (argc_new != 3 || argv_new[1][0] != '/'
+                       || argv_new[1][1] != '/') {
+               poptPrintUsage(pc, stdout, 0);
+               poptFreeContext(pc);
+               exit(1);
        }
-    }
 
-    if (argc_new != 3 || argv_new[1][0] != '/'
-       || argv_new[1][1] != '/') {
-       poptPrintUsage(pc, stdout, 0);
+       pmyargs->hostname = argv_new[1] + 2;
+       pmyargs->query = argv_new[2];
        poptFreeContext(pc);
-       exit(1);
-    }
+}
+
+static void escape_string(const char *src, char *dst, int len)
+{
+       char *p = dst, *end = dst + len - 1;
+       const char *q = src;
+
+       if ( q == NULL) {
+               strncpy( dst, "(null)", len);
+               return;
+       }
+
+       while ( *q && p <= end ) {
+               if ( strchr( "|\\(),", *q)) {
+                       *p++ = '\\';
+                       *p++ = *q++;
+               } else if ( *q == '\n' ) {
+                       *p++ = '\\';
+                       *p++ = 'n';
+                       q++;
+               } else if ( *q == '\r' ) {
+                       *p++ = '\\';
+                       *p++ = 'r';
+                       q++;
+               } else {
+                       *p++ = *q++;
+               }
+       }
 
-    pmyargs->hostname = argv_new[1] + 2;
-    pmyargs->query = argv_new[2];
-    poptFreeContext(pc);
+       *p++ = 0;
 }
 
 #define WERR_CHECK(msg) if (!W_ERROR_IS_OK(result)) { \
@@ -99,20 +129,33 @@ static void parse_args(int argc, char *argv[], struct program_args *pmyargs)
                            DEBUG(1, ("OK   : %s\n", msg)); \
                        }
 
-#define RETURN_CVAR_ARRAY_STR(fmt, arr) {\
-       uint32_t i;\
+#define RETURN_CVAR_ARRAY_STR_START(arr) {\
+        uint32_t i;\
        char *r;\
 \
-       if (!arr) {\
-               return talloc_strdup(mem_ctx, "NULL");\
-       }\
+        if (!arr) {\
+                return talloc_strdup(mem_ctx, "(null)");\
+        }\
        r = talloc_strdup(mem_ctx, "(");\
-       for (i = 0; i < arr->count; ++i) {\
-               r = talloc_asprintf_append(r, fmt "%s", arr->item[i], (i+1 == arr->count)?"":",");\
-       }\
-       return talloc_asprintf_append(r, ")");\
+        for (i = 0; i < arr->count; ++i) {
+
+
+#define RETURN_CVAR_ARRAY_STR_END(fmt, arr, item) \
+               r = talloc_asprintf_append(r, fmt "%s", item, (i+1 == arr->count)?"":",");\
+        }\
+        return talloc_asprintf_append(r, ")");\
 }
 
+#define RETURN_CVAR_ARRAY_STR(fmt, arr) \
+       RETURN_CVAR_ARRAY_STR_START(arr) \
+       RETURN_CVAR_ARRAY_STR_END(fmt, arr, arr->item[i])
+
+#define RETURN_CVAR_ARRAY_ESCAPED(fmt, arr) \
+       RETURN_CVAR_ARRAY_STR_START(arr) \
+       char buf[2048]; \
+       escape_string( arr->item[i], buf, 2048); \
+       RETURN_CVAR_ARRAY_STR_END(fmt, arr, buf)
+
 char *string_CIMVAR(TALLOC_CTX *mem_ctx, union CIMVAR *v, enum CIMTYPE_ENUMERATION cimtype)
 {
        switch (cimtype) {
@@ -129,7 +172,11 @@ char *string_CIMVAR(TALLOC_CTX *mem_ctx, union CIMVAR *v, enum CIMTYPE_ENUMERATI
        case CIM_BOOLEAN: return talloc_asprintf(mem_ctx, "%s", v->v_boolean?"True":"False");
        case CIM_STRING:
        case CIM_DATETIME:
-       case CIM_REFERENCE: return talloc_asprintf(mem_ctx, "%s", v->v_string);
+       case CIM_REFERENCE: {
+               char buf[2048];
+               escape_string((char*) v-> v_string, buf, 2048);
+               return talloc_asprintf(mem_ctx, "%s", buf);
+       }
        case CIM_CHAR16: return talloc_asprintf(mem_ctx, "Unsupported");
        case CIM_OBJECT: return talloc_asprintf(mem_ctx, "Unsupported");
        case CIM_ARR_SINT8: RETURN_CVAR_ARRAY_STR("%d", v->a_sint8);
@@ -143,9 +190,9 @@ char *string_CIMVAR(TALLOC_CTX *mem_ctx, union CIMVAR *v, enum CIMTYPE_ENUMERATI
        case CIM_ARR_REAL32: RETURN_CVAR_ARRAY_STR("%f", v->a_real32);
        case CIM_ARR_REAL64: RETURN_CVAR_ARRAY_STR("%f", v->a_real64);
        case CIM_ARR_BOOLEAN: RETURN_CVAR_ARRAY_STR("%d", v->a_boolean);
-       case CIM_ARR_STRING: RETURN_CVAR_ARRAY_STR("%s", v->a_string);
-       case CIM_ARR_DATETIME: RETURN_CVAR_ARRAY_STR("%s", v->a_datetime);
-       case CIM_ARR_REFERENCE: RETURN_CVAR_ARRAY_STR("%s", v->a_reference);
+       case CIM_ARR_STRING: RETURN_CVAR_ARRAY_ESCAPED("%s", v->a_string);
+       case CIM_ARR_DATETIME: RETURN_CVAR_ARRAY_ESCAPED("%s", v->a_datetime);
+       case CIM_ARR_REFERENCE: RETURN_CVAR_ARRAY_ESCAPED("%s", v->a_reference);
        default: return talloc_asprintf(mem_ctx, "Unsupported");
        }
 }