support \uXXXX as well as \xXX in args field
[dbuscron] / dbuscron / parser.py
index 7ddc75a..6937e14 100644 (file)
@@ -3,6 +3,23 @@ from __future__ import with_statement
 import re
 from dbuscron.bus import DbusBus
 
+def unescape_():
+    h = '[0-9A-Fa-f]'
+    r = re.compile(r'\\x('+h+r'{2})|\\u('+h+'{4})')
+    def unescape(value):
+        if not (value and \
+            (r'\x' in value or r'\u' in value)):
+            return value
+
+        return r.sub(\
+            lambda m: chr(int(m.group(1), 16)) \
+                if m.group(1) is not None else \
+                    unichr(int(m.group(2), 16))\
+                        .encode('utf-8'),\
+            value)
+    return unescape
+unescape = unescape_()
+
 def product(*args):
     if args:
         head, tail = args[0], args[1:]
@@ -71,7 +88,7 @@ class CrontabParser(object):
 
                 parts = self.__fields_sep.split(line, 8)
                 if len(parts) < 9:
-                    parts = self.__envvar_sep(line, 1)
+                    parts = self.__envvar_sep.split(line, 1)
                     if len(parts) == 2:
                         self.__environ[parts[0]] = parts[1]
                         continue
@@ -96,11 +113,11 @@ class CrontabParser(object):
                         raise CrontabParserError('Unexpected bus value', lineno, expected=('S', 's', '*'))
 
                     if r[7]:
-                        r[7] = r[7].split(';')
+                        r[7] = map(unescape, r[7].split(';'))
 
                     ruled = dict()
                     for i, f in enumerate(self.__fields):
-                        if self.__fields_chk[f]:
+                        if r[i] is not None and self.__fields_chk[f]:
                             if isinstance(self.__fields_chk[f], tuple):
                                 if r[i] not in self.__fields_chk[f]:
                                     raise CrontabParserError('Unexpected %s value' % (f.strip('_')), lineno,