summaryrefslogtreecommitdiff
path: root/src/utils.c
diff options
context:
space:
mode:
authorThorsten Wißmann <edu@thorsten-wissmann.de>2012-02-12 23:58:36 +0100
committerThorsten Wißmann <edu@thorsten-wissmann.de>2012-02-13 00:00:14 +0100
commitb69d1b3e0a13ea511800c6a24c1bd139f17e5fe0 (patch)
treef02aab1e2e12c925d17f0697ea7cae6263c4c907 /src/utils.c
parent5208faff415d99476c8c39934d2cb4522b29ac88 (diff)
use XGetTextProperty for strings of unknown length
Do not use XGetWindowProperty() because it needs many calls until a string of a (at compile time) unknown length is received. This causes a race-condition if the value is changed between calls of XGetWindowProperty() and can cause invalid values or even a xerror. Example: Say you have a property with the value "123456789" and a bufsize of 4. Then the first XGetWindowProperty call returns "1234". If the value is changed to "123" and XGetWindowProperty is called again with offset 4 then it would call a xerror. If the value is changed to "abcdefgh" then the result would be "1234efgh". Many thanks to Florian Bruhin (The-Compiler) for spotting this bug and for making it reproducible!
Diffstat (limited to 'src/utils.c')
-rw-r--r--src/utils.c56
1 files changed, 20 insertions, 36 deletions
diff --git a/src/utils.c b/src/utils.c
index 27d4629d..656d3ba0 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -40,46 +40,30 @@ unsigned long getcolor(const char *colstr) {
return color.pixel;
}
+// inspired by dwm's gettextprop()
GString* window_property_to_g_string(Display* dpy, Window window, Atom atom) {
- GString* result = g_string_new("");
- long bufsize = 10;
- char *buf;
- Atom type;
- int format;
- unsigned long items, bytes;
- long offset = 0;
- bool parse_error_occured = false;
- Atom req_type = ATOM("UTF8_STRING");
- Atom req_type_string = ATOM("STRING");
- do {
- int status = XGetWindowProperty(dpy, window,
- atom, offset, bufsize, False,
- req_type, &type, &format,
- &items, &bytes, (unsigned char**)&buf);
- if (status == Success
- && req_type != req_type_string
- && req_type_string == type) {
- req_type = req_type_string;
- continue;
- }
- if (status != Success || format != 8 || req_type != type) {
- parse_error_occured = true;
- break; // then stop parsing
- } else {
- result = g_string_append(result, buf);
- offset += bufsize;
- XFree(buf);
- }
- HSDebug("XGetWindowProperty received: \"%s\"\n", result->str);
- } while (bytes > 0);
- //
- if (parse_error_occured) {
- // then just return NULL
- g_string_free(result, true);
+ GString* result = NULL;
+ char** list = NULL;
+ int n = 0;
+ XTextProperty prop;
+
+ if (0 == XGetTextProperty(dpy, window, &prop, atom)) {
return NULL;
+ }
+ // convert text property to a gstring
+ result = g_string_new("");
+ if (prop.encoding == XA_STRING || prop.encoding == ATOM("UTF8_STRING")) {
+ result = g_string_new((char*)prop.value);
} else {
- return result;
+ if (XmbTextPropertyToTextList(dpy, &prop, &list, &n) >= Success
+ && n > 0 && *list)
+ {
+ result = g_string_new(*list);
+ XFreeStringList(list);
+ }
}
+ XFree(prop.value);
+ return result;
}
GString* window_class_to_g_string(Display* dpy, Window window) {