1 #!/usr/bin/env python 2 3 "A calendar application." 4 5 import WebStack.Generic 6 import time 7 8 class DirectoryResource: 9 10 """ 11 A resource which handles incoming calendars and viewing requests. 12 An arbitrary set of rules can be applied to determine what is to be done 13 with a request, and in this case, the application appears as a directory of 14 calendars, yet also accepts incoming calendars. 15 """ 16 17 def respond(self, trans): 18 19 """ 20 Examine the incoming request, either saving a calendar or displaying 21 one. 22 """ 23 24 # Remember uploaded calendars using a session. 25 26 session = trans.get_session(create=1) 27 28 # Determine the action to be taken. 29 30 method = trans.get_request_method() 31 32 # NOTE: Some frameworks do not pass in the content type. 33 34 content_type = trans.get_content_type() 35 36 # Handle uploads. 37 38 if method == "PUT": 39 40 # Get the last path component as the name of the calendar. 41 # NOTE: This could be improved to permit hierarchical naming. 42 43 calendar_name = trans.get_path_without_query().split("/")[-1] 44 input = trans.get_request_stream() 45 data = input.read() 46 47 # Store the calendar in the session. 48 49 session["calendar name"] = calendar_name 50 session["media type"] = content_type.media_type 51 session["calendar data"] = data 52 session["calendar size"] = len(data) 53 session["calendar time"] = time.strftime("%Y-%m-%dT%T") 54 55 # Handle directory browsing. 56 57 elif method == "PROPFIND": 58 trans.set_response_code(207) 59 trans.set_content_type(WebStack.Generic.ContentType("text/html")) 60 out = trans.get_response_stream() 61 out.write("""<?xml version="1.0"?> 62 <D:multistatus xmlns:D="DAV:"> 63 """) 64 65 if trans.get_path_info() == "/": 66 out.write(""" 67 <D:response> 68 <D:href>%s</D:href> 69 <D:propstat> 70 <D:prop> 71 <D:creationdate>%s</D:creationdate> 72 <D:displayname>%s</D:displayname> 73 <D:resourcetype> 74 <D:collection/> 75 </D:resourcetype> 76 </D:prop> 77 <D:status>HTTP/1.1 200 OK</D:status> 78 </D:propstat> 79 </D:response> 80 """ % (trans.get_path_without_query(), time.strftime("%Y-%m-%dT%T"), trans.get_path_without_query())) 81 82 if session.has_key("calendar name"): 83 out.write(""" 84 <D:response> 85 <D:href>%s%s</D:href> 86 <D:propstat> 87 <D:prop> 88 <D:creationdate>%s</D:creationdate> 89 <D:displayname>%s</D:displayname> 90 <D:resourcetype/> 91 <D:getcontenttype>%s</D:getcontenttype> 92 </D:prop> 93 <D:status>HTTP/1.1 200 OK</D:status> 94 </D:propstat> 95 </D:response> 96 """ % (trans.get_path_without_query(), session.get("calendar name"), session.get("calendar time") or time.strftime("%Y-%m-%dT%T"), 97 session.get("calendar name"), session.get("media type") or "")) 98 99 out.write(""" 100 </D:multistatus> 101 """) 102 103 # Handle downloads. 104 105 elif method == "GET": 106 trans.set_content_type(WebStack.Generic.ContentType("text/html")) 107 out = trans.get_response_stream() 108 out.write(""" 109 <html> 110 <head> 111 <title>Last Uploaded Calendar</title> 112 </head> 113 <body> 114 <h1>Calendar %s</h1> 115 <p>Media type: %s</p> 116 <p>Calendar size: %s</p> 117 <pre>%s</pre> 118 </body> 119 </html> 120 """ % (session.get("calendar name"), session.get("media type"), session.get("calendar size"), 121 session.get("calendar data", "").replace("&", "&").replace("<", "<").replace(">", ">"))) 122 123 # Disallow other methods. 124 125 else: 126 trans.set_response_code(405) 127 128 # vim: tabstop=4 expandtab shiftwidth=4