1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 from caldavclientlibrary.browser.command import Command
18 from caldavclientlibrary.browser.command import WrongOptions
19 from caldavclientlibrary.protocol.url import URL
20 from caldavclientlibrary.protocol.webdav.definitions import davxml
21 from caldavclientlibrary.browser.subshell import SubShell
22 from caldavclientlibrary.browser import commands
23 from caldavclientlibrary.protocol.webdav.ace import ACE
24 from caldavclientlibrary.browser import utils
25 from caldavclientlibrary.protocol.caldav.definitions import caldavxml
26 from xml.etree.ElementTree import QName
27 import readline
28 import os
29 import getopt
30 import shlex
31
33
38
40
41 interactive = False
42 path = None
43
44 try:
45 opts, args = getopt.getopt(shlex.split(options), 'i')
46 except getopt.GetoptError, e:
47 print str(e)
48 print self.usage(name)
49 raise WrongOptions
50
51 for name, _ignore_value in opts:
52
53 if name == "-i":
54 interactive = True
55 else:
56 print "Unknown option: %s" % (name,)
57 print self.usage(name)
58 raise WrongOptions
59
60 if len(args) > 1:
61 print "Wrong number of arguments: %d" % (len(args),)
62 print self.usage(name)
63 raise WrongOptions
64 elif args:
65 path = args[0]
66 if not path.startswith("/"):
67 path = os.path.join(self.shell.wd, path)
68 else:
69 path = self.shell.wd
70 if not path.endswith("/"):
71 path += "/"
72 resource = URL(url=path)
73
74 results, bad = self.shell.account.session.getProperties(resource, (davxml.acl,))
75 if davxml.acl in bad:
76 print "Could not retrieve DAV:acl property, status=%d" % (bad[davxml.acl],)
77 else:
78 if interactive:
79 self.doInteractiveMode(resource, results[davxml.acl])
80 else:
81 aces = ACE.parseFromACL(results[davxml.acl])
82 print utils.printACEList(aces, self.shell.account)
83
84 return True
85
87
88 print "Entering ACL edit mode on resource: %s" % (resource.relativeURL(),)
89 if not self.subshell:
90 self.subshell = SubShell(self.shell, "ACL", (
91 commands.help.Cmd(),
92 commands.logging.Cmd(),
93 commands.quit.Cmd(),
94 Add(),
95 Change(),
96 Remove(),
97 List(),
98 ))
99 self.subshell.resource = resource
100 self.subshell.account = self.shell.account
101 self.subshell.run()
102
104 return """Usage: %s [OPTIONS] [PATH]
105 PATH is a relative or absolute path.
106
107 Options:
108 -i interactive mode for adding, changing and deleting ACLs.
109 if not present, existing ACLs will be printed.
110 """ % (name,)
111
113 return "Manage the access privileges of a directory or file."
114
116
127
129
130 ace = ACE()
131 print "Principal Type:"
132 print " 1. Principal path"
133 print " 2. All"
134 print " 3. Authenticated"
135 print " 4. Unauthenticated"
136 print " 5. Property"
137 insert = None
138 if oldace:
139 mapper = {
140 str(davxml.href): "1",
141 str(davxml.all): "2",
142 str(davxml.authenticated): "3",
143 str(davxml.unauthenticated): "4",
144 str(davxml.property): "5",
145 }
146 insert = mapper.get(oldace.principal)
147 choice = utils.numericInput("Select type: ", 1, 5, insert=insert)
148 if choice == "q":
149 return None
150
151 if choice == 1:
152 href = utils.textInput("Enter principal path: ", insert=oldace.data if oldace else None)
153 principal = self.shell.shell.account.getPrincipal(URL(url=href))
154 ace.principal = str(davxml.href)
155 ace.data = principal.principalURL.relativeURL()
156 elif choice == 2:
157 ace.principal = str(davxml.all)
158 elif choice == 3:
159 ace.principal = str(davxml.authenticated)
160 elif choice == 4:
161 ace.principal = str(davxml.unauthenticated)
162 elif choice == 5:
163 prop = utils.textInput("Enter property qname: ", insert=str(oldace.data) if oldace else None)
164 ace.principal = str(davxml.property)
165 ace.data = QName(prop)
166
167 invert = utils.yesNoInput("Invert principal [y/n]: ", insert=("y" if oldace.invert else "n") if oldace else None)
168 ace.invert = (invert == "y")
169
170 grant = utils.choiceInput("Grant or Deny privileges [g/d]: ", ("g", "d",), insert=("g" if oldace.grant else "d") if oldace else None)
171 ace.grant = (grant == "g")
172
173 print "Privileges:"
174 print " a. {DAV}read"
175 print " b. {DAV}write"
176 print " c. {DAV}write-properties"
177 print " d. {DAV}write-content"
178 print " e. {DAV}read-acl"
179 print " f. {DAV}read-current-user-privilege-set"
180 print " g. {DAV}write-acl"
181 print " h. {DAV}bind"
182 print " i. {DAV}unbind"
183 print " j. {DAV}all"
184 print " k. {CALDAV}read-free-busy"
185 print " l. {CALDAV}schedule"
186 print " q. quit without changes"
187 choice = utils.multiChoiceInput(
188 "Select multiple items: ",
189 [char for char in "abcdefghijklq"],
190 )
191 if "q" in choice:
192 return None
193
194 mappedPrivs = {
195 'a': davxml.read,
196 'b': davxml.write,
197 'c': davxml.write_properties,
198 'd': davxml.write_content,
199 'e': davxml.read_acl,
200 'f': davxml.read_current_user_privilege_set,
201 'g': davxml.write_acl,
202 'h': davxml.bind,
203 'i': davxml.unbind,
204 'j': davxml.all,
205 'k': caldavxml.read_free_busy,
206 'l': caldavxml.schedule,
207 }
208 ace.privs = ()
209 for char in choice:
210 ace.privs += (mappedPrivs[char],)
211
212 return ace
213
214 -class Add(CommonACLCommand):
218
220
221
222 aces = self.displayACEList()
223 if aces:
224
225 while True:
226 result = raw_input("Add ACL before [1 - %d] or cancel [q]: " % (len(aces) + 1,))
227 if readline.get_current_history_length():
228 readline.remove_history_item(readline.get_current_history_length() - 1)
229 if not result:
230 continue
231 if result[0] == "q":
232 break
233 try:
234 number = int(result)
235 if number > len(aces):
236 number = len(aces)
237 except ValueError:
238 print "Invalid input, try again."
239 continue
240
241
242 ace = self.createACE()
243 if not ace:
244 break
245 aces.insert(number, ace)
246
247
248 aces = [ace for ace in aces if ace.canChange()]
249
250
251 self.shell.shell.account.session.setACL(self.shell.resource, aces)
252 break
253
255 return """Usage: %s
256 """ % (name,)
257
259 return "Add ACL to existing resource."
260
261 -class Change(CommonACLCommand):
265
267
268
269 aces = self.displayACEList()
270 if aces:
271
272 while True:
273 result = raw_input("Change ACL at [1 - %d] or cancel [q]: " % (len(aces),))
274 if readline.get_current_history_length():
275 readline.remove_history_item(readline.get_current_history_length() - 1)
276 if not result:
277 continue
278 if result[0] == "q":
279 break
280 try:
281 number = int(result)
282 except ValueError:
283 print "Invalid input, try again."
284 continue
285
286
287 if not aces[number - 1].canChange():
288 print "You cannot change a protected or inherited ace."
289 break
290
291
292 ace = self.createACE(oldace=aces[number - 1])
293 if not ace:
294 break
295 aces[number - 1] = ace
296
297
298 aces = [ace for ace in aces if ace.canChange()]
299
300
301 self.shell.shell.account.session.setACL(self.shell.resource, aces)
302 break
303
305 return """Usage: %s
306 """ % (name,)
307
309 return "Change ACL on existing resource."
310
311 -class Remove(CommonACLCommand):
315
317
318
319 aces = self.displayACEList()
320 if aces:
321
322 while True:
323 result = raw_input("Remove ACL [1 - %d] or cancel [q]: " % (len(aces),))
324 if readline.get_current_history_length():
325 readline.remove_history_item(readline.get_current_history_length() - 1)
326 if not result:
327 continue
328 if result[0] == "q":
329 break
330 try:
331 number = int(result)
332 except ValueError:
333 print "Invalid input, try again."
334 continue
335
336
337 if not aces[number-1].canChange():
338 print "You cannot remove a protected or inherited ace."
339 break
340
341
342 del aces[number-1]
343
344
345 aces = [ace for ace in aces if ace.canChange()]
346
347
348 self.shell.shell.account.session.setACL(self.shell.resource, aces)
349 break
350
352 return """Usage: %s
353 """ % (name,)
354
356 return "Remove ACL on existing resource."
357
358 -class List(CommonACLCommand):
362
367
369 return """Usage: %s
370 """ % (name,)
371
373 return "List current ACLs on existing resource."
374