def request(self, url, method="GET", body="", headers={}): """ Actually sends the request """ # objectify the url url = URL.objectify(url) proxies = None if self.proxy is not None: proxies = {url.scheme: self.proxy} logging.debug("using proxy - %s" % (proxies)) # ensure that url is a unicode string url = unicode(URL.objectify(url)) combined_headers = self.headers combined_headers.update(headers) if body is None or body == "" and "Content-Type" in combined_headers: del combined_headers["Content-Type"] if isinstance(body, unicode): body = body.encode('utf-8') logging.debug( "sending request - method={0}, url={1}, headers={2}\nbody:\n{3}". format(method, url.encode('utf-8'), combined_headers, body)) auth = None if self.username is not None: auth = requests.auth.HTTPBasicAuth(self.username, self.password) r = requests.request(method, url, data=body, headers=combined_headers, proxies=proxies, auth=auth) response = DAVResponse(r) # this is an error condition the application wants to know if response.status == requests.codes.forbidden or \ response.status == requests.codes.unauthorized: ex = error.AuthorizationError() ex.url = url ex.reason = response.reason raise ex return response
def __init__(self, client=None, url=None): """ url input is for backward compatibility and should normally be avoided. If url is not given, deduct principal path as well as calendar home set path from doing propfinds. """ self.client = client self._calendar_home_set = None ## backwards compatibility. if url is not None: self.url = client.url.join(URL.objectify(url)) else: self.url = self.client.url cup = self.get_properties([dav.CurrentUserPrincipal()]) self.url = self.client.url.join(URL.objectify(cup['{DAV:}current-user-principal']))
def __init__(self, client=None, url=None): """ url input is for backward compatibility and should normally be avoided. If url is not given, deduct principal path as well as calendar home set path from doing propfinds. """ self.client = client self._calendar_home_set = None ## backwards compatibility. if url is not None: self.url = client.url.join(URL.objectify(url)) else: self.url = self.client.url cup = self.get_properties([dav.CurrentUserPrincipal()]) self.url = self.client.url.join( URL.objectify(cup['{DAV:}current-user-principal']))
def __init__(self, client, url): ## backwards compatibility. if url is not None: print 'url1-%s' % url url = client.url.join(URL.objectify(url)) print 'url2-%s' % url else: raise TypeError("url can't be NoneType") super(CalendarClient, self).__init__(client=client, url=url)
def children(self, type=None): """ List children, using a propfind (resourcetype) on the parent object, at depth = 1. """ c = [] depth = 1 properties = {} props = [ dav.ResourceType(), ] response = self._query_properties(props, depth) for r in response.tree.findall(dav.Response.tag): # We use canonicalized urls to index children href = str(self.url.join(URL.objectify(r.find(dav.Href.tag).text))) assert (href) properties[href] = {} for p in props: t = r.find(".//" + p.tag) if len(list(t)) > 0: if type is not None: val = t.find(".//" + type) else: val = t.find(".//*") if val is not None: val = val.tag else: val = None else: val = t.text properties[href][p.tag] = val for path in properties.keys(): resource_type = properties[path][dav.ResourceType.tag] if resource_type == type or type is None: if self.url != path: c.append((URL.objectify(path), resource_type)) return c
def request(self, url, method="GET", body="", headers={}): """ Actually sends the request """ # objectify the url url = URL.objectify(url) proxies = None if self.proxy is not None: proxies = {url.scheme: self.proxy} logging.debug("using proxy - %s" % (proxies)) # ensure that url is a unicode string url = unicode(URL.objectify(url)) combined_headers = self.headers combined_headers.update(headers) if body is None or body == "" and "Content-Type" in combined_headers: del combined_headers["Content-Type"] if isinstance(body, unicode): body = body.encode('utf-8') logging.debug("sending request - method={0}, url={1}, headers={2}\nbody:\n{3}".format(method, url.encode('utf-8'), combined_headers, body)) auth = None if self.username is not None: auth = requests.auth.HTTPBasicAuth(self.username, self.password) r = requests.request(method, url, data=body, headers=combined_headers, proxies=proxies, auth=auth) response = DAVResponse(r) # this is an error condition the application wants to know if response.status == requests.codes.forbidden or \ response.status == requests.codes.unauthorized: ex = error.AuthorizationError() ex.url = url ex.reason = response.reason raise ex return response
def children(self, type=None): """ List children, using a propfind (resourcetype) on the parent object, at depth = 1. """ c = [] depth = 1 properties = {} props = [dav.ResourceType(), ] response = self._query_properties(props, depth) for r in response.tree.findall(dav.Response.tag): # We use canonicalized urls to index children href = str(self.url.join(URL.objectify(r.find(dav.Href.tag).text))) assert(href) properties[href] = {} for p in props: t = r.find(".//" + p.tag) if len(list(t)) > 0: if type is not None: val = t.find(".//" + type) else: val = t.find(".//*") if val is not None: val = val.tag else: val = None else: val = t.text properties[href][p.tag] = val for path in properties.keys(): resource_type = properties[path][dav.ResourceType.tag] if resource_type == type or type is None: if self.url != path: c.append((URL.objectify(path), resource_type)) return c
def save(self): """ The save method for a calendar is only used to create it, for now. We know we have to create it when we don't have a url. Returns: * self """ if self.url is None: self._create(self.name, self.id) if not self.url.endswith('/'): self.url = URL.objectify(str(self.url) + '/') return self
def _create(self, data, id=None, path=None): if id is None and path is not None and str(path).endswith('.ics'): id = re.search('(/|^)([^/]*).ics',str(path)).group(2) elif id is None: id = self.instance.vevent.uid.value if path is None: path = id + ".ics" path = self.parent.url.join(path) r = self.client.put(path, data, {"Content-Type": 'text/calendar; charset="utf-8"'}) if r.status == 302: path = [x[1] for x in r.headers if x[0]=='location'][0] elif not (r.status in (204, 201)): raise error.PutError(r.raw) self.url = URL.objectify(path) self.id = id
def _create(self, data, id=None, path=None): if id is None and path is not None and str(path).endswith('.ics'): id = re.search('(/|^)([^/]*).ics', str(path)).group(2) elif id is None: id = self.instance.vevent.uid.value if path is None: path = id + ".ics" path = self.parent.url.join(path) r = self.client.put(path, data, {"Content-Type": 'text/calendar; charset="utf-8"'}) if r.status == 302: path = [x[1] for x in r.headers if x[0] == 'location'][0] elif not (r.status in (204, 201)): raise error.PutError(r.raw) self.url = URL.objectify(path) self.id = id
def __init__(self, url, proxy=None, username=None, password=None): """ Sets up a HTTPConnection object towards the server in the url. Parameters: * url: A fully qualified url: `scheme://user:pass@hostname:port` * proxy: A string defining a proxy server: `hostname:port` * username and password should be passed as arguments or in the URL """ logging.debug("url: " + str(url)) self.url = URL.objectify(url) # Prepare proxy info if proxy is not None: self.proxy = proxy if re.match( '^.*://', proxy ) is None: # requests library expects the proxy url to have a scheme self.proxy = self.url.scheme + '://' + proxy # add a port is one is not specified # TODO: this will break if using basic auth and embedding # username:password in the proxy URL p = self.proxy.split(":") if len(p) == 2: self.proxy += ':8080' logging.debug("init - proxy: %s" % (self.proxy)) # Build global headers self.headers = { "User-Agent": "Mozilla/5.0", "Content-Type": "text/xml", "Accept": "text/xml" } if self.url.username is not None: username = urllib.unquote(self.url.username) password = urllib.unquote(self.url.password) self.username = username self.password = password self.url = self.url.unauth() logging.debug("self.url: " + str(url))
def event_by_uid(self, uid): """ Get one event from the calendar. Parameters: * uid: the event uid Returns: * Event() or None """ e = None data = cdav.CalendarData() prop = dav.Prop() + data match = cdav.TextMatch(uid) propf = cdav.PropFilter("UID") + match vevent = cdav.CompFilter("VEVENT") + propf vcalendar = cdav.CompFilter("VCALENDAR") + vevent filter = cdav.Filter() + vcalendar root = cdav.CalendarQuery() + [prop, filter] q = etree.tostring(root.xmlelement(), encoding="utf-8", xml_declaration=True) response = self.client.report(self.url, q, 1) if response.status == 404: raise error.NotFoundError(response.raw) elif response.status == 400: raise error.ReportError(response.raw) r = response.tree.find(".//" + dav.Response.tag) if r is not None: href = URL.objectify(r.find(".//" + dav.Href.tag).text) data = r.find(".//" + cdav.CalendarData.tag).text e = Event(self.client, url=href, data=data, parent=self) else: raise error.NotFoundError(response.raw) return e
def date_search(self, start, end=None): """ Search events by date in the calendar. Recurring events are expanded if they have an occurence during the specified time frame. Parameters: * start = datetime.today(). * end = same as above. Returns: * [Event(), ...] """ matches = [] # build the request expand = cdav.Expand(start, end) data = cdav.CalendarData() + expand prop = dav.Prop() + data range = cdav.TimeRange(start, end) vevent = cdav.CompFilter("VEVENT") + range vcalendar = cdav.CompFilter("VCALENDAR") + vevent filter = cdav.Filter() + vcalendar root = cdav.CalendarQuery() + [prop, filter] q = etree.tostring(root.xmlelement(), encoding="utf-8", xml_declaration=True) response = self.client.report(self.url, q, 1) for r in response.tree.findall(".//" + dav.Response.tag): status = r.find(".//" + dav.Status.tag) if status.text.endswith("200 OK"): href = URL.objectify(r.find(dav.Href.tag).text) href = self.url.join(href) data = r.find(".//" + cdav.CalendarData.tag).text e = Event(self.client, url=href, data=data, parent=self) matches.append(e) else: raise error.ReportError(response.raw) return matches
def __init__(self, url, proxy=None, username=None, password=None): """ Sets up a HTTPConnection object towards the server in the url. Parameters: * url: A fully qualified url: `scheme://user:pass@hostname:port` * proxy: A string defining a proxy server: `hostname:port` * username and password should be passed as arguments or in the URL """ logging.debug("url: " + str(url)) self.url = URL.objectify(url) # Prepare proxy info if proxy is not None: self.proxy = proxy if re.match('^.*://', proxy) is None: # requests library expects the proxy url to have a scheme self.proxy = self.url.scheme + '://' + proxy # add a port is one is not specified # TODO: this will break if using basic auth and embedding # username:password in the proxy URL p = self.proxy.split(":") if len(p) == 2: self.proxy += ':8080' logging.debug("init - proxy: %s" % (self.proxy)) # Build global headers self.headers = {"User-Agent": "Mozilla/5.0", "Content-Type": "text/xml", "Accept": "text/xml"} if self.url.username is not None: username = urllib.unquote(self.url.username) password = urllib.unquote(self.url.password) self.username = username self.password = password self.url = self.url.unauth() logging.debug("self.url: " + str(url))
def __init__(self, client=None, url=None, parent=None, name=None, id=None): """ Default constructor. Parameters: * client: A DAVClient instance * url: The url for this object. May be a full URL or a relative URL. * parent: The parent object - used when creating objects * name: A displayname * id: The resource id (UID for an Event) """ if client is None and parent is not None: client = parent.client self.client = client self.parent = parent self.name = name self.id = id ## url may be a path relative to the caldav root if client and url: self.url = client.url.join(url) else: self.url = URL.objectify(url)
def calendar_home_set(self, url): if isinstance(url, CalendarSet): self._calendar_home_set = url else: self._calendar_home_set = CalendarSet(self.client, self.client.url.join(URL.objectify(url)))
def calendar_home_set(self, url): if isinstance(url, CalendarSet): self._calendar_home_set = url else: self._calendar_home_set = CalendarSet( self.client, self.client.url.join(URL.objectify(url)))