From 5cfa0640166b7123619ad641a0771e8a6e127f56 Mon Sep 17 00:00:00 2001 From: Huang Hao Date: Tue, 31 Dec 2013 12:19:53 +0800 Subject: [PATCH] Rewrite SafeURL class without using zypp.Url Since SafeURL implementation depends on lib zypp which provided by python-zypp package. This package will not be installed when only install "mic" package instead of "mic-native". Then import zypp will raise exception of "No module named _zypp". Change-Id: If8232b0ee77166eadc04f016cd2cda722c7ff23e Fixed: 1568 --- mic/utils/safeurl.py | 121 ++++++++++++++++++++++-------------------- plugins/backend/zypppkgmgr.py | 2 +- 2 files changed, 65 insertions(+), 58 deletions(-) diff --git a/mic/utils/safeurl.py b/mic/utils/safeurl.py index d962298..d91509b 100644 --- a/mic/utils/safeurl.py +++ b/mic/utils/safeurl.py @@ -1,70 +1,77 @@ -"safe url" -import os +""" +This module provides a class SafeURL which can contain url/user/password read +from config file, and hide plain user and password when it print to screen +""" +import os.path +import urllib +from urlparse import urlsplit, urlunsplit -from zypp import Url +def join_userpass(href, user, passwd): + """Return authenticated URL with user and passwd embeded""" + if not user and not passwd: + return href -def remove_userpass(urlstring): - "Remove user and password from url string" - url = Url(urlstring) - url.setUsername('') - url.setPassword('') - return str(url) + if passwd: + userpass = '%s:%s' % (urllib.quote(user, safe=''), + urllib.quote(passwd, safe='')) + else: + userpass = urllib.quote(user, safe='') + parts = urlsplit(href) + netloc = '%s@%s' % (userpass, parts[1]) + comps = list(parts) + comps[1] = netloc + return urlunsplit(comps) -class SafeURL(str): - """URL wrapper which won't show password out""" - def __new__(cls, urlstring, user=None, password=None): - # sometimes we get unicode here, but zypp don't accept unicode string - urlstring = str(urlstring) - safe = remove_userpass(urlstring) - if safe.startswith("file:/"): - # zypp.Url converts file:///path/to/file to file:/path/to/file - safe = "file://" + safe[len("file:"):] - instance = super(SafeURL, cls).__new__(cls, safe) - url = Url(urlstring) - if user: - url.setUsername(user) - if password: - url.setPassword(password) - instance.url = url - return instance +def split_userpass(href): + """Returns (href, user, passwd) of an authenticated URL""" + parts = urlsplit(href) - def join(self, *path): - """ - Returns a new SafeURL with new path. Search part is removed since - after join path is changed, keep the same search part is useless. - """ - urlstring = self.without_search().full.rstrip('/') - return SafeURL(os.path.join(urlstring, *path)) + netloc = parts[1] + if '@' not in netloc: + return href, None, None - @property - def full(self): - "Returns full url string with auth info" - fullstring = self.url.asCompleteString() - if fullstring.startswith("file:/"): - fullstring = "file://" + fullstring[len("file:/"):] - return fullstring + userpass, netloc = netloc.split('@', 1) + if ':' in userpass: + user, passwd = [ urllib.unquote(i) + for i in userpass.split(':', 1) ] + else: + user, passwd = userpass, None - def without_search(self): - "Returns a SafeURL without search part" - urlstring = self.full - idx = urlstring.find('?') - return self if idx == -1 else SafeURL(urlstring[:idx]) + comps = list(parts) + comps[1] = netloc + return urlunsplit(comps), user, passwd - @property - def scheme(self): - return self.url.getScheme() - @property - def user(self): - return self.url.getUsername() +class SafeURL(str): + '''SafeURL can hide user info when it's printed to console. + Use property full to get url with user info + ''' + def __new__(cls, urlstring, user=None, passwd=None): + """Imuutable object""" + href, user1, passwd1 = split_userpass(urlstring) + user = user if user else user1 + passwd = passwd if passwd else passwd1 + + obj = super(SafeURL, cls).__new__(cls, href) + obj.user = user + obj.passwd = passwd + obj.full = join_userpass(href, user, passwd) - @property - def password(self): - return self.url.getPassword() + parts = urlsplit(href) + obj.scheme = parts[0] + obj.netloc = parts[1] + obj.path = parts[2] + obj.host = parts.hostname + obj.port = parts.port + return obj - @property - def host(self): - return self.url.getHost() + def join(self, *path): + """Returns a new SafeURL with new path. Search part is removed since + after join path is changed, keep the same search part is useless. + """ + idx = self.full.find('?') + url = self.full if idx < 0 else self.full[:idx] + return SafeURL(os.path.join(url.rstrip('/'), *path)) diff --git a/plugins/backend/zypppkgmgr.py b/plugins/backend/zypppkgmgr.py index a83fa92..604e3e9 100644 --- a/plugins/backend/zypppkgmgr.py +++ b/plugins/backend/zypppkgmgr.py @@ -370,7 +370,7 @@ class Zypp(BackendPlugin): repo_info.setEnabled(repo.enabled) repo_info.setAutorefresh(repo.autorefresh) repo_info.setKeepPackages(repo.keeppackages) - baseurl = repo.baseurl[0].url + baseurl = zypp.Url(repo.baseurl[0].full) if not ssl_verify: baseurl.setQueryParam("ssl_verify", "no") if proxy: -- 2.7.4