summaryrefslogtreecommitdiff
path: root/src/mailman/utilities/protocols.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/mailman/utilities/protocols.py')
-rw-r--r--src/mailman/utilities/protocols.py101
1 files changed, 101 insertions, 0 deletions
diff --git a/src/mailman/utilities/protocols.py b/src/mailman/utilities/protocols.py
new file mode 100644
index 000000000..5f447c465
--- /dev/null
+++ b/src/mailman/utilities/protocols.py
@@ -0,0 +1,101 @@
+# Copyright (C) 2016 by the Free Software Foundation, Inc.
+#
+# This file is part of GNU Mailman.
+#
+# GNU Mailman is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
+
+"""Various URL protocol support."""
+
+import requests
+
+from mailman import public
+from mailman.interfaces.languages import ILanguageManager
+from mailman.interfaces.listmanager import IListManager
+from mailman.utilities.i18n import TemplateNotFoundError, find
+from urllib.error import URLError
+from urllib.parse import urlparse
+from zope.component import getUtility
+
+COMMASPACE = ', '
+
+
+@public
+def get(url, **kws):
+ parsed = urlparse(url)
+ if parsed.scheme in ('http', 'https'):
+ response = requests.get(url, **kws)
+ response.raise_for_status()
+ return response.text
+ if parsed.scheme == 'file':
+ mode = kws.pop('mode', 'r')
+ arguments = dict(mode=mode)
+ if 'encoding' in kws or 'b' not in mode:
+ arguments['encoding'] = kws.pop('encoding', 'utf-8')
+ if len(kws) > 0:
+ raise ValueError('Unexpected arguments: {}'.format(
+ COMMASPACE.join(sorted(kws))))
+ with open(parsed.path, **arguments) as fp:
+ return fp.read()
+ if parsed.scheme == 'mailman':
+ mlist = code = None
+ if len(kws) > 0:
+ raise ValueError('Unexpected arguments: {}'.format(
+ COMMASPACE.join(sorted(kws))))
+ # The path can contain one, two, or three components. Since no empty
+ # path components are legal, filter them out.
+ parts = [p for p in parsed.path.split('/') if p]
+ if len(parts) == 0:
+ raise URLError('No template specified')
+ elif len(parts) == 1:
+ template = parts[0]
+ elif len(parts) == 2:
+ part0, template = parts
+ # Is part0 a language code or a mailing list? This is rather
+ # tricky because if it's a mailing list, it could be a list-id and
+ # that will contain dots, as could the language code.
+ language = getUtility(ILanguageManager).get(part0)
+ if language is None:
+ list_manager = getUtility(IListManager)
+ # part0 must be a fqdn-listname or list-id.
+ mlist = (list_manager.get(part0)
+ if '@' in part0 else
+ list_manager.get_by_list_id(part0))
+ if mlist is None:
+ raise URLError('Bad language or list name')
+ else:
+ code = language.code
+ elif len(parts) == 3:
+ part0, code, template = parts
+ # part0 could be an fqdn-listname or a list-id.
+ mlist = (getUtility(IListManager).get(part0)
+ if '@' in part0 else
+ getUtility(IListManager).get_by_list_id(part0))
+ if mlist is None:
+ raise URLError('Missing list')
+ language = getUtility(ILanguageManager).get(code)
+ if language is None:
+ raise URLError('No such language')
+ code = language.code
+ else:
+ raise URLError('No such file')
+ # Find the template, mutating any missing template exception.
+ try:
+ path, fp = find(template, mlist, code)
+ except TemplateNotFoundError:
+ raise URLError('No such file')
+ try:
+ return fp.read()
+ finally:
+ fp.close()
+ raise URLError(url)