1.1 --- a/imip_manager.py Sun Oct 26 00:45:58 2014 +0200
1.2 +++ b/imip_manager.py Sun Oct 26 17:51:04 2014 +0100
1.3 @@ -4,6 +4,7 @@
1.4
1.5 sys.path.append("/var/lib/imip-agent")
1.6
1.7 +from imiptools.content import get_values, parse_object
1.8 import markup
1.9 import imip_store
1.10
1.11 @@ -80,6 +81,11 @@
1.12 self.new_page(title="Forbidden")
1.13 self.page.p("You are not logged in and thus cannot access scheduling requests.")
1.14
1.15 + def no_page(self):
1.16 + self.status(404, "Not Found")
1.17 + self.new_page(title="Not Found")
1.18 + self.page.p("No page is provided at the given address.")
1.19 +
1.20 def show_requests(self):
1.21
1.22 "Show requests for the current user."
1.23 @@ -91,6 +97,7 @@
1.24 self.page.ul()
1.25
1.26 requests = self.store.get_requests(self.user)
1.27 +
1.28 for request in requests:
1.29 self.page.li()
1.30 self.page.a(request, href="%s/%s" % (self.env.get_url(), request))
1.31 @@ -98,6 +105,33 @@
1.32
1.33 self.page.ul.close()
1.34
1.35 + def show_request(self, path_info):
1.36 +
1.37 + "Show a request using the given 'path_info' for the current user."
1.38 +
1.39 + uid = path_info.lstrip("/").split("/", 1)[0]
1.40 + f = uid and self.store.get_event(self.user, uid) or None
1.41 +
1.42 + if not f:
1.43 + return False
1.44 +
1.45 + request = parse_object(f, "utf-8")
1.46 +
1.47 + if not request:
1.48 + return False
1.49 +
1.50 + self.new_page(title="Request")
1.51 + self.page.p("The following request was received:")
1.52 + self.page.dl()
1.53 +
1.54 + for name in ["DTSTART", "DTEND", "ORGANIZER", "ATTENDEE"]:
1.55 + for value in get_values(request, name):
1.56 + self.page.dt(name)
1.57 + self.page.dd(value)
1.58 +
1.59 + self.page.dl.close()
1.60 + return True
1.61 +
1.62 def select_action(self):
1.63
1.64 "Select the desired action and show the result."
1.65 @@ -105,6 +139,10 @@
1.66 path_info = self.env.get_path_info().rstrip("/")
1.67 if not path_info:
1.68 self.show_requests()
1.69 + elif self.show_request(path_info):
1.70 + pass
1.71 + else:
1.72 + self.no_page()
1.73
1.74 def show(self):
1.75
1.76 @@ -115,6 +153,8 @@
1.77 else:
1.78 self.select_action()
1.79
1.80 + # Write the headers and actual content.
1.81 +
1.82 print >>self.out, "Content-Type: text/html; charset=%s" % self.encoding
1.83 print >>self.out
1.84 self.out.write(unicode(self.page).encode(self.encoding))
2.1 --- a/imiptools/config.py Sun Oct 26 00:45:58 2014 +0200
2.2 +++ b/imiptools/config.py Sun Oct 26 17:51:04 2014 +0100
2.3 @@ -8,4 +8,14 @@
2.4
2.5 PUBLISH_DIR = "/var/www/imip-agent/static"
2.6
2.7 +# The published location of the manager application.
2.8 +# This must match any Web site configuration details for the manager.
2.9 +
2.10 +MANAGER_PATH = "/imip-manager"
2.11 +
2.12 +# The full URL of the manager application excluding the above path.
2.13 +# If set to None, the details of this machine will be employed.
2.14 +
2.15 +MANAGER_URL = None
2.16 +
2.17 # vim: tabstop=4 expandtab shiftwidth=4
3.1 --- a/imiptools/content.py Sun Oct 26 00:45:58 2014 +0200
3.2 +++ b/imiptools/content.py Sun Oct 26 17:51:04 2014 +0100
3.3 @@ -186,18 +186,22 @@
3.4
3.5 return []
3.6
3.7 -def parse_object(f, encoding, objtype):
3.8 +def parse_object(f, encoding, objtype=None):
3.9
3.10 """
3.11 - Parse the iTIP content from 'f' having the given 'encoding'. Return None if
3.12 - the content was not readable or suitable.
3.13 + Parse the iTIP content from 'f' having the given 'encoding'. If 'objtype' is
3.14 + given, only objects of that type will be returned.
3.15 +
3.16 + Return None if the content was not readable or suitable.
3.17 """
3.18
3.19 try:
3.20 try:
3.21 doctype, attrs, elements = obj = parse(f, encoding=encoding)
3.22 - if doctype == objtype:
3.23 + if objtype and doctype == objtype:
3.24 return to_dict(obj)[objtype][0]
3.25 + elif not objtype:
3.26 + return to_dict(obj)[doctype][0]
3.27 finally:
3.28 f.close()
3.29 except (ParseError, ValueError):
3.30 @@ -248,6 +252,8 @@
3.31 except OSError:
3.32 self.publisher = None
3.33
3.34 + # Access to calendar structures and other data.
3.35 +
3.36 def get_items(self, name, all=True):
3.37 return get_items(self.details, name, all)
3.38
4.1 --- a/imiptools/handlers/person.py Sun Oct 26 00:45:58 2014 +0200
4.2 +++ b/imiptools/handlers/person.py Sun Oct 26 17:51:04 2014 +0100
4.3 @@ -5,9 +5,15 @@
4.4 """
4.5
4.6 from email.mime.text import MIMEText
4.7 +from imiptools.config import MANAGER_PATH, MANAGER_URL
4.8 from imiptools.content import Handler, to_part
4.9 +from socket import gethostname
4.10 from vCalendar import to_node
4.11
4.12 +def get_manager_url():
4.13 + url_base = MANAGER_URL or "http://%s/" % gethostname()
4.14 + return "%s/%s" % (url_base.rstrip("/"), MANAGER_PATH.lstrip("/"))
4.15 +
4.16 class PersonHandler(Handler):
4.17
4.18 "Handling mechanisms specific to people."
4.19 @@ -108,7 +114,8 @@
4.20
4.21 # The message is now wrapped and passed on to the recipient.
4.22
4.23 - return "REQUEST", MIMEText("A request has been queued.")
4.24 + url = "%s/%s" % (get_manager_url().rstrip("/"), self.uid)
4.25 + return "REQUEST", MIMEText("A request has been queued and can be viewed here: %s" % url)
4.26
4.27 class Freebusy(PersonHandler):
4.28