Package caldavclientlibrary :: Package protocol :: Module url
[hide private]
[frames] | no frames]

Source Code for Module caldavclientlibrary.protocol.url

  1  ## 
  2  # Copyright (c) 2007-2016 Apple Inc. All rights reserved. 
  3  # 
  4  # Licensed under the Apache License, Version 2.0 (the "License"); 
  5  # you may not use this file except in compliance with the License. 
  6  # You may obtain a copy of the License at 
  7  # 
  8  # http://www.apache.org/licenses/LICENSE-2.0 
  9  # 
 10  # Unless required by applicable law or agreed to in writing, software 
 11  # distributed under the License is distributed on an "AS IS" BASIS, 
 12  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 13  # See the License for the specific language governing permissions and 
 14  # limitations under the License. 
 15  ## 
 16   
 17  import os 
 18  import urllib 
 19   
20 -class URL(object):
21 22 eAbsolute = 0 23 eRelative = 1 24 eLastPath = 2 25 26 URLEscape = '%' 27 URLReserved = "/?:@&=" 28 URLUnreserved = ( # Allowable URL chars 29 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 0 - 15 30 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 16 - 31 31 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, # 32 - 47 32 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, # 48 - 63 33 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, # 64 - 79 34 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, # 80 - 95 35 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, # 96 - 111 36 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, # 112 - 127 37 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 128 - 143 38 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 144 - 159 39 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 160 - 175 40 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 176 - 191 41 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 192 - 207 42 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 208 - 223 43 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 224 - 239 44 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 240 - 255 45 ) 46 47 URLCharacter = ( # Allowable URL chars -- all 48 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 0 - 15 49 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 16 - 31 50 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, # 32 - 47 51 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, # 48 - 63 52 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, # 64 - 79 53 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, # 80 - 95 54 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, # 96 - 111 55 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, # 112 - 127 56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 128 - 143 57 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 144 - 159 58 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 160 - 175 59 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 176 - 191 60 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 192 - 207 61 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 208 - 223 62 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 224 - 239 63 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 240 - 255 64 ) 65 66 URLXCharacter = ( # Allowable URL chars (all) 67 # RFC2732 uses '[...]' for IPv6 addressing - [] are now allowed 68 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 0 - 15 69 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 16 - 31 70 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, # 32 - 47 71 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, # 48 - 63 72 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, # 64 - 79 73 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, # 80 - 95 74 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, # 96 - 111 75 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, # 112 - 127 76 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 128 - 143 77 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 144 - 159 78 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 160 - 175 79 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 176 - 191 80 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 192 - 207 81 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 208 - 223 82 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 224 - 239 83 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 240 - 255 84 ) 85 86 URLSchemeDoubleSlash = ("http", "https", "webcal",) 87
88 - def __init__(self, url=None, scheme=None, server=None, path=None, extended=None, decode=False):
89 90 self.scheme = "" 91 self.server = "" 92 self.path = "" 93 self.extended = "" 94 95 if not url: 96 self.scheme = scheme 97 self.server = server 98 self.path = path 99 if self.path and decode: 100 self.path = urllib.unquote(self.path) 101 self.extended = extended 102 if self.extended and decode: 103 self.extended = urllib.unquote_plus(self.extended) 104 else: 105 self._parse(url, decode)
106
107 - def __str__(self):
108 return "URL: %s" % (self.toString(),)
109
110 - def __repr__(self):
111 return "URL: %s" % (self.toString(),)
112
113 - def __cmp__(self, other):
114 return cmp(self.toString(), other.toString())
115
116 - def absoluteURL(self):
117 return self.toString()
118
119 - def relativeURL(self):
120 return self.toString(conversion=URL.eRelative)
121
122 - def toString(self, conversion=eAbsolute, encode=True):
123 124 result = "" 125 126 # Add scheme & host if not relative 127 if conversion == URL.eAbsolute and self.scheme and self.server: 128 result += self.scheme + ":" 129 if self.scheme in URL.URLSchemeDoubleSlash: 130 result += "//" 131 result += self.server 132 133 # Get path (or last part of it if required) 134 if self.path and conversion == URL.eLastPath: 135 path = self.path[self.path.rfind("/"):] 136 else: 137 path = self.path 138 139 # Now encode if required 140 if path: 141 result += (urllib.quote(path) if encode else path) 142 143 if self.extended: 144 result += (urllib.quote_plus(self.extended, "?=") if encode else self.extended) 145 146 return result
147
148 - def equal(self, comp):
149 # Compare each component 150 151 if self.scheme != comp.scheme: 152 return False 153 154 if self.server != comp.server: 155 return False 156 157 # Ignore trailing slash 158 if self.path.rstrip("/") != comp.path.rstrip("/"): 159 return False 160 161 return True
162
163 - def equalRelative(self, comp):
164 # Must be relative 165 if comp.server: 166 return False 167 168 # Just compare paths, ignore trailing slash 169 return self.path.rstrip("/") == comp.path.rstrip("/")
170
171 - def dirname(self):
172 if self.path: 173 newpath = os.path.dirname(self.path.rstrip("/")) + "/" 174 return URL(scheme=self.scheme, server=self.server, path=newpath)
175
176 - def _parse(self, url, decode=False):
177 178 # Strip off main scheme 179 if url.lower().startswith("url:"): 180 url = url[4:] 181 182 # Special - if it starts with "/" its a relative HTTP url 183 if url[0] == '/': 184 self.scheme = "http" 185 self.server = None 186 self._parsePath(url, decode) 187 else: 188 # Get protocol scheme 189 self.scheme = url[:url.find(":")].lower() 190 url = url[len(self.scheme):] 191 192 if self.scheme in URL.URLSchemeDoubleSlash: 193 194 assert(url.startswith("://")) 195 196 # Look for server 197 splits = url[3:].split("/", 1) 198 self.server = splits[0] 199 if len(splits) == 2: 200 self._parsePath("/" + splits[1], decode) 201 202 elif self.scheme in ("mailto", "urn",): 203 204 assert(url.startswith(":")) 205 206 # Look for server 207 self.server = url[1:]
208
209 - def _parsePath(self, path, decode=False):
210 211 # Look for extended bits 212 splits = path.split("?", 1) 213 self.path = splits[0] 214 if decode: 215 self.path = urllib.unquote(self.path) 216 if len(splits) == 2: 217 self.extended = "?" + splits[1] 218 if decode: 219 self.extended = urllib.unquote_plus(self.extended)
220