Switch to unified view

a b/src/mediaserver/cdplugins/uprcl/uprclsearch.py
1
#!/usr/bin/env python
2
from __future__ import print_function
3
4
def _getchar(s, i):
5
    if i < len(s):
6
        return i+1,s[i]
7
    else:
8
        return i,None
9
10
def _readword(s, i):
11
    w = ''
12
    for j in range(i, len(s)):
13
        if s[j].isspace():
14
            return j,w
15
        w += s[j]
16
    return j,w
17
18
# Called with '"' already read:
19
def _readstring(s, i):
20
    str = '"'
21
    escape = False
22
    for j in range(i, len(s)):
23
        #print("s[j] [%s] out now [%s]" % (s[j],out))
24
        if s[j] == '\\':
25
            if not escape:
26
                escape = True
27
                str += '\\'
28
            continue
29
30
        if s[j] == '"':
31
            str += '"'
32
            if not escape:
33
                return j+1, str
34
        else:
35
            str += s[j]
36
        
37
        escape = False        
38
39
    return len(s), str
40
41
def upnpsearchtorecoll(s):
42
    s = s.replace('\t', ' ')
43
    s = s.replace('\n', ' ')
44
    s = s.replace('\r', ' ')
45
    s = s.replace('\f', ' ')
46
47
    out = []
48
    hadDerived = False
49
    i = 0
50
    while True:
51
        i,c = _getchar(s, i)
52
        if not c:
53
            break
54
55
        if c.isspace():
56
            continue
57
58
        if c == "*":
59
            if (len(out) > 1 or (len(out) == 1 and not out[-1].isspace())) or \
60
                   (len(s[i:]) and not s[i:].isspace()):
61
                raise Exception("If * is used it must be the only input")
62
            out = ["mime:*"]
63
            break
64
65
        if c == '(' or c == ')' or c == '>' or c == '<' or c == '=':
66
            out.append(c)
67
        else:
68
            if c == '"':
69
                i,w = _readstring(s, i)
70
                if not w.endswith('"'):
71
                    raise Exception("Unterminated string in [%s]" % out)
72
            else:
73
                i -= 1
74
                i,w = _readword(s, i)
75
76
            #print("Got word [%s]" % w)
77
            if w == 'contains':
78
                out.append(':')
79
            elif w == 'doesNotContain':
80
                if len(out) < 1:
81
                    raise Exception("doesNotContain can't be the first word")
82
                out.insert(-1, "-")
83
                out.append(':')
84
            elif w == 'derivedFrom':
85
                hadDerived = True
86
                out.append(':')
87
            elif w == 'true':
88
                out.append('*')
89
            elif w == 'false':
90
                out.append('xxxjanzocsduochterrrrm')
91
            elif w == 'exists':
92
                out.append(':')
93
            elif w == 'and':
94
                # Recoll has implied AND, but see next
95
                pass
96
            elif w == 'or':
97
                # Does not work because OR/AND priorities are reversed
98
                # between recoll and upnp. This would be very
99
                # difficult to correct, let's hope that the callers
100
                # use parenthesese
101
                out.append('OR')
102
            else:
103
                if hadDerived:
104
                    hadDerived = False
105
                    if len(w) >= 1 and w[-1] == '"':
106
                        w = w[:-1] + '*' + '"'
107
                    else:
108
                        w += '*'
109
                out.append(w)
110
111
    ostr = ""
112
    for tok in out:
113
        ostr += tok + " "
114
    return ostr
115
116
117
if __name__ == '__main__':
118
    s = '(upnp:artist derivedFrom  "abc\\"def\\g") or (dc:title:xxx) '
119
    print("INPUT: %s" % s)
120
    o = upnpsearchtorecoll(s)
121
    print("OUTPUT: %s" % o)