diff --git a/.gitignore b/.gitignore index 5d381cc..646aeb6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,162 +1,11 @@ -# ---> Python # Byte-compiled / optimized / DLL files __pycache__/ -*.py[cod] -*$py.class -# C extensions -*.so +# vue +./nsi-collection-platform/node_modules/ +./nsi-collection-platform/dist/ +./nsi-collection-platform/.idea -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock - -# pdm -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -#pdm.lock -# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it -# in version control. -# https://pdm.fming.dev/#use-with-ide -.pdm.toml - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ - -# PyCharm -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ +NSICollectionPlatformServer/.idea +NSICollectionPlatformServer/venv diff --git a/NSICollectionPlatformServer/README.md b/NSICollectionPlatformServer/README.md new file mode 100644 index 0000000..03adfc7 --- /dev/null +++ b/NSICollectionPlatformServer/README.md @@ -0,0 +1,53 @@ +# 网络安全信息搜集平台 +> 网络安全信息搜集平台服务端。为前端页面展示提供全套后台服务功能。 + +## 项目说明 +* app.py +> 项目启动文件,包含全部的request请求接口和拦截器设置 + +* userManager.py +> 用户信息管理模块。提供对用户增、删、改、查、登录、注册等功能。 + +* dnsResolve.py.py +> DNS解析模块。提供对dns进行解析的功能。 + +* subdomainLookup.py +> 子域名解析模块。 + +* emailGrabbing.py +> 邮箱内容解析模块。目前只对指定邮箱账号中的内容进行扒取和解析。 + +* portDetection.py +> 端口检测模块。用于检测指定地址上指定端口的状态(开启/关闭)。 + +* requirements.txt +> 包管理文件。包含所有需要依赖的三方包。需要在项目启动前执行安装。 + +## To Start +1. 使用以下命令安装需要的Python依赖包。 +```shell +pip install -r requirements.txt +``` + +2. 切换目录到当前路径下 + +3. 运行app.py +```shell +#前台执行 +python3 app.py +#后台守护进程执行 +nohup python3 app.py >> app.log 2>&1 & +``` + +## 备注 +1. 更新依赖包文件可以使用以下命令 +```shell +pip freeze > requirements.txt +``` + + + + + + + diff --git a/NSICollectionPlatformServer/app.py b/NSICollectionPlatformServer/app.py new file mode 100644 index 0000000..5493bf9 --- /dev/null +++ b/NSICollectionPlatformServer/app.py @@ -0,0 +1,349 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import json + +from flask import Flask +from flask import request, make_response + +import userManager as User +import dnsResolve +import subdomainLookup +import emailGrabbing +import portDetection +import logOperation as Operation + +app = Flask(__name__) + +data_source = { + "host": "118.24.151.27", + "username": "admin", + "password": "Liu947752894!", + "database": "NSI" +} +logOperation = Operation.OperationLog(**data_source) +user_manager = User.UserManager(**data_source) + +if __name__ == '__main__': + app.run(host="127.0.0.1", port=8080) + + +def result(code="000000", desc="SUCCESS", data=None): + res = { + "code": code, + "desc": desc, + "data": data + } + return res + + +@app.before_request +def request_handle(): + """ + 请求拦截器,根据token统一判断是否可用 + :return: 拦截结果 + """ + print(request.url) + print(request.headers) + url = request.url.split("/admin")[1] + print(url) + url = url.split("?")[0] + print(url) + if url not in ["/login", "/register"]: + flag = False + if "token" in request.headers: + token = request.headers['token'] + flag = user_manager.valid_token(token) + if not flag: + response = make_response(result(code="100000", desc="valid token error")) + response.status = 401 + return response + + +def log_operation(request_info, desc="", data=None): + """ + 记录操作日志记录并保存在数据库中 + :param request_info: 请求命令 + :param desc: 用户执行的操作 + :param data: 操作执行数据内容 + """ + token = "" + username = "" + if "token" in request_info.headers \ + and request_info.headers["token"] is not None \ + and 'null' != request_info.headers["token"]: + token = request_info.headers["token"] + else: + username = request_info.json["username"] + logOperation.log(token=token, desc=desc, data=data, username=username) + + +@app.route('/admin/login', methods=['POST']) +def login(): + """ + 用户登录 + :return: 登录结果 + """ + username = request.json['username'] + password = request.json['password'] + __res = user_manager.valid_login(username, password) + if __res is None or len(__res) == 0: + res = result(code="10000", desc="用户不存在") + else: + data = { + "token": User.create_token(username + password), + "role": __res['role'] + } + res = result(data=data) + log_operation(request_info=request, desc="用户登录", data={ + "用户名": username, + "操作执行结果": res + }) + return res + + +@app.route('/admin/register', methods=['POST']) +def register(): + """ + 用户注册,此时无法设置权限,只能管理员对用户设置权限 + :return: + """ + username = request.json['username'] + password = request.json['password'] + role = request.json['role'] + __res = user_manager.user_register(username, password, role) + if __res: + res = result(data="用户注册成功") + else: + res = result(code="10000", desc="用户已经存在") + log_operation(request_info=request, desc="用户注册", data={ + "用户名": username, + "操作执行结果": res + }) + return res + + +@app.route('/admin/user/add', methods=['POST']) +def user_add(): + """ + 新增用户 + :return: + """ + __res = user_manager.user_add( + request.json['username'], + request.json['password'], + request.json['role'], + ) + if __res: + res = result(data="新增用户成功") + else: + res = result(code="10000", desc="新增用户失败") + log_operation(request_info=request, desc="管理员新增用户", data={ + "用户名": request.json['username'], + "角色": request.json['role'], + "操作执行结果": res + }) + return res + + +@app.route('/admin/user/delete', methods=['POST']) +def user_delete(): + """ + 根据id删除用户 + :return: + """ + __id = request.json['id'] + __res = user_manager.user_delete(__id) + if __res: + res = result(data="删除用户成功") + else: + res = result(code="10000", desc="删除用户失败") + log_operation(request_info=request, desc="删除用户", data={ + "ID": __id, + "操作结果": res + }) + return res + + +@app.route('/admin/user/edit', methods=['POST']) +def user_edit(): + """ + 编辑用户 + :return: + """ + __res = user_manager.user_edit( + request.json['id'], + request.json['username'], + request.json['password'], + request.json['role'], + ) + if __res: + res = result(data="编辑用户成功") + else: + res = result(code="10000", desc="编辑用户失败") + log_operation(request_info=request, desc="编辑用户", data={ + "ID": request.json['id'], + "用户名": request.json['username'], + "角色": request.json['role'], + "操作执行结果": res + }) + return res + + +@app.route('/admin/user/list', methods=['GET']) +def user_list(): + """ + 获取用户列表 + :return: + """ + __res = user_manager.user_list() + if __res: + return result(data=__res) + else: + return result(code="10000", desc="获取用户列表失败") + + +@app.route('/admin/user/get', methods=['GET']) +def user_get(): + """ + 根据id获取用户信息 + :return: + """ + __res = user_manager.user_get(request.values['id']) + if __res: + return result(data=__res) + else: + return result(code="10000", desc="获取用户信息失败") + + +@app.route('/admin/user/authority/change', methods=['POST']) +def user_authority_change(): + """ + 根据id修改用户权限 + :return: + """ + __id = request.json['id'] + __role = request.json['role'] + __res = user_manager.user_authority_change(__id, __role) + if __res: + res = result(data=__res) + else: + res = result(code="10000", desc="获取用户信息失败") + log_operation(request_info=request, desc="修改用户权限", data={ + "ID": __id, + "角色": __role, + "操作执行结果": res + }) + return res + + +@app.route('/admin/dns/resolution', methods=['GET']) +def dns_resolution(): + """ + DNS解析 + :return: + """ + __domainType = request.values["domainType"] + __domain = request.values["domain"] + if __domainType is None or __domainType not in ["A", "MX", "NS", "CNAME"]: + res = result(code="100000", desc="无效类型") + else: + if "A" == __domainType: + __data = dnsResolve.resolution_a(__domain) + elif "MX" == __domainType: + __data = dnsResolve.resolution_mx(__domain) + elif "NS" == __domainType: + __data = dnsResolve.resolution_ns(__domain) + elif "CNAME" == __domainType: + __data = dnsResolve.resolution_cname(__domain) + else: + __data = [] + res = result(data=__data) + log_operation(request_info=request, desc="DNS解析", data={ + "解析类型": __domainType, + "解析域名": __domain, + "解析结果": res + }) + return res + + +@app.route('/admin/subdomain/lookup', methods=['GET']) +def subdomain_lookup(): + """ + 子域名查询 + :return: + """ + domain = request.values["domain"] + if domain is None or domain == "": + res = result(code="100000", desc="域名为空") + else: + sub_domain_list = subdomainLookup.sub_domain_lookup(domain=domain) + __data = [] + for key in sub_domain_list: + __data.append({ + "href": key, + "title": sub_domain_list[key] + }) + res = result(data=__data) + log_operation(request_info=request, desc="子域名查询", data={ + "解析域名": domain, + "解析结果": res + }) + return res + + +@app.route('/admin/email/grabbing', methods=['GET']) +def email_grabbing(): + """ + 邮箱账号抓取 + :return: + """ + keyword = request.values["keyword"] + email_suffix = request.values["email_suffix"] + email_count = int(request.values["email_count"]) + if keyword is None or keyword == "": + res = result(code="100000", desc="搜索关键值不能为空") + elif email_suffix is None or email_suffix == "": + res = result(code="100000", desc="搜索邮箱后缀不能为空") + else: + email_grabbing_result = emailGrabbing.EmailAccountGrabbing(keyword=keyword, email_suffix=email_suffix, + email_count=email_count).grabbing() + res = result(data=email_grabbing_result) + log_operation(request_info=request, desc="邮箱账号抓取", data={ + "查询关键字": keyword, + "指定邮箱后缀": email_suffix, + "邮箱账号抓取结果": res + }) + return res + + +@app.route('/admin/port/detection', methods=['GET']) +def port_detection(): + """ + 端口检测 + :return: + """ + domain = request.values["domain"] + port = request.values["port"] + if domain is None or domain == "": + res = result(code="100000", desc="域名/IP不能为空") + else: + port_detection_result = portDetection.detection(domain=domain, port=port) + res = result(data=port_detection_result) + log_operation(request_info=request, desc="端口检测", data={ + "域名或IP": domain, + "端口号": port, + "执行结果": res + }) + return res + + +@app.route('/admin/operation/log/get', methods=['GET']) +def operation_log(): + """ + 操作记录 + :return: + """ + username = request.values["username"] + __operation_log_list = logOperation.list_log(username=username) + res = result(data=__operation_log_list) + return res diff --git a/NSICollectionPlatformServer/dataSource.py b/NSICollectionPlatformServer/dataSource.py new file mode 100644 index 0000000..879adc7 --- /dev/null +++ b/NSICollectionPlatformServer/dataSource.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" + @Time : 2021/05/12 + @Author : + @Site : + @File : dataSource.py + @Software: PyCharm + @Description: +""" +import pymysql +import traceback + + +class DataSource: + def __init__(self, host='localhost', port=3306, username=None, password=None, database=None): + self.host = host + self.port = port + self.username = username + self.password = password + self.database = database + # 打开数据库连接 + self.db = pymysql.connect(host=self.host, port=self.port, user=self.username, password=self.password, database=self.database) + # 使用 cursor() 方法创建一个游标对象 cursor + self.cursor = self.db.cursor(cursor=pymysql.cursors.DictCursor) + + def __is_connected(self): + try: + self.db.ping(reconnect=True) + except Exception as e: + traceback.print_exc() + self.db = pymysql.connections.Connection(host=self.host, port=self.port, user=self.username, password=self.password, database=self.database) + + def fetchall(self, sql): + self.__is_connected() + self.cursor.execute(sql) + return self.cursor.fetchall() + + def fetchmany(self, sql): + self.__is_connected() + self.cursor.execute(sql) + return self.cursor.fetchmany() + + def fetchone(self, sql): + self.__is_connected() + self.cursor.execute(sql) + return self.cursor.fetchone() + + def execute(self, sql): + self.__is_connected() + try: + self.cursor.execute(sql) + self.db.commit() + except: + self.db.rollback() + + def close(self): + self.__is_connected() + # 关闭数据库连接 + self.db.close() diff --git a/NSICollectionPlatformServer/dnsResolve.py b/NSICollectionPlatformServer/dnsResolve.py new file mode 100644 index 0000000..684682a --- /dev/null +++ b/NSICollectionPlatformServer/dnsResolve.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import json + +import dns +import requests + + +def resolution_a(domain): + query_list = [] + a = dns.resolver.resolve(domain, 'A') + for i in a.response.answer: + for j in i.items: + if j.rdtype == 1: + ip = j.address + __ip_query = get_ip_info(ip) + __ip_query["ip"] = ip + __ip_query["domain"] = domain + query_list.append(__ip_query) + return query_list + + +def resolution_mx(domain): + mx = dns.resolver.resolve(domain, 'MX') # 指定查看类型为MX + for i in mx: + print('MX preference=', i.preference, 'mail exchanger=', i.exchange) + + +def resolution_ns(domain): + ns = dns.resolver.resolve(domain, 'NS') # 指定查询类型为NS记录 + for i in ns.response.answer: + for j in i.items: + print(j.to_text()) + + +def resolution_cname(domain): + cname = dns.resolver.resolve(domain, 'CNAME') # 指定查询类型为CNAME记录 + for i in cname.response.answer: # 结果将回应cname后的目标域名 + for j in i.items: + print(j.to_text()) + + +def get_ip_info(ip): + # IP地址库接口 + r = requests.get('https://ip.taobao.com/getIpInfo.php?ip=%s' % ip) + content = json.loads(r.content.decode("utf8")) + ip_query = {} + if "code" in content and content["code"] == '0': + i = content['data'] + ip_query["country"] = i['COUNTRY_CN'] + ip_query["area"] = i['AREA_CN'] + ip_query["province"] = i['PROVINCE_CN'] + ip_query["city"] = i['CITY_CN'] + ip_query["isp"] = i['ISP_CN'] + return ip_query diff --git a/NSICollectionPlatformServer/emailGrabbing.py b/NSICollectionPlatformServer/emailGrabbing.py new file mode 100644 index 0000000..38fc43e --- /dev/null +++ b/NSICollectionPlatformServer/emailGrabbing.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +import requests +from bs4 import BeautifulSoup +from fake_useragent import UserAgent + + +def get_http_headers(): + try: + ua = UserAgent() + header = { + "User-Agent": ua.random, + "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7,zh-TW;q=0.6" + } + except Exception as e: + header = { + u'User-Agent': u'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36'} + return header + + +class EmailAccountGrabbing: + def __init__(self, keyword="test", email_count=2, grabbing_engine="https://www.bing.com/search", email_suffix="hotmail.com"): + self.keyword = keyword + self.email_count = email_count + self.grabbing_engine = grabbing_engine + self.email_suffix = email_suffix + + def grabbing(self): + email_grabbing_result = [] + for i in range(1, self.email_count): + j = 1 + if i != 1: + j = i*10+1 + params = { + "q": "%s @%s" % (self.keyword, self.email_suffix), + "go": "搜索", + "qs": "bs", + "form": "QBRE", + "first": j + } + cookies = { + "SRCHHPGUSR": "NRSLT=50" + } + ret = requests.get(self.grabbing_engine, headers=get_http_headers(), params=params, cookies=cookies) + soup = BeautifulSoup(ret.text, "html.parser") + nodes = soup.find_all(class_="b_caption") + re_email = re.compile('\w+[a-zA-Z0-9_.\-]*@%s' % self.email_suffix) + for node in nodes: + emails = re_email.findall(node.text) + for email in emails: + email_grabbing_result.append({ + "grabbingEngine": ret.url, + "emailAddress": email, + "keyword": self.keyword + }) + return email_grabbing_result diff --git a/NSICollectionPlatformServer/logOperation.py b/NSICollectionPlatformServer/logOperation.py new file mode 100644 index 0000000..490b839 --- /dev/null +++ b/NSICollectionPlatformServer/logOperation.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import json +import traceback + +from dataSource import DataSource + + +class OperationLog: + def __init__(self, host='localhost', port=3306, username=None, password=None, database=None): + self.db = DataSource(host, port, username, password, database) + + def log(self, token, desc="", data=None, username=""): + """ + 记录用户操作 + :param token: 令牌(用户名和令牌不可同时有值) + :param desc: 操作描述 + :param data: 操作数据 + :param username: 用户名(用户名和令牌不可同时有值) + """ + try: + if data is None: + data = {} + if "" == token: + sql_insert = 'INSERT INTO LOG_OPERATION (username, operationContent, operationData) VALUES ("' + username + '", "' + desc + '", ' + json.dumps( + json.dumps(data)) + ')' + else: + sql = 'SELECT * FROM USER WHERE `password`="' + token + '"' + user_info = self.db.fetchone(sql) + sql_insert = 'INSERT INTO LOG_OPERATION (username, operationContent, operationData) VALUES ("' + \ + user_info["username"] + '", "' + desc + '", ' + json.dumps(json.dumps(data)) + ')' + self.db.execute(sql=sql_insert) + except Exception as e: + traceback.print_exc() + + def list_log(self, username=""): + """ + 获取用户操作列表集合 + :param username: 根据用户名查看对应操作记录 + :return: + """ + if username is None or username == "": + sql = 'SELECT * FROM LOG_OPERATION' + else: + sql = 'SELECT * FROM LOG_OPERATION WHERE username="' + username + '"' + return self.db.fetchall(sql) diff --git a/NSICollectionPlatformServer/packages/Flask-2.0.0-py3-none-any.whl b/NSICollectionPlatformServer/packages/Flask-2.0.0-py3-none-any.whl new file mode 100644 index 0000000..5ce53a0 Binary files /dev/null and b/NSICollectionPlatformServer/packages/Flask-2.0.0-py3-none-any.whl differ diff --git a/NSICollectionPlatformServer/packages/Jinja2-3.0.0-py3-none-any.whl b/NSICollectionPlatformServer/packages/Jinja2-3.0.0-py3-none-any.whl new file mode 100644 index 0000000..7a02c2d Binary files /dev/null and b/NSICollectionPlatformServer/packages/Jinja2-3.0.0-py3-none-any.whl differ diff --git a/NSICollectionPlatformServer/packages/MarkupSafe-2.0.0-cp39-cp39-win_amd64.whl b/NSICollectionPlatformServer/packages/MarkupSafe-2.0.0-cp39-cp39-win_amd64.whl new file mode 100644 index 0000000..f5b9a0a Binary files /dev/null and b/NSICollectionPlatformServer/packages/MarkupSafe-2.0.0-cp39-cp39-win_amd64.whl differ diff --git a/NSICollectionPlatformServer/packages/PyMySQL-1.0.2-py3-none-any.whl b/NSICollectionPlatformServer/packages/PyMySQL-1.0.2-py3-none-any.whl new file mode 100644 index 0000000..01ec7d3 Binary files /dev/null and b/NSICollectionPlatformServer/packages/PyMySQL-1.0.2-py3-none-any.whl differ diff --git a/NSICollectionPlatformServer/packages/Werkzeug-2.0.0-py3-none-any.whl b/NSICollectionPlatformServer/packages/Werkzeug-2.0.0-py3-none-any.whl new file mode 100644 index 0000000..906d452 Binary files /dev/null and b/NSICollectionPlatformServer/packages/Werkzeug-2.0.0-py3-none-any.whl differ diff --git a/NSICollectionPlatformServer/packages/bs4-0.0.1.tar.gz b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar.gz new file mode 100644 index 0000000..adc6bf6 Binary files /dev/null and b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar.gz differ diff --git a/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1.tar b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1.tar new file mode 100644 index 0000000..e624fff Binary files /dev/null and b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1.tar differ diff --git a/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/PKG-INFO b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/PKG-INFO new file mode 100644 index 0000000..60137e4 --- /dev/null +++ b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/PKG-INFO @@ -0,0 +1,21 @@ +Metadata-Version: 1.1 +Name: bs4 +Version: 0.0.1 +Summary: Screen-scraping library +Home-page: https://pypi.python.org/pypi/beautifulsoup4 +Author: Leonard Richardson +Author-email: leonardr@segfault.org +License: MIT +Download-URL: http://www.crummy.com/software/BeautifulSoup/bs4/download/ +Description: Use `beautifulsoup4 `_ instead. +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 3 +Classifier: Topic :: Text Processing :: Markup :: HTML +Classifier: Topic :: Text Processing :: Markup :: XML +Classifier: Topic :: Text Processing :: Markup :: SGML +Classifier: Topic :: Software Development :: Libraries :: Python Modules diff --git a/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/bs4.egg-info/PKG-INFO b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/bs4.egg-info/PKG-INFO new file mode 100644 index 0000000..60137e4 --- /dev/null +++ b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/bs4.egg-info/PKG-INFO @@ -0,0 +1,21 @@ +Metadata-Version: 1.1 +Name: bs4 +Version: 0.0.1 +Summary: Screen-scraping library +Home-page: https://pypi.python.org/pypi/beautifulsoup4 +Author: Leonard Richardson +Author-email: leonardr@segfault.org +License: MIT +Download-URL: http://www.crummy.com/software/BeautifulSoup/bs4/download/ +Description: Use `beautifulsoup4 `_ instead. +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 3 +Classifier: Topic :: Text Processing :: Markup :: HTML +Classifier: Topic :: Text Processing :: Markup :: XML +Classifier: Topic :: Text Processing :: Markup :: SGML +Classifier: Topic :: Software Development :: Libraries :: Python Modules diff --git a/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/bs4.egg-info/SOURCES.txt b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/bs4.egg-info/SOURCES.txt new file mode 100644 index 0000000..b46d1c5 --- /dev/null +++ b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/bs4.egg-info/SOURCES.txt @@ -0,0 +1,7 @@ +setup.cfg +setup.py +bs4.egg-info/PKG-INFO +bs4.egg-info/SOURCES.txt +bs4.egg-info/dependency_links.txt +bs4.egg-info/requires.txt +bs4.egg-info/top_level.txt \ No newline at end of file diff --git a/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/bs4.egg-info/dependency_links.txt b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/bs4.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/bs4.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/bs4.egg-info/requires.txt b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/bs4.egg-info/requires.txt new file mode 100644 index 0000000..c1f5f71 --- /dev/null +++ b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/bs4.egg-info/requires.txt @@ -0,0 +1 @@ +beautifulsoup4 diff --git a/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/bs4.egg-info/top_level.txt b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/bs4.egg-info/top_level.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/bs4.egg-info/top_level.txt @@ -0,0 +1 @@ + diff --git a/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/dist/bs4-0.0.1-py3.9.egg b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/dist/bs4-0.0.1-py3.9.egg new file mode 100644 index 0000000..c8676b8 Binary files /dev/null and b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/dist/bs4-0.0.1-py3.9.egg differ diff --git a/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/setup.cfg b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/setup.cfg new file mode 100644 index 0000000..861a9f5 --- /dev/null +++ b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/setup.cfg @@ -0,0 +1,5 @@ +[egg_info] +tag_build = +tag_date = 0 +tag_svn_revision = 0 + diff --git a/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/setup.py b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/setup.py new file mode 100644 index 0000000..74c9413 --- /dev/null +++ b/NSICollectionPlatformServer/packages/bs4-0.0.1.tar/dist/bs4-0.0.1/setup.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +from setuptools import setup + +setup( + name="bs4", + version="0.0.1", + author="Leonard Richardson", + author_email='leonardr@segfault.org', + url="https://pypi.python.org/pypi/beautifulsoup4", + download_url="http://www.crummy.com/software/BeautifulSoup/bs4/download/", + description="Screen-scraping library", + long_description="""Use `beautifulsoup4 `_ instead.""", # noqa + license="MIT", + install_requires=['beautifulsoup4'], + classifiers=[ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python", + "Programming Language :: Python :: 2", + 'Programming Language :: Python :: 3', + "Topic :: Text Processing :: Markup :: HTML", + "Topic :: Text Processing :: Markup :: XML", + "Topic :: Text Processing :: Markup :: SGML", + "Topic :: Software Development :: Libraries :: Python Modules", + ], +) diff --git a/NSICollectionPlatformServer/packages/certifi-2020.12.5-py2.py3-none-any.whl b/NSICollectionPlatformServer/packages/certifi-2020.12.5-py2.py3-none-any.whl new file mode 100644 index 0000000..ef0e2ec Binary files /dev/null and b/NSICollectionPlatformServer/packages/certifi-2020.12.5-py2.py3-none-any.whl differ diff --git a/NSICollectionPlatformServer/packages/chardet-4.0.0-py2.py3-none-any.whl b/NSICollectionPlatformServer/packages/chardet-4.0.0-py2.py3-none-any.whl new file mode 100644 index 0000000..b83344e Binary files /dev/null and b/NSICollectionPlatformServer/packages/chardet-4.0.0-py2.py3-none-any.whl differ diff --git a/NSICollectionPlatformServer/packages/click-8.0.0-py3-none-any.whl b/NSICollectionPlatformServer/packages/click-8.0.0-py3-none-any.whl new file mode 100644 index 0000000..e82e140 Binary files /dev/null and b/NSICollectionPlatformServer/packages/click-8.0.0-py3-none-any.whl differ diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0.zip b/NSICollectionPlatformServer/packages/dnspython-2.1.0.zip new file mode 100644 index 0000000..f2e1631 Binary files /dev/null and b/NSICollectionPlatformServer/packages/dnspython-2.1.0.zip differ diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/LICENSE b/NSICollectionPlatformServer/packages/dnspython-2.1.0/LICENSE new file mode 100644 index 0000000..390a726 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/LICENSE @@ -0,0 +1,35 @@ +ISC License + +Copyright (C) Dnspython Contributors + +Permission to use, copy, modify, and/or distribute this software for +any purpose with or without fee is hereby granted, provided that the +above copyright notice and this permission notice appear in all +copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + + + +Copyright (C) 2001-2017 Nominum, Inc. +Copyright (C) Google Inc. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose with or without fee is hereby granted, +provided that the above copyright notice and this permission notice +appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/MANIFEST.in b/NSICollectionPlatformServer/packages/dnspython-2.1.0/MANIFEST.in new file mode 100644 index 0000000..8fdc68c --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/MANIFEST.in @@ -0,0 +1,3 @@ +include LICENSE ChangeLog README.md +recursive-include examples *.txt *.py +recursive-include tests *.txt *.py Makefile *.good example query diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/PKG-INFO b/NSICollectionPlatformServer/packages/dnspython-2.1.0/PKG-INFO new file mode 100644 index 0000000..3b29b31 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/PKG-INFO @@ -0,0 +1,38 @@ +Metadata-Version: 2.1 +Name: dnspython +Version: 2.1.0 +Summary: DNS toolkit +Home-page: http://www.dnspython.org +Author: Bob Halley +Author-email: halley@dnspython.org +License: ISC +Description: dnspython is a DNS toolkit for Python. It supports almost all + record types. It can be used for queries, zone transfers, and dynamic + updates. It supports TSIG authenticated messages and EDNS0. + + dnspython provides both high and low level access to DNS. The high + level classes perform queries for data of a given name, type, and + class, and return an answer set. The low level classes allow + direct manipulation of DNS zones, messages, names, and records. +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: System Administrators +Classifier: License :: OSI Approved :: ISC License (ISCL) +Classifier: Operating System :: POSIX +Classifier: Operating System :: Microsoft :: Windows +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: Name Service (DNS) +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Provides: dns +Requires-Python: >=3.6 +Provides-Extra: DOH +Provides-Extra: IDNA +Provides-Extra: DNSSEC +Provides-Extra: trio +Provides-Extra: curio diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/README.md b/NSICollectionPlatformServer/packages/dnspython-2.1.0/README.md new file mode 100644 index 0000000..62b6df1 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/README.md @@ -0,0 +1,74 @@ +# dnspython + +[![Build Status](https://travis-ci.org/rthalley/dnspython.svg?branch=master)](https://travis-ci.org/rthalley/dnspython) +[![Documentation Status](https://readthedocs.org/projects/dnspython/badge/?version=latest)](https://dnspython.readthedocs.io/en/latest/?badge=latest) +[![PyPI version](https://badge.fury.io/py/dnspython.svg)](https://badge.fury.io/py/dnspython) +[![Coverage](https://codecov.io/github/rthalley/dnspython/coverage.svg?branch=master)](https://codecov.io/gh/rthalley/dnspython) +[![License: ISC](https://img.shields.io/badge/License-ISC-brightgreen.svg)](https://opensource.org/licenses/ISC) + +## INTRODUCTION + +dnspython is a DNS toolkit for Python. It supports almost all record types. It +can be used for queries, zone transfers, and dynamic updates. It supports TSIG +authenticated messages and EDNS0. + +dnspython provides both high and low level access to DNS. The high level classes +perform queries for data of a given name, type, and class, and return an answer +set. The low level classes allow direct manipulation of DNS zones, messages, +names, and records. + +To see a few of the ways dnspython can be used, look in the `examples/` +directory. + +dnspython is a utility to work with DNS, `/etc/hosts` is thus not used. For +simple forward DNS lookups, it's better to use `socket.getaddrinfo()` or +`socket.gethostbyname()`. + +dnspython originated at Nominum where it was developed +to facilitate the testing of DNS software. + +## ABOUT THIS RELEASE + +This is dnspython 2.1.0. +Please read +[What's New](https://dnspython.readthedocs.io/en/stable/whatsnew.html) for +information about the changes in this release. + +## INSTALLATION + +* Many distributions have dnspython packaged for you, so you should + check there first. +* If you have pip installed, you can do `pip install dnspython` +* If not just download the source file and unzip it, then run + `sudo python setup.py install` +* To install the latest from the master branch, run `pip install git+https://github.com/rthalley/dnspython.git` + +If you want to use DNS-over-HTTPS, you must run +`pip install dnspython[doh]`. + +If you want to use DNSSEC functionality, you must run +`pip install dnspython[dnssec]`. + +If you want to use internationalized domain names (IDNA) +functionality, you must run +`pip install dnspython[idna]` + +If you want to use the Trio asynchronous I/O package, you must run +`pip install dnspython[trio]`. + +If you want to use the Curio asynchronous I/O package, you must run +`pip install dnspython[curio]`. + +Note that you can install any combination of the above, e.g.: +`pip install dnspython[doh,dnssec,idna]` + +### Notices + +Python 2.x support ended with the release of 1.16.0. dnspython 2.0.0 and +later only support Python 3.6 and later. + +Documentation has moved to +[dnspython.readthedocs.io](https://dnspython.readthedocs.io). + +The ChangeLog has been discontinued. Please see the git history for detailed +change information. diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/__init__.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/__init__.py new file mode 100644 index 0000000..0473ca1 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/__init__.py @@ -0,0 +1,66 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009, 2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""dnspython DNS toolkit""" + +__all__ = [ + 'asyncbackend', + 'asyncquery', + 'asyncresolver', + 'dnssec', + 'e164', + 'edns', + 'entropy', + 'exception', + 'flags', + 'immutable', + 'inet', + 'ipv4', + 'ipv6', + 'message', + 'name', + 'namedict', + 'node', + 'opcode', + 'query', + 'rcode', + 'rdata', + 'rdataclass', + 'rdataset', + 'rdatatype', + 'renderer', + 'resolver', + 'reversename', + 'rrset', + 'serial', + 'set', + 'tokenizer', + 'transaction', + 'tsig', + 'tsigkeyring', + 'ttl', + 'rdtypes', + 'update', + 'version', + 'versioned', + 'wire', + 'xfr', + 'zone', + 'zonefile', +] + +from dns.version import version as __version__ # noqa diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/_asyncbackend.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/_asyncbackend.py new file mode 100644 index 0000000..c7ecfad --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/_asyncbackend.py @@ -0,0 +1,60 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# This is a nullcontext for both sync and async. 3.7 has a nullcontext, +# but it is only for sync use. + +class NullContext: + def __init__(self, enter_result=None): + self.enter_result = enter_result + + def __enter__(self): + return self.enter_result + + def __exit__(self, exc_type, exc_value, traceback): + pass + + async def __aenter__(self): + return self.enter_result + + async def __aexit__(self, exc_type, exc_value, traceback): + pass + + +# These are declared here so backends can import them without creating +# circular dependencies with dns.asyncbackend. + +class Socket: # pragma: no cover + async def close(self): + pass + + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc_value, traceback): + await self.close() + + +class DatagramSocket(Socket): # pragma: no cover + async def sendto(self, what, destination, timeout): + pass + + async def recvfrom(self, size, timeout): + pass + + +class StreamSocket(Socket): # pragma: no cover + async def sendall(self, what, destination, timeout): + pass + + async def recv(self, size, timeout): + pass + + +class Backend: # pragma: no cover + def name(self): + return 'unknown' + + async def make_socket(self, af, socktype, proto=0, + source=None, destination=None, timeout=None, + ssl_context=None, server_hostname=None): + raise NotImplementedError diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/_asyncio_backend.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/_asyncio_backend.py new file mode 100644 index 0000000..6a56332 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/_asyncio_backend.py @@ -0,0 +1,138 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +"""asyncio library query support""" + +import socket +import asyncio + +import dns._asyncbackend +import dns.exception + + +def _get_running_loop(): + try: + return asyncio.get_running_loop() + except AttributeError: # pragma: no cover + return asyncio.get_event_loop() + + +class _DatagramProtocol: + def __init__(self): + self.transport = None + self.recvfrom = None + + def connection_made(self, transport): + self.transport = transport + + def datagram_received(self, data, addr): + if self.recvfrom: + self.recvfrom.set_result((data, addr)) + self.recvfrom = None + + def error_received(self, exc): # pragma: no cover + if self.recvfrom and not self.recvfrom.done(): + self.recvfrom.set_exception(exc) + + def connection_lost(self, exc): + if self.recvfrom and not self.recvfrom.done(): + self.recvfrom.set_exception(exc) + + def close(self): + self.transport.close() + + +async def _maybe_wait_for(awaitable, timeout): + if timeout: + try: + return await asyncio.wait_for(awaitable, timeout) + except asyncio.TimeoutError: + raise dns.exception.Timeout(timeout=timeout) + else: + return await awaitable + + +class DatagramSocket(dns._asyncbackend.DatagramSocket): + def __init__(self, family, transport, protocol): + self.family = family + self.transport = transport + self.protocol = protocol + + async def sendto(self, what, destination, timeout): # pragma: no cover + # no timeout for asyncio sendto + self.transport.sendto(what, destination) + + async def recvfrom(self, size, timeout): + # ignore size as there's no way I know to tell protocol about it + done = _get_running_loop().create_future() + assert self.protocol.recvfrom is None + self.protocol.recvfrom = done + await _maybe_wait_for(done, timeout) + return done.result() + + async def close(self): + self.protocol.close() + + async def getpeername(self): + return self.transport.get_extra_info('peername') + + async def getsockname(self): + return self.transport.get_extra_info('sockname') + + +class StreamSocket(dns._asyncbackend.DatagramSocket): + def __init__(self, af, reader, writer): + self.family = af + self.reader = reader + self.writer = writer + + async def sendall(self, what, timeout): + self.writer.write(what) + return await _maybe_wait_for(self.writer.drain(), timeout) + + async def recv(self, count, timeout): + return await _maybe_wait_for(self.reader.read(count), + timeout) + + async def close(self): + self.writer.close() + try: + await self.writer.wait_closed() + except AttributeError: # pragma: no cover + pass + + async def getpeername(self): + return self.writer.get_extra_info('peername') + + async def getsockname(self): + return self.writer.get_extra_info('sockname') + + +class Backend(dns._asyncbackend.Backend): + def name(self): + return 'asyncio' + + async def make_socket(self, af, socktype, proto=0, + source=None, destination=None, timeout=None, + ssl_context=None, server_hostname=None): + loop = _get_running_loop() + if socktype == socket.SOCK_DGRAM: + transport, protocol = await loop.create_datagram_endpoint( + _DatagramProtocol, source, family=af, + proto=proto) + return DatagramSocket(af, transport, protocol) + elif socktype == socket.SOCK_STREAM: + (r, w) = await _maybe_wait_for( + asyncio.open_connection(destination[0], + destination[1], + ssl=ssl_context, + family=af, + proto=proto, + local_addr=source, + server_hostname=server_hostname), + timeout) + return StreamSocket(af, r, w) + raise NotImplementedError('unsupported socket ' + + f'type {socktype}') # pragma: no cover + + async def sleep(self, interval): + await asyncio.sleep(interval) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/_curio_backend.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/_curio_backend.py new file mode 100644 index 0000000..894e87c --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/_curio_backend.py @@ -0,0 +1,108 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +"""curio async I/O library query support""" + +import socket +import curio +import curio.socket # type: ignore + +import dns._asyncbackend +import dns.exception +import dns.inet + + +def _maybe_timeout(timeout): + if timeout: + return curio.ignore_after(timeout) + else: + return dns._asyncbackend.NullContext() + + +# for brevity +_lltuple = dns.inet.low_level_address_tuple + +# pylint: disable=redefined-outer-name + + +class DatagramSocket(dns._asyncbackend.DatagramSocket): + def __init__(self, socket): + self.socket = socket + self.family = socket.family + + async def sendto(self, what, destination, timeout): + async with _maybe_timeout(timeout): + return await self.socket.sendto(what, destination) + raise dns.exception.Timeout(timeout=timeout) # pragma: no cover + + async def recvfrom(self, size, timeout): + async with _maybe_timeout(timeout): + return await self.socket.recvfrom(size) + raise dns.exception.Timeout(timeout=timeout) + + async def close(self): + await self.socket.close() + + async def getpeername(self): + return self.socket.getpeername() + + async def getsockname(self): + return self.socket.getsockname() + + +class StreamSocket(dns._asyncbackend.DatagramSocket): + def __init__(self, socket): + self.socket = socket + self.family = socket.family + + async def sendall(self, what, timeout): + async with _maybe_timeout(timeout): + return await self.socket.sendall(what) + raise dns.exception.Timeout(timeout=timeout) + + async def recv(self, size, timeout): + async with _maybe_timeout(timeout): + return await self.socket.recv(size) + raise dns.exception.Timeout(timeout=timeout) + + async def close(self): + await self.socket.close() + + async def getpeername(self): + return self.socket.getpeername() + + async def getsockname(self): + return self.socket.getsockname() + + +class Backend(dns._asyncbackend.Backend): + def name(self): + return 'curio' + + async def make_socket(self, af, socktype, proto=0, + source=None, destination=None, timeout=None, + ssl_context=None, server_hostname=None): + if socktype == socket.SOCK_DGRAM: + s = curio.socket.socket(af, socktype, proto) + try: + if source: + s.bind(_lltuple(source, af)) + except Exception: # pragma: no cover + await s.close() + raise + return DatagramSocket(s) + elif socktype == socket.SOCK_STREAM: + if source: + source_addr = _lltuple(source, af) + else: + source_addr = None + async with _maybe_timeout(timeout): + s = await curio.open_connection(destination[0], destination[1], + ssl=ssl_context, + source_addr=source_addr, + server_hostname=server_hostname) + return StreamSocket(s) + raise NotImplementedError('unsupported socket ' + + f'type {socktype}') # pragma: no cover + + async def sleep(self, interval): + await curio.sleep(interval) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/_immutable_attr.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/_immutable_attr.py new file mode 100644 index 0000000..f7b9f8b --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/_immutable_attr.py @@ -0,0 +1,84 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# This implementation of the immutable decorator is for python 3.6, +# which doesn't have Context Variables. This implementation is somewhat +# costly for classes with slots, as it adds a __dict__ to them. + + +import inspect + + +class _Immutable: + """Immutable mixin class""" + + # Note we MUST NOT have __slots__ as that causes + # + # TypeError: multiple bases have instance lay-out conflict + # + # when we get mixed in with another class with slots. When we + # get mixed into something with slots, it effectively adds __dict__ to + # the slots of the other class, which allows attribute setting to work, + # albeit at the cost of the dictionary. + + def __setattr__(self, name, value): + if not hasattr(self, '_immutable_init') or \ + self._immutable_init is not self: + raise TypeError("object doesn't support attribute assignment") + else: + super().__setattr__(name, value) + + def __delattr__(self, name): + if not hasattr(self, '_immutable_init') or \ + self._immutable_init is not self: + raise TypeError("object doesn't support attribute assignment") + else: + super().__delattr__(name) + + +def _immutable_init(f): + def nf(*args, **kwargs): + try: + # Are we already initializing an immutable class? + previous = args[0]._immutable_init + except AttributeError: + # We are the first! + previous = None + object.__setattr__(args[0], '_immutable_init', args[0]) + try: + # call the actual __init__ + f(*args, **kwargs) + finally: + if not previous: + # If we started the initialzation, establish immutability + # by removing the attribute that allows mutation + object.__delattr__(args[0], '_immutable_init') + nf.__signature__ = inspect.signature(f) + return nf + + +def immutable(cls): + if _Immutable in cls.__mro__: + # Some ancestor already has the mixin, so just make sure we keep + # following the __init__ protocol. + cls.__init__ = _immutable_init(cls.__init__) + if hasattr(cls, '__setstate__'): + cls.__setstate__ = _immutable_init(cls.__setstate__) + ncls = cls + else: + # Mixin the Immutable class and follow the __init__ protocol. + class ncls(_Immutable, cls): + + @_immutable_init + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + if hasattr(cls, '__setstate__'): + @_immutable_init + def __setstate__(self, *args, **kwargs): + super().__setstate__(*args, **kwargs) + + # make ncls have the same name and module as cls + ncls.__name__ = cls.__name__ + ncls.__qualname__ = cls.__qualname__ + ncls.__module__ = cls.__module__ + return ncls diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/_immutable_ctx.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/_immutable_ctx.py new file mode 100644 index 0000000..ececdbe --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/_immutable_ctx.py @@ -0,0 +1,75 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# This implementation of the immutable decorator requires python >= +# 3.7, and is significantly more storage efficient when making classes +# with slots immutable. It's also faster. + +import contextvars +import inspect + + +_in__init__ = contextvars.ContextVar('_immutable_in__init__', default=False) + + +class _Immutable: + """Immutable mixin class""" + + # We set slots to the empty list to say "we don't have any attributes". + # We do this so that if we're mixed in with a class with __slots__, we + # don't cause a __dict__ to be added which would waste space. + + __slots__ = () + + def __setattr__(self, name, value): + if _in__init__.get() is not self: + raise TypeError("object doesn't support attribute assignment") + else: + super().__setattr__(name, value) + + def __delattr__(self, name): + if _in__init__.get() is not self: + raise TypeError("object doesn't support attribute assignment") + else: + super().__delattr__(name) + + +def _immutable_init(f): + def nf(*args, **kwargs): + previous = _in__init__.set(args[0]) + try: + # call the actual __init__ + f(*args, **kwargs) + finally: + _in__init__.reset(previous) + nf.__signature__ = inspect.signature(f) + return nf + + +def immutable(cls): + if _Immutable in cls.__mro__: + # Some ancestor already has the mixin, so just make sure we keep + # following the __init__ protocol. + cls.__init__ = _immutable_init(cls.__init__) + if hasattr(cls, '__setstate__'): + cls.__setstate__ = _immutable_init(cls.__setstate__) + ncls = cls + else: + # Mixin the Immutable class and follow the __init__ protocol. + class ncls(_Immutable, cls): + # We have to do the __slots__ declaration here too! + __slots__ = () + + @_immutable_init + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + if hasattr(cls, '__setstate__'): + @_immutable_init + def __setstate__(self, *args, **kwargs): + super().__setstate__(*args, **kwargs) + + # make ncls have the same name and module as cls + ncls.__name__ = cls.__name__ + ncls.__qualname__ = cls.__qualname__ + ncls.__module__ = cls.__module__ + return ncls diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/_trio_backend.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/_trio_backend.py new file mode 100644 index 0000000..82512cd --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/_trio_backend.py @@ -0,0 +1,121 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +"""trio async I/O library query support""" + +import socket +import trio +import trio.socket # type: ignore + +import dns._asyncbackend +import dns.exception +import dns.inet + + +def _maybe_timeout(timeout): + if timeout: + return trio.move_on_after(timeout) + else: + return dns._asyncbackend.NullContext() + + +# for brevity +_lltuple = dns.inet.low_level_address_tuple + +# pylint: disable=redefined-outer-name + + +class DatagramSocket(dns._asyncbackend.DatagramSocket): + def __init__(self, socket): + self.socket = socket + self.family = socket.family + + async def sendto(self, what, destination, timeout): + with _maybe_timeout(timeout): + return await self.socket.sendto(what, destination) + raise dns.exception.Timeout(timeout=timeout) # pragma: no cover + + async def recvfrom(self, size, timeout): + with _maybe_timeout(timeout): + return await self.socket.recvfrom(size) + raise dns.exception.Timeout(timeout=timeout) + + async def close(self): + self.socket.close() + + async def getpeername(self): + return self.socket.getpeername() + + async def getsockname(self): + return self.socket.getsockname() + + +class StreamSocket(dns._asyncbackend.DatagramSocket): + def __init__(self, family, stream, tls=False): + self.family = family + self.stream = stream + self.tls = tls + + async def sendall(self, what, timeout): + with _maybe_timeout(timeout): + return await self.stream.send_all(what) + raise dns.exception.Timeout(timeout=timeout) + + async def recv(self, size, timeout): + with _maybe_timeout(timeout): + return await self.stream.receive_some(size) + raise dns.exception.Timeout(timeout=timeout) + + async def close(self): + await self.stream.aclose() + + async def getpeername(self): + if self.tls: + return self.stream.transport_stream.socket.getpeername() + else: + return self.stream.socket.getpeername() + + async def getsockname(self): + if self.tls: + return self.stream.transport_stream.socket.getsockname() + else: + return self.stream.socket.getsockname() + + +class Backend(dns._asyncbackend.Backend): + def name(self): + return 'trio' + + async def make_socket(self, af, socktype, proto=0, source=None, + destination=None, timeout=None, + ssl_context=None, server_hostname=None): + s = trio.socket.socket(af, socktype, proto) + stream = None + try: + if source: + await s.bind(_lltuple(source, af)) + if socktype == socket.SOCK_STREAM: + with _maybe_timeout(timeout): + await s.connect(_lltuple(destination, af)) + except Exception: # pragma: no cover + s.close() + raise + if socktype == socket.SOCK_DGRAM: + return DatagramSocket(s) + elif socktype == socket.SOCK_STREAM: + stream = trio.SocketStream(s) + s = None + tls = False + if ssl_context: + tls = True + try: + stream = trio.SSLStream(stream, ssl_context, + server_hostname=server_hostname) + except Exception: # pragma: no cover + await stream.aclose() + raise + return StreamSocket(af, stream, tls) + raise NotImplementedError('unsupported socket ' + + f'type {socktype}') # pragma: no cover + + async def sleep(self, interval): + await trio.sleep(interval) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/asyncbackend.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/asyncbackend.py new file mode 100644 index 0000000..e6a42ce --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/asyncbackend.py @@ -0,0 +1,101 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import dns.exception + +# pylint: disable=unused-import + +from dns._asyncbackend import Socket, DatagramSocket, \ + StreamSocket, Backend # noqa: + +# pylint: enable=unused-import + +_default_backend = None + +_backends = {} + +# Allow sniffio import to be disabled for testing purposes +_no_sniffio = False + +class AsyncLibraryNotFoundError(dns.exception.DNSException): + pass + + +def get_backend(name): + """Get the specified asychronous backend. + + *name*, a ``str``, the name of the backend. Currently the "trio", + "curio", and "asyncio" backends are available. + + Raises NotImplementError if an unknown backend name is specified. + """ + # pylint: disable=import-outside-toplevel,redefined-outer-name + backend = _backends.get(name) + if backend: + return backend + if name == 'trio': + import dns._trio_backend + backend = dns._trio_backend.Backend() + elif name == 'curio': + import dns._curio_backend + backend = dns._curio_backend.Backend() + elif name == 'asyncio': + import dns._asyncio_backend + backend = dns._asyncio_backend.Backend() + else: + raise NotImplementedError(f'unimplemented async backend {name}') + _backends[name] = backend + return backend + + +def sniff(): + """Attempt to determine the in-use asynchronous I/O library by using + the ``sniffio`` module if it is available. + + Returns the name of the library, or raises AsyncLibraryNotFoundError + if the library cannot be determined. + """ + # pylint: disable=import-outside-toplevel + try: + if _no_sniffio: + raise ImportError + import sniffio + try: + return sniffio.current_async_library() + except sniffio.AsyncLibraryNotFoundError: + raise AsyncLibraryNotFoundError('sniffio cannot determine ' + + 'async library') + except ImportError: + import asyncio + try: + asyncio.get_running_loop() + return 'asyncio' + except RuntimeError: + raise AsyncLibraryNotFoundError('no async library detected') + except AttributeError: # pragma: no cover + # we have to check current_task on 3.6 + if not asyncio.Task.current_task(): + raise AsyncLibraryNotFoundError('no async library detected') + return 'asyncio' + + +def get_default_backend(): + """Get the default backend, initializing it if necessary. + """ + if _default_backend: + return _default_backend + + return set_default_backend(sniff()) + + +def set_default_backend(name): + """Set the default backend. + + It's not normally necessary to call this method, as + ``get_default_backend()`` will initialize the backend + appropriately in many cases. If ``sniffio`` is not installed, or + in testing situations, this function allows the backend to be set + explicitly. + """ + global _default_backend + _default_backend = get_backend(name) + return _default_backend diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/asyncquery.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/asyncquery.py new file mode 100644 index 0000000..89c2622 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/asyncquery.py @@ -0,0 +1,434 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Talk to a DNS server.""" + +import socket +import struct +import time + +import dns.asyncbackend +import dns.exception +import dns.inet +import dns.name +import dns.message +import dns.rcode +import dns.rdataclass +import dns.rdatatype + +from dns.query import _compute_times, _matches_destination, BadResponse, ssl, \ + UDPMode + + +# for brevity +_lltuple = dns.inet.low_level_address_tuple + + +def _source_tuple(af, address, port): + # Make a high level source tuple, or return None if address and port + # are both None + if address or port: + if address is None: + if af == socket.AF_INET: + address = '0.0.0.0' + elif af == socket.AF_INET6: + address = '::' + else: + raise NotImplementedError(f'unknown address family {af}') + return (address, port) + else: + return None + + +def _timeout(expiration, now=None): + if expiration: + if not now: + now = time.time() + return max(expiration - now, 0) + else: + return None + + +async def send_udp(sock, what, destination, expiration=None): + """Send a DNS message to the specified UDP socket. + + *sock*, a ``dns.asyncbackend.DatagramSocket``. + + *what*, a ``bytes`` or ``dns.message.Message``, the message to send. + + *destination*, a destination tuple appropriate for the address family + of the socket, specifying where to send the query. + + *expiration*, a ``float`` or ``None``, the absolute time at which + a timeout exception should be raised. If ``None``, no timeout will + occur. + + Returns an ``(int, float)`` tuple of bytes sent and the sent time. + """ + + if isinstance(what, dns.message.Message): + what = what.to_wire() + sent_time = time.time() + n = await sock.sendto(what, destination, _timeout(expiration, sent_time)) + return (n, sent_time) + + +async def receive_udp(sock, destination=None, expiration=None, + ignore_unexpected=False, one_rr_per_rrset=False, + keyring=None, request_mac=b'', ignore_trailing=False, + raise_on_truncation=False): + """Read a DNS message from a UDP socket. + + *sock*, a ``dns.asyncbackend.DatagramSocket``. + + See :py:func:`dns.query.receive_udp()` for the documentation of the other + parameters, exceptions, and return type of this method. + """ + + wire = b'' + while 1: + (wire, from_address) = await sock.recvfrom(65535, _timeout(expiration)) + if _matches_destination(sock.family, from_address, destination, + ignore_unexpected): + break + received_time = time.time() + r = dns.message.from_wire(wire, keyring=keyring, request_mac=request_mac, + one_rr_per_rrset=one_rr_per_rrset, + ignore_trailing=ignore_trailing, + raise_on_truncation=raise_on_truncation) + return (r, received_time, from_address) + +async def udp(q, where, timeout=None, port=53, source=None, source_port=0, + ignore_unexpected=False, one_rr_per_rrset=False, + ignore_trailing=False, raise_on_truncation=False, sock=None, + backend=None): + """Return the response obtained after sending a query via UDP. + + *sock*, a ``dns.asyncbackend.DatagramSocket``, or ``None``, + the socket to use for the query. If ``None``, the default, a + socket is created. Note that if a socket is provided, the + *source*, *source_port*, and *backend* are ignored. + + *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``, + the default, then dnspython will use the default backend. + + See :py:func:`dns.query.udp()` for the documentation of the other + parameters, exceptions, and return type of this method. + """ + wire = q.to_wire() + (begin_time, expiration) = _compute_times(timeout) + s = None + # After 3.6 is no longer supported, this can use an AsyncExitStack. + try: + af = dns.inet.af_for_address(where) + destination = _lltuple((where, port), af) + if sock: + s = sock + else: + if not backend: + backend = dns.asyncbackend.get_default_backend() + stuple = _source_tuple(af, source, source_port) + s = await backend.make_socket(af, socket.SOCK_DGRAM, 0, stuple) + await send_udp(s, wire, destination, expiration) + (r, received_time, _) = await receive_udp(s, destination, expiration, + ignore_unexpected, + one_rr_per_rrset, + q.keyring, q.mac, + ignore_trailing, + raise_on_truncation) + r.time = received_time - begin_time + if not q.is_response(r): + raise BadResponse + return r + finally: + if not sock and s: + await s.close() + +async def udp_with_fallback(q, where, timeout=None, port=53, source=None, + source_port=0, ignore_unexpected=False, + one_rr_per_rrset=False, ignore_trailing=False, + udp_sock=None, tcp_sock=None, backend=None): + """Return the response to the query, trying UDP first and falling back + to TCP if UDP results in a truncated response. + + *udp_sock*, a ``dns.asyncbackend.DatagramSocket``, or ``None``, + the socket to use for the UDP query. If ``None``, the default, a + socket is created. Note that if a socket is provided the *source*, + *source_port*, and *backend* are ignored for the UDP query. + + *tcp_sock*, a ``dns.asyncbackend.StreamSocket``, or ``None``, the + socket to use for the TCP query. If ``None``, the default, a + socket is created. Note that if a socket is provided *where*, + *source*, *source_port*, and *backend* are ignored for the TCP query. + + *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``, + the default, then dnspython will use the default backend. + + See :py:func:`dns.query.udp_with_fallback()` for the documentation + of the other parameters, exceptions, and return type of this + method. + """ + try: + response = await udp(q, where, timeout, port, source, source_port, + ignore_unexpected, one_rr_per_rrset, + ignore_trailing, True, udp_sock, backend) + return (response, False) + except dns.message.Truncated: + response = await tcp(q, where, timeout, port, source, source_port, + one_rr_per_rrset, ignore_trailing, tcp_sock, + backend) + return (response, True) + + +async def send_tcp(sock, what, expiration=None): + """Send a DNS message to the specified TCP socket. + + *sock*, a ``dns.asyncbackend.StreamSocket``. + + See :py:func:`dns.query.send_tcp()` for the documentation of the other + parameters, exceptions, and return type of this method. + """ + + if isinstance(what, dns.message.Message): + what = what.to_wire() + l = len(what) + # copying the wire into tcpmsg is inefficient, but lets us + # avoid writev() or doing a short write that would get pushed + # onto the net + tcpmsg = struct.pack("!H", l) + what + sent_time = time.time() + await sock.sendall(tcpmsg, _timeout(expiration, sent_time)) + return (len(tcpmsg), sent_time) + + +async def _read_exactly(sock, count, expiration): + """Read the specified number of bytes from stream. Keep trying until we + either get the desired amount, or we hit EOF. + """ + s = b'' + while count > 0: + n = await sock.recv(count, _timeout(expiration)) + if n == b'': + raise EOFError + count = count - len(n) + s = s + n + return s + + +async def receive_tcp(sock, expiration=None, one_rr_per_rrset=False, + keyring=None, request_mac=b'', ignore_trailing=False): + """Read a DNS message from a TCP socket. + + *sock*, a ``dns.asyncbackend.StreamSocket``. + + See :py:func:`dns.query.receive_tcp()` for the documentation of the other + parameters, exceptions, and return type of this method. + """ + + ldata = await _read_exactly(sock, 2, expiration) + (l,) = struct.unpack("!H", ldata) + wire = await _read_exactly(sock, l, expiration) + received_time = time.time() + r = dns.message.from_wire(wire, keyring=keyring, request_mac=request_mac, + one_rr_per_rrset=one_rr_per_rrset, + ignore_trailing=ignore_trailing) + return (r, received_time) + + +async def tcp(q, where, timeout=None, port=53, source=None, source_port=0, + one_rr_per_rrset=False, ignore_trailing=False, sock=None, + backend=None): + """Return the response obtained after sending a query via TCP. + + *sock*, a ``dns.asyncbacket.StreamSocket``, or ``None``, the + socket to use for the query. If ``None``, the default, a socket + is created. Note that if a socket is provided + *where*, *port*, *source*, *source_port*, and *backend* are ignored. + + *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``, + the default, then dnspython will use the default backend. + + See :py:func:`dns.query.tcp()` for the documentation of the other + parameters, exceptions, and return type of this method. + """ + + wire = q.to_wire() + (begin_time, expiration) = _compute_times(timeout) + s = None + # After 3.6 is no longer supported, this can use an AsyncExitStack. + try: + if sock: + # Verify that the socket is connected, as if it's not connected, + # it's not writable, and the polling in send_tcp() will time out or + # hang forever. + await sock.getpeername() + s = sock + else: + # These are simple (address, port) pairs, not + # family-dependent tuples you pass to lowlevel socket + # code. + af = dns.inet.af_for_address(where) + stuple = _source_tuple(af, source, source_port) + dtuple = (where, port) + if not backend: + backend = dns.asyncbackend.get_default_backend() + s = await backend.make_socket(af, socket.SOCK_STREAM, 0, stuple, + dtuple, timeout) + await send_tcp(s, wire, expiration) + (r, received_time) = await receive_tcp(s, expiration, one_rr_per_rrset, + q.keyring, q.mac, + ignore_trailing) + r.time = received_time - begin_time + if not q.is_response(r): + raise BadResponse + return r + finally: + if not sock and s: + await s.close() + +async def tls(q, where, timeout=None, port=853, source=None, source_port=0, + one_rr_per_rrset=False, ignore_trailing=False, sock=None, + backend=None, ssl_context=None, server_hostname=None): + """Return the response obtained after sending a query via TLS. + + *sock*, an ``asyncbackend.StreamSocket``, or ``None``, the socket + to use for the query. If ``None``, the default, a socket is + created. Note that if a socket is provided, it must be a + connected SSL stream socket, and *where*, *port*, + *source*, *source_port*, *backend*, *ssl_context*, and *server_hostname* + are ignored. + + *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``, + the default, then dnspython will use the default backend. + + See :py:func:`dns.query.tls()` for the documentation of the other + parameters, exceptions, and return type of this method. + """ + # After 3.6 is no longer supported, this can use an AsyncExitStack. + (begin_time, expiration) = _compute_times(timeout) + if not sock: + if ssl_context is None: + ssl_context = ssl.create_default_context() + if server_hostname is None: + ssl_context.check_hostname = False + else: + ssl_context = None + server_hostname = None + af = dns.inet.af_for_address(where) + stuple = _source_tuple(af, source, source_port) + dtuple = (where, port) + if not backend: + backend = dns.asyncbackend.get_default_backend() + s = await backend.make_socket(af, socket.SOCK_STREAM, 0, stuple, + dtuple, timeout, ssl_context, + server_hostname) + else: + s = sock + try: + timeout = _timeout(expiration) + response = await tcp(q, where, timeout, port, source, source_port, + one_rr_per_rrset, ignore_trailing, s, backend) + end_time = time.time() + response.time = end_time - begin_time + return response + finally: + if not sock and s: + await s.close() + +async def inbound_xfr(where, txn_manager, query=None, + port=53, timeout=None, lifetime=None, source=None, + source_port=0, udp_mode=UDPMode.NEVER, + backend=None): + """Conduct an inbound transfer and apply it via a transaction from the + txn_manager. + + *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``, + the default, then dnspython will use the default backend. + + See :py:func:`dns.query.inbound_xfr()` for the documentation of + the other parameters, exceptions, and return type of this method. + """ + if query is None: + (query, serial) = dns.xfr.make_query(txn_manager) + rdtype = query.question[0].rdtype + is_ixfr = rdtype == dns.rdatatype.IXFR + origin = txn_manager.from_wire_origin() + wire = query.to_wire() + af = dns.inet.af_for_address(where) + stuple = _source_tuple(af, source, source_port) + dtuple = (where, port) + (_, expiration) = _compute_times(lifetime) + retry = True + while retry: + retry = False + if is_ixfr and udp_mode != UDPMode.NEVER: + sock_type = socket.SOCK_DGRAM + is_udp = True + else: + sock_type = socket.SOCK_STREAM + is_udp = False + if not backend: + backend = dns.asyncbackend.get_default_backend() + s = await backend.make_socket(af, sock_type, 0, stuple, dtuple, + _timeout(expiration)) + async with s: + if is_udp: + await s.sendto(wire, dtuple, _timeout(expiration)) + else: + tcpmsg = struct.pack("!H", len(wire)) + wire + await s.sendall(tcpmsg, expiration) + with dns.xfr.Inbound(txn_manager, rdtype, serial, + is_udp) as inbound: + done = False + tsig_ctx = None + while not done: + (_, mexpiration) = _compute_times(timeout) + if mexpiration is None or \ + (expiration is not None and mexpiration > expiration): + mexpiration = expiration + if is_udp: + destination = _lltuple((where, port), af) + while True: + timeout = _timeout(mexpiration) + (rwire, from_address) = await s.recvfrom(65535, + timeout) + if _matches_destination(af, from_address, + destination, True): + break + else: + ldata = await _read_exactly(s, 2, mexpiration) + (l,) = struct.unpack("!H", ldata) + rwire = await _read_exactly(s, l, mexpiration) + is_ixfr = (rdtype == dns.rdatatype.IXFR) + r = dns.message.from_wire(rwire, keyring=query.keyring, + request_mac=query.mac, xfr=True, + origin=origin, tsig_ctx=tsig_ctx, + multi=(not is_udp), + one_rr_per_rrset=is_ixfr) + try: + done = inbound.process_message(r) + except dns.xfr.UseTCP: + assert is_udp # should not happen if we used TCP! + if udp_mode == UDPMode.ONLY: + raise + done = True + retry = True + udp_mode = UDPMode.NEVER + continue + tsig_ctx = r.tsig_ctx + if not retry and query.keyring and not r.had_tsig: + raise dns.exception.FormError("missing TSIG") diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/asyncresolver.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/asyncresolver.py new file mode 100644 index 0000000..a60cf77 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/asyncresolver.py @@ -0,0 +1,230 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Asynchronous DNS stub resolver.""" + +import time + +import dns.asyncbackend +import dns.asyncquery +import dns.exception +import dns.query +import dns.resolver + +# import some resolver symbols for brevity +from dns.resolver import NXDOMAIN, NoAnswer, NotAbsolute, NoRootSOA + + +# for indentation purposes below +_udp = dns.asyncquery.udp +_tcp = dns.asyncquery.tcp + + +class Resolver(dns.resolver.BaseResolver): + """Asynchronous DNS stub resolver.""" + + async def resolve(self, qname, rdtype=dns.rdatatype.A, + rdclass=dns.rdataclass.IN, + tcp=False, source=None, raise_on_no_answer=True, + source_port=0, lifetime=None, search=None, + backend=None): + """Query nameservers asynchronously to find the answer to the question. + + *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``, + the default, then dnspython will use the default backend. + + See :py:func:`dns.resolver.Resolver.resolve()` for the + documentation of the other parameters, exceptions, and return + type of this method. + """ + + resolution = dns.resolver._Resolution(self, qname, rdtype, rdclass, tcp, + raise_on_no_answer, search) + if not backend: + backend = dns.asyncbackend.get_default_backend() + start = time.time() + while True: + (request, answer) = resolution.next_request() + # Note we need to say "if answer is not None" and not just + # "if answer" because answer implements __len__, and python + # will call that. We want to return if we have an answer + # object, including in cases where its length is 0. + if answer is not None: + # cache hit! + return answer + done = False + while not done: + (nameserver, port, tcp, backoff) = resolution.next_nameserver() + if backoff: + await backend.sleep(backoff) + timeout = self._compute_timeout(start, lifetime) + try: + if dns.inet.is_address(nameserver): + if tcp: + response = await _tcp(request, nameserver, + timeout, port, + source, source_port, + backend=backend) + else: + response = await _udp(request, nameserver, + timeout, port, + source, source_port, + raise_on_truncation=True, + backend=backend) + else: + # We don't do DoH yet. + raise NotImplementedError + except Exception as ex: + (_, done) = resolution.query_result(None, ex) + continue + (answer, done) = resolution.query_result(response, None) + # Note we need to say "if answer is not None" and not just + # "if answer" because answer implements __len__, and python + # will call that. We want to return if we have an answer + # object, including in cases where its length is 0. + if answer is not None: + return answer + + async def resolve_address(self, ipaddr, *args, **kwargs): + """Use an asynchronous resolver to run a reverse query for PTR + records. + + This utilizes the resolve() method to perform a PTR lookup on the + specified IP address. + + *ipaddr*, a ``str``, the IPv4 or IPv6 address you want to get + the PTR record for. + + All other arguments that can be passed to the resolve() function + except for rdtype and rdclass are also supported by this + function. + + """ + + return await self.resolve(dns.reversename.from_address(ipaddr), + rdtype=dns.rdatatype.PTR, + rdclass=dns.rdataclass.IN, + *args, **kwargs) + + # pylint: disable=redefined-outer-name + + async def canonical_name(self, name): + """Determine the canonical name of *name*. + + The canonical name is the name the resolver uses for queries + after all CNAME and DNAME renamings have been applied. + + *name*, a ``dns.name.Name`` or ``str``, the query name. + + This method can raise any exception that ``resolve()`` can + raise, other than ``dns.resolver.NoAnswer`` and + ``dns.resolver.NXDOMAIN``. + + Returns a ``dns.name.Name``. + """ + try: + answer = await self.resolve(name, raise_on_no_answer=False) + canonical_name = answer.canonical_name + except dns.resolver.NXDOMAIN as e: + canonical_name = e.canonical_name + return canonical_name + + +default_resolver = None + + +def get_default_resolver(): + """Get the default asynchronous resolver, initializing it if necessary.""" + if default_resolver is None: + reset_default_resolver() + return default_resolver + + +def reset_default_resolver(): + """Re-initialize default asynchronous resolver. + + Note that the resolver configuration (i.e. /etc/resolv.conf on UNIX + systems) will be re-read immediately. + """ + + global default_resolver + default_resolver = Resolver() + + +async def resolve(qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN, + tcp=False, source=None, raise_on_no_answer=True, + source_port=0, lifetime=None, search=None, backend=None): + """Query nameservers asynchronously to find the answer to the question. + + This is a convenience function that uses the default resolver + object to make the query. + + See :py:func:`dns.asyncresolver.Resolver.resolve` for more + information on the parameters. + """ + + return await get_default_resolver().resolve(qname, rdtype, rdclass, tcp, + source, raise_on_no_answer, + source_port, lifetime, search, + backend) + + +async def resolve_address(ipaddr, *args, **kwargs): + """Use a resolver to run a reverse query for PTR records. + + See :py:func:`dns.asyncresolver.Resolver.resolve_address` for more + information on the parameters. + """ + + return await get_default_resolver().resolve_address(ipaddr, *args, **kwargs) + +async def canonical_name(name): + """Determine the canonical name of *name*. + + See :py:func:`dns.resolver.Resolver.canonical_name` for more + information on the parameters and possible exceptions. + """ + + return await get_default_resolver().canonical_name(name) + +async def zone_for_name(name, rdclass=dns.rdataclass.IN, tcp=False, + resolver=None, backend=None): + """Find the name of the zone which contains the specified name. + + See :py:func:`dns.resolver.Resolver.zone_for_name` for more + information on the parameters and possible exceptions. + """ + + if isinstance(name, str): + name = dns.name.from_text(name, dns.name.root) + if resolver is None: + resolver = get_default_resolver() + if not name.is_absolute(): + raise NotAbsolute(name) + while True: + try: + answer = await resolver.resolve(name, dns.rdatatype.SOA, rdclass, + tcp, backend=backend) + if answer.rrset.name == name: + return name + # otherwise we were CNAMEd or DNAMEd and need to look higher + except (NXDOMAIN, NoAnswer): + pass + try: + name = name.parent() + except dns.name.NoParent: # pragma: no cover + raise NoRootSOA diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/dnssec.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/dnssec.py new file mode 100644 index 0000000..095fabd --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/dnssec.py @@ -0,0 +1,605 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Common DNSSEC-related functions and constants.""" + +import hashlib +import struct +import time +import base64 + +import dns.enum +import dns.exception +import dns.name +import dns.node +import dns.rdataset +import dns.rdata +import dns.rdatatype +import dns.rdataclass + + +class UnsupportedAlgorithm(dns.exception.DNSException): + """The DNSSEC algorithm is not supported.""" + + +class ValidationFailure(dns.exception.DNSException): + """The DNSSEC signature is invalid.""" + + +class Algorithm(dns.enum.IntEnum): + RSAMD5 = 1 + DH = 2 + DSA = 3 + ECC = 4 + RSASHA1 = 5 + DSANSEC3SHA1 = 6 + RSASHA1NSEC3SHA1 = 7 + RSASHA256 = 8 + RSASHA512 = 10 + ECCGOST = 12 + ECDSAP256SHA256 = 13 + ECDSAP384SHA384 = 14 + ED25519 = 15 + ED448 = 16 + INDIRECT = 252 + PRIVATEDNS = 253 + PRIVATEOID = 254 + + @classmethod + def _maximum(cls): + return 255 + + +def algorithm_from_text(text): + """Convert text into a DNSSEC algorithm value. + + *text*, a ``str``, the text to convert to into an algorithm value. + + Returns an ``int``. + """ + + return Algorithm.from_text(text) + + +def algorithm_to_text(value): + """Convert a DNSSEC algorithm value to text + + *value*, an ``int`` a DNSSEC algorithm. + + Returns a ``str``, the name of a DNSSEC algorithm. + """ + + return Algorithm.to_text(value) + + +def key_id(key): + """Return the key id (a 16-bit number) for the specified key. + + *key*, a ``dns.rdtypes.ANY.DNSKEY.DNSKEY`` + + Returns an ``int`` between 0 and 65535 + """ + + rdata = key.to_wire() + if key.algorithm == Algorithm.RSAMD5: + return (rdata[-3] << 8) + rdata[-2] + else: + total = 0 + for i in range(len(rdata) // 2): + total += (rdata[2 * i] << 8) + \ + rdata[2 * i + 1] + if len(rdata) % 2 != 0: + total += rdata[len(rdata) - 1] << 8 + total += ((total >> 16) & 0xffff) + return total & 0xffff + +class DSDigest(dns.enum.IntEnum): + """DNSSEC Delgation Signer Digest Algorithm""" + + SHA1 = 1 + SHA256 = 2 + SHA384 = 4 + + @classmethod + def _maximum(cls): + return 255 + + +def make_ds(name, key, algorithm, origin=None): + """Create a DS record for a DNSSEC key. + + *name*, a ``dns.name.Name`` or ``str``, the owner name of the DS record. + + *key*, a ``dns.rdtypes.ANY.DNSKEY.DNSKEY``, the key the DS is about. + + *algorithm*, a ``str`` or ``int`` specifying the hash algorithm. + The currently supported hashes are "SHA1", "SHA256", and "SHA384". Case + does not matter for these strings. + + *origin*, a ``dns.name.Name`` or ``None``. If `key` is a relative name, + then it will be made absolute using the specified origin. + + Raises ``UnsupportedAlgorithm`` if the algorithm is unknown. + + Returns a ``dns.rdtypes.ANY.DS.DS`` + """ + + try: + if isinstance(algorithm, str): + algorithm = DSDigest[algorithm.upper()] + except Exception: + raise UnsupportedAlgorithm('unsupported algorithm "%s"' % algorithm) + + if algorithm == DSDigest.SHA1: + dshash = hashlib.sha1() + elif algorithm == DSDigest.SHA256: + dshash = hashlib.sha256() + elif algorithm == DSDigest.SHA384: + dshash = hashlib.sha384() + else: + raise UnsupportedAlgorithm('unsupported algorithm "%s"' % algorithm) + + if isinstance(name, str): + name = dns.name.from_text(name, origin) + dshash.update(name.canonicalize().to_wire()) + dshash.update(key.to_wire(origin=origin)) + digest = dshash.digest() + + dsrdata = struct.pack("!HBB", key_id(key), key.algorithm, algorithm) + \ + digest + return dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.DS, dsrdata, 0, + len(dsrdata)) + + +def _find_candidate_keys(keys, rrsig): + candidate_keys = [] + value = keys.get(rrsig.signer) + if value is None: + return None + if isinstance(value, dns.node.Node): + try: + rdataset = value.find_rdataset(dns.rdataclass.IN, + dns.rdatatype.DNSKEY) + except KeyError: + return None + else: + rdataset = value + for rdata in rdataset: + if rdata.algorithm == rrsig.algorithm and \ + key_id(rdata) == rrsig.key_tag: + candidate_keys.append(rdata) + return candidate_keys + + +def _is_rsa(algorithm): + return algorithm in (Algorithm.RSAMD5, Algorithm.RSASHA1, + Algorithm.RSASHA1NSEC3SHA1, Algorithm.RSASHA256, + Algorithm.RSASHA512) + + +def _is_dsa(algorithm): + return algorithm in (Algorithm.DSA, Algorithm.DSANSEC3SHA1) + + +def _is_ecdsa(algorithm): + return algorithm in (Algorithm.ECDSAP256SHA256, Algorithm.ECDSAP384SHA384) + + +def _is_eddsa(algorithm): + return algorithm in (Algorithm.ED25519, Algorithm.ED448) + + +def _is_gost(algorithm): + return algorithm == Algorithm.ECCGOST + + +def _is_md5(algorithm): + return algorithm == Algorithm.RSAMD5 + + +def _is_sha1(algorithm): + return algorithm in (Algorithm.DSA, Algorithm.RSASHA1, + Algorithm.DSANSEC3SHA1, Algorithm.RSASHA1NSEC3SHA1) + + +def _is_sha256(algorithm): + return algorithm in (Algorithm.RSASHA256, Algorithm.ECDSAP256SHA256) + + +def _is_sha384(algorithm): + return algorithm == Algorithm.ECDSAP384SHA384 + + +def _is_sha512(algorithm): + return algorithm == Algorithm.RSASHA512 + + +def _make_hash(algorithm): + if _is_md5(algorithm): + return hashes.MD5() + if _is_sha1(algorithm): + return hashes.SHA1() + if _is_sha256(algorithm): + return hashes.SHA256() + if _is_sha384(algorithm): + return hashes.SHA384() + if _is_sha512(algorithm): + return hashes.SHA512() + if algorithm == Algorithm.ED25519: + return hashes.SHA512() + if algorithm == Algorithm.ED448: + return hashes.SHAKE256(114) + + raise ValidationFailure('unknown hash for algorithm %u' % algorithm) + + +def _bytes_to_long(b): + return int.from_bytes(b, 'big') + + +def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): + """Validate an RRset against a single signature rdata, throwing an + exception if validation is not successful. + + *rrset*, the RRset to validate. This can be a + ``dns.rrset.RRset`` or a (``dns.name.Name``, ``dns.rdataset.Rdataset``) + tuple. + + *rrsig*, a ``dns.rdata.Rdata``, the signature to validate. + + *keys*, the key dictionary, used to find the DNSKEY associated + with a given name. The dictionary is keyed by a + ``dns.name.Name``, and has ``dns.node.Node`` or + ``dns.rdataset.Rdataset`` values. + + *origin*, a ``dns.name.Name`` or ``None``, the origin to use for relative + names. + + *now*, an ``int`` or ``None``, the time, in seconds since the epoch, to + use as the current time when validating. If ``None``, the actual current + time is used. + + Raises ``ValidationFailure`` if the signature is expired, not yet valid, + the public key is invalid, the algorithm is unknown, the verification + fails, etc. + + Raises ``UnsupportedAlgorithm`` if the algorithm is recognized by + dnspython but not implemented. + """ + + if isinstance(origin, str): + origin = dns.name.from_text(origin, dns.name.root) + + candidate_keys = _find_candidate_keys(keys, rrsig) + if candidate_keys is None: + raise ValidationFailure('unknown key') + + for candidate_key in candidate_keys: + # For convenience, allow the rrset to be specified as a (name, + # rdataset) tuple as well as a proper rrset + if isinstance(rrset, tuple): + rrname = rrset[0] + rdataset = rrset[1] + else: + rrname = rrset.name + rdataset = rrset + + if now is None: + now = time.time() + if rrsig.expiration < now: + raise ValidationFailure('expired') + if rrsig.inception > now: + raise ValidationFailure('not yet valid') + + if _is_rsa(rrsig.algorithm): + keyptr = candidate_key.key + (bytes_,) = struct.unpack('!B', keyptr[0:1]) + keyptr = keyptr[1:] + if bytes_ == 0: + (bytes_,) = struct.unpack('!H', keyptr[0:2]) + keyptr = keyptr[2:] + rsa_e = keyptr[0:bytes_] + rsa_n = keyptr[bytes_:] + try: + public_key = rsa.RSAPublicNumbers( + _bytes_to_long(rsa_e), + _bytes_to_long(rsa_n)).public_key(default_backend()) + except ValueError: + raise ValidationFailure('invalid public key') + sig = rrsig.signature + elif _is_dsa(rrsig.algorithm): + keyptr = candidate_key.key + (t,) = struct.unpack('!B', keyptr[0:1]) + keyptr = keyptr[1:] + octets = 64 + t * 8 + dsa_q = keyptr[0:20] + keyptr = keyptr[20:] + dsa_p = keyptr[0:octets] + keyptr = keyptr[octets:] + dsa_g = keyptr[0:octets] + keyptr = keyptr[octets:] + dsa_y = keyptr[0:octets] + try: + public_key = dsa.DSAPublicNumbers( + _bytes_to_long(dsa_y), + dsa.DSAParameterNumbers( + _bytes_to_long(dsa_p), + _bytes_to_long(dsa_q), + _bytes_to_long(dsa_g))).public_key(default_backend()) + except ValueError: + raise ValidationFailure('invalid public key') + sig_r = rrsig.signature[1:21] + sig_s = rrsig.signature[21:] + sig = utils.encode_dss_signature(_bytes_to_long(sig_r), + _bytes_to_long(sig_s)) + elif _is_ecdsa(rrsig.algorithm): + keyptr = candidate_key.key + if rrsig.algorithm == Algorithm.ECDSAP256SHA256: + curve = ec.SECP256R1() + octets = 32 + else: + curve = ec.SECP384R1() + octets = 48 + ecdsa_x = keyptr[0:octets] + ecdsa_y = keyptr[octets:octets * 2] + try: + public_key = ec.EllipticCurvePublicNumbers( + curve=curve, + x=_bytes_to_long(ecdsa_x), + y=_bytes_to_long(ecdsa_y)).public_key(default_backend()) + except ValueError: + raise ValidationFailure('invalid public key') + sig_r = rrsig.signature[0:octets] + sig_s = rrsig.signature[octets:] + sig = utils.encode_dss_signature(_bytes_to_long(sig_r), + _bytes_to_long(sig_s)) + + elif _is_eddsa(rrsig.algorithm): + keyptr = candidate_key.key + if rrsig.algorithm == Algorithm.ED25519: + loader = ed25519.Ed25519PublicKey + else: + loader = ed448.Ed448PublicKey + try: + public_key = loader.from_public_bytes(keyptr) + except ValueError: + raise ValidationFailure('invalid public key') + sig = rrsig.signature + elif _is_gost(rrsig.algorithm): + raise UnsupportedAlgorithm( + 'algorithm "%s" not supported by dnspython' % + algorithm_to_text(rrsig.algorithm)) + else: + raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm) + + data = b'' + data += rrsig.to_wire(origin=origin)[:18] + data += rrsig.signer.to_digestable(origin) + + # Derelativize the name before considering labels. + rrname = rrname.derelativize(origin) + + if len(rrname) - 1 < rrsig.labels: + raise ValidationFailure('owner name longer than RRSIG labels') + elif rrsig.labels < len(rrname) - 1: + suffix = rrname.split(rrsig.labels + 1)[1] + rrname = dns.name.from_text('*', suffix) + rrnamebuf = rrname.to_digestable() + rrfixed = struct.pack('!HHI', rdataset.rdtype, rdataset.rdclass, + rrsig.original_ttl) + rrlist = sorted(rdataset) + for rr in rrlist: + data += rrnamebuf + data += rrfixed + rrdata = rr.to_digestable(origin) + rrlen = struct.pack('!H', len(rrdata)) + data += rrlen + data += rrdata + + chosen_hash = _make_hash(rrsig.algorithm) + try: + if _is_rsa(rrsig.algorithm): + public_key.verify(sig, data, padding.PKCS1v15(), chosen_hash) + elif _is_dsa(rrsig.algorithm): + public_key.verify(sig, data, chosen_hash) + elif _is_ecdsa(rrsig.algorithm): + public_key.verify(sig, data, ec.ECDSA(chosen_hash)) + elif _is_eddsa(rrsig.algorithm): + public_key.verify(sig, data) + else: + # Raise here for code clarity; this won't actually ever happen + # since if the algorithm is really unknown we'd already have + # raised an exception above + raise ValidationFailure('unknown algorithm %u' % + rrsig.algorithm) # pragma: no cover + # If we got here, we successfully verified so we can return + # without error + return + except InvalidSignature: + # this happens on an individual validation failure + continue + # nothing verified -- raise failure: + raise ValidationFailure('verify failure') + + +def _validate(rrset, rrsigset, keys, origin=None, now=None): + """Validate an RRset against a signature RRset, throwing an exception + if none of the signatures validate. + + *rrset*, the RRset to validate. This can be a + ``dns.rrset.RRset`` or a (``dns.name.Name``, ``dns.rdataset.Rdataset``) + tuple. + + *rrsigset*, the signature RRset. This can be a + ``dns.rrset.RRset`` or a (``dns.name.Name``, ``dns.rdataset.Rdataset``) + tuple. + + *keys*, the key dictionary, used to find the DNSKEY associated + with a given name. The dictionary is keyed by a + ``dns.name.Name``, and has ``dns.node.Node`` or + ``dns.rdataset.Rdataset`` values. + + *origin*, a ``dns.name.Name``, the origin to use for relative names; + defaults to None. + + *now*, an ``int`` or ``None``, the time, in seconds since the epoch, to + use as the current time when validating. If ``None``, the actual current + time is used. + + Raises ``ValidationFailure`` if the signature is expired, not yet valid, + the public key is invalid, the algorithm is unknown, the verification + fails, etc. + """ + + if isinstance(origin, str): + origin = dns.name.from_text(origin, dns.name.root) + + if isinstance(rrset, tuple): + rrname = rrset[0] + else: + rrname = rrset.name + + if isinstance(rrsigset, tuple): + rrsigname = rrsigset[0] + rrsigrdataset = rrsigset[1] + else: + rrsigname = rrsigset.name + rrsigrdataset = rrsigset + + rrname = rrname.choose_relativity(origin) + rrsigname = rrsigname.choose_relativity(origin) + if rrname != rrsigname: + raise ValidationFailure("owner names do not match") + + for rrsig in rrsigrdataset: + try: + _validate_rrsig(rrset, rrsig, keys, origin, now) + return + except (ValidationFailure, UnsupportedAlgorithm): + pass + raise ValidationFailure("no RRSIGs validated") + + +class NSEC3Hash(dns.enum.IntEnum): + """NSEC3 hash algorithm""" + + SHA1 = 1 + + @classmethod + def _maximum(cls): + return 255 + +def nsec3_hash(domain, salt, iterations, algorithm): + """ + Calculate the NSEC3 hash, according to + https://tools.ietf.org/html/rfc5155#section-5 + + *domain*, a ``dns.name.Name`` or ``str``, the name to hash. + + *salt*, a ``str``, ``bytes``, or ``None``, the hash salt. If a + string, it is decoded as a hex string. + + *iterations*, an ``int``, the number of iterations. + + *algorithm*, a ``str`` or ``int``, the hash algorithm. + The only defined algorithm is SHA1. + + Returns a ``str``, the encoded NSEC3 hash. + """ + + b32_conversion = str.maketrans( + "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", "0123456789ABCDEFGHIJKLMNOPQRSTUV" + ) + + try: + if isinstance(algorithm, str): + algorithm = NSEC3Hash[algorithm.upper()] + except Exception: + raise ValueError("Wrong hash algorithm (only SHA1 is supported)") + + if algorithm != NSEC3Hash.SHA1: + raise ValueError("Wrong hash algorithm (only SHA1 is supported)") + + salt_encoded = salt + if salt is None: + salt_encoded = b'' + elif isinstance(salt, str): + if len(salt) % 2 == 0: + salt_encoded = bytes.fromhex(salt) + else: + raise ValueError("Invalid salt length") + + if not isinstance(domain, dns.name.Name): + domain = dns.name.from_text(domain) + domain_encoded = domain.canonicalize().to_wire() + + digest = hashlib.sha1(domain_encoded + salt_encoded).digest() + for _ in range(iterations): + digest = hashlib.sha1(digest + salt_encoded).digest() + + output = base64.b32encode(digest).decode("utf-8") + output = output.translate(b32_conversion) + + return output + + +def _need_pyca(*args, **kwargs): + raise ImportError("DNSSEC validation requires " + + "python cryptography") # pragma: no cover + + +try: + from cryptography.exceptions import InvalidSignature + from cryptography.hazmat.backends import default_backend + from cryptography.hazmat.primitives import hashes + from cryptography.hazmat.primitives.asymmetric import padding + from cryptography.hazmat.primitives.asymmetric import utils + from cryptography.hazmat.primitives.asymmetric import dsa + from cryptography.hazmat.primitives.asymmetric import ec + from cryptography.hazmat.primitives.asymmetric import ed25519 + from cryptography.hazmat.primitives.asymmetric import ed448 + from cryptography.hazmat.primitives.asymmetric import rsa +except ImportError: # pragma: no cover + validate = _need_pyca + validate_rrsig = _need_pyca + _have_pyca = False +else: + validate = _validate # type: ignore + validate_rrsig = _validate_rrsig # type: ignore + _have_pyca = True + +### BEGIN generated Algorithm constants + +RSAMD5 = Algorithm.RSAMD5 +DH = Algorithm.DH +DSA = Algorithm.DSA +ECC = Algorithm.ECC +RSASHA1 = Algorithm.RSASHA1 +DSANSEC3SHA1 = Algorithm.DSANSEC3SHA1 +RSASHA1NSEC3SHA1 = Algorithm.RSASHA1NSEC3SHA1 +RSASHA256 = Algorithm.RSASHA256 +RSASHA512 = Algorithm.RSASHA512 +ECCGOST = Algorithm.ECCGOST +ECDSAP256SHA256 = Algorithm.ECDSAP256SHA256 +ECDSAP384SHA384 = Algorithm.ECDSAP384SHA384 +ED25519 = Algorithm.ED25519 +ED448 = Algorithm.ED448 +INDIRECT = Algorithm.INDIRECT +PRIVATEDNS = Algorithm.PRIVATEDNS +PRIVATEOID = Algorithm.PRIVATEOID + +### END generated Algorithm constants diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/e164.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/e164.py new file mode 100644 index 0000000..83731b2 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/e164.py @@ -0,0 +1,104 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS E.164 helpers.""" + +import dns.exception +import dns.name +import dns.resolver + +#: The public E.164 domain. +public_enum_domain = dns.name.from_text('e164.arpa.') + + +def from_e164(text, origin=public_enum_domain): + """Convert an E.164 number in textual form into a Name object whose + value is the ENUM domain name for that number. + + Non-digits in the text are ignored, i.e. "16505551212", + "+1.650.555.1212" and "1 (650) 555-1212" are all the same. + + *text*, a ``str``, is an E.164 number in textual form. + + *origin*, a ``dns.name.Name``, the domain in which the number + should be constructed. The default is ``e164.arpa.``. + + Returns a ``dns.name.Name``. + """ + + parts = [d for d in text if d.isdigit()] + parts.reverse() + return dns.name.from_text('.'.join(parts), origin=origin) + + +def to_e164(name, origin=public_enum_domain, want_plus_prefix=True): + """Convert an ENUM domain name into an E.164 number. + + Note that dnspython does not have any information about preferred + number formats within national numbering plans, so all numbers are + emitted as a simple string of digits, prefixed by a '+' (unless + *want_plus_prefix* is ``False``). + + *name* is a ``dns.name.Name``, the ENUM domain name. + + *origin* is a ``dns.name.Name``, a domain containing the ENUM + domain name. The name is relativized to this domain before being + converted to text. If ``None``, no relativization is done. + + *want_plus_prefix* is a ``bool``. If True, add a '+' to the beginning of + the returned number. + + Returns a ``str``. + + """ + if origin is not None: + name = name.relativize(origin) + dlabels = [d for d in name.labels if d.isdigit() and len(d) == 1] + if len(dlabels) != len(name.labels): + raise dns.exception.SyntaxError('non-digit labels in ENUM domain name') + dlabels.reverse() + text = b''.join(dlabels) + if want_plus_prefix: + text = b'+' + text + return text.decode() + + +def query(number, domains, resolver=None): + """Look for NAPTR RRs for the specified number in the specified domains. + + e.g. lookup('16505551212', ['e164.dnspython.org.', 'e164.arpa.']) + + *number*, a ``str`` is the number to look for. + + *domains* is an iterable containing ``dns.name.Name`` values. + + *resolver*, a ``dns.resolver.Resolver``, is the resolver to use. If + ``None``, the default resolver is used. + """ + + if resolver is None: + resolver = dns.resolver.get_default_resolver() + e_nx = dns.resolver.NXDOMAIN() + for domain in domains: + if isinstance(domain, str): + domain = dns.name.from_text(domain) + qname = dns.e164.from_e164(number, domain) + try: + return resolver.resolve(qname, 'NAPTR') + except dns.resolver.NXDOMAIN as e: + e_nx += e + raise e_nx diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/edns.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/edns.py new file mode 100644 index 0000000..237178f --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/edns.py @@ -0,0 +1,376 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2009-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""EDNS Options""" + +import math +import socket +import struct + +import dns.enum +import dns.inet +import dns.rdata + + +class OptionType(dns.enum.IntEnum): + #: NSID + NSID = 3 + #: DAU + DAU = 5 + #: DHU + DHU = 6 + #: N3U + N3U = 7 + #: ECS (client-subnet) + ECS = 8 + #: EXPIRE + EXPIRE = 9 + #: COOKIE + COOKIE = 10 + #: KEEPALIVE + KEEPALIVE = 11 + #: PADDING + PADDING = 12 + #: CHAIN + CHAIN = 13 + + @classmethod + def _maximum(cls): + return 65535 + + +class Option: + + """Base class for all EDNS option types.""" + + def __init__(self, otype): + """Initialize an option. + + *otype*, an ``int``, is the option type. + """ + self.otype = OptionType.make(otype) + + def to_wire(self, file=None): + """Convert an option to wire format. + + Returns a ``bytes`` or ``None``. + + """ + raise NotImplementedError # pragma: no cover + + @classmethod + def from_wire_parser(cls, otype, parser): + """Build an EDNS option object from wire format. + + *otype*, an ``int``, is the option type. + + *parser*, a ``dns.wire.Parser``, the parser, which should be + restructed to the option length. + + Returns a ``dns.edns.Option``. + """ + raise NotImplementedError # pragma: no cover + + def _cmp(self, other): + """Compare an EDNS option with another option of the same type. + + Returns < 0 if < *other*, 0 if == *other*, and > 0 if > *other*. + """ + wire = self.to_wire() + owire = other.to_wire() + if wire == owire: + return 0 + if wire > owire: + return 1 + return -1 + + def __eq__(self, other): + if not isinstance(other, Option): + return False + if self.otype != other.otype: + return False + return self._cmp(other) == 0 + + def __ne__(self, other): + if not isinstance(other, Option): + return True + if self.otype != other.otype: + return True + return self._cmp(other) != 0 + + def __lt__(self, other): + if not isinstance(other, Option) or \ + self.otype != other.otype: + return NotImplemented + return self._cmp(other) < 0 + + def __le__(self, other): + if not isinstance(other, Option) or \ + self.otype != other.otype: + return NotImplemented + return self._cmp(other) <= 0 + + def __ge__(self, other): + if not isinstance(other, Option) or \ + self.otype != other.otype: + return NotImplemented + return self._cmp(other) >= 0 + + def __gt__(self, other): + if not isinstance(other, Option) or \ + self.otype != other.otype: + return NotImplemented + return self._cmp(other) > 0 + + def __str__(self): + return self.to_text() + + +class GenericOption(Option): + + """Generic Option Class + + This class is used for EDNS option types for which we have no better + implementation. + """ + + def __init__(self, otype, data): + super().__init__(otype) + self.data = dns.rdata.Rdata._as_bytes(data, True) + + def to_wire(self, file=None): + if file: + file.write(self.data) + else: + return self.data + + def to_text(self): + return "Generic %d" % self.otype + + @classmethod + def from_wire_parser(cls, otype, parser): + return cls(otype, parser.get_remaining()) + + +class ECSOption(Option): + """EDNS Client Subnet (ECS, RFC7871)""" + + def __init__(self, address, srclen=None, scopelen=0): + """*address*, a ``str``, is the client address information. + + *srclen*, an ``int``, the source prefix length, which is the + leftmost number of bits of the address to be used for the + lookup. The default is 24 for IPv4 and 56 for IPv6. + + *scopelen*, an ``int``, the scope prefix length. This value + must be 0 in queries, and should be set in responses. + """ + + super().__init__(OptionType.ECS) + af = dns.inet.af_for_address(address) + + if af == socket.AF_INET6: + self.family = 2 + if srclen is None: + srclen = 56 + address = dns.rdata.Rdata._as_ipv6_address(address) + srclen = dns.rdata.Rdata._as_int(srclen, 0, 128) + scopelen = dns.rdata.Rdata._as_int(scopelen, 0, 128) + elif af == socket.AF_INET: + self.family = 1 + if srclen is None: + srclen = 24 + address = dns.rdata.Rdata._as_ipv4_address(address) + srclen = dns.rdata.Rdata._as_int(srclen, 0, 32) + scopelen = dns.rdata.Rdata._as_int(scopelen, 0, 32) + else: # pragma: no cover (this will never happen) + raise ValueError('Bad address family') + + self.address = address + self.srclen = srclen + self.scopelen = scopelen + + addrdata = dns.inet.inet_pton(af, address) + nbytes = int(math.ceil(srclen / 8.0)) + + # Truncate to srclen and pad to the end of the last octet needed + # See RFC section 6 + self.addrdata = addrdata[:nbytes] + nbits = srclen % 8 + if nbits != 0: + last = struct.pack('B', + ord(self.addrdata[-1:]) & (0xff << (8 - nbits))) + self.addrdata = self.addrdata[:-1] + last + + def to_text(self): + return "ECS {}/{} scope/{}".format(self.address, self.srclen, + self.scopelen) + + @staticmethod + def from_text(text): + """Convert a string into a `dns.edns.ECSOption` + + *text*, a `str`, the text form of the option. + + Returns a `dns.edns.ECSOption`. + + Examples: + + >>> import dns.edns + >>> + >>> # basic example + >>> dns.edns.ECSOption.from_text('1.2.3.4/24') + >>> + >>> # also understands scope + >>> dns.edns.ECSOption.from_text('1.2.3.4/24/32') + >>> + >>> # IPv6 + >>> dns.edns.ECSOption.from_text('2001:4b98::1/64/64') + >>> + >>> # it understands results from `dns.edns.ECSOption.to_text()` + >>> dns.edns.ECSOption.from_text('ECS 1.2.3.4/24/32') + """ + optional_prefix = 'ECS' + tokens = text.split() + ecs_text = None + if len(tokens) == 1: + ecs_text = tokens[0] + elif len(tokens) == 2: + if tokens[0] != optional_prefix: + raise ValueError('could not parse ECS from "{}"'.format(text)) + ecs_text = tokens[1] + else: + raise ValueError('could not parse ECS from "{}"'.format(text)) + n_slashes = ecs_text.count('/') + if n_slashes == 1: + address, srclen = ecs_text.split('/') + scope = 0 + elif n_slashes == 2: + address, srclen, scope = ecs_text.split('/') + else: + raise ValueError('could not parse ECS from "{}"'.format(text)) + try: + scope = int(scope) + except ValueError: + raise ValueError('invalid scope ' + + '"{}": scope must be an integer'.format(scope)) + try: + srclen = int(srclen) + except ValueError: + raise ValueError('invalid srclen ' + + '"{}": srclen must be an integer'.format(srclen)) + return ECSOption(address, srclen, scope) + + def to_wire(self, file=None): + value = (struct.pack('!HBB', self.family, self.srclen, self.scopelen) + + self.addrdata) + if file: + file.write(value) + else: + return value + + @classmethod + def from_wire_parser(cls, otype, parser): + family, src, scope = parser.get_struct('!HBB') + addrlen = int(math.ceil(src / 8.0)) + prefix = parser.get_bytes(addrlen) + if family == 1: + pad = 4 - addrlen + addr = dns.ipv4.inet_ntoa(prefix + b'\x00' * pad) + elif family == 2: + pad = 16 - addrlen + addr = dns.ipv6.inet_ntoa(prefix + b'\x00' * pad) + else: + raise ValueError('unsupported family') + + return cls(addr, src, scope) + + +_type_to_class = { + OptionType.ECS: ECSOption +} + +def get_option_class(otype): + """Return the class for the specified option type. + + The GenericOption class is used if a more specific class is not + known. + """ + + cls = _type_to_class.get(otype) + if cls is None: + cls = GenericOption + return cls + + +def option_from_wire_parser(otype, parser): + """Build an EDNS option object from wire format. + + *otype*, an ``int``, is the option type. + + *parser*, a ``dns.wire.Parser``, the parser, which should be + restricted to the option length. + + Returns an instance of a subclass of ``dns.edns.Option``. + """ + cls = get_option_class(otype) + otype = OptionType.make(otype) + return cls.from_wire_parser(otype, parser) + + +def option_from_wire(otype, wire, current, olen): + """Build an EDNS option object from wire format. + + *otype*, an ``int``, is the option type. + + *wire*, a ``bytes``, is the wire-format message. + + *current*, an ``int``, is the offset in *wire* of the beginning + of the rdata. + + *olen*, an ``int``, is the length of the wire-format option data + + Returns an instance of a subclass of ``dns.edns.Option``. + """ + parser = dns.wire.Parser(wire, current) + with parser.restrict_to(olen): + return option_from_wire_parser(otype, parser) + +def register_type(implementation, otype): + """Register the implementation of an option type. + + *implementation*, a ``class``, is a subclass of ``dns.edns.Option``. + + *otype*, an ``int``, is the option type. + """ + + _type_to_class[otype] = implementation + +### BEGIN generated OptionType constants + +NSID = OptionType.NSID +DAU = OptionType.DAU +DHU = OptionType.DHU +N3U = OptionType.N3U +ECS = OptionType.ECS +EXPIRE = OptionType.EXPIRE +COOKIE = OptionType.COOKIE +KEEPALIVE = OptionType.KEEPALIVE +PADDING = OptionType.PADDING +CHAIN = OptionType.CHAIN + +### END generated OptionType constants diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/entropy.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/entropy.py new file mode 100644 index 0000000..086bba7 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/entropy.py @@ -0,0 +1,129 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2009-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import os +import hashlib +import random +import time +try: + import threading as _threading +except ImportError: # pragma: no cover + import dummy_threading as _threading # type: ignore + + +class EntropyPool: + + # This is an entropy pool for Python implementations that do not + # have a working SystemRandom. I'm not sure there are any, but + # leaving this code doesn't hurt anything as the library code + # is used if present. + + def __init__(self, seed=None): + self.pool_index = 0 + self.digest = None + self.next_byte = 0 + self.lock = _threading.Lock() + self.hash = hashlib.sha1() + self.hash_len = 20 + self.pool = bytearray(b'\0' * self.hash_len) + if seed is not None: + self._stir(bytearray(seed)) + self.seeded = True + self.seed_pid = os.getpid() + else: + self.seeded = False + self.seed_pid = 0 + + def _stir(self, entropy): + for c in entropy: + if self.pool_index == self.hash_len: + self.pool_index = 0 + b = c & 0xff + self.pool[self.pool_index] ^= b + self.pool_index += 1 + + def stir(self, entropy): + with self.lock: + self._stir(entropy) + + def _maybe_seed(self): + if not self.seeded or self.seed_pid != os.getpid(): + try: + seed = os.urandom(16) + except Exception: # pragma: no cover + try: + with open('/dev/urandom', 'rb', 0) as r: + seed = r.read(16) + except Exception: + seed = str(time.time()) + self.seeded = True + self.seed_pid = os.getpid() + self.digest = None + seed = bytearray(seed) + self._stir(seed) + + def random_8(self): + with self.lock: + self._maybe_seed() + if self.digest is None or self.next_byte == self.hash_len: + self.hash.update(bytes(self.pool)) + self.digest = bytearray(self.hash.digest()) + self._stir(self.digest) + self.next_byte = 0 + value = self.digest[self.next_byte] + self.next_byte += 1 + return value + + def random_16(self): + return self.random_8() * 256 + self.random_8() + + def random_32(self): + return self.random_16() * 65536 + self.random_16() + + def random_between(self, first, last): + size = last - first + 1 + if size > 4294967296: + raise ValueError('too big') + if size > 65536: + rand = self.random_32 + max = 4294967295 + elif size > 256: + rand = self.random_16 + max = 65535 + else: + rand = self.random_8 + max = 255 + return first + size * rand() // (max + 1) + +pool = EntropyPool() + +try: + system_random = random.SystemRandom() +except Exception: # pragma: no cover + system_random = None + +def random_16(): + if system_random is not None: + return system_random.randrange(0, 65536) + else: + return pool.random_16() + +def between(first, last): + if system_random is not None: + return system_random.randrange(first, last + 1) + else: + return pool.random_between(first, last) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/enum.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/enum.py new file mode 100644 index 0000000..b822dd5 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/enum.py @@ -0,0 +1,90 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import enum + +class IntEnum(enum.IntEnum): + @classmethod + def _check_value(cls, value): + max = cls._maximum() + if value < 0 or value > max: + name = cls._short_name() + raise ValueError(f"{name} must be between >= 0 and <= {max}") + + @classmethod + def from_text(cls, text): + text = text.upper() + try: + return cls[text] + except KeyError: + pass + prefix = cls._prefix() + if text.startswith(prefix) and text[len(prefix):].isdigit(): + value = int(text[len(prefix):]) + cls._check_value(value) + try: + return cls(value) + except ValueError: + return value + raise cls._unknown_exception_class() + + @classmethod + def to_text(cls, value): + cls._check_value(value) + try: + return cls(value).name + except ValueError: + return f"{cls._prefix()}{value}" + + @classmethod + def make(cls, value): + """Convert text or a value into an enumerated type, if possible. + + *value*, the ``int`` or ``str`` to convert. + + Raises a class-specific exception if a ``str`` is provided that + cannot be converted. + + Raises ``ValueError`` if the value is out of range. + + Returns an enumeration from the calling class corresponding to the + value, if one is defined, or an ``int`` otherwise. + """ + + if isinstance(value, str): + return cls.from_text(value) + cls._check_value(value) + try: + return cls(value) + except ValueError: + return value + + @classmethod + def _maximum(cls): + raise NotImplementedError # pragma: no cover + + @classmethod + def _short_name(cls): + return cls.__name__.lower() + + @classmethod + def _prefix(cls): + return '' + + @classmethod + def _unknown_exception_class(cls): + return ValueError diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/exception.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/exception.py new file mode 100644 index 0000000..9392373 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/exception.py @@ -0,0 +1,142 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Common DNS Exceptions. + +Dnspython modules may also define their own exceptions, which will +always be subclasses of ``DNSException``. +""" + +class DNSException(Exception): + """Abstract base class shared by all dnspython exceptions. + + It supports two basic modes of operation: + + a) Old/compatible mode is used if ``__init__`` was called with + empty *kwargs*. In compatible mode all *args* are passed + to the standard Python Exception class as before and all *args* are + printed by the standard ``__str__`` implementation. Class variable + ``msg`` (or doc string if ``msg`` is ``None``) is returned from ``str()`` + if *args* is empty. + + b) New/parametrized mode is used if ``__init__`` was called with + non-empty *kwargs*. + In the new mode *args* must be empty and all kwargs must match + those set in class variable ``supp_kwargs``. All kwargs are stored inside + ``self.kwargs`` and used in a new ``__str__`` implementation to construct + a formatted message based on the ``fmt`` class variable, a ``string``. + + In the simplest case it is enough to override the ``supp_kwargs`` + and ``fmt`` class variables to get nice parametrized messages. + """ + + msg = None # non-parametrized message + supp_kwargs = set() # accepted parameters for _fmt_kwargs (sanity check) + fmt = None # message parametrized with results from _fmt_kwargs + + def __init__(self, *args, **kwargs): + self._check_params(*args, **kwargs) + if kwargs: + self.kwargs = self._check_kwargs(**kwargs) + self.msg = str(self) + else: + self.kwargs = dict() # defined but empty for old mode exceptions + if self.msg is None: + # doc string is better implicit message than empty string + self.msg = self.__doc__ + if args: + super().__init__(*args) + else: + super().__init__(self.msg) + + def _check_params(self, *args, **kwargs): + """Old exceptions supported only args and not kwargs. + + For sanity we do not allow to mix old and new behavior.""" + if args or kwargs: + assert bool(args) != bool(kwargs), \ + 'keyword arguments are mutually exclusive with positional args' + + def _check_kwargs(self, **kwargs): + if kwargs: + assert set(kwargs.keys()) == self.supp_kwargs, \ + 'following set of keyword args is required: %s' % ( + self.supp_kwargs) + return kwargs + + def _fmt_kwargs(self, **kwargs): + """Format kwargs before printing them. + + Resulting dictionary has to have keys necessary for str.format call + on fmt class variable. + """ + fmtargs = {} + for kw, data in kwargs.items(): + if isinstance(data, (list, set)): + # convert list of to list of str() + fmtargs[kw] = list(map(str, data)) + if len(fmtargs[kw]) == 1: + # remove list brackets [] from single-item lists + fmtargs[kw] = fmtargs[kw].pop() + else: + fmtargs[kw] = data + return fmtargs + + def __str__(self): + if self.kwargs and self.fmt: + # provide custom message constructed from keyword arguments + fmtargs = self._fmt_kwargs(**self.kwargs) + return self.fmt.format(**fmtargs) + else: + # print *args directly in the same way as old DNSException + return super().__str__() + + +class FormError(DNSException): + """DNS message is malformed.""" + + +class SyntaxError(DNSException): + """Text input is malformed.""" + + +class UnexpectedEnd(SyntaxError): + """Text input ended unexpectedly.""" + + +class TooBig(DNSException): + """The DNS message is too big.""" + + +class Timeout(DNSException): + """The DNS operation timed out.""" + supp_kwargs = {'timeout'} + fmt = "The DNS operation timed out after {timeout} seconds" + + +class ExceptionWrapper: + def __init__(self, exception_class): + self.exception_class = exception_class + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + if exc_type is not None and not isinstance(exc_val, + self.exception_class): + raise self.exception_class(str(exc_val)) from exc_val + return False diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/flags.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/flags.py new file mode 100644 index 0000000..9652287 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/flags.py @@ -0,0 +1,119 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Message Flags.""" + +import enum + +# Standard DNS flags + +class Flag(enum.IntFlag): + #: Query Response + QR = 0x8000 + #: Authoritative Answer + AA = 0x0400 + #: Truncated Response + TC = 0x0200 + #: Recursion Desired + RD = 0x0100 + #: Recursion Available + RA = 0x0080 + #: Authentic Data + AD = 0x0020 + #: Checking Disabled + CD = 0x0010 + + +# EDNS flags + +class EDNSFlag(enum.IntFlag): + #: DNSSEC answer OK + DO = 0x8000 + + +def _from_text(text, enum_class): + flags = 0 + tokens = text.split() + for t in tokens: + flags |= enum_class[t.upper()] + return flags + + +def _to_text(flags, enum_class): + text_flags = [] + for k, v in enum_class.__members__.items(): + if flags & v != 0: + text_flags.append(k) + return ' '.join(text_flags) + + +def from_text(text): + """Convert a space-separated list of flag text values into a flags + value. + + Returns an ``int`` + """ + + return _from_text(text, Flag) + + +def to_text(flags): + """Convert a flags value into a space-separated list of flag text + values. + + Returns a ``str``. + """ + + return _to_text(flags, Flag) + + +def edns_from_text(text): + """Convert a space-separated list of EDNS flag text values into a EDNS + flags value. + + Returns an ``int`` + """ + + return _from_text(text, EDNSFlag) + + +def edns_to_text(flags): + """Convert an EDNS flags value into a space-separated list of EDNS flag + text values. + + Returns a ``str``. + """ + + return _to_text(flags, EDNSFlag) + +### BEGIN generated Flag constants + +QR = Flag.QR +AA = Flag.AA +TC = Flag.TC +RD = Flag.RD +RA = Flag.RA +AD = Flag.AD +CD = Flag.CD + +### END generated Flag constants + +### BEGIN generated EDNSFlag constants + +DO = EDNSFlag.DO + +### END generated EDNSFlag constants diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/grange.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/grange.py new file mode 100644 index 0000000..112ede4 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/grange.py @@ -0,0 +1,69 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2012-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS GENERATE range conversion.""" + +import dns + +def from_text(text): + """Convert the text form of a range in a ``$GENERATE`` statement to an + integer. + + *text*, a ``str``, the textual range in ``$GENERATE`` form. + + Returns a tuple of three ``int`` values ``(start, stop, step)``. + """ + + start = -1 + stop = -1 + step = 1 + cur = '' + state = 0 + # state 0 1 2 + # x - y / z + + if text and text[0] == '-': + raise dns.exception.SyntaxError("Start cannot be a negative number") + + for c in text: + if c == '-' and state == 0: + start = int(cur) + cur = '' + state = 1 + elif c == '/': + stop = int(cur) + cur = '' + state = 2 + elif c.isdigit(): + cur += c + else: + raise dns.exception.SyntaxError("Could not parse %s" % (c)) + + if state == 0: + raise dns.exception.SyntaxError("no stop value specified") + elif state == 1: + stop = int(cur) + else: + assert state == 2 + step = int(cur) + + assert step >= 1 + assert start >= 0 + if start > stop: + raise dns.exception.SyntaxError('start must be <= stop') + + return (start, stop, step) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/immutable.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/immutable.py new file mode 100644 index 0000000..db7abbc --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/immutable.py @@ -0,0 +1,70 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import collections.abc +import sys + +# pylint: disable=unused-import +if sys.version_info >= (3, 7): + odict = dict + from dns._immutable_ctx import immutable +else: + # pragma: no cover + from collections import OrderedDict as odict + from dns._immutable_attr import immutable # noqa +# pylint: enable=unused-import + + +@immutable +class Dict(collections.abc.Mapping): + def __init__(self, dictionary, no_copy=False): + """Make an immutable dictionary from the specified dictionary. + + If *no_copy* is `True`, then *dictionary* will be wrapped instead + of copied. Only set this if you are sure there will be no external + references to the dictionary. + """ + if no_copy and isinstance(dictionary, odict): + self._odict = dictionary + else: + self._odict = odict(dictionary) + self._hash = None + + def __getitem__(self, key): + return self._odict.__getitem__(key) + + def __hash__(self): # pylint: disable=invalid-hash-returned + if self._hash is None: + h = 0 + for key in sorted(self._odict.keys()): + h ^= hash(key) + object.__setattr__(self, '_hash', h) + # this does return an int, but pylint doesn't figure that out + return self._hash + + def __len__(self): + return len(self._odict) + + def __iter__(self): + return iter(self._odict) + + +def constify(o): + """ + Convert mutable types to immutable types. + """ + if isinstance(o, bytearray): + return bytes(o) + if isinstance(o, tuple): + try: + hash(o) + return o + except Exception: + return tuple(constify(elt) for elt in o) + if isinstance(o, list): + return tuple(constify(elt) for elt in o) + if isinstance(o, dict): + cdict = odict() + for k, v in o.items(): + cdict[k] = constify(v) + return Dict(cdict, True) + return o diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/inet.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/inet.py new file mode 100644 index 0000000..d3bdc64 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/inet.py @@ -0,0 +1,170 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Generic Internet address helper functions.""" + +import socket + +import dns.ipv4 +import dns.ipv6 + + +# We assume that AF_INET and AF_INET6 are always defined. We keep +# these here for the benefit of any old code (unlikely though that +# is!). +AF_INET = socket.AF_INET +AF_INET6 = socket.AF_INET6 + + +def inet_pton(family, text): + """Convert the textual form of a network address into its binary form. + + *family* is an ``int``, the address family. + + *text* is a ``str``, the textual address. + + Raises ``NotImplementedError`` if the address family specified is not + implemented. + + Returns a ``bytes``. + """ + + if family == AF_INET: + return dns.ipv4.inet_aton(text) + elif family == AF_INET6: + return dns.ipv6.inet_aton(text, True) + else: + raise NotImplementedError + + +def inet_ntop(family, address): + """Convert the binary form of a network address into its textual form. + + *family* is an ``int``, the address family. + + *address* is a ``bytes``, the network address in binary form. + + Raises ``NotImplementedError`` if the address family specified is not + implemented. + + Returns a ``str``. + """ + + if family == AF_INET: + return dns.ipv4.inet_ntoa(address) + elif family == AF_INET6: + return dns.ipv6.inet_ntoa(address) + else: + raise NotImplementedError + + +def af_for_address(text): + """Determine the address family of a textual-form network address. + + *text*, a ``str``, the textual address. + + Raises ``ValueError`` if the address family cannot be determined + from the input. + + Returns an ``int``. + """ + + try: + dns.ipv4.inet_aton(text) + return AF_INET + except Exception: + try: + dns.ipv6.inet_aton(text, True) + return AF_INET6 + except Exception: + raise ValueError + + +def is_multicast(text): + """Is the textual-form network address a multicast address? + + *text*, a ``str``, the textual address. + + Raises ``ValueError`` if the address family cannot be determined + from the input. + + Returns a ``bool``. + """ + + try: + first = dns.ipv4.inet_aton(text)[0] + return first >= 224 and first <= 239 + except Exception: + try: + first = dns.ipv6.inet_aton(text, True)[0] + return first == 255 + except Exception: + raise ValueError + + +def is_address(text): + """Is the specified string an IPv4 or IPv6 address? + + *text*, a ``str``, the textual address. + + Returns a ``bool``. + """ + + try: + dns.ipv4.inet_aton(text) + return True + except Exception: + try: + dns.ipv6.inet_aton(text, True) + return True + except Exception: + return False + + +def low_level_address_tuple(high_tuple, af=None): + """Given a "high-level" address tuple, i.e. + an (address, port) return the appropriate "low-level" address tuple + suitable for use in socket calls. + + If an *af* other than ``None`` is provided, it is assumed the + address in the high-level tuple is valid and has that af. If af + is ``None``, then af_for_address will be called. + + """ + address, port = high_tuple + if af is None: + af = af_for_address(address) + if af == AF_INET: + return (address, port) + elif af == AF_INET6: + i = address.find('%') + if i < 0: + # no scope, shortcut! + return (address, port, 0, 0) + # try to avoid getaddrinfo() + addrpart = address[:i] + scope = address[i + 1:] + if scope.isdigit(): + return (addrpart, port, 0, int(scope)) + try: + return (addrpart, port, 0, socket.if_nametoindex(scope)) + except AttributeError: # pragma: no cover (we can't really test this) + ai_flags = socket.AI_NUMERICHOST + ((*_, tup), *_) = socket.getaddrinfo(address, port, flags=ai_flags) + return tup + else: + raise NotImplementedError(f'unknown address family {af}') diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/ipv4.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/ipv4.py new file mode 100644 index 0000000..e1f38d3 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/ipv4.py @@ -0,0 +1,60 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""IPv4 helper functions.""" + +import struct + +import dns.exception + +def inet_ntoa(address): + """Convert an IPv4 address in binary form to text form. + + *address*, a ``bytes``, the IPv4 address in binary form. + + Returns a ``str``. + """ + + if len(address) != 4: + raise dns.exception.SyntaxError + return ('%u.%u.%u.%u' % (address[0], address[1], + address[2], address[3])) + +def inet_aton(text): + """Convert an IPv4 address in text form to binary form. + + *text*, a ``str``, the IPv4 address in textual form. + + Returns a ``bytes``. + """ + + if not isinstance(text, bytes): + text = text.encode() + parts = text.split(b'.') + if len(parts) != 4: + raise dns.exception.SyntaxError + for part in parts: + if not part.isdigit(): + raise dns.exception.SyntaxError + if len(part) > 1 and part[0] == ord('0'): + # No leading zeros + raise dns.exception.SyntaxError + try: + b = [int(part) for part in parts] + return struct.pack('BBBB', *b) + except Exception: + raise dns.exception.SyntaxError diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/ipv6.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/ipv6.py new file mode 100644 index 0000000..f0e522c --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/ipv6.py @@ -0,0 +1,197 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""IPv6 helper functions.""" + +import re +import binascii + +import dns.exception +import dns.ipv4 + +_leading_zero = re.compile(r'0+([0-9a-f]+)') + +def inet_ntoa(address): + """Convert an IPv6 address in binary form to text form. + + *address*, a ``bytes``, the IPv6 address in binary form. + + Raises ``ValueError`` if the address isn't 16 bytes long. + Returns a ``str``. + """ + + if len(address) != 16: + raise ValueError("IPv6 addresses are 16 bytes long") + hex = binascii.hexlify(address) + chunks = [] + i = 0 + l = len(hex) + while i < l: + chunk = hex[i:i + 4].decode() + # strip leading zeros. we do this with an re instead of + # with lstrip() because lstrip() didn't support chars until + # python 2.2.2 + m = _leading_zero.match(chunk) + if m is not None: + chunk = m.group(1) + chunks.append(chunk) + i += 4 + # + # Compress the longest subsequence of 0-value chunks to :: + # + best_start = 0 + best_len = 0 + start = -1 + last_was_zero = False + for i in range(8): + if chunks[i] != '0': + if last_was_zero: + end = i + current_len = end - start + if current_len > best_len: + best_start = start + best_len = current_len + last_was_zero = False + elif not last_was_zero: + start = i + last_was_zero = True + if last_was_zero: + end = 8 + current_len = end - start + if current_len > best_len: + best_start = start + best_len = current_len + if best_len > 1: + if best_start == 0 and \ + (best_len == 6 or + best_len == 5 and chunks[5] == 'ffff'): + # We have an embedded IPv4 address + if best_len == 6: + prefix = '::' + else: + prefix = '::ffff:' + hex = prefix + dns.ipv4.inet_ntoa(address[12:]) + else: + hex = ':'.join(chunks[:best_start]) + '::' + \ + ':'.join(chunks[best_start + best_len:]) + else: + hex = ':'.join(chunks) + return hex + +_v4_ending = re.compile(br'(.*):(\d+\.\d+\.\d+\.\d+)$') +_colon_colon_start = re.compile(br'::.*') +_colon_colon_end = re.compile(br'.*::$') + +def inet_aton(text, ignore_scope=False): + """Convert an IPv6 address in text form to binary form. + + *text*, a ``str``, the IPv6 address in textual form. + + *ignore_scope*, a ``bool``. If ``True``, a scope will be ignored. + If ``False``, the default, it is an error for a scope to be present. + + Returns a ``bytes``. + """ + + # + # Our aim here is not something fast; we just want something that works. + # + if not isinstance(text, bytes): + text = text.encode() + + if ignore_scope: + parts = text.split(b'%') + l = len(parts) + if l == 2: + text = parts[0] + elif l > 2: + raise dns.exception.SyntaxError + + if text == b'': + raise dns.exception.SyntaxError + elif text.endswith(b':') and not text.endswith(b'::'): + raise dns.exception.SyntaxError + elif text.startswith(b':') and not text.startswith(b'::'): + raise dns.exception.SyntaxError + elif text == b'::': + text = b'0::' + # + # Get rid of the icky dot-quad syntax if we have it. + # + m = _v4_ending.match(text) + if m is not None: + b = dns.ipv4.inet_aton(m.group(2)) + text = (u"{}:{:02x}{:02x}:{:02x}{:02x}".format(m.group(1).decode(), + b[0], b[1], b[2], + b[3])).encode() + # + # Try to turn '::' into ':'; if no match try to + # turn '::' into ':' + # + m = _colon_colon_start.match(text) + if m is not None: + text = text[1:] + else: + m = _colon_colon_end.match(text) + if m is not None: + text = text[:-1] + # + # Now canonicalize into 8 chunks of 4 hex digits each + # + chunks = text.split(b':') + l = len(chunks) + if l > 8: + raise dns.exception.SyntaxError + seen_empty = False + canonical = [] + for c in chunks: + if c == b'': + if seen_empty: + raise dns.exception.SyntaxError + seen_empty = True + for _ in range(0, 8 - l + 1): + canonical.append(b'0000') + else: + lc = len(c) + if lc > 4: + raise dns.exception.SyntaxError + if lc != 4: + c = (b'0' * (4 - lc)) + c + canonical.append(c) + if l < 8 and not seen_empty: + raise dns.exception.SyntaxError + text = b''.join(canonical) + + # + # Finally we can go to binary. + # + try: + return binascii.unhexlify(text) + except (binascii.Error, TypeError): + raise dns.exception.SyntaxError + +_mapped_prefix = b'\x00' * 10 + b'\xff\xff' + +def is_mapped(address): + """Is the specified address a mapped IPv4 address? + + *address*, a ``bytes`` is an IPv6 address in binary form. + + Returns a ``bool``. + """ + + return address.startswith(_mapped_prefix) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/message.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/message.py new file mode 100644 index 0000000..2a7565a --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/message.py @@ -0,0 +1,1507 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Messages""" + +import contextlib +import io +import time + +import dns.wire +import dns.edns +import dns.enum +import dns.exception +import dns.flags +import dns.name +import dns.opcode +import dns.entropy +import dns.rcode +import dns.rdata +import dns.rdataclass +import dns.rdatatype +import dns.rrset +import dns.renderer +import dns.ttl +import dns.tsig +import dns.rdtypes.ANY.OPT +import dns.rdtypes.ANY.TSIG + + +class ShortHeader(dns.exception.FormError): + """The DNS packet passed to from_wire() is too short.""" + + +class TrailingJunk(dns.exception.FormError): + """The DNS packet passed to from_wire() has extra junk at the end of it.""" + + +class UnknownHeaderField(dns.exception.DNSException): + """The header field name was not recognized when converting from text + into a message.""" + + +class BadEDNS(dns.exception.FormError): + """An OPT record occurred somewhere other than + the additional data section.""" + + +class BadTSIG(dns.exception.FormError): + """A TSIG record occurred somewhere other than the end of + the additional data section.""" + + +class UnknownTSIGKey(dns.exception.DNSException): + """A TSIG with an unknown key was received.""" + + +class Truncated(dns.exception.DNSException): + """The truncated flag is set.""" + + supp_kwargs = {'message'} + + def message(self): + """As much of the message as could be processed. + + Returns a ``dns.message.Message``. + """ + return self.kwargs['message'] + + +class NotQueryResponse(dns.exception.DNSException): + """Message is not a response to a query.""" + + +class ChainTooLong(dns.exception.DNSException): + """The CNAME chain is too long.""" + + +class AnswerForNXDOMAIN(dns.exception.DNSException): + """The rcode is NXDOMAIN but an answer was found.""" + +class NoPreviousName(dns.exception.SyntaxError): + """No previous name was known.""" + + +class MessageSection(dns.enum.IntEnum): + """Message sections""" + QUESTION = 0 + ANSWER = 1 + AUTHORITY = 2 + ADDITIONAL = 3 + + @classmethod + def _maximum(cls): + return 3 + + +DEFAULT_EDNS_PAYLOAD = 1232 +MAX_CHAIN = 16 + +class Message: + """A DNS message.""" + + _section_enum = MessageSection + + def __init__(self, id=None): + if id is None: + self.id = dns.entropy.random_16() + else: + self.id = id + self.flags = 0 + self.sections = [[], [], [], []] + self.opt = None + self.request_payload = 0 + self.keyring = None + self.tsig = None + self.request_mac = b'' + self.xfr = False + self.origin = None + self.tsig_ctx = None + self.index = {} + + @property + def question(self): + """ The question section.""" + return self.sections[0] + + @question.setter + def question(self, v): + self.sections[0] = v + + @property + def answer(self): + """ The answer section.""" + return self.sections[1] + + @answer.setter + def answer(self, v): + self.sections[1] = v + + @property + def authority(self): + """ The authority section.""" + return self.sections[2] + + @authority.setter + def authority(self, v): + self.sections[2] = v + + @property + def additional(self): + """ The additional data section.""" + return self.sections[3] + + @additional.setter + def additional(self, v): + self.sections[3] = v + + def __repr__(self): + return '' + + def __str__(self): + return self.to_text() + + def to_text(self, origin=None, relativize=True, **kw): + """Convert the message to text. + + The *origin*, *relativize*, and any other keyword + arguments are passed to the RRset ``to_wire()`` method. + + Returns a ``str``. + """ + + s = io.StringIO() + s.write('id %d\n' % self.id) + s.write('opcode %s\n' % dns.opcode.to_text(self.opcode())) + s.write('rcode %s\n' % dns.rcode.to_text(self.rcode())) + s.write('flags %s\n' % dns.flags.to_text(self.flags)) + if self.edns >= 0: + s.write('edns %s\n' % self.edns) + if self.ednsflags != 0: + s.write('eflags %s\n' % + dns.flags.edns_to_text(self.ednsflags)) + s.write('payload %d\n' % self.payload) + for opt in self.options: + s.write('option %s\n' % opt.to_text()) + for (name, which) in self._section_enum.__members__.items(): + s.write(f';{name}\n') + for rrset in self.section_from_number(which): + s.write(rrset.to_text(origin, relativize, **kw)) + s.write('\n') + # + # We strip off the final \n so the caller can print the result without + # doing weird things to get around eccentricities in Python print + # formatting + # + return s.getvalue()[:-1] + + def __eq__(self, other): + """Two messages are equal if they have the same content in the + header, question, answer, and authority sections. + + Returns a ``bool``. + """ + + if not isinstance(other, Message): + return False + if self.id != other.id: + return False + if self.flags != other.flags: + return False + for i, section in enumerate(self.sections): + other_section = other.sections[i] + for n in section: + if n not in other_section: + return False + for n in other_section: + if n not in section: + return False + return True + + def __ne__(self, other): + return not self.__eq__(other) + + def is_response(self, other): + """Is *other* a response this message? + + Returns a ``bool``. + """ + + if other.flags & dns.flags.QR == 0 or \ + self.id != other.id or \ + dns.opcode.from_flags(self.flags) != \ + dns.opcode.from_flags(other.flags): + return False + if other.rcode() in {dns.rcode.FORMERR, dns.rcode.SERVFAIL, + dns.rcode.NOTIMP, dns.rcode.REFUSED}: + # We don't check the question section in these cases if + # the other question section is empty, even though they + # still really ought to have a question section. + if len(other.question) == 0: + return True + if dns.opcode.is_update(self.flags): + # This is assuming the "sender doesn't include anything + # from the update", but we don't care to check the other + # case, which is that all the sections are returned and + # identical. + return True + for n in self.question: + if n not in other.question: + return False + for n in other.question: + if n not in self.question: + return False + return True + + def section_number(self, section): + """Return the "section number" of the specified section for use + in indexing. + + *section* is one of the section attributes of this message. + + Raises ``ValueError`` if the section isn't known. + + Returns an ``int``. + """ + + for i, our_section in enumerate(self.sections): + if section is our_section: + return self._section_enum(i) + raise ValueError('unknown section') + + def section_from_number(self, number): + """Return the section list associated with the specified section + number. + + *number* is a section number `int` or the text form of a section + name. + + Raises ``ValueError`` if the section isn't known. + + Returns a ``list``. + """ + + section = self._section_enum.make(number) + return self.sections[section] + + def find_rrset(self, section, name, rdclass, rdtype, + covers=dns.rdatatype.NONE, deleting=None, create=False, + force_unique=False): + """Find the RRset with the given attributes in the specified section. + + *section*, an ``int`` section number, or one of the section + attributes of this message. This specifies the + the section of the message to search. For example:: + + my_message.find_rrset(my_message.answer, name, rdclass, rdtype) + my_message.find_rrset(dns.message.ANSWER, name, rdclass, rdtype) + + *name*, a ``dns.name.Name``, the name of the RRset. + + *rdclass*, an ``int``, the class of the RRset. + + *rdtype*, an ``int``, the type of the RRset. + + *covers*, an ``int`` or ``None``, the covers value of the RRset. + The default is ``None``. + + *deleting*, an ``int`` or ``None``, the deleting value of the RRset. + The default is ``None``. + + *create*, a ``bool``. If ``True``, create the RRset if it is not found. + The created RRset is appended to *section*. + + *force_unique*, a ``bool``. If ``True`` and *create* is also ``True``, + create a new RRset regardless of whether a matching RRset exists + already. The default is ``False``. This is useful when creating + DDNS Update messages, as order matters for them. + + Raises ``KeyError`` if the RRset was not found and create was + ``False``. + + Returns a ``dns.rrset.RRset object``. + """ + + if isinstance(section, int): + section_number = section + section = self.section_from_number(section_number) + else: + section_number = self.section_number(section) + key = (section_number, name, rdclass, rdtype, covers, deleting) + if not force_unique: + if self.index is not None: + rrset = self.index.get(key) + if rrset is not None: + return rrset + else: + for rrset in section: + if rrset.full_match(name, rdclass, rdtype, covers, + deleting): + return rrset + if not create: + raise KeyError + rrset = dns.rrset.RRset(name, rdclass, rdtype, covers, deleting) + section.append(rrset) + if self.index is not None: + self.index[key] = rrset + return rrset + + def get_rrset(self, section, name, rdclass, rdtype, + covers=dns.rdatatype.NONE, deleting=None, create=False, + force_unique=False): + """Get the RRset with the given attributes in the specified section. + + If the RRset is not found, None is returned. + + *section*, an ``int`` section number, or one of the section + attributes of this message. This specifies the + the section of the message to search. For example:: + + my_message.get_rrset(my_message.answer, name, rdclass, rdtype) + my_message.get_rrset(dns.message.ANSWER, name, rdclass, rdtype) + + *name*, a ``dns.name.Name``, the name of the RRset. + + *rdclass*, an ``int``, the class of the RRset. + + *rdtype*, an ``int``, the type of the RRset. + + *covers*, an ``int`` or ``None``, the covers value of the RRset. + The default is ``None``. + + *deleting*, an ``int`` or ``None``, the deleting value of the RRset. + The default is ``None``. + + *create*, a ``bool``. If ``True``, create the RRset if it is not found. + The created RRset is appended to *section*. + + *force_unique*, a ``bool``. If ``True`` and *create* is also ``True``, + create a new RRset regardless of whether a matching RRset exists + already. The default is ``False``. This is useful when creating + DDNS Update messages, as order matters for them. + + Returns a ``dns.rrset.RRset object`` or ``None``. + """ + + try: + rrset = self.find_rrset(section, name, rdclass, rdtype, covers, + deleting, create, force_unique) + except KeyError: + rrset = None + return rrset + + def to_wire(self, origin=None, max_size=0, multi=False, tsig_ctx=None, + **kw): + """Return a string containing the message in DNS compressed wire + format. + + Additional keyword arguments are passed to the RRset ``to_wire()`` + method. + + *origin*, a ``dns.name.Name`` or ``None``, the origin to be appended + to any relative names. If ``None``, and the message has an origin + attribute that is not ``None``, then it will be used. + + *max_size*, an ``int``, the maximum size of the wire format + output; default is 0, which means "the message's request + payload, if nonzero, or 65535". + + *multi*, a ``bool``, should be set to ``True`` if this message is + part of a multiple message sequence. + + *tsig_ctx*, a ``dns.tsig.HMACTSig`` or ``dns.tsig.GSSTSig`` object, the + ongoing TSIG context, used when signing zone transfers. + + Raises ``dns.exception.TooBig`` if *max_size* was exceeded. + + Returns a ``bytes``. + """ + + if origin is None and self.origin is not None: + origin = self.origin + if max_size == 0: + if self.request_payload != 0: + max_size = self.request_payload + else: + max_size = 65535 + if max_size < 512: + max_size = 512 + elif max_size > 65535: + max_size = 65535 + r = dns.renderer.Renderer(self.id, self.flags, max_size, origin) + for rrset in self.question: + r.add_question(rrset.name, rrset.rdtype, rrset.rdclass) + for rrset in self.answer: + r.add_rrset(dns.renderer.ANSWER, rrset, **kw) + for rrset in self.authority: + r.add_rrset(dns.renderer.AUTHORITY, rrset, **kw) + if self.opt is not None: + r.add_rrset(dns.renderer.ADDITIONAL, self.opt) + for rrset in self.additional: + r.add_rrset(dns.renderer.ADDITIONAL, rrset, **kw) + r.write_header() + if self.tsig is not None: + (new_tsig, ctx) = dns.tsig.sign(r.get_wire(), + self.keyring, + self.tsig[0], + int(time.time()), + self.request_mac, + tsig_ctx, + multi) + self.tsig.clear() + self.tsig.add(new_tsig) + r.add_rrset(dns.renderer.ADDITIONAL, self.tsig) + r.write_header() + if multi: + self.tsig_ctx = ctx + return r.get_wire() + + @staticmethod + def _make_tsig(keyname, algorithm, time_signed, fudge, mac, original_id, + error, other): + tsig = dns.rdtypes.ANY.TSIG.TSIG(dns.rdataclass.ANY, dns.rdatatype.TSIG, + algorithm, time_signed, fudge, mac, + original_id, error, other) + return dns.rrset.from_rdata(keyname, 0, tsig) + + def use_tsig(self, keyring, keyname=None, fudge=300, + original_id=None, tsig_error=0, other_data=b'', + algorithm=dns.tsig.default_algorithm): + """When sending, a TSIG signature using the specified key + should be added. + + *key*, a ``dns.tsig.Key`` is the key to use. If a key is specified, + the *keyring* and *algorithm* fields are not used. + + *keyring*, a ``dict``, ``callable`` or ``dns.tsig.Key``, is either + the TSIG keyring or key to use. + + The format of a keyring dict is a mapping from TSIG key name, as + ``dns.name.Name`` to ``dns.tsig.Key`` or a TSIG secret, a ``bytes``. + If a ``dict`` *keyring* is specified but a *keyname* is not, the key + used will be the first key in the *keyring*. Note that the order of + keys in a dictionary is not defined, so applications should supply a + keyname when a ``dict`` keyring is used, unless they know the keyring + contains only one key. If a ``callable`` keyring is specified, the + callable will be called with the message and the keyname, and is + expected to return a key. + + *keyname*, a ``dns.name.Name``, ``str`` or ``None``, the name of + thes TSIG key to use; defaults to ``None``. If *keyring* is a + ``dict``, the key must be defined in it. If *keyring* is a + ``dns.tsig.Key``, this is ignored. + + *fudge*, an ``int``, the TSIG time fudge. + + *original_id*, an ``int``, the TSIG original id. If ``None``, + the message's id is used. + + *tsig_error*, an ``int``, the TSIG error code. + + *other_data*, a ``bytes``, the TSIG other data. + + *algorithm*, a ``dns.name.Name``, the TSIG algorithm to use. This is + only used if *keyring* is a ``dict``, and the key entry is a ``bytes``. + """ + + if isinstance(keyring, dns.tsig.Key): + key = keyring + keyname = key.name + elif callable(keyring): + key = keyring(self, keyname) + else: + if isinstance(keyname, str): + keyname = dns.name.from_text(keyname) + if keyname is None: + keyname = next(iter(keyring)) + key = keyring[keyname] + if isinstance(key, bytes): + key = dns.tsig.Key(keyname, key, algorithm) + self.keyring = key + if original_id is None: + original_id = self.id + self.tsig = self._make_tsig(keyname, self.keyring.algorithm, 0, fudge, + b'', original_id, tsig_error, other_data) + + @property + def keyname(self): + if self.tsig: + return self.tsig.name + else: + return None + + @property + def keyalgorithm(self): + if self.tsig: + return self.tsig[0].algorithm + else: + return None + + @property + def mac(self): + if self.tsig: + return self.tsig[0].mac + else: + return None + + @property + def tsig_error(self): + if self.tsig: + return self.tsig[0].error + else: + return None + + @property + def had_tsig(self): + return bool(self.tsig) + + @staticmethod + def _make_opt(flags=0, payload=DEFAULT_EDNS_PAYLOAD, options=None): + opt = dns.rdtypes.ANY.OPT.OPT(payload, dns.rdatatype.OPT, + options or ()) + return dns.rrset.from_rdata(dns.name.root, int(flags), opt) + + def use_edns(self, edns=0, ednsflags=0, payload=DEFAULT_EDNS_PAYLOAD, + request_payload=None, options=None): + """Configure EDNS behavior. + + *edns*, an ``int``, is the EDNS level to use. Specifying + ``None``, ``False``, or ``-1`` means "do not use EDNS", and in this case + the other parameters are ignored. Specifying ``True`` is + equivalent to specifying 0, i.e. "use EDNS0". + + *ednsflags*, an ``int``, the EDNS flag values. + + *payload*, an ``int``, is the EDNS sender's payload field, which is the + maximum size of UDP datagram the sender can handle. I.e. how big + a response to this message can be. + + *request_payload*, an ``int``, is the EDNS payload size to use when + sending this message. If not specified, defaults to the value of + *payload*. + + *options*, a list of ``dns.edns.Option`` objects or ``None``, the EDNS + options. + """ + + if edns is None or edns is False: + edns = -1 + elif edns is True: + edns = 0 + if edns < 0: + self.opt = None + self.request_payload = 0 + else: + # make sure the EDNS version in ednsflags agrees with edns + ednsflags &= 0xFF00FFFF + ednsflags |= (edns << 16) + if options is None: + options = [] + self.opt = self._make_opt(ednsflags, payload, options) + if request_payload is None: + request_payload = payload + self.request_payload = request_payload + + @property + def edns(self): + if self.opt: + return (self.ednsflags & 0xff0000) >> 16 + else: + return -1 + + @property + def ednsflags(self): + if self.opt: + return self.opt.ttl + else: + return 0 + + @ednsflags.setter + def ednsflags(self, v): + if self.opt: + self.opt.ttl = v + elif v: + self.opt = self._make_opt(v) + + @property + def payload(self): + if self.opt: + return self.opt[0].payload + else: + return 0 + + @property + def options(self): + if self.opt: + return self.opt[0].options + else: + return () + + def want_dnssec(self, wanted=True): + """Enable or disable 'DNSSEC desired' flag in requests. + + *wanted*, a ``bool``. If ``True``, then DNSSEC data is + desired in the response, EDNS is enabled if required, and then + the DO bit is set. If ``False``, the DO bit is cleared if + EDNS is enabled. + """ + + if wanted: + self.ednsflags |= dns.flags.DO + elif self.opt: + self.ednsflags &= ~dns.flags.DO + + def rcode(self): + """Return the rcode. + + Returns an ``int``. + """ + return dns.rcode.from_flags(int(self.flags), int(self.ednsflags)) + + def set_rcode(self, rcode): + """Set the rcode. + + *rcode*, an ``int``, is the rcode to set. + """ + (value, evalue) = dns.rcode.to_flags(rcode) + self.flags &= 0xFFF0 + self.flags |= value + self.ednsflags &= 0x00FFFFFF + self.ednsflags |= evalue + + def opcode(self): + """Return the opcode. + + Returns an ``int``. + """ + return dns.opcode.from_flags(int(self.flags)) + + def set_opcode(self, opcode): + """Set the opcode. + + *opcode*, an ``int``, is the opcode to set. + """ + self.flags &= 0x87FF + self.flags |= dns.opcode.to_flags(opcode) + + def _get_one_rr_per_rrset(self, value): + # What the caller picked is fine. + return value + + # pylint: disable=unused-argument + + def _parse_rr_header(self, section, name, rdclass, rdtype): + return (rdclass, rdtype, None, False) + + # pylint: enable=unused-argument + + def _parse_special_rr_header(self, section, count, position, + name, rdclass, rdtype): + if rdtype == dns.rdatatype.OPT: + if section != MessageSection.ADDITIONAL or self.opt or \ + name != dns.name.root: + raise BadEDNS + elif rdtype == dns.rdatatype.TSIG: + if section != MessageSection.ADDITIONAL or \ + rdclass != dns.rdatatype.ANY or \ + position != count - 1: + raise BadTSIG + return (rdclass, rdtype, None, False) + + +class ChainingResult: + """The result of a call to dns.message.QueryMessage.resolve_chaining(). + + The ``answer`` attribute is the answer RRSet, or ``None`` if it doesn't + exist. + + The ``canonical_name`` attribute is the canonical name after all + chaining has been applied (this is the name as ``rrset.name`` in cases + where rrset is not ``None``). + + The ``minimum_ttl`` attribute is the minimum TTL, i.e. the TTL to + use if caching the data. It is the smallest of all the CNAME TTLs + and either the answer TTL if it exists or the SOA TTL and SOA + minimum values for negative answers. + + The ``cnames`` attribute is a list of all the CNAME RRSets followed to + get to the canonical name. + """ + def __init__(self, canonical_name, answer, minimum_ttl, cnames): + self.canonical_name = canonical_name + self.answer = answer + self.minimum_ttl = minimum_ttl + self.cnames = cnames + + +class QueryMessage(Message): + def resolve_chaining(self): + """Follow the CNAME chain in the response to determine the answer + RRset. + + Raises ``dns.message.NotQueryResponse`` if the message is not + a response. + + Raises ``dns.message.ChainTooLong`` if the CNAME chain is too long. + + Raises ``dns.message.AnswerForNXDOMAIN`` if the rcode is NXDOMAIN + but an answer was found. + + Raises ``dns.exception.FormError`` if the question count is not 1. + + Returns a ChainingResult object. + """ + if self.flags & dns.flags.QR == 0: + raise NotQueryResponse + if len(self.question) != 1: + raise dns.exception.FormError + question = self.question[0] + qname = question.name + min_ttl = dns.ttl.MAX_TTL + answer = None + count = 0 + cnames = [] + while count < MAX_CHAIN: + try: + answer = self.find_rrset(self.answer, qname, question.rdclass, + question.rdtype) + min_ttl = min(min_ttl, answer.ttl) + break + except KeyError: + if question.rdtype != dns.rdatatype.CNAME: + try: + crrset = self.find_rrset(self.answer, qname, + question.rdclass, + dns.rdatatype.CNAME) + cnames.append(crrset) + min_ttl = min(min_ttl, crrset.ttl) + for rd in crrset: + qname = rd.target + break + count += 1 + continue + except KeyError: + # Exit the chaining loop + break + else: + # Exit the chaining loop + break + if count >= MAX_CHAIN: + raise ChainTooLong + if self.rcode() == dns.rcode.NXDOMAIN and answer is not None: + raise AnswerForNXDOMAIN + if answer is None: + # Further minimize the TTL with NCACHE. + auname = qname + while True: + # Look for an SOA RR whose owner name is a superdomain + # of qname. + try: + srrset = self.find_rrset(self.authority, auname, + question.rdclass, + dns.rdatatype.SOA) + min_ttl = min(min_ttl, srrset.ttl, srrset[0].minimum) + break + except KeyError: + try: + auname = auname.parent() + except dns.name.NoParent: + break + return ChainingResult(qname, answer, min_ttl, cnames) + + def canonical_name(self): + """Return the canonical name of the first name in the question + section. + + Raises ``dns.message.NotQueryResponse`` if the message is not + a response. + + Raises ``dns.message.ChainTooLong`` if the CNAME chain is too long. + + Raises ``dns.message.AnswerForNXDOMAIN`` if the rcode is NXDOMAIN + but an answer was found. + + Raises ``dns.exception.FormError`` if the question count is not 1. + """ + return self.resolve_chaining().canonical_name + + +def _maybe_import_update(): + # We avoid circular imports by doing this here. We do it in another + # function as doing it in _message_factory_from_opcode() makes "dns" + # a local symbol, and the first line fails :) + + # pylint: disable=redefined-outer-name,import-outside-toplevel,unused-import + import dns.update # noqa: F401 + + +def _message_factory_from_opcode(opcode): + if opcode == dns.opcode.QUERY: + return QueryMessage + elif opcode == dns.opcode.UPDATE: + _maybe_import_update() + return dns.update.UpdateMessage + else: + return Message + + +class _WireReader: + + """Wire format reader. + + parser: the binary parser + message: The message object being built + initialize_message: Callback to set message parsing options + question_only: Are we only reading the question? + one_rr_per_rrset: Put each RR into its own RRset? + keyring: TSIG keyring + ignore_trailing: Ignore trailing junk at end of request? + multi: Is this message part of a multi-message sequence? + DNS dynamic updates. + """ + + def __init__(self, wire, initialize_message, question_only=False, + one_rr_per_rrset=False, ignore_trailing=False, + keyring=None, multi=False): + self.parser = dns.wire.Parser(wire) + self.message = None + self.initialize_message = initialize_message + self.question_only = question_only + self.one_rr_per_rrset = one_rr_per_rrset + self.ignore_trailing = ignore_trailing + self.keyring = keyring + self.multi = multi + + def _get_question(self, section_number, qcount): + """Read the next *qcount* records from the wire data and add them to + the question section. + """ + + section = self.message.sections[section_number] + for _ in range(qcount): + qname = self.parser.get_name(self.message.origin) + (rdtype, rdclass) = self.parser.get_struct('!HH') + (rdclass, rdtype, _, _) = \ + self.message._parse_rr_header(section_number, qname, rdclass, + rdtype) + self.message.find_rrset(section, qname, rdclass, rdtype, + create=True, force_unique=True) + + def _get_section(self, section_number, count): + """Read the next I{count} records from the wire data and add them to + the specified section. + + section: the section of the message to which to add records + count: the number of records to read + """ + + section = self.message.sections[section_number] + force_unique = self.one_rr_per_rrset + for i in range(count): + rr_start = self.parser.current + absolute_name = self.parser.get_name() + if self.message.origin is not None: + name = absolute_name.relativize(self.message.origin) + else: + name = absolute_name + (rdtype, rdclass, ttl, rdlen) = self.parser.get_struct('!HHIH') + if rdtype in (dns.rdatatype.OPT, dns.rdatatype.TSIG): + (rdclass, rdtype, deleting, empty) = \ + self.message._parse_special_rr_header(section_number, + count, i, name, + rdclass, rdtype) + else: + (rdclass, rdtype, deleting, empty) = \ + self.message._parse_rr_header(section_number, + name, rdclass, rdtype) + if empty: + if rdlen > 0: + raise dns.exception.FormError + rd = None + covers = dns.rdatatype.NONE + else: + with self.parser.restrict_to(rdlen): + rd = dns.rdata.from_wire_parser(rdclass, rdtype, + self.parser, + self.message.origin) + covers = rd.covers() + if self.message.xfr and rdtype == dns.rdatatype.SOA: + force_unique = True + if rdtype == dns.rdatatype.OPT: + self.message.opt = dns.rrset.from_rdata(name, ttl, rd) + elif rdtype == dns.rdatatype.TSIG: + if self.keyring is None: + raise UnknownTSIGKey('got signed message without keyring') + if isinstance(self.keyring, dict): + key = self.keyring.get(absolute_name) + if isinstance(key, bytes): + key = dns.tsig.Key(absolute_name, key, rd.algorithm) + elif callable(self.keyring): + key = self.keyring(self.message, absolute_name) + else: + key = self.keyring + if key is None: + raise UnknownTSIGKey("key '%s' unknown" % name) + self.message.keyring = key + self.message.tsig_ctx = \ + dns.tsig.validate(self.parser.wire, + key, + absolute_name, + rd, + int(time.time()), + self.message.request_mac, + rr_start, + self.message.tsig_ctx, + self.multi) + self.message.tsig = dns.rrset.from_rdata(absolute_name, 0, rd) + else: + rrset = self.message.find_rrset(section, name, + rdclass, rdtype, covers, + deleting, True, + force_unique) + if rd is not None: + if ttl > 0x7fffffff: + ttl = 0 + rrset.add(rd, ttl) + + def read(self): + """Read a wire format DNS message and build a dns.message.Message + object.""" + + if self.parser.remaining() < 12: + raise ShortHeader + (id, flags, qcount, ancount, aucount, adcount) = \ + self.parser.get_struct('!HHHHHH') + factory = _message_factory_from_opcode(dns.opcode.from_flags(flags)) + self.message = factory(id=id) + self.message.flags = dns.flags.Flag(flags) + self.initialize_message(self.message) + self.one_rr_per_rrset = \ + self.message._get_one_rr_per_rrset(self.one_rr_per_rrset) + self._get_question(MessageSection.QUESTION, qcount) + if self.question_only: + return self.message + self._get_section(MessageSection.ANSWER, ancount) + self._get_section(MessageSection.AUTHORITY, aucount) + self._get_section(MessageSection.ADDITIONAL, adcount) + if not self.ignore_trailing and self.parser.remaining() != 0: + raise TrailingJunk + if self.multi and self.message.tsig_ctx and not self.message.had_tsig: + self.message.tsig_ctx.update(self.parser.wire) + return self.message + + +def from_wire(wire, keyring=None, request_mac=b'', xfr=False, origin=None, + tsig_ctx=None, multi=False, + question_only=False, one_rr_per_rrset=False, + ignore_trailing=False, raise_on_truncation=False): + """Convert a DNS wire format message into a message + object. + + *keyring*, a ``dns.tsig.Key`` or ``dict``, the key or keyring to use + if the message is signed. + + *request_mac*, a ``bytes``. If the message is a response to a + TSIG-signed request, *request_mac* should be set to the MAC of + that request. + + *xfr*, a ``bool``, should be set to ``True`` if this message is part of + a zone transfer. + + *origin*, a ``dns.name.Name`` or ``None``. If the message is part + of a zone transfer, *origin* should be the origin name of the + zone. If not ``None``, names will be relativized to the origin. + + *tsig_ctx*, a ``dns.tsig.HMACTSig`` or ``dns.tsig.GSSTSig`` object, the + ongoing TSIG context, used when validating zone transfers. + + *multi*, a ``bool``, should be set to ``True`` if this message is + part of a multiple message sequence. + + *question_only*, a ``bool``. If ``True``, read only up to + the end of the question section. + + *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its + own RRset. + + *ignore_trailing*, a ``bool``. If ``True``, ignore trailing + junk at end of the message. + + *raise_on_truncation*, a ``bool``. If ``True``, raise an exception if + the TC bit is set. + + Raises ``dns.message.ShortHeader`` if the message is less than 12 octets + long. + + Raises ``dns.message.TrailingJunk`` if there were octets in the message + past the end of the proper DNS message, and *ignore_trailing* is ``False``. + + Raises ``dns.message.BadEDNS`` if an OPT record was in the + wrong section, or occurred more than once. + + Raises ``dns.message.BadTSIG`` if a TSIG record was not the last + record of the additional data section. + + Raises ``dns.message.Truncated`` if the TC flag is set and + *raise_on_truncation* is ``True``. + + Returns a ``dns.message.Message``. + """ + + def initialize_message(message): + message.request_mac = request_mac + message.xfr = xfr + message.origin = origin + message.tsig_ctx = tsig_ctx + + reader = _WireReader(wire, initialize_message, question_only, + one_rr_per_rrset, ignore_trailing, keyring, multi) + try: + m = reader.read() + except dns.exception.FormError: + if reader.message and (reader.message.flags & dns.flags.TC) and \ + raise_on_truncation: + raise Truncated(message=reader.message) + else: + raise + # Reading a truncated message might not have any errors, so we + # have to do this check here too. + if m.flags & dns.flags.TC and raise_on_truncation: + raise Truncated(message=m) + + return m + + +class _TextReader: + + """Text format reader. + + tok: the tokenizer. + message: The message object being built. + DNS dynamic updates. + last_name: The most recently read name when building a message object. + one_rr_per_rrset: Put each RR into its own RRset? + origin: The origin for relative names + relativize: relativize names? + relativize_to: the origin to relativize to. + """ + + def __init__(self, text, idna_codec, one_rr_per_rrset=False, + origin=None, relativize=True, relativize_to=None): + self.message = None + self.tok = dns.tokenizer.Tokenizer(text, idna_codec=idna_codec) + self.last_name = None + self.one_rr_per_rrset = one_rr_per_rrset + self.origin = origin + self.relativize = relativize + self.relativize_to = relativize_to + self.id = None + self.edns = -1 + self.ednsflags = 0 + self.payload = DEFAULT_EDNS_PAYLOAD + self.rcode = None + self.opcode = dns.opcode.QUERY + self.flags = 0 + + def _header_line(self, _): + """Process one line from the text format header section.""" + + token = self.tok.get() + what = token.value + if what == 'id': + self.id = self.tok.get_int() + elif what == 'flags': + while True: + token = self.tok.get() + if not token.is_identifier(): + self.tok.unget(token) + break + self.flags = self.flags | dns.flags.from_text(token.value) + elif what == 'edns': + self.edns = self.tok.get_int() + self.ednsflags = self.ednsflags | (self.edns << 16) + elif what == 'eflags': + if self.edns < 0: + self.edns = 0 + while True: + token = self.tok.get() + if not token.is_identifier(): + self.tok.unget(token) + break + self.ednsflags = self.ednsflags | \ + dns.flags.edns_from_text(token.value) + elif what == 'payload': + self.payload = self.tok.get_int() + if self.edns < 0: + self.edns = 0 + elif what == 'opcode': + text = self.tok.get_string() + self.opcode = dns.opcode.from_text(text) + self.flags = self.flags | dns.opcode.to_flags(self.opcode) + elif what == 'rcode': + text = self.tok.get_string() + self.rcode = dns.rcode.from_text(text) + else: + raise UnknownHeaderField + self.tok.get_eol() + + def _question_line(self, section_number): + """Process one line from the text format question section.""" + + section = self.message.sections[section_number] + token = self.tok.get(want_leading=True) + if not token.is_whitespace(): + self.last_name = self.tok.as_name(token, self.message.origin, + self.relativize, + self.relativize_to) + name = self.last_name + if name is None: + raise NoPreviousName + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + # Class + try: + rdclass = dns.rdataclass.from_text(token.value) + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + except dns.exception.SyntaxError: + raise dns.exception.SyntaxError + except Exception: + rdclass = dns.rdataclass.IN + # Type + rdtype = dns.rdatatype.from_text(token.value) + (rdclass, rdtype, _, _) = \ + self.message._parse_rr_header(section_number, name, rdclass, rdtype) + self.message.find_rrset(section, name, rdclass, rdtype, create=True, + force_unique=True) + self.tok.get_eol() + + def _rr_line(self, section_number): + """Process one line from the text format answer, authority, or + additional data sections. + """ + + section = self.message.sections[section_number] + # Name + token = self.tok.get(want_leading=True) + if not token.is_whitespace(): + self.last_name = self.tok.as_name(token, self.message.origin, + self.relativize, + self.relativize_to) + name = self.last_name + if name is None: + raise NoPreviousName + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + # TTL + try: + ttl = int(token.value, 0) + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + except dns.exception.SyntaxError: + raise dns.exception.SyntaxError + except Exception: + ttl = 0 + # Class + try: + rdclass = dns.rdataclass.from_text(token.value) + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + except dns.exception.SyntaxError: + raise dns.exception.SyntaxError + except Exception: + rdclass = dns.rdataclass.IN + # Type + rdtype = dns.rdatatype.from_text(token.value) + (rdclass, rdtype, deleting, empty) = \ + self.message._parse_rr_header(section_number, name, rdclass, rdtype) + token = self.tok.get() + if empty and not token.is_eol_or_eof(): + raise dns.exception.SyntaxError + if not empty and token.is_eol_or_eof(): + raise dns.exception.UnexpectedEnd + if not token.is_eol_or_eof(): + self.tok.unget(token) + rd = dns.rdata.from_text(rdclass, rdtype, self.tok, + self.message.origin, self.relativize, + self.relativize_to) + covers = rd.covers() + else: + rd = None + covers = dns.rdatatype.NONE + rrset = self.message.find_rrset(section, name, + rdclass, rdtype, covers, + deleting, True, self.one_rr_per_rrset) + if rd is not None: + rrset.add(rd, ttl) + + def _make_message(self): + factory = _message_factory_from_opcode(self.opcode) + message = factory(id=self.id) + message.flags = self.flags + if self.edns >= 0: + message.use_edns(self.edns, self.ednsflags, self.payload) + if self.rcode: + message.set_rcode(self.rcode) + if self.origin: + message.origin = self.origin + return message + + def read(self): + """Read a text format DNS message and build a dns.message.Message + object.""" + + line_method = self._header_line + section_number = None + while 1: + token = self.tok.get(True, True) + if token.is_eol_or_eof(): + break + if token.is_comment(): + u = token.value.upper() + if u == 'HEADER': + line_method = self._header_line + + if self.message: + message = self.message + else: + # If we don't have a message, create one with the current + # opcode, so that we know which section names to parse. + message = self._make_message() + try: + section_number = message._section_enum.from_text(u) + # We found a section name. If we don't have a message, + # use the one we just created. + if not self.message: + self.message = message + self.one_rr_per_rrset = \ + message._get_one_rr_per_rrset(self.one_rr_per_rrset) + if section_number == MessageSection.QUESTION: + line_method = self._question_line + else: + line_method = self._rr_line + except Exception: + # It's just a comment. + pass + self.tok.get_eol() + continue + self.tok.unget(token) + line_method(section_number) + if not self.message: + self.message = self._make_message() + return self.message + + +def from_text(text, idna_codec=None, one_rr_per_rrset=False, + origin=None, relativize=True, relativize_to=None): + """Convert the text format message into a message object. + + The reader stops after reading the first blank line in the input to + facilitate reading multiple messages from a single file with + ``dns.message.from_file()``. + + *text*, a ``str``, the text format message. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder + is used. + + *one_rr_per_rrset*, a ``bool``. If ``True``, then each RR is put + into its own rrset. The default is ``False``. + + *origin*, a ``dns.name.Name`` (or ``None``), the + origin to use for relative names. + + *relativize*, a ``bool``. If true, name will be relativized. + + *relativize_to*, a ``dns.name.Name`` (or ``None``), the origin to use + when relativizing names. If not set, the *origin* value will be used. + + Raises ``dns.message.UnknownHeaderField`` if a header is unknown. + + Raises ``dns.exception.SyntaxError`` if the text is badly formed. + + Returns a ``dns.message.Message object`` + """ + + # 'text' can also be a file, but we don't publish that fact + # since it's an implementation detail. The official file + # interface is from_file(). + + reader = _TextReader(text, idna_codec, one_rr_per_rrset, origin, + relativize, relativize_to) + return reader.read() + + +def from_file(f, idna_codec=None, one_rr_per_rrset=False): + """Read the next text format message from the specified file. + + Message blocks are separated by a single blank line. + + *f*, a ``file`` or ``str``. If *f* is text, it is treated as the + pathname of a file to open. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder + is used. + + *one_rr_per_rrset*, a ``bool``. If ``True``, then each RR is put + into its own rrset. The default is ``False``. + + Raises ``dns.message.UnknownHeaderField`` if a header is unknown. + + Raises ``dns.exception.SyntaxError`` if the text is badly formed. + + Returns a ``dns.message.Message object`` + """ + + with contextlib.ExitStack() as stack: + if isinstance(f, str): + f = stack.enter_context(open(f)) + return from_text(f, idna_codec, one_rr_per_rrset) + + +def make_query(qname, rdtype, rdclass=dns.rdataclass.IN, use_edns=None, + want_dnssec=False, ednsflags=None, payload=None, + request_payload=None, options=None, idna_codec=None): + """Make a query message. + + The query name, type, and class may all be specified either + as objects of the appropriate type, or as strings. + + The query will have a randomly chosen query id, and its DNS flags + will be set to dns.flags.RD. + + qname, a ``dns.name.Name`` or ``str``, the query name. + + *rdtype*, an ``int`` or ``str``, the desired rdata type. + + *rdclass*, an ``int`` or ``str``, the desired rdata class; the default + is class IN. + + *use_edns*, an ``int``, ``bool`` or ``None``. The EDNS level to use; the + default is None (no EDNS). + See the description of dns.message.Message.use_edns() for the possible + values for use_edns and their meanings. + + *want_dnssec*, a ``bool``. If ``True``, DNSSEC data is desired. + + *ednsflags*, an ``int``, the EDNS flag values. + + *payload*, an ``int``, is the EDNS sender's payload field, which is the + maximum size of UDP datagram the sender can handle. I.e. how big + a response to this message can be. + + *request_payload*, an ``int``, is the EDNS payload size to use when + sending this message. If not specified, defaults to the value of + *payload*. + + *options*, a list of ``dns.edns.Option`` objects or ``None``, the EDNS + options. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder + is used. + + Returns a ``dns.message.QueryMessage`` + """ + + if isinstance(qname, str): + qname = dns.name.from_text(qname, idna_codec=idna_codec) + rdtype = dns.rdatatype.RdataType.make(rdtype) + rdclass = dns.rdataclass.RdataClass.make(rdclass) + m = QueryMessage() + m.flags |= dns.flags.RD + m.find_rrset(m.question, qname, rdclass, rdtype, create=True, + force_unique=True) + # only pass keywords on to use_edns if they have been set to a + # non-None value. Setting a field will turn EDNS on if it hasn't + # been configured. + kwargs = {} + if ednsflags is not None: + kwargs['ednsflags'] = ednsflags + if payload is not None: + kwargs['payload'] = payload + if request_payload is not None: + kwargs['request_payload'] = request_payload + if options is not None: + kwargs['options'] = options + if kwargs and use_edns is None: + use_edns = 0 + kwargs['edns'] = use_edns + m.use_edns(**kwargs) + m.want_dnssec(want_dnssec) + return m + + +def make_response(query, recursion_available=False, our_payload=8192, + fudge=300, tsig_error=0): + """Make a message which is a response for the specified query. + The message returned is really a response skeleton; it has all + of the infrastructure required of a response, but none of the + content. + + The response's question section is a shallow copy of the query's + question section, so the query's question RRsets should not be + changed. + + *query*, a ``dns.message.Message``, the query to respond to. + + *recursion_available*, a ``bool``, should RA be set in the response? + + *our_payload*, an ``int``, the payload size to advertise in EDNS + responses. + + *fudge*, an ``int``, the TSIG time fudge. + + *tsig_error*, an ``int``, the TSIG error. + + Returns a ``dns.message.Message`` object whose specific class is + appropriate for the query. For example, if query is a + ``dns.update.UpdateMessage``, response will be too. + """ + + if query.flags & dns.flags.QR: + raise dns.exception.FormError('specified query message is not a query') + factory = _message_factory_from_opcode(query.opcode()) + response = factory(id=query.id) + response.flags = dns.flags.QR | (query.flags & dns.flags.RD) + if recursion_available: + response.flags |= dns.flags.RA + response.set_opcode(query.opcode()) + response.question = list(query.question) + if query.edns >= 0: + response.use_edns(0, 0, our_payload, query.payload) + if query.had_tsig: + response.use_tsig(query.keyring, query.keyname, fudge, None, + tsig_error, b'', query.keyalgorithm) + response.request_mac = query.mac + return response + +### BEGIN generated MessageSection constants + +QUESTION = MessageSection.QUESTION +ANSWER = MessageSection.ANSWER +AUTHORITY = MessageSection.AUTHORITY +ADDITIONAL = MessageSection.ADDITIONAL + +### END generated MessageSection constants diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/name.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/name.py new file mode 100644 index 0000000..8905d70 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/name.py @@ -0,0 +1,1018 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Names. +""" + +import copy +import struct + +import encodings.idna # type: ignore +try: + import idna # type: ignore + have_idna_2008 = True +except ImportError: # pragma: no cover + have_idna_2008 = False + +import dns.wire +import dns.exception +import dns.immutable + +# fullcompare() result values + +#: The compared names have no relationship to each other. +NAMERELN_NONE = 0 +#: the first name is a superdomain of the second. +NAMERELN_SUPERDOMAIN = 1 +#: The first name is a subdomain of the second. +NAMERELN_SUBDOMAIN = 2 +#: The compared names are equal. +NAMERELN_EQUAL = 3 +#: The compared names have a common ancestor. +NAMERELN_COMMONANCESTOR = 4 + + +class EmptyLabel(dns.exception.SyntaxError): + """A DNS label is empty.""" + + +class BadEscape(dns.exception.SyntaxError): + """An escaped code in a text format of DNS name is invalid.""" + + +class BadPointer(dns.exception.FormError): + """A DNS compression pointer points forward instead of backward.""" + + +class BadLabelType(dns.exception.FormError): + """The label type in DNS name wire format is unknown.""" + + +class NeedAbsoluteNameOrOrigin(dns.exception.DNSException): + """An attempt was made to convert a non-absolute name to + wire when there was also a non-absolute (or missing) origin.""" + + +class NameTooLong(dns.exception.FormError): + """A DNS name is > 255 octets long.""" + + +class LabelTooLong(dns.exception.SyntaxError): + """A DNS label is > 63 octets long.""" + + +class AbsoluteConcatenation(dns.exception.DNSException): + """An attempt was made to append anything other than the + empty name to an absolute DNS name.""" + + +class NoParent(dns.exception.DNSException): + """An attempt was made to get the parent of the root name + or the empty name.""" + +class NoIDNA2008(dns.exception.DNSException): + """IDNA 2008 processing was requested but the idna module is not + available.""" + + +class IDNAException(dns.exception.DNSException): + """IDNA processing raised an exception.""" + + supp_kwargs = {'idna_exception'} + fmt = "IDNA processing exception: {idna_exception}" + + +class IDNACodec: + """Abstract base class for IDNA encoder/decoders.""" + + def __init__(self): + pass + + def is_idna(self, label): + return label.lower().startswith(b'xn--') + + def encode(self, label): + raise NotImplementedError # pragma: no cover + + def decode(self, label): + # We do not apply any IDNA policy on decode. + if self.is_idna(label): + try: + label = label[4:].decode('punycode') + except Exception as e: + raise IDNAException(idna_exception=e) + return _escapify(label) + + +class IDNA2003Codec(IDNACodec): + """IDNA 2003 encoder/decoder.""" + + def __init__(self, strict_decode=False): + """Initialize the IDNA 2003 encoder/decoder. + + *strict_decode* is a ``bool``. If `True`, then IDNA2003 checking + is done when decoding. This can cause failures if the name + was encoded with IDNA2008. The default is `False`. + """ + + super().__init__() + self.strict_decode = strict_decode + + def encode(self, label): + """Encode *label*.""" + + if label == '': + return b'' + try: + return encodings.idna.ToASCII(label) + except UnicodeError: + raise LabelTooLong + + def decode(self, label): + """Decode *label*.""" + if not self.strict_decode: + return super().decode(label) + if label == b'': + return '' + try: + return _escapify(encodings.idna.ToUnicode(label)) + except Exception as e: + raise IDNAException(idna_exception=e) + + +class IDNA2008Codec(IDNACodec): + """IDNA 2008 encoder/decoder. + """ + + def __init__(self, uts_46=False, transitional=False, + allow_pure_ascii=False, strict_decode=False): + """Initialize the IDNA 2008 encoder/decoder. + + *uts_46* is a ``bool``. If True, apply Unicode IDNA + compatibility processing as described in Unicode Technical + Standard #46 (http://unicode.org/reports/tr46/). + If False, do not apply the mapping. The default is False. + + *transitional* is a ``bool``: If True, use the + "transitional" mode described in Unicode Technical Standard + #46. The default is False. + + *allow_pure_ascii* is a ``bool``. If True, then a label which + consists of only ASCII characters is allowed. This is less + strict than regular IDNA 2008, but is also necessary for mixed + names, e.g. a name with starting with "_sip._tcp." and ending + in an IDN suffix which would otherwise be disallowed. The + default is False. + + *strict_decode* is a ``bool``: If True, then IDNA2008 checking + is done when decoding. This can cause failures if the name + was encoded with IDNA2003. The default is False. + """ + super().__init__() + self.uts_46 = uts_46 + self.transitional = transitional + self.allow_pure_ascii = allow_pure_ascii + self.strict_decode = strict_decode + + def encode(self, label): + if label == '': + return b'' + if self.allow_pure_ascii and is_all_ascii(label): + encoded = label.encode('ascii') + if len(encoded) > 63: + raise LabelTooLong + return encoded + if not have_idna_2008: + raise NoIDNA2008 + try: + if self.uts_46: + label = idna.uts46_remap(label, False, self.transitional) + return idna.alabel(label) + except idna.IDNAError as e: + if e.args[0] == 'Label too long': + raise LabelTooLong + else: + raise IDNAException(idna_exception=e) + + def decode(self, label): + if not self.strict_decode: + return super().decode(label) + if label == b'': + return '' + if not have_idna_2008: + raise NoIDNA2008 + try: + ulabel = idna.ulabel(label) + if self.uts_46: + ulabel = idna.uts46_remap(ulabel, False, self.transitional) + return _escapify(ulabel) + except (idna.IDNAError, UnicodeError) as e: + raise IDNAException(idna_exception=e) + +_escaped = b'"().;\\@$' +_escaped_text = '"().;\\@$' + +IDNA_2003_Practical = IDNA2003Codec(False) +IDNA_2003_Strict = IDNA2003Codec(True) +IDNA_2003 = IDNA_2003_Practical +IDNA_2008_Practical = IDNA2008Codec(True, False, True, False) +IDNA_2008_UTS_46 = IDNA2008Codec(True, False, False, False) +IDNA_2008_Strict = IDNA2008Codec(False, False, False, True) +IDNA_2008_Transitional = IDNA2008Codec(True, True, False, False) +IDNA_2008 = IDNA_2008_Practical + +def _escapify(label): + """Escape the characters in label which need it. + @returns: the escaped string + @rtype: string""" + if isinstance(label, bytes): + # Ordinary DNS label mode. Escape special characters and values + # < 0x20 or > 0x7f. + text = '' + for c in label: + if c in _escaped: + text += '\\' + chr(c) + elif c > 0x20 and c < 0x7F: + text += chr(c) + else: + text += '\\%03d' % c + return text + + # Unicode label mode. Escape only special characters and values < 0x20 + text = '' + for c in label: + if c in _escaped_text: + text += '\\' + c + elif c <= '\x20': + text += '\\%03d' % ord(c) + else: + text += c + return text + +def _validate_labels(labels): + """Check for empty labels in the middle of a label sequence, + labels that are too long, and for too many labels. + + Raises ``dns.name.NameTooLong`` if the name as a whole is too long. + + Raises ``dns.name.EmptyLabel`` if a label is empty (i.e. the root + label) and appears in a position other than the end of the label + sequence + + """ + + l = len(labels) + total = 0 + i = -1 + j = 0 + for label in labels: + ll = len(label) + total += ll + 1 + if ll > 63: + raise LabelTooLong + if i < 0 and label == b'': + i = j + j += 1 + if total > 255: + raise NameTooLong + if i >= 0 and i != l - 1: + raise EmptyLabel + + +def _maybe_convert_to_binary(label): + """If label is ``str``, convert it to ``bytes``. If it is already + ``bytes`` just return it. + + """ + + if isinstance(label, bytes): + return label + if isinstance(label, str): + return label.encode() + raise ValueError # pragma: no cover + + +@dns.immutable.immutable +class Name: + + """A DNS name. + + The dns.name.Name class represents a DNS name as a tuple of + labels. Each label is a ``bytes`` in DNS wire format. Instances + of the class are immutable. + """ + + __slots__ = ['labels'] + + def __init__(self, labels): + """*labels* is any iterable whose values are ``str`` or ``bytes``. + """ + + labels = [_maybe_convert_to_binary(x) for x in labels] + self.labels = tuple(labels) + _validate_labels(self.labels) + + def __copy__(self): + return Name(self.labels) + + def __deepcopy__(self, memo): + return Name(copy.deepcopy(self.labels, memo)) + + def __getstate__(self): + # Names can be pickled + return {'labels': self.labels} + + def __setstate__(self, state): + super().__setattr__('labels', state['labels']) + _validate_labels(self.labels) + + def is_absolute(self): + """Is the most significant label of this name the root label? + + Returns a ``bool``. + """ + + return len(self.labels) > 0 and self.labels[-1] == b'' + + def is_wild(self): + """Is this name wild? (I.e. Is the least significant label '*'?) + + Returns a ``bool``. + """ + + return len(self.labels) > 0 and self.labels[0] == b'*' + + def __hash__(self): + """Return a case-insensitive hash of the name. + + Returns an ``int``. + """ + + h = 0 + for label in self.labels: + for c in label.lower(): + h += (h << 3) + c + return h + + def fullcompare(self, other): + """Compare two names, returning a 3-tuple + ``(relation, order, nlabels)``. + + *relation* describes the relation ship between the names, + and is one of: ``dns.name.NAMERELN_NONE``, + ``dns.name.NAMERELN_SUPERDOMAIN``, ``dns.name.NAMERELN_SUBDOMAIN``, + ``dns.name.NAMERELN_EQUAL``, or ``dns.name.NAMERELN_COMMONANCESTOR``. + + *order* is < 0 if *self* < *other*, > 0 if *self* > *other*, and == + 0 if *self* == *other*. A relative name is always less than an + absolute name. If both names have the same relativity, then + the DNSSEC order relation is used to order them. + + *nlabels* is the number of significant labels that the two names + have in common. + + Here are some examples. Names ending in "." are absolute names, + those not ending in "." are relative names. + + ============= ============= =========== ===== ======= + self other relation order nlabels + ============= ============= =========== ===== ======= + www.example. www.example. equal 0 3 + www.example. example. subdomain > 0 2 + example. www.example. superdomain < 0 2 + example1.com. example2.com. common anc. < 0 2 + example1 example2. none < 0 0 + example1. example2 none > 0 0 + ============= ============= =========== ===== ======= + """ + + sabs = self.is_absolute() + oabs = other.is_absolute() + if sabs != oabs: + if sabs: + return (NAMERELN_NONE, 1, 0) + else: + return (NAMERELN_NONE, -1, 0) + l1 = len(self.labels) + l2 = len(other.labels) + ldiff = l1 - l2 + if ldiff < 0: + l = l1 + else: + l = l2 + + order = 0 + nlabels = 0 + namereln = NAMERELN_NONE + while l > 0: + l -= 1 + l1 -= 1 + l2 -= 1 + label1 = self.labels[l1].lower() + label2 = other.labels[l2].lower() + if label1 < label2: + order = -1 + if nlabels > 0: + namereln = NAMERELN_COMMONANCESTOR + return (namereln, order, nlabels) + elif label1 > label2: + order = 1 + if nlabels > 0: + namereln = NAMERELN_COMMONANCESTOR + return (namereln, order, nlabels) + nlabels += 1 + order = ldiff + if ldiff < 0: + namereln = NAMERELN_SUPERDOMAIN + elif ldiff > 0: + namereln = NAMERELN_SUBDOMAIN + else: + namereln = NAMERELN_EQUAL + return (namereln, order, nlabels) + + def is_subdomain(self, other): + """Is self a subdomain of other? + + Note that the notion of subdomain includes equality, e.g. + "dnpython.org" is a subdomain of itself. + + Returns a ``bool``. + """ + + (nr, _, _) = self.fullcompare(other) + if nr == NAMERELN_SUBDOMAIN or nr == NAMERELN_EQUAL: + return True + return False + + def is_superdomain(self, other): + """Is self a superdomain of other? + + Note that the notion of superdomain includes equality, e.g. + "dnpython.org" is a superdomain of itself. + + Returns a ``bool``. + """ + + (nr, _, _) = self.fullcompare(other) + if nr == NAMERELN_SUPERDOMAIN or nr == NAMERELN_EQUAL: + return True + return False + + def canonicalize(self): + """Return a name which is equal to the current name, but is in + DNSSEC canonical form. + """ + + return Name([x.lower() for x in self.labels]) + + def __eq__(self, other): + if isinstance(other, Name): + return self.fullcompare(other)[1] == 0 + else: + return False + + def __ne__(self, other): + if isinstance(other, Name): + return self.fullcompare(other)[1] != 0 + else: + return True + + def __lt__(self, other): + if isinstance(other, Name): + return self.fullcompare(other)[1] < 0 + else: + return NotImplemented + + def __le__(self, other): + if isinstance(other, Name): + return self.fullcompare(other)[1] <= 0 + else: + return NotImplemented + + def __ge__(self, other): + if isinstance(other, Name): + return self.fullcompare(other)[1] >= 0 + else: + return NotImplemented + + def __gt__(self, other): + if isinstance(other, Name): + return self.fullcompare(other)[1] > 0 + else: + return NotImplemented + + def __repr__(self): + return '' + + def __str__(self): + return self.to_text(False) + + def to_text(self, omit_final_dot=False): + """Convert name to DNS text format. + + *omit_final_dot* is a ``bool``. If True, don't emit the final + dot (denoting the root label) for absolute names. The default + is False. + + Returns a ``str``. + """ + + if len(self.labels) == 0: + return '@' + if len(self.labels) == 1 and self.labels[0] == b'': + return '.' + if omit_final_dot and self.is_absolute(): + l = self.labels[:-1] + else: + l = self.labels + s = '.'.join(map(_escapify, l)) + return s + + def to_unicode(self, omit_final_dot=False, idna_codec=None): + """Convert name to Unicode text format. + + IDN ACE labels are converted to Unicode. + + *omit_final_dot* is a ``bool``. If True, don't emit the final + dot (denoting the root label) for absolute names. The default + is False. + *idna_codec* specifies the IDNA encoder/decoder. If None, the + dns.name.IDNA_2003_Practical encoder/decoder is used. + The IDNA_2003_Practical decoder does + not impose any policy, it just decodes punycode, so if you + don't want checking for compliance, you can use this decoder + for IDNA2008 as well. + + Returns a ``str``. + """ + + if len(self.labels) == 0: + return '@' + if len(self.labels) == 1 and self.labels[0] == b'': + return '.' + if omit_final_dot and self.is_absolute(): + l = self.labels[:-1] + else: + l = self.labels + if idna_codec is None: + idna_codec = IDNA_2003_Practical + return '.'.join([idna_codec.decode(x) for x in l]) + + def to_digestable(self, origin=None): + """Convert name to a format suitable for digesting in hashes. + + The name is canonicalized and converted to uncompressed wire + format. All names in wire format are absolute. If the name + is a relative name, then an origin must be supplied. + + *origin* is a ``dns.name.Name`` or ``None``. If the name is + relative and origin is not ``None``, then origin will be appended + to the name. + + Raises ``dns.name.NeedAbsoluteNameOrOrigin`` if the name is + relative and no origin was provided. + + Returns a ``bytes``. + """ + + return self.to_wire(origin=origin, canonicalize=True) + + def to_wire(self, file=None, compress=None, origin=None, + canonicalize=False): + """Convert name to wire format, possibly compressing it. + + *file* is the file where the name is emitted (typically an + io.BytesIO file). If ``None`` (the default), a ``bytes`` + containing the wire name will be returned. + + *compress*, a ``dict``, is the compression table to use. If + ``None`` (the default), names will not be compressed. Note that + the compression code assumes that compression offset 0 is the + start of *file*, and thus compression will not be correct + if this is not the case. + + *origin* is a ``dns.name.Name`` or ``None``. If the name is + relative and origin is not ``None``, then *origin* will be appended + to it. + + *canonicalize*, a ``bool``, indicates whether the name should + be canonicalized; that is, converted to a format suitable for + digesting in hashes. + + Raises ``dns.name.NeedAbsoluteNameOrOrigin`` if the name is + relative and no origin was provided. + + Returns a ``bytes`` or ``None``. + """ + + if file is None: + out = bytearray() + for label in self.labels: + out.append(len(label)) + if canonicalize: + out += label.lower() + else: + out += label + if not self.is_absolute(): + if origin is None or not origin.is_absolute(): + raise NeedAbsoluteNameOrOrigin + for label in origin.labels: + out.append(len(label)) + if canonicalize: + out += label.lower() + else: + out += label + return bytes(out) + + if not self.is_absolute(): + if origin is None or not origin.is_absolute(): + raise NeedAbsoluteNameOrOrigin + labels = list(self.labels) + labels.extend(list(origin.labels)) + else: + labels = self.labels + i = 0 + for label in labels: + n = Name(labels[i:]) + i += 1 + if compress is not None: + pos = compress.get(n) + else: + pos = None + if pos is not None: + value = 0xc000 + pos + s = struct.pack('!H', value) + file.write(s) + break + else: + if compress is not None and len(n) > 1: + pos = file.tell() + if pos <= 0x3fff: + compress[n] = pos + l = len(label) + file.write(struct.pack('!B', l)) + if l > 0: + if canonicalize: + file.write(label.lower()) + else: + file.write(label) + + def __len__(self): + """The length of the name (in labels). + + Returns an ``int``. + """ + + return len(self.labels) + + def __getitem__(self, index): + return self.labels[index] + + def __add__(self, other): + return self.concatenate(other) + + def __sub__(self, other): + return self.relativize(other) + + def split(self, depth): + """Split a name into a prefix and suffix names at the specified depth. + + *depth* is an ``int`` specifying the number of labels in the suffix + + Raises ``ValueError`` if *depth* was not >= 0 and <= the length of the + name. + + Returns the tuple ``(prefix, suffix)``. + """ + + l = len(self.labels) + if depth == 0: + return (self, dns.name.empty) + elif depth == l: + return (dns.name.empty, self) + elif depth < 0 or depth > l: + raise ValueError( + 'depth must be >= 0 and <= the length of the name') + return (Name(self[: -depth]), Name(self[-depth:])) + + def concatenate(self, other): + """Return a new name which is the concatenation of self and other. + + Raises ``dns.name.AbsoluteConcatenation`` if the name is + absolute and *other* is not the empty name. + + Returns a ``dns.name.Name``. + """ + + if self.is_absolute() and len(other) > 0: + raise AbsoluteConcatenation + labels = list(self.labels) + labels.extend(list(other.labels)) + return Name(labels) + + def relativize(self, origin): + """If the name is a subdomain of *origin*, return a new name which is + the name relative to origin. Otherwise return the name. + + For example, relativizing ``www.dnspython.org.`` to origin + ``dnspython.org.`` returns the name ``www``. Relativizing ``example.`` + to origin ``dnspython.org.`` returns ``example.``. + + Returns a ``dns.name.Name``. + """ + + if origin is not None and self.is_subdomain(origin): + return Name(self[: -len(origin)]) + else: + return self + + def derelativize(self, origin): + """If the name is a relative name, return a new name which is the + concatenation of the name and origin. Otherwise return the name. + + For example, derelativizing ``www`` to origin ``dnspython.org.`` + returns the name ``www.dnspython.org.``. Derelativizing ``example.`` + to origin ``dnspython.org.`` returns ``example.``. + + Returns a ``dns.name.Name``. + """ + + if not self.is_absolute(): + return self.concatenate(origin) + else: + return self + + def choose_relativity(self, origin=None, relativize=True): + """Return a name with the relativity desired by the caller. + + If *origin* is ``None``, then the name is returned. + Otherwise, if *relativize* is ``True`` the name is + relativized, and if *relativize* is ``False`` the name is + derelativized. + + Returns a ``dns.name.Name``. + """ + + if origin: + if relativize: + return self.relativize(origin) + else: + return self.derelativize(origin) + else: + return self + + def parent(self): + """Return the parent of the name. + + For example, the parent of ``www.dnspython.org.`` is ``dnspython.org``. + + Raises ``dns.name.NoParent`` if the name is either the root name or the + empty name, and thus has no parent. + + Returns a ``dns.name.Name``. + """ + + if self == root or self == empty: + raise NoParent + return Name(self.labels[1:]) + +#: The root name, '.' +root = Name([b'']) + +#: The empty name. +empty = Name([]) + +def from_unicode(text, origin=root, idna_codec=None): + """Convert unicode text into a Name object. + + Labels are encoded in IDN ACE form according to rules specified by + the IDNA codec. + + *text*, a ``str``, is the text to convert into a name. + + *origin*, a ``dns.name.Name``, specifies the origin to + append to non-absolute names. The default is the root name. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder + is used. + + Returns a ``dns.name.Name``. + """ + + if not isinstance(text, str): + raise ValueError("input to from_unicode() must be a unicode string") + if not (origin is None or isinstance(origin, Name)): + raise ValueError("origin must be a Name or None") + labels = [] + label = '' + escaping = False + edigits = 0 + total = 0 + if idna_codec is None: + idna_codec = IDNA_2003 + if text == '@': + text = '' + if text: + if text in ['.', '\u3002', '\uff0e', '\uff61']: + return Name([b'']) # no Unicode "u" on this constant! + for c in text: + if escaping: + if edigits == 0: + if c.isdigit(): + total = int(c) + edigits += 1 + else: + label += c + escaping = False + else: + if not c.isdigit(): + raise BadEscape + total *= 10 + total += int(c) + edigits += 1 + if edigits == 3: + escaping = False + label += chr(total) + elif c in ['.', '\u3002', '\uff0e', '\uff61']: + if len(label) == 0: + raise EmptyLabel + labels.append(idna_codec.encode(label)) + label = '' + elif c == '\\': + escaping = True + edigits = 0 + total = 0 + else: + label += c + if escaping: + raise BadEscape + if len(label) > 0: + labels.append(idna_codec.encode(label)) + else: + labels.append(b'') + + if (len(labels) == 0 or labels[-1] != b'') and origin is not None: + labels.extend(list(origin.labels)) + return Name(labels) + +def is_all_ascii(text): + for c in text: + if ord(c) > 0x7f: + return False + return True + +def from_text(text, origin=root, idna_codec=None): + """Convert text into a Name object. + + *text*, a ``str``, is the text to convert into a name. + + *origin*, a ``dns.name.Name``, specifies the origin to + append to non-absolute names. The default is the root name. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder + is used. + + Returns a ``dns.name.Name``. + """ + + if isinstance(text, str): + if not is_all_ascii(text): + # Some codepoint in the input text is > 127, so IDNA applies. + return from_unicode(text, origin, idna_codec) + # The input is all ASCII, so treat this like an ordinary non-IDNA + # domain name. Note that "all ASCII" is about the input text, + # not the codepoints in the domain name. E.g. if text has value + # + # r'\150\151\152\153\154\155\156\157\158\159' + # + # then it's still "all ASCII" even though the domain name has + # codepoints > 127. + text = text.encode('ascii') + if not isinstance(text, bytes): + raise ValueError("input to from_text() must be a string") + if not (origin is None or isinstance(origin, Name)): + raise ValueError("origin must be a Name or None") + labels = [] + label = b'' + escaping = False + edigits = 0 + total = 0 + if text == b'@': + text = b'' + if text: + if text == b'.': + return Name([b'']) + for c in text: + byte_ = struct.pack('!B', c) + if escaping: + if edigits == 0: + if byte_.isdigit(): + total = int(byte_) + edigits += 1 + else: + label += byte_ + escaping = False + else: + if not byte_.isdigit(): + raise BadEscape + total *= 10 + total += int(byte_) + edigits += 1 + if edigits == 3: + escaping = False + label += struct.pack('!B', total) + elif byte_ == b'.': + if len(label) == 0: + raise EmptyLabel + labels.append(label) + label = b'' + elif byte_ == b'\\': + escaping = True + edigits = 0 + total = 0 + else: + label += byte_ + if escaping: + raise BadEscape + if len(label) > 0: + labels.append(label) + else: + labels.append(b'') + if (len(labels) == 0 or labels[-1] != b'') and origin is not None: + labels.extend(list(origin.labels)) + return Name(labels) + + +def from_wire_parser(parser): + """Convert possibly compressed wire format into a Name. + + *parser* is a dns.wire.Parser. + + Raises ``dns.name.BadPointer`` if a compression pointer did not + point backwards in the message. + + Raises ``dns.name.BadLabelType`` if an invalid label type was encountered. + + Returns a ``dns.name.Name`` + """ + + labels = [] + biggest_pointer = parser.current + with parser.restore_furthest(): + count = parser.get_uint8() + while count != 0: + if count < 64: + labels.append(parser.get_bytes(count)) + elif count >= 192: + current = (count & 0x3f) * 256 + parser.get_uint8() + if current >= biggest_pointer: + raise BadPointer + biggest_pointer = current + parser.seek(current) + else: + raise BadLabelType + count = parser.get_uint8() + labels.append(b'') + return Name(labels) + + +def from_wire(message, current): + """Convert possibly compressed wire format into a Name. + + *message* is a ``bytes`` containing an entire DNS message in DNS + wire form. + + *current*, an ``int``, is the offset of the beginning of the name + from the start of the message + + Raises ``dns.name.BadPointer`` if a compression pointer did not + point backwards in the message. + + Raises ``dns.name.BadLabelType`` if an invalid label type was encountered. + + Returns a ``(dns.name.Name, int)`` tuple consisting of the name + that was read and the number of bytes of the wire format message + which were consumed reading it. + """ + + if not isinstance(message, bytes): + raise ValueError("input to from_wire() must be a byte string") + parser = dns.wire.Parser(message, current) + name = from_wire_parser(parser) + return (name, parser.current - current) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/namedict.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/namedict.py new file mode 100644 index 0000000..4c8f9ab --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/namedict.py @@ -0,0 +1,108 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# Copyright (C) 2016 Coresec Systems AB +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND CORESEC SYSTEMS AB DISCLAIMS ALL +# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CORESEC +# SYSTEMS AB BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS name dictionary""" + +from collections.abc import MutableMapping + +import dns.name + + +class NameDict(MutableMapping): + """A dictionary whose keys are dns.name.Name objects. + + In addition to being like a regular Python dictionary, this + dictionary can also get the deepest match for a given key. + """ + + __slots__ = ["max_depth", "max_depth_items", "__store"] + + def __init__(self, *args, **kwargs): + super().__init__() + self.__store = dict() + #: the maximum depth of the keys that have ever been added + self.max_depth = 0 + #: the number of items of maximum depth + self.max_depth_items = 0 + self.update(dict(*args, **kwargs)) + + def __update_max_depth(self, key): + if len(key) == self.max_depth: + self.max_depth_items = self.max_depth_items + 1 + elif len(key) > self.max_depth: + self.max_depth = len(key) + self.max_depth_items = 1 + + def __getitem__(self, key): + return self.__store[key] + + def __setitem__(self, key, value): + if not isinstance(key, dns.name.Name): + raise ValueError('NameDict key must be a name') + self.__store[key] = value + self.__update_max_depth(key) + + def __delitem__(self, key): + self.__store.pop(key) + if len(key) == self.max_depth: + self.max_depth_items = self.max_depth_items - 1 + if self.max_depth_items == 0: + self.max_depth = 0 + for k in self.__store: + self.__update_max_depth(k) + + def __iter__(self): + return iter(self.__store) + + def __len__(self): + return len(self.__store) + + def has_key(self, key): + return key in self.__store + + def get_deepest_match(self, name): + """Find the deepest match to *fname* in the dictionary. + + The deepest match is the longest name in the dictionary which is + a superdomain of *name*. Note that *superdomain* includes matching + *name* itself. + + *name*, a ``dns.name.Name``, the name to find. + + Returns a ``(key, value)`` where *key* is the deepest + ``dns.name.Name``, and *value* is the value associated with *key*. + """ + + depth = len(name) + if depth > self.max_depth: + depth = self.max_depth + for i in range(-depth, 0): + n = dns.name.Name(name[i:]) + if n in self: + return (n, self[n]) + v = self[dns.name.empty] + return (dns.name.empty, v) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/node.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/node.py new file mode 100644 index 0000000..b1baf27 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/node.py @@ -0,0 +1,189 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS nodes. A node is a set of rdatasets.""" + +import io + +import dns.rdataset +import dns.rdatatype +import dns.renderer + + +class Node: + + """A Node is a set of rdatasets.""" + + __slots__ = ['rdatasets'] + + def __init__(self): + # the set of rdatasets, represented as a list. + self.rdatasets = [] + + def to_text(self, name, **kw): + """Convert a node to text format. + + Each rdataset at the node is printed. Any keyword arguments + to this method are passed on to the rdataset's to_text() method. + + *name*, a ``dns.name.Name`` or ``str``, the owner name of the + rdatasets. + + Returns a ``str``. + + """ + + s = io.StringIO() + for rds in self.rdatasets: + if len(rds) > 0: + s.write(rds.to_text(name, **kw)) + s.write('\n') + return s.getvalue()[:-1] + + def __repr__(self): + return '' + + def __eq__(self, other): + # + # This is inefficient. Good thing we don't need to do it much. + # + for rd in self.rdatasets: + if rd not in other.rdatasets: + return False + for rd in other.rdatasets: + if rd not in self.rdatasets: + return False + return True + + def __ne__(self, other): + return not self.__eq__(other) + + def __len__(self): + return len(self.rdatasets) + + def __iter__(self): + return iter(self.rdatasets) + + def find_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE, + create=False): + """Find an rdataset matching the specified properties in the + current node. + + *rdclass*, an ``int``, the class of the rdataset. + + *rdtype*, an ``int``, the type of the rdataset. + + *covers*, an ``int`` or ``None``, the covered type. + Usually this value is ``dns.rdatatype.NONE``, but if the + rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, + then the covers value will be the rdata type the SIG/RRSIG + covers. The library treats the SIG and RRSIG types as if they + were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). + This makes RRSIGs much easier to work with than if RRSIGs + covering different rdata types were aggregated into a single + RRSIG rdataset. + + *create*, a ``bool``. If True, create the rdataset if it is not found. + + Raises ``KeyError`` if an rdataset of the desired type and class does + not exist and *create* is not ``True``. + + Returns a ``dns.rdataset.Rdataset``. + """ + + for rds in self.rdatasets: + if rds.match(rdclass, rdtype, covers): + return rds + if not create: + raise KeyError + rds = dns.rdataset.Rdataset(rdclass, rdtype) + self.rdatasets.append(rds) + return rds + + def get_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE, + create=False): + """Get an rdataset matching the specified properties in the + current node. + + None is returned if an rdataset of the specified type and + class does not exist and *create* is not ``True``. + + *rdclass*, an ``int``, the class of the rdataset. + + *rdtype*, an ``int``, the type of the rdataset. + + *covers*, an ``int``, the covered type. Usually this value is + dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or + dns.rdatatype.RRSIG, then the covers value will be the rdata + type the SIG/RRSIG covers. The library treats the SIG and RRSIG + types as if they were a family of + types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much + easier to work with than if RRSIGs covering different rdata + types were aggregated into a single RRSIG rdataset. + + *create*, a ``bool``. If True, create the rdataset if it is not found. + + Returns a ``dns.rdataset.Rdataset`` or ``None``. + """ + + try: + rds = self.find_rdataset(rdclass, rdtype, covers, create) + except KeyError: + rds = None + return rds + + def delete_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE): + """Delete the rdataset matching the specified properties in the + current node. + + If a matching rdataset does not exist, it is not an error. + + *rdclass*, an ``int``, the class of the rdataset. + + *rdtype*, an ``int``, the type of the rdataset. + + *covers*, an ``int``, the covered type. + """ + + rds = self.get_rdataset(rdclass, rdtype, covers) + if rds is not None: + self.rdatasets.remove(rds) + + def replace_rdataset(self, replacement): + """Replace an rdataset. + + It is not an error if there is no rdataset matching *replacement*. + + Ownership of the *replacement* object is transferred to the node; + in other words, this method does not store a copy of *replacement* + at the node, it stores *replacement* itself. + + *replacement*, a ``dns.rdataset.Rdataset``. + + Raises ``ValueError`` if *replacement* is not a + ``dns.rdataset.Rdataset``. + """ + + if not isinstance(replacement, dns.rdataset.Rdataset): + raise ValueError('replacement is not an rdataset') + if isinstance(replacement, dns.rrset.RRset): + # RRsets are not good replacements as the match() method + # is not compatible. + replacement = replacement.to_rdataset() + self.delete_rdataset(replacement.rdclass, replacement.rdtype, + replacement.covers) + self.rdatasets.append(replacement) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/opcode.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/opcode.py new file mode 100644 index 0000000..5cf6143 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/opcode.py @@ -0,0 +1,115 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Opcodes.""" + +import dns.enum +import dns.exception + +class Opcode(dns.enum.IntEnum): + #: Query + QUERY = 0 + #: Inverse Query (historical) + IQUERY = 1 + #: Server Status (unspecified and unimplemented anywhere) + STATUS = 2 + #: Notify + NOTIFY = 4 + #: Dynamic Update + UPDATE = 5 + + @classmethod + def _maximum(cls): + return 15 + + @classmethod + def _unknown_exception_class(cls): + return UnknownOpcode + + +class UnknownOpcode(dns.exception.DNSException): + """An DNS opcode is unknown.""" + + +def from_text(text): + """Convert text into an opcode. + + *text*, a ``str``, the textual opcode + + Raises ``dns.opcode.UnknownOpcode`` if the opcode is unknown. + + Returns an ``int``. + """ + + return Opcode.from_text(text) + + +def from_flags(flags): + """Extract an opcode from DNS message flags. + + *flags*, an ``int``, the DNS flags. + + Returns an ``int``. + """ + + return (flags & 0x7800) >> 11 + + +def to_flags(value): + """Convert an opcode to a value suitable for ORing into DNS message + flags. + + *value*, an ``int``, the DNS opcode value. + + Returns an ``int``. + """ + + return (value << 11) & 0x7800 + + +def to_text(value): + """Convert an opcode to text. + + *value*, an ``int`` the opcode value, + + Raises ``dns.opcode.UnknownOpcode`` if the opcode is unknown. + + Returns a ``str``. + """ + + return Opcode.to_text(value) + + +def is_update(flags): + """Is the opcode in flags UPDATE? + + *flags*, an ``int``, the DNS message flags. + + Returns a ``bool``. + """ + + return from_flags(flags) == Opcode.UPDATE + +### BEGIN generated Opcode constants + +QUERY = Opcode.QUERY +IQUERY = Opcode.IQUERY +STATUS = Opcode.STATUS +NOTIFY = Opcode.NOTIFY +UPDATE = Opcode.UPDATE + +### END generated Opcode constants diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/py.typed b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/query.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/query.py new file mode 100644 index 0000000..bd62a7a --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/query.py @@ -0,0 +1,1094 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Talk to a DNS server.""" + +import contextlib +import enum +import errno +import os +import selectors +import socket +import struct +import time +import base64 +import urllib.parse + +import dns.exception +import dns.inet +import dns.name +import dns.message +import dns.rcode +import dns.rdataclass +import dns.rdatatype +import dns.serial +import dns.xfr + +try: + import requests + from requests_toolbelt.adapters.source import SourceAddressAdapter + from requests_toolbelt.adapters.host_header_ssl import HostHeaderSSLAdapter + have_doh = True +except ImportError: # pragma: no cover + have_doh = False + +try: + import ssl +except ImportError: # pragma: no cover + class ssl: # type: ignore + + class WantReadException(Exception): + pass + + class WantWriteException(Exception): + pass + + class SSLSocket: + pass + + def create_default_context(self, *args, **kwargs): + raise Exception('no ssl support') + +# Function used to create a socket. Can be overridden if needed in special +# situations. +socket_factory = socket.socket + +class UnexpectedSource(dns.exception.DNSException): + """A DNS query response came from an unexpected address or port.""" + + +class BadResponse(dns.exception.FormError): + """A DNS query response does not respond to the question asked.""" + + +class NoDOH(dns.exception.DNSException): + """DNS over HTTPS (DOH) was requested but the requests module is not + available.""" + + +# for backwards compatibility +TransferError = dns.xfr.TransferError + + +def _compute_times(timeout): + now = time.time() + if timeout is None: + return (now, None) + else: + return (now, now + timeout) + + +def _wait_for(fd, readable, writable, _, expiration): + # Use the selected selector class to wait for any of the specified + # events. An "expiration" absolute time is converted into a relative + # timeout. + # + # The unused parameter is 'error', which is always set when + # selecting for read or write, and we have no error-only selects. + + if readable and isinstance(fd, ssl.SSLSocket) and fd.pending() > 0: + return True + sel = _selector_class() + events = 0 + if readable: + events |= selectors.EVENT_READ + if writable: + events |= selectors.EVENT_WRITE + if events: + sel.register(fd, events) + if expiration is None: + timeout = None + else: + timeout = expiration - time.time() + if timeout <= 0.0: + raise dns.exception.Timeout + if not sel.select(timeout): + raise dns.exception.Timeout + + +def _set_selector_class(selector_class): + # Internal API. Do not use. + + global _selector_class + + _selector_class = selector_class + +if hasattr(selectors, 'PollSelector'): + # Prefer poll() on platforms that support it because it has no + # limits on the maximum value of a file descriptor (plus it will + # be more efficient for high values). + _selector_class = selectors.PollSelector +else: + _selector_class = selectors.SelectSelector # pragma: no cover + + +def _wait_for_readable(s, expiration): + _wait_for(s, True, False, True, expiration) + + +def _wait_for_writable(s, expiration): + _wait_for(s, False, True, True, expiration) + + +def _addresses_equal(af, a1, a2): + # Convert the first value of the tuple, which is a textual format + # address into binary form, so that we are not confused by different + # textual representations of the same address + try: + n1 = dns.inet.inet_pton(af, a1[0]) + n2 = dns.inet.inet_pton(af, a2[0]) + except dns.exception.SyntaxError: + return False + return n1 == n2 and a1[1:] == a2[1:] + + +def _matches_destination(af, from_address, destination, ignore_unexpected): + # Check that from_address is appropriate for a response to a query + # sent to destination. + if not destination: + return True + if _addresses_equal(af, from_address, destination) or \ + (dns.inet.is_multicast(destination[0]) and + from_address[1:] == destination[1:]): + return True + elif ignore_unexpected: + return False + raise UnexpectedSource(f'got a response from {from_address} instead of ' + f'{destination}') + + +def _destination_and_source(where, port, source, source_port, + where_must_be_address=True): + # Apply defaults and compute destination and source tuples + # suitable for use in connect(), sendto(), or bind(). + af = None + destination = None + try: + af = dns.inet.af_for_address(where) + destination = where + except Exception: + if where_must_be_address: + raise + # URLs are ok so eat the exception + if source: + saf = dns.inet.af_for_address(source) + if af: + # We know the destination af, so source had better agree! + if saf != af: + raise ValueError('different address families for source ' + + 'and destination') + else: + # We didn't know the destination af, but we know the source, + # so that's our af. + af = saf + if source_port and not source: + # Caller has specified a source_port but not an address, so we + # need to return a source, and we need to use the appropriate + # wildcard address as the address. + if af == socket.AF_INET: + source = '0.0.0.0' + elif af == socket.AF_INET6: + source = '::' + else: + raise ValueError('source_port specified but address family is ' + 'unknown') + # Convert high-level (address, port) tuples into low-level address + # tuples. + if destination: + destination = dns.inet.low_level_address_tuple((destination, port), af) + if source: + source = dns.inet.low_level_address_tuple((source, source_port), af) + return (af, destination, source) + +def _make_socket(af, type, source, ssl_context=None, server_hostname=None): + s = socket_factory(af, type) + try: + s.setblocking(False) + if source is not None: + s.bind(source) + if ssl_context: + return ssl_context.wrap_socket(s, do_handshake_on_connect=False, + server_hostname=server_hostname) + else: + return s + except Exception: + s.close() + raise + +def https(q, where, timeout=None, port=443, source=None, source_port=0, + one_rr_per_rrset=False, ignore_trailing=False, + session=None, path='/dns-query', post=True, + bootstrap_address=None, verify=True): + """Return the response obtained after sending a query via DNS-over-HTTPS. + + *q*, a ``dns.message.Message``, the query to send. + + *where*, a ``str``, the nameserver IP address or the full URL. If an IP + address is given, the URL will be constructed using the following schema: + https://:/. + + *timeout*, a ``float`` or ``None``, the number of seconds to + wait before the query times out. If ``None``, the default, wait forever. + + *port*, a ``int``, the port to send the query to. The default is 443. + + *source*, a ``str`` containing an IPv4 or IPv6 address, specifying + the source address. The default is the wildcard address. + + *source_port*, an ``int``, the port from which to send the message. + The default is 0. + + *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own + RRset. + + *ignore_trailing*, a ``bool``. If ``True``, ignore trailing + junk at end of the received message. + + *session*, a ``requests.session.Session``. If provided, the session to use + to send the queries. + + *path*, a ``str``. If *where* is an IP address, then *path* will be used to + construct the URL to send the DNS query to. + + *post*, a ``bool``. If ``True``, the default, POST method will be used. + + *bootstrap_address*, a ``str``, the IP address to use to bypass the + system's DNS resolver. + + *verify*, a ``str``, containing a path to a certificate file or directory. + + Returns a ``dns.message.Message``. + """ + + if not have_doh: + raise NoDOH # pragma: no cover + + wire = q.to_wire() + (af, _, source) = _destination_and_source(where, port, source, source_port, + False) + transport_adapter = None + headers = { + "accept": "application/dns-message" + } + if af is not None: + if af == socket.AF_INET: + url = 'https://{}:{}{}'.format(where, port, path) + elif af == socket.AF_INET6: + url = 'https://[{}]:{}{}'.format(where, port, path) + elif bootstrap_address is not None: + split_url = urllib.parse.urlsplit(where) + headers['Host'] = split_url.hostname + url = where.replace(split_url.hostname, bootstrap_address) + transport_adapter = HostHeaderSSLAdapter() + else: + url = where + if source is not None: + # set source port and source address + transport_adapter = SourceAddressAdapter(source) + + with contextlib.ExitStack() as stack: + if not session: + session = stack.enter_context(requests.sessions.Session()) + + if transport_adapter: + session.mount(url, transport_adapter) + + # see https://tools.ietf.org/html/rfc8484#section-4.1.1 for DoH + # GET and POST examples + if post: + headers.update({ + "content-type": "application/dns-message", + "content-length": str(len(wire)) + }) + response = session.post(url, headers=headers, data=wire, + timeout=timeout, verify=verify) + else: + wire = base64.urlsafe_b64encode(wire).rstrip(b"=") + response = session.get(url, headers=headers, + timeout=timeout, verify=verify, + params={"dns": wire}) + + # see https://tools.ietf.org/html/rfc8484#section-4.2.1 for info about DoH + # status codes + if response.status_code < 200 or response.status_code > 299: + raise ValueError('{} responded with status code {}' + '\nResponse body: {}'.format(where, + response.status_code, + response.content)) + r = dns.message.from_wire(response.content, + keyring=q.keyring, + request_mac=q.request_mac, + one_rr_per_rrset=one_rr_per_rrset, + ignore_trailing=ignore_trailing) + r.time = response.elapsed + if not q.is_response(r): + raise BadResponse + return r + +def _udp_recv(sock, max_size, expiration): + """Reads a datagram from the socket. + A Timeout exception will be raised if the operation is not completed + by the expiration time. + """ + while True: + try: + return sock.recvfrom(max_size) + except BlockingIOError: + _wait_for_readable(sock, expiration) + + +def _udp_send(sock, data, destination, expiration): + """Sends the specified datagram to destination over the socket. + A Timeout exception will be raised if the operation is not completed + by the expiration time. + """ + while True: + try: + if destination: + return sock.sendto(data, destination) + else: + return sock.send(data) + except BlockingIOError: # pragma: no cover + _wait_for_writable(sock, expiration) + + +def send_udp(sock, what, destination, expiration=None): + """Send a DNS message to the specified UDP socket. + + *sock*, a ``socket``. + + *what*, a ``bytes`` or ``dns.message.Message``, the message to send. + + *destination*, a destination tuple appropriate for the address family + of the socket, specifying where to send the query. + + *expiration*, a ``float`` or ``None``, the absolute time at which + a timeout exception should be raised. If ``None``, no timeout will + occur. + + Returns an ``(int, float)`` tuple of bytes sent and the sent time. + """ + + if isinstance(what, dns.message.Message): + what = what.to_wire() + sent_time = time.time() + n = _udp_send(sock, what, destination, expiration) + return (n, sent_time) + + +def receive_udp(sock, destination=None, expiration=None, + ignore_unexpected=False, one_rr_per_rrset=False, + keyring=None, request_mac=b'', ignore_trailing=False, + raise_on_truncation=False): + """Read a DNS message from a UDP socket. + + *sock*, a ``socket``. + + *destination*, a destination tuple appropriate for the address family + of the socket, specifying where the message is expected to arrive from. + When receiving a response, this would be where the associated query was + sent. + + *expiration*, a ``float`` or ``None``, the absolute time at which + a timeout exception should be raised. If ``None``, no timeout will + occur. + + *ignore_unexpected*, a ``bool``. If ``True``, ignore responses from + unexpected sources. + + *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own + RRset. + + *keyring*, a ``dict``, the keyring to use for TSIG. + + *request_mac*, a ``bytes``, the MAC of the request (for TSIG). + + *ignore_trailing*, a ``bool``. If ``True``, ignore trailing + junk at end of the received message. + + *raise_on_truncation*, a ``bool``. If ``True``, raise an exception if + the TC bit is set. + + Raises if the message is malformed, if network errors occur, of if + there is a timeout. + + If *destination* is not ``None``, returns a ``(dns.message.Message, float)`` + tuple of the received message and the received time. + + If *destination* is ``None``, returns a + ``(dns.message.Message, float, tuple)`` + tuple of the received message, the received time, and the address where + the message arrived from. + """ + + wire = b'' + while True: + (wire, from_address) = _udp_recv(sock, 65535, expiration) + if _matches_destination(sock.family, from_address, destination, + ignore_unexpected): + break + received_time = time.time() + r = dns.message.from_wire(wire, keyring=keyring, request_mac=request_mac, + one_rr_per_rrset=one_rr_per_rrset, + ignore_trailing=ignore_trailing, + raise_on_truncation=raise_on_truncation) + if destination: + return (r, received_time) + else: + return (r, received_time, from_address) + +def udp(q, where, timeout=None, port=53, source=None, source_port=0, + ignore_unexpected=False, one_rr_per_rrset=False, ignore_trailing=False, + raise_on_truncation=False, sock=None): + """Return the response obtained after sending a query via UDP. + + *q*, a ``dns.message.Message``, the query to send + + *where*, a ``str`` containing an IPv4 or IPv6 address, where + to send the message. + + *timeout*, a ``float`` or ``None``, the number of seconds to wait before the + query times out. If ``None``, the default, wait forever. + + *port*, an ``int``, the port send the message to. The default is 53. + + *source*, a ``str`` containing an IPv4 or IPv6 address, specifying + the source address. The default is the wildcard address. + + *source_port*, an ``int``, the port from which to send the message. + The default is 0. + + *ignore_unexpected*, a ``bool``. If ``True``, ignore responses from + unexpected sources. + + *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own + RRset. + + *ignore_trailing*, a ``bool``. If ``True``, ignore trailing + junk at end of the received message. + + *raise_on_truncation*, a ``bool``. If ``True``, raise an exception if + the TC bit is set. + + *sock*, a ``socket.socket``, or ``None``, the socket to use for the + query. If ``None``, the default, a socket is created. Note that + if a socket is provided, it must be a nonblocking datagram socket, + and the *source* and *source_port* are ignored. + + Returns a ``dns.message.Message``. + """ + + wire = q.to_wire() + (af, destination, source) = _destination_and_source(where, port, + source, source_port) + (begin_time, expiration) = _compute_times(timeout) + with contextlib.ExitStack() as stack: + if sock: + s = sock + else: + s = stack.enter_context(_make_socket(af, socket.SOCK_DGRAM, source)) + send_udp(s, wire, destination, expiration) + (r, received_time) = receive_udp(s, destination, expiration, + ignore_unexpected, one_rr_per_rrset, + q.keyring, q.mac, ignore_trailing, + raise_on_truncation) + r.time = received_time - begin_time + if not q.is_response(r): + raise BadResponse + return r + +def udp_with_fallback(q, where, timeout=None, port=53, source=None, + source_port=0, ignore_unexpected=False, + one_rr_per_rrset=False, ignore_trailing=False, + udp_sock=None, tcp_sock=None): + """Return the response to the query, trying UDP first and falling back + to TCP if UDP results in a truncated response. + + *q*, a ``dns.message.Message``, the query to send + + *where*, a ``str`` containing an IPv4 or IPv6 address, where + to send the message. + + *timeout*, a ``float`` or ``None``, the number of seconds to wait before the + query times out. If ``None``, the default, wait forever. + + *port*, an ``int``, the port send the message to. The default is 53. + + *source*, a ``str`` containing an IPv4 or IPv6 address, specifying + the source address. The default is the wildcard address. + + *source_port*, an ``int``, the port from which to send the message. + The default is 0. + + *ignore_unexpected*, a ``bool``. If ``True``, ignore responses from + unexpected sources. + + *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own + RRset. + + *ignore_trailing*, a ``bool``. If ``True``, ignore trailing + junk at end of the received message. + + *udp_sock*, a ``socket.socket``, or ``None``, the socket to use for the + UDP query. If ``None``, the default, a socket is created. Note that + if a socket is provided, it must be a nonblocking datagram socket, + and the *source* and *source_port* are ignored for the UDP query. + + *tcp_sock*, a ``socket.socket``, or ``None``, the socket to use for the + TCP query. If ``None``, the default, a socket is created. Note that + if a socket is provided, it must be a nonblocking connected stream + socket, and *where*, *source* and *source_port* are ignored for the TCP + query. + + Returns a (``dns.message.Message``, tcp) tuple where tcp is ``True`` + if and only if TCP was used. + """ + try: + response = udp(q, where, timeout, port, source, source_port, + ignore_unexpected, one_rr_per_rrset, + ignore_trailing, True, udp_sock) + return (response, False) + except dns.message.Truncated: + response = tcp(q, where, timeout, port, source, source_port, + one_rr_per_rrset, ignore_trailing, tcp_sock) + return (response, True) + +def _net_read(sock, count, expiration): + """Read the specified number of bytes from sock. Keep trying until we + either get the desired amount, or we hit EOF. + A Timeout exception will be raised if the operation is not completed + by the expiration time. + """ + s = b'' + while count > 0: + try: + n = sock.recv(count) + if n == b'': + raise EOFError + count -= len(n) + s += n + except (BlockingIOError, ssl.SSLWantReadError): + _wait_for_readable(sock, expiration) + except ssl.SSLWantWriteError: # pragma: no cover + _wait_for_writable(sock, expiration) + return s + + +def _net_write(sock, data, expiration): + """Write the specified data to the socket. + A Timeout exception will be raised if the operation is not completed + by the expiration time. + """ + current = 0 + l = len(data) + while current < l: + try: + current += sock.send(data[current:]) + except (BlockingIOError, ssl.SSLWantWriteError): + _wait_for_writable(sock, expiration) + except ssl.SSLWantReadError: # pragma: no cover + _wait_for_readable(sock, expiration) + + +def send_tcp(sock, what, expiration=None): + """Send a DNS message to the specified TCP socket. + + *sock*, a ``socket``. + + *what*, a ``bytes`` or ``dns.message.Message``, the message to send. + + *expiration*, a ``float`` or ``None``, the absolute time at which + a timeout exception should be raised. If ``None``, no timeout will + occur. + + Returns an ``(int, float)`` tuple of bytes sent and the sent time. + """ + + if isinstance(what, dns.message.Message): + what = what.to_wire() + l = len(what) + # copying the wire into tcpmsg is inefficient, but lets us + # avoid writev() or doing a short write that would get pushed + # onto the net + tcpmsg = struct.pack("!H", l) + what + sent_time = time.time() + _net_write(sock, tcpmsg, expiration) + return (len(tcpmsg), sent_time) + +def receive_tcp(sock, expiration=None, one_rr_per_rrset=False, + keyring=None, request_mac=b'', ignore_trailing=False): + """Read a DNS message from a TCP socket. + + *sock*, a ``socket``. + + *expiration*, a ``float`` or ``None``, the absolute time at which + a timeout exception should be raised. If ``None``, no timeout will + occur. + + *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own + RRset. + + *keyring*, a ``dict``, the keyring to use for TSIG. + + *request_mac*, a ``bytes``, the MAC of the request (for TSIG). + + *ignore_trailing*, a ``bool``. If ``True``, ignore trailing + junk at end of the received message. + + Raises if the message is malformed, if network errors occur, of if + there is a timeout. + + Returns a ``(dns.message.Message, float)`` tuple of the received message + and the received time. + """ + + ldata = _net_read(sock, 2, expiration) + (l,) = struct.unpack("!H", ldata) + wire = _net_read(sock, l, expiration) + received_time = time.time() + r = dns.message.from_wire(wire, keyring=keyring, request_mac=request_mac, + one_rr_per_rrset=one_rr_per_rrset, + ignore_trailing=ignore_trailing) + return (r, received_time) + +def _connect(s, address, expiration): + err = s.connect_ex(address) + if err == 0: + return + if err in (errno.EINPROGRESS, errno.EWOULDBLOCK, errno.EALREADY): + _wait_for_writable(s, expiration) + err = s.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) + if err != 0: + raise OSError(err, os.strerror(err)) + + +def tcp(q, where, timeout=None, port=53, source=None, source_port=0, + one_rr_per_rrset=False, ignore_trailing=False, sock=None): + """Return the response obtained after sending a query via TCP. + + *q*, a ``dns.message.Message``, the query to send + + *where*, a ``str`` containing an IPv4 or IPv6 address, where + to send the message. + + *timeout*, a ``float`` or ``None``, the number of seconds to wait before the + query times out. If ``None``, the default, wait forever. + + *port*, an ``int``, the port send the message to. The default is 53. + + *source*, a ``str`` containing an IPv4 or IPv6 address, specifying + the source address. The default is the wildcard address. + + *source_port*, an ``int``, the port from which to send the message. + The default is 0. + + *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own + RRset. + + *ignore_trailing*, a ``bool``. If ``True``, ignore trailing + junk at end of the received message. + + *sock*, a ``socket.socket``, or ``None``, the socket to use for the + query. If ``None``, the default, a socket is created. Note that + if a socket is provided, it must be a nonblocking connected stream + socket, and *where*, *port*, *source* and *source_port* are ignored. + + Returns a ``dns.message.Message``. + """ + + wire = q.to_wire() + (begin_time, expiration) = _compute_times(timeout) + with contextlib.ExitStack() as stack: + if sock: + s = sock + else: + (af, destination, source) = _destination_and_source(where, port, + source, + source_port) + s = stack.enter_context(_make_socket(af, socket.SOCK_STREAM, + source)) + _connect(s, destination, expiration) + send_tcp(s, wire, expiration) + (r, received_time) = receive_tcp(s, expiration, one_rr_per_rrset, + q.keyring, q.mac, ignore_trailing) + r.time = received_time - begin_time + if not q.is_response(r): + raise BadResponse + return r + + +def _tls_handshake(s, expiration): + while True: + try: + s.do_handshake() + return + except ssl.SSLWantReadError: + _wait_for_readable(s, expiration) + except ssl.SSLWantWriteError: # pragma: no cover + _wait_for_writable(s, expiration) + + +def tls(q, where, timeout=None, port=853, source=None, source_port=0, + one_rr_per_rrset=False, ignore_trailing=False, sock=None, + ssl_context=None, server_hostname=None): + """Return the response obtained after sending a query via TLS. + + *q*, a ``dns.message.Message``, the query to send + + *where*, a ``str`` containing an IPv4 or IPv6 address, where + to send the message. + + *timeout*, a ``float`` or ``None``, the number of seconds to wait before the + query times out. If ``None``, the default, wait forever. + + *port*, an ``int``, the port send the message to. The default is 853. + + *source*, a ``str`` containing an IPv4 or IPv6 address, specifying + the source address. The default is the wildcard address. + + *source_port*, an ``int``, the port from which to send the message. + The default is 0. + + *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own + RRset. + + *ignore_trailing*, a ``bool``. If ``True``, ignore trailing + junk at end of the received message. + + *sock*, an ``ssl.SSLSocket``, or ``None``, the socket to use for + the query. If ``None``, the default, a socket is created. Note + that if a socket is provided, it must be a nonblocking connected + SSL stream socket, and *where*, *port*, *source*, *source_port*, + and *ssl_context* are ignored. + + *ssl_context*, an ``ssl.SSLContext``, the context to use when establishing + a TLS connection. If ``None``, the default, creates one with the default + configuration. + + *server_hostname*, a ``str`` containing the server's hostname. The + default is ``None``, which means that no hostname is known, and if an + SSL context is created, hostname checking will be disabled. + + Returns a ``dns.message.Message``. + + """ + + if sock: + # + # If a socket was provided, there's no special TLS handling needed. + # + return tcp(q, where, timeout, port, source, source_port, + one_rr_per_rrset, ignore_trailing, sock) + + wire = q.to_wire() + (begin_time, expiration) = _compute_times(timeout) + (af, destination, source) = _destination_and_source(where, port, + source, source_port) + if ssl_context is None and not sock: + ssl_context = ssl.create_default_context() + if server_hostname is None: + ssl_context.check_hostname = False + + with _make_socket(af, socket.SOCK_STREAM, source, ssl_context=ssl_context, + server_hostname=server_hostname) as s: + _connect(s, destination, expiration) + _tls_handshake(s, expiration) + send_tcp(s, wire, expiration) + (r, received_time) = receive_tcp(s, expiration, one_rr_per_rrset, + q.keyring, q.mac, ignore_trailing) + r.time = received_time - begin_time + if not q.is_response(r): + raise BadResponse + return r + + +def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN, + timeout=None, port=53, keyring=None, keyname=None, relativize=True, + lifetime=None, source=None, source_port=0, serial=0, + use_udp=False, keyalgorithm=dns.tsig.default_algorithm): + """Return a generator for the responses to a zone transfer. + + *where*, a ``str`` containing an IPv4 or IPv6 address, where + to send the message. + + *zone*, a ``dns.name.Name`` or ``str``, the name of the zone to transfer. + + *rdtype*, an ``int`` or ``str``, the type of zone transfer. The + default is ``dns.rdatatype.AXFR``. ``dns.rdatatype.IXFR`` can be + used to do an incremental transfer instead. + + *rdclass*, an ``int`` or ``str``, the class of the zone transfer. + The default is ``dns.rdataclass.IN``. + + *timeout*, a ``float``, the number of seconds to wait for each + response message. If None, the default, wait forever. + + *port*, an ``int``, the port send the message to. The default is 53. + + *keyring*, a ``dict``, the keyring to use for TSIG. + + *keyname*, a ``dns.name.Name`` or ``str``, the name of the TSIG + key to use. + + *relativize*, a ``bool``. If ``True``, all names in the zone will be + relativized to the zone origin. It is essential that the + relativize setting matches the one specified to + ``dns.zone.from_xfr()`` if using this generator to make a zone. + + *lifetime*, a ``float``, the total number of seconds to spend + doing the transfer. If ``None``, the default, then there is no + limit on the time the transfer may take. + + *source*, a ``str`` containing an IPv4 or IPv6 address, specifying + the source address. The default is the wildcard address. + + *source_port*, an ``int``, the port from which to send the message. + The default is 0. + + *serial*, an ``int``, the SOA serial number to use as the base for + an IXFR diff sequence (only meaningful if *rdtype* is + ``dns.rdatatype.IXFR``). + + *use_udp*, a ``bool``. If ``True``, use UDP (only meaningful for IXFR). + + *keyalgorithm*, a ``dns.name.Name`` or ``str``, the TSIG algorithm to use. + + Raises on errors, and so does the generator. + + Returns a generator of ``dns.message.Message`` objects. + """ + + if isinstance(zone, str): + zone = dns.name.from_text(zone) + rdtype = dns.rdatatype.RdataType.make(rdtype) + q = dns.message.make_query(zone, rdtype, rdclass) + if rdtype == dns.rdatatype.IXFR: + rrset = dns.rrset.from_text(zone, 0, 'IN', 'SOA', + '. . %u 0 0 0 0' % serial) + q.authority.append(rrset) + if keyring is not None: + q.use_tsig(keyring, keyname, algorithm=keyalgorithm) + wire = q.to_wire() + (af, destination, source) = _destination_and_source(where, port, + source, source_port) + if use_udp and rdtype != dns.rdatatype.IXFR: + raise ValueError('cannot do a UDP AXFR') + sock_type = socket.SOCK_DGRAM if use_udp else socket.SOCK_STREAM + with _make_socket(af, sock_type, source) as s: + (_, expiration) = _compute_times(lifetime) + _connect(s, destination, expiration) + l = len(wire) + if use_udp: + _udp_send(s, wire, None, expiration) + else: + tcpmsg = struct.pack("!H", l) + wire + _net_write(s, tcpmsg, expiration) + done = False + delete_mode = True + expecting_SOA = False + soa_rrset = None + if relativize: + origin = zone + oname = dns.name.empty + else: + origin = None + oname = zone + tsig_ctx = None + while not done: + (_, mexpiration) = _compute_times(timeout) + if mexpiration is None or \ + (expiration is not None and mexpiration > expiration): + mexpiration = expiration + if use_udp: + (wire, _) = _udp_recv(s, 65535, mexpiration) + else: + ldata = _net_read(s, 2, mexpiration) + (l,) = struct.unpack("!H", ldata) + wire = _net_read(s, l, mexpiration) + is_ixfr = (rdtype == dns.rdatatype.IXFR) + r = dns.message.from_wire(wire, keyring=q.keyring, + request_mac=q.mac, xfr=True, + origin=origin, tsig_ctx=tsig_ctx, + multi=True, one_rr_per_rrset=is_ixfr) + rcode = r.rcode() + if rcode != dns.rcode.NOERROR: + raise TransferError(rcode) + tsig_ctx = r.tsig_ctx + answer_index = 0 + if soa_rrset is None: + if not r.answer or r.answer[0].name != oname: + raise dns.exception.FormError( + "No answer or RRset not for qname") + rrset = r.answer[0] + if rrset.rdtype != dns.rdatatype.SOA: + raise dns.exception.FormError("first RRset is not an SOA") + answer_index = 1 + soa_rrset = rrset.copy() + if rdtype == dns.rdatatype.IXFR: + if dns.serial.Serial(soa_rrset[0].serial) <= serial: + # + # We're already up-to-date. + # + done = True + else: + expecting_SOA = True + # + # Process SOAs in the answer section (other than the initial + # SOA in the first message). + # + for rrset in r.answer[answer_index:]: + if done: + raise dns.exception.FormError("answers after final SOA") + if rrset.rdtype == dns.rdatatype.SOA and rrset.name == oname: + if expecting_SOA: + if rrset[0].serial != serial: + raise dns.exception.FormError( + "IXFR base serial mismatch") + expecting_SOA = False + elif rdtype == dns.rdatatype.IXFR: + delete_mode = not delete_mode + # + # If this SOA RRset is equal to the first we saw then we're + # finished. If this is an IXFR we also check that we're + # seeing the record in the expected part of the response. + # + if rrset == soa_rrset and \ + (rdtype == dns.rdatatype.AXFR or + (rdtype == dns.rdatatype.IXFR and delete_mode)): + done = True + elif expecting_SOA: + # + # We made an IXFR request and are expecting another + # SOA RR, but saw something else, so this must be an + # AXFR response. + # + rdtype = dns.rdatatype.AXFR + expecting_SOA = False + if done and q.keyring and not r.had_tsig: + raise dns.exception.FormError("missing TSIG") + yield r + + +class UDPMode(enum.IntEnum): + """How should UDP be used in an IXFR from :py:func:`inbound_xfr()`? + + NEVER means "never use UDP; always use TCP" + TRY_FIRST means "try to use UDP but fall back to TCP if needed" + ONLY means "raise ``dns.xfr.UseTCP`` if trying UDP does not succeed" + """ + NEVER = 0 + TRY_FIRST = 1 + ONLY = 2 + + +def inbound_xfr(where, txn_manager, query=None, + port=53, timeout=None, lifetime=None, source=None, + source_port=0, udp_mode=UDPMode.NEVER): + """Conduct an inbound transfer and apply it via a transaction from the + txn_manager. + + *where*, a ``str`` containing an IPv4 or IPv6 address, where + to send the message. + + *txn_manager*, a ``dns.transaction.TransactionManager``, the txn_manager + for this transfer (typically a ``dns.zone.Zone``). + + *query*, the query to send. If not supplied, a default query is + constructed using information from the *txn_manager*. + + *port*, an ``int``, the port send the message to. The default is 53. + + *timeout*, a ``float``, the number of seconds to wait for each + response message. If None, the default, wait forever. + + *lifetime*, a ``float``, the total number of seconds to spend + doing the transfer. If ``None``, the default, then there is no + limit on the time the transfer may take. + + *source*, a ``str`` containing an IPv4 or IPv6 address, specifying + the source address. The default is the wildcard address. + + *source_port*, an ``int``, the port from which to send the message. + The default is 0. + + *udp_mode*, a ``dns.query.UDPMode``, determines how UDP is used + for IXFRs. The default is ``dns.UDPMode.NEVER``, i.e. only use + TCP. Other possibilites are ``dns.UDPMode.TRY_FIRST``, which + means "try UDP but fallback to TCP if needed", and + ``dns.UDPMode.ONLY``, which means "try UDP and raise + ``dns.xfr.UseTCP`` if it does not succeeed. + + Raises on errors. + """ + if query is None: + (query, serial) = dns.xfr.make_query(txn_manager) + rdtype = query.question[0].rdtype + is_ixfr = rdtype == dns.rdatatype.IXFR + origin = txn_manager.from_wire_origin() + wire = query.to_wire() + (af, destination, source) = _destination_and_source(where, port, + source, source_port) + (_, expiration) = _compute_times(lifetime) + retry = True + while retry: + retry = False + if is_ixfr and udp_mode != UDPMode.NEVER: + sock_type = socket.SOCK_DGRAM + is_udp = True + else: + sock_type = socket.SOCK_STREAM + is_udp = False + with _make_socket(af, sock_type, source) as s: + _connect(s, destination, expiration) + if is_udp: + _udp_send(s, wire, None, expiration) + else: + tcpmsg = struct.pack("!H", len(wire)) + wire + _net_write(s, tcpmsg, expiration) + with dns.xfr.Inbound(txn_manager, rdtype, serial, + is_udp) as inbound: + done = False + tsig_ctx = None + while not done: + (_, mexpiration) = _compute_times(timeout) + if mexpiration is None or \ + (expiration is not None and mexpiration > expiration): + mexpiration = expiration + if is_udp: + (rwire, _) = _udp_recv(s, 65535, mexpiration) + else: + ldata = _net_read(s, 2, mexpiration) + (l,) = struct.unpack("!H", ldata) + rwire = _net_read(s, l, mexpiration) + r = dns.message.from_wire(rwire, keyring=query.keyring, + request_mac=query.mac, xfr=True, + origin=origin, tsig_ctx=tsig_ctx, + multi=(not is_udp), + one_rr_per_rrset=is_ixfr) + try: + done = inbound.process_message(r) + except dns.xfr.UseTCP: + assert is_udp # should not happen if we used TCP! + if udp_mode == UDPMode.ONLY: + raise + done = True + retry = True + udp_mode = UDPMode.NEVER + continue + tsig_ctx = r.tsig_ctx + if not retry and query.keyring and not r.had_tsig: + raise dns.exception.FormError("missing TSIG") diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rcode.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rcode.py new file mode 100644 index 0000000..49fee69 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rcode.py @@ -0,0 +1,164 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Result Codes.""" + +import dns.enum +import dns.exception + +class Rcode(dns.enum.IntEnum): + #: No error + NOERROR = 0 + #: Format error + FORMERR = 1 + #: Server failure + SERVFAIL = 2 + #: Name does not exist ("Name Error" in RFC 1025 terminology). + NXDOMAIN = 3 + #: Not implemented + NOTIMP = 4 + #: Refused + REFUSED = 5 + #: Name exists. + YXDOMAIN = 6 + #: RRset exists. + YXRRSET = 7 + #: RRset does not exist. + NXRRSET = 8 + #: Not authoritative. + NOTAUTH = 9 + #: Name not in zone. + NOTZONE = 10 + #: DSO-TYPE Not Implemented + DSOTYPENI = 11 + #: Bad EDNS version. + BADVERS = 16 + #: TSIG Signature Failure + BADSIG = 16 + #: Key not recognized. + BADKEY = 17 + #: Signature out of time window. + BADTIME = 18 + #: Bad TKEY Mode. + BADMODE = 19 + #: Duplicate key name. + BADNAME = 20 + #: Algorithm not supported. + BADALG = 21 + #: Bad Truncation + BADTRUNC = 22 + #: Bad/missing Server Cookie + BADCOOKIE = 23 + + @classmethod + def _maximum(cls): + return 4095 + + @classmethod + def _unknown_exception_class(cls): + return UnknownRcode + + +class UnknownRcode(dns.exception.DNSException): + """A DNS rcode is unknown.""" + + +def from_text(text): + """Convert text into an rcode. + + *text*, a ``str``, the textual rcode or an integer in textual form. + + Raises ``dns.rcode.UnknownRcode`` if the rcode mnemonic is unknown. + + Returns an ``int``. + """ + + return Rcode.from_text(text) + + +def from_flags(flags, ednsflags): + """Return the rcode value encoded by flags and ednsflags. + + *flags*, an ``int``, the DNS flags field. + + *ednsflags*, an ``int``, the EDNS flags field. + + Raises ``ValueError`` if rcode is < 0 or > 4095 + + Returns an ``int``. + """ + + value = (flags & 0x000f) | ((ednsflags >> 20) & 0xff0) + return value + + +def to_flags(value): + """Return a (flags, ednsflags) tuple which encodes the rcode. + + *value*, an ``int``, the rcode. + + Raises ``ValueError`` if rcode is < 0 or > 4095. + + Returns an ``(int, int)`` tuple. + """ + + if value < 0 or value > 4095: + raise ValueError('rcode must be >= 0 and <= 4095') + v = value & 0xf + ev = (value & 0xff0) << 20 + return (v, ev) + + +def to_text(value, tsig=False): + """Convert rcode into text. + + *value*, an ``int``, the rcode. + + Raises ``ValueError`` if rcode is < 0 or > 4095. + + Returns a ``str``. + """ + + if tsig and value == Rcode.BADVERS: + return 'BADSIG' + return Rcode.to_text(value) + +### BEGIN generated Rcode constants + +NOERROR = Rcode.NOERROR +FORMERR = Rcode.FORMERR +SERVFAIL = Rcode.SERVFAIL +NXDOMAIN = Rcode.NXDOMAIN +NOTIMP = Rcode.NOTIMP +REFUSED = Rcode.REFUSED +YXDOMAIN = Rcode.YXDOMAIN +YXRRSET = Rcode.YXRRSET +NXRRSET = Rcode.NXRRSET +NOTAUTH = Rcode.NOTAUTH +NOTZONE = Rcode.NOTZONE +DSOTYPENI = Rcode.DSOTYPENI +BADVERS = Rcode.BADVERS +BADSIG = Rcode.BADSIG +BADKEY = Rcode.BADKEY +BADTIME = Rcode.BADTIME +BADMODE = Rcode.BADMODE +BADNAME = Rcode.BADNAME +BADALG = Rcode.BADALG +BADTRUNC = Rcode.BADTRUNC +BADCOOKIE = Rcode.BADCOOKIE + +### END generated Rcode constants diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdata.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdata.py new file mode 100644 index 0000000..12f3b6f --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdata.py @@ -0,0 +1,719 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS rdata.""" + +from importlib import import_module +import base64 +import binascii +import io +import inspect +import itertools +import random + +import dns.wire +import dns.exception +import dns.immutable +import dns.ipv4 +import dns.ipv6 +import dns.name +import dns.rdataclass +import dns.rdatatype +import dns.tokenizer +import dns.ttl + +_chunksize = 32 + + +def _wordbreak(data, chunksize=_chunksize): + """Break a binary string into chunks of chunksize characters separated by + a space. + """ + + if not chunksize: + return data.decode() + return b' '.join([data[i:i + chunksize] + for i + in range(0, len(data), chunksize)]).decode() + + +def _hexify(data, chunksize=_chunksize, **kw): + """Convert a binary string into its hex encoding, broken up into chunks + of chunksize characters separated by a space. + """ + + return _wordbreak(binascii.hexlify(data), chunksize) + + +def _base64ify(data, chunksize=_chunksize, **kw): + """Convert a binary string into its base64 encoding, broken up into chunks + of chunksize characters separated by a space. + """ + + return _wordbreak(base64.b64encode(data), chunksize) + + +__escaped = b'"\\' + +def _escapify(qstring): + """Escape the characters in a quoted string which need it.""" + + if isinstance(qstring, str): + qstring = qstring.encode() + if not isinstance(qstring, bytearray): + qstring = bytearray(qstring) + + text = '' + for c in qstring: + if c in __escaped: + text += '\\' + chr(c) + elif c >= 0x20 and c < 0x7F: + text += chr(c) + else: + text += '\\%03d' % c + return text + + +def _truncate_bitmap(what): + """Determine the index of greatest byte that isn't all zeros, and + return the bitmap that contains all the bytes less than that index. + """ + + for i in range(len(what) - 1, -1, -1): + if what[i] != 0: + return what[0: i + 1] + return what[0:1] + +# So we don't have to edit all the rdata classes... +_constify = dns.immutable.constify + + +@dns.immutable.immutable +class Rdata: + """Base class for all DNS rdata types.""" + + __slots__ = ['rdclass', 'rdtype', 'rdcomment'] + + def __init__(self, rdclass, rdtype): + """Initialize an rdata. + + *rdclass*, an ``int`` is the rdataclass of the Rdata. + + *rdtype*, an ``int`` is the rdatatype of the Rdata. + """ + + self.rdclass = self._as_rdataclass(rdclass) + self.rdtype = self._as_rdatatype(rdtype) + self.rdcomment = None + + def _get_all_slots(self): + return itertools.chain.from_iterable(getattr(cls, '__slots__', []) + for cls in self.__class__.__mro__) + + def __getstate__(self): + # We used to try to do a tuple of all slots here, but it + # doesn't work as self._all_slots isn't available at + # __setstate__() time. Before that we tried to store a tuple + # of __slots__, but that didn't work as it didn't store the + # slots defined by ancestors. This older way didn't fail + # outright, but ended up with partially broken objects, e.g. + # if you unpickled an A RR it wouldn't have rdclass and rdtype + # attributes, and would compare badly. + state = {} + for slot in self._get_all_slots(): + state[slot] = getattr(self, slot) + return state + + def __setstate__(self, state): + for slot, val in state.items(): + object.__setattr__(self, slot, val) + if not hasattr(self, 'rdcomment'): + # Pickled rdata from 2.0.x might not have a rdcomment, so add + # it if needed. + object.__setattr__(self, 'rdcomment', None) + + def covers(self): + """Return the type a Rdata covers. + + DNS SIG/RRSIG rdatas apply to a specific type; this type is + returned by the covers() function. If the rdata type is not + SIG or RRSIG, dns.rdatatype.NONE is returned. This is useful when + creating rdatasets, allowing the rdataset to contain only RRSIGs + of a particular type, e.g. RRSIG(NS). + + Returns an ``int``. + """ + + return dns.rdatatype.NONE + + def extended_rdatatype(self): + """Return a 32-bit type value, the least significant 16 bits of + which are the ordinary DNS type, and the upper 16 bits of which are + the "covered" type, if any. + + Returns an ``int``. + """ + + return self.covers() << 16 | self.rdtype + + def to_text(self, origin=None, relativize=True, **kw): + """Convert an rdata to text format. + + Returns a ``str``. + """ + + raise NotImplementedError # pragma: no cover + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + raise NotImplementedError # pragma: no cover + + def to_wire(self, file=None, compress=None, origin=None, + canonicalize=False): + """Convert an rdata to wire format. + + Returns a ``bytes`` or ``None``. + """ + + if file: + return self._to_wire(file, compress, origin, canonicalize) + else: + f = io.BytesIO() + self._to_wire(f, compress, origin, canonicalize) + return f.getvalue() + + def to_generic(self, origin=None): + """Creates a dns.rdata.GenericRdata equivalent of this rdata. + + Returns a ``dns.rdata.GenericRdata``. + """ + return dns.rdata.GenericRdata(self.rdclass, self.rdtype, + self.to_wire(origin=origin)) + + def to_digestable(self, origin=None): + """Convert rdata to a format suitable for digesting in hashes. This + is also the DNSSEC canonical form. + + Returns a ``bytes``. + """ + + return self.to_wire(origin=origin, canonicalize=True) + + def __repr__(self): + covers = self.covers() + if covers == dns.rdatatype.NONE: + ctext = '' + else: + ctext = '(' + dns.rdatatype.to_text(covers) + ')' + return '' + + def __str__(self): + return self.to_text() + + def _cmp(self, other): + """Compare an rdata with another rdata of the same rdtype and + rdclass. + + Return < 0 if self < other in the DNSSEC ordering, 0 if self + == other, and > 0 if self > other. + + """ + our = self.to_digestable(dns.name.root) + their = other.to_digestable(dns.name.root) + if our == their: + return 0 + elif our > their: + return 1 + else: + return -1 + + def __eq__(self, other): + if not isinstance(other, Rdata): + return False + if self.rdclass != other.rdclass or self.rdtype != other.rdtype: + return False + return self._cmp(other) == 0 + + def __ne__(self, other): + if not isinstance(other, Rdata): + return True + if self.rdclass != other.rdclass or self.rdtype != other.rdtype: + return True + return self._cmp(other) != 0 + + def __lt__(self, other): + if not isinstance(other, Rdata) or \ + self.rdclass != other.rdclass or self.rdtype != other.rdtype: + + return NotImplemented + return self._cmp(other) < 0 + + def __le__(self, other): + if not isinstance(other, Rdata) or \ + self.rdclass != other.rdclass or self.rdtype != other.rdtype: + return NotImplemented + return self._cmp(other) <= 0 + + def __ge__(self, other): + if not isinstance(other, Rdata) or \ + self.rdclass != other.rdclass or self.rdtype != other.rdtype: + return NotImplemented + return self._cmp(other) >= 0 + + def __gt__(self, other): + if not isinstance(other, Rdata) or \ + self.rdclass != other.rdclass or self.rdtype != other.rdtype: + return NotImplemented + return self._cmp(other) > 0 + + def __hash__(self): + return hash(self.to_digestable(dns.name.root)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + raise NotImplementedError # pragma: no cover + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + raise NotImplementedError # pragma: no cover + + def replace(self, **kwargs): + """ + Create a new Rdata instance based on the instance replace was + invoked on. It is possible to pass different parameters to + override the corresponding properties of the base Rdata. + + Any field specific to the Rdata type can be replaced, but the + *rdtype* and *rdclass* fields cannot. + + Returns an instance of the same Rdata subclass as *self*. + """ + + # Get the constructor parameters. + parameters = inspect.signature(self.__init__).parameters + + # Ensure that all of the arguments correspond to valid fields. + # Don't allow rdclass or rdtype to be changed, though. + for key in kwargs: + if key == 'rdcomment': + continue + if key not in parameters: + raise AttributeError("'{}' object has no attribute '{}'" + .format(self.__class__.__name__, key)) + if key in ('rdclass', 'rdtype'): + raise AttributeError("Cannot overwrite '{}' attribute '{}'" + .format(self.__class__.__name__, key)) + + # Construct the parameter list. For each field, use the value in + # kwargs if present, and the current value otherwise. + args = (kwargs.get(key, getattr(self, key)) for key in parameters) + + # Create, validate, and return the new object. + rd = self.__class__(*args) + # The comment is not set in the constructor, so give it special + # handling. + rdcomment = kwargs.get('rdcomment', self.rdcomment) + if rdcomment is not None: + object.__setattr__(rd, 'rdcomment', rdcomment) + return rd + + # Type checking and conversion helpers. These are class methods as + # they don't touch object state and may be useful to others. + + @classmethod + def _as_rdataclass(cls, value): + return dns.rdataclass.RdataClass.make(value) + + @classmethod + def _as_rdatatype(cls, value): + return dns.rdatatype.RdataType.make(value) + + @classmethod + def _as_bytes(cls, value, encode=False, max_length=None, empty_ok=True): + if encode and isinstance(value, str): + value = value.encode() + elif isinstance(value, bytearray): + value = bytes(value) + elif not isinstance(value, bytes): + raise ValueError('not bytes') + if max_length is not None and len(value) > max_length: + raise ValueError('too long') + if not empty_ok and len(value) == 0: + raise ValueError('empty bytes not allowed') + return value + + @classmethod + def _as_name(cls, value): + # Note that proper name conversion (e.g. with origin and IDNA + # awareness) is expected to be done via from_text. This is just + # a simple thing for people invoking the constructor directly. + if isinstance(value, str): + return dns.name.from_text(value) + elif not isinstance(value, dns.name.Name): + raise ValueError('not a name') + return value + + @classmethod + def _as_uint8(cls, value): + if not isinstance(value, int): + raise ValueError('not an integer') + if value < 0 or value > 255: + raise ValueError('not a uint8') + return value + + @classmethod + def _as_uint16(cls, value): + if not isinstance(value, int): + raise ValueError('not an integer') + if value < 0 or value > 65535: + raise ValueError('not a uint16') + return value + + @classmethod + def _as_uint32(cls, value): + if not isinstance(value, int): + raise ValueError('not an integer') + if value < 0 or value > 4294967295: + raise ValueError('not a uint32') + return value + + @classmethod + def _as_uint48(cls, value): + if not isinstance(value, int): + raise ValueError('not an integer') + if value < 0 or value > 281474976710655: + raise ValueError('not a uint48') + return value + + @classmethod + def _as_int(cls, value, low=None, high=None): + if not isinstance(value, int): + raise ValueError('not an integer') + if low is not None and value < low: + raise ValueError('value too small') + if high is not None and value > high: + raise ValueError('value too large') + return value + + @classmethod + def _as_ipv4_address(cls, value): + if isinstance(value, str): + # call to check validity + dns.ipv4.inet_aton(value) + return value + elif isinstance(value, bytes): + return dns.ipv4.inet_ntoa(value) + else: + raise ValueError('not an IPv4 address') + + @classmethod + def _as_ipv6_address(cls, value): + if isinstance(value, str): + # call to check validity + dns.ipv6.inet_aton(value) + return value + elif isinstance(value, bytes): + return dns.ipv6.inet_ntoa(value) + else: + raise ValueError('not an IPv6 address') + + @classmethod + def _as_bool(cls, value): + if isinstance(value, bool): + return value + else: + raise ValueError('not a boolean') + + @classmethod + def _as_ttl(cls, value): + if isinstance(value, int): + return cls._as_int(value, 0, dns.ttl.MAX_TTL) + elif isinstance(value, str): + return dns.ttl.from_text(value) + else: + raise ValueError('not a TTL') + + @classmethod + def _as_tuple(cls, value, as_value): + try: + # For user convenience, if value is a singleton of the list + # element type, wrap it in a tuple. + return (as_value(value),) + except Exception: + # Otherwise, check each element of the iterable *value* + # against *as_value*. + return tuple(as_value(v) for v in value) + + # Processing order + + @classmethod + def _processing_order(cls, iterable): + items = list(iterable) + random.shuffle(items) + return items + + +class GenericRdata(Rdata): + + """Generic Rdata Class + + This class is used for rdata types for which we have no better + implementation. It implements the DNS "unknown RRs" scheme. + """ + + __slots__ = ['data'] + + def __init__(self, rdclass, rdtype, data): + super().__init__(rdclass, rdtype) + object.__setattr__(self, 'data', data) + + def to_text(self, origin=None, relativize=True, **kw): + return r'\# %d ' % len(self.data) + _hexify(self.data, **kw) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + token = tok.get() + if not token.is_identifier() or token.value != r'\#': + raise dns.exception.SyntaxError( + r'generic rdata does not start with \#') + length = tok.get_int() + hex = tok.concatenate_remaining_identifiers().encode() + data = binascii.unhexlify(hex) + if len(data) != length: + raise dns.exception.SyntaxError( + 'generic rdata hex data has wrong length') + return cls(rdclass, rdtype, data) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(self.data) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + return cls(rdclass, rdtype, parser.get_remaining()) + +_rdata_classes = {} +_module_prefix = 'dns.rdtypes' + +def get_rdata_class(rdclass, rdtype): + cls = _rdata_classes.get((rdclass, rdtype)) + if not cls: + cls = _rdata_classes.get((dns.rdatatype.ANY, rdtype)) + if not cls: + rdclass_text = dns.rdataclass.to_text(rdclass) + rdtype_text = dns.rdatatype.to_text(rdtype) + rdtype_text = rdtype_text.replace('-', '_') + try: + mod = import_module('.'.join([_module_prefix, + rdclass_text, rdtype_text])) + cls = getattr(mod, rdtype_text) + _rdata_classes[(rdclass, rdtype)] = cls + except ImportError: + try: + mod = import_module('.'.join([_module_prefix, + 'ANY', rdtype_text])) + cls = getattr(mod, rdtype_text) + _rdata_classes[(dns.rdataclass.ANY, rdtype)] = cls + _rdata_classes[(rdclass, rdtype)] = cls + except ImportError: + pass + if not cls: + cls = GenericRdata + _rdata_classes[(rdclass, rdtype)] = cls + return cls + + +def from_text(rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None, idna_codec=None): + """Build an rdata object from text format. + + This function attempts to dynamically load a class which + implements the specified rdata class and type. If there is no + class-and-type-specific implementation, the GenericRdata class + is used. + + Once a class is chosen, its from_text() class method is called + with the parameters to this function. + + If *tok* is a ``str``, then a tokenizer is created and the string + is used as its input. + + *rdclass*, an ``int``, the rdataclass. + + *rdtype*, an ``int``, the rdatatype. + + *tok*, a ``dns.tokenizer.Tokenizer`` or a ``str``. + + *origin*, a ``dns.name.Name`` (or ``None``), the + origin to use for relative names. + + *relativize*, a ``bool``. If true, name will be relativized. + + *relativize_to*, a ``dns.name.Name`` (or ``None``), the origin to use + when relativizing names. If not set, the *origin* value will be used. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder to use if a tokenizer needs to be created. If + ``None``, the default IDNA 2003 encoder/decoder is used. If a + tokenizer is not created, then the codec associated with the tokenizer + is the one that is used. + + Returns an instance of the chosen Rdata subclass. + + """ + if isinstance(tok, str): + tok = dns.tokenizer.Tokenizer(tok, idna_codec=idna_codec) + rdclass = dns.rdataclass.RdataClass.make(rdclass) + rdtype = dns.rdatatype.RdataType.make(rdtype) + cls = get_rdata_class(rdclass, rdtype) + with dns.exception.ExceptionWrapper(dns.exception.SyntaxError): + rdata = None + if cls != GenericRdata: + # peek at first token + token = tok.get() + tok.unget(token) + if token.is_identifier() and \ + token.value == r'\#': + # + # Known type using the generic syntax. Extract the + # wire form from the generic syntax, and then run + # from_wire on it. + # + grdata = GenericRdata.from_text(rdclass, rdtype, tok, origin, + relativize, relativize_to) + rdata = from_wire(rdclass, rdtype, grdata.data, 0, + len(grdata.data), origin) + # + # If this comparison isn't equal, then there must have been + # compressed names in the wire format, which is an error, + # there being no reasonable context to decompress with. + # + rwire = rdata.to_wire() + if rwire != grdata.data: + raise dns.exception.SyntaxError('compressed data in ' + 'generic syntax form ' + 'of known rdatatype') + if rdata is None: + rdata = cls.from_text(rdclass, rdtype, tok, origin, relativize, + relativize_to) + token = tok.get_eol_as_token() + if token.comment is not None: + object.__setattr__(rdata, 'rdcomment', token.comment) + return rdata + + +def from_wire_parser(rdclass, rdtype, parser, origin=None): + """Build an rdata object from wire format + + This function attempts to dynamically load a class which + implements the specified rdata class and type. If there is no + class-and-type-specific implementation, the GenericRdata class + is used. + + Once a class is chosen, its from_wire() class method is called + with the parameters to this function. + + *rdclass*, an ``int``, the rdataclass. + + *rdtype*, an ``int``, the rdatatype. + + *parser*, a ``dns.wire.Parser``, the parser, which should be + restricted to the rdata length. + + *origin*, a ``dns.name.Name`` (or ``None``). If not ``None``, + then names will be relativized to this origin. + + Returns an instance of the chosen Rdata subclass. + """ + + rdclass = dns.rdataclass.RdataClass.make(rdclass) + rdtype = dns.rdatatype.RdataType.make(rdtype) + cls = get_rdata_class(rdclass, rdtype) + with dns.exception.ExceptionWrapper(dns.exception.FormError): + return cls.from_wire_parser(rdclass, rdtype, parser, origin) + + +def from_wire(rdclass, rdtype, wire, current, rdlen, origin=None): + """Build an rdata object from wire format + + This function attempts to dynamically load a class which + implements the specified rdata class and type. If there is no + class-and-type-specific implementation, the GenericRdata class + is used. + + Once a class is chosen, its from_wire() class method is called + with the parameters to this function. + + *rdclass*, an ``int``, the rdataclass. + + *rdtype*, an ``int``, the rdatatype. + + *wire*, a ``bytes``, the wire-format message. + + *current*, an ``int``, the offset in wire of the beginning of + the rdata. + + *rdlen*, an ``int``, the length of the wire-format rdata + + *origin*, a ``dns.name.Name`` (or ``None``). If not ``None``, + then names will be relativized to this origin. + + Returns an instance of the chosen Rdata subclass. + """ + parser = dns.wire.Parser(wire, current) + with parser.restrict_to(rdlen): + return from_wire_parser(rdclass, rdtype, parser, origin) + + +class RdatatypeExists(dns.exception.DNSException): + """DNS rdatatype already exists.""" + supp_kwargs = {'rdclass', 'rdtype'} + fmt = "The rdata type with class {rdclass} and rdtype {rdtype} " + \ + "already exists." + + +def register_type(implementation, rdtype, rdtype_text, is_singleton=False, + rdclass=dns.rdataclass.IN): + """Dynamically register a module to handle an rdatatype. + + *implementation*, a module implementing the type in the usual dnspython + way. + + *rdtype*, an ``int``, the rdatatype to register. + + *rdtype_text*, a ``str``, the textual form of the rdatatype. + + *is_singleton*, a ``bool``, indicating if the type is a singleton (i.e. + RRsets of the type can have only one member.) + + *rdclass*, the rdataclass of the type, or ``dns.rdataclass.ANY`` if + it applies to all classes. + """ + + existing_cls = get_rdata_class(rdclass, rdtype) + if existing_cls != GenericRdata or dns.rdatatype.is_metatype(rdtype): + raise RdatatypeExists(rdclass=rdclass, rdtype=rdtype) + try: + if dns.rdatatype.RdataType(rdtype).name != rdtype_text: + raise RdatatypeExists(rdclass=rdclass, rdtype=rdtype) + except ValueError: + pass + _rdata_classes[(rdclass, rdtype)] = getattr(implementation, + rdtype_text.replace('-', '_')) + dns.rdatatype.register_type(rdtype, rdtype_text, is_singleton) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdataclass.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdataclass.py new file mode 100644 index 0000000..41bba69 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdataclass.py @@ -0,0 +1,115 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Rdata Classes.""" + +import dns.enum +import dns.exception + +class RdataClass(dns.enum.IntEnum): + """DNS Rdata Class""" + RESERVED0 = 0 + IN = 1 + INTERNET = IN + CH = 3 + CHAOS = CH + HS = 4 + HESIOD = HS + NONE = 254 + ANY = 255 + + @classmethod + def _maximum(cls): + return 65535 + + @classmethod + def _short_name(cls): + return "class" + + @classmethod + def _prefix(cls): + return "CLASS" + + @classmethod + def _unknown_exception_class(cls): + return UnknownRdataclass + + +_metaclasses = {RdataClass.NONE, RdataClass.ANY} + + +class UnknownRdataclass(dns.exception.DNSException): + """A DNS class is unknown.""" + + +def from_text(text): + """Convert text into a DNS rdata class value. + + The input text can be a defined DNS RR class mnemonic or + instance of the DNS generic class syntax. + + For example, "IN" and "CLASS1" will both result in a value of 1. + + Raises ``dns.rdatatype.UnknownRdataclass`` if the class is unknown. + + Raises ``ValueError`` if the rdata class value is not >= 0 and <= 65535. + + Returns an ``int``. + """ + + return RdataClass.from_text(text) + + +def to_text(value): + """Convert a DNS rdata class value to text. + + If the value has a known mnemonic, it will be used, otherwise the + DNS generic class syntax will be used. + + Raises ``ValueError`` if the rdata class value is not >= 0 and <= 65535. + + Returns a ``str``. + """ + + return RdataClass.to_text(value) + + +def is_metaclass(rdclass): + """True if the specified class is a metaclass. + + The currently defined metaclasses are ANY and NONE. + + *rdclass* is an ``int``. + """ + + if rdclass in _metaclasses: + return True + return False + +### BEGIN generated RdataClass constants + +RESERVED0 = RdataClass.RESERVED0 +IN = RdataClass.IN +INTERNET = RdataClass.INTERNET +CH = RdataClass.CH +CHAOS = RdataClass.CHAOS +HS = RdataClass.HS +HESIOD = RdataClass.HESIOD +NONE = RdataClass.NONE +ANY = RdataClass.ANY + +### END generated RdataClass constants diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdataset.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdataset.py new file mode 100644 index 0000000..e69ee23 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdataset.py @@ -0,0 +1,456 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS rdatasets (an rdataset is a set of rdatas of a given type and class)""" + +import io +import random +import struct + +import dns.exception +import dns.immutable +import dns.rdatatype +import dns.rdataclass +import dns.rdata +import dns.set + +# define SimpleSet here for backwards compatibility +SimpleSet = dns.set.Set + + +class DifferingCovers(dns.exception.DNSException): + """An attempt was made to add a DNS SIG/RRSIG whose covered type + is not the same as that of the other rdatas in the rdataset.""" + + +class IncompatibleTypes(dns.exception.DNSException): + """An attempt was made to add DNS RR data of an incompatible type.""" + + +class Rdataset(dns.set.Set): + + """A DNS rdataset.""" + + __slots__ = ['rdclass', 'rdtype', 'covers', 'ttl'] + + def __init__(self, rdclass, rdtype, covers=dns.rdatatype.NONE, ttl=0): + """Create a new rdataset of the specified class and type. + + *rdclass*, an ``int``, the rdataclass. + + *rdtype*, an ``int``, the rdatatype. + + *covers*, an ``int``, the covered rdatatype. + + *ttl*, an ``int``, the TTL. + """ + + super().__init__() + self.rdclass = rdclass + self.rdtype = rdtype + self.covers = covers + self.ttl = ttl + + def _clone(self): + obj = super()._clone() + obj.rdclass = self.rdclass + obj.rdtype = self.rdtype + obj.covers = self.covers + obj.ttl = self.ttl + return obj + + def update_ttl(self, ttl): + """Perform TTL minimization. + + Set the TTL of the rdataset to be the lesser of the set's current + TTL or the specified TTL. If the set contains no rdatas, set the TTL + to the specified TTL. + + *ttl*, an ``int`` or ``str``. + """ + ttl = dns.ttl.make(ttl) + if len(self) == 0: + self.ttl = ttl + elif ttl < self.ttl: + self.ttl = ttl + + def add(self, rd, ttl=None): # pylint: disable=arguments-differ + """Add the specified rdata to the rdataset. + + If the optional *ttl* parameter is supplied, then + ``self.update_ttl(ttl)`` will be called prior to adding the rdata. + + *rd*, a ``dns.rdata.Rdata``, the rdata + + *ttl*, an ``int``, the TTL. + + Raises ``dns.rdataset.IncompatibleTypes`` if the type and class + do not match the type and class of the rdataset. + + Raises ``dns.rdataset.DifferingCovers`` if the type is a signature + type and the covered type does not match that of the rdataset. + """ + + # + # If we're adding a signature, do some special handling to + # check that the signature covers the same type as the + # other rdatas in this rdataset. If this is the first rdata + # in the set, initialize the covers field. + # + if self.rdclass != rd.rdclass or self.rdtype != rd.rdtype: + raise IncompatibleTypes + if ttl is not None: + self.update_ttl(ttl) + if self.rdtype == dns.rdatatype.RRSIG or \ + self.rdtype == dns.rdatatype.SIG: + covers = rd.covers() + if len(self) == 0 and self.covers == dns.rdatatype.NONE: + self.covers = covers + elif self.covers != covers: + raise DifferingCovers + if dns.rdatatype.is_singleton(rd.rdtype) and len(self) > 0: + self.clear() + super().add(rd) + + def union_update(self, other): + self.update_ttl(other.ttl) + super().union_update(other) + + def intersection_update(self, other): + self.update_ttl(other.ttl) + super().intersection_update(other) + + def update(self, other): + """Add all rdatas in other to self. + + *other*, a ``dns.rdataset.Rdataset``, the rdataset from which + to update. + """ + + self.update_ttl(other.ttl) + super().update(other) + + def _rdata_repr(self): + def maybe_truncate(s): + if len(s) > 100: + return s[:100] + '...' + return s + return '[%s]' % ', '.join('<%s>' % maybe_truncate(str(rr)) + for rr in self) + + def __repr__(self): + if self.covers == 0: + ctext = '' + else: + ctext = '(' + dns.rdatatype.to_text(self.covers) + ')' + return '' + + def __str__(self): + return self.to_text() + + def __eq__(self, other): + if not isinstance(other, Rdataset): + return False + if self.rdclass != other.rdclass or \ + self.rdtype != other.rdtype or \ + self.covers != other.covers: + return False + return super().__eq__(other) + + def __ne__(self, other): + return not self.__eq__(other) + + def to_text(self, name=None, origin=None, relativize=True, + override_rdclass=None, want_comments=False, **kw): + """Convert the rdataset into DNS zone file format. + + See ``dns.name.Name.choose_relativity`` for more information + on how *origin* and *relativize* determine the way names + are emitted. + + Any additional keyword arguments are passed on to the rdata + ``to_text()`` method. + + *name*, a ``dns.name.Name``. If name is not ``None``, emit RRs with + *name* as the owner name. + + *origin*, a ``dns.name.Name`` or ``None``, the origin for relative + names. + + *relativize*, a ``bool``. If ``True``, names will be relativized + to *origin*. + + *override_rdclass*, a ``dns.rdataclass.RdataClass`` or ``None``. + If not ``None``, use this class instead of the Rdataset's class. + + *want_comments*, a ``bool``. If ``True``, emit comments for rdata + which have them. The default is ``False``. + """ + + if name is not None: + name = name.choose_relativity(origin, relativize) + ntext = str(name) + pad = ' ' + else: + ntext = '' + pad = '' + s = io.StringIO() + if override_rdclass is not None: + rdclass = override_rdclass + else: + rdclass = self.rdclass + if len(self) == 0: + # + # Empty rdatasets are used for the question section, and in + # some dynamic updates, so we don't need to print out the TTL + # (which is meaningless anyway). + # + s.write('{}{}{} {}\n'.format(ntext, pad, + dns.rdataclass.to_text(rdclass), + dns.rdatatype.to_text(self.rdtype))) + else: + for rd in self: + extra = '' + if want_comments: + if rd.rdcomment: + extra = f' ;{rd.rdcomment}' + s.write('%s%s%d %s %s %s%s\n' % + (ntext, pad, self.ttl, dns.rdataclass.to_text(rdclass), + dns.rdatatype.to_text(self.rdtype), + rd.to_text(origin=origin, relativize=relativize, + **kw), + extra)) + # + # We strip off the final \n for the caller's convenience in printing + # + return s.getvalue()[:-1] + + def to_wire(self, name, file, compress=None, origin=None, + override_rdclass=None, want_shuffle=True): + """Convert the rdataset to wire format. + + *name*, a ``dns.name.Name`` is the owner name to use. + + *file* is the file where the name is emitted (typically a + BytesIO file). + + *compress*, a ``dict``, is the compression table to use. If + ``None`` (the default), names will not be compressed. + + *origin* is a ``dns.name.Name`` or ``None``. If the name is + relative and origin is not ``None``, then *origin* will be appended + to it. + + *override_rdclass*, an ``int``, is used as the class instead of the + class of the rdataset. This is useful when rendering rdatasets + associated with dynamic updates. + + *want_shuffle*, a ``bool``. If ``True``, then the order of the + Rdatas within the Rdataset will be shuffled before rendering. + + Returns an ``int``, the number of records emitted. + """ + + if override_rdclass is not None: + rdclass = override_rdclass + want_shuffle = False + else: + rdclass = self.rdclass + file.seek(0, io.SEEK_END) + if len(self) == 0: + name.to_wire(file, compress, origin) + stuff = struct.pack("!HHIH", self.rdtype, rdclass, 0, 0) + file.write(stuff) + return 1 + else: + if want_shuffle: + l = list(self) + random.shuffle(l) + else: + l = self + for rd in l: + name.to_wire(file, compress, origin) + stuff = struct.pack("!HHIH", self.rdtype, rdclass, + self.ttl, 0) + file.write(stuff) + start = file.tell() + rd.to_wire(file, compress, origin) + end = file.tell() + assert end - start < 65536 + file.seek(start - 2) + stuff = struct.pack("!H", end - start) + file.write(stuff) + file.seek(0, io.SEEK_END) + return len(self) + + def match(self, rdclass, rdtype, covers): + """Returns ``True`` if this rdataset matches the specified class, + type, and covers. + """ + if self.rdclass == rdclass and \ + self.rdtype == rdtype and \ + self.covers == covers: + return True + return False + + def processing_order(self): + """Return rdatas in a valid processing order according to the type's + specification. For example, MX records are in preference order from + lowest to highest preferences, with items of the same perference + shuffled. + + For types that do not define a processing order, the rdatas are + simply shuffled. + """ + if len(self) == 0: + return [] + else: + return self[0]._processing_order(iter(self)) + + +@dns.immutable.immutable +class ImmutableRdataset(Rdataset): + + """An immutable DNS rdataset.""" + + _clone_class = Rdataset + + def __init__(self, rdataset): + """Create an immutable rdataset from the specified rdataset.""" + + super().__init__(rdataset.rdclass, rdataset.rdtype, rdataset.covers, + rdataset.ttl) + self.items = dns.immutable.Dict(rdataset.items) + + def update_ttl(self, ttl): + raise TypeError('immutable') + + def add(self, rd, ttl=None): + raise TypeError('immutable') + + def union_update(self, other): + raise TypeError('immutable') + + def intersection_update(self, other): + raise TypeError('immutable') + + def update(self, other): + raise TypeError('immutable') + + def __delitem__(self, i): + raise TypeError('immutable') + + def __ior__(self, other): + raise TypeError('immutable') + + def __iand__(self, other): + raise TypeError('immutable') + + def __iadd__(self, other): + raise TypeError('immutable') + + def __isub__(self, other): + raise TypeError('immutable') + + def clear(self): + raise TypeError('immutable') + + def __copy__(self): + return ImmutableRdataset(super().copy()) + + def copy(self): + return ImmutableRdataset(super().copy()) + + def union(self, other): + return ImmutableRdataset(super().union(other)) + + def intersection(self, other): + return ImmutableRdataset(super().intersection(other)) + + def difference(self, other): + return ImmutableRdataset(super().difference(other)) + + +def from_text_list(rdclass, rdtype, ttl, text_rdatas, idna_codec=None, + origin=None, relativize=True, relativize_to=None): + """Create an rdataset with the specified class, type, and TTL, and with + the specified list of rdatas in text format. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder to use; if ``None``, the default IDNA 2003 + encoder/decoder is used. + + *origin*, a ``dns.name.Name`` (or ``None``), the + origin to use for relative names. + + *relativize*, a ``bool``. If true, name will be relativized. + + *relativize_to*, a ``dns.name.Name`` (or ``None``), the origin to use + when relativizing names. If not set, the *origin* value will be used. + + Returns a ``dns.rdataset.Rdataset`` object. + """ + + rdclass = dns.rdataclass.RdataClass.make(rdclass) + rdtype = dns.rdatatype.RdataType.make(rdtype) + r = Rdataset(rdclass, rdtype) + r.update_ttl(ttl) + for t in text_rdatas: + rd = dns.rdata.from_text(r.rdclass, r.rdtype, t, origin, relativize, + relativize_to, idna_codec) + r.add(rd) + return r + + +def from_text(rdclass, rdtype, ttl, *text_rdatas): + """Create an rdataset with the specified class, type, and TTL, and with + the specified rdatas in text format. + + Returns a ``dns.rdataset.Rdataset`` object. + """ + + return from_text_list(rdclass, rdtype, ttl, text_rdatas) + + +def from_rdata_list(ttl, rdatas): + """Create an rdataset with the specified TTL, and with + the specified list of rdata objects. + + Returns a ``dns.rdataset.Rdataset`` object. + """ + + if len(rdatas) == 0: + raise ValueError("rdata list must not be empty") + r = None + for rd in rdatas: + if r is None: + r = Rdataset(rd.rdclass, rd.rdtype) + r.update_ttl(ttl) + r.add(rd) + return r + + +def from_rdata(ttl, *rdatas): + """Create an rdataset with the specified TTL, and with + the specified rdata objects. + + Returns a ``dns.rdataset.Rdataset`` object. + """ + + return from_rdata_list(ttl, rdatas) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdatatype.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdatatype.py new file mode 100644 index 0000000..65da6d4 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdatatype.py @@ -0,0 +1,303 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Rdata Types.""" + +import dns.enum +import dns.exception + +class RdataType(dns.enum.IntEnum): + """DNS Rdata Type""" + TYPE0 = 0 + NONE = 0 + A = 1 + NS = 2 + MD = 3 + MF = 4 + CNAME = 5 + SOA = 6 + MB = 7 + MG = 8 + MR = 9 + NULL = 10 + WKS = 11 + PTR = 12 + HINFO = 13 + MINFO = 14 + MX = 15 + TXT = 16 + RP = 17 + AFSDB = 18 + X25 = 19 + ISDN = 20 + RT = 21 + NSAP = 22 + NSAP_PTR = 23 + SIG = 24 + KEY = 25 + PX = 26 + GPOS = 27 + AAAA = 28 + LOC = 29 + NXT = 30 + SRV = 33 + NAPTR = 35 + KX = 36 + CERT = 37 + A6 = 38 + DNAME = 39 + OPT = 41 + APL = 42 + DS = 43 + SSHFP = 44 + IPSECKEY = 45 + RRSIG = 46 + NSEC = 47 + DNSKEY = 48 + DHCID = 49 + NSEC3 = 50 + NSEC3PARAM = 51 + TLSA = 52 + SMIMEA = 53 + HIP = 55 + NINFO = 56 + CDS = 59 + CDNSKEY = 60 + OPENPGPKEY = 61 + CSYNC = 62 + SVCB = 64 + HTTPS = 65 + SPF = 99 + UNSPEC = 103 + EUI48 = 108 + EUI64 = 109 + TKEY = 249 + TSIG = 250 + IXFR = 251 + AXFR = 252 + MAILB = 253 + MAILA = 254 + ANY = 255 + URI = 256 + CAA = 257 + AVC = 258 + AMTRELAY = 259 + TA = 32768 + DLV = 32769 + + @classmethod + def _maximum(cls): + return 65535 + + @classmethod + def _short_name(cls): + return "type" + + @classmethod + def _prefix(cls): + return "TYPE" + + @classmethod + def _unknown_exception_class(cls): + return UnknownRdatatype + +_registered_by_text = {} +_registered_by_value = {} + +_metatypes = {RdataType.OPT} + +_singletons = {RdataType.SOA, RdataType.NXT, RdataType.DNAME, + RdataType.NSEC, RdataType.CNAME} + + +class UnknownRdatatype(dns.exception.DNSException): + """DNS resource record type is unknown.""" + + +def from_text(text): + """Convert text into a DNS rdata type value. + + The input text can be a defined DNS RR type mnemonic or + instance of the DNS generic type syntax. + + For example, "NS" and "TYPE2" will both result in a value of 2. + + Raises ``dns.rdatatype.UnknownRdatatype`` if the type is unknown. + + Raises ``ValueError`` if the rdata type value is not >= 0 and <= 65535. + + Returns an ``int``. + """ + + text = text.upper().replace('-', '_') + try: + return RdataType.from_text(text) + except UnknownRdatatype: + registered_type = _registered_by_text.get(text) + if registered_type: + return registered_type + raise + + +def to_text(value): + """Convert a DNS rdata type value to text. + + If the value has a known mnemonic, it will be used, otherwise the + DNS generic type syntax will be used. + + Raises ``ValueError`` if the rdata type value is not >= 0 and <= 65535. + + Returns a ``str``. + """ + + text = RdataType.to_text(value) + if text.startswith("TYPE"): + registered_text = _registered_by_value.get(value) + if registered_text: + text = registered_text + return text.replace('_', '-') + + +def is_metatype(rdtype): + """True if the specified type is a metatype. + + *rdtype* is an ``int``. + + The currently defined metatypes are TKEY, TSIG, IXFR, AXFR, MAILA, + MAILB, ANY, and OPT. + + Returns a ``bool``. + """ + + return (256 > rdtype >= 128) or rdtype in _metatypes + + +def is_singleton(rdtype): + """Is the specified type a singleton type? + + Singleton types can only have a single rdata in an rdataset, or a single + RR in an RRset. + + The currently defined singleton types are CNAME, DNAME, NSEC, NXT, and + SOA. + + *rdtype* is an ``int``. + + Returns a ``bool``. + """ + + if rdtype in _singletons: + return True + return False + +# pylint: disable=redefined-outer-name +def register_type(rdtype, rdtype_text, is_singleton=False): + """Dynamically register an rdatatype. + + *rdtype*, an ``int``, the rdatatype to register. + + *rdtype_text*, a ``str``, the textual form of the rdatatype. + + *is_singleton*, a ``bool``, indicating if the type is a singleton (i.e. + RRsets of the type can have only one member.) + """ + + _registered_by_text[rdtype_text] = rdtype + _registered_by_value[rdtype] = rdtype_text + if is_singleton: + _singletons.add(rdtype) + +### BEGIN generated RdataType constants + +TYPE0 = RdataType.TYPE0 +NONE = RdataType.NONE +A = RdataType.A +NS = RdataType.NS +MD = RdataType.MD +MF = RdataType.MF +CNAME = RdataType.CNAME +SOA = RdataType.SOA +MB = RdataType.MB +MG = RdataType.MG +MR = RdataType.MR +NULL = RdataType.NULL +WKS = RdataType.WKS +PTR = RdataType.PTR +HINFO = RdataType.HINFO +MINFO = RdataType.MINFO +MX = RdataType.MX +TXT = RdataType.TXT +RP = RdataType.RP +AFSDB = RdataType.AFSDB +X25 = RdataType.X25 +ISDN = RdataType.ISDN +RT = RdataType.RT +NSAP = RdataType.NSAP +NSAP_PTR = RdataType.NSAP_PTR +SIG = RdataType.SIG +KEY = RdataType.KEY +PX = RdataType.PX +GPOS = RdataType.GPOS +AAAA = RdataType.AAAA +LOC = RdataType.LOC +NXT = RdataType.NXT +SRV = RdataType.SRV +NAPTR = RdataType.NAPTR +KX = RdataType.KX +CERT = RdataType.CERT +A6 = RdataType.A6 +DNAME = RdataType.DNAME +OPT = RdataType.OPT +APL = RdataType.APL +DS = RdataType.DS +SSHFP = RdataType.SSHFP +IPSECKEY = RdataType.IPSECKEY +RRSIG = RdataType.RRSIG +NSEC = RdataType.NSEC +DNSKEY = RdataType.DNSKEY +DHCID = RdataType.DHCID +NSEC3 = RdataType.NSEC3 +NSEC3PARAM = RdataType.NSEC3PARAM +TLSA = RdataType.TLSA +SMIMEA = RdataType.SMIMEA +HIP = RdataType.HIP +NINFO = RdataType.NINFO +CDS = RdataType.CDS +CDNSKEY = RdataType.CDNSKEY +OPENPGPKEY = RdataType.OPENPGPKEY +CSYNC = RdataType.CSYNC +SVCB = RdataType.SVCB +HTTPS = RdataType.HTTPS +SPF = RdataType.SPF +UNSPEC = RdataType.UNSPEC +EUI48 = RdataType.EUI48 +EUI64 = RdataType.EUI64 +TKEY = RdataType.TKEY +TSIG = RdataType.TSIG +IXFR = RdataType.IXFR +AXFR = RdataType.AXFR +MAILB = RdataType.MAILB +MAILA = RdataType.MAILA +ANY = RdataType.ANY +URI = RdataType.URI +CAA = RdataType.CAA +AVC = RdataType.AVC +AMTRELAY = RdataType.AMTRELAY +TA = RdataType.TA +DLV = RdataType.DLV + +### END generated RdataType constants diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/AFSDB.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/AFSDB.py new file mode 100644 index 0000000..d7838e7 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/AFSDB.py @@ -0,0 +1,46 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.mxbase +import dns.immutable + + +@dns.immutable.immutable +class AFSDB(dns.rdtypes.mxbase.UncompressedDowncasingMX): + + """AFSDB record""" + + # Use the property mechanism to make "subtype" an alias for the + # "preference" attribute, and "hostname" an alias for the "exchange" + # attribute. + # + # This lets us inherit the UncompressedMX implementation but lets + # the caller use appropriate attribute names for the rdata type. + # + # We probably lose some performance vs. a cut-and-paste + # implementation, but this way we don't copy code, and that's + # good. + + @property + def subtype(self): + "the AFSDB subtype" + return self.preference + + @property + def hostname(self): + "the AFSDB hostname" + return self.exchange diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/AMTRELAY.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/AMTRELAY.py new file mode 100644 index 0000000..9f093de --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/AMTRELAY.py @@ -0,0 +1,86 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdtypes.util + + +class Relay(dns.rdtypes.util.Gateway): + name = 'AMTRELAY relay' + + @property + def relay(self): + return self.gateway + + +@dns.immutable.immutable +class AMTRELAY(dns.rdata.Rdata): + + """AMTRELAY record""" + + # see: RFC 8777 + + __slots__ = ['precedence', 'discovery_optional', 'relay_type', 'relay'] + + def __init__(self, rdclass, rdtype, precedence, discovery_optional, + relay_type, relay): + super().__init__(rdclass, rdtype) + relay = Relay(relay_type, relay) + self.precedence = self._as_uint8(precedence) + self.discovery_optional = self._as_bool(discovery_optional) + self.relay_type = relay.type + self.relay = relay.relay + + def to_text(self, origin=None, relativize=True, **kw): + relay = Relay(self.relay_type, self.relay).to_text(origin, relativize) + return '%d %d %d %s' % (self.precedence, self.discovery_optional, + self.relay_type, relay) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + precedence = tok.get_uint8() + discovery_optional = tok.get_uint8() + if discovery_optional > 1: + raise dns.exception.SyntaxError('expecting 0 or 1') + discovery_optional = bool(discovery_optional) + relay_type = tok.get_uint8() + if relay_type > 0x7f: + raise dns.exception.SyntaxError('expecting an integer <= 127') + relay = Relay.from_text(relay_type, tok, origin, relativize, + relativize_to) + return cls(rdclass, rdtype, precedence, discovery_optional, relay_type, + relay.relay) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + relay_type = self.relay_type | (self.discovery_optional << 7) + header = struct.pack("!BB", self.precedence, relay_type) + file.write(header) + Relay(self.relay_type, self.relay).to_wire(file, compress, origin, + canonicalize) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + (precedence, relay_type) = parser.get_struct('!BB') + discovery_optional = bool(relay_type >> 7) + relay_type &= 0x7f + relay = Relay.from_wire_parser(relay_type, parser, origin) + return cls(rdclass, rdtype, precedence, discovery_optional, relay_type, + relay.relay) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/AVC.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/AVC.py new file mode 100644 index 0000000..11e026d --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/AVC.py @@ -0,0 +1,27 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2016 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.txtbase +import dns.immutable + + +@dns.immutable.immutable +class AVC(dns.rdtypes.txtbase.TXTBase): + + """AVC record""" + + # See: IANA dns parameters for AVC diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/CAA.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/CAA.py new file mode 100644 index 0000000..c86b45e --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/CAA.py @@ -0,0 +1,69 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.tokenizer + + +@dns.immutable.immutable +class CAA(dns.rdata.Rdata): + + """CAA (Certification Authority Authorization) record""" + + # see: RFC 6844 + + __slots__ = ['flags', 'tag', 'value'] + + def __init__(self, rdclass, rdtype, flags, tag, value): + super().__init__(rdclass, rdtype) + self.flags = self._as_uint8(flags) + self.tag = self._as_bytes(tag, True, 255) + if not tag.isalnum(): + raise ValueError("tag is not alphanumeric") + self.value = self._as_bytes(value) + + def to_text(self, origin=None, relativize=True, **kw): + return '%u %s "%s"' % (self.flags, + dns.rdata._escapify(self.tag), + dns.rdata._escapify(self.value)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + flags = tok.get_uint8() + tag = tok.get_string().encode() + value = tok.get_string().encode() + return cls(rdclass, rdtype, flags, tag, value) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(struct.pack('!B', self.flags)) + l = len(self.tag) + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(self.tag) + file.write(self.value) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + flags = parser.get_uint8() + tag = parser.get_counted_bytes() + value = parser.get_remaining() + return cls(rdclass, rdtype, flags, tag, value) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/CDNSKEY.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/CDNSKEY.py new file mode 100644 index 0000000..14b1941 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/CDNSKEY.py @@ -0,0 +1,28 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.dnskeybase +import dns.immutable + +# pylint: disable=unused-import +from dns.rdtypes.dnskeybase import SEP, REVOKE, ZONE # noqa: F401 +# pylint: enable=unused-import + +@dns.immutable.immutable +class CDNSKEY(dns.rdtypes.dnskeybase.DNSKEYBase): + + """CDNSKEY record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/CDS.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/CDS.py new file mode 100644 index 0000000..39e3556 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/CDS.py @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.dsbase +import dns.immutable + + +@dns.immutable.immutable +class CDS(dns.rdtypes.dsbase.DSBase): + + """CDS record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/CERT.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/CERT.py new file mode 100644 index 0000000..5f26dde --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/CERT.py @@ -0,0 +1,103 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct +import base64 + +import dns.exception +import dns.immutable +import dns.dnssec +import dns.rdata +import dns.tokenizer + +_ctype_by_value = { + 1: 'PKIX', + 2: 'SPKI', + 3: 'PGP', + 253: 'URI', + 254: 'OID', +} + +_ctype_by_name = { + 'PKIX': 1, + 'SPKI': 2, + 'PGP': 3, + 'URI': 253, + 'OID': 254, +} + + +def _ctype_from_text(what): + v = _ctype_by_name.get(what) + if v is not None: + return v + return int(what) + + +def _ctype_to_text(what): + v = _ctype_by_value.get(what) + if v is not None: + return v + return str(what) + + +@dns.immutable.immutable +class CERT(dns.rdata.Rdata): + + """CERT record""" + + # see RFC 2538 + + __slots__ = ['certificate_type', 'key_tag', 'algorithm', 'certificate'] + + def __init__(self, rdclass, rdtype, certificate_type, key_tag, algorithm, + certificate): + super().__init__(rdclass, rdtype) + self.certificate_type = self._as_uint16(certificate_type) + self.key_tag = self._as_uint16(key_tag) + self.algorithm = self._as_uint8(algorithm) + self.certificate = self._as_bytes(certificate) + + def to_text(self, origin=None, relativize=True, **kw): + certificate_type = _ctype_to_text(self.certificate_type) + return "%s %d %s %s" % (certificate_type, self.key_tag, + dns.dnssec.algorithm_to_text(self.algorithm), + dns.rdata._base64ify(self.certificate, **kw)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + certificate_type = _ctype_from_text(tok.get_string()) + key_tag = tok.get_uint16() + algorithm = dns.dnssec.algorithm_from_text(tok.get_string()) + b64 = tok.concatenate_remaining_identifiers().encode() + certificate = base64.b64decode(b64) + return cls(rdclass, rdtype, certificate_type, key_tag, + algorithm, certificate) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + prefix = struct.pack("!HHB", self.certificate_type, self.key_tag, + self.algorithm) + file.write(prefix) + file.write(self.certificate) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + (certificate_type, key_tag, algorithm) = parser.get_struct("!HHB") + certificate = parser.get_remaining() + return cls(rdclass, rdtype, certificate_type, key_tag, algorithm, + certificate) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/CNAME.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/CNAME.py new file mode 100644 index 0000000..a4fcfa8 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/CNAME.py @@ -0,0 +1,29 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.nsbase +import dns.immutable + + +@dns.immutable.immutable +class CNAME(dns.rdtypes.nsbase.NSBase): + + """CNAME record + + Note: although CNAME is officially a singleton type, dnspython allows + non-singleton CNAME rdatasets because such sets have been commonly + used by BIND and other nameservers for load balancing.""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/CSYNC.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/CSYNC.py new file mode 100644 index 0000000..979028a --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/CSYNC.py @@ -0,0 +1,68 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2004-2007, 2009-2011, 2016 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.rdatatype +import dns.name +import dns.rdtypes.util + + +@dns.immutable.immutable +class Bitmap(dns.rdtypes.util.Bitmap): + type_name = 'CSYNC' + + +@dns.immutable.immutable +class CSYNC(dns.rdata.Rdata): + + """CSYNC record""" + + __slots__ = ['serial', 'flags', 'windows'] + + def __init__(self, rdclass, rdtype, serial, flags, windows): + super().__init__(rdclass, rdtype) + self.serial = self._as_uint32(serial) + self.flags = self._as_uint16(flags) + if not isinstance(windows, Bitmap): + windows = Bitmap(windows) + self.windows = tuple(windows.windows) + + def to_text(self, origin=None, relativize=True, **kw): + text = Bitmap(self.windows).to_text() + return '%d %d%s' % (self.serial, self.flags, text) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + serial = tok.get_uint32() + flags = tok.get_uint16() + bitmap = Bitmap.from_text(tok) + return cls(rdclass, rdtype, serial, flags, bitmap) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(struct.pack('!IH', self.serial, self.flags)) + Bitmap(self.windows).to_wire(file) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + (serial, flags) = parser.get_struct("!IH") + bitmap = Bitmap.from_wire_parser(parser) + return cls(rdclass, rdtype, serial, flags, bitmap) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/DLV.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/DLV.py new file mode 100644 index 0000000..947dc42 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/DLV.py @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.dsbase +import dns.immutable + + +@dns.immutable.immutable +class DLV(dns.rdtypes.dsbase.DSBase): + + """DLV record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/DNAME.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/DNAME.py new file mode 100644 index 0000000..f4984b5 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/DNAME.py @@ -0,0 +1,28 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.nsbase +import dns.immutable + + +@dns.immutable.immutable +class DNAME(dns.rdtypes.nsbase.UncompressedNS): + + """DNAME record""" + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.target.to_wire(file, None, origin, canonicalize) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/DNSKEY.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/DNSKEY.py new file mode 100644 index 0000000..e69a7c1 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/DNSKEY.py @@ -0,0 +1,28 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.dnskeybase +import dns.immutable + +# pylint: disable=unused-import +from dns.rdtypes.dnskeybase import SEP, REVOKE, ZONE # noqa: F401 +# pylint: enable=unused-import + +@dns.immutable.immutable +class DNSKEY(dns.rdtypes.dnskeybase.DNSKEYBase): + + """DNSKEY record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/DS.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/DS.py new file mode 100644 index 0000000..3f6c3ee --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/DS.py @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.dsbase +import dns.immutable + + +@dns.immutable.immutable +class DS(dns.rdtypes.dsbase.DSBase): + + """DS record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/EUI48.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/EUI48.py new file mode 100644 index 0000000..0ab88ad --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/EUI48.py @@ -0,0 +1,31 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2015 Red Hat, Inc. +# Author: Petr Spacek +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.euibase +import dns.immutable + + +@dns.immutable.immutable +class EUI48(dns.rdtypes.euibase.EUIBase): + + """EUI48 record""" + + # see: rfc7043.txt + + byte_len = 6 # 0123456789ab (in hex) + text_len = byte_len * 3 - 1 # 01-23-45-67-89-ab diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/EUI64.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/EUI64.py new file mode 100644 index 0000000..c42957e --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/EUI64.py @@ -0,0 +1,31 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2015 Red Hat, Inc. +# Author: Petr Spacek +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.euibase +import dns.immutable + + +@dns.immutable.immutable +class EUI64(dns.rdtypes.euibase.EUIBase): + + """EUI64 record""" + + # see: rfc7043.txt + + byte_len = 8 # 0123456789abcdef (in hex) + text_len = byte_len * 3 - 1 # 01-23-45-67-89-ab-cd-ef diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/GPOS.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/GPOS.py new file mode 100644 index 0000000..29fa8f8 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/GPOS.py @@ -0,0 +1,128 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.tokenizer + + +def _validate_float_string(what): + if len(what) == 0: + raise dns.exception.FormError + if what[0] == b'-'[0] or what[0] == b'+'[0]: + what = what[1:] + if what.isdigit(): + return + try: + (left, right) = what.split(b'.') + except ValueError: + raise dns.exception.FormError + if left == b'' and right == b'': + raise dns.exception.FormError + if not left == b'' and not left.decode().isdigit(): + raise dns.exception.FormError + if not right == b'' and not right.decode().isdigit(): + raise dns.exception.FormError + + +@dns.immutable.immutable +class GPOS(dns.rdata.Rdata): + + """GPOS record""" + + # see: RFC 1712 + + __slots__ = ['latitude', 'longitude', 'altitude'] + + def __init__(self, rdclass, rdtype, latitude, longitude, altitude): + super().__init__(rdclass, rdtype) + if isinstance(latitude, float) or \ + isinstance(latitude, int): + latitude = str(latitude) + if isinstance(longitude, float) or \ + isinstance(longitude, int): + longitude = str(longitude) + if isinstance(altitude, float) or \ + isinstance(altitude, int): + altitude = str(altitude) + latitude = self._as_bytes(latitude, True, 255) + longitude = self._as_bytes(longitude, True, 255) + altitude = self._as_bytes(altitude, True, 255) + _validate_float_string(latitude) + _validate_float_string(longitude) + _validate_float_string(altitude) + self.latitude = latitude + self.longitude = longitude + self.altitude = altitude + flat = self.float_latitude + if flat < -90.0 or flat > 90.0: + raise dns.exception.FormError('bad latitude') + flong = self.float_longitude + if flong < -180.0 or flong > 180.0: + raise dns.exception.FormError('bad longitude') + + def to_text(self, origin=None, relativize=True, **kw): + return '{} {} {}'.format(self.latitude.decode(), + self.longitude.decode(), + self.altitude.decode()) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + latitude = tok.get_string() + longitude = tok.get_string() + altitude = tok.get_string() + return cls(rdclass, rdtype, latitude, longitude, altitude) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + l = len(self.latitude) + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(self.latitude) + l = len(self.longitude) + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(self.longitude) + l = len(self.altitude) + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(self.altitude) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + latitude = parser.get_counted_bytes() + longitude = parser.get_counted_bytes() + altitude = parser.get_counted_bytes() + return cls(rdclass, rdtype, latitude, longitude, altitude) + + @property + def float_latitude(self): + "latitude as a floating point value" + return float(self.latitude) + + @property + def float_longitude(self): + "longitude as a floating point value" + return float(self.longitude) + + @property + def float_altitude(self): + "altitude as a floating point value" + return float(self.altitude) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/HINFO.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/HINFO.py new file mode 100644 index 0000000..cd04969 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/HINFO.py @@ -0,0 +1,65 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.tokenizer + + +@dns.immutable.immutable +class HINFO(dns.rdata.Rdata): + + """HINFO record""" + + # see: RFC 1035 + + __slots__ = ['cpu', 'os'] + + def __init__(self, rdclass, rdtype, cpu, os): + super().__init__(rdclass, rdtype) + self.cpu = self._as_bytes(cpu, True, 255) + self.os = self._as_bytes(os, True, 255) + + def to_text(self, origin=None, relativize=True, **kw): + return '"{}" "{}"'.format(dns.rdata._escapify(self.cpu), + dns.rdata._escapify(self.os)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + cpu = tok.get_string(max_length=255) + os = tok.get_string(max_length=255) + return cls(rdclass, rdtype, cpu, os) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + l = len(self.cpu) + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(self.cpu) + l = len(self.os) + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(self.os) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + cpu = parser.get_counted_bytes() + os = parser.get_counted_bytes() + return cls(rdclass, rdtype, cpu, os) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/HIP.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/HIP.py new file mode 100644 index 0000000..e887359 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/HIP.py @@ -0,0 +1,85 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2010, 2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct +import base64 +import binascii + +import dns.exception +import dns.immutable +import dns.rdata +import dns.rdatatype + + +@dns.immutable.immutable +class HIP(dns.rdata.Rdata): + + """HIP record""" + + # see: RFC 5205 + + __slots__ = ['hit', 'algorithm', 'key', 'servers'] + + def __init__(self, rdclass, rdtype, hit, algorithm, key, servers): + super().__init__(rdclass, rdtype) + self.hit = self._as_bytes(hit, True, 255) + self.algorithm = self._as_uint8(algorithm) + self.key = self._as_bytes(key, True) + self.servers = self._as_tuple(servers, self._as_name) + + def to_text(self, origin=None, relativize=True, **kw): + hit = binascii.hexlify(self.hit).decode() + key = base64.b64encode(self.key).replace(b'\n', b'').decode() + text = '' + servers = [] + for server in self.servers: + servers.append(server.choose_relativity(origin, relativize)) + if len(servers) > 0: + text += (' ' + ' '.join((x.to_unicode() for x in servers))) + return '%u %s %s%s' % (self.algorithm, hit, key, text) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + algorithm = tok.get_uint8() + hit = binascii.unhexlify(tok.get_string().encode()) + key = base64.b64decode(tok.get_string().encode()) + servers = [] + for token in tok.get_remaining(): + server = tok.as_name(token, origin, relativize, relativize_to) + servers.append(server) + return cls(rdclass, rdtype, hit, algorithm, key, servers) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + lh = len(self.hit) + lk = len(self.key) + file.write(struct.pack("!BBH", lh, self.algorithm, lk)) + file.write(self.hit) + file.write(self.key) + for server in self.servers: + server.to_wire(file, None, origin, False) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + (lh, algorithm, lk) = parser.get_struct('!BBH') + hit = parser.get_bytes(lh) + key = parser.get_bytes(lk) + servers = [] + while parser.remaining() > 0: + server = parser.get_name(origin) + servers.append(server) + return cls(rdclass, rdtype, hit, algorithm, key, servers) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/ISDN.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/ISDN.py new file mode 100644 index 0000000..b9a49ad --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/ISDN.py @@ -0,0 +1,76 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.tokenizer + + +@dns.immutable.immutable +class ISDN(dns.rdata.Rdata): + + """ISDN record""" + + # see: RFC 1183 + + __slots__ = ['address', 'subaddress'] + + def __init__(self, rdclass, rdtype, address, subaddress): + super().__init__(rdclass, rdtype) + self.address = self._as_bytes(address, True, 255) + self.subaddress = self._as_bytes(subaddress, True, 255) + + def to_text(self, origin=None, relativize=True, **kw): + if self.subaddress: + return '"{}" "{}"'.format(dns.rdata._escapify(self.address), + dns.rdata._escapify(self.subaddress)) + else: + return '"%s"' % dns.rdata._escapify(self.address) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + address = tok.get_string() + tokens = tok.get_remaining(max_tokens=1) + if len(tokens) >= 1: + subaddress = tokens[0].unescape().value + else: + subaddress = '' + return cls(rdclass, rdtype, address, subaddress) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + l = len(self.address) + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(self.address) + l = len(self.subaddress) + if l > 0: + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(self.subaddress) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + address = parser.get_counted_bytes() + if parser.remaining() > 0: + subaddress = parser.get_counted_bytes() + else: + subaddress = b'' + return cls(rdclass, rdtype, address, subaddress) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/LOC.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/LOC.py new file mode 100644 index 0000000..1a4ee2b --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/LOC.py @@ -0,0 +1,326 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata + + +_pows = tuple(10**i for i in range(0, 11)) + +# default values are in centimeters +_default_size = 100.0 +_default_hprec = 1000000.0 +_default_vprec = 1000.0 + +# for use by from_wire() +_MAX_LATITUDE = 0x80000000 + 90 * 3600000 +_MIN_LATITUDE = 0x80000000 - 90 * 3600000 +_MAX_LONGITUDE = 0x80000000 + 180 * 3600000 +_MIN_LONGITUDE = 0x80000000 - 180 * 3600000 + + +def _exponent_of(what, desc): + if what == 0: + return 0 + exp = None + for (i, pow) in enumerate(_pows): + if what < pow: + exp = i - 1 + break + if exp is None or exp < 0: + raise dns.exception.SyntaxError("%s value out of bounds" % desc) + return exp + + +def _float_to_tuple(what): + if what < 0: + sign = -1 + what *= -1 + else: + sign = 1 + what = round(what * 3600000) # pylint: disable=round-builtin + degrees = int(what // 3600000) + what -= degrees * 3600000 + minutes = int(what // 60000) + what -= minutes * 60000 + seconds = int(what // 1000) + what -= int(seconds * 1000) + what = int(what) + return (degrees, minutes, seconds, what, sign) + + +def _tuple_to_float(what): + value = float(what[0]) + value += float(what[1]) / 60.0 + value += float(what[2]) / 3600.0 + value += float(what[3]) / 3600000.0 + return float(what[4]) * value + + +def _encode_size(what, desc): + what = int(what) + exponent = _exponent_of(what, desc) & 0xF + base = what // pow(10, exponent) & 0xF + return base * 16 + exponent + + +def _decode_size(what, desc): + exponent = what & 0x0F + if exponent > 9: + raise dns.exception.FormError("bad %s exponent" % desc) + base = (what & 0xF0) >> 4 + if base > 9: + raise dns.exception.FormError("bad %s base" % desc) + return base * pow(10, exponent) + + +def _check_coordinate_list(value, low, high): + if value[0] < low or value[0] > high: + raise ValueError(f'not in range [{low}, {high}]') + if value[1] < 0 or value[1] > 59: + raise ValueError('bad minutes value') + if value[2] < 0 or value[2] > 59: + raise ValueError('bad seconds value') + if value[3] < 0 or value[3] > 999: + raise ValueError('bad milliseconds value') + if value[4] != 1 and value[4] != -1: + raise ValueError('bad hemisphere value') + + +@dns.immutable.immutable +class LOC(dns.rdata.Rdata): + + """LOC record""" + + # see: RFC 1876 + + __slots__ = ['latitude', 'longitude', 'altitude', 'size', + 'horizontal_precision', 'vertical_precision'] + + def __init__(self, rdclass, rdtype, latitude, longitude, altitude, + size=_default_size, hprec=_default_hprec, + vprec=_default_vprec): + """Initialize a LOC record instance. + + The parameters I{latitude} and I{longitude} may be either a 4-tuple + of integers specifying (degrees, minutes, seconds, milliseconds), + or they may be floating point values specifying the number of + degrees. The other parameters are floats. Size, horizontal precision, + and vertical precision are specified in centimeters.""" + + super().__init__(rdclass, rdtype) + if isinstance(latitude, int): + latitude = float(latitude) + if isinstance(latitude, float): + latitude = _float_to_tuple(latitude) + _check_coordinate_list(latitude, -90, 90) + self.latitude = tuple(latitude) + if isinstance(longitude, int): + longitude = float(longitude) + if isinstance(longitude, float): + longitude = _float_to_tuple(longitude) + _check_coordinate_list(longitude, -180, 180) + self.longitude = tuple(longitude) + self.altitude = float(altitude) + self.size = float(size) + self.horizontal_precision = float(hprec) + self.vertical_precision = float(vprec) + + def to_text(self, origin=None, relativize=True, **kw): + if self.latitude[4] > 0: + lat_hemisphere = 'N' + else: + lat_hemisphere = 'S' + if self.longitude[4] > 0: + long_hemisphere = 'E' + else: + long_hemisphere = 'W' + text = "%d %d %d.%03d %s %d %d %d.%03d %s %0.2fm" % ( + self.latitude[0], self.latitude[1], + self.latitude[2], self.latitude[3], lat_hemisphere, + self.longitude[0], self.longitude[1], self.longitude[2], + self.longitude[3], long_hemisphere, + self.altitude / 100.0 + ) + + # do not print default values + if self.size != _default_size or \ + self.horizontal_precision != _default_hprec or \ + self.vertical_precision != _default_vprec: + text += " {:0.2f}m {:0.2f}m {:0.2f}m".format( + self.size / 100.0, self.horizontal_precision / 100.0, + self.vertical_precision / 100.0 + ) + return text + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + latitude = [0, 0, 0, 0, 1] + longitude = [0, 0, 0, 0, 1] + size = _default_size + hprec = _default_hprec + vprec = _default_vprec + + latitude[0] = tok.get_int() + t = tok.get_string() + if t.isdigit(): + latitude[1] = int(t) + t = tok.get_string() + if '.' in t: + (seconds, milliseconds) = t.split('.') + if not seconds.isdigit(): + raise dns.exception.SyntaxError( + 'bad latitude seconds value') + latitude[2] = int(seconds) + l = len(milliseconds) + if l == 0 or l > 3 or not milliseconds.isdigit(): + raise dns.exception.SyntaxError( + 'bad latitude milliseconds value') + if l == 1: + m = 100 + elif l == 2: + m = 10 + else: + m = 1 + latitude[3] = m * int(milliseconds) + t = tok.get_string() + elif t.isdigit(): + latitude[2] = int(t) + t = tok.get_string() + if t == 'S': + latitude[4] = -1 + elif t != 'N': + raise dns.exception.SyntaxError('bad latitude hemisphere value') + + longitude[0] = tok.get_int() + t = tok.get_string() + if t.isdigit(): + longitude[1] = int(t) + t = tok.get_string() + if '.' in t: + (seconds, milliseconds) = t.split('.') + if not seconds.isdigit(): + raise dns.exception.SyntaxError( + 'bad longitude seconds value') + longitude[2] = int(seconds) + l = len(milliseconds) + if l == 0 or l > 3 or not milliseconds.isdigit(): + raise dns.exception.SyntaxError( + 'bad longitude milliseconds value') + if l == 1: + m = 100 + elif l == 2: + m = 10 + else: + m = 1 + longitude[3] = m * int(milliseconds) + t = tok.get_string() + elif t.isdigit(): + longitude[2] = int(t) + t = tok.get_string() + if t == 'W': + longitude[4] = -1 + elif t != 'E': + raise dns.exception.SyntaxError('bad longitude hemisphere value') + + t = tok.get_string() + if t[-1] == 'm': + t = t[0: -1] + altitude = float(t) * 100.0 # m -> cm + + tokens = tok.get_remaining(max_tokens=3) + if len(tokens) >= 1: + value = tokens[0].unescape().value + if value[-1] == 'm': + value = value[0: -1] + size = float(value) * 100.0 # m -> cm + if len(tokens) >= 2: + value = tokens[1].unescape().value + if value[-1] == 'm': + value = value[0: -1] + hprec = float(value) * 100.0 # m -> cm + if len(tokens) >= 3: + value = tokens[2].unescape().value + if value[-1] == 'm': + value = value[0: -1] + vprec = float(value) * 100.0 # m -> cm + + # Try encoding these now so we raise if they are bad + _encode_size(size, "size") + _encode_size(hprec, "horizontal precision") + _encode_size(vprec, "vertical precision") + + return cls(rdclass, rdtype, latitude, longitude, altitude, + size, hprec, vprec) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + milliseconds = (self.latitude[0] * 3600000 + + self.latitude[1] * 60000 + + self.latitude[2] * 1000 + + self.latitude[3]) * self.latitude[4] + latitude = 0x80000000 + milliseconds + milliseconds = (self.longitude[0] * 3600000 + + self.longitude[1] * 60000 + + self.longitude[2] * 1000 + + self.longitude[3]) * self.longitude[4] + longitude = 0x80000000 + milliseconds + altitude = int(self.altitude) + 10000000 + size = _encode_size(self.size, "size") + hprec = _encode_size(self.horizontal_precision, "horizontal precision") + vprec = _encode_size(self.vertical_precision, "vertical precision") + wire = struct.pack("!BBBBIII", 0, size, hprec, vprec, latitude, + longitude, altitude) + file.write(wire) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + (version, size, hprec, vprec, latitude, longitude, altitude) = \ + parser.get_struct("!BBBBIII") + if version != 0: + raise dns.exception.FormError("LOC version not zero") + if latitude < _MIN_LATITUDE or latitude > _MAX_LATITUDE: + raise dns.exception.FormError("bad latitude") + if latitude > 0x80000000: + latitude = (latitude - 0x80000000) / 3600000 + else: + latitude = -1 * (0x80000000 - latitude) / 3600000 + if longitude < _MIN_LONGITUDE or longitude > _MAX_LONGITUDE: + raise dns.exception.FormError("bad longitude") + if longitude > 0x80000000: + longitude = (longitude - 0x80000000) / 3600000 + else: + longitude = -1 * (0x80000000 - longitude) / 3600000 + altitude = float(altitude) - 10000000.0 + size = _decode_size(size, "size") + hprec = _decode_size(hprec, "horizontal precision") + vprec = _decode_size(vprec, "vertical precision") + return cls(rdclass, rdtype, latitude, longitude, altitude, + size, hprec, vprec) + + @property + def float_latitude(self): + "latitude as a floating point value" + return _tuple_to_float(self.latitude) + + @property + def float_longitude(self): + "longitude as a floating point value" + return _tuple_to_float(self.longitude) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/MX.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/MX.py new file mode 100644 index 0000000..a697ea4 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/MX.py @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.mxbase +import dns.immutable + + +@dns.immutable.immutable +class MX(dns.rdtypes.mxbase.MXBase): + + """MX record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/NINFO.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/NINFO.py new file mode 100644 index 0000000..d53e967 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/NINFO.py @@ -0,0 +1,27 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.txtbase +import dns.immutable + + +@dns.immutable.immutable +class NINFO(dns.rdtypes.txtbase.TXTBase): + + """NINFO record""" + + # see: draft-reid-dnsext-zs-01 diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/NS.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/NS.py new file mode 100644 index 0000000..a0cc232 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/NS.py @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.nsbase +import dns.immutable + + +@dns.immutable.immutable +class NS(dns.rdtypes.nsbase.NSBase): + + """NS record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/NSEC.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/NSEC.py new file mode 100644 index 0000000..dc31f4c --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/NSEC.py @@ -0,0 +1,67 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.exception +import dns.immutable +import dns.rdata +import dns.rdatatype +import dns.name +import dns.rdtypes.util + + +@dns.immutable.immutable +class Bitmap(dns.rdtypes.util.Bitmap): + type_name = 'NSEC' + + +@dns.immutable.immutable +class NSEC(dns.rdata.Rdata): + + """NSEC record""" + + __slots__ = ['next', 'windows'] + + def __init__(self, rdclass, rdtype, next, windows): + super().__init__(rdclass, rdtype) + self.next = self._as_name(next) + if not isinstance(windows, Bitmap): + windows = Bitmap(windows) + self.windows = tuple(windows.windows) + + def to_text(self, origin=None, relativize=True, **kw): + next = self.next.choose_relativity(origin, relativize) + text = Bitmap(self.windows).to_text() + return '{}{}'.format(next, text) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + next = tok.get_name(origin, relativize, relativize_to) + windows = Bitmap.from_text(tok) + return cls(rdclass, rdtype, next, windows) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + # Note that NSEC downcasing, originally mandated by RFC 4034 + # section 6.2 was removed by RFC 6840 section 5.1. + self.next.to_wire(file, None, origin, False) + Bitmap(self.windows).to_wire(file) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + next = parser.get_name(origin) + bitmap = Bitmap.from_wire_parser(parser) + return cls(rdclass, rdtype, next, bitmap) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/NSEC3.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/NSEC3.py new file mode 100644 index 0000000..14242bd --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/NSEC3.py @@ -0,0 +1,111 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2004-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import base64 +import binascii +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.rdatatype +import dns.rdtypes.util + + +b32_hex_to_normal = bytes.maketrans(b'0123456789ABCDEFGHIJKLMNOPQRSTUV', + b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567') +b32_normal_to_hex = bytes.maketrans(b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', + b'0123456789ABCDEFGHIJKLMNOPQRSTUV') + +# hash algorithm constants +SHA1 = 1 + +# flag constants +OPTOUT = 1 + + +@dns.immutable.immutable +class Bitmap(dns.rdtypes.util.Bitmap): + type_name = 'NSEC3' + + +@dns.immutable.immutable +class NSEC3(dns.rdata.Rdata): + + """NSEC3 record""" + + __slots__ = ['algorithm', 'flags', 'iterations', 'salt', 'next', 'windows'] + + def __init__(self, rdclass, rdtype, algorithm, flags, iterations, salt, + next, windows): + super().__init__(rdclass, rdtype) + self.algorithm = self._as_uint8(algorithm) + self.flags = self._as_uint8(flags) + self.iterations = self._as_uint16(iterations) + self.salt = self._as_bytes(salt, True, 255) + self.next = self._as_bytes(next, True, 255) + if not isinstance(windows, Bitmap): + windows = Bitmap(windows) + self.windows = tuple(windows.windows) + + def to_text(self, origin=None, relativize=True, **kw): + next = base64.b32encode(self.next).translate( + b32_normal_to_hex).lower().decode() + if self.salt == b'': + salt = '-' + else: + salt = binascii.hexlify(self.salt).decode() + text = Bitmap(self.windows).to_text() + return '%u %u %u %s %s%s' % (self.algorithm, self.flags, + self.iterations, salt, next, text) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + algorithm = tok.get_uint8() + flags = tok.get_uint8() + iterations = tok.get_uint16() + salt = tok.get_string() + if salt == '-': + salt = b'' + else: + salt = binascii.unhexlify(salt.encode('ascii')) + next = tok.get_string().encode( + 'ascii').upper().translate(b32_hex_to_normal) + next = base64.b32decode(next) + bitmap = Bitmap.from_text(tok) + return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next, + bitmap) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + l = len(self.salt) + file.write(struct.pack("!BBHB", self.algorithm, self.flags, + self.iterations, l)) + file.write(self.salt) + l = len(self.next) + file.write(struct.pack("!B", l)) + file.write(self.next) + Bitmap(self.windows).to_wire(file) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + (algorithm, flags, iterations) = parser.get_struct('!BBH') + salt = parser.get_counted_bytes() + next = parser.get_counted_bytes() + bitmap = Bitmap.from_wire_parser(parser) + return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next, + bitmap) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/NSEC3PARAM.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/NSEC3PARAM.py new file mode 100644 index 0000000..299bf6e --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/NSEC3PARAM.py @@ -0,0 +1,71 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct +import binascii + +import dns.exception +import dns.immutable +import dns.rdata + + +@dns.immutable.immutable +class NSEC3PARAM(dns.rdata.Rdata): + + """NSEC3PARAM record""" + + __slots__ = ['algorithm', 'flags', 'iterations', 'salt'] + + def __init__(self, rdclass, rdtype, algorithm, flags, iterations, salt): + super().__init__(rdclass, rdtype) + self.algorithm = self._as_uint8(algorithm) + self.flags = self._as_uint8(flags) + self.iterations = self._as_uint16(iterations) + self.salt = self._as_bytes(salt, True, 255) + + def to_text(self, origin=None, relativize=True, **kw): + if self.salt == b'': + salt = '-' + else: + salt = binascii.hexlify(self.salt).decode() + return '%u %u %u %s' % (self.algorithm, self.flags, self.iterations, + salt) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + algorithm = tok.get_uint8() + flags = tok.get_uint8() + iterations = tok.get_uint16() + salt = tok.get_string() + if salt == '-': + salt = '' + else: + salt = binascii.unhexlify(salt.encode()) + return cls(rdclass, rdtype, algorithm, flags, iterations, salt) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + l = len(self.salt) + file.write(struct.pack("!BBHB", self.algorithm, self.flags, + self.iterations, l)) + file.write(self.salt) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + (algorithm, flags, iterations) = parser.get_struct('!BBH') + salt = parser.get_counted_bytes() + return cls(rdclass, rdtype, algorithm, flags, iterations, salt) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/OPENPGPKEY.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/OPENPGPKEY.py new file mode 100644 index 0000000..dcfa028 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/OPENPGPKEY.py @@ -0,0 +1,52 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2016 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import base64 + +import dns.exception +import dns.immutable +import dns.rdata +import dns.tokenizer + +@dns.immutable.immutable +class OPENPGPKEY(dns.rdata.Rdata): + + """OPENPGPKEY record""" + + # see: RFC 7929 + + def __init__(self, rdclass, rdtype, key): + super().__init__(rdclass, rdtype) + self.key = self._as_bytes(key) + + def to_text(self, origin=None, relativize=True, **kw): + return dns.rdata._base64ify(self.key, chunksize=None, **kw) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + b64 = tok.concatenate_remaining_identifiers().encode() + key = base64.b64decode(b64) + return cls(rdclass, rdtype, key) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(self.key) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + key = parser.get_remaining() + return cls(rdclass, rdtype, key) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/OPT.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/OPT.py new file mode 100644 index 0000000..69b8fe7 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/OPT.py @@ -0,0 +1,76 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.edns +import dns.immutable +import dns.exception +import dns.rdata + + +# We don't implement from_text, and that's ok. +# pylint: disable=abstract-method + +@dns.immutable.immutable +class OPT(dns.rdata.Rdata): + + """OPT record""" + + __slots__ = ['options'] + + def __init__(self, rdclass, rdtype, options): + """Initialize an OPT rdata. + + *rdclass*, an ``int`` is the rdataclass of the Rdata, + which is also the payload size. + + *rdtype*, an ``int`` is the rdatatype of the Rdata. + + *options*, a tuple of ``bytes`` + """ + + super().__init__(rdclass, rdtype) + def as_option(option): + if not isinstance(option, dns.edns.Option): + raise ValueError('option is not a dns.edns.option') + return option + self.options = self._as_tuple(options, as_option) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + for opt in self.options: + owire = opt.to_wire() + file.write(struct.pack("!HH", opt.otype, len(owire))) + file.write(owire) + + def to_text(self, origin=None, relativize=True, **kw): + return ' '.join(opt.to_text() for opt in self.options) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + options = [] + while parser.remaining() > 0: + (otype, olen) = parser.get_struct('!HH') + with parser.restrict_to(olen): + opt = dns.edns.option_from_wire_parser(otype, parser) + options.append(opt) + return cls(rdclass, rdtype, options) + + @property + def payload(self): + "payload size" + return self.rdclass diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/PTR.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/PTR.py new file mode 100644 index 0000000..265bed0 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/PTR.py @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.nsbase +import dns.immutable + + +@dns.immutable.immutable +class PTR(dns.rdtypes.nsbase.NSBase): + + """PTR record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/RP.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/RP.py new file mode 100644 index 0000000..a4e2297 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/RP.py @@ -0,0 +1,58 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.exception +import dns.immutable +import dns.rdata +import dns.name + + +@dns.immutable.immutable +class RP(dns.rdata.Rdata): + + """RP record""" + + # see: RFC 1183 + + __slots__ = ['mbox', 'txt'] + + def __init__(self, rdclass, rdtype, mbox, txt): + super().__init__(rdclass, rdtype) + self.mbox = self._as_name(mbox) + self.txt = self._as_name(txt) + + def to_text(self, origin=None, relativize=True, **kw): + mbox = self.mbox.choose_relativity(origin, relativize) + txt = self.txt.choose_relativity(origin, relativize) + return "{} {}".format(str(mbox), str(txt)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + mbox = tok.get_name(origin, relativize, relativize_to) + txt = tok.get_name(origin, relativize, relativize_to) + return cls(rdclass, rdtype, mbox, txt) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.mbox.to_wire(file, None, origin, canonicalize) + self.txt.to_wire(file, None, origin, canonicalize) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + mbox = parser.get_name(origin) + txt = parser.get_name(origin) + return cls(rdclass, rdtype, mbox, txt) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/RRSIG.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/RRSIG.py new file mode 100644 index 0000000..d050ccc --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/RRSIG.py @@ -0,0 +1,124 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import base64 +import calendar +import struct +import time + +import dns.dnssec +import dns.immutable +import dns.exception +import dns.rdata +import dns.rdatatype + + +class BadSigTime(dns.exception.DNSException): + + """Time in DNS SIG or RRSIG resource record cannot be parsed.""" + + +def sigtime_to_posixtime(what): + if len(what) <= 10 and what.isdigit(): + return int(what) + if len(what) != 14: + raise BadSigTime + year = int(what[0:4]) + month = int(what[4:6]) + day = int(what[6:8]) + hour = int(what[8:10]) + minute = int(what[10:12]) + second = int(what[12:14]) + return calendar.timegm((year, month, day, hour, minute, second, + 0, 0, 0)) + + +def posixtime_to_sigtime(what): + return time.strftime('%Y%m%d%H%M%S', time.gmtime(what)) + + +@dns.immutable.immutable +class RRSIG(dns.rdata.Rdata): + + """RRSIG record""" + + __slots__ = ['type_covered', 'algorithm', 'labels', 'original_ttl', + 'expiration', 'inception', 'key_tag', 'signer', + 'signature'] + + def __init__(self, rdclass, rdtype, type_covered, algorithm, labels, + original_ttl, expiration, inception, key_tag, signer, + signature): + super().__init__(rdclass, rdtype) + self.type_covered = self._as_rdatatype(type_covered) + self.algorithm = dns.dnssec.Algorithm.make(algorithm) + self.labels = self._as_uint8(labels) + self.original_ttl = self._as_ttl(original_ttl) + self.expiration = self._as_uint32(expiration) + self.inception = self._as_uint32(inception) + self.key_tag = self._as_uint16(key_tag) + self.signer = self._as_name(signer) + self.signature = self._as_bytes(signature) + + def covers(self): + return self.type_covered + + def to_text(self, origin=None, relativize=True, **kw): + return '%s %d %d %d %s %s %d %s %s' % ( + dns.rdatatype.to_text(self.type_covered), + self.algorithm, + self.labels, + self.original_ttl, + posixtime_to_sigtime(self.expiration), + posixtime_to_sigtime(self.inception), + self.key_tag, + self.signer.choose_relativity(origin, relativize), + dns.rdata._base64ify(self.signature, **kw) + ) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + type_covered = dns.rdatatype.from_text(tok.get_string()) + algorithm = dns.dnssec.algorithm_from_text(tok.get_string()) + labels = tok.get_int() + original_ttl = tok.get_ttl() + expiration = sigtime_to_posixtime(tok.get_string()) + inception = sigtime_to_posixtime(tok.get_string()) + key_tag = tok.get_int() + signer = tok.get_name(origin, relativize, relativize_to) + b64 = tok.concatenate_remaining_identifiers().encode() + signature = base64.b64decode(b64) + return cls(rdclass, rdtype, type_covered, algorithm, labels, + original_ttl, expiration, inception, key_tag, signer, + signature) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + header = struct.pack('!HBBIIIH', self.type_covered, + self.algorithm, self.labels, + self.original_ttl, self.expiration, + self.inception, self.key_tag) + file.write(header) + self.signer.to_wire(file, None, origin, canonicalize) + file.write(self.signature) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + header = parser.get_struct('!HBBIIIH') + signer = parser.get_name(origin) + signature = parser.get_remaining() + return cls(rdclass, rdtype, *header, signer, signature) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/RT.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/RT.py new file mode 100644 index 0000000..8d9c6bd --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/RT.py @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.mxbase +import dns.immutable + + +@dns.immutable.immutable +class RT(dns.rdtypes.mxbase.UncompressedDowncasingMX): + + """RT record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/SMIMEA.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/SMIMEA.py new file mode 100644 index 0000000..55d87bf --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/SMIMEA.py @@ -0,0 +1,9 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import dns.immutable +import dns.rdtypes.tlsabase + + +@dns.immutable.immutable +class SMIMEA(dns.rdtypes.tlsabase.TLSABase): + """SMIMEA record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/SOA.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/SOA.py new file mode 100644 index 0000000..7ce8865 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/SOA.py @@ -0,0 +1,78 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.name + + +@dns.immutable.immutable +class SOA(dns.rdata.Rdata): + + """SOA record""" + + # see: RFC 1035 + + __slots__ = ['mname', 'rname', 'serial', 'refresh', 'retry', 'expire', + 'minimum'] + + def __init__(self, rdclass, rdtype, mname, rname, serial, refresh, retry, + expire, minimum): + super().__init__(rdclass, rdtype) + self.mname = self._as_name(mname) + self.rname = self._as_name(rname) + self.serial = self._as_uint32(serial) + self.refresh = self._as_ttl(refresh) + self.retry = self._as_ttl(retry) + self.expire = self._as_ttl(expire) + self.minimum = self._as_ttl(minimum) + + def to_text(self, origin=None, relativize=True, **kw): + mname = self.mname.choose_relativity(origin, relativize) + rname = self.rname.choose_relativity(origin, relativize) + return '%s %s %d %d %d %d %d' % ( + mname, rname, self.serial, self.refresh, self.retry, + self.expire, self.minimum) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + mname = tok.get_name(origin, relativize, relativize_to) + rname = tok.get_name(origin, relativize, relativize_to) + serial = tok.get_uint32() + refresh = tok.get_ttl() + retry = tok.get_ttl() + expire = tok.get_ttl() + minimum = tok.get_ttl() + return cls(rdclass, rdtype, mname, rname, serial, refresh, retry, + expire, minimum) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.mname.to_wire(file, compress, origin, canonicalize) + self.rname.to_wire(file, compress, origin, canonicalize) + five_ints = struct.pack('!IIIII', self.serial, self.refresh, + self.retry, self.expire, self.minimum) + file.write(five_ints) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + mname = parser.get_name(origin) + rname = parser.get_name(origin) + return cls(rdclass, rdtype, mname, rname, *parser.get_struct('!IIIII')) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/SPF.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/SPF.py new file mode 100644 index 0000000..1190e0d --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/SPF.py @@ -0,0 +1,27 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.txtbase +import dns.immutable + + +@dns.immutable.immutable +class SPF(dns.rdtypes.txtbase.TXTBase): + + """SPF record""" + + # see: RFC 4408 diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/SSHFP.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/SSHFP.py new file mode 100644 index 0000000..cc03519 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/SSHFP.py @@ -0,0 +1,69 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2005-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct +import binascii + +import dns.rdata +import dns.immutable +import dns.rdatatype + + +@dns.immutable.immutable +class SSHFP(dns.rdata.Rdata): + + """SSHFP record""" + + # See RFC 4255 + + __slots__ = ['algorithm', 'fp_type', 'fingerprint'] + + def __init__(self, rdclass, rdtype, algorithm, fp_type, + fingerprint): + super().__init__(rdclass, rdtype) + self.algorithm = self._as_uint8(algorithm) + self.fp_type = self._as_uint8(fp_type) + self.fingerprint = self._as_bytes(fingerprint, True) + + def to_text(self, origin=None, relativize=True, **kw): + kw = kw.copy() + chunksize = kw.pop('chunksize', 128) + return '%d %d %s' % (self.algorithm, + self.fp_type, + dns.rdata._hexify(self.fingerprint, + chunksize=chunksize, + **kw)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + algorithm = tok.get_uint8() + fp_type = tok.get_uint8() + fingerprint = tok.concatenate_remaining_identifiers().encode() + fingerprint = binascii.unhexlify(fingerprint) + return cls(rdclass, rdtype, algorithm, fp_type, fingerprint) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + header = struct.pack("!BB", self.algorithm, self.fp_type) + file.write(header) + file.write(self.fingerprint) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + header = parser.get_struct("BB") + fingerprint = parser.get_remaining() + return cls(rdclass, rdtype, header[0], header[1], fingerprint) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/TKEY.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/TKEY.py new file mode 100644 index 0000000..f8c4737 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/TKEY.py @@ -0,0 +1,118 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import base64 +import struct + +import dns.dnssec +import dns.immutable +import dns.exception +import dns.rdata + + +@dns.immutable.immutable +class TKEY(dns.rdata.Rdata): + + """TKEY Record""" + + __slots__ = ['algorithm', 'inception', 'expiration', 'mode', 'error', + 'key', 'other'] + + def __init__(self, rdclass, rdtype, algorithm, inception, expiration, + mode, error, key, other=b''): + super().__init__(rdclass, rdtype) + self.algorithm = self._as_name(algorithm) + self.inception = self._as_uint32(inception) + self.expiration = self._as_uint32(expiration) + self.mode = self._as_uint16(mode) + self.error = self._as_uint16(error) + self.key = self._as_bytes(key) + self.other = self._as_bytes(other) + + def to_text(self, origin=None, relativize=True, **kw): + _algorithm = self.algorithm.choose_relativity(origin, relativize) + text = '%s %u %u %u %u %s' % (str(_algorithm), self.inception, + self.expiration, self.mode, self.error, + dns.rdata._base64ify(self.key, 0)) + if len(self.other) > 0: + text += ' %s' % (dns.rdata._base64ify(self.other, 0)) + + return text + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + algorithm = tok.get_name(relativize=False) + inception = tok.get_uint32() + expiration = tok.get_uint32() + mode = tok.get_uint16() + error = tok.get_uint16() + key_b64 = tok.get_string().encode() + key = base64.b64decode(key_b64) + other_b64 = tok.concatenate_remaining_identifiers().encode() + other = base64.b64decode(other_b64) + + return cls(rdclass, rdtype, algorithm, inception, expiration, mode, + error, key, other) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.algorithm.to_wire(file, compress, origin) + file.write(struct.pack("!IIHH", self.inception, self.expiration, + self.mode, self.error)) + file.write(struct.pack("!H", len(self.key))) + file.write(self.key) + file.write(struct.pack("!H", len(self.other))) + if len(self.other) > 0: + file.write(self.other) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + algorithm = parser.get_name(origin) + inception, expiration, mode, error = parser.get_struct("!IIHH") + key = parser.get_counted_bytes(2) + other = parser.get_counted_bytes(2) + + return cls(rdclass, rdtype, algorithm, inception, expiration, mode, + error, key, other) + + # Constants for the mode field - from RFC 2930: + # 2.5 The Mode Field + # + # The mode field specifies the general scheme for key agreement or + # the purpose of the TKEY DNS message. Servers and resolvers + # supporting this specification MUST implement the Diffie-Hellman key + # agreement mode and the key deletion mode for queries. All other + # modes are OPTIONAL. A server supporting TKEY that receives a TKEY + # request with a mode it does not support returns the BADMODE error. + # The following values of the Mode octet are defined, available, or + # reserved: + # + # Value Description + # ----- ----------- + # 0 - reserved, see section 7 + # 1 server assignment + # 2 Diffie-Hellman exchange + # 3 GSS-API negotiation + # 4 resolver assignment + # 5 key deletion + # 6-65534 - available, see section 7 + # 65535 - reserved, see section 7 + SERVER_ASSIGNMENT = 1 + DIFFIE_HELLMAN_EXCHANGE = 2 + GSSAPI_NEGOTIATION = 3 + RESOLVER_ASSIGNMENT = 4 + KEY_DELETION = 5 diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/TLSA.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/TLSA.py new file mode 100644 index 0000000..c9ba199 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/TLSA.py @@ -0,0 +1,10 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import dns.immutable +import dns.rdtypes.tlsabase + + +@dns.immutable.immutable +class TLSA(dns.rdtypes.tlsabase.TLSABase): + + """TLSA record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/TSIG.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/TSIG.py new file mode 100644 index 0000000..b43a78f --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/TSIG.py @@ -0,0 +1,120 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import base64 +import struct + +import dns.exception +import dns.immutable +import dns.rcode +import dns.rdata + + +@dns.immutable.immutable +class TSIG(dns.rdata.Rdata): + + """TSIG record""" + + __slots__ = ['algorithm', 'time_signed', 'fudge', 'mac', + 'original_id', 'error', 'other'] + + def __init__(self, rdclass, rdtype, algorithm, time_signed, fudge, mac, + original_id, error, other): + """Initialize a TSIG rdata. + + *rdclass*, an ``int`` is the rdataclass of the Rdata. + + *rdtype*, an ``int`` is the rdatatype of the Rdata. + + *algorithm*, a ``dns.name.Name``. + + *time_signed*, an ``int``. + + *fudge*, an ``int`. + + *mac*, a ``bytes`` + + *original_id*, an ``int`` + + *error*, an ``int`` + + *other*, a ``bytes`` + """ + + super().__init__(rdclass, rdtype) + self.algorithm = self._as_name(algorithm) + self.time_signed = self._as_uint48(time_signed) + self.fudge = self._as_uint16(fudge) + self.mac = self._as_bytes(mac) + self.original_id = self._as_uint16(original_id) + self.error = dns.rcode.Rcode.make(error) + self.other = self._as_bytes(other) + + def to_text(self, origin=None, relativize=True, **kw): + algorithm = self.algorithm.choose_relativity(origin, relativize) + error = dns.rcode.to_text(self.error, True) + text = f"{algorithm} {self.time_signed} {self.fudge} " + \ + f"{len(self.mac)} {dns.rdata._base64ify(self.mac, 0)} " + \ + f"{self.original_id} {error} {len(self.other)}" + if self.other: + text += f" {dns.rdata._base64ify(self.other, 0)}" + return text + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + algorithm = tok.get_name(relativize=False) + time_signed = tok.get_uint48() + fudge = tok.get_uint16() + mac_len = tok.get_uint16() + mac = base64.b64decode(tok.get_string()) + if len(mac) != mac_len: + raise SyntaxError('invalid MAC') + original_id = tok.get_uint16() + error = dns.rcode.from_text(tok.get_string()) + other_len = tok.get_uint16() + if other_len > 0: + other = base64.b64decode(tok.get_string()) + if len(other) != other_len: + raise SyntaxError('invalid other data') + else: + other = b'' + return cls(rdclass, rdtype, algorithm, time_signed, fudge, mac, + original_id, error, other) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.algorithm.to_wire(file, None, origin, False) + file.write(struct.pack('!HIHH', + (self.time_signed >> 32) & 0xffff, + self.time_signed & 0xffffffff, + self.fudge, + len(self.mac))) + file.write(self.mac) + file.write(struct.pack('!HHH', self.original_id, self.error, + len(self.other))) + file.write(self.other) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + algorithm = parser.get_name() + time_signed = parser.get_uint48() + fudge = parser.get_uint16() + mac = parser.get_counted_bytes(2) + (original_id, error) = parser.get_struct('!HH') + other = parser.get_counted_bytes(2) + return cls(rdclass, rdtype, algorithm, time_signed, fudge, mac, + original_id, error, other) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/TXT.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/TXT.py new file mode 100644 index 0000000..cc4b661 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/TXT.py @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.txtbase +import dns.immutable + + +@dns.immutable.immutable +class TXT(dns.rdtypes.txtbase.TXTBase): + + """TXT record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/URI.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/URI.py new file mode 100644 index 0000000..ccbd2ce --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/URI.py @@ -0,0 +1,79 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# Copyright (C) 2015 Red Hat, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.name + + +@dns.immutable.immutable +class URI(dns.rdata.Rdata): + + """URI record""" + + # see RFC 7553 + + __slots__ = ['priority', 'weight', 'target'] + + def __init__(self, rdclass, rdtype, priority, weight, target): + super().__init__(rdclass, rdtype) + self.priority = self._as_uint16(priority) + self.weight = self._as_uint16(weight) + self.target = self._as_bytes(target, True) + if len(self.target) == 0: + raise dns.exception.SyntaxError("URI target cannot be empty") + + def to_text(self, origin=None, relativize=True, **kw): + return '%d %d "%s"' % (self.priority, self.weight, + self.target.decode()) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + priority = tok.get_uint16() + weight = tok.get_uint16() + target = tok.get().unescape() + if not (target.is_quoted_string() or target.is_identifier()): + raise dns.exception.SyntaxError("URI target must be a string") + return cls(rdclass, rdtype, priority, weight, target.value) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + two_ints = struct.pack("!HH", self.priority, self.weight) + file.write(two_ints) + file.write(self.target) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + (priority, weight) = parser.get_struct('!HH') + target = parser.get_remaining() + if len(target) == 0: + raise dns.exception.FormError('URI target may not be empty') + return cls(rdclass, rdtype, priority, weight, target) + + def _processing_priority(self): + return self.priority + + def _processing_weight(self): + return self.weight + + @classmethod + def _processing_order(cls, iterable): + return dns.rdtypes.util.weighted_processing_order(iterable) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/X25.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/X25.py new file mode 100644 index 0000000..4f7230c --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/X25.py @@ -0,0 +1,57 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.tokenizer + + +@dns.immutable.immutable +class X25(dns.rdata.Rdata): + + """X25 record""" + + # see RFC 1183 + + __slots__ = ['address'] + + def __init__(self, rdclass, rdtype, address): + super().__init__(rdclass, rdtype) + self.address = self._as_bytes(address, True, 255) + + def to_text(self, origin=None, relativize=True, **kw): + return '"%s"' % dns.rdata._escapify(self.address) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + address = tok.get_string() + return cls(rdclass, rdtype, address) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + l = len(self.address) + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(self.address) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + address = parser.get_counted_bytes() + return cls(rdclass, rdtype, address) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/__init__.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/__init__.py new file mode 100644 index 0000000..b0ea707 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/ANY/__init__.py @@ -0,0 +1,61 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Class ANY (generic) rdata type classes.""" + +__all__ = [ + 'AFSDB', + 'AVC', + 'CAA', + 'CDNSKEY', + 'CDS', + 'CERT', + 'CNAME', + 'CSYNC', + 'DLV', + 'DNAME', + 'DNSKEY', + 'DS', + 'EUI48', + 'EUI64', + 'GPOS', + 'HINFO', + 'HIP', + 'ISDN', + 'LOC', + 'MX', + 'NS', + 'NSEC', + 'NSEC3', + 'NSEC3PARAM', + 'OPENPGPKEY', + 'OPT', + 'PTR', + 'RP', + 'RRSIG', + 'RT', + 'SMIMEA', + 'SOA', + 'SPF', + 'SSHFP', + 'TKEY', + 'TLSA', + 'TSIG', + 'TXT', + 'URI', + 'X25', +] diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/CH/A.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/CH/A.py new file mode 100644 index 0000000..828701b --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/CH/A.py @@ -0,0 +1,58 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.rdtypes.mxbase +import dns.immutable + +@dns.immutable.immutable +class A(dns.rdata.Rdata): + + """A record for Chaosnet""" + + # domain: the domain of the address + # address: the 16-bit address + + __slots__ = ['domain', 'address'] + + def __init__(self, rdclass, rdtype, domain, address): + super().__init__(rdclass, rdtype) + self.domain = self._as_name(domain) + self.address = self._as_uint16(address) + + def to_text(self, origin=None, relativize=True, **kw): + domain = self.domain.choose_relativity(origin, relativize) + return '%s %o' % (domain, self.address) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + domain = tok.get_name(origin, relativize, relativize_to) + address = tok.get_uint16(base=8) + return cls(rdclass, rdtype, domain, address) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.domain.to_wire(file, compress, origin, canonicalize) + pref = struct.pack("!H", self.address) + file.write(pref) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + domain = parser.get_name(origin) + address = parser.get_uint16() + return cls(rdclass, rdtype, domain, address) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/CH/__init__.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/CH/__init__.py new file mode 100644 index 0000000..7184a73 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/CH/__init__.py @@ -0,0 +1,22 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Class CH rdata type classes.""" + +__all__ = [ + 'A', +] diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/A.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/A.py new file mode 100644 index 0000000..74b591e --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/A.py @@ -0,0 +1,51 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.exception +import dns.immutable +import dns.ipv4 +import dns.rdata +import dns.tokenizer + + +@dns.immutable.immutable +class A(dns.rdata.Rdata): + + """A record.""" + + __slots__ = ['address'] + + def __init__(self, rdclass, rdtype, address): + super().__init__(rdclass, rdtype) + self.address = self._as_ipv4_address(address) + + def to_text(self, origin=None, relativize=True, **kw): + return self.address + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + address = tok.get_identifier() + return cls(rdclass, rdtype, address) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(dns.ipv4.inet_aton(self.address)) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + address = parser.get_remaining() + return cls(rdclass, rdtype, address) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/AAAA.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/AAAA.py new file mode 100644 index 0000000..2d3ec90 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/AAAA.py @@ -0,0 +1,51 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.exception +import dns.immutable +import dns.ipv6 +import dns.rdata +import dns.tokenizer + + +@dns.immutable.immutable +class AAAA(dns.rdata.Rdata): + + """AAAA record.""" + + __slots__ = ['address'] + + def __init__(self, rdclass, rdtype, address): + super().__init__(rdclass, rdtype) + self.address = self._as_ipv6_address(address) + + def to_text(self, origin=None, relativize=True, **kw): + return self.address + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + address = tok.get_identifier() + return cls(rdclass, rdtype, address) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(dns.ipv6.inet_aton(self.address)) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + address = parser.get_remaining() + return cls(rdclass, rdtype, address) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/APL.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/APL.py new file mode 100644 index 0000000..5cfdc34 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/APL.py @@ -0,0 +1,151 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import binascii +import codecs +import struct + +import dns.exception +import dns.immutable +import dns.ipv4 +import dns.ipv6 +import dns.rdata +import dns.tokenizer + +@dns.immutable.immutable +class APLItem: + + """An APL list item.""" + + __slots__ = ['family', 'negation', 'address', 'prefix'] + + def __init__(self, family, negation, address, prefix): + self.family = dns.rdata.Rdata._as_uint16(family) + self.negation = dns.rdata.Rdata._as_bool(negation) + if self.family == 1: + self.address = dns.rdata.Rdata._as_ipv4_address(address) + self.prefix = dns.rdata.Rdata._as_int(prefix, 0, 32) + elif self.family == 2: + self.address = dns.rdata.Rdata._as_ipv6_address(address) + self.prefix = dns.rdata.Rdata._as_int(prefix, 0, 128) + else: + self.address = dns.rdata.Rdata._as_bytes(address) + self.prefix = dns.rdata.Rdata._as_uint8(prefix) + + def __str__(self): + if self.negation: + return "!%d:%s/%s" % (self.family, self.address, self.prefix) + else: + return "%d:%s/%s" % (self.family, self.address, self.prefix) + + def to_wire(self, file): + if self.family == 1: + address = dns.ipv4.inet_aton(self.address) + elif self.family == 2: + address = dns.ipv6.inet_aton(self.address) + else: + address = binascii.unhexlify(self.address) + # + # Truncate least significant zero bytes. + # + last = 0 + for i in range(len(address) - 1, -1, -1): + if address[i] != 0: + last = i + 1 + break + address = address[0: last] + l = len(address) + assert l < 128 + if self.negation: + l |= 0x80 + header = struct.pack('!HBB', self.family, self.prefix, l) + file.write(header) + file.write(address) + + +@dns.immutable.immutable +class APL(dns.rdata.Rdata): + + """APL record.""" + + # see: RFC 3123 + + __slots__ = ['items'] + + def __init__(self, rdclass, rdtype, items): + super().__init__(rdclass, rdtype) + for item in items: + if not isinstance(item, APLItem): + raise ValueError('item not an APLItem') + self.items = tuple(items) + + def to_text(self, origin=None, relativize=True, **kw): + return ' '.join(map(str, self.items)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + items = [] + for token in tok.get_remaining(): + item = token.unescape().value + if item[0] == '!': + negation = True + item = item[1:] + else: + negation = False + (family, rest) = item.split(':', 1) + family = int(family) + (address, prefix) = rest.split('/', 1) + prefix = int(prefix) + item = APLItem(family, negation, address, prefix) + items.append(item) + + return cls(rdclass, rdtype, items) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + for item in self.items: + item.to_wire(file) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + + items = [] + while parser.remaining() > 0: + header = parser.get_struct('!HBB') + afdlen = header[2] + if afdlen > 127: + negation = True + afdlen -= 128 + else: + negation = False + address = parser.get_bytes(afdlen) + l = len(address) + if header[0] == 1: + if l < 4: + address += b'\x00' * (4 - l) + elif header[0] == 2: + if l < 16: + address += b'\x00' * (16 - l) + else: + # + # This isn't really right according to the RFC, but it + # seems better than throwing an exception + # + address = codecs.encode(address, 'hex_codec') + item = APLItem(header[0], negation, address, header[1]) + items.append(item) + return cls(rdclass, rdtype, items) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/DHCID.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/DHCID.py new file mode 100644 index 0000000..a918598 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/DHCID.py @@ -0,0 +1,53 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import base64 + +import dns.exception +import dns.immutable + + +@dns.immutable.immutable +class DHCID(dns.rdata.Rdata): + + """DHCID record""" + + # see: RFC 4701 + + __slots__ = ['data'] + + def __init__(self, rdclass, rdtype, data): + super().__init__(rdclass, rdtype) + self.data = self._as_bytes(data) + + def to_text(self, origin=None, relativize=True, **kw): + return dns.rdata._base64ify(self.data, **kw) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + b64 = tok.concatenate_remaining_identifiers().encode() + data = base64.b64decode(b64) + return cls(rdclass, rdtype, data) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(self.data) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + data = parser.get_remaining() + return cls(rdclass, rdtype, data) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/HTTPS.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/HTTPS.py new file mode 100644 index 0000000..6a67e8e --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/HTTPS.py @@ -0,0 +1,8 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import dns.rdtypes.svcbbase +import dns.immutable + +@dns.immutable.immutable +class HTTPS(dns.rdtypes.svcbbase.SVCBBase): + """HTTPS record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/IPSECKEY.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/IPSECKEY.py new file mode 100644 index 0000000..d1d3943 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/IPSECKEY.py @@ -0,0 +1,83 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct +import base64 + +import dns.exception +import dns.immutable +import dns.rdtypes.util + + +class Gateway(dns.rdtypes.util.Gateway): + name = 'IPSECKEY gateway' + +@dns.immutable.immutable +class IPSECKEY(dns.rdata.Rdata): + + """IPSECKEY record""" + + # see: RFC 4025 + + __slots__ = ['precedence', 'gateway_type', 'algorithm', 'gateway', 'key'] + + def __init__(self, rdclass, rdtype, precedence, gateway_type, algorithm, + gateway, key): + super().__init__(rdclass, rdtype) + gateway = Gateway(gateway_type, gateway) + self.precedence = self._as_uint8(precedence) + self.gateway_type = gateway.type + self.algorithm = self._as_uint8(algorithm) + self.gateway = gateway.gateway + self.key = self._as_bytes(key) + + def to_text(self, origin=None, relativize=True, **kw): + gateway = Gateway(self.gateway_type, self.gateway).to_text(origin, + relativize) + return '%d %d %d %s %s' % (self.precedence, self.gateway_type, + self.algorithm, gateway, + dns.rdata._base64ify(self.key, **kw)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + precedence = tok.get_uint8() + gateway_type = tok.get_uint8() + algorithm = tok.get_uint8() + gateway = Gateway.from_text(gateway_type, tok, origin, relativize, + relativize_to) + b64 = tok.concatenate_remaining_identifiers().encode() + key = base64.b64decode(b64) + return cls(rdclass, rdtype, precedence, gateway_type, algorithm, + gateway.gateway, key) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + header = struct.pack("!BBB", self.precedence, self.gateway_type, + self.algorithm) + file.write(header) + Gateway(self.gateway_type, self.gateway).to_wire(file, compress, + origin, canonicalize) + file.write(self.key) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + header = parser.get_struct('!BBB') + gateway_type = header[1] + gateway = Gateway.from_wire_parser(gateway_type, parser, origin) + key = parser.get_remaining() + return cls(rdclass, rdtype, header[0], gateway_type, header[2], + gateway.gateway, key) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/KX.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/KX.py new file mode 100644 index 0000000..c27e921 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/KX.py @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.mxbase +import dns.immutable + + +@dns.immutable.immutable +class KX(dns.rdtypes.mxbase.UncompressedDowncasingMX): + + """KX record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/NAPTR.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/NAPTR.py new file mode 100644 index 0000000..1f072f8 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/NAPTR.py @@ -0,0 +1,98 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.name +import dns.rdata + + +def _write_string(file, s): + l = len(s) + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(s) + + +@dns.immutable.immutable +class NAPTR(dns.rdata.Rdata): + + """NAPTR record""" + + # see: RFC 3403 + + __slots__ = ['order', 'preference', 'flags', 'service', 'regexp', + 'replacement'] + + def __init__(self, rdclass, rdtype, order, preference, flags, service, + regexp, replacement): + super().__init__(rdclass, rdtype) + self.flags = self._as_bytes(flags, True, 255) + self.service = self._as_bytes(service, True, 255) + self.regexp = self._as_bytes(regexp, True, 255) + self.order = self._as_uint16(order) + self.preference = self._as_uint16(preference) + self.replacement = self._as_name(replacement) + + def to_text(self, origin=None, relativize=True, **kw): + replacement = self.replacement.choose_relativity(origin, relativize) + return '%d %d "%s" "%s" "%s" %s' % \ + (self.order, self.preference, + dns.rdata._escapify(self.flags), + dns.rdata._escapify(self.service), + dns.rdata._escapify(self.regexp), + replacement) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + order = tok.get_uint16() + preference = tok.get_uint16() + flags = tok.get_string() + service = tok.get_string() + regexp = tok.get_string() + replacement = tok.get_name(origin, relativize, relativize_to) + return cls(rdclass, rdtype, order, preference, flags, service, + regexp, replacement) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + two_ints = struct.pack("!HH", self.order, self.preference) + file.write(two_ints) + _write_string(file, self.flags) + _write_string(file, self.service) + _write_string(file, self.regexp) + self.replacement.to_wire(file, compress, origin, canonicalize) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + (order, preference) = parser.get_struct('!HH') + strings = [] + for _ in range(3): + s = parser.get_counted_bytes() + strings.append(s) + replacement = parser.get_name(origin) + return cls(rdclass, rdtype, order, preference, strings[0], strings[1], + strings[2], replacement) + + def _processing_priority(self): + return (self.order, self.preference) + + @classmethod + def _processing_order(cls, iterable): + return dns.rdtypes.util.priority_processing_order(iterable) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/NSAP.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/NSAP.py new file mode 100644 index 0000000..23ae9b1 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/NSAP.py @@ -0,0 +1,60 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import binascii + +import dns.exception +import dns.immutable +import dns.rdata +import dns.tokenizer + + +@dns.immutable.immutable +class NSAP(dns.rdata.Rdata): + + """NSAP record.""" + + # see: RFC 1706 + + __slots__ = ['address'] + + def __init__(self, rdclass, rdtype, address): + super().__init__(rdclass, rdtype) + self.address = self._as_bytes(address) + + def to_text(self, origin=None, relativize=True, **kw): + return "0x%s" % binascii.hexlify(self.address).decode() + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + address = tok.get_string() + if address[0:2] != '0x': + raise dns.exception.SyntaxError('string does not start with 0x') + address = address[2:].replace('.', '') + if len(address) % 2 != 0: + raise dns.exception.SyntaxError('hexstring has odd length') + address = binascii.unhexlify(address.encode()) + return cls(rdclass, rdtype, address) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(self.address) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + address = parser.get_remaining() + return cls(rdclass, rdtype, address) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/NSAP_PTR.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/NSAP_PTR.py new file mode 100644 index 0000000..57dadd4 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/NSAP_PTR.py @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.nsbase +import dns.immutable + + +@dns.immutable.immutable +class NSAP_PTR(dns.rdtypes.nsbase.UncompressedNS): + + """NSAP-PTR record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/PX.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/PX.py new file mode 100644 index 0000000..8abfb29 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/PX.py @@ -0,0 +1,72 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.name + + +@dns.immutable.immutable +class PX(dns.rdata.Rdata): + + """PX record.""" + + # see: RFC 2163 + + __slots__ = ['preference', 'map822', 'mapx400'] + + def __init__(self, rdclass, rdtype, preference, map822, mapx400): + super().__init__(rdclass, rdtype) + self.preference = self._as_uint16(preference) + self.map822 = self._as_name(map822) + self.mapx400 = self._as_name(mapx400) + + def to_text(self, origin=None, relativize=True, **kw): + map822 = self.map822.choose_relativity(origin, relativize) + mapx400 = self.mapx400.choose_relativity(origin, relativize) + return '%d %s %s' % (self.preference, map822, mapx400) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + preference = tok.get_uint16() + map822 = tok.get_name(origin, relativize, relativize_to) + mapx400 = tok.get_name(origin, relativize, relativize_to) + return cls(rdclass, rdtype, preference, map822, mapx400) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + pref = struct.pack("!H", self.preference) + file.write(pref) + self.map822.to_wire(file, None, origin, canonicalize) + self.mapx400.to_wire(file, None, origin, canonicalize) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + preference = parser.get_uint16() + map822 = parser.get_name(origin) + mapx400 = parser.get_name(origin) + return cls(rdclass, rdtype, preference, map822, mapx400) + + def _processing_priority(self): + return self.preference + + @classmethod + def _processing_order(cls, iterable): + return dns.rdtypes.util.priority_processing_order(iterable) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/SRV.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/SRV.py new file mode 100644 index 0000000..6d9b683 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/SRV.py @@ -0,0 +1,75 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.name + + +@dns.immutable.immutable +class SRV(dns.rdata.Rdata): + + """SRV record""" + + # see: RFC 2782 + + __slots__ = ['priority', 'weight', 'port', 'target'] + + def __init__(self, rdclass, rdtype, priority, weight, port, target): + super().__init__(rdclass, rdtype) + self.priority = self._as_uint16(priority) + self.weight = self._as_uint16(weight) + self.port = self._as_uint16(port) + self.target = self._as_name(target) + + def to_text(self, origin=None, relativize=True, **kw): + target = self.target.choose_relativity(origin, relativize) + return '%d %d %d %s' % (self.priority, self.weight, self.port, + target) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + priority = tok.get_uint16() + weight = tok.get_uint16() + port = tok.get_uint16() + target = tok.get_name(origin, relativize, relativize_to) + return cls(rdclass, rdtype, priority, weight, port, target) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + three_ints = struct.pack("!HHH", self.priority, self.weight, self.port) + file.write(three_ints) + self.target.to_wire(file, compress, origin, canonicalize) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + (priority, weight, port) = parser.get_struct('!HHH') + target = parser.get_name(origin) + return cls(rdclass, rdtype, priority, weight, port, target) + + def _processing_priority(self): + return self.priority + + def _processing_weight(self): + return self.weight + + @classmethod + def _processing_order(cls, iterable): + return dns.rdtypes.util.weighted_processing_order(iterable) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/SVCB.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/SVCB.py new file mode 100644 index 0000000..14838e1 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/SVCB.py @@ -0,0 +1,8 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import dns.rdtypes.svcbbase +import dns.immutable + +@dns.immutable.immutable +class SVCB(dns.rdtypes.svcbbase.SVCBBase): + """SVCB record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/WKS.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/WKS.py new file mode 100644 index 0000000..0d36281 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/WKS.py @@ -0,0 +1,96 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import socket +import struct + +import dns.ipv4 +import dns.immutable +import dns.rdata + +_proto_tcp = socket.getprotobyname('tcp') +_proto_udp = socket.getprotobyname('udp') + + +@dns.immutable.immutable +class WKS(dns.rdata.Rdata): + + """WKS record""" + + # see: RFC 1035 + + __slots__ = ['address', 'protocol', 'bitmap'] + + def __init__(self, rdclass, rdtype, address, protocol, bitmap): + super().__init__(rdclass, rdtype) + self.address = self._as_ipv4_address(address) + self.protocol = self._as_uint8(protocol) + self.bitmap = self._as_bytes(bitmap) + + def to_text(self, origin=None, relativize=True, **kw): + bits = [] + for i in range(0, len(self.bitmap)): + byte = self.bitmap[i] + for j in range(0, 8): + if byte & (0x80 >> j): + bits.append(str(i * 8 + j)) + text = ' '.join(bits) + return '%s %d %s' % (self.address, self.protocol, text) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + address = tok.get_string() + protocol = tok.get_string() + if protocol.isdigit(): + protocol = int(protocol) + else: + protocol = socket.getprotobyname(protocol) + bitmap = bytearray() + for token in tok.get_remaining(): + value = token.unescape().value + if value.isdigit(): + serv = int(value) + else: + if protocol != _proto_udp and protocol != _proto_tcp: + raise NotImplementedError("protocol must be TCP or UDP") + if protocol == _proto_udp: + protocol_text = "udp" + else: + protocol_text = "tcp" + serv = socket.getservbyname(value, protocol_text) + i = serv // 8 + l = len(bitmap) + if l < i + 1: + for _ in range(l, i + 1): + bitmap.append(0) + bitmap[i] = bitmap[i] | (0x80 >> (serv % 8)) + bitmap = dns.rdata._truncate_bitmap(bitmap) + return cls(rdclass, rdtype, address, protocol, bitmap) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(dns.ipv4.inet_aton(self.address)) + protocol = struct.pack('!B', self.protocol) + file.write(protocol) + file.write(self.bitmap) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + address = parser.get_bytes(4) + protocol = parser.get_uint8() + bitmap = parser.get_remaining() + return cls(rdclass, rdtype, address, protocol, bitmap) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/__init__.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/__init__.py new file mode 100644 index 0000000..d7e69c9 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/IN/__init__.py @@ -0,0 +1,33 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Class IN rdata type classes.""" + +__all__ = [ + 'A', + 'AAAA', + 'APL', + 'DHCID', + 'IPSECKEY', + 'KX', + 'NAPTR', + 'NSAP', + 'NSAP_PTR', + 'PX', + 'SRV', + 'WKS', +] diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/__init__.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/__init__.py new file mode 100644 index 0000000..c3af264 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/__init__.py @@ -0,0 +1,33 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS rdata type classes""" + +__all__ = [ + 'ANY', + 'IN', + 'CH', + 'dnskeybase', + 'dsbase', + 'euibase', + 'mxbase', + 'nsbase', + 'svcbbase', + 'tlsabase', + 'txtbase', + 'util' +] diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/dnskeybase.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/dnskeybase.py new file mode 100644 index 0000000..788bb2b --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/dnskeybase.py @@ -0,0 +1,82 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import base64 +import enum +import struct + +import dns.exception +import dns.immutable +import dns.dnssec +import dns.rdata + +# wildcard import +__all__ = ["SEP", "REVOKE", "ZONE"] # noqa: F822 + +class Flag(enum.IntFlag): + SEP = 0x0001 + REVOKE = 0x0080 + ZONE = 0x0100 + + +@dns.immutable.immutable +class DNSKEYBase(dns.rdata.Rdata): + + """Base class for rdata that is like a DNSKEY record""" + + __slots__ = ['flags', 'protocol', 'algorithm', 'key'] + + def __init__(self, rdclass, rdtype, flags, protocol, algorithm, key): + super().__init__(rdclass, rdtype) + self.flags = self._as_uint16(flags) + self.protocol = self._as_uint8(protocol) + self.algorithm = dns.dnssec.Algorithm.make(algorithm) + self.key = self._as_bytes(key) + + def to_text(self, origin=None, relativize=True, **kw): + return '%d %d %d %s' % (self.flags, self.protocol, self.algorithm, + dns.rdata._base64ify(self.key, **kw)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + flags = tok.get_uint16() + protocol = tok.get_uint8() + algorithm = tok.get_string() + b64 = tok.concatenate_remaining_identifiers().encode() + key = base64.b64decode(b64) + return cls(rdclass, rdtype, flags, protocol, algorithm, key) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + header = struct.pack("!HBB", self.flags, self.protocol, self.algorithm) + file.write(header) + file.write(self.key) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + header = parser.get_struct('!HBB') + key = parser.get_remaining() + return cls(rdclass, rdtype, header[0], header[1], header[2], + key) + +### BEGIN generated Flag constants + +SEP = Flag.SEP +REVOKE = Flag.REVOKE +ZONE = Flag.ZONE + +### END generated Flag constants diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/dsbase.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/dsbase.py new file mode 100644 index 0000000..38c9548 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/dsbase.py @@ -0,0 +1,72 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2010, 2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct +import binascii + +import dns.dnssec +import dns.immutable +import dns.rdata +import dns.rdatatype + + +@dns.immutable.immutable +class DSBase(dns.rdata.Rdata): + + """Base class for rdata that is like a DS record""" + + __slots__ = ['key_tag', 'algorithm', 'digest_type', 'digest'] + + def __init__(self, rdclass, rdtype, key_tag, algorithm, digest_type, + digest): + super().__init__(rdclass, rdtype) + self.key_tag = self._as_uint16(key_tag) + self.algorithm = dns.dnssec.Algorithm.make(algorithm) + self.digest_type = self._as_uint8(digest_type) + self.digest = self._as_bytes(digest) + + def to_text(self, origin=None, relativize=True, **kw): + kw = kw.copy() + chunksize = kw.pop('chunksize', 128) + return '%d %d %d %s' % (self.key_tag, self.algorithm, + self.digest_type, + dns.rdata._hexify(self.digest, + chunksize=chunksize, + **kw)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + key_tag = tok.get_uint16() + algorithm = tok.get_string() + digest_type = tok.get_uint8() + digest = tok.concatenate_remaining_identifiers().encode() + digest = binascii.unhexlify(digest) + return cls(rdclass, rdtype, key_tag, algorithm, digest_type, + digest) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + header = struct.pack("!HBB", self.key_tag, self.algorithm, + self.digest_type) + file.write(header) + file.write(self.digest) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + header = parser.get_struct("!HBB") + digest = parser.get_remaining() + return cls(rdclass, rdtype, header[0], header[1], header[2], digest) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/euibase.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/euibase.py new file mode 100644 index 0000000..60ab56d --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/euibase.py @@ -0,0 +1,69 @@ +# Copyright (C) 2015 Red Hat, Inc. +# Author: Petr Spacek +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import binascii + +import dns.rdata +import dns.immutable + + +@dns.immutable.immutable +class EUIBase(dns.rdata.Rdata): + + """EUIxx record""" + + # see: rfc7043.txt + + __slots__ = ['eui'] + # define these in subclasses + # byte_len = 6 # 0123456789ab (in hex) + # text_len = byte_len * 3 - 1 # 01-23-45-67-89-ab + + def __init__(self, rdclass, rdtype, eui): + super().__init__(rdclass, rdtype) + self.eui = self._as_bytes(eui) + if len(self.eui) != self.byte_len: + raise dns.exception.FormError('EUI%s rdata has to have %s bytes' + % (self.byte_len * 8, self.byte_len)) + + def to_text(self, origin=None, relativize=True, **kw): + return dns.rdata._hexify(self.eui, chunksize=2, **kw).replace(' ', '-') + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + text = tok.get_string() + if len(text) != cls.text_len: + raise dns.exception.SyntaxError( + 'Input text must have %s characters' % cls.text_len) + for i in range(2, cls.byte_len * 3 - 1, 3): + if text[i] != '-': + raise dns.exception.SyntaxError('Dash expected at position %s' + % i) + text = text.replace('-', '') + try: + data = binascii.unhexlify(text.encode()) + except (ValueError, TypeError) as ex: + raise dns.exception.SyntaxError('Hex decoding error: %s' % str(ex)) + return cls(rdclass, rdtype, data) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(self.eui) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + eui = parser.get_bytes(cls.byte_len) + return cls(rdclass, rdtype, eui) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/mxbase.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/mxbase.py new file mode 100644 index 0000000..5641823 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/mxbase.py @@ -0,0 +1,89 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""MX-like base classes.""" + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.name +import dns.rdtypes.util + + +@dns.immutable.immutable +class MXBase(dns.rdata.Rdata): + + """Base class for rdata that is like an MX record.""" + + __slots__ = ['preference', 'exchange'] + + def __init__(self, rdclass, rdtype, preference, exchange): + super().__init__(rdclass, rdtype) + self.preference = self._as_uint16(preference) + self.exchange = self._as_name(exchange) + + def to_text(self, origin=None, relativize=True, **kw): + exchange = self.exchange.choose_relativity(origin, relativize) + return '%d %s' % (self.preference, exchange) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + preference = tok.get_uint16() + exchange = tok.get_name(origin, relativize, relativize_to) + return cls(rdclass, rdtype, preference, exchange) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + pref = struct.pack("!H", self.preference) + file.write(pref) + self.exchange.to_wire(file, compress, origin, canonicalize) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + preference = parser.get_uint16() + exchange = parser.get_name(origin) + return cls(rdclass, rdtype, preference, exchange) + + def _processing_priority(self): + return self.preference + + @classmethod + def _processing_order(cls, iterable): + return dns.rdtypes.util.priority_processing_order(iterable) + + +@dns.immutable.immutable +class UncompressedMX(MXBase): + + """Base class for rdata that is like an MX record, but whose name + is not compressed when converted to DNS wire format, and whose + digestable form is not downcased.""" + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + super()._to_wire(file, None, origin, False) + + +@dns.immutable.immutable +class UncompressedDowncasingMX(MXBase): + + """Base class for rdata that is like an MX record, but whose name + is not compressed when convert to DNS wire format.""" + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + super()._to_wire(file, None, origin, canonicalize) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/nsbase.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/nsbase.py new file mode 100644 index 0000000..b3e2550 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/nsbase.py @@ -0,0 +1,64 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""NS-like base classes.""" + +import dns.exception +import dns.immutable +import dns.rdata +import dns.name + + +@dns.immutable.immutable +class NSBase(dns.rdata.Rdata): + + """Base class for rdata that is like an NS record.""" + + __slots__ = ['target'] + + def __init__(self, rdclass, rdtype, target): + super().__init__(rdclass, rdtype) + self.target = self._as_name(target) + + def to_text(self, origin=None, relativize=True, **kw): + target = self.target.choose_relativity(origin, relativize) + return str(target) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + target = tok.get_name(origin, relativize, relativize_to) + return cls(rdclass, rdtype, target) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.target.to_wire(file, compress, origin, canonicalize) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + target = parser.get_name(origin) + return cls(rdclass, rdtype, target) + + +@dns.immutable.immutable +class UncompressedNS(NSBase): + + """Base class for rdata that is like an NS record, but whose name + is not compressed when convert to DNS wire format, and whose + digestable form is not downcased.""" + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.target.to_wire(file, None, origin, False) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/svcbbase.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/svcbbase.py new file mode 100644 index 0000000..f757f02 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/svcbbase.py @@ -0,0 +1,543 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import base64 +import enum +import io +import struct + +import dns.enum +import dns.exception +import dns.immutable +import dns.ipv4 +import dns.ipv6 +import dns.name +import dns.rdata +import dns.tokenizer +import dns.wire + +# Until there is an RFC, this module is experimental and may be changed in +# incompatible ways. + + +class UnknownParamKey(dns.exception.DNSException): + """Unknown SVCB ParamKey""" + + +class ParamKey(dns.enum.IntEnum): + """SVCB ParamKey""" + + MANDATORY = 0 + ALPN = 1 + NO_DEFAULT_ALPN = 2 + PORT = 3 + IPV4HINT = 4 + ECHCONFIG = 5 + IPV6HINT = 6 + + @classmethod + def _maximum(cls): + return 65535 + + @classmethod + def _short_name(cls): + return "SVCBParamKey" + + @classmethod + def _prefix(cls): + return "KEY" + + @classmethod + def _unknown_exception_class(cls): + return UnknownParamKey + + +class Emptiness(enum.IntEnum): + NEVER = 0 + ALWAYS = 1 + ALLOWED = 2 + + +def _validate_key(key): + force_generic = False + if isinstance(key, bytes): + # We decode to latin-1 so we get 0-255 as valid and do NOT interpret + # UTF-8 sequences + key = key.decode('latin-1') + if isinstance(key, str): + if key.lower().startswith('key'): + force_generic = True + if key[3:].startswith('0') and len(key) != 4: + # key has leading zeros + raise ValueError('leading zeros in key') + key = key.replace('-', '_') + return (ParamKey.make(key), force_generic) + +def key_to_text(key): + return ParamKey.to_text(key).replace('_', '-').lower() + +# Like rdata escapify, but escapes ',' too. + +_escaped = b'",\\' + +def _escapify(qstring): + text = '' + for c in qstring: + if c in _escaped: + text += '\\' + chr(c) + elif c >= 0x20 and c < 0x7F: + text += chr(c) + else: + text += '\\%03d' % c + return text + +def _unescape(value, list_mode=False): + if value == '': + return value + items = [] + unescaped = b'' + l = len(value) + i = 0 + while i < l: + c = value[i] + i += 1 + if c == ',' and list_mode: + if len(unescaped) == 0: + raise ValueError('list item cannot be empty') + items.append(unescaped) + unescaped = b'' + continue + if c == '\\': + if i >= l: # pragma: no cover (can't happen via tokenizer get()) + raise dns.exception.UnexpectedEnd + c = value[i] + i += 1 + if c.isdigit(): + if i >= l: + raise dns.exception.UnexpectedEnd + c2 = value[i] + i += 1 + if i >= l: + raise dns.exception.UnexpectedEnd + c3 = value[i] + i += 1 + if not (c2.isdigit() and c3.isdigit()): + raise dns.exception.SyntaxError + codepoint = int(c) * 100 + int(c2) * 10 + int(c3) + if codepoint > 255: + raise dns.exception.SyntaxError + c = chr(codepoint) + unescaped += c.encode() + if len(unescaped) > 0: + items.append(unescaped) + else: + # This can't happen outside of list_mode because that would + # require the value parameter to the function to be empty, but + # we special case that at the beginning. + assert list_mode + raise ValueError('trailing comma') + if list_mode: + return items + else: + return items[0] + + +@dns.immutable.immutable +class Param: + """Abstract base class for SVCB parameters""" + + @classmethod + def emptiness(cls): + return Emptiness.NEVER + + +@dns.immutable.immutable +class GenericParam(Param): + """Generic SVCB parameter + """ + def __init__(self, value): + self.value = dns.rdata.Rdata._as_bytes(value, True) + + @classmethod + def emptiness(cls): + return Emptiness.ALLOWED + + @classmethod + def from_value(cls, value): + if value is None or len(value) == 0: + return None + else: + return cls(_unescape(value)) + + def to_text(self): + return '"' + _escapify(self.value) + '"' + + @classmethod + def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 + value = parser.get_bytes(parser.remaining()) + if len(value) == 0: + return None + else: + return cls(value) + + def to_wire(self, file, origin=None): # pylint: disable=W0613 + file.write(self.value) + + +@dns.immutable.immutable +class MandatoryParam(Param): + def __init__(self, keys): + # check for duplicates + keys = sorted([_validate_key(key)[0] for key in keys]) + prior_k = None + for k in keys: + if k == prior_k: + raise ValueError(f'duplicate key {k}') + prior_k = k + if k == ParamKey.MANDATORY: + raise ValueError('listed the mandatory key as mandatory') + self.keys = tuple(keys) + + @classmethod + def from_value(cls, value): + keys = [k.encode() for k in value.split(',')] + return cls(keys) + + def to_text(self): + return '"' + ','.join([key_to_text(key) for key in self.keys]) + '"' + + @classmethod + def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 + keys = [] + last_key = -1 + while parser.remaining() > 0: + key = parser.get_uint16() + if key < last_key: + raise dns.exception.FormError('manadatory keys not ascending') + last_key = key + keys.append(key) + return cls(keys) + + def to_wire(self, file, origin=None): # pylint: disable=W0613 + for key in self.keys: + file.write(struct.pack('!H', key)) + + +@dns.immutable.immutable +class ALPNParam(Param): + def __init__(self, ids): + self.ids = dns.rdata.Rdata._as_tuple( + ids, lambda x: dns.rdata.Rdata._as_bytes(x, True, 255, False)) + + @classmethod + def from_value(cls, value): + return cls(_unescape(value, True)) + + def to_text(self): + return '"' + ','.join([_escapify(id) for id in self.ids]) + '"' + + @classmethod + def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 + ids = [] + while parser.remaining() > 0: + id = parser.get_counted_bytes() + ids.append(id) + return cls(ids) + + def to_wire(self, file, origin=None): # pylint: disable=W0613 + for id in self.ids: + file.write(struct.pack('!B', len(id))) + file.write(id) + + +@dns.immutable.immutable +class NoDefaultALPNParam(Param): + # We don't ever expect to instantiate this class, but we need + # a from_value() and a from_wire_parser(), so we just return None + # from the class methods when things are OK. + + @classmethod + def emptiness(cls): + return Emptiness.ALWAYS + + @classmethod + def from_value(cls, value): + if value is None or value == '': + return None + else: + raise ValueError('no-default-alpn with non-empty value') + + def to_text(self): + raise NotImplementedError # pragma: no cover + + @classmethod + def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 + if parser.remaining() != 0: + raise dns.exception.FormError + return None + + def to_wire(self, file, origin=None): # pylint: disable=W0613 + raise NotImplementedError # pragma: no cover + + +@dns.immutable.immutable +class PortParam(Param): + def __init__(self, port): + self.port = dns.rdata.Rdata._as_uint16(port) + + @classmethod + def from_value(cls, value): + value = int(value) + return cls(value) + + def to_text(self): + return f'"{self.port}"' + + @classmethod + def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 + port = parser.get_uint16() + return cls(port) + + def to_wire(self, file, origin=None): # pylint: disable=W0613 + file.write(struct.pack('!H', self.port)) + + +@dns.immutable.immutable +class IPv4HintParam(Param): + def __init__(self, addresses): + self.addresses = dns.rdata.Rdata._as_tuple( + addresses, dns.rdata.Rdata._as_ipv4_address) + + @classmethod + def from_value(cls, value): + addresses = value.split(',') + return cls(addresses) + + def to_text(self): + return '"' + ','.join(self.addresses) + '"' + + @classmethod + def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 + addresses = [] + while parser.remaining() > 0: + ip = parser.get_bytes(4) + addresses.append(dns.ipv4.inet_ntoa(ip)) + return cls(addresses) + + def to_wire(self, file, origin=None): # pylint: disable=W0613 + for address in self.addresses: + file.write(dns.ipv4.inet_aton(address)) + + +@dns.immutable.immutable +class IPv6HintParam(Param): + def __init__(self, addresses): + self.addresses = dns.rdata.Rdata._as_tuple( + addresses, dns.rdata.Rdata._as_ipv6_address) + + @classmethod + def from_value(cls, value): + addresses = value.split(',') + return cls(addresses) + + def to_text(self): + return '"' + ','.join(self.addresses) + '"' + + @classmethod + def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 + addresses = [] + while parser.remaining() > 0: + ip = parser.get_bytes(16) + addresses.append(dns.ipv6.inet_ntoa(ip)) + return cls(addresses) + + def to_wire(self, file, origin=None): # pylint: disable=W0613 + for address in self.addresses: + file.write(dns.ipv6.inet_aton(address)) + + +@dns.immutable.immutable +class ECHConfigParam(Param): + def __init__(self, echconfig): + self.echconfig = dns.rdata.Rdata._as_bytes(echconfig, True) + + @classmethod + def from_value(cls, value): + if '\\' in value: + raise ValueError('escape in ECHConfig value') + value = base64.b64decode(value.encode()) + return cls(value) + + def to_text(self): + b64 = base64.b64encode(self.echconfig).decode('ascii') + return f'"{b64}"' + + @classmethod + def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 + value = parser.get_bytes(parser.remaining()) + return cls(value) + + def to_wire(self, file, origin=None): # pylint: disable=W0613 + file.write(self.echconfig) + + +_class_for_key = { + ParamKey.MANDATORY: MandatoryParam, + ParamKey.ALPN: ALPNParam, + ParamKey.NO_DEFAULT_ALPN: NoDefaultALPNParam, + ParamKey.PORT: PortParam, + ParamKey.IPV4HINT: IPv4HintParam, + ParamKey.ECHCONFIG: ECHConfigParam, + ParamKey.IPV6HINT: IPv6HintParam, +} + + +def _validate_and_define(params, key, value): + (key, force_generic) = _validate_key(_unescape(key)) + if key in params: + raise SyntaxError(f'duplicate key "{key}"') + cls = _class_for_key.get(key, GenericParam) + emptiness = cls.emptiness() + if value is None: + if emptiness == Emptiness.NEVER: + raise SyntaxError('value cannot be empty') + value = cls.from_value(value) + else: + if force_generic: + value = cls.from_wire_parser(dns.wire.Parser(_unescape(value))) + else: + value = cls.from_value(value) + params[key] = value + + +@dns.immutable.immutable +class SVCBBase(dns.rdata.Rdata): + + """Base class for SVCB-like records""" + + # see: draft-ietf-dnsop-svcb-https-01 + + __slots__ = ['priority', 'target', 'params'] + + def __init__(self, rdclass, rdtype, priority, target, params): + super().__init__(rdclass, rdtype) + self.priority = self._as_uint16(priority) + self.target = self._as_name(target) + for k, v in params.items(): + k = ParamKey.make(k) + if not isinstance(v, Param) and v is not None: + raise ValueError("not a Param") + self.params = dns.immutable.Dict(params) + # Make sure any paramater listed as mandatory is present in the + # record. + mandatory = params.get(ParamKey.MANDATORY) + if mandatory: + for key in mandatory.keys: + # Note we have to say "not in" as we have None as a value + # so a get() and a not None test would be wrong. + if key not in params: + raise ValueError(f'key {key} declared mandatory but not' + 'present') + + def to_text(self, origin=None, relativize=True, **kw): + target = self.target.choose_relativity(origin, relativize) + params = [] + for key in sorted(self.params.keys()): + value = self.params[key] + if value is None: + params.append(key_to_text(key)) + else: + kv = key_to_text(key) + '=' + value.to_text() + params.append(kv) + if len(params) > 0: + space = ' ' + else: + space = '' + return '%d %s%s%s' % (self.priority, target, space, ' '.join(params)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + priority = tok.get_uint16() + target = tok.get_name(origin, relativize, relativize_to) + if priority == 0: + token = tok.get() + if not token.is_eol_or_eof(): + raise SyntaxError('parameters in AliasMode') + tok.unget(token) + params = {} + while True: + token = tok.get() + if token.is_eol_or_eof(): + tok.unget(token) + break + if token.ttype != dns.tokenizer.IDENTIFIER: + raise SyntaxError('parameter is not an identifier') + equals = token.value.find('=') + if equals == len(token.value) - 1: + # 'key=', so next token should be a quoted string without + # any intervening whitespace. + key = token.value[:-1] + token = tok.get(want_leading=True) + if token.ttype != dns.tokenizer.QUOTED_STRING: + raise SyntaxError('whitespace after =') + value = token.value + elif equals > 0: + # key=value + key = token.value[:equals] + value = token.value[equals + 1:] + elif equals == 0: + # =key + raise SyntaxError('parameter cannot start with "="') + else: + # key + key = token.value + value = None + _validate_and_define(params, key, value) + return cls(rdclass, rdtype, priority, target, params) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(struct.pack("!H", self.priority)) + self.target.to_wire(file, None, origin, False) + for key in sorted(self.params): + file.write(struct.pack("!H", key)) + value = self.params[key] + # placeholder for length (or actual length of empty values) + file.write(struct.pack("!H", 0)) + if value is None: + continue + else: + start = file.tell() + value.to_wire(file, origin) + end = file.tell() + assert end - start < 65536 + file.seek(start - 2) + stuff = struct.pack("!H", end - start) + file.write(stuff) + file.seek(0, io.SEEK_END) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + priority = parser.get_uint16() + target = parser.get_name(origin) + if priority == 0 and parser.remaining() != 0: + raise dns.exception.FormError('parameters in AliasMode') + params = {} + prior_key = -1 + while parser.remaining() > 0: + key = parser.get_uint16() + if key < prior_key: + raise dns.exception.FormError('keys not in order') + prior_key = key + vlen = parser.get_uint16() + pcls = _class_for_key.get(key, GenericParam) + with parser.restrict_to(vlen): + value = pcls.from_wire_parser(parser, origin) + params[key] = value + return cls(rdclass, rdtype, priority, target, params) + + def _processing_priority(self): + return self.priority + + @classmethod + def _processing_order(cls, iterable): + return dns.rdtypes.util.priority_processing_order(iterable) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/tlsabase.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/tlsabase.py new file mode 100644 index 0000000..786fca5 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/tlsabase.py @@ -0,0 +1,72 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2005-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct +import binascii + +import dns.rdata +import dns.immutable +import dns.rdatatype + + +@dns.immutable.immutable +class TLSABase(dns.rdata.Rdata): + + """Base class for TLSA and SMIMEA records""" + + # see: RFC 6698 + + __slots__ = ['usage', 'selector', 'mtype', 'cert'] + + def __init__(self, rdclass, rdtype, usage, selector, + mtype, cert): + super().__init__(rdclass, rdtype) + self.usage = self._as_uint8(usage) + self.selector = self._as_uint8(selector) + self.mtype = self._as_uint8(mtype) + self.cert = self._as_bytes(cert) + + def to_text(self, origin=None, relativize=True, **kw): + kw = kw.copy() + chunksize = kw.pop('chunksize', 128) + return '%d %d %d %s' % (self.usage, + self.selector, + self.mtype, + dns.rdata._hexify(self.cert, + chunksize=chunksize, + **kw)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + usage = tok.get_uint8() + selector = tok.get_uint8() + mtype = tok.get_uint8() + cert = tok.concatenate_remaining_identifiers().encode() + cert = binascii.unhexlify(cert) + return cls(rdclass, rdtype, usage, selector, mtype, cert) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + header = struct.pack("!BBB", self.usage, self.selector, self.mtype) + file.write(header) + file.write(self.cert) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + header = parser.get_struct("BBB") + cert = parser.get_remaining() + return cls(rdclass, rdtype, header[0], header[1], header[2], cert) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/txtbase.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/txtbase.py new file mode 100644 index 0000000..68071ee --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/txtbase.py @@ -0,0 +1,87 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""TXT-like base class.""" + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.tokenizer + + +@dns.immutable.immutable +class TXTBase(dns.rdata.Rdata): + + """Base class for rdata that is like a TXT record (see RFC 1035).""" + + __slots__ = ['strings'] + + def __init__(self, rdclass, rdtype, strings): + """Initialize a TXT-like rdata. + + *rdclass*, an ``int`` is the rdataclass of the Rdata. + + *rdtype*, an ``int`` is the rdatatype of the Rdata. + + *strings*, a tuple of ``bytes`` + """ + super().__init__(rdclass, rdtype) + self.strings = self._as_tuple(strings, + lambda x: self._as_bytes(x, True, 255)) + + def to_text(self, origin=None, relativize=True, **kw): + txt = '' + prefix = '' + for s in self.strings: + txt += '{}"{}"'.format(prefix, dns.rdata._escapify(s)) + prefix = ' ' + return txt + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + strings = [] + for token in tok.get_remaining(): + token = token.unescape_to_bytes() + # The 'if' below is always true in the current code, but we + # are leaving this check in in case things change some day. + if not (token.is_quoted_string() or + token.is_identifier()): # pragma: no cover + raise dns.exception.SyntaxError("expected a string") + if len(token.value) > 255: + raise dns.exception.SyntaxError("string too long") + strings.append(token.value) + if len(strings) == 0: + raise dns.exception.UnexpectedEnd + return cls(rdclass, rdtype, strings) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + for s in self.strings: + l = len(s) + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(s) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + strings = [] + while parser.remaining() > 0: + s = parser.get_counted_bytes() + strings.append(s) + return cls(rdclass, rdtype, strings) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/util.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/util.py new file mode 100644 index 0000000..7fc08cd --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rdtypes/util.py @@ -0,0 +1,231 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import collections +import random +import struct + +import dns.exception +import dns.ipv4 +import dns.ipv6 +import dns.name +import dns.rdata + + +class Gateway: + """A helper class for the IPSECKEY gateway and AMTRELAY relay fields""" + name = "" + + def __init__(self, type, gateway=None): + self.type = dns.rdata.Rdata._as_uint8(type) + self.gateway = gateway + self._check() + + @classmethod + def _invalid_type(cls, gateway_type): + return f"invalid {cls.name} type: {gateway_type}" + + def _check(self): + if self.type == 0: + if self.gateway not in (".", None): + raise SyntaxError(f"invalid {self.name} for type 0") + self.gateway = None + elif self.type == 1: + # check that it's OK + dns.ipv4.inet_aton(self.gateway) + elif self.type == 2: + # check that it's OK + dns.ipv6.inet_aton(self.gateway) + elif self.type == 3: + if not isinstance(self.gateway, dns.name.Name): + raise SyntaxError(f"invalid {self.name}; not a name") + else: + raise SyntaxError(self._invalid_type(self.type)) + + def to_text(self, origin=None, relativize=True): + if self.type == 0: + return "." + elif self.type in (1, 2): + return self.gateway + elif self.type == 3: + return str(self.gateway.choose_relativity(origin, relativize)) + else: + raise ValueError(self._invalid_type(self.type)) # pragma: no cover + + @classmethod + def from_text(cls, gateway_type, tok, origin=None, relativize=True, + relativize_to=None): + if gateway_type in (0, 1, 2): + gateway = tok.get_string() + elif gateway_type == 3: + gateway = tok.get_name(origin, relativize, relativize_to) + else: + raise dns.exception.SyntaxError( + cls._invalid_type(gateway_type)) # pragma: no cover + return cls(gateway_type, gateway) + + # pylint: disable=unused-argument + def to_wire(self, file, compress=None, origin=None, canonicalize=False): + if self.type == 0: + pass + elif self.type == 1: + file.write(dns.ipv4.inet_aton(self.gateway)) + elif self.type == 2: + file.write(dns.ipv6.inet_aton(self.gateway)) + elif self.type == 3: + self.gateway.to_wire(file, None, origin, False) + else: + raise ValueError(self._invalid_type(self.type)) # pragma: no cover + # pylint: enable=unused-argument + + @classmethod + def from_wire_parser(cls, gateway_type, parser, origin=None): + if gateway_type == 0: + gateway = None + elif gateway_type == 1: + gateway = dns.ipv4.inet_ntoa(parser.get_bytes(4)) + elif gateway_type == 2: + gateway = dns.ipv6.inet_ntoa(parser.get_bytes(16)) + elif gateway_type == 3: + gateway = parser.get_name(origin) + else: + raise dns.exception.FormError(cls._invalid_type(gateway_type)) + return cls(gateway_type, gateway) + + +class Bitmap: + """A helper class for the NSEC/NSEC3/CSYNC type bitmaps""" + type_name = "" + + def __init__(self, windows=None): + last_window = -1 + self.windows = windows + for (window, bitmap) in self.windows: + if not isinstance(window, int): + raise ValueError(f"bad {self.type_name} window type") + if window <= last_window: + raise ValueError(f"bad {self.type_name} window order") + if window > 256: + raise ValueError(f"bad {self.type_name} window number") + last_window = window + if not isinstance(bitmap, bytes): + raise ValueError(f"bad {self.type_name} octets type") + if len(bitmap) == 0 or len(bitmap) > 32: + raise ValueError(f"bad {self.type_name} octets") + + def to_text(self): + text = "" + for (window, bitmap) in self.windows: + bits = [] + for (i, byte) in enumerate(bitmap): + for j in range(0, 8): + if byte & (0x80 >> j): + rdtype = window * 256 + i * 8 + j + bits.append(dns.rdatatype.to_text(rdtype)) + text += (' ' + ' '.join(bits)) + return text + + @classmethod + def from_text(cls, tok): + rdtypes = [] + for token in tok.get_remaining(): + rdtype = dns.rdatatype.from_text(token.unescape().value) + if rdtype == 0: + raise dns.exception.SyntaxError(f"{cls.type_name} with bit 0") + rdtypes.append(rdtype) + rdtypes.sort() + window = 0 + octets = 0 + prior_rdtype = 0 + bitmap = bytearray(b'\0' * 32) + windows = [] + for rdtype in rdtypes: + if rdtype == prior_rdtype: + continue + prior_rdtype = rdtype + new_window = rdtype // 256 + if new_window != window: + if octets != 0: + windows.append((window, bytes(bitmap[0:octets]))) + bitmap = bytearray(b'\0' * 32) + window = new_window + offset = rdtype % 256 + byte = offset // 8 + bit = offset % 8 + octets = byte + 1 + bitmap[byte] = bitmap[byte] | (0x80 >> bit) + if octets != 0: + windows.append((window, bytes(bitmap[0:octets]))) + return cls(windows) + + def to_wire(self, file): + for (window, bitmap) in self.windows: + file.write(struct.pack('!BB', window, len(bitmap))) + file.write(bitmap) + + @classmethod + def from_wire_parser(cls, parser): + windows = [] + while parser.remaining() > 0: + window = parser.get_uint8() + bitmap = parser.get_counted_bytes() + windows.append((window, bitmap)) + return cls(windows) + + +def _priority_table(items): + by_priority = collections.defaultdict(list) + for rdata in items: + by_priority[rdata._processing_priority()].append(rdata) + return by_priority + +def priority_processing_order(iterable): + items = list(iterable) + if len(items) == 1: + return items + by_priority = _priority_table(items) + ordered = [] + for k in sorted(by_priority.keys()): + rdatas = by_priority[k] + random.shuffle(rdatas) + ordered.extend(rdatas) + return ordered + +_no_weight = 0.1 + +def weighted_processing_order(iterable): + items = list(iterable) + if len(items) == 1: + return items + by_priority = _priority_table(items) + ordered = [] + for k in sorted(by_priority.keys()): + rdatas = by_priority[k] + total = sum(rdata._processing_weight() or _no_weight + for rdata in rdatas) + while len(rdatas) > 1: + r = random.uniform(0, total) + for (n, rdata) in enumerate(rdatas): + weight = rdata._processing_weight() or _no_weight + if weight > r: + break + r -= weight + total -= weight + ordered.append(rdata) + del rdatas[n] + ordered.append(rdatas[0]) + return ordered diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/renderer.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/renderer.py new file mode 100644 index 0000000..72f0f7a --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/renderer.py @@ -0,0 +1,250 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Help for building DNS wire format messages""" + +import contextlib +import io +import struct +import random +import time + +import dns.exception +import dns.tsig + + +QUESTION = 0 +ANSWER = 1 +AUTHORITY = 2 +ADDITIONAL = 3 + + +class Renderer: + """Helper class for building DNS wire-format messages. + + Most applications can use the higher-level L{dns.message.Message} + class and its to_wire() method to generate wire-format messages. + This class is for those applications which need finer control + over the generation of messages. + + Typical use:: + + r = dns.renderer.Renderer(id=1, flags=0x80, max_size=512) + r.add_question(qname, qtype, qclass) + r.add_rrset(dns.renderer.ANSWER, rrset_1) + r.add_rrset(dns.renderer.ANSWER, rrset_2) + r.add_rrset(dns.renderer.AUTHORITY, ns_rrset) + r.add_edns(0, 0, 4096) + r.add_rrset(dns.renderer.ADDTIONAL, ad_rrset_1) + r.add_rrset(dns.renderer.ADDTIONAL, ad_rrset_2) + r.write_header() + r.add_tsig(keyname, secret, 300, 1, 0, '', request_mac) + wire = r.get_wire() + + output, an io.BytesIO, where rendering is written + + id: the message id + + flags: the message flags + + max_size: the maximum size of the message + + origin: the origin to use when rendering relative names + + compress: the compression table + + section: an int, the section currently being rendered + + counts: list of the number of RRs in each section + + mac: the MAC of the rendered message (if TSIG was used) + """ + + def __init__(self, id=None, flags=0, max_size=65535, origin=None): + """Initialize a new renderer.""" + + self.output = io.BytesIO() + if id is None: + self.id = random.randint(0, 65535) + else: + self.id = id + self.flags = flags + self.max_size = max_size + self.origin = origin + self.compress = {} + self.section = QUESTION + self.counts = [0, 0, 0, 0] + self.output.write(b'\x00' * 12) + self.mac = '' + + def _rollback(self, where): + """Truncate the output buffer at offset *where*, and remove any + compression table entries that pointed beyond the truncation + point. + """ + + self.output.seek(where) + self.output.truncate() + keys_to_delete = [] + for k, v in self.compress.items(): + if v >= where: + keys_to_delete.append(k) + for k in keys_to_delete: + del self.compress[k] + + def _set_section(self, section): + """Set the renderer's current section. + + Sections must be rendered order: QUESTION, ANSWER, AUTHORITY, + ADDITIONAL. Sections may be empty. + + Raises dns.exception.FormError if an attempt was made to set + a section value less than the current section. + """ + + if self.section != section: + if self.section > section: + raise dns.exception.FormError + self.section = section + + @contextlib.contextmanager + def _track_size(self): + start = self.output.tell() + yield start + if self.output.tell() > self.max_size: + self._rollback(start) + raise dns.exception.TooBig + + def add_question(self, qname, rdtype, rdclass=dns.rdataclass.IN): + """Add a question to the message.""" + + self._set_section(QUESTION) + with self._track_size(): + qname.to_wire(self.output, self.compress, self.origin) + self.output.write(struct.pack("!HH", rdtype, rdclass)) + self.counts[QUESTION] += 1 + + def add_rrset(self, section, rrset, **kw): + """Add the rrset to the specified section. + + Any keyword arguments are passed on to the rdataset's to_wire() + routine. + """ + + self._set_section(section) + with self._track_size(): + n = rrset.to_wire(self.output, self.compress, self.origin, **kw) + self.counts[section] += n + + def add_rdataset(self, section, name, rdataset, **kw): + """Add the rdataset to the specified section, using the specified + name as the owner name. + + Any keyword arguments are passed on to the rdataset's to_wire() + routine. + """ + + self._set_section(section) + with self._track_size(): + n = rdataset.to_wire(name, self.output, self.compress, self.origin, + **kw) + self.counts[section] += n + + def add_edns(self, edns, ednsflags, payload, options=None): + """Add an EDNS OPT record to the message.""" + + # make sure the EDNS version in ednsflags agrees with edns + ednsflags &= 0xFF00FFFF + ednsflags |= (edns << 16) + opt = dns.message.Message._make_opt(ednsflags, payload, options) + self.add_rrset(ADDITIONAL, opt) + + def add_tsig(self, keyname, secret, fudge, id, tsig_error, other_data, + request_mac, algorithm=dns.tsig.default_algorithm): + """Add a TSIG signature to the message.""" + + s = self.output.getvalue() + + if isinstance(secret, dns.tsig.Key): + key = secret + else: + key = dns.tsig.Key(keyname, secret, algorithm) + tsig = dns.message.Message._make_tsig(keyname, algorithm, 0, fudge, + b'', id, tsig_error, other_data) + (tsig, _) = dns.tsig.sign(s, key, tsig[0], int(time.time()), + request_mac) + self._write_tsig(tsig, keyname) + + def add_multi_tsig(self, ctx, keyname, secret, fudge, id, tsig_error, + other_data, request_mac, + algorithm=dns.tsig.default_algorithm): + """Add a TSIG signature to the message. Unlike add_tsig(), this can be + used for a series of consecutive DNS envelopes, e.g. for a zone + transfer over TCP [RFC2845, 4.4]. + + For the first message in the sequence, give ctx=None. For each + subsequent message, give the ctx that was returned from the + add_multi_tsig() call for the previous message.""" + + s = self.output.getvalue() + + if isinstance(secret, dns.tsig.Key): + key = secret + else: + key = dns.tsig.Key(keyname, secret, algorithm) + tsig = dns.message.Message._make_tsig(keyname, algorithm, 0, fudge, + b'', id, tsig_error, other_data) + (tsig, ctx) = dns.tsig.sign(s, key, tsig[0], int(time.time()), + request_mac, ctx, True) + self._write_tsig(tsig, keyname) + return ctx + + def _write_tsig(self, tsig, keyname): + self._set_section(ADDITIONAL) + with self._track_size(): + keyname.to_wire(self.output, self.compress, self.origin) + self.output.write(struct.pack('!HHIH', dns.rdatatype.TSIG, + dns.rdataclass.ANY, 0, 0)) + rdata_start = self.output.tell() + tsig.to_wire(self.output) + + after = self.output.tell() + self.output.seek(rdata_start - 2) + self.output.write(struct.pack('!H', after - rdata_start)) + self.counts[ADDITIONAL] += 1 + self.output.seek(10) + self.output.write(struct.pack('!H', self.counts[ADDITIONAL])) + self.output.seek(0, io.SEEK_END) + + def write_header(self): + """Write the DNS message header. + + Writing the DNS message header is done after all sections + have been rendered, but before the optional TSIG signature + is added. + """ + + self.output.seek(0) + self.output.write(struct.pack('!HHHHHH', self.id, self.flags, + self.counts[0], self.counts[1], + self.counts[2], self.counts[3])) + self.output.seek(0, io.SEEK_END) + + def get_wire(self): + """Return the wire format message.""" + + return self.output.getvalue() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/resolver.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/resolver.py new file mode 100644 index 0000000..7bdfd91 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/resolver.py @@ -0,0 +1,1649 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS stub resolver.""" +from urllib.parse import urlparse +import contextlib +import socket +import sys +import time +import random +import warnings +try: + import threading as _threading +except ImportError: # pragma: no cover + import dummy_threading as _threading # type: ignore + +import dns.exception +import dns.flags +import dns.inet +import dns.ipv4 +import dns.ipv6 +import dns.message +import dns.name +import dns.query +import dns.rcode +import dns.rdataclass +import dns.rdatatype +import dns.reversename +import dns.tsig + +if sys.platform == 'win32': + # pylint: disable=import-error + import winreg + +class NXDOMAIN(dns.exception.DNSException): + """The DNS query name does not exist.""" + supp_kwargs = {'qnames', 'responses'} + fmt = None # we have our own __str__ implementation + + # pylint: disable=arguments-differ + + def _check_kwargs(self, qnames, + responses=None): + if not isinstance(qnames, (list, tuple, set)): + raise AttributeError("qnames must be a list, tuple or set") + if len(qnames) == 0: + raise AttributeError("qnames must contain at least one element") + if responses is None: + responses = {} + elif not isinstance(responses, dict): + raise AttributeError("responses must be a dict(qname=response)") + kwargs = dict(qnames=qnames, responses=responses) + return kwargs + + def __str__(self): + if 'qnames' not in self.kwargs: + return super().__str__() + qnames = self.kwargs['qnames'] + if len(qnames) > 1: + msg = 'None of DNS query names exist' + else: + msg = 'The DNS query name does not exist' + qnames = ', '.join(map(str, qnames)) + return "{}: {}".format(msg, qnames) + + @property + def canonical_name(self): + """Return the unresolved canonical name.""" + if 'qnames' not in self.kwargs: + raise TypeError("parametrized exception required") + for qname in self.kwargs['qnames']: + response = self.kwargs['responses'][qname] + try: + cname = response.canonical_name() + if cname != qname: + return cname + except Exception: + # We can just eat this exception as it means there was + # something wrong with the response. + pass + return self.kwargs['qnames'][0] + + def __add__(self, e_nx): + """Augment by results from another NXDOMAIN exception.""" + qnames0 = list(self.kwargs.get('qnames', [])) + responses0 = dict(self.kwargs.get('responses', {})) + responses1 = e_nx.kwargs.get('responses', {}) + for qname1 in e_nx.kwargs.get('qnames', []): + if qname1 not in qnames0: + qnames0.append(qname1) + if qname1 in responses1: + responses0[qname1] = responses1[qname1] + return NXDOMAIN(qnames=qnames0, responses=responses0) + + def qnames(self): + """All of the names that were tried. + + Returns a list of ``dns.name.Name``. + """ + return self.kwargs['qnames'] + + def responses(self): + """A map from queried names to their NXDOMAIN responses. + + Returns a dict mapping a ``dns.name.Name`` to a + ``dns.message.Message``. + """ + return self.kwargs['responses'] + + def response(self, qname): + """The response for query *qname*. + + Returns a ``dns.message.Message``. + """ + return self.kwargs['responses'][qname] + + +class YXDOMAIN(dns.exception.DNSException): + """The DNS query name is too long after DNAME substitution.""" + +# The definition of the Timeout exception has moved from here to the +# dns.exception module. We keep dns.resolver.Timeout defined for +# backwards compatibility. + +Timeout = dns.exception.Timeout + + +class NoAnswer(dns.exception.DNSException): + """The DNS response does not contain an answer to the question.""" + fmt = 'The DNS response does not contain an answer ' + \ + 'to the question: {query}' + supp_kwargs = {'response'} + + def _fmt_kwargs(self, **kwargs): + return super()._fmt_kwargs(query=kwargs['response'].question) + + +class NoNameservers(dns.exception.DNSException): + """All nameservers failed to answer the query. + + errors: list of servers and respective errors + The type of errors is + [(server IP address, any object convertible to string)]. + Non-empty errors list will add explanatory message () + """ + + msg = "All nameservers failed to answer the query." + fmt = "%s {query}: {errors}" % msg[:-1] + supp_kwargs = {'request', 'errors'} + + def _fmt_kwargs(self, **kwargs): + srv_msgs = [] + for err in kwargs['errors']: + # pylint: disable=bad-continuation + srv_msgs.append('Server {} {} port {} answered {}'.format(err[0], + 'TCP' if err[1] else 'UDP', err[2], err[3])) + return super()._fmt_kwargs(query=kwargs['request'].question, + errors='; '.join(srv_msgs)) + + +class NotAbsolute(dns.exception.DNSException): + """An absolute domain name is required but a relative name was provided.""" + + +class NoRootSOA(dns.exception.DNSException): + """There is no SOA RR at the DNS root name. This should never happen!""" + + +class NoMetaqueries(dns.exception.DNSException): + """DNS metaqueries are not allowed.""" + +class NoResolverConfiguration(dns.exception.DNSException): + """Resolver configuration could not be read or specified no nameservers.""" + +class Answer: + """DNS stub resolver answer. + + Instances of this class bundle up the result of a successful DNS + resolution. + + For convenience, the answer object implements much of the sequence + protocol, forwarding to its ``rrset`` attribute. E.g. + ``for a in answer`` is equivalent to ``for a in answer.rrset``. + ``answer[i]`` is equivalent to ``answer.rrset[i]``, and + ``answer[i:j]`` is equivalent to ``answer.rrset[i:j]``. + + Note that CNAMEs or DNAMEs in the response may mean that answer + RRset's name might not be the query name. + """ + + def __init__(self, qname, rdtype, rdclass, response, nameserver=None, + port=None): + self.qname = qname + self.rdtype = rdtype + self.rdclass = rdclass + self.response = response + self.nameserver = nameserver + self.port = port + self.chaining_result = response.resolve_chaining() + # Copy some attributes out of chaining_result for backwards + # compatibility and convenience. + self.canonical_name = self.chaining_result.canonical_name + self.rrset = self.chaining_result.answer + self.expiration = time.time() + self.chaining_result.minimum_ttl + + def __getattr__(self, attr): # pragma: no cover + if attr == 'name': + return self.rrset.name + elif attr == 'ttl': + return self.rrset.ttl + elif attr == 'covers': + return self.rrset.covers + elif attr == 'rdclass': + return self.rrset.rdclass + elif attr == 'rdtype': + return self.rrset.rdtype + else: + raise AttributeError(attr) + + def __len__(self): + return self.rrset and len(self.rrset) or 0 + + def __iter__(self): + return self.rrset and iter(self.rrset) or iter(tuple()) + + def __getitem__(self, i): + if self.rrset is None: + raise IndexError + return self.rrset[i] + + def __delitem__(self, i): + if self.rrset is None: + raise IndexError + del self.rrset[i] + + +class CacheStatistics: + """Cache Statistics + """ + + def __init__(self, hits=0, misses=0): + self.hits = hits + self.misses = misses + + def reset(self): + self.hits = 0 + self.misses = 0 + + def clone(self): + return CacheStatistics(self.hits, self.misses) + + +class CacheBase: + def __init__(self): + self.lock = _threading.Lock() + self.statistics = CacheStatistics() + + def reset_statistics(self): + """Reset all statistics to zero.""" + with self.lock: + self.statistics.reset() + + def hits(self): + """How many hits has the cache had?""" + with self.lock: + return self.statistics.hits + + def misses(self): + """How many misses has the cache had?""" + with self.lock: + return self.statistics.misses + + def get_statistics_snapshot(self): + """Return a consistent snapshot of all the statistics. + + If running with multiple threads, it's better to take a + snapshot than to call statistics methods such as hits() and + misses() individually. + """ + with self.lock: + return self.statistics.clone() + + +class Cache(CacheBase): + """Simple thread-safe DNS answer cache.""" + + def __init__(self, cleaning_interval=300.0): + """*cleaning_interval*, a ``float`` is the number of seconds between + periodic cleanings. + """ + + super().__init__() + self.data = {} + self.cleaning_interval = cleaning_interval + self.next_cleaning = time.time() + self.cleaning_interval + + def _maybe_clean(self): + """Clean the cache if it's time to do so.""" + + now = time.time() + if self.next_cleaning <= now: + keys_to_delete = [] + for (k, v) in self.data.items(): + if v.expiration <= now: + keys_to_delete.append(k) + for k in keys_to_delete: + del self.data[k] + now = time.time() + self.next_cleaning = now + self.cleaning_interval + + def get(self, key): + """Get the answer associated with *key*. + + Returns None if no answer is cached for the key. + + *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the + query name, rdtype, and rdclass respectively. + + Returns a ``dns.resolver.Answer`` or ``None``. + """ + + with self.lock: + self._maybe_clean() + v = self.data.get(key) + if v is None or v.expiration <= time.time(): + self.statistics.misses += 1 + return None + self.statistics.hits += 1 + return v + + def put(self, key, value): + """Associate key and value in the cache. + + *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the + query name, rdtype, and rdclass respectively. + + *value*, a ``dns.resolver.Answer``, the answer. + """ + + with self.lock: + self._maybe_clean() + self.data[key] = value + + def flush(self, key=None): + """Flush the cache. + + If *key* is not ``None``, only that item is flushed. Otherwise + the entire cache is flushed. + + *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the + query name, rdtype, and rdclass respectively. + """ + + with self.lock: + if key is not None: + if key in self.data: + del self.data[key] + else: + self.data = {} + self.next_cleaning = time.time() + self.cleaning_interval + + +class LRUCacheNode: + """LRUCache node.""" + + def __init__(self, key, value): + self.key = key + self.value = value + self.hits = 0 + self.prev = self + self.next = self + + def link_after(self, node): + self.prev = node + self.next = node.next + node.next.prev = self + node.next = self + + def unlink(self): + self.next.prev = self.prev + self.prev.next = self.next + + +class LRUCache(CacheBase): + """Thread-safe, bounded, least-recently-used DNS answer cache. + + This cache is better than the simple cache (above) if you're + running a web crawler or other process that does a lot of + resolutions. The LRUCache has a maximum number of nodes, and when + it is full, the least-recently used node is removed to make space + for a new one. + """ + + def __init__(self, max_size=100000): + """*max_size*, an ``int``, is the maximum number of nodes to cache; + it must be greater than 0. + """ + + super().__init__() + self.data = {} + self.set_max_size(max_size) + self.sentinel = LRUCacheNode(None, None) + self.sentinel.prev = self.sentinel + self.sentinel.next = self.sentinel + + def set_max_size(self, max_size): + if max_size < 1: + max_size = 1 + self.max_size = max_size + + def get(self, key): + """Get the answer associated with *key*. + + Returns None if no answer is cached for the key. + + *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the + query name, rdtype, and rdclass respectively. + + Returns a ``dns.resolver.Answer`` or ``None``. + """ + + with self.lock: + node = self.data.get(key) + if node is None: + self.statistics.misses += 1 + return None + # Unlink because we're either going to move the node to the front + # of the LRU list or we're going to free it. + node.unlink() + if node.value.expiration <= time.time(): + del self.data[node.key] + self.statistics.misses += 1 + return None + node.link_after(self.sentinel) + self.statistics.hits += 1 + node.hits += 1 + return node.value + + def get_hits_for_key(self, key): + """Return the number of cache hits associated with the specified key.""" + with self.lock: + node = self.data.get(key) + if node is None or node.value.expiration <= time.time(): + return 0 + else: + return node.hits + + def put(self, key, value): + """Associate key and value in the cache. + + *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the + query name, rdtype, and rdclass respectively. + + *value*, a ``dns.resolver.Answer``, the answer. + """ + + with self.lock: + node = self.data.get(key) + if node is not None: + node.unlink() + del self.data[node.key] + while len(self.data) >= self.max_size: + node = self.sentinel.prev + node.unlink() + del self.data[node.key] + node = LRUCacheNode(key, value) + node.link_after(self.sentinel) + self.data[key] = node + + def flush(self, key=None): + """Flush the cache. + + If *key* is not ``None``, only that item is flushed. Otherwise + the entire cache is flushed. + + *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the + query name, rdtype, and rdclass respectively. + """ + + with self.lock: + if key is not None: + node = self.data.get(key) + if node is not None: + node.unlink() + del self.data[node.key] + else: + node = self.sentinel.next + while node != self.sentinel: + next = node.next + node.unlink() + node = next + self.data = {} + +class _Resolution: + """Helper class for dns.resolver.Resolver.resolve(). + + All of the "business logic" of resolution is encapsulated in this + class, allowing us to have multiple resolve() implementations + using different I/O schemes without copying all of the + complicated logic. + + This class is a "friend" to dns.resolver.Resolver and manipulates + resolver data structures directly. + """ + + def __init__(self, resolver, qname, rdtype, rdclass, tcp, + raise_on_no_answer, search): + if isinstance(qname, str): + qname = dns.name.from_text(qname, None) + rdtype = dns.rdatatype.RdataType.make(rdtype) + if dns.rdatatype.is_metatype(rdtype): + raise NoMetaqueries + rdclass = dns.rdataclass.RdataClass.make(rdclass) + if dns.rdataclass.is_metaclass(rdclass): + raise NoMetaqueries + self.resolver = resolver + self.qnames_to_try = resolver._get_qnames_to_try(qname, search) + self.qnames = self.qnames_to_try[:] + self.rdtype = rdtype + self.rdclass = rdclass + self.tcp = tcp + self.raise_on_no_answer = raise_on_no_answer + self.nxdomain_responses = {} + # + # Initialize other things to help analysis tools + self.qname = dns.name.empty + self.nameservers = [] + self.current_nameservers = [] + self.errors = [] + self.nameserver = None + self.port = 0 + self.tcp_attempt = False + self.retry_with_tcp = False + self.request = None + self.backoff = 0 + + def next_request(self): + """Get the next request to send, and check the cache. + + Returns a (request, answer) tuple. At most one of request or + answer will not be None. + """ + + # We return a tuple instead of Union[Message,Answer] as it lets + # the caller avoid isinstance(). + + while len(self.qnames) > 0: + self.qname = self.qnames.pop(0) + + # Do we know the answer? + if self.resolver.cache: + answer = self.resolver.cache.get((self.qname, self.rdtype, + self.rdclass)) + if answer is not None: + if answer.rrset is None and self.raise_on_no_answer: + raise NoAnswer(response=answer.response) + else: + return (None, answer) + answer = self.resolver.cache.get((self.qname, + dns.rdatatype.ANY, + self.rdclass)) + if answer is not None and \ + answer.response.rcode() == dns.rcode.NXDOMAIN: + # cached NXDOMAIN; record it and continue to next + # name. + self.nxdomain_responses[self.qname] = answer.response + continue + + # Build the request + request = dns.message.make_query(self.qname, self.rdtype, + self.rdclass) + if self.resolver.keyname is not None: + request.use_tsig(self.resolver.keyring, self.resolver.keyname, + algorithm=self.resolver.keyalgorithm) + request.use_edns(self.resolver.edns, self.resolver.ednsflags, + self.resolver.payload) + if self.resolver.flags is not None: + request.flags = self.resolver.flags + + self.nameservers = self.resolver.nameservers[:] + if self.resolver.rotate: + random.shuffle(self.nameservers) + self.current_nameservers = self.nameservers[:] + self.errors = [] + self.nameserver = None + self.tcp_attempt = False + self.retry_with_tcp = False + self.request = request + self.backoff = 0.10 + + return (request, None) + + # + # We've tried everything and only gotten NXDOMAINs. (We know + # it's only NXDOMAINs as anything else would have returned + # before now.) + # + raise NXDOMAIN(qnames=self.qnames_to_try, + responses=self.nxdomain_responses) + + def next_nameserver(self): + if self.retry_with_tcp: + assert self.nameserver is not None + self.tcp_attempt = True + self.retry_with_tcp = False + return (self.nameserver, self.port, True, 0) + + backoff = 0 + if not self.current_nameservers: + if len(self.nameservers) == 0: + # Out of things to try! + raise NoNameservers(request=self.request, errors=self.errors) + self.current_nameservers = self.nameservers[:] + backoff = self.backoff + self.backoff = min(self.backoff * 2, 2) + + self.nameserver = self.current_nameservers.pop(0) + self.port = self.resolver.nameserver_ports.get(self.nameserver, + self.resolver.port) + self.tcp_attempt = self.tcp + return (self.nameserver, self.port, self.tcp_attempt, backoff) + + def query_result(self, response, ex): + # + # returns an (answer: Answer, end_loop: bool) tuple. + # + if ex: + # Exception during I/O or from_wire() + assert response is None + self.errors.append((self.nameserver, self.tcp_attempt, self.port, + ex, response)) + if isinstance(ex, dns.exception.FormError) or \ + isinstance(ex, EOFError) or \ + isinstance(ex, OSError) or \ + isinstance(ex, NotImplementedError): + # This nameserver is no good, take it out of the mix. + self.nameservers.remove(self.nameserver) + elif isinstance(ex, dns.message.Truncated): + if self.tcp_attempt: + # Truncation with TCP is no good! + self.nameservers.remove(self.nameserver) + else: + self.retry_with_tcp = True + return (None, False) + # We got an answer! + assert response is not None + rcode = response.rcode() + if rcode == dns.rcode.NOERROR: + try: + answer = Answer(self.qname, self.rdtype, self.rdclass, response, + self.nameserver, self.port) + except Exception: + # The nameserver is no good, take it out of the mix. + self.nameservers.remove(self.nameserver) + return (None, False) + if self.resolver.cache: + self.resolver.cache.put((self.qname, self.rdtype, + self.rdclass), answer) + if answer.rrset is None and self.raise_on_no_answer: + raise NoAnswer(response=answer.response) + return (answer, True) + elif rcode == dns.rcode.NXDOMAIN: + # Further validate the response by making an Answer, even + # if we aren't going to cache it. + try: + answer = Answer(self.qname, dns.rdatatype.ANY, + dns.rdataclass.IN, response) + except Exception: + # The nameserver is no good, take it out of the mix. + self.nameservers.remove(self.nameserver) + return (None, False) + self.nxdomain_responses[self.qname] = response + if self.resolver.cache: + self.resolver.cache.put((self.qname, + dns.rdatatype.ANY, + self.rdclass), answer) + # Make next_nameserver() return None, so caller breaks its + # inner loop and calls next_request(). + return (None, True) + elif rcode == dns.rcode.YXDOMAIN: + yex = YXDOMAIN() + self.errors.append((self.nameserver, self.tcp_attempt, + self.port, yex, response)) + raise yex + else: + # + # We got a response, but we're not happy with the + # rcode in it. + # + if rcode != dns.rcode.SERVFAIL or not self.resolver.retry_servfail: + self.nameservers.remove(self.nameserver) + self.errors.append((self.nameserver, self.tcp_attempt, self.port, + dns.rcode.to_text(rcode), response)) + return (None, False) + +class BaseResolver: + """DNS stub resolver.""" + + # We initialize in reset() + # + # pylint: disable=attribute-defined-outside-init + + def __init__(self, filename='/etc/resolv.conf', configure=True): + """*filename*, a ``str`` or file object, specifying a file + in standard /etc/resolv.conf format. This parameter is meaningful + only when *configure* is true and the platform is POSIX. + + *configure*, a ``bool``. If True (the default), the resolver + instance is configured in the normal fashion for the operating + system the resolver is running on. (I.e. by reading a + /etc/resolv.conf file on POSIX systems and from the registry + on Windows systems.) + """ + + self.reset() + if configure: + if sys.platform == 'win32': + self.read_registry() + elif filename: + self.read_resolv_conf(filename) + + def reset(self): + """Reset all resolver configuration to the defaults.""" + + self.domain = \ + dns.name.Name(dns.name.from_text(socket.gethostname())[1:]) + if len(self.domain) == 0: + self.domain = dns.name.root + self.nameservers = [] + self.nameserver_ports = {} + self.port = 53 + self.search = [] + self.use_search_by_default = False + self.timeout = 2.0 + self.lifetime = 5.0 + self.keyring = None + self.keyname = None + self.keyalgorithm = dns.tsig.default_algorithm + self.edns = -1 + self.ednsflags = 0 + self.payload = 0 + self.cache = None + self.flags = None + self.retry_servfail = False + self.rotate = False + self.ndots = None + + def read_resolv_conf(self, f): + """Process *f* as a file in the /etc/resolv.conf format. If f is + a ``str``, it is used as the name of the file to open; otherwise it + is treated as the file itself. + + Interprets the following items: + + - nameserver - name server IP address + + - domain - local domain name + + - search - search list for host-name lookup + + - options - supported options are rotate, timeout, edns0, and ndots + + """ + + with contextlib.ExitStack() as stack: + if isinstance(f, str): + try: + f = stack.enter_context(open(f)) + except OSError: + # /etc/resolv.conf doesn't exist, can't be read, etc. + raise NoResolverConfiguration + + for l in f: + if len(l) == 0 or l[0] == '#' or l[0] == ';': + continue + tokens = l.split() + + # Any line containing less than 2 tokens is malformed + if len(tokens) < 2: + continue + + if tokens[0] == 'nameserver': + self.nameservers.append(tokens[1]) + elif tokens[0] == 'domain': + self.domain = dns.name.from_text(tokens[1]) + # domain and search are exclusive + self.search = [] + elif tokens[0] == 'search': + # the last search wins + self.search = [] + for suffix in tokens[1:]: + self.search.append(dns.name.from_text(suffix)) + # We don't set domain as it is not used if + # len(self.search) > 0 + elif tokens[0] == 'options': + for opt in tokens[1:]: + if opt == 'rotate': + self.rotate = True + elif opt == 'edns0': + self.use_edns() + elif 'timeout' in opt: + try: + self.timeout = int(opt.split(':')[1]) + except (ValueError, IndexError): + pass + elif 'ndots' in opt: + try: + self.ndots = int(opt.split(':')[1]) + except (ValueError, IndexError): + pass + if len(self.nameservers) == 0: + raise NoResolverConfiguration + + def _determine_split_char(self, entry): + # + # The windows registry irritatingly changes the list element + # delimiter in between ' ' and ',' (and vice-versa) in various + # versions of windows. + # + if entry.find(' ') >= 0: # pragma: no cover + split_char = ' ' + elif entry.find(',') >= 0: # pragma: no cover + split_char = ',' + else: + # probably a singleton; treat as a space-separated list. + split_char = ' ' + return split_char + + def _config_win32_nameservers(self, nameservers): + # we call str() on nameservers to convert it from unicode to ascii + nameservers = str(nameservers) + split_char = self._determine_split_char(nameservers) + ns_list = nameservers.split(split_char) + for ns in ns_list: + if ns not in self.nameservers: + self.nameservers.append(ns) + + def _config_win32_domain(self, domain): # pragma: no cover + # we call str() on domain to convert it from unicode to ascii + self.domain = dns.name.from_text(str(domain)) + + def _config_win32_search(self, search): # pragma: no cover + # we call str() on search to convert it from unicode to ascii + search = str(search) + split_char = self._determine_split_char(search) + search_list = search.split(split_char) + for s in search_list: + if s not in self.search: + self.search.append(dns.name.from_text(s)) + + def _config_win32_fromkey(self, key, always_try_domain): + # pylint: disable=undefined-variable + # (disabled for WindowsError) + try: + servers, _ = winreg.QueryValueEx(key, 'NameServer') + except WindowsError: # pragma: no cover + servers = None + if servers: + self._config_win32_nameservers(servers) + if servers or always_try_domain: + try: + dom, _ = winreg.QueryValueEx(key, 'Domain') + if dom: + self._config_win32_domain(dom) # pragma: no cover + except WindowsError: # pragma: no cover + pass + else: + try: + servers, _ = winreg.QueryValueEx(key, 'DhcpNameServer') + except WindowsError: # pragma: no cover + servers = None + if servers: + self._config_win32_nameservers(servers) + try: + dom, _ = winreg.QueryValueEx(key, 'DhcpDomain') + if dom: + self._config_win32_domain(dom) + except WindowsError: # pragma: no cover + pass + try: + search, _ = winreg.QueryValueEx(key, 'SearchList') + except WindowsError: # pragma: no cover + search = None + if search: # pragma: no cover + self._config_win32_search(search) + + def read_registry(self): + """Extract resolver configuration from the Windows registry.""" + + lm = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) + try: + tcp_params = winreg.OpenKey(lm, + r'SYSTEM\CurrentControlSet' + r'\Services\Tcpip\Parameters') + try: + self._config_win32_fromkey(tcp_params, True) + finally: + tcp_params.Close() + interfaces = winreg.OpenKey(lm, + r'SYSTEM\CurrentControlSet' + r'\Services\Tcpip\Parameters' + r'\Interfaces') + try: + i = 0 + while True: + try: + guid = winreg.EnumKey(interfaces, i) + i += 1 + # XXXRTH why do we get this key and then not use it? + key = winreg.OpenKey(interfaces, guid) + if not self._win32_is_nic_enabled(lm, guid, key): + continue + try: + self._config_win32_fromkey(key, False) + finally: + key.Close() + except EnvironmentError: # pragma: no cover + break + finally: + interfaces.Close() + finally: + lm.Close() + + def _win32_is_nic_enabled(self, lm, guid, _): + # Look in the Windows Registry to determine whether the network + # interface corresponding to the given guid is enabled. + # + # (Code contributed by Paul Marks, thanks!) + # + try: + # This hard-coded location seems to be consistent, at least + # from Windows 2000 through Vista. + connection_key = winreg.OpenKey( + lm, + r'SYSTEM\CurrentControlSet\Control\Network' + r'\{4D36E972-E325-11CE-BFC1-08002BE10318}' + r'\%s\Connection' % guid) + + try: + # The PnpInstanceID points to a key inside Enum + (pnp_id, ttype) = winreg.QueryValueEx( + connection_key, 'PnpInstanceID') + + if ttype != winreg.REG_SZ: + raise ValueError # pragma: no cover + + device_key = winreg.OpenKey( + lm, r'SYSTEM\CurrentControlSet\Enum\%s' % pnp_id) + + try: + # Get ConfigFlags for this device + (flags, ttype) = winreg.QueryValueEx( + device_key, 'ConfigFlags') + + if ttype != winreg.REG_DWORD: + raise ValueError # pragma: no cover + + # Based on experimentation, bit 0x1 indicates that the + # device is disabled. + return not flags & 0x1 + + finally: + device_key.Close() + finally: + connection_key.Close() + except Exception: # pragma: no cover + return False + + def _compute_timeout(self, start, lifetime=None): + lifetime = self.lifetime if lifetime is None else lifetime + now = time.time() + duration = now - start + if duration < 0: + if duration < -1: + # Time going backwards is bad. Just give up. + raise Timeout(timeout=duration) + else: + # Time went backwards, but only a little. This can + # happen, e.g. under vmware with older linux kernels. + # Pretend it didn't happen. + now = start + if duration >= lifetime: + raise Timeout(timeout=duration) + return min(lifetime - duration, self.timeout) + + def _get_qnames_to_try(self, qname, search): + # This is a separate method so we can unit test the search + # rules without requiring the Internet. + if search is None: + search = self.use_search_by_default + qnames_to_try = [] + if qname.is_absolute(): + qnames_to_try.append(qname) + else: + abs_qname = qname.concatenate(dns.name.root) + if search: + if len(self.search) > 0: + # There is a search list, so use it exclusively + search_list = self.search[:] + elif self.domain != dns.name.root and self.domain is not None: + # We have some notion of a domain that isn't the root, so + # use it as the search list. + search_list = [self.domain] + else: + search_list = [] + # Figure out the effective ndots (default is 1) + if self.ndots is None: + ndots = 1 + else: + ndots = self.ndots + for suffix in search_list: + qnames_to_try.append(qname + suffix) + if len(qname) > ndots: + # The name has at least ndots dots, so we should try an + # absolute query first. + qnames_to_try.insert(0, abs_qname) + else: + # The name has less than ndots dots, so we should search + # first, then try the absolute name. + qnames_to_try.append(abs_qname) + else: + qnames_to_try.append(abs_qname) + return qnames_to_try + + def use_tsig(self, keyring, keyname=None, + algorithm=dns.tsig.default_algorithm): + """Add a TSIG signature to each query. + + The parameters are passed to ``dns.message.Message.use_tsig()``; + see its documentation for details. + """ + + self.keyring = keyring + self.keyname = keyname + self.keyalgorithm = algorithm + + def use_edns(self, edns=0, ednsflags=0, + payload=dns.message.DEFAULT_EDNS_PAYLOAD): + """Configure EDNS behavior. + + *edns*, an ``int``, is the EDNS level to use. Specifying + ``None``, ``False``, or ``-1`` means "do not use EDNS", and in this case + the other parameters are ignored. Specifying ``True`` is + equivalent to specifying 0, i.e. "use EDNS0". + + *ednsflags*, an ``int``, the EDNS flag values. + + *payload*, an ``int``, is the EDNS sender's payload field, which is the + maximum size of UDP datagram the sender can handle. I.e. how big + a response to this message can be. + """ + + if edns is None or edns is False: + edns = -1 + elif edns is True: + edns = 0 + self.edns = edns + self.ednsflags = ednsflags + self.payload = payload + + def set_flags(self, flags): + """Overrides the default flags with your own. + + *flags*, an ``int``, the message flags to use. + """ + + self.flags = flags + + @property + def nameservers(self): + return self._nameservers + + @nameservers.setter + def nameservers(self, nameservers): + """ + *nameservers*, a ``list`` of nameservers. + + Raises ``ValueError`` if *nameservers* is anything other than a + ``list``. + """ + if isinstance(nameservers, list): + self._nameservers = nameservers + else: + raise ValueError('nameservers must be a list' + ' (not a {})'.format(type(nameservers))) + + +class Resolver(BaseResolver): + """DNS stub resolver.""" + + def resolve(self, qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN, + tcp=False, source=None, raise_on_no_answer=True, source_port=0, + lifetime=None, search=None): # pylint: disable=arguments-differ + """Query nameservers to find the answer to the question. + + The *qname*, *rdtype*, and *rdclass* parameters may be objects + of the appropriate type, or strings that can be converted into objects + of the appropriate type. + + *qname*, a ``dns.name.Name`` or ``str``, the query name. + + *rdtype*, an ``int`` or ``str``, the query type. + + *rdclass*, an ``int`` or ``str``, the query class. + + *tcp*, a ``bool``. If ``True``, use TCP to make the query. + + *source*, a ``str`` or ``None``. If not ``None``, bind to this IP + address when making queries. + + *raise_on_no_answer*, a ``bool``. If ``True``, raise + ``dns.resolver.NoAnswer`` if there's no answer to the question. + + *source_port*, an ``int``, the port from which to send the message. + + *lifetime*, a ``float``, how many seconds a query should run + before timing out. + + *search*, a ``bool`` or ``None``, determines whether the + search list configured in the system's resolver configuration + are used for relative names, and whether the resolver's domain + may be added to relative names. The default is ``None``, + which causes the value of the resolver's + ``use_search_by_default`` attribute to be used. + + Raises ``dns.exception.Timeout`` if no answers could be found + in the specified lifetime. + + Raises ``dns.resolver.NXDOMAIN`` if the query name does not exist. + + Raises ``dns.resolver.YXDOMAIN`` if the query name is too long after + DNAME substitution. + + Raises ``dns.resolver.NoAnswer`` if *raise_on_no_answer* is + ``True`` and the query name exists but has no RRset of the + desired type and class. + + Raises ``dns.resolver.NoNameservers`` if no non-broken + nameservers are available to answer the question. + + Returns a ``dns.resolver.Answer`` instance. + + """ + + resolution = _Resolution(self, qname, rdtype, rdclass, tcp, + raise_on_no_answer, search) + start = time.time() + while True: + (request, answer) = resolution.next_request() + # Note we need to say "if answer is not None" and not just + # "if answer" because answer implements __len__, and python + # will call that. We want to return if we have an answer + # object, including in cases where its length is 0. + if answer is not None: + # cache hit! + return answer + done = False + while not done: + (nameserver, port, tcp, backoff) = resolution.next_nameserver() + if backoff: + time.sleep(backoff) + timeout = self._compute_timeout(start, lifetime) + try: + if dns.inet.is_address(nameserver): + if tcp: + response = dns.query.tcp(request, nameserver, + timeout=timeout, + port=port, + source=source, + source_port=source_port) + else: + response = dns.query.udp(request, + nameserver, + timeout=timeout, + port=port, + source=source, + source_port=source_port, + raise_on_truncation=True) + else: + protocol = urlparse(nameserver).scheme + if protocol != 'https': + raise NotImplementedError + response = dns.query.https(request, nameserver, + timeout=timeout) + except Exception as ex: + (_, done) = resolution.query_result(None, ex) + continue + (answer, done) = resolution.query_result(response, None) + # Note we need to say "if answer is not None" and not just + # "if answer" because answer implements __len__, and python + # will call that. We want to return if we have an answer + # object, including in cases where its length is 0. + if answer is not None: + return answer + + def query(self, qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN, + tcp=False, source=None, raise_on_no_answer=True, source_port=0, + lifetime=None): # pragma: no cover + """Query nameservers to find the answer to the question. + + This method calls resolve() with ``search=True``, and is + provided for backwards compatbility with prior versions of + dnspython. See the documentation for the resolve() method for + further details. + """ + warnings.warn('please use dns.resolver.Resolver.resolve() instead', + DeprecationWarning, stacklevel=2) + return self.resolve(qname, rdtype, rdclass, tcp, source, + raise_on_no_answer, source_port, lifetime, + True) + + def resolve_address(self, ipaddr, *args, **kwargs): + """Use a resolver to run a reverse query for PTR records. + + This utilizes the resolve() method to perform a PTR lookup on the + specified IP address. + + *ipaddr*, a ``str``, the IPv4 or IPv6 address you want to get + the PTR record for. + + All other arguments that can be passed to the resolve() function + except for rdtype and rdclass are also supported by this + function. + """ + + return self.resolve(dns.reversename.from_address(ipaddr), + rdtype=dns.rdatatype.PTR, + rdclass=dns.rdataclass.IN, + *args, **kwargs) + + # pylint: disable=redefined-outer-name + + def canonical_name(self, name): + """Determine the canonical name of *name*. + + The canonical name is the name the resolver uses for queries + after all CNAME and DNAME renamings have been applied. + + *name*, a ``dns.name.Name`` or ``str``, the query name. + + This method can raise any exception that ``resolve()`` can + raise, other than ``dns.resolver.NoAnswer`` and + ``dns.resolver.NXDOMAIN``. + + Returns a ``dns.name.Name``. + """ + try: + answer = self.resolve(name, raise_on_no_answer=False) + canonical_name = answer.canonical_name + except dns.resolver.NXDOMAIN as e: + canonical_name = e.canonical_name + return canonical_name + + # pylint: enable=redefined-outer-name + + +#: The default resolver. +default_resolver = None + + +def get_default_resolver(): + """Get the default resolver, initializing it if necessary.""" + if default_resolver is None: + reset_default_resolver() + return default_resolver + + +def reset_default_resolver(): + """Re-initialize default resolver. + + Note that the resolver configuration (i.e. /etc/resolv.conf on UNIX + systems) will be re-read immediately. + """ + + global default_resolver + default_resolver = Resolver() + + +def resolve(qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN, + tcp=False, source=None, raise_on_no_answer=True, + source_port=0, lifetime=None, search=None): + """Query nameservers to find the answer to the question. + + This is a convenience function that uses the default resolver + object to make the query. + + See ``dns.resolver.Resolver.resolve`` for more information on the + parameters. + """ + + return get_default_resolver().resolve(qname, rdtype, rdclass, tcp, source, + raise_on_no_answer, source_port, + lifetime, search) + +def query(qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN, + tcp=False, source=None, raise_on_no_answer=True, + source_port=0, lifetime=None): # pragma: no cover + """Query nameservers to find the answer to the question. + + This method calls resolve() with ``search=True``, and is + provided for backwards compatbility with prior versions of + dnspython. See the documentation for the resolve() method for + further details. + """ + warnings.warn('please use dns.resolver.resolve() instead', + DeprecationWarning, stacklevel=2) + return resolve(qname, rdtype, rdclass, tcp, source, + raise_on_no_answer, source_port, lifetime, + True) + + +def resolve_address(ipaddr, *args, **kwargs): + """Use a resolver to run a reverse query for PTR records. + + See ``dns.resolver.Resolver.resolve_address`` for more information on the + parameters. + """ + + return get_default_resolver().resolve_address(ipaddr, *args, **kwargs) + + +def canonical_name(name): + """Determine the canonical name of *name*. + + See ``dns.resolver.Resolver.canonical_name`` for more information on the + parameters and possible exceptions. + """ + + return get_default_resolver().canonical_name(name) + + +def zone_for_name(name, rdclass=dns.rdataclass.IN, tcp=False, resolver=None): + """Find the name of the zone which contains the specified name. + + *name*, an absolute ``dns.name.Name`` or ``str``, the query name. + + *rdclass*, an ``int``, the query class. + + *tcp*, a ``bool``. If ``True``, use TCP to make the query. + + *resolver*, a ``dns.resolver.Resolver`` or ``None``, the resolver to use. + If ``None``, the default resolver is used. + + Raises ``dns.resolver.NoRootSOA`` if there is no SOA RR at the DNS + root. (This is only likely to happen if you're using non-default + root servers in your network and they are misconfigured.) + + Returns a ``dns.name.Name``. + """ + + if isinstance(name, str): + name = dns.name.from_text(name, dns.name.root) + if resolver is None: + resolver = get_default_resolver() + if not name.is_absolute(): + raise NotAbsolute(name) + while 1: + try: + answer = resolver.resolve(name, dns.rdatatype.SOA, rdclass, tcp) + if answer.rrset.name == name: + return name + # otherwise we were CNAMEd or DNAMEd and need to look higher + except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer): + pass + try: + name = name.parent() + except dns.name.NoParent: + raise NoRootSOA + +# +# Support for overriding the system resolver for all python code in the +# running process. +# + +_protocols_for_socktype = { + socket.SOCK_DGRAM: [socket.SOL_UDP], + socket.SOCK_STREAM: [socket.SOL_TCP], +} + +_resolver = None +_original_getaddrinfo = socket.getaddrinfo +_original_getnameinfo = socket.getnameinfo +_original_getfqdn = socket.getfqdn +_original_gethostbyname = socket.gethostbyname +_original_gethostbyname_ex = socket.gethostbyname_ex +_original_gethostbyaddr = socket.gethostbyaddr + + +def _getaddrinfo(host=None, service=None, family=socket.AF_UNSPEC, socktype=0, + proto=0, flags=0): + if flags & socket.AI_NUMERICHOST != 0: + # Short circuit directly into the system's getaddrinfo(). We're + # not adding any value in this case, and this avoids infinite loops + # because dns.query.* needs to call getaddrinfo() for IPv6 scoping + # reasons. We will also do this short circuit below if we + # discover that the host is an address literal. + return _original_getaddrinfo(host, service, family, socktype, proto, + flags) + if flags & (socket.AI_ADDRCONFIG | socket.AI_V4MAPPED) != 0: + # Not implemented. We raise a gaierror as opposed to a + # NotImplementedError as it helps callers handle errors more + # appropriately. [Issue #316] + # + # We raise EAI_FAIL as opposed to EAI_SYSTEM because there is + # no EAI_SYSTEM on Windows [Issue #416]. We didn't go for + # EAI_BADFLAGS as the flags aren't bad, we just don't + # implement them. + raise socket.gaierror(socket.EAI_FAIL, + 'Non-recoverable failure in name resolution') + if host is None and service is None: + raise socket.gaierror(socket.EAI_NONAME, 'Name or service not known') + v6addrs = [] + v4addrs = [] + canonical_name = None # pylint: disable=redefined-outer-name + # Is host None or an address literal? If so, use the system's + # getaddrinfo(). + if host is None: + return _original_getaddrinfo(host, service, family, socktype, + proto, flags) + try: + # We don't care about the result of af_for_address(), we're just + # calling it so it raises an exception if host is not an IPv4 or + # IPv6 address. + dns.inet.af_for_address(host) + return _original_getaddrinfo(host, service, family, socktype, + proto, flags) + except Exception: + pass + # Something needs resolution! + try: + if family == socket.AF_INET6 or family == socket.AF_UNSPEC: + v6 = _resolver.resolve(host, dns.rdatatype.AAAA, + raise_on_no_answer=False) + # Note that setting host ensures we query the same name + # for A as we did for AAAA. + host = v6.qname + canonical_name = v6.canonical_name.to_text(True) + if v6.rrset is not None: + for rdata in v6.rrset: + v6addrs.append(rdata.address) + if family == socket.AF_INET or family == socket.AF_UNSPEC: + v4 = _resolver.resolve(host, dns.rdatatype.A, + raise_on_no_answer=False) + host = v4.qname + canonical_name = v4.canonical_name.to_text(True) + if v4.rrset is not None: + for rdata in v4.rrset: + v4addrs.append(rdata.address) + except dns.resolver.NXDOMAIN: + raise socket.gaierror(socket.EAI_NONAME, 'Name or service not known') + except Exception: + # We raise EAI_AGAIN here as the failure may be temporary + # (e.g. a timeout) and EAI_SYSTEM isn't defined on Windows. + # [Issue #416] + raise socket.gaierror(socket.EAI_AGAIN, + 'Temporary failure in name resolution') + port = None + try: + # Is it a port literal? + if service is None: + port = 0 + else: + port = int(service) + except Exception: + if flags & socket.AI_NUMERICSERV == 0: + try: + port = socket.getservbyname(service) + except Exception: + pass + if port is None: + raise socket.gaierror(socket.EAI_NONAME, 'Name or service not known') + tuples = [] + if socktype == 0: + socktypes = [socket.SOCK_DGRAM, socket.SOCK_STREAM] + else: + socktypes = [socktype] + if flags & socket.AI_CANONNAME != 0: + cname = canonical_name + else: + cname = '' + if family == socket.AF_INET6 or family == socket.AF_UNSPEC: + for addr in v6addrs: + for socktype in socktypes: + for proto in _protocols_for_socktype[socktype]: + tuples.append((socket.AF_INET6, socktype, proto, + cname, (addr, port, 0, 0))) + if family == socket.AF_INET or family == socket.AF_UNSPEC: + for addr in v4addrs: + for socktype in socktypes: + for proto in _protocols_for_socktype[socktype]: + tuples.append((socket.AF_INET, socktype, proto, + cname, (addr, port))) + if len(tuples) == 0: + raise socket.gaierror(socket.EAI_NONAME, 'Name or service not known') + return tuples + + +def _getnameinfo(sockaddr, flags=0): + host = sockaddr[0] + port = sockaddr[1] + if len(sockaddr) == 4: + scope = sockaddr[3] + family = socket.AF_INET6 + else: + scope = None + family = socket.AF_INET + tuples = _getaddrinfo(host, port, family, socket.SOCK_STREAM, + socket.SOL_TCP, 0) + if len(tuples) > 1: + raise socket.error('sockaddr resolved to multiple addresses') + addr = tuples[0][4][0] + if flags & socket.NI_DGRAM: + pname = 'udp' + else: + pname = 'tcp' + qname = dns.reversename.from_address(addr) + if flags & socket.NI_NUMERICHOST == 0: + try: + answer = _resolver.resolve(qname, 'PTR') + hostname = answer.rrset[0].target.to_text(True) + except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer): + if flags & socket.NI_NAMEREQD: + raise socket.gaierror(socket.EAI_NONAME, + 'Name or service not known') + hostname = addr + if scope is not None: + hostname += '%' + str(scope) + else: + hostname = addr + if scope is not None: + hostname += '%' + str(scope) + if flags & socket.NI_NUMERICSERV: + service = str(port) + else: + service = socket.getservbyport(port, pname) + return (hostname, service) + + +def _getfqdn(name=None): + if name is None: + name = socket.gethostname() + try: + (name, _, _) = _gethostbyaddr(name) + # Python's version checks aliases too, but our gethostbyname + # ignores them, so we do so here as well. + except Exception: + pass + return name + + +def _gethostbyname(name): + return _gethostbyname_ex(name)[2][0] + + +def _gethostbyname_ex(name): + aliases = [] + addresses = [] + tuples = _getaddrinfo(name, 0, socket.AF_INET, socket.SOCK_STREAM, + socket.SOL_TCP, socket.AI_CANONNAME) + canonical = tuples[0][3] + for item in tuples: + addresses.append(item[4][0]) + # XXX we just ignore aliases + return (canonical, aliases, addresses) + + +def _gethostbyaddr(ip): + try: + dns.ipv6.inet_aton(ip) + sockaddr = (ip, 80, 0, 0) + family = socket.AF_INET6 + except Exception: + try: + dns.ipv4.inet_aton(ip) + except Exception: + raise socket.gaierror(socket.EAI_NONAME, + 'Name or service not known') + sockaddr = (ip, 80) + family = socket.AF_INET + (name, _) = _getnameinfo(sockaddr, socket.NI_NAMEREQD) + aliases = [] + addresses = [] + tuples = _getaddrinfo(name, 0, family, socket.SOCK_STREAM, socket.SOL_TCP, + socket.AI_CANONNAME) + canonical = tuples[0][3] + # We only want to include an address from the tuples if it's the + # same as the one we asked about. We do this comparison in binary + # to avoid any differences in text representations. + bin_ip = dns.inet.inet_pton(family, ip) + for item in tuples: + addr = item[4][0] + bin_addr = dns.inet.inet_pton(family, addr) + if bin_ip == bin_addr: + addresses.append(addr) + # XXX we just ignore aliases + return (canonical, aliases, addresses) + + +def override_system_resolver(resolver=None): + """Override the system resolver routines in the socket module with + versions which use dnspython's resolver. + + This can be useful in testing situations where you want to control + the resolution behavior of python code without having to change + the system's resolver settings (e.g. /etc/resolv.conf). + + The resolver to use may be specified; if it's not, the default + resolver will be used. + + resolver, a ``dns.resolver.Resolver`` or ``None``, the resolver to use. + """ + + if resolver is None: + resolver = get_default_resolver() + global _resolver + _resolver = resolver + socket.getaddrinfo = _getaddrinfo + socket.getnameinfo = _getnameinfo + socket.getfqdn = _getfqdn + socket.gethostbyname = _gethostbyname + socket.gethostbyname_ex = _gethostbyname_ex + socket.gethostbyaddr = _gethostbyaddr + + +def restore_system_resolver(): + """Undo the effects of prior override_system_resolver().""" + + global _resolver + _resolver = None + socket.getaddrinfo = _original_getaddrinfo + socket.getnameinfo = _original_getnameinfo + socket.getfqdn = _original_getfqdn + socket.gethostbyname = _original_gethostbyname + socket.gethostbyname_ex = _original_gethostbyname_ex + socket.gethostbyaddr = _original_gethostbyaddr diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/reversename.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/reversename.py new file mode 100644 index 0000000..e0beb03 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/reversename.py @@ -0,0 +1,100 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Reverse Map Names.""" + +import binascii + +import dns.name +import dns.ipv6 +import dns.ipv4 + +ipv4_reverse_domain = dns.name.from_text('in-addr.arpa.') +ipv6_reverse_domain = dns.name.from_text('ip6.arpa.') + + +def from_address(text, v4_origin=ipv4_reverse_domain, + v6_origin=ipv6_reverse_domain): + """Convert an IPv4 or IPv6 address in textual form into a Name object whose + value is the reverse-map domain name of the address. + + *text*, a ``str``, is an IPv4 or IPv6 address in textual form + (e.g. '127.0.0.1', '::1') + + *v4_origin*, a ``dns.name.Name`` to append to the labels corresponding to + the address if the address is an IPv4 address, instead of the default + (in-addr.arpa.) + + *v6_origin*, a ``dns.name.Name`` to append to the labels corresponding to + the address if the address is an IPv6 address, instead of the default + (ip6.arpa.) + + Raises ``dns.exception.SyntaxError`` if the address is badly formed. + + Returns a ``dns.name.Name``. + """ + + try: + v6 = dns.ipv6.inet_aton(text) + if dns.ipv6.is_mapped(v6): + parts = ['%d' % byte for byte in v6[12:]] + origin = v4_origin + else: + parts = [x for x in str(binascii.hexlify(v6).decode())] + origin = v6_origin + except Exception: + parts = ['%d' % + byte for byte in dns.ipv4.inet_aton(text)] + origin = v4_origin + return dns.name.from_text('.'.join(reversed(parts)), origin=origin) + + +def to_address(name, v4_origin=ipv4_reverse_domain, + v6_origin=ipv6_reverse_domain): + """Convert a reverse map domain name into textual address form. + + *name*, a ``dns.name.Name``, an IPv4 or IPv6 address in reverse-map name + form. + + *v4_origin*, a ``dns.name.Name`` representing the top-level domain for + IPv4 addresses, instead of the default (in-addr.arpa.) + + *v6_origin*, a ``dns.name.Name`` representing the top-level domain for + IPv4 addresses, instead of the default (ip6.arpa.) + + Raises ``dns.exception.SyntaxError`` if the name does not have a + reverse-map form. + + Returns a ``str``. + """ + + if name.is_subdomain(v4_origin): + name = name.relativize(v4_origin) + text = b'.'.join(reversed(name.labels)) + # run through inet_ntoa() to check syntax and make pretty. + return dns.ipv4.inet_ntoa(dns.ipv4.inet_aton(text)) + elif name.is_subdomain(v6_origin): + name = name.relativize(v6_origin) + labels = list(reversed(name.labels)) + parts = [] + for i in range(0, len(labels), 4): + parts.append(b''.join(labels[i:i + 4])) + text = b':'.join(parts) + # run through inet_ntoa() to check syntax and make pretty. + return dns.ipv6.inet_ntoa(dns.ipv6.inet_aton(text)) + else: + raise dns.exception.SyntaxError('unknown reverse-map address family') diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rrset.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rrset.py new file mode 100644 index 0000000..a71d457 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/rrset.py @@ -0,0 +1,229 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS RRsets (an RRset is a named rdataset)""" + + +import dns.name +import dns.rdataset +import dns.rdataclass +import dns.renderer + + +class RRset(dns.rdataset.Rdataset): + + """A DNS RRset (named rdataset). + + RRset inherits from Rdataset, and RRsets can be treated as + Rdatasets in most cases. There are, however, a few notable + exceptions. RRsets have different to_wire() and to_text() method + arguments, reflecting the fact that RRsets always have an owner + name. + """ + + __slots__ = ['name', 'deleting'] + + def __init__(self, name, rdclass, rdtype, covers=dns.rdatatype.NONE, + deleting=None): + """Create a new RRset.""" + + super().__init__(rdclass, rdtype, covers) + self.name = name + self.deleting = deleting + + def _clone(self): + obj = super()._clone() + obj.name = self.name + obj.deleting = self.deleting + return obj + + def __repr__(self): + if self.covers == 0: + ctext = '' + else: + ctext = '(' + dns.rdatatype.to_text(self.covers) + ')' + if self.deleting is not None: + dtext = ' delete=' + dns.rdataclass.to_text(self.deleting) + else: + dtext = '' + return '' + + def __str__(self): + return self.to_text() + + def __eq__(self, other): + if isinstance(other, RRset): + if self.name != other.name: + return False + elif not isinstance(other, dns.rdataset.Rdataset): + return False + return super().__eq__(other) + + def match(self, *args, **kwargs): + """Does this rrset match the specified attributes? + + Behaves as :py:func:`full_match()` if the first argument is a + ``dns.name.Name``, and as :py:func:`dns.rdataset.Rdataset.match()` + otherwise. + + (This behavior fixes a design mistake where the signature of this + method became incompatible with that of its superclass. The fix + makes RRsets matchable as Rdatasets while preserving backwards + compatibility.) + """ + if isinstance(args[0], dns.name.Name): + return self.full_match(*args, **kwargs) + else: + return super().match(*args, **kwargs) + + def full_match(self, name, rdclass, rdtype, covers, + deleting=None): + """Returns ``True`` if this rrset matches the specified name, class, + type, covers, and deletion state. + """ + if not super().match(rdclass, rdtype, covers): + return False + if self.name != name or self.deleting != deleting: + return False + return True + + # pylint: disable=arguments-differ + + def to_text(self, origin=None, relativize=True, **kw): + """Convert the RRset into DNS zone file format. + + See ``dns.name.Name.choose_relativity`` for more information + on how *origin* and *relativize* determine the way names + are emitted. + + Any additional keyword arguments are passed on to the rdata + ``to_text()`` method. + + *origin*, a ``dns.name.Name`` or ``None``, the origin for relative + names. + + *relativize*, a ``bool``. If ``True``, names will be relativized + to *origin*. + """ + + return super().to_text(self.name, origin, relativize, + self.deleting, **kw) + + def to_wire(self, file, compress=None, origin=None, + **kw): + """Convert the RRset to wire format. + + All keyword arguments are passed to ``dns.rdataset.to_wire()``; see + that function for details. + + Returns an ``int``, the number of records emitted. + """ + + return super().to_wire(self.name, file, compress, origin, + self.deleting, **kw) + + # pylint: enable=arguments-differ + + def to_rdataset(self): + """Convert an RRset into an Rdataset. + + Returns a ``dns.rdataset.Rdataset``. + """ + return dns.rdataset.from_rdata_list(self.ttl, list(self)) + + +def from_text_list(name, ttl, rdclass, rdtype, text_rdatas, + idna_codec=None, origin=None, relativize=True, + relativize_to=None): + """Create an RRset with the specified name, TTL, class, and type, and with + the specified list of rdatas in text format. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder to use; if ``None``, the default IDNA 2003 + encoder/decoder is used. + + *origin*, a ``dns.name.Name`` (or ``None``), the + origin to use for relative names. + + *relativize*, a ``bool``. If true, name will be relativized. + + *relativize_to*, a ``dns.name.Name`` (or ``None``), the origin to use + when relativizing names. If not set, the *origin* value will be used. + + Returns a ``dns.rrset.RRset`` object. + """ + + if isinstance(name, str): + name = dns.name.from_text(name, None, idna_codec=idna_codec) + rdclass = dns.rdataclass.RdataClass.make(rdclass) + rdtype = dns.rdatatype.RdataType.make(rdtype) + r = RRset(name, rdclass, rdtype) + r.update_ttl(ttl) + for t in text_rdatas: + rd = dns.rdata.from_text(r.rdclass, r.rdtype, t, origin, relativize, + relativize_to, idna_codec) + r.add(rd) + return r + + +def from_text(name, ttl, rdclass, rdtype, *text_rdatas): + """Create an RRset with the specified name, TTL, class, and type and with + the specified rdatas in text format. + + Returns a ``dns.rrset.RRset`` object. + """ + + return from_text_list(name, ttl, rdclass, rdtype, text_rdatas) + + +def from_rdata_list(name, ttl, rdatas, idna_codec=None): + """Create an RRset with the specified name and TTL, and with + the specified list of rdata objects. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder to use; if ``None``, the default IDNA 2003 + encoder/decoder is used. + + Returns a ``dns.rrset.RRset`` object. + + """ + + if isinstance(name, str): + name = dns.name.from_text(name, None, idna_codec=idna_codec) + + if len(rdatas) == 0: + raise ValueError("rdata list must not be empty") + r = None + for rd in rdatas: + if r is None: + r = RRset(name, rd.rdclass, rd.rdtype) + r.update_ttl(ttl) + r.add(rd) + return r + + +def from_rdata(name, ttl, *rdatas): + """Create an RRset with the specified name and TTL, and with + the specified rdata objects. + + Returns a ``dns.rrset.RRset`` object. + """ + + return from_rdata_list(name, ttl, rdatas) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/serial.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/serial.py new file mode 100644 index 0000000..b047415 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/serial.py @@ -0,0 +1,117 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +"""Serial Number Arthimetic from RFC 1982""" + +class Serial: + def __init__(self, value, bits=32): + self.value = value % 2 ** bits + self.bits = bits + + def __repr__(self): + return f'dns.serial.Serial({self.value}, {self.bits})' + + def __eq__(self, other): + if isinstance(other, int): + other = Serial(other, self.bits) + elif not isinstance(other, Serial) or other.bits != self.bits: + return NotImplemented + return self.value == other.value + + def __ne__(self, other): + if isinstance(other, int): + other = Serial(other, self.bits) + elif not isinstance(other, Serial) or other.bits != self.bits: + return NotImplemented + return self.value != other.value + + def __lt__(self, other): + if isinstance(other, int): + other = Serial(other, self.bits) + elif not isinstance(other, Serial) or other.bits != self.bits: + return NotImplemented + if self.value < other.value and \ + other.value - self.value < 2 ** (self.bits - 1): + return True + elif self.value > other.value and \ + self.value - other.value > 2 ** (self.bits - 1): + return True + else: + return False + + def __le__(self, other): + return self == other or self < other + + def __gt__(self, other): + if isinstance(other, int): + other = Serial(other, self.bits) + elif not isinstance(other, Serial) or other.bits != self.bits: + return NotImplemented + if self.value < other.value and \ + other.value - self.value > 2 ** (self.bits - 1): + return True + elif self.value > other.value and \ + self.value - other.value < 2 ** (self.bits - 1): + return True + else: + return False + + def __ge__(self, other): + return self == other or self > other + + def __add__(self, other): + v = self.value + if isinstance(other, Serial): + delta = other.value + elif isinstance(other, int): + delta = other + else: + raise ValueError + if abs(delta) > (2 ** (self.bits - 1) - 1): + raise ValueError + v += delta + v = v % 2 ** self.bits + return Serial(v, self.bits) + + def __iadd__(self, other): + v = self.value + if isinstance(other, Serial): + delta = other.value + elif isinstance(other, int): + delta = other + else: + raise ValueError + if abs(delta) > (2 ** (self.bits - 1) - 1): + raise ValueError + v += delta + v = v % 2 ** self.bits + self.value = v + return self + + def __sub__(self, other): + v = self.value + if isinstance(other, Serial): + delta = other.value + elif isinstance(other, int): + delta = other + else: + raise ValueError + if abs(delta) > (2 ** (self.bits - 1) - 1): + raise ValueError + v -= delta + v = v % 2 ** self.bits + return Serial(v, self.bits) + + def __isub__(self, other): + v = self.value + if isinstance(other, Serial): + delta = other.value + elif isinstance(other, int): + delta = other + else: + raise ValueError + if abs(delta) > (2 ** (self.bits - 1) - 1): + raise ValueError + v -= delta + v = v % 2 ** self.bits + self.value = v + return self diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/set.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/set.py new file mode 100644 index 0000000..1fd4d0a --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/set.py @@ -0,0 +1,278 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import itertools +import sys + +if sys.version_info >= (3, 7): + odict = dict +else: + from collections import OrderedDict as odict # pragma: no cover + +class Set: + + """A simple set class. + + This class was originally used to deal with sets being missing in + ancient versions of python, but dnspython will continue to use it + as these sets are based on lists and are thus indexable, and this + ability is widely used in dnspython applications. + """ + + __slots__ = ['items'] + + def __init__(self, items=None): + """Initialize the set. + + *items*, an iterable or ``None``, the initial set of items. + """ + + self.items = odict() + if items is not None: + for item in items: + self.add(item) + + def __repr__(self): + return "dns.set.Set(%s)" % repr(list(self.items.keys())) + + def add(self, item): + """Add an item to the set. + """ + + if item not in self.items: + self.items[item] = None + + def remove(self, item): + """Remove an item from the set. + """ + + try: + del self.items[item] + except KeyError: + raise ValueError + + def discard(self, item): + """Remove an item from the set if present. + """ + + self.items.pop(item, None) + + def _clone(self): + """Make a (shallow) copy of the set. + + There is a 'clone protocol' that subclasses of this class + should use. To make a copy, first call your super's _clone() + method, and use the object returned as the new instance. Then + make shallow copies of the attributes defined in the subclass. + + This protocol allows us to write the set algorithms that + return new instances (e.g. union) once, and keep using them in + subclasses. + """ + + if hasattr(self, '_clone_class'): + cls = self._clone_class + else: + cls = self.__class__ + obj = cls.__new__(cls) + obj.items = odict() + obj.items.update(self.items) + return obj + + def __copy__(self): + """Make a (shallow) copy of the set. + """ + + return self._clone() + + def copy(self): + """Make a (shallow) copy of the set. + """ + + return self._clone() + + def union_update(self, other): + """Update the set, adding any elements from other which are not + already in the set. + """ + + if not isinstance(other, Set): + raise ValueError('other must be a Set instance') + if self is other: + return + for item in other.items: + self.add(item) + + def intersection_update(self, other): + """Update the set, removing any elements from other which are not + in both sets. + """ + + if not isinstance(other, Set): + raise ValueError('other must be a Set instance') + if self is other: + return + # we make a copy of the list so that we can remove items from + # the list without breaking the iterator. + for item in list(self.items): + if item not in other.items: + del self.items[item] + + def difference_update(self, other): + """Update the set, removing any elements from other which are in + the set. + """ + + if not isinstance(other, Set): + raise ValueError('other must be a Set instance') + if self is other: + self.items.clear() + else: + for item in other.items: + self.discard(item) + + def union(self, other): + """Return a new set which is the union of ``self`` and ``other``. + + Returns the same Set type as this set. + """ + + obj = self._clone() + obj.union_update(other) + return obj + + def intersection(self, other): + """Return a new set which is the intersection of ``self`` and + ``other``. + + Returns the same Set type as this set. + """ + + obj = self._clone() + obj.intersection_update(other) + return obj + + def difference(self, other): + """Return a new set which ``self`` - ``other``, i.e. the items + in ``self`` which are not also in ``other``. + + Returns the same Set type as this set. + """ + + obj = self._clone() + obj.difference_update(other) + return obj + + def __or__(self, other): + return self.union(other) + + def __and__(self, other): + return self.intersection(other) + + def __add__(self, other): + return self.union(other) + + def __sub__(self, other): + return self.difference(other) + + def __ior__(self, other): + self.union_update(other) + return self + + def __iand__(self, other): + self.intersection_update(other) + return self + + def __iadd__(self, other): + self.union_update(other) + return self + + def __isub__(self, other): + self.difference_update(other) + return self + + def update(self, other): + """Update the set, adding any elements from other which are not + already in the set. + + *other*, the collection of items with which to update the set, which + may be any iterable type. + """ + + for item in other: + self.add(item) + + def clear(self): + """Make the set empty.""" + self.items.clear() + + def __eq__(self, other): + if odict == dict: + return self.items == other.items + else: + # We don't want an ordered comparison. + if len(self.items) != len(other.items): + return False + return all(elt in other.items for elt in self.items) + + def __ne__(self, other): + return not self.__eq__(other) + + def __len__(self): + return len(self.items) + + def __iter__(self): + return iter(self.items) + + def __getitem__(self, i): + if isinstance(i, slice): + return list(itertools.islice(self.items, i.start, i.stop, i.step)) + else: + return next(itertools.islice(self.items, i, i + 1)) + + def __delitem__(self, i): + if isinstance(i, slice): + for elt in list(self[i]): + del self.items[elt] + else: + del self.items[self[i]] + + def issubset(self, other): + """Is this set a subset of *other*? + + Returns a ``bool``. + """ + + if not isinstance(other, Set): + raise ValueError('other must be a Set instance') + for item in self.items: + if item not in other.items: + return False + return True + + def issuperset(self, other): + """Is this set a superset of *other*? + + Returns a ``bool``. + """ + + if not isinstance(other, Set): + raise ValueError('other must be a Set instance') + for item in other.items: + if item not in self.items: + return False + return True diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/tokenizer.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/tokenizer.py new file mode 100644 index 0000000..7ddc7a9 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/tokenizer.py @@ -0,0 +1,675 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Tokenize DNS zone file format""" + +import io +import sys + +import dns.exception +import dns.name +import dns.ttl + +_DELIMITERS = {' ', '\t', '\n', ';', '(', ')', '"'} +_QUOTING_DELIMITERS = {'"'} + +EOF = 0 +EOL = 1 +WHITESPACE = 2 +IDENTIFIER = 3 +QUOTED_STRING = 4 +COMMENT = 5 +DELIMITER = 6 + + +class UngetBufferFull(dns.exception.DNSException): + """An attempt was made to unget a token when the unget buffer was full.""" + + +class Token: + """A DNS zone file format token. + + ttype: The token type + value: The token value + has_escape: Does the token value contain escapes? + """ + + def __init__(self, ttype, value='', has_escape=False, comment=None): + """Initialize a token instance.""" + + self.ttype = ttype + self.value = value + self.has_escape = has_escape + self.comment = comment + + def is_eof(self): + return self.ttype == EOF + + def is_eol(self): + return self.ttype == EOL + + def is_whitespace(self): + return self.ttype == WHITESPACE + + def is_identifier(self): + return self.ttype == IDENTIFIER + + def is_quoted_string(self): + return self.ttype == QUOTED_STRING + + def is_comment(self): + return self.ttype == COMMENT + + def is_delimiter(self): # pragma: no cover (we don't return delimiters yet) + return self.ttype == DELIMITER + + def is_eol_or_eof(self): + return self.ttype == EOL or self.ttype == EOF + + def __eq__(self, other): + if not isinstance(other, Token): + return False + return (self.ttype == other.ttype and + self.value == other.value) + + def __ne__(self, other): + if not isinstance(other, Token): + return True + return (self.ttype != other.ttype or + self.value != other.value) + + def __str__(self): + return '%d "%s"' % (self.ttype, self.value) + + def unescape(self): + if not self.has_escape: + return self + unescaped = '' + l = len(self.value) + i = 0 + while i < l: + c = self.value[i] + i += 1 + if c == '\\': + if i >= l: # pragma: no cover (can't happen via get()) + raise dns.exception.UnexpectedEnd + c = self.value[i] + i += 1 + if c.isdigit(): + if i >= l: + raise dns.exception.UnexpectedEnd + c2 = self.value[i] + i += 1 + if i >= l: + raise dns.exception.UnexpectedEnd + c3 = self.value[i] + i += 1 + if not (c2.isdigit() and c3.isdigit()): + raise dns.exception.SyntaxError + codepoint = int(c) * 100 + int(c2) * 10 + int(c3) + if codepoint > 255: + raise dns.exception.SyntaxError + c = chr(codepoint) + unescaped += c + return Token(self.ttype, unescaped) + + def unescape_to_bytes(self): + # We used to use unescape() for TXT-like records, but this + # caused problems as we'd process DNS escapes into Unicode code + # points instead of byte values, and then a to_text() of the + # processed data would not equal the original input. For + # example, \226 in the TXT record would have a to_text() of + # \195\162 because we applied UTF-8 encoding to Unicode code + # point 226. + # + # We now apply escapes while converting directly to bytes, + # avoiding this double encoding. + # + # This code also handles cases where the unicode input has + # non-ASCII code-points in it by converting it to UTF-8. TXT + # records aren't defined for Unicode, but this is the best we + # can do to preserve meaning. For example, + # + # foo\u200bbar + # + # (where \u200b is Unicode code point 0x200b) will be treated + # as if the input had been the UTF-8 encoding of that string, + # namely: + # + # foo\226\128\139bar + # + unescaped = b'' + l = len(self.value) + i = 0 + while i < l: + c = self.value[i] + i += 1 + if c == '\\': + if i >= l: # pragma: no cover (can't happen via get()) + raise dns.exception.UnexpectedEnd + c = self.value[i] + i += 1 + if c.isdigit(): + if i >= l: + raise dns.exception.UnexpectedEnd + c2 = self.value[i] + i += 1 + if i >= l: + raise dns.exception.UnexpectedEnd + c3 = self.value[i] + i += 1 + if not (c2.isdigit() and c3.isdigit()): + raise dns.exception.SyntaxError + codepoint = int(c) * 100 + int(c2) * 10 + int(c3) + if codepoint > 255: + raise dns.exception.SyntaxError + unescaped += b'%c' % (codepoint) + else: + # Note that as mentioned above, if c is a Unicode + # code point outside of the ASCII range, then this + # += is converting that code point to its UTF-8 + # encoding and appending multiple bytes to + # unescaped. + unescaped += c.encode() + else: + unescaped += c.encode() + return Token(self.ttype, bytes(unescaped)) + + +class Tokenizer: + """A DNS zone file format tokenizer. + + A token object is basically a (type, value) tuple. The valid + types are EOF, EOL, WHITESPACE, IDENTIFIER, QUOTED_STRING, + COMMENT, and DELIMITER. + + file: The file to tokenize + + ungotten_char: The most recently ungotten character, or None. + + ungotten_token: The most recently ungotten token, or None. + + multiline: The current multiline level. This value is increased + by one every time a '(' delimiter is read, and decreased by one every time + a ')' delimiter is read. + + quoting: This variable is true if the tokenizer is currently + reading a quoted string. + + eof: This variable is true if the tokenizer has encountered EOF. + + delimiters: The current delimiter dictionary. + + line_number: The current line number + + filename: A filename that will be returned by the where() method. + + idna_codec: A dns.name.IDNACodec, specifies the IDNA + encoder/decoder. If None, the default IDNA 2003 + encoder/decoder is used. + """ + + def __init__(self, f=sys.stdin, filename=None, idna_codec=None): + """Initialize a tokenizer instance. + + f: The file to tokenize. The default is sys.stdin. + This parameter may also be a string, in which case the tokenizer + will take its input from the contents of the string. + + filename: the name of the filename that the where() method + will return. + + idna_codec: A dns.name.IDNACodec, specifies the IDNA + encoder/decoder. If None, the default IDNA 2003 + encoder/decoder is used. + """ + + if isinstance(f, str): + f = io.StringIO(f) + if filename is None: + filename = '' + elif isinstance(f, bytes): + f = io.StringIO(f.decode()) + if filename is None: + filename = '' + else: + if filename is None: + if f is sys.stdin: + filename = '' + else: + filename = '' + self.file = f + self.ungotten_char = None + self.ungotten_token = None + self.multiline = 0 + self.quoting = False + self.eof = False + self.delimiters = _DELIMITERS + self.line_number = 1 + self.filename = filename + if idna_codec is None: + idna_codec = dns.name.IDNA_2003 + self.idna_codec = idna_codec + + def _get_char(self): + """Read a character from input. + """ + + if self.ungotten_char is None: + if self.eof: + c = '' + else: + c = self.file.read(1) + if c == '': + self.eof = True + elif c == '\n': + self.line_number += 1 + else: + c = self.ungotten_char + self.ungotten_char = None + return c + + def where(self): + """Return the current location in the input. + + Returns a (string, int) tuple. The first item is the filename of + the input, the second is the current line number. + """ + + return (self.filename, self.line_number) + + def _unget_char(self, c): + """Unget a character. + + The unget buffer for characters is only one character large; it is + an error to try to unget a character when the unget buffer is not + empty. + + c: the character to unget + raises UngetBufferFull: there is already an ungotten char + """ + + if self.ungotten_char is not None: + # this should never happen! + raise UngetBufferFull # pragma: no cover + self.ungotten_char = c + + def skip_whitespace(self): + """Consume input until a non-whitespace character is encountered. + + The non-whitespace character is then ungotten, and the number of + whitespace characters consumed is returned. + + If the tokenizer is in multiline mode, then newlines are whitespace. + + Returns the number of characters skipped. + """ + + skipped = 0 + while True: + c = self._get_char() + if c != ' ' and c != '\t': + if (c != '\n') or not self.multiline: + self._unget_char(c) + return skipped + skipped += 1 + + def get(self, want_leading=False, want_comment=False): + """Get the next token. + + want_leading: If True, return a WHITESPACE token if the + first character read is whitespace. The default is False. + + want_comment: If True, return a COMMENT token if the + first token read is a comment. The default is False. + + Raises dns.exception.UnexpectedEnd: input ended prematurely + + Raises dns.exception.SyntaxError: input was badly formed + + Returns a Token. + """ + + if self.ungotten_token is not None: + token = self.ungotten_token + self.ungotten_token = None + if token.is_whitespace(): + if want_leading: + return token + elif token.is_comment(): + if want_comment: + return token + else: + return token + skipped = self.skip_whitespace() + if want_leading and skipped > 0: + return Token(WHITESPACE, ' ') + token = '' + ttype = IDENTIFIER + has_escape = False + while True: + c = self._get_char() + if c == '' or c in self.delimiters: + if c == '' and self.quoting: + raise dns.exception.UnexpectedEnd + if token == '' and ttype != QUOTED_STRING: + if c == '(': + self.multiline += 1 + self.skip_whitespace() + continue + elif c == ')': + if self.multiline <= 0: + raise dns.exception.SyntaxError + self.multiline -= 1 + self.skip_whitespace() + continue + elif c == '"': + if not self.quoting: + self.quoting = True + self.delimiters = _QUOTING_DELIMITERS + ttype = QUOTED_STRING + continue + else: + self.quoting = False + self.delimiters = _DELIMITERS + self.skip_whitespace() + continue + elif c == '\n': + return Token(EOL, '\n') + elif c == ';': + while 1: + c = self._get_char() + if c == '\n' or c == '': + break + token += c + if want_comment: + self._unget_char(c) + return Token(COMMENT, token) + elif c == '': + if self.multiline: + raise dns.exception.SyntaxError( + 'unbalanced parentheses') + return Token(EOF, comment=token) + elif self.multiline: + self.skip_whitespace() + token = '' + continue + else: + return Token(EOL, '\n', comment=token) + else: + # This code exists in case we ever want a + # delimiter to be returned. It never produces + # a token currently. + token = c + ttype = DELIMITER + else: + self._unget_char(c) + break + elif self.quoting and c == '\n': + raise dns.exception.SyntaxError('newline in quoted string') + elif c == '\\': + # + # It's an escape. Put it and the next character into + # the token; it will be checked later for goodness. + # + token += c + has_escape = True + c = self._get_char() + if c == '' or (c == '\n' and not self.quoting): + raise dns.exception.UnexpectedEnd + token += c + if token == '' and ttype != QUOTED_STRING: + if self.multiline: + raise dns.exception.SyntaxError('unbalanced parentheses') + ttype = EOF + return Token(ttype, token, has_escape) + + def unget(self, token): + """Unget a token. + + The unget buffer for tokens is only one token large; it is + an error to try to unget a token when the unget buffer is not + empty. + + token: the token to unget + + Raises UngetBufferFull: there is already an ungotten token + """ + + if self.ungotten_token is not None: + raise UngetBufferFull + self.ungotten_token = token + + def next(self): + """Return the next item in an iteration. + + Returns a Token. + """ + + token = self.get() + if token.is_eof(): + raise StopIteration + return token + + __next__ = next + + def __iter__(self): + return self + + # Helpers + + def get_int(self, base=10): + """Read the next token and interpret it as an unsigned integer. + + Raises dns.exception.SyntaxError if not an unsigned integer. + + Returns an int. + """ + + token = self.get().unescape() + if not token.is_identifier(): + raise dns.exception.SyntaxError('expecting an identifier') + if not token.value.isdigit(): + raise dns.exception.SyntaxError('expecting an integer') + return int(token.value, base) + + def get_uint8(self): + """Read the next token and interpret it as an 8-bit unsigned + integer. + + Raises dns.exception.SyntaxError if not an 8-bit unsigned integer. + + Returns an int. + """ + + value = self.get_int() + if value < 0 or value > 255: + raise dns.exception.SyntaxError( + '%d is not an unsigned 8-bit integer' % value) + return value + + def get_uint16(self, base=10): + """Read the next token and interpret it as a 16-bit unsigned + integer. + + Raises dns.exception.SyntaxError if not a 16-bit unsigned integer. + + Returns an int. + """ + + value = self.get_int(base=base) + if value < 0 or value > 65535: + if base == 8: + raise dns.exception.SyntaxError( + '%o is not an octal unsigned 16-bit integer' % value) + else: + raise dns.exception.SyntaxError( + '%d is not an unsigned 16-bit integer' % value) + return value + + def get_uint32(self, base=10): + """Read the next token and interpret it as a 32-bit unsigned + integer. + + Raises dns.exception.SyntaxError if not a 32-bit unsigned integer. + + Returns an int. + """ + + value = self.get_int(base=base) + if value < 0 or value > 4294967295: + raise dns.exception.SyntaxError( + '%d is not an unsigned 32-bit integer' % value) + return value + + def get_uint48(self, base=10): + """Read the next token and interpret it as a 48-bit unsigned + integer. + + Raises dns.exception.SyntaxError if not a 48-bit unsigned integer. + + Returns an int. + """ + + value = self.get_int(base=base) + if value < 0 or value > 281474976710655: + raise dns.exception.SyntaxError( + '%d is not an unsigned 48-bit integer' % value) + return value + + def get_string(self, max_length=None): + """Read the next token and interpret it as a string. + + Raises dns.exception.SyntaxError if not a string. + Raises dns.exception.SyntaxError if token value length + exceeds max_length (if specified). + + Returns a string. + """ + + token = self.get().unescape() + if not (token.is_identifier() or token.is_quoted_string()): + raise dns.exception.SyntaxError('expecting a string') + if max_length and len(token.value) > max_length: + raise dns.exception.SyntaxError("string too long") + return token.value + + def get_identifier(self): + """Read the next token, which should be an identifier. + + Raises dns.exception.SyntaxError if not an identifier. + + Returns a string. + """ + + token = self.get().unescape() + if not token.is_identifier(): + raise dns.exception.SyntaxError('expecting an identifier') + return token.value + + def get_remaining(self, max_tokens=None): + """Return the remaining tokens on the line, until an EOL or EOF is seen. + + max_tokens: If not None, stop after this number of tokens. + + Returns a list of tokens. + """ + + tokens = [] + while True: + token = self.get() + if token.is_eol_or_eof(): + self.unget(token) + break + tokens.append(token) + if len(tokens) == max_tokens: + break + return tokens + + def concatenate_remaining_identifiers(self): + """Read the remaining tokens on the line, which should be identifiers. + + Raises dns.exception.SyntaxError if a token is seen that is not an + identifier. + + Returns a string containing a concatenation of the remaining + identifiers. + """ + s = "" + while True: + token = self.get().unescape() + if token.is_eol_or_eof(): + self.unget(token) + break + if not token.is_identifier(): + raise dns.exception.SyntaxError + s += token.value + return s + + def as_name(self, token, origin=None, relativize=False, relativize_to=None): + """Try to interpret the token as a DNS name. + + Raises dns.exception.SyntaxError if not a name. + + Returns a dns.name.Name. + """ + if not token.is_identifier(): + raise dns.exception.SyntaxError('expecting an identifier') + name = dns.name.from_text(token.value, origin, self.idna_codec) + return name.choose_relativity(relativize_to or origin, relativize) + + def get_name(self, origin=None, relativize=False, relativize_to=None): + """Read the next token and interpret it as a DNS name. + + Raises dns.exception.SyntaxError if not a name. + + Returns a dns.name.Name. + """ + + token = self.get() + return self.as_name(token, origin, relativize, relativize_to) + + def get_eol_as_token(self): + """Read the next token and raise an exception if it isn't EOL or + EOF. + + Returns a string. + """ + + token = self.get() + if not token.is_eol_or_eof(): + raise dns.exception.SyntaxError( + 'expected EOL or EOF, got %d "%s"' % (token.ttype, + token.value)) + return token + + def get_eol(self): + return self.get_eol_as_token().value + + def get_ttl(self): + """Read the next token and interpret it as a DNS TTL. + + Raises dns.exception.SyntaxError or dns.ttl.BadTTL if not an + identifier or badly formed. + + Returns an int. + """ + + token = self.get().unescape() + if not token.is_identifier(): + raise dns.exception.SyntaxError('expecting an identifier') + return dns.ttl.from_text(token.value) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/transaction.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/transaction.py new file mode 100644 index 0000000..8aec2e8 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/transaction.py @@ -0,0 +1,512 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import collections + +import dns.exception +import dns.name +import dns.rdataclass +import dns.rdataset +import dns.rdatatype +import dns.rrset +import dns.serial +import dns.ttl + + +class TransactionManager: + def reader(self): + """Begin a read-only transaction.""" + raise NotImplementedError # pragma: no cover + + def writer(self, replacement=False): + """Begin a writable transaction. + + *replacement*, a ``bool``. If `True`, the content of the + transaction completely replaces any prior content. If False, + the default, then the content of the transaction updates the + existing content. + """ + raise NotImplementedError # pragma: no cover + + def origin_information(self): + """Returns a tuple + + (absolute_origin, relativize, effective_origin) + + giving the absolute name of the default origin for any + relative domain names, the "effective origin", and whether + names should be relativized. The "effective origin" is the + absolute origin if relativize is False, and the empty name if + relativize is true. (The effective origin is provided even + though it can be computed from the absolute_origin and + relativize setting because it avoids a lot of code + duplication.) + + If the returned names are `None`, then no origin information is + available. + + This information is used by code working with transactions to + allow it to coordinate relativization. The transaction code + itself takes what it gets (i.e. does not change name + relativity). + + """ + raise NotImplementedError # pragma: no cover + + def get_class(self): + """The class of the transaction manager. + """ + raise NotImplementedError # pragma: no cover + + def from_wire_origin(self): + """Origin to use in from_wire() calls. + """ + (absolute_origin, relativize, _) = self.origin_information() + if relativize: + return absolute_origin + else: + return None + + +class DeleteNotExact(dns.exception.DNSException): + """Existing data did not match data specified by an exact delete.""" + + +class ReadOnly(dns.exception.DNSException): + """Tried to write to a read-only transaction.""" + + +class AlreadyEnded(dns.exception.DNSException): + """Tried to use an already-ended transaction.""" + + +class Transaction: + + def __init__(self, manager, replacement=False, read_only=False): + self.manager = manager + self.replacement = replacement + self.read_only = read_only + self._ended = False + + # + # This is the high level API + # + + def get(self, name, rdtype, covers=dns.rdatatype.NONE): + """Return the rdataset associated with *name*, *rdtype*, and *covers*, + or `None` if not found. + + Note that the returned rdataset is immutable. + """ + self._check_ended() + if isinstance(name, str): + name = dns.name.from_text(name, None) + rdtype = dns.rdatatype.RdataType.make(rdtype) + rdataset = self._get_rdataset(name, rdtype, covers) + if rdataset is not None and \ + not isinstance(rdataset, dns.rdataset.ImmutableRdataset): + rdataset = dns.rdataset.ImmutableRdataset(rdataset) + return rdataset + + def _check_read_only(self): + if self.read_only: + raise ReadOnly + + def add(self, *args): + """Add records. + + The arguments may be: + + - rrset + + - name, rdataset... + + - name, ttl, rdata... + """ + self._check_ended() + self._check_read_only() + return self._add(False, args) + + def replace(self, *args): + """Replace the existing rdataset at the name with the specified + rdataset, or add the specified rdataset if there was no existing + rdataset. + + The arguments may be: + + - rrset + + - name, rdataset... + + - name, ttl, rdata... + + Note that if you want to replace the entire node, you should do + a delete of the name followed by one or more calls to add() or + replace(). + """ + self._check_ended() + self._check_read_only() + return self._add(True, args) + + def delete(self, *args): + """Delete records. + + It is not an error if some of the records are not in the existing + set. + + The arguments may be: + + - rrset + + - name + + - name, rdataclass, rdatatype, [covers] + + - name, rdataset... + + - name, rdata... + """ + self._check_ended() + self._check_read_only() + return self._delete(False, args) + + def delete_exact(self, *args): + """Delete records. + + The arguments may be: + + - rrset + + - name + + - name, rdataclass, rdatatype, [covers] + + - name, rdataset... + + - name, rdata... + + Raises dns.transaction.DeleteNotExact if some of the records + are not in the existing set. + + """ + self._check_ended() + self._check_read_only() + return self._delete(True, args) + + def name_exists(self, name): + """Does the specified name exist?""" + self._check_ended() + if isinstance(name, str): + name = dns.name.from_text(name, None) + return self._name_exists(name) + + def update_serial(self, value=1, relative=True, name=dns.name.empty): + """Update the serial number. + + *value*, an `int`, is an increment if *relative* is `True`, or the + actual value to set if *relative* is `False`. + + Raises `KeyError` if there is no SOA rdataset at *name*. + + Raises `ValueError` if *value* is negative or if the increment is + so large that it would cause the new serial to be less than the + prior value. + """ + self._check_ended() + if value < 0: + raise ValueError('negative update_serial() value') + if isinstance(name, str): + name = dns.name.from_text(name, None) + rdataset = self._get_rdataset(name, dns.rdatatype.SOA, + dns.rdatatype.NONE) + if rdataset is None or len(rdataset) == 0: + raise KeyError + if relative: + serial = dns.serial.Serial(rdataset[0].serial) + value + else: + serial = dns.serial.Serial(value) + serial = serial.value # convert back to int + if serial == 0: + serial = 1 + rdata = rdataset[0].replace(serial=serial) + new_rdataset = dns.rdataset.from_rdata(rdataset.ttl, rdata) + self.replace(name, new_rdataset) + + def __iter__(self): + self._check_ended() + return self._iterate_rdatasets() + + def changed(self): + """Has this transaction changed anything? + + For read-only transactions, the result is always `False`. + + For writable transactions, the result is `True` if at some time + during the life of the transaction, the content was changed. + """ + self._check_ended() + return self._changed() + + def commit(self): + """Commit the transaction. + + Normally transactions are used as context managers and commit + or rollback automatically, but it may be done explicitly if needed. + A ``dns.transaction.Ended`` exception will be raised if you try + to use a transaction after it has been committed or rolled back. + + Raises an exception if the commit fails (in which case the transaction + is also rolled back. + """ + self._end(True) + + def rollback(self): + """Rollback the transaction. + + Normally transactions are used as context managers and commit + or rollback automatically, but it may be done explicitly if needed. + A ``dns.transaction.AlreadyEnded`` exception will be raised if you try + to use a transaction after it has been committed or rolled back. + + Rollback cannot otherwise fail. + """ + self._end(False) + + # + # Helper methods + # + + def _raise_if_not_empty(self, method, args): + if len(args) != 0: + raise TypeError(f'extra parameters to {method}') + + def _rdataset_from_args(self, method, deleting, args): + try: + arg = args.popleft() + if isinstance(arg, dns.rrset.RRset): + rdataset = arg.to_rdataset() + elif isinstance(arg, dns.rdataset.Rdataset): + rdataset = arg + else: + if deleting: + ttl = 0 + else: + if isinstance(arg, int): + ttl = arg + if ttl > dns.ttl.MAX_TTL: + raise ValueError(f'{method}: TTL value too big') + else: + raise TypeError(f'{method}: expected a TTL') + arg = args.popleft() + if isinstance(arg, dns.rdata.Rdata): + rdataset = dns.rdataset.from_rdata(ttl, arg) + else: + raise TypeError(f'{method}: expected an Rdata') + return rdataset + except IndexError: + if deleting: + return None + else: + # reraise + raise TypeError(f'{method}: expected more arguments') + + def _add(self, replace, args): + try: + args = collections.deque(args) + if replace: + method = 'replace()' + else: + method = 'add()' + arg = args.popleft() + if isinstance(arg, str): + arg = dns.name.from_text(arg, None) + if isinstance(arg, dns.name.Name): + name = arg + rdataset = self._rdataset_from_args(method, False, args) + elif isinstance(arg, dns.rrset.RRset): + rrset = arg + name = rrset.name + # rrsets are also rdatasets, but they don't print the + # same and can't be stored in nodes, so convert. + rdataset = rrset.to_rdataset() + else: + raise TypeError(f'{method} requires a name or RRset ' + + 'as the first argument') + if rdataset.rdclass != self.manager.get_class(): + raise ValueError(f'{method} has objects of wrong RdataClass') + if rdataset.rdtype == dns.rdatatype.SOA: + (_, _, origin) = self.manager.origin_information() + if name != origin: + raise ValueError(f'{method} has non-origin SOA') + self._raise_if_not_empty(method, args) + if not replace: + existing = self._get_rdataset(name, rdataset.rdtype, + rdataset.covers) + if existing is not None: + if isinstance(existing, dns.rdataset.ImmutableRdataset): + trds = dns.rdataset.Rdataset(existing.rdclass, + existing.rdtype, + existing.covers) + trds.update(existing) + existing = trds + rdataset = existing.union(rdataset) + self._put_rdataset(name, rdataset) + except IndexError: + raise TypeError(f'not enough parameters to {method}') + + def _delete(self, exact, args): + try: + args = collections.deque(args) + if exact: + method = 'delete_exact()' + else: + method = 'delete()' + arg = args.popleft() + if isinstance(arg, str): + arg = dns.name.from_text(arg, None) + if isinstance(arg, dns.name.Name): + name = arg + if len(args) > 0 and (isinstance(args[0], int) or + isinstance(args[0], str)): + # deleting by type and (optionally) covers + rdtype = dns.rdatatype.RdataType.make(args.popleft()) + if len(args) > 0: + covers = dns.rdatatype.RdataType.make(args.popleft()) + else: + covers = dns.rdatatype.NONE + self._raise_if_not_empty(method, args) + existing = self._get_rdataset(name, rdtype, covers) + if existing is None: + if exact: + raise DeleteNotExact(f'{method}: missing rdataset') + else: + self._delete_rdataset(name, rdtype, covers) + return + else: + rdataset = self._rdataset_from_args(method, True, args) + elif isinstance(arg, dns.rrset.RRset): + rdataset = arg # rrsets are also rdatasets + name = rdataset.name + else: + raise TypeError(f'{method} requires a name or RRset ' + + 'as the first argument') + self._raise_if_not_empty(method, args) + if rdataset: + if rdataset.rdclass != self.manager.get_class(): + raise ValueError(f'{method} has objects of wrong ' + 'RdataClass') + existing = self._get_rdataset(name, rdataset.rdtype, + rdataset.covers) + if existing is not None: + if exact: + intersection = existing.intersection(rdataset) + if intersection != rdataset: + raise DeleteNotExact(f'{method}: missing rdatas') + rdataset = existing.difference(rdataset) + if len(rdataset) == 0: + self._delete_rdataset(name, rdataset.rdtype, + rdataset.covers) + else: + self._put_rdataset(name, rdataset) + elif exact: + raise DeleteNotExact(f'{method}: missing rdataset') + else: + if exact and not self._name_exists(name): + raise DeleteNotExact(f'{method}: name not known') + self._delete_name(name) + except IndexError: + raise TypeError(f'not enough parameters to {method}') + + def _check_ended(self): + if self._ended: + raise AlreadyEnded + + def _end(self, commit): + self._check_ended() + if self._ended: + raise AlreadyEnded + try: + self._end_transaction(commit) + finally: + self._ended = True + + # + # Transactions are context managers. + # + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + if not self._ended: + if exc_type is None: + self.commit() + else: + self.rollback() + return False + + # + # This is the low level API, which must be implemented by subclasses + # of Transaction. + # + + def _get_rdataset(self, name, rdtype, covers): + """Return the rdataset associated with *name*, *rdtype*, and *covers*, + or `None` if not found. + """ + raise NotImplementedError # pragma: no cover + + def _put_rdataset(self, name, rdataset): + """Store the rdataset.""" + raise NotImplementedError # pragma: no cover + + def _delete_name(self, name): + """Delete all data associated with *name*. + + It is not an error if the rdataset does not exist. + """ + raise NotImplementedError # pragma: no cover + + def _delete_rdataset(self, name, rdtype, covers): + """Delete all data associated with *name*, *rdtype*, and *covers*. + + It is not an error if the rdataset does not exist. + """ + raise NotImplementedError # pragma: no cover + + def _name_exists(self, name): + """Does name exist? + + Returns a bool. + """ + raise NotImplementedError # pragma: no cover + + def _changed(self): + """Has this transaction changed anything?""" + raise NotImplementedError # pragma: no cover + + def _end_transaction(self, commit): + """End the transaction. + + *commit*, a bool. If ``True``, commit the transaction, otherwise + roll it back. + + If committing adn the commit fails, then roll back and raise an + exception. + """ + raise NotImplementedError # pragma: no cover + + def _set_origin(self, origin): + """Set the origin. + + This method is called when reading a possibly relativized + source, and an origin setting operation occurs (e.g. $ORIGIN + in a zone file). + """ + raise NotImplementedError # pragma: no cover + + def _iterate_rdatasets(self): + """Return an iterator that yields (name, rdataset) tuples. + + Not all Transaction subclasses implement this. + """ + raise NotImplementedError # pragma: no cover diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/tsig.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/tsig.py new file mode 100644 index 0000000..5c773ff --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/tsig.py @@ -0,0 +1,343 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS TSIG support.""" + +import base64 +import hashlib +import hmac +import struct + +import dns.exception +import dns.rdataclass +import dns.name +import dns.rcode + +class BadTime(dns.exception.DNSException): + + """The current time is not within the TSIG's validity time.""" + + +class BadSignature(dns.exception.DNSException): + + """The TSIG signature fails to verify.""" + + +class BadKey(dns.exception.DNSException): + + """The TSIG record owner name does not match the key.""" + + +class BadAlgorithm(dns.exception.DNSException): + + """The TSIG algorithm does not match the key.""" + + +class PeerError(dns.exception.DNSException): + + """Base class for all TSIG errors generated by the remote peer""" + + +class PeerBadKey(PeerError): + + """The peer didn't know the key we used""" + + +class PeerBadSignature(PeerError): + + """The peer didn't like the signature we sent""" + + +class PeerBadTime(PeerError): + + """The peer didn't like the time we sent""" + + +class PeerBadTruncation(PeerError): + + """The peer didn't like amount of truncation in the TSIG we sent""" + + +# TSIG Algorithms + +HMAC_MD5 = dns.name.from_text("HMAC-MD5.SIG-ALG.REG.INT") +HMAC_SHA1 = dns.name.from_text("hmac-sha1") +HMAC_SHA224 = dns.name.from_text("hmac-sha224") +HMAC_SHA256 = dns.name.from_text("hmac-sha256") +HMAC_SHA256_128 = dns.name.from_text("hmac-sha256-128") +HMAC_SHA384 = dns.name.from_text("hmac-sha384") +HMAC_SHA384_192 = dns.name.from_text("hmac-sha384-192") +HMAC_SHA512 = dns.name.from_text("hmac-sha512") +HMAC_SHA512_256 = dns.name.from_text("hmac-sha512-256") +GSS_TSIG = dns.name.from_text("gss-tsig") + +default_algorithm = HMAC_SHA256 + + +class GSSTSig: + """ + GSS-TSIG TSIG implementation. This uses the GSS-API context established + in the TKEY message handshake to sign messages using GSS-API message + integrity codes, per the RFC. + + In order to avoid a direct GSSAPI dependency, the keyring holds a ref + to the GSSAPI object required, rather than the key itself. + """ + def __init__(self, gssapi_context): + self.gssapi_context = gssapi_context + self.data = b'' + self.name = 'gss-tsig' + + def update(self, data): + self.data += data + + def sign(self): + # defer to the GSSAPI function to sign + return self.gssapi_context.get_signature(self.data) + + def verify(self, expected): + try: + # defer to the GSSAPI function to verify + return self.gssapi_context.verify_signature(self.data, expected) + except Exception: + # note the usage of a bare exception + raise BadSignature + + +class GSSTSigAdapter: + def __init__(self, keyring): + self.keyring = keyring + + def __call__(self, message, keyname): + if keyname in self.keyring: + key = self.keyring[keyname] + if isinstance(key, Key) and key.algorithm == GSS_TSIG: + if message: + GSSTSigAdapter.parse_tkey_and_step(key, message, keyname) + return key + else: + return None + + @classmethod + def parse_tkey_and_step(cls, key, message, keyname): + # if the message is a TKEY type, absorb the key material + # into the context using step(); this is used to allow the + # client to complete the GSSAPI negotiation before attempting + # to verify the signed response to a TKEY message exchange + try: + rrset = message.find_rrset(message.answer, keyname, + dns.rdataclass.ANY, + dns.rdatatype.TKEY) + if rrset: + token = rrset[0].key + gssapi_context = key.secret + return gssapi_context.step(token) + except KeyError: + pass + + +class HMACTSig: + """ + HMAC TSIG implementation. This uses the HMAC python module to handle the + sign/verify operations. + """ + + _hashes = { + HMAC_SHA1: hashlib.sha1, + HMAC_SHA224: hashlib.sha224, + HMAC_SHA256: hashlib.sha256, + HMAC_SHA256_128: (hashlib.sha256, 128), + HMAC_SHA384: hashlib.sha384, + HMAC_SHA384_192: (hashlib.sha384, 192), + HMAC_SHA512: hashlib.sha512, + HMAC_SHA512_256: (hashlib.sha512, 256), + HMAC_MD5: hashlib.md5, + } + + def __init__(self, key, algorithm): + try: + hashinfo = self._hashes[algorithm] + except KeyError: + raise NotImplementedError(f"TSIG algorithm {algorithm} " + + "is not supported") + + # create the HMAC context + if isinstance(hashinfo, tuple): + self.hmac_context = hmac.new(key, digestmod=hashinfo[0]) + self.size = hashinfo[1] + else: + self.hmac_context = hmac.new(key, digestmod=hashinfo) + self.size = None + self.name = self.hmac_context.name + if self.size: + self.name += f'-{self.size}' + + def update(self, data): + return self.hmac_context.update(data) + + def sign(self): + # defer to the HMAC digest() function for that digestmod + digest = self.hmac_context.digest() + if self.size: + digest = digest[: (self.size // 8)] + return digest + + def verify(self, expected): + # re-digest and compare the results + mac = self.sign() + if not hmac.compare_digest(mac, expected): + raise BadSignature + + +def _digest(wire, key, rdata, time=None, request_mac=None, ctx=None, + multi=None): + """Return a context containing the TSIG rdata for the input parameters + @rtype: dns.tsig.HMACTSig or dns.tsig.GSSTSig object + @raises ValueError: I{other_data} is too long + @raises NotImplementedError: I{algorithm} is not supported + """ + + first = not (ctx and multi) + if first: + ctx = get_context(key) + if request_mac: + ctx.update(struct.pack('!H', len(request_mac))) + ctx.update(request_mac) + ctx.update(struct.pack('!H', rdata.original_id)) + ctx.update(wire[2:]) + if first: + ctx.update(key.name.to_digestable()) + ctx.update(struct.pack('!H', dns.rdataclass.ANY)) + ctx.update(struct.pack('!I', 0)) + if time is None: + time = rdata.time_signed + upper_time = (time >> 32) & 0xffff + lower_time = time & 0xffffffff + time_encoded = struct.pack('!HIH', upper_time, lower_time, rdata.fudge) + other_len = len(rdata.other) + if other_len > 65535: + raise ValueError('TSIG Other Data is > 65535 bytes') + if first: + ctx.update(key.algorithm.to_digestable() + time_encoded) + ctx.update(struct.pack('!HH', rdata.error, other_len) + rdata.other) + else: + ctx.update(time_encoded) + return ctx + + +def _maybe_start_digest(key, mac, multi): + """If this is the first message in a multi-message sequence, + start a new context. + @rtype: dns.tsig.HMACTSig or dns.tsig.GSSTSig object + """ + if multi: + ctx = get_context(key) + ctx.update(struct.pack('!H', len(mac))) + ctx.update(mac) + return ctx + else: + return None + + +def sign(wire, key, rdata, time=None, request_mac=None, ctx=None, multi=False): + """Return a (tsig_rdata, mac, ctx) tuple containing the HMAC TSIG rdata + for the input parameters, the HMAC MAC calculated by applying the + TSIG signature algorithm, and the TSIG digest context. + @rtype: (string, dns.tsig.HMACTSig or dns.tsig.GSSTSig object) + @raises ValueError: I{other_data} is too long + @raises NotImplementedError: I{algorithm} is not supported + """ + + ctx = _digest(wire, key, rdata, time, request_mac, ctx, multi) + mac = ctx.sign() + tsig = rdata.replace(time_signed=time, mac=mac) + + return (tsig, _maybe_start_digest(key, mac, multi)) + + +def validate(wire, key, owner, rdata, now, request_mac, tsig_start, ctx=None, + multi=False): + """Validate the specified TSIG rdata against the other input parameters. + + @raises FormError: The TSIG is badly formed. + @raises BadTime: There is too much time skew between the client and the + server. + @raises BadSignature: The TSIG signature did not validate + @rtype: dns.tsig.HMACTSig or dns.tsig.GSSTSig object""" + + (adcount,) = struct.unpack("!H", wire[10:12]) + if adcount == 0: + raise dns.exception.FormError + adcount -= 1 + new_wire = wire[0:10] + struct.pack("!H", adcount) + wire[12:tsig_start] + if rdata.error != 0: + if rdata.error == dns.rcode.BADSIG: + raise PeerBadSignature + elif rdata.error == dns.rcode.BADKEY: + raise PeerBadKey + elif rdata.error == dns.rcode.BADTIME: + raise PeerBadTime + elif rdata.error == dns.rcode.BADTRUNC: + raise PeerBadTruncation + else: + raise PeerError('unknown TSIG error code %d' % rdata.error) + if abs(rdata.time_signed - now) > rdata.fudge: + raise BadTime + if key.name != owner: + raise BadKey + if key.algorithm != rdata.algorithm: + raise BadAlgorithm + ctx = _digest(new_wire, key, rdata, None, request_mac, ctx, multi) + ctx.verify(rdata.mac) + return _maybe_start_digest(key, rdata.mac, multi) + + +def get_context(key): + """Returns an HMAC context for the specified key. + + @rtype: HMAC context + @raises NotImplementedError: I{algorithm} is not supported + """ + + if key.algorithm == GSS_TSIG: + return GSSTSig(key.secret) + else: + return HMACTSig(key.secret, key.algorithm) + + +class Key: + def __init__(self, name, secret, algorithm=default_algorithm): + if isinstance(name, str): + name = dns.name.from_text(name) + self.name = name + if isinstance(secret, str): + secret = base64.decodebytes(secret.encode()) + self.secret = secret + if isinstance(algorithm, str): + algorithm = dns.name.from_text(algorithm) + self.algorithm = algorithm + + def __eq__(self, other): + return (isinstance(other, Key) and + self.name == other.name and + self.secret == other.secret and + self.algorithm == other.algorithm) + + def __repr__(self): + return f"" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/tsigkeyring.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/tsigkeyring.py new file mode 100644 index 0000000..47a1f79 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/tsigkeyring.py @@ -0,0 +1,64 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""A place to store TSIG keys.""" + +import base64 + +import dns.name + + +def from_text(textring): + """Convert a dictionary containing (textual DNS name, base64 secret) + pairs into a binary keyring which has (dns.name.Name, bytes) pairs, or + a dictionary containing (textual DNS name, (algorithm, base64 secret)) + pairs into a binary keyring which has (dns.name.Name, dns.tsig.Key) pairs. + @rtype: dict""" + + keyring = {} + for (name, value) in textring.items(): + name = dns.name.from_text(name) + if isinstance(value, str): + keyring[name] = dns.tsig.Key(name, value).secret + else: + (algorithm, secret) = value + keyring[name] = dns.tsig.Key(name, secret, algorithm) + return keyring + + +def to_text(keyring): + """Convert a dictionary containing (dns.name.Name, dns.tsig.Key) pairs + into a text keyring which has (textual DNS name, (textual algorithm, + base64 secret)) pairs, or a dictionary containing (dns.name.Name, bytes) + pairs into a text keyring which has (textual DNS name, base64 secret) pairs. + @rtype: dict""" + + textring = {} + def b64encode(secret): + return base64.encodebytes(secret).decode().rstrip() + for (name, key) in keyring.items(): + name = name.to_text() + if isinstance(key, bytes): + textring[name] = b64encode(key) + else: + if isinstance(key.secret, bytes): + text_secret = b64encode(key.secret) + else: + text_secret = str(key.secret) + + textring[name] = (key.algorithm.to_text(), text_secret) + return textring diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/ttl.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/ttl.py new file mode 100644 index 0000000..8ea5213 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/ttl.py @@ -0,0 +1,84 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS TTL conversion.""" + +import dns.exception + +MAX_TTL = 2147483647 + +class BadTTL(dns.exception.SyntaxError): + """DNS TTL value is not well-formed.""" + + +def from_text(text): + """Convert the text form of a TTL to an integer. + + The BIND 8 units syntax for TTLs (e.g. '1w6d4h3m10s') is supported. + + *text*, a ``str``, the textual TTL. + + Raises ``dns.ttl.BadTTL`` if the TTL is not well-formed. + + Returns an ``int``. + """ + + if text.isdigit(): + total = int(text) + elif len(text) == 0: + raise BadTTL + else: + total = 0 + current = 0 + need_digit = True + for c in text: + if c.isdigit(): + current *= 10 + current += int(c) + need_digit = False + else: + if need_digit: + raise BadTTL + c = c.lower() + if c == 'w': + total += current * 604800 + elif c == 'd': + total += current * 86400 + elif c == 'h': + total += current * 3600 + elif c == 'm': + total += current * 60 + elif c == 's': + total += current + else: + raise BadTTL("unknown unit '%s'" % c) + current = 0 + need_digit = True + if not current == 0: + raise BadTTL("trailing integer") + if total < 0 or total > MAX_TTL: + raise BadTTL("TTL should be between 0 and 2^31 - 1 (inclusive)") + return total + + +def make(value): + if isinstance(value, int): + return value + elif isinstance(value, str): + return dns.ttl.from_text(value) + else: + raise ValueError('cannot convert value to TTL') diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/update.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/update.py new file mode 100644 index 0000000..a541af2 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/update.py @@ -0,0 +1,319 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Dynamic Update Support""" + + +import dns.message +import dns.name +import dns.opcode +import dns.rdata +import dns.rdataclass +import dns.rdataset +import dns.tsig + + +class UpdateSection(dns.enum.IntEnum): + """Update sections""" + ZONE = 0 + PREREQ = 1 + UPDATE = 2 + ADDITIONAL = 3 + + @classmethod + def _maximum(cls): + return 3 + + +class UpdateMessage(dns.message.Message): + + _section_enum = UpdateSection + + def __init__(self, zone=None, rdclass=dns.rdataclass.IN, keyring=None, + keyname=None, keyalgorithm=dns.tsig.default_algorithm, + id=None): + """Initialize a new DNS Update object. + + See the documentation of the Message class for a complete + description of the keyring dictionary. + + *zone*, a ``dns.name.Name``, ``str``, or ``None``, the zone + which is being updated. ``None`` should only be used by dnspython's + message constructors, as a zone is required for the convenience + methods like ``add()``, ``replace()``, etc. + + *rdclass*, an ``int`` or ``str``, the class of the zone. + + The *keyring*, *keyname*, and *keyalgorithm* parameters are passed to + ``use_tsig()``; see its documentation for details. + """ + super().__init__(id=id) + self.flags |= dns.opcode.to_flags(dns.opcode.UPDATE) + if isinstance(zone, str): + zone = dns.name.from_text(zone) + self.origin = zone + rdclass = dns.rdataclass.RdataClass.make(rdclass) + self.zone_rdclass = rdclass + if self.origin: + self.find_rrset(self.zone, self.origin, rdclass, dns.rdatatype.SOA, + create=True, force_unique=True) + if keyring is not None: + self.use_tsig(keyring, keyname, algorithm=keyalgorithm) + + @property + def zone(self): + """The zone section.""" + return self.sections[0] + + @zone.setter + def zone(self, v): + self.sections[0] = v + + @property + def prerequisite(self): + """The prerequisite section.""" + return self.sections[1] + + @prerequisite.setter + def prerequisite(self, v): + self.sections[1] = v + + @property + def update(self): + """The update section.""" + return self.sections[2] + + @update.setter + def update(self, v): + self.sections[2] = v + + def _add_rr(self, name, ttl, rd, deleting=None, section=None): + """Add a single RR to the update section.""" + + if section is None: + section = self.update + covers = rd.covers() + rrset = self.find_rrset(section, name, self.zone_rdclass, rd.rdtype, + covers, deleting, True, True) + rrset.add(rd, ttl) + + def _add(self, replace, section, name, *args): + """Add records. + + *replace* is the replacement mode. If ``False``, + RRs are added to an existing RRset; if ``True``, the RRset + is replaced with the specified contents. The second + argument is the section to add to. The third argument + is always a name. The other arguments can be: + + - rdataset... + + - ttl, rdata... + + - ttl, rdtype, string... + """ + + if isinstance(name, str): + name = dns.name.from_text(name, None) + if isinstance(args[0], dns.rdataset.Rdataset): + for rds in args: + if replace: + self.delete(name, rds.rdtype) + for rd in rds: + self._add_rr(name, rds.ttl, rd, section=section) + else: + args = list(args) + ttl = int(args.pop(0)) + if isinstance(args[0], dns.rdata.Rdata): + if replace: + self.delete(name, args[0].rdtype) + for rd in args: + self._add_rr(name, ttl, rd, section=section) + else: + rdtype = dns.rdatatype.RdataType.make(args.pop(0)) + if replace: + self.delete(name, rdtype) + for s in args: + rd = dns.rdata.from_text(self.zone_rdclass, rdtype, s, + self.origin) + self._add_rr(name, ttl, rd, section=section) + + def add(self, name, *args): + """Add records. + + The first argument is always a name. The other + arguments can be: + + - rdataset... + + - ttl, rdata... + + - ttl, rdtype, string... + """ + + self._add(False, self.update, name, *args) + + def delete(self, name, *args): + """Delete records. + + The first argument is always a name. The other + arguments can be: + + - *empty* + + - rdataset... + + - rdata... + + - rdtype, [string...] + """ + + if isinstance(name, str): + name = dns.name.from_text(name, None) + if len(args) == 0: + self.find_rrset(self.update, name, dns.rdataclass.ANY, + dns.rdatatype.ANY, dns.rdatatype.NONE, + dns.rdatatype.ANY, True, True) + elif isinstance(args[0], dns.rdataset.Rdataset): + for rds in args: + for rd in rds: + self._add_rr(name, 0, rd, dns.rdataclass.NONE) + else: + args = list(args) + if isinstance(args[0], dns.rdata.Rdata): + for rd in args: + self._add_rr(name, 0, rd, dns.rdataclass.NONE) + else: + rdtype = dns.rdatatype.RdataType.make(args.pop(0)) + if len(args) == 0: + self.find_rrset(self.update, name, + self.zone_rdclass, rdtype, + dns.rdatatype.NONE, + dns.rdataclass.ANY, + True, True) + else: + for s in args: + rd = dns.rdata.from_text(self.zone_rdclass, rdtype, s, + self.origin) + self._add_rr(name, 0, rd, dns.rdataclass.NONE) + + def replace(self, name, *args): + """Replace records. + + The first argument is always a name. The other + arguments can be: + + - rdataset... + + - ttl, rdata... + + - ttl, rdtype, string... + + Note that if you want to replace the entire node, you should do + a delete of the name followed by one or more calls to add. + """ + + self._add(True, self.update, name, *args) + + def present(self, name, *args): + """Require that an owner name (and optionally an rdata type, + or specific rdataset) exists as a prerequisite to the + execution of the update. + + The first argument is always a name. + The other arguments can be: + + - rdataset... + + - rdata... + + - rdtype, string... + """ + + if isinstance(name, str): + name = dns.name.from_text(name, None) + if len(args) == 0: + self.find_rrset(self.prerequisite, name, + dns.rdataclass.ANY, dns.rdatatype.ANY, + dns.rdatatype.NONE, None, + True, True) + elif isinstance(args[0], dns.rdataset.Rdataset) or \ + isinstance(args[0], dns.rdata.Rdata) or \ + len(args) > 1: + if not isinstance(args[0], dns.rdataset.Rdataset): + # Add a 0 TTL + args = list(args) + args.insert(0, 0) + self._add(False, self.prerequisite, name, *args) + else: + rdtype = dns.rdatatype.RdataType.make(args[0]) + self.find_rrset(self.prerequisite, name, + dns.rdataclass.ANY, rdtype, + dns.rdatatype.NONE, None, + True, True) + + def absent(self, name, rdtype=None): + """Require that an owner name (and optionally an rdata type) does + not exist as a prerequisite to the execution of the update.""" + + if isinstance(name, str): + name = dns.name.from_text(name, None) + if rdtype is None: + self.find_rrset(self.prerequisite, name, + dns.rdataclass.NONE, dns.rdatatype.ANY, + dns.rdatatype.NONE, None, + True, True) + else: + rdtype = dns.rdatatype.RdataType.make(rdtype) + self.find_rrset(self.prerequisite, name, + dns.rdataclass.NONE, rdtype, + dns.rdatatype.NONE, None, + True, True) + + def _get_one_rr_per_rrset(self, value): + # Updates are always one_rr_per_rrset + return True + + def _parse_rr_header(self, section, name, rdclass, rdtype): + deleting = None + empty = False + if section == UpdateSection.ZONE: + if dns.rdataclass.is_metaclass(rdclass) or \ + rdtype != dns.rdatatype.SOA or \ + self.zone: + raise dns.exception.FormError + else: + if not self.zone: + raise dns.exception.FormError + if rdclass in (dns.rdataclass.ANY, dns.rdataclass.NONE): + deleting = rdclass + rdclass = self.zone[0].rdclass + empty = (deleting == dns.rdataclass.ANY or + section == UpdateSection.PREREQ) + return (rdclass, rdtype, deleting, empty) + +# backwards compatibility +Update = UpdateMessage + +### BEGIN generated UpdateSection constants + +ZONE = UpdateSection.ZONE +PREREQ = UpdateSection.PREREQ +UPDATE = UpdateSection.UPDATE +ADDITIONAL = UpdateSection.ADDITIONAL + +### END generated UpdateSection constants diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/version.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/version.py new file mode 100644 index 0000000..b371b73 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/version.py @@ -0,0 +1,46 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""dnspython release version information.""" + +#: MAJOR +MAJOR = 2 +#: MINOR +MINOR = 1 +#: MICRO +MICRO = 0 +#: RELEASELEVEL +RELEASELEVEL = 0x0f +#: SERIAL +SERIAL = 0 + +if RELEASELEVEL == 0x0f: # pragma: no cover + #: version + version = '%d.%d.%d' % (MAJOR, MINOR, MICRO) +elif RELEASELEVEL == 0x00: # pragma: no cover + version = '%d.%d.%ddev%d' % \ + (MAJOR, MINOR, MICRO, SERIAL) +elif RELEASELEVEL == 0x0c: # pragma: no cover + version = '%d.%d.%drc%d' % \ + (MAJOR, MINOR, MICRO, SERIAL) +else: # pragma: no cover + version = '%d.%d.%d%x%d' % \ + (MAJOR, MINOR, MICRO, RELEASELEVEL, SERIAL) + +#: hexversion +hexversion = MAJOR << 24 | MINOR << 16 | MICRO << 8 | RELEASELEVEL << 4 | \ + SERIAL diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/versioned.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/versioned.py new file mode 100644 index 0000000..686a83b --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/versioned.py @@ -0,0 +1,455 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +"""DNS Versioned Zones.""" + +import collections +try: + import threading as _threading +except ImportError: # pragma: no cover + import dummy_threading as _threading # type: ignore + +import dns.exception +import dns.immutable +import dns.name +import dns.node +import dns.rdataclass +import dns.rdatatype +import dns.rdata +import dns.rdtypes.ANY.SOA +import dns.transaction +import dns.zone + + +class UseTransaction(dns.exception.DNSException): + """To alter a versioned zone, use a transaction.""" + + +class Version: + def __init__(self, zone, id): + self.zone = zone + self.id = id + self.nodes = {} + + def _validate_name(self, name): + if name.is_absolute(): + if not name.is_subdomain(self.zone.origin): + raise KeyError("name is not a subdomain of the zone origin") + if self.zone.relativize: + name = name.relativize(self.origin) + return name + + def get_node(self, name): + name = self._validate_name(name) + return self.nodes.get(name) + + def get_rdataset(self, name, rdtype, covers): + node = self.get_node(name) + if node is None: + return None + return node.get_rdataset(self.zone.rdclass, rdtype, covers) + + def items(self): + return self.nodes.items() # pylint: disable=dict-items-not-iterating + + +class WritableVersion(Version): + def __init__(self, zone, replacement=False): + # The zone._versions_lock must be held by our caller. + if len(zone._versions) > 0: + id = zone._versions[-1].id + 1 + else: + id = 1 + super().__init__(zone, id) + if not replacement: + # We copy the map, because that gives us a simple and thread-safe + # way of doing versions, and we have a garbage collector to help + # us. We only make new node objects if we actually change the + # node. + self.nodes.update(zone.nodes) + # We have to copy the zone origin as it may be None in the first + # version, and we don't want to mutate the zone until we commit. + self.origin = zone.origin + self.changed = set() + + def _maybe_cow(self, name): + name = self._validate_name(name) + node = self.nodes.get(name) + if node is None or node.id != self.id: + new_node = self.zone.node_factory() + new_node.id = self.id + if node is not None: + # moo! copy on write! + new_node.rdatasets.extend(node.rdatasets) + self.nodes[name] = new_node + self.changed.add(name) + return new_node + else: + return node + + def delete_node(self, name): + name = self._validate_name(name) + if name in self.nodes: + del self.nodes[name] + self.changed.add(name) + + def put_rdataset(self, name, rdataset): + node = self._maybe_cow(name) + node.replace_rdataset(rdataset) + + def delete_rdataset(self, name, rdtype, covers): + node = self._maybe_cow(name) + node.delete_rdataset(self.zone.rdclass, rdtype, covers) + if len(node) == 0: + del self.nodes[name] + + +@dns.immutable.immutable +class ImmutableVersion(Version): + def __init__(self, version): + # We tell super() that it's a replacement as we don't want it + # to copy the nodes, as we're about to do that with an + # immutable Dict. + super().__init__(version.zone, True) + # set the right id! + self.id = version.id + # Make changed nodes immutable + for name in version.changed: + node = version.nodes.get(name) + # it might not exist if we deleted it in the version + if node: + version.nodes[name] = ImmutableNode(node) + self.nodes = dns.immutable.Dict(version.nodes, True) + + +# A node with a version id. + +class Node(dns.node.Node): + __slots__ = ['id'] + + def __init__(self): + super().__init__() + # A proper id will get set by the Version + self.id = 0 + + +@dns.immutable.immutable +class ImmutableNode(Node): + __slots__ = ['id'] + + def __init__(self, node): + super().__init__() + self.id = node.id + self.rdatasets = tuple( + [dns.rdataset.ImmutableRdataset(rds) for rds in node.rdatasets] + ) + + def find_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE, + create=False): + if create: + raise TypeError("immutable") + return super().find_rdataset(rdclass, rdtype, covers, False) + + def get_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE, + create=False): + if create: + raise TypeError("immutable") + return super().get_rdataset(rdclass, rdtype, covers, False) + + def delete_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE): + raise TypeError("immutable") + + def replace_rdataset(self, replacement): + raise TypeError("immutable") + + +class Zone(dns.zone.Zone): + + __slots__ = ['_versions', '_versions_lock', '_write_txn', + '_write_waiters', '_write_event', '_pruning_policy', + '_readers'] + + node_factory = Node + + def __init__(self, origin, rdclass=dns.rdataclass.IN, relativize=True, + pruning_policy=None): + """Initialize a versioned zone object. + + *origin* is the origin of the zone. It may be a ``dns.name.Name``, + a ``str``, or ``None``. If ``None``, then the zone's origin will + be set by the first ``$ORIGIN`` line in a zone file. + + *rdclass*, an ``int``, the zone's rdata class; the default is class IN. + + *relativize*, a ``bool``, determine's whether domain names are + relativized to the zone's origin. The default is ``True``. + + *pruning policy*, a function taking a `Version` and returning + a `bool`, or `None`. Should the version be pruned? If `None`, + the default policy, which retains one version is used. + """ + super().__init__(origin, rdclass, relativize) + self._versions = collections.deque() + self._version_lock = _threading.Lock() + if pruning_policy is None: + self._pruning_policy = self._default_pruning_policy + else: + self._pruning_policy = pruning_policy + self._write_txn = None + self._write_event = None + self._write_waiters = collections.deque() + self._readers = set() + self._commit_version_unlocked(None, WritableVersion(self), origin) + + def reader(self, id=None, serial=None): # pylint: disable=arguments-differ + if id is not None and serial is not None: + raise ValueError('cannot specify both id and serial') + with self._version_lock: + if id is not None: + version = None + for v in reversed(self._versions): + if v.id == id: + version = v + break + if version is None: + raise KeyError('version not found') + elif serial is not None: + if self.relativize: + oname = dns.name.empty + else: + oname = self.origin + version = None + for v in reversed(self._versions): + n = v.nodes.get(oname) + if n: + rds = n.get_rdataset(self.rdclass, dns.rdatatype.SOA) + if rds and rds[0].serial == serial: + version = v + break + if version is None: + raise KeyError('serial not found') + else: + version = self._versions[-1] + txn = Transaction(self, False, version) + self._readers.add(txn) + return txn + + def writer(self, replacement=False): + event = None + while True: + with self._version_lock: + # Checking event == self._write_event ensures that either + # no one was waiting before we got lucky and found no write + # txn, or we were the one who was waiting and got woken up. + # This prevents "taking cuts" when creating a write txn. + if self._write_txn is None and event == self._write_event: + # Creating the transaction defers version setup + # (i.e. copying the nodes dictionary) until we + # give up the lock, so that we hold the lock as + # short a time as possible. This is why we call + # _setup_version() below. + self._write_txn = Transaction(self, replacement) + # give up our exclusive right to make a Transaction + self._write_event = None + break + # Someone else is writing already, so we will have to + # wait, but we want to do the actual wait outside the + # lock. + event = _threading.Event() + self._write_waiters.append(event) + # wait (note we gave up the lock!) + # + # We only wake one sleeper at a time, so it's important + # that no event waiter can exit this method (e.g. via + # cancelation) without returning a transaction or waking + # someone else up. + # + # This is not a problem with Threading module threads as + # they cannot be canceled, but could be an issue with trio + # or curio tasks when we do the async version of writer(). + # I.e. we'd need to do something like: + # + # try: + # event.wait() + # except trio.Cancelled: + # with self._version_lock: + # self._maybe_wakeup_one_waiter_unlocked() + # raise + # + event.wait() + # Do the deferred version setup. + self._write_txn._setup_version() + return self._write_txn + + def _maybe_wakeup_one_waiter_unlocked(self): + if len(self._write_waiters) > 0: + self._write_event = self._write_waiters.popleft() + self._write_event.set() + + # pylint: disable=unused-argument + def _default_pruning_policy(self, zone, version): + return True + # pylint: enable=unused-argument + + def _prune_versions_unlocked(self): + assert len(self._versions) > 0 + # Don't ever prune a version greater than or equal to one that + # a reader has open. This pins versions in memory while the + # reader is open, and importantly lets the reader open a txn on + # a successor version (e.g. if generating an IXFR). + # + # Note our definition of least_kept also ensures we do not try to + # delete the greatest version. + if len(self._readers) > 0: + least_kept = min(txn.version.id for txn in self._readers) + else: + least_kept = self._versions[-1].id + while self._versions[0].id < least_kept and \ + self._pruning_policy(self, self._versions[0]): + self._versions.popleft() + + def set_max_versions(self, max_versions): + """Set a pruning policy that retains up to the specified number + of versions + """ + if max_versions is not None and max_versions < 1: + raise ValueError('max versions must be at least 1') + if max_versions is None: + def policy(*_): + return False + else: + def policy(zone, _): + return len(zone._versions) > max_versions + self.set_pruning_policy(policy) + + def set_pruning_policy(self, policy): + """Set the pruning policy for the zone. + + The *policy* function takes a `Version` and returns `True` if + the version should be pruned, and `False` otherwise. `None` + may also be specified for policy, in which case the default policy + is used. + + Pruning checking proceeds from the least version and the first + time the function returns `False`, the checking stops. I.e. the + retained versions are always a consecutive sequence. + """ + if policy is None: + policy = self._default_pruning_policy + with self._version_lock: + self._pruning_policy = policy + self._prune_versions_unlocked() + + def _end_read(self, txn): + with self._version_lock: + self._readers.remove(txn) + self._prune_versions_unlocked() + + def _end_write_unlocked(self, txn): + assert self._write_txn == txn + self._write_txn = None + self._maybe_wakeup_one_waiter_unlocked() + + def _end_write(self, txn): + with self._version_lock: + self._end_write_unlocked(txn) + + def _commit_version_unlocked(self, txn, version, origin): + self._versions.append(version) + self._prune_versions_unlocked() + self.nodes = version.nodes + if self.origin is None: + self.origin = origin + # txn can be None in __init__ when we make the empty version. + if txn is not None: + self._end_write_unlocked(txn) + + def _commit_version(self, txn, version, origin): + with self._version_lock: + self._commit_version_unlocked(txn, version, origin) + + def find_node(self, name, create=False): + if create: + raise UseTransaction + return super().find_node(name) + + def delete_node(self, name): + raise UseTransaction + + def find_rdataset(self, name, rdtype, covers=dns.rdatatype.NONE, + create=False): + if create: + raise UseTransaction + rdataset = super().find_rdataset(name, rdtype, covers) + return dns.rdataset.ImmutableRdataset(rdataset) + + def get_rdataset(self, name, rdtype, covers=dns.rdatatype.NONE, + create=False): + if create: + raise UseTransaction + rdataset = super().get_rdataset(name, rdtype, covers) + return dns.rdataset.ImmutableRdataset(rdataset) + + def delete_rdataset(self, name, rdtype, covers=dns.rdatatype.NONE): + raise UseTransaction + + def replace_rdataset(self, name, replacement): + raise UseTransaction + + +class Transaction(dns.transaction.Transaction): + + def __init__(self, zone, replacement, version=None): + read_only = version is not None + super().__init__(zone, replacement, read_only) + self.version = version + + @property + def zone(self): + return self.manager + + def _setup_version(self): + assert self.version is None + self.version = WritableVersion(self.zone, self.replacement) + + def _get_rdataset(self, name, rdtype, covers): + return self.version.get_rdataset(name, rdtype, covers) + + def _put_rdataset(self, name, rdataset): + assert not self.read_only + self.version.put_rdataset(name, rdataset) + + def _delete_name(self, name): + assert not self.read_only + self.version.delete_node(name) + + def _delete_rdataset(self, name, rdtype, covers): + assert not self.read_only + self.version.delete_rdataset(name, rdtype, covers) + + def _name_exists(self, name): + return self.version.get_node(name) is not None + + def _changed(self): + if self.read_only: + return False + else: + return len(self.version.changed) > 0 + + def _end_transaction(self, commit): + if self.read_only: + self.zone._end_read(self) + elif commit and len(self.version.changed) > 0: + self.zone._commit_version(self, ImmutableVersion(self.version), + self.version.origin) + else: + # rollback + self.zone._end_write(self) + + def _set_origin(self, origin): + if self.version.origin is None: + self.version.origin = origin + + def _iterate_rdatasets(self): + for (name, node) in self.version.items(): + for rdataset in node: + yield (name, rdataset) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/wire.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/wire.py new file mode 100644 index 0000000..572e27e --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/wire.py @@ -0,0 +1,85 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import contextlib +import struct + +import dns.exception +import dns.name + +class Parser: + def __init__(self, wire, current=0): + self.wire = wire + self.current = 0 + self.end = len(self.wire) + if current: + self.seek(current) + self.furthest = current + + def remaining(self): + return self.end - self.current + + def get_bytes(self, size): + if size > self.remaining(): + raise dns.exception.FormError + output = self.wire[self.current:self.current + size] + self.current += size + self.furthest = max(self.furthest, self.current) + return output + + def get_counted_bytes(self, length_size=1): + length = int.from_bytes(self.get_bytes(length_size), 'big') + return self.get_bytes(length) + + def get_remaining(self): + return self.get_bytes(self.remaining()) + + def get_uint8(self): + return struct.unpack('!B', self.get_bytes(1))[0] + + def get_uint16(self): + return struct.unpack('!H', self.get_bytes(2))[0] + + def get_uint32(self): + return struct.unpack('!I', self.get_bytes(4))[0] + + def get_uint48(self): + return int.from_bytes(self.get_bytes(6), 'big') + + def get_struct(self, format): + return struct.unpack(format, self.get_bytes(struct.calcsize(format))) + + def get_name(self, origin=None): + name = dns.name.from_wire_parser(self) + if origin: + name = name.relativize(origin) + return name + + def seek(self, where): + # Note that seeking to the end is OK! (If you try to read + # after such a seek, you'll get an exception as expected.) + if where < 0 or where > self.end: + raise dns.exception.FormError + self.current = where + + @contextlib.contextmanager + def restrict_to(self, size): + if size > self.remaining(): + raise dns.exception.FormError + saved_end = self.end + try: + self.end = self.current + size + yield + # We make this check here and not in the finally as we + # don't want to raise if we're already raising for some + # other reason. + if self.current != self.end: + raise dns.exception.FormError + finally: + self.end = saved_end + + @contextlib.contextmanager + def restore_furthest(self): + try: + yield None + finally: + self.current = self.furthest diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/xfr.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/xfr.py new file mode 100644 index 0000000..b07f8b9 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/xfr.py @@ -0,0 +1,295 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.exception +import dns.message +import dns.name +import dns.rcode +import dns.serial +import dns.rdatatype +import dns.zone + + +class TransferError(dns.exception.DNSException): + """A zone transfer response got a non-zero rcode.""" + + def __init__(self, rcode): + message = 'Zone transfer error: %s' % dns.rcode.to_text(rcode) + super().__init__(message) + self.rcode = rcode + + +class SerialWentBackwards(dns.exception.FormError): + """The current serial number is less than the serial we know.""" + + +class UseTCP(dns.exception.DNSException): + """This IXFR cannot be completed with UDP.""" + + +class Inbound: + """ + State machine for zone transfers. + """ + + def __init__(self, txn_manager, rdtype=dns.rdatatype.AXFR, + serial=None, is_udp=False): + """Initialize an inbound zone transfer. + + *txn_manager* is a :py:class:`dns.transaction.TransactionManager`. + + *rdtype* can be `dns.rdatatype.AXFR` or `dns.rdatatype.IXFR` + + *serial* is the base serial number for IXFRs, and is required in + that case. + + *is_udp*, a ``bool`` indidicates if UDP is being used for this + XFR. + """ + self.txn_manager = txn_manager + self.txn = None + self.rdtype = rdtype + if rdtype == dns.rdatatype.IXFR: + if serial is None: + raise ValueError('a starting serial must be supplied for IXFRs') + elif is_udp: + raise ValueError('is_udp specified for AXFR') + self.serial = serial + self.is_udp = is_udp + (_, _, self.origin) = txn_manager.origin_information() + self.soa_rdataset = None + self.done = False + self.expecting_SOA = False + self.delete_mode = False + + def process_message(self, message): + """Process one message in the transfer. + + The message should have the same relativization as was specified when + the `dns.xfr.Inbound` was created. The message should also have been + created with `one_rr_per_rrset=True` because order matters. + + Returns `True` if the transfer is complete, and `False` otherwise. + """ + if self.txn is None: + replacement = self.rdtype == dns.rdatatype.AXFR + self.txn = self.txn_manager.writer(replacement) + rcode = message.rcode() + if rcode != dns.rcode.NOERROR: + raise TransferError(rcode) + # + # We don't require a question section, but if it is present is + # should be correct. + # + if len(message.question) > 0: + if message.question[0].name != self.origin: + raise dns.exception.FormError("wrong question name") + if message.question[0].rdtype != self.rdtype: + raise dns.exception.FormError("wrong question rdatatype") + answer_index = 0 + if self.soa_rdataset is None: + # + # This is the first message. We're expecting an SOA at + # the origin. + # + if not message.answer or message.answer[0].name != self.origin: + raise dns.exception.FormError("No answer or RRset not " + "for zone origin") + rrset = message.answer[0] + name = rrset.name + rdataset = rrset + if rdataset.rdtype != dns.rdatatype.SOA: + raise dns.exception.FormError("first RRset is not an SOA") + answer_index = 1 + self.soa_rdataset = rdataset.copy() + if self.rdtype == dns.rdatatype.IXFR: + if self.soa_rdataset[0].serial == self.serial: + # + # We're already up-to-date. + # + self.done = True + elif dns.serial.Serial(self.soa_rdataset[0].serial) < \ + self.serial: + # It went backwards! + print(dns.serial.Serial(self.soa_rdataset[0].serial), + self.serial) + raise SerialWentBackwards + else: + if self.is_udp and len(message.answer[answer_index:]) == 0: + # + # There are no more records, so this is the + # "truncated" response. Say to use TCP + # + raise UseTCP + # + # Note we're expecting another SOA so we can detect + # if this IXFR response is an AXFR-style response. + # + self.expecting_SOA = True + # + # Process the answer section (other than the initial SOA in + # the first message). + # + for rrset in message.answer[answer_index:]: + name = rrset.name + rdataset = rrset + if self.done: + raise dns.exception.FormError("answers after final SOA") + if rdataset.rdtype == dns.rdatatype.SOA and \ + name == self.origin: + # + # Every time we see an origin SOA delete_mode inverts + # + if self.rdtype == dns.rdatatype.IXFR: + self.delete_mode = not self.delete_mode + # + # If this SOA Rdataset is equal to the first we saw + # then we're finished. If this is an IXFR we also + # check that we're seeing the record in the expected + # part of the response. + # + if rdataset == self.soa_rdataset and \ + (self.rdtype == dns.rdatatype.AXFR or + (self.rdtype == dns.rdatatype.IXFR and + self.delete_mode)): + # + # This is the final SOA + # + if self.expecting_SOA: + # We got an empty IXFR sequence! + raise dns.exception.FormError('empty IXFR sequence') + if self.rdtype == dns.rdatatype.IXFR \ + and self.serial != rdataset[0].serial: + raise dns.exception.FormError('unexpected end of IXFR ' + 'sequence') + self.txn.replace(name, rdataset) + self.txn.commit() + self.txn = None + self.done = True + else: + # + # This is not the final SOA + # + self.expecting_SOA = False + if self.rdtype == dns.rdatatype.IXFR: + if self.delete_mode: + # This is the start of an IXFR deletion set + if rdataset[0].serial != self.serial: + raise dns.exception.FormError( + "IXFR base serial mismatch") + else: + # This is the start of an IXFR addition set + self.serial = rdataset[0].serial + self.txn.replace(name, rdataset) + else: + # We saw a non-final SOA for the origin in an AXFR. + raise dns.exception.FormError('unexpected origin SOA ' + 'in AXFR') + continue + if self.expecting_SOA: + # + # We made an IXFR request and are expecting another + # SOA RR, but saw something else, so this must be an + # AXFR response. + # + self.rdtype = dns.rdatatype.AXFR + self.expecting_SOA = False + self.delete_mode = False + self.txn.rollback() + self.txn = self.txn_manager.writer(True) + # + # Note we are falling through into the code below + # so whatever rdataset this was gets written. + # + # Add or remove the data + if self.delete_mode: + self.txn.delete_exact(name, rdataset) + else: + self.txn.add(name, rdataset) + if self.is_udp and not self.done: + # + # This is a UDP IXFR and we didn't get to done, and we didn't + # get the proper "truncated" response + # + raise dns.exception.FormError('unexpected end of UDP IXFR') + return self.done + + # + # Inbounds are context managers. + # + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + if self.txn: + self.txn.rollback() + return False + + +def make_query(txn_manager, serial=0, + use_edns=None, ednsflags=None, payload=None, + request_payload=None, options=None, + keyring=None, keyname=None, + keyalgorithm=dns.tsig.default_algorithm): + """Make an AXFR or IXFR query. + + *txn_manager* is a ``dns.transaction.TransactionManager``, typically a + ``dns.zone.Zone``. + + *serial* is an ``int`` or ``None``. If 0, then IXFR will be + attempted using the most recent serial number from the + *txn_manager*; it is the caller's responsibility to ensure there + are no write transactions active that could invalidate the + retrieved serial. If a serial cannot be determined, AXFR will be + forced. Other integer values are the starting serial to use. + ``None`` forces an AXFR. + + Please see the documentation for :py:func:`dns.message.make_query` and + :py:func:`dns.message.Message.use_tsig` for details on the other parameters + to this function. + + Returns a `(query, serial)` tuple. + """ + (zone_origin, _, origin) = txn_manager.origin_information() + if serial is None: + rdtype = dns.rdatatype.AXFR + elif not isinstance(serial, int): + raise ValueError('serial is not an integer') + elif serial == 0: + with txn_manager.reader() as txn: + rdataset = txn.get(origin, 'SOA') + if rdataset: + serial = rdataset[0].serial + rdtype = dns.rdatatype.IXFR + else: + serial = None + rdtype = dns.rdatatype.AXFR + elif serial > 0 and serial < 4294967296: + rdtype = dns.rdatatype.IXFR + else: + raise ValueError('serial out-of-range') + q = dns.message.make_query(zone_origin, rdtype, txn_manager.get_class(), + use_edns, False, ednsflags, payload, + request_payload, options) + if serial is not None: + rrset = dns.rrset.from_text(zone_origin, 0, 'IN', 'SOA', + f'. . {serial} 0 0 0 0') + q.authority.append(rrset) + if keyring is not None: + q.use_tsig(keyring, keyname, algorithm=keyalgorithm) + return (q, serial) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/zone.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/zone.py new file mode 100644 index 0000000..c9c1c20 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/zone.py @@ -0,0 +1,926 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Zones.""" + +import contextlib +import io +import os + +import dns.exception +import dns.name +import dns.node +import dns.rdataclass +import dns.rdatatype +import dns.rdata +import dns.rdtypes.ANY.SOA +import dns.rrset +import dns.tokenizer +import dns.transaction +import dns.ttl +import dns.grange +import dns.zonefile + + +class BadZone(dns.exception.DNSException): + + """The DNS zone is malformed.""" + + +class NoSOA(BadZone): + + """The DNS zone has no SOA RR at its origin.""" + + +class NoNS(BadZone): + + """The DNS zone has no NS RRset at its origin.""" + + +class UnknownOrigin(BadZone): + + """The DNS zone's origin is unknown.""" + + +class Zone(dns.transaction.TransactionManager): + + """A DNS zone. + + A ``Zone`` is a mapping from names to nodes. The zone object may be + treated like a Python dictionary, e.g. ``zone[name]`` will retrieve + the node associated with that name. The *name* may be a + ``dns.name.Name object``, or it may be a string. In either case, + if the name is relative it is treated as relative to the origin of + the zone. + """ + + node_factory = dns.node.Node + + __slots__ = ['rdclass', 'origin', 'nodes', 'relativize'] + + def __init__(self, origin, rdclass=dns.rdataclass.IN, relativize=True): + """Initialize a zone object. + + *origin* is the origin of the zone. It may be a ``dns.name.Name``, + a ``str``, or ``None``. If ``None``, then the zone's origin will + be set by the first ``$ORIGIN`` line in a zone file. + + *rdclass*, an ``int``, the zone's rdata class; the default is class IN. + + *relativize*, a ``bool``, determine's whether domain names are + relativized to the zone's origin. The default is ``True``. + """ + + if origin is not None: + if isinstance(origin, str): + origin = dns.name.from_text(origin) + elif not isinstance(origin, dns.name.Name): + raise ValueError("origin parameter must be convertible to a " + "DNS name") + if not origin.is_absolute(): + raise ValueError("origin parameter must be an absolute name") + self.origin = origin + self.rdclass = rdclass + self.nodes = {} + self.relativize = relativize + + def __eq__(self, other): + """Two zones are equal if they have the same origin, class, and + nodes. + + Returns a ``bool``. + """ + + if not isinstance(other, Zone): + return False + if self.rdclass != other.rdclass or \ + self.origin != other.origin or \ + self.nodes != other.nodes: + return False + return True + + def __ne__(self, other): + """Are two zones not equal? + + Returns a ``bool``. + """ + + return not self.__eq__(other) + + def _validate_name(self, name): + if isinstance(name, str): + name = dns.name.from_text(name, None) + elif not isinstance(name, dns.name.Name): + raise KeyError("name parameter must be convertible to a DNS name") + if name.is_absolute(): + if not name.is_subdomain(self.origin): + raise KeyError( + "name parameter must be a subdomain of the zone origin") + if self.relativize: + name = name.relativize(self.origin) + return name + + def __getitem__(self, key): + key = self._validate_name(key) + return self.nodes[key] + + def __setitem__(self, key, value): + key = self._validate_name(key) + self.nodes[key] = value + + def __delitem__(self, key): + key = self._validate_name(key) + del self.nodes[key] + + def __iter__(self): + return self.nodes.__iter__() + + def keys(self): + return self.nodes.keys() # pylint: disable=dict-keys-not-iterating + + def values(self): + return self.nodes.values() # pylint: disable=dict-values-not-iterating + + def items(self): + return self.nodes.items() # pylint: disable=dict-items-not-iterating + + def get(self, key): + key = self._validate_name(key) + return self.nodes.get(key) + + def __contains__(self, other): + return other in self.nodes + + def find_node(self, name, create=False): + """Find a node in the zone, possibly creating it. + + *name*: the name of the node to find. + The value may be a ``dns.name.Name`` or a ``str``. If absolute, the + name must be a subdomain of the zone's origin. If ``zone.relativize`` + is ``True``, then the name will be relativized. + + *create*, a ``bool``. If true, the node will be created if it does + not exist. + + Raises ``KeyError`` if the name is not known and create was + not specified, or if the name was not a subdomain of the origin. + + Returns a ``dns.node.Node``. + """ + + name = self._validate_name(name) + node = self.nodes.get(name) + if node is None: + if not create: + raise KeyError + node = self.node_factory() + self.nodes[name] = node + return node + + def get_node(self, name, create=False): + """Get a node in the zone, possibly creating it. + + This method is like ``find_node()``, except it returns None instead + of raising an exception if the node does not exist and creation + has not been requested. + + *name*: the name of the node to find. + The value may be a ``dns.name.Name`` or a ``str``. If absolute, the + name must be a subdomain of the zone's origin. If ``zone.relativize`` + is ``True``, then the name will be relativized. + + *create*, a ``bool``. If true, the node will be created if it does + not exist. + + Raises ``KeyError`` if the name is not known and create was + not specified, or if the name was not a subdomain of the origin. + + Returns a ``dns.node.Node`` or ``None``. + """ + + try: + node = self.find_node(name, create) + except KeyError: + node = None + return node + + def delete_node(self, name): + """Delete the specified node if it exists. + + *name*: the name of the node to find. + The value may be a ``dns.name.Name`` or a ``str``. If absolute, the + name must be a subdomain of the zone's origin. If ``zone.relativize`` + is ``True``, then the name will be relativized. + + It is not an error if the node does not exist. + """ + + name = self._validate_name(name) + if name in self.nodes: + del self.nodes[name] + + def find_rdataset(self, name, rdtype, covers=dns.rdatatype.NONE, + create=False): + """Look for an rdataset with the specified name and type in the zone, + and return an rdataset encapsulating it. + + The rdataset returned is not a copy; changes to it will change + the zone. + + KeyError is raised if the name or type are not found. + + *name*: the name of the node to find. + The value may be a ``dns.name.Name`` or a ``str``. If absolute, the + name must be a subdomain of the zone's origin. If ``zone.relativize`` + is ``True``, then the name will be relativized. + + *rdtype*, an ``int`` or ``str``, the rdata type desired. + + *covers*, an ``int`` or ``str`` or ``None``, the covered type. + Usually this value is ``dns.rdatatype.NONE``, but if the + rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, + then the covers value will be the rdata type the SIG/RRSIG + covers. The library treats the SIG and RRSIG types as if they + were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). + This makes RRSIGs much easier to work with than if RRSIGs + covering different rdata types were aggregated into a single + RRSIG rdataset. + + *create*, a ``bool``. If true, the node will be created if it does + not exist. + + Raises ``KeyError`` if the name is not known and create was + not specified, or if the name was not a subdomain of the origin. + + Returns a ``dns.rdataset.Rdataset``. + """ + + name = self._validate_name(name) + rdtype = dns.rdatatype.RdataType.make(rdtype) + if covers is not None: + covers = dns.rdatatype.RdataType.make(covers) + node = self.find_node(name, create) + return node.find_rdataset(self.rdclass, rdtype, covers, create) + + def get_rdataset(self, name, rdtype, covers=dns.rdatatype.NONE, + create=False): + """Look for an rdataset with the specified name and type in the zone. + + This method is like ``find_rdataset()``, except it returns None instead + of raising an exception if the rdataset does not exist and creation + has not been requested. + + The rdataset returned is not a copy; changes to it will change + the zone. + + *name*: the name of the node to find. + The value may be a ``dns.name.Name`` or a ``str``. If absolute, the + name must be a subdomain of the zone's origin. If ``zone.relativize`` + is ``True``, then the name will be relativized. + + *rdtype*, an ``int`` or ``str``, the rdata type desired. + + *covers*, an ``int`` or ``str`` or ``None``, the covered type. + Usually this value is ``dns.rdatatype.NONE``, but if the + rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, + then the covers value will be the rdata type the SIG/RRSIG + covers. The library treats the SIG and RRSIG types as if they + were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). + This makes RRSIGs much easier to work with than if RRSIGs + covering different rdata types were aggregated into a single + RRSIG rdataset. + + *create*, a ``bool``. If true, the node will be created if it does + not exist. + + Raises ``KeyError`` if the name is not known and create was + not specified, or if the name was not a subdomain of the origin. + + Returns a ``dns.rdataset.Rdataset`` or ``None``. + """ + + try: + rdataset = self.find_rdataset(name, rdtype, covers, create) + except KeyError: + rdataset = None + return rdataset + + def delete_rdataset(self, name, rdtype, covers=dns.rdatatype.NONE): + """Delete the rdataset matching *rdtype* and *covers*, if it + exists at the node specified by *name*. + + It is not an error if the node does not exist, or if there is no + matching rdataset at the node. + + If the node has no rdatasets after the deletion, it will itself + be deleted. + + *name*: the name of the node to find. + The value may be a ``dns.name.Name`` or a ``str``. If absolute, the + name must be a subdomain of the zone's origin. If ``zone.relativize`` + is ``True``, then the name will be relativized. + + *rdtype*, an ``int`` or ``str``, the rdata type desired. + + *covers*, an ``int`` or ``str`` or ``None``, the covered type. + Usually this value is ``dns.rdatatype.NONE``, but if the + rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, + then the covers value will be the rdata type the SIG/RRSIG + covers. The library treats the SIG and RRSIG types as if they + were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). + This makes RRSIGs much easier to work with than if RRSIGs + covering different rdata types were aggregated into a single + RRSIG rdataset. + """ + + name = self._validate_name(name) + rdtype = dns.rdatatype.RdataType.make(rdtype) + if covers is not None: + covers = dns.rdatatype.RdataType.make(covers) + node = self.get_node(name) + if node is not None: + node.delete_rdataset(self.rdclass, rdtype, covers) + if len(node) == 0: + self.delete_node(name) + + def replace_rdataset(self, name, replacement): + """Replace an rdataset at name. + + It is not an error if there is no rdataset matching I{replacement}. + + Ownership of the *replacement* object is transferred to the zone; + in other words, this method does not store a copy of *replacement* + at the node, it stores *replacement* itself. + + If the node does not exist, it is created. + + *name*: the name of the node to find. + The value may be a ``dns.name.Name`` or a ``str``. If absolute, the + name must be a subdomain of the zone's origin. If ``zone.relativize`` + is ``True``, then the name will be relativized. + + *replacement*, a ``dns.rdataset.Rdataset``, the replacement rdataset. + """ + + if replacement.rdclass != self.rdclass: + raise ValueError('replacement.rdclass != zone.rdclass') + node = self.find_node(name, True) + node.replace_rdataset(replacement) + + def find_rrset(self, name, rdtype, covers=dns.rdatatype.NONE): + """Look for an rdataset with the specified name and type in the zone, + and return an RRset encapsulating it. + + This method is less efficient than the similar + ``find_rdataset()`` because it creates an RRset instead of + returning the matching rdataset. It may be more convenient + for some uses since it returns an object which binds the owner + name to the rdataset. + + This method may not be used to create new nodes or rdatasets; + use ``find_rdataset`` instead. + + *name*: the name of the node to find. + The value may be a ``dns.name.Name`` or a ``str``. If absolute, the + name must be a subdomain of the zone's origin. If ``zone.relativize`` + is ``True``, then the name will be relativized. + + *rdtype*, an ``int`` or ``str``, the rdata type desired. + + *covers*, an ``int`` or ``str`` or ``None``, the covered type. + Usually this value is ``dns.rdatatype.NONE``, but if the + rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, + then the covers value will be the rdata type the SIG/RRSIG + covers. The library treats the SIG and RRSIG types as if they + were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). + This makes RRSIGs much easier to work with than if RRSIGs + covering different rdata types were aggregated into a single + RRSIG rdataset. + + *create*, a ``bool``. If true, the node will be created if it does + not exist. + + Raises ``KeyError`` if the name is not known and create was + not specified, or if the name was not a subdomain of the origin. + + Returns a ``dns.rrset.RRset`` or ``None``. + """ + + name = self._validate_name(name) + rdtype = dns.rdatatype.RdataType.make(rdtype) + if covers is not None: + covers = dns.rdatatype.RdataType.make(covers) + rdataset = self.nodes[name].find_rdataset(self.rdclass, rdtype, covers) + rrset = dns.rrset.RRset(name, self.rdclass, rdtype, covers) + rrset.update(rdataset) + return rrset + + def get_rrset(self, name, rdtype, covers=dns.rdatatype.NONE): + """Look for an rdataset with the specified name and type in the zone, + and return an RRset encapsulating it. + + This method is less efficient than the similar ``get_rdataset()`` + because it creates an RRset instead of returning the matching + rdataset. It may be more convenient for some uses since it + returns an object which binds the owner name to the rdataset. + + This method may not be used to create new nodes or rdatasets; + use ``get_rdataset()`` instead. + + *name*: the name of the node to find. + The value may be a ``dns.name.Name`` or a ``str``. If absolute, the + name must be a subdomain of the zone's origin. If ``zone.relativize`` + is ``True``, then the name will be relativized. + + *rdtype*, an ``int`` or ``str``, the rdata type desired. + + *covers*, an ``int`` or ``str`` or ``None``, the covered type. + Usually this value is ``dns.rdatatype.NONE``, but if the + rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, + then the covers value will be the rdata type the SIG/RRSIG + covers. The library treats the SIG and RRSIG types as if they + were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). + This makes RRSIGs much easier to work with than if RRSIGs + covering different rdata types were aggregated into a single + RRSIG rdataset. + + *create*, a ``bool``. If true, the node will be created if it does + not exist. + + Raises ``KeyError`` if the name is not known and create was + not specified, or if the name was not a subdomain of the origin. + + Returns a ``dns.rrset.RRset`` or ``None``. + """ + + try: + rrset = self.find_rrset(name, rdtype, covers) + except KeyError: + rrset = None + return rrset + + def iterate_rdatasets(self, rdtype=dns.rdatatype.ANY, + covers=dns.rdatatype.NONE): + """Return a generator which yields (name, rdataset) tuples for + all rdatasets in the zone which have the specified *rdtype* + and *covers*. If *rdtype* is ``dns.rdatatype.ANY``, the default, + then all rdatasets will be matched. + + *rdtype*, an ``int`` or ``str``, the rdata type desired. + + *covers*, an ``int`` or ``str`` or ``None``, the covered type. + Usually this value is ``dns.rdatatype.NONE``, but if the + rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, + then the covers value will be the rdata type the SIG/RRSIG + covers. The library treats the SIG and RRSIG types as if they + were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). + This makes RRSIGs much easier to work with than if RRSIGs + covering different rdata types were aggregated into a single + RRSIG rdataset. + """ + + rdtype = dns.rdatatype.RdataType.make(rdtype) + if covers is not None: + covers = dns.rdatatype.RdataType.make(covers) + for (name, node) in self.items(): + for rds in node: + if rdtype == dns.rdatatype.ANY or \ + (rds.rdtype == rdtype and rds.covers == covers): + yield (name, rds) + + def iterate_rdatas(self, rdtype=dns.rdatatype.ANY, + covers=dns.rdatatype.NONE): + """Return a generator which yields (name, ttl, rdata) tuples for + all rdatas in the zone which have the specified *rdtype* + and *covers*. If *rdtype* is ``dns.rdatatype.ANY``, the default, + then all rdatas will be matched. + + *rdtype*, an ``int`` or ``str``, the rdata type desired. + + *covers*, an ``int`` or ``str`` or ``None``, the covered type. + Usually this value is ``dns.rdatatype.NONE``, but if the + rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, + then the covers value will be the rdata type the SIG/RRSIG + covers. The library treats the SIG and RRSIG types as if they + were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). + This makes RRSIGs much easier to work with than if RRSIGs + covering different rdata types were aggregated into a single + RRSIG rdataset. + """ + + rdtype = dns.rdatatype.RdataType.make(rdtype) + if covers is not None: + covers = dns.rdatatype.RdataType.make(covers) + for (name, node) in self.items(): + for rds in node: + if rdtype == dns.rdatatype.ANY or \ + (rds.rdtype == rdtype and rds.covers == covers): + for rdata in rds: + yield (name, rds.ttl, rdata) + + def to_file(self, f, sorted=True, relativize=True, nl=None, + want_comments=False): + """Write a zone to a file. + + *f*, a file or `str`. If *f* is a string, it is treated + as the name of a file to open. + + *sorted*, a ``bool``. If True, the default, then the file + will be written with the names sorted in DNSSEC order from + least to greatest. Otherwise the names will be written in + whatever order they happen to have in the zone's dictionary. + + *relativize*, a ``bool``. If True, the default, then domain + names in the output will be relativized to the zone's origin + if possible. + + *nl*, a ``str`` or None. The end of line string. If not + ``None``, the output will use the platform's native + end-of-line marker (i.e. LF on POSIX, CRLF on Windows). + + *want_comments*, a ``bool``. If ``True``, emit end-of-line comments + as part of writing the file. If ``False``, the default, do not + emit them. + """ + + with contextlib.ExitStack() as stack: + if isinstance(f, str): + f = stack.enter_context(open(f, 'wb')) + + # must be in this way, f.encoding may contain None, or even + # attribute may not be there + file_enc = getattr(f, 'encoding', None) + if file_enc is None: + file_enc = 'utf-8' + + if nl is None: + # binary mode, '\n' is not enough + nl_b = os.linesep.encode(file_enc) + nl = '\n' + elif isinstance(nl, str): + nl_b = nl.encode(file_enc) + else: + nl_b = nl + nl = nl.decode() + + if sorted: + names = list(self.keys()) + names.sort() + else: + names = self.keys() + for n in names: + l = self[n].to_text(n, origin=self.origin, + relativize=relativize, + want_comments=want_comments) + l_b = l.encode(file_enc) + + try: + f.write(l_b) + f.write(nl_b) + except TypeError: # textual mode + f.write(l) + f.write(nl) + + def to_text(self, sorted=True, relativize=True, nl=None, + want_comments=False): + """Return a zone's text as though it were written to a file. + + *sorted*, a ``bool``. If True, the default, then the file + will be written with the names sorted in DNSSEC order from + least to greatest. Otherwise the names will be written in + whatever order they happen to have in the zone's dictionary. + + *relativize*, a ``bool``. If True, the default, then domain + names in the output will be relativized to the zone's origin + if possible. + + *nl*, a ``str`` or None. The end of line string. If not + ``None``, the output will use the platform's native + end-of-line marker (i.e. LF on POSIX, CRLF on Windows). + + *want_comments*, a ``bool``. If ``True``, emit end-of-line comments + as part of writing the file. If ``False``, the default, do not + emit them. + + Returns a ``str``. + """ + temp_buffer = io.StringIO() + self.to_file(temp_buffer, sorted, relativize, nl, want_comments) + return_value = temp_buffer.getvalue() + temp_buffer.close() + return return_value + + def check_origin(self): + """Do some simple checking of the zone's origin. + + Raises ``dns.zone.NoSOA`` if there is no SOA RRset. + + Raises ``dns.zone.NoNS`` if there is no NS RRset. + + Raises ``KeyError`` if there is no origin node. + """ + if self.relativize: + name = dns.name.empty + else: + name = self.origin + if self.get_rdataset(name, dns.rdatatype.SOA) is None: + raise NoSOA + if self.get_rdataset(name, dns.rdatatype.NS) is None: + raise NoNS + + # TransactionManager methods + + def reader(self): + return Transaction(self, False, True) + + def writer(self, replacement=False): + return Transaction(self, replacement, False) + + def origin_information(self): + if self.relativize: + effective = dns.name.empty + else: + effective = self.origin + return (self.origin, self.relativize, effective) + + def get_class(self): + return self.rdclass + + +class Transaction(dns.transaction.Transaction): + + _deleted_rdataset = dns.rdataset.Rdataset(dns.rdataclass.ANY, + dns.rdatatype.ANY) + + def __init__(self, zone, replacement, read_only): + super().__init__(zone, replacement, read_only) + self.rdatasets = {} + + @property + def zone(self): + return self.manager + + def _get_rdataset(self, name, rdtype, covers): + rdataset = self.rdatasets.get((name, rdtype, covers)) + if rdataset is self._deleted_rdataset: + return None + elif rdataset is None: + rdataset = self.zone.get_rdataset(name, rdtype, covers) + return rdataset + + def _put_rdataset(self, name, rdataset): + assert not self.read_only + self.zone._validate_name(name) + self.rdatasets[(name, rdataset.rdtype, rdataset.covers)] = rdataset + + def _delete_name(self, name): + assert not self.read_only + # First remove any changes involving the name + remove = [] + for key in self.rdatasets: + if key[0] == name: + remove.append(key) + if len(remove) > 0: + for key in remove: + del self.rdatasets[key] + # Next add deletion records for any rdatasets matching the + # name in the zone + node = self.zone.get_node(name) + if node is not None: + for rdataset in node.rdatasets: + self.rdatasets[(name, rdataset.rdtype, rdataset.covers)] = \ + self._deleted_rdataset + + def _delete_rdataset(self, name, rdtype, covers): + assert not self.read_only + try: + del self.rdatasets[(name, rdtype, covers)] + except KeyError: + pass + rdataset = self.zone.get_rdataset(name, rdtype, covers) + if rdataset is not None: + self.rdatasets[(name, rdataset.rdtype, rdataset.covers)] = \ + self._deleted_rdataset + + def _name_exists(self, name): + for key, rdataset in self.rdatasets.items(): + if key[0] == name: + if rdataset != self._deleted_rdataset: + return True + else: + return None + self.zone._validate_name(name) + if self.zone.get_node(name): + return True + return False + + def _changed(self): + if self.read_only: + return False + else: + return len(self.rdatasets) > 0 + + def _end_transaction(self, commit): + if commit and self._changed(): + for (name, rdtype, covers), rdataset in \ + self.rdatasets.items(): + if rdataset is self._deleted_rdataset: + self.zone.delete_rdataset(name, rdtype, covers) + else: + self.zone.replace_rdataset(name, rdataset) + + def _set_origin(self, origin): + if self.zone.origin is None: + self.zone.origin = origin + + def _iterate_rdatasets(self): + # Expensive but simple! Use a versioned zone for efficient txn + # iteration. + rdatasets = {} + for (name, rdataset) in self.zone.iterate_rdatasets(): + rdatasets[(name, rdataset.rdtype, rdataset.covers)] = rdataset + rdatasets.update(self.rdatasets) + for (name, _, _), rdataset in rdatasets.items(): + yield (name, rdataset) + + +def from_text(text, origin=None, rdclass=dns.rdataclass.IN, + relativize=True, zone_factory=Zone, filename=None, + allow_include=False, check_origin=True, idna_codec=None): + """Build a zone object from a zone file format string. + + *text*, a ``str``, the zone file format input. + + *origin*, a ``dns.name.Name``, a ``str``, or ``None``. The origin + of the zone; if not specified, the first ``$ORIGIN`` statement in the + zone file will determine the origin of the zone. + + *rdclass*, an ``int``, the zone's rdata class; the default is class IN. + + *relativize*, a ``bool``, determine's whether domain names are + relativized to the zone's origin. The default is ``True``. + + *zone_factory*, the zone factory to use or ``None``. If ``None``, then + ``dns.zone.Zone`` will be used. The value may be any class or callable + that returns a subclass of ``dns.zone.Zone``. + + *filename*, a ``str`` or ``None``, the filename to emit when + describing where an error occurred; the default is ``''``. + + *allow_include*, a ``bool``. If ``True``, the default, then ``$INCLUDE`` + directives are permitted. If ``False``, then encoutering a ``$INCLUDE`` + will raise a ``SyntaxError`` exception. + + *check_origin*, a ``bool``. If ``True``, the default, then sanity + checks of the origin node will be made by calling the zone's + ``check_origin()`` method. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder + is used. + + Raises ``dns.zone.NoSOA`` if there is no SOA RRset. + + Raises ``dns.zone.NoNS`` if there is no NS RRset. + + Raises ``KeyError`` if there is no origin node. + + Returns a subclass of ``dns.zone.Zone``. + """ + + # 'text' can also be a file, but we don't publish that fact + # since it's an implementation detail. The official file + # interface is from_file(). + + if filename is None: + filename = '' + zone = zone_factory(origin, rdclass, relativize=relativize) + with zone.writer(True) as txn: + tok = dns.tokenizer.Tokenizer(text, filename, idna_codec=idna_codec) + reader = dns.zonefile.Reader(tok, rdclass, txn, + allow_include=allow_include) + try: + reader.read() + except dns.zonefile.UnknownOrigin: + # for backwards compatibility + raise dns.zone.UnknownOrigin + # Now that we're done reading, do some basic checking of the zone. + if check_origin: + zone.check_origin() + return zone + + +def from_file(f, origin=None, rdclass=dns.rdataclass.IN, + relativize=True, zone_factory=Zone, filename=None, + allow_include=True, check_origin=True): + """Read a zone file and build a zone object. + + *f*, a file or ``str``. If *f* is a string, it is treated + as the name of a file to open. + + *origin*, a ``dns.name.Name``, a ``str``, or ``None``. The origin + of the zone; if not specified, the first ``$ORIGIN`` statement in the + zone file will determine the origin of the zone. + + *rdclass*, an ``int``, the zone's rdata class; the default is class IN. + + *relativize*, a ``bool``, determine's whether domain names are + relativized to the zone's origin. The default is ``True``. + + *zone_factory*, the zone factory to use or ``None``. If ``None``, then + ``dns.zone.Zone`` will be used. The value may be any class or callable + that returns a subclass of ``dns.zone.Zone``. + + *filename*, a ``str`` or ``None``, the filename to emit when + describing where an error occurred; the default is ``''``. + + *allow_include*, a ``bool``. If ``True``, the default, then ``$INCLUDE`` + directives are permitted. If ``False``, then encoutering a ``$INCLUDE`` + will raise a ``SyntaxError`` exception. + + *check_origin*, a ``bool``. If ``True``, the default, then sanity + checks of the origin node will be made by calling the zone's + ``check_origin()`` method. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder + is used. + + Raises ``dns.zone.NoSOA`` if there is no SOA RRset. + + Raises ``dns.zone.NoNS`` if there is no NS RRset. + + Raises ``KeyError`` if there is no origin node. + + Returns a subclass of ``dns.zone.Zone``. + """ + + with contextlib.ExitStack() as stack: + if isinstance(f, str): + if filename is None: + filename = f + f = stack.enter_context(open(f)) + return from_text(f, origin, rdclass, relativize, zone_factory, + filename, allow_include, check_origin) + + +def from_xfr(xfr, zone_factory=Zone, relativize=True, check_origin=True): + """Convert the output of a zone transfer generator into a zone object. + + *xfr*, a generator of ``dns.message.Message`` objects, typically + ``dns.query.xfr()``. + + *relativize*, a ``bool``, determine's whether domain names are + relativized to the zone's origin. The default is ``True``. + It is essential that the relativize setting matches the one specified + to the generator. + + *check_origin*, a ``bool``. If ``True``, the default, then sanity + checks of the origin node will be made by calling the zone's + ``check_origin()`` method. + + Raises ``dns.zone.NoSOA`` if there is no SOA RRset. + + Raises ``dns.zone.NoNS`` if there is no NS RRset. + + Raises ``KeyError`` if there is no origin node. + + Returns a subclass of ``dns.zone.Zone``. + """ + + z = None + for r in xfr: + if z is None: + if relativize: + origin = r.origin + else: + origin = r.answer[0].name + rdclass = r.answer[0].rdclass + z = zone_factory(origin, rdclass, relativize=relativize) + for rrset in r.answer: + znode = z.nodes.get(rrset.name) + if not znode: + znode = z.node_factory() + z.nodes[rrset.name] = znode + zrds = znode.find_rdataset(rrset.rdclass, rrset.rdtype, + rrset.covers, True) + zrds.update_ttl(rrset.ttl) + for rd in rrset: + zrds.add(rd) + if check_origin: + z.check_origin() + return z diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/zonefile.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/zonefile.py new file mode 100644 index 0000000..92e2f0c --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/build/lib/dns/zonefile.py @@ -0,0 +1,401 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Zones.""" + +import re +import sys + +import dns.exception +import dns.name +import dns.node +import dns.rdataclass +import dns.rdatatype +import dns.rdata +import dns.rdtypes.ANY.SOA +import dns.rrset +import dns.tokenizer +import dns.transaction +import dns.ttl +import dns.grange + + +class UnknownOrigin(dns.exception.DNSException): + """Unknown origin""" + + +class Reader: + + """Read a DNS zone file into a transaction.""" + + def __init__(self, tok, rdclass, txn, allow_include=False): + self.tok = tok + (self.zone_origin, self.relativize, _) = \ + txn.manager.origin_information() + self.current_origin = self.zone_origin + self.last_ttl = 0 + self.last_ttl_known = False + self.default_ttl = 0 + self.default_ttl_known = False + self.last_name = self.current_origin + self.zone_rdclass = rdclass + self.txn = txn + self.saved_state = [] + self.current_file = None + self.allow_include = allow_include + + def _eat_line(self): + while 1: + token = self.tok.get() + if token.is_eol_or_eof(): + break + + def _rr_line(self): + """Process one line from a DNS zone file.""" + # Name + if self.current_origin is None: + raise UnknownOrigin + token = self.tok.get(want_leading=True) + if not token.is_whitespace(): + self.last_name = self.tok.as_name(token, self.current_origin) + else: + token = self.tok.get() + if token.is_eol_or_eof(): + # treat leading WS followed by EOL/EOF as if they were EOL/EOF. + return + self.tok.unget(token) + name = self.last_name + if not name.is_subdomain(self.zone_origin): + self._eat_line() + return + if self.relativize: + name = name.relativize(self.zone_origin) + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + + # TTL + ttl = None + try: + ttl = dns.ttl.from_text(token.value) + self.last_ttl = ttl + self.last_ttl_known = True + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + except dns.ttl.BadTTL: + if self.default_ttl_known: + ttl = self.default_ttl + elif self.last_ttl_known: + ttl = self.last_ttl + + # Class + try: + rdclass = dns.rdataclass.from_text(token.value) + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + except dns.exception.SyntaxError: + raise + except Exception: + rdclass = self.zone_rdclass + if rdclass != self.zone_rdclass: + raise dns.exception.SyntaxError("RR class is not zone's class") + # Type + try: + rdtype = dns.rdatatype.from_text(token.value) + except Exception: + raise dns.exception.SyntaxError( + "unknown rdatatype '%s'" % token.value) + try: + rd = dns.rdata.from_text(rdclass, rdtype, self.tok, + self.current_origin, self.relativize, + self.zone_origin) + except dns.exception.SyntaxError: + # Catch and reraise. + raise + except Exception: + # All exceptions that occur in the processing of rdata + # are treated as syntax errors. This is not strictly + # correct, but it is correct almost all of the time. + # We convert them to syntax errors so that we can emit + # helpful filename:line info. + (ty, va) = sys.exc_info()[:2] + raise dns.exception.SyntaxError( + "caught exception {}: {}".format(str(ty), str(va))) + + if not self.default_ttl_known and rdtype == dns.rdatatype.SOA: + # The pre-RFC2308 and pre-BIND9 behavior inherits the zone default + # TTL from the SOA minttl if no $TTL statement is present before the + # SOA is parsed. + self.default_ttl = rd.minimum + self.default_ttl_known = True + if ttl is None: + # if we didn't have a TTL on the SOA, set it! + ttl = rd.minimum + + # TTL check. We had to wait until now to do this as the SOA RR's + # own TTL can be inferred from its minimum. + if ttl is None: + raise dns.exception.SyntaxError("Missing default TTL value") + + self.txn.add(name, ttl, rd) + + def _parse_modify(self, side): + # Here we catch everything in '{' '}' in a group so we can replace it + # with ''. + is_generate1 = re.compile(r"^.*\$({(\+|-?)(\d+),(\d+),(.)}).*$") + is_generate2 = re.compile(r"^.*\$({(\+|-?)(\d+)}).*$") + is_generate3 = re.compile(r"^.*\$({(\+|-?)(\d+),(\d+)}).*$") + # Sometimes there are modifiers in the hostname. These come after + # the dollar sign. They are in the form: ${offset[,width[,base]]}. + # Make names + g1 = is_generate1.match(side) + if g1: + mod, sign, offset, width, base = g1.groups() + if sign == '': + sign = '+' + g2 = is_generate2.match(side) + if g2: + mod, sign, offset = g2.groups() + if sign == '': + sign = '+' + width = 0 + base = 'd' + g3 = is_generate3.match(side) + if g3: + mod, sign, offset, width = g3.groups() + if sign == '': + sign = '+' + base = 'd' + + if not (g1 or g2 or g3): + mod = '' + sign = '+' + offset = 0 + width = 0 + base = 'd' + + if base != 'd': + raise NotImplementedError() + + return mod, sign, offset, width, base + + def _generate_line(self): + # range lhs [ttl] [class] type rhs [ comment ] + """Process one line containing the GENERATE statement from a DNS + zone file.""" + if self.current_origin is None: + raise UnknownOrigin + + token = self.tok.get() + # Range (required) + try: + start, stop, step = dns.grange.from_text(token.value) + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + except Exception: + raise dns.exception.SyntaxError + + # lhs (required) + try: + lhs = token.value + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + except Exception: + raise dns.exception.SyntaxError + + # TTL + try: + ttl = dns.ttl.from_text(token.value) + self.last_ttl = ttl + self.last_ttl_known = True + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + except dns.ttl.BadTTL: + if not (self.last_ttl_known or self.default_ttl_known): + raise dns.exception.SyntaxError("Missing default TTL value") + if self.default_ttl_known: + ttl = self.default_ttl + elif self.last_ttl_known: + ttl = self.last_ttl + # Class + try: + rdclass = dns.rdataclass.from_text(token.value) + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + except dns.exception.SyntaxError: + raise dns.exception.SyntaxError + except Exception: + rdclass = self.zone_rdclass + if rdclass != self.zone_rdclass: + raise dns.exception.SyntaxError("RR class is not zone's class") + # Type + try: + rdtype = dns.rdatatype.from_text(token.value) + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + except Exception: + raise dns.exception.SyntaxError("unknown rdatatype '%s'" % + token.value) + + # rhs (required) + rhs = token.value + + # The code currently only supports base 'd', so the last value + # in the tuple _parse_modify returns is ignored + lmod, lsign, loffset, lwidth, _ = self._parse_modify(lhs) + rmod, rsign, roffset, rwidth, _ = self._parse_modify(rhs) + for i in range(start, stop + 1, step): + # +1 because bind is inclusive and python is exclusive + + if lsign == '+': + lindex = i + int(loffset) + elif lsign == '-': + lindex = i - int(loffset) + + if rsign == '-': + rindex = i - int(roffset) + elif rsign == '+': + rindex = i + int(roffset) + + lzfindex = str(lindex).zfill(int(lwidth)) + rzfindex = str(rindex).zfill(int(rwidth)) + + name = lhs.replace('$%s' % (lmod), lzfindex) + rdata = rhs.replace('$%s' % (rmod), rzfindex) + + self.last_name = dns.name.from_text(name, self.current_origin, + self.tok.idna_codec) + name = self.last_name + if not name.is_subdomain(self.zone_origin): + self._eat_line() + return + if self.relativize: + name = name.relativize(self.zone_origin) + + try: + rd = dns.rdata.from_text(rdclass, rdtype, rdata, + self.current_origin, self.relativize, + self.zone_origin) + except dns.exception.SyntaxError: + # Catch and reraise. + raise + except Exception: + # All exceptions that occur in the processing of rdata + # are treated as syntax errors. This is not strictly + # correct, but it is correct almost all of the time. + # We convert them to syntax errors so that we can emit + # helpful filename:line info. + (ty, va) = sys.exc_info()[:2] + raise dns.exception.SyntaxError("caught exception %s: %s" % + (str(ty), str(va))) + + self.txn.add(name, ttl, rd) + + def read(self): + """Read a DNS zone file and build a zone object. + + @raises dns.zone.NoSOA: No SOA RR was found at the zone origin + @raises dns.zone.NoNS: No NS RRset was found at the zone origin + """ + + try: + while 1: + token = self.tok.get(True, True) + if token.is_eof(): + if self.current_file is not None: + self.current_file.close() + if len(self.saved_state) > 0: + (self.tok, + self.current_origin, + self.last_name, + self.current_file, + self.last_ttl, + self.last_ttl_known, + self.default_ttl, + self.default_ttl_known) = self.saved_state.pop(-1) + continue + break + elif token.is_eol(): + continue + elif token.is_comment(): + self.tok.get_eol() + continue + elif token.value[0] == '$': + c = token.value.upper() + if c == '$TTL': + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError("bad $TTL") + self.default_ttl = dns.ttl.from_text(token.value) + self.default_ttl_known = True + self.tok.get_eol() + elif c == '$ORIGIN': + self.current_origin = self.tok.get_name() + self.tok.get_eol() + if self.zone_origin is None: + self.zone_origin = self.current_origin + self.txn._set_origin(self.current_origin) + elif c == '$INCLUDE' and self.allow_include: + token = self.tok.get() + filename = token.value + token = self.tok.get() + if token.is_identifier(): + new_origin =\ + dns.name.from_text(token.value, + self.current_origin, + self.tok.idna_codec) + self.tok.get_eol() + elif not token.is_eol_or_eof(): + raise dns.exception.SyntaxError( + "bad origin in $INCLUDE") + else: + new_origin = self.current_origin + self.saved_state.append((self.tok, + self.current_origin, + self.last_name, + self.current_file, + self.last_ttl, + self.last_ttl_known, + self.default_ttl, + self.default_ttl_known)) + self.current_file = open(filename, 'r') + self.tok = dns.tokenizer.Tokenizer(self.current_file, + filename) + self.current_origin = new_origin + elif c == '$GENERATE': + self._generate_line() + else: + raise dns.exception.SyntaxError( + "Unknown zone file directive '" + c + "'") + continue + self.tok.unget(token) + self._rr_line() + except dns.exception.SyntaxError as detail: + (filename, line_number) = self.tok.where() + if detail is None: + detail = "syntax error" + ex = dns.exception.SyntaxError( + "%s:%d: %s" % (filename, line_number, detail)) + tb = sys.exc_info()[2] + raise ex.with_traceback(tb) from None diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dist/dnspython-2.1.0-py3.9.egg b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dist/dnspython-2.1.0-py3.9.egg new file mode 100644 index 0000000..0301012 Binary files /dev/null and b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dist/dnspython-2.1.0-py3.9.egg differ diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/__init__.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/__init__.py new file mode 100644 index 0000000..0473ca1 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/__init__.py @@ -0,0 +1,66 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009, 2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""dnspython DNS toolkit""" + +__all__ = [ + 'asyncbackend', + 'asyncquery', + 'asyncresolver', + 'dnssec', + 'e164', + 'edns', + 'entropy', + 'exception', + 'flags', + 'immutable', + 'inet', + 'ipv4', + 'ipv6', + 'message', + 'name', + 'namedict', + 'node', + 'opcode', + 'query', + 'rcode', + 'rdata', + 'rdataclass', + 'rdataset', + 'rdatatype', + 'renderer', + 'resolver', + 'reversename', + 'rrset', + 'serial', + 'set', + 'tokenizer', + 'transaction', + 'tsig', + 'tsigkeyring', + 'ttl', + 'rdtypes', + 'update', + 'version', + 'versioned', + 'wire', + 'xfr', + 'zone', + 'zonefile', +] + +from dns.version import version as __version__ # noqa diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/_asyncbackend.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/_asyncbackend.py new file mode 100644 index 0000000..c7ecfad --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/_asyncbackend.py @@ -0,0 +1,60 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# This is a nullcontext for both sync and async. 3.7 has a nullcontext, +# but it is only for sync use. + +class NullContext: + def __init__(self, enter_result=None): + self.enter_result = enter_result + + def __enter__(self): + return self.enter_result + + def __exit__(self, exc_type, exc_value, traceback): + pass + + async def __aenter__(self): + return self.enter_result + + async def __aexit__(self, exc_type, exc_value, traceback): + pass + + +# These are declared here so backends can import them without creating +# circular dependencies with dns.asyncbackend. + +class Socket: # pragma: no cover + async def close(self): + pass + + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc_value, traceback): + await self.close() + + +class DatagramSocket(Socket): # pragma: no cover + async def sendto(self, what, destination, timeout): + pass + + async def recvfrom(self, size, timeout): + pass + + +class StreamSocket(Socket): # pragma: no cover + async def sendall(self, what, destination, timeout): + pass + + async def recv(self, size, timeout): + pass + + +class Backend: # pragma: no cover + def name(self): + return 'unknown' + + async def make_socket(self, af, socktype, proto=0, + source=None, destination=None, timeout=None, + ssl_context=None, server_hostname=None): + raise NotImplementedError diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/_asyncio_backend.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/_asyncio_backend.py new file mode 100644 index 0000000..6a56332 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/_asyncio_backend.py @@ -0,0 +1,138 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +"""asyncio library query support""" + +import socket +import asyncio + +import dns._asyncbackend +import dns.exception + + +def _get_running_loop(): + try: + return asyncio.get_running_loop() + except AttributeError: # pragma: no cover + return asyncio.get_event_loop() + + +class _DatagramProtocol: + def __init__(self): + self.transport = None + self.recvfrom = None + + def connection_made(self, transport): + self.transport = transport + + def datagram_received(self, data, addr): + if self.recvfrom: + self.recvfrom.set_result((data, addr)) + self.recvfrom = None + + def error_received(self, exc): # pragma: no cover + if self.recvfrom and not self.recvfrom.done(): + self.recvfrom.set_exception(exc) + + def connection_lost(self, exc): + if self.recvfrom and not self.recvfrom.done(): + self.recvfrom.set_exception(exc) + + def close(self): + self.transport.close() + + +async def _maybe_wait_for(awaitable, timeout): + if timeout: + try: + return await asyncio.wait_for(awaitable, timeout) + except asyncio.TimeoutError: + raise dns.exception.Timeout(timeout=timeout) + else: + return await awaitable + + +class DatagramSocket(dns._asyncbackend.DatagramSocket): + def __init__(self, family, transport, protocol): + self.family = family + self.transport = transport + self.protocol = protocol + + async def sendto(self, what, destination, timeout): # pragma: no cover + # no timeout for asyncio sendto + self.transport.sendto(what, destination) + + async def recvfrom(self, size, timeout): + # ignore size as there's no way I know to tell protocol about it + done = _get_running_loop().create_future() + assert self.protocol.recvfrom is None + self.protocol.recvfrom = done + await _maybe_wait_for(done, timeout) + return done.result() + + async def close(self): + self.protocol.close() + + async def getpeername(self): + return self.transport.get_extra_info('peername') + + async def getsockname(self): + return self.transport.get_extra_info('sockname') + + +class StreamSocket(dns._asyncbackend.DatagramSocket): + def __init__(self, af, reader, writer): + self.family = af + self.reader = reader + self.writer = writer + + async def sendall(self, what, timeout): + self.writer.write(what) + return await _maybe_wait_for(self.writer.drain(), timeout) + + async def recv(self, count, timeout): + return await _maybe_wait_for(self.reader.read(count), + timeout) + + async def close(self): + self.writer.close() + try: + await self.writer.wait_closed() + except AttributeError: # pragma: no cover + pass + + async def getpeername(self): + return self.writer.get_extra_info('peername') + + async def getsockname(self): + return self.writer.get_extra_info('sockname') + + +class Backend(dns._asyncbackend.Backend): + def name(self): + return 'asyncio' + + async def make_socket(self, af, socktype, proto=0, + source=None, destination=None, timeout=None, + ssl_context=None, server_hostname=None): + loop = _get_running_loop() + if socktype == socket.SOCK_DGRAM: + transport, protocol = await loop.create_datagram_endpoint( + _DatagramProtocol, source, family=af, + proto=proto) + return DatagramSocket(af, transport, protocol) + elif socktype == socket.SOCK_STREAM: + (r, w) = await _maybe_wait_for( + asyncio.open_connection(destination[0], + destination[1], + ssl=ssl_context, + family=af, + proto=proto, + local_addr=source, + server_hostname=server_hostname), + timeout) + return StreamSocket(af, r, w) + raise NotImplementedError('unsupported socket ' + + f'type {socktype}') # pragma: no cover + + async def sleep(self, interval): + await asyncio.sleep(interval) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/_curio_backend.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/_curio_backend.py new file mode 100644 index 0000000..894e87c --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/_curio_backend.py @@ -0,0 +1,108 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +"""curio async I/O library query support""" + +import socket +import curio +import curio.socket # type: ignore + +import dns._asyncbackend +import dns.exception +import dns.inet + + +def _maybe_timeout(timeout): + if timeout: + return curio.ignore_after(timeout) + else: + return dns._asyncbackend.NullContext() + + +# for brevity +_lltuple = dns.inet.low_level_address_tuple + +# pylint: disable=redefined-outer-name + + +class DatagramSocket(dns._asyncbackend.DatagramSocket): + def __init__(self, socket): + self.socket = socket + self.family = socket.family + + async def sendto(self, what, destination, timeout): + async with _maybe_timeout(timeout): + return await self.socket.sendto(what, destination) + raise dns.exception.Timeout(timeout=timeout) # pragma: no cover + + async def recvfrom(self, size, timeout): + async with _maybe_timeout(timeout): + return await self.socket.recvfrom(size) + raise dns.exception.Timeout(timeout=timeout) + + async def close(self): + await self.socket.close() + + async def getpeername(self): + return self.socket.getpeername() + + async def getsockname(self): + return self.socket.getsockname() + + +class StreamSocket(dns._asyncbackend.DatagramSocket): + def __init__(self, socket): + self.socket = socket + self.family = socket.family + + async def sendall(self, what, timeout): + async with _maybe_timeout(timeout): + return await self.socket.sendall(what) + raise dns.exception.Timeout(timeout=timeout) + + async def recv(self, size, timeout): + async with _maybe_timeout(timeout): + return await self.socket.recv(size) + raise dns.exception.Timeout(timeout=timeout) + + async def close(self): + await self.socket.close() + + async def getpeername(self): + return self.socket.getpeername() + + async def getsockname(self): + return self.socket.getsockname() + + +class Backend(dns._asyncbackend.Backend): + def name(self): + return 'curio' + + async def make_socket(self, af, socktype, proto=0, + source=None, destination=None, timeout=None, + ssl_context=None, server_hostname=None): + if socktype == socket.SOCK_DGRAM: + s = curio.socket.socket(af, socktype, proto) + try: + if source: + s.bind(_lltuple(source, af)) + except Exception: # pragma: no cover + await s.close() + raise + return DatagramSocket(s) + elif socktype == socket.SOCK_STREAM: + if source: + source_addr = _lltuple(source, af) + else: + source_addr = None + async with _maybe_timeout(timeout): + s = await curio.open_connection(destination[0], destination[1], + ssl=ssl_context, + source_addr=source_addr, + server_hostname=server_hostname) + return StreamSocket(s) + raise NotImplementedError('unsupported socket ' + + f'type {socktype}') # pragma: no cover + + async def sleep(self, interval): + await curio.sleep(interval) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/_immutable_attr.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/_immutable_attr.py new file mode 100644 index 0000000..f7b9f8b --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/_immutable_attr.py @@ -0,0 +1,84 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# This implementation of the immutable decorator is for python 3.6, +# which doesn't have Context Variables. This implementation is somewhat +# costly for classes with slots, as it adds a __dict__ to them. + + +import inspect + + +class _Immutable: + """Immutable mixin class""" + + # Note we MUST NOT have __slots__ as that causes + # + # TypeError: multiple bases have instance lay-out conflict + # + # when we get mixed in with another class with slots. When we + # get mixed into something with slots, it effectively adds __dict__ to + # the slots of the other class, which allows attribute setting to work, + # albeit at the cost of the dictionary. + + def __setattr__(self, name, value): + if not hasattr(self, '_immutable_init') or \ + self._immutable_init is not self: + raise TypeError("object doesn't support attribute assignment") + else: + super().__setattr__(name, value) + + def __delattr__(self, name): + if not hasattr(self, '_immutable_init') or \ + self._immutable_init is not self: + raise TypeError("object doesn't support attribute assignment") + else: + super().__delattr__(name) + + +def _immutable_init(f): + def nf(*args, **kwargs): + try: + # Are we already initializing an immutable class? + previous = args[0]._immutable_init + except AttributeError: + # We are the first! + previous = None + object.__setattr__(args[0], '_immutable_init', args[0]) + try: + # call the actual __init__ + f(*args, **kwargs) + finally: + if not previous: + # If we started the initialzation, establish immutability + # by removing the attribute that allows mutation + object.__delattr__(args[0], '_immutable_init') + nf.__signature__ = inspect.signature(f) + return nf + + +def immutable(cls): + if _Immutable in cls.__mro__: + # Some ancestor already has the mixin, so just make sure we keep + # following the __init__ protocol. + cls.__init__ = _immutable_init(cls.__init__) + if hasattr(cls, '__setstate__'): + cls.__setstate__ = _immutable_init(cls.__setstate__) + ncls = cls + else: + # Mixin the Immutable class and follow the __init__ protocol. + class ncls(_Immutable, cls): + + @_immutable_init + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + if hasattr(cls, '__setstate__'): + @_immutable_init + def __setstate__(self, *args, **kwargs): + super().__setstate__(*args, **kwargs) + + # make ncls have the same name and module as cls + ncls.__name__ = cls.__name__ + ncls.__qualname__ = cls.__qualname__ + ncls.__module__ = cls.__module__ + return ncls diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/_immutable_ctx.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/_immutable_ctx.py new file mode 100644 index 0000000..ececdbe --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/_immutable_ctx.py @@ -0,0 +1,75 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# This implementation of the immutable decorator requires python >= +# 3.7, and is significantly more storage efficient when making classes +# with slots immutable. It's also faster. + +import contextvars +import inspect + + +_in__init__ = contextvars.ContextVar('_immutable_in__init__', default=False) + + +class _Immutable: + """Immutable mixin class""" + + # We set slots to the empty list to say "we don't have any attributes". + # We do this so that if we're mixed in with a class with __slots__, we + # don't cause a __dict__ to be added which would waste space. + + __slots__ = () + + def __setattr__(self, name, value): + if _in__init__.get() is not self: + raise TypeError("object doesn't support attribute assignment") + else: + super().__setattr__(name, value) + + def __delattr__(self, name): + if _in__init__.get() is not self: + raise TypeError("object doesn't support attribute assignment") + else: + super().__delattr__(name) + + +def _immutable_init(f): + def nf(*args, **kwargs): + previous = _in__init__.set(args[0]) + try: + # call the actual __init__ + f(*args, **kwargs) + finally: + _in__init__.reset(previous) + nf.__signature__ = inspect.signature(f) + return nf + + +def immutable(cls): + if _Immutable in cls.__mro__: + # Some ancestor already has the mixin, so just make sure we keep + # following the __init__ protocol. + cls.__init__ = _immutable_init(cls.__init__) + if hasattr(cls, '__setstate__'): + cls.__setstate__ = _immutable_init(cls.__setstate__) + ncls = cls + else: + # Mixin the Immutable class and follow the __init__ protocol. + class ncls(_Immutable, cls): + # We have to do the __slots__ declaration here too! + __slots__ = () + + @_immutable_init + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + if hasattr(cls, '__setstate__'): + @_immutable_init + def __setstate__(self, *args, **kwargs): + super().__setstate__(*args, **kwargs) + + # make ncls have the same name and module as cls + ncls.__name__ = cls.__name__ + ncls.__qualname__ = cls.__qualname__ + ncls.__module__ = cls.__module__ + return ncls diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/_trio_backend.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/_trio_backend.py new file mode 100644 index 0000000..82512cd --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/_trio_backend.py @@ -0,0 +1,121 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +"""trio async I/O library query support""" + +import socket +import trio +import trio.socket # type: ignore + +import dns._asyncbackend +import dns.exception +import dns.inet + + +def _maybe_timeout(timeout): + if timeout: + return trio.move_on_after(timeout) + else: + return dns._asyncbackend.NullContext() + + +# for brevity +_lltuple = dns.inet.low_level_address_tuple + +# pylint: disable=redefined-outer-name + + +class DatagramSocket(dns._asyncbackend.DatagramSocket): + def __init__(self, socket): + self.socket = socket + self.family = socket.family + + async def sendto(self, what, destination, timeout): + with _maybe_timeout(timeout): + return await self.socket.sendto(what, destination) + raise dns.exception.Timeout(timeout=timeout) # pragma: no cover + + async def recvfrom(self, size, timeout): + with _maybe_timeout(timeout): + return await self.socket.recvfrom(size) + raise dns.exception.Timeout(timeout=timeout) + + async def close(self): + self.socket.close() + + async def getpeername(self): + return self.socket.getpeername() + + async def getsockname(self): + return self.socket.getsockname() + + +class StreamSocket(dns._asyncbackend.DatagramSocket): + def __init__(self, family, stream, tls=False): + self.family = family + self.stream = stream + self.tls = tls + + async def sendall(self, what, timeout): + with _maybe_timeout(timeout): + return await self.stream.send_all(what) + raise dns.exception.Timeout(timeout=timeout) + + async def recv(self, size, timeout): + with _maybe_timeout(timeout): + return await self.stream.receive_some(size) + raise dns.exception.Timeout(timeout=timeout) + + async def close(self): + await self.stream.aclose() + + async def getpeername(self): + if self.tls: + return self.stream.transport_stream.socket.getpeername() + else: + return self.stream.socket.getpeername() + + async def getsockname(self): + if self.tls: + return self.stream.transport_stream.socket.getsockname() + else: + return self.stream.socket.getsockname() + + +class Backend(dns._asyncbackend.Backend): + def name(self): + return 'trio' + + async def make_socket(self, af, socktype, proto=0, source=None, + destination=None, timeout=None, + ssl_context=None, server_hostname=None): + s = trio.socket.socket(af, socktype, proto) + stream = None + try: + if source: + await s.bind(_lltuple(source, af)) + if socktype == socket.SOCK_STREAM: + with _maybe_timeout(timeout): + await s.connect(_lltuple(destination, af)) + except Exception: # pragma: no cover + s.close() + raise + if socktype == socket.SOCK_DGRAM: + return DatagramSocket(s) + elif socktype == socket.SOCK_STREAM: + stream = trio.SocketStream(s) + s = None + tls = False + if ssl_context: + tls = True + try: + stream = trio.SSLStream(stream, ssl_context, + server_hostname=server_hostname) + except Exception: # pragma: no cover + await stream.aclose() + raise + return StreamSocket(af, stream, tls) + raise NotImplementedError('unsupported socket ' + + f'type {socktype}') # pragma: no cover + + async def sleep(self, interval): + await trio.sleep(interval) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/asyncbackend.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/asyncbackend.py new file mode 100644 index 0000000..e6a42ce --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/asyncbackend.py @@ -0,0 +1,101 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import dns.exception + +# pylint: disable=unused-import + +from dns._asyncbackend import Socket, DatagramSocket, \ + StreamSocket, Backend # noqa: + +# pylint: enable=unused-import + +_default_backend = None + +_backends = {} + +# Allow sniffio import to be disabled for testing purposes +_no_sniffio = False + +class AsyncLibraryNotFoundError(dns.exception.DNSException): + pass + + +def get_backend(name): + """Get the specified asychronous backend. + + *name*, a ``str``, the name of the backend. Currently the "trio", + "curio", and "asyncio" backends are available. + + Raises NotImplementError if an unknown backend name is specified. + """ + # pylint: disable=import-outside-toplevel,redefined-outer-name + backend = _backends.get(name) + if backend: + return backend + if name == 'trio': + import dns._trio_backend + backend = dns._trio_backend.Backend() + elif name == 'curio': + import dns._curio_backend + backend = dns._curio_backend.Backend() + elif name == 'asyncio': + import dns._asyncio_backend + backend = dns._asyncio_backend.Backend() + else: + raise NotImplementedError(f'unimplemented async backend {name}') + _backends[name] = backend + return backend + + +def sniff(): + """Attempt to determine the in-use asynchronous I/O library by using + the ``sniffio`` module if it is available. + + Returns the name of the library, or raises AsyncLibraryNotFoundError + if the library cannot be determined. + """ + # pylint: disable=import-outside-toplevel + try: + if _no_sniffio: + raise ImportError + import sniffio + try: + return sniffio.current_async_library() + except sniffio.AsyncLibraryNotFoundError: + raise AsyncLibraryNotFoundError('sniffio cannot determine ' + + 'async library') + except ImportError: + import asyncio + try: + asyncio.get_running_loop() + return 'asyncio' + except RuntimeError: + raise AsyncLibraryNotFoundError('no async library detected') + except AttributeError: # pragma: no cover + # we have to check current_task on 3.6 + if not asyncio.Task.current_task(): + raise AsyncLibraryNotFoundError('no async library detected') + return 'asyncio' + + +def get_default_backend(): + """Get the default backend, initializing it if necessary. + """ + if _default_backend: + return _default_backend + + return set_default_backend(sniff()) + + +def set_default_backend(name): + """Set the default backend. + + It's not normally necessary to call this method, as + ``get_default_backend()`` will initialize the backend + appropriately in many cases. If ``sniffio`` is not installed, or + in testing situations, this function allows the backend to be set + explicitly. + """ + global _default_backend + _default_backend = get_backend(name) + return _default_backend diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/asyncquery.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/asyncquery.py new file mode 100644 index 0000000..89c2622 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/asyncquery.py @@ -0,0 +1,434 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Talk to a DNS server.""" + +import socket +import struct +import time + +import dns.asyncbackend +import dns.exception +import dns.inet +import dns.name +import dns.message +import dns.rcode +import dns.rdataclass +import dns.rdatatype + +from dns.query import _compute_times, _matches_destination, BadResponse, ssl, \ + UDPMode + + +# for brevity +_lltuple = dns.inet.low_level_address_tuple + + +def _source_tuple(af, address, port): + # Make a high level source tuple, or return None if address and port + # are both None + if address or port: + if address is None: + if af == socket.AF_INET: + address = '0.0.0.0' + elif af == socket.AF_INET6: + address = '::' + else: + raise NotImplementedError(f'unknown address family {af}') + return (address, port) + else: + return None + + +def _timeout(expiration, now=None): + if expiration: + if not now: + now = time.time() + return max(expiration - now, 0) + else: + return None + + +async def send_udp(sock, what, destination, expiration=None): + """Send a DNS message to the specified UDP socket. + + *sock*, a ``dns.asyncbackend.DatagramSocket``. + + *what*, a ``bytes`` or ``dns.message.Message``, the message to send. + + *destination*, a destination tuple appropriate for the address family + of the socket, specifying where to send the query. + + *expiration*, a ``float`` or ``None``, the absolute time at which + a timeout exception should be raised. If ``None``, no timeout will + occur. + + Returns an ``(int, float)`` tuple of bytes sent and the sent time. + """ + + if isinstance(what, dns.message.Message): + what = what.to_wire() + sent_time = time.time() + n = await sock.sendto(what, destination, _timeout(expiration, sent_time)) + return (n, sent_time) + + +async def receive_udp(sock, destination=None, expiration=None, + ignore_unexpected=False, one_rr_per_rrset=False, + keyring=None, request_mac=b'', ignore_trailing=False, + raise_on_truncation=False): + """Read a DNS message from a UDP socket. + + *sock*, a ``dns.asyncbackend.DatagramSocket``. + + See :py:func:`dns.query.receive_udp()` for the documentation of the other + parameters, exceptions, and return type of this method. + """ + + wire = b'' + while 1: + (wire, from_address) = await sock.recvfrom(65535, _timeout(expiration)) + if _matches_destination(sock.family, from_address, destination, + ignore_unexpected): + break + received_time = time.time() + r = dns.message.from_wire(wire, keyring=keyring, request_mac=request_mac, + one_rr_per_rrset=one_rr_per_rrset, + ignore_trailing=ignore_trailing, + raise_on_truncation=raise_on_truncation) + return (r, received_time, from_address) + +async def udp(q, where, timeout=None, port=53, source=None, source_port=0, + ignore_unexpected=False, one_rr_per_rrset=False, + ignore_trailing=False, raise_on_truncation=False, sock=None, + backend=None): + """Return the response obtained after sending a query via UDP. + + *sock*, a ``dns.asyncbackend.DatagramSocket``, or ``None``, + the socket to use for the query. If ``None``, the default, a + socket is created. Note that if a socket is provided, the + *source*, *source_port*, and *backend* are ignored. + + *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``, + the default, then dnspython will use the default backend. + + See :py:func:`dns.query.udp()` for the documentation of the other + parameters, exceptions, and return type of this method. + """ + wire = q.to_wire() + (begin_time, expiration) = _compute_times(timeout) + s = None + # After 3.6 is no longer supported, this can use an AsyncExitStack. + try: + af = dns.inet.af_for_address(where) + destination = _lltuple((where, port), af) + if sock: + s = sock + else: + if not backend: + backend = dns.asyncbackend.get_default_backend() + stuple = _source_tuple(af, source, source_port) + s = await backend.make_socket(af, socket.SOCK_DGRAM, 0, stuple) + await send_udp(s, wire, destination, expiration) + (r, received_time, _) = await receive_udp(s, destination, expiration, + ignore_unexpected, + one_rr_per_rrset, + q.keyring, q.mac, + ignore_trailing, + raise_on_truncation) + r.time = received_time - begin_time + if not q.is_response(r): + raise BadResponse + return r + finally: + if not sock and s: + await s.close() + +async def udp_with_fallback(q, where, timeout=None, port=53, source=None, + source_port=0, ignore_unexpected=False, + one_rr_per_rrset=False, ignore_trailing=False, + udp_sock=None, tcp_sock=None, backend=None): + """Return the response to the query, trying UDP first and falling back + to TCP if UDP results in a truncated response. + + *udp_sock*, a ``dns.asyncbackend.DatagramSocket``, or ``None``, + the socket to use for the UDP query. If ``None``, the default, a + socket is created. Note that if a socket is provided the *source*, + *source_port*, and *backend* are ignored for the UDP query. + + *tcp_sock*, a ``dns.asyncbackend.StreamSocket``, or ``None``, the + socket to use for the TCP query. If ``None``, the default, a + socket is created. Note that if a socket is provided *where*, + *source*, *source_port*, and *backend* are ignored for the TCP query. + + *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``, + the default, then dnspython will use the default backend. + + See :py:func:`dns.query.udp_with_fallback()` for the documentation + of the other parameters, exceptions, and return type of this + method. + """ + try: + response = await udp(q, where, timeout, port, source, source_port, + ignore_unexpected, one_rr_per_rrset, + ignore_trailing, True, udp_sock, backend) + return (response, False) + except dns.message.Truncated: + response = await tcp(q, where, timeout, port, source, source_port, + one_rr_per_rrset, ignore_trailing, tcp_sock, + backend) + return (response, True) + + +async def send_tcp(sock, what, expiration=None): + """Send a DNS message to the specified TCP socket. + + *sock*, a ``dns.asyncbackend.StreamSocket``. + + See :py:func:`dns.query.send_tcp()` for the documentation of the other + parameters, exceptions, and return type of this method. + """ + + if isinstance(what, dns.message.Message): + what = what.to_wire() + l = len(what) + # copying the wire into tcpmsg is inefficient, but lets us + # avoid writev() or doing a short write that would get pushed + # onto the net + tcpmsg = struct.pack("!H", l) + what + sent_time = time.time() + await sock.sendall(tcpmsg, _timeout(expiration, sent_time)) + return (len(tcpmsg), sent_time) + + +async def _read_exactly(sock, count, expiration): + """Read the specified number of bytes from stream. Keep trying until we + either get the desired amount, or we hit EOF. + """ + s = b'' + while count > 0: + n = await sock.recv(count, _timeout(expiration)) + if n == b'': + raise EOFError + count = count - len(n) + s = s + n + return s + + +async def receive_tcp(sock, expiration=None, one_rr_per_rrset=False, + keyring=None, request_mac=b'', ignore_trailing=False): + """Read a DNS message from a TCP socket. + + *sock*, a ``dns.asyncbackend.StreamSocket``. + + See :py:func:`dns.query.receive_tcp()` for the documentation of the other + parameters, exceptions, and return type of this method. + """ + + ldata = await _read_exactly(sock, 2, expiration) + (l,) = struct.unpack("!H", ldata) + wire = await _read_exactly(sock, l, expiration) + received_time = time.time() + r = dns.message.from_wire(wire, keyring=keyring, request_mac=request_mac, + one_rr_per_rrset=one_rr_per_rrset, + ignore_trailing=ignore_trailing) + return (r, received_time) + + +async def tcp(q, where, timeout=None, port=53, source=None, source_port=0, + one_rr_per_rrset=False, ignore_trailing=False, sock=None, + backend=None): + """Return the response obtained after sending a query via TCP. + + *sock*, a ``dns.asyncbacket.StreamSocket``, or ``None``, the + socket to use for the query. If ``None``, the default, a socket + is created. Note that if a socket is provided + *where*, *port*, *source*, *source_port*, and *backend* are ignored. + + *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``, + the default, then dnspython will use the default backend. + + See :py:func:`dns.query.tcp()` for the documentation of the other + parameters, exceptions, and return type of this method. + """ + + wire = q.to_wire() + (begin_time, expiration) = _compute_times(timeout) + s = None + # After 3.6 is no longer supported, this can use an AsyncExitStack. + try: + if sock: + # Verify that the socket is connected, as if it's not connected, + # it's not writable, and the polling in send_tcp() will time out or + # hang forever. + await sock.getpeername() + s = sock + else: + # These are simple (address, port) pairs, not + # family-dependent tuples you pass to lowlevel socket + # code. + af = dns.inet.af_for_address(where) + stuple = _source_tuple(af, source, source_port) + dtuple = (where, port) + if not backend: + backend = dns.asyncbackend.get_default_backend() + s = await backend.make_socket(af, socket.SOCK_STREAM, 0, stuple, + dtuple, timeout) + await send_tcp(s, wire, expiration) + (r, received_time) = await receive_tcp(s, expiration, one_rr_per_rrset, + q.keyring, q.mac, + ignore_trailing) + r.time = received_time - begin_time + if not q.is_response(r): + raise BadResponse + return r + finally: + if not sock and s: + await s.close() + +async def tls(q, where, timeout=None, port=853, source=None, source_port=0, + one_rr_per_rrset=False, ignore_trailing=False, sock=None, + backend=None, ssl_context=None, server_hostname=None): + """Return the response obtained after sending a query via TLS. + + *sock*, an ``asyncbackend.StreamSocket``, or ``None``, the socket + to use for the query. If ``None``, the default, a socket is + created. Note that if a socket is provided, it must be a + connected SSL stream socket, and *where*, *port*, + *source*, *source_port*, *backend*, *ssl_context*, and *server_hostname* + are ignored. + + *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``, + the default, then dnspython will use the default backend. + + See :py:func:`dns.query.tls()` for the documentation of the other + parameters, exceptions, and return type of this method. + """ + # After 3.6 is no longer supported, this can use an AsyncExitStack. + (begin_time, expiration) = _compute_times(timeout) + if not sock: + if ssl_context is None: + ssl_context = ssl.create_default_context() + if server_hostname is None: + ssl_context.check_hostname = False + else: + ssl_context = None + server_hostname = None + af = dns.inet.af_for_address(where) + stuple = _source_tuple(af, source, source_port) + dtuple = (where, port) + if not backend: + backend = dns.asyncbackend.get_default_backend() + s = await backend.make_socket(af, socket.SOCK_STREAM, 0, stuple, + dtuple, timeout, ssl_context, + server_hostname) + else: + s = sock + try: + timeout = _timeout(expiration) + response = await tcp(q, where, timeout, port, source, source_port, + one_rr_per_rrset, ignore_trailing, s, backend) + end_time = time.time() + response.time = end_time - begin_time + return response + finally: + if not sock and s: + await s.close() + +async def inbound_xfr(where, txn_manager, query=None, + port=53, timeout=None, lifetime=None, source=None, + source_port=0, udp_mode=UDPMode.NEVER, + backend=None): + """Conduct an inbound transfer and apply it via a transaction from the + txn_manager. + + *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``, + the default, then dnspython will use the default backend. + + See :py:func:`dns.query.inbound_xfr()` for the documentation of + the other parameters, exceptions, and return type of this method. + """ + if query is None: + (query, serial) = dns.xfr.make_query(txn_manager) + rdtype = query.question[0].rdtype + is_ixfr = rdtype == dns.rdatatype.IXFR + origin = txn_manager.from_wire_origin() + wire = query.to_wire() + af = dns.inet.af_for_address(where) + stuple = _source_tuple(af, source, source_port) + dtuple = (where, port) + (_, expiration) = _compute_times(lifetime) + retry = True + while retry: + retry = False + if is_ixfr and udp_mode != UDPMode.NEVER: + sock_type = socket.SOCK_DGRAM + is_udp = True + else: + sock_type = socket.SOCK_STREAM + is_udp = False + if not backend: + backend = dns.asyncbackend.get_default_backend() + s = await backend.make_socket(af, sock_type, 0, stuple, dtuple, + _timeout(expiration)) + async with s: + if is_udp: + await s.sendto(wire, dtuple, _timeout(expiration)) + else: + tcpmsg = struct.pack("!H", len(wire)) + wire + await s.sendall(tcpmsg, expiration) + with dns.xfr.Inbound(txn_manager, rdtype, serial, + is_udp) as inbound: + done = False + tsig_ctx = None + while not done: + (_, mexpiration) = _compute_times(timeout) + if mexpiration is None or \ + (expiration is not None and mexpiration > expiration): + mexpiration = expiration + if is_udp: + destination = _lltuple((where, port), af) + while True: + timeout = _timeout(mexpiration) + (rwire, from_address) = await s.recvfrom(65535, + timeout) + if _matches_destination(af, from_address, + destination, True): + break + else: + ldata = await _read_exactly(s, 2, mexpiration) + (l,) = struct.unpack("!H", ldata) + rwire = await _read_exactly(s, l, mexpiration) + is_ixfr = (rdtype == dns.rdatatype.IXFR) + r = dns.message.from_wire(rwire, keyring=query.keyring, + request_mac=query.mac, xfr=True, + origin=origin, tsig_ctx=tsig_ctx, + multi=(not is_udp), + one_rr_per_rrset=is_ixfr) + try: + done = inbound.process_message(r) + except dns.xfr.UseTCP: + assert is_udp # should not happen if we used TCP! + if udp_mode == UDPMode.ONLY: + raise + done = True + retry = True + udp_mode = UDPMode.NEVER + continue + tsig_ctx = r.tsig_ctx + if not retry and query.keyring and not r.had_tsig: + raise dns.exception.FormError("missing TSIG") diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/asyncresolver.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/asyncresolver.py new file mode 100644 index 0000000..a60cf77 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/asyncresolver.py @@ -0,0 +1,230 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Asynchronous DNS stub resolver.""" + +import time + +import dns.asyncbackend +import dns.asyncquery +import dns.exception +import dns.query +import dns.resolver + +# import some resolver symbols for brevity +from dns.resolver import NXDOMAIN, NoAnswer, NotAbsolute, NoRootSOA + + +# for indentation purposes below +_udp = dns.asyncquery.udp +_tcp = dns.asyncquery.tcp + + +class Resolver(dns.resolver.BaseResolver): + """Asynchronous DNS stub resolver.""" + + async def resolve(self, qname, rdtype=dns.rdatatype.A, + rdclass=dns.rdataclass.IN, + tcp=False, source=None, raise_on_no_answer=True, + source_port=0, lifetime=None, search=None, + backend=None): + """Query nameservers asynchronously to find the answer to the question. + + *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``, + the default, then dnspython will use the default backend. + + See :py:func:`dns.resolver.Resolver.resolve()` for the + documentation of the other parameters, exceptions, and return + type of this method. + """ + + resolution = dns.resolver._Resolution(self, qname, rdtype, rdclass, tcp, + raise_on_no_answer, search) + if not backend: + backend = dns.asyncbackend.get_default_backend() + start = time.time() + while True: + (request, answer) = resolution.next_request() + # Note we need to say "if answer is not None" and not just + # "if answer" because answer implements __len__, and python + # will call that. We want to return if we have an answer + # object, including in cases where its length is 0. + if answer is not None: + # cache hit! + return answer + done = False + while not done: + (nameserver, port, tcp, backoff) = resolution.next_nameserver() + if backoff: + await backend.sleep(backoff) + timeout = self._compute_timeout(start, lifetime) + try: + if dns.inet.is_address(nameserver): + if tcp: + response = await _tcp(request, nameserver, + timeout, port, + source, source_port, + backend=backend) + else: + response = await _udp(request, nameserver, + timeout, port, + source, source_port, + raise_on_truncation=True, + backend=backend) + else: + # We don't do DoH yet. + raise NotImplementedError + except Exception as ex: + (_, done) = resolution.query_result(None, ex) + continue + (answer, done) = resolution.query_result(response, None) + # Note we need to say "if answer is not None" and not just + # "if answer" because answer implements __len__, and python + # will call that. We want to return if we have an answer + # object, including in cases where its length is 0. + if answer is not None: + return answer + + async def resolve_address(self, ipaddr, *args, **kwargs): + """Use an asynchronous resolver to run a reverse query for PTR + records. + + This utilizes the resolve() method to perform a PTR lookup on the + specified IP address. + + *ipaddr*, a ``str``, the IPv4 or IPv6 address you want to get + the PTR record for. + + All other arguments that can be passed to the resolve() function + except for rdtype and rdclass are also supported by this + function. + + """ + + return await self.resolve(dns.reversename.from_address(ipaddr), + rdtype=dns.rdatatype.PTR, + rdclass=dns.rdataclass.IN, + *args, **kwargs) + + # pylint: disable=redefined-outer-name + + async def canonical_name(self, name): + """Determine the canonical name of *name*. + + The canonical name is the name the resolver uses for queries + after all CNAME and DNAME renamings have been applied. + + *name*, a ``dns.name.Name`` or ``str``, the query name. + + This method can raise any exception that ``resolve()`` can + raise, other than ``dns.resolver.NoAnswer`` and + ``dns.resolver.NXDOMAIN``. + + Returns a ``dns.name.Name``. + """ + try: + answer = await self.resolve(name, raise_on_no_answer=False) + canonical_name = answer.canonical_name + except dns.resolver.NXDOMAIN as e: + canonical_name = e.canonical_name + return canonical_name + + +default_resolver = None + + +def get_default_resolver(): + """Get the default asynchronous resolver, initializing it if necessary.""" + if default_resolver is None: + reset_default_resolver() + return default_resolver + + +def reset_default_resolver(): + """Re-initialize default asynchronous resolver. + + Note that the resolver configuration (i.e. /etc/resolv.conf on UNIX + systems) will be re-read immediately. + """ + + global default_resolver + default_resolver = Resolver() + + +async def resolve(qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN, + tcp=False, source=None, raise_on_no_answer=True, + source_port=0, lifetime=None, search=None, backend=None): + """Query nameservers asynchronously to find the answer to the question. + + This is a convenience function that uses the default resolver + object to make the query. + + See :py:func:`dns.asyncresolver.Resolver.resolve` for more + information on the parameters. + """ + + return await get_default_resolver().resolve(qname, rdtype, rdclass, tcp, + source, raise_on_no_answer, + source_port, lifetime, search, + backend) + + +async def resolve_address(ipaddr, *args, **kwargs): + """Use a resolver to run a reverse query for PTR records. + + See :py:func:`dns.asyncresolver.Resolver.resolve_address` for more + information on the parameters. + """ + + return await get_default_resolver().resolve_address(ipaddr, *args, **kwargs) + +async def canonical_name(name): + """Determine the canonical name of *name*. + + See :py:func:`dns.resolver.Resolver.canonical_name` for more + information on the parameters and possible exceptions. + """ + + return await get_default_resolver().canonical_name(name) + +async def zone_for_name(name, rdclass=dns.rdataclass.IN, tcp=False, + resolver=None, backend=None): + """Find the name of the zone which contains the specified name. + + See :py:func:`dns.resolver.Resolver.zone_for_name` for more + information on the parameters and possible exceptions. + """ + + if isinstance(name, str): + name = dns.name.from_text(name, dns.name.root) + if resolver is None: + resolver = get_default_resolver() + if not name.is_absolute(): + raise NotAbsolute(name) + while True: + try: + answer = await resolver.resolve(name, dns.rdatatype.SOA, rdclass, + tcp, backend=backend) + if answer.rrset.name == name: + return name + # otherwise we were CNAMEd or DNAMEd and need to look higher + except (NXDOMAIN, NoAnswer): + pass + try: + name = name.parent() + except dns.name.NoParent: # pragma: no cover + raise NoRootSOA diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/dnssec.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/dnssec.py new file mode 100644 index 0000000..095fabd --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/dnssec.py @@ -0,0 +1,605 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Common DNSSEC-related functions and constants.""" + +import hashlib +import struct +import time +import base64 + +import dns.enum +import dns.exception +import dns.name +import dns.node +import dns.rdataset +import dns.rdata +import dns.rdatatype +import dns.rdataclass + + +class UnsupportedAlgorithm(dns.exception.DNSException): + """The DNSSEC algorithm is not supported.""" + + +class ValidationFailure(dns.exception.DNSException): + """The DNSSEC signature is invalid.""" + + +class Algorithm(dns.enum.IntEnum): + RSAMD5 = 1 + DH = 2 + DSA = 3 + ECC = 4 + RSASHA1 = 5 + DSANSEC3SHA1 = 6 + RSASHA1NSEC3SHA1 = 7 + RSASHA256 = 8 + RSASHA512 = 10 + ECCGOST = 12 + ECDSAP256SHA256 = 13 + ECDSAP384SHA384 = 14 + ED25519 = 15 + ED448 = 16 + INDIRECT = 252 + PRIVATEDNS = 253 + PRIVATEOID = 254 + + @classmethod + def _maximum(cls): + return 255 + + +def algorithm_from_text(text): + """Convert text into a DNSSEC algorithm value. + + *text*, a ``str``, the text to convert to into an algorithm value. + + Returns an ``int``. + """ + + return Algorithm.from_text(text) + + +def algorithm_to_text(value): + """Convert a DNSSEC algorithm value to text + + *value*, an ``int`` a DNSSEC algorithm. + + Returns a ``str``, the name of a DNSSEC algorithm. + """ + + return Algorithm.to_text(value) + + +def key_id(key): + """Return the key id (a 16-bit number) for the specified key. + + *key*, a ``dns.rdtypes.ANY.DNSKEY.DNSKEY`` + + Returns an ``int`` between 0 and 65535 + """ + + rdata = key.to_wire() + if key.algorithm == Algorithm.RSAMD5: + return (rdata[-3] << 8) + rdata[-2] + else: + total = 0 + for i in range(len(rdata) // 2): + total += (rdata[2 * i] << 8) + \ + rdata[2 * i + 1] + if len(rdata) % 2 != 0: + total += rdata[len(rdata) - 1] << 8 + total += ((total >> 16) & 0xffff) + return total & 0xffff + +class DSDigest(dns.enum.IntEnum): + """DNSSEC Delgation Signer Digest Algorithm""" + + SHA1 = 1 + SHA256 = 2 + SHA384 = 4 + + @classmethod + def _maximum(cls): + return 255 + + +def make_ds(name, key, algorithm, origin=None): + """Create a DS record for a DNSSEC key. + + *name*, a ``dns.name.Name`` or ``str``, the owner name of the DS record. + + *key*, a ``dns.rdtypes.ANY.DNSKEY.DNSKEY``, the key the DS is about. + + *algorithm*, a ``str`` or ``int`` specifying the hash algorithm. + The currently supported hashes are "SHA1", "SHA256", and "SHA384". Case + does not matter for these strings. + + *origin*, a ``dns.name.Name`` or ``None``. If `key` is a relative name, + then it will be made absolute using the specified origin. + + Raises ``UnsupportedAlgorithm`` if the algorithm is unknown. + + Returns a ``dns.rdtypes.ANY.DS.DS`` + """ + + try: + if isinstance(algorithm, str): + algorithm = DSDigest[algorithm.upper()] + except Exception: + raise UnsupportedAlgorithm('unsupported algorithm "%s"' % algorithm) + + if algorithm == DSDigest.SHA1: + dshash = hashlib.sha1() + elif algorithm == DSDigest.SHA256: + dshash = hashlib.sha256() + elif algorithm == DSDigest.SHA384: + dshash = hashlib.sha384() + else: + raise UnsupportedAlgorithm('unsupported algorithm "%s"' % algorithm) + + if isinstance(name, str): + name = dns.name.from_text(name, origin) + dshash.update(name.canonicalize().to_wire()) + dshash.update(key.to_wire(origin=origin)) + digest = dshash.digest() + + dsrdata = struct.pack("!HBB", key_id(key), key.algorithm, algorithm) + \ + digest + return dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.DS, dsrdata, 0, + len(dsrdata)) + + +def _find_candidate_keys(keys, rrsig): + candidate_keys = [] + value = keys.get(rrsig.signer) + if value is None: + return None + if isinstance(value, dns.node.Node): + try: + rdataset = value.find_rdataset(dns.rdataclass.IN, + dns.rdatatype.DNSKEY) + except KeyError: + return None + else: + rdataset = value + for rdata in rdataset: + if rdata.algorithm == rrsig.algorithm and \ + key_id(rdata) == rrsig.key_tag: + candidate_keys.append(rdata) + return candidate_keys + + +def _is_rsa(algorithm): + return algorithm in (Algorithm.RSAMD5, Algorithm.RSASHA1, + Algorithm.RSASHA1NSEC3SHA1, Algorithm.RSASHA256, + Algorithm.RSASHA512) + + +def _is_dsa(algorithm): + return algorithm in (Algorithm.DSA, Algorithm.DSANSEC3SHA1) + + +def _is_ecdsa(algorithm): + return algorithm in (Algorithm.ECDSAP256SHA256, Algorithm.ECDSAP384SHA384) + + +def _is_eddsa(algorithm): + return algorithm in (Algorithm.ED25519, Algorithm.ED448) + + +def _is_gost(algorithm): + return algorithm == Algorithm.ECCGOST + + +def _is_md5(algorithm): + return algorithm == Algorithm.RSAMD5 + + +def _is_sha1(algorithm): + return algorithm in (Algorithm.DSA, Algorithm.RSASHA1, + Algorithm.DSANSEC3SHA1, Algorithm.RSASHA1NSEC3SHA1) + + +def _is_sha256(algorithm): + return algorithm in (Algorithm.RSASHA256, Algorithm.ECDSAP256SHA256) + + +def _is_sha384(algorithm): + return algorithm == Algorithm.ECDSAP384SHA384 + + +def _is_sha512(algorithm): + return algorithm == Algorithm.RSASHA512 + + +def _make_hash(algorithm): + if _is_md5(algorithm): + return hashes.MD5() + if _is_sha1(algorithm): + return hashes.SHA1() + if _is_sha256(algorithm): + return hashes.SHA256() + if _is_sha384(algorithm): + return hashes.SHA384() + if _is_sha512(algorithm): + return hashes.SHA512() + if algorithm == Algorithm.ED25519: + return hashes.SHA512() + if algorithm == Algorithm.ED448: + return hashes.SHAKE256(114) + + raise ValidationFailure('unknown hash for algorithm %u' % algorithm) + + +def _bytes_to_long(b): + return int.from_bytes(b, 'big') + + +def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): + """Validate an RRset against a single signature rdata, throwing an + exception if validation is not successful. + + *rrset*, the RRset to validate. This can be a + ``dns.rrset.RRset`` or a (``dns.name.Name``, ``dns.rdataset.Rdataset``) + tuple. + + *rrsig*, a ``dns.rdata.Rdata``, the signature to validate. + + *keys*, the key dictionary, used to find the DNSKEY associated + with a given name. The dictionary is keyed by a + ``dns.name.Name``, and has ``dns.node.Node`` or + ``dns.rdataset.Rdataset`` values. + + *origin*, a ``dns.name.Name`` or ``None``, the origin to use for relative + names. + + *now*, an ``int`` or ``None``, the time, in seconds since the epoch, to + use as the current time when validating. If ``None``, the actual current + time is used. + + Raises ``ValidationFailure`` if the signature is expired, not yet valid, + the public key is invalid, the algorithm is unknown, the verification + fails, etc. + + Raises ``UnsupportedAlgorithm`` if the algorithm is recognized by + dnspython but not implemented. + """ + + if isinstance(origin, str): + origin = dns.name.from_text(origin, dns.name.root) + + candidate_keys = _find_candidate_keys(keys, rrsig) + if candidate_keys is None: + raise ValidationFailure('unknown key') + + for candidate_key in candidate_keys: + # For convenience, allow the rrset to be specified as a (name, + # rdataset) tuple as well as a proper rrset + if isinstance(rrset, tuple): + rrname = rrset[0] + rdataset = rrset[1] + else: + rrname = rrset.name + rdataset = rrset + + if now is None: + now = time.time() + if rrsig.expiration < now: + raise ValidationFailure('expired') + if rrsig.inception > now: + raise ValidationFailure('not yet valid') + + if _is_rsa(rrsig.algorithm): + keyptr = candidate_key.key + (bytes_,) = struct.unpack('!B', keyptr[0:1]) + keyptr = keyptr[1:] + if bytes_ == 0: + (bytes_,) = struct.unpack('!H', keyptr[0:2]) + keyptr = keyptr[2:] + rsa_e = keyptr[0:bytes_] + rsa_n = keyptr[bytes_:] + try: + public_key = rsa.RSAPublicNumbers( + _bytes_to_long(rsa_e), + _bytes_to_long(rsa_n)).public_key(default_backend()) + except ValueError: + raise ValidationFailure('invalid public key') + sig = rrsig.signature + elif _is_dsa(rrsig.algorithm): + keyptr = candidate_key.key + (t,) = struct.unpack('!B', keyptr[0:1]) + keyptr = keyptr[1:] + octets = 64 + t * 8 + dsa_q = keyptr[0:20] + keyptr = keyptr[20:] + dsa_p = keyptr[0:octets] + keyptr = keyptr[octets:] + dsa_g = keyptr[0:octets] + keyptr = keyptr[octets:] + dsa_y = keyptr[0:octets] + try: + public_key = dsa.DSAPublicNumbers( + _bytes_to_long(dsa_y), + dsa.DSAParameterNumbers( + _bytes_to_long(dsa_p), + _bytes_to_long(dsa_q), + _bytes_to_long(dsa_g))).public_key(default_backend()) + except ValueError: + raise ValidationFailure('invalid public key') + sig_r = rrsig.signature[1:21] + sig_s = rrsig.signature[21:] + sig = utils.encode_dss_signature(_bytes_to_long(sig_r), + _bytes_to_long(sig_s)) + elif _is_ecdsa(rrsig.algorithm): + keyptr = candidate_key.key + if rrsig.algorithm == Algorithm.ECDSAP256SHA256: + curve = ec.SECP256R1() + octets = 32 + else: + curve = ec.SECP384R1() + octets = 48 + ecdsa_x = keyptr[0:octets] + ecdsa_y = keyptr[octets:octets * 2] + try: + public_key = ec.EllipticCurvePublicNumbers( + curve=curve, + x=_bytes_to_long(ecdsa_x), + y=_bytes_to_long(ecdsa_y)).public_key(default_backend()) + except ValueError: + raise ValidationFailure('invalid public key') + sig_r = rrsig.signature[0:octets] + sig_s = rrsig.signature[octets:] + sig = utils.encode_dss_signature(_bytes_to_long(sig_r), + _bytes_to_long(sig_s)) + + elif _is_eddsa(rrsig.algorithm): + keyptr = candidate_key.key + if rrsig.algorithm == Algorithm.ED25519: + loader = ed25519.Ed25519PublicKey + else: + loader = ed448.Ed448PublicKey + try: + public_key = loader.from_public_bytes(keyptr) + except ValueError: + raise ValidationFailure('invalid public key') + sig = rrsig.signature + elif _is_gost(rrsig.algorithm): + raise UnsupportedAlgorithm( + 'algorithm "%s" not supported by dnspython' % + algorithm_to_text(rrsig.algorithm)) + else: + raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm) + + data = b'' + data += rrsig.to_wire(origin=origin)[:18] + data += rrsig.signer.to_digestable(origin) + + # Derelativize the name before considering labels. + rrname = rrname.derelativize(origin) + + if len(rrname) - 1 < rrsig.labels: + raise ValidationFailure('owner name longer than RRSIG labels') + elif rrsig.labels < len(rrname) - 1: + suffix = rrname.split(rrsig.labels + 1)[1] + rrname = dns.name.from_text('*', suffix) + rrnamebuf = rrname.to_digestable() + rrfixed = struct.pack('!HHI', rdataset.rdtype, rdataset.rdclass, + rrsig.original_ttl) + rrlist = sorted(rdataset) + for rr in rrlist: + data += rrnamebuf + data += rrfixed + rrdata = rr.to_digestable(origin) + rrlen = struct.pack('!H', len(rrdata)) + data += rrlen + data += rrdata + + chosen_hash = _make_hash(rrsig.algorithm) + try: + if _is_rsa(rrsig.algorithm): + public_key.verify(sig, data, padding.PKCS1v15(), chosen_hash) + elif _is_dsa(rrsig.algorithm): + public_key.verify(sig, data, chosen_hash) + elif _is_ecdsa(rrsig.algorithm): + public_key.verify(sig, data, ec.ECDSA(chosen_hash)) + elif _is_eddsa(rrsig.algorithm): + public_key.verify(sig, data) + else: + # Raise here for code clarity; this won't actually ever happen + # since if the algorithm is really unknown we'd already have + # raised an exception above + raise ValidationFailure('unknown algorithm %u' % + rrsig.algorithm) # pragma: no cover + # If we got here, we successfully verified so we can return + # without error + return + except InvalidSignature: + # this happens on an individual validation failure + continue + # nothing verified -- raise failure: + raise ValidationFailure('verify failure') + + +def _validate(rrset, rrsigset, keys, origin=None, now=None): + """Validate an RRset against a signature RRset, throwing an exception + if none of the signatures validate. + + *rrset*, the RRset to validate. This can be a + ``dns.rrset.RRset`` or a (``dns.name.Name``, ``dns.rdataset.Rdataset``) + tuple. + + *rrsigset*, the signature RRset. This can be a + ``dns.rrset.RRset`` or a (``dns.name.Name``, ``dns.rdataset.Rdataset``) + tuple. + + *keys*, the key dictionary, used to find the DNSKEY associated + with a given name. The dictionary is keyed by a + ``dns.name.Name``, and has ``dns.node.Node`` or + ``dns.rdataset.Rdataset`` values. + + *origin*, a ``dns.name.Name``, the origin to use for relative names; + defaults to None. + + *now*, an ``int`` or ``None``, the time, in seconds since the epoch, to + use as the current time when validating. If ``None``, the actual current + time is used. + + Raises ``ValidationFailure`` if the signature is expired, not yet valid, + the public key is invalid, the algorithm is unknown, the verification + fails, etc. + """ + + if isinstance(origin, str): + origin = dns.name.from_text(origin, dns.name.root) + + if isinstance(rrset, tuple): + rrname = rrset[0] + else: + rrname = rrset.name + + if isinstance(rrsigset, tuple): + rrsigname = rrsigset[0] + rrsigrdataset = rrsigset[1] + else: + rrsigname = rrsigset.name + rrsigrdataset = rrsigset + + rrname = rrname.choose_relativity(origin) + rrsigname = rrsigname.choose_relativity(origin) + if rrname != rrsigname: + raise ValidationFailure("owner names do not match") + + for rrsig in rrsigrdataset: + try: + _validate_rrsig(rrset, rrsig, keys, origin, now) + return + except (ValidationFailure, UnsupportedAlgorithm): + pass + raise ValidationFailure("no RRSIGs validated") + + +class NSEC3Hash(dns.enum.IntEnum): + """NSEC3 hash algorithm""" + + SHA1 = 1 + + @classmethod + def _maximum(cls): + return 255 + +def nsec3_hash(domain, salt, iterations, algorithm): + """ + Calculate the NSEC3 hash, according to + https://tools.ietf.org/html/rfc5155#section-5 + + *domain*, a ``dns.name.Name`` or ``str``, the name to hash. + + *salt*, a ``str``, ``bytes``, or ``None``, the hash salt. If a + string, it is decoded as a hex string. + + *iterations*, an ``int``, the number of iterations. + + *algorithm*, a ``str`` or ``int``, the hash algorithm. + The only defined algorithm is SHA1. + + Returns a ``str``, the encoded NSEC3 hash. + """ + + b32_conversion = str.maketrans( + "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", "0123456789ABCDEFGHIJKLMNOPQRSTUV" + ) + + try: + if isinstance(algorithm, str): + algorithm = NSEC3Hash[algorithm.upper()] + except Exception: + raise ValueError("Wrong hash algorithm (only SHA1 is supported)") + + if algorithm != NSEC3Hash.SHA1: + raise ValueError("Wrong hash algorithm (only SHA1 is supported)") + + salt_encoded = salt + if salt is None: + salt_encoded = b'' + elif isinstance(salt, str): + if len(salt) % 2 == 0: + salt_encoded = bytes.fromhex(salt) + else: + raise ValueError("Invalid salt length") + + if not isinstance(domain, dns.name.Name): + domain = dns.name.from_text(domain) + domain_encoded = domain.canonicalize().to_wire() + + digest = hashlib.sha1(domain_encoded + salt_encoded).digest() + for _ in range(iterations): + digest = hashlib.sha1(digest + salt_encoded).digest() + + output = base64.b32encode(digest).decode("utf-8") + output = output.translate(b32_conversion) + + return output + + +def _need_pyca(*args, **kwargs): + raise ImportError("DNSSEC validation requires " + + "python cryptography") # pragma: no cover + + +try: + from cryptography.exceptions import InvalidSignature + from cryptography.hazmat.backends import default_backend + from cryptography.hazmat.primitives import hashes + from cryptography.hazmat.primitives.asymmetric import padding + from cryptography.hazmat.primitives.asymmetric import utils + from cryptography.hazmat.primitives.asymmetric import dsa + from cryptography.hazmat.primitives.asymmetric import ec + from cryptography.hazmat.primitives.asymmetric import ed25519 + from cryptography.hazmat.primitives.asymmetric import ed448 + from cryptography.hazmat.primitives.asymmetric import rsa +except ImportError: # pragma: no cover + validate = _need_pyca + validate_rrsig = _need_pyca + _have_pyca = False +else: + validate = _validate # type: ignore + validate_rrsig = _validate_rrsig # type: ignore + _have_pyca = True + +### BEGIN generated Algorithm constants + +RSAMD5 = Algorithm.RSAMD5 +DH = Algorithm.DH +DSA = Algorithm.DSA +ECC = Algorithm.ECC +RSASHA1 = Algorithm.RSASHA1 +DSANSEC3SHA1 = Algorithm.DSANSEC3SHA1 +RSASHA1NSEC3SHA1 = Algorithm.RSASHA1NSEC3SHA1 +RSASHA256 = Algorithm.RSASHA256 +RSASHA512 = Algorithm.RSASHA512 +ECCGOST = Algorithm.ECCGOST +ECDSAP256SHA256 = Algorithm.ECDSAP256SHA256 +ECDSAP384SHA384 = Algorithm.ECDSAP384SHA384 +ED25519 = Algorithm.ED25519 +ED448 = Algorithm.ED448 +INDIRECT = Algorithm.INDIRECT +PRIVATEDNS = Algorithm.PRIVATEDNS +PRIVATEOID = Algorithm.PRIVATEOID + +### END generated Algorithm constants diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/e164.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/e164.py new file mode 100644 index 0000000..83731b2 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/e164.py @@ -0,0 +1,104 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS E.164 helpers.""" + +import dns.exception +import dns.name +import dns.resolver + +#: The public E.164 domain. +public_enum_domain = dns.name.from_text('e164.arpa.') + + +def from_e164(text, origin=public_enum_domain): + """Convert an E.164 number in textual form into a Name object whose + value is the ENUM domain name for that number. + + Non-digits in the text are ignored, i.e. "16505551212", + "+1.650.555.1212" and "1 (650) 555-1212" are all the same. + + *text*, a ``str``, is an E.164 number in textual form. + + *origin*, a ``dns.name.Name``, the domain in which the number + should be constructed. The default is ``e164.arpa.``. + + Returns a ``dns.name.Name``. + """ + + parts = [d for d in text if d.isdigit()] + parts.reverse() + return dns.name.from_text('.'.join(parts), origin=origin) + + +def to_e164(name, origin=public_enum_domain, want_plus_prefix=True): + """Convert an ENUM domain name into an E.164 number. + + Note that dnspython does not have any information about preferred + number formats within national numbering plans, so all numbers are + emitted as a simple string of digits, prefixed by a '+' (unless + *want_plus_prefix* is ``False``). + + *name* is a ``dns.name.Name``, the ENUM domain name. + + *origin* is a ``dns.name.Name``, a domain containing the ENUM + domain name. The name is relativized to this domain before being + converted to text. If ``None``, no relativization is done. + + *want_plus_prefix* is a ``bool``. If True, add a '+' to the beginning of + the returned number. + + Returns a ``str``. + + """ + if origin is not None: + name = name.relativize(origin) + dlabels = [d for d in name.labels if d.isdigit() and len(d) == 1] + if len(dlabels) != len(name.labels): + raise dns.exception.SyntaxError('non-digit labels in ENUM domain name') + dlabels.reverse() + text = b''.join(dlabels) + if want_plus_prefix: + text = b'+' + text + return text.decode() + + +def query(number, domains, resolver=None): + """Look for NAPTR RRs for the specified number in the specified domains. + + e.g. lookup('16505551212', ['e164.dnspython.org.', 'e164.arpa.']) + + *number*, a ``str`` is the number to look for. + + *domains* is an iterable containing ``dns.name.Name`` values. + + *resolver*, a ``dns.resolver.Resolver``, is the resolver to use. If + ``None``, the default resolver is used. + """ + + if resolver is None: + resolver = dns.resolver.get_default_resolver() + e_nx = dns.resolver.NXDOMAIN() + for domain in domains: + if isinstance(domain, str): + domain = dns.name.from_text(domain) + qname = dns.e164.from_e164(number, domain) + try: + return resolver.resolve(qname, 'NAPTR') + except dns.resolver.NXDOMAIN as e: + e_nx += e + raise e_nx diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/edns.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/edns.py new file mode 100644 index 0000000..237178f --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/edns.py @@ -0,0 +1,376 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2009-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""EDNS Options""" + +import math +import socket +import struct + +import dns.enum +import dns.inet +import dns.rdata + + +class OptionType(dns.enum.IntEnum): + #: NSID + NSID = 3 + #: DAU + DAU = 5 + #: DHU + DHU = 6 + #: N3U + N3U = 7 + #: ECS (client-subnet) + ECS = 8 + #: EXPIRE + EXPIRE = 9 + #: COOKIE + COOKIE = 10 + #: KEEPALIVE + KEEPALIVE = 11 + #: PADDING + PADDING = 12 + #: CHAIN + CHAIN = 13 + + @classmethod + def _maximum(cls): + return 65535 + + +class Option: + + """Base class for all EDNS option types.""" + + def __init__(self, otype): + """Initialize an option. + + *otype*, an ``int``, is the option type. + """ + self.otype = OptionType.make(otype) + + def to_wire(self, file=None): + """Convert an option to wire format. + + Returns a ``bytes`` or ``None``. + + """ + raise NotImplementedError # pragma: no cover + + @classmethod + def from_wire_parser(cls, otype, parser): + """Build an EDNS option object from wire format. + + *otype*, an ``int``, is the option type. + + *parser*, a ``dns.wire.Parser``, the parser, which should be + restructed to the option length. + + Returns a ``dns.edns.Option``. + """ + raise NotImplementedError # pragma: no cover + + def _cmp(self, other): + """Compare an EDNS option with another option of the same type. + + Returns < 0 if < *other*, 0 if == *other*, and > 0 if > *other*. + """ + wire = self.to_wire() + owire = other.to_wire() + if wire == owire: + return 0 + if wire > owire: + return 1 + return -1 + + def __eq__(self, other): + if not isinstance(other, Option): + return False + if self.otype != other.otype: + return False + return self._cmp(other) == 0 + + def __ne__(self, other): + if not isinstance(other, Option): + return True + if self.otype != other.otype: + return True + return self._cmp(other) != 0 + + def __lt__(self, other): + if not isinstance(other, Option) or \ + self.otype != other.otype: + return NotImplemented + return self._cmp(other) < 0 + + def __le__(self, other): + if not isinstance(other, Option) or \ + self.otype != other.otype: + return NotImplemented + return self._cmp(other) <= 0 + + def __ge__(self, other): + if not isinstance(other, Option) or \ + self.otype != other.otype: + return NotImplemented + return self._cmp(other) >= 0 + + def __gt__(self, other): + if not isinstance(other, Option) or \ + self.otype != other.otype: + return NotImplemented + return self._cmp(other) > 0 + + def __str__(self): + return self.to_text() + + +class GenericOption(Option): + + """Generic Option Class + + This class is used for EDNS option types for which we have no better + implementation. + """ + + def __init__(self, otype, data): + super().__init__(otype) + self.data = dns.rdata.Rdata._as_bytes(data, True) + + def to_wire(self, file=None): + if file: + file.write(self.data) + else: + return self.data + + def to_text(self): + return "Generic %d" % self.otype + + @classmethod + def from_wire_parser(cls, otype, parser): + return cls(otype, parser.get_remaining()) + + +class ECSOption(Option): + """EDNS Client Subnet (ECS, RFC7871)""" + + def __init__(self, address, srclen=None, scopelen=0): + """*address*, a ``str``, is the client address information. + + *srclen*, an ``int``, the source prefix length, which is the + leftmost number of bits of the address to be used for the + lookup. The default is 24 for IPv4 and 56 for IPv6. + + *scopelen*, an ``int``, the scope prefix length. This value + must be 0 in queries, and should be set in responses. + """ + + super().__init__(OptionType.ECS) + af = dns.inet.af_for_address(address) + + if af == socket.AF_INET6: + self.family = 2 + if srclen is None: + srclen = 56 + address = dns.rdata.Rdata._as_ipv6_address(address) + srclen = dns.rdata.Rdata._as_int(srclen, 0, 128) + scopelen = dns.rdata.Rdata._as_int(scopelen, 0, 128) + elif af == socket.AF_INET: + self.family = 1 + if srclen is None: + srclen = 24 + address = dns.rdata.Rdata._as_ipv4_address(address) + srclen = dns.rdata.Rdata._as_int(srclen, 0, 32) + scopelen = dns.rdata.Rdata._as_int(scopelen, 0, 32) + else: # pragma: no cover (this will never happen) + raise ValueError('Bad address family') + + self.address = address + self.srclen = srclen + self.scopelen = scopelen + + addrdata = dns.inet.inet_pton(af, address) + nbytes = int(math.ceil(srclen / 8.0)) + + # Truncate to srclen and pad to the end of the last octet needed + # See RFC section 6 + self.addrdata = addrdata[:nbytes] + nbits = srclen % 8 + if nbits != 0: + last = struct.pack('B', + ord(self.addrdata[-1:]) & (0xff << (8 - nbits))) + self.addrdata = self.addrdata[:-1] + last + + def to_text(self): + return "ECS {}/{} scope/{}".format(self.address, self.srclen, + self.scopelen) + + @staticmethod + def from_text(text): + """Convert a string into a `dns.edns.ECSOption` + + *text*, a `str`, the text form of the option. + + Returns a `dns.edns.ECSOption`. + + Examples: + + >>> import dns.edns + >>> + >>> # basic example + >>> dns.edns.ECSOption.from_text('1.2.3.4/24') + >>> + >>> # also understands scope + >>> dns.edns.ECSOption.from_text('1.2.3.4/24/32') + >>> + >>> # IPv6 + >>> dns.edns.ECSOption.from_text('2001:4b98::1/64/64') + >>> + >>> # it understands results from `dns.edns.ECSOption.to_text()` + >>> dns.edns.ECSOption.from_text('ECS 1.2.3.4/24/32') + """ + optional_prefix = 'ECS' + tokens = text.split() + ecs_text = None + if len(tokens) == 1: + ecs_text = tokens[0] + elif len(tokens) == 2: + if tokens[0] != optional_prefix: + raise ValueError('could not parse ECS from "{}"'.format(text)) + ecs_text = tokens[1] + else: + raise ValueError('could not parse ECS from "{}"'.format(text)) + n_slashes = ecs_text.count('/') + if n_slashes == 1: + address, srclen = ecs_text.split('/') + scope = 0 + elif n_slashes == 2: + address, srclen, scope = ecs_text.split('/') + else: + raise ValueError('could not parse ECS from "{}"'.format(text)) + try: + scope = int(scope) + except ValueError: + raise ValueError('invalid scope ' + + '"{}": scope must be an integer'.format(scope)) + try: + srclen = int(srclen) + except ValueError: + raise ValueError('invalid srclen ' + + '"{}": srclen must be an integer'.format(srclen)) + return ECSOption(address, srclen, scope) + + def to_wire(self, file=None): + value = (struct.pack('!HBB', self.family, self.srclen, self.scopelen) + + self.addrdata) + if file: + file.write(value) + else: + return value + + @classmethod + def from_wire_parser(cls, otype, parser): + family, src, scope = parser.get_struct('!HBB') + addrlen = int(math.ceil(src / 8.0)) + prefix = parser.get_bytes(addrlen) + if family == 1: + pad = 4 - addrlen + addr = dns.ipv4.inet_ntoa(prefix + b'\x00' * pad) + elif family == 2: + pad = 16 - addrlen + addr = dns.ipv6.inet_ntoa(prefix + b'\x00' * pad) + else: + raise ValueError('unsupported family') + + return cls(addr, src, scope) + + +_type_to_class = { + OptionType.ECS: ECSOption +} + +def get_option_class(otype): + """Return the class for the specified option type. + + The GenericOption class is used if a more specific class is not + known. + """ + + cls = _type_to_class.get(otype) + if cls is None: + cls = GenericOption + return cls + + +def option_from_wire_parser(otype, parser): + """Build an EDNS option object from wire format. + + *otype*, an ``int``, is the option type. + + *parser*, a ``dns.wire.Parser``, the parser, which should be + restricted to the option length. + + Returns an instance of a subclass of ``dns.edns.Option``. + """ + cls = get_option_class(otype) + otype = OptionType.make(otype) + return cls.from_wire_parser(otype, parser) + + +def option_from_wire(otype, wire, current, olen): + """Build an EDNS option object from wire format. + + *otype*, an ``int``, is the option type. + + *wire*, a ``bytes``, is the wire-format message. + + *current*, an ``int``, is the offset in *wire* of the beginning + of the rdata. + + *olen*, an ``int``, is the length of the wire-format option data + + Returns an instance of a subclass of ``dns.edns.Option``. + """ + parser = dns.wire.Parser(wire, current) + with parser.restrict_to(olen): + return option_from_wire_parser(otype, parser) + +def register_type(implementation, otype): + """Register the implementation of an option type. + + *implementation*, a ``class``, is a subclass of ``dns.edns.Option``. + + *otype*, an ``int``, is the option type. + """ + + _type_to_class[otype] = implementation + +### BEGIN generated OptionType constants + +NSID = OptionType.NSID +DAU = OptionType.DAU +DHU = OptionType.DHU +N3U = OptionType.N3U +ECS = OptionType.ECS +EXPIRE = OptionType.EXPIRE +COOKIE = OptionType.COOKIE +KEEPALIVE = OptionType.KEEPALIVE +PADDING = OptionType.PADDING +CHAIN = OptionType.CHAIN + +### END generated OptionType constants diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/entropy.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/entropy.py new file mode 100644 index 0000000..086bba7 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/entropy.py @@ -0,0 +1,129 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2009-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import os +import hashlib +import random +import time +try: + import threading as _threading +except ImportError: # pragma: no cover + import dummy_threading as _threading # type: ignore + + +class EntropyPool: + + # This is an entropy pool for Python implementations that do not + # have a working SystemRandom. I'm not sure there are any, but + # leaving this code doesn't hurt anything as the library code + # is used if present. + + def __init__(self, seed=None): + self.pool_index = 0 + self.digest = None + self.next_byte = 0 + self.lock = _threading.Lock() + self.hash = hashlib.sha1() + self.hash_len = 20 + self.pool = bytearray(b'\0' * self.hash_len) + if seed is not None: + self._stir(bytearray(seed)) + self.seeded = True + self.seed_pid = os.getpid() + else: + self.seeded = False + self.seed_pid = 0 + + def _stir(self, entropy): + for c in entropy: + if self.pool_index == self.hash_len: + self.pool_index = 0 + b = c & 0xff + self.pool[self.pool_index] ^= b + self.pool_index += 1 + + def stir(self, entropy): + with self.lock: + self._stir(entropy) + + def _maybe_seed(self): + if not self.seeded or self.seed_pid != os.getpid(): + try: + seed = os.urandom(16) + except Exception: # pragma: no cover + try: + with open('/dev/urandom', 'rb', 0) as r: + seed = r.read(16) + except Exception: + seed = str(time.time()) + self.seeded = True + self.seed_pid = os.getpid() + self.digest = None + seed = bytearray(seed) + self._stir(seed) + + def random_8(self): + with self.lock: + self._maybe_seed() + if self.digest is None or self.next_byte == self.hash_len: + self.hash.update(bytes(self.pool)) + self.digest = bytearray(self.hash.digest()) + self._stir(self.digest) + self.next_byte = 0 + value = self.digest[self.next_byte] + self.next_byte += 1 + return value + + def random_16(self): + return self.random_8() * 256 + self.random_8() + + def random_32(self): + return self.random_16() * 65536 + self.random_16() + + def random_between(self, first, last): + size = last - first + 1 + if size > 4294967296: + raise ValueError('too big') + if size > 65536: + rand = self.random_32 + max = 4294967295 + elif size > 256: + rand = self.random_16 + max = 65535 + else: + rand = self.random_8 + max = 255 + return first + size * rand() // (max + 1) + +pool = EntropyPool() + +try: + system_random = random.SystemRandom() +except Exception: # pragma: no cover + system_random = None + +def random_16(): + if system_random is not None: + return system_random.randrange(0, 65536) + else: + return pool.random_16() + +def between(first, last): + if system_random is not None: + return system_random.randrange(first, last + 1) + else: + return pool.random_between(first, last) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/enum.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/enum.py new file mode 100644 index 0000000..b822dd5 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/enum.py @@ -0,0 +1,90 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import enum + +class IntEnum(enum.IntEnum): + @classmethod + def _check_value(cls, value): + max = cls._maximum() + if value < 0 or value > max: + name = cls._short_name() + raise ValueError(f"{name} must be between >= 0 and <= {max}") + + @classmethod + def from_text(cls, text): + text = text.upper() + try: + return cls[text] + except KeyError: + pass + prefix = cls._prefix() + if text.startswith(prefix) and text[len(prefix):].isdigit(): + value = int(text[len(prefix):]) + cls._check_value(value) + try: + return cls(value) + except ValueError: + return value + raise cls._unknown_exception_class() + + @classmethod + def to_text(cls, value): + cls._check_value(value) + try: + return cls(value).name + except ValueError: + return f"{cls._prefix()}{value}" + + @classmethod + def make(cls, value): + """Convert text or a value into an enumerated type, if possible. + + *value*, the ``int`` or ``str`` to convert. + + Raises a class-specific exception if a ``str`` is provided that + cannot be converted. + + Raises ``ValueError`` if the value is out of range. + + Returns an enumeration from the calling class corresponding to the + value, if one is defined, or an ``int`` otherwise. + """ + + if isinstance(value, str): + return cls.from_text(value) + cls._check_value(value) + try: + return cls(value) + except ValueError: + return value + + @classmethod + def _maximum(cls): + raise NotImplementedError # pragma: no cover + + @classmethod + def _short_name(cls): + return cls.__name__.lower() + + @classmethod + def _prefix(cls): + return '' + + @classmethod + def _unknown_exception_class(cls): + return ValueError diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/exception.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/exception.py new file mode 100644 index 0000000..9392373 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/exception.py @@ -0,0 +1,142 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Common DNS Exceptions. + +Dnspython modules may also define their own exceptions, which will +always be subclasses of ``DNSException``. +""" + +class DNSException(Exception): + """Abstract base class shared by all dnspython exceptions. + + It supports two basic modes of operation: + + a) Old/compatible mode is used if ``__init__`` was called with + empty *kwargs*. In compatible mode all *args* are passed + to the standard Python Exception class as before and all *args* are + printed by the standard ``__str__`` implementation. Class variable + ``msg`` (or doc string if ``msg`` is ``None``) is returned from ``str()`` + if *args* is empty. + + b) New/parametrized mode is used if ``__init__`` was called with + non-empty *kwargs*. + In the new mode *args* must be empty and all kwargs must match + those set in class variable ``supp_kwargs``. All kwargs are stored inside + ``self.kwargs`` and used in a new ``__str__`` implementation to construct + a formatted message based on the ``fmt`` class variable, a ``string``. + + In the simplest case it is enough to override the ``supp_kwargs`` + and ``fmt`` class variables to get nice parametrized messages. + """ + + msg = None # non-parametrized message + supp_kwargs = set() # accepted parameters for _fmt_kwargs (sanity check) + fmt = None # message parametrized with results from _fmt_kwargs + + def __init__(self, *args, **kwargs): + self._check_params(*args, **kwargs) + if kwargs: + self.kwargs = self._check_kwargs(**kwargs) + self.msg = str(self) + else: + self.kwargs = dict() # defined but empty for old mode exceptions + if self.msg is None: + # doc string is better implicit message than empty string + self.msg = self.__doc__ + if args: + super().__init__(*args) + else: + super().__init__(self.msg) + + def _check_params(self, *args, **kwargs): + """Old exceptions supported only args and not kwargs. + + For sanity we do not allow to mix old and new behavior.""" + if args or kwargs: + assert bool(args) != bool(kwargs), \ + 'keyword arguments are mutually exclusive with positional args' + + def _check_kwargs(self, **kwargs): + if kwargs: + assert set(kwargs.keys()) == self.supp_kwargs, \ + 'following set of keyword args is required: %s' % ( + self.supp_kwargs) + return kwargs + + def _fmt_kwargs(self, **kwargs): + """Format kwargs before printing them. + + Resulting dictionary has to have keys necessary for str.format call + on fmt class variable. + """ + fmtargs = {} + for kw, data in kwargs.items(): + if isinstance(data, (list, set)): + # convert list of to list of str() + fmtargs[kw] = list(map(str, data)) + if len(fmtargs[kw]) == 1: + # remove list brackets [] from single-item lists + fmtargs[kw] = fmtargs[kw].pop() + else: + fmtargs[kw] = data + return fmtargs + + def __str__(self): + if self.kwargs and self.fmt: + # provide custom message constructed from keyword arguments + fmtargs = self._fmt_kwargs(**self.kwargs) + return self.fmt.format(**fmtargs) + else: + # print *args directly in the same way as old DNSException + return super().__str__() + + +class FormError(DNSException): + """DNS message is malformed.""" + + +class SyntaxError(DNSException): + """Text input is malformed.""" + + +class UnexpectedEnd(SyntaxError): + """Text input ended unexpectedly.""" + + +class TooBig(DNSException): + """The DNS message is too big.""" + + +class Timeout(DNSException): + """The DNS operation timed out.""" + supp_kwargs = {'timeout'} + fmt = "The DNS operation timed out after {timeout} seconds" + + +class ExceptionWrapper: + def __init__(self, exception_class): + self.exception_class = exception_class + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + if exc_type is not None and not isinstance(exc_val, + self.exception_class): + raise self.exception_class(str(exc_val)) from exc_val + return False diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/flags.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/flags.py new file mode 100644 index 0000000..9652287 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/flags.py @@ -0,0 +1,119 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Message Flags.""" + +import enum + +# Standard DNS flags + +class Flag(enum.IntFlag): + #: Query Response + QR = 0x8000 + #: Authoritative Answer + AA = 0x0400 + #: Truncated Response + TC = 0x0200 + #: Recursion Desired + RD = 0x0100 + #: Recursion Available + RA = 0x0080 + #: Authentic Data + AD = 0x0020 + #: Checking Disabled + CD = 0x0010 + + +# EDNS flags + +class EDNSFlag(enum.IntFlag): + #: DNSSEC answer OK + DO = 0x8000 + + +def _from_text(text, enum_class): + flags = 0 + tokens = text.split() + for t in tokens: + flags |= enum_class[t.upper()] + return flags + + +def _to_text(flags, enum_class): + text_flags = [] + for k, v in enum_class.__members__.items(): + if flags & v != 0: + text_flags.append(k) + return ' '.join(text_flags) + + +def from_text(text): + """Convert a space-separated list of flag text values into a flags + value. + + Returns an ``int`` + """ + + return _from_text(text, Flag) + + +def to_text(flags): + """Convert a flags value into a space-separated list of flag text + values. + + Returns a ``str``. + """ + + return _to_text(flags, Flag) + + +def edns_from_text(text): + """Convert a space-separated list of EDNS flag text values into a EDNS + flags value. + + Returns an ``int`` + """ + + return _from_text(text, EDNSFlag) + + +def edns_to_text(flags): + """Convert an EDNS flags value into a space-separated list of EDNS flag + text values. + + Returns a ``str``. + """ + + return _to_text(flags, EDNSFlag) + +### BEGIN generated Flag constants + +QR = Flag.QR +AA = Flag.AA +TC = Flag.TC +RD = Flag.RD +RA = Flag.RA +AD = Flag.AD +CD = Flag.CD + +### END generated Flag constants + +### BEGIN generated EDNSFlag constants + +DO = EDNSFlag.DO + +### END generated EDNSFlag constants diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/grange.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/grange.py new file mode 100644 index 0000000..112ede4 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/grange.py @@ -0,0 +1,69 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2012-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS GENERATE range conversion.""" + +import dns + +def from_text(text): + """Convert the text form of a range in a ``$GENERATE`` statement to an + integer. + + *text*, a ``str``, the textual range in ``$GENERATE`` form. + + Returns a tuple of three ``int`` values ``(start, stop, step)``. + """ + + start = -1 + stop = -1 + step = 1 + cur = '' + state = 0 + # state 0 1 2 + # x - y / z + + if text and text[0] == '-': + raise dns.exception.SyntaxError("Start cannot be a negative number") + + for c in text: + if c == '-' and state == 0: + start = int(cur) + cur = '' + state = 1 + elif c == '/': + stop = int(cur) + cur = '' + state = 2 + elif c.isdigit(): + cur += c + else: + raise dns.exception.SyntaxError("Could not parse %s" % (c)) + + if state == 0: + raise dns.exception.SyntaxError("no stop value specified") + elif state == 1: + stop = int(cur) + else: + assert state == 2 + step = int(cur) + + assert step >= 1 + assert start >= 0 + if start > stop: + raise dns.exception.SyntaxError('start must be <= stop') + + return (start, stop, step) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/immutable.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/immutable.py new file mode 100644 index 0000000..db7abbc --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/immutable.py @@ -0,0 +1,70 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import collections.abc +import sys + +# pylint: disable=unused-import +if sys.version_info >= (3, 7): + odict = dict + from dns._immutable_ctx import immutable +else: + # pragma: no cover + from collections import OrderedDict as odict + from dns._immutable_attr import immutable # noqa +# pylint: enable=unused-import + + +@immutable +class Dict(collections.abc.Mapping): + def __init__(self, dictionary, no_copy=False): + """Make an immutable dictionary from the specified dictionary. + + If *no_copy* is `True`, then *dictionary* will be wrapped instead + of copied. Only set this if you are sure there will be no external + references to the dictionary. + """ + if no_copy and isinstance(dictionary, odict): + self._odict = dictionary + else: + self._odict = odict(dictionary) + self._hash = None + + def __getitem__(self, key): + return self._odict.__getitem__(key) + + def __hash__(self): # pylint: disable=invalid-hash-returned + if self._hash is None: + h = 0 + for key in sorted(self._odict.keys()): + h ^= hash(key) + object.__setattr__(self, '_hash', h) + # this does return an int, but pylint doesn't figure that out + return self._hash + + def __len__(self): + return len(self._odict) + + def __iter__(self): + return iter(self._odict) + + +def constify(o): + """ + Convert mutable types to immutable types. + """ + if isinstance(o, bytearray): + return bytes(o) + if isinstance(o, tuple): + try: + hash(o) + return o + except Exception: + return tuple(constify(elt) for elt in o) + if isinstance(o, list): + return tuple(constify(elt) for elt in o) + if isinstance(o, dict): + cdict = odict() + for k, v in o.items(): + cdict[k] = constify(v) + return Dict(cdict, True) + return o diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/inet.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/inet.py new file mode 100644 index 0000000..d3bdc64 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/inet.py @@ -0,0 +1,170 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Generic Internet address helper functions.""" + +import socket + +import dns.ipv4 +import dns.ipv6 + + +# We assume that AF_INET and AF_INET6 are always defined. We keep +# these here for the benefit of any old code (unlikely though that +# is!). +AF_INET = socket.AF_INET +AF_INET6 = socket.AF_INET6 + + +def inet_pton(family, text): + """Convert the textual form of a network address into its binary form. + + *family* is an ``int``, the address family. + + *text* is a ``str``, the textual address. + + Raises ``NotImplementedError`` if the address family specified is not + implemented. + + Returns a ``bytes``. + """ + + if family == AF_INET: + return dns.ipv4.inet_aton(text) + elif family == AF_INET6: + return dns.ipv6.inet_aton(text, True) + else: + raise NotImplementedError + + +def inet_ntop(family, address): + """Convert the binary form of a network address into its textual form. + + *family* is an ``int``, the address family. + + *address* is a ``bytes``, the network address in binary form. + + Raises ``NotImplementedError`` if the address family specified is not + implemented. + + Returns a ``str``. + """ + + if family == AF_INET: + return dns.ipv4.inet_ntoa(address) + elif family == AF_INET6: + return dns.ipv6.inet_ntoa(address) + else: + raise NotImplementedError + + +def af_for_address(text): + """Determine the address family of a textual-form network address. + + *text*, a ``str``, the textual address. + + Raises ``ValueError`` if the address family cannot be determined + from the input. + + Returns an ``int``. + """ + + try: + dns.ipv4.inet_aton(text) + return AF_INET + except Exception: + try: + dns.ipv6.inet_aton(text, True) + return AF_INET6 + except Exception: + raise ValueError + + +def is_multicast(text): + """Is the textual-form network address a multicast address? + + *text*, a ``str``, the textual address. + + Raises ``ValueError`` if the address family cannot be determined + from the input. + + Returns a ``bool``. + """ + + try: + first = dns.ipv4.inet_aton(text)[0] + return first >= 224 and first <= 239 + except Exception: + try: + first = dns.ipv6.inet_aton(text, True)[0] + return first == 255 + except Exception: + raise ValueError + + +def is_address(text): + """Is the specified string an IPv4 or IPv6 address? + + *text*, a ``str``, the textual address. + + Returns a ``bool``. + """ + + try: + dns.ipv4.inet_aton(text) + return True + except Exception: + try: + dns.ipv6.inet_aton(text, True) + return True + except Exception: + return False + + +def low_level_address_tuple(high_tuple, af=None): + """Given a "high-level" address tuple, i.e. + an (address, port) return the appropriate "low-level" address tuple + suitable for use in socket calls. + + If an *af* other than ``None`` is provided, it is assumed the + address in the high-level tuple is valid and has that af. If af + is ``None``, then af_for_address will be called. + + """ + address, port = high_tuple + if af is None: + af = af_for_address(address) + if af == AF_INET: + return (address, port) + elif af == AF_INET6: + i = address.find('%') + if i < 0: + # no scope, shortcut! + return (address, port, 0, 0) + # try to avoid getaddrinfo() + addrpart = address[:i] + scope = address[i + 1:] + if scope.isdigit(): + return (addrpart, port, 0, int(scope)) + try: + return (addrpart, port, 0, socket.if_nametoindex(scope)) + except AttributeError: # pragma: no cover (we can't really test this) + ai_flags = socket.AI_NUMERICHOST + ((*_, tup), *_) = socket.getaddrinfo(address, port, flags=ai_flags) + return tup + else: + raise NotImplementedError(f'unknown address family {af}') diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/ipv4.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/ipv4.py new file mode 100644 index 0000000..e1f38d3 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/ipv4.py @@ -0,0 +1,60 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""IPv4 helper functions.""" + +import struct + +import dns.exception + +def inet_ntoa(address): + """Convert an IPv4 address in binary form to text form. + + *address*, a ``bytes``, the IPv4 address in binary form. + + Returns a ``str``. + """ + + if len(address) != 4: + raise dns.exception.SyntaxError + return ('%u.%u.%u.%u' % (address[0], address[1], + address[2], address[3])) + +def inet_aton(text): + """Convert an IPv4 address in text form to binary form. + + *text*, a ``str``, the IPv4 address in textual form. + + Returns a ``bytes``. + """ + + if not isinstance(text, bytes): + text = text.encode() + parts = text.split(b'.') + if len(parts) != 4: + raise dns.exception.SyntaxError + for part in parts: + if not part.isdigit(): + raise dns.exception.SyntaxError + if len(part) > 1 and part[0] == ord('0'): + # No leading zeros + raise dns.exception.SyntaxError + try: + b = [int(part) for part in parts] + return struct.pack('BBBB', *b) + except Exception: + raise dns.exception.SyntaxError diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/ipv6.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/ipv6.py new file mode 100644 index 0000000..f0e522c --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/ipv6.py @@ -0,0 +1,197 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""IPv6 helper functions.""" + +import re +import binascii + +import dns.exception +import dns.ipv4 + +_leading_zero = re.compile(r'0+([0-9a-f]+)') + +def inet_ntoa(address): + """Convert an IPv6 address in binary form to text form. + + *address*, a ``bytes``, the IPv6 address in binary form. + + Raises ``ValueError`` if the address isn't 16 bytes long. + Returns a ``str``. + """ + + if len(address) != 16: + raise ValueError("IPv6 addresses are 16 bytes long") + hex = binascii.hexlify(address) + chunks = [] + i = 0 + l = len(hex) + while i < l: + chunk = hex[i:i + 4].decode() + # strip leading zeros. we do this with an re instead of + # with lstrip() because lstrip() didn't support chars until + # python 2.2.2 + m = _leading_zero.match(chunk) + if m is not None: + chunk = m.group(1) + chunks.append(chunk) + i += 4 + # + # Compress the longest subsequence of 0-value chunks to :: + # + best_start = 0 + best_len = 0 + start = -1 + last_was_zero = False + for i in range(8): + if chunks[i] != '0': + if last_was_zero: + end = i + current_len = end - start + if current_len > best_len: + best_start = start + best_len = current_len + last_was_zero = False + elif not last_was_zero: + start = i + last_was_zero = True + if last_was_zero: + end = 8 + current_len = end - start + if current_len > best_len: + best_start = start + best_len = current_len + if best_len > 1: + if best_start == 0 and \ + (best_len == 6 or + best_len == 5 and chunks[5] == 'ffff'): + # We have an embedded IPv4 address + if best_len == 6: + prefix = '::' + else: + prefix = '::ffff:' + hex = prefix + dns.ipv4.inet_ntoa(address[12:]) + else: + hex = ':'.join(chunks[:best_start]) + '::' + \ + ':'.join(chunks[best_start + best_len:]) + else: + hex = ':'.join(chunks) + return hex + +_v4_ending = re.compile(br'(.*):(\d+\.\d+\.\d+\.\d+)$') +_colon_colon_start = re.compile(br'::.*') +_colon_colon_end = re.compile(br'.*::$') + +def inet_aton(text, ignore_scope=False): + """Convert an IPv6 address in text form to binary form. + + *text*, a ``str``, the IPv6 address in textual form. + + *ignore_scope*, a ``bool``. If ``True``, a scope will be ignored. + If ``False``, the default, it is an error for a scope to be present. + + Returns a ``bytes``. + """ + + # + # Our aim here is not something fast; we just want something that works. + # + if not isinstance(text, bytes): + text = text.encode() + + if ignore_scope: + parts = text.split(b'%') + l = len(parts) + if l == 2: + text = parts[0] + elif l > 2: + raise dns.exception.SyntaxError + + if text == b'': + raise dns.exception.SyntaxError + elif text.endswith(b':') and not text.endswith(b'::'): + raise dns.exception.SyntaxError + elif text.startswith(b':') and not text.startswith(b'::'): + raise dns.exception.SyntaxError + elif text == b'::': + text = b'0::' + # + # Get rid of the icky dot-quad syntax if we have it. + # + m = _v4_ending.match(text) + if m is not None: + b = dns.ipv4.inet_aton(m.group(2)) + text = (u"{}:{:02x}{:02x}:{:02x}{:02x}".format(m.group(1).decode(), + b[0], b[1], b[2], + b[3])).encode() + # + # Try to turn '::' into ':'; if no match try to + # turn '::' into ':' + # + m = _colon_colon_start.match(text) + if m is not None: + text = text[1:] + else: + m = _colon_colon_end.match(text) + if m is not None: + text = text[:-1] + # + # Now canonicalize into 8 chunks of 4 hex digits each + # + chunks = text.split(b':') + l = len(chunks) + if l > 8: + raise dns.exception.SyntaxError + seen_empty = False + canonical = [] + for c in chunks: + if c == b'': + if seen_empty: + raise dns.exception.SyntaxError + seen_empty = True + for _ in range(0, 8 - l + 1): + canonical.append(b'0000') + else: + lc = len(c) + if lc > 4: + raise dns.exception.SyntaxError + if lc != 4: + c = (b'0' * (4 - lc)) + c + canonical.append(c) + if l < 8 and not seen_empty: + raise dns.exception.SyntaxError + text = b''.join(canonical) + + # + # Finally we can go to binary. + # + try: + return binascii.unhexlify(text) + except (binascii.Error, TypeError): + raise dns.exception.SyntaxError + +_mapped_prefix = b'\x00' * 10 + b'\xff\xff' + +def is_mapped(address): + """Is the specified address a mapped IPv4 address? + + *address*, a ``bytes`` is an IPv6 address in binary form. + + Returns a ``bool``. + """ + + return address.startswith(_mapped_prefix) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/message.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/message.py new file mode 100644 index 0000000..2a7565a --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/message.py @@ -0,0 +1,1507 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Messages""" + +import contextlib +import io +import time + +import dns.wire +import dns.edns +import dns.enum +import dns.exception +import dns.flags +import dns.name +import dns.opcode +import dns.entropy +import dns.rcode +import dns.rdata +import dns.rdataclass +import dns.rdatatype +import dns.rrset +import dns.renderer +import dns.ttl +import dns.tsig +import dns.rdtypes.ANY.OPT +import dns.rdtypes.ANY.TSIG + + +class ShortHeader(dns.exception.FormError): + """The DNS packet passed to from_wire() is too short.""" + + +class TrailingJunk(dns.exception.FormError): + """The DNS packet passed to from_wire() has extra junk at the end of it.""" + + +class UnknownHeaderField(dns.exception.DNSException): + """The header field name was not recognized when converting from text + into a message.""" + + +class BadEDNS(dns.exception.FormError): + """An OPT record occurred somewhere other than + the additional data section.""" + + +class BadTSIG(dns.exception.FormError): + """A TSIG record occurred somewhere other than the end of + the additional data section.""" + + +class UnknownTSIGKey(dns.exception.DNSException): + """A TSIG with an unknown key was received.""" + + +class Truncated(dns.exception.DNSException): + """The truncated flag is set.""" + + supp_kwargs = {'message'} + + def message(self): + """As much of the message as could be processed. + + Returns a ``dns.message.Message``. + """ + return self.kwargs['message'] + + +class NotQueryResponse(dns.exception.DNSException): + """Message is not a response to a query.""" + + +class ChainTooLong(dns.exception.DNSException): + """The CNAME chain is too long.""" + + +class AnswerForNXDOMAIN(dns.exception.DNSException): + """The rcode is NXDOMAIN but an answer was found.""" + +class NoPreviousName(dns.exception.SyntaxError): + """No previous name was known.""" + + +class MessageSection(dns.enum.IntEnum): + """Message sections""" + QUESTION = 0 + ANSWER = 1 + AUTHORITY = 2 + ADDITIONAL = 3 + + @classmethod + def _maximum(cls): + return 3 + + +DEFAULT_EDNS_PAYLOAD = 1232 +MAX_CHAIN = 16 + +class Message: + """A DNS message.""" + + _section_enum = MessageSection + + def __init__(self, id=None): + if id is None: + self.id = dns.entropy.random_16() + else: + self.id = id + self.flags = 0 + self.sections = [[], [], [], []] + self.opt = None + self.request_payload = 0 + self.keyring = None + self.tsig = None + self.request_mac = b'' + self.xfr = False + self.origin = None + self.tsig_ctx = None + self.index = {} + + @property + def question(self): + """ The question section.""" + return self.sections[0] + + @question.setter + def question(self, v): + self.sections[0] = v + + @property + def answer(self): + """ The answer section.""" + return self.sections[1] + + @answer.setter + def answer(self, v): + self.sections[1] = v + + @property + def authority(self): + """ The authority section.""" + return self.sections[2] + + @authority.setter + def authority(self, v): + self.sections[2] = v + + @property + def additional(self): + """ The additional data section.""" + return self.sections[3] + + @additional.setter + def additional(self, v): + self.sections[3] = v + + def __repr__(self): + return '' + + def __str__(self): + return self.to_text() + + def to_text(self, origin=None, relativize=True, **kw): + """Convert the message to text. + + The *origin*, *relativize*, and any other keyword + arguments are passed to the RRset ``to_wire()`` method. + + Returns a ``str``. + """ + + s = io.StringIO() + s.write('id %d\n' % self.id) + s.write('opcode %s\n' % dns.opcode.to_text(self.opcode())) + s.write('rcode %s\n' % dns.rcode.to_text(self.rcode())) + s.write('flags %s\n' % dns.flags.to_text(self.flags)) + if self.edns >= 0: + s.write('edns %s\n' % self.edns) + if self.ednsflags != 0: + s.write('eflags %s\n' % + dns.flags.edns_to_text(self.ednsflags)) + s.write('payload %d\n' % self.payload) + for opt in self.options: + s.write('option %s\n' % opt.to_text()) + for (name, which) in self._section_enum.__members__.items(): + s.write(f';{name}\n') + for rrset in self.section_from_number(which): + s.write(rrset.to_text(origin, relativize, **kw)) + s.write('\n') + # + # We strip off the final \n so the caller can print the result without + # doing weird things to get around eccentricities in Python print + # formatting + # + return s.getvalue()[:-1] + + def __eq__(self, other): + """Two messages are equal if they have the same content in the + header, question, answer, and authority sections. + + Returns a ``bool``. + """ + + if not isinstance(other, Message): + return False + if self.id != other.id: + return False + if self.flags != other.flags: + return False + for i, section in enumerate(self.sections): + other_section = other.sections[i] + for n in section: + if n not in other_section: + return False + for n in other_section: + if n not in section: + return False + return True + + def __ne__(self, other): + return not self.__eq__(other) + + def is_response(self, other): + """Is *other* a response this message? + + Returns a ``bool``. + """ + + if other.flags & dns.flags.QR == 0 or \ + self.id != other.id or \ + dns.opcode.from_flags(self.flags) != \ + dns.opcode.from_flags(other.flags): + return False + if other.rcode() in {dns.rcode.FORMERR, dns.rcode.SERVFAIL, + dns.rcode.NOTIMP, dns.rcode.REFUSED}: + # We don't check the question section in these cases if + # the other question section is empty, even though they + # still really ought to have a question section. + if len(other.question) == 0: + return True + if dns.opcode.is_update(self.flags): + # This is assuming the "sender doesn't include anything + # from the update", but we don't care to check the other + # case, which is that all the sections are returned and + # identical. + return True + for n in self.question: + if n not in other.question: + return False + for n in other.question: + if n not in self.question: + return False + return True + + def section_number(self, section): + """Return the "section number" of the specified section for use + in indexing. + + *section* is one of the section attributes of this message. + + Raises ``ValueError`` if the section isn't known. + + Returns an ``int``. + """ + + for i, our_section in enumerate(self.sections): + if section is our_section: + return self._section_enum(i) + raise ValueError('unknown section') + + def section_from_number(self, number): + """Return the section list associated with the specified section + number. + + *number* is a section number `int` or the text form of a section + name. + + Raises ``ValueError`` if the section isn't known. + + Returns a ``list``. + """ + + section = self._section_enum.make(number) + return self.sections[section] + + def find_rrset(self, section, name, rdclass, rdtype, + covers=dns.rdatatype.NONE, deleting=None, create=False, + force_unique=False): + """Find the RRset with the given attributes in the specified section. + + *section*, an ``int`` section number, or one of the section + attributes of this message. This specifies the + the section of the message to search. For example:: + + my_message.find_rrset(my_message.answer, name, rdclass, rdtype) + my_message.find_rrset(dns.message.ANSWER, name, rdclass, rdtype) + + *name*, a ``dns.name.Name``, the name of the RRset. + + *rdclass*, an ``int``, the class of the RRset. + + *rdtype*, an ``int``, the type of the RRset. + + *covers*, an ``int`` or ``None``, the covers value of the RRset. + The default is ``None``. + + *deleting*, an ``int`` or ``None``, the deleting value of the RRset. + The default is ``None``. + + *create*, a ``bool``. If ``True``, create the RRset if it is not found. + The created RRset is appended to *section*. + + *force_unique*, a ``bool``. If ``True`` and *create* is also ``True``, + create a new RRset regardless of whether a matching RRset exists + already. The default is ``False``. This is useful when creating + DDNS Update messages, as order matters for them. + + Raises ``KeyError`` if the RRset was not found and create was + ``False``. + + Returns a ``dns.rrset.RRset object``. + """ + + if isinstance(section, int): + section_number = section + section = self.section_from_number(section_number) + else: + section_number = self.section_number(section) + key = (section_number, name, rdclass, rdtype, covers, deleting) + if not force_unique: + if self.index is not None: + rrset = self.index.get(key) + if rrset is not None: + return rrset + else: + for rrset in section: + if rrset.full_match(name, rdclass, rdtype, covers, + deleting): + return rrset + if not create: + raise KeyError + rrset = dns.rrset.RRset(name, rdclass, rdtype, covers, deleting) + section.append(rrset) + if self.index is not None: + self.index[key] = rrset + return rrset + + def get_rrset(self, section, name, rdclass, rdtype, + covers=dns.rdatatype.NONE, deleting=None, create=False, + force_unique=False): + """Get the RRset with the given attributes in the specified section. + + If the RRset is not found, None is returned. + + *section*, an ``int`` section number, or one of the section + attributes of this message. This specifies the + the section of the message to search. For example:: + + my_message.get_rrset(my_message.answer, name, rdclass, rdtype) + my_message.get_rrset(dns.message.ANSWER, name, rdclass, rdtype) + + *name*, a ``dns.name.Name``, the name of the RRset. + + *rdclass*, an ``int``, the class of the RRset. + + *rdtype*, an ``int``, the type of the RRset. + + *covers*, an ``int`` or ``None``, the covers value of the RRset. + The default is ``None``. + + *deleting*, an ``int`` or ``None``, the deleting value of the RRset. + The default is ``None``. + + *create*, a ``bool``. If ``True``, create the RRset if it is not found. + The created RRset is appended to *section*. + + *force_unique*, a ``bool``. If ``True`` and *create* is also ``True``, + create a new RRset regardless of whether a matching RRset exists + already. The default is ``False``. This is useful when creating + DDNS Update messages, as order matters for them. + + Returns a ``dns.rrset.RRset object`` or ``None``. + """ + + try: + rrset = self.find_rrset(section, name, rdclass, rdtype, covers, + deleting, create, force_unique) + except KeyError: + rrset = None + return rrset + + def to_wire(self, origin=None, max_size=0, multi=False, tsig_ctx=None, + **kw): + """Return a string containing the message in DNS compressed wire + format. + + Additional keyword arguments are passed to the RRset ``to_wire()`` + method. + + *origin*, a ``dns.name.Name`` or ``None``, the origin to be appended + to any relative names. If ``None``, and the message has an origin + attribute that is not ``None``, then it will be used. + + *max_size*, an ``int``, the maximum size of the wire format + output; default is 0, which means "the message's request + payload, if nonzero, or 65535". + + *multi*, a ``bool``, should be set to ``True`` if this message is + part of a multiple message sequence. + + *tsig_ctx*, a ``dns.tsig.HMACTSig`` or ``dns.tsig.GSSTSig`` object, the + ongoing TSIG context, used when signing zone transfers. + + Raises ``dns.exception.TooBig`` if *max_size* was exceeded. + + Returns a ``bytes``. + """ + + if origin is None and self.origin is not None: + origin = self.origin + if max_size == 0: + if self.request_payload != 0: + max_size = self.request_payload + else: + max_size = 65535 + if max_size < 512: + max_size = 512 + elif max_size > 65535: + max_size = 65535 + r = dns.renderer.Renderer(self.id, self.flags, max_size, origin) + for rrset in self.question: + r.add_question(rrset.name, rrset.rdtype, rrset.rdclass) + for rrset in self.answer: + r.add_rrset(dns.renderer.ANSWER, rrset, **kw) + for rrset in self.authority: + r.add_rrset(dns.renderer.AUTHORITY, rrset, **kw) + if self.opt is not None: + r.add_rrset(dns.renderer.ADDITIONAL, self.opt) + for rrset in self.additional: + r.add_rrset(dns.renderer.ADDITIONAL, rrset, **kw) + r.write_header() + if self.tsig is not None: + (new_tsig, ctx) = dns.tsig.sign(r.get_wire(), + self.keyring, + self.tsig[0], + int(time.time()), + self.request_mac, + tsig_ctx, + multi) + self.tsig.clear() + self.tsig.add(new_tsig) + r.add_rrset(dns.renderer.ADDITIONAL, self.tsig) + r.write_header() + if multi: + self.tsig_ctx = ctx + return r.get_wire() + + @staticmethod + def _make_tsig(keyname, algorithm, time_signed, fudge, mac, original_id, + error, other): + tsig = dns.rdtypes.ANY.TSIG.TSIG(dns.rdataclass.ANY, dns.rdatatype.TSIG, + algorithm, time_signed, fudge, mac, + original_id, error, other) + return dns.rrset.from_rdata(keyname, 0, tsig) + + def use_tsig(self, keyring, keyname=None, fudge=300, + original_id=None, tsig_error=0, other_data=b'', + algorithm=dns.tsig.default_algorithm): + """When sending, a TSIG signature using the specified key + should be added. + + *key*, a ``dns.tsig.Key`` is the key to use. If a key is specified, + the *keyring* and *algorithm* fields are not used. + + *keyring*, a ``dict``, ``callable`` or ``dns.tsig.Key``, is either + the TSIG keyring or key to use. + + The format of a keyring dict is a mapping from TSIG key name, as + ``dns.name.Name`` to ``dns.tsig.Key`` or a TSIG secret, a ``bytes``. + If a ``dict`` *keyring* is specified but a *keyname* is not, the key + used will be the first key in the *keyring*. Note that the order of + keys in a dictionary is not defined, so applications should supply a + keyname when a ``dict`` keyring is used, unless they know the keyring + contains only one key. If a ``callable`` keyring is specified, the + callable will be called with the message and the keyname, and is + expected to return a key. + + *keyname*, a ``dns.name.Name``, ``str`` or ``None``, the name of + thes TSIG key to use; defaults to ``None``. If *keyring* is a + ``dict``, the key must be defined in it. If *keyring* is a + ``dns.tsig.Key``, this is ignored. + + *fudge*, an ``int``, the TSIG time fudge. + + *original_id*, an ``int``, the TSIG original id. If ``None``, + the message's id is used. + + *tsig_error*, an ``int``, the TSIG error code. + + *other_data*, a ``bytes``, the TSIG other data. + + *algorithm*, a ``dns.name.Name``, the TSIG algorithm to use. This is + only used if *keyring* is a ``dict``, and the key entry is a ``bytes``. + """ + + if isinstance(keyring, dns.tsig.Key): + key = keyring + keyname = key.name + elif callable(keyring): + key = keyring(self, keyname) + else: + if isinstance(keyname, str): + keyname = dns.name.from_text(keyname) + if keyname is None: + keyname = next(iter(keyring)) + key = keyring[keyname] + if isinstance(key, bytes): + key = dns.tsig.Key(keyname, key, algorithm) + self.keyring = key + if original_id is None: + original_id = self.id + self.tsig = self._make_tsig(keyname, self.keyring.algorithm, 0, fudge, + b'', original_id, tsig_error, other_data) + + @property + def keyname(self): + if self.tsig: + return self.tsig.name + else: + return None + + @property + def keyalgorithm(self): + if self.tsig: + return self.tsig[0].algorithm + else: + return None + + @property + def mac(self): + if self.tsig: + return self.tsig[0].mac + else: + return None + + @property + def tsig_error(self): + if self.tsig: + return self.tsig[0].error + else: + return None + + @property + def had_tsig(self): + return bool(self.tsig) + + @staticmethod + def _make_opt(flags=0, payload=DEFAULT_EDNS_PAYLOAD, options=None): + opt = dns.rdtypes.ANY.OPT.OPT(payload, dns.rdatatype.OPT, + options or ()) + return dns.rrset.from_rdata(dns.name.root, int(flags), opt) + + def use_edns(self, edns=0, ednsflags=0, payload=DEFAULT_EDNS_PAYLOAD, + request_payload=None, options=None): + """Configure EDNS behavior. + + *edns*, an ``int``, is the EDNS level to use. Specifying + ``None``, ``False``, or ``-1`` means "do not use EDNS", and in this case + the other parameters are ignored. Specifying ``True`` is + equivalent to specifying 0, i.e. "use EDNS0". + + *ednsflags*, an ``int``, the EDNS flag values. + + *payload*, an ``int``, is the EDNS sender's payload field, which is the + maximum size of UDP datagram the sender can handle. I.e. how big + a response to this message can be. + + *request_payload*, an ``int``, is the EDNS payload size to use when + sending this message. If not specified, defaults to the value of + *payload*. + + *options*, a list of ``dns.edns.Option`` objects or ``None``, the EDNS + options. + """ + + if edns is None or edns is False: + edns = -1 + elif edns is True: + edns = 0 + if edns < 0: + self.opt = None + self.request_payload = 0 + else: + # make sure the EDNS version in ednsflags agrees with edns + ednsflags &= 0xFF00FFFF + ednsflags |= (edns << 16) + if options is None: + options = [] + self.opt = self._make_opt(ednsflags, payload, options) + if request_payload is None: + request_payload = payload + self.request_payload = request_payload + + @property + def edns(self): + if self.opt: + return (self.ednsflags & 0xff0000) >> 16 + else: + return -1 + + @property + def ednsflags(self): + if self.opt: + return self.opt.ttl + else: + return 0 + + @ednsflags.setter + def ednsflags(self, v): + if self.opt: + self.opt.ttl = v + elif v: + self.opt = self._make_opt(v) + + @property + def payload(self): + if self.opt: + return self.opt[0].payload + else: + return 0 + + @property + def options(self): + if self.opt: + return self.opt[0].options + else: + return () + + def want_dnssec(self, wanted=True): + """Enable or disable 'DNSSEC desired' flag in requests. + + *wanted*, a ``bool``. If ``True``, then DNSSEC data is + desired in the response, EDNS is enabled if required, and then + the DO bit is set. If ``False``, the DO bit is cleared if + EDNS is enabled. + """ + + if wanted: + self.ednsflags |= dns.flags.DO + elif self.opt: + self.ednsflags &= ~dns.flags.DO + + def rcode(self): + """Return the rcode. + + Returns an ``int``. + """ + return dns.rcode.from_flags(int(self.flags), int(self.ednsflags)) + + def set_rcode(self, rcode): + """Set the rcode. + + *rcode*, an ``int``, is the rcode to set. + """ + (value, evalue) = dns.rcode.to_flags(rcode) + self.flags &= 0xFFF0 + self.flags |= value + self.ednsflags &= 0x00FFFFFF + self.ednsflags |= evalue + + def opcode(self): + """Return the opcode. + + Returns an ``int``. + """ + return dns.opcode.from_flags(int(self.flags)) + + def set_opcode(self, opcode): + """Set the opcode. + + *opcode*, an ``int``, is the opcode to set. + """ + self.flags &= 0x87FF + self.flags |= dns.opcode.to_flags(opcode) + + def _get_one_rr_per_rrset(self, value): + # What the caller picked is fine. + return value + + # pylint: disable=unused-argument + + def _parse_rr_header(self, section, name, rdclass, rdtype): + return (rdclass, rdtype, None, False) + + # pylint: enable=unused-argument + + def _parse_special_rr_header(self, section, count, position, + name, rdclass, rdtype): + if rdtype == dns.rdatatype.OPT: + if section != MessageSection.ADDITIONAL or self.opt or \ + name != dns.name.root: + raise BadEDNS + elif rdtype == dns.rdatatype.TSIG: + if section != MessageSection.ADDITIONAL or \ + rdclass != dns.rdatatype.ANY or \ + position != count - 1: + raise BadTSIG + return (rdclass, rdtype, None, False) + + +class ChainingResult: + """The result of a call to dns.message.QueryMessage.resolve_chaining(). + + The ``answer`` attribute is the answer RRSet, or ``None`` if it doesn't + exist. + + The ``canonical_name`` attribute is the canonical name after all + chaining has been applied (this is the name as ``rrset.name`` in cases + where rrset is not ``None``). + + The ``minimum_ttl`` attribute is the minimum TTL, i.e. the TTL to + use if caching the data. It is the smallest of all the CNAME TTLs + and either the answer TTL if it exists or the SOA TTL and SOA + minimum values for negative answers. + + The ``cnames`` attribute is a list of all the CNAME RRSets followed to + get to the canonical name. + """ + def __init__(self, canonical_name, answer, minimum_ttl, cnames): + self.canonical_name = canonical_name + self.answer = answer + self.minimum_ttl = minimum_ttl + self.cnames = cnames + + +class QueryMessage(Message): + def resolve_chaining(self): + """Follow the CNAME chain in the response to determine the answer + RRset. + + Raises ``dns.message.NotQueryResponse`` if the message is not + a response. + + Raises ``dns.message.ChainTooLong`` if the CNAME chain is too long. + + Raises ``dns.message.AnswerForNXDOMAIN`` if the rcode is NXDOMAIN + but an answer was found. + + Raises ``dns.exception.FormError`` if the question count is not 1. + + Returns a ChainingResult object. + """ + if self.flags & dns.flags.QR == 0: + raise NotQueryResponse + if len(self.question) != 1: + raise dns.exception.FormError + question = self.question[0] + qname = question.name + min_ttl = dns.ttl.MAX_TTL + answer = None + count = 0 + cnames = [] + while count < MAX_CHAIN: + try: + answer = self.find_rrset(self.answer, qname, question.rdclass, + question.rdtype) + min_ttl = min(min_ttl, answer.ttl) + break + except KeyError: + if question.rdtype != dns.rdatatype.CNAME: + try: + crrset = self.find_rrset(self.answer, qname, + question.rdclass, + dns.rdatatype.CNAME) + cnames.append(crrset) + min_ttl = min(min_ttl, crrset.ttl) + for rd in crrset: + qname = rd.target + break + count += 1 + continue + except KeyError: + # Exit the chaining loop + break + else: + # Exit the chaining loop + break + if count >= MAX_CHAIN: + raise ChainTooLong + if self.rcode() == dns.rcode.NXDOMAIN and answer is not None: + raise AnswerForNXDOMAIN + if answer is None: + # Further minimize the TTL with NCACHE. + auname = qname + while True: + # Look for an SOA RR whose owner name is a superdomain + # of qname. + try: + srrset = self.find_rrset(self.authority, auname, + question.rdclass, + dns.rdatatype.SOA) + min_ttl = min(min_ttl, srrset.ttl, srrset[0].minimum) + break + except KeyError: + try: + auname = auname.parent() + except dns.name.NoParent: + break + return ChainingResult(qname, answer, min_ttl, cnames) + + def canonical_name(self): + """Return the canonical name of the first name in the question + section. + + Raises ``dns.message.NotQueryResponse`` if the message is not + a response. + + Raises ``dns.message.ChainTooLong`` if the CNAME chain is too long. + + Raises ``dns.message.AnswerForNXDOMAIN`` if the rcode is NXDOMAIN + but an answer was found. + + Raises ``dns.exception.FormError`` if the question count is not 1. + """ + return self.resolve_chaining().canonical_name + + +def _maybe_import_update(): + # We avoid circular imports by doing this here. We do it in another + # function as doing it in _message_factory_from_opcode() makes "dns" + # a local symbol, and the first line fails :) + + # pylint: disable=redefined-outer-name,import-outside-toplevel,unused-import + import dns.update # noqa: F401 + + +def _message_factory_from_opcode(opcode): + if opcode == dns.opcode.QUERY: + return QueryMessage + elif opcode == dns.opcode.UPDATE: + _maybe_import_update() + return dns.update.UpdateMessage + else: + return Message + + +class _WireReader: + + """Wire format reader. + + parser: the binary parser + message: The message object being built + initialize_message: Callback to set message parsing options + question_only: Are we only reading the question? + one_rr_per_rrset: Put each RR into its own RRset? + keyring: TSIG keyring + ignore_trailing: Ignore trailing junk at end of request? + multi: Is this message part of a multi-message sequence? + DNS dynamic updates. + """ + + def __init__(self, wire, initialize_message, question_only=False, + one_rr_per_rrset=False, ignore_trailing=False, + keyring=None, multi=False): + self.parser = dns.wire.Parser(wire) + self.message = None + self.initialize_message = initialize_message + self.question_only = question_only + self.one_rr_per_rrset = one_rr_per_rrset + self.ignore_trailing = ignore_trailing + self.keyring = keyring + self.multi = multi + + def _get_question(self, section_number, qcount): + """Read the next *qcount* records from the wire data and add them to + the question section. + """ + + section = self.message.sections[section_number] + for _ in range(qcount): + qname = self.parser.get_name(self.message.origin) + (rdtype, rdclass) = self.parser.get_struct('!HH') + (rdclass, rdtype, _, _) = \ + self.message._parse_rr_header(section_number, qname, rdclass, + rdtype) + self.message.find_rrset(section, qname, rdclass, rdtype, + create=True, force_unique=True) + + def _get_section(self, section_number, count): + """Read the next I{count} records from the wire data and add them to + the specified section. + + section: the section of the message to which to add records + count: the number of records to read + """ + + section = self.message.sections[section_number] + force_unique = self.one_rr_per_rrset + for i in range(count): + rr_start = self.parser.current + absolute_name = self.parser.get_name() + if self.message.origin is not None: + name = absolute_name.relativize(self.message.origin) + else: + name = absolute_name + (rdtype, rdclass, ttl, rdlen) = self.parser.get_struct('!HHIH') + if rdtype in (dns.rdatatype.OPT, dns.rdatatype.TSIG): + (rdclass, rdtype, deleting, empty) = \ + self.message._parse_special_rr_header(section_number, + count, i, name, + rdclass, rdtype) + else: + (rdclass, rdtype, deleting, empty) = \ + self.message._parse_rr_header(section_number, + name, rdclass, rdtype) + if empty: + if rdlen > 0: + raise dns.exception.FormError + rd = None + covers = dns.rdatatype.NONE + else: + with self.parser.restrict_to(rdlen): + rd = dns.rdata.from_wire_parser(rdclass, rdtype, + self.parser, + self.message.origin) + covers = rd.covers() + if self.message.xfr and rdtype == dns.rdatatype.SOA: + force_unique = True + if rdtype == dns.rdatatype.OPT: + self.message.opt = dns.rrset.from_rdata(name, ttl, rd) + elif rdtype == dns.rdatatype.TSIG: + if self.keyring is None: + raise UnknownTSIGKey('got signed message without keyring') + if isinstance(self.keyring, dict): + key = self.keyring.get(absolute_name) + if isinstance(key, bytes): + key = dns.tsig.Key(absolute_name, key, rd.algorithm) + elif callable(self.keyring): + key = self.keyring(self.message, absolute_name) + else: + key = self.keyring + if key is None: + raise UnknownTSIGKey("key '%s' unknown" % name) + self.message.keyring = key + self.message.tsig_ctx = \ + dns.tsig.validate(self.parser.wire, + key, + absolute_name, + rd, + int(time.time()), + self.message.request_mac, + rr_start, + self.message.tsig_ctx, + self.multi) + self.message.tsig = dns.rrset.from_rdata(absolute_name, 0, rd) + else: + rrset = self.message.find_rrset(section, name, + rdclass, rdtype, covers, + deleting, True, + force_unique) + if rd is not None: + if ttl > 0x7fffffff: + ttl = 0 + rrset.add(rd, ttl) + + def read(self): + """Read a wire format DNS message and build a dns.message.Message + object.""" + + if self.parser.remaining() < 12: + raise ShortHeader + (id, flags, qcount, ancount, aucount, adcount) = \ + self.parser.get_struct('!HHHHHH') + factory = _message_factory_from_opcode(dns.opcode.from_flags(flags)) + self.message = factory(id=id) + self.message.flags = dns.flags.Flag(flags) + self.initialize_message(self.message) + self.one_rr_per_rrset = \ + self.message._get_one_rr_per_rrset(self.one_rr_per_rrset) + self._get_question(MessageSection.QUESTION, qcount) + if self.question_only: + return self.message + self._get_section(MessageSection.ANSWER, ancount) + self._get_section(MessageSection.AUTHORITY, aucount) + self._get_section(MessageSection.ADDITIONAL, adcount) + if not self.ignore_trailing and self.parser.remaining() != 0: + raise TrailingJunk + if self.multi and self.message.tsig_ctx and not self.message.had_tsig: + self.message.tsig_ctx.update(self.parser.wire) + return self.message + + +def from_wire(wire, keyring=None, request_mac=b'', xfr=False, origin=None, + tsig_ctx=None, multi=False, + question_only=False, one_rr_per_rrset=False, + ignore_trailing=False, raise_on_truncation=False): + """Convert a DNS wire format message into a message + object. + + *keyring*, a ``dns.tsig.Key`` or ``dict``, the key or keyring to use + if the message is signed. + + *request_mac*, a ``bytes``. If the message is a response to a + TSIG-signed request, *request_mac* should be set to the MAC of + that request. + + *xfr*, a ``bool``, should be set to ``True`` if this message is part of + a zone transfer. + + *origin*, a ``dns.name.Name`` or ``None``. If the message is part + of a zone transfer, *origin* should be the origin name of the + zone. If not ``None``, names will be relativized to the origin. + + *tsig_ctx*, a ``dns.tsig.HMACTSig`` or ``dns.tsig.GSSTSig`` object, the + ongoing TSIG context, used when validating zone transfers. + + *multi*, a ``bool``, should be set to ``True`` if this message is + part of a multiple message sequence. + + *question_only*, a ``bool``. If ``True``, read only up to + the end of the question section. + + *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its + own RRset. + + *ignore_trailing*, a ``bool``. If ``True``, ignore trailing + junk at end of the message. + + *raise_on_truncation*, a ``bool``. If ``True``, raise an exception if + the TC bit is set. + + Raises ``dns.message.ShortHeader`` if the message is less than 12 octets + long. + + Raises ``dns.message.TrailingJunk`` if there were octets in the message + past the end of the proper DNS message, and *ignore_trailing* is ``False``. + + Raises ``dns.message.BadEDNS`` if an OPT record was in the + wrong section, or occurred more than once. + + Raises ``dns.message.BadTSIG`` if a TSIG record was not the last + record of the additional data section. + + Raises ``dns.message.Truncated`` if the TC flag is set and + *raise_on_truncation* is ``True``. + + Returns a ``dns.message.Message``. + """ + + def initialize_message(message): + message.request_mac = request_mac + message.xfr = xfr + message.origin = origin + message.tsig_ctx = tsig_ctx + + reader = _WireReader(wire, initialize_message, question_only, + one_rr_per_rrset, ignore_trailing, keyring, multi) + try: + m = reader.read() + except dns.exception.FormError: + if reader.message and (reader.message.flags & dns.flags.TC) and \ + raise_on_truncation: + raise Truncated(message=reader.message) + else: + raise + # Reading a truncated message might not have any errors, so we + # have to do this check here too. + if m.flags & dns.flags.TC and raise_on_truncation: + raise Truncated(message=m) + + return m + + +class _TextReader: + + """Text format reader. + + tok: the tokenizer. + message: The message object being built. + DNS dynamic updates. + last_name: The most recently read name when building a message object. + one_rr_per_rrset: Put each RR into its own RRset? + origin: The origin for relative names + relativize: relativize names? + relativize_to: the origin to relativize to. + """ + + def __init__(self, text, idna_codec, one_rr_per_rrset=False, + origin=None, relativize=True, relativize_to=None): + self.message = None + self.tok = dns.tokenizer.Tokenizer(text, idna_codec=idna_codec) + self.last_name = None + self.one_rr_per_rrset = one_rr_per_rrset + self.origin = origin + self.relativize = relativize + self.relativize_to = relativize_to + self.id = None + self.edns = -1 + self.ednsflags = 0 + self.payload = DEFAULT_EDNS_PAYLOAD + self.rcode = None + self.opcode = dns.opcode.QUERY + self.flags = 0 + + def _header_line(self, _): + """Process one line from the text format header section.""" + + token = self.tok.get() + what = token.value + if what == 'id': + self.id = self.tok.get_int() + elif what == 'flags': + while True: + token = self.tok.get() + if not token.is_identifier(): + self.tok.unget(token) + break + self.flags = self.flags | dns.flags.from_text(token.value) + elif what == 'edns': + self.edns = self.tok.get_int() + self.ednsflags = self.ednsflags | (self.edns << 16) + elif what == 'eflags': + if self.edns < 0: + self.edns = 0 + while True: + token = self.tok.get() + if not token.is_identifier(): + self.tok.unget(token) + break + self.ednsflags = self.ednsflags | \ + dns.flags.edns_from_text(token.value) + elif what == 'payload': + self.payload = self.tok.get_int() + if self.edns < 0: + self.edns = 0 + elif what == 'opcode': + text = self.tok.get_string() + self.opcode = dns.opcode.from_text(text) + self.flags = self.flags | dns.opcode.to_flags(self.opcode) + elif what == 'rcode': + text = self.tok.get_string() + self.rcode = dns.rcode.from_text(text) + else: + raise UnknownHeaderField + self.tok.get_eol() + + def _question_line(self, section_number): + """Process one line from the text format question section.""" + + section = self.message.sections[section_number] + token = self.tok.get(want_leading=True) + if not token.is_whitespace(): + self.last_name = self.tok.as_name(token, self.message.origin, + self.relativize, + self.relativize_to) + name = self.last_name + if name is None: + raise NoPreviousName + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + # Class + try: + rdclass = dns.rdataclass.from_text(token.value) + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + except dns.exception.SyntaxError: + raise dns.exception.SyntaxError + except Exception: + rdclass = dns.rdataclass.IN + # Type + rdtype = dns.rdatatype.from_text(token.value) + (rdclass, rdtype, _, _) = \ + self.message._parse_rr_header(section_number, name, rdclass, rdtype) + self.message.find_rrset(section, name, rdclass, rdtype, create=True, + force_unique=True) + self.tok.get_eol() + + def _rr_line(self, section_number): + """Process one line from the text format answer, authority, or + additional data sections. + """ + + section = self.message.sections[section_number] + # Name + token = self.tok.get(want_leading=True) + if not token.is_whitespace(): + self.last_name = self.tok.as_name(token, self.message.origin, + self.relativize, + self.relativize_to) + name = self.last_name + if name is None: + raise NoPreviousName + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + # TTL + try: + ttl = int(token.value, 0) + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + except dns.exception.SyntaxError: + raise dns.exception.SyntaxError + except Exception: + ttl = 0 + # Class + try: + rdclass = dns.rdataclass.from_text(token.value) + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + except dns.exception.SyntaxError: + raise dns.exception.SyntaxError + except Exception: + rdclass = dns.rdataclass.IN + # Type + rdtype = dns.rdatatype.from_text(token.value) + (rdclass, rdtype, deleting, empty) = \ + self.message._parse_rr_header(section_number, name, rdclass, rdtype) + token = self.tok.get() + if empty and not token.is_eol_or_eof(): + raise dns.exception.SyntaxError + if not empty and token.is_eol_or_eof(): + raise dns.exception.UnexpectedEnd + if not token.is_eol_or_eof(): + self.tok.unget(token) + rd = dns.rdata.from_text(rdclass, rdtype, self.tok, + self.message.origin, self.relativize, + self.relativize_to) + covers = rd.covers() + else: + rd = None + covers = dns.rdatatype.NONE + rrset = self.message.find_rrset(section, name, + rdclass, rdtype, covers, + deleting, True, self.one_rr_per_rrset) + if rd is not None: + rrset.add(rd, ttl) + + def _make_message(self): + factory = _message_factory_from_opcode(self.opcode) + message = factory(id=self.id) + message.flags = self.flags + if self.edns >= 0: + message.use_edns(self.edns, self.ednsflags, self.payload) + if self.rcode: + message.set_rcode(self.rcode) + if self.origin: + message.origin = self.origin + return message + + def read(self): + """Read a text format DNS message and build a dns.message.Message + object.""" + + line_method = self._header_line + section_number = None + while 1: + token = self.tok.get(True, True) + if token.is_eol_or_eof(): + break + if token.is_comment(): + u = token.value.upper() + if u == 'HEADER': + line_method = self._header_line + + if self.message: + message = self.message + else: + # If we don't have a message, create one with the current + # opcode, so that we know which section names to parse. + message = self._make_message() + try: + section_number = message._section_enum.from_text(u) + # We found a section name. If we don't have a message, + # use the one we just created. + if not self.message: + self.message = message + self.one_rr_per_rrset = \ + message._get_one_rr_per_rrset(self.one_rr_per_rrset) + if section_number == MessageSection.QUESTION: + line_method = self._question_line + else: + line_method = self._rr_line + except Exception: + # It's just a comment. + pass + self.tok.get_eol() + continue + self.tok.unget(token) + line_method(section_number) + if not self.message: + self.message = self._make_message() + return self.message + + +def from_text(text, idna_codec=None, one_rr_per_rrset=False, + origin=None, relativize=True, relativize_to=None): + """Convert the text format message into a message object. + + The reader stops after reading the first blank line in the input to + facilitate reading multiple messages from a single file with + ``dns.message.from_file()``. + + *text*, a ``str``, the text format message. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder + is used. + + *one_rr_per_rrset*, a ``bool``. If ``True``, then each RR is put + into its own rrset. The default is ``False``. + + *origin*, a ``dns.name.Name`` (or ``None``), the + origin to use for relative names. + + *relativize*, a ``bool``. If true, name will be relativized. + + *relativize_to*, a ``dns.name.Name`` (or ``None``), the origin to use + when relativizing names. If not set, the *origin* value will be used. + + Raises ``dns.message.UnknownHeaderField`` if a header is unknown. + + Raises ``dns.exception.SyntaxError`` if the text is badly formed. + + Returns a ``dns.message.Message object`` + """ + + # 'text' can also be a file, but we don't publish that fact + # since it's an implementation detail. The official file + # interface is from_file(). + + reader = _TextReader(text, idna_codec, one_rr_per_rrset, origin, + relativize, relativize_to) + return reader.read() + + +def from_file(f, idna_codec=None, one_rr_per_rrset=False): + """Read the next text format message from the specified file. + + Message blocks are separated by a single blank line. + + *f*, a ``file`` or ``str``. If *f* is text, it is treated as the + pathname of a file to open. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder + is used. + + *one_rr_per_rrset*, a ``bool``. If ``True``, then each RR is put + into its own rrset. The default is ``False``. + + Raises ``dns.message.UnknownHeaderField`` if a header is unknown. + + Raises ``dns.exception.SyntaxError`` if the text is badly formed. + + Returns a ``dns.message.Message object`` + """ + + with contextlib.ExitStack() as stack: + if isinstance(f, str): + f = stack.enter_context(open(f)) + return from_text(f, idna_codec, one_rr_per_rrset) + + +def make_query(qname, rdtype, rdclass=dns.rdataclass.IN, use_edns=None, + want_dnssec=False, ednsflags=None, payload=None, + request_payload=None, options=None, idna_codec=None): + """Make a query message. + + The query name, type, and class may all be specified either + as objects of the appropriate type, or as strings. + + The query will have a randomly chosen query id, and its DNS flags + will be set to dns.flags.RD. + + qname, a ``dns.name.Name`` or ``str``, the query name. + + *rdtype*, an ``int`` or ``str``, the desired rdata type. + + *rdclass*, an ``int`` or ``str``, the desired rdata class; the default + is class IN. + + *use_edns*, an ``int``, ``bool`` or ``None``. The EDNS level to use; the + default is None (no EDNS). + See the description of dns.message.Message.use_edns() for the possible + values for use_edns and their meanings. + + *want_dnssec*, a ``bool``. If ``True``, DNSSEC data is desired. + + *ednsflags*, an ``int``, the EDNS flag values. + + *payload*, an ``int``, is the EDNS sender's payload field, which is the + maximum size of UDP datagram the sender can handle. I.e. how big + a response to this message can be. + + *request_payload*, an ``int``, is the EDNS payload size to use when + sending this message. If not specified, defaults to the value of + *payload*. + + *options*, a list of ``dns.edns.Option`` objects or ``None``, the EDNS + options. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder + is used. + + Returns a ``dns.message.QueryMessage`` + """ + + if isinstance(qname, str): + qname = dns.name.from_text(qname, idna_codec=idna_codec) + rdtype = dns.rdatatype.RdataType.make(rdtype) + rdclass = dns.rdataclass.RdataClass.make(rdclass) + m = QueryMessage() + m.flags |= dns.flags.RD + m.find_rrset(m.question, qname, rdclass, rdtype, create=True, + force_unique=True) + # only pass keywords on to use_edns if they have been set to a + # non-None value. Setting a field will turn EDNS on if it hasn't + # been configured. + kwargs = {} + if ednsflags is not None: + kwargs['ednsflags'] = ednsflags + if payload is not None: + kwargs['payload'] = payload + if request_payload is not None: + kwargs['request_payload'] = request_payload + if options is not None: + kwargs['options'] = options + if kwargs and use_edns is None: + use_edns = 0 + kwargs['edns'] = use_edns + m.use_edns(**kwargs) + m.want_dnssec(want_dnssec) + return m + + +def make_response(query, recursion_available=False, our_payload=8192, + fudge=300, tsig_error=0): + """Make a message which is a response for the specified query. + The message returned is really a response skeleton; it has all + of the infrastructure required of a response, but none of the + content. + + The response's question section is a shallow copy of the query's + question section, so the query's question RRsets should not be + changed. + + *query*, a ``dns.message.Message``, the query to respond to. + + *recursion_available*, a ``bool``, should RA be set in the response? + + *our_payload*, an ``int``, the payload size to advertise in EDNS + responses. + + *fudge*, an ``int``, the TSIG time fudge. + + *tsig_error*, an ``int``, the TSIG error. + + Returns a ``dns.message.Message`` object whose specific class is + appropriate for the query. For example, if query is a + ``dns.update.UpdateMessage``, response will be too. + """ + + if query.flags & dns.flags.QR: + raise dns.exception.FormError('specified query message is not a query') + factory = _message_factory_from_opcode(query.opcode()) + response = factory(id=query.id) + response.flags = dns.flags.QR | (query.flags & dns.flags.RD) + if recursion_available: + response.flags |= dns.flags.RA + response.set_opcode(query.opcode()) + response.question = list(query.question) + if query.edns >= 0: + response.use_edns(0, 0, our_payload, query.payload) + if query.had_tsig: + response.use_tsig(query.keyring, query.keyname, fudge, None, + tsig_error, b'', query.keyalgorithm) + response.request_mac = query.mac + return response + +### BEGIN generated MessageSection constants + +QUESTION = MessageSection.QUESTION +ANSWER = MessageSection.ANSWER +AUTHORITY = MessageSection.AUTHORITY +ADDITIONAL = MessageSection.ADDITIONAL + +### END generated MessageSection constants diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/name.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/name.py new file mode 100644 index 0000000..8905d70 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/name.py @@ -0,0 +1,1018 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Names. +""" + +import copy +import struct + +import encodings.idna # type: ignore +try: + import idna # type: ignore + have_idna_2008 = True +except ImportError: # pragma: no cover + have_idna_2008 = False + +import dns.wire +import dns.exception +import dns.immutable + +# fullcompare() result values + +#: The compared names have no relationship to each other. +NAMERELN_NONE = 0 +#: the first name is a superdomain of the second. +NAMERELN_SUPERDOMAIN = 1 +#: The first name is a subdomain of the second. +NAMERELN_SUBDOMAIN = 2 +#: The compared names are equal. +NAMERELN_EQUAL = 3 +#: The compared names have a common ancestor. +NAMERELN_COMMONANCESTOR = 4 + + +class EmptyLabel(dns.exception.SyntaxError): + """A DNS label is empty.""" + + +class BadEscape(dns.exception.SyntaxError): + """An escaped code in a text format of DNS name is invalid.""" + + +class BadPointer(dns.exception.FormError): + """A DNS compression pointer points forward instead of backward.""" + + +class BadLabelType(dns.exception.FormError): + """The label type in DNS name wire format is unknown.""" + + +class NeedAbsoluteNameOrOrigin(dns.exception.DNSException): + """An attempt was made to convert a non-absolute name to + wire when there was also a non-absolute (or missing) origin.""" + + +class NameTooLong(dns.exception.FormError): + """A DNS name is > 255 octets long.""" + + +class LabelTooLong(dns.exception.SyntaxError): + """A DNS label is > 63 octets long.""" + + +class AbsoluteConcatenation(dns.exception.DNSException): + """An attempt was made to append anything other than the + empty name to an absolute DNS name.""" + + +class NoParent(dns.exception.DNSException): + """An attempt was made to get the parent of the root name + or the empty name.""" + +class NoIDNA2008(dns.exception.DNSException): + """IDNA 2008 processing was requested but the idna module is not + available.""" + + +class IDNAException(dns.exception.DNSException): + """IDNA processing raised an exception.""" + + supp_kwargs = {'idna_exception'} + fmt = "IDNA processing exception: {idna_exception}" + + +class IDNACodec: + """Abstract base class for IDNA encoder/decoders.""" + + def __init__(self): + pass + + def is_idna(self, label): + return label.lower().startswith(b'xn--') + + def encode(self, label): + raise NotImplementedError # pragma: no cover + + def decode(self, label): + # We do not apply any IDNA policy on decode. + if self.is_idna(label): + try: + label = label[4:].decode('punycode') + except Exception as e: + raise IDNAException(idna_exception=e) + return _escapify(label) + + +class IDNA2003Codec(IDNACodec): + """IDNA 2003 encoder/decoder.""" + + def __init__(self, strict_decode=False): + """Initialize the IDNA 2003 encoder/decoder. + + *strict_decode* is a ``bool``. If `True`, then IDNA2003 checking + is done when decoding. This can cause failures if the name + was encoded with IDNA2008. The default is `False`. + """ + + super().__init__() + self.strict_decode = strict_decode + + def encode(self, label): + """Encode *label*.""" + + if label == '': + return b'' + try: + return encodings.idna.ToASCII(label) + except UnicodeError: + raise LabelTooLong + + def decode(self, label): + """Decode *label*.""" + if not self.strict_decode: + return super().decode(label) + if label == b'': + return '' + try: + return _escapify(encodings.idna.ToUnicode(label)) + except Exception as e: + raise IDNAException(idna_exception=e) + + +class IDNA2008Codec(IDNACodec): + """IDNA 2008 encoder/decoder. + """ + + def __init__(self, uts_46=False, transitional=False, + allow_pure_ascii=False, strict_decode=False): + """Initialize the IDNA 2008 encoder/decoder. + + *uts_46* is a ``bool``. If True, apply Unicode IDNA + compatibility processing as described in Unicode Technical + Standard #46 (http://unicode.org/reports/tr46/). + If False, do not apply the mapping. The default is False. + + *transitional* is a ``bool``: If True, use the + "transitional" mode described in Unicode Technical Standard + #46. The default is False. + + *allow_pure_ascii* is a ``bool``. If True, then a label which + consists of only ASCII characters is allowed. This is less + strict than regular IDNA 2008, but is also necessary for mixed + names, e.g. a name with starting with "_sip._tcp." and ending + in an IDN suffix which would otherwise be disallowed. The + default is False. + + *strict_decode* is a ``bool``: If True, then IDNA2008 checking + is done when decoding. This can cause failures if the name + was encoded with IDNA2003. The default is False. + """ + super().__init__() + self.uts_46 = uts_46 + self.transitional = transitional + self.allow_pure_ascii = allow_pure_ascii + self.strict_decode = strict_decode + + def encode(self, label): + if label == '': + return b'' + if self.allow_pure_ascii and is_all_ascii(label): + encoded = label.encode('ascii') + if len(encoded) > 63: + raise LabelTooLong + return encoded + if not have_idna_2008: + raise NoIDNA2008 + try: + if self.uts_46: + label = idna.uts46_remap(label, False, self.transitional) + return idna.alabel(label) + except idna.IDNAError as e: + if e.args[0] == 'Label too long': + raise LabelTooLong + else: + raise IDNAException(idna_exception=e) + + def decode(self, label): + if not self.strict_decode: + return super().decode(label) + if label == b'': + return '' + if not have_idna_2008: + raise NoIDNA2008 + try: + ulabel = idna.ulabel(label) + if self.uts_46: + ulabel = idna.uts46_remap(ulabel, False, self.transitional) + return _escapify(ulabel) + except (idna.IDNAError, UnicodeError) as e: + raise IDNAException(idna_exception=e) + +_escaped = b'"().;\\@$' +_escaped_text = '"().;\\@$' + +IDNA_2003_Practical = IDNA2003Codec(False) +IDNA_2003_Strict = IDNA2003Codec(True) +IDNA_2003 = IDNA_2003_Practical +IDNA_2008_Practical = IDNA2008Codec(True, False, True, False) +IDNA_2008_UTS_46 = IDNA2008Codec(True, False, False, False) +IDNA_2008_Strict = IDNA2008Codec(False, False, False, True) +IDNA_2008_Transitional = IDNA2008Codec(True, True, False, False) +IDNA_2008 = IDNA_2008_Practical + +def _escapify(label): + """Escape the characters in label which need it. + @returns: the escaped string + @rtype: string""" + if isinstance(label, bytes): + # Ordinary DNS label mode. Escape special characters and values + # < 0x20 or > 0x7f. + text = '' + for c in label: + if c in _escaped: + text += '\\' + chr(c) + elif c > 0x20 and c < 0x7F: + text += chr(c) + else: + text += '\\%03d' % c + return text + + # Unicode label mode. Escape only special characters and values < 0x20 + text = '' + for c in label: + if c in _escaped_text: + text += '\\' + c + elif c <= '\x20': + text += '\\%03d' % ord(c) + else: + text += c + return text + +def _validate_labels(labels): + """Check for empty labels in the middle of a label sequence, + labels that are too long, and for too many labels. + + Raises ``dns.name.NameTooLong`` if the name as a whole is too long. + + Raises ``dns.name.EmptyLabel`` if a label is empty (i.e. the root + label) and appears in a position other than the end of the label + sequence + + """ + + l = len(labels) + total = 0 + i = -1 + j = 0 + for label in labels: + ll = len(label) + total += ll + 1 + if ll > 63: + raise LabelTooLong + if i < 0 and label == b'': + i = j + j += 1 + if total > 255: + raise NameTooLong + if i >= 0 and i != l - 1: + raise EmptyLabel + + +def _maybe_convert_to_binary(label): + """If label is ``str``, convert it to ``bytes``. If it is already + ``bytes`` just return it. + + """ + + if isinstance(label, bytes): + return label + if isinstance(label, str): + return label.encode() + raise ValueError # pragma: no cover + + +@dns.immutable.immutable +class Name: + + """A DNS name. + + The dns.name.Name class represents a DNS name as a tuple of + labels. Each label is a ``bytes`` in DNS wire format. Instances + of the class are immutable. + """ + + __slots__ = ['labels'] + + def __init__(self, labels): + """*labels* is any iterable whose values are ``str`` or ``bytes``. + """ + + labels = [_maybe_convert_to_binary(x) for x in labels] + self.labels = tuple(labels) + _validate_labels(self.labels) + + def __copy__(self): + return Name(self.labels) + + def __deepcopy__(self, memo): + return Name(copy.deepcopy(self.labels, memo)) + + def __getstate__(self): + # Names can be pickled + return {'labels': self.labels} + + def __setstate__(self, state): + super().__setattr__('labels', state['labels']) + _validate_labels(self.labels) + + def is_absolute(self): + """Is the most significant label of this name the root label? + + Returns a ``bool``. + """ + + return len(self.labels) > 0 and self.labels[-1] == b'' + + def is_wild(self): + """Is this name wild? (I.e. Is the least significant label '*'?) + + Returns a ``bool``. + """ + + return len(self.labels) > 0 and self.labels[0] == b'*' + + def __hash__(self): + """Return a case-insensitive hash of the name. + + Returns an ``int``. + """ + + h = 0 + for label in self.labels: + for c in label.lower(): + h += (h << 3) + c + return h + + def fullcompare(self, other): + """Compare two names, returning a 3-tuple + ``(relation, order, nlabels)``. + + *relation* describes the relation ship between the names, + and is one of: ``dns.name.NAMERELN_NONE``, + ``dns.name.NAMERELN_SUPERDOMAIN``, ``dns.name.NAMERELN_SUBDOMAIN``, + ``dns.name.NAMERELN_EQUAL``, or ``dns.name.NAMERELN_COMMONANCESTOR``. + + *order* is < 0 if *self* < *other*, > 0 if *self* > *other*, and == + 0 if *self* == *other*. A relative name is always less than an + absolute name. If both names have the same relativity, then + the DNSSEC order relation is used to order them. + + *nlabels* is the number of significant labels that the two names + have in common. + + Here are some examples. Names ending in "." are absolute names, + those not ending in "." are relative names. + + ============= ============= =========== ===== ======= + self other relation order nlabels + ============= ============= =========== ===== ======= + www.example. www.example. equal 0 3 + www.example. example. subdomain > 0 2 + example. www.example. superdomain < 0 2 + example1.com. example2.com. common anc. < 0 2 + example1 example2. none < 0 0 + example1. example2 none > 0 0 + ============= ============= =========== ===== ======= + """ + + sabs = self.is_absolute() + oabs = other.is_absolute() + if sabs != oabs: + if sabs: + return (NAMERELN_NONE, 1, 0) + else: + return (NAMERELN_NONE, -1, 0) + l1 = len(self.labels) + l2 = len(other.labels) + ldiff = l1 - l2 + if ldiff < 0: + l = l1 + else: + l = l2 + + order = 0 + nlabels = 0 + namereln = NAMERELN_NONE + while l > 0: + l -= 1 + l1 -= 1 + l2 -= 1 + label1 = self.labels[l1].lower() + label2 = other.labels[l2].lower() + if label1 < label2: + order = -1 + if nlabels > 0: + namereln = NAMERELN_COMMONANCESTOR + return (namereln, order, nlabels) + elif label1 > label2: + order = 1 + if nlabels > 0: + namereln = NAMERELN_COMMONANCESTOR + return (namereln, order, nlabels) + nlabels += 1 + order = ldiff + if ldiff < 0: + namereln = NAMERELN_SUPERDOMAIN + elif ldiff > 0: + namereln = NAMERELN_SUBDOMAIN + else: + namereln = NAMERELN_EQUAL + return (namereln, order, nlabels) + + def is_subdomain(self, other): + """Is self a subdomain of other? + + Note that the notion of subdomain includes equality, e.g. + "dnpython.org" is a subdomain of itself. + + Returns a ``bool``. + """ + + (nr, _, _) = self.fullcompare(other) + if nr == NAMERELN_SUBDOMAIN or nr == NAMERELN_EQUAL: + return True + return False + + def is_superdomain(self, other): + """Is self a superdomain of other? + + Note that the notion of superdomain includes equality, e.g. + "dnpython.org" is a superdomain of itself. + + Returns a ``bool``. + """ + + (nr, _, _) = self.fullcompare(other) + if nr == NAMERELN_SUPERDOMAIN or nr == NAMERELN_EQUAL: + return True + return False + + def canonicalize(self): + """Return a name which is equal to the current name, but is in + DNSSEC canonical form. + """ + + return Name([x.lower() for x in self.labels]) + + def __eq__(self, other): + if isinstance(other, Name): + return self.fullcompare(other)[1] == 0 + else: + return False + + def __ne__(self, other): + if isinstance(other, Name): + return self.fullcompare(other)[1] != 0 + else: + return True + + def __lt__(self, other): + if isinstance(other, Name): + return self.fullcompare(other)[1] < 0 + else: + return NotImplemented + + def __le__(self, other): + if isinstance(other, Name): + return self.fullcompare(other)[1] <= 0 + else: + return NotImplemented + + def __ge__(self, other): + if isinstance(other, Name): + return self.fullcompare(other)[1] >= 0 + else: + return NotImplemented + + def __gt__(self, other): + if isinstance(other, Name): + return self.fullcompare(other)[1] > 0 + else: + return NotImplemented + + def __repr__(self): + return '' + + def __str__(self): + return self.to_text(False) + + def to_text(self, omit_final_dot=False): + """Convert name to DNS text format. + + *omit_final_dot* is a ``bool``. If True, don't emit the final + dot (denoting the root label) for absolute names. The default + is False. + + Returns a ``str``. + """ + + if len(self.labels) == 0: + return '@' + if len(self.labels) == 1 and self.labels[0] == b'': + return '.' + if omit_final_dot and self.is_absolute(): + l = self.labels[:-1] + else: + l = self.labels + s = '.'.join(map(_escapify, l)) + return s + + def to_unicode(self, omit_final_dot=False, idna_codec=None): + """Convert name to Unicode text format. + + IDN ACE labels are converted to Unicode. + + *omit_final_dot* is a ``bool``. If True, don't emit the final + dot (denoting the root label) for absolute names. The default + is False. + *idna_codec* specifies the IDNA encoder/decoder. If None, the + dns.name.IDNA_2003_Practical encoder/decoder is used. + The IDNA_2003_Practical decoder does + not impose any policy, it just decodes punycode, so if you + don't want checking for compliance, you can use this decoder + for IDNA2008 as well. + + Returns a ``str``. + """ + + if len(self.labels) == 0: + return '@' + if len(self.labels) == 1 and self.labels[0] == b'': + return '.' + if omit_final_dot and self.is_absolute(): + l = self.labels[:-1] + else: + l = self.labels + if idna_codec is None: + idna_codec = IDNA_2003_Practical + return '.'.join([idna_codec.decode(x) for x in l]) + + def to_digestable(self, origin=None): + """Convert name to a format suitable for digesting in hashes. + + The name is canonicalized and converted to uncompressed wire + format. All names in wire format are absolute. If the name + is a relative name, then an origin must be supplied. + + *origin* is a ``dns.name.Name`` or ``None``. If the name is + relative and origin is not ``None``, then origin will be appended + to the name. + + Raises ``dns.name.NeedAbsoluteNameOrOrigin`` if the name is + relative and no origin was provided. + + Returns a ``bytes``. + """ + + return self.to_wire(origin=origin, canonicalize=True) + + def to_wire(self, file=None, compress=None, origin=None, + canonicalize=False): + """Convert name to wire format, possibly compressing it. + + *file* is the file where the name is emitted (typically an + io.BytesIO file). If ``None`` (the default), a ``bytes`` + containing the wire name will be returned. + + *compress*, a ``dict``, is the compression table to use. If + ``None`` (the default), names will not be compressed. Note that + the compression code assumes that compression offset 0 is the + start of *file*, and thus compression will not be correct + if this is not the case. + + *origin* is a ``dns.name.Name`` or ``None``. If the name is + relative and origin is not ``None``, then *origin* will be appended + to it. + + *canonicalize*, a ``bool``, indicates whether the name should + be canonicalized; that is, converted to a format suitable for + digesting in hashes. + + Raises ``dns.name.NeedAbsoluteNameOrOrigin`` if the name is + relative and no origin was provided. + + Returns a ``bytes`` or ``None``. + """ + + if file is None: + out = bytearray() + for label in self.labels: + out.append(len(label)) + if canonicalize: + out += label.lower() + else: + out += label + if not self.is_absolute(): + if origin is None or not origin.is_absolute(): + raise NeedAbsoluteNameOrOrigin + for label in origin.labels: + out.append(len(label)) + if canonicalize: + out += label.lower() + else: + out += label + return bytes(out) + + if not self.is_absolute(): + if origin is None or not origin.is_absolute(): + raise NeedAbsoluteNameOrOrigin + labels = list(self.labels) + labels.extend(list(origin.labels)) + else: + labels = self.labels + i = 0 + for label in labels: + n = Name(labels[i:]) + i += 1 + if compress is not None: + pos = compress.get(n) + else: + pos = None + if pos is not None: + value = 0xc000 + pos + s = struct.pack('!H', value) + file.write(s) + break + else: + if compress is not None and len(n) > 1: + pos = file.tell() + if pos <= 0x3fff: + compress[n] = pos + l = len(label) + file.write(struct.pack('!B', l)) + if l > 0: + if canonicalize: + file.write(label.lower()) + else: + file.write(label) + + def __len__(self): + """The length of the name (in labels). + + Returns an ``int``. + """ + + return len(self.labels) + + def __getitem__(self, index): + return self.labels[index] + + def __add__(self, other): + return self.concatenate(other) + + def __sub__(self, other): + return self.relativize(other) + + def split(self, depth): + """Split a name into a prefix and suffix names at the specified depth. + + *depth* is an ``int`` specifying the number of labels in the suffix + + Raises ``ValueError`` if *depth* was not >= 0 and <= the length of the + name. + + Returns the tuple ``(prefix, suffix)``. + """ + + l = len(self.labels) + if depth == 0: + return (self, dns.name.empty) + elif depth == l: + return (dns.name.empty, self) + elif depth < 0 or depth > l: + raise ValueError( + 'depth must be >= 0 and <= the length of the name') + return (Name(self[: -depth]), Name(self[-depth:])) + + def concatenate(self, other): + """Return a new name which is the concatenation of self and other. + + Raises ``dns.name.AbsoluteConcatenation`` if the name is + absolute and *other* is not the empty name. + + Returns a ``dns.name.Name``. + """ + + if self.is_absolute() and len(other) > 0: + raise AbsoluteConcatenation + labels = list(self.labels) + labels.extend(list(other.labels)) + return Name(labels) + + def relativize(self, origin): + """If the name is a subdomain of *origin*, return a new name which is + the name relative to origin. Otherwise return the name. + + For example, relativizing ``www.dnspython.org.`` to origin + ``dnspython.org.`` returns the name ``www``. Relativizing ``example.`` + to origin ``dnspython.org.`` returns ``example.``. + + Returns a ``dns.name.Name``. + """ + + if origin is not None and self.is_subdomain(origin): + return Name(self[: -len(origin)]) + else: + return self + + def derelativize(self, origin): + """If the name is a relative name, return a new name which is the + concatenation of the name and origin. Otherwise return the name. + + For example, derelativizing ``www`` to origin ``dnspython.org.`` + returns the name ``www.dnspython.org.``. Derelativizing ``example.`` + to origin ``dnspython.org.`` returns ``example.``. + + Returns a ``dns.name.Name``. + """ + + if not self.is_absolute(): + return self.concatenate(origin) + else: + return self + + def choose_relativity(self, origin=None, relativize=True): + """Return a name with the relativity desired by the caller. + + If *origin* is ``None``, then the name is returned. + Otherwise, if *relativize* is ``True`` the name is + relativized, and if *relativize* is ``False`` the name is + derelativized. + + Returns a ``dns.name.Name``. + """ + + if origin: + if relativize: + return self.relativize(origin) + else: + return self.derelativize(origin) + else: + return self + + def parent(self): + """Return the parent of the name. + + For example, the parent of ``www.dnspython.org.`` is ``dnspython.org``. + + Raises ``dns.name.NoParent`` if the name is either the root name or the + empty name, and thus has no parent. + + Returns a ``dns.name.Name``. + """ + + if self == root or self == empty: + raise NoParent + return Name(self.labels[1:]) + +#: The root name, '.' +root = Name([b'']) + +#: The empty name. +empty = Name([]) + +def from_unicode(text, origin=root, idna_codec=None): + """Convert unicode text into a Name object. + + Labels are encoded in IDN ACE form according to rules specified by + the IDNA codec. + + *text*, a ``str``, is the text to convert into a name. + + *origin*, a ``dns.name.Name``, specifies the origin to + append to non-absolute names. The default is the root name. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder + is used. + + Returns a ``dns.name.Name``. + """ + + if not isinstance(text, str): + raise ValueError("input to from_unicode() must be a unicode string") + if not (origin is None or isinstance(origin, Name)): + raise ValueError("origin must be a Name or None") + labels = [] + label = '' + escaping = False + edigits = 0 + total = 0 + if idna_codec is None: + idna_codec = IDNA_2003 + if text == '@': + text = '' + if text: + if text in ['.', '\u3002', '\uff0e', '\uff61']: + return Name([b'']) # no Unicode "u" on this constant! + for c in text: + if escaping: + if edigits == 0: + if c.isdigit(): + total = int(c) + edigits += 1 + else: + label += c + escaping = False + else: + if not c.isdigit(): + raise BadEscape + total *= 10 + total += int(c) + edigits += 1 + if edigits == 3: + escaping = False + label += chr(total) + elif c in ['.', '\u3002', '\uff0e', '\uff61']: + if len(label) == 0: + raise EmptyLabel + labels.append(idna_codec.encode(label)) + label = '' + elif c == '\\': + escaping = True + edigits = 0 + total = 0 + else: + label += c + if escaping: + raise BadEscape + if len(label) > 0: + labels.append(idna_codec.encode(label)) + else: + labels.append(b'') + + if (len(labels) == 0 or labels[-1] != b'') and origin is not None: + labels.extend(list(origin.labels)) + return Name(labels) + +def is_all_ascii(text): + for c in text: + if ord(c) > 0x7f: + return False + return True + +def from_text(text, origin=root, idna_codec=None): + """Convert text into a Name object. + + *text*, a ``str``, is the text to convert into a name. + + *origin*, a ``dns.name.Name``, specifies the origin to + append to non-absolute names. The default is the root name. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder + is used. + + Returns a ``dns.name.Name``. + """ + + if isinstance(text, str): + if not is_all_ascii(text): + # Some codepoint in the input text is > 127, so IDNA applies. + return from_unicode(text, origin, idna_codec) + # The input is all ASCII, so treat this like an ordinary non-IDNA + # domain name. Note that "all ASCII" is about the input text, + # not the codepoints in the domain name. E.g. if text has value + # + # r'\150\151\152\153\154\155\156\157\158\159' + # + # then it's still "all ASCII" even though the domain name has + # codepoints > 127. + text = text.encode('ascii') + if not isinstance(text, bytes): + raise ValueError("input to from_text() must be a string") + if not (origin is None or isinstance(origin, Name)): + raise ValueError("origin must be a Name or None") + labels = [] + label = b'' + escaping = False + edigits = 0 + total = 0 + if text == b'@': + text = b'' + if text: + if text == b'.': + return Name([b'']) + for c in text: + byte_ = struct.pack('!B', c) + if escaping: + if edigits == 0: + if byte_.isdigit(): + total = int(byte_) + edigits += 1 + else: + label += byte_ + escaping = False + else: + if not byte_.isdigit(): + raise BadEscape + total *= 10 + total += int(byte_) + edigits += 1 + if edigits == 3: + escaping = False + label += struct.pack('!B', total) + elif byte_ == b'.': + if len(label) == 0: + raise EmptyLabel + labels.append(label) + label = b'' + elif byte_ == b'\\': + escaping = True + edigits = 0 + total = 0 + else: + label += byte_ + if escaping: + raise BadEscape + if len(label) > 0: + labels.append(label) + else: + labels.append(b'') + if (len(labels) == 0 or labels[-1] != b'') and origin is not None: + labels.extend(list(origin.labels)) + return Name(labels) + + +def from_wire_parser(parser): + """Convert possibly compressed wire format into a Name. + + *parser* is a dns.wire.Parser. + + Raises ``dns.name.BadPointer`` if a compression pointer did not + point backwards in the message. + + Raises ``dns.name.BadLabelType`` if an invalid label type was encountered. + + Returns a ``dns.name.Name`` + """ + + labels = [] + biggest_pointer = parser.current + with parser.restore_furthest(): + count = parser.get_uint8() + while count != 0: + if count < 64: + labels.append(parser.get_bytes(count)) + elif count >= 192: + current = (count & 0x3f) * 256 + parser.get_uint8() + if current >= biggest_pointer: + raise BadPointer + biggest_pointer = current + parser.seek(current) + else: + raise BadLabelType + count = parser.get_uint8() + labels.append(b'') + return Name(labels) + + +def from_wire(message, current): + """Convert possibly compressed wire format into a Name. + + *message* is a ``bytes`` containing an entire DNS message in DNS + wire form. + + *current*, an ``int``, is the offset of the beginning of the name + from the start of the message + + Raises ``dns.name.BadPointer`` if a compression pointer did not + point backwards in the message. + + Raises ``dns.name.BadLabelType`` if an invalid label type was encountered. + + Returns a ``(dns.name.Name, int)`` tuple consisting of the name + that was read and the number of bytes of the wire format message + which were consumed reading it. + """ + + if not isinstance(message, bytes): + raise ValueError("input to from_wire() must be a byte string") + parser = dns.wire.Parser(message, current) + name = from_wire_parser(parser) + return (name, parser.current - current) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/namedict.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/namedict.py new file mode 100644 index 0000000..4c8f9ab --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/namedict.py @@ -0,0 +1,108 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# Copyright (C) 2016 Coresec Systems AB +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND CORESEC SYSTEMS AB DISCLAIMS ALL +# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CORESEC +# SYSTEMS AB BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS name dictionary""" + +from collections.abc import MutableMapping + +import dns.name + + +class NameDict(MutableMapping): + """A dictionary whose keys are dns.name.Name objects. + + In addition to being like a regular Python dictionary, this + dictionary can also get the deepest match for a given key. + """ + + __slots__ = ["max_depth", "max_depth_items", "__store"] + + def __init__(self, *args, **kwargs): + super().__init__() + self.__store = dict() + #: the maximum depth of the keys that have ever been added + self.max_depth = 0 + #: the number of items of maximum depth + self.max_depth_items = 0 + self.update(dict(*args, **kwargs)) + + def __update_max_depth(self, key): + if len(key) == self.max_depth: + self.max_depth_items = self.max_depth_items + 1 + elif len(key) > self.max_depth: + self.max_depth = len(key) + self.max_depth_items = 1 + + def __getitem__(self, key): + return self.__store[key] + + def __setitem__(self, key, value): + if not isinstance(key, dns.name.Name): + raise ValueError('NameDict key must be a name') + self.__store[key] = value + self.__update_max_depth(key) + + def __delitem__(self, key): + self.__store.pop(key) + if len(key) == self.max_depth: + self.max_depth_items = self.max_depth_items - 1 + if self.max_depth_items == 0: + self.max_depth = 0 + for k in self.__store: + self.__update_max_depth(k) + + def __iter__(self): + return iter(self.__store) + + def __len__(self): + return len(self.__store) + + def has_key(self, key): + return key in self.__store + + def get_deepest_match(self, name): + """Find the deepest match to *fname* in the dictionary. + + The deepest match is the longest name in the dictionary which is + a superdomain of *name*. Note that *superdomain* includes matching + *name* itself. + + *name*, a ``dns.name.Name``, the name to find. + + Returns a ``(key, value)`` where *key* is the deepest + ``dns.name.Name``, and *value* is the value associated with *key*. + """ + + depth = len(name) + if depth > self.max_depth: + depth = self.max_depth + for i in range(-depth, 0): + n = dns.name.Name(name[i:]) + if n in self: + return (n, self[n]) + v = self[dns.name.empty] + return (dns.name.empty, v) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/node.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/node.py new file mode 100644 index 0000000..b1baf27 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/node.py @@ -0,0 +1,189 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS nodes. A node is a set of rdatasets.""" + +import io + +import dns.rdataset +import dns.rdatatype +import dns.renderer + + +class Node: + + """A Node is a set of rdatasets.""" + + __slots__ = ['rdatasets'] + + def __init__(self): + # the set of rdatasets, represented as a list. + self.rdatasets = [] + + def to_text(self, name, **kw): + """Convert a node to text format. + + Each rdataset at the node is printed. Any keyword arguments + to this method are passed on to the rdataset's to_text() method. + + *name*, a ``dns.name.Name`` or ``str``, the owner name of the + rdatasets. + + Returns a ``str``. + + """ + + s = io.StringIO() + for rds in self.rdatasets: + if len(rds) > 0: + s.write(rds.to_text(name, **kw)) + s.write('\n') + return s.getvalue()[:-1] + + def __repr__(self): + return '' + + def __eq__(self, other): + # + # This is inefficient. Good thing we don't need to do it much. + # + for rd in self.rdatasets: + if rd not in other.rdatasets: + return False + for rd in other.rdatasets: + if rd not in self.rdatasets: + return False + return True + + def __ne__(self, other): + return not self.__eq__(other) + + def __len__(self): + return len(self.rdatasets) + + def __iter__(self): + return iter(self.rdatasets) + + def find_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE, + create=False): + """Find an rdataset matching the specified properties in the + current node. + + *rdclass*, an ``int``, the class of the rdataset. + + *rdtype*, an ``int``, the type of the rdataset. + + *covers*, an ``int`` or ``None``, the covered type. + Usually this value is ``dns.rdatatype.NONE``, but if the + rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, + then the covers value will be the rdata type the SIG/RRSIG + covers. The library treats the SIG and RRSIG types as if they + were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). + This makes RRSIGs much easier to work with than if RRSIGs + covering different rdata types were aggregated into a single + RRSIG rdataset. + + *create*, a ``bool``. If True, create the rdataset if it is not found. + + Raises ``KeyError`` if an rdataset of the desired type and class does + not exist and *create* is not ``True``. + + Returns a ``dns.rdataset.Rdataset``. + """ + + for rds in self.rdatasets: + if rds.match(rdclass, rdtype, covers): + return rds + if not create: + raise KeyError + rds = dns.rdataset.Rdataset(rdclass, rdtype) + self.rdatasets.append(rds) + return rds + + def get_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE, + create=False): + """Get an rdataset matching the specified properties in the + current node. + + None is returned if an rdataset of the specified type and + class does not exist and *create* is not ``True``. + + *rdclass*, an ``int``, the class of the rdataset. + + *rdtype*, an ``int``, the type of the rdataset. + + *covers*, an ``int``, the covered type. Usually this value is + dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or + dns.rdatatype.RRSIG, then the covers value will be the rdata + type the SIG/RRSIG covers. The library treats the SIG and RRSIG + types as if they were a family of + types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much + easier to work with than if RRSIGs covering different rdata + types were aggregated into a single RRSIG rdataset. + + *create*, a ``bool``. If True, create the rdataset if it is not found. + + Returns a ``dns.rdataset.Rdataset`` or ``None``. + """ + + try: + rds = self.find_rdataset(rdclass, rdtype, covers, create) + except KeyError: + rds = None + return rds + + def delete_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE): + """Delete the rdataset matching the specified properties in the + current node. + + If a matching rdataset does not exist, it is not an error. + + *rdclass*, an ``int``, the class of the rdataset. + + *rdtype*, an ``int``, the type of the rdataset. + + *covers*, an ``int``, the covered type. + """ + + rds = self.get_rdataset(rdclass, rdtype, covers) + if rds is not None: + self.rdatasets.remove(rds) + + def replace_rdataset(self, replacement): + """Replace an rdataset. + + It is not an error if there is no rdataset matching *replacement*. + + Ownership of the *replacement* object is transferred to the node; + in other words, this method does not store a copy of *replacement* + at the node, it stores *replacement* itself. + + *replacement*, a ``dns.rdataset.Rdataset``. + + Raises ``ValueError`` if *replacement* is not a + ``dns.rdataset.Rdataset``. + """ + + if not isinstance(replacement, dns.rdataset.Rdataset): + raise ValueError('replacement is not an rdataset') + if isinstance(replacement, dns.rrset.RRset): + # RRsets are not good replacements as the match() method + # is not compatible. + replacement = replacement.to_rdataset() + self.delete_rdataset(replacement.rdclass, replacement.rdtype, + replacement.covers) + self.rdatasets.append(replacement) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/opcode.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/opcode.py new file mode 100644 index 0000000..5cf6143 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/opcode.py @@ -0,0 +1,115 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Opcodes.""" + +import dns.enum +import dns.exception + +class Opcode(dns.enum.IntEnum): + #: Query + QUERY = 0 + #: Inverse Query (historical) + IQUERY = 1 + #: Server Status (unspecified and unimplemented anywhere) + STATUS = 2 + #: Notify + NOTIFY = 4 + #: Dynamic Update + UPDATE = 5 + + @classmethod + def _maximum(cls): + return 15 + + @classmethod + def _unknown_exception_class(cls): + return UnknownOpcode + + +class UnknownOpcode(dns.exception.DNSException): + """An DNS opcode is unknown.""" + + +def from_text(text): + """Convert text into an opcode. + + *text*, a ``str``, the textual opcode + + Raises ``dns.opcode.UnknownOpcode`` if the opcode is unknown. + + Returns an ``int``. + """ + + return Opcode.from_text(text) + + +def from_flags(flags): + """Extract an opcode from DNS message flags. + + *flags*, an ``int``, the DNS flags. + + Returns an ``int``. + """ + + return (flags & 0x7800) >> 11 + + +def to_flags(value): + """Convert an opcode to a value suitable for ORing into DNS message + flags. + + *value*, an ``int``, the DNS opcode value. + + Returns an ``int``. + """ + + return (value << 11) & 0x7800 + + +def to_text(value): + """Convert an opcode to text. + + *value*, an ``int`` the opcode value, + + Raises ``dns.opcode.UnknownOpcode`` if the opcode is unknown. + + Returns a ``str``. + """ + + return Opcode.to_text(value) + + +def is_update(flags): + """Is the opcode in flags UPDATE? + + *flags*, an ``int``, the DNS message flags. + + Returns a ``bool``. + """ + + return from_flags(flags) == Opcode.UPDATE + +### BEGIN generated Opcode constants + +QUERY = Opcode.QUERY +IQUERY = Opcode.IQUERY +STATUS = Opcode.STATUS +NOTIFY = Opcode.NOTIFY +UPDATE = Opcode.UPDATE + +### END generated Opcode constants diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/py.typed b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/query.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/query.py new file mode 100644 index 0000000..bd62a7a --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/query.py @@ -0,0 +1,1094 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Talk to a DNS server.""" + +import contextlib +import enum +import errno +import os +import selectors +import socket +import struct +import time +import base64 +import urllib.parse + +import dns.exception +import dns.inet +import dns.name +import dns.message +import dns.rcode +import dns.rdataclass +import dns.rdatatype +import dns.serial +import dns.xfr + +try: + import requests + from requests_toolbelt.adapters.source import SourceAddressAdapter + from requests_toolbelt.adapters.host_header_ssl import HostHeaderSSLAdapter + have_doh = True +except ImportError: # pragma: no cover + have_doh = False + +try: + import ssl +except ImportError: # pragma: no cover + class ssl: # type: ignore + + class WantReadException(Exception): + pass + + class WantWriteException(Exception): + pass + + class SSLSocket: + pass + + def create_default_context(self, *args, **kwargs): + raise Exception('no ssl support') + +# Function used to create a socket. Can be overridden if needed in special +# situations. +socket_factory = socket.socket + +class UnexpectedSource(dns.exception.DNSException): + """A DNS query response came from an unexpected address or port.""" + + +class BadResponse(dns.exception.FormError): + """A DNS query response does not respond to the question asked.""" + + +class NoDOH(dns.exception.DNSException): + """DNS over HTTPS (DOH) was requested but the requests module is not + available.""" + + +# for backwards compatibility +TransferError = dns.xfr.TransferError + + +def _compute_times(timeout): + now = time.time() + if timeout is None: + return (now, None) + else: + return (now, now + timeout) + + +def _wait_for(fd, readable, writable, _, expiration): + # Use the selected selector class to wait for any of the specified + # events. An "expiration" absolute time is converted into a relative + # timeout. + # + # The unused parameter is 'error', which is always set when + # selecting for read or write, and we have no error-only selects. + + if readable and isinstance(fd, ssl.SSLSocket) and fd.pending() > 0: + return True + sel = _selector_class() + events = 0 + if readable: + events |= selectors.EVENT_READ + if writable: + events |= selectors.EVENT_WRITE + if events: + sel.register(fd, events) + if expiration is None: + timeout = None + else: + timeout = expiration - time.time() + if timeout <= 0.0: + raise dns.exception.Timeout + if not sel.select(timeout): + raise dns.exception.Timeout + + +def _set_selector_class(selector_class): + # Internal API. Do not use. + + global _selector_class + + _selector_class = selector_class + +if hasattr(selectors, 'PollSelector'): + # Prefer poll() on platforms that support it because it has no + # limits on the maximum value of a file descriptor (plus it will + # be more efficient for high values). + _selector_class = selectors.PollSelector +else: + _selector_class = selectors.SelectSelector # pragma: no cover + + +def _wait_for_readable(s, expiration): + _wait_for(s, True, False, True, expiration) + + +def _wait_for_writable(s, expiration): + _wait_for(s, False, True, True, expiration) + + +def _addresses_equal(af, a1, a2): + # Convert the first value of the tuple, which is a textual format + # address into binary form, so that we are not confused by different + # textual representations of the same address + try: + n1 = dns.inet.inet_pton(af, a1[0]) + n2 = dns.inet.inet_pton(af, a2[0]) + except dns.exception.SyntaxError: + return False + return n1 == n2 and a1[1:] == a2[1:] + + +def _matches_destination(af, from_address, destination, ignore_unexpected): + # Check that from_address is appropriate for a response to a query + # sent to destination. + if not destination: + return True + if _addresses_equal(af, from_address, destination) or \ + (dns.inet.is_multicast(destination[0]) and + from_address[1:] == destination[1:]): + return True + elif ignore_unexpected: + return False + raise UnexpectedSource(f'got a response from {from_address} instead of ' + f'{destination}') + + +def _destination_and_source(where, port, source, source_port, + where_must_be_address=True): + # Apply defaults and compute destination and source tuples + # suitable for use in connect(), sendto(), or bind(). + af = None + destination = None + try: + af = dns.inet.af_for_address(where) + destination = where + except Exception: + if where_must_be_address: + raise + # URLs are ok so eat the exception + if source: + saf = dns.inet.af_for_address(source) + if af: + # We know the destination af, so source had better agree! + if saf != af: + raise ValueError('different address families for source ' + + 'and destination') + else: + # We didn't know the destination af, but we know the source, + # so that's our af. + af = saf + if source_port and not source: + # Caller has specified a source_port but not an address, so we + # need to return a source, and we need to use the appropriate + # wildcard address as the address. + if af == socket.AF_INET: + source = '0.0.0.0' + elif af == socket.AF_INET6: + source = '::' + else: + raise ValueError('source_port specified but address family is ' + 'unknown') + # Convert high-level (address, port) tuples into low-level address + # tuples. + if destination: + destination = dns.inet.low_level_address_tuple((destination, port), af) + if source: + source = dns.inet.low_level_address_tuple((source, source_port), af) + return (af, destination, source) + +def _make_socket(af, type, source, ssl_context=None, server_hostname=None): + s = socket_factory(af, type) + try: + s.setblocking(False) + if source is not None: + s.bind(source) + if ssl_context: + return ssl_context.wrap_socket(s, do_handshake_on_connect=False, + server_hostname=server_hostname) + else: + return s + except Exception: + s.close() + raise + +def https(q, where, timeout=None, port=443, source=None, source_port=0, + one_rr_per_rrset=False, ignore_trailing=False, + session=None, path='/dns-query', post=True, + bootstrap_address=None, verify=True): + """Return the response obtained after sending a query via DNS-over-HTTPS. + + *q*, a ``dns.message.Message``, the query to send. + + *where*, a ``str``, the nameserver IP address or the full URL. If an IP + address is given, the URL will be constructed using the following schema: + https://:/. + + *timeout*, a ``float`` or ``None``, the number of seconds to + wait before the query times out. If ``None``, the default, wait forever. + + *port*, a ``int``, the port to send the query to. The default is 443. + + *source*, a ``str`` containing an IPv4 or IPv6 address, specifying + the source address. The default is the wildcard address. + + *source_port*, an ``int``, the port from which to send the message. + The default is 0. + + *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own + RRset. + + *ignore_trailing*, a ``bool``. If ``True``, ignore trailing + junk at end of the received message. + + *session*, a ``requests.session.Session``. If provided, the session to use + to send the queries. + + *path*, a ``str``. If *where* is an IP address, then *path* will be used to + construct the URL to send the DNS query to. + + *post*, a ``bool``. If ``True``, the default, POST method will be used. + + *bootstrap_address*, a ``str``, the IP address to use to bypass the + system's DNS resolver. + + *verify*, a ``str``, containing a path to a certificate file or directory. + + Returns a ``dns.message.Message``. + """ + + if not have_doh: + raise NoDOH # pragma: no cover + + wire = q.to_wire() + (af, _, source) = _destination_and_source(where, port, source, source_port, + False) + transport_adapter = None + headers = { + "accept": "application/dns-message" + } + if af is not None: + if af == socket.AF_INET: + url = 'https://{}:{}{}'.format(where, port, path) + elif af == socket.AF_INET6: + url = 'https://[{}]:{}{}'.format(where, port, path) + elif bootstrap_address is not None: + split_url = urllib.parse.urlsplit(where) + headers['Host'] = split_url.hostname + url = where.replace(split_url.hostname, bootstrap_address) + transport_adapter = HostHeaderSSLAdapter() + else: + url = where + if source is not None: + # set source port and source address + transport_adapter = SourceAddressAdapter(source) + + with contextlib.ExitStack() as stack: + if not session: + session = stack.enter_context(requests.sessions.Session()) + + if transport_adapter: + session.mount(url, transport_adapter) + + # see https://tools.ietf.org/html/rfc8484#section-4.1.1 for DoH + # GET and POST examples + if post: + headers.update({ + "content-type": "application/dns-message", + "content-length": str(len(wire)) + }) + response = session.post(url, headers=headers, data=wire, + timeout=timeout, verify=verify) + else: + wire = base64.urlsafe_b64encode(wire).rstrip(b"=") + response = session.get(url, headers=headers, + timeout=timeout, verify=verify, + params={"dns": wire}) + + # see https://tools.ietf.org/html/rfc8484#section-4.2.1 for info about DoH + # status codes + if response.status_code < 200 or response.status_code > 299: + raise ValueError('{} responded with status code {}' + '\nResponse body: {}'.format(where, + response.status_code, + response.content)) + r = dns.message.from_wire(response.content, + keyring=q.keyring, + request_mac=q.request_mac, + one_rr_per_rrset=one_rr_per_rrset, + ignore_trailing=ignore_trailing) + r.time = response.elapsed + if not q.is_response(r): + raise BadResponse + return r + +def _udp_recv(sock, max_size, expiration): + """Reads a datagram from the socket. + A Timeout exception will be raised if the operation is not completed + by the expiration time. + """ + while True: + try: + return sock.recvfrom(max_size) + except BlockingIOError: + _wait_for_readable(sock, expiration) + + +def _udp_send(sock, data, destination, expiration): + """Sends the specified datagram to destination over the socket. + A Timeout exception will be raised if the operation is not completed + by the expiration time. + """ + while True: + try: + if destination: + return sock.sendto(data, destination) + else: + return sock.send(data) + except BlockingIOError: # pragma: no cover + _wait_for_writable(sock, expiration) + + +def send_udp(sock, what, destination, expiration=None): + """Send a DNS message to the specified UDP socket. + + *sock*, a ``socket``. + + *what*, a ``bytes`` or ``dns.message.Message``, the message to send. + + *destination*, a destination tuple appropriate for the address family + of the socket, specifying where to send the query. + + *expiration*, a ``float`` or ``None``, the absolute time at which + a timeout exception should be raised. If ``None``, no timeout will + occur. + + Returns an ``(int, float)`` tuple of bytes sent and the sent time. + """ + + if isinstance(what, dns.message.Message): + what = what.to_wire() + sent_time = time.time() + n = _udp_send(sock, what, destination, expiration) + return (n, sent_time) + + +def receive_udp(sock, destination=None, expiration=None, + ignore_unexpected=False, one_rr_per_rrset=False, + keyring=None, request_mac=b'', ignore_trailing=False, + raise_on_truncation=False): + """Read a DNS message from a UDP socket. + + *sock*, a ``socket``. + + *destination*, a destination tuple appropriate for the address family + of the socket, specifying where the message is expected to arrive from. + When receiving a response, this would be where the associated query was + sent. + + *expiration*, a ``float`` or ``None``, the absolute time at which + a timeout exception should be raised. If ``None``, no timeout will + occur. + + *ignore_unexpected*, a ``bool``. If ``True``, ignore responses from + unexpected sources. + + *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own + RRset. + + *keyring*, a ``dict``, the keyring to use for TSIG. + + *request_mac*, a ``bytes``, the MAC of the request (for TSIG). + + *ignore_trailing*, a ``bool``. If ``True``, ignore trailing + junk at end of the received message. + + *raise_on_truncation*, a ``bool``. If ``True``, raise an exception if + the TC bit is set. + + Raises if the message is malformed, if network errors occur, of if + there is a timeout. + + If *destination* is not ``None``, returns a ``(dns.message.Message, float)`` + tuple of the received message and the received time. + + If *destination* is ``None``, returns a + ``(dns.message.Message, float, tuple)`` + tuple of the received message, the received time, and the address where + the message arrived from. + """ + + wire = b'' + while True: + (wire, from_address) = _udp_recv(sock, 65535, expiration) + if _matches_destination(sock.family, from_address, destination, + ignore_unexpected): + break + received_time = time.time() + r = dns.message.from_wire(wire, keyring=keyring, request_mac=request_mac, + one_rr_per_rrset=one_rr_per_rrset, + ignore_trailing=ignore_trailing, + raise_on_truncation=raise_on_truncation) + if destination: + return (r, received_time) + else: + return (r, received_time, from_address) + +def udp(q, where, timeout=None, port=53, source=None, source_port=0, + ignore_unexpected=False, one_rr_per_rrset=False, ignore_trailing=False, + raise_on_truncation=False, sock=None): + """Return the response obtained after sending a query via UDP. + + *q*, a ``dns.message.Message``, the query to send + + *where*, a ``str`` containing an IPv4 or IPv6 address, where + to send the message. + + *timeout*, a ``float`` or ``None``, the number of seconds to wait before the + query times out. If ``None``, the default, wait forever. + + *port*, an ``int``, the port send the message to. The default is 53. + + *source*, a ``str`` containing an IPv4 or IPv6 address, specifying + the source address. The default is the wildcard address. + + *source_port*, an ``int``, the port from which to send the message. + The default is 0. + + *ignore_unexpected*, a ``bool``. If ``True``, ignore responses from + unexpected sources. + + *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own + RRset. + + *ignore_trailing*, a ``bool``. If ``True``, ignore trailing + junk at end of the received message. + + *raise_on_truncation*, a ``bool``. If ``True``, raise an exception if + the TC bit is set. + + *sock*, a ``socket.socket``, or ``None``, the socket to use for the + query. If ``None``, the default, a socket is created. Note that + if a socket is provided, it must be a nonblocking datagram socket, + and the *source* and *source_port* are ignored. + + Returns a ``dns.message.Message``. + """ + + wire = q.to_wire() + (af, destination, source) = _destination_and_source(where, port, + source, source_port) + (begin_time, expiration) = _compute_times(timeout) + with contextlib.ExitStack() as stack: + if sock: + s = sock + else: + s = stack.enter_context(_make_socket(af, socket.SOCK_DGRAM, source)) + send_udp(s, wire, destination, expiration) + (r, received_time) = receive_udp(s, destination, expiration, + ignore_unexpected, one_rr_per_rrset, + q.keyring, q.mac, ignore_trailing, + raise_on_truncation) + r.time = received_time - begin_time + if not q.is_response(r): + raise BadResponse + return r + +def udp_with_fallback(q, where, timeout=None, port=53, source=None, + source_port=0, ignore_unexpected=False, + one_rr_per_rrset=False, ignore_trailing=False, + udp_sock=None, tcp_sock=None): + """Return the response to the query, trying UDP first and falling back + to TCP if UDP results in a truncated response. + + *q*, a ``dns.message.Message``, the query to send + + *where*, a ``str`` containing an IPv4 or IPv6 address, where + to send the message. + + *timeout*, a ``float`` or ``None``, the number of seconds to wait before the + query times out. If ``None``, the default, wait forever. + + *port*, an ``int``, the port send the message to. The default is 53. + + *source*, a ``str`` containing an IPv4 or IPv6 address, specifying + the source address. The default is the wildcard address. + + *source_port*, an ``int``, the port from which to send the message. + The default is 0. + + *ignore_unexpected*, a ``bool``. If ``True``, ignore responses from + unexpected sources. + + *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own + RRset. + + *ignore_trailing*, a ``bool``. If ``True``, ignore trailing + junk at end of the received message. + + *udp_sock*, a ``socket.socket``, or ``None``, the socket to use for the + UDP query. If ``None``, the default, a socket is created. Note that + if a socket is provided, it must be a nonblocking datagram socket, + and the *source* and *source_port* are ignored for the UDP query. + + *tcp_sock*, a ``socket.socket``, or ``None``, the socket to use for the + TCP query. If ``None``, the default, a socket is created. Note that + if a socket is provided, it must be a nonblocking connected stream + socket, and *where*, *source* and *source_port* are ignored for the TCP + query. + + Returns a (``dns.message.Message``, tcp) tuple where tcp is ``True`` + if and only if TCP was used. + """ + try: + response = udp(q, where, timeout, port, source, source_port, + ignore_unexpected, one_rr_per_rrset, + ignore_trailing, True, udp_sock) + return (response, False) + except dns.message.Truncated: + response = tcp(q, where, timeout, port, source, source_port, + one_rr_per_rrset, ignore_trailing, tcp_sock) + return (response, True) + +def _net_read(sock, count, expiration): + """Read the specified number of bytes from sock. Keep trying until we + either get the desired amount, or we hit EOF. + A Timeout exception will be raised if the operation is not completed + by the expiration time. + """ + s = b'' + while count > 0: + try: + n = sock.recv(count) + if n == b'': + raise EOFError + count -= len(n) + s += n + except (BlockingIOError, ssl.SSLWantReadError): + _wait_for_readable(sock, expiration) + except ssl.SSLWantWriteError: # pragma: no cover + _wait_for_writable(sock, expiration) + return s + + +def _net_write(sock, data, expiration): + """Write the specified data to the socket. + A Timeout exception will be raised if the operation is not completed + by the expiration time. + """ + current = 0 + l = len(data) + while current < l: + try: + current += sock.send(data[current:]) + except (BlockingIOError, ssl.SSLWantWriteError): + _wait_for_writable(sock, expiration) + except ssl.SSLWantReadError: # pragma: no cover + _wait_for_readable(sock, expiration) + + +def send_tcp(sock, what, expiration=None): + """Send a DNS message to the specified TCP socket. + + *sock*, a ``socket``. + + *what*, a ``bytes`` or ``dns.message.Message``, the message to send. + + *expiration*, a ``float`` or ``None``, the absolute time at which + a timeout exception should be raised. If ``None``, no timeout will + occur. + + Returns an ``(int, float)`` tuple of bytes sent and the sent time. + """ + + if isinstance(what, dns.message.Message): + what = what.to_wire() + l = len(what) + # copying the wire into tcpmsg is inefficient, but lets us + # avoid writev() or doing a short write that would get pushed + # onto the net + tcpmsg = struct.pack("!H", l) + what + sent_time = time.time() + _net_write(sock, tcpmsg, expiration) + return (len(tcpmsg), sent_time) + +def receive_tcp(sock, expiration=None, one_rr_per_rrset=False, + keyring=None, request_mac=b'', ignore_trailing=False): + """Read a DNS message from a TCP socket. + + *sock*, a ``socket``. + + *expiration*, a ``float`` or ``None``, the absolute time at which + a timeout exception should be raised. If ``None``, no timeout will + occur. + + *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own + RRset. + + *keyring*, a ``dict``, the keyring to use for TSIG. + + *request_mac*, a ``bytes``, the MAC of the request (for TSIG). + + *ignore_trailing*, a ``bool``. If ``True``, ignore trailing + junk at end of the received message. + + Raises if the message is malformed, if network errors occur, of if + there is a timeout. + + Returns a ``(dns.message.Message, float)`` tuple of the received message + and the received time. + """ + + ldata = _net_read(sock, 2, expiration) + (l,) = struct.unpack("!H", ldata) + wire = _net_read(sock, l, expiration) + received_time = time.time() + r = dns.message.from_wire(wire, keyring=keyring, request_mac=request_mac, + one_rr_per_rrset=one_rr_per_rrset, + ignore_trailing=ignore_trailing) + return (r, received_time) + +def _connect(s, address, expiration): + err = s.connect_ex(address) + if err == 0: + return + if err in (errno.EINPROGRESS, errno.EWOULDBLOCK, errno.EALREADY): + _wait_for_writable(s, expiration) + err = s.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) + if err != 0: + raise OSError(err, os.strerror(err)) + + +def tcp(q, where, timeout=None, port=53, source=None, source_port=0, + one_rr_per_rrset=False, ignore_trailing=False, sock=None): + """Return the response obtained after sending a query via TCP. + + *q*, a ``dns.message.Message``, the query to send + + *where*, a ``str`` containing an IPv4 or IPv6 address, where + to send the message. + + *timeout*, a ``float`` or ``None``, the number of seconds to wait before the + query times out. If ``None``, the default, wait forever. + + *port*, an ``int``, the port send the message to. The default is 53. + + *source*, a ``str`` containing an IPv4 or IPv6 address, specifying + the source address. The default is the wildcard address. + + *source_port*, an ``int``, the port from which to send the message. + The default is 0. + + *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own + RRset. + + *ignore_trailing*, a ``bool``. If ``True``, ignore trailing + junk at end of the received message. + + *sock*, a ``socket.socket``, or ``None``, the socket to use for the + query. If ``None``, the default, a socket is created. Note that + if a socket is provided, it must be a nonblocking connected stream + socket, and *where*, *port*, *source* and *source_port* are ignored. + + Returns a ``dns.message.Message``. + """ + + wire = q.to_wire() + (begin_time, expiration) = _compute_times(timeout) + with contextlib.ExitStack() as stack: + if sock: + s = sock + else: + (af, destination, source) = _destination_and_source(where, port, + source, + source_port) + s = stack.enter_context(_make_socket(af, socket.SOCK_STREAM, + source)) + _connect(s, destination, expiration) + send_tcp(s, wire, expiration) + (r, received_time) = receive_tcp(s, expiration, one_rr_per_rrset, + q.keyring, q.mac, ignore_trailing) + r.time = received_time - begin_time + if not q.is_response(r): + raise BadResponse + return r + + +def _tls_handshake(s, expiration): + while True: + try: + s.do_handshake() + return + except ssl.SSLWantReadError: + _wait_for_readable(s, expiration) + except ssl.SSLWantWriteError: # pragma: no cover + _wait_for_writable(s, expiration) + + +def tls(q, where, timeout=None, port=853, source=None, source_port=0, + one_rr_per_rrset=False, ignore_trailing=False, sock=None, + ssl_context=None, server_hostname=None): + """Return the response obtained after sending a query via TLS. + + *q*, a ``dns.message.Message``, the query to send + + *where*, a ``str`` containing an IPv4 or IPv6 address, where + to send the message. + + *timeout*, a ``float`` or ``None``, the number of seconds to wait before the + query times out. If ``None``, the default, wait forever. + + *port*, an ``int``, the port send the message to. The default is 853. + + *source*, a ``str`` containing an IPv4 or IPv6 address, specifying + the source address. The default is the wildcard address. + + *source_port*, an ``int``, the port from which to send the message. + The default is 0. + + *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own + RRset. + + *ignore_trailing*, a ``bool``. If ``True``, ignore trailing + junk at end of the received message. + + *sock*, an ``ssl.SSLSocket``, or ``None``, the socket to use for + the query. If ``None``, the default, a socket is created. Note + that if a socket is provided, it must be a nonblocking connected + SSL stream socket, and *where*, *port*, *source*, *source_port*, + and *ssl_context* are ignored. + + *ssl_context*, an ``ssl.SSLContext``, the context to use when establishing + a TLS connection. If ``None``, the default, creates one with the default + configuration. + + *server_hostname*, a ``str`` containing the server's hostname. The + default is ``None``, which means that no hostname is known, and if an + SSL context is created, hostname checking will be disabled. + + Returns a ``dns.message.Message``. + + """ + + if sock: + # + # If a socket was provided, there's no special TLS handling needed. + # + return tcp(q, where, timeout, port, source, source_port, + one_rr_per_rrset, ignore_trailing, sock) + + wire = q.to_wire() + (begin_time, expiration) = _compute_times(timeout) + (af, destination, source) = _destination_and_source(where, port, + source, source_port) + if ssl_context is None and not sock: + ssl_context = ssl.create_default_context() + if server_hostname is None: + ssl_context.check_hostname = False + + with _make_socket(af, socket.SOCK_STREAM, source, ssl_context=ssl_context, + server_hostname=server_hostname) as s: + _connect(s, destination, expiration) + _tls_handshake(s, expiration) + send_tcp(s, wire, expiration) + (r, received_time) = receive_tcp(s, expiration, one_rr_per_rrset, + q.keyring, q.mac, ignore_trailing) + r.time = received_time - begin_time + if not q.is_response(r): + raise BadResponse + return r + + +def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN, + timeout=None, port=53, keyring=None, keyname=None, relativize=True, + lifetime=None, source=None, source_port=0, serial=0, + use_udp=False, keyalgorithm=dns.tsig.default_algorithm): + """Return a generator for the responses to a zone transfer. + + *where*, a ``str`` containing an IPv4 or IPv6 address, where + to send the message. + + *zone*, a ``dns.name.Name`` or ``str``, the name of the zone to transfer. + + *rdtype*, an ``int`` or ``str``, the type of zone transfer. The + default is ``dns.rdatatype.AXFR``. ``dns.rdatatype.IXFR`` can be + used to do an incremental transfer instead. + + *rdclass*, an ``int`` or ``str``, the class of the zone transfer. + The default is ``dns.rdataclass.IN``. + + *timeout*, a ``float``, the number of seconds to wait for each + response message. If None, the default, wait forever. + + *port*, an ``int``, the port send the message to. The default is 53. + + *keyring*, a ``dict``, the keyring to use for TSIG. + + *keyname*, a ``dns.name.Name`` or ``str``, the name of the TSIG + key to use. + + *relativize*, a ``bool``. If ``True``, all names in the zone will be + relativized to the zone origin. It is essential that the + relativize setting matches the one specified to + ``dns.zone.from_xfr()`` if using this generator to make a zone. + + *lifetime*, a ``float``, the total number of seconds to spend + doing the transfer. If ``None``, the default, then there is no + limit on the time the transfer may take. + + *source*, a ``str`` containing an IPv4 or IPv6 address, specifying + the source address. The default is the wildcard address. + + *source_port*, an ``int``, the port from which to send the message. + The default is 0. + + *serial*, an ``int``, the SOA serial number to use as the base for + an IXFR diff sequence (only meaningful if *rdtype* is + ``dns.rdatatype.IXFR``). + + *use_udp*, a ``bool``. If ``True``, use UDP (only meaningful for IXFR). + + *keyalgorithm*, a ``dns.name.Name`` or ``str``, the TSIG algorithm to use. + + Raises on errors, and so does the generator. + + Returns a generator of ``dns.message.Message`` objects. + """ + + if isinstance(zone, str): + zone = dns.name.from_text(zone) + rdtype = dns.rdatatype.RdataType.make(rdtype) + q = dns.message.make_query(zone, rdtype, rdclass) + if rdtype == dns.rdatatype.IXFR: + rrset = dns.rrset.from_text(zone, 0, 'IN', 'SOA', + '. . %u 0 0 0 0' % serial) + q.authority.append(rrset) + if keyring is not None: + q.use_tsig(keyring, keyname, algorithm=keyalgorithm) + wire = q.to_wire() + (af, destination, source) = _destination_and_source(where, port, + source, source_port) + if use_udp and rdtype != dns.rdatatype.IXFR: + raise ValueError('cannot do a UDP AXFR') + sock_type = socket.SOCK_DGRAM if use_udp else socket.SOCK_STREAM + with _make_socket(af, sock_type, source) as s: + (_, expiration) = _compute_times(lifetime) + _connect(s, destination, expiration) + l = len(wire) + if use_udp: + _udp_send(s, wire, None, expiration) + else: + tcpmsg = struct.pack("!H", l) + wire + _net_write(s, tcpmsg, expiration) + done = False + delete_mode = True + expecting_SOA = False + soa_rrset = None + if relativize: + origin = zone + oname = dns.name.empty + else: + origin = None + oname = zone + tsig_ctx = None + while not done: + (_, mexpiration) = _compute_times(timeout) + if mexpiration is None or \ + (expiration is not None and mexpiration > expiration): + mexpiration = expiration + if use_udp: + (wire, _) = _udp_recv(s, 65535, mexpiration) + else: + ldata = _net_read(s, 2, mexpiration) + (l,) = struct.unpack("!H", ldata) + wire = _net_read(s, l, mexpiration) + is_ixfr = (rdtype == dns.rdatatype.IXFR) + r = dns.message.from_wire(wire, keyring=q.keyring, + request_mac=q.mac, xfr=True, + origin=origin, tsig_ctx=tsig_ctx, + multi=True, one_rr_per_rrset=is_ixfr) + rcode = r.rcode() + if rcode != dns.rcode.NOERROR: + raise TransferError(rcode) + tsig_ctx = r.tsig_ctx + answer_index = 0 + if soa_rrset is None: + if not r.answer or r.answer[0].name != oname: + raise dns.exception.FormError( + "No answer or RRset not for qname") + rrset = r.answer[0] + if rrset.rdtype != dns.rdatatype.SOA: + raise dns.exception.FormError("first RRset is not an SOA") + answer_index = 1 + soa_rrset = rrset.copy() + if rdtype == dns.rdatatype.IXFR: + if dns.serial.Serial(soa_rrset[0].serial) <= serial: + # + # We're already up-to-date. + # + done = True + else: + expecting_SOA = True + # + # Process SOAs in the answer section (other than the initial + # SOA in the first message). + # + for rrset in r.answer[answer_index:]: + if done: + raise dns.exception.FormError("answers after final SOA") + if rrset.rdtype == dns.rdatatype.SOA and rrset.name == oname: + if expecting_SOA: + if rrset[0].serial != serial: + raise dns.exception.FormError( + "IXFR base serial mismatch") + expecting_SOA = False + elif rdtype == dns.rdatatype.IXFR: + delete_mode = not delete_mode + # + # If this SOA RRset is equal to the first we saw then we're + # finished. If this is an IXFR we also check that we're + # seeing the record in the expected part of the response. + # + if rrset == soa_rrset and \ + (rdtype == dns.rdatatype.AXFR or + (rdtype == dns.rdatatype.IXFR and delete_mode)): + done = True + elif expecting_SOA: + # + # We made an IXFR request and are expecting another + # SOA RR, but saw something else, so this must be an + # AXFR response. + # + rdtype = dns.rdatatype.AXFR + expecting_SOA = False + if done and q.keyring and not r.had_tsig: + raise dns.exception.FormError("missing TSIG") + yield r + + +class UDPMode(enum.IntEnum): + """How should UDP be used in an IXFR from :py:func:`inbound_xfr()`? + + NEVER means "never use UDP; always use TCP" + TRY_FIRST means "try to use UDP but fall back to TCP if needed" + ONLY means "raise ``dns.xfr.UseTCP`` if trying UDP does not succeed" + """ + NEVER = 0 + TRY_FIRST = 1 + ONLY = 2 + + +def inbound_xfr(where, txn_manager, query=None, + port=53, timeout=None, lifetime=None, source=None, + source_port=0, udp_mode=UDPMode.NEVER): + """Conduct an inbound transfer and apply it via a transaction from the + txn_manager. + + *where*, a ``str`` containing an IPv4 or IPv6 address, where + to send the message. + + *txn_manager*, a ``dns.transaction.TransactionManager``, the txn_manager + for this transfer (typically a ``dns.zone.Zone``). + + *query*, the query to send. If not supplied, a default query is + constructed using information from the *txn_manager*. + + *port*, an ``int``, the port send the message to. The default is 53. + + *timeout*, a ``float``, the number of seconds to wait for each + response message. If None, the default, wait forever. + + *lifetime*, a ``float``, the total number of seconds to spend + doing the transfer. If ``None``, the default, then there is no + limit on the time the transfer may take. + + *source*, a ``str`` containing an IPv4 or IPv6 address, specifying + the source address. The default is the wildcard address. + + *source_port*, an ``int``, the port from which to send the message. + The default is 0. + + *udp_mode*, a ``dns.query.UDPMode``, determines how UDP is used + for IXFRs. The default is ``dns.UDPMode.NEVER``, i.e. only use + TCP. Other possibilites are ``dns.UDPMode.TRY_FIRST``, which + means "try UDP but fallback to TCP if needed", and + ``dns.UDPMode.ONLY``, which means "try UDP and raise + ``dns.xfr.UseTCP`` if it does not succeeed. + + Raises on errors. + """ + if query is None: + (query, serial) = dns.xfr.make_query(txn_manager) + rdtype = query.question[0].rdtype + is_ixfr = rdtype == dns.rdatatype.IXFR + origin = txn_manager.from_wire_origin() + wire = query.to_wire() + (af, destination, source) = _destination_and_source(where, port, + source, source_port) + (_, expiration) = _compute_times(lifetime) + retry = True + while retry: + retry = False + if is_ixfr and udp_mode != UDPMode.NEVER: + sock_type = socket.SOCK_DGRAM + is_udp = True + else: + sock_type = socket.SOCK_STREAM + is_udp = False + with _make_socket(af, sock_type, source) as s: + _connect(s, destination, expiration) + if is_udp: + _udp_send(s, wire, None, expiration) + else: + tcpmsg = struct.pack("!H", len(wire)) + wire + _net_write(s, tcpmsg, expiration) + with dns.xfr.Inbound(txn_manager, rdtype, serial, + is_udp) as inbound: + done = False + tsig_ctx = None + while not done: + (_, mexpiration) = _compute_times(timeout) + if mexpiration is None or \ + (expiration is not None and mexpiration > expiration): + mexpiration = expiration + if is_udp: + (rwire, _) = _udp_recv(s, 65535, mexpiration) + else: + ldata = _net_read(s, 2, mexpiration) + (l,) = struct.unpack("!H", ldata) + rwire = _net_read(s, l, mexpiration) + r = dns.message.from_wire(rwire, keyring=query.keyring, + request_mac=query.mac, xfr=True, + origin=origin, tsig_ctx=tsig_ctx, + multi=(not is_udp), + one_rr_per_rrset=is_ixfr) + try: + done = inbound.process_message(r) + except dns.xfr.UseTCP: + assert is_udp # should not happen if we used TCP! + if udp_mode == UDPMode.ONLY: + raise + done = True + retry = True + udp_mode = UDPMode.NEVER + continue + tsig_ctx = r.tsig_ctx + if not retry and query.keyring and not r.had_tsig: + raise dns.exception.FormError("missing TSIG") diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rcode.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rcode.py new file mode 100644 index 0000000..49fee69 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rcode.py @@ -0,0 +1,164 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Result Codes.""" + +import dns.enum +import dns.exception + +class Rcode(dns.enum.IntEnum): + #: No error + NOERROR = 0 + #: Format error + FORMERR = 1 + #: Server failure + SERVFAIL = 2 + #: Name does not exist ("Name Error" in RFC 1025 terminology). + NXDOMAIN = 3 + #: Not implemented + NOTIMP = 4 + #: Refused + REFUSED = 5 + #: Name exists. + YXDOMAIN = 6 + #: RRset exists. + YXRRSET = 7 + #: RRset does not exist. + NXRRSET = 8 + #: Not authoritative. + NOTAUTH = 9 + #: Name not in zone. + NOTZONE = 10 + #: DSO-TYPE Not Implemented + DSOTYPENI = 11 + #: Bad EDNS version. + BADVERS = 16 + #: TSIG Signature Failure + BADSIG = 16 + #: Key not recognized. + BADKEY = 17 + #: Signature out of time window. + BADTIME = 18 + #: Bad TKEY Mode. + BADMODE = 19 + #: Duplicate key name. + BADNAME = 20 + #: Algorithm not supported. + BADALG = 21 + #: Bad Truncation + BADTRUNC = 22 + #: Bad/missing Server Cookie + BADCOOKIE = 23 + + @classmethod + def _maximum(cls): + return 4095 + + @classmethod + def _unknown_exception_class(cls): + return UnknownRcode + + +class UnknownRcode(dns.exception.DNSException): + """A DNS rcode is unknown.""" + + +def from_text(text): + """Convert text into an rcode. + + *text*, a ``str``, the textual rcode or an integer in textual form. + + Raises ``dns.rcode.UnknownRcode`` if the rcode mnemonic is unknown. + + Returns an ``int``. + """ + + return Rcode.from_text(text) + + +def from_flags(flags, ednsflags): + """Return the rcode value encoded by flags and ednsflags. + + *flags*, an ``int``, the DNS flags field. + + *ednsflags*, an ``int``, the EDNS flags field. + + Raises ``ValueError`` if rcode is < 0 or > 4095 + + Returns an ``int``. + """ + + value = (flags & 0x000f) | ((ednsflags >> 20) & 0xff0) + return value + + +def to_flags(value): + """Return a (flags, ednsflags) tuple which encodes the rcode. + + *value*, an ``int``, the rcode. + + Raises ``ValueError`` if rcode is < 0 or > 4095. + + Returns an ``(int, int)`` tuple. + """ + + if value < 0 or value > 4095: + raise ValueError('rcode must be >= 0 and <= 4095') + v = value & 0xf + ev = (value & 0xff0) << 20 + return (v, ev) + + +def to_text(value, tsig=False): + """Convert rcode into text. + + *value*, an ``int``, the rcode. + + Raises ``ValueError`` if rcode is < 0 or > 4095. + + Returns a ``str``. + """ + + if tsig and value == Rcode.BADVERS: + return 'BADSIG' + return Rcode.to_text(value) + +### BEGIN generated Rcode constants + +NOERROR = Rcode.NOERROR +FORMERR = Rcode.FORMERR +SERVFAIL = Rcode.SERVFAIL +NXDOMAIN = Rcode.NXDOMAIN +NOTIMP = Rcode.NOTIMP +REFUSED = Rcode.REFUSED +YXDOMAIN = Rcode.YXDOMAIN +YXRRSET = Rcode.YXRRSET +NXRRSET = Rcode.NXRRSET +NOTAUTH = Rcode.NOTAUTH +NOTZONE = Rcode.NOTZONE +DSOTYPENI = Rcode.DSOTYPENI +BADVERS = Rcode.BADVERS +BADSIG = Rcode.BADSIG +BADKEY = Rcode.BADKEY +BADTIME = Rcode.BADTIME +BADMODE = Rcode.BADMODE +BADNAME = Rcode.BADNAME +BADALG = Rcode.BADALG +BADTRUNC = Rcode.BADTRUNC +BADCOOKIE = Rcode.BADCOOKIE + +### END generated Rcode constants diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdata.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdata.py new file mode 100644 index 0000000..12f3b6f --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdata.py @@ -0,0 +1,719 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS rdata.""" + +from importlib import import_module +import base64 +import binascii +import io +import inspect +import itertools +import random + +import dns.wire +import dns.exception +import dns.immutable +import dns.ipv4 +import dns.ipv6 +import dns.name +import dns.rdataclass +import dns.rdatatype +import dns.tokenizer +import dns.ttl + +_chunksize = 32 + + +def _wordbreak(data, chunksize=_chunksize): + """Break a binary string into chunks of chunksize characters separated by + a space. + """ + + if not chunksize: + return data.decode() + return b' '.join([data[i:i + chunksize] + for i + in range(0, len(data), chunksize)]).decode() + + +def _hexify(data, chunksize=_chunksize, **kw): + """Convert a binary string into its hex encoding, broken up into chunks + of chunksize characters separated by a space. + """ + + return _wordbreak(binascii.hexlify(data), chunksize) + + +def _base64ify(data, chunksize=_chunksize, **kw): + """Convert a binary string into its base64 encoding, broken up into chunks + of chunksize characters separated by a space. + """ + + return _wordbreak(base64.b64encode(data), chunksize) + + +__escaped = b'"\\' + +def _escapify(qstring): + """Escape the characters in a quoted string which need it.""" + + if isinstance(qstring, str): + qstring = qstring.encode() + if not isinstance(qstring, bytearray): + qstring = bytearray(qstring) + + text = '' + for c in qstring: + if c in __escaped: + text += '\\' + chr(c) + elif c >= 0x20 and c < 0x7F: + text += chr(c) + else: + text += '\\%03d' % c + return text + + +def _truncate_bitmap(what): + """Determine the index of greatest byte that isn't all zeros, and + return the bitmap that contains all the bytes less than that index. + """ + + for i in range(len(what) - 1, -1, -1): + if what[i] != 0: + return what[0: i + 1] + return what[0:1] + +# So we don't have to edit all the rdata classes... +_constify = dns.immutable.constify + + +@dns.immutable.immutable +class Rdata: + """Base class for all DNS rdata types.""" + + __slots__ = ['rdclass', 'rdtype', 'rdcomment'] + + def __init__(self, rdclass, rdtype): + """Initialize an rdata. + + *rdclass*, an ``int`` is the rdataclass of the Rdata. + + *rdtype*, an ``int`` is the rdatatype of the Rdata. + """ + + self.rdclass = self._as_rdataclass(rdclass) + self.rdtype = self._as_rdatatype(rdtype) + self.rdcomment = None + + def _get_all_slots(self): + return itertools.chain.from_iterable(getattr(cls, '__slots__', []) + for cls in self.__class__.__mro__) + + def __getstate__(self): + # We used to try to do a tuple of all slots here, but it + # doesn't work as self._all_slots isn't available at + # __setstate__() time. Before that we tried to store a tuple + # of __slots__, but that didn't work as it didn't store the + # slots defined by ancestors. This older way didn't fail + # outright, but ended up with partially broken objects, e.g. + # if you unpickled an A RR it wouldn't have rdclass and rdtype + # attributes, and would compare badly. + state = {} + for slot in self._get_all_slots(): + state[slot] = getattr(self, slot) + return state + + def __setstate__(self, state): + for slot, val in state.items(): + object.__setattr__(self, slot, val) + if not hasattr(self, 'rdcomment'): + # Pickled rdata from 2.0.x might not have a rdcomment, so add + # it if needed. + object.__setattr__(self, 'rdcomment', None) + + def covers(self): + """Return the type a Rdata covers. + + DNS SIG/RRSIG rdatas apply to a specific type; this type is + returned by the covers() function. If the rdata type is not + SIG or RRSIG, dns.rdatatype.NONE is returned. This is useful when + creating rdatasets, allowing the rdataset to contain only RRSIGs + of a particular type, e.g. RRSIG(NS). + + Returns an ``int``. + """ + + return dns.rdatatype.NONE + + def extended_rdatatype(self): + """Return a 32-bit type value, the least significant 16 bits of + which are the ordinary DNS type, and the upper 16 bits of which are + the "covered" type, if any. + + Returns an ``int``. + """ + + return self.covers() << 16 | self.rdtype + + def to_text(self, origin=None, relativize=True, **kw): + """Convert an rdata to text format. + + Returns a ``str``. + """ + + raise NotImplementedError # pragma: no cover + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + raise NotImplementedError # pragma: no cover + + def to_wire(self, file=None, compress=None, origin=None, + canonicalize=False): + """Convert an rdata to wire format. + + Returns a ``bytes`` or ``None``. + """ + + if file: + return self._to_wire(file, compress, origin, canonicalize) + else: + f = io.BytesIO() + self._to_wire(f, compress, origin, canonicalize) + return f.getvalue() + + def to_generic(self, origin=None): + """Creates a dns.rdata.GenericRdata equivalent of this rdata. + + Returns a ``dns.rdata.GenericRdata``. + """ + return dns.rdata.GenericRdata(self.rdclass, self.rdtype, + self.to_wire(origin=origin)) + + def to_digestable(self, origin=None): + """Convert rdata to a format suitable for digesting in hashes. This + is also the DNSSEC canonical form. + + Returns a ``bytes``. + """ + + return self.to_wire(origin=origin, canonicalize=True) + + def __repr__(self): + covers = self.covers() + if covers == dns.rdatatype.NONE: + ctext = '' + else: + ctext = '(' + dns.rdatatype.to_text(covers) + ')' + return '' + + def __str__(self): + return self.to_text() + + def _cmp(self, other): + """Compare an rdata with another rdata of the same rdtype and + rdclass. + + Return < 0 if self < other in the DNSSEC ordering, 0 if self + == other, and > 0 if self > other. + + """ + our = self.to_digestable(dns.name.root) + their = other.to_digestable(dns.name.root) + if our == their: + return 0 + elif our > their: + return 1 + else: + return -1 + + def __eq__(self, other): + if not isinstance(other, Rdata): + return False + if self.rdclass != other.rdclass or self.rdtype != other.rdtype: + return False + return self._cmp(other) == 0 + + def __ne__(self, other): + if not isinstance(other, Rdata): + return True + if self.rdclass != other.rdclass or self.rdtype != other.rdtype: + return True + return self._cmp(other) != 0 + + def __lt__(self, other): + if not isinstance(other, Rdata) or \ + self.rdclass != other.rdclass or self.rdtype != other.rdtype: + + return NotImplemented + return self._cmp(other) < 0 + + def __le__(self, other): + if not isinstance(other, Rdata) or \ + self.rdclass != other.rdclass or self.rdtype != other.rdtype: + return NotImplemented + return self._cmp(other) <= 0 + + def __ge__(self, other): + if not isinstance(other, Rdata) or \ + self.rdclass != other.rdclass or self.rdtype != other.rdtype: + return NotImplemented + return self._cmp(other) >= 0 + + def __gt__(self, other): + if not isinstance(other, Rdata) or \ + self.rdclass != other.rdclass or self.rdtype != other.rdtype: + return NotImplemented + return self._cmp(other) > 0 + + def __hash__(self): + return hash(self.to_digestable(dns.name.root)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + raise NotImplementedError # pragma: no cover + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + raise NotImplementedError # pragma: no cover + + def replace(self, **kwargs): + """ + Create a new Rdata instance based on the instance replace was + invoked on. It is possible to pass different parameters to + override the corresponding properties of the base Rdata. + + Any field specific to the Rdata type can be replaced, but the + *rdtype* and *rdclass* fields cannot. + + Returns an instance of the same Rdata subclass as *self*. + """ + + # Get the constructor parameters. + parameters = inspect.signature(self.__init__).parameters + + # Ensure that all of the arguments correspond to valid fields. + # Don't allow rdclass or rdtype to be changed, though. + for key in kwargs: + if key == 'rdcomment': + continue + if key not in parameters: + raise AttributeError("'{}' object has no attribute '{}'" + .format(self.__class__.__name__, key)) + if key in ('rdclass', 'rdtype'): + raise AttributeError("Cannot overwrite '{}' attribute '{}'" + .format(self.__class__.__name__, key)) + + # Construct the parameter list. For each field, use the value in + # kwargs if present, and the current value otherwise. + args = (kwargs.get(key, getattr(self, key)) for key in parameters) + + # Create, validate, and return the new object. + rd = self.__class__(*args) + # The comment is not set in the constructor, so give it special + # handling. + rdcomment = kwargs.get('rdcomment', self.rdcomment) + if rdcomment is not None: + object.__setattr__(rd, 'rdcomment', rdcomment) + return rd + + # Type checking and conversion helpers. These are class methods as + # they don't touch object state and may be useful to others. + + @classmethod + def _as_rdataclass(cls, value): + return dns.rdataclass.RdataClass.make(value) + + @classmethod + def _as_rdatatype(cls, value): + return dns.rdatatype.RdataType.make(value) + + @classmethod + def _as_bytes(cls, value, encode=False, max_length=None, empty_ok=True): + if encode and isinstance(value, str): + value = value.encode() + elif isinstance(value, bytearray): + value = bytes(value) + elif not isinstance(value, bytes): + raise ValueError('not bytes') + if max_length is not None and len(value) > max_length: + raise ValueError('too long') + if not empty_ok and len(value) == 0: + raise ValueError('empty bytes not allowed') + return value + + @classmethod + def _as_name(cls, value): + # Note that proper name conversion (e.g. with origin and IDNA + # awareness) is expected to be done via from_text. This is just + # a simple thing for people invoking the constructor directly. + if isinstance(value, str): + return dns.name.from_text(value) + elif not isinstance(value, dns.name.Name): + raise ValueError('not a name') + return value + + @classmethod + def _as_uint8(cls, value): + if not isinstance(value, int): + raise ValueError('not an integer') + if value < 0 or value > 255: + raise ValueError('not a uint8') + return value + + @classmethod + def _as_uint16(cls, value): + if not isinstance(value, int): + raise ValueError('not an integer') + if value < 0 or value > 65535: + raise ValueError('not a uint16') + return value + + @classmethod + def _as_uint32(cls, value): + if not isinstance(value, int): + raise ValueError('not an integer') + if value < 0 or value > 4294967295: + raise ValueError('not a uint32') + return value + + @classmethod + def _as_uint48(cls, value): + if not isinstance(value, int): + raise ValueError('not an integer') + if value < 0 or value > 281474976710655: + raise ValueError('not a uint48') + return value + + @classmethod + def _as_int(cls, value, low=None, high=None): + if not isinstance(value, int): + raise ValueError('not an integer') + if low is not None and value < low: + raise ValueError('value too small') + if high is not None and value > high: + raise ValueError('value too large') + return value + + @classmethod + def _as_ipv4_address(cls, value): + if isinstance(value, str): + # call to check validity + dns.ipv4.inet_aton(value) + return value + elif isinstance(value, bytes): + return dns.ipv4.inet_ntoa(value) + else: + raise ValueError('not an IPv4 address') + + @classmethod + def _as_ipv6_address(cls, value): + if isinstance(value, str): + # call to check validity + dns.ipv6.inet_aton(value) + return value + elif isinstance(value, bytes): + return dns.ipv6.inet_ntoa(value) + else: + raise ValueError('not an IPv6 address') + + @classmethod + def _as_bool(cls, value): + if isinstance(value, bool): + return value + else: + raise ValueError('not a boolean') + + @classmethod + def _as_ttl(cls, value): + if isinstance(value, int): + return cls._as_int(value, 0, dns.ttl.MAX_TTL) + elif isinstance(value, str): + return dns.ttl.from_text(value) + else: + raise ValueError('not a TTL') + + @classmethod + def _as_tuple(cls, value, as_value): + try: + # For user convenience, if value is a singleton of the list + # element type, wrap it in a tuple. + return (as_value(value),) + except Exception: + # Otherwise, check each element of the iterable *value* + # against *as_value*. + return tuple(as_value(v) for v in value) + + # Processing order + + @classmethod + def _processing_order(cls, iterable): + items = list(iterable) + random.shuffle(items) + return items + + +class GenericRdata(Rdata): + + """Generic Rdata Class + + This class is used for rdata types for which we have no better + implementation. It implements the DNS "unknown RRs" scheme. + """ + + __slots__ = ['data'] + + def __init__(self, rdclass, rdtype, data): + super().__init__(rdclass, rdtype) + object.__setattr__(self, 'data', data) + + def to_text(self, origin=None, relativize=True, **kw): + return r'\# %d ' % len(self.data) + _hexify(self.data, **kw) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + token = tok.get() + if not token.is_identifier() or token.value != r'\#': + raise dns.exception.SyntaxError( + r'generic rdata does not start with \#') + length = tok.get_int() + hex = tok.concatenate_remaining_identifiers().encode() + data = binascii.unhexlify(hex) + if len(data) != length: + raise dns.exception.SyntaxError( + 'generic rdata hex data has wrong length') + return cls(rdclass, rdtype, data) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(self.data) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + return cls(rdclass, rdtype, parser.get_remaining()) + +_rdata_classes = {} +_module_prefix = 'dns.rdtypes' + +def get_rdata_class(rdclass, rdtype): + cls = _rdata_classes.get((rdclass, rdtype)) + if not cls: + cls = _rdata_classes.get((dns.rdatatype.ANY, rdtype)) + if not cls: + rdclass_text = dns.rdataclass.to_text(rdclass) + rdtype_text = dns.rdatatype.to_text(rdtype) + rdtype_text = rdtype_text.replace('-', '_') + try: + mod = import_module('.'.join([_module_prefix, + rdclass_text, rdtype_text])) + cls = getattr(mod, rdtype_text) + _rdata_classes[(rdclass, rdtype)] = cls + except ImportError: + try: + mod = import_module('.'.join([_module_prefix, + 'ANY', rdtype_text])) + cls = getattr(mod, rdtype_text) + _rdata_classes[(dns.rdataclass.ANY, rdtype)] = cls + _rdata_classes[(rdclass, rdtype)] = cls + except ImportError: + pass + if not cls: + cls = GenericRdata + _rdata_classes[(rdclass, rdtype)] = cls + return cls + + +def from_text(rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None, idna_codec=None): + """Build an rdata object from text format. + + This function attempts to dynamically load a class which + implements the specified rdata class and type. If there is no + class-and-type-specific implementation, the GenericRdata class + is used. + + Once a class is chosen, its from_text() class method is called + with the parameters to this function. + + If *tok* is a ``str``, then a tokenizer is created and the string + is used as its input. + + *rdclass*, an ``int``, the rdataclass. + + *rdtype*, an ``int``, the rdatatype. + + *tok*, a ``dns.tokenizer.Tokenizer`` or a ``str``. + + *origin*, a ``dns.name.Name`` (or ``None``), the + origin to use for relative names. + + *relativize*, a ``bool``. If true, name will be relativized. + + *relativize_to*, a ``dns.name.Name`` (or ``None``), the origin to use + when relativizing names. If not set, the *origin* value will be used. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder to use if a tokenizer needs to be created. If + ``None``, the default IDNA 2003 encoder/decoder is used. If a + tokenizer is not created, then the codec associated with the tokenizer + is the one that is used. + + Returns an instance of the chosen Rdata subclass. + + """ + if isinstance(tok, str): + tok = dns.tokenizer.Tokenizer(tok, idna_codec=idna_codec) + rdclass = dns.rdataclass.RdataClass.make(rdclass) + rdtype = dns.rdatatype.RdataType.make(rdtype) + cls = get_rdata_class(rdclass, rdtype) + with dns.exception.ExceptionWrapper(dns.exception.SyntaxError): + rdata = None + if cls != GenericRdata: + # peek at first token + token = tok.get() + tok.unget(token) + if token.is_identifier() and \ + token.value == r'\#': + # + # Known type using the generic syntax. Extract the + # wire form from the generic syntax, and then run + # from_wire on it. + # + grdata = GenericRdata.from_text(rdclass, rdtype, tok, origin, + relativize, relativize_to) + rdata = from_wire(rdclass, rdtype, grdata.data, 0, + len(grdata.data), origin) + # + # If this comparison isn't equal, then there must have been + # compressed names in the wire format, which is an error, + # there being no reasonable context to decompress with. + # + rwire = rdata.to_wire() + if rwire != grdata.data: + raise dns.exception.SyntaxError('compressed data in ' + 'generic syntax form ' + 'of known rdatatype') + if rdata is None: + rdata = cls.from_text(rdclass, rdtype, tok, origin, relativize, + relativize_to) + token = tok.get_eol_as_token() + if token.comment is not None: + object.__setattr__(rdata, 'rdcomment', token.comment) + return rdata + + +def from_wire_parser(rdclass, rdtype, parser, origin=None): + """Build an rdata object from wire format + + This function attempts to dynamically load a class which + implements the specified rdata class and type. If there is no + class-and-type-specific implementation, the GenericRdata class + is used. + + Once a class is chosen, its from_wire() class method is called + with the parameters to this function. + + *rdclass*, an ``int``, the rdataclass. + + *rdtype*, an ``int``, the rdatatype. + + *parser*, a ``dns.wire.Parser``, the parser, which should be + restricted to the rdata length. + + *origin*, a ``dns.name.Name`` (or ``None``). If not ``None``, + then names will be relativized to this origin. + + Returns an instance of the chosen Rdata subclass. + """ + + rdclass = dns.rdataclass.RdataClass.make(rdclass) + rdtype = dns.rdatatype.RdataType.make(rdtype) + cls = get_rdata_class(rdclass, rdtype) + with dns.exception.ExceptionWrapper(dns.exception.FormError): + return cls.from_wire_parser(rdclass, rdtype, parser, origin) + + +def from_wire(rdclass, rdtype, wire, current, rdlen, origin=None): + """Build an rdata object from wire format + + This function attempts to dynamically load a class which + implements the specified rdata class and type. If there is no + class-and-type-specific implementation, the GenericRdata class + is used. + + Once a class is chosen, its from_wire() class method is called + with the parameters to this function. + + *rdclass*, an ``int``, the rdataclass. + + *rdtype*, an ``int``, the rdatatype. + + *wire*, a ``bytes``, the wire-format message. + + *current*, an ``int``, the offset in wire of the beginning of + the rdata. + + *rdlen*, an ``int``, the length of the wire-format rdata + + *origin*, a ``dns.name.Name`` (or ``None``). If not ``None``, + then names will be relativized to this origin. + + Returns an instance of the chosen Rdata subclass. + """ + parser = dns.wire.Parser(wire, current) + with parser.restrict_to(rdlen): + return from_wire_parser(rdclass, rdtype, parser, origin) + + +class RdatatypeExists(dns.exception.DNSException): + """DNS rdatatype already exists.""" + supp_kwargs = {'rdclass', 'rdtype'} + fmt = "The rdata type with class {rdclass} and rdtype {rdtype} " + \ + "already exists." + + +def register_type(implementation, rdtype, rdtype_text, is_singleton=False, + rdclass=dns.rdataclass.IN): + """Dynamically register a module to handle an rdatatype. + + *implementation*, a module implementing the type in the usual dnspython + way. + + *rdtype*, an ``int``, the rdatatype to register. + + *rdtype_text*, a ``str``, the textual form of the rdatatype. + + *is_singleton*, a ``bool``, indicating if the type is a singleton (i.e. + RRsets of the type can have only one member.) + + *rdclass*, the rdataclass of the type, or ``dns.rdataclass.ANY`` if + it applies to all classes. + """ + + existing_cls = get_rdata_class(rdclass, rdtype) + if existing_cls != GenericRdata or dns.rdatatype.is_metatype(rdtype): + raise RdatatypeExists(rdclass=rdclass, rdtype=rdtype) + try: + if dns.rdatatype.RdataType(rdtype).name != rdtype_text: + raise RdatatypeExists(rdclass=rdclass, rdtype=rdtype) + except ValueError: + pass + _rdata_classes[(rdclass, rdtype)] = getattr(implementation, + rdtype_text.replace('-', '_')) + dns.rdatatype.register_type(rdtype, rdtype_text, is_singleton) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdataclass.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdataclass.py new file mode 100644 index 0000000..41bba69 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdataclass.py @@ -0,0 +1,115 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Rdata Classes.""" + +import dns.enum +import dns.exception + +class RdataClass(dns.enum.IntEnum): + """DNS Rdata Class""" + RESERVED0 = 0 + IN = 1 + INTERNET = IN + CH = 3 + CHAOS = CH + HS = 4 + HESIOD = HS + NONE = 254 + ANY = 255 + + @classmethod + def _maximum(cls): + return 65535 + + @classmethod + def _short_name(cls): + return "class" + + @classmethod + def _prefix(cls): + return "CLASS" + + @classmethod + def _unknown_exception_class(cls): + return UnknownRdataclass + + +_metaclasses = {RdataClass.NONE, RdataClass.ANY} + + +class UnknownRdataclass(dns.exception.DNSException): + """A DNS class is unknown.""" + + +def from_text(text): + """Convert text into a DNS rdata class value. + + The input text can be a defined DNS RR class mnemonic or + instance of the DNS generic class syntax. + + For example, "IN" and "CLASS1" will both result in a value of 1. + + Raises ``dns.rdatatype.UnknownRdataclass`` if the class is unknown. + + Raises ``ValueError`` if the rdata class value is not >= 0 and <= 65535. + + Returns an ``int``. + """ + + return RdataClass.from_text(text) + + +def to_text(value): + """Convert a DNS rdata class value to text. + + If the value has a known mnemonic, it will be used, otherwise the + DNS generic class syntax will be used. + + Raises ``ValueError`` if the rdata class value is not >= 0 and <= 65535. + + Returns a ``str``. + """ + + return RdataClass.to_text(value) + + +def is_metaclass(rdclass): + """True if the specified class is a metaclass. + + The currently defined metaclasses are ANY and NONE. + + *rdclass* is an ``int``. + """ + + if rdclass in _metaclasses: + return True + return False + +### BEGIN generated RdataClass constants + +RESERVED0 = RdataClass.RESERVED0 +IN = RdataClass.IN +INTERNET = RdataClass.INTERNET +CH = RdataClass.CH +CHAOS = RdataClass.CHAOS +HS = RdataClass.HS +HESIOD = RdataClass.HESIOD +NONE = RdataClass.NONE +ANY = RdataClass.ANY + +### END generated RdataClass constants diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdataset.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdataset.py new file mode 100644 index 0000000..e69ee23 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdataset.py @@ -0,0 +1,456 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS rdatasets (an rdataset is a set of rdatas of a given type and class)""" + +import io +import random +import struct + +import dns.exception +import dns.immutable +import dns.rdatatype +import dns.rdataclass +import dns.rdata +import dns.set + +# define SimpleSet here for backwards compatibility +SimpleSet = dns.set.Set + + +class DifferingCovers(dns.exception.DNSException): + """An attempt was made to add a DNS SIG/RRSIG whose covered type + is not the same as that of the other rdatas in the rdataset.""" + + +class IncompatibleTypes(dns.exception.DNSException): + """An attempt was made to add DNS RR data of an incompatible type.""" + + +class Rdataset(dns.set.Set): + + """A DNS rdataset.""" + + __slots__ = ['rdclass', 'rdtype', 'covers', 'ttl'] + + def __init__(self, rdclass, rdtype, covers=dns.rdatatype.NONE, ttl=0): + """Create a new rdataset of the specified class and type. + + *rdclass*, an ``int``, the rdataclass. + + *rdtype*, an ``int``, the rdatatype. + + *covers*, an ``int``, the covered rdatatype. + + *ttl*, an ``int``, the TTL. + """ + + super().__init__() + self.rdclass = rdclass + self.rdtype = rdtype + self.covers = covers + self.ttl = ttl + + def _clone(self): + obj = super()._clone() + obj.rdclass = self.rdclass + obj.rdtype = self.rdtype + obj.covers = self.covers + obj.ttl = self.ttl + return obj + + def update_ttl(self, ttl): + """Perform TTL minimization. + + Set the TTL of the rdataset to be the lesser of the set's current + TTL or the specified TTL. If the set contains no rdatas, set the TTL + to the specified TTL. + + *ttl*, an ``int`` or ``str``. + """ + ttl = dns.ttl.make(ttl) + if len(self) == 0: + self.ttl = ttl + elif ttl < self.ttl: + self.ttl = ttl + + def add(self, rd, ttl=None): # pylint: disable=arguments-differ + """Add the specified rdata to the rdataset. + + If the optional *ttl* parameter is supplied, then + ``self.update_ttl(ttl)`` will be called prior to adding the rdata. + + *rd*, a ``dns.rdata.Rdata``, the rdata + + *ttl*, an ``int``, the TTL. + + Raises ``dns.rdataset.IncompatibleTypes`` if the type and class + do not match the type and class of the rdataset. + + Raises ``dns.rdataset.DifferingCovers`` if the type is a signature + type and the covered type does not match that of the rdataset. + """ + + # + # If we're adding a signature, do some special handling to + # check that the signature covers the same type as the + # other rdatas in this rdataset. If this is the first rdata + # in the set, initialize the covers field. + # + if self.rdclass != rd.rdclass or self.rdtype != rd.rdtype: + raise IncompatibleTypes + if ttl is not None: + self.update_ttl(ttl) + if self.rdtype == dns.rdatatype.RRSIG or \ + self.rdtype == dns.rdatatype.SIG: + covers = rd.covers() + if len(self) == 0 and self.covers == dns.rdatatype.NONE: + self.covers = covers + elif self.covers != covers: + raise DifferingCovers + if dns.rdatatype.is_singleton(rd.rdtype) and len(self) > 0: + self.clear() + super().add(rd) + + def union_update(self, other): + self.update_ttl(other.ttl) + super().union_update(other) + + def intersection_update(self, other): + self.update_ttl(other.ttl) + super().intersection_update(other) + + def update(self, other): + """Add all rdatas in other to self. + + *other*, a ``dns.rdataset.Rdataset``, the rdataset from which + to update. + """ + + self.update_ttl(other.ttl) + super().update(other) + + def _rdata_repr(self): + def maybe_truncate(s): + if len(s) > 100: + return s[:100] + '...' + return s + return '[%s]' % ', '.join('<%s>' % maybe_truncate(str(rr)) + for rr in self) + + def __repr__(self): + if self.covers == 0: + ctext = '' + else: + ctext = '(' + dns.rdatatype.to_text(self.covers) + ')' + return '' + + def __str__(self): + return self.to_text() + + def __eq__(self, other): + if not isinstance(other, Rdataset): + return False + if self.rdclass != other.rdclass or \ + self.rdtype != other.rdtype or \ + self.covers != other.covers: + return False + return super().__eq__(other) + + def __ne__(self, other): + return not self.__eq__(other) + + def to_text(self, name=None, origin=None, relativize=True, + override_rdclass=None, want_comments=False, **kw): + """Convert the rdataset into DNS zone file format. + + See ``dns.name.Name.choose_relativity`` for more information + on how *origin* and *relativize* determine the way names + are emitted. + + Any additional keyword arguments are passed on to the rdata + ``to_text()`` method. + + *name*, a ``dns.name.Name``. If name is not ``None``, emit RRs with + *name* as the owner name. + + *origin*, a ``dns.name.Name`` or ``None``, the origin for relative + names. + + *relativize*, a ``bool``. If ``True``, names will be relativized + to *origin*. + + *override_rdclass*, a ``dns.rdataclass.RdataClass`` or ``None``. + If not ``None``, use this class instead of the Rdataset's class. + + *want_comments*, a ``bool``. If ``True``, emit comments for rdata + which have them. The default is ``False``. + """ + + if name is not None: + name = name.choose_relativity(origin, relativize) + ntext = str(name) + pad = ' ' + else: + ntext = '' + pad = '' + s = io.StringIO() + if override_rdclass is not None: + rdclass = override_rdclass + else: + rdclass = self.rdclass + if len(self) == 0: + # + # Empty rdatasets are used for the question section, and in + # some dynamic updates, so we don't need to print out the TTL + # (which is meaningless anyway). + # + s.write('{}{}{} {}\n'.format(ntext, pad, + dns.rdataclass.to_text(rdclass), + dns.rdatatype.to_text(self.rdtype))) + else: + for rd in self: + extra = '' + if want_comments: + if rd.rdcomment: + extra = f' ;{rd.rdcomment}' + s.write('%s%s%d %s %s %s%s\n' % + (ntext, pad, self.ttl, dns.rdataclass.to_text(rdclass), + dns.rdatatype.to_text(self.rdtype), + rd.to_text(origin=origin, relativize=relativize, + **kw), + extra)) + # + # We strip off the final \n for the caller's convenience in printing + # + return s.getvalue()[:-1] + + def to_wire(self, name, file, compress=None, origin=None, + override_rdclass=None, want_shuffle=True): + """Convert the rdataset to wire format. + + *name*, a ``dns.name.Name`` is the owner name to use. + + *file* is the file where the name is emitted (typically a + BytesIO file). + + *compress*, a ``dict``, is the compression table to use. If + ``None`` (the default), names will not be compressed. + + *origin* is a ``dns.name.Name`` or ``None``. If the name is + relative and origin is not ``None``, then *origin* will be appended + to it. + + *override_rdclass*, an ``int``, is used as the class instead of the + class of the rdataset. This is useful when rendering rdatasets + associated with dynamic updates. + + *want_shuffle*, a ``bool``. If ``True``, then the order of the + Rdatas within the Rdataset will be shuffled before rendering. + + Returns an ``int``, the number of records emitted. + """ + + if override_rdclass is not None: + rdclass = override_rdclass + want_shuffle = False + else: + rdclass = self.rdclass + file.seek(0, io.SEEK_END) + if len(self) == 0: + name.to_wire(file, compress, origin) + stuff = struct.pack("!HHIH", self.rdtype, rdclass, 0, 0) + file.write(stuff) + return 1 + else: + if want_shuffle: + l = list(self) + random.shuffle(l) + else: + l = self + for rd in l: + name.to_wire(file, compress, origin) + stuff = struct.pack("!HHIH", self.rdtype, rdclass, + self.ttl, 0) + file.write(stuff) + start = file.tell() + rd.to_wire(file, compress, origin) + end = file.tell() + assert end - start < 65536 + file.seek(start - 2) + stuff = struct.pack("!H", end - start) + file.write(stuff) + file.seek(0, io.SEEK_END) + return len(self) + + def match(self, rdclass, rdtype, covers): + """Returns ``True`` if this rdataset matches the specified class, + type, and covers. + """ + if self.rdclass == rdclass and \ + self.rdtype == rdtype and \ + self.covers == covers: + return True + return False + + def processing_order(self): + """Return rdatas in a valid processing order according to the type's + specification. For example, MX records are in preference order from + lowest to highest preferences, with items of the same perference + shuffled. + + For types that do not define a processing order, the rdatas are + simply shuffled. + """ + if len(self) == 0: + return [] + else: + return self[0]._processing_order(iter(self)) + + +@dns.immutable.immutable +class ImmutableRdataset(Rdataset): + + """An immutable DNS rdataset.""" + + _clone_class = Rdataset + + def __init__(self, rdataset): + """Create an immutable rdataset from the specified rdataset.""" + + super().__init__(rdataset.rdclass, rdataset.rdtype, rdataset.covers, + rdataset.ttl) + self.items = dns.immutable.Dict(rdataset.items) + + def update_ttl(self, ttl): + raise TypeError('immutable') + + def add(self, rd, ttl=None): + raise TypeError('immutable') + + def union_update(self, other): + raise TypeError('immutable') + + def intersection_update(self, other): + raise TypeError('immutable') + + def update(self, other): + raise TypeError('immutable') + + def __delitem__(self, i): + raise TypeError('immutable') + + def __ior__(self, other): + raise TypeError('immutable') + + def __iand__(self, other): + raise TypeError('immutable') + + def __iadd__(self, other): + raise TypeError('immutable') + + def __isub__(self, other): + raise TypeError('immutable') + + def clear(self): + raise TypeError('immutable') + + def __copy__(self): + return ImmutableRdataset(super().copy()) + + def copy(self): + return ImmutableRdataset(super().copy()) + + def union(self, other): + return ImmutableRdataset(super().union(other)) + + def intersection(self, other): + return ImmutableRdataset(super().intersection(other)) + + def difference(self, other): + return ImmutableRdataset(super().difference(other)) + + +def from_text_list(rdclass, rdtype, ttl, text_rdatas, idna_codec=None, + origin=None, relativize=True, relativize_to=None): + """Create an rdataset with the specified class, type, and TTL, and with + the specified list of rdatas in text format. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder to use; if ``None``, the default IDNA 2003 + encoder/decoder is used. + + *origin*, a ``dns.name.Name`` (or ``None``), the + origin to use for relative names. + + *relativize*, a ``bool``. If true, name will be relativized. + + *relativize_to*, a ``dns.name.Name`` (or ``None``), the origin to use + when relativizing names. If not set, the *origin* value will be used. + + Returns a ``dns.rdataset.Rdataset`` object. + """ + + rdclass = dns.rdataclass.RdataClass.make(rdclass) + rdtype = dns.rdatatype.RdataType.make(rdtype) + r = Rdataset(rdclass, rdtype) + r.update_ttl(ttl) + for t in text_rdatas: + rd = dns.rdata.from_text(r.rdclass, r.rdtype, t, origin, relativize, + relativize_to, idna_codec) + r.add(rd) + return r + + +def from_text(rdclass, rdtype, ttl, *text_rdatas): + """Create an rdataset with the specified class, type, and TTL, and with + the specified rdatas in text format. + + Returns a ``dns.rdataset.Rdataset`` object. + """ + + return from_text_list(rdclass, rdtype, ttl, text_rdatas) + + +def from_rdata_list(ttl, rdatas): + """Create an rdataset with the specified TTL, and with + the specified list of rdata objects. + + Returns a ``dns.rdataset.Rdataset`` object. + """ + + if len(rdatas) == 0: + raise ValueError("rdata list must not be empty") + r = None + for rd in rdatas: + if r is None: + r = Rdataset(rd.rdclass, rd.rdtype) + r.update_ttl(ttl) + r.add(rd) + return r + + +def from_rdata(ttl, *rdatas): + """Create an rdataset with the specified TTL, and with + the specified rdata objects. + + Returns a ``dns.rdataset.Rdataset`` object. + """ + + return from_rdata_list(ttl, rdatas) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdatatype.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdatatype.py new file mode 100644 index 0000000..65da6d4 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdatatype.py @@ -0,0 +1,303 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Rdata Types.""" + +import dns.enum +import dns.exception + +class RdataType(dns.enum.IntEnum): + """DNS Rdata Type""" + TYPE0 = 0 + NONE = 0 + A = 1 + NS = 2 + MD = 3 + MF = 4 + CNAME = 5 + SOA = 6 + MB = 7 + MG = 8 + MR = 9 + NULL = 10 + WKS = 11 + PTR = 12 + HINFO = 13 + MINFO = 14 + MX = 15 + TXT = 16 + RP = 17 + AFSDB = 18 + X25 = 19 + ISDN = 20 + RT = 21 + NSAP = 22 + NSAP_PTR = 23 + SIG = 24 + KEY = 25 + PX = 26 + GPOS = 27 + AAAA = 28 + LOC = 29 + NXT = 30 + SRV = 33 + NAPTR = 35 + KX = 36 + CERT = 37 + A6 = 38 + DNAME = 39 + OPT = 41 + APL = 42 + DS = 43 + SSHFP = 44 + IPSECKEY = 45 + RRSIG = 46 + NSEC = 47 + DNSKEY = 48 + DHCID = 49 + NSEC3 = 50 + NSEC3PARAM = 51 + TLSA = 52 + SMIMEA = 53 + HIP = 55 + NINFO = 56 + CDS = 59 + CDNSKEY = 60 + OPENPGPKEY = 61 + CSYNC = 62 + SVCB = 64 + HTTPS = 65 + SPF = 99 + UNSPEC = 103 + EUI48 = 108 + EUI64 = 109 + TKEY = 249 + TSIG = 250 + IXFR = 251 + AXFR = 252 + MAILB = 253 + MAILA = 254 + ANY = 255 + URI = 256 + CAA = 257 + AVC = 258 + AMTRELAY = 259 + TA = 32768 + DLV = 32769 + + @classmethod + def _maximum(cls): + return 65535 + + @classmethod + def _short_name(cls): + return "type" + + @classmethod + def _prefix(cls): + return "TYPE" + + @classmethod + def _unknown_exception_class(cls): + return UnknownRdatatype + +_registered_by_text = {} +_registered_by_value = {} + +_metatypes = {RdataType.OPT} + +_singletons = {RdataType.SOA, RdataType.NXT, RdataType.DNAME, + RdataType.NSEC, RdataType.CNAME} + + +class UnknownRdatatype(dns.exception.DNSException): + """DNS resource record type is unknown.""" + + +def from_text(text): + """Convert text into a DNS rdata type value. + + The input text can be a defined DNS RR type mnemonic or + instance of the DNS generic type syntax. + + For example, "NS" and "TYPE2" will both result in a value of 2. + + Raises ``dns.rdatatype.UnknownRdatatype`` if the type is unknown. + + Raises ``ValueError`` if the rdata type value is not >= 0 and <= 65535. + + Returns an ``int``. + """ + + text = text.upper().replace('-', '_') + try: + return RdataType.from_text(text) + except UnknownRdatatype: + registered_type = _registered_by_text.get(text) + if registered_type: + return registered_type + raise + + +def to_text(value): + """Convert a DNS rdata type value to text. + + If the value has a known mnemonic, it will be used, otherwise the + DNS generic type syntax will be used. + + Raises ``ValueError`` if the rdata type value is not >= 0 and <= 65535. + + Returns a ``str``. + """ + + text = RdataType.to_text(value) + if text.startswith("TYPE"): + registered_text = _registered_by_value.get(value) + if registered_text: + text = registered_text + return text.replace('_', '-') + + +def is_metatype(rdtype): + """True if the specified type is a metatype. + + *rdtype* is an ``int``. + + The currently defined metatypes are TKEY, TSIG, IXFR, AXFR, MAILA, + MAILB, ANY, and OPT. + + Returns a ``bool``. + """ + + return (256 > rdtype >= 128) or rdtype in _metatypes + + +def is_singleton(rdtype): + """Is the specified type a singleton type? + + Singleton types can only have a single rdata in an rdataset, or a single + RR in an RRset. + + The currently defined singleton types are CNAME, DNAME, NSEC, NXT, and + SOA. + + *rdtype* is an ``int``. + + Returns a ``bool``. + """ + + if rdtype in _singletons: + return True + return False + +# pylint: disable=redefined-outer-name +def register_type(rdtype, rdtype_text, is_singleton=False): + """Dynamically register an rdatatype. + + *rdtype*, an ``int``, the rdatatype to register. + + *rdtype_text*, a ``str``, the textual form of the rdatatype. + + *is_singleton*, a ``bool``, indicating if the type is a singleton (i.e. + RRsets of the type can have only one member.) + """ + + _registered_by_text[rdtype_text] = rdtype + _registered_by_value[rdtype] = rdtype_text + if is_singleton: + _singletons.add(rdtype) + +### BEGIN generated RdataType constants + +TYPE0 = RdataType.TYPE0 +NONE = RdataType.NONE +A = RdataType.A +NS = RdataType.NS +MD = RdataType.MD +MF = RdataType.MF +CNAME = RdataType.CNAME +SOA = RdataType.SOA +MB = RdataType.MB +MG = RdataType.MG +MR = RdataType.MR +NULL = RdataType.NULL +WKS = RdataType.WKS +PTR = RdataType.PTR +HINFO = RdataType.HINFO +MINFO = RdataType.MINFO +MX = RdataType.MX +TXT = RdataType.TXT +RP = RdataType.RP +AFSDB = RdataType.AFSDB +X25 = RdataType.X25 +ISDN = RdataType.ISDN +RT = RdataType.RT +NSAP = RdataType.NSAP +NSAP_PTR = RdataType.NSAP_PTR +SIG = RdataType.SIG +KEY = RdataType.KEY +PX = RdataType.PX +GPOS = RdataType.GPOS +AAAA = RdataType.AAAA +LOC = RdataType.LOC +NXT = RdataType.NXT +SRV = RdataType.SRV +NAPTR = RdataType.NAPTR +KX = RdataType.KX +CERT = RdataType.CERT +A6 = RdataType.A6 +DNAME = RdataType.DNAME +OPT = RdataType.OPT +APL = RdataType.APL +DS = RdataType.DS +SSHFP = RdataType.SSHFP +IPSECKEY = RdataType.IPSECKEY +RRSIG = RdataType.RRSIG +NSEC = RdataType.NSEC +DNSKEY = RdataType.DNSKEY +DHCID = RdataType.DHCID +NSEC3 = RdataType.NSEC3 +NSEC3PARAM = RdataType.NSEC3PARAM +TLSA = RdataType.TLSA +SMIMEA = RdataType.SMIMEA +HIP = RdataType.HIP +NINFO = RdataType.NINFO +CDS = RdataType.CDS +CDNSKEY = RdataType.CDNSKEY +OPENPGPKEY = RdataType.OPENPGPKEY +CSYNC = RdataType.CSYNC +SVCB = RdataType.SVCB +HTTPS = RdataType.HTTPS +SPF = RdataType.SPF +UNSPEC = RdataType.UNSPEC +EUI48 = RdataType.EUI48 +EUI64 = RdataType.EUI64 +TKEY = RdataType.TKEY +TSIG = RdataType.TSIG +IXFR = RdataType.IXFR +AXFR = RdataType.AXFR +MAILB = RdataType.MAILB +MAILA = RdataType.MAILA +ANY = RdataType.ANY +URI = RdataType.URI +CAA = RdataType.CAA +AVC = RdataType.AVC +AMTRELAY = RdataType.AMTRELAY +TA = RdataType.TA +DLV = RdataType.DLV + +### END generated RdataType constants diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/AFSDB.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/AFSDB.py new file mode 100644 index 0000000..d7838e7 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/AFSDB.py @@ -0,0 +1,46 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.mxbase +import dns.immutable + + +@dns.immutable.immutable +class AFSDB(dns.rdtypes.mxbase.UncompressedDowncasingMX): + + """AFSDB record""" + + # Use the property mechanism to make "subtype" an alias for the + # "preference" attribute, and "hostname" an alias for the "exchange" + # attribute. + # + # This lets us inherit the UncompressedMX implementation but lets + # the caller use appropriate attribute names for the rdata type. + # + # We probably lose some performance vs. a cut-and-paste + # implementation, but this way we don't copy code, and that's + # good. + + @property + def subtype(self): + "the AFSDB subtype" + return self.preference + + @property + def hostname(self): + "the AFSDB hostname" + return self.exchange diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/AMTRELAY.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/AMTRELAY.py new file mode 100644 index 0000000..9f093de --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/AMTRELAY.py @@ -0,0 +1,86 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdtypes.util + + +class Relay(dns.rdtypes.util.Gateway): + name = 'AMTRELAY relay' + + @property + def relay(self): + return self.gateway + + +@dns.immutable.immutable +class AMTRELAY(dns.rdata.Rdata): + + """AMTRELAY record""" + + # see: RFC 8777 + + __slots__ = ['precedence', 'discovery_optional', 'relay_type', 'relay'] + + def __init__(self, rdclass, rdtype, precedence, discovery_optional, + relay_type, relay): + super().__init__(rdclass, rdtype) + relay = Relay(relay_type, relay) + self.precedence = self._as_uint8(precedence) + self.discovery_optional = self._as_bool(discovery_optional) + self.relay_type = relay.type + self.relay = relay.relay + + def to_text(self, origin=None, relativize=True, **kw): + relay = Relay(self.relay_type, self.relay).to_text(origin, relativize) + return '%d %d %d %s' % (self.precedence, self.discovery_optional, + self.relay_type, relay) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + precedence = tok.get_uint8() + discovery_optional = tok.get_uint8() + if discovery_optional > 1: + raise dns.exception.SyntaxError('expecting 0 or 1') + discovery_optional = bool(discovery_optional) + relay_type = tok.get_uint8() + if relay_type > 0x7f: + raise dns.exception.SyntaxError('expecting an integer <= 127') + relay = Relay.from_text(relay_type, tok, origin, relativize, + relativize_to) + return cls(rdclass, rdtype, precedence, discovery_optional, relay_type, + relay.relay) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + relay_type = self.relay_type | (self.discovery_optional << 7) + header = struct.pack("!BB", self.precedence, relay_type) + file.write(header) + Relay(self.relay_type, self.relay).to_wire(file, compress, origin, + canonicalize) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + (precedence, relay_type) = parser.get_struct('!BB') + discovery_optional = bool(relay_type >> 7) + relay_type &= 0x7f + relay = Relay.from_wire_parser(relay_type, parser, origin) + return cls(rdclass, rdtype, precedence, discovery_optional, relay_type, + relay.relay) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/AVC.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/AVC.py new file mode 100644 index 0000000..11e026d --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/AVC.py @@ -0,0 +1,27 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2016 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.txtbase +import dns.immutable + + +@dns.immutable.immutable +class AVC(dns.rdtypes.txtbase.TXTBase): + + """AVC record""" + + # See: IANA dns parameters for AVC diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/CAA.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/CAA.py new file mode 100644 index 0000000..c86b45e --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/CAA.py @@ -0,0 +1,69 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.tokenizer + + +@dns.immutable.immutable +class CAA(dns.rdata.Rdata): + + """CAA (Certification Authority Authorization) record""" + + # see: RFC 6844 + + __slots__ = ['flags', 'tag', 'value'] + + def __init__(self, rdclass, rdtype, flags, tag, value): + super().__init__(rdclass, rdtype) + self.flags = self._as_uint8(flags) + self.tag = self._as_bytes(tag, True, 255) + if not tag.isalnum(): + raise ValueError("tag is not alphanumeric") + self.value = self._as_bytes(value) + + def to_text(self, origin=None, relativize=True, **kw): + return '%u %s "%s"' % (self.flags, + dns.rdata._escapify(self.tag), + dns.rdata._escapify(self.value)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + flags = tok.get_uint8() + tag = tok.get_string().encode() + value = tok.get_string().encode() + return cls(rdclass, rdtype, flags, tag, value) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(struct.pack('!B', self.flags)) + l = len(self.tag) + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(self.tag) + file.write(self.value) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + flags = parser.get_uint8() + tag = parser.get_counted_bytes() + value = parser.get_remaining() + return cls(rdclass, rdtype, flags, tag, value) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/CDNSKEY.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/CDNSKEY.py new file mode 100644 index 0000000..14b1941 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/CDNSKEY.py @@ -0,0 +1,28 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.dnskeybase +import dns.immutable + +# pylint: disable=unused-import +from dns.rdtypes.dnskeybase import SEP, REVOKE, ZONE # noqa: F401 +# pylint: enable=unused-import + +@dns.immutable.immutable +class CDNSKEY(dns.rdtypes.dnskeybase.DNSKEYBase): + + """CDNSKEY record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/CDS.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/CDS.py new file mode 100644 index 0000000..39e3556 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/CDS.py @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.dsbase +import dns.immutable + + +@dns.immutable.immutable +class CDS(dns.rdtypes.dsbase.DSBase): + + """CDS record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/CERT.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/CERT.py new file mode 100644 index 0000000..5f26dde --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/CERT.py @@ -0,0 +1,103 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct +import base64 + +import dns.exception +import dns.immutable +import dns.dnssec +import dns.rdata +import dns.tokenizer + +_ctype_by_value = { + 1: 'PKIX', + 2: 'SPKI', + 3: 'PGP', + 253: 'URI', + 254: 'OID', +} + +_ctype_by_name = { + 'PKIX': 1, + 'SPKI': 2, + 'PGP': 3, + 'URI': 253, + 'OID': 254, +} + + +def _ctype_from_text(what): + v = _ctype_by_name.get(what) + if v is not None: + return v + return int(what) + + +def _ctype_to_text(what): + v = _ctype_by_value.get(what) + if v is not None: + return v + return str(what) + + +@dns.immutable.immutable +class CERT(dns.rdata.Rdata): + + """CERT record""" + + # see RFC 2538 + + __slots__ = ['certificate_type', 'key_tag', 'algorithm', 'certificate'] + + def __init__(self, rdclass, rdtype, certificate_type, key_tag, algorithm, + certificate): + super().__init__(rdclass, rdtype) + self.certificate_type = self._as_uint16(certificate_type) + self.key_tag = self._as_uint16(key_tag) + self.algorithm = self._as_uint8(algorithm) + self.certificate = self._as_bytes(certificate) + + def to_text(self, origin=None, relativize=True, **kw): + certificate_type = _ctype_to_text(self.certificate_type) + return "%s %d %s %s" % (certificate_type, self.key_tag, + dns.dnssec.algorithm_to_text(self.algorithm), + dns.rdata._base64ify(self.certificate, **kw)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + certificate_type = _ctype_from_text(tok.get_string()) + key_tag = tok.get_uint16() + algorithm = dns.dnssec.algorithm_from_text(tok.get_string()) + b64 = tok.concatenate_remaining_identifiers().encode() + certificate = base64.b64decode(b64) + return cls(rdclass, rdtype, certificate_type, key_tag, + algorithm, certificate) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + prefix = struct.pack("!HHB", self.certificate_type, self.key_tag, + self.algorithm) + file.write(prefix) + file.write(self.certificate) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + (certificate_type, key_tag, algorithm) = parser.get_struct("!HHB") + certificate = parser.get_remaining() + return cls(rdclass, rdtype, certificate_type, key_tag, algorithm, + certificate) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/CNAME.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/CNAME.py new file mode 100644 index 0000000..a4fcfa8 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/CNAME.py @@ -0,0 +1,29 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.nsbase +import dns.immutable + + +@dns.immutable.immutable +class CNAME(dns.rdtypes.nsbase.NSBase): + + """CNAME record + + Note: although CNAME is officially a singleton type, dnspython allows + non-singleton CNAME rdatasets because such sets have been commonly + used by BIND and other nameservers for load balancing.""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/CSYNC.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/CSYNC.py new file mode 100644 index 0000000..979028a --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/CSYNC.py @@ -0,0 +1,68 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2004-2007, 2009-2011, 2016 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.rdatatype +import dns.name +import dns.rdtypes.util + + +@dns.immutable.immutable +class Bitmap(dns.rdtypes.util.Bitmap): + type_name = 'CSYNC' + + +@dns.immutable.immutable +class CSYNC(dns.rdata.Rdata): + + """CSYNC record""" + + __slots__ = ['serial', 'flags', 'windows'] + + def __init__(self, rdclass, rdtype, serial, flags, windows): + super().__init__(rdclass, rdtype) + self.serial = self._as_uint32(serial) + self.flags = self._as_uint16(flags) + if not isinstance(windows, Bitmap): + windows = Bitmap(windows) + self.windows = tuple(windows.windows) + + def to_text(self, origin=None, relativize=True, **kw): + text = Bitmap(self.windows).to_text() + return '%d %d%s' % (self.serial, self.flags, text) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + serial = tok.get_uint32() + flags = tok.get_uint16() + bitmap = Bitmap.from_text(tok) + return cls(rdclass, rdtype, serial, flags, bitmap) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(struct.pack('!IH', self.serial, self.flags)) + Bitmap(self.windows).to_wire(file) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + (serial, flags) = parser.get_struct("!IH") + bitmap = Bitmap.from_wire_parser(parser) + return cls(rdclass, rdtype, serial, flags, bitmap) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/DLV.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/DLV.py new file mode 100644 index 0000000..947dc42 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/DLV.py @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.dsbase +import dns.immutable + + +@dns.immutable.immutable +class DLV(dns.rdtypes.dsbase.DSBase): + + """DLV record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/DNAME.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/DNAME.py new file mode 100644 index 0000000..f4984b5 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/DNAME.py @@ -0,0 +1,28 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.nsbase +import dns.immutable + + +@dns.immutable.immutable +class DNAME(dns.rdtypes.nsbase.UncompressedNS): + + """DNAME record""" + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.target.to_wire(file, None, origin, canonicalize) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/DNSKEY.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/DNSKEY.py new file mode 100644 index 0000000..e69a7c1 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/DNSKEY.py @@ -0,0 +1,28 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.dnskeybase +import dns.immutable + +# pylint: disable=unused-import +from dns.rdtypes.dnskeybase import SEP, REVOKE, ZONE # noqa: F401 +# pylint: enable=unused-import + +@dns.immutable.immutable +class DNSKEY(dns.rdtypes.dnskeybase.DNSKEYBase): + + """DNSKEY record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/DS.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/DS.py new file mode 100644 index 0000000..3f6c3ee --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/DS.py @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.dsbase +import dns.immutable + + +@dns.immutable.immutable +class DS(dns.rdtypes.dsbase.DSBase): + + """DS record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/EUI48.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/EUI48.py new file mode 100644 index 0000000..0ab88ad --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/EUI48.py @@ -0,0 +1,31 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2015 Red Hat, Inc. +# Author: Petr Spacek +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.euibase +import dns.immutable + + +@dns.immutable.immutable +class EUI48(dns.rdtypes.euibase.EUIBase): + + """EUI48 record""" + + # see: rfc7043.txt + + byte_len = 6 # 0123456789ab (in hex) + text_len = byte_len * 3 - 1 # 01-23-45-67-89-ab diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/EUI64.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/EUI64.py new file mode 100644 index 0000000..c42957e --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/EUI64.py @@ -0,0 +1,31 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2015 Red Hat, Inc. +# Author: Petr Spacek +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.euibase +import dns.immutable + + +@dns.immutable.immutable +class EUI64(dns.rdtypes.euibase.EUIBase): + + """EUI64 record""" + + # see: rfc7043.txt + + byte_len = 8 # 0123456789abcdef (in hex) + text_len = byte_len * 3 - 1 # 01-23-45-67-89-ab-cd-ef diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/GPOS.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/GPOS.py new file mode 100644 index 0000000..29fa8f8 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/GPOS.py @@ -0,0 +1,128 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.tokenizer + + +def _validate_float_string(what): + if len(what) == 0: + raise dns.exception.FormError + if what[0] == b'-'[0] or what[0] == b'+'[0]: + what = what[1:] + if what.isdigit(): + return + try: + (left, right) = what.split(b'.') + except ValueError: + raise dns.exception.FormError + if left == b'' and right == b'': + raise dns.exception.FormError + if not left == b'' and not left.decode().isdigit(): + raise dns.exception.FormError + if not right == b'' and not right.decode().isdigit(): + raise dns.exception.FormError + + +@dns.immutable.immutable +class GPOS(dns.rdata.Rdata): + + """GPOS record""" + + # see: RFC 1712 + + __slots__ = ['latitude', 'longitude', 'altitude'] + + def __init__(self, rdclass, rdtype, latitude, longitude, altitude): + super().__init__(rdclass, rdtype) + if isinstance(latitude, float) or \ + isinstance(latitude, int): + latitude = str(latitude) + if isinstance(longitude, float) or \ + isinstance(longitude, int): + longitude = str(longitude) + if isinstance(altitude, float) or \ + isinstance(altitude, int): + altitude = str(altitude) + latitude = self._as_bytes(latitude, True, 255) + longitude = self._as_bytes(longitude, True, 255) + altitude = self._as_bytes(altitude, True, 255) + _validate_float_string(latitude) + _validate_float_string(longitude) + _validate_float_string(altitude) + self.latitude = latitude + self.longitude = longitude + self.altitude = altitude + flat = self.float_latitude + if flat < -90.0 or flat > 90.0: + raise dns.exception.FormError('bad latitude') + flong = self.float_longitude + if flong < -180.0 or flong > 180.0: + raise dns.exception.FormError('bad longitude') + + def to_text(self, origin=None, relativize=True, **kw): + return '{} {} {}'.format(self.latitude.decode(), + self.longitude.decode(), + self.altitude.decode()) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + latitude = tok.get_string() + longitude = tok.get_string() + altitude = tok.get_string() + return cls(rdclass, rdtype, latitude, longitude, altitude) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + l = len(self.latitude) + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(self.latitude) + l = len(self.longitude) + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(self.longitude) + l = len(self.altitude) + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(self.altitude) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + latitude = parser.get_counted_bytes() + longitude = parser.get_counted_bytes() + altitude = parser.get_counted_bytes() + return cls(rdclass, rdtype, latitude, longitude, altitude) + + @property + def float_latitude(self): + "latitude as a floating point value" + return float(self.latitude) + + @property + def float_longitude(self): + "longitude as a floating point value" + return float(self.longitude) + + @property + def float_altitude(self): + "altitude as a floating point value" + return float(self.altitude) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/HINFO.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/HINFO.py new file mode 100644 index 0000000..cd04969 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/HINFO.py @@ -0,0 +1,65 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.tokenizer + + +@dns.immutable.immutable +class HINFO(dns.rdata.Rdata): + + """HINFO record""" + + # see: RFC 1035 + + __slots__ = ['cpu', 'os'] + + def __init__(self, rdclass, rdtype, cpu, os): + super().__init__(rdclass, rdtype) + self.cpu = self._as_bytes(cpu, True, 255) + self.os = self._as_bytes(os, True, 255) + + def to_text(self, origin=None, relativize=True, **kw): + return '"{}" "{}"'.format(dns.rdata._escapify(self.cpu), + dns.rdata._escapify(self.os)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + cpu = tok.get_string(max_length=255) + os = tok.get_string(max_length=255) + return cls(rdclass, rdtype, cpu, os) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + l = len(self.cpu) + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(self.cpu) + l = len(self.os) + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(self.os) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + cpu = parser.get_counted_bytes() + os = parser.get_counted_bytes() + return cls(rdclass, rdtype, cpu, os) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/HIP.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/HIP.py new file mode 100644 index 0000000..e887359 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/HIP.py @@ -0,0 +1,85 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2010, 2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct +import base64 +import binascii + +import dns.exception +import dns.immutable +import dns.rdata +import dns.rdatatype + + +@dns.immutable.immutable +class HIP(dns.rdata.Rdata): + + """HIP record""" + + # see: RFC 5205 + + __slots__ = ['hit', 'algorithm', 'key', 'servers'] + + def __init__(self, rdclass, rdtype, hit, algorithm, key, servers): + super().__init__(rdclass, rdtype) + self.hit = self._as_bytes(hit, True, 255) + self.algorithm = self._as_uint8(algorithm) + self.key = self._as_bytes(key, True) + self.servers = self._as_tuple(servers, self._as_name) + + def to_text(self, origin=None, relativize=True, **kw): + hit = binascii.hexlify(self.hit).decode() + key = base64.b64encode(self.key).replace(b'\n', b'').decode() + text = '' + servers = [] + for server in self.servers: + servers.append(server.choose_relativity(origin, relativize)) + if len(servers) > 0: + text += (' ' + ' '.join((x.to_unicode() for x in servers))) + return '%u %s %s%s' % (self.algorithm, hit, key, text) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + algorithm = tok.get_uint8() + hit = binascii.unhexlify(tok.get_string().encode()) + key = base64.b64decode(tok.get_string().encode()) + servers = [] + for token in tok.get_remaining(): + server = tok.as_name(token, origin, relativize, relativize_to) + servers.append(server) + return cls(rdclass, rdtype, hit, algorithm, key, servers) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + lh = len(self.hit) + lk = len(self.key) + file.write(struct.pack("!BBH", lh, self.algorithm, lk)) + file.write(self.hit) + file.write(self.key) + for server in self.servers: + server.to_wire(file, None, origin, False) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + (lh, algorithm, lk) = parser.get_struct('!BBH') + hit = parser.get_bytes(lh) + key = parser.get_bytes(lk) + servers = [] + while parser.remaining() > 0: + server = parser.get_name(origin) + servers.append(server) + return cls(rdclass, rdtype, hit, algorithm, key, servers) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/ISDN.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/ISDN.py new file mode 100644 index 0000000..b9a49ad --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/ISDN.py @@ -0,0 +1,76 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.tokenizer + + +@dns.immutable.immutable +class ISDN(dns.rdata.Rdata): + + """ISDN record""" + + # see: RFC 1183 + + __slots__ = ['address', 'subaddress'] + + def __init__(self, rdclass, rdtype, address, subaddress): + super().__init__(rdclass, rdtype) + self.address = self._as_bytes(address, True, 255) + self.subaddress = self._as_bytes(subaddress, True, 255) + + def to_text(self, origin=None, relativize=True, **kw): + if self.subaddress: + return '"{}" "{}"'.format(dns.rdata._escapify(self.address), + dns.rdata._escapify(self.subaddress)) + else: + return '"%s"' % dns.rdata._escapify(self.address) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + address = tok.get_string() + tokens = tok.get_remaining(max_tokens=1) + if len(tokens) >= 1: + subaddress = tokens[0].unescape().value + else: + subaddress = '' + return cls(rdclass, rdtype, address, subaddress) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + l = len(self.address) + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(self.address) + l = len(self.subaddress) + if l > 0: + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(self.subaddress) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + address = parser.get_counted_bytes() + if parser.remaining() > 0: + subaddress = parser.get_counted_bytes() + else: + subaddress = b'' + return cls(rdclass, rdtype, address, subaddress) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/LOC.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/LOC.py new file mode 100644 index 0000000..1a4ee2b --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/LOC.py @@ -0,0 +1,326 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata + + +_pows = tuple(10**i for i in range(0, 11)) + +# default values are in centimeters +_default_size = 100.0 +_default_hprec = 1000000.0 +_default_vprec = 1000.0 + +# for use by from_wire() +_MAX_LATITUDE = 0x80000000 + 90 * 3600000 +_MIN_LATITUDE = 0x80000000 - 90 * 3600000 +_MAX_LONGITUDE = 0x80000000 + 180 * 3600000 +_MIN_LONGITUDE = 0x80000000 - 180 * 3600000 + + +def _exponent_of(what, desc): + if what == 0: + return 0 + exp = None + for (i, pow) in enumerate(_pows): + if what < pow: + exp = i - 1 + break + if exp is None or exp < 0: + raise dns.exception.SyntaxError("%s value out of bounds" % desc) + return exp + + +def _float_to_tuple(what): + if what < 0: + sign = -1 + what *= -1 + else: + sign = 1 + what = round(what * 3600000) # pylint: disable=round-builtin + degrees = int(what // 3600000) + what -= degrees * 3600000 + minutes = int(what // 60000) + what -= minutes * 60000 + seconds = int(what // 1000) + what -= int(seconds * 1000) + what = int(what) + return (degrees, minutes, seconds, what, sign) + + +def _tuple_to_float(what): + value = float(what[0]) + value += float(what[1]) / 60.0 + value += float(what[2]) / 3600.0 + value += float(what[3]) / 3600000.0 + return float(what[4]) * value + + +def _encode_size(what, desc): + what = int(what) + exponent = _exponent_of(what, desc) & 0xF + base = what // pow(10, exponent) & 0xF + return base * 16 + exponent + + +def _decode_size(what, desc): + exponent = what & 0x0F + if exponent > 9: + raise dns.exception.FormError("bad %s exponent" % desc) + base = (what & 0xF0) >> 4 + if base > 9: + raise dns.exception.FormError("bad %s base" % desc) + return base * pow(10, exponent) + + +def _check_coordinate_list(value, low, high): + if value[0] < low or value[0] > high: + raise ValueError(f'not in range [{low}, {high}]') + if value[1] < 0 or value[1] > 59: + raise ValueError('bad minutes value') + if value[2] < 0 or value[2] > 59: + raise ValueError('bad seconds value') + if value[3] < 0 or value[3] > 999: + raise ValueError('bad milliseconds value') + if value[4] != 1 and value[4] != -1: + raise ValueError('bad hemisphere value') + + +@dns.immutable.immutable +class LOC(dns.rdata.Rdata): + + """LOC record""" + + # see: RFC 1876 + + __slots__ = ['latitude', 'longitude', 'altitude', 'size', + 'horizontal_precision', 'vertical_precision'] + + def __init__(self, rdclass, rdtype, latitude, longitude, altitude, + size=_default_size, hprec=_default_hprec, + vprec=_default_vprec): + """Initialize a LOC record instance. + + The parameters I{latitude} and I{longitude} may be either a 4-tuple + of integers specifying (degrees, minutes, seconds, milliseconds), + or they may be floating point values specifying the number of + degrees. The other parameters are floats. Size, horizontal precision, + and vertical precision are specified in centimeters.""" + + super().__init__(rdclass, rdtype) + if isinstance(latitude, int): + latitude = float(latitude) + if isinstance(latitude, float): + latitude = _float_to_tuple(latitude) + _check_coordinate_list(latitude, -90, 90) + self.latitude = tuple(latitude) + if isinstance(longitude, int): + longitude = float(longitude) + if isinstance(longitude, float): + longitude = _float_to_tuple(longitude) + _check_coordinate_list(longitude, -180, 180) + self.longitude = tuple(longitude) + self.altitude = float(altitude) + self.size = float(size) + self.horizontal_precision = float(hprec) + self.vertical_precision = float(vprec) + + def to_text(self, origin=None, relativize=True, **kw): + if self.latitude[4] > 0: + lat_hemisphere = 'N' + else: + lat_hemisphere = 'S' + if self.longitude[4] > 0: + long_hemisphere = 'E' + else: + long_hemisphere = 'W' + text = "%d %d %d.%03d %s %d %d %d.%03d %s %0.2fm" % ( + self.latitude[0], self.latitude[1], + self.latitude[2], self.latitude[3], lat_hemisphere, + self.longitude[0], self.longitude[1], self.longitude[2], + self.longitude[3], long_hemisphere, + self.altitude / 100.0 + ) + + # do not print default values + if self.size != _default_size or \ + self.horizontal_precision != _default_hprec or \ + self.vertical_precision != _default_vprec: + text += " {:0.2f}m {:0.2f}m {:0.2f}m".format( + self.size / 100.0, self.horizontal_precision / 100.0, + self.vertical_precision / 100.0 + ) + return text + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + latitude = [0, 0, 0, 0, 1] + longitude = [0, 0, 0, 0, 1] + size = _default_size + hprec = _default_hprec + vprec = _default_vprec + + latitude[0] = tok.get_int() + t = tok.get_string() + if t.isdigit(): + latitude[1] = int(t) + t = tok.get_string() + if '.' in t: + (seconds, milliseconds) = t.split('.') + if not seconds.isdigit(): + raise dns.exception.SyntaxError( + 'bad latitude seconds value') + latitude[2] = int(seconds) + l = len(milliseconds) + if l == 0 or l > 3 or not milliseconds.isdigit(): + raise dns.exception.SyntaxError( + 'bad latitude milliseconds value') + if l == 1: + m = 100 + elif l == 2: + m = 10 + else: + m = 1 + latitude[3] = m * int(milliseconds) + t = tok.get_string() + elif t.isdigit(): + latitude[2] = int(t) + t = tok.get_string() + if t == 'S': + latitude[4] = -1 + elif t != 'N': + raise dns.exception.SyntaxError('bad latitude hemisphere value') + + longitude[0] = tok.get_int() + t = tok.get_string() + if t.isdigit(): + longitude[1] = int(t) + t = tok.get_string() + if '.' in t: + (seconds, milliseconds) = t.split('.') + if not seconds.isdigit(): + raise dns.exception.SyntaxError( + 'bad longitude seconds value') + longitude[2] = int(seconds) + l = len(milliseconds) + if l == 0 or l > 3 or not milliseconds.isdigit(): + raise dns.exception.SyntaxError( + 'bad longitude milliseconds value') + if l == 1: + m = 100 + elif l == 2: + m = 10 + else: + m = 1 + longitude[3] = m * int(milliseconds) + t = tok.get_string() + elif t.isdigit(): + longitude[2] = int(t) + t = tok.get_string() + if t == 'W': + longitude[4] = -1 + elif t != 'E': + raise dns.exception.SyntaxError('bad longitude hemisphere value') + + t = tok.get_string() + if t[-1] == 'm': + t = t[0: -1] + altitude = float(t) * 100.0 # m -> cm + + tokens = tok.get_remaining(max_tokens=3) + if len(tokens) >= 1: + value = tokens[0].unescape().value + if value[-1] == 'm': + value = value[0: -1] + size = float(value) * 100.0 # m -> cm + if len(tokens) >= 2: + value = tokens[1].unescape().value + if value[-1] == 'm': + value = value[0: -1] + hprec = float(value) * 100.0 # m -> cm + if len(tokens) >= 3: + value = tokens[2].unescape().value + if value[-1] == 'm': + value = value[0: -1] + vprec = float(value) * 100.0 # m -> cm + + # Try encoding these now so we raise if they are bad + _encode_size(size, "size") + _encode_size(hprec, "horizontal precision") + _encode_size(vprec, "vertical precision") + + return cls(rdclass, rdtype, latitude, longitude, altitude, + size, hprec, vprec) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + milliseconds = (self.latitude[0] * 3600000 + + self.latitude[1] * 60000 + + self.latitude[2] * 1000 + + self.latitude[3]) * self.latitude[4] + latitude = 0x80000000 + milliseconds + milliseconds = (self.longitude[0] * 3600000 + + self.longitude[1] * 60000 + + self.longitude[2] * 1000 + + self.longitude[3]) * self.longitude[4] + longitude = 0x80000000 + milliseconds + altitude = int(self.altitude) + 10000000 + size = _encode_size(self.size, "size") + hprec = _encode_size(self.horizontal_precision, "horizontal precision") + vprec = _encode_size(self.vertical_precision, "vertical precision") + wire = struct.pack("!BBBBIII", 0, size, hprec, vprec, latitude, + longitude, altitude) + file.write(wire) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + (version, size, hprec, vprec, latitude, longitude, altitude) = \ + parser.get_struct("!BBBBIII") + if version != 0: + raise dns.exception.FormError("LOC version not zero") + if latitude < _MIN_LATITUDE or latitude > _MAX_LATITUDE: + raise dns.exception.FormError("bad latitude") + if latitude > 0x80000000: + latitude = (latitude - 0x80000000) / 3600000 + else: + latitude = -1 * (0x80000000 - latitude) / 3600000 + if longitude < _MIN_LONGITUDE or longitude > _MAX_LONGITUDE: + raise dns.exception.FormError("bad longitude") + if longitude > 0x80000000: + longitude = (longitude - 0x80000000) / 3600000 + else: + longitude = -1 * (0x80000000 - longitude) / 3600000 + altitude = float(altitude) - 10000000.0 + size = _decode_size(size, "size") + hprec = _decode_size(hprec, "horizontal precision") + vprec = _decode_size(vprec, "vertical precision") + return cls(rdclass, rdtype, latitude, longitude, altitude, + size, hprec, vprec) + + @property + def float_latitude(self): + "latitude as a floating point value" + return _tuple_to_float(self.latitude) + + @property + def float_longitude(self): + "longitude as a floating point value" + return _tuple_to_float(self.longitude) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/MX.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/MX.py new file mode 100644 index 0000000..a697ea4 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/MX.py @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.mxbase +import dns.immutable + + +@dns.immutable.immutable +class MX(dns.rdtypes.mxbase.MXBase): + + """MX record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/NINFO.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/NINFO.py new file mode 100644 index 0000000..d53e967 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/NINFO.py @@ -0,0 +1,27 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.txtbase +import dns.immutable + + +@dns.immutable.immutable +class NINFO(dns.rdtypes.txtbase.TXTBase): + + """NINFO record""" + + # see: draft-reid-dnsext-zs-01 diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/NS.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/NS.py new file mode 100644 index 0000000..a0cc232 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/NS.py @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.nsbase +import dns.immutable + + +@dns.immutable.immutable +class NS(dns.rdtypes.nsbase.NSBase): + + """NS record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/NSEC.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/NSEC.py new file mode 100644 index 0000000..dc31f4c --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/NSEC.py @@ -0,0 +1,67 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.exception +import dns.immutable +import dns.rdata +import dns.rdatatype +import dns.name +import dns.rdtypes.util + + +@dns.immutable.immutable +class Bitmap(dns.rdtypes.util.Bitmap): + type_name = 'NSEC' + + +@dns.immutable.immutable +class NSEC(dns.rdata.Rdata): + + """NSEC record""" + + __slots__ = ['next', 'windows'] + + def __init__(self, rdclass, rdtype, next, windows): + super().__init__(rdclass, rdtype) + self.next = self._as_name(next) + if not isinstance(windows, Bitmap): + windows = Bitmap(windows) + self.windows = tuple(windows.windows) + + def to_text(self, origin=None, relativize=True, **kw): + next = self.next.choose_relativity(origin, relativize) + text = Bitmap(self.windows).to_text() + return '{}{}'.format(next, text) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + next = tok.get_name(origin, relativize, relativize_to) + windows = Bitmap.from_text(tok) + return cls(rdclass, rdtype, next, windows) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + # Note that NSEC downcasing, originally mandated by RFC 4034 + # section 6.2 was removed by RFC 6840 section 5.1. + self.next.to_wire(file, None, origin, False) + Bitmap(self.windows).to_wire(file) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + next = parser.get_name(origin) + bitmap = Bitmap.from_wire_parser(parser) + return cls(rdclass, rdtype, next, bitmap) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/NSEC3.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/NSEC3.py new file mode 100644 index 0000000..14242bd --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/NSEC3.py @@ -0,0 +1,111 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2004-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import base64 +import binascii +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.rdatatype +import dns.rdtypes.util + + +b32_hex_to_normal = bytes.maketrans(b'0123456789ABCDEFGHIJKLMNOPQRSTUV', + b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567') +b32_normal_to_hex = bytes.maketrans(b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', + b'0123456789ABCDEFGHIJKLMNOPQRSTUV') + +# hash algorithm constants +SHA1 = 1 + +# flag constants +OPTOUT = 1 + + +@dns.immutable.immutable +class Bitmap(dns.rdtypes.util.Bitmap): + type_name = 'NSEC3' + + +@dns.immutable.immutable +class NSEC3(dns.rdata.Rdata): + + """NSEC3 record""" + + __slots__ = ['algorithm', 'flags', 'iterations', 'salt', 'next', 'windows'] + + def __init__(self, rdclass, rdtype, algorithm, flags, iterations, salt, + next, windows): + super().__init__(rdclass, rdtype) + self.algorithm = self._as_uint8(algorithm) + self.flags = self._as_uint8(flags) + self.iterations = self._as_uint16(iterations) + self.salt = self._as_bytes(salt, True, 255) + self.next = self._as_bytes(next, True, 255) + if not isinstance(windows, Bitmap): + windows = Bitmap(windows) + self.windows = tuple(windows.windows) + + def to_text(self, origin=None, relativize=True, **kw): + next = base64.b32encode(self.next).translate( + b32_normal_to_hex).lower().decode() + if self.salt == b'': + salt = '-' + else: + salt = binascii.hexlify(self.salt).decode() + text = Bitmap(self.windows).to_text() + return '%u %u %u %s %s%s' % (self.algorithm, self.flags, + self.iterations, salt, next, text) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + algorithm = tok.get_uint8() + flags = tok.get_uint8() + iterations = tok.get_uint16() + salt = tok.get_string() + if salt == '-': + salt = b'' + else: + salt = binascii.unhexlify(salt.encode('ascii')) + next = tok.get_string().encode( + 'ascii').upper().translate(b32_hex_to_normal) + next = base64.b32decode(next) + bitmap = Bitmap.from_text(tok) + return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next, + bitmap) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + l = len(self.salt) + file.write(struct.pack("!BBHB", self.algorithm, self.flags, + self.iterations, l)) + file.write(self.salt) + l = len(self.next) + file.write(struct.pack("!B", l)) + file.write(self.next) + Bitmap(self.windows).to_wire(file) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + (algorithm, flags, iterations) = parser.get_struct('!BBH') + salt = parser.get_counted_bytes() + next = parser.get_counted_bytes() + bitmap = Bitmap.from_wire_parser(parser) + return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next, + bitmap) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/NSEC3PARAM.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/NSEC3PARAM.py new file mode 100644 index 0000000..299bf6e --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/NSEC3PARAM.py @@ -0,0 +1,71 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct +import binascii + +import dns.exception +import dns.immutable +import dns.rdata + + +@dns.immutable.immutable +class NSEC3PARAM(dns.rdata.Rdata): + + """NSEC3PARAM record""" + + __slots__ = ['algorithm', 'flags', 'iterations', 'salt'] + + def __init__(self, rdclass, rdtype, algorithm, flags, iterations, salt): + super().__init__(rdclass, rdtype) + self.algorithm = self._as_uint8(algorithm) + self.flags = self._as_uint8(flags) + self.iterations = self._as_uint16(iterations) + self.salt = self._as_bytes(salt, True, 255) + + def to_text(self, origin=None, relativize=True, **kw): + if self.salt == b'': + salt = '-' + else: + salt = binascii.hexlify(self.salt).decode() + return '%u %u %u %s' % (self.algorithm, self.flags, self.iterations, + salt) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + algorithm = tok.get_uint8() + flags = tok.get_uint8() + iterations = tok.get_uint16() + salt = tok.get_string() + if salt == '-': + salt = '' + else: + salt = binascii.unhexlify(salt.encode()) + return cls(rdclass, rdtype, algorithm, flags, iterations, salt) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + l = len(self.salt) + file.write(struct.pack("!BBHB", self.algorithm, self.flags, + self.iterations, l)) + file.write(self.salt) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + (algorithm, flags, iterations) = parser.get_struct('!BBH') + salt = parser.get_counted_bytes() + return cls(rdclass, rdtype, algorithm, flags, iterations, salt) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/OPENPGPKEY.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/OPENPGPKEY.py new file mode 100644 index 0000000..dcfa028 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/OPENPGPKEY.py @@ -0,0 +1,52 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2016 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import base64 + +import dns.exception +import dns.immutable +import dns.rdata +import dns.tokenizer + +@dns.immutable.immutable +class OPENPGPKEY(dns.rdata.Rdata): + + """OPENPGPKEY record""" + + # see: RFC 7929 + + def __init__(self, rdclass, rdtype, key): + super().__init__(rdclass, rdtype) + self.key = self._as_bytes(key) + + def to_text(self, origin=None, relativize=True, **kw): + return dns.rdata._base64ify(self.key, chunksize=None, **kw) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + b64 = tok.concatenate_remaining_identifiers().encode() + key = base64.b64decode(b64) + return cls(rdclass, rdtype, key) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(self.key) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + key = parser.get_remaining() + return cls(rdclass, rdtype, key) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/OPT.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/OPT.py new file mode 100644 index 0000000..69b8fe7 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/OPT.py @@ -0,0 +1,76 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.edns +import dns.immutable +import dns.exception +import dns.rdata + + +# We don't implement from_text, and that's ok. +# pylint: disable=abstract-method + +@dns.immutable.immutable +class OPT(dns.rdata.Rdata): + + """OPT record""" + + __slots__ = ['options'] + + def __init__(self, rdclass, rdtype, options): + """Initialize an OPT rdata. + + *rdclass*, an ``int`` is the rdataclass of the Rdata, + which is also the payload size. + + *rdtype*, an ``int`` is the rdatatype of the Rdata. + + *options*, a tuple of ``bytes`` + """ + + super().__init__(rdclass, rdtype) + def as_option(option): + if not isinstance(option, dns.edns.Option): + raise ValueError('option is not a dns.edns.option') + return option + self.options = self._as_tuple(options, as_option) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + for opt in self.options: + owire = opt.to_wire() + file.write(struct.pack("!HH", opt.otype, len(owire))) + file.write(owire) + + def to_text(self, origin=None, relativize=True, **kw): + return ' '.join(opt.to_text() for opt in self.options) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + options = [] + while parser.remaining() > 0: + (otype, olen) = parser.get_struct('!HH') + with parser.restrict_to(olen): + opt = dns.edns.option_from_wire_parser(otype, parser) + options.append(opt) + return cls(rdclass, rdtype, options) + + @property + def payload(self): + "payload size" + return self.rdclass diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/PTR.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/PTR.py new file mode 100644 index 0000000..265bed0 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/PTR.py @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.nsbase +import dns.immutable + + +@dns.immutable.immutable +class PTR(dns.rdtypes.nsbase.NSBase): + + """PTR record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/RP.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/RP.py new file mode 100644 index 0000000..a4e2297 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/RP.py @@ -0,0 +1,58 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.exception +import dns.immutable +import dns.rdata +import dns.name + + +@dns.immutable.immutable +class RP(dns.rdata.Rdata): + + """RP record""" + + # see: RFC 1183 + + __slots__ = ['mbox', 'txt'] + + def __init__(self, rdclass, rdtype, mbox, txt): + super().__init__(rdclass, rdtype) + self.mbox = self._as_name(mbox) + self.txt = self._as_name(txt) + + def to_text(self, origin=None, relativize=True, **kw): + mbox = self.mbox.choose_relativity(origin, relativize) + txt = self.txt.choose_relativity(origin, relativize) + return "{} {}".format(str(mbox), str(txt)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + mbox = tok.get_name(origin, relativize, relativize_to) + txt = tok.get_name(origin, relativize, relativize_to) + return cls(rdclass, rdtype, mbox, txt) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.mbox.to_wire(file, None, origin, canonicalize) + self.txt.to_wire(file, None, origin, canonicalize) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + mbox = parser.get_name(origin) + txt = parser.get_name(origin) + return cls(rdclass, rdtype, mbox, txt) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/RRSIG.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/RRSIG.py new file mode 100644 index 0000000..d050ccc --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/RRSIG.py @@ -0,0 +1,124 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import base64 +import calendar +import struct +import time + +import dns.dnssec +import dns.immutable +import dns.exception +import dns.rdata +import dns.rdatatype + + +class BadSigTime(dns.exception.DNSException): + + """Time in DNS SIG or RRSIG resource record cannot be parsed.""" + + +def sigtime_to_posixtime(what): + if len(what) <= 10 and what.isdigit(): + return int(what) + if len(what) != 14: + raise BadSigTime + year = int(what[0:4]) + month = int(what[4:6]) + day = int(what[6:8]) + hour = int(what[8:10]) + minute = int(what[10:12]) + second = int(what[12:14]) + return calendar.timegm((year, month, day, hour, minute, second, + 0, 0, 0)) + + +def posixtime_to_sigtime(what): + return time.strftime('%Y%m%d%H%M%S', time.gmtime(what)) + + +@dns.immutable.immutable +class RRSIG(dns.rdata.Rdata): + + """RRSIG record""" + + __slots__ = ['type_covered', 'algorithm', 'labels', 'original_ttl', + 'expiration', 'inception', 'key_tag', 'signer', + 'signature'] + + def __init__(self, rdclass, rdtype, type_covered, algorithm, labels, + original_ttl, expiration, inception, key_tag, signer, + signature): + super().__init__(rdclass, rdtype) + self.type_covered = self._as_rdatatype(type_covered) + self.algorithm = dns.dnssec.Algorithm.make(algorithm) + self.labels = self._as_uint8(labels) + self.original_ttl = self._as_ttl(original_ttl) + self.expiration = self._as_uint32(expiration) + self.inception = self._as_uint32(inception) + self.key_tag = self._as_uint16(key_tag) + self.signer = self._as_name(signer) + self.signature = self._as_bytes(signature) + + def covers(self): + return self.type_covered + + def to_text(self, origin=None, relativize=True, **kw): + return '%s %d %d %d %s %s %d %s %s' % ( + dns.rdatatype.to_text(self.type_covered), + self.algorithm, + self.labels, + self.original_ttl, + posixtime_to_sigtime(self.expiration), + posixtime_to_sigtime(self.inception), + self.key_tag, + self.signer.choose_relativity(origin, relativize), + dns.rdata._base64ify(self.signature, **kw) + ) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + type_covered = dns.rdatatype.from_text(tok.get_string()) + algorithm = dns.dnssec.algorithm_from_text(tok.get_string()) + labels = tok.get_int() + original_ttl = tok.get_ttl() + expiration = sigtime_to_posixtime(tok.get_string()) + inception = sigtime_to_posixtime(tok.get_string()) + key_tag = tok.get_int() + signer = tok.get_name(origin, relativize, relativize_to) + b64 = tok.concatenate_remaining_identifiers().encode() + signature = base64.b64decode(b64) + return cls(rdclass, rdtype, type_covered, algorithm, labels, + original_ttl, expiration, inception, key_tag, signer, + signature) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + header = struct.pack('!HBBIIIH', self.type_covered, + self.algorithm, self.labels, + self.original_ttl, self.expiration, + self.inception, self.key_tag) + file.write(header) + self.signer.to_wire(file, None, origin, canonicalize) + file.write(self.signature) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + header = parser.get_struct('!HBBIIIH') + signer = parser.get_name(origin) + signature = parser.get_remaining() + return cls(rdclass, rdtype, *header, signer, signature) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/RT.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/RT.py new file mode 100644 index 0000000..8d9c6bd --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/RT.py @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.mxbase +import dns.immutable + + +@dns.immutable.immutable +class RT(dns.rdtypes.mxbase.UncompressedDowncasingMX): + + """RT record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/SMIMEA.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/SMIMEA.py new file mode 100644 index 0000000..55d87bf --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/SMIMEA.py @@ -0,0 +1,9 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import dns.immutable +import dns.rdtypes.tlsabase + + +@dns.immutable.immutable +class SMIMEA(dns.rdtypes.tlsabase.TLSABase): + """SMIMEA record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/SOA.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/SOA.py new file mode 100644 index 0000000..7ce8865 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/SOA.py @@ -0,0 +1,78 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.name + + +@dns.immutable.immutable +class SOA(dns.rdata.Rdata): + + """SOA record""" + + # see: RFC 1035 + + __slots__ = ['mname', 'rname', 'serial', 'refresh', 'retry', 'expire', + 'minimum'] + + def __init__(self, rdclass, rdtype, mname, rname, serial, refresh, retry, + expire, minimum): + super().__init__(rdclass, rdtype) + self.mname = self._as_name(mname) + self.rname = self._as_name(rname) + self.serial = self._as_uint32(serial) + self.refresh = self._as_ttl(refresh) + self.retry = self._as_ttl(retry) + self.expire = self._as_ttl(expire) + self.minimum = self._as_ttl(minimum) + + def to_text(self, origin=None, relativize=True, **kw): + mname = self.mname.choose_relativity(origin, relativize) + rname = self.rname.choose_relativity(origin, relativize) + return '%s %s %d %d %d %d %d' % ( + mname, rname, self.serial, self.refresh, self.retry, + self.expire, self.minimum) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + mname = tok.get_name(origin, relativize, relativize_to) + rname = tok.get_name(origin, relativize, relativize_to) + serial = tok.get_uint32() + refresh = tok.get_ttl() + retry = tok.get_ttl() + expire = tok.get_ttl() + minimum = tok.get_ttl() + return cls(rdclass, rdtype, mname, rname, serial, refresh, retry, + expire, minimum) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.mname.to_wire(file, compress, origin, canonicalize) + self.rname.to_wire(file, compress, origin, canonicalize) + five_ints = struct.pack('!IIIII', self.serial, self.refresh, + self.retry, self.expire, self.minimum) + file.write(five_ints) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + mname = parser.get_name(origin) + rname = parser.get_name(origin) + return cls(rdclass, rdtype, mname, rname, *parser.get_struct('!IIIII')) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/SPF.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/SPF.py new file mode 100644 index 0000000..1190e0d --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/SPF.py @@ -0,0 +1,27 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.txtbase +import dns.immutable + + +@dns.immutable.immutable +class SPF(dns.rdtypes.txtbase.TXTBase): + + """SPF record""" + + # see: RFC 4408 diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/SSHFP.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/SSHFP.py new file mode 100644 index 0000000..cc03519 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/SSHFP.py @@ -0,0 +1,69 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2005-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct +import binascii + +import dns.rdata +import dns.immutable +import dns.rdatatype + + +@dns.immutable.immutable +class SSHFP(dns.rdata.Rdata): + + """SSHFP record""" + + # See RFC 4255 + + __slots__ = ['algorithm', 'fp_type', 'fingerprint'] + + def __init__(self, rdclass, rdtype, algorithm, fp_type, + fingerprint): + super().__init__(rdclass, rdtype) + self.algorithm = self._as_uint8(algorithm) + self.fp_type = self._as_uint8(fp_type) + self.fingerprint = self._as_bytes(fingerprint, True) + + def to_text(self, origin=None, relativize=True, **kw): + kw = kw.copy() + chunksize = kw.pop('chunksize', 128) + return '%d %d %s' % (self.algorithm, + self.fp_type, + dns.rdata._hexify(self.fingerprint, + chunksize=chunksize, + **kw)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + algorithm = tok.get_uint8() + fp_type = tok.get_uint8() + fingerprint = tok.concatenate_remaining_identifiers().encode() + fingerprint = binascii.unhexlify(fingerprint) + return cls(rdclass, rdtype, algorithm, fp_type, fingerprint) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + header = struct.pack("!BB", self.algorithm, self.fp_type) + file.write(header) + file.write(self.fingerprint) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + header = parser.get_struct("BB") + fingerprint = parser.get_remaining() + return cls(rdclass, rdtype, header[0], header[1], fingerprint) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/TKEY.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/TKEY.py new file mode 100644 index 0000000..f8c4737 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/TKEY.py @@ -0,0 +1,118 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import base64 +import struct + +import dns.dnssec +import dns.immutable +import dns.exception +import dns.rdata + + +@dns.immutable.immutable +class TKEY(dns.rdata.Rdata): + + """TKEY Record""" + + __slots__ = ['algorithm', 'inception', 'expiration', 'mode', 'error', + 'key', 'other'] + + def __init__(self, rdclass, rdtype, algorithm, inception, expiration, + mode, error, key, other=b''): + super().__init__(rdclass, rdtype) + self.algorithm = self._as_name(algorithm) + self.inception = self._as_uint32(inception) + self.expiration = self._as_uint32(expiration) + self.mode = self._as_uint16(mode) + self.error = self._as_uint16(error) + self.key = self._as_bytes(key) + self.other = self._as_bytes(other) + + def to_text(self, origin=None, relativize=True, **kw): + _algorithm = self.algorithm.choose_relativity(origin, relativize) + text = '%s %u %u %u %u %s' % (str(_algorithm), self.inception, + self.expiration, self.mode, self.error, + dns.rdata._base64ify(self.key, 0)) + if len(self.other) > 0: + text += ' %s' % (dns.rdata._base64ify(self.other, 0)) + + return text + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + algorithm = tok.get_name(relativize=False) + inception = tok.get_uint32() + expiration = tok.get_uint32() + mode = tok.get_uint16() + error = tok.get_uint16() + key_b64 = tok.get_string().encode() + key = base64.b64decode(key_b64) + other_b64 = tok.concatenate_remaining_identifiers().encode() + other = base64.b64decode(other_b64) + + return cls(rdclass, rdtype, algorithm, inception, expiration, mode, + error, key, other) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.algorithm.to_wire(file, compress, origin) + file.write(struct.pack("!IIHH", self.inception, self.expiration, + self.mode, self.error)) + file.write(struct.pack("!H", len(self.key))) + file.write(self.key) + file.write(struct.pack("!H", len(self.other))) + if len(self.other) > 0: + file.write(self.other) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + algorithm = parser.get_name(origin) + inception, expiration, mode, error = parser.get_struct("!IIHH") + key = parser.get_counted_bytes(2) + other = parser.get_counted_bytes(2) + + return cls(rdclass, rdtype, algorithm, inception, expiration, mode, + error, key, other) + + # Constants for the mode field - from RFC 2930: + # 2.5 The Mode Field + # + # The mode field specifies the general scheme for key agreement or + # the purpose of the TKEY DNS message. Servers and resolvers + # supporting this specification MUST implement the Diffie-Hellman key + # agreement mode and the key deletion mode for queries. All other + # modes are OPTIONAL. A server supporting TKEY that receives a TKEY + # request with a mode it does not support returns the BADMODE error. + # The following values of the Mode octet are defined, available, or + # reserved: + # + # Value Description + # ----- ----------- + # 0 - reserved, see section 7 + # 1 server assignment + # 2 Diffie-Hellman exchange + # 3 GSS-API negotiation + # 4 resolver assignment + # 5 key deletion + # 6-65534 - available, see section 7 + # 65535 - reserved, see section 7 + SERVER_ASSIGNMENT = 1 + DIFFIE_HELLMAN_EXCHANGE = 2 + GSSAPI_NEGOTIATION = 3 + RESOLVER_ASSIGNMENT = 4 + KEY_DELETION = 5 diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/TLSA.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/TLSA.py new file mode 100644 index 0000000..c9ba199 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/TLSA.py @@ -0,0 +1,10 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import dns.immutable +import dns.rdtypes.tlsabase + + +@dns.immutable.immutable +class TLSA(dns.rdtypes.tlsabase.TLSABase): + + """TLSA record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/TSIG.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/TSIG.py new file mode 100644 index 0000000..b43a78f --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/TSIG.py @@ -0,0 +1,120 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import base64 +import struct + +import dns.exception +import dns.immutable +import dns.rcode +import dns.rdata + + +@dns.immutable.immutable +class TSIG(dns.rdata.Rdata): + + """TSIG record""" + + __slots__ = ['algorithm', 'time_signed', 'fudge', 'mac', + 'original_id', 'error', 'other'] + + def __init__(self, rdclass, rdtype, algorithm, time_signed, fudge, mac, + original_id, error, other): + """Initialize a TSIG rdata. + + *rdclass*, an ``int`` is the rdataclass of the Rdata. + + *rdtype*, an ``int`` is the rdatatype of the Rdata. + + *algorithm*, a ``dns.name.Name``. + + *time_signed*, an ``int``. + + *fudge*, an ``int`. + + *mac*, a ``bytes`` + + *original_id*, an ``int`` + + *error*, an ``int`` + + *other*, a ``bytes`` + """ + + super().__init__(rdclass, rdtype) + self.algorithm = self._as_name(algorithm) + self.time_signed = self._as_uint48(time_signed) + self.fudge = self._as_uint16(fudge) + self.mac = self._as_bytes(mac) + self.original_id = self._as_uint16(original_id) + self.error = dns.rcode.Rcode.make(error) + self.other = self._as_bytes(other) + + def to_text(self, origin=None, relativize=True, **kw): + algorithm = self.algorithm.choose_relativity(origin, relativize) + error = dns.rcode.to_text(self.error, True) + text = f"{algorithm} {self.time_signed} {self.fudge} " + \ + f"{len(self.mac)} {dns.rdata._base64ify(self.mac, 0)} " + \ + f"{self.original_id} {error} {len(self.other)}" + if self.other: + text += f" {dns.rdata._base64ify(self.other, 0)}" + return text + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + algorithm = tok.get_name(relativize=False) + time_signed = tok.get_uint48() + fudge = tok.get_uint16() + mac_len = tok.get_uint16() + mac = base64.b64decode(tok.get_string()) + if len(mac) != mac_len: + raise SyntaxError('invalid MAC') + original_id = tok.get_uint16() + error = dns.rcode.from_text(tok.get_string()) + other_len = tok.get_uint16() + if other_len > 0: + other = base64.b64decode(tok.get_string()) + if len(other) != other_len: + raise SyntaxError('invalid other data') + else: + other = b'' + return cls(rdclass, rdtype, algorithm, time_signed, fudge, mac, + original_id, error, other) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.algorithm.to_wire(file, None, origin, False) + file.write(struct.pack('!HIHH', + (self.time_signed >> 32) & 0xffff, + self.time_signed & 0xffffffff, + self.fudge, + len(self.mac))) + file.write(self.mac) + file.write(struct.pack('!HHH', self.original_id, self.error, + len(self.other))) + file.write(self.other) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + algorithm = parser.get_name() + time_signed = parser.get_uint48() + fudge = parser.get_uint16() + mac = parser.get_counted_bytes(2) + (original_id, error) = parser.get_struct('!HH') + other = parser.get_counted_bytes(2) + return cls(rdclass, rdtype, algorithm, time_signed, fudge, mac, + original_id, error, other) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/TXT.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/TXT.py new file mode 100644 index 0000000..cc4b661 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/TXT.py @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.txtbase +import dns.immutable + + +@dns.immutable.immutable +class TXT(dns.rdtypes.txtbase.TXTBase): + + """TXT record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/URI.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/URI.py new file mode 100644 index 0000000..ccbd2ce --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/URI.py @@ -0,0 +1,79 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# Copyright (C) 2015 Red Hat, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.name + + +@dns.immutable.immutable +class URI(dns.rdata.Rdata): + + """URI record""" + + # see RFC 7553 + + __slots__ = ['priority', 'weight', 'target'] + + def __init__(self, rdclass, rdtype, priority, weight, target): + super().__init__(rdclass, rdtype) + self.priority = self._as_uint16(priority) + self.weight = self._as_uint16(weight) + self.target = self._as_bytes(target, True) + if len(self.target) == 0: + raise dns.exception.SyntaxError("URI target cannot be empty") + + def to_text(self, origin=None, relativize=True, **kw): + return '%d %d "%s"' % (self.priority, self.weight, + self.target.decode()) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + priority = tok.get_uint16() + weight = tok.get_uint16() + target = tok.get().unescape() + if not (target.is_quoted_string() or target.is_identifier()): + raise dns.exception.SyntaxError("URI target must be a string") + return cls(rdclass, rdtype, priority, weight, target.value) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + two_ints = struct.pack("!HH", self.priority, self.weight) + file.write(two_ints) + file.write(self.target) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + (priority, weight) = parser.get_struct('!HH') + target = parser.get_remaining() + if len(target) == 0: + raise dns.exception.FormError('URI target may not be empty') + return cls(rdclass, rdtype, priority, weight, target) + + def _processing_priority(self): + return self.priority + + def _processing_weight(self): + return self.weight + + @classmethod + def _processing_order(cls, iterable): + return dns.rdtypes.util.weighted_processing_order(iterable) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/X25.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/X25.py new file mode 100644 index 0000000..4f7230c --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/X25.py @@ -0,0 +1,57 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.tokenizer + + +@dns.immutable.immutable +class X25(dns.rdata.Rdata): + + """X25 record""" + + # see RFC 1183 + + __slots__ = ['address'] + + def __init__(self, rdclass, rdtype, address): + super().__init__(rdclass, rdtype) + self.address = self._as_bytes(address, True, 255) + + def to_text(self, origin=None, relativize=True, **kw): + return '"%s"' % dns.rdata._escapify(self.address) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + address = tok.get_string() + return cls(rdclass, rdtype, address) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + l = len(self.address) + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(self.address) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + address = parser.get_counted_bytes() + return cls(rdclass, rdtype, address) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/__init__.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/__init__.py new file mode 100644 index 0000000..b0ea707 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/ANY/__init__.py @@ -0,0 +1,61 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Class ANY (generic) rdata type classes.""" + +__all__ = [ + 'AFSDB', + 'AVC', + 'CAA', + 'CDNSKEY', + 'CDS', + 'CERT', + 'CNAME', + 'CSYNC', + 'DLV', + 'DNAME', + 'DNSKEY', + 'DS', + 'EUI48', + 'EUI64', + 'GPOS', + 'HINFO', + 'HIP', + 'ISDN', + 'LOC', + 'MX', + 'NS', + 'NSEC', + 'NSEC3', + 'NSEC3PARAM', + 'OPENPGPKEY', + 'OPT', + 'PTR', + 'RP', + 'RRSIG', + 'RT', + 'SMIMEA', + 'SOA', + 'SPF', + 'SSHFP', + 'TKEY', + 'TLSA', + 'TSIG', + 'TXT', + 'URI', + 'X25', +] diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/CH/A.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/CH/A.py new file mode 100644 index 0000000..828701b --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/CH/A.py @@ -0,0 +1,58 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.rdtypes.mxbase +import dns.immutable + +@dns.immutable.immutable +class A(dns.rdata.Rdata): + + """A record for Chaosnet""" + + # domain: the domain of the address + # address: the 16-bit address + + __slots__ = ['domain', 'address'] + + def __init__(self, rdclass, rdtype, domain, address): + super().__init__(rdclass, rdtype) + self.domain = self._as_name(domain) + self.address = self._as_uint16(address) + + def to_text(self, origin=None, relativize=True, **kw): + domain = self.domain.choose_relativity(origin, relativize) + return '%s %o' % (domain, self.address) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + domain = tok.get_name(origin, relativize, relativize_to) + address = tok.get_uint16(base=8) + return cls(rdclass, rdtype, domain, address) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.domain.to_wire(file, compress, origin, canonicalize) + pref = struct.pack("!H", self.address) + file.write(pref) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + domain = parser.get_name(origin) + address = parser.get_uint16() + return cls(rdclass, rdtype, domain, address) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/CH/__init__.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/CH/__init__.py new file mode 100644 index 0000000..7184a73 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/CH/__init__.py @@ -0,0 +1,22 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Class CH rdata type classes.""" + +__all__ = [ + 'A', +] diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/A.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/A.py new file mode 100644 index 0000000..74b591e --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/A.py @@ -0,0 +1,51 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.exception +import dns.immutable +import dns.ipv4 +import dns.rdata +import dns.tokenizer + + +@dns.immutable.immutable +class A(dns.rdata.Rdata): + + """A record.""" + + __slots__ = ['address'] + + def __init__(self, rdclass, rdtype, address): + super().__init__(rdclass, rdtype) + self.address = self._as_ipv4_address(address) + + def to_text(self, origin=None, relativize=True, **kw): + return self.address + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + address = tok.get_identifier() + return cls(rdclass, rdtype, address) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(dns.ipv4.inet_aton(self.address)) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + address = parser.get_remaining() + return cls(rdclass, rdtype, address) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/AAAA.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/AAAA.py new file mode 100644 index 0000000..2d3ec90 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/AAAA.py @@ -0,0 +1,51 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.exception +import dns.immutable +import dns.ipv6 +import dns.rdata +import dns.tokenizer + + +@dns.immutable.immutable +class AAAA(dns.rdata.Rdata): + + """AAAA record.""" + + __slots__ = ['address'] + + def __init__(self, rdclass, rdtype, address): + super().__init__(rdclass, rdtype) + self.address = self._as_ipv6_address(address) + + def to_text(self, origin=None, relativize=True, **kw): + return self.address + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + address = tok.get_identifier() + return cls(rdclass, rdtype, address) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(dns.ipv6.inet_aton(self.address)) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + address = parser.get_remaining() + return cls(rdclass, rdtype, address) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/APL.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/APL.py new file mode 100644 index 0000000..5cfdc34 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/APL.py @@ -0,0 +1,151 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import binascii +import codecs +import struct + +import dns.exception +import dns.immutable +import dns.ipv4 +import dns.ipv6 +import dns.rdata +import dns.tokenizer + +@dns.immutable.immutable +class APLItem: + + """An APL list item.""" + + __slots__ = ['family', 'negation', 'address', 'prefix'] + + def __init__(self, family, negation, address, prefix): + self.family = dns.rdata.Rdata._as_uint16(family) + self.negation = dns.rdata.Rdata._as_bool(negation) + if self.family == 1: + self.address = dns.rdata.Rdata._as_ipv4_address(address) + self.prefix = dns.rdata.Rdata._as_int(prefix, 0, 32) + elif self.family == 2: + self.address = dns.rdata.Rdata._as_ipv6_address(address) + self.prefix = dns.rdata.Rdata._as_int(prefix, 0, 128) + else: + self.address = dns.rdata.Rdata._as_bytes(address) + self.prefix = dns.rdata.Rdata._as_uint8(prefix) + + def __str__(self): + if self.negation: + return "!%d:%s/%s" % (self.family, self.address, self.prefix) + else: + return "%d:%s/%s" % (self.family, self.address, self.prefix) + + def to_wire(self, file): + if self.family == 1: + address = dns.ipv4.inet_aton(self.address) + elif self.family == 2: + address = dns.ipv6.inet_aton(self.address) + else: + address = binascii.unhexlify(self.address) + # + # Truncate least significant zero bytes. + # + last = 0 + for i in range(len(address) - 1, -1, -1): + if address[i] != 0: + last = i + 1 + break + address = address[0: last] + l = len(address) + assert l < 128 + if self.negation: + l |= 0x80 + header = struct.pack('!HBB', self.family, self.prefix, l) + file.write(header) + file.write(address) + + +@dns.immutable.immutable +class APL(dns.rdata.Rdata): + + """APL record.""" + + # see: RFC 3123 + + __slots__ = ['items'] + + def __init__(self, rdclass, rdtype, items): + super().__init__(rdclass, rdtype) + for item in items: + if not isinstance(item, APLItem): + raise ValueError('item not an APLItem') + self.items = tuple(items) + + def to_text(self, origin=None, relativize=True, **kw): + return ' '.join(map(str, self.items)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + items = [] + for token in tok.get_remaining(): + item = token.unescape().value + if item[0] == '!': + negation = True + item = item[1:] + else: + negation = False + (family, rest) = item.split(':', 1) + family = int(family) + (address, prefix) = rest.split('/', 1) + prefix = int(prefix) + item = APLItem(family, negation, address, prefix) + items.append(item) + + return cls(rdclass, rdtype, items) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + for item in self.items: + item.to_wire(file) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + + items = [] + while parser.remaining() > 0: + header = parser.get_struct('!HBB') + afdlen = header[2] + if afdlen > 127: + negation = True + afdlen -= 128 + else: + negation = False + address = parser.get_bytes(afdlen) + l = len(address) + if header[0] == 1: + if l < 4: + address += b'\x00' * (4 - l) + elif header[0] == 2: + if l < 16: + address += b'\x00' * (16 - l) + else: + # + # This isn't really right according to the RFC, but it + # seems better than throwing an exception + # + address = codecs.encode(address, 'hex_codec') + item = APLItem(header[0], negation, address, header[1]) + items.append(item) + return cls(rdclass, rdtype, items) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/DHCID.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/DHCID.py new file mode 100644 index 0000000..a918598 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/DHCID.py @@ -0,0 +1,53 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import base64 + +import dns.exception +import dns.immutable + + +@dns.immutable.immutable +class DHCID(dns.rdata.Rdata): + + """DHCID record""" + + # see: RFC 4701 + + __slots__ = ['data'] + + def __init__(self, rdclass, rdtype, data): + super().__init__(rdclass, rdtype) + self.data = self._as_bytes(data) + + def to_text(self, origin=None, relativize=True, **kw): + return dns.rdata._base64ify(self.data, **kw) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + b64 = tok.concatenate_remaining_identifiers().encode() + data = base64.b64decode(b64) + return cls(rdclass, rdtype, data) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(self.data) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + data = parser.get_remaining() + return cls(rdclass, rdtype, data) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/HTTPS.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/HTTPS.py new file mode 100644 index 0000000..6a67e8e --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/HTTPS.py @@ -0,0 +1,8 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import dns.rdtypes.svcbbase +import dns.immutable + +@dns.immutable.immutable +class HTTPS(dns.rdtypes.svcbbase.SVCBBase): + """HTTPS record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/IPSECKEY.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/IPSECKEY.py new file mode 100644 index 0000000..d1d3943 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/IPSECKEY.py @@ -0,0 +1,83 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct +import base64 + +import dns.exception +import dns.immutable +import dns.rdtypes.util + + +class Gateway(dns.rdtypes.util.Gateway): + name = 'IPSECKEY gateway' + +@dns.immutable.immutable +class IPSECKEY(dns.rdata.Rdata): + + """IPSECKEY record""" + + # see: RFC 4025 + + __slots__ = ['precedence', 'gateway_type', 'algorithm', 'gateway', 'key'] + + def __init__(self, rdclass, rdtype, precedence, gateway_type, algorithm, + gateway, key): + super().__init__(rdclass, rdtype) + gateway = Gateway(gateway_type, gateway) + self.precedence = self._as_uint8(precedence) + self.gateway_type = gateway.type + self.algorithm = self._as_uint8(algorithm) + self.gateway = gateway.gateway + self.key = self._as_bytes(key) + + def to_text(self, origin=None, relativize=True, **kw): + gateway = Gateway(self.gateway_type, self.gateway).to_text(origin, + relativize) + return '%d %d %d %s %s' % (self.precedence, self.gateway_type, + self.algorithm, gateway, + dns.rdata._base64ify(self.key, **kw)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + precedence = tok.get_uint8() + gateway_type = tok.get_uint8() + algorithm = tok.get_uint8() + gateway = Gateway.from_text(gateway_type, tok, origin, relativize, + relativize_to) + b64 = tok.concatenate_remaining_identifiers().encode() + key = base64.b64decode(b64) + return cls(rdclass, rdtype, precedence, gateway_type, algorithm, + gateway.gateway, key) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + header = struct.pack("!BBB", self.precedence, self.gateway_type, + self.algorithm) + file.write(header) + Gateway(self.gateway_type, self.gateway).to_wire(file, compress, + origin, canonicalize) + file.write(self.key) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + header = parser.get_struct('!BBB') + gateway_type = header[1] + gateway = Gateway.from_wire_parser(gateway_type, parser, origin) + key = parser.get_remaining() + return cls(rdclass, rdtype, header[0], gateway_type, header[2], + gateway.gateway, key) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/KX.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/KX.py new file mode 100644 index 0000000..c27e921 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/KX.py @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.mxbase +import dns.immutable + + +@dns.immutable.immutable +class KX(dns.rdtypes.mxbase.UncompressedDowncasingMX): + + """KX record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/NAPTR.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/NAPTR.py new file mode 100644 index 0000000..1f072f8 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/NAPTR.py @@ -0,0 +1,98 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.name +import dns.rdata + + +def _write_string(file, s): + l = len(s) + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(s) + + +@dns.immutable.immutable +class NAPTR(dns.rdata.Rdata): + + """NAPTR record""" + + # see: RFC 3403 + + __slots__ = ['order', 'preference', 'flags', 'service', 'regexp', + 'replacement'] + + def __init__(self, rdclass, rdtype, order, preference, flags, service, + regexp, replacement): + super().__init__(rdclass, rdtype) + self.flags = self._as_bytes(flags, True, 255) + self.service = self._as_bytes(service, True, 255) + self.regexp = self._as_bytes(regexp, True, 255) + self.order = self._as_uint16(order) + self.preference = self._as_uint16(preference) + self.replacement = self._as_name(replacement) + + def to_text(self, origin=None, relativize=True, **kw): + replacement = self.replacement.choose_relativity(origin, relativize) + return '%d %d "%s" "%s" "%s" %s' % \ + (self.order, self.preference, + dns.rdata._escapify(self.flags), + dns.rdata._escapify(self.service), + dns.rdata._escapify(self.regexp), + replacement) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + order = tok.get_uint16() + preference = tok.get_uint16() + flags = tok.get_string() + service = tok.get_string() + regexp = tok.get_string() + replacement = tok.get_name(origin, relativize, relativize_to) + return cls(rdclass, rdtype, order, preference, flags, service, + regexp, replacement) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + two_ints = struct.pack("!HH", self.order, self.preference) + file.write(two_ints) + _write_string(file, self.flags) + _write_string(file, self.service) + _write_string(file, self.regexp) + self.replacement.to_wire(file, compress, origin, canonicalize) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + (order, preference) = parser.get_struct('!HH') + strings = [] + for _ in range(3): + s = parser.get_counted_bytes() + strings.append(s) + replacement = parser.get_name(origin) + return cls(rdclass, rdtype, order, preference, strings[0], strings[1], + strings[2], replacement) + + def _processing_priority(self): + return (self.order, self.preference) + + @classmethod + def _processing_order(cls, iterable): + return dns.rdtypes.util.priority_processing_order(iterable) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/NSAP.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/NSAP.py new file mode 100644 index 0000000..23ae9b1 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/NSAP.py @@ -0,0 +1,60 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import binascii + +import dns.exception +import dns.immutable +import dns.rdata +import dns.tokenizer + + +@dns.immutable.immutable +class NSAP(dns.rdata.Rdata): + + """NSAP record.""" + + # see: RFC 1706 + + __slots__ = ['address'] + + def __init__(self, rdclass, rdtype, address): + super().__init__(rdclass, rdtype) + self.address = self._as_bytes(address) + + def to_text(self, origin=None, relativize=True, **kw): + return "0x%s" % binascii.hexlify(self.address).decode() + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + address = tok.get_string() + if address[0:2] != '0x': + raise dns.exception.SyntaxError('string does not start with 0x') + address = address[2:].replace('.', '') + if len(address) % 2 != 0: + raise dns.exception.SyntaxError('hexstring has odd length') + address = binascii.unhexlify(address.encode()) + return cls(rdclass, rdtype, address) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(self.address) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + address = parser.get_remaining() + return cls(rdclass, rdtype, address) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/NSAP_PTR.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/NSAP_PTR.py new file mode 100644 index 0000000..57dadd4 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/NSAP_PTR.py @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.nsbase +import dns.immutable + + +@dns.immutable.immutable +class NSAP_PTR(dns.rdtypes.nsbase.UncompressedNS): + + """NSAP-PTR record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/PX.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/PX.py new file mode 100644 index 0000000..8abfb29 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/PX.py @@ -0,0 +1,72 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.name + + +@dns.immutable.immutable +class PX(dns.rdata.Rdata): + + """PX record.""" + + # see: RFC 2163 + + __slots__ = ['preference', 'map822', 'mapx400'] + + def __init__(self, rdclass, rdtype, preference, map822, mapx400): + super().__init__(rdclass, rdtype) + self.preference = self._as_uint16(preference) + self.map822 = self._as_name(map822) + self.mapx400 = self._as_name(mapx400) + + def to_text(self, origin=None, relativize=True, **kw): + map822 = self.map822.choose_relativity(origin, relativize) + mapx400 = self.mapx400.choose_relativity(origin, relativize) + return '%d %s %s' % (self.preference, map822, mapx400) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + preference = tok.get_uint16() + map822 = tok.get_name(origin, relativize, relativize_to) + mapx400 = tok.get_name(origin, relativize, relativize_to) + return cls(rdclass, rdtype, preference, map822, mapx400) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + pref = struct.pack("!H", self.preference) + file.write(pref) + self.map822.to_wire(file, None, origin, canonicalize) + self.mapx400.to_wire(file, None, origin, canonicalize) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + preference = parser.get_uint16() + map822 = parser.get_name(origin) + mapx400 = parser.get_name(origin) + return cls(rdclass, rdtype, preference, map822, mapx400) + + def _processing_priority(self): + return self.preference + + @classmethod + def _processing_order(cls, iterable): + return dns.rdtypes.util.priority_processing_order(iterable) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/SRV.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/SRV.py new file mode 100644 index 0000000..6d9b683 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/SRV.py @@ -0,0 +1,75 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.name + + +@dns.immutable.immutable +class SRV(dns.rdata.Rdata): + + """SRV record""" + + # see: RFC 2782 + + __slots__ = ['priority', 'weight', 'port', 'target'] + + def __init__(self, rdclass, rdtype, priority, weight, port, target): + super().__init__(rdclass, rdtype) + self.priority = self._as_uint16(priority) + self.weight = self._as_uint16(weight) + self.port = self._as_uint16(port) + self.target = self._as_name(target) + + def to_text(self, origin=None, relativize=True, **kw): + target = self.target.choose_relativity(origin, relativize) + return '%d %d %d %s' % (self.priority, self.weight, self.port, + target) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + priority = tok.get_uint16() + weight = tok.get_uint16() + port = tok.get_uint16() + target = tok.get_name(origin, relativize, relativize_to) + return cls(rdclass, rdtype, priority, weight, port, target) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + three_ints = struct.pack("!HHH", self.priority, self.weight, self.port) + file.write(three_ints) + self.target.to_wire(file, compress, origin, canonicalize) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + (priority, weight, port) = parser.get_struct('!HHH') + target = parser.get_name(origin) + return cls(rdclass, rdtype, priority, weight, port, target) + + def _processing_priority(self): + return self.priority + + def _processing_weight(self): + return self.weight + + @classmethod + def _processing_order(cls, iterable): + return dns.rdtypes.util.weighted_processing_order(iterable) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/SVCB.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/SVCB.py new file mode 100644 index 0000000..14838e1 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/SVCB.py @@ -0,0 +1,8 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import dns.rdtypes.svcbbase +import dns.immutable + +@dns.immutable.immutable +class SVCB(dns.rdtypes.svcbbase.SVCBBase): + """SVCB record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/WKS.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/WKS.py new file mode 100644 index 0000000..0d36281 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/WKS.py @@ -0,0 +1,96 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import socket +import struct + +import dns.ipv4 +import dns.immutable +import dns.rdata + +_proto_tcp = socket.getprotobyname('tcp') +_proto_udp = socket.getprotobyname('udp') + + +@dns.immutable.immutable +class WKS(dns.rdata.Rdata): + + """WKS record""" + + # see: RFC 1035 + + __slots__ = ['address', 'protocol', 'bitmap'] + + def __init__(self, rdclass, rdtype, address, protocol, bitmap): + super().__init__(rdclass, rdtype) + self.address = self._as_ipv4_address(address) + self.protocol = self._as_uint8(protocol) + self.bitmap = self._as_bytes(bitmap) + + def to_text(self, origin=None, relativize=True, **kw): + bits = [] + for i in range(0, len(self.bitmap)): + byte = self.bitmap[i] + for j in range(0, 8): + if byte & (0x80 >> j): + bits.append(str(i * 8 + j)) + text = ' '.join(bits) + return '%s %d %s' % (self.address, self.protocol, text) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + address = tok.get_string() + protocol = tok.get_string() + if protocol.isdigit(): + protocol = int(protocol) + else: + protocol = socket.getprotobyname(protocol) + bitmap = bytearray() + for token in tok.get_remaining(): + value = token.unescape().value + if value.isdigit(): + serv = int(value) + else: + if protocol != _proto_udp and protocol != _proto_tcp: + raise NotImplementedError("protocol must be TCP or UDP") + if protocol == _proto_udp: + protocol_text = "udp" + else: + protocol_text = "tcp" + serv = socket.getservbyname(value, protocol_text) + i = serv // 8 + l = len(bitmap) + if l < i + 1: + for _ in range(l, i + 1): + bitmap.append(0) + bitmap[i] = bitmap[i] | (0x80 >> (serv % 8)) + bitmap = dns.rdata._truncate_bitmap(bitmap) + return cls(rdclass, rdtype, address, protocol, bitmap) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(dns.ipv4.inet_aton(self.address)) + protocol = struct.pack('!B', self.protocol) + file.write(protocol) + file.write(self.bitmap) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + address = parser.get_bytes(4) + protocol = parser.get_uint8() + bitmap = parser.get_remaining() + return cls(rdclass, rdtype, address, protocol, bitmap) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/__init__.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/__init__.py new file mode 100644 index 0000000..d7e69c9 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/IN/__init__.py @@ -0,0 +1,33 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Class IN rdata type classes.""" + +__all__ = [ + 'A', + 'AAAA', + 'APL', + 'DHCID', + 'IPSECKEY', + 'KX', + 'NAPTR', + 'NSAP', + 'NSAP_PTR', + 'PX', + 'SRV', + 'WKS', +] diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/__init__.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/__init__.py new file mode 100644 index 0000000..c3af264 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/__init__.py @@ -0,0 +1,33 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS rdata type classes""" + +__all__ = [ + 'ANY', + 'IN', + 'CH', + 'dnskeybase', + 'dsbase', + 'euibase', + 'mxbase', + 'nsbase', + 'svcbbase', + 'tlsabase', + 'txtbase', + 'util' +] diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/dnskeybase.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/dnskeybase.py new file mode 100644 index 0000000..788bb2b --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/dnskeybase.py @@ -0,0 +1,82 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import base64 +import enum +import struct + +import dns.exception +import dns.immutable +import dns.dnssec +import dns.rdata + +# wildcard import +__all__ = ["SEP", "REVOKE", "ZONE"] # noqa: F822 + +class Flag(enum.IntFlag): + SEP = 0x0001 + REVOKE = 0x0080 + ZONE = 0x0100 + + +@dns.immutable.immutable +class DNSKEYBase(dns.rdata.Rdata): + + """Base class for rdata that is like a DNSKEY record""" + + __slots__ = ['flags', 'protocol', 'algorithm', 'key'] + + def __init__(self, rdclass, rdtype, flags, protocol, algorithm, key): + super().__init__(rdclass, rdtype) + self.flags = self._as_uint16(flags) + self.protocol = self._as_uint8(protocol) + self.algorithm = dns.dnssec.Algorithm.make(algorithm) + self.key = self._as_bytes(key) + + def to_text(self, origin=None, relativize=True, **kw): + return '%d %d %d %s' % (self.flags, self.protocol, self.algorithm, + dns.rdata._base64ify(self.key, **kw)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + flags = tok.get_uint16() + protocol = tok.get_uint8() + algorithm = tok.get_string() + b64 = tok.concatenate_remaining_identifiers().encode() + key = base64.b64decode(b64) + return cls(rdclass, rdtype, flags, protocol, algorithm, key) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + header = struct.pack("!HBB", self.flags, self.protocol, self.algorithm) + file.write(header) + file.write(self.key) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + header = parser.get_struct('!HBB') + key = parser.get_remaining() + return cls(rdclass, rdtype, header[0], header[1], header[2], + key) + +### BEGIN generated Flag constants + +SEP = Flag.SEP +REVOKE = Flag.REVOKE +ZONE = Flag.ZONE + +### END generated Flag constants diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/dsbase.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/dsbase.py new file mode 100644 index 0000000..38c9548 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/dsbase.py @@ -0,0 +1,72 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2010, 2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct +import binascii + +import dns.dnssec +import dns.immutable +import dns.rdata +import dns.rdatatype + + +@dns.immutable.immutable +class DSBase(dns.rdata.Rdata): + + """Base class for rdata that is like a DS record""" + + __slots__ = ['key_tag', 'algorithm', 'digest_type', 'digest'] + + def __init__(self, rdclass, rdtype, key_tag, algorithm, digest_type, + digest): + super().__init__(rdclass, rdtype) + self.key_tag = self._as_uint16(key_tag) + self.algorithm = dns.dnssec.Algorithm.make(algorithm) + self.digest_type = self._as_uint8(digest_type) + self.digest = self._as_bytes(digest) + + def to_text(self, origin=None, relativize=True, **kw): + kw = kw.copy() + chunksize = kw.pop('chunksize', 128) + return '%d %d %d %s' % (self.key_tag, self.algorithm, + self.digest_type, + dns.rdata._hexify(self.digest, + chunksize=chunksize, + **kw)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + key_tag = tok.get_uint16() + algorithm = tok.get_string() + digest_type = tok.get_uint8() + digest = tok.concatenate_remaining_identifiers().encode() + digest = binascii.unhexlify(digest) + return cls(rdclass, rdtype, key_tag, algorithm, digest_type, + digest) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + header = struct.pack("!HBB", self.key_tag, self.algorithm, + self.digest_type) + file.write(header) + file.write(self.digest) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + header = parser.get_struct("!HBB") + digest = parser.get_remaining() + return cls(rdclass, rdtype, header[0], header[1], header[2], digest) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/euibase.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/euibase.py new file mode 100644 index 0000000..60ab56d --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/euibase.py @@ -0,0 +1,69 @@ +# Copyright (C) 2015 Red Hat, Inc. +# Author: Petr Spacek +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import binascii + +import dns.rdata +import dns.immutable + + +@dns.immutable.immutable +class EUIBase(dns.rdata.Rdata): + + """EUIxx record""" + + # see: rfc7043.txt + + __slots__ = ['eui'] + # define these in subclasses + # byte_len = 6 # 0123456789ab (in hex) + # text_len = byte_len * 3 - 1 # 01-23-45-67-89-ab + + def __init__(self, rdclass, rdtype, eui): + super().__init__(rdclass, rdtype) + self.eui = self._as_bytes(eui) + if len(self.eui) != self.byte_len: + raise dns.exception.FormError('EUI%s rdata has to have %s bytes' + % (self.byte_len * 8, self.byte_len)) + + def to_text(self, origin=None, relativize=True, **kw): + return dns.rdata._hexify(self.eui, chunksize=2, **kw).replace(' ', '-') + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + text = tok.get_string() + if len(text) != cls.text_len: + raise dns.exception.SyntaxError( + 'Input text must have %s characters' % cls.text_len) + for i in range(2, cls.byte_len * 3 - 1, 3): + if text[i] != '-': + raise dns.exception.SyntaxError('Dash expected at position %s' + % i) + text = text.replace('-', '') + try: + data = binascii.unhexlify(text.encode()) + except (ValueError, TypeError) as ex: + raise dns.exception.SyntaxError('Hex decoding error: %s' % str(ex)) + return cls(rdclass, rdtype, data) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(self.eui) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + eui = parser.get_bytes(cls.byte_len) + return cls(rdclass, rdtype, eui) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/mxbase.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/mxbase.py new file mode 100644 index 0000000..5641823 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/mxbase.py @@ -0,0 +1,89 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""MX-like base classes.""" + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.name +import dns.rdtypes.util + + +@dns.immutable.immutable +class MXBase(dns.rdata.Rdata): + + """Base class for rdata that is like an MX record.""" + + __slots__ = ['preference', 'exchange'] + + def __init__(self, rdclass, rdtype, preference, exchange): + super().__init__(rdclass, rdtype) + self.preference = self._as_uint16(preference) + self.exchange = self._as_name(exchange) + + def to_text(self, origin=None, relativize=True, **kw): + exchange = self.exchange.choose_relativity(origin, relativize) + return '%d %s' % (self.preference, exchange) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + preference = tok.get_uint16() + exchange = tok.get_name(origin, relativize, relativize_to) + return cls(rdclass, rdtype, preference, exchange) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + pref = struct.pack("!H", self.preference) + file.write(pref) + self.exchange.to_wire(file, compress, origin, canonicalize) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + preference = parser.get_uint16() + exchange = parser.get_name(origin) + return cls(rdclass, rdtype, preference, exchange) + + def _processing_priority(self): + return self.preference + + @classmethod + def _processing_order(cls, iterable): + return dns.rdtypes.util.priority_processing_order(iterable) + + +@dns.immutable.immutable +class UncompressedMX(MXBase): + + """Base class for rdata that is like an MX record, but whose name + is not compressed when converted to DNS wire format, and whose + digestable form is not downcased.""" + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + super()._to_wire(file, None, origin, False) + + +@dns.immutable.immutable +class UncompressedDowncasingMX(MXBase): + + """Base class for rdata that is like an MX record, but whose name + is not compressed when convert to DNS wire format.""" + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + super()._to_wire(file, None, origin, canonicalize) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/nsbase.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/nsbase.py new file mode 100644 index 0000000..b3e2550 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/nsbase.py @@ -0,0 +1,64 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""NS-like base classes.""" + +import dns.exception +import dns.immutable +import dns.rdata +import dns.name + + +@dns.immutable.immutable +class NSBase(dns.rdata.Rdata): + + """Base class for rdata that is like an NS record.""" + + __slots__ = ['target'] + + def __init__(self, rdclass, rdtype, target): + super().__init__(rdclass, rdtype) + self.target = self._as_name(target) + + def to_text(self, origin=None, relativize=True, **kw): + target = self.target.choose_relativity(origin, relativize) + return str(target) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + target = tok.get_name(origin, relativize, relativize_to) + return cls(rdclass, rdtype, target) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.target.to_wire(file, compress, origin, canonicalize) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + target = parser.get_name(origin) + return cls(rdclass, rdtype, target) + + +@dns.immutable.immutable +class UncompressedNS(NSBase): + + """Base class for rdata that is like an NS record, but whose name + is not compressed when convert to DNS wire format, and whose + digestable form is not downcased.""" + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.target.to_wire(file, None, origin, False) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/svcbbase.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/svcbbase.py new file mode 100644 index 0000000..f757f02 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/svcbbase.py @@ -0,0 +1,543 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import base64 +import enum +import io +import struct + +import dns.enum +import dns.exception +import dns.immutable +import dns.ipv4 +import dns.ipv6 +import dns.name +import dns.rdata +import dns.tokenizer +import dns.wire + +# Until there is an RFC, this module is experimental and may be changed in +# incompatible ways. + + +class UnknownParamKey(dns.exception.DNSException): + """Unknown SVCB ParamKey""" + + +class ParamKey(dns.enum.IntEnum): + """SVCB ParamKey""" + + MANDATORY = 0 + ALPN = 1 + NO_DEFAULT_ALPN = 2 + PORT = 3 + IPV4HINT = 4 + ECHCONFIG = 5 + IPV6HINT = 6 + + @classmethod + def _maximum(cls): + return 65535 + + @classmethod + def _short_name(cls): + return "SVCBParamKey" + + @classmethod + def _prefix(cls): + return "KEY" + + @classmethod + def _unknown_exception_class(cls): + return UnknownParamKey + + +class Emptiness(enum.IntEnum): + NEVER = 0 + ALWAYS = 1 + ALLOWED = 2 + + +def _validate_key(key): + force_generic = False + if isinstance(key, bytes): + # We decode to latin-1 so we get 0-255 as valid and do NOT interpret + # UTF-8 sequences + key = key.decode('latin-1') + if isinstance(key, str): + if key.lower().startswith('key'): + force_generic = True + if key[3:].startswith('0') and len(key) != 4: + # key has leading zeros + raise ValueError('leading zeros in key') + key = key.replace('-', '_') + return (ParamKey.make(key), force_generic) + +def key_to_text(key): + return ParamKey.to_text(key).replace('_', '-').lower() + +# Like rdata escapify, but escapes ',' too. + +_escaped = b'",\\' + +def _escapify(qstring): + text = '' + for c in qstring: + if c in _escaped: + text += '\\' + chr(c) + elif c >= 0x20 and c < 0x7F: + text += chr(c) + else: + text += '\\%03d' % c + return text + +def _unescape(value, list_mode=False): + if value == '': + return value + items = [] + unescaped = b'' + l = len(value) + i = 0 + while i < l: + c = value[i] + i += 1 + if c == ',' and list_mode: + if len(unescaped) == 0: + raise ValueError('list item cannot be empty') + items.append(unescaped) + unescaped = b'' + continue + if c == '\\': + if i >= l: # pragma: no cover (can't happen via tokenizer get()) + raise dns.exception.UnexpectedEnd + c = value[i] + i += 1 + if c.isdigit(): + if i >= l: + raise dns.exception.UnexpectedEnd + c2 = value[i] + i += 1 + if i >= l: + raise dns.exception.UnexpectedEnd + c3 = value[i] + i += 1 + if not (c2.isdigit() and c3.isdigit()): + raise dns.exception.SyntaxError + codepoint = int(c) * 100 + int(c2) * 10 + int(c3) + if codepoint > 255: + raise dns.exception.SyntaxError + c = chr(codepoint) + unescaped += c.encode() + if len(unescaped) > 0: + items.append(unescaped) + else: + # This can't happen outside of list_mode because that would + # require the value parameter to the function to be empty, but + # we special case that at the beginning. + assert list_mode + raise ValueError('trailing comma') + if list_mode: + return items + else: + return items[0] + + +@dns.immutable.immutable +class Param: + """Abstract base class for SVCB parameters""" + + @classmethod + def emptiness(cls): + return Emptiness.NEVER + + +@dns.immutable.immutable +class GenericParam(Param): + """Generic SVCB parameter + """ + def __init__(self, value): + self.value = dns.rdata.Rdata._as_bytes(value, True) + + @classmethod + def emptiness(cls): + return Emptiness.ALLOWED + + @classmethod + def from_value(cls, value): + if value is None or len(value) == 0: + return None + else: + return cls(_unescape(value)) + + def to_text(self): + return '"' + _escapify(self.value) + '"' + + @classmethod + def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 + value = parser.get_bytes(parser.remaining()) + if len(value) == 0: + return None + else: + return cls(value) + + def to_wire(self, file, origin=None): # pylint: disable=W0613 + file.write(self.value) + + +@dns.immutable.immutable +class MandatoryParam(Param): + def __init__(self, keys): + # check for duplicates + keys = sorted([_validate_key(key)[0] for key in keys]) + prior_k = None + for k in keys: + if k == prior_k: + raise ValueError(f'duplicate key {k}') + prior_k = k + if k == ParamKey.MANDATORY: + raise ValueError('listed the mandatory key as mandatory') + self.keys = tuple(keys) + + @classmethod + def from_value(cls, value): + keys = [k.encode() for k in value.split(',')] + return cls(keys) + + def to_text(self): + return '"' + ','.join([key_to_text(key) for key in self.keys]) + '"' + + @classmethod + def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 + keys = [] + last_key = -1 + while parser.remaining() > 0: + key = parser.get_uint16() + if key < last_key: + raise dns.exception.FormError('manadatory keys not ascending') + last_key = key + keys.append(key) + return cls(keys) + + def to_wire(self, file, origin=None): # pylint: disable=W0613 + for key in self.keys: + file.write(struct.pack('!H', key)) + + +@dns.immutable.immutable +class ALPNParam(Param): + def __init__(self, ids): + self.ids = dns.rdata.Rdata._as_tuple( + ids, lambda x: dns.rdata.Rdata._as_bytes(x, True, 255, False)) + + @classmethod + def from_value(cls, value): + return cls(_unescape(value, True)) + + def to_text(self): + return '"' + ','.join([_escapify(id) for id in self.ids]) + '"' + + @classmethod + def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 + ids = [] + while parser.remaining() > 0: + id = parser.get_counted_bytes() + ids.append(id) + return cls(ids) + + def to_wire(self, file, origin=None): # pylint: disable=W0613 + for id in self.ids: + file.write(struct.pack('!B', len(id))) + file.write(id) + + +@dns.immutable.immutable +class NoDefaultALPNParam(Param): + # We don't ever expect to instantiate this class, but we need + # a from_value() and a from_wire_parser(), so we just return None + # from the class methods when things are OK. + + @classmethod + def emptiness(cls): + return Emptiness.ALWAYS + + @classmethod + def from_value(cls, value): + if value is None or value == '': + return None + else: + raise ValueError('no-default-alpn with non-empty value') + + def to_text(self): + raise NotImplementedError # pragma: no cover + + @classmethod + def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 + if parser.remaining() != 0: + raise dns.exception.FormError + return None + + def to_wire(self, file, origin=None): # pylint: disable=W0613 + raise NotImplementedError # pragma: no cover + + +@dns.immutable.immutable +class PortParam(Param): + def __init__(self, port): + self.port = dns.rdata.Rdata._as_uint16(port) + + @classmethod + def from_value(cls, value): + value = int(value) + return cls(value) + + def to_text(self): + return f'"{self.port}"' + + @classmethod + def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 + port = parser.get_uint16() + return cls(port) + + def to_wire(self, file, origin=None): # pylint: disable=W0613 + file.write(struct.pack('!H', self.port)) + + +@dns.immutable.immutable +class IPv4HintParam(Param): + def __init__(self, addresses): + self.addresses = dns.rdata.Rdata._as_tuple( + addresses, dns.rdata.Rdata._as_ipv4_address) + + @classmethod + def from_value(cls, value): + addresses = value.split(',') + return cls(addresses) + + def to_text(self): + return '"' + ','.join(self.addresses) + '"' + + @classmethod + def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 + addresses = [] + while parser.remaining() > 0: + ip = parser.get_bytes(4) + addresses.append(dns.ipv4.inet_ntoa(ip)) + return cls(addresses) + + def to_wire(self, file, origin=None): # pylint: disable=W0613 + for address in self.addresses: + file.write(dns.ipv4.inet_aton(address)) + + +@dns.immutable.immutable +class IPv6HintParam(Param): + def __init__(self, addresses): + self.addresses = dns.rdata.Rdata._as_tuple( + addresses, dns.rdata.Rdata._as_ipv6_address) + + @classmethod + def from_value(cls, value): + addresses = value.split(',') + return cls(addresses) + + def to_text(self): + return '"' + ','.join(self.addresses) + '"' + + @classmethod + def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 + addresses = [] + while parser.remaining() > 0: + ip = parser.get_bytes(16) + addresses.append(dns.ipv6.inet_ntoa(ip)) + return cls(addresses) + + def to_wire(self, file, origin=None): # pylint: disable=W0613 + for address in self.addresses: + file.write(dns.ipv6.inet_aton(address)) + + +@dns.immutable.immutable +class ECHConfigParam(Param): + def __init__(self, echconfig): + self.echconfig = dns.rdata.Rdata._as_bytes(echconfig, True) + + @classmethod + def from_value(cls, value): + if '\\' in value: + raise ValueError('escape in ECHConfig value') + value = base64.b64decode(value.encode()) + return cls(value) + + def to_text(self): + b64 = base64.b64encode(self.echconfig).decode('ascii') + return f'"{b64}"' + + @classmethod + def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 + value = parser.get_bytes(parser.remaining()) + return cls(value) + + def to_wire(self, file, origin=None): # pylint: disable=W0613 + file.write(self.echconfig) + + +_class_for_key = { + ParamKey.MANDATORY: MandatoryParam, + ParamKey.ALPN: ALPNParam, + ParamKey.NO_DEFAULT_ALPN: NoDefaultALPNParam, + ParamKey.PORT: PortParam, + ParamKey.IPV4HINT: IPv4HintParam, + ParamKey.ECHCONFIG: ECHConfigParam, + ParamKey.IPV6HINT: IPv6HintParam, +} + + +def _validate_and_define(params, key, value): + (key, force_generic) = _validate_key(_unescape(key)) + if key in params: + raise SyntaxError(f'duplicate key "{key}"') + cls = _class_for_key.get(key, GenericParam) + emptiness = cls.emptiness() + if value is None: + if emptiness == Emptiness.NEVER: + raise SyntaxError('value cannot be empty') + value = cls.from_value(value) + else: + if force_generic: + value = cls.from_wire_parser(dns.wire.Parser(_unescape(value))) + else: + value = cls.from_value(value) + params[key] = value + + +@dns.immutable.immutable +class SVCBBase(dns.rdata.Rdata): + + """Base class for SVCB-like records""" + + # see: draft-ietf-dnsop-svcb-https-01 + + __slots__ = ['priority', 'target', 'params'] + + def __init__(self, rdclass, rdtype, priority, target, params): + super().__init__(rdclass, rdtype) + self.priority = self._as_uint16(priority) + self.target = self._as_name(target) + for k, v in params.items(): + k = ParamKey.make(k) + if not isinstance(v, Param) and v is not None: + raise ValueError("not a Param") + self.params = dns.immutable.Dict(params) + # Make sure any paramater listed as mandatory is present in the + # record. + mandatory = params.get(ParamKey.MANDATORY) + if mandatory: + for key in mandatory.keys: + # Note we have to say "not in" as we have None as a value + # so a get() and a not None test would be wrong. + if key not in params: + raise ValueError(f'key {key} declared mandatory but not' + 'present') + + def to_text(self, origin=None, relativize=True, **kw): + target = self.target.choose_relativity(origin, relativize) + params = [] + for key in sorted(self.params.keys()): + value = self.params[key] + if value is None: + params.append(key_to_text(key)) + else: + kv = key_to_text(key) + '=' + value.to_text() + params.append(kv) + if len(params) > 0: + space = ' ' + else: + space = '' + return '%d %s%s%s' % (self.priority, target, space, ' '.join(params)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + priority = tok.get_uint16() + target = tok.get_name(origin, relativize, relativize_to) + if priority == 0: + token = tok.get() + if not token.is_eol_or_eof(): + raise SyntaxError('parameters in AliasMode') + tok.unget(token) + params = {} + while True: + token = tok.get() + if token.is_eol_or_eof(): + tok.unget(token) + break + if token.ttype != dns.tokenizer.IDENTIFIER: + raise SyntaxError('parameter is not an identifier') + equals = token.value.find('=') + if equals == len(token.value) - 1: + # 'key=', so next token should be a quoted string without + # any intervening whitespace. + key = token.value[:-1] + token = tok.get(want_leading=True) + if token.ttype != dns.tokenizer.QUOTED_STRING: + raise SyntaxError('whitespace after =') + value = token.value + elif equals > 0: + # key=value + key = token.value[:equals] + value = token.value[equals + 1:] + elif equals == 0: + # =key + raise SyntaxError('parameter cannot start with "="') + else: + # key + key = token.value + value = None + _validate_and_define(params, key, value) + return cls(rdclass, rdtype, priority, target, params) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + file.write(struct.pack("!H", self.priority)) + self.target.to_wire(file, None, origin, False) + for key in sorted(self.params): + file.write(struct.pack("!H", key)) + value = self.params[key] + # placeholder for length (or actual length of empty values) + file.write(struct.pack("!H", 0)) + if value is None: + continue + else: + start = file.tell() + value.to_wire(file, origin) + end = file.tell() + assert end - start < 65536 + file.seek(start - 2) + stuff = struct.pack("!H", end - start) + file.write(stuff) + file.seek(0, io.SEEK_END) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + priority = parser.get_uint16() + target = parser.get_name(origin) + if priority == 0 and parser.remaining() != 0: + raise dns.exception.FormError('parameters in AliasMode') + params = {} + prior_key = -1 + while parser.remaining() > 0: + key = parser.get_uint16() + if key < prior_key: + raise dns.exception.FormError('keys not in order') + prior_key = key + vlen = parser.get_uint16() + pcls = _class_for_key.get(key, GenericParam) + with parser.restrict_to(vlen): + value = pcls.from_wire_parser(parser, origin) + params[key] = value + return cls(rdclass, rdtype, priority, target, params) + + def _processing_priority(self): + return self.priority + + @classmethod + def _processing_order(cls, iterable): + return dns.rdtypes.util.priority_processing_order(iterable) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/tlsabase.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/tlsabase.py new file mode 100644 index 0000000..786fca5 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/tlsabase.py @@ -0,0 +1,72 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2005-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct +import binascii + +import dns.rdata +import dns.immutable +import dns.rdatatype + + +@dns.immutable.immutable +class TLSABase(dns.rdata.Rdata): + + """Base class for TLSA and SMIMEA records""" + + # see: RFC 6698 + + __slots__ = ['usage', 'selector', 'mtype', 'cert'] + + def __init__(self, rdclass, rdtype, usage, selector, + mtype, cert): + super().__init__(rdclass, rdtype) + self.usage = self._as_uint8(usage) + self.selector = self._as_uint8(selector) + self.mtype = self._as_uint8(mtype) + self.cert = self._as_bytes(cert) + + def to_text(self, origin=None, relativize=True, **kw): + kw = kw.copy() + chunksize = kw.pop('chunksize', 128) + return '%d %d %d %s' % (self.usage, + self.selector, + self.mtype, + dns.rdata._hexify(self.cert, + chunksize=chunksize, + **kw)) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + usage = tok.get_uint8() + selector = tok.get_uint8() + mtype = tok.get_uint8() + cert = tok.concatenate_remaining_identifiers().encode() + cert = binascii.unhexlify(cert) + return cls(rdclass, rdtype, usage, selector, mtype, cert) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + header = struct.pack("!BBB", self.usage, self.selector, self.mtype) + file.write(header) + file.write(self.cert) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + header = parser.get_struct("BBB") + cert = parser.get_remaining() + return cls(rdclass, rdtype, header[0], header[1], header[2], cert) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/txtbase.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/txtbase.py new file mode 100644 index 0000000..68071ee --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/txtbase.py @@ -0,0 +1,87 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""TXT-like base class.""" + +import struct + +import dns.exception +import dns.immutable +import dns.rdata +import dns.tokenizer + + +@dns.immutable.immutable +class TXTBase(dns.rdata.Rdata): + + """Base class for rdata that is like a TXT record (see RFC 1035).""" + + __slots__ = ['strings'] + + def __init__(self, rdclass, rdtype, strings): + """Initialize a TXT-like rdata. + + *rdclass*, an ``int`` is the rdataclass of the Rdata. + + *rdtype*, an ``int`` is the rdatatype of the Rdata. + + *strings*, a tuple of ``bytes`` + """ + super().__init__(rdclass, rdtype) + self.strings = self._as_tuple(strings, + lambda x: self._as_bytes(x, True, 255)) + + def to_text(self, origin=None, relativize=True, **kw): + txt = '' + prefix = '' + for s in self.strings: + txt += '{}"{}"'.format(prefix, dns.rdata._escapify(s)) + prefix = ' ' + return txt + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + strings = [] + for token in tok.get_remaining(): + token = token.unescape_to_bytes() + # The 'if' below is always true in the current code, but we + # are leaving this check in in case things change some day. + if not (token.is_quoted_string() or + token.is_identifier()): # pragma: no cover + raise dns.exception.SyntaxError("expected a string") + if len(token.value) > 255: + raise dns.exception.SyntaxError("string too long") + strings.append(token.value) + if len(strings) == 0: + raise dns.exception.UnexpectedEnd + return cls(rdclass, rdtype, strings) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + for s in self.strings: + l = len(s) + assert l < 256 + file.write(struct.pack('!B', l)) + file.write(s) + + @classmethod + def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): + strings = [] + while parser.remaining() > 0: + s = parser.get_counted_bytes() + strings.append(s) + return cls(rdclass, rdtype, strings) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/util.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/util.py new file mode 100644 index 0000000..7fc08cd --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rdtypes/util.py @@ -0,0 +1,231 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import collections +import random +import struct + +import dns.exception +import dns.ipv4 +import dns.ipv6 +import dns.name +import dns.rdata + + +class Gateway: + """A helper class for the IPSECKEY gateway and AMTRELAY relay fields""" + name = "" + + def __init__(self, type, gateway=None): + self.type = dns.rdata.Rdata._as_uint8(type) + self.gateway = gateway + self._check() + + @classmethod + def _invalid_type(cls, gateway_type): + return f"invalid {cls.name} type: {gateway_type}" + + def _check(self): + if self.type == 0: + if self.gateway not in (".", None): + raise SyntaxError(f"invalid {self.name} for type 0") + self.gateway = None + elif self.type == 1: + # check that it's OK + dns.ipv4.inet_aton(self.gateway) + elif self.type == 2: + # check that it's OK + dns.ipv6.inet_aton(self.gateway) + elif self.type == 3: + if not isinstance(self.gateway, dns.name.Name): + raise SyntaxError(f"invalid {self.name}; not a name") + else: + raise SyntaxError(self._invalid_type(self.type)) + + def to_text(self, origin=None, relativize=True): + if self.type == 0: + return "." + elif self.type in (1, 2): + return self.gateway + elif self.type == 3: + return str(self.gateway.choose_relativity(origin, relativize)) + else: + raise ValueError(self._invalid_type(self.type)) # pragma: no cover + + @classmethod + def from_text(cls, gateway_type, tok, origin=None, relativize=True, + relativize_to=None): + if gateway_type in (0, 1, 2): + gateway = tok.get_string() + elif gateway_type == 3: + gateway = tok.get_name(origin, relativize, relativize_to) + else: + raise dns.exception.SyntaxError( + cls._invalid_type(gateway_type)) # pragma: no cover + return cls(gateway_type, gateway) + + # pylint: disable=unused-argument + def to_wire(self, file, compress=None, origin=None, canonicalize=False): + if self.type == 0: + pass + elif self.type == 1: + file.write(dns.ipv4.inet_aton(self.gateway)) + elif self.type == 2: + file.write(dns.ipv6.inet_aton(self.gateway)) + elif self.type == 3: + self.gateway.to_wire(file, None, origin, False) + else: + raise ValueError(self._invalid_type(self.type)) # pragma: no cover + # pylint: enable=unused-argument + + @classmethod + def from_wire_parser(cls, gateway_type, parser, origin=None): + if gateway_type == 0: + gateway = None + elif gateway_type == 1: + gateway = dns.ipv4.inet_ntoa(parser.get_bytes(4)) + elif gateway_type == 2: + gateway = dns.ipv6.inet_ntoa(parser.get_bytes(16)) + elif gateway_type == 3: + gateway = parser.get_name(origin) + else: + raise dns.exception.FormError(cls._invalid_type(gateway_type)) + return cls(gateway_type, gateway) + + +class Bitmap: + """A helper class for the NSEC/NSEC3/CSYNC type bitmaps""" + type_name = "" + + def __init__(self, windows=None): + last_window = -1 + self.windows = windows + for (window, bitmap) in self.windows: + if not isinstance(window, int): + raise ValueError(f"bad {self.type_name} window type") + if window <= last_window: + raise ValueError(f"bad {self.type_name} window order") + if window > 256: + raise ValueError(f"bad {self.type_name} window number") + last_window = window + if not isinstance(bitmap, bytes): + raise ValueError(f"bad {self.type_name} octets type") + if len(bitmap) == 0 or len(bitmap) > 32: + raise ValueError(f"bad {self.type_name} octets") + + def to_text(self): + text = "" + for (window, bitmap) in self.windows: + bits = [] + for (i, byte) in enumerate(bitmap): + for j in range(0, 8): + if byte & (0x80 >> j): + rdtype = window * 256 + i * 8 + j + bits.append(dns.rdatatype.to_text(rdtype)) + text += (' ' + ' '.join(bits)) + return text + + @classmethod + def from_text(cls, tok): + rdtypes = [] + for token in tok.get_remaining(): + rdtype = dns.rdatatype.from_text(token.unescape().value) + if rdtype == 0: + raise dns.exception.SyntaxError(f"{cls.type_name} with bit 0") + rdtypes.append(rdtype) + rdtypes.sort() + window = 0 + octets = 0 + prior_rdtype = 0 + bitmap = bytearray(b'\0' * 32) + windows = [] + for rdtype in rdtypes: + if rdtype == prior_rdtype: + continue + prior_rdtype = rdtype + new_window = rdtype // 256 + if new_window != window: + if octets != 0: + windows.append((window, bytes(bitmap[0:octets]))) + bitmap = bytearray(b'\0' * 32) + window = new_window + offset = rdtype % 256 + byte = offset // 8 + bit = offset % 8 + octets = byte + 1 + bitmap[byte] = bitmap[byte] | (0x80 >> bit) + if octets != 0: + windows.append((window, bytes(bitmap[0:octets]))) + return cls(windows) + + def to_wire(self, file): + for (window, bitmap) in self.windows: + file.write(struct.pack('!BB', window, len(bitmap))) + file.write(bitmap) + + @classmethod + def from_wire_parser(cls, parser): + windows = [] + while parser.remaining() > 0: + window = parser.get_uint8() + bitmap = parser.get_counted_bytes() + windows.append((window, bitmap)) + return cls(windows) + + +def _priority_table(items): + by_priority = collections.defaultdict(list) + for rdata in items: + by_priority[rdata._processing_priority()].append(rdata) + return by_priority + +def priority_processing_order(iterable): + items = list(iterable) + if len(items) == 1: + return items + by_priority = _priority_table(items) + ordered = [] + for k in sorted(by_priority.keys()): + rdatas = by_priority[k] + random.shuffle(rdatas) + ordered.extend(rdatas) + return ordered + +_no_weight = 0.1 + +def weighted_processing_order(iterable): + items = list(iterable) + if len(items) == 1: + return items + by_priority = _priority_table(items) + ordered = [] + for k in sorted(by_priority.keys()): + rdatas = by_priority[k] + total = sum(rdata._processing_weight() or _no_weight + for rdata in rdatas) + while len(rdatas) > 1: + r = random.uniform(0, total) + for (n, rdata) in enumerate(rdatas): + weight = rdata._processing_weight() or _no_weight + if weight > r: + break + r -= weight + total -= weight + ordered.append(rdata) + del rdatas[n] + ordered.append(rdatas[0]) + return ordered diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/renderer.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/renderer.py new file mode 100644 index 0000000..72f0f7a --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/renderer.py @@ -0,0 +1,250 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Help for building DNS wire format messages""" + +import contextlib +import io +import struct +import random +import time + +import dns.exception +import dns.tsig + + +QUESTION = 0 +ANSWER = 1 +AUTHORITY = 2 +ADDITIONAL = 3 + + +class Renderer: + """Helper class for building DNS wire-format messages. + + Most applications can use the higher-level L{dns.message.Message} + class and its to_wire() method to generate wire-format messages. + This class is for those applications which need finer control + over the generation of messages. + + Typical use:: + + r = dns.renderer.Renderer(id=1, flags=0x80, max_size=512) + r.add_question(qname, qtype, qclass) + r.add_rrset(dns.renderer.ANSWER, rrset_1) + r.add_rrset(dns.renderer.ANSWER, rrset_2) + r.add_rrset(dns.renderer.AUTHORITY, ns_rrset) + r.add_edns(0, 0, 4096) + r.add_rrset(dns.renderer.ADDTIONAL, ad_rrset_1) + r.add_rrset(dns.renderer.ADDTIONAL, ad_rrset_2) + r.write_header() + r.add_tsig(keyname, secret, 300, 1, 0, '', request_mac) + wire = r.get_wire() + + output, an io.BytesIO, where rendering is written + + id: the message id + + flags: the message flags + + max_size: the maximum size of the message + + origin: the origin to use when rendering relative names + + compress: the compression table + + section: an int, the section currently being rendered + + counts: list of the number of RRs in each section + + mac: the MAC of the rendered message (if TSIG was used) + """ + + def __init__(self, id=None, flags=0, max_size=65535, origin=None): + """Initialize a new renderer.""" + + self.output = io.BytesIO() + if id is None: + self.id = random.randint(0, 65535) + else: + self.id = id + self.flags = flags + self.max_size = max_size + self.origin = origin + self.compress = {} + self.section = QUESTION + self.counts = [0, 0, 0, 0] + self.output.write(b'\x00' * 12) + self.mac = '' + + def _rollback(self, where): + """Truncate the output buffer at offset *where*, and remove any + compression table entries that pointed beyond the truncation + point. + """ + + self.output.seek(where) + self.output.truncate() + keys_to_delete = [] + for k, v in self.compress.items(): + if v >= where: + keys_to_delete.append(k) + for k in keys_to_delete: + del self.compress[k] + + def _set_section(self, section): + """Set the renderer's current section. + + Sections must be rendered order: QUESTION, ANSWER, AUTHORITY, + ADDITIONAL. Sections may be empty. + + Raises dns.exception.FormError if an attempt was made to set + a section value less than the current section. + """ + + if self.section != section: + if self.section > section: + raise dns.exception.FormError + self.section = section + + @contextlib.contextmanager + def _track_size(self): + start = self.output.tell() + yield start + if self.output.tell() > self.max_size: + self._rollback(start) + raise dns.exception.TooBig + + def add_question(self, qname, rdtype, rdclass=dns.rdataclass.IN): + """Add a question to the message.""" + + self._set_section(QUESTION) + with self._track_size(): + qname.to_wire(self.output, self.compress, self.origin) + self.output.write(struct.pack("!HH", rdtype, rdclass)) + self.counts[QUESTION] += 1 + + def add_rrset(self, section, rrset, **kw): + """Add the rrset to the specified section. + + Any keyword arguments are passed on to the rdataset's to_wire() + routine. + """ + + self._set_section(section) + with self._track_size(): + n = rrset.to_wire(self.output, self.compress, self.origin, **kw) + self.counts[section] += n + + def add_rdataset(self, section, name, rdataset, **kw): + """Add the rdataset to the specified section, using the specified + name as the owner name. + + Any keyword arguments are passed on to the rdataset's to_wire() + routine. + """ + + self._set_section(section) + with self._track_size(): + n = rdataset.to_wire(name, self.output, self.compress, self.origin, + **kw) + self.counts[section] += n + + def add_edns(self, edns, ednsflags, payload, options=None): + """Add an EDNS OPT record to the message.""" + + # make sure the EDNS version in ednsflags agrees with edns + ednsflags &= 0xFF00FFFF + ednsflags |= (edns << 16) + opt = dns.message.Message._make_opt(ednsflags, payload, options) + self.add_rrset(ADDITIONAL, opt) + + def add_tsig(self, keyname, secret, fudge, id, tsig_error, other_data, + request_mac, algorithm=dns.tsig.default_algorithm): + """Add a TSIG signature to the message.""" + + s = self.output.getvalue() + + if isinstance(secret, dns.tsig.Key): + key = secret + else: + key = dns.tsig.Key(keyname, secret, algorithm) + tsig = dns.message.Message._make_tsig(keyname, algorithm, 0, fudge, + b'', id, tsig_error, other_data) + (tsig, _) = dns.tsig.sign(s, key, tsig[0], int(time.time()), + request_mac) + self._write_tsig(tsig, keyname) + + def add_multi_tsig(self, ctx, keyname, secret, fudge, id, tsig_error, + other_data, request_mac, + algorithm=dns.tsig.default_algorithm): + """Add a TSIG signature to the message. Unlike add_tsig(), this can be + used for a series of consecutive DNS envelopes, e.g. for a zone + transfer over TCP [RFC2845, 4.4]. + + For the first message in the sequence, give ctx=None. For each + subsequent message, give the ctx that was returned from the + add_multi_tsig() call for the previous message.""" + + s = self.output.getvalue() + + if isinstance(secret, dns.tsig.Key): + key = secret + else: + key = dns.tsig.Key(keyname, secret, algorithm) + tsig = dns.message.Message._make_tsig(keyname, algorithm, 0, fudge, + b'', id, tsig_error, other_data) + (tsig, ctx) = dns.tsig.sign(s, key, tsig[0], int(time.time()), + request_mac, ctx, True) + self._write_tsig(tsig, keyname) + return ctx + + def _write_tsig(self, tsig, keyname): + self._set_section(ADDITIONAL) + with self._track_size(): + keyname.to_wire(self.output, self.compress, self.origin) + self.output.write(struct.pack('!HHIH', dns.rdatatype.TSIG, + dns.rdataclass.ANY, 0, 0)) + rdata_start = self.output.tell() + tsig.to_wire(self.output) + + after = self.output.tell() + self.output.seek(rdata_start - 2) + self.output.write(struct.pack('!H', after - rdata_start)) + self.counts[ADDITIONAL] += 1 + self.output.seek(10) + self.output.write(struct.pack('!H', self.counts[ADDITIONAL])) + self.output.seek(0, io.SEEK_END) + + def write_header(self): + """Write the DNS message header. + + Writing the DNS message header is done after all sections + have been rendered, but before the optional TSIG signature + is added. + """ + + self.output.seek(0) + self.output.write(struct.pack('!HHHHHH', self.id, self.flags, + self.counts[0], self.counts[1], + self.counts[2], self.counts[3])) + self.output.seek(0, io.SEEK_END) + + def get_wire(self): + """Return the wire format message.""" + + return self.output.getvalue() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/resolver.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/resolver.py new file mode 100644 index 0000000..7bdfd91 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/resolver.py @@ -0,0 +1,1649 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS stub resolver.""" +from urllib.parse import urlparse +import contextlib +import socket +import sys +import time +import random +import warnings +try: + import threading as _threading +except ImportError: # pragma: no cover + import dummy_threading as _threading # type: ignore + +import dns.exception +import dns.flags +import dns.inet +import dns.ipv4 +import dns.ipv6 +import dns.message +import dns.name +import dns.query +import dns.rcode +import dns.rdataclass +import dns.rdatatype +import dns.reversename +import dns.tsig + +if sys.platform == 'win32': + # pylint: disable=import-error + import winreg + +class NXDOMAIN(dns.exception.DNSException): + """The DNS query name does not exist.""" + supp_kwargs = {'qnames', 'responses'} + fmt = None # we have our own __str__ implementation + + # pylint: disable=arguments-differ + + def _check_kwargs(self, qnames, + responses=None): + if not isinstance(qnames, (list, tuple, set)): + raise AttributeError("qnames must be a list, tuple or set") + if len(qnames) == 0: + raise AttributeError("qnames must contain at least one element") + if responses is None: + responses = {} + elif not isinstance(responses, dict): + raise AttributeError("responses must be a dict(qname=response)") + kwargs = dict(qnames=qnames, responses=responses) + return kwargs + + def __str__(self): + if 'qnames' not in self.kwargs: + return super().__str__() + qnames = self.kwargs['qnames'] + if len(qnames) > 1: + msg = 'None of DNS query names exist' + else: + msg = 'The DNS query name does not exist' + qnames = ', '.join(map(str, qnames)) + return "{}: {}".format(msg, qnames) + + @property + def canonical_name(self): + """Return the unresolved canonical name.""" + if 'qnames' not in self.kwargs: + raise TypeError("parametrized exception required") + for qname in self.kwargs['qnames']: + response = self.kwargs['responses'][qname] + try: + cname = response.canonical_name() + if cname != qname: + return cname + except Exception: + # We can just eat this exception as it means there was + # something wrong with the response. + pass + return self.kwargs['qnames'][0] + + def __add__(self, e_nx): + """Augment by results from another NXDOMAIN exception.""" + qnames0 = list(self.kwargs.get('qnames', [])) + responses0 = dict(self.kwargs.get('responses', {})) + responses1 = e_nx.kwargs.get('responses', {}) + for qname1 in e_nx.kwargs.get('qnames', []): + if qname1 not in qnames0: + qnames0.append(qname1) + if qname1 in responses1: + responses0[qname1] = responses1[qname1] + return NXDOMAIN(qnames=qnames0, responses=responses0) + + def qnames(self): + """All of the names that were tried. + + Returns a list of ``dns.name.Name``. + """ + return self.kwargs['qnames'] + + def responses(self): + """A map from queried names to their NXDOMAIN responses. + + Returns a dict mapping a ``dns.name.Name`` to a + ``dns.message.Message``. + """ + return self.kwargs['responses'] + + def response(self, qname): + """The response for query *qname*. + + Returns a ``dns.message.Message``. + """ + return self.kwargs['responses'][qname] + + +class YXDOMAIN(dns.exception.DNSException): + """The DNS query name is too long after DNAME substitution.""" + +# The definition of the Timeout exception has moved from here to the +# dns.exception module. We keep dns.resolver.Timeout defined for +# backwards compatibility. + +Timeout = dns.exception.Timeout + + +class NoAnswer(dns.exception.DNSException): + """The DNS response does not contain an answer to the question.""" + fmt = 'The DNS response does not contain an answer ' + \ + 'to the question: {query}' + supp_kwargs = {'response'} + + def _fmt_kwargs(self, **kwargs): + return super()._fmt_kwargs(query=kwargs['response'].question) + + +class NoNameservers(dns.exception.DNSException): + """All nameservers failed to answer the query. + + errors: list of servers and respective errors + The type of errors is + [(server IP address, any object convertible to string)]. + Non-empty errors list will add explanatory message () + """ + + msg = "All nameservers failed to answer the query." + fmt = "%s {query}: {errors}" % msg[:-1] + supp_kwargs = {'request', 'errors'} + + def _fmt_kwargs(self, **kwargs): + srv_msgs = [] + for err in kwargs['errors']: + # pylint: disable=bad-continuation + srv_msgs.append('Server {} {} port {} answered {}'.format(err[0], + 'TCP' if err[1] else 'UDP', err[2], err[3])) + return super()._fmt_kwargs(query=kwargs['request'].question, + errors='; '.join(srv_msgs)) + + +class NotAbsolute(dns.exception.DNSException): + """An absolute domain name is required but a relative name was provided.""" + + +class NoRootSOA(dns.exception.DNSException): + """There is no SOA RR at the DNS root name. This should never happen!""" + + +class NoMetaqueries(dns.exception.DNSException): + """DNS metaqueries are not allowed.""" + +class NoResolverConfiguration(dns.exception.DNSException): + """Resolver configuration could not be read or specified no nameservers.""" + +class Answer: + """DNS stub resolver answer. + + Instances of this class bundle up the result of a successful DNS + resolution. + + For convenience, the answer object implements much of the sequence + protocol, forwarding to its ``rrset`` attribute. E.g. + ``for a in answer`` is equivalent to ``for a in answer.rrset``. + ``answer[i]`` is equivalent to ``answer.rrset[i]``, and + ``answer[i:j]`` is equivalent to ``answer.rrset[i:j]``. + + Note that CNAMEs or DNAMEs in the response may mean that answer + RRset's name might not be the query name. + """ + + def __init__(self, qname, rdtype, rdclass, response, nameserver=None, + port=None): + self.qname = qname + self.rdtype = rdtype + self.rdclass = rdclass + self.response = response + self.nameserver = nameserver + self.port = port + self.chaining_result = response.resolve_chaining() + # Copy some attributes out of chaining_result for backwards + # compatibility and convenience. + self.canonical_name = self.chaining_result.canonical_name + self.rrset = self.chaining_result.answer + self.expiration = time.time() + self.chaining_result.minimum_ttl + + def __getattr__(self, attr): # pragma: no cover + if attr == 'name': + return self.rrset.name + elif attr == 'ttl': + return self.rrset.ttl + elif attr == 'covers': + return self.rrset.covers + elif attr == 'rdclass': + return self.rrset.rdclass + elif attr == 'rdtype': + return self.rrset.rdtype + else: + raise AttributeError(attr) + + def __len__(self): + return self.rrset and len(self.rrset) or 0 + + def __iter__(self): + return self.rrset and iter(self.rrset) or iter(tuple()) + + def __getitem__(self, i): + if self.rrset is None: + raise IndexError + return self.rrset[i] + + def __delitem__(self, i): + if self.rrset is None: + raise IndexError + del self.rrset[i] + + +class CacheStatistics: + """Cache Statistics + """ + + def __init__(self, hits=0, misses=0): + self.hits = hits + self.misses = misses + + def reset(self): + self.hits = 0 + self.misses = 0 + + def clone(self): + return CacheStatistics(self.hits, self.misses) + + +class CacheBase: + def __init__(self): + self.lock = _threading.Lock() + self.statistics = CacheStatistics() + + def reset_statistics(self): + """Reset all statistics to zero.""" + with self.lock: + self.statistics.reset() + + def hits(self): + """How many hits has the cache had?""" + with self.lock: + return self.statistics.hits + + def misses(self): + """How many misses has the cache had?""" + with self.lock: + return self.statistics.misses + + def get_statistics_snapshot(self): + """Return a consistent snapshot of all the statistics. + + If running with multiple threads, it's better to take a + snapshot than to call statistics methods such as hits() and + misses() individually. + """ + with self.lock: + return self.statistics.clone() + + +class Cache(CacheBase): + """Simple thread-safe DNS answer cache.""" + + def __init__(self, cleaning_interval=300.0): + """*cleaning_interval*, a ``float`` is the number of seconds between + periodic cleanings. + """ + + super().__init__() + self.data = {} + self.cleaning_interval = cleaning_interval + self.next_cleaning = time.time() + self.cleaning_interval + + def _maybe_clean(self): + """Clean the cache if it's time to do so.""" + + now = time.time() + if self.next_cleaning <= now: + keys_to_delete = [] + for (k, v) in self.data.items(): + if v.expiration <= now: + keys_to_delete.append(k) + for k in keys_to_delete: + del self.data[k] + now = time.time() + self.next_cleaning = now + self.cleaning_interval + + def get(self, key): + """Get the answer associated with *key*. + + Returns None if no answer is cached for the key. + + *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the + query name, rdtype, and rdclass respectively. + + Returns a ``dns.resolver.Answer`` or ``None``. + """ + + with self.lock: + self._maybe_clean() + v = self.data.get(key) + if v is None or v.expiration <= time.time(): + self.statistics.misses += 1 + return None + self.statistics.hits += 1 + return v + + def put(self, key, value): + """Associate key and value in the cache. + + *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the + query name, rdtype, and rdclass respectively. + + *value*, a ``dns.resolver.Answer``, the answer. + """ + + with self.lock: + self._maybe_clean() + self.data[key] = value + + def flush(self, key=None): + """Flush the cache. + + If *key* is not ``None``, only that item is flushed. Otherwise + the entire cache is flushed. + + *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the + query name, rdtype, and rdclass respectively. + """ + + with self.lock: + if key is not None: + if key in self.data: + del self.data[key] + else: + self.data = {} + self.next_cleaning = time.time() + self.cleaning_interval + + +class LRUCacheNode: + """LRUCache node.""" + + def __init__(self, key, value): + self.key = key + self.value = value + self.hits = 0 + self.prev = self + self.next = self + + def link_after(self, node): + self.prev = node + self.next = node.next + node.next.prev = self + node.next = self + + def unlink(self): + self.next.prev = self.prev + self.prev.next = self.next + + +class LRUCache(CacheBase): + """Thread-safe, bounded, least-recently-used DNS answer cache. + + This cache is better than the simple cache (above) if you're + running a web crawler or other process that does a lot of + resolutions. The LRUCache has a maximum number of nodes, and when + it is full, the least-recently used node is removed to make space + for a new one. + """ + + def __init__(self, max_size=100000): + """*max_size*, an ``int``, is the maximum number of nodes to cache; + it must be greater than 0. + """ + + super().__init__() + self.data = {} + self.set_max_size(max_size) + self.sentinel = LRUCacheNode(None, None) + self.sentinel.prev = self.sentinel + self.sentinel.next = self.sentinel + + def set_max_size(self, max_size): + if max_size < 1: + max_size = 1 + self.max_size = max_size + + def get(self, key): + """Get the answer associated with *key*. + + Returns None if no answer is cached for the key. + + *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the + query name, rdtype, and rdclass respectively. + + Returns a ``dns.resolver.Answer`` or ``None``. + """ + + with self.lock: + node = self.data.get(key) + if node is None: + self.statistics.misses += 1 + return None + # Unlink because we're either going to move the node to the front + # of the LRU list or we're going to free it. + node.unlink() + if node.value.expiration <= time.time(): + del self.data[node.key] + self.statistics.misses += 1 + return None + node.link_after(self.sentinel) + self.statistics.hits += 1 + node.hits += 1 + return node.value + + def get_hits_for_key(self, key): + """Return the number of cache hits associated with the specified key.""" + with self.lock: + node = self.data.get(key) + if node is None or node.value.expiration <= time.time(): + return 0 + else: + return node.hits + + def put(self, key, value): + """Associate key and value in the cache. + + *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the + query name, rdtype, and rdclass respectively. + + *value*, a ``dns.resolver.Answer``, the answer. + """ + + with self.lock: + node = self.data.get(key) + if node is not None: + node.unlink() + del self.data[node.key] + while len(self.data) >= self.max_size: + node = self.sentinel.prev + node.unlink() + del self.data[node.key] + node = LRUCacheNode(key, value) + node.link_after(self.sentinel) + self.data[key] = node + + def flush(self, key=None): + """Flush the cache. + + If *key* is not ``None``, only that item is flushed. Otherwise + the entire cache is flushed. + + *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the + query name, rdtype, and rdclass respectively. + """ + + with self.lock: + if key is not None: + node = self.data.get(key) + if node is not None: + node.unlink() + del self.data[node.key] + else: + node = self.sentinel.next + while node != self.sentinel: + next = node.next + node.unlink() + node = next + self.data = {} + +class _Resolution: + """Helper class for dns.resolver.Resolver.resolve(). + + All of the "business logic" of resolution is encapsulated in this + class, allowing us to have multiple resolve() implementations + using different I/O schemes without copying all of the + complicated logic. + + This class is a "friend" to dns.resolver.Resolver and manipulates + resolver data structures directly. + """ + + def __init__(self, resolver, qname, rdtype, rdclass, tcp, + raise_on_no_answer, search): + if isinstance(qname, str): + qname = dns.name.from_text(qname, None) + rdtype = dns.rdatatype.RdataType.make(rdtype) + if dns.rdatatype.is_metatype(rdtype): + raise NoMetaqueries + rdclass = dns.rdataclass.RdataClass.make(rdclass) + if dns.rdataclass.is_metaclass(rdclass): + raise NoMetaqueries + self.resolver = resolver + self.qnames_to_try = resolver._get_qnames_to_try(qname, search) + self.qnames = self.qnames_to_try[:] + self.rdtype = rdtype + self.rdclass = rdclass + self.tcp = tcp + self.raise_on_no_answer = raise_on_no_answer + self.nxdomain_responses = {} + # + # Initialize other things to help analysis tools + self.qname = dns.name.empty + self.nameservers = [] + self.current_nameservers = [] + self.errors = [] + self.nameserver = None + self.port = 0 + self.tcp_attempt = False + self.retry_with_tcp = False + self.request = None + self.backoff = 0 + + def next_request(self): + """Get the next request to send, and check the cache. + + Returns a (request, answer) tuple. At most one of request or + answer will not be None. + """ + + # We return a tuple instead of Union[Message,Answer] as it lets + # the caller avoid isinstance(). + + while len(self.qnames) > 0: + self.qname = self.qnames.pop(0) + + # Do we know the answer? + if self.resolver.cache: + answer = self.resolver.cache.get((self.qname, self.rdtype, + self.rdclass)) + if answer is not None: + if answer.rrset is None and self.raise_on_no_answer: + raise NoAnswer(response=answer.response) + else: + return (None, answer) + answer = self.resolver.cache.get((self.qname, + dns.rdatatype.ANY, + self.rdclass)) + if answer is not None and \ + answer.response.rcode() == dns.rcode.NXDOMAIN: + # cached NXDOMAIN; record it and continue to next + # name. + self.nxdomain_responses[self.qname] = answer.response + continue + + # Build the request + request = dns.message.make_query(self.qname, self.rdtype, + self.rdclass) + if self.resolver.keyname is not None: + request.use_tsig(self.resolver.keyring, self.resolver.keyname, + algorithm=self.resolver.keyalgorithm) + request.use_edns(self.resolver.edns, self.resolver.ednsflags, + self.resolver.payload) + if self.resolver.flags is not None: + request.flags = self.resolver.flags + + self.nameservers = self.resolver.nameservers[:] + if self.resolver.rotate: + random.shuffle(self.nameservers) + self.current_nameservers = self.nameservers[:] + self.errors = [] + self.nameserver = None + self.tcp_attempt = False + self.retry_with_tcp = False + self.request = request + self.backoff = 0.10 + + return (request, None) + + # + # We've tried everything and only gotten NXDOMAINs. (We know + # it's only NXDOMAINs as anything else would have returned + # before now.) + # + raise NXDOMAIN(qnames=self.qnames_to_try, + responses=self.nxdomain_responses) + + def next_nameserver(self): + if self.retry_with_tcp: + assert self.nameserver is not None + self.tcp_attempt = True + self.retry_with_tcp = False + return (self.nameserver, self.port, True, 0) + + backoff = 0 + if not self.current_nameservers: + if len(self.nameservers) == 0: + # Out of things to try! + raise NoNameservers(request=self.request, errors=self.errors) + self.current_nameservers = self.nameservers[:] + backoff = self.backoff + self.backoff = min(self.backoff * 2, 2) + + self.nameserver = self.current_nameservers.pop(0) + self.port = self.resolver.nameserver_ports.get(self.nameserver, + self.resolver.port) + self.tcp_attempt = self.tcp + return (self.nameserver, self.port, self.tcp_attempt, backoff) + + def query_result(self, response, ex): + # + # returns an (answer: Answer, end_loop: bool) tuple. + # + if ex: + # Exception during I/O or from_wire() + assert response is None + self.errors.append((self.nameserver, self.tcp_attempt, self.port, + ex, response)) + if isinstance(ex, dns.exception.FormError) or \ + isinstance(ex, EOFError) or \ + isinstance(ex, OSError) or \ + isinstance(ex, NotImplementedError): + # This nameserver is no good, take it out of the mix. + self.nameservers.remove(self.nameserver) + elif isinstance(ex, dns.message.Truncated): + if self.tcp_attempt: + # Truncation with TCP is no good! + self.nameservers.remove(self.nameserver) + else: + self.retry_with_tcp = True + return (None, False) + # We got an answer! + assert response is not None + rcode = response.rcode() + if rcode == dns.rcode.NOERROR: + try: + answer = Answer(self.qname, self.rdtype, self.rdclass, response, + self.nameserver, self.port) + except Exception: + # The nameserver is no good, take it out of the mix. + self.nameservers.remove(self.nameserver) + return (None, False) + if self.resolver.cache: + self.resolver.cache.put((self.qname, self.rdtype, + self.rdclass), answer) + if answer.rrset is None and self.raise_on_no_answer: + raise NoAnswer(response=answer.response) + return (answer, True) + elif rcode == dns.rcode.NXDOMAIN: + # Further validate the response by making an Answer, even + # if we aren't going to cache it. + try: + answer = Answer(self.qname, dns.rdatatype.ANY, + dns.rdataclass.IN, response) + except Exception: + # The nameserver is no good, take it out of the mix. + self.nameservers.remove(self.nameserver) + return (None, False) + self.nxdomain_responses[self.qname] = response + if self.resolver.cache: + self.resolver.cache.put((self.qname, + dns.rdatatype.ANY, + self.rdclass), answer) + # Make next_nameserver() return None, so caller breaks its + # inner loop and calls next_request(). + return (None, True) + elif rcode == dns.rcode.YXDOMAIN: + yex = YXDOMAIN() + self.errors.append((self.nameserver, self.tcp_attempt, + self.port, yex, response)) + raise yex + else: + # + # We got a response, but we're not happy with the + # rcode in it. + # + if rcode != dns.rcode.SERVFAIL or not self.resolver.retry_servfail: + self.nameservers.remove(self.nameserver) + self.errors.append((self.nameserver, self.tcp_attempt, self.port, + dns.rcode.to_text(rcode), response)) + return (None, False) + +class BaseResolver: + """DNS stub resolver.""" + + # We initialize in reset() + # + # pylint: disable=attribute-defined-outside-init + + def __init__(self, filename='/etc/resolv.conf', configure=True): + """*filename*, a ``str`` or file object, specifying a file + in standard /etc/resolv.conf format. This parameter is meaningful + only when *configure* is true and the platform is POSIX. + + *configure*, a ``bool``. If True (the default), the resolver + instance is configured in the normal fashion for the operating + system the resolver is running on. (I.e. by reading a + /etc/resolv.conf file on POSIX systems and from the registry + on Windows systems.) + """ + + self.reset() + if configure: + if sys.platform == 'win32': + self.read_registry() + elif filename: + self.read_resolv_conf(filename) + + def reset(self): + """Reset all resolver configuration to the defaults.""" + + self.domain = \ + dns.name.Name(dns.name.from_text(socket.gethostname())[1:]) + if len(self.domain) == 0: + self.domain = dns.name.root + self.nameservers = [] + self.nameserver_ports = {} + self.port = 53 + self.search = [] + self.use_search_by_default = False + self.timeout = 2.0 + self.lifetime = 5.0 + self.keyring = None + self.keyname = None + self.keyalgorithm = dns.tsig.default_algorithm + self.edns = -1 + self.ednsflags = 0 + self.payload = 0 + self.cache = None + self.flags = None + self.retry_servfail = False + self.rotate = False + self.ndots = None + + def read_resolv_conf(self, f): + """Process *f* as a file in the /etc/resolv.conf format. If f is + a ``str``, it is used as the name of the file to open; otherwise it + is treated as the file itself. + + Interprets the following items: + + - nameserver - name server IP address + + - domain - local domain name + + - search - search list for host-name lookup + + - options - supported options are rotate, timeout, edns0, and ndots + + """ + + with contextlib.ExitStack() as stack: + if isinstance(f, str): + try: + f = stack.enter_context(open(f)) + except OSError: + # /etc/resolv.conf doesn't exist, can't be read, etc. + raise NoResolverConfiguration + + for l in f: + if len(l) == 0 or l[0] == '#' or l[0] == ';': + continue + tokens = l.split() + + # Any line containing less than 2 tokens is malformed + if len(tokens) < 2: + continue + + if tokens[0] == 'nameserver': + self.nameservers.append(tokens[1]) + elif tokens[0] == 'domain': + self.domain = dns.name.from_text(tokens[1]) + # domain and search are exclusive + self.search = [] + elif tokens[0] == 'search': + # the last search wins + self.search = [] + for suffix in tokens[1:]: + self.search.append(dns.name.from_text(suffix)) + # We don't set domain as it is not used if + # len(self.search) > 0 + elif tokens[0] == 'options': + for opt in tokens[1:]: + if opt == 'rotate': + self.rotate = True + elif opt == 'edns0': + self.use_edns() + elif 'timeout' in opt: + try: + self.timeout = int(opt.split(':')[1]) + except (ValueError, IndexError): + pass + elif 'ndots' in opt: + try: + self.ndots = int(opt.split(':')[1]) + except (ValueError, IndexError): + pass + if len(self.nameservers) == 0: + raise NoResolverConfiguration + + def _determine_split_char(self, entry): + # + # The windows registry irritatingly changes the list element + # delimiter in between ' ' and ',' (and vice-versa) in various + # versions of windows. + # + if entry.find(' ') >= 0: # pragma: no cover + split_char = ' ' + elif entry.find(',') >= 0: # pragma: no cover + split_char = ',' + else: + # probably a singleton; treat as a space-separated list. + split_char = ' ' + return split_char + + def _config_win32_nameservers(self, nameservers): + # we call str() on nameservers to convert it from unicode to ascii + nameservers = str(nameservers) + split_char = self._determine_split_char(nameservers) + ns_list = nameservers.split(split_char) + for ns in ns_list: + if ns not in self.nameservers: + self.nameservers.append(ns) + + def _config_win32_domain(self, domain): # pragma: no cover + # we call str() on domain to convert it from unicode to ascii + self.domain = dns.name.from_text(str(domain)) + + def _config_win32_search(self, search): # pragma: no cover + # we call str() on search to convert it from unicode to ascii + search = str(search) + split_char = self._determine_split_char(search) + search_list = search.split(split_char) + for s in search_list: + if s not in self.search: + self.search.append(dns.name.from_text(s)) + + def _config_win32_fromkey(self, key, always_try_domain): + # pylint: disable=undefined-variable + # (disabled for WindowsError) + try: + servers, _ = winreg.QueryValueEx(key, 'NameServer') + except WindowsError: # pragma: no cover + servers = None + if servers: + self._config_win32_nameservers(servers) + if servers or always_try_domain: + try: + dom, _ = winreg.QueryValueEx(key, 'Domain') + if dom: + self._config_win32_domain(dom) # pragma: no cover + except WindowsError: # pragma: no cover + pass + else: + try: + servers, _ = winreg.QueryValueEx(key, 'DhcpNameServer') + except WindowsError: # pragma: no cover + servers = None + if servers: + self._config_win32_nameservers(servers) + try: + dom, _ = winreg.QueryValueEx(key, 'DhcpDomain') + if dom: + self._config_win32_domain(dom) + except WindowsError: # pragma: no cover + pass + try: + search, _ = winreg.QueryValueEx(key, 'SearchList') + except WindowsError: # pragma: no cover + search = None + if search: # pragma: no cover + self._config_win32_search(search) + + def read_registry(self): + """Extract resolver configuration from the Windows registry.""" + + lm = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) + try: + tcp_params = winreg.OpenKey(lm, + r'SYSTEM\CurrentControlSet' + r'\Services\Tcpip\Parameters') + try: + self._config_win32_fromkey(tcp_params, True) + finally: + tcp_params.Close() + interfaces = winreg.OpenKey(lm, + r'SYSTEM\CurrentControlSet' + r'\Services\Tcpip\Parameters' + r'\Interfaces') + try: + i = 0 + while True: + try: + guid = winreg.EnumKey(interfaces, i) + i += 1 + # XXXRTH why do we get this key and then not use it? + key = winreg.OpenKey(interfaces, guid) + if not self._win32_is_nic_enabled(lm, guid, key): + continue + try: + self._config_win32_fromkey(key, False) + finally: + key.Close() + except EnvironmentError: # pragma: no cover + break + finally: + interfaces.Close() + finally: + lm.Close() + + def _win32_is_nic_enabled(self, lm, guid, _): + # Look in the Windows Registry to determine whether the network + # interface corresponding to the given guid is enabled. + # + # (Code contributed by Paul Marks, thanks!) + # + try: + # This hard-coded location seems to be consistent, at least + # from Windows 2000 through Vista. + connection_key = winreg.OpenKey( + lm, + r'SYSTEM\CurrentControlSet\Control\Network' + r'\{4D36E972-E325-11CE-BFC1-08002BE10318}' + r'\%s\Connection' % guid) + + try: + # The PnpInstanceID points to a key inside Enum + (pnp_id, ttype) = winreg.QueryValueEx( + connection_key, 'PnpInstanceID') + + if ttype != winreg.REG_SZ: + raise ValueError # pragma: no cover + + device_key = winreg.OpenKey( + lm, r'SYSTEM\CurrentControlSet\Enum\%s' % pnp_id) + + try: + # Get ConfigFlags for this device + (flags, ttype) = winreg.QueryValueEx( + device_key, 'ConfigFlags') + + if ttype != winreg.REG_DWORD: + raise ValueError # pragma: no cover + + # Based on experimentation, bit 0x1 indicates that the + # device is disabled. + return not flags & 0x1 + + finally: + device_key.Close() + finally: + connection_key.Close() + except Exception: # pragma: no cover + return False + + def _compute_timeout(self, start, lifetime=None): + lifetime = self.lifetime if lifetime is None else lifetime + now = time.time() + duration = now - start + if duration < 0: + if duration < -1: + # Time going backwards is bad. Just give up. + raise Timeout(timeout=duration) + else: + # Time went backwards, but only a little. This can + # happen, e.g. under vmware with older linux kernels. + # Pretend it didn't happen. + now = start + if duration >= lifetime: + raise Timeout(timeout=duration) + return min(lifetime - duration, self.timeout) + + def _get_qnames_to_try(self, qname, search): + # This is a separate method so we can unit test the search + # rules without requiring the Internet. + if search is None: + search = self.use_search_by_default + qnames_to_try = [] + if qname.is_absolute(): + qnames_to_try.append(qname) + else: + abs_qname = qname.concatenate(dns.name.root) + if search: + if len(self.search) > 0: + # There is a search list, so use it exclusively + search_list = self.search[:] + elif self.domain != dns.name.root and self.domain is not None: + # We have some notion of a domain that isn't the root, so + # use it as the search list. + search_list = [self.domain] + else: + search_list = [] + # Figure out the effective ndots (default is 1) + if self.ndots is None: + ndots = 1 + else: + ndots = self.ndots + for suffix in search_list: + qnames_to_try.append(qname + suffix) + if len(qname) > ndots: + # The name has at least ndots dots, so we should try an + # absolute query first. + qnames_to_try.insert(0, abs_qname) + else: + # The name has less than ndots dots, so we should search + # first, then try the absolute name. + qnames_to_try.append(abs_qname) + else: + qnames_to_try.append(abs_qname) + return qnames_to_try + + def use_tsig(self, keyring, keyname=None, + algorithm=dns.tsig.default_algorithm): + """Add a TSIG signature to each query. + + The parameters are passed to ``dns.message.Message.use_tsig()``; + see its documentation for details. + """ + + self.keyring = keyring + self.keyname = keyname + self.keyalgorithm = algorithm + + def use_edns(self, edns=0, ednsflags=0, + payload=dns.message.DEFAULT_EDNS_PAYLOAD): + """Configure EDNS behavior. + + *edns*, an ``int``, is the EDNS level to use. Specifying + ``None``, ``False``, or ``-1`` means "do not use EDNS", and in this case + the other parameters are ignored. Specifying ``True`` is + equivalent to specifying 0, i.e. "use EDNS0". + + *ednsflags*, an ``int``, the EDNS flag values. + + *payload*, an ``int``, is the EDNS sender's payload field, which is the + maximum size of UDP datagram the sender can handle. I.e. how big + a response to this message can be. + """ + + if edns is None or edns is False: + edns = -1 + elif edns is True: + edns = 0 + self.edns = edns + self.ednsflags = ednsflags + self.payload = payload + + def set_flags(self, flags): + """Overrides the default flags with your own. + + *flags*, an ``int``, the message flags to use. + """ + + self.flags = flags + + @property + def nameservers(self): + return self._nameservers + + @nameservers.setter + def nameservers(self, nameservers): + """ + *nameservers*, a ``list`` of nameservers. + + Raises ``ValueError`` if *nameservers* is anything other than a + ``list``. + """ + if isinstance(nameservers, list): + self._nameservers = nameservers + else: + raise ValueError('nameservers must be a list' + ' (not a {})'.format(type(nameservers))) + + +class Resolver(BaseResolver): + """DNS stub resolver.""" + + def resolve(self, qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN, + tcp=False, source=None, raise_on_no_answer=True, source_port=0, + lifetime=None, search=None): # pylint: disable=arguments-differ + """Query nameservers to find the answer to the question. + + The *qname*, *rdtype*, and *rdclass* parameters may be objects + of the appropriate type, or strings that can be converted into objects + of the appropriate type. + + *qname*, a ``dns.name.Name`` or ``str``, the query name. + + *rdtype*, an ``int`` or ``str``, the query type. + + *rdclass*, an ``int`` or ``str``, the query class. + + *tcp*, a ``bool``. If ``True``, use TCP to make the query. + + *source*, a ``str`` or ``None``. If not ``None``, bind to this IP + address when making queries. + + *raise_on_no_answer*, a ``bool``. If ``True``, raise + ``dns.resolver.NoAnswer`` if there's no answer to the question. + + *source_port*, an ``int``, the port from which to send the message. + + *lifetime*, a ``float``, how many seconds a query should run + before timing out. + + *search*, a ``bool`` or ``None``, determines whether the + search list configured in the system's resolver configuration + are used for relative names, and whether the resolver's domain + may be added to relative names. The default is ``None``, + which causes the value of the resolver's + ``use_search_by_default`` attribute to be used. + + Raises ``dns.exception.Timeout`` if no answers could be found + in the specified lifetime. + + Raises ``dns.resolver.NXDOMAIN`` if the query name does not exist. + + Raises ``dns.resolver.YXDOMAIN`` if the query name is too long after + DNAME substitution. + + Raises ``dns.resolver.NoAnswer`` if *raise_on_no_answer* is + ``True`` and the query name exists but has no RRset of the + desired type and class. + + Raises ``dns.resolver.NoNameservers`` if no non-broken + nameservers are available to answer the question. + + Returns a ``dns.resolver.Answer`` instance. + + """ + + resolution = _Resolution(self, qname, rdtype, rdclass, tcp, + raise_on_no_answer, search) + start = time.time() + while True: + (request, answer) = resolution.next_request() + # Note we need to say "if answer is not None" and not just + # "if answer" because answer implements __len__, and python + # will call that. We want to return if we have an answer + # object, including in cases where its length is 0. + if answer is not None: + # cache hit! + return answer + done = False + while not done: + (nameserver, port, tcp, backoff) = resolution.next_nameserver() + if backoff: + time.sleep(backoff) + timeout = self._compute_timeout(start, lifetime) + try: + if dns.inet.is_address(nameserver): + if tcp: + response = dns.query.tcp(request, nameserver, + timeout=timeout, + port=port, + source=source, + source_port=source_port) + else: + response = dns.query.udp(request, + nameserver, + timeout=timeout, + port=port, + source=source, + source_port=source_port, + raise_on_truncation=True) + else: + protocol = urlparse(nameserver).scheme + if protocol != 'https': + raise NotImplementedError + response = dns.query.https(request, nameserver, + timeout=timeout) + except Exception as ex: + (_, done) = resolution.query_result(None, ex) + continue + (answer, done) = resolution.query_result(response, None) + # Note we need to say "if answer is not None" and not just + # "if answer" because answer implements __len__, and python + # will call that. We want to return if we have an answer + # object, including in cases where its length is 0. + if answer is not None: + return answer + + def query(self, qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN, + tcp=False, source=None, raise_on_no_answer=True, source_port=0, + lifetime=None): # pragma: no cover + """Query nameservers to find the answer to the question. + + This method calls resolve() with ``search=True``, and is + provided for backwards compatbility with prior versions of + dnspython. See the documentation for the resolve() method for + further details. + """ + warnings.warn('please use dns.resolver.Resolver.resolve() instead', + DeprecationWarning, stacklevel=2) + return self.resolve(qname, rdtype, rdclass, tcp, source, + raise_on_no_answer, source_port, lifetime, + True) + + def resolve_address(self, ipaddr, *args, **kwargs): + """Use a resolver to run a reverse query for PTR records. + + This utilizes the resolve() method to perform a PTR lookup on the + specified IP address. + + *ipaddr*, a ``str``, the IPv4 or IPv6 address you want to get + the PTR record for. + + All other arguments that can be passed to the resolve() function + except for rdtype and rdclass are also supported by this + function. + """ + + return self.resolve(dns.reversename.from_address(ipaddr), + rdtype=dns.rdatatype.PTR, + rdclass=dns.rdataclass.IN, + *args, **kwargs) + + # pylint: disable=redefined-outer-name + + def canonical_name(self, name): + """Determine the canonical name of *name*. + + The canonical name is the name the resolver uses for queries + after all CNAME and DNAME renamings have been applied. + + *name*, a ``dns.name.Name`` or ``str``, the query name. + + This method can raise any exception that ``resolve()`` can + raise, other than ``dns.resolver.NoAnswer`` and + ``dns.resolver.NXDOMAIN``. + + Returns a ``dns.name.Name``. + """ + try: + answer = self.resolve(name, raise_on_no_answer=False) + canonical_name = answer.canonical_name + except dns.resolver.NXDOMAIN as e: + canonical_name = e.canonical_name + return canonical_name + + # pylint: enable=redefined-outer-name + + +#: The default resolver. +default_resolver = None + + +def get_default_resolver(): + """Get the default resolver, initializing it if necessary.""" + if default_resolver is None: + reset_default_resolver() + return default_resolver + + +def reset_default_resolver(): + """Re-initialize default resolver. + + Note that the resolver configuration (i.e. /etc/resolv.conf on UNIX + systems) will be re-read immediately. + """ + + global default_resolver + default_resolver = Resolver() + + +def resolve(qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN, + tcp=False, source=None, raise_on_no_answer=True, + source_port=0, lifetime=None, search=None): + """Query nameservers to find the answer to the question. + + This is a convenience function that uses the default resolver + object to make the query. + + See ``dns.resolver.Resolver.resolve`` for more information on the + parameters. + """ + + return get_default_resolver().resolve(qname, rdtype, rdclass, tcp, source, + raise_on_no_answer, source_port, + lifetime, search) + +def query(qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN, + tcp=False, source=None, raise_on_no_answer=True, + source_port=0, lifetime=None): # pragma: no cover + """Query nameservers to find the answer to the question. + + This method calls resolve() with ``search=True``, and is + provided for backwards compatbility with prior versions of + dnspython. See the documentation for the resolve() method for + further details. + """ + warnings.warn('please use dns.resolver.resolve() instead', + DeprecationWarning, stacklevel=2) + return resolve(qname, rdtype, rdclass, tcp, source, + raise_on_no_answer, source_port, lifetime, + True) + + +def resolve_address(ipaddr, *args, **kwargs): + """Use a resolver to run a reverse query for PTR records. + + See ``dns.resolver.Resolver.resolve_address`` for more information on the + parameters. + """ + + return get_default_resolver().resolve_address(ipaddr, *args, **kwargs) + + +def canonical_name(name): + """Determine the canonical name of *name*. + + See ``dns.resolver.Resolver.canonical_name`` for more information on the + parameters and possible exceptions. + """ + + return get_default_resolver().canonical_name(name) + + +def zone_for_name(name, rdclass=dns.rdataclass.IN, tcp=False, resolver=None): + """Find the name of the zone which contains the specified name. + + *name*, an absolute ``dns.name.Name`` or ``str``, the query name. + + *rdclass*, an ``int``, the query class. + + *tcp*, a ``bool``. If ``True``, use TCP to make the query. + + *resolver*, a ``dns.resolver.Resolver`` or ``None``, the resolver to use. + If ``None``, the default resolver is used. + + Raises ``dns.resolver.NoRootSOA`` if there is no SOA RR at the DNS + root. (This is only likely to happen if you're using non-default + root servers in your network and they are misconfigured.) + + Returns a ``dns.name.Name``. + """ + + if isinstance(name, str): + name = dns.name.from_text(name, dns.name.root) + if resolver is None: + resolver = get_default_resolver() + if not name.is_absolute(): + raise NotAbsolute(name) + while 1: + try: + answer = resolver.resolve(name, dns.rdatatype.SOA, rdclass, tcp) + if answer.rrset.name == name: + return name + # otherwise we were CNAMEd or DNAMEd and need to look higher + except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer): + pass + try: + name = name.parent() + except dns.name.NoParent: + raise NoRootSOA + +# +# Support for overriding the system resolver for all python code in the +# running process. +# + +_protocols_for_socktype = { + socket.SOCK_DGRAM: [socket.SOL_UDP], + socket.SOCK_STREAM: [socket.SOL_TCP], +} + +_resolver = None +_original_getaddrinfo = socket.getaddrinfo +_original_getnameinfo = socket.getnameinfo +_original_getfqdn = socket.getfqdn +_original_gethostbyname = socket.gethostbyname +_original_gethostbyname_ex = socket.gethostbyname_ex +_original_gethostbyaddr = socket.gethostbyaddr + + +def _getaddrinfo(host=None, service=None, family=socket.AF_UNSPEC, socktype=0, + proto=0, flags=0): + if flags & socket.AI_NUMERICHOST != 0: + # Short circuit directly into the system's getaddrinfo(). We're + # not adding any value in this case, and this avoids infinite loops + # because dns.query.* needs to call getaddrinfo() for IPv6 scoping + # reasons. We will also do this short circuit below if we + # discover that the host is an address literal. + return _original_getaddrinfo(host, service, family, socktype, proto, + flags) + if flags & (socket.AI_ADDRCONFIG | socket.AI_V4MAPPED) != 0: + # Not implemented. We raise a gaierror as opposed to a + # NotImplementedError as it helps callers handle errors more + # appropriately. [Issue #316] + # + # We raise EAI_FAIL as opposed to EAI_SYSTEM because there is + # no EAI_SYSTEM on Windows [Issue #416]. We didn't go for + # EAI_BADFLAGS as the flags aren't bad, we just don't + # implement them. + raise socket.gaierror(socket.EAI_FAIL, + 'Non-recoverable failure in name resolution') + if host is None and service is None: + raise socket.gaierror(socket.EAI_NONAME, 'Name or service not known') + v6addrs = [] + v4addrs = [] + canonical_name = None # pylint: disable=redefined-outer-name + # Is host None or an address literal? If so, use the system's + # getaddrinfo(). + if host is None: + return _original_getaddrinfo(host, service, family, socktype, + proto, flags) + try: + # We don't care about the result of af_for_address(), we're just + # calling it so it raises an exception if host is not an IPv4 or + # IPv6 address. + dns.inet.af_for_address(host) + return _original_getaddrinfo(host, service, family, socktype, + proto, flags) + except Exception: + pass + # Something needs resolution! + try: + if family == socket.AF_INET6 or family == socket.AF_UNSPEC: + v6 = _resolver.resolve(host, dns.rdatatype.AAAA, + raise_on_no_answer=False) + # Note that setting host ensures we query the same name + # for A as we did for AAAA. + host = v6.qname + canonical_name = v6.canonical_name.to_text(True) + if v6.rrset is not None: + for rdata in v6.rrset: + v6addrs.append(rdata.address) + if family == socket.AF_INET or family == socket.AF_UNSPEC: + v4 = _resolver.resolve(host, dns.rdatatype.A, + raise_on_no_answer=False) + host = v4.qname + canonical_name = v4.canonical_name.to_text(True) + if v4.rrset is not None: + for rdata in v4.rrset: + v4addrs.append(rdata.address) + except dns.resolver.NXDOMAIN: + raise socket.gaierror(socket.EAI_NONAME, 'Name or service not known') + except Exception: + # We raise EAI_AGAIN here as the failure may be temporary + # (e.g. a timeout) and EAI_SYSTEM isn't defined on Windows. + # [Issue #416] + raise socket.gaierror(socket.EAI_AGAIN, + 'Temporary failure in name resolution') + port = None + try: + # Is it a port literal? + if service is None: + port = 0 + else: + port = int(service) + except Exception: + if flags & socket.AI_NUMERICSERV == 0: + try: + port = socket.getservbyname(service) + except Exception: + pass + if port is None: + raise socket.gaierror(socket.EAI_NONAME, 'Name or service not known') + tuples = [] + if socktype == 0: + socktypes = [socket.SOCK_DGRAM, socket.SOCK_STREAM] + else: + socktypes = [socktype] + if flags & socket.AI_CANONNAME != 0: + cname = canonical_name + else: + cname = '' + if family == socket.AF_INET6 or family == socket.AF_UNSPEC: + for addr in v6addrs: + for socktype in socktypes: + for proto in _protocols_for_socktype[socktype]: + tuples.append((socket.AF_INET6, socktype, proto, + cname, (addr, port, 0, 0))) + if family == socket.AF_INET or family == socket.AF_UNSPEC: + for addr in v4addrs: + for socktype in socktypes: + for proto in _protocols_for_socktype[socktype]: + tuples.append((socket.AF_INET, socktype, proto, + cname, (addr, port))) + if len(tuples) == 0: + raise socket.gaierror(socket.EAI_NONAME, 'Name or service not known') + return tuples + + +def _getnameinfo(sockaddr, flags=0): + host = sockaddr[0] + port = sockaddr[1] + if len(sockaddr) == 4: + scope = sockaddr[3] + family = socket.AF_INET6 + else: + scope = None + family = socket.AF_INET + tuples = _getaddrinfo(host, port, family, socket.SOCK_STREAM, + socket.SOL_TCP, 0) + if len(tuples) > 1: + raise socket.error('sockaddr resolved to multiple addresses') + addr = tuples[0][4][0] + if flags & socket.NI_DGRAM: + pname = 'udp' + else: + pname = 'tcp' + qname = dns.reversename.from_address(addr) + if flags & socket.NI_NUMERICHOST == 0: + try: + answer = _resolver.resolve(qname, 'PTR') + hostname = answer.rrset[0].target.to_text(True) + except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer): + if flags & socket.NI_NAMEREQD: + raise socket.gaierror(socket.EAI_NONAME, + 'Name or service not known') + hostname = addr + if scope is not None: + hostname += '%' + str(scope) + else: + hostname = addr + if scope is not None: + hostname += '%' + str(scope) + if flags & socket.NI_NUMERICSERV: + service = str(port) + else: + service = socket.getservbyport(port, pname) + return (hostname, service) + + +def _getfqdn(name=None): + if name is None: + name = socket.gethostname() + try: + (name, _, _) = _gethostbyaddr(name) + # Python's version checks aliases too, but our gethostbyname + # ignores them, so we do so here as well. + except Exception: + pass + return name + + +def _gethostbyname(name): + return _gethostbyname_ex(name)[2][0] + + +def _gethostbyname_ex(name): + aliases = [] + addresses = [] + tuples = _getaddrinfo(name, 0, socket.AF_INET, socket.SOCK_STREAM, + socket.SOL_TCP, socket.AI_CANONNAME) + canonical = tuples[0][3] + for item in tuples: + addresses.append(item[4][0]) + # XXX we just ignore aliases + return (canonical, aliases, addresses) + + +def _gethostbyaddr(ip): + try: + dns.ipv6.inet_aton(ip) + sockaddr = (ip, 80, 0, 0) + family = socket.AF_INET6 + except Exception: + try: + dns.ipv4.inet_aton(ip) + except Exception: + raise socket.gaierror(socket.EAI_NONAME, + 'Name or service not known') + sockaddr = (ip, 80) + family = socket.AF_INET + (name, _) = _getnameinfo(sockaddr, socket.NI_NAMEREQD) + aliases = [] + addresses = [] + tuples = _getaddrinfo(name, 0, family, socket.SOCK_STREAM, socket.SOL_TCP, + socket.AI_CANONNAME) + canonical = tuples[0][3] + # We only want to include an address from the tuples if it's the + # same as the one we asked about. We do this comparison in binary + # to avoid any differences in text representations. + bin_ip = dns.inet.inet_pton(family, ip) + for item in tuples: + addr = item[4][0] + bin_addr = dns.inet.inet_pton(family, addr) + if bin_ip == bin_addr: + addresses.append(addr) + # XXX we just ignore aliases + return (canonical, aliases, addresses) + + +def override_system_resolver(resolver=None): + """Override the system resolver routines in the socket module with + versions which use dnspython's resolver. + + This can be useful in testing situations where you want to control + the resolution behavior of python code without having to change + the system's resolver settings (e.g. /etc/resolv.conf). + + The resolver to use may be specified; if it's not, the default + resolver will be used. + + resolver, a ``dns.resolver.Resolver`` or ``None``, the resolver to use. + """ + + if resolver is None: + resolver = get_default_resolver() + global _resolver + _resolver = resolver + socket.getaddrinfo = _getaddrinfo + socket.getnameinfo = _getnameinfo + socket.getfqdn = _getfqdn + socket.gethostbyname = _gethostbyname + socket.gethostbyname_ex = _gethostbyname_ex + socket.gethostbyaddr = _gethostbyaddr + + +def restore_system_resolver(): + """Undo the effects of prior override_system_resolver().""" + + global _resolver + _resolver = None + socket.getaddrinfo = _original_getaddrinfo + socket.getnameinfo = _original_getnameinfo + socket.getfqdn = _original_getfqdn + socket.gethostbyname = _original_gethostbyname + socket.gethostbyname_ex = _original_gethostbyname_ex + socket.gethostbyaddr = _original_gethostbyaddr diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/reversename.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/reversename.py new file mode 100644 index 0000000..e0beb03 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/reversename.py @@ -0,0 +1,100 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Reverse Map Names.""" + +import binascii + +import dns.name +import dns.ipv6 +import dns.ipv4 + +ipv4_reverse_domain = dns.name.from_text('in-addr.arpa.') +ipv6_reverse_domain = dns.name.from_text('ip6.arpa.') + + +def from_address(text, v4_origin=ipv4_reverse_domain, + v6_origin=ipv6_reverse_domain): + """Convert an IPv4 or IPv6 address in textual form into a Name object whose + value is the reverse-map domain name of the address. + + *text*, a ``str``, is an IPv4 or IPv6 address in textual form + (e.g. '127.0.0.1', '::1') + + *v4_origin*, a ``dns.name.Name`` to append to the labels corresponding to + the address if the address is an IPv4 address, instead of the default + (in-addr.arpa.) + + *v6_origin*, a ``dns.name.Name`` to append to the labels corresponding to + the address if the address is an IPv6 address, instead of the default + (ip6.arpa.) + + Raises ``dns.exception.SyntaxError`` if the address is badly formed. + + Returns a ``dns.name.Name``. + """ + + try: + v6 = dns.ipv6.inet_aton(text) + if dns.ipv6.is_mapped(v6): + parts = ['%d' % byte for byte in v6[12:]] + origin = v4_origin + else: + parts = [x for x in str(binascii.hexlify(v6).decode())] + origin = v6_origin + except Exception: + parts = ['%d' % + byte for byte in dns.ipv4.inet_aton(text)] + origin = v4_origin + return dns.name.from_text('.'.join(reversed(parts)), origin=origin) + + +def to_address(name, v4_origin=ipv4_reverse_domain, + v6_origin=ipv6_reverse_domain): + """Convert a reverse map domain name into textual address form. + + *name*, a ``dns.name.Name``, an IPv4 or IPv6 address in reverse-map name + form. + + *v4_origin*, a ``dns.name.Name`` representing the top-level domain for + IPv4 addresses, instead of the default (in-addr.arpa.) + + *v6_origin*, a ``dns.name.Name`` representing the top-level domain for + IPv4 addresses, instead of the default (ip6.arpa.) + + Raises ``dns.exception.SyntaxError`` if the name does not have a + reverse-map form. + + Returns a ``str``. + """ + + if name.is_subdomain(v4_origin): + name = name.relativize(v4_origin) + text = b'.'.join(reversed(name.labels)) + # run through inet_ntoa() to check syntax and make pretty. + return dns.ipv4.inet_ntoa(dns.ipv4.inet_aton(text)) + elif name.is_subdomain(v6_origin): + name = name.relativize(v6_origin) + labels = list(reversed(name.labels)) + parts = [] + for i in range(0, len(labels), 4): + parts.append(b''.join(labels[i:i + 4])) + text = b':'.join(parts) + # run through inet_ntoa() to check syntax and make pretty. + return dns.ipv6.inet_ntoa(dns.ipv6.inet_aton(text)) + else: + raise dns.exception.SyntaxError('unknown reverse-map address family') diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rrset.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rrset.py new file mode 100644 index 0000000..a71d457 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/rrset.py @@ -0,0 +1,229 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS RRsets (an RRset is a named rdataset)""" + + +import dns.name +import dns.rdataset +import dns.rdataclass +import dns.renderer + + +class RRset(dns.rdataset.Rdataset): + + """A DNS RRset (named rdataset). + + RRset inherits from Rdataset, and RRsets can be treated as + Rdatasets in most cases. There are, however, a few notable + exceptions. RRsets have different to_wire() and to_text() method + arguments, reflecting the fact that RRsets always have an owner + name. + """ + + __slots__ = ['name', 'deleting'] + + def __init__(self, name, rdclass, rdtype, covers=dns.rdatatype.NONE, + deleting=None): + """Create a new RRset.""" + + super().__init__(rdclass, rdtype, covers) + self.name = name + self.deleting = deleting + + def _clone(self): + obj = super()._clone() + obj.name = self.name + obj.deleting = self.deleting + return obj + + def __repr__(self): + if self.covers == 0: + ctext = '' + else: + ctext = '(' + dns.rdatatype.to_text(self.covers) + ')' + if self.deleting is not None: + dtext = ' delete=' + dns.rdataclass.to_text(self.deleting) + else: + dtext = '' + return '' + + def __str__(self): + return self.to_text() + + def __eq__(self, other): + if isinstance(other, RRset): + if self.name != other.name: + return False + elif not isinstance(other, dns.rdataset.Rdataset): + return False + return super().__eq__(other) + + def match(self, *args, **kwargs): + """Does this rrset match the specified attributes? + + Behaves as :py:func:`full_match()` if the first argument is a + ``dns.name.Name``, and as :py:func:`dns.rdataset.Rdataset.match()` + otherwise. + + (This behavior fixes a design mistake where the signature of this + method became incompatible with that of its superclass. The fix + makes RRsets matchable as Rdatasets while preserving backwards + compatibility.) + """ + if isinstance(args[0], dns.name.Name): + return self.full_match(*args, **kwargs) + else: + return super().match(*args, **kwargs) + + def full_match(self, name, rdclass, rdtype, covers, + deleting=None): + """Returns ``True`` if this rrset matches the specified name, class, + type, covers, and deletion state. + """ + if not super().match(rdclass, rdtype, covers): + return False + if self.name != name or self.deleting != deleting: + return False + return True + + # pylint: disable=arguments-differ + + def to_text(self, origin=None, relativize=True, **kw): + """Convert the RRset into DNS zone file format. + + See ``dns.name.Name.choose_relativity`` for more information + on how *origin* and *relativize* determine the way names + are emitted. + + Any additional keyword arguments are passed on to the rdata + ``to_text()`` method. + + *origin*, a ``dns.name.Name`` or ``None``, the origin for relative + names. + + *relativize*, a ``bool``. If ``True``, names will be relativized + to *origin*. + """ + + return super().to_text(self.name, origin, relativize, + self.deleting, **kw) + + def to_wire(self, file, compress=None, origin=None, + **kw): + """Convert the RRset to wire format. + + All keyword arguments are passed to ``dns.rdataset.to_wire()``; see + that function for details. + + Returns an ``int``, the number of records emitted. + """ + + return super().to_wire(self.name, file, compress, origin, + self.deleting, **kw) + + # pylint: enable=arguments-differ + + def to_rdataset(self): + """Convert an RRset into an Rdataset. + + Returns a ``dns.rdataset.Rdataset``. + """ + return dns.rdataset.from_rdata_list(self.ttl, list(self)) + + +def from_text_list(name, ttl, rdclass, rdtype, text_rdatas, + idna_codec=None, origin=None, relativize=True, + relativize_to=None): + """Create an RRset with the specified name, TTL, class, and type, and with + the specified list of rdatas in text format. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder to use; if ``None``, the default IDNA 2003 + encoder/decoder is used. + + *origin*, a ``dns.name.Name`` (or ``None``), the + origin to use for relative names. + + *relativize*, a ``bool``. If true, name will be relativized. + + *relativize_to*, a ``dns.name.Name`` (or ``None``), the origin to use + when relativizing names. If not set, the *origin* value will be used. + + Returns a ``dns.rrset.RRset`` object. + """ + + if isinstance(name, str): + name = dns.name.from_text(name, None, idna_codec=idna_codec) + rdclass = dns.rdataclass.RdataClass.make(rdclass) + rdtype = dns.rdatatype.RdataType.make(rdtype) + r = RRset(name, rdclass, rdtype) + r.update_ttl(ttl) + for t in text_rdatas: + rd = dns.rdata.from_text(r.rdclass, r.rdtype, t, origin, relativize, + relativize_to, idna_codec) + r.add(rd) + return r + + +def from_text(name, ttl, rdclass, rdtype, *text_rdatas): + """Create an RRset with the specified name, TTL, class, and type and with + the specified rdatas in text format. + + Returns a ``dns.rrset.RRset`` object. + """ + + return from_text_list(name, ttl, rdclass, rdtype, text_rdatas) + + +def from_rdata_list(name, ttl, rdatas, idna_codec=None): + """Create an RRset with the specified name and TTL, and with + the specified list of rdata objects. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder to use; if ``None``, the default IDNA 2003 + encoder/decoder is used. + + Returns a ``dns.rrset.RRset`` object. + + """ + + if isinstance(name, str): + name = dns.name.from_text(name, None, idna_codec=idna_codec) + + if len(rdatas) == 0: + raise ValueError("rdata list must not be empty") + r = None + for rd in rdatas: + if r is None: + r = RRset(name, rd.rdclass, rd.rdtype) + r.update_ttl(ttl) + r.add(rd) + return r + + +def from_rdata(name, ttl, *rdatas): + """Create an RRset with the specified name and TTL, and with + the specified rdata objects. + + Returns a ``dns.rrset.RRset`` object. + """ + + return from_rdata_list(name, ttl, rdatas) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/serial.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/serial.py new file mode 100644 index 0000000..b047415 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/serial.py @@ -0,0 +1,117 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +"""Serial Number Arthimetic from RFC 1982""" + +class Serial: + def __init__(self, value, bits=32): + self.value = value % 2 ** bits + self.bits = bits + + def __repr__(self): + return f'dns.serial.Serial({self.value}, {self.bits})' + + def __eq__(self, other): + if isinstance(other, int): + other = Serial(other, self.bits) + elif not isinstance(other, Serial) or other.bits != self.bits: + return NotImplemented + return self.value == other.value + + def __ne__(self, other): + if isinstance(other, int): + other = Serial(other, self.bits) + elif not isinstance(other, Serial) or other.bits != self.bits: + return NotImplemented + return self.value != other.value + + def __lt__(self, other): + if isinstance(other, int): + other = Serial(other, self.bits) + elif not isinstance(other, Serial) or other.bits != self.bits: + return NotImplemented + if self.value < other.value and \ + other.value - self.value < 2 ** (self.bits - 1): + return True + elif self.value > other.value and \ + self.value - other.value > 2 ** (self.bits - 1): + return True + else: + return False + + def __le__(self, other): + return self == other or self < other + + def __gt__(self, other): + if isinstance(other, int): + other = Serial(other, self.bits) + elif not isinstance(other, Serial) or other.bits != self.bits: + return NotImplemented + if self.value < other.value and \ + other.value - self.value > 2 ** (self.bits - 1): + return True + elif self.value > other.value and \ + self.value - other.value < 2 ** (self.bits - 1): + return True + else: + return False + + def __ge__(self, other): + return self == other or self > other + + def __add__(self, other): + v = self.value + if isinstance(other, Serial): + delta = other.value + elif isinstance(other, int): + delta = other + else: + raise ValueError + if abs(delta) > (2 ** (self.bits - 1) - 1): + raise ValueError + v += delta + v = v % 2 ** self.bits + return Serial(v, self.bits) + + def __iadd__(self, other): + v = self.value + if isinstance(other, Serial): + delta = other.value + elif isinstance(other, int): + delta = other + else: + raise ValueError + if abs(delta) > (2 ** (self.bits - 1) - 1): + raise ValueError + v += delta + v = v % 2 ** self.bits + self.value = v + return self + + def __sub__(self, other): + v = self.value + if isinstance(other, Serial): + delta = other.value + elif isinstance(other, int): + delta = other + else: + raise ValueError + if abs(delta) > (2 ** (self.bits - 1) - 1): + raise ValueError + v -= delta + v = v % 2 ** self.bits + return Serial(v, self.bits) + + def __isub__(self, other): + v = self.value + if isinstance(other, Serial): + delta = other.value + elif isinstance(other, int): + delta = other + else: + raise ValueError + if abs(delta) > (2 ** (self.bits - 1) - 1): + raise ValueError + v -= delta + v = v % 2 ** self.bits + self.value = v + return self diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/set.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/set.py new file mode 100644 index 0000000..1fd4d0a --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/set.py @@ -0,0 +1,278 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import itertools +import sys + +if sys.version_info >= (3, 7): + odict = dict +else: + from collections import OrderedDict as odict # pragma: no cover + +class Set: + + """A simple set class. + + This class was originally used to deal with sets being missing in + ancient versions of python, but dnspython will continue to use it + as these sets are based on lists and are thus indexable, and this + ability is widely used in dnspython applications. + """ + + __slots__ = ['items'] + + def __init__(self, items=None): + """Initialize the set. + + *items*, an iterable or ``None``, the initial set of items. + """ + + self.items = odict() + if items is not None: + for item in items: + self.add(item) + + def __repr__(self): + return "dns.set.Set(%s)" % repr(list(self.items.keys())) + + def add(self, item): + """Add an item to the set. + """ + + if item not in self.items: + self.items[item] = None + + def remove(self, item): + """Remove an item from the set. + """ + + try: + del self.items[item] + except KeyError: + raise ValueError + + def discard(self, item): + """Remove an item from the set if present. + """ + + self.items.pop(item, None) + + def _clone(self): + """Make a (shallow) copy of the set. + + There is a 'clone protocol' that subclasses of this class + should use. To make a copy, first call your super's _clone() + method, and use the object returned as the new instance. Then + make shallow copies of the attributes defined in the subclass. + + This protocol allows us to write the set algorithms that + return new instances (e.g. union) once, and keep using them in + subclasses. + """ + + if hasattr(self, '_clone_class'): + cls = self._clone_class + else: + cls = self.__class__ + obj = cls.__new__(cls) + obj.items = odict() + obj.items.update(self.items) + return obj + + def __copy__(self): + """Make a (shallow) copy of the set. + """ + + return self._clone() + + def copy(self): + """Make a (shallow) copy of the set. + """ + + return self._clone() + + def union_update(self, other): + """Update the set, adding any elements from other which are not + already in the set. + """ + + if not isinstance(other, Set): + raise ValueError('other must be a Set instance') + if self is other: + return + for item in other.items: + self.add(item) + + def intersection_update(self, other): + """Update the set, removing any elements from other which are not + in both sets. + """ + + if not isinstance(other, Set): + raise ValueError('other must be a Set instance') + if self is other: + return + # we make a copy of the list so that we can remove items from + # the list without breaking the iterator. + for item in list(self.items): + if item not in other.items: + del self.items[item] + + def difference_update(self, other): + """Update the set, removing any elements from other which are in + the set. + """ + + if not isinstance(other, Set): + raise ValueError('other must be a Set instance') + if self is other: + self.items.clear() + else: + for item in other.items: + self.discard(item) + + def union(self, other): + """Return a new set which is the union of ``self`` and ``other``. + + Returns the same Set type as this set. + """ + + obj = self._clone() + obj.union_update(other) + return obj + + def intersection(self, other): + """Return a new set which is the intersection of ``self`` and + ``other``. + + Returns the same Set type as this set. + """ + + obj = self._clone() + obj.intersection_update(other) + return obj + + def difference(self, other): + """Return a new set which ``self`` - ``other``, i.e. the items + in ``self`` which are not also in ``other``. + + Returns the same Set type as this set. + """ + + obj = self._clone() + obj.difference_update(other) + return obj + + def __or__(self, other): + return self.union(other) + + def __and__(self, other): + return self.intersection(other) + + def __add__(self, other): + return self.union(other) + + def __sub__(self, other): + return self.difference(other) + + def __ior__(self, other): + self.union_update(other) + return self + + def __iand__(self, other): + self.intersection_update(other) + return self + + def __iadd__(self, other): + self.union_update(other) + return self + + def __isub__(self, other): + self.difference_update(other) + return self + + def update(self, other): + """Update the set, adding any elements from other which are not + already in the set. + + *other*, the collection of items with which to update the set, which + may be any iterable type. + """ + + for item in other: + self.add(item) + + def clear(self): + """Make the set empty.""" + self.items.clear() + + def __eq__(self, other): + if odict == dict: + return self.items == other.items + else: + # We don't want an ordered comparison. + if len(self.items) != len(other.items): + return False + return all(elt in other.items for elt in self.items) + + def __ne__(self, other): + return not self.__eq__(other) + + def __len__(self): + return len(self.items) + + def __iter__(self): + return iter(self.items) + + def __getitem__(self, i): + if isinstance(i, slice): + return list(itertools.islice(self.items, i.start, i.stop, i.step)) + else: + return next(itertools.islice(self.items, i, i + 1)) + + def __delitem__(self, i): + if isinstance(i, slice): + for elt in list(self[i]): + del self.items[elt] + else: + del self.items[self[i]] + + def issubset(self, other): + """Is this set a subset of *other*? + + Returns a ``bool``. + """ + + if not isinstance(other, Set): + raise ValueError('other must be a Set instance') + for item in self.items: + if item not in other.items: + return False + return True + + def issuperset(self, other): + """Is this set a superset of *other*? + + Returns a ``bool``. + """ + + if not isinstance(other, Set): + raise ValueError('other must be a Set instance') + for item in other.items: + if item not in self.items: + return False + return True diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/tokenizer.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/tokenizer.py new file mode 100644 index 0000000..7ddc7a9 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/tokenizer.py @@ -0,0 +1,675 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Tokenize DNS zone file format""" + +import io +import sys + +import dns.exception +import dns.name +import dns.ttl + +_DELIMITERS = {' ', '\t', '\n', ';', '(', ')', '"'} +_QUOTING_DELIMITERS = {'"'} + +EOF = 0 +EOL = 1 +WHITESPACE = 2 +IDENTIFIER = 3 +QUOTED_STRING = 4 +COMMENT = 5 +DELIMITER = 6 + + +class UngetBufferFull(dns.exception.DNSException): + """An attempt was made to unget a token when the unget buffer was full.""" + + +class Token: + """A DNS zone file format token. + + ttype: The token type + value: The token value + has_escape: Does the token value contain escapes? + """ + + def __init__(self, ttype, value='', has_escape=False, comment=None): + """Initialize a token instance.""" + + self.ttype = ttype + self.value = value + self.has_escape = has_escape + self.comment = comment + + def is_eof(self): + return self.ttype == EOF + + def is_eol(self): + return self.ttype == EOL + + def is_whitespace(self): + return self.ttype == WHITESPACE + + def is_identifier(self): + return self.ttype == IDENTIFIER + + def is_quoted_string(self): + return self.ttype == QUOTED_STRING + + def is_comment(self): + return self.ttype == COMMENT + + def is_delimiter(self): # pragma: no cover (we don't return delimiters yet) + return self.ttype == DELIMITER + + def is_eol_or_eof(self): + return self.ttype == EOL or self.ttype == EOF + + def __eq__(self, other): + if not isinstance(other, Token): + return False + return (self.ttype == other.ttype and + self.value == other.value) + + def __ne__(self, other): + if not isinstance(other, Token): + return True + return (self.ttype != other.ttype or + self.value != other.value) + + def __str__(self): + return '%d "%s"' % (self.ttype, self.value) + + def unescape(self): + if not self.has_escape: + return self + unescaped = '' + l = len(self.value) + i = 0 + while i < l: + c = self.value[i] + i += 1 + if c == '\\': + if i >= l: # pragma: no cover (can't happen via get()) + raise dns.exception.UnexpectedEnd + c = self.value[i] + i += 1 + if c.isdigit(): + if i >= l: + raise dns.exception.UnexpectedEnd + c2 = self.value[i] + i += 1 + if i >= l: + raise dns.exception.UnexpectedEnd + c3 = self.value[i] + i += 1 + if not (c2.isdigit() and c3.isdigit()): + raise dns.exception.SyntaxError + codepoint = int(c) * 100 + int(c2) * 10 + int(c3) + if codepoint > 255: + raise dns.exception.SyntaxError + c = chr(codepoint) + unescaped += c + return Token(self.ttype, unescaped) + + def unescape_to_bytes(self): + # We used to use unescape() for TXT-like records, but this + # caused problems as we'd process DNS escapes into Unicode code + # points instead of byte values, and then a to_text() of the + # processed data would not equal the original input. For + # example, \226 in the TXT record would have a to_text() of + # \195\162 because we applied UTF-8 encoding to Unicode code + # point 226. + # + # We now apply escapes while converting directly to bytes, + # avoiding this double encoding. + # + # This code also handles cases where the unicode input has + # non-ASCII code-points in it by converting it to UTF-8. TXT + # records aren't defined for Unicode, but this is the best we + # can do to preserve meaning. For example, + # + # foo\u200bbar + # + # (where \u200b is Unicode code point 0x200b) will be treated + # as if the input had been the UTF-8 encoding of that string, + # namely: + # + # foo\226\128\139bar + # + unescaped = b'' + l = len(self.value) + i = 0 + while i < l: + c = self.value[i] + i += 1 + if c == '\\': + if i >= l: # pragma: no cover (can't happen via get()) + raise dns.exception.UnexpectedEnd + c = self.value[i] + i += 1 + if c.isdigit(): + if i >= l: + raise dns.exception.UnexpectedEnd + c2 = self.value[i] + i += 1 + if i >= l: + raise dns.exception.UnexpectedEnd + c3 = self.value[i] + i += 1 + if not (c2.isdigit() and c3.isdigit()): + raise dns.exception.SyntaxError + codepoint = int(c) * 100 + int(c2) * 10 + int(c3) + if codepoint > 255: + raise dns.exception.SyntaxError + unescaped += b'%c' % (codepoint) + else: + # Note that as mentioned above, if c is a Unicode + # code point outside of the ASCII range, then this + # += is converting that code point to its UTF-8 + # encoding and appending multiple bytes to + # unescaped. + unescaped += c.encode() + else: + unescaped += c.encode() + return Token(self.ttype, bytes(unescaped)) + + +class Tokenizer: + """A DNS zone file format tokenizer. + + A token object is basically a (type, value) tuple. The valid + types are EOF, EOL, WHITESPACE, IDENTIFIER, QUOTED_STRING, + COMMENT, and DELIMITER. + + file: The file to tokenize + + ungotten_char: The most recently ungotten character, or None. + + ungotten_token: The most recently ungotten token, or None. + + multiline: The current multiline level. This value is increased + by one every time a '(' delimiter is read, and decreased by one every time + a ')' delimiter is read. + + quoting: This variable is true if the tokenizer is currently + reading a quoted string. + + eof: This variable is true if the tokenizer has encountered EOF. + + delimiters: The current delimiter dictionary. + + line_number: The current line number + + filename: A filename that will be returned by the where() method. + + idna_codec: A dns.name.IDNACodec, specifies the IDNA + encoder/decoder. If None, the default IDNA 2003 + encoder/decoder is used. + """ + + def __init__(self, f=sys.stdin, filename=None, idna_codec=None): + """Initialize a tokenizer instance. + + f: The file to tokenize. The default is sys.stdin. + This parameter may also be a string, in which case the tokenizer + will take its input from the contents of the string. + + filename: the name of the filename that the where() method + will return. + + idna_codec: A dns.name.IDNACodec, specifies the IDNA + encoder/decoder. If None, the default IDNA 2003 + encoder/decoder is used. + """ + + if isinstance(f, str): + f = io.StringIO(f) + if filename is None: + filename = '' + elif isinstance(f, bytes): + f = io.StringIO(f.decode()) + if filename is None: + filename = '' + else: + if filename is None: + if f is sys.stdin: + filename = '' + else: + filename = '' + self.file = f + self.ungotten_char = None + self.ungotten_token = None + self.multiline = 0 + self.quoting = False + self.eof = False + self.delimiters = _DELIMITERS + self.line_number = 1 + self.filename = filename + if idna_codec is None: + idna_codec = dns.name.IDNA_2003 + self.idna_codec = idna_codec + + def _get_char(self): + """Read a character from input. + """ + + if self.ungotten_char is None: + if self.eof: + c = '' + else: + c = self.file.read(1) + if c == '': + self.eof = True + elif c == '\n': + self.line_number += 1 + else: + c = self.ungotten_char + self.ungotten_char = None + return c + + def where(self): + """Return the current location in the input. + + Returns a (string, int) tuple. The first item is the filename of + the input, the second is the current line number. + """ + + return (self.filename, self.line_number) + + def _unget_char(self, c): + """Unget a character. + + The unget buffer for characters is only one character large; it is + an error to try to unget a character when the unget buffer is not + empty. + + c: the character to unget + raises UngetBufferFull: there is already an ungotten char + """ + + if self.ungotten_char is not None: + # this should never happen! + raise UngetBufferFull # pragma: no cover + self.ungotten_char = c + + def skip_whitespace(self): + """Consume input until a non-whitespace character is encountered. + + The non-whitespace character is then ungotten, and the number of + whitespace characters consumed is returned. + + If the tokenizer is in multiline mode, then newlines are whitespace. + + Returns the number of characters skipped. + """ + + skipped = 0 + while True: + c = self._get_char() + if c != ' ' and c != '\t': + if (c != '\n') or not self.multiline: + self._unget_char(c) + return skipped + skipped += 1 + + def get(self, want_leading=False, want_comment=False): + """Get the next token. + + want_leading: If True, return a WHITESPACE token if the + first character read is whitespace. The default is False. + + want_comment: If True, return a COMMENT token if the + first token read is a comment. The default is False. + + Raises dns.exception.UnexpectedEnd: input ended prematurely + + Raises dns.exception.SyntaxError: input was badly formed + + Returns a Token. + """ + + if self.ungotten_token is not None: + token = self.ungotten_token + self.ungotten_token = None + if token.is_whitespace(): + if want_leading: + return token + elif token.is_comment(): + if want_comment: + return token + else: + return token + skipped = self.skip_whitespace() + if want_leading and skipped > 0: + return Token(WHITESPACE, ' ') + token = '' + ttype = IDENTIFIER + has_escape = False + while True: + c = self._get_char() + if c == '' or c in self.delimiters: + if c == '' and self.quoting: + raise dns.exception.UnexpectedEnd + if token == '' and ttype != QUOTED_STRING: + if c == '(': + self.multiline += 1 + self.skip_whitespace() + continue + elif c == ')': + if self.multiline <= 0: + raise dns.exception.SyntaxError + self.multiline -= 1 + self.skip_whitespace() + continue + elif c == '"': + if not self.quoting: + self.quoting = True + self.delimiters = _QUOTING_DELIMITERS + ttype = QUOTED_STRING + continue + else: + self.quoting = False + self.delimiters = _DELIMITERS + self.skip_whitespace() + continue + elif c == '\n': + return Token(EOL, '\n') + elif c == ';': + while 1: + c = self._get_char() + if c == '\n' or c == '': + break + token += c + if want_comment: + self._unget_char(c) + return Token(COMMENT, token) + elif c == '': + if self.multiline: + raise dns.exception.SyntaxError( + 'unbalanced parentheses') + return Token(EOF, comment=token) + elif self.multiline: + self.skip_whitespace() + token = '' + continue + else: + return Token(EOL, '\n', comment=token) + else: + # This code exists in case we ever want a + # delimiter to be returned. It never produces + # a token currently. + token = c + ttype = DELIMITER + else: + self._unget_char(c) + break + elif self.quoting and c == '\n': + raise dns.exception.SyntaxError('newline in quoted string') + elif c == '\\': + # + # It's an escape. Put it and the next character into + # the token; it will be checked later for goodness. + # + token += c + has_escape = True + c = self._get_char() + if c == '' or (c == '\n' and not self.quoting): + raise dns.exception.UnexpectedEnd + token += c + if token == '' and ttype != QUOTED_STRING: + if self.multiline: + raise dns.exception.SyntaxError('unbalanced parentheses') + ttype = EOF + return Token(ttype, token, has_escape) + + def unget(self, token): + """Unget a token. + + The unget buffer for tokens is only one token large; it is + an error to try to unget a token when the unget buffer is not + empty. + + token: the token to unget + + Raises UngetBufferFull: there is already an ungotten token + """ + + if self.ungotten_token is not None: + raise UngetBufferFull + self.ungotten_token = token + + def next(self): + """Return the next item in an iteration. + + Returns a Token. + """ + + token = self.get() + if token.is_eof(): + raise StopIteration + return token + + __next__ = next + + def __iter__(self): + return self + + # Helpers + + def get_int(self, base=10): + """Read the next token and interpret it as an unsigned integer. + + Raises dns.exception.SyntaxError if not an unsigned integer. + + Returns an int. + """ + + token = self.get().unescape() + if not token.is_identifier(): + raise dns.exception.SyntaxError('expecting an identifier') + if not token.value.isdigit(): + raise dns.exception.SyntaxError('expecting an integer') + return int(token.value, base) + + def get_uint8(self): + """Read the next token and interpret it as an 8-bit unsigned + integer. + + Raises dns.exception.SyntaxError if not an 8-bit unsigned integer. + + Returns an int. + """ + + value = self.get_int() + if value < 0 or value > 255: + raise dns.exception.SyntaxError( + '%d is not an unsigned 8-bit integer' % value) + return value + + def get_uint16(self, base=10): + """Read the next token and interpret it as a 16-bit unsigned + integer. + + Raises dns.exception.SyntaxError if not a 16-bit unsigned integer. + + Returns an int. + """ + + value = self.get_int(base=base) + if value < 0 or value > 65535: + if base == 8: + raise dns.exception.SyntaxError( + '%o is not an octal unsigned 16-bit integer' % value) + else: + raise dns.exception.SyntaxError( + '%d is not an unsigned 16-bit integer' % value) + return value + + def get_uint32(self, base=10): + """Read the next token and interpret it as a 32-bit unsigned + integer. + + Raises dns.exception.SyntaxError if not a 32-bit unsigned integer. + + Returns an int. + """ + + value = self.get_int(base=base) + if value < 0 or value > 4294967295: + raise dns.exception.SyntaxError( + '%d is not an unsigned 32-bit integer' % value) + return value + + def get_uint48(self, base=10): + """Read the next token and interpret it as a 48-bit unsigned + integer. + + Raises dns.exception.SyntaxError if not a 48-bit unsigned integer. + + Returns an int. + """ + + value = self.get_int(base=base) + if value < 0 or value > 281474976710655: + raise dns.exception.SyntaxError( + '%d is not an unsigned 48-bit integer' % value) + return value + + def get_string(self, max_length=None): + """Read the next token and interpret it as a string. + + Raises dns.exception.SyntaxError if not a string. + Raises dns.exception.SyntaxError if token value length + exceeds max_length (if specified). + + Returns a string. + """ + + token = self.get().unescape() + if not (token.is_identifier() or token.is_quoted_string()): + raise dns.exception.SyntaxError('expecting a string') + if max_length and len(token.value) > max_length: + raise dns.exception.SyntaxError("string too long") + return token.value + + def get_identifier(self): + """Read the next token, which should be an identifier. + + Raises dns.exception.SyntaxError if not an identifier. + + Returns a string. + """ + + token = self.get().unescape() + if not token.is_identifier(): + raise dns.exception.SyntaxError('expecting an identifier') + return token.value + + def get_remaining(self, max_tokens=None): + """Return the remaining tokens on the line, until an EOL or EOF is seen. + + max_tokens: If not None, stop after this number of tokens. + + Returns a list of tokens. + """ + + tokens = [] + while True: + token = self.get() + if token.is_eol_or_eof(): + self.unget(token) + break + tokens.append(token) + if len(tokens) == max_tokens: + break + return tokens + + def concatenate_remaining_identifiers(self): + """Read the remaining tokens on the line, which should be identifiers. + + Raises dns.exception.SyntaxError if a token is seen that is not an + identifier. + + Returns a string containing a concatenation of the remaining + identifiers. + """ + s = "" + while True: + token = self.get().unescape() + if token.is_eol_or_eof(): + self.unget(token) + break + if not token.is_identifier(): + raise dns.exception.SyntaxError + s += token.value + return s + + def as_name(self, token, origin=None, relativize=False, relativize_to=None): + """Try to interpret the token as a DNS name. + + Raises dns.exception.SyntaxError if not a name. + + Returns a dns.name.Name. + """ + if not token.is_identifier(): + raise dns.exception.SyntaxError('expecting an identifier') + name = dns.name.from_text(token.value, origin, self.idna_codec) + return name.choose_relativity(relativize_to or origin, relativize) + + def get_name(self, origin=None, relativize=False, relativize_to=None): + """Read the next token and interpret it as a DNS name. + + Raises dns.exception.SyntaxError if not a name. + + Returns a dns.name.Name. + """ + + token = self.get() + return self.as_name(token, origin, relativize, relativize_to) + + def get_eol_as_token(self): + """Read the next token and raise an exception if it isn't EOL or + EOF. + + Returns a string. + """ + + token = self.get() + if not token.is_eol_or_eof(): + raise dns.exception.SyntaxError( + 'expected EOL or EOF, got %d "%s"' % (token.ttype, + token.value)) + return token + + def get_eol(self): + return self.get_eol_as_token().value + + def get_ttl(self): + """Read the next token and interpret it as a DNS TTL. + + Raises dns.exception.SyntaxError or dns.ttl.BadTTL if not an + identifier or badly formed. + + Returns an int. + """ + + token = self.get().unescape() + if not token.is_identifier(): + raise dns.exception.SyntaxError('expecting an identifier') + return dns.ttl.from_text(token.value) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/transaction.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/transaction.py new file mode 100644 index 0000000..8aec2e8 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/transaction.py @@ -0,0 +1,512 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import collections + +import dns.exception +import dns.name +import dns.rdataclass +import dns.rdataset +import dns.rdatatype +import dns.rrset +import dns.serial +import dns.ttl + + +class TransactionManager: + def reader(self): + """Begin a read-only transaction.""" + raise NotImplementedError # pragma: no cover + + def writer(self, replacement=False): + """Begin a writable transaction. + + *replacement*, a ``bool``. If `True`, the content of the + transaction completely replaces any prior content. If False, + the default, then the content of the transaction updates the + existing content. + """ + raise NotImplementedError # pragma: no cover + + def origin_information(self): + """Returns a tuple + + (absolute_origin, relativize, effective_origin) + + giving the absolute name of the default origin for any + relative domain names, the "effective origin", and whether + names should be relativized. The "effective origin" is the + absolute origin if relativize is False, and the empty name if + relativize is true. (The effective origin is provided even + though it can be computed from the absolute_origin and + relativize setting because it avoids a lot of code + duplication.) + + If the returned names are `None`, then no origin information is + available. + + This information is used by code working with transactions to + allow it to coordinate relativization. The transaction code + itself takes what it gets (i.e. does not change name + relativity). + + """ + raise NotImplementedError # pragma: no cover + + def get_class(self): + """The class of the transaction manager. + """ + raise NotImplementedError # pragma: no cover + + def from_wire_origin(self): + """Origin to use in from_wire() calls. + """ + (absolute_origin, relativize, _) = self.origin_information() + if relativize: + return absolute_origin + else: + return None + + +class DeleteNotExact(dns.exception.DNSException): + """Existing data did not match data specified by an exact delete.""" + + +class ReadOnly(dns.exception.DNSException): + """Tried to write to a read-only transaction.""" + + +class AlreadyEnded(dns.exception.DNSException): + """Tried to use an already-ended transaction.""" + + +class Transaction: + + def __init__(self, manager, replacement=False, read_only=False): + self.manager = manager + self.replacement = replacement + self.read_only = read_only + self._ended = False + + # + # This is the high level API + # + + def get(self, name, rdtype, covers=dns.rdatatype.NONE): + """Return the rdataset associated with *name*, *rdtype*, and *covers*, + or `None` if not found. + + Note that the returned rdataset is immutable. + """ + self._check_ended() + if isinstance(name, str): + name = dns.name.from_text(name, None) + rdtype = dns.rdatatype.RdataType.make(rdtype) + rdataset = self._get_rdataset(name, rdtype, covers) + if rdataset is not None and \ + not isinstance(rdataset, dns.rdataset.ImmutableRdataset): + rdataset = dns.rdataset.ImmutableRdataset(rdataset) + return rdataset + + def _check_read_only(self): + if self.read_only: + raise ReadOnly + + def add(self, *args): + """Add records. + + The arguments may be: + + - rrset + + - name, rdataset... + + - name, ttl, rdata... + """ + self._check_ended() + self._check_read_only() + return self._add(False, args) + + def replace(self, *args): + """Replace the existing rdataset at the name with the specified + rdataset, or add the specified rdataset if there was no existing + rdataset. + + The arguments may be: + + - rrset + + - name, rdataset... + + - name, ttl, rdata... + + Note that if you want to replace the entire node, you should do + a delete of the name followed by one or more calls to add() or + replace(). + """ + self._check_ended() + self._check_read_only() + return self._add(True, args) + + def delete(self, *args): + """Delete records. + + It is not an error if some of the records are not in the existing + set. + + The arguments may be: + + - rrset + + - name + + - name, rdataclass, rdatatype, [covers] + + - name, rdataset... + + - name, rdata... + """ + self._check_ended() + self._check_read_only() + return self._delete(False, args) + + def delete_exact(self, *args): + """Delete records. + + The arguments may be: + + - rrset + + - name + + - name, rdataclass, rdatatype, [covers] + + - name, rdataset... + + - name, rdata... + + Raises dns.transaction.DeleteNotExact if some of the records + are not in the existing set. + + """ + self._check_ended() + self._check_read_only() + return self._delete(True, args) + + def name_exists(self, name): + """Does the specified name exist?""" + self._check_ended() + if isinstance(name, str): + name = dns.name.from_text(name, None) + return self._name_exists(name) + + def update_serial(self, value=1, relative=True, name=dns.name.empty): + """Update the serial number. + + *value*, an `int`, is an increment if *relative* is `True`, or the + actual value to set if *relative* is `False`. + + Raises `KeyError` if there is no SOA rdataset at *name*. + + Raises `ValueError` if *value* is negative or if the increment is + so large that it would cause the new serial to be less than the + prior value. + """ + self._check_ended() + if value < 0: + raise ValueError('negative update_serial() value') + if isinstance(name, str): + name = dns.name.from_text(name, None) + rdataset = self._get_rdataset(name, dns.rdatatype.SOA, + dns.rdatatype.NONE) + if rdataset is None or len(rdataset) == 0: + raise KeyError + if relative: + serial = dns.serial.Serial(rdataset[0].serial) + value + else: + serial = dns.serial.Serial(value) + serial = serial.value # convert back to int + if serial == 0: + serial = 1 + rdata = rdataset[0].replace(serial=serial) + new_rdataset = dns.rdataset.from_rdata(rdataset.ttl, rdata) + self.replace(name, new_rdataset) + + def __iter__(self): + self._check_ended() + return self._iterate_rdatasets() + + def changed(self): + """Has this transaction changed anything? + + For read-only transactions, the result is always `False`. + + For writable transactions, the result is `True` if at some time + during the life of the transaction, the content was changed. + """ + self._check_ended() + return self._changed() + + def commit(self): + """Commit the transaction. + + Normally transactions are used as context managers and commit + or rollback automatically, but it may be done explicitly if needed. + A ``dns.transaction.Ended`` exception will be raised if you try + to use a transaction after it has been committed or rolled back. + + Raises an exception if the commit fails (in which case the transaction + is also rolled back. + """ + self._end(True) + + def rollback(self): + """Rollback the transaction. + + Normally transactions are used as context managers and commit + or rollback automatically, but it may be done explicitly if needed. + A ``dns.transaction.AlreadyEnded`` exception will be raised if you try + to use a transaction after it has been committed or rolled back. + + Rollback cannot otherwise fail. + """ + self._end(False) + + # + # Helper methods + # + + def _raise_if_not_empty(self, method, args): + if len(args) != 0: + raise TypeError(f'extra parameters to {method}') + + def _rdataset_from_args(self, method, deleting, args): + try: + arg = args.popleft() + if isinstance(arg, dns.rrset.RRset): + rdataset = arg.to_rdataset() + elif isinstance(arg, dns.rdataset.Rdataset): + rdataset = arg + else: + if deleting: + ttl = 0 + else: + if isinstance(arg, int): + ttl = arg + if ttl > dns.ttl.MAX_TTL: + raise ValueError(f'{method}: TTL value too big') + else: + raise TypeError(f'{method}: expected a TTL') + arg = args.popleft() + if isinstance(arg, dns.rdata.Rdata): + rdataset = dns.rdataset.from_rdata(ttl, arg) + else: + raise TypeError(f'{method}: expected an Rdata') + return rdataset + except IndexError: + if deleting: + return None + else: + # reraise + raise TypeError(f'{method}: expected more arguments') + + def _add(self, replace, args): + try: + args = collections.deque(args) + if replace: + method = 'replace()' + else: + method = 'add()' + arg = args.popleft() + if isinstance(arg, str): + arg = dns.name.from_text(arg, None) + if isinstance(arg, dns.name.Name): + name = arg + rdataset = self._rdataset_from_args(method, False, args) + elif isinstance(arg, dns.rrset.RRset): + rrset = arg + name = rrset.name + # rrsets are also rdatasets, but they don't print the + # same and can't be stored in nodes, so convert. + rdataset = rrset.to_rdataset() + else: + raise TypeError(f'{method} requires a name or RRset ' + + 'as the first argument') + if rdataset.rdclass != self.manager.get_class(): + raise ValueError(f'{method} has objects of wrong RdataClass') + if rdataset.rdtype == dns.rdatatype.SOA: + (_, _, origin) = self.manager.origin_information() + if name != origin: + raise ValueError(f'{method} has non-origin SOA') + self._raise_if_not_empty(method, args) + if not replace: + existing = self._get_rdataset(name, rdataset.rdtype, + rdataset.covers) + if existing is not None: + if isinstance(existing, dns.rdataset.ImmutableRdataset): + trds = dns.rdataset.Rdataset(existing.rdclass, + existing.rdtype, + existing.covers) + trds.update(existing) + existing = trds + rdataset = existing.union(rdataset) + self._put_rdataset(name, rdataset) + except IndexError: + raise TypeError(f'not enough parameters to {method}') + + def _delete(self, exact, args): + try: + args = collections.deque(args) + if exact: + method = 'delete_exact()' + else: + method = 'delete()' + arg = args.popleft() + if isinstance(arg, str): + arg = dns.name.from_text(arg, None) + if isinstance(arg, dns.name.Name): + name = arg + if len(args) > 0 and (isinstance(args[0], int) or + isinstance(args[0], str)): + # deleting by type and (optionally) covers + rdtype = dns.rdatatype.RdataType.make(args.popleft()) + if len(args) > 0: + covers = dns.rdatatype.RdataType.make(args.popleft()) + else: + covers = dns.rdatatype.NONE + self._raise_if_not_empty(method, args) + existing = self._get_rdataset(name, rdtype, covers) + if existing is None: + if exact: + raise DeleteNotExact(f'{method}: missing rdataset') + else: + self._delete_rdataset(name, rdtype, covers) + return + else: + rdataset = self._rdataset_from_args(method, True, args) + elif isinstance(arg, dns.rrset.RRset): + rdataset = arg # rrsets are also rdatasets + name = rdataset.name + else: + raise TypeError(f'{method} requires a name or RRset ' + + 'as the first argument') + self._raise_if_not_empty(method, args) + if rdataset: + if rdataset.rdclass != self.manager.get_class(): + raise ValueError(f'{method} has objects of wrong ' + 'RdataClass') + existing = self._get_rdataset(name, rdataset.rdtype, + rdataset.covers) + if existing is not None: + if exact: + intersection = existing.intersection(rdataset) + if intersection != rdataset: + raise DeleteNotExact(f'{method}: missing rdatas') + rdataset = existing.difference(rdataset) + if len(rdataset) == 0: + self._delete_rdataset(name, rdataset.rdtype, + rdataset.covers) + else: + self._put_rdataset(name, rdataset) + elif exact: + raise DeleteNotExact(f'{method}: missing rdataset') + else: + if exact and not self._name_exists(name): + raise DeleteNotExact(f'{method}: name not known') + self._delete_name(name) + except IndexError: + raise TypeError(f'not enough parameters to {method}') + + def _check_ended(self): + if self._ended: + raise AlreadyEnded + + def _end(self, commit): + self._check_ended() + if self._ended: + raise AlreadyEnded + try: + self._end_transaction(commit) + finally: + self._ended = True + + # + # Transactions are context managers. + # + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + if not self._ended: + if exc_type is None: + self.commit() + else: + self.rollback() + return False + + # + # This is the low level API, which must be implemented by subclasses + # of Transaction. + # + + def _get_rdataset(self, name, rdtype, covers): + """Return the rdataset associated with *name*, *rdtype*, and *covers*, + or `None` if not found. + """ + raise NotImplementedError # pragma: no cover + + def _put_rdataset(self, name, rdataset): + """Store the rdataset.""" + raise NotImplementedError # pragma: no cover + + def _delete_name(self, name): + """Delete all data associated with *name*. + + It is not an error if the rdataset does not exist. + """ + raise NotImplementedError # pragma: no cover + + def _delete_rdataset(self, name, rdtype, covers): + """Delete all data associated with *name*, *rdtype*, and *covers*. + + It is not an error if the rdataset does not exist. + """ + raise NotImplementedError # pragma: no cover + + def _name_exists(self, name): + """Does name exist? + + Returns a bool. + """ + raise NotImplementedError # pragma: no cover + + def _changed(self): + """Has this transaction changed anything?""" + raise NotImplementedError # pragma: no cover + + def _end_transaction(self, commit): + """End the transaction. + + *commit*, a bool. If ``True``, commit the transaction, otherwise + roll it back. + + If committing adn the commit fails, then roll back and raise an + exception. + """ + raise NotImplementedError # pragma: no cover + + def _set_origin(self, origin): + """Set the origin. + + This method is called when reading a possibly relativized + source, and an origin setting operation occurs (e.g. $ORIGIN + in a zone file). + """ + raise NotImplementedError # pragma: no cover + + def _iterate_rdatasets(self): + """Return an iterator that yields (name, rdataset) tuples. + + Not all Transaction subclasses implement this. + """ + raise NotImplementedError # pragma: no cover diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/tsig.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/tsig.py new file mode 100644 index 0000000..5c773ff --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/tsig.py @@ -0,0 +1,343 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS TSIG support.""" + +import base64 +import hashlib +import hmac +import struct + +import dns.exception +import dns.rdataclass +import dns.name +import dns.rcode + +class BadTime(dns.exception.DNSException): + + """The current time is not within the TSIG's validity time.""" + + +class BadSignature(dns.exception.DNSException): + + """The TSIG signature fails to verify.""" + + +class BadKey(dns.exception.DNSException): + + """The TSIG record owner name does not match the key.""" + + +class BadAlgorithm(dns.exception.DNSException): + + """The TSIG algorithm does not match the key.""" + + +class PeerError(dns.exception.DNSException): + + """Base class for all TSIG errors generated by the remote peer""" + + +class PeerBadKey(PeerError): + + """The peer didn't know the key we used""" + + +class PeerBadSignature(PeerError): + + """The peer didn't like the signature we sent""" + + +class PeerBadTime(PeerError): + + """The peer didn't like the time we sent""" + + +class PeerBadTruncation(PeerError): + + """The peer didn't like amount of truncation in the TSIG we sent""" + + +# TSIG Algorithms + +HMAC_MD5 = dns.name.from_text("HMAC-MD5.SIG-ALG.REG.INT") +HMAC_SHA1 = dns.name.from_text("hmac-sha1") +HMAC_SHA224 = dns.name.from_text("hmac-sha224") +HMAC_SHA256 = dns.name.from_text("hmac-sha256") +HMAC_SHA256_128 = dns.name.from_text("hmac-sha256-128") +HMAC_SHA384 = dns.name.from_text("hmac-sha384") +HMAC_SHA384_192 = dns.name.from_text("hmac-sha384-192") +HMAC_SHA512 = dns.name.from_text("hmac-sha512") +HMAC_SHA512_256 = dns.name.from_text("hmac-sha512-256") +GSS_TSIG = dns.name.from_text("gss-tsig") + +default_algorithm = HMAC_SHA256 + + +class GSSTSig: + """ + GSS-TSIG TSIG implementation. This uses the GSS-API context established + in the TKEY message handshake to sign messages using GSS-API message + integrity codes, per the RFC. + + In order to avoid a direct GSSAPI dependency, the keyring holds a ref + to the GSSAPI object required, rather than the key itself. + """ + def __init__(self, gssapi_context): + self.gssapi_context = gssapi_context + self.data = b'' + self.name = 'gss-tsig' + + def update(self, data): + self.data += data + + def sign(self): + # defer to the GSSAPI function to sign + return self.gssapi_context.get_signature(self.data) + + def verify(self, expected): + try: + # defer to the GSSAPI function to verify + return self.gssapi_context.verify_signature(self.data, expected) + except Exception: + # note the usage of a bare exception + raise BadSignature + + +class GSSTSigAdapter: + def __init__(self, keyring): + self.keyring = keyring + + def __call__(self, message, keyname): + if keyname in self.keyring: + key = self.keyring[keyname] + if isinstance(key, Key) and key.algorithm == GSS_TSIG: + if message: + GSSTSigAdapter.parse_tkey_and_step(key, message, keyname) + return key + else: + return None + + @classmethod + def parse_tkey_and_step(cls, key, message, keyname): + # if the message is a TKEY type, absorb the key material + # into the context using step(); this is used to allow the + # client to complete the GSSAPI negotiation before attempting + # to verify the signed response to a TKEY message exchange + try: + rrset = message.find_rrset(message.answer, keyname, + dns.rdataclass.ANY, + dns.rdatatype.TKEY) + if rrset: + token = rrset[0].key + gssapi_context = key.secret + return gssapi_context.step(token) + except KeyError: + pass + + +class HMACTSig: + """ + HMAC TSIG implementation. This uses the HMAC python module to handle the + sign/verify operations. + """ + + _hashes = { + HMAC_SHA1: hashlib.sha1, + HMAC_SHA224: hashlib.sha224, + HMAC_SHA256: hashlib.sha256, + HMAC_SHA256_128: (hashlib.sha256, 128), + HMAC_SHA384: hashlib.sha384, + HMAC_SHA384_192: (hashlib.sha384, 192), + HMAC_SHA512: hashlib.sha512, + HMAC_SHA512_256: (hashlib.sha512, 256), + HMAC_MD5: hashlib.md5, + } + + def __init__(self, key, algorithm): + try: + hashinfo = self._hashes[algorithm] + except KeyError: + raise NotImplementedError(f"TSIG algorithm {algorithm} " + + "is not supported") + + # create the HMAC context + if isinstance(hashinfo, tuple): + self.hmac_context = hmac.new(key, digestmod=hashinfo[0]) + self.size = hashinfo[1] + else: + self.hmac_context = hmac.new(key, digestmod=hashinfo) + self.size = None + self.name = self.hmac_context.name + if self.size: + self.name += f'-{self.size}' + + def update(self, data): + return self.hmac_context.update(data) + + def sign(self): + # defer to the HMAC digest() function for that digestmod + digest = self.hmac_context.digest() + if self.size: + digest = digest[: (self.size // 8)] + return digest + + def verify(self, expected): + # re-digest and compare the results + mac = self.sign() + if not hmac.compare_digest(mac, expected): + raise BadSignature + + +def _digest(wire, key, rdata, time=None, request_mac=None, ctx=None, + multi=None): + """Return a context containing the TSIG rdata for the input parameters + @rtype: dns.tsig.HMACTSig or dns.tsig.GSSTSig object + @raises ValueError: I{other_data} is too long + @raises NotImplementedError: I{algorithm} is not supported + """ + + first = not (ctx and multi) + if first: + ctx = get_context(key) + if request_mac: + ctx.update(struct.pack('!H', len(request_mac))) + ctx.update(request_mac) + ctx.update(struct.pack('!H', rdata.original_id)) + ctx.update(wire[2:]) + if first: + ctx.update(key.name.to_digestable()) + ctx.update(struct.pack('!H', dns.rdataclass.ANY)) + ctx.update(struct.pack('!I', 0)) + if time is None: + time = rdata.time_signed + upper_time = (time >> 32) & 0xffff + lower_time = time & 0xffffffff + time_encoded = struct.pack('!HIH', upper_time, lower_time, rdata.fudge) + other_len = len(rdata.other) + if other_len > 65535: + raise ValueError('TSIG Other Data is > 65535 bytes') + if first: + ctx.update(key.algorithm.to_digestable() + time_encoded) + ctx.update(struct.pack('!HH', rdata.error, other_len) + rdata.other) + else: + ctx.update(time_encoded) + return ctx + + +def _maybe_start_digest(key, mac, multi): + """If this is the first message in a multi-message sequence, + start a new context. + @rtype: dns.tsig.HMACTSig or dns.tsig.GSSTSig object + """ + if multi: + ctx = get_context(key) + ctx.update(struct.pack('!H', len(mac))) + ctx.update(mac) + return ctx + else: + return None + + +def sign(wire, key, rdata, time=None, request_mac=None, ctx=None, multi=False): + """Return a (tsig_rdata, mac, ctx) tuple containing the HMAC TSIG rdata + for the input parameters, the HMAC MAC calculated by applying the + TSIG signature algorithm, and the TSIG digest context. + @rtype: (string, dns.tsig.HMACTSig or dns.tsig.GSSTSig object) + @raises ValueError: I{other_data} is too long + @raises NotImplementedError: I{algorithm} is not supported + """ + + ctx = _digest(wire, key, rdata, time, request_mac, ctx, multi) + mac = ctx.sign() + tsig = rdata.replace(time_signed=time, mac=mac) + + return (tsig, _maybe_start_digest(key, mac, multi)) + + +def validate(wire, key, owner, rdata, now, request_mac, tsig_start, ctx=None, + multi=False): + """Validate the specified TSIG rdata against the other input parameters. + + @raises FormError: The TSIG is badly formed. + @raises BadTime: There is too much time skew between the client and the + server. + @raises BadSignature: The TSIG signature did not validate + @rtype: dns.tsig.HMACTSig or dns.tsig.GSSTSig object""" + + (adcount,) = struct.unpack("!H", wire[10:12]) + if adcount == 0: + raise dns.exception.FormError + adcount -= 1 + new_wire = wire[0:10] + struct.pack("!H", adcount) + wire[12:tsig_start] + if rdata.error != 0: + if rdata.error == dns.rcode.BADSIG: + raise PeerBadSignature + elif rdata.error == dns.rcode.BADKEY: + raise PeerBadKey + elif rdata.error == dns.rcode.BADTIME: + raise PeerBadTime + elif rdata.error == dns.rcode.BADTRUNC: + raise PeerBadTruncation + else: + raise PeerError('unknown TSIG error code %d' % rdata.error) + if abs(rdata.time_signed - now) > rdata.fudge: + raise BadTime + if key.name != owner: + raise BadKey + if key.algorithm != rdata.algorithm: + raise BadAlgorithm + ctx = _digest(new_wire, key, rdata, None, request_mac, ctx, multi) + ctx.verify(rdata.mac) + return _maybe_start_digest(key, rdata.mac, multi) + + +def get_context(key): + """Returns an HMAC context for the specified key. + + @rtype: HMAC context + @raises NotImplementedError: I{algorithm} is not supported + """ + + if key.algorithm == GSS_TSIG: + return GSSTSig(key.secret) + else: + return HMACTSig(key.secret, key.algorithm) + + +class Key: + def __init__(self, name, secret, algorithm=default_algorithm): + if isinstance(name, str): + name = dns.name.from_text(name) + self.name = name + if isinstance(secret, str): + secret = base64.decodebytes(secret.encode()) + self.secret = secret + if isinstance(algorithm, str): + algorithm = dns.name.from_text(algorithm) + self.algorithm = algorithm + + def __eq__(self, other): + return (isinstance(other, Key) and + self.name == other.name and + self.secret == other.secret and + self.algorithm == other.algorithm) + + def __repr__(self): + return f"" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/tsigkeyring.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/tsigkeyring.py new file mode 100644 index 0000000..47a1f79 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/tsigkeyring.py @@ -0,0 +1,64 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""A place to store TSIG keys.""" + +import base64 + +import dns.name + + +def from_text(textring): + """Convert a dictionary containing (textual DNS name, base64 secret) + pairs into a binary keyring which has (dns.name.Name, bytes) pairs, or + a dictionary containing (textual DNS name, (algorithm, base64 secret)) + pairs into a binary keyring which has (dns.name.Name, dns.tsig.Key) pairs. + @rtype: dict""" + + keyring = {} + for (name, value) in textring.items(): + name = dns.name.from_text(name) + if isinstance(value, str): + keyring[name] = dns.tsig.Key(name, value).secret + else: + (algorithm, secret) = value + keyring[name] = dns.tsig.Key(name, secret, algorithm) + return keyring + + +def to_text(keyring): + """Convert a dictionary containing (dns.name.Name, dns.tsig.Key) pairs + into a text keyring which has (textual DNS name, (textual algorithm, + base64 secret)) pairs, or a dictionary containing (dns.name.Name, bytes) + pairs into a text keyring which has (textual DNS name, base64 secret) pairs. + @rtype: dict""" + + textring = {} + def b64encode(secret): + return base64.encodebytes(secret).decode().rstrip() + for (name, key) in keyring.items(): + name = name.to_text() + if isinstance(key, bytes): + textring[name] = b64encode(key) + else: + if isinstance(key.secret, bytes): + text_secret = b64encode(key.secret) + else: + text_secret = str(key.secret) + + textring[name] = (key.algorithm.to_text(), text_secret) + return textring diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/ttl.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/ttl.py new file mode 100644 index 0000000..8ea5213 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/ttl.py @@ -0,0 +1,84 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS TTL conversion.""" + +import dns.exception + +MAX_TTL = 2147483647 + +class BadTTL(dns.exception.SyntaxError): + """DNS TTL value is not well-formed.""" + + +def from_text(text): + """Convert the text form of a TTL to an integer. + + The BIND 8 units syntax for TTLs (e.g. '1w6d4h3m10s') is supported. + + *text*, a ``str``, the textual TTL. + + Raises ``dns.ttl.BadTTL`` if the TTL is not well-formed. + + Returns an ``int``. + """ + + if text.isdigit(): + total = int(text) + elif len(text) == 0: + raise BadTTL + else: + total = 0 + current = 0 + need_digit = True + for c in text: + if c.isdigit(): + current *= 10 + current += int(c) + need_digit = False + else: + if need_digit: + raise BadTTL + c = c.lower() + if c == 'w': + total += current * 604800 + elif c == 'd': + total += current * 86400 + elif c == 'h': + total += current * 3600 + elif c == 'm': + total += current * 60 + elif c == 's': + total += current + else: + raise BadTTL("unknown unit '%s'" % c) + current = 0 + need_digit = True + if not current == 0: + raise BadTTL("trailing integer") + if total < 0 or total > MAX_TTL: + raise BadTTL("TTL should be between 0 and 2^31 - 1 (inclusive)") + return total + + +def make(value): + if isinstance(value, int): + return value + elif isinstance(value, str): + return dns.ttl.from_text(value) + else: + raise ValueError('cannot convert value to TTL') diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/update.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/update.py new file mode 100644 index 0000000..a541af2 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/update.py @@ -0,0 +1,319 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Dynamic Update Support""" + + +import dns.message +import dns.name +import dns.opcode +import dns.rdata +import dns.rdataclass +import dns.rdataset +import dns.tsig + + +class UpdateSection(dns.enum.IntEnum): + """Update sections""" + ZONE = 0 + PREREQ = 1 + UPDATE = 2 + ADDITIONAL = 3 + + @classmethod + def _maximum(cls): + return 3 + + +class UpdateMessage(dns.message.Message): + + _section_enum = UpdateSection + + def __init__(self, zone=None, rdclass=dns.rdataclass.IN, keyring=None, + keyname=None, keyalgorithm=dns.tsig.default_algorithm, + id=None): + """Initialize a new DNS Update object. + + See the documentation of the Message class for a complete + description of the keyring dictionary. + + *zone*, a ``dns.name.Name``, ``str``, or ``None``, the zone + which is being updated. ``None`` should only be used by dnspython's + message constructors, as a zone is required for the convenience + methods like ``add()``, ``replace()``, etc. + + *rdclass*, an ``int`` or ``str``, the class of the zone. + + The *keyring*, *keyname*, and *keyalgorithm* parameters are passed to + ``use_tsig()``; see its documentation for details. + """ + super().__init__(id=id) + self.flags |= dns.opcode.to_flags(dns.opcode.UPDATE) + if isinstance(zone, str): + zone = dns.name.from_text(zone) + self.origin = zone + rdclass = dns.rdataclass.RdataClass.make(rdclass) + self.zone_rdclass = rdclass + if self.origin: + self.find_rrset(self.zone, self.origin, rdclass, dns.rdatatype.SOA, + create=True, force_unique=True) + if keyring is not None: + self.use_tsig(keyring, keyname, algorithm=keyalgorithm) + + @property + def zone(self): + """The zone section.""" + return self.sections[0] + + @zone.setter + def zone(self, v): + self.sections[0] = v + + @property + def prerequisite(self): + """The prerequisite section.""" + return self.sections[1] + + @prerequisite.setter + def prerequisite(self, v): + self.sections[1] = v + + @property + def update(self): + """The update section.""" + return self.sections[2] + + @update.setter + def update(self, v): + self.sections[2] = v + + def _add_rr(self, name, ttl, rd, deleting=None, section=None): + """Add a single RR to the update section.""" + + if section is None: + section = self.update + covers = rd.covers() + rrset = self.find_rrset(section, name, self.zone_rdclass, rd.rdtype, + covers, deleting, True, True) + rrset.add(rd, ttl) + + def _add(self, replace, section, name, *args): + """Add records. + + *replace* is the replacement mode. If ``False``, + RRs are added to an existing RRset; if ``True``, the RRset + is replaced with the specified contents. The second + argument is the section to add to. The third argument + is always a name. The other arguments can be: + + - rdataset... + + - ttl, rdata... + + - ttl, rdtype, string... + """ + + if isinstance(name, str): + name = dns.name.from_text(name, None) + if isinstance(args[0], dns.rdataset.Rdataset): + for rds in args: + if replace: + self.delete(name, rds.rdtype) + for rd in rds: + self._add_rr(name, rds.ttl, rd, section=section) + else: + args = list(args) + ttl = int(args.pop(0)) + if isinstance(args[0], dns.rdata.Rdata): + if replace: + self.delete(name, args[0].rdtype) + for rd in args: + self._add_rr(name, ttl, rd, section=section) + else: + rdtype = dns.rdatatype.RdataType.make(args.pop(0)) + if replace: + self.delete(name, rdtype) + for s in args: + rd = dns.rdata.from_text(self.zone_rdclass, rdtype, s, + self.origin) + self._add_rr(name, ttl, rd, section=section) + + def add(self, name, *args): + """Add records. + + The first argument is always a name. The other + arguments can be: + + - rdataset... + + - ttl, rdata... + + - ttl, rdtype, string... + """ + + self._add(False, self.update, name, *args) + + def delete(self, name, *args): + """Delete records. + + The first argument is always a name. The other + arguments can be: + + - *empty* + + - rdataset... + + - rdata... + + - rdtype, [string...] + """ + + if isinstance(name, str): + name = dns.name.from_text(name, None) + if len(args) == 0: + self.find_rrset(self.update, name, dns.rdataclass.ANY, + dns.rdatatype.ANY, dns.rdatatype.NONE, + dns.rdatatype.ANY, True, True) + elif isinstance(args[0], dns.rdataset.Rdataset): + for rds in args: + for rd in rds: + self._add_rr(name, 0, rd, dns.rdataclass.NONE) + else: + args = list(args) + if isinstance(args[0], dns.rdata.Rdata): + for rd in args: + self._add_rr(name, 0, rd, dns.rdataclass.NONE) + else: + rdtype = dns.rdatatype.RdataType.make(args.pop(0)) + if len(args) == 0: + self.find_rrset(self.update, name, + self.zone_rdclass, rdtype, + dns.rdatatype.NONE, + dns.rdataclass.ANY, + True, True) + else: + for s in args: + rd = dns.rdata.from_text(self.zone_rdclass, rdtype, s, + self.origin) + self._add_rr(name, 0, rd, dns.rdataclass.NONE) + + def replace(self, name, *args): + """Replace records. + + The first argument is always a name. The other + arguments can be: + + - rdataset... + + - ttl, rdata... + + - ttl, rdtype, string... + + Note that if you want to replace the entire node, you should do + a delete of the name followed by one or more calls to add. + """ + + self._add(True, self.update, name, *args) + + def present(self, name, *args): + """Require that an owner name (and optionally an rdata type, + or specific rdataset) exists as a prerequisite to the + execution of the update. + + The first argument is always a name. + The other arguments can be: + + - rdataset... + + - rdata... + + - rdtype, string... + """ + + if isinstance(name, str): + name = dns.name.from_text(name, None) + if len(args) == 0: + self.find_rrset(self.prerequisite, name, + dns.rdataclass.ANY, dns.rdatatype.ANY, + dns.rdatatype.NONE, None, + True, True) + elif isinstance(args[0], dns.rdataset.Rdataset) or \ + isinstance(args[0], dns.rdata.Rdata) or \ + len(args) > 1: + if not isinstance(args[0], dns.rdataset.Rdataset): + # Add a 0 TTL + args = list(args) + args.insert(0, 0) + self._add(False, self.prerequisite, name, *args) + else: + rdtype = dns.rdatatype.RdataType.make(args[0]) + self.find_rrset(self.prerequisite, name, + dns.rdataclass.ANY, rdtype, + dns.rdatatype.NONE, None, + True, True) + + def absent(self, name, rdtype=None): + """Require that an owner name (and optionally an rdata type) does + not exist as a prerequisite to the execution of the update.""" + + if isinstance(name, str): + name = dns.name.from_text(name, None) + if rdtype is None: + self.find_rrset(self.prerequisite, name, + dns.rdataclass.NONE, dns.rdatatype.ANY, + dns.rdatatype.NONE, None, + True, True) + else: + rdtype = dns.rdatatype.RdataType.make(rdtype) + self.find_rrset(self.prerequisite, name, + dns.rdataclass.NONE, rdtype, + dns.rdatatype.NONE, None, + True, True) + + def _get_one_rr_per_rrset(self, value): + # Updates are always one_rr_per_rrset + return True + + def _parse_rr_header(self, section, name, rdclass, rdtype): + deleting = None + empty = False + if section == UpdateSection.ZONE: + if dns.rdataclass.is_metaclass(rdclass) or \ + rdtype != dns.rdatatype.SOA or \ + self.zone: + raise dns.exception.FormError + else: + if not self.zone: + raise dns.exception.FormError + if rdclass in (dns.rdataclass.ANY, dns.rdataclass.NONE): + deleting = rdclass + rdclass = self.zone[0].rdclass + empty = (deleting == dns.rdataclass.ANY or + section == UpdateSection.PREREQ) + return (rdclass, rdtype, deleting, empty) + +# backwards compatibility +Update = UpdateMessage + +### BEGIN generated UpdateSection constants + +ZONE = UpdateSection.ZONE +PREREQ = UpdateSection.PREREQ +UPDATE = UpdateSection.UPDATE +ADDITIONAL = UpdateSection.ADDITIONAL + +### END generated UpdateSection constants diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/version.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/version.py new file mode 100644 index 0000000..b371b73 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/version.py @@ -0,0 +1,46 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""dnspython release version information.""" + +#: MAJOR +MAJOR = 2 +#: MINOR +MINOR = 1 +#: MICRO +MICRO = 0 +#: RELEASELEVEL +RELEASELEVEL = 0x0f +#: SERIAL +SERIAL = 0 + +if RELEASELEVEL == 0x0f: # pragma: no cover + #: version + version = '%d.%d.%d' % (MAJOR, MINOR, MICRO) +elif RELEASELEVEL == 0x00: # pragma: no cover + version = '%d.%d.%ddev%d' % \ + (MAJOR, MINOR, MICRO, SERIAL) +elif RELEASELEVEL == 0x0c: # pragma: no cover + version = '%d.%d.%drc%d' % \ + (MAJOR, MINOR, MICRO, SERIAL) +else: # pragma: no cover + version = '%d.%d.%d%x%d' % \ + (MAJOR, MINOR, MICRO, RELEASELEVEL, SERIAL) + +#: hexversion +hexversion = MAJOR << 24 | MINOR << 16 | MICRO << 8 | RELEASELEVEL << 4 | \ + SERIAL diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/versioned.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/versioned.py new file mode 100644 index 0000000..686a83b --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/versioned.py @@ -0,0 +1,455 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +"""DNS Versioned Zones.""" + +import collections +try: + import threading as _threading +except ImportError: # pragma: no cover + import dummy_threading as _threading # type: ignore + +import dns.exception +import dns.immutable +import dns.name +import dns.node +import dns.rdataclass +import dns.rdatatype +import dns.rdata +import dns.rdtypes.ANY.SOA +import dns.transaction +import dns.zone + + +class UseTransaction(dns.exception.DNSException): + """To alter a versioned zone, use a transaction.""" + + +class Version: + def __init__(self, zone, id): + self.zone = zone + self.id = id + self.nodes = {} + + def _validate_name(self, name): + if name.is_absolute(): + if not name.is_subdomain(self.zone.origin): + raise KeyError("name is not a subdomain of the zone origin") + if self.zone.relativize: + name = name.relativize(self.origin) + return name + + def get_node(self, name): + name = self._validate_name(name) + return self.nodes.get(name) + + def get_rdataset(self, name, rdtype, covers): + node = self.get_node(name) + if node is None: + return None + return node.get_rdataset(self.zone.rdclass, rdtype, covers) + + def items(self): + return self.nodes.items() # pylint: disable=dict-items-not-iterating + + +class WritableVersion(Version): + def __init__(self, zone, replacement=False): + # The zone._versions_lock must be held by our caller. + if len(zone._versions) > 0: + id = zone._versions[-1].id + 1 + else: + id = 1 + super().__init__(zone, id) + if not replacement: + # We copy the map, because that gives us a simple and thread-safe + # way of doing versions, and we have a garbage collector to help + # us. We only make new node objects if we actually change the + # node. + self.nodes.update(zone.nodes) + # We have to copy the zone origin as it may be None in the first + # version, and we don't want to mutate the zone until we commit. + self.origin = zone.origin + self.changed = set() + + def _maybe_cow(self, name): + name = self._validate_name(name) + node = self.nodes.get(name) + if node is None or node.id != self.id: + new_node = self.zone.node_factory() + new_node.id = self.id + if node is not None: + # moo! copy on write! + new_node.rdatasets.extend(node.rdatasets) + self.nodes[name] = new_node + self.changed.add(name) + return new_node + else: + return node + + def delete_node(self, name): + name = self._validate_name(name) + if name in self.nodes: + del self.nodes[name] + self.changed.add(name) + + def put_rdataset(self, name, rdataset): + node = self._maybe_cow(name) + node.replace_rdataset(rdataset) + + def delete_rdataset(self, name, rdtype, covers): + node = self._maybe_cow(name) + node.delete_rdataset(self.zone.rdclass, rdtype, covers) + if len(node) == 0: + del self.nodes[name] + + +@dns.immutable.immutable +class ImmutableVersion(Version): + def __init__(self, version): + # We tell super() that it's a replacement as we don't want it + # to copy the nodes, as we're about to do that with an + # immutable Dict. + super().__init__(version.zone, True) + # set the right id! + self.id = version.id + # Make changed nodes immutable + for name in version.changed: + node = version.nodes.get(name) + # it might not exist if we deleted it in the version + if node: + version.nodes[name] = ImmutableNode(node) + self.nodes = dns.immutable.Dict(version.nodes, True) + + +# A node with a version id. + +class Node(dns.node.Node): + __slots__ = ['id'] + + def __init__(self): + super().__init__() + # A proper id will get set by the Version + self.id = 0 + + +@dns.immutable.immutable +class ImmutableNode(Node): + __slots__ = ['id'] + + def __init__(self, node): + super().__init__() + self.id = node.id + self.rdatasets = tuple( + [dns.rdataset.ImmutableRdataset(rds) for rds in node.rdatasets] + ) + + def find_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE, + create=False): + if create: + raise TypeError("immutable") + return super().find_rdataset(rdclass, rdtype, covers, False) + + def get_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE, + create=False): + if create: + raise TypeError("immutable") + return super().get_rdataset(rdclass, rdtype, covers, False) + + def delete_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE): + raise TypeError("immutable") + + def replace_rdataset(self, replacement): + raise TypeError("immutable") + + +class Zone(dns.zone.Zone): + + __slots__ = ['_versions', '_versions_lock', '_write_txn', + '_write_waiters', '_write_event', '_pruning_policy', + '_readers'] + + node_factory = Node + + def __init__(self, origin, rdclass=dns.rdataclass.IN, relativize=True, + pruning_policy=None): + """Initialize a versioned zone object. + + *origin* is the origin of the zone. It may be a ``dns.name.Name``, + a ``str``, or ``None``. If ``None``, then the zone's origin will + be set by the first ``$ORIGIN`` line in a zone file. + + *rdclass*, an ``int``, the zone's rdata class; the default is class IN. + + *relativize*, a ``bool``, determine's whether domain names are + relativized to the zone's origin. The default is ``True``. + + *pruning policy*, a function taking a `Version` and returning + a `bool`, or `None`. Should the version be pruned? If `None`, + the default policy, which retains one version is used. + """ + super().__init__(origin, rdclass, relativize) + self._versions = collections.deque() + self._version_lock = _threading.Lock() + if pruning_policy is None: + self._pruning_policy = self._default_pruning_policy + else: + self._pruning_policy = pruning_policy + self._write_txn = None + self._write_event = None + self._write_waiters = collections.deque() + self._readers = set() + self._commit_version_unlocked(None, WritableVersion(self), origin) + + def reader(self, id=None, serial=None): # pylint: disable=arguments-differ + if id is not None and serial is not None: + raise ValueError('cannot specify both id and serial') + with self._version_lock: + if id is not None: + version = None + for v in reversed(self._versions): + if v.id == id: + version = v + break + if version is None: + raise KeyError('version not found') + elif serial is not None: + if self.relativize: + oname = dns.name.empty + else: + oname = self.origin + version = None + for v in reversed(self._versions): + n = v.nodes.get(oname) + if n: + rds = n.get_rdataset(self.rdclass, dns.rdatatype.SOA) + if rds and rds[0].serial == serial: + version = v + break + if version is None: + raise KeyError('serial not found') + else: + version = self._versions[-1] + txn = Transaction(self, False, version) + self._readers.add(txn) + return txn + + def writer(self, replacement=False): + event = None + while True: + with self._version_lock: + # Checking event == self._write_event ensures that either + # no one was waiting before we got lucky and found no write + # txn, or we were the one who was waiting and got woken up. + # This prevents "taking cuts" when creating a write txn. + if self._write_txn is None and event == self._write_event: + # Creating the transaction defers version setup + # (i.e. copying the nodes dictionary) until we + # give up the lock, so that we hold the lock as + # short a time as possible. This is why we call + # _setup_version() below. + self._write_txn = Transaction(self, replacement) + # give up our exclusive right to make a Transaction + self._write_event = None + break + # Someone else is writing already, so we will have to + # wait, but we want to do the actual wait outside the + # lock. + event = _threading.Event() + self._write_waiters.append(event) + # wait (note we gave up the lock!) + # + # We only wake one sleeper at a time, so it's important + # that no event waiter can exit this method (e.g. via + # cancelation) without returning a transaction or waking + # someone else up. + # + # This is not a problem with Threading module threads as + # they cannot be canceled, but could be an issue with trio + # or curio tasks when we do the async version of writer(). + # I.e. we'd need to do something like: + # + # try: + # event.wait() + # except trio.Cancelled: + # with self._version_lock: + # self._maybe_wakeup_one_waiter_unlocked() + # raise + # + event.wait() + # Do the deferred version setup. + self._write_txn._setup_version() + return self._write_txn + + def _maybe_wakeup_one_waiter_unlocked(self): + if len(self._write_waiters) > 0: + self._write_event = self._write_waiters.popleft() + self._write_event.set() + + # pylint: disable=unused-argument + def _default_pruning_policy(self, zone, version): + return True + # pylint: enable=unused-argument + + def _prune_versions_unlocked(self): + assert len(self._versions) > 0 + # Don't ever prune a version greater than or equal to one that + # a reader has open. This pins versions in memory while the + # reader is open, and importantly lets the reader open a txn on + # a successor version (e.g. if generating an IXFR). + # + # Note our definition of least_kept also ensures we do not try to + # delete the greatest version. + if len(self._readers) > 0: + least_kept = min(txn.version.id for txn in self._readers) + else: + least_kept = self._versions[-1].id + while self._versions[0].id < least_kept and \ + self._pruning_policy(self, self._versions[0]): + self._versions.popleft() + + def set_max_versions(self, max_versions): + """Set a pruning policy that retains up to the specified number + of versions + """ + if max_versions is not None and max_versions < 1: + raise ValueError('max versions must be at least 1') + if max_versions is None: + def policy(*_): + return False + else: + def policy(zone, _): + return len(zone._versions) > max_versions + self.set_pruning_policy(policy) + + def set_pruning_policy(self, policy): + """Set the pruning policy for the zone. + + The *policy* function takes a `Version` and returns `True` if + the version should be pruned, and `False` otherwise. `None` + may also be specified for policy, in which case the default policy + is used. + + Pruning checking proceeds from the least version and the first + time the function returns `False`, the checking stops. I.e. the + retained versions are always a consecutive sequence. + """ + if policy is None: + policy = self._default_pruning_policy + with self._version_lock: + self._pruning_policy = policy + self._prune_versions_unlocked() + + def _end_read(self, txn): + with self._version_lock: + self._readers.remove(txn) + self._prune_versions_unlocked() + + def _end_write_unlocked(self, txn): + assert self._write_txn == txn + self._write_txn = None + self._maybe_wakeup_one_waiter_unlocked() + + def _end_write(self, txn): + with self._version_lock: + self._end_write_unlocked(txn) + + def _commit_version_unlocked(self, txn, version, origin): + self._versions.append(version) + self._prune_versions_unlocked() + self.nodes = version.nodes + if self.origin is None: + self.origin = origin + # txn can be None in __init__ when we make the empty version. + if txn is not None: + self._end_write_unlocked(txn) + + def _commit_version(self, txn, version, origin): + with self._version_lock: + self._commit_version_unlocked(txn, version, origin) + + def find_node(self, name, create=False): + if create: + raise UseTransaction + return super().find_node(name) + + def delete_node(self, name): + raise UseTransaction + + def find_rdataset(self, name, rdtype, covers=dns.rdatatype.NONE, + create=False): + if create: + raise UseTransaction + rdataset = super().find_rdataset(name, rdtype, covers) + return dns.rdataset.ImmutableRdataset(rdataset) + + def get_rdataset(self, name, rdtype, covers=dns.rdatatype.NONE, + create=False): + if create: + raise UseTransaction + rdataset = super().get_rdataset(name, rdtype, covers) + return dns.rdataset.ImmutableRdataset(rdataset) + + def delete_rdataset(self, name, rdtype, covers=dns.rdatatype.NONE): + raise UseTransaction + + def replace_rdataset(self, name, replacement): + raise UseTransaction + + +class Transaction(dns.transaction.Transaction): + + def __init__(self, zone, replacement, version=None): + read_only = version is not None + super().__init__(zone, replacement, read_only) + self.version = version + + @property + def zone(self): + return self.manager + + def _setup_version(self): + assert self.version is None + self.version = WritableVersion(self.zone, self.replacement) + + def _get_rdataset(self, name, rdtype, covers): + return self.version.get_rdataset(name, rdtype, covers) + + def _put_rdataset(self, name, rdataset): + assert not self.read_only + self.version.put_rdataset(name, rdataset) + + def _delete_name(self, name): + assert not self.read_only + self.version.delete_node(name) + + def _delete_rdataset(self, name, rdtype, covers): + assert not self.read_only + self.version.delete_rdataset(name, rdtype, covers) + + def _name_exists(self, name): + return self.version.get_node(name) is not None + + def _changed(self): + if self.read_only: + return False + else: + return len(self.version.changed) > 0 + + def _end_transaction(self, commit): + if self.read_only: + self.zone._end_read(self) + elif commit and len(self.version.changed) > 0: + self.zone._commit_version(self, ImmutableVersion(self.version), + self.version.origin) + else: + # rollback + self.zone._end_write(self) + + def _set_origin(self, origin): + if self.version.origin is None: + self.version.origin = origin + + def _iterate_rdatasets(self): + for (name, node) in self.version.items(): + for rdataset in node: + yield (name, rdataset) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/wire.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/wire.py new file mode 100644 index 0000000..572e27e --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/wire.py @@ -0,0 +1,85 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import contextlib +import struct + +import dns.exception +import dns.name + +class Parser: + def __init__(self, wire, current=0): + self.wire = wire + self.current = 0 + self.end = len(self.wire) + if current: + self.seek(current) + self.furthest = current + + def remaining(self): + return self.end - self.current + + def get_bytes(self, size): + if size > self.remaining(): + raise dns.exception.FormError + output = self.wire[self.current:self.current + size] + self.current += size + self.furthest = max(self.furthest, self.current) + return output + + def get_counted_bytes(self, length_size=1): + length = int.from_bytes(self.get_bytes(length_size), 'big') + return self.get_bytes(length) + + def get_remaining(self): + return self.get_bytes(self.remaining()) + + def get_uint8(self): + return struct.unpack('!B', self.get_bytes(1))[0] + + def get_uint16(self): + return struct.unpack('!H', self.get_bytes(2))[0] + + def get_uint32(self): + return struct.unpack('!I', self.get_bytes(4))[0] + + def get_uint48(self): + return int.from_bytes(self.get_bytes(6), 'big') + + def get_struct(self, format): + return struct.unpack(format, self.get_bytes(struct.calcsize(format))) + + def get_name(self, origin=None): + name = dns.name.from_wire_parser(self) + if origin: + name = name.relativize(origin) + return name + + def seek(self, where): + # Note that seeking to the end is OK! (If you try to read + # after such a seek, you'll get an exception as expected.) + if where < 0 or where > self.end: + raise dns.exception.FormError + self.current = where + + @contextlib.contextmanager + def restrict_to(self, size): + if size > self.remaining(): + raise dns.exception.FormError + saved_end = self.end + try: + self.end = self.current + size + yield + # We make this check here and not in the finally as we + # don't want to raise if we're already raising for some + # other reason. + if self.current != self.end: + raise dns.exception.FormError + finally: + self.end = saved_end + + @contextlib.contextmanager + def restore_furthest(self): + try: + yield None + finally: + self.current = self.furthest diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/xfr.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/xfr.py new file mode 100644 index 0000000..b07f8b9 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/xfr.py @@ -0,0 +1,295 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.exception +import dns.message +import dns.name +import dns.rcode +import dns.serial +import dns.rdatatype +import dns.zone + + +class TransferError(dns.exception.DNSException): + """A zone transfer response got a non-zero rcode.""" + + def __init__(self, rcode): + message = 'Zone transfer error: %s' % dns.rcode.to_text(rcode) + super().__init__(message) + self.rcode = rcode + + +class SerialWentBackwards(dns.exception.FormError): + """The current serial number is less than the serial we know.""" + + +class UseTCP(dns.exception.DNSException): + """This IXFR cannot be completed with UDP.""" + + +class Inbound: + """ + State machine for zone transfers. + """ + + def __init__(self, txn_manager, rdtype=dns.rdatatype.AXFR, + serial=None, is_udp=False): + """Initialize an inbound zone transfer. + + *txn_manager* is a :py:class:`dns.transaction.TransactionManager`. + + *rdtype* can be `dns.rdatatype.AXFR` or `dns.rdatatype.IXFR` + + *serial* is the base serial number for IXFRs, and is required in + that case. + + *is_udp*, a ``bool`` indidicates if UDP is being used for this + XFR. + """ + self.txn_manager = txn_manager + self.txn = None + self.rdtype = rdtype + if rdtype == dns.rdatatype.IXFR: + if serial is None: + raise ValueError('a starting serial must be supplied for IXFRs') + elif is_udp: + raise ValueError('is_udp specified for AXFR') + self.serial = serial + self.is_udp = is_udp + (_, _, self.origin) = txn_manager.origin_information() + self.soa_rdataset = None + self.done = False + self.expecting_SOA = False + self.delete_mode = False + + def process_message(self, message): + """Process one message in the transfer. + + The message should have the same relativization as was specified when + the `dns.xfr.Inbound` was created. The message should also have been + created with `one_rr_per_rrset=True` because order matters. + + Returns `True` if the transfer is complete, and `False` otherwise. + """ + if self.txn is None: + replacement = self.rdtype == dns.rdatatype.AXFR + self.txn = self.txn_manager.writer(replacement) + rcode = message.rcode() + if rcode != dns.rcode.NOERROR: + raise TransferError(rcode) + # + # We don't require a question section, but if it is present is + # should be correct. + # + if len(message.question) > 0: + if message.question[0].name != self.origin: + raise dns.exception.FormError("wrong question name") + if message.question[0].rdtype != self.rdtype: + raise dns.exception.FormError("wrong question rdatatype") + answer_index = 0 + if self.soa_rdataset is None: + # + # This is the first message. We're expecting an SOA at + # the origin. + # + if not message.answer or message.answer[0].name != self.origin: + raise dns.exception.FormError("No answer or RRset not " + "for zone origin") + rrset = message.answer[0] + name = rrset.name + rdataset = rrset + if rdataset.rdtype != dns.rdatatype.SOA: + raise dns.exception.FormError("first RRset is not an SOA") + answer_index = 1 + self.soa_rdataset = rdataset.copy() + if self.rdtype == dns.rdatatype.IXFR: + if self.soa_rdataset[0].serial == self.serial: + # + # We're already up-to-date. + # + self.done = True + elif dns.serial.Serial(self.soa_rdataset[0].serial) < \ + self.serial: + # It went backwards! + print(dns.serial.Serial(self.soa_rdataset[0].serial), + self.serial) + raise SerialWentBackwards + else: + if self.is_udp and len(message.answer[answer_index:]) == 0: + # + # There are no more records, so this is the + # "truncated" response. Say to use TCP + # + raise UseTCP + # + # Note we're expecting another SOA so we can detect + # if this IXFR response is an AXFR-style response. + # + self.expecting_SOA = True + # + # Process the answer section (other than the initial SOA in + # the first message). + # + for rrset in message.answer[answer_index:]: + name = rrset.name + rdataset = rrset + if self.done: + raise dns.exception.FormError("answers after final SOA") + if rdataset.rdtype == dns.rdatatype.SOA and \ + name == self.origin: + # + # Every time we see an origin SOA delete_mode inverts + # + if self.rdtype == dns.rdatatype.IXFR: + self.delete_mode = not self.delete_mode + # + # If this SOA Rdataset is equal to the first we saw + # then we're finished. If this is an IXFR we also + # check that we're seeing the record in the expected + # part of the response. + # + if rdataset == self.soa_rdataset and \ + (self.rdtype == dns.rdatatype.AXFR or + (self.rdtype == dns.rdatatype.IXFR and + self.delete_mode)): + # + # This is the final SOA + # + if self.expecting_SOA: + # We got an empty IXFR sequence! + raise dns.exception.FormError('empty IXFR sequence') + if self.rdtype == dns.rdatatype.IXFR \ + and self.serial != rdataset[0].serial: + raise dns.exception.FormError('unexpected end of IXFR ' + 'sequence') + self.txn.replace(name, rdataset) + self.txn.commit() + self.txn = None + self.done = True + else: + # + # This is not the final SOA + # + self.expecting_SOA = False + if self.rdtype == dns.rdatatype.IXFR: + if self.delete_mode: + # This is the start of an IXFR deletion set + if rdataset[0].serial != self.serial: + raise dns.exception.FormError( + "IXFR base serial mismatch") + else: + # This is the start of an IXFR addition set + self.serial = rdataset[0].serial + self.txn.replace(name, rdataset) + else: + # We saw a non-final SOA for the origin in an AXFR. + raise dns.exception.FormError('unexpected origin SOA ' + 'in AXFR') + continue + if self.expecting_SOA: + # + # We made an IXFR request and are expecting another + # SOA RR, but saw something else, so this must be an + # AXFR response. + # + self.rdtype = dns.rdatatype.AXFR + self.expecting_SOA = False + self.delete_mode = False + self.txn.rollback() + self.txn = self.txn_manager.writer(True) + # + # Note we are falling through into the code below + # so whatever rdataset this was gets written. + # + # Add or remove the data + if self.delete_mode: + self.txn.delete_exact(name, rdataset) + else: + self.txn.add(name, rdataset) + if self.is_udp and not self.done: + # + # This is a UDP IXFR and we didn't get to done, and we didn't + # get the proper "truncated" response + # + raise dns.exception.FormError('unexpected end of UDP IXFR') + return self.done + + # + # Inbounds are context managers. + # + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + if self.txn: + self.txn.rollback() + return False + + +def make_query(txn_manager, serial=0, + use_edns=None, ednsflags=None, payload=None, + request_payload=None, options=None, + keyring=None, keyname=None, + keyalgorithm=dns.tsig.default_algorithm): + """Make an AXFR or IXFR query. + + *txn_manager* is a ``dns.transaction.TransactionManager``, typically a + ``dns.zone.Zone``. + + *serial* is an ``int`` or ``None``. If 0, then IXFR will be + attempted using the most recent serial number from the + *txn_manager*; it is the caller's responsibility to ensure there + are no write transactions active that could invalidate the + retrieved serial. If a serial cannot be determined, AXFR will be + forced. Other integer values are the starting serial to use. + ``None`` forces an AXFR. + + Please see the documentation for :py:func:`dns.message.make_query` and + :py:func:`dns.message.Message.use_tsig` for details on the other parameters + to this function. + + Returns a `(query, serial)` tuple. + """ + (zone_origin, _, origin) = txn_manager.origin_information() + if serial is None: + rdtype = dns.rdatatype.AXFR + elif not isinstance(serial, int): + raise ValueError('serial is not an integer') + elif serial == 0: + with txn_manager.reader() as txn: + rdataset = txn.get(origin, 'SOA') + if rdataset: + serial = rdataset[0].serial + rdtype = dns.rdatatype.IXFR + else: + serial = None + rdtype = dns.rdatatype.AXFR + elif serial > 0 and serial < 4294967296: + rdtype = dns.rdatatype.IXFR + else: + raise ValueError('serial out-of-range') + q = dns.message.make_query(zone_origin, rdtype, txn_manager.get_class(), + use_edns, False, ednsflags, payload, + request_payload, options) + if serial is not None: + rrset = dns.rrset.from_text(zone_origin, 0, 'IN', 'SOA', + f'. . {serial} 0 0 0 0') + q.authority.append(rrset) + if keyring is not None: + q.use_tsig(keyring, keyname, algorithm=keyalgorithm) + return (q, serial) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/zone.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/zone.py new file mode 100644 index 0000000..c9c1c20 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/zone.py @@ -0,0 +1,926 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Zones.""" + +import contextlib +import io +import os + +import dns.exception +import dns.name +import dns.node +import dns.rdataclass +import dns.rdatatype +import dns.rdata +import dns.rdtypes.ANY.SOA +import dns.rrset +import dns.tokenizer +import dns.transaction +import dns.ttl +import dns.grange +import dns.zonefile + + +class BadZone(dns.exception.DNSException): + + """The DNS zone is malformed.""" + + +class NoSOA(BadZone): + + """The DNS zone has no SOA RR at its origin.""" + + +class NoNS(BadZone): + + """The DNS zone has no NS RRset at its origin.""" + + +class UnknownOrigin(BadZone): + + """The DNS zone's origin is unknown.""" + + +class Zone(dns.transaction.TransactionManager): + + """A DNS zone. + + A ``Zone`` is a mapping from names to nodes. The zone object may be + treated like a Python dictionary, e.g. ``zone[name]`` will retrieve + the node associated with that name. The *name* may be a + ``dns.name.Name object``, or it may be a string. In either case, + if the name is relative it is treated as relative to the origin of + the zone. + """ + + node_factory = dns.node.Node + + __slots__ = ['rdclass', 'origin', 'nodes', 'relativize'] + + def __init__(self, origin, rdclass=dns.rdataclass.IN, relativize=True): + """Initialize a zone object. + + *origin* is the origin of the zone. It may be a ``dns.name.Name``, + a ``str``, or ``None``. If ``None``, then the zone's origin will + be set by the first ``$ORIGIN`` line in a zone file. + + *rdclass*, an ``int``, the zone's rdata class; the default is class IN. + + *relativize*, a ``bool``, determine's whether domain names are + relativized to the zone's origin. The default is ``True``. + """ + + if origin is not None: + if isinstance(origin, str): + origin = dns.name.from_text(origin) + elif not isinstance(origin, dns.name.Name): + raise ValueError("origin parameter must be convertible to a " + "DNS name") + if not origin.is_absolute(): + raise ValueError("origin parameter must be an absolute name") + self.origin = origin + self.rdclass = rdclass + self.nodes = {} + self.relativize = relativize + + def __eq__(self, other): + """Two zones are equal if they have the same origin, class, and + nodes. + + Returns a ``bool``. + """ + + if not isinstance(other, Zone): + return False + if self.rdclass != other.rdclass or \ + self.origin != other.origin or \ + self.nodes != other.nodes: + return False + return True + + def __ne__(self, other): + """Are two zones not equal? + + Returns a ``bool``. + """ + + return not self.__eq__(other) + + def _validate_name(self, name): + if isinstance(name, str): + name = dns.name.from_text(name, None) + elif not isinstance(name, dns.name.Name): + raise KeyError("name parameter must be convertible to a DNS name") + if name.is_absolute(): + if not name.is_subdomain(self.origin): + raise KeyError( + "name parameter must be a subdomain of the zone origin") + if self.relativize: + name = name.relativize(self.origin) + return name + + def __getitem__(self, key): + key = self._validate_name(key) + return self.nodes[key] + + def __setitem__(self, key, value): + key = self._validate_name(key) + self.nodes[key] = value + + def __delitem__(self, key): + key = self._validate_name(key) + del self.nodes[key] + + def __iter__(self): + return self.nodes.__iter__() + + def keys(self): + return self.nodes.keys() # pylint: disable=dict-keys-not-iterating + + def values(self): + return self.nodes.values() # pylint: disable=dict-values-not-iterating + + def items(self): + return self.nodes.items() # pylint: disable=dict-items-not-iterating + + def get(self, key): + key = self._validate_name(key) + return self.nodes.get(key) + + def __contains__(self, other): + return other in self.nodes + + def find_node(self, name, create=False): + """Find a node in the zone, possibly creating it. + + *name*: the name of the node to find. + The value may be a ``dns.name.Name`` or a ``str``. If absolute, the + name must be a subdomain of the zone's origin. If ``zone.relativize`` + is ``True``, then the name will be relativized. + + *create*, a ``bool``. If true, the node will be created if it does + not exist. + + Raises ``KeyError`` if the name is not known and create was + not specified, or if the name was not a subdomain of the origin. + + Returns a ``dns.node.Node``. + """ + + name = self._validate_name(name) + node = self.nodes.get(name) + if node is None: + if not create: + raise KeyError + node = self.node_factory() + self.nodes[name] = node + return node + + def get_node(self, name, create=False): + """Get a node in the zone, possibly creating it. + + This method is like ``find_node()``, except it returns None instead + of raising an exception if the node does not exist and creation + has not been requested. + + *name*: the name of the node to find. + The value may be a ``dns.name.Name`` or a ``str``. If absolute, the + name must be a subdomain of the zone's origin. If ``zone.relativize`` + is ``True``, then the name will be relativized. + + *create*, a ``bool``. If true, the node will be created if it does + not exist. + + Raises ``KeyError`` if the name is not known and create was + not specified, or if the name was not a subdomain of the origin. + + Returns a ``dns.node.Node`` or ``None``. + """ + + try: + node = self.find_node(name, create) + except KeyError: + node = None + return node + + def delete_node(self, name): + """Delete the specified node if it exists. + + *name*: the name of the node to find. + The value may be a ``dns.name.Name`` or a ``str``. If absolute, the + name must be a subdomain of the zone's origin. If ``zone.relativize`` + is ``True``, then the name will be relativized. + + It is not an error if the node does not exist. + """ + + name = self._validate_name(name) + if name in self.nodes: + del self.nodes[name] + + def find_rdataset(self, name, rdtype, covers=dns.rdatatype.NONE, + create=False): + """Look for an rdataset with the specified name and type in the zone, + and return an rdataset encapsulating it. + + The rdataset returned is not a copy; changes to it will change + the zone. + + KeyError is raised if the name or type are not found. + + *name*: the name of the node to find. + The value may be a ``dns.name.Name`` or a ``str``. If absolute, the + name must be a subdomain of the zone's origin. If ``zone.relativize`` + is ``True``, then the name will be relativized. + + *rdtype*, an ``int`` or ``str``, the rdata type desired. + + *covers*, an ``int`` or ``str`` or ``None``, the covered type. + Usually this value is ``dns.rdatatype.NONE``, but if the + rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, + then the covers value will be the rdata type the SIG/RRSIG + covers. The library treats the SIG and RRSIG types as if they + were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). + This makes RRSIGs much easier to work with than if RRSIGs + covering different rdata types were aggregated into a single + RRSIG rdataset. + + *create*, a ``bool``. If true, the node will be created if it does + not exist. + + Raises ``KeyError`` if the name is not known and create was + not specified, or if the name was not a subdomain of the origin. + + Returns a ``dns.rdataset.Rdataset``. + """ + + name = self._validate_name(name) + rdtype = dns.rdatatype.RdataType.make(rdtype) + if covers is not None: + covers = dns.rdatatype.RdataType.make(covers) + node = self.find_node(name, create) + return node.find_rdataset(self.rdclass, rdtype, covers, create) + + def get_rdataset(self, name, rdtype, covers=dns.rdatatype.NONE, + create=False): + """Look for an rdataset with the specified name and type in the zone. + + This method is like ``find_rdataset()``, except it returns None instead + of raising an exception if the rdataset does not exist and creation + has not been requested. + + The rdataset returned is not a copy; changes to it will change + the zone. + + *name*: the name of the node to find. + The value may be a ``dns.name.Name`` or a ``str``. If absolute, the + name must be a subdomain of the zone's origin. If ``zone.relativize`` + is ``True``, then the name will be relativized. + + *rdtype*, an ``int`` or ``str``, the rdata type desired. + + *covers*, an ``int`` or ``str`` or ``None``, the covered type. + Usually this value is ``dns.rdatatype.NONE``, but if the + rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, + then the covers value will be the rdata type the SIG/RRSIG + covers. The library treats the SIG and RRSIG types as if they + were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). + This makes RRSIGs much easier to work with than if RRSIGs + covering different rdata types were aggregated into a single + RRSIG rdataset. + + *create*, a ``bool``. If true, the node will be created if it does + not exist. + + Raises ``KeyError`` if the name is not known and create was + not specified, or if the name was not a subdomain of the origin. + + Returns a ``dns.rdataset.Rdataset`` or ``None``. + """ + + try: + rdataset = self.find_rdataset(name, rdtype, covers, create) + except KeyError: + rdataset = None + return rdataset + + def delete_rdataset(self, name, rdtype, covers=dns.rdatatype.NONE): + """Delete the rdataset matching *rdtype* and *covers*, if it + exists at the node specified by *name*. + + It is not an error if the node does not exist, or if there is no + matching rdataset at the node. + + If the node has no rdatasets after the deletion, it will itself + be deleted. + + *name*: the name of the node to find. + The value may be a ``dns.name.Name`` or a ``str``. If absolute, the + name must be a subdomain of the zone's origin. If ``zone.relativize`` + is ``True``, then the name will be relativized. + + *rdtype*, an ``int`` or ``str``, the rdata type desired. + + *covers*, an ``int`` or ``str`` or ``None``, the covered type. + Usually this value is ``dns.rdatatype.NONE``, but if the + rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, + then the covers value will be the rdata type the SIG/RRSIG + covers. The library treats the SIG and RRSIG types as if they + were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). + This makes RRSIGs much easier to work with than if RRSIGs + covering different rdata types were aggregated into a single + RRSIG rdataset. + """ + + name = self._validate_name(name) + rdtype = dns.rdatatype.RdataType.make(rdtype) + if covers is not None: + covers = dns.rdatatype.RdataType.make(covers) + node = self.get_node(name) + if node is not None: + node.delete_rdataset(self.rdclass, rdtype, covers) + if len(node) == 0: + self.delete_node(name) + + def replace_rdataset(self, name, replacement): + """Replace an rdataset at name. + + It is not an error if there is no rdataset matching I{replacement}. + + Ownership of the *replacement* object is transferred to the zone; + in other words, this method does not store a copy of *replacement* + at the node, it stores *replacement* itself. + + If the node does not exist, it is created. + + *name*: the name of the node to find. + The value may be a ``dns.name.Name`` or a ``str``. If absolute, the + name must be a subdomain of the zone's origin. If ``zone.relativize`` + is ``True``, then the name will be relativized. + + *replacement*, a ``dns.rdataset.Rdataset``, the replacement rdataset. + """ + + if replacement.rdclass != self.rdclass: + raise ValueError('replacement.rdclass != zone.rdclass') + node = self.find_node(name, True) + node.replace_rdataset(replacement) + + def find_rrset(self, name, rdtype, covers=dns.rdatatype.NONE): + """Look for an rdataset with the specified name and type in the zone, + and return an RRset encapsulating it. + + This method is less efficient than the similar + ``find_rdataset()`` because it creates an RRset instead of + returning the matching rdataset. It may be more convenient + for some uses since it returns an object which binds the owner + name to the rdataset. + + This method may not be used to create new nodes or rdatasets; + use ``find_rdataset`` instead. + + *name*: the name of the node to find. + The value may be a ``dns.name.Name`` or a ``str``. If absolute, the + name must be a subdomain of the zone's origin. If ``zone.relativize`` + is ``True``, then the name will be relativized. + + *rdtype*, an ``int`` or ``str``, the rdata type desired. + + *covers*, an ``int`` or ``str`` or ``None``, the covered type. + Usually this value is ``dns.rdatatype.NONE``, but if the + rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, + then the covers value will be the rdata type the SIG/RRSIG + covers. The library treats the SIG and RRSIG types as if they + were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). + This makes RRSIGs much easier to work with than if RRSIGs + covering different rdata types were aggregated into a single + RRSIG rdataset. + + *create*, a ``bool``. If true, the node will be created if it does + not exist. + + Raises ``KeyError`` if the name is not known and create was + not specified, or if the name was not a subdomain of the origin. + + Returns a ``dns.rrset.RRset`` or ``None``. + """ + + name = self._validate_name(name) + rdtype = dns.rdatatype.RdataType.make(rdtype) + if covers is not None: + covers = dns.rdatatype.RdataType.make(covers) + rdataset = self.nodes[name].find_rdataset(self.rdclass, rdtype, covers) + rrset = dns.rrset.RRset(name, self.rdclass, rdtype, covers) + rrset.update(rdataset) + return rrset + + def get_rrset(self, name, rdtype, covers=dns.rdatatype.NONE): + """Look for an rdataset with the specified name and type in the zone, + and return an RRset encapsulating it. + + This method is less efficient than the similar ``get_rdataset()`` + because it creates an RRset instead of returning the matching + rdataset. It may be more convenient for some uses since it + returns an object which binds the owner name to the rdataset. + + This method may not be used to create new nodes or rdatasets; + use ``get_rdataset()`` instead. + + *name*: the name of the node to find. + The value may be a ``dns.name.Name`` or a ``str``. If absolute, the + name must be a subdomain of the zone's origin. If ``zone.relativize`` + is ``True``, then the name will be relativized. + + *rdtype*, an ``int`` or ``str``, the rdata type desired. + + *covers*, an ``int`` or ``str`` or ``None``, the covered type. + Usually this value is ``dns.rdatatype.NONE``, but if the + rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, + then the covers value will be the rdata type the SIG/RRSIG + covers. The library treats the SIG and RRSIG types as if they + were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). + This makes RRSIGs much easier to work with than if RRSIGs + covering different rdata types were aggregated into a single + RRSIG rdataset. + + *create*, a ``bool``. If true, the node will be created if it does + not exist. + + Raises ``KeyError`` if the name is not known and create was + not specified, or if the name was not a subdomain of the origin. + + Returns a ``dns.rrset.RRset`` or ``None``. + """ + + try: + rrset = self.find_rrset(name, rdtype, covers) + except KeyError: + rrset = None + return rrset + + def iterate_rdatasets(self, rdtype=dns.rdatatype.ANY, + covers=dns.rdatatype.NONE): + """Return a generator which yields (name, rdataset) tuples for + all rdatasets in the zone which have the specified *rdtype* + and *covers*. If *rdtype* is ``dns.rdatatype.ANY``, the default, + then all rdatasets will be matched. + + *rdtype*, an ``int`` or ``str``, the rdata type desired. + + *covers*, an ``int`` or ``str`` or ``None``, the covered type. + Usually this value is ``dns.rdatatype.NONE``, but if the + rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, + then the covers value will be the rdata type the SIG/RRSIG + covers. The library treats the SIG and RRSIG types as if they + were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). + This makes RRSIGs much easier to work with than if RRSIGs + covering different rdata types were aggregated into a single + RRSIG rdataset. + """ + + rdtype = dns.rdatatype.RdataType.make(rdtype) + if covers is not None: + covers = dns.rdatatype.RdataType.make(covers) + for (name, node) in self.items(): + for rds in node: + if rdtype == dns.rdatatype.ANY or \ + (rds.rdtype == rdtype and rds.covers == covers): + yield (name, rds) + + def iterate_rdatas(self, rdtype=dns.rdatatype.ANY, + covers=dns.rdatatype.NONE): + """Return a generator which yields (name, ttl, rdata) tuples for + all rdatas in the zone which have the specified *rdtype* + and *covers*. If *rdtype* is ``dns.rdatatype.ANY``, the default, + then all rdatas will be matched. + + *rdtype*, an ``int`` or ``str``, the rdata type desired. + + *covers*, an ``int`` or ``str`` or ``None``, the covered type. + Usually this value is ``dns.rdatatype.NONE``, but if the + rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, + then the covers value will be the rdata type the SIG/RRSIG + covers. The library treats the SIG and RRSIG types as if they + were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). + This makes RRSIGs much easier to work with than if RRSIGs + covering different rdata types were aggregated into a single + RRSIG rdataset. + """ + + rdtype = dns.rdatatype.RdataType.make(rdtype) + if covers is not None: + covers = dns.rdatatype.RdataType.make(covers) + for (name, node) in self.items(): + for rds in node: + if rdtype == dns.rdatatype.ANY or \ + (rds.rdtype == rdtype and rds.covers == covers): + for rdata in rds: + yield (name, rds.ttl, rdata) + + def to_file(self, f, sorted=True, relativize=True, nl=None, + want_comments=False): + """Write a zone to a file. + + *f*, a file or `str`. If *f* is a string, it is treated + as the name of a file to open. + + *sorted*, a ``bool``. If True, the default, then the file + will be written with the names sorted in DNSSEC order from + least to greatest. Otherwise the names will be written in + whatever order they happen to have in the zone's dictionary. + + *relativize*, a ``bool``. If True, the default, then domain + names in the output will be relativized to the zone's origin + if possible. + + *nl*, a ``str`` or None. The end of line string. If not + ``None``, the output will use the platform's native + end-of-line marker (i.e. LF on POSIX, CRLF on Windows). + + *want_comments*, a ``bool``. If ``True``, emit end-of-line comments + as part of writing the file. If ``False``, the default, do not + emit them. + """ + + with contextlib.ExitStack() as stack: + if isinstance(f, str): + f = stack.enter_context(open(f, 'wb')) + + # must be in this way, f.encoding may contain None, or even + # attribute may not be there + file_enc = getattr(f, 'encoding', None) + if file_enc is None: + file_enc = 'utf-8' + + if nl is None: + # binary mode, '\n' is not enough + nl_b = os.linesep.encode(file_enc) + nl = '\n' + elif isinstance(nl, str): + nl_b = nl.encode(file_enc) + else: + nl_b = nl + nl = nl.decode() + + if sorted: + names = list(self.keys()) + names.sort() + else: + names = self.keys() + for n in names: + l = self[n].to_text(n, origin=self.origin, + relativize=relativize, + want_comments=want_comments) + l_b = l.encode(file_enc) + + try: + f.write(l_b) + f.write(nl_b) + except TypeError: # textual mode + f.write(l) + f.write(nl) + + def to_text(self, sorted=True, relativize=True, nl=None, + want_comments=False): + """Return a zone's text as though it were written to a file. + + *sorted*, a ``bool``. If True, the default, then the file + will be written with the names sorted in DNSSEC order from + least to greatest. Otherwise the names will be written in + whatever order they happen to have in the zone's dictionary. + + *relativize*, a ``bool``. If True, the default, then domain + names in the output will be relativized to the zone's origin + if possible. + + *nl*, a ``str`` or None. The end of line string. If not + ``None``, the output will use the platform's native + end-of-line marker (i.e. LF on POSIX, CRLF on Windows). + + *want_comments*, a ``bool``. If ``True``, emit end-of-line comments + as part of writing the file. If ``False``, the default, do not + emit them. + + Returns a ``str``. + """ + temp_buffer = io.StringIO() + self.to_file(temp_buffer, sorted, relativize, nl, want_comments) + return_value = temp_buffer.getvalue() + temp_buffer.close() + return return_value + + def check_origin(self): + """Do some simple checking of the zone's origin. + + Raises ``dns.zone.NoSOA`` if there is no SOA RRset. + + Raises ``dns.zone.NoNS`` if there is no NS RRset. + + Raises ``KeyError`` if there is no origin node. + """ + if self.relativize: + name = dns.name.empty + else: + name = self.origin + if self.get_rdataset(name, dns.rdatatype.SOA) is None: + raise NoSOA + if self.get_rdataset(name, dns.rdatatype.NS) is None: + raise NoNS + + # TransactionManager methods + + def reader(self): + return Transaction(self, False, True) + + def writer(self, replacement=False): + return Transaction(self, replacement, False) + + def origin_information(self): + if self.relativize: + effective = dns.name.empty + else: + effective = self.origin + return (self.origin, self.relativize, effective) + + def get_class(self): + return self.rdclass + + +class Transaction(dns.transaction.Transaction): + + _deleted_rdataset = dns.rdataset.Rdataset(dns.rdataclass.ANY, + dns.rdatatype.ANY) + + def __init__(self, zone, replacement, read_only): + super().__init__(zone, replacement, read_only) + self.rdatasets = {} + + @property + def zone(self): + return self.manager + + def _get_rdataset(self, name, rdtype, covers): + rdataset = self.rdatasets.get((name, rdtype, covers)) + if rdataset is self._deleted_rdataset: + return None + elif rdataset is None: + rdataset = self.zone.get_rdataset(name, rdtype, covers) + return rdataset + + def _put_rdataset(self, name, rdataset): + assert not self.read_only + self.zone._validate_name(name) + self.rdatasets[(name, rdataset.rdtype, rdataset.covers)] = rdataset + + def _delete_name(self, name): + assert not self.read_only + # First remove any changes involving the name + remove = [] + for key in self.rdatasets: + if key[0] == name: + remove.append(key) + if len(remove) > 0: + for key in remove: + del self.rdatasets[key] + # Next add deletion records for any rdatasets matching the + # name in the zone + node = self.zone.get_node(name) + if node is not None: + for rdataset in node.rdatasets: + self.rdatasets[(name, rdataset.rdtype, rdataset.covers)] = \ + self._deleted_rdataset + + def _delete_rdataset(self, name, rdtype, covers): + assert not self.read_only + try: + del self.rdatasets[(name, rdtype, covers)] + except KeyError: + pass + rdataset = self.zone.get_rdataset(name, rdtype, covers) + if rdataset is not None: + self.rdatasets[(name, rdataset.rdtype, rdataset.covers)] = \ + self._deleted_rdataset + + def _name_exists(self, name): + for key, rdataset in self.rdatasets.items(): + if key[0] == name: + if rdataset != self._deleted_rdataset: + return True + else: + return None + self.zone._validate_name(name) + if self.zone.get_node(name): + return True + return False + + def _changed(self): + if self.read_only: + return False + else: + return len(self.rdatasets) > 0 + + def _end_transaction(self, commit): + if commit and self._changed(): + for (name, rdtype, covers), rdataset in \ + self.rdatasets.items(): + if rdataset is self._deleted_rdataset: + self.zone.delete_rdataset(name, rdtype, covers) + else: + self.zone.replace_rdataset(name, rdataset) + + def _set_origin(self, origin): + if self.zone.origin is None: + self.zone.origin = origin + + def _iterate_rdatasets(self): + # Expensive but simple! Use a versioned zone for efficient txn + # iteration. + rdatasets = {} + for (name, rdataset) in self.zone.iterate_rdatasets(): + rdatasets[(name, rdataset.rdtype, rdataset.covers)] = rdataset + rdatasets.update(self.rdatasets) + for (name, _, _), rdataset in rdatasets.items(): + yield (name, rdataset) + + +def from_text(text, origin=None, rdclass=dns.rdataclass.IN, + relativize=True, zone_factory=Zone, filename=None, + allow_include=False, check_origin=True, idna_codec=None): + """Build a zone object from a zone file format string. + + *text*, a ``str``, the zone file format input. + + *origin*, a ``dns.name.Name``, a ``str``, or ``None``. The origin + of the zone; if not specified, the first ``$ORIGIN`` statement in the + zone file will determine the origin of the zone. + + *rdclass*, an ``int``, the zone's rdata class; the default is class IN. + + *relativize*, a ``bool``, determine's whether domain names are + relativized to the zone's origin. The default is ``True``. + + *zone_factory*, the zone factory to use or ``None``. If ``None``, then + ``dns.zone.Zone`` will be used. The value may be any class or callable + that returns a subclass of ``dns.zone.Zone``. + + *filename*, a ``str`` or ``None``, the filename to emit when + describing where an error occurred; the default is ``''``. + + *allow_include*, a ``bool``. If ``True``, the default, then ``$INCLUDE`` + directives are permitted. If ``False``, then encoutering a ``$INCLUDE`` + will raise a ``SyntaxError`` exception. + + *check_origin*, a ``bool``. If ``True``, the default, then sanity + checks of the origin node will be made by calling the zone's + ``check_origin()`` method. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder + is used. + + Raises ``dns.zone.NoSOA`` if there is no SOA RRset. + + Raises ``dns.zone.NoNS`` if there is no NS RRset. + + Raises ``KeyError`` if there is no origin node. + + Returns a subclass of ``dns.zone.Zone``. + """ + + # 'text' can also be a file, but we don't publish that fact + # since it's an implementation detail. The official file + # interface is from_file(). + + if filename is None: + filename = '' + zone = zone_factory(origin, rdclass, relativize=relativize) + with zone.writer(True) as txn: + tok = dns.tokenizer.Tokenizer(text, filename, idna_codec=idna_codec) + reader = dns.zonefile.Reader(tok, rdclass, txn, + allow_include=allow_include) + try: + reader.read() + except dns.zonefile.UnknownOrigin: + # for backwards compatibility + raise dns.zone.UnknownOrigin + # Now that we're done reading, do some basic checking of the zone. + if check_origin: + zone.check_origin() + return zone + + +def from_file(f, origin=None, rdclass=dns.rdataclass.IN, + relativize=True, zone_factory=Zone, filename=None, + allow_include=True, check_origin=True): + """Read a zone file and build a zone object. + + *f*, a file or ``str``. If *f* is a string, it is treated + as the name of a file to open. + + *origin*, a ``dns.name.Name``, a ``str``, or ``None``. The origin + of the zone; if not specified, the first ``$ORIGIN`` statement in the + zone file will determine the origin of the zone. + + *rdclass*, an ``int``, the zone's rdata class; the default is class IN. + + *relativize*, a ``bool``, determine's whether domain names are + relativized to the zone's origin. The default is ``True``. + + *zone_factory*, the zone factory to use or ``None``. If ``None``, then + ``dns.zone.Zone`` will be used. The value may be any class or callable + that returns a subclass of ``dns.zone.Zone``. + + *filename*, a ``str`` or ``None``, the filename to emit when + describing where an error occurred; the default is ``''``. + + *allow_include*, a ``bool``. If ``True``, the default, then ``$INCLUDE`` + directives are permitted. If ``False``, then encoutering a ``$INCLUDE`` + will raise a ``SyntaxError`` exception. + + *check_origin*, a ``bool``. If ``True``, the default, then sanity + checks of the origin node will be made by calling the zone's + ``check_origin()`` method. + + *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA + encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder + is used. + + Raises ``dns.zone.NoSOA`` if there is no SOA RRset. + + Raises ``dns.zone.NoNS`` if there is no NS RRset. + + Raises ``KeyError`` if there is no origin node. + + Returns a subclass of ``dns.zone.Zone``. + """ + + with contextlib.ExitStack() as stack: + if isinstance(f, str): + if filename is None: + filename = f + f = stack.enter_context(open(f)) + return from_text(f, origin, rdclass, relativize, zone_factory, + filename, allow_include, check_origin) + + +def from_xfr(xfr, zone_factory=Zone, relativize=True, check_origin=True): + """Convert the output of a zone transfer generator into a zone object. + + *xfr*, a generator of ``dns.message.Message`` objects, typically + ``dns.query.xfr()``. + + *relativize*, a ``bool``, determine's whether domain names are + relativized to the zone's origin. The default is ``True``. + It is essential that the relativize setting matches the one specified + to the generator. + + *check_origin*, a ``bool``. If ``True``, the default, then sanity + checks of the origin node will be made by calling the zone's + ``check_origin()`` method. + + Raises ``dns.zone.NoSOA`` if there is no SOA RRset. + + Raises ``dns.zone.NoNS`` if there is no NS RRset. + + Raises ``KeyError`` if there is no origin node. + + Returns a subclass of ``dns.zone.Zone``. + """ + + z = None + for r in xfr: + if z is None: + if relativize: + origin = r.origin + else: + origin = r.answer[0].name + rdclass = r.answer[0].rdclass + z = zone_factory(origin, rdclass, relativize=relativize) + for rrset in r.answer: + znode = z.nodes.get(rrset.name) + if not znode: + znode = z.node_factory() + z.nodes[rrset.name] = znode + zrds = znode.find_rdataset(rrset.rdclass, rrset.rdtype, + rrset.covers, True) + zrds.update_ttl(rrset.ttl) + for rd in rrset: + zrds.add(rd) + if check_origin: + z.check_origin() + return z diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/zonefile.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/zonefile.py new file mode 100644 index 0000000..92e2f0c --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dns/zonefile.py @@ -0,0 +1,401 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Zones.""" + +import re +import sys + +import dns.exception +import dns.name +import dns.node +import dns.rdataclass +import dns.rdatatype +import dns.rdata +import dns.rdtypes.ANY.SOA +import dns.rrset +import dns.tokenizer +import dns.transaction +import dns.ttl +import dns.grange + + +class UnknownOrigin(dns.exception.DNSException): + """Unknown origin""" + + +class Reader: + + """Read a DNS zone file into a transaction.""" + + def __init__(self, tok, rdclass, txn, allow_include=False): + self.tok = tok + (self.zone_origin, self.relativize, _) = \ + txn.manager.origin_information() + self.current_origin = self.zone_origin + self.last_ttl = 0 + self.last_ttl_known = False + self.default_ttl = 0 + self.default_ttl_known = False + self.last_name = self.current_origin + self.zone_rdclass = rdclass + self.txn = txn + self.saved_state = [] + self.current_file = None + self.allow_include = allow_include + + def _eat_line(self): + while 1: + token = self.tok.get() + if token.is_eol_or_eof(): + break + + def _rr_line(self): + """Process one line from a DNS zone file.""" + # Name + if self.current_origin is None: + raise UnknownOrigin + token = self.tok.get(want_leading=True) + if not token.is_whitespace(): + self.last_name = self.tok.as_name(token, self.current_origin) + else: + token = self.tok.get() + if token.is_eol_or_eof(): + # treat leading WS followed by EOL/EOF as if they were EOL/EOF. + return + self.tok.unget(token) + name = self.last_name + if not name.is_subdomain(self.zone_origin): + self._eat_line() + return + if self.relativize: + name = name.relativize(self.zone_origin) + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + + # TTL + ttl = None + try: + ttl = dns.ttl.from_text(token.value) + self.last_ttl = ttl + self.last_ttl_known = True + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + except dns.ttl.BadTTL: + if self.default_ttl_known: + ttl = self.default_ttl + elif self.last_ttl_known: + ttl = self.last_ttl + + # Class + try: + rdclass = dns.rdataclass.from_text(token.value) + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + except dns.exception.SyntaxError: + raise + except Exception: + rdclass = self.zone_rdclass + if rdclass != self.zone_rdclass: + raise dns.exception.SyntaxError("RR class is not zone's class") + # Type + try: + rdtype = dns.rdatatype.from_text(token.value) + except Exception: + raise dns.exception.SyntaxError( + "unknown rdatatype '%s'" % token.value) + try: + rd = dns.rdata.from_text(rdclass, rdtype, self.tok, + self.current_origin, self.relativize, + self.zone_origin) + except dns.exception.SyntaxError: + # Catch and reraise. + raise + except Exception: + # All exceptions that occur in the processing of rdata + # are treated as syntax errors. This is not strictly + # correct, but it is correct almost all of the time. + # We convert them to syntax errors so that we can emit + # helpful filename:line info. + (ty, va) = sys.exc_info()[:2] + raise dns.exception.SyntaxError( + "caught exception {}: {}".format(str(ty), str(va))) + + if not self.default_ttl_known and rdtype == dns.rdatatype.SOA: + # The pre-RFC2308 and pre-BIND9 behavior inherits the zone default + # TTL from the SOA minttl if no $TTL statement is present before the + # SOA is parsed. + self.default_ttl = rd.minimum + self.default_ttl_known = True + if ttl is None: + # if we didn't have a TTL on the SOA, set it! + ttl = rd.minimum + + # TTL check. We had to wait until now to do this as the SOA RR's + # own TTL can be inferred from its minimum. + if ttl is None: + raise dns.exception.SyntaxError("Missing default TTL value") + + self.txn.add(name, ttl, rd) + + def _parse_modify(self, side): + # Here we catch everything in '{' '}' in a group so we can replace it + # with ''. + is_generate1 = re.compile(r"^.*\$({(\+|-?)(\d+),(\d+),(.)}).*$") + is_generate2 = re.compile(r"^.*\$({(\+|-?)(\d+)}).*$") + is_generate3 = re.compile(r"^.*\$({(\+|-?)(\d+),(\d+)}).*$") + # Sometimes there are modifiers in the hostname. These come after + # the dollar sign. They are in the form: ${offset[,width[,base]]}. + # Make names + g1 = is_generate1.match(side) + if g1: + mod, sign, offset, width, base = g1.groups() + if sign == '': + sign = '+' + g2 = is_generate2.match(side) + if g2: + mod, sign, offset = g2.groups() + if sign == '': + sign = '+' + width = 0 + base = 'd' + g3 = is_generate3.match(side) + if g3: + mod, sign, offset, width = g3.groups() + if sign == '': + sign = '+' + base = 'd' + + if not (g1 or g2 or g3): + mod = '' + sign = '+' + offset = 0 + width = 0 + base = 'd' + + if base != 'd': + raise NotImplementedError() + + return mod, sign, offset, width, base + + def _generate_line(self): + # range lhs [ttl] [class] type rhs [ comment ] + """Process one line containing the GENERATE statement from a DNS + zone file.""" + if self.current_origin is None: + raise UnknownOrigin + + token = self.tok.get() + # Range (required) + try: + start, stop, step = dns.grange.from_text(token.value) + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + except Exception: + raise dns.exception.SyntaxError + + # lhs (required) + try: + lhs = token.value + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + except Exception: + raise dns.exception.SyntaxError + + # TTL + try: + ttl = dns.ttl.from_text(token.value) + self.last_ttl = ttl + self.last_ttl_known = True + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + except dns.ttl.BadTTL: + if not (self.last_ttl_known or self.default_ttl_known): + raise dns.exception.SyntaxError("Missing default TTL value") + if self.default_ttl_known: + ttl = self.default_ttl + elif self.last_ttl_known: + ttl = self.last_ttl + # Class + try: + rdclass = dns.rdataclass.from_text(token.value) + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + except dns.exception.SyntaxError: + raise dns.exception.SyntaxError + except Exception: + rdclass = self.zone_rdclass + if rdclass != self.zone_rdclass: + raise dns.exception.SyntaxError("RR class is not zone's class") + # Type + try: + rdtype = dns.rdatatype.from_text(token.value) + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError + except Exception: + raise dns.exception.SyntaxError("unknown rdatatype '%s'" % + token.value) + + # rhs (required) + rhs = token.value + + # The code currently only supports base 'd', so the last value + # in the tuple _parse_modify returns is ignored + lmod, lsign, loffset, lwidth, _ = self._parse_modify(lhs) + rmod, rsign, roffset, rwidth, _ = self._parse_modify(rhs) + for i in range(start, stop + 1, step): + # +1 because bind is inclusive and python is exclusive + + if lsign == '+': + lindex = i + int(loffset) + elif lsign == '-': + lindex = i - int(loffset) + + if rsign == '-': + rindex = i - int(roffset) + elif rsign == '+': + rindex = i + int(roffset) + + lzfindex = str(lindex).zfill(int(lwidth)) + rzfindex = str(rindex).zfill(int(rwidth)) + + name = lhs.replace('$%s' % (lmod), lzfindex) + rdata = rhs.replace('$%s' % (rmod), rzfindex) + + self.last_name = dns.name.from_text(name, self.current_origin, + self.tok.idna_codec) + name = self.last_name + if not name.is_subdomain(self.zone_origin): + self._eat_line() + return + if self.relativize: + name = name.relativize(self.zone_origin) + + try: + rd = dns.rdata.from_text(rdclass, rdtype, rdata, + self.current_origin, self.relativize, + self.zone_origin) + except dns.exception.SyntaxError: + # Catch and reraise. + raise + except Exception: + # All exceptions that occur in the processing of rdata + # are treated as syntax errors. This is not strictly + # correct, but it is correct almost all of the time. + # We convert them to syntax errors so that we can emit + # helpful filename:line info. + (ty, va) = sys.exc_info()[:2] + raise dns.exception.SyntaxError("caught exception %s: %s" % + (str(ty), str(va))) + + self.txn.add(name, ttl, rd) + + def read(self): + """Read a DNS zone file and build a zone object. + + @raises dns.zone.NoSOA: No SOA RR was found at the zone origin + @raises dns.zone.NoNS: No NS RRset was found at the zone origin + """ + + try: + while 1: + token = self.tok.get(True, True) + if token.is_eof(): + if self.current_file is not None: + self.current_file.close() + if len(self.saved_state) > 0: + (self.tok, + self.current_origin, + self.last_name, + self.current_file, + self.last_ttl, + self.last_ttl_known, + self.default_ttl, + self.default_ttl_known) = self.saved_state.pop(-1) + continue + break + elif token.is_eol(): + continue + elif token.is_comment(): + self.tok.get_eol() + continue + elif token.value[0] == '$': + c = token.value.upper() + if c == '$TTL': + token = self.tok.get() + if not token.is_identifier(): + raise dns.exception.SyntaxError("bad $TTL") + self.default_ttl = dns.ttl.from_text(token.value) + self.default_ttl_known = True + self.tok.get_eol() + elif c == '$ORIGIN': + self.current_origin = self.tok.get_name() + self.tok.get_eol() + if self.zone_origin is None: + self.zone_origin = self.current_origin + self.txn._set_origin(self.current_origin) + elif c == '$INCLUDE' and self.allow_include: + token = self.tok.get() + filename = token.value + token = self.tok.get() + if token.is_identifier(): + new_origin =\ + dns.name.from_text(token.value, + self.current_origin, + self.tok.idna_codec) + self.tok.get_eol() + elif not token.is_eol_or_eof(): + raise dns.exception.SyntaxError( + "bad origin in $INCLUDE") + else: + new_origin = self.current_origin + self.saved_state.append((self.tok, + self.current_origin, + self.last_name, + self.current_file, + self.last_ttl, + self.last_ttl_known, + self.default_ttl, + self.default_ttl_known)) + self.current_file = open(filename, 'r') + self.tok = dns.tokenizer.Tokenizer(self.current_file, + filename) + self.current_origin = new_origin + elif c == '$GENERATE': + self._generate_line() + else: + raise dns.exception.SyntaxError( + "Unknown zone file directive '" + c + "'") + continue + self.tok.unget(token) + self._rr_line() + except dns.exception.SyntaxError as detail: + (filename, line_number) = self.tok.where() + if detail is None: + detail = "syntax error" + ex = dns.exception.SyntaxError( + "%s:%d: %s" % (filename, line_number, detail)) + tb = sys.exc_info()[2] + raise ex.with_traceback(tb) from None diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dnspython.egg-info/PKG-INFO b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dnspython.egg-info/PKG-INFO new file mode 100644 index 0000000..3b29b31 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dnspython.egg-info/PKG-INFO @@ -0,0 +1,38 @@ +Metadata-Version: 2.1 +Name: dnspython +Version: 2.1.0 +Summary: DNS toolkit +Home-page: http://www.dnspython.org +Author: Bob Halley +Author-email: halley@dnspython.org +License: ISC +Description: dnspython is a DNS toolkit for Python. It supports almost all + record types. It can be used for queries, zone transfers, and dynamic + updates. It supports TSIG authenticated messages and EDNS0. + + dnspython provides both high and low level access to DNS. The high + level classes perform queries for data of a given name, type, and + class, and return an answer set. The low level classes allow + direct manipulation of DNS zones, messages, names, and records. +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: System Administrators +Classifier: License :: OSI Approved :: ISC License (ISCL) +Classifier: Operating System :: POSIX +Classifier: Operating System :: Microsoft :: Windows +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: Name Service (DNS) +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Provides: dns +Requires-Python: >=3.6 +Provides-Extra: DOH +Provides-Extra: IDNA +Provides-Extra: DNSSEC +Provides-Extra: trio +Provides-Extra: curio diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dnspython.egg-info/SOURCES.txt b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dnspython.egg-info/SOURCES.txt new file mode 100644 index 0000000..38de748 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dnspython.egg-info/SOURCES.txt @@ -0,0 +1,205 @@ +LICENSE +MANIFEST.in +README.md +pyproject.toml +setup.cfg +setup.py +dns/__init__.py +dns/_asyncbackend.py +dns/_asyncio_backend.py +dns/_curio_backend.py +dns/_immutable_attr.py +dns/_immutable_ctx.py +dns/_trio_backend.py +dns/asyncbackend.py +dns/asyncquery.py +dns/asyncresolver.py +dns/dnssec.py +dns/e164.py +dns/edns.py +dns/entropy.py +dns/enum.py +dns/exception.py +dns/flags.py +dns/grange.py +dns/immutable.py +dns/inet.py +dns/ipv4.py +dns/ipv6.py +dns/message.py +dns/name.py +dns/namedict.py +dns/node.py +dns/opcode.py +dns/py.typed +dns/query.py +dns/rcode.py +dns/rdata.py +dns/rdataclass.py +dns/rdataset.py +dns/rdatatype.py +dns/renderer.py +dns/resolver.py +dns/reversename.py +dns/rrset.py +dns/serial.py +dns/set.py +dns/tokenizer.py +dns/transaction.py +dns/tsig.py +dns/tsigkeyring.py +dns/ttl.py +dns/update.py +dns/version.py +dns/versioned.py +dns/wire.py +dns/xfr.py +dns/zone.py +dns/zonefile.py +dns/rdtypes/__init__.py +dns/rdtypes/dnskeybase.py +dns/rdtypes/dsbase.py +dns/rdtypes/euibase.py +dns/rdtypes/mxbase.py +dns/rdtypes/nsbase.py +dns/rdtypes/svcbbase.py +dns/rdtypes/tlsabase.py +dns/rdtypes/txtbase.py +dns/rdtypes/util.py +dns/rdtypes/ANY/AFSDB.py +dns/rdtypes/ANY/AMTRELAY.py +dns/rdtypes/ANY/AVC.py +dns/rdtypes/ANY/CAA.py +dns/rdtypes/ANY/CDNSKEY.py +dns/rdtypes/ANY/CDS.py +dns/rdtypes/ANY/CERT.py +dns/rdtypes/ANY/CNAME.py +dns/rdtypes/ANY/CSYNC.py +dns/rdtypes/ANY/DLV.py +dns/rdtypes/ANY/DNAME.py +dns/rdtypes/ANY/DNSKEY.py +dns/rdtypes/ANY/DS.py +dns/rdtypes/ANY/EUI48.py +dns/rdtypes/ANY/EUI64.py +dns/rdtypes/ANY/GPOS.py +dns/rdtypes/ANY/HINFO.py +dns/rdtypes/ANY/HIP.py +dns/rdtypes/ANY/ISDN.py +dns/rdtypes/ANY/LOC.py +dns/rdtypes/ANY/MX.py +dns/rdtypes/ANY/NINFO.py +dns/rdtypes/ANY/NS.py +dns/rdtypes/ANY/NSEC.py +dns/rdtypes/ANY/NSEC3.py +dns/rdtypes/ANY/NSEC3PARAM.py +dns/rdtypes/ANY/OPENPGPKEY.py +dns/rdtypes/ANY/OPT.py +dns/rdtypes/ANY/PTR.py +dns/rdtypes/ANY/RP.py +dns/rdtypes/ANY/RRSIG.py +dns/rdtypes/ANY/RT.py +dns/rdtypes/ANY/SMIMEA.py +dns/rdtypes/ANY/SOA.py +dns/rdtypes/ANY/SPF.py +dns/rdtypes/ANY/SSHFP.py +dns/rdtypes/ANY/TKEY.py +dns/rdtypes/ANY/TLSA.py +dns/rdtypes/ANY/TSIG.py +dns/rdtypes/ANY/TXT.py +dns/rdtypes/ANY/URI.py +dns/rdtypes/ANY/X25.py +dns/rdtypes/ANY/__init__.py +dns/rdtypes/CH/A.py +dns/rdtypes/CH/__init__.py +dns/rdtypes/IN/A.py +dns/rdtypes/IN/AAAA.py +dns/rdtypes/IN/APL.py +dns/rdtypes/IN/DHCID.py +dns/rdtypes/IN/HTTPS.py +dns/rdtypes/IN/IPSECKEY.py +dns/rdtypes/IN/KX.py +dns/rdtypes/IN/NAPTR.py +dns/rdtypes/IN/NSAP.py +dns/rdtypes/IN/NSAP_PTR.py +dns/rdtypes/IN/PX.py +dns/rdtypes/IN/SRV.py +dns/rdtypes/IN/SVCB.py +dns/rdtypes/IN/WKS.py +dns/rdtypes/IN/__init__.py +dnspython.egg-info/PKG-INFO +dnspython.egg-info/SOURCES.txt +dnspython.egg-info/dependency_links.txt +dnspython.egg-info/requires.txt +dnspython.egg-info/top_level.txt +examples/async_dns.py +examples/ddns.py +examples/doh-json.py +examples/doh.py +examples/e164.py +examples/ecs.py +examples/mx.py +examples/name.py +examples/query_specific.py +examples/receive_notify.py +examples/reverse.py +examples/reverse_name.py +examples/xfr.py +examples/zonediff.py +tests/Makefile +tests/__init__.py +tests/example +tests/example1.good +tests/example2.good +tests/example3.good +tests/md_module.py +tests/nanonameserver.py +tests/query +tests/stxt_module.py +tests/test_address.py +tests/test_async.py +tests/test_bugs.py +tests/test_constants.py +tests/test_dnssec.py +tests/test_doh.py +tests/test_edns.py +tests/test_entropy.py +tests/test_exceptions.py +tests/test_flags.py +tests/test_generate.py +tests/test_grange.py +tests/test_immutable.py +tests/test_message.py +tests/test_name.py +tests/test_namedict.py +tests/test_nsec3.py +tests/test_nsec3_hash.py +tests/test_ntoaaton.py +tests/test_processing_order.py +tests/test_query.py +tests/test_rdata.py +tests/test_rdataset.py +tests/test_rdtypeandclass.py +tests/test_rdtypeanydnskey.py +tests/test_rdtypeanyeui.py +tests/test_rdtypeanyloc.py +tests/test_rdtypeanytkey.py +tests/test_renderer.py +tests/test_resolution.py +tests/test_resolver.py +tests/test_resolver_override.py +tests/test_rrset.py +tests/test_serial.py +tests/test_set.py +tests/test_svcb.py +tests/test_tokenizer.py +tests/test_transaction.py +tests/test_tsig.py +tests/test_tsigkeyring.py +tests/test_ttl.py +tests/test_update.py +tests/test_wire.py +tests/test_xfr.py +tests/test_zone.py +tests/ttxt_module.py +tests/utest.py +tests/util.py \ No newline at end of file diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dnspython.egg-info/dependency_links.txt b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dnspython.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dnspython.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dnspython.egg-info/requires.txt b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dnspython.egg-info/requires.txt new file mode 100644 index 0000000..8a54a6d --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dnspython.egg-info/requires.txt @@ -0,0 +1,18 @@ + +[DNSSEC] +cryptography>=2.6 + +[DOH] +requests +requests-toolbelt + +[IDNA] +idna>=2.1 + +[curio] +curio>=1.2 +sniffio>=1.1 + +[trio] +trio>=0.14.0 +sniffio>=1.1 diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/dnspython.egg-info/top_level.txt b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dnspython.egg-info/top_level.txt new file mode 100644 index 0000000..2e7065c --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/dnspython.egg-info/top_level.txt @@ -0,0 +1 @@ +dns diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/async_dns.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/async_dns.py new file mode 100644 index 0000000..c42defc --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/async_dns.py @@ -0,0 +1,30 @@ + +import sys + +import trio + +import dns.message +import dns.asyncquery +import dns.asyncresolver + +async def main(): + if len(sys.argv) > 1: + host = sys.argv[0] + else: + host = 'www.dnspython.org' + q = dns.message.make_query(host, 'A') + r = await dns.asyncquery.udp(q, '8.8.8.8') + print(r) + q = dns.message.make_query(host, 'A') + r = await dns.asyncquery.tcp(q, '8.8.8.8') + print(r) + q = dns.message.make_query(host, 'A') + r = await dns.asyncquery.tls(q, '8.8.8.8') + print(r) + a = await dns.asyncresolver.resolve(host, 'A') + print(a.response) + zn = await dns.asyncresolver.zone_for_name(host) + print(zn) + +if __name__ == '__main__': + trio.run(main) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/ddns.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/ddns.py new file mode 100644 index 0000000..c584f42 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/ddns.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 + +# +# Use a TSIG-signed DDNS update to update our hostname-to-address +# mapping. +# +# usage: ddns.py +# +# On linux systems, you can automatically update your DNS any time an +# interface comes up by adding an ifup-local script that invokes this +# python code. +# +# E.g. on my systems I have this +# +# #!/bin/sh +# +# DEVICE=$1 +# +# if [ "X${DEVICE}" == "Xeth0" ]; then +# IPADDR=`LANG= LC_ALL= ifconfig ${DEVICE} | grep 'inet addr' | +# awk -F: '{ print $2 } ' | awk '{ print $1 }'` +# /usr/local/sbin/ddns.py $IPADDR +# fi +# +# in /etc/ifup-local. +# + +import sys + +import dns.update +import dns.query +import dns.tsigkeyring + +# +# Replace the keyname and secret with appropriate values for your +# configuration. +# +keyring = dns.tsigkeyring.from_text({ + 'keyname.' : 'NjHwPsMKjdN++dOfE5iAiQ==' + }) + +# +# Replace "example." with your domain, and "host" with your hostname. +# +update = dns.update.Update('example.', keyring=keyring) +update.replace('host', 300, 'A', sys.argv[1]) + +# +# Replace "10.0.0.1" with the IP address of your master server. +# +response = dns.query.tcp(update, '10.0.0.1', timeout=10) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/doh-json.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/doh-json.py new file mode 100644 index 0000000..8cfe1b0 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/doh-json.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 + +import copy +import json +import requests + +import dns.flags +import dns.message +import dns.resolver +import dns.rdataclass +import dns.rdatatype + +# This shows how to convert to/from dnspython's message object and the +# DNS-over-HTTPS (DoH) JSON form used by Google and Cloudflare, and +# described here: +# +# https://developers.google.com/speed/public-dns/docs/doh/json +# +# There's no need to do this for DoH as dnspython supports the +# standard RFC 8484 protocol which all DoH providers implement. The +# conversion to/from JSON is useful, however, so we show a way to do +# it. +# +# "simple" below means "simple python data types", i.e. things made of +# combinations of dictionaries, lists, strings, and numbers. + +def make_rr(simple, rdata): + csimple = copy.copy(simple) + csimple['data'] = rdata.to_text() + return csimple + +def flatten_rrset(rrs): + simple = { + 'name': str(rrs.name), + 'type': rrs.rdtype, + } + if len(rrs) > 0: + simple['TTL'] = rrs.ttl + return [make_rr(simple, rdata) for rdata in rrs] + else: + return [simple] + +def to_doh_simple(message): + simple = { + 'Status': message.rcode() + } + for f in dns.flags.Flag: + if f != dns.flags.Flag.AA and f != dns.flags.Flag.QR: + # DoH JSON doesn't need AA and omits it. DoH JSON is only + # used in replies so the QR flag is implied. + simple[f.name] = (message.flags & f) != 0 + for i, s in enumerate(message.sections): + k = dns.message.MessageSection.to_text(i).title() + simple[k] = [] + for rrs in s: + simple[k].extend(flatten_rrset(rrs)) + # we don't encode the ecs_client_subnet field + return simple + +def from_doh_simple(simple, add_qr=False): + message = dns.message.QueryMessage() + flags = 0 + for f in dns.flags.Flag: + if simple.get(f.name, False): + flags |= f + if add_qr: # QR is implied + flags |= dns.flags.QR + message.flags = flags + message.set_rcode(simple.get('Status', 0)) + for i, sn in enumerate(dns.message.MessageSection): + rr_list = simple.get(sn.name.title(), []) + for rr in rr_list: + rdtype = dns.rdatatype.RdataType(rr['type']) + rrs = message.find_rrset(i, dns.name.from_text(rr['name']), + dns.rdataclass.IN, rdtype, + create=True) + if 'data' in rr: + rrs.add(dns.rdata.from_text(dns.rdataclass.IN, rdtype, + rr['data']), rr.get('TTL', 0)) + # we don't decode the ecs_client_subnet field + return message + + +a = dns.resolver.resolve('www.dnspython.org', 'a') +p = to_doh_simple(a.response) +print(json.dumps(p, indent=4)) +response = requests.get('https://dns.google/resolve?', verify=True, + params={'name': 'www.dnspython.org', + 'type': 1}) +p = json.loads(response.text) +m = from_doh_simple(p, True) +print(m) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/doh.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/doh.py new file mode 100644 index 0000000..eff9ae7 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/doh.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +# +# This is an example of sending DNS queries over HTTPS (DoH) with dnspython. +# Requires use of the requests module's Session object. +# +# See https://2.python-requests.org//en/latest/user/advanced/#session-objects +# for more details about Session objects +import requests + +import dns.message +import dns.query +import dns.rdatatype + + +def main(): + where = '1.1.1.1' + qname = 'example.com.' + # one method is to use context manager, session will automatically close + with requests.sessions.Session() as session: + q = dns.message.make_query(qname, dns.rdatatype.A) + r = dns.query.https(q, where, session=session) + for answer in r.answer: + print(answer) + + # ... do more lookups + + where = 'https://dns.google/dns-query' + qname = 'example.net.' + # second method, close session manually + session = requests.sessions.Session() + q = dns.message.make_query(qname, dns.rdatatype.A) + r = dns.query.https(q, where, session=session) + for answer in r.answer: + print(answer) + + # ... do more lookups + + # close the session when you're done + session.close() + +if __name__ == '__main__': + main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/e164.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/e164.py new file mode 100644 index 0000000..6d9e872 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/e164.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import dns.e164 +n = dns.e164.from_e164("+1 555 1212") +print(n) +print(dns.e164.to_e164(n)) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/ecs.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/ecs.py new file mode 100644 index 0000000..f7b31d8 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/ecs.py @@ -0,0 +1,15 @@ + +import dns.edns +import dns.message +import dns.query + +# This example demonstrates how to use the EDNS client subnet option + +ADDRESS = '0.0.0.0' # replace this with the address you want to check +PREFIX = 0 # replace this with a prefix length (typically 24 for IPv4) + +ecs = dns.edns.ECSOption(ADDRESS, PREFIX) +q = dns.message.make_query('www.google.com', 'A', use_edns=0, options=[ecs]) +r = dns.query.udp(q, '8.8.8.8') +print(r) + diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/mx.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/mx.py new file mode 100644 index 0000000..2c310ea --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/mx.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 + +import dns.resolver + +answers = dns.resolver.resolve('nominum.com', 'MX') +for rdata in answers: + print('Host', rdata.exchange, 'has preference', rdata.preference) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/name.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/name.py new file mode 100644 index 0000000..614fdbc --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/name.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +import dns.name + +n = dns.name.from_text('www.dnspython.org') +o = dns.name.from_text('dnspython.org') +print(n.is_subdomain(o)) # True +print(n.is_superdomain(o)) # False +print(n > o) # True +rel = n.relativize(o) # rel is the relative name www +n2 = rel + o +print(n2 == n) # True +print(n.labels) # ['www', 'dnspython', 'org', ''] diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/query_specific.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/query_specific.py new file mode 100644 index 0000000..f0121fb --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/query_specific.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 + +# Two ways of querying a specific nameserver. + +import dns.message +import dns.rdataclass +import dns.rdatatype +import dns.query + +# This way is just like nslookup/dig: + +qname = dns.name.from_text('amazon.com') +q = dns.message.make_query(qname, dns.rdatatype.NS) +print('The query is:') +print(q) +print('') +r = dns.query.udp(q, '8.8.8.8') +print('The response is:') +print(r) +print('') +print('The nameservers are:') +ns_rrset = r.find_rrset(r.answer, qname, dns.rdataclass.IN, dns.rdatatype.NS) +for rr in ns_rrset: + print(rr.target) +print('') +print('') + +# A higher-level way + +import dns.resolver + +resolver = dns.resolver.Resolver(configure=False) +resolver.nameservers = ['8.8.8.8'] +answer = resolver.resolve('amazon.com', 'NS') +print('The nameservers are:') +for rr in answer: + print(rr.target) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/receive_notify.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/receive_notify.py new file mode 100644 index 0000000..c41b336 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/receive_notify.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 + +# This is just a toy, real code would check that the received message +# really was a NOTIFY, and otherwise handle errors. + +import socket + +import dns.flags +import dns.message +import dns.rdataclass +import dns.rdatatype +import dns.name + +from typing import cast + +address = '127.0.0.1' +port = 53535 + +s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +s.bind((address, port)) +while True: + (wire, address) = s.recvfrom(512) + notify = dns.message.from_wire(wire) + + try: + soa = notify.find_rrset(notify.answer, notify.question[0].name, + dns.rdataclass.IN, dns.rdatatype.SOA) + + # Do something with the SOA RR here + print('The serial number for', soa.name, 'is', soa[0].serial) + except KeyError: + # No SOA RR in the answer section. + pass + + response = dns.message.make_response(notify) # type: dns.message.Message + response.flags |= dns.flags.AA + wire = response.to_wire(cast(dns.name.Name, response)) + s.sendto(wire, address) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/reverse.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/reverse.py new file mode 100644 index 0000000..83b99b7 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/reverse.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 + +# Usage: reverse.py ... +# +# This demo script will load in all of the zones specified by the +# filenames on the command line, find all the A RRs in them, and +# construct a reverse mapping table that maps each IP address used to +# the list of names mapping to that address. The table is then sorted +# nicely and printed. +# +# Note! The zone name is taken from the basename of the filename, so +# you must use filenames like "/wherever/you/like/dnspython.org" and +# not something like "/wherever/you/like/foo.db" (unless you're +# working with the ".db" GTLD, of course :)). +# +# If this weren't a demo script, there'd be a way of specifying the +# origin for each zone instead of constructing it from the filename. + +import dns.zone +import dns.ipv4 +import os.path +import sys +from typing import Dict, List # pylint: disable=unused-import + +reverse_map = {} # type: Dict[str, List[str]] + +for filename in sys.argv[1:]: + zone = dns.zone.from_file(filename, os.path.basename(filename), + relativize=False) + for (name, ttl, rdata) in zone.iterate_rdatas('A'): + print(type(rdata)) + try: + reverse_map[rdata.address].append(name.to_text()) + except KeyError: + reverse_map[rdata.address] = [name.to_text()] + +for k in sorted(reverse_map.keys(), key=dns.ipv4.inet_aton): + v = reverse_map[k] + v.sort() + print(k, v) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/reverse_name.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/reverse_name.py new file mode 100644 index 0000000..02b2e51 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/reverse_name.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import dns.reversename +n = dns.reversename.from_address("127.0.0.1") +print(n) +print(dns.reversename.to_address(n)) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/xfr.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/xfr.py new file mode 100644 index 0000000..a20cae3 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/xfr.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python3 + +import dns.query +import dns.resolver +import dns.zone + +soa_answer = dns.resolver.resolve('dnspython.org', 'SOA') +master_answer = dns.resolver.resolve(soa_answer[0].mname, 'A') + +z = dns.zone.from_xfr(dns.query.xfr(master_answer[0].address, 'dnspython.org')) +for n in sorted(z.nodes.keys()): + print(z[n].to_text(n)) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/zonediff.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/zonediff.py new file mode 100644 index 0000000..164bf2b --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/examples/zonediff.py @@ -0,0 +1,310 @@ +#!/usr/bin/env python3 +# +# Small library and commandline tool to do logical diffs of zonefiles +# ./zonediff -h gives you help output +# +# Requires dnspython to do all the heavy lifting +# +# (c)2009 Dennis Kaarsemaker +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +"""See diff_zones.__doc__ for more information""" + +from typing import cast, Union, Any # pylint: disable=unused-import + +__all__ = ['diff_zones', 'format_changes_plain', 'format_changes_html'] + +try: + import dns.zone + import dns.node +except ImportError: + raise SystemExit("Please install dnspython") + + +def diff_zones(zone1, # type: dns.zone.Zone + zone2, # type: dns.zone.Zone + ignore_ttl=False, + ignore_soa=False + ): # type: (...) -> list + """diff_zones(zone1, zone2, ignore_ttl=False, ignore_soa=False) -> changes + Compares two dns.zone.Zone objects and returns a list of all changes + in the format (name, oldnode, newnode). + + If ignore_ttl is true, a node will not be added to this list if the + only change is its TTL. + + If ignore_soa is true, a node will not be added to this list if the + only changes is a change in a SOA Rdata set. + + The returned nodes do include all Rdata sets, including unchanged ones. + """ + + changes = [] + for name in zone1: + namestr = str(name) + n1 = cast(dns.node.Node, zone1.get_node(namestr)) + n2 = cast(dns.node.Node, zone2.get_node(namestr)) + if not n2: + changes.append((str(name), n1, n2)) + elif _nodes_differ(n1, n2, ignore_ttl, ignore_soa): + changes.append((str(name), n1, n2)) + + for name in zone2: + n3 = cast(dns.node.Node, zone1.get_node(name)) + if not n3: + n4 = cast(dns.node.Node, zone2.get_node(name)) + changes.append((str(name), n3, n4)) + return changes + +def _nodes_differ(n1, # type: dns.node.Node + n2, # type: dns.node.Node + ignore_ttl, # type: bool + ignore_soa # type: bool + ): # type: (...) -> bool + if ignore_soa or not ignore_ttl: + # Compare datasets directly + for r in n1.rdatasets: + if ignore_soa and r.rdtype == dns.rdatatype.SOA: + continue + if r not in n2.rdatasets: + return True + if not ignore_ttl: + return r.ttl != n2.find_rdataset(r.rdclass, r.rdtype).ttl + + for r in n2.rdatasets: + if ignore_soa and r.rdtype == dns.rdatatype.SOA: + continue + if r not in n1.rdatasets: + return True + assert False + else: + return n1 != n2 + +def format_changes_plain(oldf, # type: str + newf, # type: str + changes, # type: list + ignore_ttl=False + ): # type: (...) -> str + """format_changes(oldfile, newfile, changes, ignore_ttl=False) -> str + Given 2 filenames and a list of changes from diff_zones, produce diff-like + output. If ignore_ttl is True, TTL-only changes are not displayed""" + + ret = "--- {}\n+++ {}\n".format(oldf, newf) + for name, old, new in changes: + ret += "@ %s\n" % name + if not old: + for r in new.rdatasets: + ret += "+ %s\n" % str(r).replace('\n', '\n+ ') + elif not new: + for r in old.rdatasets: + ret += "- %s\n" % str(r).replace('\n', '\n+ ') + else: + for r in old.rdatasets: + if r not in new.rdatasets or ( + r.ttl != new.find_rdataset(r.rdclass, r.rdtype).ttl and + not ignore_ttl + ): + ret += "- %s\n" % str(r).replace('\n', '\n+ ') + for r in new.rdatasets: + if r not in old.rdatasets or ( + r.ttl != old.find_rdataset(r.rdclass, r.rdtype).ttl and + not ignore_ttl + ): + ret += "+ %s\n" % str(r).replace('\n', '\n+ ') + return ret + +def format_changes_html(oldf, # type: str + newf, # type: str + changes, # type: list + ignore_ttl=False + ): # type: (...) -> str + """format_changes(oldfile, newfile, changes, ignore_ttl=False) -> str + Given 2 filenames and a list of changes from diff_zones, produce nice html + output. If ignore_ttl is True, TTL-only changes are not displayed""" + + ret = ''' + + + + + + + + \n''' % (oldf, newf) + + for name, old, new in changes: + ret += ' \n \n' % name + if not old: + for r in new.rdatasets: + ret += ( + ' \n' + ' \n' + ) % str(r).replace('\n', '
') + elif not new: + for r in old.rdatasets: + ret += ( + ' \n' + ' \n' + ) % str(r).replace('\n', '
') + else: + ret += ' \n' + ret += ' \n' + ret += ' \n' + return ret + ' \n
 %s%s
%s %s%s ' + for r in old.rdatasets: + if r not in new.rdatasets or ( + r.ttl != new.find_rdataset(r.rdclass, r.rdtype).ttl and + not ignore_ttl + ): + ret += str(r).replace('\n', '
') + ret += '
' + for r in new.rdatasets: + if r not in old.rdatasets or ( + r.ttl != old.find_rdataset(r.rdclass, r.rdtype).ttl and + not ignore_ttl + ): + ret += str(r).replace('\n', '
') + ret += '
' + + +# Make this module usable as a script too. +def main(): # type: () -> None + import argparse + import subprocess + import sys + import traceback + + usage = """%prog zonefile1 zonefile2 - Show differences between zones in a diff-like format +%prog [--git|--bzr|--rcs] zonefile rev1 [rev2] - Show differences between two revisions of a zonefile + +The differences shown will be logical differences, not textual differences. +""" + p = argparse.ArgumentParser(usage=usage) + p.add_argument('-s', '--ignore-soa', action="store_true", default=False, dest="ignore_soa", + help="Ignore SOA-only changes to records") + p.add_argument('-t', '--ignore-ttl', action="store_true", default=False, dest="ignore_ttl", + help="Ignore TTL-only changes to Rdata") + p.add_argument('-T', '--traceback', action="store_true", default=False, dest="tracebacks", + help="Show python tracebacks when errors occur") + p.add_argument('-H', '--html', action="store_true", default=False, dest="html", + help="Print HTML output") + p.add_argument('-g', '--git', action="store_true", default=False, dest="use_git", + help="Use git revisions instead of real files") + p.add_argument('-b', '--bzr', action="store_true", default=False, dest="use_bzr", + help="Use bzr revisions instead of real files") + p.add_argument('-r', '--rcs', action="store_true", default=False, dest="use_rcs", + help="Use rcs revisions instead of real files") + opts, args = p.parse_args() + opts.use_vc = opts.use_git or opts.use_bzr or opts.use_rcs + + def _open(what, err): # type: (Union[list,str], str) -> Any + if isinstance(what, list): + # Must be a list, open subprocess + try: + proc = subprocess.Popen(what, stdout=subprocess.PIPE) + proc.wait() + if proc.returncode == 0: + return proc.stdout + sys.stderr.write(err + "\n") + except Exception: + sys.stderr.write(err + "\n") + if opts.tracebacks: + traceback.print_exc() + else: + # Open as normal file + try: + return open(what, 'rb') + except IOError: + sys.stderr.write(err + "\n") + if opts.tracebacks: + traceback.print_exc() + + if not opts.use_vc and len(args) != 2: + p.print_help() + sys.exit(64) + if opts.use_vc and len(args) not in (2, 3): + p.print_help() + sys.exit(64) + + # Open file descriptors + if not opts.use_vc: + oldn, newn = args + else: + if len(args) == 3: + filename, oldr, newr = args + oldn = "{}:{}".format(oldr, filename) + newn = "{}:{}".format(newr, filename) + else: + filename, oldr = args + newr = None + oldn = "{}:{}".format(oldr, filename) + newn = filename + + old, new = None, None + oldz, newz = None, None + if opts.use_bzr: + old = _open(["bzr", "cat", "-r" + oldr, filename], + "Unable to retrieve revision {} of {}".format(oldr, filename)) + if newr is not None: + new = _open(["bzr", "cat", "-r" + newr, filename], + "Unable to retrieve revision {} of {}".format(newr, filename)) + elif opts.use_git: + old = _open(["git", "show", oldn], + "Unable to retrieve revision {} of {}".format(oldr, filename)) + if newr is not None: + new = _open(["git", "show", newn], + "Unable to retrieve revision {} of {}".format(newr, filename)) + elif opts.use_rcs: + old = _open(["co", "-q", "-p", "-r" + oldr, filename], + "Unable to retrieve revision {} of {}".format(oldr, filename)) + if newr is not None: + new = _open(["co", "-q", "-p", "-r" + newr, filename], + "Unable to retrieve revision {} of {}".format(newr, filename)) + if not opts.use_vc: + old = _open(oldn, "Unable to open %s" % oldn) + if not opts.use_vc or newr is None: + new = _open(newn, "Unable to open %s" % newn) + + if not old or not new: + sys.exit(65) + + # Parse the zones + try: + oldz = dns.zone.from_file(old, origin='.', check_origin=False) + except dns.exception.DNSException: + sys.stderr.write("Incorrect zonefile: %s\n" % old) + if opts.tracebacks: + traceback.print_exc() + try: + newz = dns.zone.from_file(new, origin='.', check_origin=False) + except dns.exception.DNSException: + sys.stderr.write("Incorrect zonefile: %s\n" % new) + if opts.tracebacks: + traceback.print_exc() + if not oldz or not newz: + sys.exit(65) + + changes = diff_zones(oldz, newz, opts.ignore_ttl, opts.ignore_soa) + changes.sort() + + if not changes: + sys.exit(0) + if opts.html: + print(format_changes_html(oldn, newn, changes, opts.ignore_ttl)) + else: + print(format_changes_plain(oldn, newn, changes, opts.ignore_ttl)) + sys.exit(1) + +if __name__ == '__main__': + main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/pyproject.toml b/NSICollectionPlatformServer/packages/dnspython-2.1.0/pyproject.toml new file mode 100644 index 0000000..11f1c63 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/pyproject.toml @@ -0,0 +1,40 @@ +[tool.poetry] +name = "dnspython" +version = "2.1.0" +description = "DNS toolkit" +authors = ["Bob Halley "] +license = "ISC" +packages = [ + {include = "dns"} +] + +[tool.poetry.dependencies] +python = "^3.6" +requests-toolbelt = {version="^0.9.1", optional=true} +requests = {version="^2.23.0", optional=true} +idna = {version="^2.1", optional=true} +cryptography = {version=">=2.6,<4.0", optional=true} +trio = {version=">=0.14,<0.18", optional=true} +curio = {version="^1.2", optional=true} +sniffio = {version="^1.1", optional=true} + +[tool.poetry.dev-dependencies] +mypy = "^0.790" +pytest = ">=5.4.1,<7" +pytest-cov = "^2.10.0" +flake8 = "^3.7.9" +sphinx = "^3.0.0" +coverage = "^5.1" +twine = "^3.1.1" +wheel = "^0.35.0" + +[tool.poetry.extras] +doh = ['requests', 'requests-toolbelt'] +idna = ['idna'] +dnssec = ['cryptography'] +trio = ['trio'] +curio = ['curio', 'sniffio'] + +[build-system] +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/setup.cfg b/NSICollectionPlatformServer/packages/dnspython-2.1.0/setup.cfg new file mode 100644 index 0000000..24f5ef6 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/setup.cfg @@ -0,0 +1,7 @@ +[metadata] +license_file = LICENSE + +[egg_info] +tag_build = +tag_date = 0 + diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/setup.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/setup.py new file mode 100644 index 0000000..196d938 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/setup.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +# +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license +# +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import sys +from setuptools import setup + +version = '2.1.0' + +try: + sys.argv.remove("--cython-compile") +except ValueError: + compile_cython = False +else: + compile_cython = True + from Cython.Build import cythonize + ext_modules = cythonize(['dns/*.py', 'dns/rdtypes/*.py', 'dns/rdtypes/*/*.py'], + language_level='3') + +kwargs = { + 'name' : 'dnspython', + 'version' : version, + 'description' : 'DNS toolkit', + 'long_description' : \ + """dnspython is a DNS toolkit for Python. It supports almost all +record types. It can be used for queries, zone transfers, and dynamic +updates. It supports TSIG authenticated messages and EDNS0. + +dnspython provides both high and low level access to DNS. The high +level classes perform queries for data of a given name, type, and +class, and return an answer set. The low level classes allow +direct manipulation of DNS zones, messages, names, and records.""", + 'author' : 'Bob Halley', + 'author_email' : 'halley@dnspython.org', + 'license' : 'ISC', + 'url' : 'http://www.dnspython.org', + 'packages' : ['dns', 'dns.rdtypes', 'dns.rdtypes.IN', 'dns.rdtypes.ANY', + 'dns.rdtypes.CH'], + 'package_data' : {'dns': ['py.typed']}, + 'classifiers' : [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Intended Audience :: System Administrators", + "License :: OSI Approved :: ISC License (ISCL)", + "Operating System :: POSIX", + "Operating System :: Microsoft :: Windows", + "Programming Language :: Python", + "Topic :: Internet :: Name Service (DNS)", + "Topic :: Software Development :: Libraries :: Python Modules", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + ], + 'python_requires': '>=3.6', + 'test_suite': 'tests', + 'provides': ['dns'], + 'extras_require': { + 'DOH': ['requests', 'requests-toolbelt'], + 'IDNA': ['idna>=2.1'], + 'DNSSEC': ['cryptography>=2.6'], + 'trio': ['trio>=0.14.0', 'sniffio>=1.1'], + 'curio': ['curio>=1.2', 'sniffio>=1.1'], + }, + 'ext_modules': ext_modules if compile_cython else None, + 'zip_safe': False if compile_cython else None, + } + +setup(**kwargs) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/Makefile b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/Makefile new file mode 100644 index 0000000..540e27c --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/Makefile @@ -0,0 +1,25 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile,v 1.5 2004/03/19 00:17:27 halley Exp $ + +PYTHON=python + +check: test + +test: + ${PYTHON} ./utest.py diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/__init__.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/example b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/example new file mode 100644 index 0000000..b9a802b --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/example @@ -0,0 +1,244 @@ +; Copyright (C) 2000, 2001 Internet Software Consortium. +; +; Permission to use, copy, modify, and distribute this software for any +; purpose with or without fee is hereby granted, provided that the above +; copyright notice and this permission notice appear in all copies. +; +; THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM +; DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL +; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +; INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, +; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +; FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +; NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +; WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +; $Id: example 265924 2016-05-20 18:26:42Z bwelling $ + +$ORIGIN . +$TTL 300 ; 5 minutes +example IN SOA ns1.example. hostmaster.example. 1 2 3 4 5 +example. NS ns1.example. +ns1.example. A 10.53.0.1 +example. NS ns2.example. +ns2.example. A 10.53.0.2 + +$ORIGIN example. +@ NSEC3PARAM 1 1 12 aabbccdd +@ NSEC3PARAM 1 1 12 - +* MX 10 mail +a TXT "foo foo foo" + PTR foo.net. +$TTL 3600 ; 1 hour +a01 A 0.0.0.0 +a02 A 255.255.255.255 +;; +;a601 A6 0 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff +; A6 64 ::ffff:ffff:ffff:ffff foo. +; A6 127 ::1 foo. +; A6 128 . +aaaa01 AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff +aaaa02 AAAA ::1 +afsdb01 AFSDB 0 hostname +afsdb02 AFSDB 65535 . +$TTL 300 ; 5 minutes +b CNAME foo.net. +c A 73.80.65.49 +$TTL 3600 ; 1 hour +cert01 CERT 65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl d80jEeC8aTrO+KKmCaY= +cname01 CNAME cname-target. +cname02 CNAME cname-target +cname03 CNAME . +dhcid01 DHCID AAIBY2/AuCccgoJbsaxcQc9TUapptP69lOjxfNuVAA2kjEA= +dhcid02 DHCID AAEBOSD+XR3Os/0LozeXVqcNc7FwCfQdWL3b/NaiUDlW2No= +dhcid03 DHCID AAABxLmlskllE0MVjd57zHcWmEH3pCQ6VytcKD//7es/deY= +$TTL 300 ; 5 minutes +d A 73.80.65.49 +$TTL 3600 ; 1 hour +dname01 DNAME dname-target. +dname02 DNAME dname-target +dname03 DNAME . +$TTL 300 ; 5 minutes +e MX 10 mail + TXT "one" + TXT "three" + TXT "two" + A 73.80.65.49 + A 73.80.65.50 + A 73.80.65.52 + A 73.80.65.51 +f A 73.80.65.52 +$TTL 3600 ; 1 hour +gpos01 GPOS "-22.6882" "116.8652" "250.0" +;; +;; XXXRTH I have commented out the following line because I don't think +;; it is a valid GPOS record. +;; +;;gpos02 GPOS "" "" "" +hinfo01 HINFO "Generic PC clone" "NetBSD-1.4" +hinfo02 HINFO "PC" "NetBSD" +isdn01 ISDN "isdn-address" +isdn02 ISDN "isdn-address" "subaddress" +isdn03 ISDN isdn-address +isdn04 ISDN isdn-address subaddress +;key01 KEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3 GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o jqf0BaqHT+8= +;key02 KEY HOST|FLAG4 DNSSEC RSAMD5 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3 GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o jqf0BaqHT+8= +kx01 KX 10 kdc +kx02 KX 10 . +loc01 LOC 60 9 N 24 39 E 10 20 2000 20 +loc02 LOC 60 09 00.000 N 24 39 00.000 E 10.00m 20.00m 2000.00m 20.00m +loc03 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 90000000.00m 2000m 20m +loc04 LOC 60 9 1.5 N 24 39 0.000 E 10.00m 90000000.00m 2000m 20m +loc05 LOC 60 9 1.51 N 24 39 0.000 E 10.00m 90000000.00m 2000m 20m +loc06 LOC 60 9 1 N 24 39 0.000 E 10.00m 90000000.00m 2000m 20m +loc07 LOC 0 9 1 N 24 39 E 10 90000000 2000 20 +loc08 LOC 0 9 1 S 24 39 0.000 E 10.00m 90000000.00m 2000m 20m +;; +;; XXXRTH These are all obsolete and unused. dnspython doesn't implement +;; them +;;mb01 MG madname +;;mb02 MG . +;;mg01 MG mgmname +;;mg02 MG . +;;minfo01 MINFO rmailbx emailbx +;;minfo02 MINFO . . +;;mr01 MR mrname +;;mr02 MR . +mx01 MX 10 mail +mx02 MX 10 . +naptr01 NAPTR 0 0 "" "" "" . +naptr02 NAPTR 65535 65535 "blurgh" "blorf" "blegh" foo. +nsap-ptr01 NSAP-PTR foo. + NSAP-PTR . +nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100 +nsap02 NSAP 0x47.000580005a0000000001e133ffffff000161.00 +;nxt01 NXT a.secure ( NS SOA MX SIG KEY LOC NXT ) +;nxt02 NXT . ( NSAP-PTR NXT ) +;nxt03 NXT . ( A ) +;nxt04 NXT . ( 127 ) +ptr01 PTR example. +px01 PX 65535 foo. bar. +px02 PX 65535 . . +rp01 RP mbox-dname txt-dname +rp02 RP . . +rt01 RT 0 intermediate-host +rt02 RT 65535 . +$TTL 300 ; 5 minutes +s NS ns.s +$ORIGIN s.example. +ns A 73.80.65.49 +$ORIGIN example. +$TTL 3600 ; 1 hour +;sig01 SIG NXT 1 3 3600 20200101000000 20030101000000 2143 foo MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl d80jEeC8aTrO+KKmCaY= +srv01 SRV 0 0 0 . +srv02 SRV 65535 65535 65535 old-slow-box.example.com. +$TTL 301 ; 5 minutes 1 second +t A 73.80.65.49 +$TTL 3600 ; 1 hour +tlsa1 TLSA 3 1 1 a9cdf989b504fe5dca90c0d2167b6550570734f7c763e09fdf88904e06157065 +tlsa2 TLSA 1 0 1 efddf0d915c7bdc5782c0881e1b2a95ad099fbdd06d7b1f77982d9364338d955 +tlsa3 TLSA 1 0 2 81ee7f6c0ecc6b09b7785a9418f54432de630dd54dc6ee9e3c49de547708d236d4c413c3e97e44f969e635958aa410495844127c04883503e5b024cf7a8f6a94 +smimea1 SMIMEA 3 1 1 a9cdf989b504fe5dca90c0d2167b6550570734f7c763e09fdf88904e06157065 +smimea2 SMIMEA 1 0 1 efddf0d915c7bdc5782c0881e1b2a95ad099fbdd06d7b1f77982d9364338d955 +smimea3 SMIMEA 1 0 2 81ee7f6c0ecc6b09b7785a9418f54432de630dd54dc6ee9e3c49de547708d236d4c413c3e97e44f969e635958aa410495844127c04883503e5b024cf7a8f6a94 +txt01 TXT "foo" +txt02 TXT "foo" "bar" +txt03 TXT foo +txt04 TXT foo bar +txt05 TXT "foo bar" +txt06 TXT "foo\032bar" +txt07 TXT foo\032bar +txt08 TXT "foo\010bar" +txt09 TXT foo\010bar +txt10 TXT foo\ bar +txt11 TXT "\"foo\"" +txt12 TXT \"foo\" +txt13 TXT "foo;" +txt14 TXT "foo\;" +txt15 TXT "bar\\;" +$TTL 300 ; 5 minutes +u TXT "txt-not-in-nxt" +$ORIGIN u.example. +a A 73.80.65.49 +b A 73.80.65.49 +$ORIGIN example. +$TTL 3600 ; 1 hour +wks01 WKS 10.0.0.1 6 ( 0 1 2 21 23 ) +wks02 WKS 10.0.0.1 17 ( 0 1 2 53 ) +wks03 WKS 10.0.0.2 6 ( 65535 ) +x2501 X25 "123456789" +ds01 DS 12345 3 1 123456789abcdef67890123456789abcdef67890 +dlv01 DLV 12345 3 1 123456789abcdef67890123456789abcdef67890 +apl01 APL 1:192.168.32.0/21 !1:192.168.38.0/28 +apl02 APL 1:224.0.0.0/4 2:FF00:0:0:0:0:0:0:0/8 +unknown2 TYPE999 \# 8 0a0000010a000001 +unknown3 A \# 4 7f000002 +rrsig01 RRSIG NSEC 1 3 3600 20200101000000 20030101000000 2143 foo MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl d80jEeC8aTrO+KKmCaY= +rrsig02 RRSIG NSEC 1 3 3600 1577836800 1041379200 2143 foo MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl d80jEeC8aTrO+KKmCaY= +nsec01 NSEC a.secure A MX RRSIG NSEC TYPE1234 +nsec02 NSEC . ( NSAP-PTR NSEC ) +nsec03 NSEC . ( NSEC TYPE65535 ) +nsec301 NSEC3 1 1 12 aabbccdd 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG +nsec302 NSEC3 1 1 12 - 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG +dnskey01 DNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3 GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o jqf0BaqHT+8= +dnskey02 DNSKEY 257 3 RSAMD5 ( AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3 GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o jqf0BaqHT+8= ) +sshfp1 SSHFP 1 1 aa549bfe898489c02d1715d97d79c57ba2fa76ab +spf SPF "v=spf1 mx -all" +ipseckey01 IPSECKEY 10 1 2 192.0.2.38 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== +ipseckey02 IPSECKEY 10 0 2 . AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== +ipseckey03 IPSECKEY 10 3 2 mygateway.example.com. AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== +ipseckey04 IPSECKEY 10 2 2 2001:0DB8:0:8002::2000:1 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== +ipseckey05 IPSECKEY 10 3 2 mygateway2 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== +hip01 HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D +hip02 HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs.example.com. +hip03 HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs1.example.com. rvs2.example.com. +cds01 CDS 12345 3 1 123456789abcdef67890123456789abcdef67890 +cdnskey01 CDNSKEY 256 3 8 ( AwEAAbmiLgh411Pz3v3XCSBrvYf52A/Gv55ItN1NbOLH Cqt3Ec3p+VB/kQ87VjjMrycanZFnZT4l9uCFuYh21Ccy xVpcxExbM0UuhX5rJoDyeFSXoQlkHrB01osPl5Vri5Ym KtcmqGxZ9An0VSunohkyiX1SrNRZSdQnk9/pIHDe/c8D ) +uri01 URI 10 1 "ftp://ftp1.example.com/public" +uri02 URI 10 1 "http://www.example.com/path" +caa01 CAA 0 issue "ca.example.net" +caa02 CAA 0 iodef "mailto:security@example.com" +caa03 CAA 0 iodef "http://iodef.example.com/" +caa04 CAA 0 issue "ca.example.net; account=230123" +caa05 CAA 0 issue "ca.example.net; policy=ev" +caa06 CAA 128 tbs "Unknown" +openpgpkey OPENPGPKEY ( +mQENBEteQDsBCADYnatn9+5t43AdJlVk9dZC2RM0idPQcmrrKcjeAWDnISqoJzkv +Q8ifX6mefquTBsDZC279uXShyTffYzQtvP2r9ewkK7zmSv52Ar563TSULAMwiLpe +0gGQE0ex20mX5ggtYn6czdbEtcKpW0t+AfDqRk5YcpgqfZKXapKQ+A3CwWJKP9i3 +ldx2Jz//kuru4YqROLBYyB8D6V2jNUFOdaP6j5C5prh9dxfYFp2O/xFeAKLWlWuH +9o96INUoIhgdEyj9PHPT3c821NMZu8tCvsZgUB+QPbHA/QYGa+aollcdGkJpVxXo +Hhbu6aMx/B+pXg55WM5pqOxmoVjyViHIUYfPABEBAAG0IUJvYiBIYWxsZXkgPGhh +bGxleUBkbnNweXRob24ub3JnPokBPgQTAQIAKAUCS15AOwIbAwUJA8JnAAYLCQgH +AwIGFQgCCQoLBBYCAwECHgECF4AACgkQ6o6Gb8yUnXaflQgAhlhIqZGncRw3LV3d +24JmPD+UEcEGiVh2b/Ic/1TMec46Ts7ZqRXAcOATNteQmpzqexx+BRKDWU8ZgYx1 +2J4GZmC06jABr2JDWxgvbMX9qjkUUgDGZZgAS/B2x5AmKgy2ZnCUlaKfePcKmtKT +B9yNJ8v/WERlFdGaUveEUiFU8g75xp1Hj9Wp9sXCg9yeG1K2RwQ3RQd5tLudhyE6 +7EQdFGgqQFynR53md7cmVhAGopKLwMkpCtToKUlxxlfnDfpKZhhXThmhA0PsUQUk +JptfGwYwH3O2N3KzfUw3wXRvLa3hona3TlHk3kfg7Qyd7oP4AZGbJKp97YHnfqo1 +kp8rObkBDQRLXkA7AQgA0ePG7g5GgZ/1SdtGZlJJiE2X15vTUc3KGfmx/kI5NaUD +u4fXb+XK+yFy9I/X+UJ46JSkyhj6QvUxpoI+A7WWk9ThfjbynoZxRD820Kbqidqx +BSgtFF36SRWzmX8DZfKKAskT9ZGU1odeSKDXLCJF7qAbZVRTuFRiDFGwtoVIICeE +6Xd65JO6ufhad+ELhgFt95vRwTiFvVrBRjwF7ZgN/nOXfYncxZ/2mpFqfwsnB2eu +0A2XZBm8IngsSmr/Wrz1RQ7+SNMqt77E7CKwBX7UIAZgyoJxIRxWirJoOt1rIm5V +UqRR25ubXLuzx9PaHYiC5GiQIU45pWAd0IWcTI/MJQARAQABiQElBBgBAgAPBQJL +XkA7AhsMBQkDwmcAAAoJEOqOhm/MlJ12HRsIAKrB9E++9X9W6VTXBfdkShCFv0yk +ZVn2eVs6tkqzoub9s4f+Z5ylWw+a5nkMDMdGVe6bn4A3oIAbf0Tjykq1AetZLVPs +Hl/QosTbSQluis/PEvJkTQXHaKHB3bFhwA90c/3HNhrLGugt9AmcfLf9LAynXDgN +LV5eYdPYqfKE+27qjEBARf6PYh/8WQ8CPKS8DILFbwCZbRxUogyrZf/7AiHAGdJi +8dmpR1WPQYef2hF3kqGX6NngLBPzZ6CQRaHBhD4pHU1S/IRSlx9/3Ytww32PYD9A +yO732NmCUcq3bmvqcOWy4Cc1NkEwU0Vg0qzwVBNGb84v/ex2MouwtAYScwc= +) +amtrelay01 AMTRELAY 0 0 0 . +amtrelay02 AMTRELAY 0 1 0 . +amtrelay03 AMTRELAY 10 0 1 203.0.113.15 +amtrelay04 AMTRELAY 10 0 2 2001:db8::15 +amtrelay05 AMTRELAY 128 1 3 amtrelays.example.com. +csync0 CSYNC 12345 0 A MX RRSIG NSEC TYPE1234 +avc01 AVC "app-name:WOLFGANG|app-class:OAM|business=yes" +svcb01 SVCB ( +100 foo.com. mandatory="alpn,port" alpn="h2,h3" no-default-alpn port="12345" +echconfig="abcd" ipv4hint=1.2.3.4,4.3.2.1 ipv6hint=1::2,3::4 key12345="foo" +) +https01 HTTPS 0 svc +https02 HTTPS 1 . port=8002 echconfig="abcd" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/example1.good b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/example1.good new file mode 100644 index 0000000..03fd08d --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/example1.good @@ -0,0 +1,149 @@ +@ 300 IN SOA ns1 hostmaster 1 2 3 4 5 +@ 300 IN NS ns1 +@ 300 IN NS ns2 +@ 300 IN NSEC3PARAM 1 1 12 aabbccdd +@ 300 IN NSEC3PARAM 1 1 12 - +* 300 IN MX 10 mail +a 300 IN TXT "foo foo foo" +a 300 IN PTR foo.net. +a01 3600 IN A 0.0.0.0 +a02 3600 IN A 255.255.255.255 +aaaa01 3600 IN AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff +aaaa02 3600 IN AAAA ::1 +afsdb01 3600 IN AFSDB 0 hostname +afsdb02 3600 IN AFSDB 65535 . +amtrelay01 3600 IN AMTRELAY 0 0 0 . +amtrelay02 3600 IN AMTRELAY 0 1 0 . +amtrelay03 3600 IN AMTRELAY 10 0 1 203.0.113.15 +amtrelay04 3600 IN AMTRELAY 10 0 2 2001:db8::15 +amtrelay05 3600 IN AMTRELAY 128 1 3 amtrelays.example.com. +apl01 3600 IN APL 1:192.168.32.0/21 !1:192.168.38.0/28 +apl02 3600 IN APL 1:224.0.0.0/4 2:FF00:0:0:0:0:0:0:0/8 +avc01 3600 IN AVC "app-name:WOLFGANG|app-class:OAM|business=yes" +b 300 IN CNAME foo.net. +c 300 IN A 73.80.65.49 +caa01 3600 IN CAA 0 issue "ca.example.net" +caa02 3600 IN CAA 0 iodef "mailto:security@example.com" +caa03 3600 IN CAA 0 iodef "http://iodef.example.com/" +caa04 3600 IN CAA 0 issue "ca.example.net; account=230123" +caa05 3600 IN CAA 0 issue "ca.example.net; policy=ev" +caa06 3600 IN CAA 128 tbs "Unknown" +cdnskey01 3600 IN CDNSKEY 256 3 8 AwEAAbmiLgh411Pz3v3XCSBrvYf52A/G v55ItN1NbOLHCqt3Ec3p+VB/kQ87VjjM rycanZFnZT4l9uCFuYh21CcyxVpcxExb M0UuhX5rJoDyeFSXoQlkHrB01osPl5Vr i5YmKtcmqGxZ9An0VSunohkyiX1SrNRZ SdQnk9/pIHDe/c8D +cds01 3600 IN CDS 12345 3 1 123456789abcdef67890123456789abcdef67890 +cert01 3600 IN CERT 65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz 45IkskceFGgiWCn/GxHhai6VAuHAoNUz 4YoU1tVfSCSqQYn6//11U6Nld80jEeC8 aTrO+KKmCaY= +cname01 3600 IN CNAME cname-target. +cname02 3600 IN CNAME cname-target +cname03 3600 IN CNAME . +csync0 3600 IN CSYNC 12345 0 A MX RRSIG NSEC TYPE1234 +d 300 IN A 73.80.65.49 +dhcid01 3600 IN DHCID AAIBY2/AuCccgoJbsaxcQc9TUapptP69 lOjxfNuVAA2kjEA= +dhcid02 3600 IN DHCID AAEBOSD+XR3Os/0LozeXVqcNc7FwCfQd WL3b/NaiUDlW2No= +dhcid03 3600 IN DHCID AAABxLmlskllE0MVjd57zHcWmEH3pCQ6 VytcKD//7es/deY= +dlv01 3600 IN DLV 12345 3 1 123456789abcdef67890123456789abcdef67890 +dname01 3600 IN DNAME dname-target. +dname02 3600 IN DNAME dname-target +dname03 3600 IN DNAME . +dnskey01 3600 IN DNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRu niJDBzC7w0aRyzWZriO6i2odGWWQVucZ qKVsENW91IOW4vqudngPZsY3GvQ/xVA8 /7pyFj6b7Esga60zyGW6LFe9r8n6paHr lG5ojqf0BaqHT+8= +dnskey02 3600 IN DNSKEY 257 3 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRu niJDBzC7w0aRyzWZriO6i2odGWWQVucZ qKVsENW91IOW4vqudngPZsY3GvQ/xVA8 /7pyFj6b7Esga60zyGW6LFe9r8n6paHr lG5ojqf0BaqHT+8= +ds01 3600 IN DS 12345 3 1 123456789abcdef67890123456789abcdef67890 +e 300 IN MX 10 mail +e 300 IN TXT "one" +e 300 IN TXT "three" +e 300 IN TXT "two" +e 300 IN A 73.80.65.49 +e 300 IN A 73.80.65.50 +e 300 IN A 73.80.65.52 +e 300 IN A 73.80.65.51 +f 300 IN A 73.80.65.52 +gpos01 3600 IN GPOS -22.6882 116.8652 250.0 +hinfo01 3600 IN HINFO "Generic PC clone" "NetBSD-1.4" +hinfo02 3600 IN HINFO "PC" "NetBSD" +hip01 3600 IN HIP 2 200100107b1a74df365639cc39f1d578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D +hip02 3600 IN HIP 2 200100107b1a74df365639cc39f1d578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs.example.com. +hip03 3600 IN HIP 2 200100107b1a74df365639cc39f1d578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs1.example.com. rvs2.example.com. +https01 3600 IN HTTPS 0 svc +https02 3600 IN HTTPS 1 . port="8002" echconfig="abcd" +ipseckey01 3600 IN IPSECKEY 10 1 2 192.0.2.38 AQNRU3mG7TVTO2BkR47usntb102uFJtu gbo6BSGvgqt4AQ== +ipseckey02 3600 IN IPSECKEY 10 0 2 . AQNRU3mG7TVTO2BkR47usntb102uFJtu gbo6BSGvgqt4AQ== +ipseckey03 3600 IN IPSECKEY 10 3 2 mygateway.example.com. AQNRU3mG7TVTO2BkR47usntb102uFJtu gbo6BSGvgqt4AQ== +ipseckey04 3600 IN IPSECKEY 10 2 2 2001:0DB8:0:8002::2000:1 AQNRU3mG7TVTO2BkR47usntb102uFJtu gbo6BSGvgqt4AQ== +ipseckey05 3600 IN IPSECKEY 10 3 2 mygateway2 AQNRU3mG7TVTO2BkR47usntb102uFJtu gbo6BSGvgqt4AQ== +isdn01 3600 IN ISDN "isdn-address" +isdn02 3600 IN ISDN "isdn-address" "subaddress" +isdn03 3600 IN ISDN "isdn-address" +isdn04 3600 IN ISDN "isdn-address" "subaddress" +kx01 3600 IN KX 10 kdc +kx02 3600 IN KX 10 . +loc01 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20.00m 2000.00m 20.00m +loc02 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20.00m 2000.00m 20.00m +loc03 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 90000000.00m 2000.00m 20.00m +loc04 3600 IN LOC 60 9 1.500 N 24 39 0.000 E 10.00m 90000000.00m 2000.00m 20.00m +loc05 3600 IN LOC 60 9 1.510 N 24 39 0.000 E 10.00m 90000000.00m 2000.00m 20.00m +loc06 3600 IN LOC 60 9 1.000 N 24 39 0.000 E 10.00m 90000000.00m 2000.00m 20.00m +loc07 3600 IN LOC 0 9 1.000 N 24 39 0.000 E 10.00m 90000000.00m 2000.00m 20.00m +loc08 3600 IN LOC 0 9 1.000 S 24 39 0.000 E 10.00m 90000000.00m 2000.00m 20.00m +mx01 3600 IN MX 10 mail +mx02 3600 IN MX 10 . +naptr01 3600 IN NAPTR 0 0 "" "" "" . +naptr02 3600 IN NAPTR 65535 65535 "blurgh" "blorf" "blegh" foo. +ns1 300 IN A 10.53.0.1 +ns2 300 IN A 10.53.0.2 +nsap-ptr01 3600 IN NSAP-PTR foo. +nsap-ptr01 3600 IN NSAP-PTR . +nsap01 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100 +nsap02 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100 +nsec01 3600 IN NSEC a.secure A MX RRSIG NSEC TYPE1234 +nsec02 3600 IN NSEC . NSAP-PTR NSEC +nsec03 3600 IN NSEC . NSEC TYPE65535 +nsec301 3600 IN NSEC3 1 1 12 aabbccdd 2t7b4g4vsa5smi47k61mv5bv1a22bojr NS SOA MX RRSIG DNSKEY NSEC3PARAM +nsec302 3600 IN NSEC3 1 1 12 - 2t7b4g4vsa5smi47k61mv5bv1a22bojr NS SOA MX RRSIG DNSKEY NSEC3PARAM +openpgpkey 3600 IN OPENPGPKEY mQENBEteQDsBCADYnatn9+5t43AdJlVk9dZC2RM0idPQcmrrKcjeAWDnISqoJzkvQ8ifX6mefquTBsDZC279uXShyTffYzQtvP2r9ewkK7zmSv52Ar563TSULAMwiLpe0gGQE0ex20mX5ggtYn6czdbEtcKpW0t+AfDqRk5YcpgqfZKXapKQ+A3CwWJKP9i3ldx2Jz//kuru4YqROLBYyB8D6V2jNUFOdaP6j5C5prh9dxfYFp2O/xFeAKLWlWuH9o96INUoIhgdEyj9PHPT3c821NMZu8tCvsZgUB+QPbHA/QYGa+aollcdGkJpVxXoHhbu6aMx/B+pXg55WM5pqOxmoVjyViHIUYfPABEBAAG0IUJvYiBIYWxsZXkgPGhhbGxleUBkbnNweXRob24ub3JnPokBPgQTAQIAKAUCS15AOwIbAwUJA8JnAAYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ6o6Gb8yUnXaflQgAhlhIqZGncRw3LV3d24JmPD+UEcEGiVh2b/Ic/1TMec46Ts7ZqRXAcOATNteQmpzqexx+BRKDWU8ZgYx12J4GZmC06jABr2JDWxgvbMX9qjkUUgDGZZgAS/B2x5AmKgy2ZnCUlaKfePcKmtKTB9yNJ8v/WERlFdGaUveEUiFU8g75xp1Hj9Wp9sXCg9yeG1K2RwQ3RQd5tLudhyE67EQdFGgqQFynR53md7cmVhAGopKLwMkpCtToKUlxxlfnDfpKZhhXThmhA0PsUQUkJptfGwYwH3O2N3KzfUw3wXRvLa3hona3TlHk3kfg7Qyd7oP4AZGbJKp97YHnfqo1kp8rObkBDQRLXkA7AQgA0ePG7g5GgZ/1SdtGZlJJiE2X15vTUc3KGfmx/kI5NaUDu4fXb+XK+yFy9I/X+UJ46JSkyhj6QvUxpoI+A7WWk9ThfjbynoZxRD820KbqidqxBSgtFF36SRWzmX8DZfKKAskT9ZGU1odeSKDXLCJF7qAbZVRTuFRiDFGwtoVIICeE6Xd65JO6ufhad+ELhgFt95vRwTiFvVrBRjwF7ZgN/nOXfYncxZ/2mpFqfwsnB2eu0A2XZBm8IngsSmr/Wrz1RQ7+SNMqt77E7CKwBX7UIAZgyoJxIRxWirJoOt1rIm5VUqRR25ubXLuzx9PaHYiC5GiQIU45pWAd0IWcTI/MJQARAQABiQElBBgBAgAPBQJLXkA7AhsMBQkDwmcAAAoJEOqOhm/MlJ12HRsIAKrB9E++9X9W6VTXBfdkShCFv0ykZVn2eVs6tkqzoub9s4f+Z5ylWw+a5nkMDMdGVe6bn4A3oIAbf0Tjykq1AetZLVPsHl/QosTbSQluis/PEvJkTQXHaKHB3bFhwA90c/3HNhrLGugt9AmcfLf9LAynXDgNLV5eYdPYqfKE+27qjEBARf6PYh/8WQ8CPKS8DILFbwCZbRxUogyrZf/7AiHAGdJi8dmpR1WPQYef2hF3kqGX6NngLBPzZ6CQRaHBhD4pHU1S/IRSlx9/3Ytww32PYD9AyO732NmCUcq3bmvqcOWy4Cc1NkEwU0Vg0qzwVBNGb84v/ex2MouwtAYScwc= +ptr01 3600 IN PTR @ +px01 3600 IN PX 65535 foo. bar. +px02 3600 IN PX 65535 . . +rp01 3600 IN RP mbox-dname txt-dname +rp02 3600 IN RP . . +rrsig01 3600 IN RRSIG NSEC 1 3 3600 20200101000000 20030101000000 2143 foo MxFcby9k/yvedMfQgKzhH5er0Mu/vILz 45IkskceFGgiWCn/GxHhai6VAuHAoNUz 4YoU1tVfSCSqQYn6//11U6Nld80jEeC8 aTrO+KKmCaY= +rrsig02 3600 IN RRSIG NSEC 1 3 3600 20200101000000 20030101000000 2143 foo MxFcby9k/yvedMfQgKzhH5er0Mu/vILz 45IkskceFGgiWCn/GxHhai6VAuHAoNUz 4YoU1tVfSCSqQYn6//11U6Nld80jEeC8 aTrO+KKmCaY= +rt01 3600 IN RT 0 intermediate-host +rt02 3600 IN RT 65535 . +s 300 IN NS ns.s +ns.s 300 IN A 73.80.65.49 +smimea1 3600 IN SMIMEA 3 1 1 a9cdf989b504fe5dca90c0d2167b6550570734f7c763e09fdf88904e06157065 +smimea2 3600 IN SMIMEA 1 0 1 efddf0d915c7bdc5782c0881e1b2a95ad099fbdd06d7b1f77982d9364338d955 +smimea3 3600 IN SMIMEA 1 0 2 81ee7f6c0ecc6b09b7785a9418f54432de630dd54dc6ee9e3c49de547708d236d4c413c3e97e44f969e635958aa410495844127c04883503e5b024cf7a8f6a94 +spf 3600 IN SPF "v=spf1 mx -all" +srv01 3600 IN SRV 0 0 0 . +srv02 3600 IN SRV 65535 65535 65535 old-slow-box.example.com. +sshfp1 3600 IN SSHFP 1 1 aa549bfe898489c02d1715d97d79c57ba2fa76ab +svcb01 3600 IN SVCB 100 foo.com. mandatory="alpn,port" alpn="h2,h3" no-default-alpn port="12345" ipv4hint="1.2.3.4,4.3.2.1" echconfig="abcd" ipv6hint="1::2,3::4" key12345="foo" +t 301 IN A 73.80.65.49 +tlsa1 3600 IN TLSA 3 1 1 a9cdf989b504fe5dca90c0d2167b6550570734f7c763e09fdf88904e06157065 +tlsa2 3600 IN TLSA 1 0 1 efddf0d915c7bdc5782c0881e1b2a95ad099fbdd06d7b1f77982d9364338d955 +tlsa3 3600 IN TLSA 1 0 2 81ee7f6c0ecc6b09b7785a9418f54432de630dd54dc6ee9e3c49de547708d236d4c413c3e97e44f969e635958aa410495844127c04883503e5b024cf7a8f6a94 +txt01 3600 IN TXT "foo" +txt02 3600 IN TXT "foo" "bar" +txt03 3600 IN TXT "foo" +txt04 3600 IN TXT "foo" "bar" +txt05 3600 IN TXT "foo bar" +txt06 3600 IN TXT "foo bar" +txt07 3600 IN TXT "foo bar" +txt08 3600 IN TXT "foo\010bar" +txt09 3600 IN TXT "foo\010bar" +txt10 3600 IN TXT "foo bar" +txt11 3600 IN TXT "\"foo\"" +txt12 3600 IN TXT "\"foo\"" +txt13 3600 IN TXT "foo;" +txt14 3600 IN TXT "foo;" +txt15 3600 IN TXT "bar\\;" +u 300 IN TXT "txt-not-in-nxt" +a.u 300 IN A 73.80.65.49 +b.u 300 IN A 73.80.65.49 +unknown2 3600 IN TYPE999 \# 8 0a0000010a000001 +unknown3 3600 IN A 127.0.0.2 +uri01 3600 IN URI 10 1 "ftp://ftp1.example.com/public" +uri02 3600 IN URI 10 1 "http://www.example.com/path" +wks01 3600 IN WKS 10.0.0.1 6 0 1 2 21 23 +wks02 3600 IN WKS 10.0.0.1 17 0 1 2 53 +wks03 3600 IN WKS 10.0.0.2 6 65535 +x2501 3600 IN X25 "123456789" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/example2.good b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/example2.good new file mode 100644 index 0000000..64696ce --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/example2.good @@ -0,0 +1,149 @@ +example. 300 IN SOA ns1.example. hostmaster.example. 1 2 3 4 5 +example. 300 IN NS ns1.example. +example. 300 IN NS ns2.example. +example. 300 IN NSEC3PARAM 1 1 12 aabbccdd +example. 300 IN NSEC3PARAM 1 1 12 - +*.example. 300 IN MX 10 mail.example. +a.example. 300 IN TXT "foo foo foo" +a.example. 300 IN PTR foo.net. +a01.example. 3600 IN A 0.0.0.0 +a02.example. 3600 IN A 255.255.255.255 +aaaa01.example. 3600 IN AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff +aaaa02.example. 3600 IN AAAA ::1 +afsdb01.example. 3600 IN AFSDB 0 hostname.example. +afsdb02.example. 3600 IN AFSDB 65535 . +amtrelay01.example. 3600 IN AMTRELAY 0 0 0 . +amtrelay02.example. 3600 IN AMTRELAY 0 1 0 . +amtrelay03.example. 3600 IN AMTRELAY 10 0 1 203.0.113.15 +amtrelay04.example. 3600 IN AMTRELAY 10 0 2 2001:db8::15 +amtrelay05.example. 3600 IN AMTRELAY 128 1 3 amtrelays.example.com. +apl01.example. 3600 IN APL 1:192.168.32.0/21 !1:192.168.38.0/28 +apl02.example. 3600 IN APL 1:224.0.0.0/4 2:FF00:0:0:0:0:0:0:0/8 +avc01.example. 3600 IN AVC "app-name:WOLFGANG|app-class:OAM|business=yes" +b.example. 300 IN CNAME foo.net. +c.example. 300 IN A 73.80.65.49 +caa01.example. 3600 IN CAA 0 issue "ca.example.net" +caa02.example. 3600 IN CAA 0 iodef "mailto:security@example.com" +caa03.example. 3600 IN CAA 0 iodef "http://iodef.example.com/" +caa04.example. 3600 IN CAA 0 issue "ca.example.net; account=230123" +caa05.example. 3600 IN CAA 0 issue "ca.example.net; policy=ev" +caa06.example. 3600 IN CAA 128 tbs "Unknown" +cdnskey01.example. 3600 IN CDNSKEY 256 3 8 AwEAAbmiLgh411Pz3v3XCSBrvYf52A/G v55ItN1NbOLHCqt3Ec3p+VB/kQ87VjjM rycanZFnZT4l9uCFuYh21CcyxVpcxExb M0UuhX5rJoDyeFSXoQlkHrB01osPl5Vr i5YmKtcmqGxZ9An0VSunohkyiX1SrNRZ SdQnk9/pIHDe/c8D +cds01.example. 3600 IN CDS 12345 3 1 123456789abcdef67890123456789abcdef67890 +cert01.example. 3600 IN CERT 65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz 45IkskceFGgiWCn/GxHhai6VAuHAoNUz 4YoU1tVfSCSqQYn6//11U6Nld80jEeC8 aTrO+KKmCaY= +cname01.example. 3600 IN CNAME cname-target. +cname02.example. 3600 IN CNAME cname-target.example. +cname03.example. 3600 IN CNAME . +csync0.example. 3600 IN CSYNC 12345 0 A MX RRSIG NSEC TYPE1234 +d.example. 300 IN A 73.80.65.49 +dhcid01.example. 3600 IN DHCID AAIBY2/AuCccgoJbsaxcQc9TUapptP69 lOjxfNuVAA2kjEA= +dhcid02.example. 3600 IN DHCID AAEBOSD+XR3Os/0LozeXVqcNc7FwCfQd WL3b/NaiUDlW2No= +dhcid03.example. 3600 IN DHCID AAABxLmlskllE0MVjd57zHcWmEH3pCQ6 VytcKD//7es/deY= +dlv01.example. 3600 IN DLV 12345 3 1 123456789abcdef67890123456789abcdef67890 +dname01.example. 3600 IN DNAME dname-target. +dname02.example. 3600 IN DNAME dname-target.example. +dname03.example. 3600 IN DNAME . +dnskey01.example. 3600 IN DNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRu niJDBzC7w0aRyzWZriO6i2odGWWQVucZ qKVsENW91IOW4vqudngPZsY3GvQ/xVA8 /7pyFj6b7Esga60zyGW6LFe9r8n6paHr lG5ojqf0BaqHT+8= +dnskey02.example. 3600 IN DNSKEY 257 3 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRu niJDBzC7w0aRyzWZriO6i2odGWWQVucZ qKVsENW91IOW4vqudngPZsY3GvQ/xVA8 /7pyFj6b7Esga60zyGW6LFe9r8n6paHr lG5ojqf0BaqHT+8= +ds01.example. 3600 IN DS 12345 3 1 123456789abcdef67890123456789abcdef67890 +e.example. 300 IN MX 10 mail.example. +e.example. 300 IN TXT "one" +e.example. 300 IN TXT "three" +e.example. 300 IN TXT "two" +e.example. 300 IN A 73.80.65.49 +e.example. 300 IN A 73.80.65.50 +e.example. 300 IN A 73.80.65.52 +e.example. 300 IN A 73.80.65.51 +f.example. 300 IN A 73.80.65.52 +gpos01.example. 3600 IN GPOS -22.6882 116.8652 250.0 +hinfo01.example. 3600 IN HINFO "Generic PC clone" "NetBSD-1.4" +hinfo02.example. 3600 IN HINFO "PC" "NetBSD" +hip01.example. 3600 IN HIP 2 200100107b1a74df365639cc39f1d578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D +hip02.example. 3600 IN HIP 2 200100107b1a74df365639cc39f1d578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs.example.com. +hip03.example. 3600 IN HIP 2 200100107b1a74df365639cc39f1d578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs1.example.com. rvs2.example.com. +https01.example. 3600 IN HTTPS 0 svc.example. +https02.example. 3600 IN HTTPS 1 . port="8002" echconfig="abcd" +ipseckey01.example. 3600 IN IPSECKEY 10 1 2 192.0.2.38 AQNRU3mG7TVTO2BkR47usntb102uFJtu gbo6BSGvgqt4AQ== +ipseckey02.example. 3600 IN IPSECKEY 10 0 2 . AQNRU3mG7TVTO2BkR47usntb102uFJtu gbo6BSGvgqt4AQ== +ipseckey03.example. 3600 IN IPSECKEY 10 3 2 mygateway.example.com. AQNRU3mG7TVTO2BkR47usntb102uFJtu gbo6BSGvgqt4AQ== +ipseckey04.example. 3600 IN IPSECKEY 10 2 2 2001:0DB8:0:8002::2000:1 AQNRU3mG7TVTO2BkR47usntb102uFJtu gbo6BSGvgqt4AQ== +ipseckey05.example. 3600 IN IPSECKEY 10 3 2 mygateway2.example. AQNRU3mG7TVTO2BkR47usntb102uFJtu gbo6BSGvgqt4AQ== +isdn01.example. 3600 IN ISDN "isdn-address" +isdn02.example. 3600 IN ISDN "isdn-address" "subaddress" +isdn03.example. 3600 IN ISDN "isdn-address" +isdn04.example. 3600 IN ISDN "isdn-address" "subaddress" +kx01.example. 3600 IN KX 10 kdc.example. +kx02.example. 3600 IN KX 10 . +loc01.example. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20.00m 2000.00m 20.00m +loc02.example. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20.00m 2000.00m 20.00m +loc03.example. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 90000000.00m 2000.00m 20.00m +loc04.example. 3600 IN LOC 60 9 1.500 N 24 39 0.000 E 10.00m 90000000.00m 2000.00m 20.00m +loc05.example. 3600 IN LOC 60 9 1.510 N 24 39 0.000 E 10.00m 90000000.00m 2000.00m 20.00m +loc06.example. 3600 IN LOC 60 9 1.000 N 24 39 0.000 E 10.00m 90000000.00m 2000.00m 20.00m +loc07.example. 3600 IN LOC 0 9 1.000 N 24 39 0.000 E 10.00m 90000000.00m 2000.00m 20.00m +loc08.example. 3600 IN LOC 0 9 1.000 S 24 39 0.000 E 10.00m 90000000.00m 2000.00m 20.00m +mx01.example. 3600 IN MX 10 mail.example. +mx02.example. 3600 IN MX 10 . +naptr01.example. 3600 IN NAPTR 0 0 "" "" "" . +naptr02.example. 3600 IN NAPTR 65535 65535 "blurgh" "blorf" "blegh" foo. +ns1.example. 300 IN A 10.53.0.1 +ns2.example. 300 IN A 10.53.0.2 +nsap-ptr01.example. 3600 IN NSAP-PTR foo. +nsap-ptr01.example. 3600 IN NSAP-PTR . +nsap01.example. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100 +nsap02.example. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100 +nsec01.example. 3600 IN NSEC a.secure.example. A MX RRSIG NSEC TYPE1234 +nsec02.example. 3600 IN NSEC . NSAP-PTR NSEC +nsec03.example. 3600 IN NSEC . NSEC TYPE65535 +nsec301.example. 3600 IN NSEC3 1 1 12 aabbccdd 2t7b4g4vsa5smi47k61mv5bv1a22bojr NS SOA MX RRSIG DNSKEY NSEC3PARAM +nsec302.example. 3600 IN NSEC3 1 1 12 - 2t7b4g4vsa5smi47k61mv5bv1a22bojr NS SOA MX RRSIG DNSKEY NSEC3PARAM +openpgpkey.example. 3600 IN OPENPGPKEY mQENBEteQDsBCADYnatn9+5t43AdJlVk9dZC2RM0idPQcmrrKcjeAWDnISqoJzkvQ8ifX6mefquTBsDZC279uXShyTffYzQtvP2r9ewkK7zmSv52Ar563TSULAMwiLpe0gGQE0ex20mX5ggtYn6czdbEtcKpW0t+AfDqRk5YcpgqfZKXapKQ+A3CwWJKP9i3ldx2Jz//kuru4YqROLBYyB8D6V2jNUFOdaP6j5C5prh9dxfYFp2O/xFeAKLWlWuH9o96INUoIhgdEyj9PHPT3c821NMZu8tCvsZgUB+QPbHA/QYGa+aollcdGkJpVxXoHhbu6aMx/B+pXg55WM5pqOxmoVjyViHIUYfPABEBAAG0IUJvYiBIYWxsZXkgPGhhbGxleUBkbnNweXRob24ub3JnPokBPgQTAQIAKAUCS15AOwIbAwUJA8JnAAYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ6o6Gb8yUnXaflQgAhlhIqZGncRw3LV3d24JmPD+UEcEGiVh2b/Ic/1TMec46Ts7ZqRXAcOATNteQmpzqexx+BRKDWU8ZgYx12J4GZmC06jABr2JDWxgvbMX9qjkUUgDGZZgAS/B2x5AmKgy2ZnCUlaKfePcKmtKTB9yNJ8v/WERlFdGaUveEUiFU8g75xp1Hj9Wp9sXCg9yeG1K2RwQ3RQd5tLudhyE67EQdFGgqQFynR53md7cmVhAGopKLwMkpCtToKUlxxlfnDfpKZhhXThmhA0PsUQUkJptfGwYwH3O2N3KzfUw3wXRvLa3hona3TlHk3kfg7Qyd7oP4AZGbJKp97YHnfqo1kp8rObkBDQRLXkA7AQgA0ePG7g5GgZ/1SdtGZlJJiE2X15vTUc3KGfmx/kI5NaUDu4fXb+XK+yFy9I/X+UJ46JSkyhj6QvUxpoI+A7WWk9ThfjbynoZxRD820KbqidqxBSgtFF36SRWzmX8DZfKKAskT9ZGU1odeSKDXLCJF7qAbZVRTuFRiDFGwtoVIICeE6Xd65JO6ufhad+ELhgFt95vRwTiFvVrBRjwF7ZgN/nOXfYncxZ/2mpFqfwsnB2eu0A2XZBm8IngsSmr/Wrz1RQ7+SNMqt77E7CKwBX7UIAZgyoJxIRxWirJoOt1rIm5VUqRR25ubXLuzx9PaHYiC5GiQIU45pWAd0IWcTI/MJQARAQABiQElBBgBAgAPBQJLXkA7AhsMBQkDwmcAAAoJEOqOhm/MlJ12HRsIAKrB9E++9X9W6VTXBfdkShCFv0ykZVn2eVs6tkqzoub9s4f+Z5ylWw+a5nkMDMdGVe6bn4A3oIAbf0Tjykq1AetZLVPsHl/QosTbSQluis/PEvJkTQXHaKHB3bFhwA90c/3HNhrLGugt9AmcfLf9LAynXDgNLV5eYdPYqfKE+27qjEBARf6PYh/8WQ8CPKS8DILFbwCZbRxUogyrZf/7AiHAGdJi8dmpR1WPQYef2hF3kqGX6NngLBPzZ6CQRaHBhD4pHU1S/IRSlx9/3Ytww32PYD9AyO732NmCUcq3bmvqcOWy4Cc1NkEwU0Vg0qzwVBNGb84v/ex2MouwtAYScwc= +ptr01.example. 3600 IN PTR example. +px01.example. 3600 IN PX 65535 foo. bar. +px02.example. 3600 IN PX 65535 . . +rp01.example. 3600 IN RP mbox-dname.example. txt-dname.example. +rp02.example. 3600 IN RP . . +rrsig01.example. 3600 IN RRSIG NSEC 1 3 3600 20200101000000 20030101000000 2143 foo.example. MxFcby9k/yvedMfQgKzhH5er0Mu/vILz 45IkskceFGgiWCn/GxHhai6VAuHAoNUz 4YoU1tVfSCSqQYn6//11U6Nld80jEeC8 aTrO+KKmCaY= +rrsig02.example. 3600 IN RRSIG NSEC 1 3 3600 20200101000000 20030101000000 2143 foo.example. MxFcby9k/yvedMfQgKzhH5er0Mu/vILz 45IkskceFGgiWCn/GxHhai6VAuHAoNUz 4YoU1tVfSCSqQYn6//11U6Nld80jEeC8 aTrO+KKmCaY= +rt01.example. 3600 IN RT 0 intermediate-host.example. +rt02.example. 3600 IN RT 65535 . +s.example. 300 IN NS ns.s.example. +ns.s.example. 300 IN A 73.80.65.49 +smimea1.example. 3600 IN SMIMEA 3 1 1 a9cdf989b504fe5dca90c0d2167b6550570734f7c763e09fdf88904e06157065 +smimea2.example. 3600 IN SMIMEA 1 0 1 efddf0d915c7bdc5782c0881e1b2a95ad099fbdd06d7b1f77982d9364338d955 +smimea3.example. 3600 IN SMIMEA 1 0 2 81ee7f6c0ecc6b09b7785a9418f54432de630dd54dc6ee9e3c49de547708d236d4c413c3e97e44f969e635958aa410495844127c04883503e5b024cf7a8f6a94 +spf.example. 3600 IN SPF "v=spf1 mx -all" +srv01.example. 3600 IN SRV 0 0 0 . +srv02.example. 3600 IN SRV 65535 65535 65535 old-slow-box.example.com. +sshfp1.example. 3600 IN SSHFP 1 1 aa549bfe898489c02d1715d97d79c57ba2fa76ab +svcb01.example. 3600 IN SVCB 100 foo.com. mandatory="alpn,port" alpn="h2,h3" no-default-alpn port="12345" ipv4hint="1.2.3.4,4.3.2.1" echconfig="abcd" ipv6hint="1::2,3::4" key12345="foo" +t.example. 301 IN A 73.80.65.49 +tlsa1.example. 3600 IN TLSA 3 1 1 a9cdf989b504fe5dca90c0d2167b6550570734f7c763e09fdf88904e06157065 +tlsa2.example. 3600 IN TLSA 1 0 1 efddf0d915c7bdc5782c0881e1b2a95ad099fbdd06d7b1f77982d9364338d955 +tlsa3.example. 3600 IN TLSA 1 0 2 81ee7f6c0ecc6b09b7785a9418f54432de630dd54dc6ee9e3c49de547708d236d4c413c3e97e44f969e635958aa410495844127c04883503e5b024cf7a8f6a94 +txt01.example. 3600 IN TXT "foo" +txt02.example. 3600 IN TXT "foo" "bar" +txt03.example. 3600 IN TXT "foo" +txt04.example. 3600 IN TXT "foo" "bar" +txt05.example. 3600 IN TXT "foo bar" +txt06.example. 3600 IN TXT "foo bar" +txt07.example. 3600 IN TXT "foo bar" +txt08.example. 3600 IN TXT "foo\010bar" +txt09.example. 3600 IN TXT "foo\010bar" +txt10.example. 3600 IN TXT "foo bar" +txt11.example. 3600 IN TXT "\"foo\"" +txt12.example. 3600 IN TXT "\"foo\"" +txt13.example. 3600 IN TXT "foo;" +txt14.example. 3600 IN TXT "foo;" +txt15.example. 3600 IN TXT "bar\\;" +u.example. 300 IN TXT "txt-not-in-nxt" +a.u.example. 300 IN A 73.80.65.49 +b.u.example. 300 IN A 73.80.65.49 +unknown2.example. 3600 IN TYPE999 \# 8 0a0000010a000001 +unknown3.example. 3600 IN A 127.0.0.2 +uri01.example. 3600 IN URI 10 1 "ftp://ftp1.example.com/public" +uri02.example. 3600 IN URI 10 1 "http://www.example.com/path" +wks01.example. 3600 IN WKS 10.0.0.1 6 0 1 2 21 23 +wks02.example. 3600 IN WKS 10.0.0.1 17 0 1 2 53 +wks03.example. 3600 IN WKS 10.0.0.2 6 65535 +x2501.example. 3600 IN X25 "123456789" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/example3.good b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/example3.good new file mode 100644 index 0000000..03fd08d --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/example3.good @@ -0,0 +1,149 @@ +@ 300 IN SOA ns1 hostmaster 1 2 3 4 5 +@ 300 IN NS ns1 +@ 300 IN NS ns2 +@ 300 IN NSEC3PARAM 1 1 12 aabbccdd +@ 300 IN NSEC3PARAM 1 1 12 - +* 300 IN MX 10 mail +a 300 IN TXT "foo foo foo" +a 300 IN PTR foo.net. +a01 3600 IN A 0.0.0.0 +a02 3600 IN A 255.255.255.255 +aaaa01 3600 IN AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff +aaaa02 3600 IN AAAA ::1 +afsdb01 3600 IN AFSDB 0 hostname +afsdb02 3600 IN AFSDB 65535 . +amtrelay01 3600 IN AMTRELAY 0 0 0 . +amtrelay02 3600 IN AMTRELAY 0 1 0 . +amtrelay03 3600 IN AMTRELAY 10 0 1 203.0.113.15 +amtrelay04 3600 IN AMTRELAY 10 0 2 2001:db8::15 +amtrelay05 3600 IN AMTRELAY 128 1 3 amtrelays.example.com. +apl01 3600 IN APL 1:192.168.32.0/21 !1:192.168.38.0/28 +apl02 3600 IN APL 1:224.0.0.0/4 2:FF00:0:0:0:0:0:0:0/8 +avc01 3600 IN AVC "app-name:WOLFGANG|app-class:OAM|business=yes" +b 300 IN CNAME foo.net. +c 300 IN A 73.80.65.49 +caa01 3600 IN CAA 0 issue "ca.example.net" +caa02 3600 IN CAA 0 iodef "mailto:security@example.com" +caa03 3600 IN CAA 0 iodef "http://iodef.example.com/" +caa04 3600 IN CAA 0 issue "ca.example.net; account=230123" +caa05 3600 IN CAA 0 issue "ca.example.net; policy=ev" +caa06 3600 IN CAA 128 tbs "Unknown" +cdnskey01 3600 IN CDNSKEY 256 3 8 AwEAAbmiLgh411Pz3v3XCSBrvYf52A/G v55ItN1NbOLHCqt3Ec3p+VB/kQ87VjjM rycanZFnZT4l9uCFuYh21CcyxVpcxExb M0UuhX5rJoDyeFSXoQlkHrB01osPl5Vr i5YmKtcmqGxZ9An0VSunohkyiX1SrNRZ SdQnk9/pIHDe/c8D +cds01 3600 IN CDS 12345 3 1 123456789abcdef67890123456789abcdef67890 +cert01 3600 IN CERT 65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz 45IkskceFGgiWCn/GxHhai6VAuHAoNUz 4YoU1tVfSCSqQYn6//11U6Nld80jEeC8 aTrO+KKmCaY= +cname01 3600 IN CNAME cname-target. +cname02 3600 IN CNAME cname-target +cname03 3600 IN CNAME . +csync0 3600 IN CSYNC 12345 0 A MX RRSIG NSEC TYPE1234 +d 300 IN A 73.80.65.49 +dhcid01 3600 IN DHCID AAIBY2/AuCccgoJbsaxcQc9TUapptP69 lOjxfNuVAA2kjEA= +dhcid02 3600 IN DHCID AAEBOSD+XR3Os/0LozeXVqcNc7FwCfQd WL3b/NaiUDlW2No= +dhcid03 3600 IN DHCID AAABxLmlskllE0MVjd57zHcWmEH3pCQ6 VytcKD//7es/deY= +dlv01 3600 IN DLV 12345 3 1 123456789abcdef67890123456789abcdef67890 +dname01 3600 IN DNAME dname-target. +dname02 3600 IN DNAME dname-target +dname03 3600 IN DNAME . +dnskey01 3600 IN DNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRu niJDBzC7w0aRyzWZriO6i2odGWWQVucZ qKVsENW91IOW4vqudngPZsY3GvQ/xVA8 /7pyFj6b7Esga60zyGW6LFe9r8n6paHr lG5ojqf0BaqHT+8= +dnskey02 3600 IN DNSKEY 257 3 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRu niJDBzC7w0aRyzWZriO6i2odGWWQVucZ qKVsENW91IOW4vqudngPZsY3GvQ/xVA8 /7pyFj6b7Esga60zyGW6LFe9r8n6paHr lG5ojqf0BaqHT+8= +ds01 3600 IN DS 12345 3 1 123456789abcdef67890123456789abcdef67890 +e 300 IN MX 10 mail +e 300 IN TXT "one" +e 300 IN TXT "three" +e 300 IN TXT "two" +e 300 IN A 73.80.65.49 +e 300 IN A 73.80.65.50 +e 300 IN A 73.80.65.52 +e 300 IN A 73.80.65.51 +f 300 IN A 73.80.65.52 +gpos01 3600 IN GPOS -22.6882 116.8652 250.0 +hinfo01 3600 IN HINFO "Generic PC clone" "NetBSD-1.4" +hinfo02 3600 IN HINFO "PC" "NetBSD" +hip01 3600 IN HIP 2 200100107b1a74df365639cc39f1d578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D +hip02 3600 IN HIP 2 200100107b1a74df365639cc39f1d578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs.example.com. +hip03 3600 IN HIP 2 200100107b1a74df365639cc39f1d578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs1.example.com. rvs2.example.com. +https01 3600 IN HTTPS 0 svc +https02 3600 IN HTTPS 1 . port="8002" echconfig="abcd" +ipseckey01 3600 IN IPSECKEY 10 1 2 192.0.2.38 AQNRU3mG7TVTO2BkR47usntb102uFJtu gbo6BSGvgqt4AQ== +ipseckey02 3600 IN IPSECKEY 10 0 2 . AQNRU3mG7TVTO2BkR47usntb102uFJtu gbo6BSGvgqt4AQ== +ipseckey03 3600 IN IPSECKEY 10 3 2 mygateway.example.com. AQNRU3mG7TVTO2BkR47usntb102uFJtu gbo6BSGvgqt4AQ== +ipseckey04 3600 IN IPSECKEY 10 2 2 2001:0DB8:0:8002::2000:1 AQNRU3mG7TVTO2BkR47usntb102uFJtu gbo6BSGvgqt4AQ== +ipseckey05 3600 IN IPSECKEY 10 3 2 mygateway2 AQNRU3mG7TVTO2BkR47usntb102uFJtu gbo6BSGvgqt4AQ== +isdn01 3600 IN ISDN "isdn-address" +isdn02 3600 IN ISDN "isdn-address" "subaddress" +isdn03 3600 IN ISDN "isdn-address" +isdn04 3600 IN ISDN "isdn-address" "subaddress" +kx01 3600 IN KX 10 kdc +kx02 3600 IN KX 10 . +loc01 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20.00m 2000.00m 20.00m +loc02 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20.00m 2000.00m 20.00m +loc03 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 90000000.00m 2000.00m 20.00m +loc04 3600 IN LOC 60 9 1.500 N 24 39 0.000 E 10.00m 90000000.00m 2000.00m 20.00m +loc05 3600 IN LOC 60 9 1.510 N 24 39 0.000 E 10.00m 90000000.00m 2000.00m 20.00m +loc06 3600 IN LOC 60 9 1.000 N 24 39 0.000 E 10.00m 90000000.00m 2000.00m 20.00m +loc07 3600 IN LOC 0 9 1.000 N 24 39 0.000 E 10.00m 90000000.00m 2000.00m 20.00m +loc08 3600 IN LOC 0 9 1.000 S 24 39 0.000 E 10.00m 90000000.00m 2000.00m 20.00m +mx01 3600 IN MX 10 mail +mx02 3600 IN MX 10 . +naptr01 3600 IN NAPTR 0 0 "" "" "" . +naptr02 3600 IN NAPTR 65535 65535 "blurgh" "blorf" "blegh" foo. +ns1 300 IN A 10.53.0.1 +ns2 300 IN A 10.53.0.2 +nsap-ptr01 3600 IN NSAP-PTR foo. +nsap-ptr01 3600 IN NSAP-PTR . +nsap01 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100 +nsap02 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100 +nsec01 3600 IN NSEC a.secure A MX RRSIG NSEC TYPE1234 +nsec02 3600 IN NSEC . NSAP-PTR NSEC +nsec03 3600 IN NSEC . NSEC TYPE65535 +nsec301 3600 IN NSEC3 1 1 12 aabbccdd 2t7b4g4vsa5smi47k61mv5bv1a22bojr NS SOA MX RRSIG DNSKEY NSEC3PARAM +nsec302 3600 IN NSEC3 1 1 12 - 2t7b4g4vsa5smi47k61mv5bv1a22bojr NS SOA MX RRSIG DNSKEY NSEC3PARAM +openpgpkey 3600 IN OPENPGPKEY mQENBEteQDsBCADYnatn9+5t43AdJlVk9dZC2RM0idPQcmrrKcjeAWDnISqoJzkvQ8ifX6mefquTBsDZC279uXShyTffYzQtvP2r9ewkK7zmSv52Ar563TSULAMwiLpe0gGQE0ex20mX5ggtYn6czdbEtcKpW0t+AfDqRk5YcpgqfZKXapKQ+A3CwWJKP9i3ldx2Jz//kuru4YqROLBYyB8D6V2jNUFOdaP6j5C5prh9dxfYFp2O/xFeAKLWlWuH9o96INUoIhgdEyj9PHPT3c821NMZu8tCvsZgUB+QPbHA/QYGa+aollcdGkJpVxXoHhbu6aMx/B+pXg55WM5pqOxmoVjyViHIUYfPABEBAAG0IUJvYiBIYWxsZXkgPGhhbGxleUBkbnNweXRob24ub3JnPokBPgQTAQIAKAUCS15AOwIbAwUJA8JnAAYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ6o6Gb8yUnXaflQgAhlhIqZGncRw3LV3d24JmPD+UEcEGiVh2b/Ic/1TMec46Ts7ZqRXAcOATNteQmpzqexx+BRKDWU8ZgYx12J4GZmC06jABr2JDWxgvbMX9qjkUUgDGZZgAS/B2x5AmKgy2ZnCUlaKfePcKmtKTB9yNJ8v/WERlFdGaUveEUiFU8g75xp1Hj9Wp9sXCg9yeG1K2RwQ3RQd5tLudhyE67EQdFGgqQFynR53md7cmVhAGopKLwMkpCtToKUlxxlfnDfpKZhhXThmhA0PsUQUkJptfGwYwH3O2N3KzfUw3wXRvLa3hona3TlHk3kfg7Qyd7oP4AZGbJKp97YHnfqo1kp8rObkBDQRLXkA7AQgA0ePG7g5GgZ/1SdtGZlJJiE2X15vTUc3KGfmx/kI5NaUDu4fXb+XK+yFy9I/X+UJ46JSkyhj6QvUxpoI+A7WWk9ThfjbynoZxRD820KbqidqxBSgtFF36SRWzmX8DZfKKAskT9ZGU1odeSKDXLCJF7qAbZVRTuFRiDFGwtoVIICeE6Xd65JO6ufhad+ELhgFt95vRwTiFvVrBRjwF7ZgN/nOXfYncxZ/2mpFqfwsnB2eu0A2XZBm8IngsSmr/Wrz1RQ7+SNMqt77E7CKwBX7UIAZgyoJxIRxWirJoOt1rIm5VUqRR25ubXLuzx9PaHYiC5GiQIU45pWAd0IWcTI/MJQARAQABiQElBBgBAgAPBQJLXkA7AhsMBQkDwmcAAAoJEOqOhm/MlJ12HRsIAKrB9E++9X9W6VTXBfdkShCFv0ykZVn2eVs6tkqzoub9s4f+Z5ylWw+a5nkMDMdGVe6bn4A3oIAbf0Tjykq1AetZLVPsHl/QosTbSQluis/PEvJkTQXHaKHB3bFhwA90c/3HNhrLGugt9AmcfLf9LAynXDgNLV5eYdPYqfKE+27qjEBARf6PYh/8WQ8CPKS8DILFbwCZbRxUogyrZf/7AiHAGdJi8dmpR1WPQYef2hF3kqGX6NngLBPzZ6CQRaHBhD4pHU1S/IRSlx9/3Ytww32PYD9AyO732NmCUcq3bmvqcOWy4Cc1NkEwU0Vg0qzwVBNGb84v/ex2MouwtAYScwc= +ptr01 3600 IN PTR @ +px01 3600 IN PX 65535 foo. bar. +px02 3600 IN PX 65535 . . +rp01 3600 IN RP mbox-dname txt-dname +rp02 3600 IN RP . . +rrsig01 3600 IN RRSIG NSEC 1 3 3600 20200101000000 20030101000000 2143 foo MxFcby9k/yvedMfQgKzhH5er0Mu/vILz 45IkskceFGgiWCn/GxHhai6VAuHAoNUz 4YoU1tVfSCSqQYn6//11U6Nld80jEeC8 aTrO+KKmCaY= +rrsig02 3600 IN RRSIG NSEC 1 3 3600 20200101000000 20030101000000 2143 foo MxFcby9k/yvedMfQgKzhH5er0Mu/vILz 45IkskceFGgiWCn/GxHhai6VAuHAoNUz 4YoU1tVfSCSqQYn6//11U6Nld80jEeC8 aTrO+KKmCaY= +rt01 3600 IN RT 0 intermediate-host +rt02 3600 IN RT 65535 . +s 300 IN NS ns.s +ns.s 300 IN A 73.80.65.49 +smimea1 3600 IN SMIMEA 3 1 1 a9cdf989b504fe5dca90c0d2167b6550570734f7c763e09fdf88904e06157065 +smimea2 3600 IN SMIMEA 1 0 1 efddf0d915c7bdc5782c0881e1b2a95ad099fbdd06d7b1f77982d9364338d955 +smimea3 3600 IN SMIMEA 1 0 2 81ee7f6c0ecc6b09b7785a9418f54432de630dd54dc6ee9e3c49de547708d236d4c413c3e97e44f969e635958aa410495844127c04883503e5b024cf7a8f6a94 +spf 3600 IN SPF "v=spf1 mx -all" +srv01 3600 IN SRV 0 0 0 . +srv02 3600 IN SRV 65535 65535 65535 old-slow-box.example.com. +sshfp1 3600 IN SSHFP 1 1 aa549bfe898489c02d1715d97d79c57ba2fa76ab +svcb01 3600 IN SVCB 100 foo.com. mandatory="alpn,port" alpn="h2,h3" no-default-alpn port="12345" ipv4hint="1.2.3.4,4.3.2.1" echconfig="abcd" ipv6hint="1::2,3::4" key12345="foo" +t 301 IN A 73.80.65.49 +tlsa1 3600 IN TLSA 3 1 1 a9cdf989b504fe5dca90c0d2167b6550570734f7c763e09fdf88904e06157065 +tlsa2 3600 IN TLSA 1 0 1 efddf0d915c7bdc5782c0881e1b2a95ad099fbdd06d7b1f77982d9364338d955 +tlsa3 3600 IN TLSA 1 0 2 81ee7f6c0ecc6b09b7785a9418f54432de630dd54dc6ee9e3c49de547708d236d4c413c3e97e44f969e635958aa410495844127c04883503e5b024cf7a8f6a94 +txt01 3600 IN TXT "foo" +txt02 3600 IN TXT "foo" "bar" +txt03 3600 IN TXT "foo" +txt04 3600 IN TXT "foo" "bar" +txt05 3600 IN TXT "foo bar" +txt06 3600 IN TXT "foo bar" +txt07 3600 IN TXT "foo bar" +txt08 3600 IN TXT "foo\010bar" +txt09 3600 IN TXT "foo\010bar" +txt10 3600 IN TXT "foo bar" +txt11 3600 IN TXT "\"foo\"" +txt12 3600 IN TXT "\"foo\"" +txt13 3600 IN TXT "foo;" +txt14 3600 IN TXT "foo;" +txt15 3600 IN TXT "bar\\;" +u 300 IN TXT "txt-not-in-nxt" +a.u 300 IN A 73.80.65.49 +b.u 300 IN A 73.80.65.49 +unknown2 3600 IN TYPE999 \# 8 0a0000010a000001 +unknown3 3600 IN A 127.0.0.2 +uri01 3600 IN URI 10 1 "ftp://ftp1.example.com/public" +uri02 3600 IN URI 10 1 "http://www.example.com/path" +wks01 3600 IN WKS 10.0.0.1 6 0 1 2 21 23 +wks02 3600 IN WKS 10.0.0.1 17 0 1 2 53 +wks03 3600 IN WKS 10.0.0.2 6 65535 +x2501 3600 IN X25 "123456789" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/md_module.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/md_module.py new file mode 100644 index 0000000..19568bd --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/md_module.py @@ -0,0 +1,4 @@ +import dns.rdtypes.nsbase + +class MD(dns.rdtypes.nsbase.NSBase): + """Test MD record.""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/nanonameserver.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/nanonameserver.py new file mode 100644 index 0000000..33452ea --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/nanonameserver.py @@ -0,0 +1,324 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import contextlib +import enum +import errno +import functools +import socket +import struct +import threading +import trio + +import dns.asyncquery +import dns.message +import dns.rcode + +async def read_exactly(stream, count): + """Read the specified number of bytes from stream. Keep trying until we + either get the desired amount, or we hit EOF. + """ + s = b'' + while count > 0: + n = await stream.receive_some(count) + if n == b'': + raise EOFError + count = count - len(n) + s = s + n + return s + +class ConnectionType(enum.IntEnum): + UDP = 1 + TCP = 2 + +class Request: + def __init__(self, message, wire, peer, local, connection_type): + self.message = message + self.wire = wire + self.peer = peer + self.local = local + self.connection_type = connection_type + + @property + def question(self): + return self.message.question[0] + + @property + def qname(self): + return self.question.name + + @property + def qclass(self): + return self.question.rdclass + + @property + def qtype(self): + return self.question.rdtype + +class Server(threading.Thread): + + """The nanoserver is a nameserver skeleton suitable for faking a DNS + server for various testing purposes. It executes with a trio run + loop in a dedicated thread, and is a context manager. Exiting the + context manager will ensure the server shuts down. + + If a port is not specified, random ports will be chosen. + + Applications should subclass the server and override the handle() + method to determine how the server responds to queries. The + default behavior is to refuse everything. + + If use_thread is set to False in the constructor, then the + server's main() method can be used directly in a trio nursery, + allowing the server's cancellation to be managed in the Trio way. + In this case, no thread creation ever happens even though Server + is a subclass of thread, because the start() method is never + called. + """ + + def __init__(self, address='127.0.0.1', port=0, enable_udp=True, + enable_tcp=True, use_thread=True, origin=None, + keyring=None): + super().__init__() + self.address = address + self.port = port + self.enable_udp = enable_udp + self.enable_tcp = enable_tcp + self.use_thread = use_thread + self.origin = origin + self.keyring = keyring + self.left = None + self.right = None + self.udp = None + self.udp_address = None + self.tcp = None + self.tcp_address = None + + def __enter__(self): + (self.left, self.right) = socket.socketpair() + # We're making the sockets now so they can be sent to by the + # caller immediately (i.e. no race with the listener starting + # in the thread). + open_udp_sockets = [] + try: + while True: + if self.enable_udp: + self.udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, + 0) + self.udp.bind((self.address, self.port)) + self.udp_address = self.udp.getsockname() + if self.enable_tcp: + self.tcp = socket.socket(socket.AF_INET, + socket.SOCK_STREAM, 0) + self.tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, + 1) + if self.port == 0 and self.enable_udp: + try: + self.tcp.bind((self.address, self.udp_address[1])) + except OSError as e: + if e.errno == errno.EADDRINUSE and \ + len(open_udp_sockets) < 100: + open_udp_sockets.append(self.udp) + continue + raise + else: + self.tcp.bind((self.address, self.port)) + self.tcp.listen() + self.tcp_address = self.tcp.getsockname() + break + finally: + for udp_socket in open_udp_sockets: + udp_socket.close() + if self.use_thread: + self.start() + return self + + def __exit__(self, ex_ty, ex_va, ex_tr): + if self.left: + self.left.close() + if self.use_thread and self.is_alive(): + self.join() + if self.right: + self.right.close() + if self.udp: + self.udp.close() + if self.tcp: + self.tcp.close() + + async def wait_for_input_or_eof(self): + # + # This trio task just waits for input on the right half of the + # socketpair (the left half is owned by the context manager + # returned by launch). As soon as something is read, or the + # socket returns EOF, EOFError is raised, causing a the + # nursery to cancel all other nursery tasks, in particular the + # listeners. + # + try: + with trio.socket.from_stdlib_socket(self.right) as sock: + self.right = None # we own cleanup + await sock.recv(1) + finally: + raise EOFError + + def handle(self, message, peer, connection_type): + # + # Handle message 'message'. Override this method to change + # how the server behaves. + # + # The return value is either a dns.message.Message, a bytes, + # None, or a list of one of those. We allow a bytes to be + # returned for cases where handle wants to return an invalid + # DNS message for testing purposes. We allow None to be + # returned to indicate there is no response. If a list is + # returned, then the output code will run for each returned + # item. + # + try: + r = dns.message.make_response(message) + r.set_rcode(dns.rcode.REFUSED) + return r + except Exception: + return None + + def maybe_listify(self, thing): + if isinstance(thing, list): + return thing + else: + return [thing] + + def handle_wire(self, wire, peer, local, connection_type): + # + # This is the common code to parse wire format, call handle() on + # the message, and then generate response wire format (if handle() + # didn't do it). + # + # It also handles any exceptions from handle() + # + # Returns a (possibly empty) list of wire format message to send. + # + # XXXRTH It might be nice to have a "debug mode" in the server + # where we'd print something in all the places we're eating + # exceptions. That way bugs in handle() would be easier to + # find. + # + items = [] + r = None + try: + q = dns.message.from_wire(wire, keyring=self.keyring) + except dns.message.ShortHeader: + # There is no hope of answering this one! + return + except Exception: + # Try to make a FORMERR using just the question section. + try: + q = dns.message.from_wire(wire, question_only=True) + r = dns.message.make_response(q) + r.set_rcode(dns.rcode.FORMERR) + items.append(r) + except Exception: + # We could try to make a response from only the header + # if dnspython had a header_only option to + # from_wire(), or if we truncated wire outselves, but + # for now we just drop. + return + try: + # items might have been appended to above, so skip + # handle() if we already have a response. + if not items: + request = Request(q, wire, peer, local, connection_type) + items = self.maybe_listify(self.handle(request)) + except Exception: + # Exceptions from handle get a SERVFAIL response. + r = dns.message.make_response(q) + r.set_rcode(dns.rcode.SERVFAIL) + items = [r] + + tsig_ctx = None + multi = len(items) > 1 + for thing in items: + if isinstance(thing, dns.message.Message): + out = thing.to_wire(self.origin, multi=multi, tsig_ctx=tsig_ctx) + tsig_ctx = thing.tsig_ctx + yield out + else: + yield thing + + async def serve_udp(self): + with trio.socket.from_stdlib_socket(self.udp) as sock: + self.udp = None # we own cleanup + local = self.udp_address + while True: + try: + (wire, peer) = await sock.recvfrom(65535) + for wire in self.handle_wire(wire, peer, local, + ConnectionType.UDP): + await sock.sendto(wire, peer) + except Exception: + pass + + async def serve_tcp(self, stream): + try: + peer = stream.socket.getpeername() + local = stream.socket.getsockname() + while True: + ldata = await read_exactly(stream, 2) + (l,) = struct.unpack("!H", ldata) + wire = await read_exactly(stream, l) + for wire in self.handle_wire(wire, peer, local, + ConnectionType.TCP): + l = len(wire) + stream_message = struct.pack("!H", l) + wire + await stream.send_all(stream_message) + except Exception: + pass + + async def orchestrate_tcp(self): + with trio.socket.from_stdlib_socket(self.tcp) as sock: + self.tcp = None # we own cleanup + listener = trio.SocketListener(sock) + async with trio.open_nursery() as nursery: + serve = functools.partial(trio.serve_listeners, self.serve_tcp, + [listener], handler_nursery=nursery) + nursery.start_soon(serve) + + async def main(self): + try: + async with trio.open_nursery() as nursery: + if self.use_thread: + nursery.start_soon(self.wait_for_input_or_eof) + if self.enable_udp: + nursery.start_soon(self.serve_udp) + if self.enable_tcp: + nursery.start_soon(self.orchestrate_tcp) + except Exception: + pass + + def run(self): + if not self.use_thread: + raise RuntimeError('start() called on a use_thread=False Server') + trio.run(self.main) + +if __name__ == "__main__": + import sys + import time + + async def trio_main(): + try: + with Server(port=5354, use_thread=False) as server: + print(f'Trio mode: listening on UDP: {server.udp_address}, ' + + f'TCP: {server.tcp_address}') + async with trio.open_nursery() as nursery: + nursery.start_soon(server.main) + except Exception: + pass + + def threaded_main(): + with Server(port=5354) as server: + print(f'Thread Mode: listening on UDP: {server.udp_address}, ' + + f'TCP: {server.tcp_address}') + time.sleep(300) + + if len(sys.argv) > 1 and sys.argv[1] == 'trio': + trio.run(trio_main) + else: + threaded_main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/query b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/query new file mode 100644 index 0000000..06edbb7 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/query @@ -0,0 +1,12 @@ +id 1234 +opcode QUERY +rcode NOERROR +flags RD +edns 0 +eflags DO +payload 4096 +;QUESTION +wwww.dnspython.org. IN A +;ANSWER +;AUTHORITY +;ADDITIONAL diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/stxt_module.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/stxt_module.py new file mode 100644 index 0000000..7f61235 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/stxt_module.py @@ -0,0 +1,4 @@ +import dns.rdtypes.txtbase + +class STXT(dns.rdtypes.txtbase.TXTBase): + """Test singleton TXT-like record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_address.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_address.py new file mode 100644 index 0000000..1ee7022 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_address.py @@ -0,0 +1,581 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import socket +import sys +import unittest + +import dns.exception +import dns.ipv4 +import dns.ipv6 + +class IPv4Tests(unittest.TestCase): + def test_valid(self): + valid = ( + "1.2.3.4", + "11.22.33.44", + "254.7.237.98", + "192.168.1.26", + "192.168.1.1", + "13.1.68.3", + "129.144.52.38", + "254.157.241.86", + "12.34.56.78", + "192.0.2.128", + ) + for s in valid: + self.assertEqual(dns.ipv4.inet_aton(s), + socket.inet_pton(socket.AF_INET, s)) + + def test_invalid(self): + invalid = ( + "", + ".", + "..", + "400.2.3.4", + "260.2.3.4", + "256.2.3.4", + "1.256.3.4", + "1.2.256.4", + "1.2.3.256", + "300.2.3.4", + "1.300.3.4", + "1.2.300.4", + "1.2.3.300", + "900.2.3.4", + "1.900.3.4", + "1.2.900.4", + "1.2.3.900", + "300.300.300.300", + "3000.30.30.30", + "255Z255X255Y255", + "192x168.1.26", + "2.3.4", + "257.1.2.3", + "00.00.00.00", + "000.000.000.000", + "256.256.256.256", + "255255.255.255", + "255.255255.255", + "255.255.255255", + "1...", + "1.2..", + "1.2.3.", + ".2..", + ".2.3.", + ".2.3.4", + "..3.", + "..3.4", + "...4", + ".1.2.3.4", + "1.2.3.4.", + " 1.2.3.4", + "1.2.3.4 ", + " 1.2.3.4 ", + "::", + ) + for s in invalid: + with self.assertRaises(dns.exception.SyntaxError, + msg=f'invalid IPv4 address: "{s}"'): + dns.ipv4.inet_aton(s) + +class IPv6Tests(unittest.TestCase): + def test_valid(self): + valid = ( + "::1", + "::", + "0:0:0:0:0:0:0:1", + "0:0:0:0:0:0:0:0", + "2001:DB8:0:0:8:800:200C:417A", + "FF01:0:0:0:0:0:0:101", + "2001:DB8::8:800:200C:417A", + "FF01::101", + "fe80::217:f2ff:fe07:ed62", + "2001:0000:1234:0000:0000:C1C0:ABCD:0876", + "3ffe:0b00:0000:0000:0001:0000:0000:000a", + "FF02:0000:0000:0000:0000:0000:0000:0001", + "0000:0000:0000:0000:0000:0000:0000:0001", + "0000:0000:0000:0000:0000:0000:0000:0000", + "2::10", + "ff02::1", + "fe80::", + "2002::", + "2001:db8::", + "2001:0db8:1234::", + "::ffff:0:0", + "1:2:3:4:5:6:7:8", + "1:2:3:4:5:6::8", + "1:2:3:4:5::8", + "1:2:3:4::8", + "1:2:3::8", + "1:2::8", + "1::8", + "1::2:3:4:5:6:7", + "1::2:3:4:5:6", + "1::2:3:4:5", + "1::2:3:4", + "1::2:3", + "::2:3:4:5:6:7:8", + "::2:3:4:5:6:7", + "::2:3:4:5:6", + "::2:3:4:5", + "::2:3:4", + "::2:3", + "::8", + "1:2:3:4:5:6::", + "1:2:3:4:5::", + "1:2:3:4::", + "1:2:3::", + "1:2::", + "1::", + "1:2:3:4:5::7:8", + "1:2:3:4::7:8", + "1:2:3::7:8", + "1:2::7:8", + "1::7:8", + "1:2:3:4:5:6:1.2.3.4", + "1:2:3:4:5::1.2.3.4", + "1:2:3:4::1.2.3.4", + "1:2:3::1.2.3.4", + "1:2::1.2.3.4", + "1::1.2.3.4", + "1:2:3:4::5:1.2.3.4", + "1:2:3::5:1.2.3.4", + "1:2:3::5:1.2.3.4", + "1:2::5:1.2.3.4", + "1::5:1.2.3.4", + "1::5:11.22.33.44", + "fe80::217:f2ff:254.7.237.98", + "::ffff:192.168.1.26", + "::ffff:192.168.1.1", + "0:0:0:0:0:0:13.1.68.3", + "0:0:0:0:0:FFFF:129.144.52.38", + "::13.1.68.3", + "::FFFF:129.144.52.38", + "fe80:0:0:0:204:61ff:254.157.241.86", + "fe80::204:61ff:254.157.241.86", + "::ffff:12.34.56.78", + "::ffff:192.0.2.128", + "fe80:0000:0000:0000:0204:61ff:fe9d:f156", + "fe80:0:0:0:204:61ff:fe9d:f156", + "fe80::204:61ff:fe9d:f156", + "fe80::1", + "::ffff:c000:280", + "2001:0db8:85a3:0000:0000:8a2e:0370:7334", + "2001:db8:85a3:0:0:8a2e:370:7334", + "2001:db8:85a3::8a2e:370:7334", + "2001:0db8:0000:0000:0000:0000:1428:57ab", + "2001:0db8:0000:0000:0000::1428:57ab", + "2001:0db8:0:0:0:0:1428:57ab", + "2001:0db8:0:0::1428:57ab", + "2001:0db8::1428:57ab", + "2001:db8::1428:57ab", + "::ffff:0c22:384e", + "2001:0db8:1234:0000:0000:0000:0000:0000", + "2001:0db8:1234:ffff:ffff:ffff:ffff:ffff", + "2001:db8:a::123", + "1111:2222:3333:4444:5555:6666:7777:8888", + "1111:2222:3333:4444:5555:6666:7777::", + "1111:2222:3333:4444:5555:6666::", + "1111:2222:3333:4444:5555::", + "1111:2222:3333:4444::", + "1111:2222:3333::", + "1111:2222::", + "1111::", + "1111:2222:3333:4444:5555:6666::8888", + "1111:2222:3333:4444:5555::8888", + "1111:2222:3333:4444::8888", + "1111:2222:3333::8888", + "1111:2222::8888", + "1111::8888", + "::8888", + "1111:2222:3333:4444:5555::7777:8888", + "1111:2222:3333:4444::7777:8888", + "1111:2222:3333::7777:8888", + "1111:2222::7777:8888", + "1111::7777:8888", + "::7777:8888", + "1111:2222:3333:4444::6666:7777:8888", + "1111:2222:3333::6666:7777:8888", + "1111:2222::6666:7777:8888", + "1111::6666:7777:8888", + "::6666:7777:8888", + "1111:2222:3333::5555:6666:7777:8888", + "1111:2222::5555:6666:7777:8888", + "1111::5555:6666:7777:8888", + "::5555:6666:7777:8888", + "1111:2222::4444:5555:6666:7777:8888", + "1111::4444:5555:6666:7777:8888", + "::4444:5555:6666:7777:8888", + "1111::3333:4444:5555:6666:7777:8888", + "::3333:4444:5555:6666:7777:8888", + "::2222:3333:4444:5555:6666:7777:8888", + "1111:2222:3333:4444:5555:6666:123.123.123.123", + "1111:2222:3333:4444:5555::123.123.123.123", + "1111:2222:3333:4444::123.123.123.123", + "1111:2222:3333::123.123.123.123", + "1111:2222::123.123.123.123", + "1111::123.123.123.123", + "::123.123.123.123", + "1111:2222:3333:4444::6666:123.123.123.123", + "1111:2222:3333::6666:123.123.123.123", + "1111:2222::6666:123.123.123.123", + "1111::6666:123.123.123.123", + "::6666:123.123.123.123", + "1111:2222:3333::5555:6666:123.123.123.123", + "1111:2222::5555:6666:123.123.123.123", + "1111::5555:6666:123.123.123.123", + "::5555:6666:123.123.123.123", + "1111:2222::4444:5555:6666:123.123.123.123", + "1111::4444:5555:6666:123.123.123.123", + "::4444:5555:6666:123.123.123.123", + "1111::3333:4444:5555:6666:123.123.123.123", + "::2222:3333:4444:5555:6666:123.123.123.123", + "::0:0:0:0:0:0:0", + "::0:0:0:0:0:0", + "::0:0:0:0:0", + "::0:0:0:0", + "::0:0:0", + "::0:0", + "::0", + "0:0:0:0:0:0:0::", + "0:0:0:0:0:0::", + "0:0:0:0:0::", + "0:0:0:0::", + "0:0:0::", + "0:0::", + "0::", + "0:a:b:c:d:e:f::", + "::0:a:b:c:d:e:f", + "a:b:c:d:e:f:0::", + ) + + win32_invalid = { + "::2:3:4:5:6:7:8", + "::2222:3333:4444:5555:6666:7777:8888", + "::2222:3333:4444:5555:6666:123.123.123.123", + "::0:0:0:0:0:0:0", + "::0:a:b:c:d:e:f", + } + + for s in valid: + if sys.platform == 'win32' and s in win32_invalid: + # socket.inet_pton() on win32 rejects some valid (as + # far as we can tell) IPv6 addresses. Skip them. + continue + self.assertEqual(dns.ipv6.inet_aton(s), + socket.inet_pton(socket.AF_INET6, s)) + + def test_invalid(self): + invalid = ( + "", + ":", + ":::", + "2001:DB8:0:0:8:800:200C:417A:221", + "FF01::101::2", + "02001:0000:1234:0000:0000:C1C0:ABCD:0876", + "2001:0000:1234:0000:00001:C1C0:ABCD:0876", + " 2001:0000:1234:0000:0000:C1C0:ABCD:0876", + "2001:0000:1234:0000:0000:C1C0:ABCD:0876 ", + " 2001:0000:1234:0000:0000:C1C0:ABCD:0876 ", + "2001:0000:1234:0000:0000:C1C0:ABCD:0876 0", + "2001:0000:1234: 0000:0000:C1C0:ABCD:0876", + "3ffe:0b00:0000:0001:0000:0000:000a", + "FF02:0000:0000:0000:0000:0000:0000:0000:0001", + "3ffe:b00::1::a", + "::1111:2222:3333:4444:5555:6666::", + "1:2:3::4:5::7:8", + "12345::6:7:8", + "1::5:400.2.3.4", + "1::5:260.2.3.4", + "1::5:256.2.3.4", + "1::5:1.256.3.4", + "1::5:1.2.256.4", + "1::5:1.2.3.256", + "1::5:300.2.3.4", + "1::5:1.300.3.4", + "1::5:1.2.300.4", + "1::5:1.2.3.300", + "1::5:900.2.3.4", + "1::5:1.900.3.4", + "1::5:1.2.900.4", + "1::5:1.2.3.900", + "1::5:300.300.300.300", + "1::5:3000.30.30.30", + "1::400.2.3.4", + "1::260.2.3.4", + "1::256.2.3.4", + "1::1.256.3.4", + "1::1.2.256.4", + "1::1.2.3.256", + "1::300.2.3.4", + "1::1.300.3.4", + "1::1.2.300.4", + "1::1.2.3.300", + "1::900.2.3.4", + "1::1.900.3.4", + "1::1.2.900.4", + "1::1.2.3.900", + "1::300.300.300.300", + "1::3000.30.30.30", + "::400.2.3.4", + "::260.2.3.4", + "::256.2.3.4", + "::1.256.3.4", + "::1.2.256.4", + "::1.2.3.256", + "::300.2.3.4", + "::1.300.3.4", + "::1.2.300.4", + "::1.2.3.300", + "::900.2.3.4", + "::1.900.3.4", + "::1.2.900.4", + "::1.2.3.900", + "::300.300.300.300", + "::3000.30.30.30", + "::1.2.3.4.", + "2001:1:1:1:1:1:255Z255X255Y255", + "::ffff:192x168.1.26", + "::ffff:2.3.4", + "::ffff:257.1.2.3", + "1.2.3.4", + "1.2.3.4:1111:2222:3333:4444::5555", + "1.2.3.4:1111:2222:3333::5555", + "1.2.3.4:1111:2222::5555", + "1.2.3.4:1111::5555", + "1.2.3.4::5555", + "1.2.3.4::", + "fe80:0000:0000:0000:0204:61ff:254.157.241.086", + "XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:1.2.3.4", + "1111:2222:3333:4444:5555:6666:00.00.00.00", + "1111:2222:3333:4444:5555:6666:000.000.000.000", + "1111:2222:3333:4444:5555:6666:256.256.256.256", + "1111:2222:3333:4444::5555:", + "1111:2222:3333::5555:", + "1111:2222::5555:", + "1111::5555:", + "::5555:", + "1111:", + ":1111:2222:3333:4444::5555", + ":1111:2222:3333::5555", + ":1111:2222::5555", + ":1111::5555", + ":::5555", + "123", + "ldkfj", + "2001::FFD3::57ab", + "2001:db8:85a3::8a2e:37023:7334", + "2001:db8:85a3::8a2e:370k:7334", + "1:2:3:4:5:6:7:8:9", + "1::2::3", + "1:::3:4:5", + "1:2:3::4:5:6:7:8:9", + "XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX", + "1111:2222:3333:4444:5555:6666:7777:8888:9999", + "1111:2222:3333:4444:5555:6666:7777:8888::", + "::2222:3333:4444:5555:6666:7777:8888:9999", + "1111:2222:3333:4444:5555:6666:7777", + "1111:2222:3333:4444:5555:6666", + "1111:2222:3333:4444:5555", + "1111:2222:3333:4444", + "1111:2222:3333", + "1111:2222", + "1111", + "11112222:3333:4444:5555:6666:7777:8888", + "1111:22223333:4444:5555:6666:7777:8888", + "1111:2222:33334444:5555:6666:7777:8888", + "1111:2222:3333:44445555:6666:7777:8888", + "1111:2222:3333:4444:55556666:7777:8888", + "1111:2222:3333:4444:5555:66667777:8888", + "1111:2222:3333:4444:5555:6666:77778888", + "1111:2222:3333:4444:5555:6666:7777:8888:", + "1111:2222:3333:4444:5555:6666:7777:", + "1111:2222:3333:4444:5555:6666:", + "1111:2222:3333:4444:5555:", + "1111:2222:3333:4444:", + "1111:2222:3333:", + "1111:2222:", + ":8888", + ":7777:8888", + ":6666:7777:8888", + ":5555:6666:7777:8888", + ":4444:5555:6666:7777:8888", + ":3333:4444:5555:6666:7777:8888", + ":2222:3333:4444:5555:6666:7777:8888", + ":1111:2222:3333:4444:5555:6666:7777:8888", + ":::2222:3333:4444:5555:6666:7777:8888", + "1111:::3333:4444:5555:6666:7777:8888", + "1111:2222:::4444:5555:6666:7777:8888", + "1111:2222:3333:::5555:6666:7777:8888", + "1111:2222:3333:4444:::6666:7777:8888", + "1111:2222:3333:4444:5555:::7777:8888", + "1111:2222:3333:4444:5555:6666:::8888", + "::2222::4444:5555:6666:7777:8888", + "::2222:3333::5555:6666:7777:8888", + "::2222:3333:4444::6666:7777:8888", + "::2222:3333:4444:5555::7777:8888", + "::2222:3333:4444:5555:7777::8888", + "::2222:3333:4444:5555:7777:8888::", + "1111::3333::5555:6666:7777:8888", + "1111::3333:4444::6666:7777:8888", + "1111::3333:4444:5555::7777:8888", + "1111::3333:4444:5555:6666::8888", + "1111::3333:4444:5555:6666:7777::", + "1111:2222::4444::6666:7777:8888", + "1111:2222::4444:5555::7777:8888", + "1111:2222::4444:5555:6666::8888", + "1111:2222::4444:5555:6666:7777::", + "1111:2222:3333::5555::7777:8888", + "1111:2222:3333::5555:6666::8888", + "1111:2222:3333::5555:6666:7777::", + "1111:2222:3333:4444::6666::8888", + "1111:2222:3333:4444::6666:7777::", + "1111:2222:3333:4444:5555::7777::", + "1111:2222:3333:4444:5555:6666:7777:8888:1.2.3.4", + "1111:2222:3333:4444:5555:6666:7777:1.2.3.4", + "1111:2222:3333:4444:5555:6666::1.2.3.4", + "::2222:3333:4444:5555:6666:7777:1.2.3.4", + "1111:2222:3333:4444:5555:6666:1.2.3.4.5", + "1111:2222:3333:4444:5555:1.2.3.4", + "1111:2222:3333:4444:1.2.3.4", + "1111:2222:3333:1.2.3.4", + "1111:2222:1.2.3.4", + "1111:1.2.3.4", + "11112222:3333:4444:5555:6666:1.2.3.4", + "1111:22223333:4444:5555:6666:1.2.3.4", + "1111:2222:33334444:5555:6666:1.2.3.4", + "1111:2222:3333:44445555:6666:1.2.3.4", + "1111:2222:3333:4444:55556666:1.2.3.4", + "1111:2222:3333:4444:5555:66661.2.3.4", + "1111:2222:3333:4444:5555:6666:255255.255.255", + "1111:2222:3333:4444:5555:6666:255.255255.255", + "1111:2222:3333:4444:5555:6666:255.255.255255", + ":1.2.3.4", + ":6666:1.2.3.4", + ":5555:6666:1.2.3.4", + ":4444:5555:6666:1.2.3.4", + ":3333:4444:5555:6666:1.2.3.4", + ":2222:3333:4444:5555:6666:1.2.3.4", + ":1111:2222:3333:4444:5555:6666:1.2.3.4", + ":::2222:3333:4444:5555:6666:1.2.3.4", + "1111:::3333:4444:5555:6666:1.2.3.4", + "1111:2222:::4444:5555:6666:1.2.3.4", + "1111:2222:3333:::5555:6666:1.2.3.4", + "1111:2222:3333:4444:::6666:1.2.3.4", + "1111:2222:3333:4444:5555:::1.2.3.4", + "::2222::4444:5555:6666:1.2.3.4", + "::2222:3333::5555:6666:1.2.3.4", + "::2222:3333:4444::6666:1.2.3.4", + "::2222:3333:4444:5555::1.2.3.4", + "1111::3333::5555:6666:1.2.3.4", + "1111::3333:4444::6666:1.2.3.4", + "1111::3333:4444:5555::1.2.3.4", + "1111:2222::4444::6666:1.2.3.4", + "1111:2222::4444:5555::1.2.3.4", + "1111:2222:3333::5555::1.2.3.4", + "::.", + "::..", + "::...", + "::1...", + "::1.2..", + "::1.2.3.", + "::.2..", + "::.2.3.", + "::.2.3.4", + "::..3.", + "::..3.4", + "::...4", + ":1111:2222:3333:4444:5555:6666:7777::", + ":1111:2222:3333:4444:5555:6666::", + ":1111:2222:3333:4444:5555::", + ":1111:2222:3333:4444::", + ":1111:2222:3333::", + ":1111:2222::", + ":1111::", + ":1111:2222:3333:4444:5555:6666::8888", + ":1111:2222:3333:4444:5555::8888", + ":1111:2222:3333:4444::8888", + ":1111:2222:3333::8888", + ":1111:2222::8888", + ":1111::8888", + ":::8888", + ":1111:2222:3333:4444:5555::7777:8888", + ":1111:2222:3333:4444::7777:8888", + ":1111:2222:3333::7777:8888", + ":1111:2222::7777:8888", + ":1111::7777:8888", + ":::7777:8888", + ":1111:2222:3333:4444::6666:7777:8888", + ":1111:2222:3333::6666:7777:8888", + ":1111:2222::6666:7777:8888", + ":1111::6666:7777:8888", + ":::6666:7777:8888", + ":1111:2222:3333::5555:6666:7777:8888", + ":1111:2222::5555:6666:7777:8888", + ":1111::5555:6666:7777:8888", + ":::5555:6666:7777:8888", + ":1111:2222::4444:5555:6666:7777:8888", + ":1111::4444:5555:6666:7777:8888", + ":::4444:5555:6666:7777:8888", + ":1111::3333:4444:5555:6666:7777:8888", + ":::3333:4444:5555:6666:7777:8888", + ":1111:2222:3333:4444:5555::1.2.3.4", + ":1111:2222:3333:4444::1.2.3.4", + ":1111:2222:3333::1.2.3.4", + ":1111:2222::1.2.3.4", + ":1111::1.2.3.4", + ":::1.2.3.4", + ":1111:2222:3333:4444::6666:1.2.3.4", + ":1111:2222:3333::6666:1.2.3.4", + ":1111:2222::6666:1.2.3.4", + ":1111::6666:1.2.3.4", + ":::6666:1.2.3.4", + ":1111:2222:3333::5555:6666:1.2.3.4", + ":1111:2222::5555:6666:1.2.3.4", + ":1111::5555:6666:1.2.3.4", + ":::5555:6666:1.2.3.4", + ":1111:2222::4444:5555:6666:1.2.3.4", + ":1111::4444:5555:6666:1.2.3.4", + ":::4444:5555:6666:1.2.3.4", + ":1111::3333:4444:5555:6666:1.2.3.4", + "1111:2222:3333:4444:5555:6666:7777:::", + "1111:2222:3333:4444:5555:6666:::", + "1111:2222:3333:4444:5555:::", + "1111:2222:3333:4444:::", + "1111:2222:3333:::", + "1111:2222:::", + "1111:::", + "1111:2222:3333:4444:5555:6666::8888:", + "1111:2222:3333:4444:5555::8888:", + "1111:2222:3333:4444::8888:", + "1111:2222:3333::8888:", + "1111:2222::8888:", + "1111::8888:", + "::8888:", + "1111:2222:3333:4444:5555::7777:8888:", + "1111:2222:3333:4444::7777:8888:", + "1111:2222:3333::7777:8888:", + "1111:2222::7777:8888:", + "1111::7777:8888:", + "::7777:8888:", + "1111:2222:3333:4444::6666:7777:8888:", + "1111:2222:3333::6666:7777:8888:", + "1111:2222::6666:7777:8888:", + "1111::6666:7777:8888:", + "::6666:7777:8888:", + "1111:2222:3333::5555:6666:7777:8888:", + "1111:2222::5555:6666:7777:8888:", + "1111::5555:6666:7777:8888:", + "::5555:6666:7777:8888:", + "1111:2222::4444:5555:6666:7777:8888:", + "1111::4444:5555:6666:7777:8888:", + "::4444:5555:6666:7777:8888:", + "1111::3333:4444:5555:6666:7777:8888:", + "::3333:4444:5555:6666:7777:8888:", + "::2222:3333:4444:5555:6666:7777:8888:", + "':10.0.0.1", + ) + for s in invalid: + with self.assertRaises(dns.exception.SyntaxError, + msg=f'invalid IPv6 address: "{s}"'): + dns.ipv6.inet_aton(s) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_async.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_async.py new file mode 100644 index 0000000..e9a26bb --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_async.py @@ -0,0 +1,462 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import asyncio +import socket +import time +import unittest + +import dns.asyncbackend +import dns.asyncquery +import dns.asyncresolver +import dns.message +import dns.name +import dns.rdataclass +import dns.rdatatype +import dns.resolver + + +# Some tests require TLS so skip those if it's not there. +from dns.query import ssl +try: + ssl.create_default_context() + _ssl_available = True +except Exception: + _ssl_available = False + + +# Some tests require the internet to be available to run, so let's +# skip those if it's not there. +_network_available = True +try: + socket.gethostbyname('dnspython.org') +except socket.gaierror: + _network_available = False + + +# Probe for IPv4 and IPv6 +query_addresses = [] +for (af, address) in ((socket.AF_INET, '8.8.8.8'), + (socket.AF_INET6, '2001:4860:4860::8888')): + try: + with socket.socket(af, socket.SOCK_DGRAM) as s: + # Connecting a UDP socket is supposed to return ENETUNREACH if + # no route to the network is present. + s.connect((address, 53)) + query_addresses.append(address) + except Exception: + pass + + +class AsyncDetectionTests(unittest.TestCase): + sniff_result = 'asyncio' + + def async_run(self, afunc): + try: + runner = asyncio.run + except AttributeError: + # this is only needed for 3.6 + def old_runner(awaitable): + loop = asyncio.get_event_loop() + return loop.run_until_complete(awaitable) + runner = old_runner + return runner(afunc()) + + def test_sniff(self): + dns.asyncbackend._default_backend = None + async def run(): + self.assertEqual(dns.asyncbackend.sniff(), self.sniff_result) + self.async_run(run) + + def test_get_default_backend(self): + dns.asyncbackend._default_backend = None + async def run(): + backend = dns.asyncbackend.get_default_backend() + self.assertEqual(backend.name(), self.sniff_result) + self.async_run(run) + +class NoSniffioAsyncDetectionTests(AsyncDetectionTests): + expect_raise = False + + def setUp(self): + dns.asyncbackend._no_sniffio = True + + def tearDown(self): + dns.asyncbackend._no_sniffio = False + + def test_sniff(self): + dns.asyncbackend._default_backend = None + if self.expect_raise: + async def abad(): + dns.asyncbackend.sniff() + def bad(): + self.async_run(abad) + self.assertRaises(dns.asyncbackend.AsyncLibraryNotFoundError, bad) + else: + super().test_sniff() + + def test_get_default_backend(self): + dns.asyncbackend._default_backend = None + if self.expect_raise: + async def abad(): + dns.asyncbackend.get_default_backend() + def bad(): + self.async_run(abad) + self.assertRaises(dns.asyncbackend.AsyncLibraryNotFoundError, bad) + else: + super().test_get_default_backend() + + +class MiscBackend(unittest.TestCase): + def test_sniff_without_run_loop(self): + dns.asyncbackend._default_backend = None + def bad(): + dns.asyncbackend.sniff() + self.assertRaises(dns.asyncbackend.AsyncLibraryNotFoundError, bad) + + def test_bogus_backend(self): + def bad(): + dns.asyncbackend.get_backend('bogus') + self.assertRaises(NotImplementedError, bad) + + +class MiscQuery(unittest.TestCase): + def test_source_tuple(self): + t = dns.asyncquery._source_tuple(socket.AF_INET, None, 0) + self.assertEqual(t, None) + t = dns.asyncquery._source_tuple(socket.AF_INET6, None, 0) + self.assertEqual(t, None) + t = dns.asyncquery._source_tuple(socket.AF_INET, '1.2.3.4', 53) + self.assertEqual(t, ('1.2.3.4', 53)) + t = dns.asyncquery._source_tuple(socket.AF_INET6, '1::2', 53) + self.assertEqual(t, ('1::2', 53)) + t = dns.asyncquery._source_tuple(socket.AF_INET, None, 53) + self.assertEqual(t, ('0.0.0.0', 53)) + t = dns.asyncquery._source_tuple(socket.AF_INET6, None, 53) + self.assertEqual(t, ('::', 53)) + + +@unittest.skipIf(not _network_available, "Internet not reachable") +class AsyncTests(unittest.TestCase): + + def setUp(self): + self.backend = dns.asyncbackend.set_default_backend('asyncio') + + def async_run(self, afunc): + try: + runner = asyncio.run + except AttributeError: + # this is only needed for 3.6 + def old_runner(awaitable): + loop = asyncio.get_event_loop() + return loop.run_until_complete(awaitable) + runner = old_runner + return runner(afunc()) + + def testResolve(self): + async def run(): + answer = await dns.asyncresolver.resolve('dns.google.', 'A') + return set([rdata.address for rdata in answer]) + seen = self.async_run(run) + self.assertTrue('8.8.8.8' in seen) + self.assertTrue('8.8.4.4' in seen) + + def testResolveAddress(self): + async def run(): + return await dns.asyncresolver.resolve_address('8.8.8.8') + answer = self.async_run(run) + dnsgoogle = dns.name.from_text('dns.google.') + self.assertEqual(answer[0].target, dnsgoogle) + + def testCanonicalNameNoCNAME(self): + cname = dns.name.from_text('www.google.com') + async def run(): + return await dns.asyncresolver.canonical_name('www.google.com') + self.assertEqual(self.async_run(run), cname) + + def testCanonicalNameCNAME(self): + name = dns.name.from_text('www.dnspython.org') + cname = dns.name.from_text('dmfrjf4ips8xa.cloudfront.net') + async def run(): + return await dns.asyncresolver.canonical_name(name) + self.assertEqual(self.async_run(run), cname) + + def testCanonicalNameDangling(self): + name = dns.name.from_text('dangling-cname.dnspython.org') + cname = dns.name.from_text('dangling-target.dnspython.org') + async def run(): + return await dns.asyncresolver.canonical_name(name) + self.assertEqual(self.async_run(run), cname) + + def testResolverBadScheme(self): + res = dns.asyncresolver.Resolver(configure=False) + res.nameservers = ['bogus://dns.google/dns-query'] + async def run(): + answer = await res.resolve('dns.google', 'A') + def bad(): + self.async_run(run) + self.assertRaises(dns.resolver.NoNameservers, bad) + + def testZoneForName1(self): + async def run(): + name = dns.name.from_text('www.dnspython.org.') + return await dns.asyncresolver.zone_for_name(name) + ezname = dns.name.from_text('dnspython.org.') + zname = self.async_run(run) + self.assertEqual(zname, ezname) + + def testZoneForName2(self): + async def run(): + name = dns.name.from_text('a.b.www.dnspython.org.') + return await dns.asyncresolver.zone_for_name(name) + ezname = dns.name.from_text('dnspython.org.') + zname = self.async_run(run) + self.assertEqual(zname, ezname) + + def testZoneForName3(self): + async def run(): + name = dns.name.from_text('dnspython.org.') + return await dns.asyncresolver.zone_for_name(name) + ezname = dns.name.from_text('dnspython.org.') + zname = self.async_run(run) + self.assertEqual(zname, ezname) + + def testZoneForName4(self): + def bad(): + name = dns.name.from_text('dnspython.org', None) + async def run(): + return await dns.asyncresolver.zone_for_name(name) + self.async_run(run) + self.assertRaises(dns.resolver.NotAbsolute, bad) + + def testQueryUDP(self): + for address in query_addresses: + qname = dns.name.from_text('dns.google.') + async def run(): + q = dns.message.make_query(qname, dns.rdatatype.A) + return await dns.asyncquery.udp(q, address, timeout=2) + response = self.async_run(run) + rrs = response.get_rrset(response.answer, qname, + dns.rdataclass.IN, dns.rdatatype.A) + self.assertTrue(rrs is not None) + seen = set([rdata.address for rdata in rrs]) + self.assertTrue('8.8.8.8' in seen) + self.assertTrue('8.8.4.4' in seen) + + def testQueryUDPWithSocket(self): + for address in query_addresses: + qname = dns.name.from_text('dns.google.') + async def run(): + async with await self.backend.make_socket( + dns.inet.af_for_address(address), + socket.SOCK_DGRAM) as s: + q = dns.message.make_query(qname, dns.rdatatype.A) + return await dns.asyncquery.udp(q, address, sock=s, + timeout=2) + response = self.async_run(run) + rrs = response.get_rrset(response.answer, qname, + dns.rdataclass.IN, dns.rdatatype.A) + self.assertTrue(rrs is not None) + seen = set([rdata.address for rdata in rrs]) + self.assertTrue('8.8.8.8' in seen) + self.assertTrue('8.8.4.4' in seen) + + def testQueryTCP(self): + for address in query_addresses: + qname = dns.name.from_text('dns.google.') + async def run(): + q = dns.message.make_query(qname, dns.rdatatype.A) + return await dns.asyncquery.tcp(q, address, timeout=2) + response = self.async_run(run) + rrs = response.get_rrset(response.answer, qname, + dns.rdataclass.IN, dns.rdatatype.A) + self.assertTrue(rrs is not None) + seen = set([rdata.address for rdata in rrs]) + self.assertTrue('8.8.8.8' in seen) + self.assertTrue('8.8.4.4' in seen) + + def testQueryTCPWithSocket(self): + for address in query_addresses: + qname = dns.name.from_text('dns.google.') + async def run(): + async with await self.backend.make_socket( + dns.inet.af_for_address(address), + socket.SOCK_STREAM, 0, + None, + (address, 53), 2) as s: + # for basic coverage + await s.getsockname() + q = dns.message.make_query(qname, dns.rdatatype.A) + return await dns.asyncquery.tcp(q, address, sock=s, + timeout=2) + response = self.async_run(run) + rrs = response.get_rrset(response.answer, qname, + dns.rdataclass.IN, dns.rdatatype.A) + self.assertTrue(rrs is not None) + seen = set([rdata.address for rdata in rrs]) + self.assertTrue('8.8.8.8' in seen) + self.assertTrue('8.8.4.4' in seen) + + @unittest.skipIf(not _ssl_available, "SSL not available") + def testQueryTLS(self): + for address in query_addresses: + qname = dns.name.from_text('dns.google.') + async def run(): + q = dns.message.make_query(qname, dns.rdatatype.A) + return await dns.asyncquery.tls(q, address, timeout=2) + response = self.async_run(run) + rrs = response.get_rrset(response.answer, qname, + dns.rdataclass.IN, dns.rdatatype.A) + self.assertTrue(rrs is not None) + seen = set([rdata.address for rdata in rrs]) + self.assertTrue('8.8.8.8' in seen) + self.assertTrue('8.8.4.4' in seen) + + @unittest.skipIf(not _ssl_available, "SSL not available") + def testQueryTLSWithSocket(self): + for address in query_addresses: + qname = dns.name.from_text('dns.google.') + async def run(): + ssl_context = ssl.create_default_context() + ssl_context.check_hostname = False + async with await self.backend.make_socket( + dns.inet.af_for_address(address), + socket.SOCK_STREAM, 0, + None, + (address, 853), 2, + ssl_context, None) as s: + # for basic coverage + await s.getsockname() + q = dns.message.make_query(qname, dns.rdatatype.A) + return await dns.asyncquery.tls(q, '8.8.8.8', sock=s, + timeout=2) + response = self.async_run(run) + rrs = response.get_rrset(response.answer, qname, + dns.rdataclass.IN, dns.rdatatype.A) + self.assertTrue(rrs is not None) + seen = set([rdata.address for rdata in rrs]) + self.assertTrue('8.8.8.8' in seen) + self.assertTrue('8.8.4.4' in seen) + + def testQueryUDPFallback(self): + for address in query_addresses: + qname = dns.name.from_text('.') + async def run(): + q = dns.message.make_query(qname, dns.rdatatype.DNSKEY) + return await dns.asyncquery.udp_with_fallback(q, address, + timeout=2) + (_, tcp) = self.async_run(run) + self.assertTrue(tcp) + + def testQueryUDPFallbackNoFallback(self): + for address in query_addresses: + qname = dns.name.from_text('dns.google.') + async def run(): + q = dns.message.make_query(qname, dns.rdatatype.A) + return await dns.asyncquery.udp_with_fallback(q, address, + timeout=2) + (_, tcp) = self.async_run(run) + self.assertFalse(tcp) + + def testUDPReceiveQuery(self): + async def run(): + async with await self.backend.make_socket( + socket.AF_INET, socket.SOCK_DGRAM, + source=('127.0.0.1', 0)) as listener: + listener_address = await listener.getsockname() + async with await self.backend.make_socket( + socket.AF_INET, socket.SOCK_DGRAM, + source=('127.0.0.1', 0)) as sender: + sender_address = await sender.getsockname() + q = dns.message.make_query('dns.google', dns.rdatatype.A) + await dns.asyncquery.send_udp(sender, q, listener_address) + expiration = time.time() + 2 + (_, _, recv_address) = await dns.asyncquery.receive_udp( + listener, expiration=expiration) + return (sender_address, recv_address) + (sender_address, recv_address) = self.async_run(run) + self.assertEqual(sender_address, recv_address) + + def testUDPReceiveTimeout(self): + async def arun(): + async with await self.backend.make_socket(socket.AF_INET, + socket.SOCK_DGRAM, 0, + ('127.0.0.1', 0)) as s: + try: + # for basic coverage + await s.getpeername() + except Exception: + # we expect failure as we haven't connected the socket + pass + await s.recvfrom(1000, 0.05) + def run(): + self.async_run(arun) + self.assertRaises(dns.exception.Timeout, run) + + def testSleep(self): + async def run(): + before = time.time() + await self.backend.sleep(0.1) + after = time.time() + self.assertTrue(after - before >= 0.1) + self.async_run(run) + +try: + import trio + import sniffio + + class TrioAsyncDetectionTests(AsyncDetectionTests): + sniff_result = 'trio' + def async_run(self, afunc): + return trio.run(afunc) + + class TrioNoSniffioAsyncDetectionTests(NoSniffioAsyncDetectionTests): + expect_raise = True + def async_run(self, afunc): + return trio.run(afunc) + + class TrioAsyncTests(AsyncTests): + def setUp(self): + self.backend = dns.asyncbackend.set_default_backend('trio') + + def async_run(self, afunc): + return trio.run(afunc) +except ImportError: + pass + +try: + import curio + import sniffio + + class CurioAsyncDetectionTests(AsyncDetectionTests): + sniff_result = 'curio' + def async_run(self, afunc): + return curio.run(afunc) + + class CurioNoSniffioAsyncDetectionTests(NoSniffioAsyncDetectionTests): + expect_raise = True + def async_run(self, afunc): + return curio.run(afunc) + + class CurioAsyncTests(AsyncTests): + def setUp(self): + self.backend = dns.asyncbackend.set_default_backend('curio') + + def async_run(self, afunc): + return curio.run(afunc) +except ImportError: + pass diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_bugs.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_bugs.py new file mode 100644 index 0000000..b9636a6 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_bugs.py @@ -0,0 +1,101 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +from io import BytesIO +import unittest + +import binascii + +import dns.rdata +import dns.rdataclass +import dns.rdatatype +import dns.rdtypes.ANY.TXT +import dns.ttl + + +class BugsTestCase(unittest.TestCase): + + def test_float_LOC(self): + rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.LOC, + u"30 30 0.000 N 100 30 0.000 W 10.00m 20m 2000m 20m") + self.assertEqual(rdata.float_latitude, 30.5) + self.assertEqual(rdata.float_longitude, -100.5) + + def test_SOA_BIND8_TTL(self): + rdata1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, + u"a b 100 1s 1m 1h 1d") + rdata2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, + u"a b 100 1 60 3600 86400") + self.assertEqual(rdata1, rdata2) + + def test_TTL_bounds_check(self): + def bad(): + dns.ttl.from_text("2147483648") + self.assertRaises(dns.ttl.BadTTL, bad) + + def test_empty_NSEC3_window(self): + rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NSEC3, + u"1 0 100 ABCD SCBCQHKU35969L2A68P3AD59LHF30715") + self.assertEqual(rdata.windows, ()) + + def test_zero_size_APL(self): + rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.APL, + "") + rdata2 = dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.APL, + "", 0, 0) + self.assertEqual(rdata, rdata2) + + def test_CAA_from_wire(self): + rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CAA, + '0 issue "ca.example.net"') + f = BytesIO() + rdata.to_wire(f) + wire = f.getvalue() + rdlen = len(wire) + wire += b"trailing garbage" + rdata2 = dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.CAA, + wire, 0, rdlen) + self.assertEqual(rdata, rdata2) + + def test_trailing_zero_APL(self): + in4 = "!1:127.0.0.0/1" + rd4 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.APL, in4) + out4 = rd4.to_digestable(dns.name.from_text("test")) + text4 = binascii.hexlify(out4).decode('ascii') + self.assertEqual(text4, '000101817f') + in6 = "!2:::1000/1" + rd6 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.APL, in6) + out6 = rd6.to_digestable(dns.name.from_text("test")) + text6 = binascii.hexlify(out6).decode('ascii') + self.assertEqual(text6, '0002018f000000000000000000000000000010') + + def test_TXT_conversions(self): + t1 = dns.rdtypes.ANY.TXT.TXT(dns.rdataclass.IN, dns.rdatatype.TXT, + [b'foo']) + t2 = dns.rdtypes.ANY.TXT.TXT(dns.rdataclass.IN, dns.rdatatype.TXT, + b'foo') + t3 = dns.rdtypes.ANY.TXT.TXT(dns.rdataclass.IN, dns.rdatatype.TXT, + 'foo') + t4 = dns.rdtypes.ANY.TXT.TXT(dns.rdataclass.IN, dns.rdatatype.TXT, + ['foo']) + self.assertEqual(t1, t2) + self.assertEqual(t1, t2) + self.assertEqual(t1, t4) + + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_constants.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_constants.py new file mode 100644 index 0000000..e818bb9 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_constants.py @@ -0,0 +1,38 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import unittest + +import dns.dnssec +import dns.rdtypes.dnskeybase +import dns.flags +import dns.rcode +import dns.opcode +import dns.message +import dns.update +import dns.edns + +import tests.util + + +class ConstantsTestCase(unittest.TestCase): + + def test_dnssec_constants(self): + tests.util.check_enum_exports(dns.dnssec, self.assertEqual, + only={dns.dnssec.Algorithm}) + tests.util.check_enum_exports(dns.rdtypes.dnskeybase, self.assertEqual) + + def test_flags_constants(self): + tests.util.check_enum_exports(dns.flags, self.assertEqual) + tests.util.check_enum_exports(dns.rcode, self.assertEqual) + tests.util.check_enum_exports(dns.opcode, self.assertEqual) + + def test_message_constants(self): + tests.util.check_enum_exports(dns.message, self.assertEqual) + tests.util.check_enum_exports(dns.update, self.assertEqual) + + def test_rdata_constants(self): + tests.util.check_enum_exports(dns.rdataclass, self.assertEqual) + tests.util.check_enum_exports(dns.rdatatype, self.assertEqual) + + def test_edns_constants(self): + tests.util.check_enum_exports(dns.edns, self.assertEqual) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_dnssec.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_dnssec.py new file mode 100644 index 0000000..ea82d7b --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_dnssec.py @@ -0,0 +1,501 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import unittest + +import dns.dnssec +import dns.name +import dns.rdata +import dns.rdataclass +import dns.rdatatype +import dns.rrset + +# pylint: disable=line-too-long + +abs_dnspython_org = dns.name.from_text('dnspython.org') + +abs_keys = { + abs_dnspython_org: dns.rrset.from_text( + 'dnspython.org.', 3600, 'IN', 'DNSKEY', + '257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=', + '256 3 5 AwEAAdSSghOGjU33IQZgwZM2Hh771VGXX05olJK49FxpSyuEAjDBXY58 LGU9R2Zgeecnk/b9EAhFu/vCV9oECtiTCvwuVAkt9YEweqYDluQInmgP NGMJCKdSLlnX93DkjDw8rMYv5dqXCuSGPlKChfTJOLQxIAxGloS7lL+c 0CTZydAF' + ) +} + +abs_keys_duplicate_keytag = { + abs_dnspython_org: dns.rrset.from_text( + 'dnspython.org.', 3600, 'IN', 'DNSKEY', + '257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=', + '256 3 5 AwEAAdSSg++++THIS/IS/NOT/THE/CORRECT/KEY++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ AaOSydAF', + '256 3 5 AwEAAdSSghOGjU33IQZgwZM2Hh771VGXX05olJK49FxpSyuEAjDBXY58 LGU9R2Zgeecnk/b9EAhFu/vCV9oECtiTCvwuVAkt9YEweqYDluQInmgP NGMJCKdSLlnX93DkjDw8rMYv5dqXCuSGPlKChfTJOLQxIAxGloS7lL+c 0CTZydAF' + ) +} + +rel_keys = { + dns.name.empty: dns.rrset.from_text( + '@', 3600, 'IN', 'DNSKEY', + '257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=', + '256 3 5 AwEAAdSSghOGjU33IQZgwZM2Hh771VGXX05olJK49FxpSyuEAjDBXY58 LGU9R2Zgeecnk/b9EAhFu/vCV9oECtiTCvwuVAkt9YEweqYDluQInmgP NGMJCKdSLlnX93DkjDw8rMYv5dqXCuSGPlKChfTJOLQxIAxGloS7lL+c 0CTZydAF' + ) +} + +when = 1290250287 + +abs_soa = dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'SOA', + 'howl.dnspython.org. hostmaster.dnspython.org. 2010020047 3600 1800 604800 3600') + +abs_other_soa = dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'SOA', + 'foo.dnspython.org. hostmaster.dnspython.org. 2010020047 3600 1800 604800 3600') + +abs_soa_rrsig = dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'RRSIG', + 'SOA 5 2 3600 20101127004331 20101119213831 61695 dnspython.org. sDUlltRlFTQw5ITFxOXW3TgmrHeMeNpdqcZ4EXxM9FHhIlte6V9YCnDw t6dvM9jAXdIEi03l9H/RAd9xNNW6gvGMHsBGzpvvqFQxIBR2PoiZA1mX /SWHZFdbt4xjYTtXqpyYvrMK0Dt7bUYPadyhPFCJ1B+I8Zi7B5WJEOd0 8vs=') + +rel_soa = dns.rrset.from_text('@', 3600, 'IN', 'SOA', + 'howl hostmaster 2010020047 3600 1800 604800 3600') + +rel_other_soa = dns.rrset.from_text('@', 3600, 'IN', 'SOA', + 'foo hostmaster 2010020047 3600 1800 604800 3600') + +rel_soa_rrsig = dns.rrset.from_text('@', 3600, 'IN', 'RRSIG', + 'SOA 5 2 3600 20101127004331 20101119213831 61695 @ sDUlltRlFTQw5ITFxOXW3TgmrHeMeNpdqcZ4EXxM9FHhIlte6V9YCnDw t6dvM9jAXdIEi03l9H/RAd9xNNW6gvGMHsBGzpvvqFQxIBR2PoiZA1mX /SWHZFdbt4xjYTtXqpyYvrMK0Dt7bUYPadyhPFCJ1B+I8Zi7B5WJEOd0 8vs=') + +sep_key = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DNSKEY, + '257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=') + +good_ds = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS, + '57349 5 2 53A79A3E7488AB44FFC56B2D1109F0699D1796DD977E72108B841F96 E47D7013') + +when2 = 1290425644 + +abs_example = dns.name.from_text('example') + +abs_dsa_keys = { + abs_example: dns.rrset.from_text( + 'example.', 86400, 'IN', 'DNSKEY', + '257 3 3 CI3nCqyJsiCJHTjrNsJOT4RaszetzcJPYuoH3F9ZTVt3KJXncCVR3bwn 1w0iavKljb9hDlAYSfHbFCp4ic/rvg4p1L8vh5s8ToMjqDNl40A0hUGQ Ybx5hsECyK+qHoajilUX1phYSAD8d9WAGO3fDWzUPBuzR7o85NiZCDxz yXuNVfni0uhj9n1KYhEO5yAbbruDGN89wIZcxMKuQsdUY2GYD93ssnBv a55W6XRABYWayKZ90WkRVODLVYLSn53Pj/wwxGH+XdhIAZJXimrZL4yl My7rtBsLMqq8Ihs4Tows7LqYwY7cp6y/50tw6pj8tFqMYcPUjKZV36l1 M/2t5BVg3i7IK61Aidt6aoC3TDJtzAxg3ZxfjZWJfhHjMJqzQIfbW5b9 q1mjFsW5EUv39RaNnX+3JWPRLyDqD4pIwDyqfutMsdk/Py3paHn82FGp CaOg+nicqZ9TiMZURN/XXy5JoXUNQ3RNvbHCUiPUe18KUkY6mTfnyHld 1l9YCWmzXQVClkx/hOYxjJ4j8Ife58+Obu5X', + '256 3 3 CJE1yb9YRQiw5d2xZrMUMR+cGCTt1bp1KDCefmYKmS+Z1+q9f42ETVhx JRiQwXclYwmxborzIkSZegTNYIV6mrYwbNB27Q44c3UGcspb3PiOw5TC jNPRYEcdwGvDZ2wWy+vkSV/S9tHXY8O6ODiE6abZJDDg/RnITyi+eoDL R3KZ5n/V1f1T1b90rrV6EewhBGQJpQGDogaXb2oHww9Tm6NfXyo7SoMM pbwbzOckXv+GxRPJIQNSF4D4A9E8XCksuzVVdE/0lr37+uoiAiPia38U 5W2QWe/FJAEPLjIp2eTzf0TrADc1pKP1wrA2ASpdzpm/aX3IB5RPp8Ew S9U72eBFZJAUwg635HxJVxH1maG6atzorR566E+e0OZSaxXS9o1o6QqN 3oPlYLGPORDiExilKfez3C/x/yioOupW9K5eKF0gmtaqrHX0oq9s67f/ RIM2xVaKHgG9Vf2cgJIZkhv7sntujr+E4htnRmy9P9BxyFxsItYxPI6Z bzygHAZpGhlI/7ltEGlIwKxyTK3ZKBm67q7B' + ) +} + +abs_dsa_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', + 'ns1.example. hostmaster.example. 2 10800 3600 604800 86400') + +abs_other_dsa_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', + 'ns1.example. hostmaster.example. 2 10800 3600 604800 86401') + +abs_dsa_soa_rrsig = dns.rrset.from_text('example.', 86400, 'IN', 'RRSIG', + 'SOA 3 1 86400 20101129143231 20101122112731 42088 example. CGul9SuBofsktunV8cJs4eRs6u+3NCS3yaPKvBbD+pB2C76OUXDZq9U=') + +example_sep_key = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DNSKEY, + '257 3 3 CI3nCqyJsiCJHTjrNsJOT4RaszetzcJPYuoH3F9ZTVt3KJXncCVR3bwn 1w0iavKljb9hDlAYSfHbFCp4ic/rvg4p1L8vh5s8ToMjqDNl40A0hUGQ Ybx5hsECyK+qHoajilUX1phYSAD8d9WAGO3fDWzUPBuzR7o85NiZCDxz yXuNVfni0uhj9n1KYhEO5yAbbruDGN89wIZcxMKuQsdUY2GYD93ssnBv a55W6XRABYWayKZ90WkRVODLVYLSn53Pj/wwxGH+XdhIAZJXimrZL4yl My7rtBsLMqq8Ihs4Tows7LqYwY7cp6y/50tw6pj8tFqMYcPUjKZV36l1 M/2t5BVg3i7IK61Aidt6aoC3TDJtzAxg3ZxfjZWJfhHjMJqzQIfbW5b9 q1mjFsW5EUv39RaNnX+3JWPRLyDqD4pIwDyqfutMsdk/Py3paHn82FGp CaOg+nicqZ9TiMZURN/XXy5JoXUNQ3RNvbHCUiPUe18KUkY6mTfnyHld 1l9YCWmzXQVClkx/hOYxjJ4j8Ife58+Obu5X') + +example_ds_sha1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS, + '18673 3 1 71b71d4f3e11bbd71b4eff12cde69f7f9215bbe7') + +example_ds_sha256 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS, + '18673 3 2 eb8344cbbf07c9d3d3d6c81d10c76653e28d8611a65e639ef8f716e4e4e5d913') + +example_ds_sha384 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS, + '18673 3 4 61ab241025c5f88d2537be04dcfba96f952adaefe0b382ecbc4108c97b75768c9e99fd16caed2a09634c51e8089fb84f') + +when3 = 1379801800 + +abs_ecdsa256_keys = { + abs_example: dns.rrset.from_text( + 'example.', 86400, 'IN', 'DNSKEY', + "256 3 13 +3ss1sCpdARVA61DJigEsL/8quo2a8MszKtn2gkkfxgzFs8S2UHtpb4N fY+XFmNW+JK6MsCkI3jHYN8eEQUgMw==", + "257 3 13 eJCEVH7AS3wnoaQpaNlAXH0W8wxymtT9P6P3qjN2ZCV641ED8pF7wZ5V yWfOpgTs6oaZevbJgehl/GaRPUgVyQ==" + ) +} + +abs_ecdsa256_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', + 'ns1.example. hostmaster.example. 4 10800 3600 604800 86400') + +abs_other_ecdsa256_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', + 'ns1.example. hostmaster.example. 2 10800 3600 604800 86401') + +abs_ecdsa256_soa_rrsig = dns.rrset.from_text('example.', 86400, 'IN', 'RRSIG', + "SOA 13 1 86400 20130921221753 20130921221638 7460 example. Sm09SOGz1ULB5D/duwdE2Zpn8bWbVBM77H6N1wPkc42LevvVO+kZEjpq 2nq4GOMJcih52667GIAbMrwmU5P2MQ==") + +when4 = 1379804850 + +abs_ecdsa384_keys = { + abs_example: dns.rrset.from_text( + 'example.', 86400, 'IN', 'DNSKEY', + "256 3 14 1bG8qWviKNXQX3BIuG6/T5jrP1FISiLW/8qGF6BsM9DQtWYhhZUA3Owr OAEiyHAhQwjkN2kTvWiAYoPN80Ii+5ff9/atzY4F9W50P4l75Dj9PYrL HN/hLUgWMNVc9pvA", + "257 3 14 mSub2n0KRt6u2FaD5XJ3oQu0R4XvB/9vUJcyW6+oo0y+KzfQeTdkf1ro ZMVKoyWXW9zUKBYGJpMUIdbAxzrYi7f5HyZ3yDpBFz1hw9+o3CX+gtgb +RyhHfJDwwFXBid9" + ) +} + +abs_ecdsa384_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', + 'ns1.example. hostmaster.example. 2 10800 3600 604800 86400') + +abs_other_ecdsa384_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', + 'ns1.example. hostmaster.example. 2 10800 3600 604800 86401') + +abs_ecdsa384_soa_rrsig = dns.rrset.from_text('example.', 86400, 'IN', 'RRSIG', + "SOA 14 1 86400 20130929021229 20130921230729 63571 example. CrnCu34EeeRz0fEhL9PLlwjpBKGYW8QjBjFQTwd+ViVLRAS8tNkcDwQE NhSV89NEjj7ze1a/JcCfcJ+/mZgnvH4NHLNg3Tf6KuLZsgs2I4kKQXEk 37oIHravPEOlGYNI") + +abs_example_com = dns.name.from_text('example.com') + +abs_ed25519_mx = dns.rrset.from_text('example.com.', 3600, 'IN', 'MX', + '10 mail.example.com.') +abs_other_ed25519_mx = dns.rrset.from_text('example.com.', 3600, 'IN', 'MX', + '11 mail.example.com.') +abs_ed25519_keys_1 = { + abs_example_com: dns.rrset.from_text( + 'example.com', 3600, 'IN', 'DNSKEY', + '257 3 15 l02Woi0iS8Aa25FQkUd9RMzZHJpBoRQwAQEX1SxZJA4=') +} +abs_ed25519_mx_rrsig_1 = dns.rrset.from_text('example.com.', 3600, 'IN', 'RRSIG', + 'MX 15 2 3600 1440021600 1438207200 3613 example.com. oL9krJun7xfBOIWcGHi7mag5/hdZrKWw15jPGrHpjQeRAvTdszaPD+QLs3fx8A4M3e23mRZ9VrbpMngwcrqNAg==') + +abs_ed25519_keys_2 = { + abs_example_com: dns.rrset.from_text( + 'example.com', 3600, 'IN', 'DNSKEY', + '257 3 15 zPnZ/QwEe7S8C5SPz2OfS5RR40ATk2/rYnE9xHIEijs=') +} +abs_ed25519_mx_rrsig_2 = dns.rrset.from_text('example.com.', 3600, 'IN', 'RRSIG', + 'MX 15 2 3600 1440021600 1438207200 35217 example.com. zXQ0bkYgQTEFyfLyi9QoiY6D8ZdYo4wyUhVioYZXFdT410QPRITQSqJSnzQoSm5poJ7gD7AQR0O7KuI5k2pcBg==') + +abs_ed448_mx = abs_ed25519_mx +abs_other_ed448_mx = abs_other_ed25519_mx + +abs_ed448_keys_1 = { + abs_example_com: dns.rrset.from_text( + 'example.com', 3600, 'IN', 'DNSKEY', + '257 3 16 3kgROaDjrh0H2iuixWBrc8g2EpBBLCdGzHmn+G2MpTPhpj/OiBVHHSfPodx1FYYUcJKm1MDpJtIA') +} +abs_ed448_mx_rrsig_1 = dns.rrset.from_text('example.com.', 3600, 'IN', 'RRSIG', + 'MX 16 2 3600 1440021600 1438207200 9713 example.com. 3cPAHkmlnxcDHMyg7vFC34l0blBhuG1qpwLmjInI8w1CMB29FkEAIJUA0amxWndkmnBZ6SKiwZSAxGILn/NBtOXft0+Gj7FSvOKxE/07+4RQvE581N3Aj/JtIyaiYVdnYtyMWbSNyGEY2213WKsJlwEA') + +abs_ed448_keys_2 = { + abs_example_com: dns.rrset.from_text( + 'example.com', 3600, 'IN', 'DNSKEY', + '257 3 16 kkreGWoccSDmUBGAe7+zsbG6ZAFQp+syPmYUurBRQc3tDjeMCJcVMRDmgcNLp5HlHAMy12VoISsA') +} +abs_ed448_mx_rrsig_2 = dns.rrset.from_text('example.com.', 3600, 'IN', 'RRSIG', + 'MX 16 2 3600 1440021600 1438207200 38353 example.com. E1/oLjSGIbmLny/4fcgM1z4oL6aqo+izT3urCyHyvEp4Sp8Syg1eI+lJ57CSnZqjJP41O/9l4m0AsQ4f7qI1gVnML8vWWiyW2KXhT9kuAICUSxv5OWbf81Rq7Yu60npabODB0QFPb/rkW3kUZmQ0YQUA') + +when5 = 1440021600 +when5_start = 1438207200 + +wildcard_keys = { + abs_example_com : dns.rrset.from_text( + 'example.com', 3600, 'IN', 'DNSKEY', + '256 3 5 AwEAAecNZbwD2thg3kaRLVqCC7ASP/3F79ZIu7pCu8HvZZ6ZdinffnxT npNoVvavjouHKFYTtJyUZAfw3ZMJSsGvEerc7uh6Ex9TgvOJtWPGUtxB Nnni2u9Nk+5k6nJzMiS3sL3RLvrfZW5d2Bwbl9L5f9Ud+r2Dbm7EG3tY pMY5OE8f') +} +wildcard_example_com = dns.name.from_text('*', abs_example_com) +wildcard_txt = dns.rrset.from_text('*.example.com.', 3600, 'IN', 'TXT', 'foo') +wildcard_txt_rrsig = dns.rrset.from_text('*.example.com.', 3600, 'IN', 'RRSIG', + 'TXT 5 2 3600 20200707211255 20200630180755 42486 example.com. qevJYhdAHq1VmehXQ5i+Epa32xs4zcd4qmb39pHa3GUKr1V504nxzdzQ gsT5mvDkRoY95+HAiysDON6DCDtZc69iBUIHWWuFo/OrcD2q/mWANG4x vyU28Pf0U1gN6Gd5iapKC0Ya12flKh//NQiNN2skOQ2MoF2MW2/MaAK2 HBc=') + +wildcard_when = 1593541048 + + +rsamd5_keys = { + abs_example: dns.rrset.from_text( + 'example', 3600, 'in', 'dnskey', + '257 3 1 AwEAAewnoEWe+AVEnQzcZTwpl8K/QKuScYIX 9xHOhejAL1enMjE0j97Gq3XXJJPWF7eQQGHs 1De4Srv2UT0zRCLkH9r36lOR/ggANvthO/Ub Es0hlD3A58LumEPudgIDwEkxGvQAXMFTMw0x 1d/a82UtzmNoPVzFOl2r+OCXx9Jbdh/L; KSK; alg = RSAMD5; key id = 30239', + '256 3 1 AwEAAb8OJM5YcqaYG0fenUdRlrhBQ6LuwCvr 5BRlrVbVzadSDBpq+yIiklfdGNBg3WZztDy1 du62NWC/olMfc6uRe/SjqTa7IJ3MdEuZQXQw MedGdNSF73zbokx8wg7zBBr74xHczJcEpQhr ZLzwCDmIPu0yoVi3Yqdl4dm4vNBj9hAD; ZSK; alg = RSAMD5; key id = 62992') +} + +rsamd5_ns = dns.rrset.from_text('example.', 3600, 'in', 'ns', + 'ns1.example.', 'ns2.example.') +rsamd5_ns_rrsig = dns.rrset.from_text('example.', 3600, 'in', 'rrsig', + 'NS 1 1 3600 20200825153103 20200726153103 62992 example. YPv0WVqzQBDH45mFcYGo9psCVoMoeeHeAugh 9RZuO2NmdwfQ3mmiQm7WJ3AYnzYIozFGf7CL nwn3vN8/fjsfcQgEv5xfhFTSd4IoAzJJiZAa vrI4L5590C/+aXQ8tjRmbMTPiqoudaXvsevE jP2lTFg5DCruJyFq5dnAY5b90RY=') + +rsamd5_when = 1595781671 + +rsasha512_keys = { + abs_example: dns.rrset.from_text( + 'example', 3600, 'in', 'dnskey', + '256 3 10 AwEAAb2JvKjZ6l5qg2ab3qqUQhLGGjsiMIuQ 2zhaXJHdTntS+8LgUXo5yLFn7YF9YL1VX9V4 5ASGxUpz0u0chjWqBNtUO3Ymzas/vck9o21M 2Ce/LrpfYsqvJaLvGf/dozW9uSeMQq1mPKYG xo4uxyhZBhZewX8znXZySrAIozBPH3yp ; ZSK; alg = RSASHA512 ; key id = 5957', + '257 3 10 AwEAAc7Lnoe+mHijJ8OOHgyJHKYantQGKx5t rIs267gOePyAL7cUt9HO1Sm3vABSGNsoHL6w 8/542SxGbT21osVISamtq7kUPTgDU9iKqCBq VdXEdzXYbhBKVoQkGPl4PflfbOgg/45xAiTi 7qOUERuRCPdKEkd4FW0tg6VfZmm7QjP1 ; KSK; alg = RSASHA512 ; key id = 53212') +} + +rsasha512_ns = dns.rrset.from_text('example.', 3600, 'in', 'ns', + 'ns1.example.', 'ns2.example.') +rsasha512_ns_rrsig = dns.rrset.from_text( + 'example.', 3600, 'in', 'rrsig', + 'NS 10 1 3600 20200825161255 20200726161255 5957 example. P9A+1zYke7yIiKEnxFMm+UIW2CIwy2WDvbx6 g8hHiI8qISe6oeKveFW23OSk9+VwFgBiOpeM ygzzFbckY7RkGbOr4TR8ogDRANt6LhV402Hu SXTV9hCLVFWU4PS+/fxxfOHCetsY5tWWSxZi zSHfgpGfsHWzQoAamag4XYDyykc=') + +rsasha512_when = 1595783997 + + +unknown_alg_keys = { + abs_example: dns.rrset.from_text( + 'example', 3600, 'in', 'dnskey', + '256 3 100 Ym9ndXM=', + '257 3 100 Ym9ndXM=') +} + +unknown_alg_ns_rrsig = dns.rrset.from_text( + 'example.', 3600, 'in', 'rrsig', + 'NS 100 1 3600 20200825161255 20200726161255 16713 example. P9A+1zYke7yIiKEnxFMm+UIW2CIwy2WDvbx6 g8hHiI8qISe6oeKveFW23OSk9+VwFgBiOpeM ygzzFbckY7RkGbOr4TR8ogDRANt6LhV402Hu SXTV9hCLVFWU4PS+/fxxfOHCetsY5tWWSxZi zSHfgpGfsHWzQoAamag4XYDyykc=') + +fake_gost_keys = { + abs_example: dns.rrset.from_text( + 'example', 3600, 'in', 'dnskey', + '256 3 12 Ym9ndXM=', + '257 3 12 Ym9ndXM=') +} + +fake_gost_ns_rrsig = dns.rrset.from_text( + 'example.', 3600, 'in', 'rrsig', + 'NS 12 1 3600 20200825161255 20200726161255 16625 example. P9A+1zYke7yIiKEnxFMm+UIW2CIwy2WDvbx6 g8hHiI8qISe6oeKveFW23OSk9+VwFgBiOpeM ygzzFbckY7RkGbOr4TR8ogDRANt6LhV402Hu SXTV9hCLVFWU4PS+/fxxfOHCetsY5tWWSxZi zSHfgpGfsHWzQoAamag4XYDyykc=') + +@unittest.skipUnless(dns.dnssec._have_pyca, + "Python Cryptography cannot be imported") +class DNSSECValidatorTestCase(unittest.TestCase): + + def testAbsoluteRSAMD5Good(self): # type: () -> None + dns.dnssec.validate(rsamd5_ns, rsamd5_ns_rrsig, rsamd5_keys, None, + rsamd5_when) + + def testRSAMD5Keyid(self): + self.assertEqual(dns.dnssec.key_id(rsamd5_keys[abs_example][0]), 30239) + self.assertEqual(dns.dnssec.key_id(rsamd5_keys[abs_example][1]), 62992) + + def testAbsoluteRSAGood(self): # type: () -> None + dns.dnssec.validate(abs_soa, abs_soa_rrsig, abs_keys, None, when) + + def testDuplicateKeytag(self): # type: () -> None + dns.dnssec.validate(abs_soa, abs_soa_rrsig, abs_keys_duplicate_keytag, None, when) + + def testAbsoluteRSABad(self): # type: () -> None + def bad(): # type: () -> None + dns.dnssec.validate(abs_other_soa, abs_soa_rrsig, abs_keys, None, + when) + self.assertRaises(dns.dnssec.ValidationFailure, bad) + + def testRelativeRSAGood(self): # type: () -> None + dns.dnssec.validate(rel_soa, rel_soa_rrsig, rel_keys, + abs_dnspython_org, when) + # test the text conversion for origin too + dns.dnssec.validate(rel_soa, rel_soa_rrsig, rel_keys, + 'dnspython.org', when) + + def testRelativeRSABad(self): # type: () -> None + def bad(): # type: () -> None + dns.dnssec.validate(rel_other_soa, rel_soa_rrsig, rel_keys, + abs_dnspython_org, when) + self.assertRaises(dns.dnssec.ValidationFailure, bad) + + def testAbsoluteDSAGood(self): # type: () -> None + dns.dnssec.validate(abs_dsa_soa, abs_dsa_soa_rrsig, abs_dsa_keys, None, + when2) + + def testAbsoluteDSABad(self): # type: () -> None + def bad(): # type: () -> None + dns.dnssec.validate(abs_other_dsa_soa, abs_dsa_soa_rrsig, + abs_dsa_keys, None, when2) + self.assertRaises(dns.dnssec.ValidationFailure, bad) + + def testAbsoluteECDSA256Good(self): # type: () -> None + dns.dnssec.validate(abs_ecdsa256_soa, abs_ecdsa256_soa_rrsig, + abs_ecdsa256_keys, None, when3) + + def testAbsoluteECDSA256Bad(self): # type: () -> None + def bad(): # type: () -> None + dns.dnssec.validate(abs_other_ecdsa256_soa, abs_ecdsa256_soa_rrsig, + abs_ecdsa256_keys, None, when3) + self.assertRaises(dns.dnssec.ValidationFailure, bad) + + def testAbsoluteECDSA384Good(self): # type: () -> None + dns.dnssec.validate(abs_ecdsa384_soa, abs_ecdsa384_soa_rrsig, + abs_ecdsa384_keys, None, when4) + + def testAbsoluteECDSA384Bad(self): # type: () -> None + def bad(): # type: () -> None + dns.dnssec.validate(abs_other_ecdsa384_soa, abs_ecdsa384_soa_rrsig, + abs_ecdsa384_keys, None, when4) + self.assertRaises(dns.dnssec.ValidationFailure, bad) + + def testAbsoluteED25519Good(self): # type: () -> None + dns.dnssec.validate(abs_ed25519_mx, abs_ed25519_mx_rrsig_1, + abs_ed25519_keys_1, None, when5) + dns.dnssec.validate(abs_ed25519_mx, abs_ed25519_mx_rrsig_2, + abs_ed25519_keys_2, None, when5) + + def testAbsoluteED25519Bad(self): # type: () -> None + with self.assertRaises(dns.dnssec.ValidationFailure): + dns.dnssec.validate(abs_other_ed25519_mx, abs_ed25519_mx_rrsig_1, + abs_ed25519_keys_1, None, when5) + with self.assertRaises(dns.dnssec.ValidationFailure): + dns.dnssec.validate(abs_other_ed25519_mx, abs_ed25519_mx_rrsig_2, + abs_ed25519_keys_2, None, when5) + + def testAbsoluteED448Good(self): # type: () -> None + dns.dnssec.validate(abs_ed448_mx, abs_ed448_mx_rrsig_1, + abs_ed448_keys_1, None, when5) + dns.dnssec.validate(abs_ed448_mx, abs_ed448_mx_rrsig_2, + abs_ed448_keys_2, None, when5) + + def testAbsoluteED448Bad(self): # type: () -> None + with self.assertRaises(dns.dnssec.ValidationFailure): + dns.dnssec.validate(abs_other_ed448_mx, abs_ed448_mx_rrsig_1, + abs_ed448_keys_1, None, when5) + with self.assertRaises(dns.dnssec.ValidationFailure): + dns.dnssec.validate(abs_other_ed448_mx, abs_ed448_mx_rrsig_2, + abs_ed448_keys_2, None, when5) + + def testAbsoluteRSASHA512Good(self): + dns.dnssec.validate(rsasha512_ns, rsasha512_ns_rrsig, rsasha512_keys, + None, rsasha512_when) + + def testWildcardGoodAndBad(self): + dns.dnssec.validate(wildcard_txt, wildcard_txt_rrsig, + wildcard_keys, None, wildcard_when) + + def clone_rrset(rrset, name): + return dns.rrset.from_rdata(name, rrset.ttl, rrset[0]) + + a_name = dns.name.from_text('a.example.com') + a_txt = clone_rrset(wildcard_txt, a_name) + a_txt_rrsig = clone_rrset(wildcard_txt_rrsig, a_name) + dns.dnssec.validate(a_txt, a_txt_rrsig, wildcard_keys, None, + wildcard_when) + + abc_name = dns.name.from_text('a.b.c.example.com') + abc_txt = clone_rrset(wildcard_txt, abc_name) + abc_txt_rrsig = clone_rrset(wildcard_txt_rrsig, abc_name) + dns.dnssec.validate(abc_txt, abc_txt_rrsig, wildcard_keys, None, + wildcard_when) + + com_name = dns.name.from_text('com.') + com_txt = clone_rrset(wildcard_txt, com_name) + com_txt_rrsig = clone_rrset(wildcard_txt_rrsig, abc_name) + with self.assertRaises(dns.dnssec.ValidationFailure): + dns.dnssec.validate_rrsig(com_txt, com_txt_rrsig[0], wildcard_keys, + None, wildcard_when) + + def testAlternateParameterFormats(self): # type: () -> None + # Pass rrset and rrsigset as (name, rdataset) tuples, not rrsets + rrset = (abs_soa.name, abs_soa.to_rdataset()) + rrsigset = (abs_soa_rrsig.name, abs_soa_rrsig.to_rdataset()) + dns.dnssec.validate(rrset, rrsigset, abs_keys, None, when) + + # Pass keys as a name->node dict, not a name->rrset dict + keys = {} + for (name, key_rrset) in abs_keys.items(): + keys[name] = dns.node.Node() + keys[name].rdatasets.append(key_rrset.to_rdataset()) + dns.dnssec.validate(abs_soa, abs_soa_rrsig, keys, None, when) + # test key not found. + keys = {} + for (name, key_rrset) in abs_keys.items(): + keys[name] = dns.node.Node() + with self.assertRaises(dns.dnssec.ValidationFailure): + dns.dnssec.validate(abs_soa, abs_soa_rrsig, keys, None, when) + + # Pass origin as a string, not a name. + dns.dnssec.validate(rel_soa, rel_soa_rrsig, rel_keys, + 'dnspython.org', when) + dns.dnssec.validate_rrsig(rel_soa, rel_soa_rrsig[0], rel_keys, + 'dnspython.org', when) + + def testAbsoluteKeyNotFound(self): + with self.assertRaises(dns.dnssec.ValidationFailure): + dns.dnssec.validate(abs_ed448_mx, abs_ed448_mx_rrsig_1, {}, None, + when5) + + def testTimeBounds(self): + # not yet valid + with self.assertRaises(dns.dnssec.ValidationFailure): + dns.dnssec.validate(abs_ed448_mx, abs_ed448_mx_rrsig_1, + abs_ed448_keys_1, None, when5_start - 1) + # expired + with self.assertRaises(dns.dnssec.ValidationFailure): + dns.dnssec.validate(abs_ed448_mx, abs_ed448_mx_rrsig_1, + abs_ed448_keys_1, None, when5 + 1) + # expired using the current time (to test the "get the time" code + # path) + with self.assertRaises(dns.dnssec.ValidationFailure): + dns.dnssec.validate(abs_ed448_mx, abs_ed448_mx_rrsig_1, + abs_ed448_keys_1, None) + + def testOwnerNameMismatch(self): + bogus = dns.name.from_text('example.bogus') + with self.assertRaises(dns.dnssec.ValidationFailure): + dns.dnssec.validate((bogus, abs_ed448_mx), abs_ed448_mx_rrsig_1, + abs_ed448_keys_1, None, when5 + 1) + + def testGOSTNotSupported(self): + with self.assertRaises(dns.dnssec.ValidationFailure): + dns.dnssec.validate(rsasha512_ns, fake_gost_ns_rrsig, + fake_gost_keys, None, rsasha512_when) + + def testUnknownAlgorithm(self): + with self.assertRaises(dns.dnssec.ValidationFailure): + dns.dnssec.validate(rsasha512_ns, unknown_alg_ns_rrsig, + unknown_alg_keys, None, rsasha512_when) + + +class DNSSECMiscTestCase(unittest.TestCase): + def testDigestToBig(self): + with self.assertRaises(ValueError): + dns.dnssec.DSDigest.make(256) + + def testNSEC3HashTooBig(self): + with self.assertRaises(ValueError): + dns.dnssec.NSEC3Hash.make(256) + + def testIsNotGOST(self): + self.assertTrue(dns.dnssec._is_gost(dns.dnssec.Algorithm.ECCGOST)) + + def testUnknownHash(self): + with self.assertRaises(dns.dnssec.ValidationFailure): + dns.dnssec._make_hash(100) + + +class DNSSECMakeDSTestCase(unittest.TestCase): + + def testMnemonicParser(self): + good_ds_mnemonic = dns.rdata.from_text(dns.rdataclass.IN, + dns.rdatatype.DS, + '57349 RSASHA1 2 53A79A3E7488AB44FFC56B2D1109F0699D1796DD977E72108B841F96 E47D7013') + self.assertEqual(good_ds, good_ds_mnemonic) + + def testMakeExampleSHA1DS(self): # type: () -> None + for algorithm in ('SHA1', 'sha1', dns.dnssec.DSDigest.SHA1): + ds = dns.dnssec.make_ds(abs_example, example_sep_key, algorithm) + self.assertEqual(ds, example_ds_sha1) + ds = dns.dnssec.make_ds('example.', example_sep_key, algorithm) + self.assertEqual(ds, example_ds_sha1) + + def testMakeExampleSHA256DS(self): # type: () -> None + for algorithm in ('SHA256', 'sha256', dns.dnssec.DSDigest.SHA256): + ds = dns.dnssec.make_ds(abs_example, example_sep_key, algorithm) + self.assertEqual(ds, example_ds_sha256) + + def testMakeExampleSHA384DS(self): # type: () -> None + for algorithm in ('SHA384', 'sha384', dns.dnssec.DSDigest.SHA384): + ds = dns.dnssec.make_ds(abs_example, example_sep_key, algorithm) + self.assertEqual(ds, example_ds_sha384) + + def testMakeSHA256DS(self): # type: () -> None + ds = dns.dnssec.make_ds(abs_dnspython_org, sep_key, 'SHA256') + self.assertEqual(ds, good_ds) + + def testInvalidAlgorithm(self): # type: () -> None + for algorithm in (10, 'shax'): + with self.assertRaises(dns.dnssec.UnsupportedAlgorithm): + ds = dns.dnssec.make_ds(abs_example, example_sep_key, algorithm) + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_doh.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_doh.py new file mode 100644 index 0000000..793a500 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_doh.py @@ -0,0 +1,150 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +import unittest +import random +import socket + +import dns.message +import dns.query +import dns.rdatatype +import dns.resolver + +if dns.query.have_doh: + import requests + from requests.exceptions import SSLError + +# Probe for IPv4 and IPv6 +resolver_v4_addresses = [] +resolver_v6_addresses = [] +try: + with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: + s.settimeout(4) + s.connect(('8.8.8.8', 53)) + resolver_v4_addresses = [ + '1.1.1.1', + '8.8.8.8', + # '9.9.9.9', + ] +except Exception: + pass +try: + with socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) as s: + s.connect(('2001:4860:4860::8888', 53)) + resolver_v6_addresses = [ + '2606:4700:4700::1111', + # Google says 404 + # '2001:4860:4860::8888', + # '2620:fe::fe', + ] +except Exception: + pass + +KNOWN_ANYCAST_DOH_RESOLVER_URLS = ['https://cloudflare-dns.com/dns-query', + 'https://dns.google/dns-query', + # 'https://dns11.quad9.net/dns-query', + ] + +# Some tests require the internet to be available to run, so let's +# skip those if it's not there. +_network_available = True +try: + socket.gethostbyname('dnspython.org') +except socket.gaierror: + _network_available = False + +@unittest.skipUnless(dns.query.have_doh and _network_available, + "Python requests cannot be imported; no DNS over HTTPS (DOH)") +class DNSOverHTTPSTestCase(unittest.TestCase): + def setUp(self): + self.session = requests.sessions.Session() + + def tearDown(self): + self.session.close() + + def test_get_request(self): + nameserver_url = random.choice(KNOWN_ANYCAST_DOH_RESOLVER_URLS) + q = dns.message.make_query('example.com.', dns.rdatatype.A) + r = dns.query.https(q, nameserver_url, session=self.session, post=False, + timeout=4) + self.assertTrue(q.is_response(r)) + + def test_post_request(self): + nameserver_url = random.choice(KNOWN_ANYCAST_DOH_RESOLVER_URLS) + q = dns.message.make_query('example.com.', dns.rdatatype.A) + r = dns.query.https(q, nameserver_url, session=self.session, post=True, + timeout=4) + self.assertTrue(q.is_response(r)) + + def test_build_url_from_ip(self): + self.assertTrue(resolver_v4_addresses or resolver_v6_addresses) + if resolver_v4_addresses: + nameserver_ip = random.choice(resolver_v4_addresses) + q = dns.message.make_query('example.com.', dns.rdatatype.A) + # For some reason Google's DNS over HTTPS fails when you POST to + # https://8.8.8.8/dns-query + # So we're just going to do GET requests here + r = dns.query.https(q, nameserver_ip, session=self.session, + post=False, timeout=4) + + self.assertTrue(q.is_response(r)) + if resolver_v6_addresses: + nameserver_ip = random.choice(resolver_v6_addresses) + q = dns.message.make_query('example.com.', dns.rdatatype.A) + r = dns.query.https(q, nameserver_ip, session=self.session, + post=False, timeout=4) + self.assertTrue(q.is_response(r)) + + def test_bootstrap_address(self): + # We test this to see if v4 is available + if resolver_v4_addresses: + ip = '185.228.168.168' + invalid_tls_url = 'https://{}/doh/family-filter/'.format(ip) + valid_tls_url = 'https://doh.cleanbrowsing.org/doh/family-filter/' + q = dns.message.make_query('example.com.', dns.rdatatype.A) + # make sure CleanBrowsing's IP address will fail TLS certificate + # check + with self.assertRaises(SSLError): + dns.query.https(q, invalid_tls_url, session=self.session, + timeout=4) + # use host header + r = dns.query.https(q, valid_tls_url, session=self.session, + bootstrap_address=ip, timeout=4) + self.assertTrue(q.is_response(r)) + + def test_new_session(self): + nameserver_url = random.choice(KNOWN_ANYCAST_DOH_RESOLVER_URLS) + q = dns.message.make_query('example.com.', dns.rdatatype.A) + r = dns.query.https(q, nameserver_url, timeout=4) + self.assertTrue(q.is_response(r)) + + def test_resolver(self): + res = dns.resolver.Resolver(configure=False) + res.nameservers = ['https://dns.google/dns-query'] + answer = res.resolve('dns.google', 'A') + seen = set([rdata.address for rdata in answer]) + self.assertTrue('8.8.8.8' in seen) + self.assertTrue('8.8.4.4' in seen) + + def test_resolver_bad_scheme(self): + res = dns.resolver.Resolver(configure=False) + res.nameservers = ['bogus://dns.google/dns-query'] + def bad(): + answer = res.resolve('dns.google', 'A') + self.assertRaises(dns.resolver.NoNameservers, bad) + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_edns.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_edns.py new file mode 100644 index 0000000..6ba0c99 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_edns.py @@ -0,0 +1,198 @@ +# -*- coding: utf-8 +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import operator +import struct +import unittest + +from io import BytesIO + +import dns.edns +import dns.wire + +class OptionTestCase(unittest.TestCase): + def testGenericOption(self): + opt = dns.edns.GenericOption(3, b'data') + io = BytesIO() + opt.to_wire(io) + data = io.getvalue() + self.assertEqual(data, b'data') + self.assertEqual(dns.edns.option_from_wire(3, data, 0, len(data)), opt) + self.assertEqual(str(opt), 'Generic 3') + + def testECSOption_prefix_length(self): + opt = dns.edns.ECSOption('1.2.255.33', 20) + io = BytesIO() + opt.to_wire(io) + data = io.getvalue() + self.assertEqual(data, b'\x00\x01\x14\x00\x01\x02\xf0') + + def testECSOption(self): + opt = dns.edns.ECSOption('1.2.3.4', 24) + io = BytesIO() + opt.to_wire(io) + data = io.getvalue() + self.assertEqual(data, b'\x00\x01\x18\x00\x01\x02\x03') + # default srclen + opt = dns.edns.ECSOption('1.2.3.4') + io = BytesIO() + opt.to_wire(io) + data = io.getvalue() + self.assertEqual(data, b'\x00\x01\x18\x00\x01\x02\x03') + self.assertEqual(opt.to_text(), 'ECS 1.2.3.4/24 scope/0') + + def testECSOption25(self): + opt = dns.edns.ECSOption('1.2.3.255', 25) + io = BytesIO() + opt.to_wire(io) + data = io.getvalue() + self.assertEqual(data, b'\x00\x01\x19\x00\x01\x02\x03\x80') + + opt2 = dns.edns.option_from_wire(dns.edns.ECS, data, 0, len(data)) + self.assertEqual(opt2.otype, dns.edns.ECS) + self.assertEqual(opt2.address, '1.2.3.128') + self.assertEqual(opt2.srclen, 25) + self.assertEqual(opt2.scopelen, 0) + + def testECSOption_v6(self): + opt = dns.edns.ECSOption('2001:4b98::1') + io = BytesIO() + opt.to_wire(io) + data = io.getvalue() + self.assertEqual(data, b'\x00\x02\x38\x00\x20\x01\x4b\x98\x00\x00\x00') + + opt2 = dns.edns.option_from_wire(dns.edns.ECS, data, 0, len(data)) + self.assertEqual(opt2.otype, dns.edns.ECS) + self.assertEqual(opt2.address, '2001:4b98::') + self.assertEqual(opt2.srclen, 56) + self.assertEqual(opt2.scopelen, 0) + + def testECSOption_from_text_valid(self): + ecs1 = dns.edns.ECSOption.from_text('1.2.3.4/24/0') + self.assertEqual(ecs1, dns.edns.ECSOption('1.2.3.4', 24, 0)) + + ecs2 = dns.edns.ECSOption.from_text('1.2.3.4/24') + self.assertEqual(ecs2, dns.edns.ECSOption('1.2.3.4', 24, 0)) + + ecs3 = dns.edns.ECSOption.from_text('ECS 1.2.3.4/24') + self.assertEqual(ecs3, dns.edns.ECSOption('1.2.3.4', 24, 0)) + + ecs4 = dns.edns.ECSOption.from_text('ECS 1.2.3.4/24/32') + self.assertEqual(ecs4, dns.edns.ECSOption('1.2.3.4', 24, 32)) + + ecs5 = dns.edns.ECSOption.from_text('2001:4b98::1/64/56') + self.assertEqual(ecs5, dns.edns.ECSOption('2001:4b98::1', 64, 56)) + + ecs6 = dns.edns.ECSOption.from_text('2001:4b98::1/64') + self.assertEqual(ecs6, dns.edns.ECSOption('2001:4b98::1', 64, 0)) + + ecs7 = dns.edns.ECSOption.from_text('ECS 2001:4b98::1/0') + self.assertEqual(ecs7, dns.edns.ECSOption('2001:4b98::1', 0, 0)) + + ecs8 = dns.edns.ECSOption.from_text('ECS 2001:4b98::1/64/128') + self.assertEqual(ecs8, dns.edns.ECSOption('2001:4b98::1', 64, 128)) + + def testECSOption_from_text_invalid(self): + with self.assertRaises(ValueError): + dns.edns.ECSOption.from_text('some random text 1.2.3.4/24/0 24') + + with self.assertRaises(ValueError): + dns.edns.ECSOption.from_text('1.2.3.4/twentyfour') + + with self.assertRaises(ValueError): + dns.edns.ECSOption.from_text('BOGUS 1.2.3.4/5/6/7') + + with self.assertRaises(ValueError): + dns.edns.ECSOption.from_text('1.2.3.4/5/6/7') + + with self.assertRaises(ValueError): + dns.edns.ECSOption.from_text('1.2.3.4/24/O') # <-- that's not a zero + + with self.assertRaises(ValueError): + dns.edns.ECSOption.from_text('') + + with self.assertRaises(ValueError): + dns.edns.ECSOption.from_text('1.2.3.4/2001:4b98::1/24') + + def testECSOption_from_wire_invalid(self): + with self.assertRaises(ValueError): + opt = dns.edns.option_from_wire(dns.edns.ECS, + b'\x00\xff\x18\x00\x01\x02\x03', + 0, 7) + + def test_basic_relations(self): + o1 = dns.edns.ECSOption.from_text('1.2.3.0/24/0') + o2 = dns.edns.ECSOption.from_text('1.2.4.0/24/0') + self.assertTrue(o1 == o1) + self.assertTrue(o1 != o2) + self.assertTrue(o1 < o2) + self.assertTrue(o1 <= o2) + self.assertTrue(o2 > o1) + self.assertTrue(o2 >= o1) + o1 = dns.edns.ECSOption.from_text('1.2.4.0/23/0') + o2 = dns.edns.ECSOption.from_text('1.2.4.0/24/0') + self.assertTrue(o1 < o2) + o1 = dns.edns.ECSOption.from_text('1.2.4.0/24/0') + o2 = dns.edns.ECSOption.from_text('1.2.4.0/24/1') + self.assertTrue(o1 < o2) + + def test_incompatible_relations(self): + o1 = dns.edns.GenericOption(3, b'data') + o2 = dns.edns.ECSOption.from_text('1.2.3.5/24/0') + for oper in [operator.lt, operator.le, operator.ge, operator.gt]: + self.assertRaises(TypeError, lambda: oper(o1, o2)) + self.assertFalse(o1 == o2) + self.assertTrue(o1 != o2) + self.assertFalse(o1 == 123) + self.assertTrue(o1 != 123) + + def test_option_registration(self): + U32OptionType = 9999 + + class U32Option(dns.edns.Option): + def __init__(self, value=None): + super().__init__(U32OptionType) + self.value = value + + def to_wire(self, file=None): + data = struct.pack('!I', self.value) + if file: + file.write(data) + else: + return data + + @classmethod + def from_wire_parser(cls, otype, parser): + (value,) = parser.get_struct('!I') + return cls(value) + + try: + dns.edns.register_type(U32Option, U32OptionType) + generic = dns.edns.GenericOption(U32OptionType, b'\x00\x00\x00\x01') + wire1 = generic.to_wire() + u32 = dns.edns.option_from_wire_parser(U32OptionType, + dns.wire.Parser(wire1)) + self.assertEqual(u32.value, 1) + wire2 = u32.to_wire() + self.assertEqual(wire1, wire2) + self.assertEqual(u32, generic) + finally: + dns.edns._type_to_class.pop(U32OptionType, None) + + opt = dns.edns.option_from_wire_parser(9999, dns.wire.Parser(wire1)) + self.assertEqual(opt, generic) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_entropy.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_entropy.py new file mode 100644 index 0000000..74092e7 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_entropy.py @@ -0,0 +1,57 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import unittest + +import dns.entropy + +# these tests are mostly for minimal coverage testing + +class EntropyTestCase(unittest.TestCase): + def test_pool(self): + pool = dns.entropy.EntropyPool(b'seed-value') + self.assertEqual(pool.random_8(), 94) + self.assertEqual(pool.random_16(), 61532) + self.assertEqual(pool.random_32(), 4226376065) + self.assertEqual(pool.random_between(10, 50), 29) + # stir in some not-really-entropy to exercise the stir API + pool.stir(b'not-really-entropy') + + def test_pool_random(self): + pool = dns.entropy.EntropyPool() + values = {pool.random_32() for n in range(12)} + # Make sure that the results are at least somewhat random. + self.assertGreater(len(values), 8) + + def test_pool_random_between(self): + pool = dns.entropy.EntropyPool() + def bad(): + pool.random_between(0, 4294967296) + self.assertRaises(ValueError, bad) + v = pool.random_between(50, 50 + 100000) + self.assertTrue(v >= 50 and v <= 50 + 100000) + v = pool.random_between(50, 50 + 10000) + self.assertTrue(v >= 50 and v <= 50 + 10000) + v = pool.random_between(50, 50 + 100) + self.assertTrue(v >= 50 and v <= 50 + 100) + + def test_functions(self): + v = dns.entropy.random_16() + self.assertTrue(0 <= v <= 65535) + v = dns.entropy.between(10, 50) + self.assertTrue(10 <= v <= 50) + + +class EntropyForcePoolTestCase(unittest.TestCase): + + def setUp(self): + self.saved_system_random = dns.entropy.system_random + dns.entropy.system_random = None + + def tearDown(self): + dns.entropy.system_random = self.saved_system_random + + def test_functions(self): + v = dns.entropy.random_16() + self.assertTrue(0 <= v <= 65535) + v = dns.entropy.between(10, 50) + self.assertTrue(10 <= v <= 50) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_exceptions.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_exceptions.py new file mode 100644 index 0000000..caaf88a --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_exceptions.py @@ -0,0 +1,63 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import unittest + +from dns.exception import DNSException + + +class FormatedError(DNSException): + fmt = "Custom format: {parameter}" + supp_kwargs = {'parameter'} + + +class ExceptionTestCase(unittest.TestCase): + + def test_custom_message(self): + msg = "this is a custom message" + try: + raise DNSException(msg) + except DNSException as ex: + self.assertEqual(str(ex), msg) + + def test_implicit_message(self): + try: + raise DNSException() + except DNSException as ex: + self.assertEqual(ex.__class__.__doc__, str(ex)) + + def test_formatted_error(self): + """Exceptions with explicit format has to respect it.""" + params = {'parameter': 'value'} + try: + raise FormatedError(**params) + except FormatedError as ex: + msg = FormatedError.fmt.format(**params) + self.assertEqual(msg, str(ex)) + + def test_kwargs_only(self): + """Kwargs cannot be combined with args.""" + with self.assertRaises(AssertionError): + raise FormatedError(1, a=2) + + def test_kwargs_unsupported(self): + """Only supported kwargs are accepted.""" + with self.assertRaises(AssertionError): + raise FormatedError(unsupported=2) + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_flags.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_flags.py new file mode 100644 index 0000000..3f5fc69 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_flags.py @@ -0,0 +1,81 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import unittest + +import dns.flags +import dns.rcode +import dns.opcode + +class FlagsTestCase(unittest.TestCase): + + def test_rcode1(self): + self.assertEqual(dns.rcode.from_text('FORMERR'), dns.rcode.FORMERR) + + def test_rcode2(self): + self.assertEqual(dns.rcode.to_text(dns.rcode.FORMERR), "FORMERR") + + def test_rcode3(self): + self.assertEqual(dns.rcode.to_flags(dns.rcode.FORMERR), (1, 0)) + + def test_rcode4(self): + self.assertEqual(dns.rcode.to_flags(dns.rcode.BADVERS), + (0, 0x01000000)) + + def test_rcode6(self): + self.assertEqual(dns.rcode.from_flags(0, 0x01000000), + dns.rcode.BADVERS) + + def test_rcode7(self): + self.assertEqual(dns.rcode.from_flags(5, 0), dns.rcode.REFUSED) + + def test_rcode8(self): + def bad(): + dns.rcode.to_flags(4096) + self.assertRaises(ValueError, bad) + + def test_flags1(self): + self.assertEqual(dns.flags.from_text("RA RD AA QR"), + dns.flags.QR|dns.flags.AA|dns.flags.RD|dns.flags.RA) + + def test_flags2(self): + flags = dns.flags.QR|dns.flags.AA|dns.flags.RD|dns.flags.RA + self.assertEqual(dns.flags.to_text(flags), "QR AA RD RA") + + def test_rcode_badvers(self): + rcode = dns.rcode.BADVERS + self.assertEqual(rcode.value, 16) + self.assertEqual(rcode.name, 'BADVERS') + self.assertEqual(dns.rcode.to_text(rcode), 'BADVERS') + + def test_rcode_badsig(self): + rcode = dns.rcode.BADSIG + self.assertEqual(rcode.value, 16) + # Yes, we mean BADVERS on the next line. BADSIG and BADVERS have + # the same code. + self.assertEqual(rcode.name, 'BADVERS') + self.assertEqual(dns.rcode.to_text(rcode), 'BADVERS') + # In TSIG text mode, it should be BADSIG + self.assertEqual(dns.rcode.to_text(rcode, True), 'BADSIG') + + def test_unknown_rcode(self): + with self.assertRaises(dns.rcode.UnknownRcode): + dns.rcode.Rcode.make('BOGUS') + + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_generate.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_generate.py new file mode 100644 index 0000000..3f7c925 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_generate.py @@ -0,0 +1,593 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import sys +sys.path.insert(0, '../') # Force the local project to be *the* dns + +import unittest + +import dns.exception +import dns.rdata +import dns.rdataclass +import dns.rdatatype +import dns.rrset +import dns.zone + + +example_text = """$TTL 1h +$ORIGIN 0.0.192.IN-ADDR.ARPA. +$GENERATE 1-2 0 CNAME SERVER$.EXAMPLE. +""" + +example_text1 = """$TTL 1h +$ORIGIN 0.0.192.IN-ADDR.ARPA. +$GENERATE 1-10 fooo$ CNAME $.0 +""" + +example_text2 = """$TTL 1h +@ 3600 IN SOA foo bar 1 2 3 4 5 +@ 3600 IN NS ns1 +@ 3600 IN NS ns2 +bar.foo 300 IN MX 0 blaz.foo +ns1 3600 IN A 10.0.0.1 +ns2 3600 IN A 10.0.0.2 +$GENERATE 3-5 foo$ A 10.0.0.$ +""" + +example_text3 = """$TTL 1h +@ 3600 IN SOA foo bar 1 2 3 4 5 +@ 3600 IN NS ns1 +@ 3600 IN NS ns2 +bar.foo 300 IN MX 0 blaz.foo +ns1 3600 IN A 10.0.0.1 +ns2 3600 IN A 10.0.0.2 +$GENERATE 4-8/2 foo$ A 10.0.0.$ +""" + +example_text4 = """$TTL 1h +@ 3600 IN SOA foo bar 1 2 3 4 5 +@ 3600 IN NS ns1 +@ 3600 IN NS ns2 +bar.foo 300 IN MX 0 blaz.foo +ns1 3600 IN A 10.0.0.1 +ns2 3600 IN A 10.0.0.2 +$GENERATE 11-13 wp-db${-10,2,d}.services.mozilla.com 0 CNAME SERVER.FOOBAR. +""" + +example_text5 = """$TTL 1h +@ 3600 IN SOA foo bar 1 2 3 4 5 +@ 3600 IN NS ns1 +@ 3600 IN NS ns2 +bar.foo 300 IN MX 0 blaz.foo +ns1 3600 IN A 10.0.0.1 +ns2 3600 IN A 10.0.0.2 +$GENERATE 11-13 wp-db${10,2,d}.services.mozilla.com 0 CNAME SERVER.FOOBAR. +""" + +example_text6 = """$TTL 1h +@ 3600 IN SOA foo bar 1 2 3 4 5 +@ 3600 IN NS ns1 +@ 3600 IN NS ns2 +bar.foo 300 IN MX 0 blaz.foo +ns1 3600 IN A 10.0.0.1 +ns2 3600 IN A 10.0.0.2 +$GENERATE 11-13 wp-db${+10,2,d}.services.mozilla.com 0 CNAME SERVER.FOOBAR. +""" + +example_text7 = """$TTL 1h +@ 3600 IN SOA foo bar 1 2 3 4 5 +@ 3600 IN NS ns1 +@ 3600 IN NS ns2 +bar.foo 300 IN MX 0 blaz.foo +ns1 3600 IN A 10.0.0.1 +ns2 3600 IN A 10.0.0.2 +$GENERATE 11-13 sync${-10}.db IN A 10.10.16.0 +""" + +example_text8 = """$TTL 1h +@ 3600 IN SOA foo bar 1 2 3 4 5 +@ 3600 IN NS ns1 +@ 3600 IN NS ns2 +bar.foo 300 IN MX 0 blaz.foo +ns1 3600 IN A 10.0.0.1 +ns2 3600 IN A 10.0.0.2 +$GENERATE 11-12 wp-db${-10,2,d} IN A 10.10.16.0 +""" + +example_text9 = """$TTL 1h +@ 3600 IN SOA foo bar 1 2 3 4 5 +@ 3600 IN NS ns1 +@ 3600 IN NS ns2 +bar.foo 300 IN MX 0 blaz.foo +ns1 3600 IN A 10.0.0.1 +ns2 3600 IN A 10.0.0.2 +$GENERATE 11-12 wp-db${-10,2,d} IN A 10.10.16.0 +$GENERATE 11-13 sync${-10}.db IN A 10.10.16.0 +""" +example_text10 = """$TTL 1h +@ 3600 IN SOA foo bar 1 2 3 4 5 +@ 3600 IN NS ns1 +@ 3600 IN NS ns2 +bar.foo 300 IN MX 0 blaz.foo +ns1 3600 IN A 10.0.0.1 +ns2 3600 IN A 10.0.0.2 +$GENERATE 27-28 $.2 PTR zlb${-26}.oob +""" + +example_text11 = """$TTL 1h +@ 3600 IN SOA foo bar 1 2 3 4 5 +@ 3600 IN NS ns1 +@ 3600 IN NS ns2 +bar.foo 300 IN MX 0 blaz.foo +ns1 3600 IN A 10.0.0.1 +ns2 3600 IN A 10.0.0.2 +$GENERATE 27-28 prefix-${0,3} A 10.0.0.$ +""" + +last_ttl_input = """foo 300 mx 10 target. +$GENERATE 1-10 foo$ CNAME $.0 +@ 3600 IN SOA foo bar 1 2 3 4 5 +@ 3600 IN NS ns1 +@ 3600 IN NS ns2 +""" + +def _rdata_sort(a): + return (a[0], a[2].rdclass, a[2].to_text()) + + +class GenerateTestCase(unittest.TestCase): + + def testFromText(self): # type: () -> None + def bad(): # type: () -> None + dns.zone.from_text(example_text, 'example.', relativize=True) + self.assertRaises(dns.zone.NoSOA, bad) + + def testFromText1(self): # type: () -> None + def bad(): # type: () -> None + dns.zone.from_text(example_text1, 'example.', relativize=True) + self.assertRaises(dns.zone.NoSOA, bad) + + def testIterateAllRdatas2(self): # type: () -> None + z = dns.zone.from_text(example_text2, 'example.', relativize=True) + l = list(z.iterate_rdatas()) + l.sort(key=_rdata_sort) + exl = [(dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + 'ns1')), + (dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + 'ns2')), + (dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, + 'foo bar 1 2 3 4 5')), + (dns.name.from_text('bar.foo', None), + 300, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, + '0 blaz.foo')), + (dns.name.from_text('ns1', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1')), + (dns.name.from_text('ns2', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.2')), + (dns.name.from_text('foo3', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.3')), + (dns.name.from_text('foo4', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.4')), + (dns.name.from_text('foo5', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.5'))] + + exl.sort(key=_rdata_sort) + self.assertEqual(l, exl) + + def testIterateAllRdatas3(self): # type: () -> None + z = dns.zone.from_text(example_text3, 'example.', relativize=True) + l = list(z.iterate_rdatas()) + l.sort(key=_rdata_sort) + exl = [(dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + 'ns1')), + (dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + 'ns2')), + (dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, + 'foo bar 1 2 3 4 5')), + (dns.name.from_text('bar.foo', None), + 300, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, + '0 blaz.foo')), + (dns.name.from_text('ns1', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1')), + (dns.name.from_text('ns2', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.2')), + (dns.name.from_text('foo4', None), 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.4')), + (dns.name.from_text('foo6', None), 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.6')), + (dns.name.from_text('foo8', None), 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.8'))] + exl.sort(key=_rdata_sort) + self.assertEqual(l, exl) + def testGenerate1(self): # type: () -> None + z = dns.zone.from_text(example_text4, 'example.', relativize=True) + l = list(z.iterate_rdatas()) + l.sort(key=_rdata_sort) + exl = [(dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + 'ns1')), + (dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + 'ns2')), + (dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, + 'foo bar 1 2 3 4 5')), + (dns.name.from_text('bar.foo', None), + 300, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, + '0 blaz.foo')), + (dns.name.from_text('ns1', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1')), + (dns.name.from_text('ns2', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.2')), + + (dns.name.from_text('wp-db01.services.mozilla.com', None), + 0, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, + 'SERVER.FOOBAR.')), + + (dns.name.from_text('wp-db02.services.mozilla.com', None), + 0, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, + 'SERVER.FOOBAR.')), + + (dns.name.from_text('wp-db03.services.mozilla.com', None), + 0, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, + 'SERVER.FOOBAR.'))] + exl.sort(key=_rdata_sort) + self.assertEqual(l, exl) + + def testGenerate2(self): # type: () -> None + z = dns.zone.from_text(example_text5, 'example.', relativize=True) + l = list(z.iterate_rdatas()) + l.sort(key=_rdata_sort) + exl = [(dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + 'ns1')), + (dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + 'ns2')), + (dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, + 'foo bar 1 2 3 4 5')), + (dns.name.from_text('bar.foo', None), + 300, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, + '0 blaz.foo')), + (dns.name.from_text('ns1', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1')), + (dns.name.from_text('ns2', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.2')), + + (dns.name.from_text('wp-db21.services.mozilla.com', None), 0, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, + 'SERVER.FOOBAR.')), + + (dns.name.from_text('wp-db22.services.mozilla.com', None), 0, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, + 'SERVER.FOOBAR.')), + + (dns.name.from_text('wp-db23.services.mozilla.com', None), 0, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, + 'SERVER.FOOBAR.'))] + exl.sort(key=_rdata_sort) + self.assertEqual(l, exl) + + def testGenerate3(self): # type: () -> None + z = dns.zone.from_text(example_text6, 'example.', relativize=True) + l = list(z.iterate_rdatas()) + l.sort(key=_rdata_sort) + + exl = [(dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + 'ns1')), + (dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + 'ns2')), + (dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, + 'foo bar 1 2 3 4 5')), + (dns.name.from_text('bar.foo', None), + 300, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, + '0 blaz.foo')), + (dns.name.from_text('ns1', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1')), + (dns.name.from_text('ns2', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.2')), + (dns.name.from_text('wp-db21.services.mozilla.com', None), 0, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, + 'SERVER.FOOBAR.')), + + (dns.name.from_text('wp-db22.services.mozilla.com', None), 0, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, + 'SERVER.FOOBAR.')), + + (dns.name.from_text('wp-db23.services.mozilla.com', None), 0, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, + 'SERVER.FOOBAR.'))] + exl.sort(key=_rdata_sort) + self.assertEqual(l, exl) + + def testGenerate4(self): # type: () -> None + z = dns.zone.from_text(example_text7, 'example.', relativize=True) + l = list(z.iterate_rdatas()) + l.sort(key=_rdata_sort) + exl = [(dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + 'ns1')), + (dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + 'ns2')), + (dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, + 'foo bar 1 2 3 4 5')), + (dns.name.from_text('bar.foo', None), + 300, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, + '0 blaz.foo')), + (dns.name.from_text('ns1', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1')), + (dns.name.from_text('ns2', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.2')), + + (dns.name.from_text('sync1.db', None), 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.10.16.0')), + + (dns.name.from_text('sync2.db', None), 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.10.16.0')), + + (dns.name.from_text('sync3.db', None), 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.10.16.0'))] + exl.sort(key=_rdata_sort) + self.assertEqual(l, exl) + + def testGenerate6(self): # type: () -> None + z = dns.zone.from_text(example_text9, 'example.', relativize=True) + l = list(z.iterate_rdatas()) + l.sort(key=_rdata_sort) + exl = [(dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + 'ns1')), + (dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + 'ns2')), + (dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, + 'foo bar 1 2 3 4 5')), + (dns.name.from_text('bar.foo', None), + 300, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, + '0 blaz.foo')), + (dns.name.from_text('ns1', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1')), + (dns.name.from_text('ns2', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.2')), + + (dns.name.from_text('wp-db01', None), 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.10.16.0')), + (dns.name.from_text('wp-db02', None), 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.10.16.0')), + + (dns.name.from_text('sync1.db', None), 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.10.16.0')), + + (dns.name.from_text('sync2.db', None), 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.10.16.0')), + + (dns.name.from_text('sync3.db', None), 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.10.16.0'))] + exl.sort(key=_rdata_sort) + self.assertEqual(l, exl) + + def testGenerate7(self): # type: () -> None + z = dns.zone.from_text(example_text10, 'example.', relativize=True) + l = list(z.iterate_rdatas()) + l.sort(key=_rdata_sort) + exl = [(dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + 'ns1')), + (dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + 'ns2')), + (dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, + 'foo bar 1 2 3 4 5')), + (dns.name.from_text('bar.foo', None), + 300, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, + '0 blaz.foo')), + (dns.name.from_text('ns1', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1')), + (dns.name.from_text('ns2', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.2')), + + (dns.name.from_text('27.2', None), 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.PTR, + 'zlb1.oob')), + + (dns.name.from_text('28.2', None), 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.PTR, + 'zlb2.oob'))] + + exl.sort(key=_rdata_sort) + self.assertEqual(l, exl) + + def testGenerate8(self): # type: () -> None + z = dns.zone.from_text(example_text11, 'example.', relativize=True) + l = list(z.iterate_rdatas()) + l.sort(key=_rdata_sort) + exl = [(dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + 'ns1')), + (dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + 'ns2')), + (dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, + 'foo bar 1 2 3 4 5')), + (dns.name.from_text('bar.foo', None), + 300, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, + '0 blaz.foo')), + + (dns.name.from_text('prefix-027', None), 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.27')), + + (dns.name.from_text('prefix-028', None), 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.28')), + + (dns.name.from_text('ns1', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1')), + (dns.name.from_text('ns2', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.2'))] + + exl.sort(key=_rdata_sort) + self.assertEqual(l, exl) + + def testNoOrigin(self): + def bad(): + dns.zone.from_text('$GENERATE 1-10 fooo$ CNAME $.0') + self.assertRaises(dns.zone.UnknownOrigin, bad) + + def testBadRdata(self): + def bad(): + dns.zone.from_text('$GENERATE 1-10 fooo$ CNAME 10 $.0', 'example') + self.assertRaises(dns.exception.SyntaxError, bad) + + def testUsesLastTTL(self): + z = dns.zone.from_text(last_ttl_input, 'example') + rrs = z.find_rrset('foo9', 'CNAME') + self.assertEqual(rrs.ttl, 300) + + def testClassMismatch(self): + def bad(): + dns.zone.from_text('$GENERATE 1-10 fooo$ CH CNAME $.0', 'example') + self.assertRaises(dns.exception.SyntaxError, bad) + + def testUnknownRdatatype(self): + def bad(): + dns.zone.from_text('$GENERATE 1-10 fooo$ BOGUSTYPE $.0', 'example') + self.assertRaises(dns.exception.SyntaxError, bad) + + def testBadAndDangling(self): + def bad1(): + dns.zone.from_text('$GENERATE bogus fooo$ CNAME $.0', + 'example.') + self.assertRaises(dns.exception.SyntaxError, bad1) + def bad2(): + dns.zone.from_text('$GENERATE 1-10', + 'example.') + self.assertRaises(dns.exception.SyntaxError, bad2) + def bad3(): + dns.zone.from_text('$GENERATE 1-10 foo$', + 'example.') + self.assertRaises(dns.exception.SyntaxError, bad3) + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_grange.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_grange.py new file mode 100644 index 0000000..9b5ddd2 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_grange.py @@ -0,0 +1,93 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import sys +sys.path.insert(0, '../') + +import unittest + +import dns +import dns.exception +import dns.grange + + +class GRangeTestCase(unittest.TestCase): + + def testFromText1(self): + start, stop, step = dns.grange.from_text('1-1') + self.assertEqual(start, 1) + self.assertEqual(stop, 1) + self.assertEqual(step, 1) + + def testFromText2(self): + start, stop, step = dns.grange.from_text('1-4') + self.assertEqual(start, 1) + self.assertEqual(stop, 4) + self.assertEqual(step, 1) + + def testFromText3(self): + start, stop, step = dns.grange.from_text('4-255') + self.assertEqual(start, 4) + self.assertEqual(stop, 255) + self.assertEqual(step, 1) + + def testFromText4(self): + start, stop, step = dns.grange.from_text('1-1/1') + self.assertEqual(start, 1) + self.assertEqual(stop, 1) + self.assertEqual(step, 1) + + def testFromText5(self): + start, stop, step = dns.grange.from_text('1-4/2') + self.assertEqual(start, 1) + self.assertEqual(stop, 4) + self.assertEqual(step, 2) + + def testFromText6(self): + start, stop, step = dns.grange.from_text('4-255/77') + self.assertEqual(start, 4) + self.assertEqual(stop, 255) + self.assertEqual(step, 77) + + def testFailFromText1(self): + with self.assertRaises(dns.exception.SyntaxError): + start = 2 + stop = 1 + step = 1 + dns.grange.from_text('%d-%d/%d' % (start, stop, step)) + self.assertTrue(False) + + def testFailFromText2(self): + with self.assertRaises(dns.exception.SyntaxError): + start = '-1' + stop = 3 + step = 1 + dns.grange.from_text('%s-%d/%d' % (start, stop, step)) + + def testFailFromText3(self): + with self.assertRaises(dns.exception.SyntaxError): + start = 1 + stop = 4 + step = '-2' + dns.grange.from_text('%d-%d/%s' % (start, stop, step)) + + def testFailFromText4(self): + with self.assertRaises(dns.exception.SyntaxError): + dns.grange.from_text('1') + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_immutable.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_immutable.py new file mode 100644 index 0000000..1a70e3d --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_immutable.py @@ -0,0 +1,160 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import unittest + +import dns.immutable +import dns._immutable_attr + +try: + import dns._immutable_ctx as immutable_ctx + _have_contextvars = True +except ImportError: + _have_contextvars = False + + class immutable_ctx: + pass + + +class ImmutableTestCase(unittest.TestCase): + + def test_immutable_dict_hash(self): + d1 = dns.immutable.Dict({'a': 1, 'b': 2}) + d2 = dns.immutable.Dict({'b': 2, 'a': 1}) + d3 = {'b': 2, 'a': 1} + self.assertEqual(d1, d2) + self.assertEqual(d2, d3) + self.assertEqual(hash(d1), hash(d2)) + + def test_immutable_dict_hash_cache(self): + d = dns.immutable.Dict({'a': 1, 'b': 2}) + self.assertEqual(d._hash, None) + h1 = hash(d) + self.assertEqual(d._hash, h1) + h2 = hash(d) + self.assertEqual(h1, h2) + + def test_constify(self): + items = ( + (bytearray([1, 2, 3]), b'\x01\x02\x03'), + ((1, 2, 3), (1, 2, 3)), + ((1, [2], 3), (1, (2,), 3)), + ([1, 2, 3], (1, 2, 3)), + ([1, {'a': [1, 2]}], + (1, dns.immutable.Dict({'a': (1, 2)}))), + ('hi', 'hi'), + (b'hi', b'hi'), + ) + for input, expected in items: + self.assertEqual(dns.immutable.constify(input), expected) + self.assertIsInstance(dns.immutable.constify({'a': 1}), + dns.immutable.Dict) + + +class DecoratorTestCase(unittest.TestCase): + + immutable_module = dns._immutable_attr + + def make_classes(self): + class A: + def __init__(self, a, akw=10): + self.a = a + self.akw = akw + + class B(A): + def __init__(self, a, b): + super().__init__(a, akw=20) + self.b = b + B = self.immutable_module.immutable(B) + + # note C is immutable by inheritance + class C(B): + def __init__(self, a, b, c): + super().__init__(a, b) + self.c = c + C = self.immutable_module.immutable(C) + + class SA: + __slots__ = ('a', 'akw') + def __init__(self, a, akw=10): + self.a = a + self.akw = akw + + class SB(A): + __slots__ = ('b') + def __init__(self, a, b): + super().__init__(a, akw=20) + self.b = b + SB = self.immutable_module.immutable(SB) + + # note SC is immutable by inheritance and has no slots of its own + class SC(SB): + def __init__(self, a, b, c): + super().__init__(a, b) + self.c = c + SC = self.immutable_module.immutable(SC) + + return ((A, B, C), (SA, SB, SC)) + + def test_basic(self): + for A, B, C in self.make_classes(): + a = A(1) + self.assertEqual(a.a, 1) + self.assertEqual(a.akw, 10) + b = B(11, 21) + self.assertEqual(b.a, 11) + self.assertEqual(b.akw, 20) + self.assertEqual(b.b, 21) + c = C(111, 211, 311) + self.assertEqual(c.a, 111) + self.assertEqual(c.akw, 20) + self.assertEqual(c.b, 211) + self.assertEqual(c.c, 311) + # changing A is ok! + a.a = 11 + self.assertEqual(a.a, 11) + # changing B is not! + with self.assertRaises(TypeError): + b.a = 11 + with self.assertRaises(TypeError): + del b.a + + def test_constructor_deletes_attribute(self): + class A: + def __init__(self, a): + self.a = a + self.b = a + del self.b + A = self.immutable_module.immutable(A) + a = A(10) + self.assertEqual(a.a, 10) + self.assertFalse(hasattr(a, 'b')) + + def test_no_collateral_damage(self): + + # A and B are immutable but not related. The magic that lets + # us write to immutable things while initializing B should not let + # B mess with A. + + class A: + def __init__(self, a): + self.a = a + A = self.immutable_module.immutable(A) + + class B: + def __init__(self, a, b): + self.b = a.a + b + # rudely attempt to mutate innocent immutable bystander 'a' + a.a = 1000 + B = self.immutable_module.immutable(B) + + a = A(10) + self.assertEqual(a.a, 10) + with self.assertRaises(TypeError): + B(a, 20) + self.assertEqual(a.a, 10) + + +@unittest.skipIf(not _have_contextvars, "contextvars not available") +class CtxDecoratorTestCase(DecoratorTestCase): + + immutable_module = immutable_ctx diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_message.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_message.py new file mode 100644 index 0000000..19738e6 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_message.py @@ -0,0 +1,686 @@ +# -*- coding: utf-8 +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import unittest +import binascii + +import dns.exception +import dns.flags +import dns.message +import dns.name +import dns.rdataclass +import dns.rdatatype +import dns.rrset +import dns.tsig +import dns.update +import dns.rdtypes.ANY.OPT +import dns.rdtypes.ANY.TSIG + +from tests.util import here + +query_text = """id 1234 +opcode QUERY +rcode NOERROR +flags RD +edns 0 +eflags DO +payload 4096 +;QUESTION +wwww.dnspython.org. IN A +;ANSWER +;AUTHORITY +;ADDITIONAL""" + +goodhex = b'04d201000001000000000001047777777709646e73707974686f6e' \ + b'036f726700000100010000291000000080000000' + +goodwire = binascii.unhexlify(goodhex) + +answer_text = """id 1234 +opcode QUERY +rcode NOERROR +flags QR AA RD +;QUESTION +dnspython.org. IN SOA +;ANSWER +dnspython.org. 3600 IN SOA woof.dnspython.org. hostmaster.dnspython.org. 2003052700 3600 1800 604800 3600 +;AUTHORITY +dnspython.org. 3600 IN NS ns1.staff.nominum.org. +dnspython.org. 3600 IN NS ns2.staff.nominum.org. +dnspython.org. 3600 IN NS woof.play-bow.org. +;ADDITIONAL +woof.play-bow.org. 3600 IN A 204.152.186.150 +""" + +goodhex2 = '04d2 8500 0001 0001 0003 0001' \ + '09646e73707974686f6e036f726700 0006 0001' \ + 'c00c 0006 0001 00000e10 0028 ' \ + '04776f6f66c00c 0a686f73746d6173746572c00c' \ + '7764289c 00000e10 00000708 00093a80 00000e10' \ + 'c00c 0002 0001 00000e10 0014' \ + '036e7331057374616666076e6f6d696e756dc016' \ + 'c00c 0002 0001 00000e10 0006 036e7332c063' \ + 'c00c 0002 0001 00000e10 0010 04776f6f6608706c61792d626f77c016' \ + 'c091 0001 0001 00000e10 0004 cc98ba96' + + +goodwire2 = binascii.unhexlify(goodhex2.replace(' ', '').encode()) + +query_text_2 = """id 1234 +opcode QUERY +rcode 4095 +flags RD +edns 0 +eflags DO +payload 4096 +;QUESTION +wwww.dnspython.org. IN A +;ANSWER +;AUTHORITY +;ADDITIONAL""" + +goodhex3 = b'04d2010f0001000000000001047777777709646e73707974686f6e' \ + b'036f726700000100010000291000ff0080000000' + +goodwire3 = binascii.unhexlify(goodhex3) + +idna_text = """id 1234 +opcode QUERY +rcode NOERROR +flags QR AA RD +;QUESTION +Königsgäßchen. IN NS +;ANSWER +Königsgäßchen. 3600 IN NS Königsgäßchen. +""" + +class MessageTestCase(unittest.TestCase): + + def test_class(self): + m = dns.message.from_text(query_text) + self.assertTrue(isinstance(m, dns.message.QueryMessage)) + + def test_comparison_eq1(self): + q1 = dns.message.from_text(query_text) + q2 = dns.message.from_text(query_text) + self.assertEqual(q1, q2) + + def test_comparison_ne1(self): + q1 = dns.message.from_text(query_text) + q2 = dns.message.from_text(query_text) + q2.id = 10 + self.assertNotEqual(q1, q2) + + def test_comparison_ne2(self): + q1 = dns.message.from_text(query_text) + q2 = dns.message.from_text(query_text) + q2.question = [] + self.assertNotEqual(q1, q2) + + def test_comparison_ne3(self): + q1 = dns.message.from_text(query_text) + self.assertNotEqual(q1, 1) + + def test_EDNS_to_wire1(self): + q = dns.message.from_text(query_text) + w = q.to_wire() + self.assertEqual(w, goodwire) + + def test_EDNS_from_wire1(self): + m = dns.message.from_wire(goodwire) + self.assertEqual(str(m), query_text) + + def test_EDNS_to_wire2(self): + q = dns.message.from_text(query_text_2) + w = q.to_wire() + self.assertEqual(w, goodwire3) + + def test_EDNS_from_wire2(self): + m = dns.message.from_wire(goodwire3) + self.assertEqual(str(m), query_text_2) + + def test_EDNS_options_wire(self): + m = dns.message.make_query('foo', 'A') + opt = dns.edns.GenericOption(3, b'data') + m.use_edns(options=[opt]) + m2 = dns.message.from_wire(m.to_wire()) + self.assertEqual(m2.edns, 0) + self.assertEqual(len(m2.options), 1) + self.assertEqual(m2.options[0], opt) + + def test_TooBig(self): + def bad(): + q = dns.message.from_text(query_text) + for i in range(0, 25): + rrset = dns.rrset.from_text('foo%d.' % i, 3600, + dns.rdataclass.IN, + dns.rdatatype.A, + '10.0.0.%d' % i) + q.additional.append(rrset) + q.to_wire(max_size=512) + self.assertRaises(dns.exception.TooBig, bad) + + def test_answer1(self): + a = dns.message.from_text(answer_text) + wire = a.to_wire(want_shuffle=False) + self.assertEqual(wire, goodwire2) + + def test_TrailingJunk(self): + def bad(): + badwire = goodwire + b'\x00' + dns.message.from_wire(badwire) + self.assertRaises(dns.message.TrailingJunk, bad) + + def test_ShortHeader(self): + def bad(): + badwire = b'\x00' * 11 + dns.message.from_wire(badwire) + self.assertRaises(dns.message.ShortHeader, bad) + + def test_RespondingToResponse(self): + def bad(): + q = dns.message.make_query('foo', 'A') + r1 = dns.message.make_response(q) + dns.message.make_response(r1) + self.assertRaises(dns.exception.FormError, bad) + + def test_RespondingToEDNSRequestAndSettingRA(self): + q = dns.message.make_query('foo', 'A', use_edns=0) + r = dns.message.make_response(q, True) + self.assertTrue(r.flags & dns.flags.RA != 0) + self.assertEqual(r.edns, 0) + + def test_ExtendedRcodeSetting(self): + m = dns.message.make_query('foo', 'A') + m.set_rcode(4095) + self.assertEqual(m.rcode(), 4095) + self.assertEqual(m.edns, 0) + m.set_rcode(2) + self.assertEqual(m.rcode(), 2) + + def test_EDNSVersionCoherence(self): + m = dns.message.make_query('foo', 'A') + m.use_edns(1) + self.assertEqual((m.ednsflags >> 16) & 0xFF, 1) + + def test_SettingNoEDNSOptionsImpliesNoEDNS(self): + m = dns.message.make_query('foo', 'A') + self.assertEqual(m.edns, -1) + + def test_SettingEDNSFlagsImpliesEDNS(self): + m = dns.message.make_query('foo', 'A', ednsflags=dns.flags.DO) + self.assertEqual(m.edns, 0) + + def test_SettingEDNSPayloadImpliesEDNS(self): + m = dns.message.make_query('foo', 'A', payload=4096) + self.assertEqual(m.edns, 0) + + def test_SettingEDNSRequestPayloadImpliesEDNS(self): + m = dns.message.make_query('foo', 'A', request_payload=4096) + self.assertEqual(m.edns, 0) + + def test_SettingOptionsImpliesEDNS(self): + m = dns.message.make_query('foo', 'A', options=[]) + self.assertEqual(m.edns, 0) + + def test_FindRRset(self): + a = dns.message.from_text(answer_text) + n = dns.name.from_text('dnspython.org.') + rrs1 = a.find_rrset(a.answer, n, dns.rdataclass.IN, dns.rdatatype.SOA) + rrs2 = a.find_rrset(dns.message.ANSWER, n, dns.rdataclass.IN, + dns.rdatatype.SOA) + self.assertEqual(rrs1, rrs2) + + def test_FindRRsetUnindexed(self): + a = dns.message.from_text(answer_text) + a.index = None + n = dns.name.from_text('dnspython.org.') + rrs1 = a.find_rrset(a.answer, n, dns.rdataclass.IN, dns.rdatatype.SOA) + rrs2 = a.find_rrset(dns.message.ANSWER, n, dns.rdataclass.IN, + dns.rdatatype.SOA) + self.assertEqual(rrs1, rrs2) + + def test_GetRRset(self): + a = dns.message.from_text(answer_text) + a.index = None + n = dns.name.from_text('dnspython.org.') + rrs1 = a.get_rrset(a.answer, n, dns.rdataclass.IN, dns.rdatatype.SOA) + rrs2 = a.get_rrset(dns.message.ANSWER, n, dns.rdataclass.IN, + dns.rdatatype.SOA) + self.assertEqual(rrs1, rrs2) + + def test_GetNonexistentRRset(self): + a = dns.message.from_text(answer_text) + a.index = None + n = dns.name.from_text('dnspython.org.') + rrs1 = a.get_rrset(a.answer, n, dns.rdataclass.IN, dns.rdatatype.TXT) + rrs2 = a.get_rrset(dns.message.ANSWER, n, dns.rdataclass.IN, + dns.rdatatype.TXT) + self.assertTrue(rrs1 is None) + self.assertEqual(rrs1, rrs2) + + def test_CleanTruncated(self): + def bad(): + a = dns.message.from_text(answer_text) + a.flags |= dns.flags.TC + wire = a.to_wire(want_shuffle=False) + dns.message.from_wire(wire, raise_on_truncation=True) + self.assertRaises(dns.message.Truncated, bad) + + def test_MessyTruncated(self): + def bad(): + a = dns.message.from_text(answer_text) + a.flags |= dns.flags.TC + wire = a.to_wire(want_shuffle=False) + dns.message.from_wire(wire[:-3], raise_on_truncation=True) + self.assertRaises(dns.message.Truncated, bad) + + def test_IDNA_2003(self): + a = dns.message.from_text(idna_text, idna_codec=dns.name.IDNA_2003) + rrs = dns.rrset.from_text_list('xn--knigsgsschen-lcb0w.', 30, + 'in', 'ns', + ['xn--knigsgsschen-lcb0w.'], + idna_codec=dns.name.IDNA_2003) + self.assertEqual(a.answer[0], rrs) + + @unittest.skipUnless(dns.name.have_idna_2008, + 'Python idna cannot be imported; no IDNA2008') + def test_IDNA_2008(self): + a = dns.message.from_text(idna_text, idna_codec=dns.name.IDNA_2008) + rrs = dns.rrset.from_text_list('xn--knigsgchen-b4a3dun.', 30, + 'in', 'ns', + ['xn--knigsgchen-b4a3dun.'], + idna_codec=dns.name.IDNA_2008) + self.assertEqual(a.answer[0], rrs) + + def test_bad_section_number(self): + m = dns.message.make_query('foo', 'A') + self.assertRaises(ValueError, + lambda: m.section_number(123)) + + def test_section_from_number(self): + m = dns.message.make_query('foo', 'A') + self.assertEqual(m.section_from_number(dns.message.QUESTION), + m.question) + self.assertEqual(m.section_from_number(dns.message.ANSWER), + m.answer) + self.assertEqual(m.section_from_number(dns.message.AUTHORITY), + m.authority) + self.assertEqual(m.section_from_number(dns.message.ADDITIONAL), + m.additional) + self.assertRaises(ValueError, + lambda: m.section_from_number(999)) + + def test_wanting_EDNS_true_is_EDNS0(self): + m = dns.message.make_query('foo', 'A') + self.assertEqual(m.edns, -1) + m.use_edns(True) + self.assertEqual(m.edns, 0) + + def test_wanting_DNSSEC_turns_on_EDNS(self): + m = dns.message.make_query('foo', 'A') + self.assertEqual(m.edns, -1) + m.want_dnssec() + self.assertEqual(m.edns, 0) + self.assertTrue(m.ednsflags & dns.flags.DO) + + def test_EDNS_default_payload_is_1232(self): + m = dns.message.make_query('foo', 'A') + m.use_edns() + self.assertEqual(m.payload, dns.message.DEFAULT_EDNS_PAYLOAD) + + def test_from_file(self): + m = dns.message.from_file(here('query')) + expected = dns.message.from_text(query_text) + self.assertEqual(m, expected) + + def test_explicit_header_comment(self): + m = dns.message.from_text(';HEADER\n' + query_text) + expected = dns.message.from_text(query_text) + self.assertEqual(m, expected) + + def test_repr(self): + q = dns.message.from_text(query_text) + self.assertEqual(repr(q), '') + + def test_non_question_setters(self): + rrset = dns.rrset.from_text('foo', 300, 'in', 'a', '10.0.0.1') + q = dns.message.QueryMessage(id=1) + q.answer = [rrset] + self.assertEqual(q.sections[1], [rrset]) + self.assertEqual(q.sections[2], []) + self.assertEqual(q.sections[3], []) + q.authority = [rrset] + self.assertEqual(q.sections[2], [rrset]) + self.assertEqual(q.sections[3], []) + q.additional = [rrset] + self.assertEqual(q.sections[3], [rrset]) + + def test_is_a_response_empty_question(self): + q = dns.message.make_query('www.dnspython.org.', 'a') + r = dns.message.make_response(q) + r.question = [] + r.set_rcode(dns.rcode.FORMERR) + self.assertTrue(q.is_response(r)) + + def test_not_a_response(self): + q = dns.message.QueryMessage(id=1) + self.assertFalse(q.is_response(q)) + r = dns.message.QueryMessage(id=2) + r.flags = dns.flags.QR + self.assertFalse(q.is_response(r)) + r = dns.update.UpdateMessage(id=1) + self.assertFalse(q.is_response(r)) + q1 = dns.message.make_query('www.dnspython.org.', 'a') + q2 = dns.message.make_query('www.google.com.', 'a') + # Give them the same id, as we want to test if responses for + # differing questions are rejected. + q1.id = 1 + q2.id = 1 + r = dns.message.make_response(q2) + self.assertFalse(q1.is_response(r)) + # Now set rcode to FORMERR and check again. It should still + # not be a response as we check the question section for FORMERR + # if it is present. + r.set_rcode(dns.rcode.FORMERR) + self.assertFalse(q1.is_response(r)) + # Test the other case of differing questions, where there is + # something in the response's question section that is not in + # the question's. We have to do multiple questions to test + # this :) + r = dns.message.make_query('www.dnspython.org.', 'a') + r.flags |= dns.flags.QR + r.id = 1 + r.find_rrset(r.question, dns.name.from_text('example'), + dns.rdataclass.IN, dns.rdatatype.A, create=True, + force_unique=True) + self.assertFalse(q1.is_response(r)) + + def test_more_not_equal_cases(self): + q1 = dns.message.make_query('www.dnspython.org.', 'a') + q2 = dns.message.make_query('www.dnspython.org.', 'a') + # ensure ids are same + q1.id = 1 + q2.id = 1 + # and flags are different + q2.flags |= dns.flags.QR + self.assertFalse(q1 == q2) + q2.flags = q1.flags + q2.find_rrset(q2.question, dns.name.from_text('example'), + dns.rdataclass.IN, dns.rdatatype.A, create=True, + force_unique=True) + self.assertFalse(q1 == q2) + + def test_edns_properties(self): + q = dns.message.make_query('www.dnspython.org.', 'a') + self.assertEqual(q.edns, -1) + self.assertEqual(q.payload, 0) + self.assertEqual(q.options, ()) + q = dns.message.make_query('www.dnspython.org.', 'a', use_edns=0, + payload=4096) + self.assertEqual(q.edns, 0) + self.assertEqual(q.payload, 4096) + self.assertEqual(q.options, ()) + + def test_generic_message_class(self): + q1 = dns.message.Message(id=1) + q1.set_opcode(dns.opcode.NOTIFY) + q1.flags |= dns.flags.AA + q1.find_rrset(q1.question, dns.name.from_text('example'), + dns.rdataclass.IN, dns.rdatatype.SOA, create=True, + force_unique=True) + w = q1.to_wire() + q2 = dns.message.from_wire(w) + self.assertTrue(isinstance(q2, dns.message.Message)) + self.assertFalse(isinstance(q2, dns.message.QueryMessage)) + self.assertFalse(isinstance(q2, dns.update.UpdateMessage)) + self.assertEqual(q1, q2) + + def test_truncated_exception_message(self): + q = dns.message.Message(id=1) + q.flags |= dns.flags.TC + te = dns.message.Truncated(message=q) + self.assertEqual(te.message(), q) + + def test_bad_opt(self): + # Not in addtional + q = dns.message.Message(id=1) + opt = dns.rdtypes.ANY.OPT.OPT(1200, dns.rdatatype.OPT, ()) + rrs = dns.rrset.from_rdata(dns.name.root, 0, opt) + q.answer.append(rrs) + wire = q.to_wire() + with self.assertRaises(dns.message.BadEDNS): + dns.message.from_wire(wire) + # Owner name not root name + q = dns.message.Message(id=1) + rrs = dns.rrset.from_rdata('foo.', 0, opt) + q.additional.append(rrs) + wire = q.to_wire() + with self.assertRaises(dns.message.BadEDNS): + dns.message.from_wire(wire) + # Multiple opts + q = dns.message.Message(id=1) + rrs = dns.rrset.from_rdata(dns.name.root, 0, opt) + q.additional.append(rrs) + q.additional.append(rrs) + wire = q.to_wire() + with self.assertRaises(dns.message.BadEDNS): + dns.message.from_wire(wire) + + def test_bad_tsig(self): + keyname = dns.name.from_text('key.') + # Not in addtional + q = dns.message.Message(id=1) + tsig = dns.rdtypes.ANY.TSIG.TSIG(dns.rdataclass.ANY, dns.rdatatype.TSIG, + dns.tsig.HMAC_SHA256, 0, 300, b'1234', + 0, 0, b'') + rrs = dns.rrset.from_rdata(keyname, 0, tsig) + q.answer.append(rrs) + wire = q.to_wire() + with self.assertRaises(dns.message.BadTSIG): + dns.message.from_wire(wire) + # Multiple tsigs + q = dns.message.Message(id=1) + q.additional.append(rrs) + q.additional.append(rrs) + wire = q.to_wire() + with self.assertRaises(dns.message.BadTSIG): + dns.message.from_wire(wire) + # Class not ANY + tsig = dns.rdtypes.ANY.TSIG.TSIG(dns.rdataclass.IN, dns.rdatatype.TSIG, + dns.tsig.HMAC_SHA256, 0, 300, b'1234', + 0, 0, b'') + rrs = dns.rrset.from_rdata(keyname, 0, tsig) + wire = q.to_wire() + with self.assertRaises(dns.message.BadTSIG): + dns.message.from_wire(wire) + + def test_read_no_content_message(self): + m = dns.message.from_text(';comment') + self.assertIsInstance(m, dns.message.QueryMessage) + + def test_eflags_turns_on_edns(self): + m = dns.message.from_text('eflags DO') + self.assertIsInstance(m, dns.message.QueryMessage) + self.assertEqual(m.edns, 0) + + def test_payload_turns_on_edns(self): + m = dns.message.from_text('payload 1200') + self.assertIsInstance(m, dns.message.QueryMessage) + self.assertEqual(m.payload, 1200) + + def test_bogus_header(self): + with self.assertRaises(dns.message.UnknownHeaderField): + dns.message.from_text('bogus foo') + + def test_question_only(self): + m = dns.message.from_text(answer_text) + w = m.to_wire() + r = dns.message.from_wire(w, question_only=True) + self.assertEqual(r.id, m.id) + self.assertEqual(r.question[0], m.question[0]) + self.assertEqual(len(r.answer), 0) + self.assertEqual(len(r.authority), 0) + self.assertEqual(len(r.additional), 0) + + def test_bad_resolve_chaining(self): + r = dns.message.make_query('www.dnspython.org.', 'a') + with self.assertRaises(dns.message.NotQueryResponse): + r.resolve_chaining() + r.flags |= dns.flags.QR + r.id = 1 + r.find_rrset(r.question, dns.name.from_text('example'), + dns.rdataclass.IN, dns.rdatatype.A, create=True, + force_unique=True) + with self.assertRaises(dns.exception.FormError): + r.resolve_chaining() + + def test_resolve_chaining_no_infinite_loop(self): + r = dns.message.from_text('''id 1 +flags QR +;QUESTION +www.example. IN CNAME +;AUTHORITY +example. 300 IN SOA . . 1 2 3 4 5 +''') + # passing is actuall not going into an infinite loop in this call + result = r.resolve_chaining() + self.assertEqual(result.canonical_name, + dns.name.from_text('www.example.')) + self.assertEqual(result.minimum_ttl, 5) + self.assertIsNone(result.answer) + + def test_bad_text_questions(self): + with self.assertRaises(dns.exception.SyntaxError): + dns.message.from_text('''id 1 +;QUESTION +example. +''') + with self.assertRaises(dns.exception.SyntaxError): + dns.message.from_text('''id 1 +;QUESTION +example. IN +''') + with self.assertRaises(dns.rdatatype.UnknownRdatatype): + dns.message.from_text('''id 1 +;QUESTION +example. INA +''') + with self.assertRaises(dns.rdatatype.UnknownRdatatype): + dns.message.from_text('''id 1 +;QUESTION +example. IN BOGUS +''') + + def test_bad_text_rrs(self): + with self.assertRaises(dns.exception.SyntaxError): + dns.message.from_text('''id 1 +flags QR +;QUESTION +example. IN A +;ANSWER +example. +''') + with self.assertRaises(dns.exception.SyntaxError): + dns.message.from_text('''id 1 +flags QR +;QUESTION +example. IN A +;ANSWER +example. IN +''') + with self.assertRaises(dns.exception.SyntaxError): + dns.message.from_text('''id 1 +flags QR +;QUESTION +example. IN A +;ANSWER +example. 300 +''') + with self.assertRaises(dns.rdatatype.UnknownRdatatype): + dns.message.from_text('''id 1 +flags QR +;QUESTION +example. IN A +;ANSWER +example. 30a IN A +''') + with self.assertRaises(dns.rdatatype.UnknownRdatatype): + dns.message.from_text('''id 1 +flags QR +;QUESTION +example. IN A +;ANSWER +example. 300 INA A +''') + with self.assertRaises(dns.exception.UnexpectedEnd): + dns.message.from_text('''id 1 +flags QR +;QUESTION +example. IN A +;ANSWER +example. 300 IN A +''') + with self.assertRaises(dns.exception.SyntaxError): + dns.message.from_text('''id 1 +flags QR +opcode UPDATE +;ZONE +example. IN SOA +;UPDATE +example. 300 IN A +''') + with self.assertRaises(dns.exception.SyntaxError): + dns.message.from_text('''id 1 +flags QR +opcode UPDATE +;ZONE +example. IN SOA +;UPDATE +example. 300 NONE A +''') + with self.assertRaises(dns.exception.SyntaxError): + dns.message.from_text('''id 1 +flags QR +opcode UPDATE +;ZONE +example. IN SOA +;PREREQ +example. 300 NONE A 10.0.0.1 +''') + with self.assertRaises(dns.exception.SyntaxError): + dns.message.from_text('''id 1 +flags QR +;ANSWER + 300 IN A 10.0.0.1 +''') + with self.assertRaises(dns.exception.SyntaxError): + dns.message.from_text('''id 1 +flags QR +;QUESTION + IN SOA +''') + + def test_from_wire_makes_Flag(self): + m = dns.message.from_wire(goodwire) + self.assertIsInstance(m.flags, dns.flags.Flag) + self.assertEqual(m.flags, dns.flags.Flag.RD) + + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_name.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_name.py new file mode 100644 index 0000000..f91d7e6 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_name.py @@ -0,0 +1,1090 @@ +# -*- coding: utf-8 +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +from typing import Dict # pylint: disable=unused-import +import copy +import operator +import pickle +import unittest + +from io import BytesIO + +import dns.name +import dns.reversename +import dns.e164 + +# pylint: disable=line-too-long,unsupported-assignment-operation + + +class NameTestCase(unittest.TestCase): + def setUp(self): + self.origin = dns.name.from_text('example.') + + def testFromTextRel1(self): + n = dns.name.from_text('foo.bar') + self.assertEqual(n.labels, (b'foo', b'bar', b'')) + + def testFromTextRel2(self): + n = dns.name.from_text('foo.bar', origin=self.origin) + self.assertEqual(n.labels, (b'foo', b'bar', b'example', b'')) + + def testFromTextRel3(self): + n = dns.name.from_text('foo.bar', origin=None) + self.assertEqual(n.labels, (b'foo', b'bar')) + + def testFromTextRel4(self): + n = dns.name.from_text('@', origin=None) + self.assertEqual(n, dns.name.empty) + + def testFromTextRel5(self): + n = dns.name.from_text('@', origin=self.origin) + self.assertEqual(n, self.origin) + + def testFromTextAbs1(self): + n = dns.name.from_text('foo.bar.') + self.assertEqual(n.labels, (b'foo', b'bar', b'')) + + def testTortureFromText(self): + good = [ + br'.', + br'a', + br'a.', + br'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + br'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + br'\000.\008.\010.\032.\046.\092.\099.\255', + br'\\', + br'\..\.', + br'\\.\\', + br'!"#%&/()=+-', + br'\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255', + ] + bad = [ + br'..', + br'.a', + br'\\..', + b'\\', # yes, we don't want the 'r' prefix! + br'\0', + br'\00', + br'\00Z', + br'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + br'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + br'\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255', + ] + for t in good: + try: + dns.name.from_text(t) + except Exception: + self.fail("good test '%s' raised an exception" % t) + for t in bad: + caught = False + try: + dns.name.from_text(t) + except Exception: + caught = True + if not caught: + self.fail("bad test '%s' did not raise an exception" % t) + + def testImmutable1(self): + def bad(): + self.origin.labels = () + self.assertRaises(TypeError, bad) + + def testImmutable2(self): + def bad(): + self.origin.labels[0] = 'foo' + self.assertRaises(TypeError, bad) + + def testAbs1(self): + self.assertTrue(dns.name.root.is_absolute()) + + def testAbs2(self): + self.assertFalse(dns.name.empty.is_absolute()) + + def testAbs3(self): + self.assertTrue(self.origin.is_absolute()) + + def testAbs4(self): + n = dns.name.from_text('foo', origin=None) + self.assertFalse(n.is_absolute()) + + def testWild1(self): + n = dns.name.from_text('*.foo', origin=None) + self.assertTrue(n.is_wild()) + + def testWild2(self): + n = dns.name.from_text('*a.foo', origin=None) + self.assertFalse(n.is_wild()) + + def testWild3(self): + n = dns.name.from_text('a.*.foo', origin=None) + self.assertFalse(n.is_wild()) + + def testWild4(self): + self.assertFalse(dns.name.root.is_wild()) + + def testWild5(self): + self.assertFalse(dns.name.empty.is_wild()) + + def testHash1(self): + n1 = dns.name.from_text('fOo.COM') + n2 = dns.name.from_text('foo.com') + self.assertEqual(hash(n1), hash(n2)) + + def testCompare1(self): + n1 = dns.name.from_text('a') + n2 = dns.name.from_text('b') + self.assertLess(n1, n2) + self.assertLessEqual(n1, n2) + self.assertGreater(n2, n1) + self.assertGreaterEqual(n2, n1) + + def testCompare2(self): + n1 = dns.name.from_text('') + n2 = dns.name.from_text('b') + self.assertLess(n1, n2) + self.assertLessEqual(n1, n2) + self.assertGreater(n2, n1) + self.assertGreaterEqual(n2, n1) + + def testCompare3(self): + self.assertLess(dns.name.empty, dns.name.root) + self.assertGreater(dns.name.root, dns.name.empty) + + def testCompare4(self): + self.assertNotEqual(dns.name.root, 1) + + def testSubdomain1(self): + self.assertFalse(dns.name.empty.is_subdomain(dns.name.root)) + + def testSubdomain2(self): + self.assertFalse(dns.name.root.is_subdomain(dns.name.empty)) + + def testSubdomain3(self): + n = dns.name.from_text('foo', origin=self.origin) + self.assertTrue(n.is_subdomain(self.origin)) + + def testSubdomain4(self): + n = dns.name.from_text('foo', origin=self.origin) + self.assertTrue(n.is_subdomain(dns.name.root)) + + def testSubdomain5(self): + n = dns.name.from_text('foo', origin=self.origin) + self.assertTrue(n.is_subdomain(n)) + + def testSuperdomain1(self): + self.assertFalse(dns.name.empty.is_superdomain(dns.name.root)) + + def testSuperdomain2(self): + self.assertFalse(dns.name.root.is_superdomain(dns.name.empty)) + + def testSuperdomain3(self): + n = dns.name.from_text('foo', origin=self.origin) + self.assertTrue(self.origin.is_superdomain(n)) + + def testSuperdomain4(self): + n = dns.name.from_text('foo', origin=self.origin) + self.assertTrue(dns.name.root.is_superdomain(n)) + + def testSuperdomain5(self): + n = dns.name.from_text('foo', origin=self.origin) + self.assertTrue(n.is_superdomain(n)) + + def testCanonicalize1(self): + n = dns.name.from_text('FOO.bar', origin=self.origin) + c = n.canonicalize() + self.assertEqual(c.labels, (b'foo', b'bar', b'example', b'')) + + def testToText1(self): + n = dns.name.from_text('FOO.bar', origin=self.origin) + t = n.to_text() + self.assertEqual(t, 'FOO.bar.example.') + + def testToText2(self): + n = dns.name.from_text('FOO.bar', origin=self.origin) + t = n.to_text(True) + self.assertEqual(t, 'FOO.bar.example') + + def testToText3(self): + n = dns.name.from_text('FOO.bar', origin=None) + t = n.to_text() + self.assertEqual(t, 'FOO.bar') + + def testToText4(self): + t = dns.name.empty.to_text() + self.assertEqual(t, '@') + + def testToText5(self): + t = dns.name.root.to_text() + self.assertEqual(t, '.') + + def testToText6(self): + n = dns.name.from_text('FOO bar', origin=None) + t = n.to_text() + self.assertEqual(t, r'FOO\032bar') + + def testToText7(self): + n = dns.name.from_text(r'FOO\.bar', origin=None) + t = n.to_text() + self.assertEqual(t, r'FOO\.bar') + + def testToText8(self): + n = dns.name.from_text(r'\070OO\.bar', origin=None) + t = n.to_text() + self.assertEqual(t, r'FOO\.bar') + + def testToText9(self): + n = dns.name.from_text('FOO bar', origin=None) + t = n.to_unicode() + self.assertEqual(t, 'FOO\\032bar') + + def testToText10(self): + t = dns.name.empty.to_unicode() + self.assertEqual(t, '@') + + def testToText11(self): + t = dns.name.root.to_unicode() + self.assertEqual(t, '.') + + def testToText12(self): + n = dns.name.from_text(r'a\.b.c') + t = n.to_unicode() + self.assertEqual(t, r'a\.b.c.') + + def testToText13(self): + n = dns.name.from_text(r'\150\151\152\153\154\155\156\157\158\159.') + t = n.to_text() + self.assertEqual(t, r'\150\151\152\153\154\155\156\157\158\159.') + + def testToText14(self): + # Something that didn't start as unicode should go to escapes and not + # raise due to interpreting arbitrary binary DNS labels as UTF-8. + n = dns.name.from_text(r'\150\151\152\153\154\155\156\157\158\159.') + t = n.to_unicode() + self.assertEqual(t, r'\150\151\152\153\154\155\156\157\158\159.') + + def testSlice1(self): + n = dns.name.from_text(r'a.b.c.', origin=None) + s = n[:] + self.assertEqual(s, (b'a', b'b', b'c', b'')) + + def testSlice2(self): + n = dns.name.from_text(r'a.b.c.', origin=None) + s = n[:2] + self.assertEqual(s, (b'a', b'b')) + + def testSlice3(self): + n = dns.name.from_text(r'a.b.c.', origin=None) + s = n[2:] + self.assertEqual(s, (b'c', b'')) + + def testEmptyLabel1(self): + def bad(): + dns.name.Name(['a', '', 'b']) + self.assertRaises(dns.name.EmptyLabel, bad) + + def testEmptyLabel2(self): + def bad(): + dns.name.Name(['', 'b']) + self.assertRaises(dns.name.EmptyLabel, bad) + + def testEmptyLabel3(self): + n = dns.name.Name(['b', '']) + self.assertTrue(n) + + def testLongLabel(self): + n = dns.name.Name(['a' * 63]) + self.assertTrue(n) + + def testLabelTooLong(self): + def bad(): + dns.name.Name(['a' * 64, 'b']) + self.assertRaises(dns.name.LabelTooLong, bad) + + def testLongName(self): + n = dns.name.Name(['a' * 63, 'a' * 63, 'a' * 63, 'a' * 62]) + self.assertTrue(n) + + def testNameTooLong(self): + def bad(): + dns.name.Name(['a' * 63, 'a' * 63, 'a' * 63, 'a' * 63]) + self.assertRaises(dns.name.NameTooLong, bad) + + def testConcat1(self): + n1 = dns.name.Name(['a', 'b']) + n2 = dns.name.Name(['c', 'd']) + e = dns.name.Name(['a', 'b', 'c', 'd']) + r = n1 + n2 + self.assertEqual(r, e) + + def testConcat2(self): + n1 = dns.name.Name(['a', 'b']) + n2 = dns.name.Name([]) + e = dns.name.Name(['a', 'b']) + r = n1 + n2 + self.assertEqual(r, e) + + def testConcat3(self): + n1 = dns.name.Name([]) + n2 = dns.name.Name(['a', 'b']) + e = dns.name.Name(['a', 'b']) + r = n1 + n2 + self.assertEqual(r, e) + + def testConcat4(self): + n1 = dns.name.Name(['a', 'b', '']) + n2 = dns.name.Name([]) + e = dns.name.Name(['a', 'b', '']) + r = n1 + n2 + self.assertEqual(r, e) + + def testConcat5(self): + n1 = dns.name.Name(['a', 'b']) + n2 = dns.name.Name(['c', '']) + e = dns.name.Name(['a', 'b', 'c', '']) + r = n1 + n2 + self.assertEqual(r, e) + + def testConcat6(self): + def bad(): + n1 = dns.name.Name(['a', 'b', '']) + n2 = dns.name.Name(['c']) + return n1 + n2 + self.assertRaises(dns.name.AbsoluteConcatenation, bad) + + def testBadEscape(self): + def bad(): + n = dns.name.from_text(r'a.b\0q1.c.') + self.assertRaises(dns.name.BadEscape, bad) + + def testDigestable1(self): + n = dns.name.from_text('FOO.bar') + d = n.to_digestable() + self.assertEqual(d, b'\x03foo\x03bar\x00') + + def testDigestable2(self): + n1 = dns.name.from_text('FOO.bar') + n2 = dns.name.from_text('foo.BAR.') + d1 = n1.to_digestable() + d2 = n2.to_digestable() + self.assertEqual(d1, d2) + + def testDigestable3(self): + d = dns.name.root.to_digestable() + self.assertEqual(d, b'\x00') + + def testDigestable4(self): + n = dns.name.from_text('FOO.bar', None) + d = n.to_digestable(dns.name.root) + self.assertEqual(d, b'\x03foo\x03bar\x00') + + def testBadDigestable(self): + def bad(): + n = dns.name.from_text('FOO.bar', None) + n.to_digestable() + self.assertRaises(dns.name.NeedAbsoluteNameOrOrigin, bad) + + def testToWire1(self): + n = dns.name.from_text('FOO.bar') + f = BytesIO() + compress = {} # type: Dict[dns.name.Name,int] + n.to_wire(f, compress) + self.assertEqual(f.getvalue(), b'\x03FOO\x03bar\x00') + + def testToWire2(self): + n = dns.name.from_text('FOO.bar') + f = BytesIO() + compress = {} # type: Dict[dns.name.Name,int] + n.to_wire(f, compress) + n.to_wire(f, compress) + self.assertEqual(f.getvalue(), b'\x03FOO\x03bar\x00\xc0\x00') + + def testToWire3(self): + n1 = dns.name.from_text('FOO.bar') + n2 = dns.name.from_text('foo.bar') + f = BytesIO() + compress = {} # type: Dict[dns.name.Name,int] + n1.to_wire(f, compress) + n2.to_wire(f, compress) + self.assertEqual(f.getvalue(), b'\x03FOO\x03bar\x00\xc0\x00') + + def testToWire4(self): + n1 = dns.name.from_text('FOO.bar') + n2 = dns.name.from_text('a.foo.bar') + f = BytesIO() + compress = {} # type: Dict[dns.name.Name,int] + n1.to_wire(f, compress) + n2.to_wire(f, compress) + self.assertEqual(f.getvalue(), b'\x03FOO\x03bar\x00\x01\x61\xc0\x00') + + def testToWire5(self): + n1 = dns.name.from_text('FOO.bar') + n2 = dns.name.from_text('a.foo.bar') + f = BytesIO() + compress = {} # type: Dict[dns.name.Name,int] + n1.to_wire(f, compress) + n2.to_wire(f, None) + self.assertEqual(f.getvalue(), + b'\x03FOO\x03bar\x00\x01\x61\x03foo\x03bar\x00') + + def testToWire6(self): + n = dns.name.from_text('FOO.bar') + v = n.to_wire() + self.assertEqual(v, b'\x03FOO\x03bar\x00') + + def testToWireRelativeNameWithOrigin(self): + n = dns.name.from_text('FOO', None) + o = dns.name.from_text('bar') + v = n.to_wire(origin=o) + self.assertEqual(v, b'\x03FOO\x03bar\x00') + + def testToWireRelativeNameWithoutOrigin(self): + n = dns.name.from_text('FOO', None) + def bad(): + v = n.to_wire() + self.assertRaises(dns.name.NeedAbsoluteNameOrOrigin, bad) + + def testBadToWire(self): + def bad(): + n = dns.name.from_text('FOO.bar', None) + f = BytesIO() + compress = {} # type: Dict[dns.name.Name,int] + n.to_wire(f, compress) + self.assertRaises(dns.name.NeedAbsoluteNameOrOrigin, bad) + + def testGiantCompressionTable(self): + # Only the first 16KiB of a message can have compression pointers. + f = BytesIO() + compress = {} # type: Dict[dns.name.Name,int] + # exactly 16 bytes encoded + n = dns.name.from_text('0000000000.com.') + n.to_wire(f, compress) + # There are now two entries in the compression table (for the full + # name, and for the com. suffix. + self.assertEqual(len(compress), 2) + for i in range(1023): + # exactly 16 bytes encoded with compression + n = dns.name.from_text(f'{i:013d}.com') + n.to_wire(f, compress) + # There are now 1025 entries in the compression table with + # the last entry at offset 16368. + self.assertEqual(len(compress), 1025) + self.assertEqual(compress[n], 16368) + # Adding another name should not increase the size of the compression + # table, as the pointer would be at offset 16384, which is too big. + n = dns.name.from_text('toobig.com.') + n.to_wire(f, compress) + self.assertEqual(len(compress), 1025) + + def testSplit1(self): + n = dns.name.from_text('foo.bar.') + (prefix, suffix) = n.split(2) + ep = dns.name.from_text('foo', None) + es = dns.name.from_text('bar.', None) + self.assertEqual(prefix, ep) + self.assertEqual(suffix, es) + + def testSplit2(self): + n = dns.name.from_text('foo.bar.') + (prefix, suffix) = n.split(1) + ep = dns.name.from_text('foo.bar', None) + es = dns.name.from_text('.', None) + self.assertEqual(prefix, ep) + self.assertEqual(suffix, es) + + def testSplit3(self): + n = dns.name.from_text('foo.bar.') + (prefix, suffix) = n.split(0) + ep = dns.name.from_text('foo.bar.', None) + es = dns.name.from_text('', None) + self.assertEqual(prefix, ep) + self.assertEqual(suffix, es) + + def testSplit4(self): + n = dns.name.from_text('foo.bar.') + (prefix, suffix) = n.split(3) + ep = dns.name.from_text('', None) + es = dns.name.from_text('foo.bar.', None) + self.assertEqual(prefix, ep) + self.assertEqual(suffix, es) + + def testBadSplit1(self): + def bad(): + n = dns.name.from_text('foo.bar.') + n.split(-1) + self.assertRaises(ValueError, bad) + + def testBadSplit2(self): + def bad(): + n = dns.name.from_text('foo.bar.') + n.split(4) + self.assertRaises(ValueError, bad) + + def testRelativize1(self): + n = dns.name.from_text('a.foo.bar.', None) + o = dns.name.from_text('bar.', None) + e = dns.name.from_text('a.foo', None) + self.assertEqual(n.relativize(o), e) + + def testRelativize2(self): + n = dns.name.from_text('a.foo.bar.', None) + o = n + e = dns.name.empty + self.assertEqual(n.relativize(o), e) + + def testRelativize3(self): + n = dns.name.from_text('a.foo.bar.', None) + o = dns.name.from_text('blaz.', None) + e = n + self.assertEqual(n.relativize(o), e) + + def testRelativize4(self): + n = dns.name.from_text('a.foo', None) + o = dns.name.root + e = n + self.assertEqual(n.relativize(o), e) + + def testDerelativize1(self): + n = dns.name.from_text('a.foo', None) + o = dns.name.from_text('bar.', None) + e = dns.name.from_text('a.foo.bar.', None) + self.assertEqual(n.derelativize(o), e) + + def testDerelativize2(self): + n = dns.name.empty + o = dns.name.from_text('a.foo.bar.', None) + e = o + self.assertEqual(n.derelativize(o), e) + + def testDerelativize3(self): + n = dns.name.from_text('a.foo.bar.', None) + o = dns.name.from_text('blaz.', None) + e = n + self.assertEqual(n.derelativize(o), e) + + def testChooseRelativity1(self): + n = dns.name.from_text('a.foo.bar.', None) + o = dns.name.from_text('bar.', None) + e = dns.name.from_text('a.foo', None) + self.assertEqual(n.choose_relativity(o, True), e) + + def testChooseRelativity2(self): + n = dns.name.from_text('a.foo.bar.', None) + o = dns.name.from_text('bar.', None) + e = n + self.assertEqual(n.choose_relativity(o, False), e) + + def testChooseRelativity3(self): + n = dns.name.from_text('a.foo', None) + o = dns.name.from_text('bar.', None) + e = dns.name.from_text('a.foo.bar.', None) + self.assertEqual(n.choose_relativity(o, False), e) + + def testChooseRelativity4(self): + n = dns.name.from_text('a.foo', None) + o = None + e = n + self.assertEqual(n.choose_relativity(o, True), e) + + def testChooseRelativity5(self): + n = dns.name.from_text('a.foo', None) + o = None + e = n + self.assertEqual(n.choose_relativity(o, False), e) + + def testChooseRelativity6(self): + n = dns.name.from_text('a.foo.', None) + o = None + e = n + self.assertEqual(n.choose_relativity(o, True), e) + + def testChooseRelativity7(self): + n = dns.name.from_text('a.foo.', None) + o = None + e = n + self.assertEqual(n.choose_relativity(o, False), e) + + def testFromWire1(self): + w = b'\x03foo\x00\xc0\x00' + (n1, cused1) = dns.name.from_wire(w, 0) + (n2, cused2) = dns.name.from_wire(w, cused1) + en1 = dns.name.from_text('foo.') + en2 = en1 + ecused1 = 5 + ecused2 = 2 + self.assertEqual(n1, en1) + self.assertEqual(cused1, ecused1) + self.assertEqual(n2, en2) + self.assertEqual(cused2, ecused2) + + def testFromWire2(self): + w = b'\x03foo\x00\x01a\xc0\x00\x01b\xc0\x05' + current = 0 + (n1, cused1) = dns.name.from_wire(w, current) + current += cused1 + (n2, cused2) = dns.name.from_wire(w, current) + current += cused2 + (n3, cused3) = dns.name.from_wire(w, current) + en1 = dns.name.from_text('foo.') + en2 = dns.name.from_text('a.foo.') + en3 = dns.name.from_text('b.a.foo.') + ecused1 = 5 + ecused2 = 4 + ecused3 = 4 + self.assertEqual(n1, en1) + self.assertEqual(cused1, ecused1) + self.assertEqual(n2, en2) + self.assertEqual(cused2, ecused2) + self.assertEqual(n3, en3) + self.assertEqual(cused3, ecused3) + + def testBadFromWire1(self): + def bad(): + w = b'\x03foo\xc0\x04' + dns.name.from_wire(w, 0) + self.assertRaises(dns.name.BadPointer, bad) + + def testBadFromWire2(self): + def bad(): + w = b'\x03foo\xc0\x05' + dns.name.from_wire(w, 0) + self.assertRaises(dns.name.BadPointer, bad) + + def testBadFromWire3(self): + def bad(): + w = b'\xbffoo' + dns.name.from_wire(w, 0) + self.assertRaises(dns.name.BadLabelType, bad) + + def testBadFromWire4(self): + def bad(): + w = b'\x41foo' + dns.name.from_wire(w, 0) + self.assertRaises(dns.name.BadLabelType, bad) + + def testParent1(self): + n = dns.name.from_text('foo.bar.') + self.assertEqual(n.parent(), dns.name.from_text('bar.')) + self.assertEqual(n.parent().parent(), dns.name.root) + + def testParent2(self): + n = dns.name.from_text('foo.bar', None) + self.assertEqual(n.parent(), dns.name.from_text('bar', None)) + self.assertEqual(n.parent().parent(), dns.name.empty) + + def testParent3(self): + def bad(): + n = dns.name.root + n.parent() + self.assertRaises(dns.name.NoParent, bad) + + def testParent4(self): + def bad(): + n = dns.name.empty + n.parent() + self.assertRaises(dns.name.NoParent, bad) + + def testFromUnicode1(self): + n = dns.name.from_text('foo.bar') + self.assertEqual(n.labels, (b'foo', b'bar', b'')) + + def testFromUnicode2(self): + n = dns.name.from_text('foo\u1234bar.bar') + self.assertEqual(n.labels, (b'xn--foobar-r5z', b'bar', b'')) + + def testFromUnicodeAlternateDot1(self): + n = dns.name.from_text('foo\u3002bar') + self.assertEqual(n.labels, (b'foo', b'bar', b'')) + + def testFromUnicodeAlternateDot2(self): + n = dns.name.from_text('foo\uff0ebar') + self.assertEqual(n.labels, (b'foo', b'bar', b'')) + + def testFromUnicodeAlternateDot3(self): + n = dns.name.from_text('foo\uff61bar') + self.assertEqual(n.labels, (b'foo', b'bar', b'')) + + def testFromUnicodeRoot(self): + n = dns.name.from_text('.') + self.assertEqual(n.labels, (b'',)) + + def testFromUnicodeAlternateRoot1(self): + n = dns.name.from_text('\u3002') + self.assertEqual(n.labels, (b'',)) + + def testFromUnicodeAlternateRoot2(self): + n = dns.name.from_text('\uff0e') + self.assertEqual(n.labels, (b'',)) + + def testFromUnicodeAlternateRoot3(self): + n = dns.name.from_text('\uff61') + self.assertEqual(n.labels, (b'', )) + + def testFromUnicodeIDNA2003Explicit(self): + t = 'Königsgäßchen' + e = dns.name.from_unicode(t, idna_codec=dns.name.IDNA_2003) + self.assertEqual(str(e), 'xn--knigsgsschen-lcb0w.') + + def testFromUnicodeIDNA2003Default(self): + t = 'Königsgäßchen' + e = dns.name.from_unicode(t) + self.assertEqual(str(e), 'xn--knigsgsschen-lcb0w.') + + @unittest.skipUnless(dns.name.have_idna_2008, + 'Python idna cannot be imported; no IDNA2008') + def testFromUnicodeIDNA2008(self): + t = 'Königsgäßchen' + def bad(): + codec = dns.name.IDNA_2008_Strict + return dns.name.from_unicode(t, idna_codec=codec) + self.assertRaises(dns.name.IDNAException, bad) + e1 = dns.name.from_unicode(t, idna_codec=dns.name.IDNA_2008) + self.assertEqual(str(e1), 'xn--knigsgchen-b4a3dun.') + c2 = dns.name.IDNA_2008_Transitional + e2 = dns.name.from_unicode(t, idna_codec=c2) + self.assertEqual(str(e2), 'xn--knigsgsschen-lcb0w.') + + @unittest.skipUnless(dns.name.have_idna_2008, + 'Python idna cannot be imported; no IDNA2008') + def testFromUnicodeIDNA2008Mixed(self): + # the IDN rules for names are very restrictive, disallowing + # practical names like '_sip._tcp.Königsgäßchen'. Dnspython + # has a "practical" mode which permits labels which are purely + # ASCII to go straight through, and thus not invalid useful + # things in the real world. + t = '_sip._tcp.Königsgäßchen' + def bad1(): + codec = dns.name.IDNA_2008_Strict + return dns.name.from_unicode(t, idna_codec=codec) + def bad2(): + codec = dns.name.IDNA_2008_UTS_46 + return dns.name.from_unicode(t, idna_codec=codec) + def bad3(): + codec = dns.name.IDNA_2008_Transitional + return dns.name.from_unicode(t, idna_codec=codec) + self.assertRaises(dns.name.IDNAException, bad1) + self.assertRaises(dns.name.IDNAException, bad2) + self.assertRaises(dns.name.IDNAException, bad3) + e = dns.name.from_unicode(t, + idna_codec=dns.name.IDNA_2008_Practical) + self.assertEqual(str(e), '_sip._tcp.xn--knigsgchen-b4a3dun.') + + def testFromUnicodeEscapes(self): + n = dns.name.from_unicode(r'\097.\098.\099.') + t = n.to_unicode() + self.assertEqual(t, 'a.b.c.') + + def testToUnicode1(self): + n = dns.name.from_text('foo.bar') + s = n.to_unicode() + self.assertEqual(s, 'foo.bar.') + + def testToUnicode2(self): + n = dns.name.from_text('foo\u1234bar.bar') + s = n.to_unicode() + self.assertEqual(s, 'foo\u1234bar.bar.') + + def testToUnicode3(self): + n = dns.name.from_text('foo.bar') + s = n.to_unicode() + self.assertEqual(s, 'foo.bar.') + + @unittest.skipUnless(dns.name.have_idna_2008, + 'Python idna cannot be imported; no IDNA2008') + def testToUnicode4(self): + n = dns.name.from_text('ドメイン.テスト', + idna_codec=dns.name.IDNA_2008) + s = n.to_unicode() + self.assertEqual(str(n), 'xn--eckwd4c7c.xn--zckzah.') + self.assertEqual(s, 'ドメイン.テスト.') + + @unittest.skipUnless(dns.name.have_idna_2008, + 'Python idna cannot be imported; no IDNA2008') + def testToUnicode5(self): + # Exercise UTS 46 remapping in decode. This doesn't normally happen + # as you can see from us having to instantiate the codec as + # transitional with strict decoding, not one of our usual choices. + codec = dns.name.IDNA2008Codec(True, True, False, True) + n = dns.name.from_text('xn--gro-7ka.com') + self.assertEqual(n.to_unicode(idna_codec=codec), + 'gross.com.') + + @unittest.skipUnless(dns.name.have_idna_2008, + 'Python idna cannot be imported; no IDNA2008') + def testToUnicode6(self): + # Test strict 2008 decoding without UTS 46 + n = dns.name.from_text('xn--gro-7ka.com') + self.assertEqual(n.to_unicode(idna_codec=dns.name.IDNA_2008_Strict), + 'groß.com.') + + def testDefaultDecodeIsJustPunycode(self): + # groß.com. in IDNA2008 form, pre-encoded. + n = dns.name.from_text('xn--gro-7ka.com') + # output using default codec which just decodes the punycode and + # doesn't test for IDNA2003 or IDNA2008. + self.assertEqual(n.to_unicode(), 'groß.com.') + + def testStrictINDA2003Decode(self): + # groß.com. in IDNA2008 form, pre-encoded. + n = dns.name.from_text('xn--gro-7ka.com') + def bad(): + # This throws in IDNA2003 because it doesn't "round trip". + n.to_unicode(idna_codec=dns.name.IDNA_2003_Strict) + self.assertRaises(dns.name.IDNAException, bad) + + def testINDA2008Decode(self): + # groß.com. in IDNA2008 form, pre-encoded. + n = dns.name.from_text('xn--gro-7ka.com') + self.assertEqual(n.to_unicode(idna_codec=dns.name.IDNA_2008), + 'groß.com.') + + def testToUnicodeOmitFinalDot(self): + # groß.com. in IDNA2008 form, pre-encoded. + n = dns.name.from_text('xn--gro-7ka.com') + self.assertEqual(n.to_unicode(True, dns.name.IDNA_2008), + 'groß.com') + + def testIDNA2003Misc(self): + self.assertEqual(dns.name.IDNA_2003.encode(''), b'') + self.assertRaises(dns.name.LabelTooLong, + lambda: dns.name.IDNA_2003.encode('x' * 64)) + + @unittest.skipUnless(dns.name.have_idna_2008, + 'Python idna cannot be imported; no IDNA2008') + def testIDNA2008Misc(self): + self.assertEqual(dns.name.IDNA_2008.encode(''), b'') + self.assertRaises(dns.name.LabelTooLong, + lambda: dns.name.IDNA_2008.encode('x' * 64)) + self.assertRaises(dns.name.LabelTooLong, + lambda: dns.name.IDNA_2008.encode('groß' + 'x' * 60)) + + def testReverseIPv4(self): + e = dns.name.from_text('1.0.0.127.in-addr.arpa.') + n = dns.reversename.from_address('127.0.0.1') + self.assertEqual(e, n) + + def testReverseIPv6(self): + e = dns.name.from_text('1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.') + n = dns.reversename.from_address(b'::1') + self.assertEqual(e, n) + + def testReverseIPv6MappedIpv4(self): + e = dns.name.from_text('1.0.0.127.in-addr.arpa.') + n = dns.reversename.from_address('::ffff:127.0.0.1') + self.assertEqual(e, n) + + def testBadReverseIPv4(self): + def bad(): + dns.reversename.from_address('127.0.foo.1') + self.assertRaises(dns.exception.SyntaxError, bad) + + def testBadReverseIPv6(self): + def bad(): + dns.reversename.from_address('::1::1') + self.assertRaises(dns.exception.SyntaxError, bad) + + def testReverseIPv4AlternateOrigin(self): + e = dns.name.from_text('1.0.0.127.foo.bar.') + origin = dns.name.from_text('foo.bar') + n = dns.reversename.from_address('127.0.0.1', v4_origin=origin) + self.assertEqual(e, n) + + def testReverseIPv6AlternateOrigin(self): + e = dns.name.from_text('1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.foo.bar.') + origin = dns.name.from_text('foo.bar') + n = dns.reversename.from_address(b'::1', v6_origin=origin) + self.assertEqual(e, n) + + def testForwardIPv4(self): + n = dns.name.from_text('1.0.0.127.in-addr.arpa.') + e = '127.0.0.1' + text = dns.reversename.to_address(n) + self.assertEqual(text, e) + + def testForwardIPv6(self): + n = dns.name.from_text('1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.') + e = '::1' + text = dns.reversename.to_address(n) + self.assertEqual(text, e) + + def testForwardIPv4AlternateOrigin(self): + n = dns.name.from_text('1.0.0.127.foo.bar.') + e = '127.0.0.1' + origin = dns.name.from_text('foo.bar') + text = dns.reversename.to_address(n, v4_origin=origin) + self.assertEqual(text, e) + + def testForwardIPv6AlternateOrigin(self): + n = dns.name.from_text('1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.foo.bar.') + e = '::1' + origin = dns.name.from_text('foo.bar') + text = dns.reversename.to_address(n, v6_origin=origin) + self.assertEqual(text, e) + + def testUnknownReverseOrigin(self): + n = dns.name.from_text('1.2.3.4.unknown.') + with self.assertRaises(dns.exception.SyntaxError): + dns.reversename.to_address(n) + + def testE164ToEnum(self): + text = '+1 650 555 1212' + e = dns.name.from_text('2.1.2.1.5.5.5.0.5.6.1.e164.arpa.') + n = dns.e164.from_e164(text) + self.assertEqual(n, e) + + def testEnumToE164(self): + n = dns.name.from_text('2.1.2.1.5.5.5.0.5.6.1.e164.arpa.') + e = '+16505551212' + text = dns.e164.to_e164(n) + self.assertEqual(text, e) + + def testBadEnumToE164(self): + n = dns.name.from_text('2.1.2.q.5.5.5.0.5.6.1.e164.arpa.') + self.assertRaises(dns.exception.SyntaxError, + lambda: dns.e164.to_e164(n)) + + def test_incompatible_relations(self): + n1 = dns.name.from_text('example') + n2 = 'abc' + for oper in [operator.lt, operator.le, operator.ge, operator.gt]: + self.assertRaises(TypeError, lambda: oper(n1, n2)) + self.assertFalse(n1 == n2) + self.assertTrue(n1 != n2) + + def testFromUnicodeSimpleEscape(self): + n = dns.name.from_unicode(r'a.\b') + e = dns.name.from_unicode(r'a.b') + self.assertEqual(n, e) + + def testFromUnicodeBadEscape(self): + def bad1(): + n = dns.name.from_unicode(r'a.b\0q1.c.') + self.assertRaises(dns.name.BadEscape, bad1) + def bad2(): + n = dns.name.from_unicode(r'a.b\0') + self.assertRaises(dns.name.BadEscape, bad2) + + def testFromUnicodeNotString(self): + def bad(): + dns.name.from_unicode(b'123') + self.assertRaises(ValueError, bad) + + def testFromUnicodeBadOrigin(self): + def bad(): + dns.name.from_unicode('example', 123) + self.assertRaises(ValueError, bad) + + def testFromUnicodeEmptyLabel(self): + def bad(): + dns.name.from_unicode('a..b.example') + self.assertRaises(dns.name.EmptyLabel, bad) + + def testFromUnicodeEmptyName(self): + self.assertEqual(dns.name.from_unicode('@', None), dns.name.empty) + + def testFromTextNotString(self): + def bad(): + dns.name.from_text(123) + self.assertRaises(ValueError, bad) + + def testFromTextBadOrigin(self): + def bad(): + dns.name.from_text('example', 123) + self.assertRaises(ValueError, bad) + + def testFromWireNotBytes(self): + def bad(): + dns.name.from_wire(123, 0) + self.assertRaises(ValueError, bad) + + def testBadPunycode(self): + c = dns.name.IDNACodec() + with self.assertRaises(dns.name.IDNAException): + c.decode(b'xn--0000h') + + def testRootLabel2003StrictDecode(self): + c = dns.name.IDNA_2003_Strict + self.assertEqual(c.decode(b''), '') + + @unittest.skipUnless(dns.name.have_idna_2008, + 'Python idna cannot be imported; no IDNA2008') + def testRootLabel2008StrictDecode(self): + c = dns.name.IDNA_2008_Strict + self.assertEqual(c.decode(b''), '') + + @unittest.skipUnless(dns.name.have_idna_2008, + 'Python idna cannot be imported; no IDNA2008') + def testCodecNotFoundRaises(self): + dns.name.have_idna_2008 = False + with self.assertRaises(dns.name.NoIDNA2008): + c = dns.name.IDNA2008Codec() + c.encode('Königsgäßchen') + with self.assertRaises(dns.name.NoIDNA2008): + c = dns.name.IDNA2008Codec(strict_decode=True) + c.decode('xn--eckwd4c7c.xn--zckzah.') + dns.name.have_idna_2008 = True + + @unittest.skipUnless(dns.name.have_idna_2008, + 'Python idna cannot be imported; no IDNA2008') + def testBadPunycodeStrict2008(self): + c = dns.name.IDNA2008Codec(strict_decode=True) + with self.assertRaises(dns.name.IDNAException): + c.decode(b'xn--0000h') + + def testRelativizeSubtractionSyntax(self): + n = dns.name.from_text('foo.example.') + o = dns.name.from_text('example.') + e = dns.name.from_text('foo', None) + self.assertEqual(n - o, e) + + def testCopy(self): + n1 = dns.name.from_text('foo.example.') + n2 = copy.copy(n1) + self.assertTrue(n1 is not n2) + # the Name constructor always copies labels, so there is no + # difference between copy and deepcopy + self.assertTrue(n1.labels is not n2.labels) + self.assertEqual(len(n1.labels), len(n2.labels)) + for i, l in enumerate(n1.labels): + self.assertTrue(l is n2[i]) + + def testDeepCopy(self): + n1 = dns.name.from_text('foo.example.') + n2 = copy.deepcopy(n1) + self.assertTrue(n1 is not n2) + self.assertTrue(n1.labels is not n2.labels) + self.assertEqual(len(n1.labels), len(n2.labels)) + for i, l in enumerate(n1.labels): + self.assertTrue(l is n2[i]) + + def testNoAttributeDeletion(self): + n = dns.name.from_text('foo.example.') + with self.assertRaises(TypeError): + del n.labels + + def testUnicodeEscapify(self): + n = dns.name.from_unicode('Königsgäßchen;\ttext') + self.assertEqual(n.to_unicode(), 'königsgässchen\\;\\009text.') + + def test_pickle(self): + n1 = dns.name.from_text('foo.example') + p = pickle.dumps(n1) + n2 = pickle.loads(p) + self.assertEqual(n1, n2) + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_namedict.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_namedict.py new file mode 100644 index 0000000..73097a6 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_namedict.py @@ -0,0 +1,161 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import unittest + +import dns.name +import dns.namedict + +class NameTestCase(unittest.TestCase): + + def setUp(self): + self.ndict = dns.namedict.NameDict() + n1 = dns.name.from_text('foo.bar.') + n2 = dns.name.from_text('bar.') + self.ndict[n1] = 1 + self.ndict[n2] = 2 + self.rndict = dns.namedict.NameDict() + n1 = dns.name.from_text('foo.bar', None) + n2 = dns.name.from_text('bar', None) + self.rndict[n1] = 1 + self.rndict[n2] = 2 + + def testDepth(self): + self.assertEqual(self.ndict.max_depth, 3) + + def testLookup1(self): + k = dns.name.from_text('foo.bar.') + self.assertEqual(self.ndict[k], 1) + + def testLookup2(self): + k = dns.name.from_text('foo.bar.') + self.assertEqual(self.ndict.get_deepest_match(k)[1], 1) + + def testLookup3(self): + k = dns.name.from_text('a.b.c.foo.bar.') + self.assertEqual(self.ndict.get_deepest_match(k)[1], 1) + + def testLookup4(self): + k = dns.name.from_text('a.b.c.bar.') + self.assertEqual(self.ndict.get_deepest_match(k)[1], 2) + + def testLookup5(self): + def bad(): + n = dns.name.from_text('a.b.c.') + self.ndict.get_deepest_match(n) + self.assertRaises(KeyError, bad) + + def testLookup6(self): + def bad(): + self.ndict.get_deepest_match(dns.name.empty) + self.assertRaises(KeyError, bad) + + def testLookup7(self): + self.ndict[dns.name.empty] = 100 + n = dns.name.from_text('a.b.c.') + v = self.ndict.get_deepest_match(n)[1] + self.assertEqual(v, 100) + + def testLookup8(self): + def bad(): + self.ndict['foo'] = 100 + self.assertRaises(ValueError, bad) + + def testRelDepth(self): + self.assertEqual(self.rndict.max_depth, 2) + + def testRelLookup1(self): + k = dns.name.from_text('foo.bar', None) + self.assertEqual(self.rndict[k], 1) + + def testRelLookup2(self): + k = dns.name.from_text('foo.bar', None) + self.assertEqual(self.rndict.get_deepest_match(k)[1], 1) + + def testRelLookup3(self): + k = dns.name.from_text('a.b.c.foo.bar', None) + self.assertEqual(self.rndict.get_deepest_match(k)[1], 1) + + def testRelLookup4(self): + k = dns.name.from_text('a.b.c.bar', None) + self.assertEqual(self.rndict.get_deepest_match(k)[1], 2) + + def testRelLookup7(self): + self.rndict[dns.name.empty] = 100 + n = dns.name.from_text('a.b.c', None) + v = self.rndict.get_deepest_match(n)[1] + self.assertEqual(v, 100) + + def test_max_depth_increases(self): + n = dns.name.from_text('a.foo.bar.') + self.assertEqual(self.ndict.max_depth, 3) + self.ndict[n] = 1 + self.assertEqual(self.ndict.max_depth, 4) + + def test_delete_no_max_depth_change(self): + self.assertEqual(self.ndict.max_depth, 3) + n = dns.name.from_text('bar.') + del self.ndict[n] + self.assertEqual(self.ndict.max_depth, 3) + self.assertEqual(self.ndict.get(n), None) + + def test_delete_max_depth_changes(self): + self.assertEqual(self.ndict.max_depth, 3) + n = dns.name.from_text('foo.bar.') + del self.ndict[n] + self.assertEqual(self.ndict.max_depth, 2) + self.assertEqual(self.ndict.get(n), None) + + def test_delete_multiple_max_depth_changes(self): + self.assertEqual(self.ndict.max_depth, 3) + nr = dns.name.from_text('roo.') + self.ndict[nr] = 1 + nf = dns.name.from_text('foo.bar.') + nb = dns.name.from_text('bar.bar.') + self.ndict[nb] = 1 + self.assertEqual(self.ndict.max_depth, 3) + self.assertEqual(self.ndict.max_depth_items, 2) + del self.ndict[nb] + self.assertEqual(self.ndict.max_depth, 3) + self.assertEqual(self.ndict.max_depth_items, 1) + del self.ndict[nf] + self.assertEqual(self.ndict.max_depth, 2) + self.assertEqual(self.ndict.max_depth_items, 2) + self.assertEqual(self.ndict.get(nf), None) + self.assertEqual(self.ndict.get(nb), None) + + def test_iter(self): + nf = dns.name.from_text('foo.bar.') + nb = dns.name.from_text('bar.') + keys = set([x for x in self.ndict]) + self.assertEqual(len(keys), 2) + self.assertTrue(nf in keys) + self.assertTrue(nb in keys) + + def test_len(self): + self.assertEqual(len(self.ndict), 2) + + def test_haskey(self): + nf = dns.name.from_text('foo.bar.') + nb = dns.name.from_text('bar.') + nx = dns.name.from_text('x.') + self.assertTrue(self.ndict.has_key(nf)) + self.assertTrue(self.ndict.has_key(nb)) + self.assertFalse(self.ndict.has_key(nx)) + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_nsec3.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_nsec3.py new file mode 100644 index 0000000..bf7d115 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_nsec3.py @@ -0,0 +1,48 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import unittest + +import dns.exception +import dns.rdata +import dns.rdataclass +import dns.rdatatype +import dns.rdtypes.ANY.TXT +import dns.ttl + +class NSEC3TestCase(unittest.TestCase): + def test_NSEC3_bitmap(self): + rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NSEC3, + u"1 0 100 ABCD SCBCQHKU35969L2A68P3AD59LHF30715 A CAA TYPE65534") + bitmap = bytearray(b'\0' * 32) + bitmap[31] = bitmap[31] | 2 + self.assertEqual(rdata.windows, ((0, b'@'), + (1, b'@'), # CAA = 257 + (255, bitmap) + )) + + def test_NSEC3_bad_bitmaps(self): + rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NSEC3, + u"1 0 100 ABCD SCBCQHKU35969L2A68P3AD59LHF30715 A CAA") + + with self.assertRaises(dns.exception.FormError): + copy = bytearray(rdata.to_wire()) + copy[-3] = 0 + dns.rdata.from_wire('IN', 'NSEC3', copy, 0, len(copy)) + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_nsec3_hash.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_nsec3_hash.py new file mode 100644 index 0000000..f7c4337 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_nsec3_hash.py @@ -0,0 +1,96 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import unittest + +from dns import dnssec, name + + +class NSEC3Hash(unittest.TestCase): + + DATA = [ + # Source: https://tools.ietf.org/html/rfc5155#appendix-A + ("example", "aabbccdd", 12, "0p9mhaveqvm6t7vbl5lop2u3t2rp3tom", 1), + ("a.example", "aabbccdd", 12, "35mthgpgcu1qg68fab165klnsnk3dpvl", 1), + ("ai.example", "aabbccdd", 12, "gjeqe526plbf1g8mklp59enfd789njgi", 1), + ("ns1.example", "aabbccdd", 12, "2t7b4g4vsa5smi47k61mv5bv1a22bojr", 1), + ("ns2.example", "aabbccdd", 12, "q04jkcevqvmu85r014c7dkba38o0ji5r", 1), + ("w.example", "aabbccdd", 12, "k8udemvp1j2f7eg6jebps17vp3n8i58h", 1), + ("*.w.example", "aabbccdd", 12, "r53bq7cc2uvmubfu5ocmm6pers9tk9en", 1), + ("x.w.example", "aabbccdd", 12, "b4um86eghhds6nea196smvmlo4ors995", 1), + ("y.w.example", "aabbccdd", 12, "ji6neoaepv8b5o6k4ev33abha8ht9fgc", 1), + ("x.y.w.example", "aabbccdd", 12, "2vptu5timamqttgl4luu9kg21e0aor3s", 1), + ("xx.example", "aabbccdd", 12, "t644ebqk9bibcna874givr6joj62mlhv", 1), + ( + "2t7b4g4vsa5smi47k61mv5bv1a22bojr.example", + "aabbccdd", + 12, + "kohar7mbb8dc2ce8a9qvl8hon4k53uhi", + 1, + ), + # Source: generated with knsec3hash (Linux knot package) + ("example.com", "9F1AB450CF71D6", 0, "qfo2sv6jaej4cm11a3npoorfrckdao2c", 1), + ("example.com", "9F1AB450CF71D6", 1, "1nr64to0bb861lku97deb4ubbk6cl5qh", 1), + ("example.com.", "AF6AB45CCF79D6", 6, "sale3fn6penahh1lq5oqtr5rcl1d113a", 1), + ("test.domain.dev.", "", 6, "8q98lv9jgkhoq272e42c8blesivia7bu", 1), + ("www.test.domain.dev.", "B4", 2, "nv7ti6brgh94ke2f3pgiigjevfgpo5j0", 1), + ("*.test-domain.dev", "", 0, "o6uadafckb6hea9qpcgir2gl71vt23gu", 1), + ("*.test-domain.dev", "", 45, "505k9g118d9sofnjhh54rr8fadgpa0ct", 1), + # Alternate forms of parameters + ( + name.from_text("example"), + "aabbccdd", + 12, + "0p9mhaveqvm6t7vbl5lop2u3t2rp3tom", + 1, + ), + ( + "example", + b"\xaa\xbb\xcc\xdd", + 12, + "0p9mhaveqvm6t7vbl5lop2u3t2rp3tom", + 1, + ), + ("*.test-domain.dev", None, 45, "505k9g118d9sofnjhh54rr8fadgpa0ct", 1), + ( + "example", + "aabbccdd", + 12, + "0p9mhaveqvm6t7vbl5lop2u3t2rp3tom", + dnssec.NSEC3Hash.SHA1 + ), + ("example", "aabbccdd", 12, "0p9mhaveqvm6t7vbl5lop2u3t2rp3tom", "SHA1"), + ("example", "aabbccdd", 12, "0p9mhaveqvm6t7vbl5lop2u3t2rp3tom", "sha1") + ] + + def test_hash_function(self): + for d in self.DATA: + hash = dnssec.nsec3_hash(d[0], d[1], d[2], d[4]) + self.assertEqual(hash, d[3].upper(), "Error {}".format(d)) + + def test_hash_invalid_salt_length(self): + data = ( + "example.com", + "9F1AB450CF71D", + 0, + "qfo2sv6jaej4cm11a3npoorfrckdao2c", + 1, + ) + with self.assertRaises(ValueError): + hash = dnssec.nsec3_hash(data[0], data[1], data[2], data[4]) + + def test_hash_invalid_algorithm(self): + data = ( + "example.com", + "9F1AB450CF71D", + 0, + "qfo2sv6jaej4cm11a3npoorfrckdao2c", + 1, + ) + with self.assertRaises(ValueError): + dnssec.nsec3_hash(data[0], data[1], data[2], 10) + with self.assertRaises(ValueError): + dnssec.nsec3_hash(data[0], data[1], data[2], "foo") + + +if __name__ == "__main__": + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_ntoaaton.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_ntoaaton.py new file mode 100644 index 0000000..7e30bce --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_ntoaaton.py @@ -0,0 +1,326 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import unittest +import binascii +import socket + +import dns.exception +import dns.ipv4 +import dns.ipv6 +import dns.inet + +# for convenience +aton4 = dns.ipv4.inet_aton +ntoa4 = dns.ipv4.inet_ntoa +aton6 = dns.ipv6.inet_aton +ntoa6 = dns.ipv6.inet_ntoa + +v4_bad_addrs = ['256.1.1.1', '1.1.1', '1.1.1.1.1', + '+1.1.1.1', '1.1.1.1+', '1..2.3.4', '.1.2.3.4', + '1.2.3.4.'] + +class NtoAAtoNTestCase(unittest.TestCase): + + def test_aton1(self): + a = aton6('::') + self.assertEqual(a, b'\x00' * 16) + + def test_aton2(self): + a = aton6('::1') + self.assertEqual(a, b'\x00' * 15 + b'\x01') + + def test_aton3(self): + a = aton6('::10.0.0.1') + self.assertEqual(a, b'\x00' * 12 + b'\x0a\x00\x00\x01') + + def test_aton4(self): + a = aton6('abcd::dcba') + self.assertEqual(a, b'\xab\xcd' + b'\x00' * 12 + b'\xdc\xba') + + def test_aton5(self): + a = aton6('1:2:3:4:5:6:7:8') + self.assertEqual(a, + binascii.unhexlify(b'00010002000300040005000600070008')) + + def test_bad_aton1(self): + def bad(): + aton6('abcd:dcba') + self.assertRaises(dns.exception.SyntaxError, bad) + + def test_bad_aton2(self): + def bad(): + aton6('abcd::dcba::1') + self.assertRaises(dns.exception.SyntaxError, bad) + + def test_bad_aton3(self): + def bad(): + aton6('1:2:3:4:5:6:7:8:9') + self.assertRaises(dns.exception.SyntaxError, bad) + + def test_bad_aton4(self): + def bad(): + aton4('001.002.003.004') + self.assertRaises(dns.exception.SyntaxError, bad) + + def test_aton6(self): + a = aton6('::') + self.assertEqual(a, b'\x00' * 16) + + def test_aton7(self): + a = aton6('::1') + self.assertEqual(a, b'\x00' * 15 + b'\x01') + + def test_aton8(self): + a = aton6('::10.0.0.1') + self.assertEqual(a, b'\x00' * 12 + b'\x0a\x00\x00\x01') + + def test_aton9(self): + a = aton6('abcd::dcba') + self.assertEqual(a, b'\xab\xcd' + b'\x00' * 12 + b'\xdc\xba') + + def test_ntoa1(self): + b = binascii.unhexlify(b'00010002000300040005000600070008') + t = ntoa6(b) + self.assertEqual(t, '1:2:3:4:5:6:7:8') + + def test_ntoa2(self): + b = b'\x00' * 16 + t = ntoa6(b) + self.assertEqual(t, '::') + + def test_ntoa3(self): + b = b'\x00' * 15 + b'\x01' + t = ntoa6(b) + self.assertEqual(t, '::1') + + def test_ntoa4(self): + b = b'\x80' + b'\x00' * 15 + t = ntoa6(b) + self.assertEqual(t, '8000::') + + def test_ntoa5(self): + b = b'\x01\xcd' + b'\x00' * 12 + b'\x03\xef' + t = ntoa6(b) + self.assertEqual(t, '1cd::3ef') + + def test_ntoa6(self): + b = binascii.unhexlify(b'ffff00000000ffff000000000000ffff') + t = ntoa6(b) + self.assertEqual(t, 'ffff:0:0:ffff::ffff') + + def test_ntoa7(self): + b = binascii.unhexlify(b'00000000ffff000000000000ffffffff') + t = ntoa6(b) + self.assertEqual(t, '0:0:ffff::ffff:ffff') + + def test_ntoa8(self): + b = binascii.unhexlify(b'ffff0000ffff00000000ffff00000000') + t = ntoa6(b) + self.assertEqual(t, 'ffff:0:ffff::ffff:0:0') + + def test_ntoa9(self): + b = binascii.unhexlify(b'0000000000000000000000000a000001') + t = ntoa6(b) + self.assertEqual(t, '::10.0.0.1') + + def test_ntoa10(self): + b = binascii.unhexlify(b'0000000000000000000000010a000001') + t = ntoa6(b) + self.assertEqual(t, '::1:a00:1') + + def test_ntoa11(self): + b = binascii.unhexlify(b'00000000000000000000ffff0a000001') + t = ntoa6(b) + self.assertEqual(t, '::ffff:10.0.0.1') + + def test_ntoa12(self): + b = binascii.unhexlify(b'000000000000000000000000ffffffff') + t = ntoa6(b) + self.assertEqual(t, '::255.255.255.255') + + def test_ntoa13(self): + b = binascii.unhexlify(b'00000000000000000000ffffffffffff') + t = ntoa6(b) + self.assertEqual(t, '::ffff:255.255.255.255') + + def test_ntoa14(self): + b = binascii.unhexlify(b'0000000000000000000000000001ffff') + t = ntoa6(b) + self.assertEqual(t, '::0.1.255.255') + + def test_ntoa15(self): + # This exercises the current_len > best_len branch in the <= case. + b = binascii.unhexlify(b'0000ffff00000000ffff00000000ffff') + t = ntoa6(b) + self.assertEqual(t, '0:ffff::ffff:0:0:ffff') + + def test_bad_ntoa1(self): + def bad(): + ntoa6(b'') + self.assertRaises(ValueError, bad) + + def test_bad_ntoa2(self): + def bad(): + ntoa6(b'\x00' * 17) + self.assertRaises(ValueError, bad) + + def test_bad_ntoa3(self): + def bad(): + ntoa4(b'\x00' * 5) + # Ideally we'd have been consistent and raised ValueError as + # we do for IPv6, but oh well! + self.assertRaises(dns.exception.SyntaxError, bad) + + def test_good_v4_aton(self): + pairs = [('1.2.3.4', b'\x01\x02\x03\x04'), + ('255.255.255.255', b'\xff\xff\xff\xff'), + ('0.0.0.0', b'\x00\x00\x00\x00')] + for (t, b) in pairs: + b1 = aton4(t) + t1 = ntoa4(b1) + self.assertEqual(b1, b) + self.assertEqual(t1, t) + + def test_bad_v4_aton(self): + def make_bad(a): + def bad(): + return aton4(a) + return bad + for addr in v4_bad_addrs: + self.assertRaises(dns.exception.SyntaxError, make_bad(addr)) + + def test_bad_v6_aton(self): + addrs = ['+::0', '0::0::', '::0::', '1:2:3:4:5:6:7:8:9', + ':::::::'] + embedded = ['::' + x for x in v4_bad_addrs] + addrs.extend(embedded) + def make_bad(a): + def bad(): + x = aton6(a) + return bad + for addr in addrs: + self.assertRaises(dns.exception.SyntaxError, make_bad(addr)) + + def test_rfc5952_section_4_2_2(self): + addr = '2001:db8:0:1:1:1:1:1' + b1 = aton6(addr) + t1 = ntoa6(b1) + self.assertEqual(t1, addr) + + def test_is_mapped(self): + t1 = '2001:db8:0:1:1:1:1:1' + t2 = '::ffff:127.0.0.1' + t3 = '1::ffff:127.0.0.1' + self.assertFalse(dns.ipv6.is_mapped(aton6(t1))) + self.assertTrue(dns.ipv6.is_mapped(aton6(t2))) + self.assertFalse(dns.ipv6.is_mapped(aton6(t3))) + + def test_is_multicast(self): + t1 = '223.0.0.1' + t2 = '240.0.0.1' + t3 = '224.0.0.1' + t4 = '239.0.0.1' + t5 = 'fe00::1' + t6 = 'ff00::1' + self.assertFalse(dns.inet.is_multicast(t1)) + self.assertFalse(dns.inet.is_multicast(t2)) + self.assertTrue(dns.inet.is_multicast(t3)) + self.assertTrue(dns.inet.is_multicast(t4)) + self.assertFalse(dns.inet.is_multicast(t5)) + self.assertTrue(dns.inet.is_multicast(t6)) + + def test_is_multicast_bad_input(self): + def bad(): + dns.inet.is_multicast('hello world') + self.assertRaises(ValueError, bad) + + def test_ignore_scope(self): + t1 = 'fe80::1%lo0' + t2 = 'fe80::1' + self.assertEqual(aton6(t1, True), aton6(t2)) + + def test_do_not_ignore_scope(self): + def bad(): + t1 = 'fe80::1%lo0' + aton6(t1) + self.assertRaises(dns.exception.SyntaxError, bad) + + def test_multiple_scopes_bad(self): + def bad(): + t1 = 'fe80::1%lo0%lo1' + aton6(t1, True) + self.assertRaises(dns.exception.SyntaxError, bad) + + def test_ptontop(self): + for (af, a) in [(socket.AF_INET, '1.2.3.4'), + (socket.AF_INET6, '2001:db8:0:1:1:1:1:1')]: + self.assertEqual(dns.inet.inet_ntop(af, dns.inet.inet_pton(af, a)), + a) + + def test_isaddress(self): + for (t, e) in [('1.2.3.4', True), + ('2001:db8:0:1:1:1:1:1', True), + ('hello world', False), + ('http://www.dnspython.org', False), + ('1.2.3.4a', False), + ('2001:db8:0:1:1:1:1:q1', False)]: + self.assertEqual(dns.inet.is_address(t), e) + + def test_low_level_address_tuple(self): + t = dns.inet.low_level_address_tuple(('1.2.3.4', 53)) + self.assertEqual(t, ('1.2.3.4', 53)) + t = dns.inet.low_level_address_tuple(('2600::1', 53)) + self.assertEqual(t, ('2600::1', 53, 0, 0)) + t = dns.inet.low_level_address_tuple(('1.2.3.4', 53), socket.AF_INET) + self.assertEqual(t, ('1.2.3.4', 53)) + t = dns.inet.low_level_address_tuple(('2600::1', 53), socket.AF_INET6) + self.assertEqual(t, ('2600::1', 53, 0, 0)) + t = dns.inet.low_level_address_tuple(('fd80::1%2', 53), socket.AF_INET6) + self.assertEqual(t, ('fd80::1', 53, 0, 2)) + try: + # This can fail on windows for python < 3.8, so we tolerate + # the failure and only test if we have something we can work + # with. + info = socket.if_nameindex() + except Exception: + info = [] + if info: + # find first thing on list that is not zero (should be first thing! + pair = None + for p in info: + if p[0] != 0: + pair = p + break + if pair: + address = 'fd80::1%' + pair[1] + t = dns.inet.low_level_address_tuple((address, 53), + socket.AF_INET6) + self.assertEqual(t, ('fd80::1', 53, 0, pair[0])) + def bad(): + bogus = socket.AF_INET + socket.AF_INET6 + 1 + t = dns.inet.low_level_address_tuple(('2600::1', 53), bogus) + self.assertRaises(NotImplementedError, bad) + + def test_bogus_family(self): + self.assertRaises(NotImplementedError, + lambda: dns.inet.inet_pton(12345, 'bogus')) + self.assertRaises(NotImplementedError, + lambda: dns.inet.inet_ntop(12345, b'bogus')) + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_processing_order.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_processing_order.py new file mode 100644 index 0000000..45a90cf --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_processing_order.py @@ -0,0 +1,132 @@ + +import dns.rdata +import dns.rdataset + + +def test_processing_order_shuffle(): + rds = dns.rdataset.from_text('in', 'a', 300, + '10.0.0.1', '10.0.0.2', '10.0.0.3') + seen = set() + for i in range(100): + po = rds.processing_order() + assert len(po) == 3 + for j in range(3): + assert rds[j] in po + seen.add(tuple(po)) + assert len(seen) == 6 + + +def test_processing_order_priority_mx(): + rds = dns.rdataset.from_text('in', 'mx', 300, + '10 a', '20 b', '20 c') + seen = set() + for i in range(100): + po = rds.processing_order() + assert len(po) == 3 + for j in range(3): + assert rds[j] in po + assert rds[0] == po[0] + seen.add(tuple(po)) + assert len(seen) == 2 + + +def test_processing_order_priority_weighted(): + rds = dns.rdataset.from_text('in', 'srv', 300, + '1 10 1234 a', '2 90 1234 b', '2 10 1234 c') + seen = set() + weight_90_count = 0 + weight_10_count = 0 + for i in range(100): + po = rds.processing_order() + assert len(po) == 3 + for j in range(3): + assert rds[j] in po + assert rds[0] == po[0] + if po[1].weight == 90: + weight_90_count += 1 + else: + assert po[1].weight == 10 + weight_10_count += 1 + seen.add(tuple(po)) + assert len(seen) == 2 + # We can't assert anything with certainty given these are random + # draws, but it's super likely that weight_90_count > weight_10_count, + # so we just assert that. + assert weight_90_count > weight_10_count + + +def test_processing_order_priority_naptr(): + rds = dns.rdataset.from_text('in', 'naptr', 300, + '1 10 a b c foo.', '1 20 a b c foo.', + '2 10 a b c foo.', '2 10 d e f bar.') + seen = set() + for i in range(100): + po = rds.processing_order() + assert len(po) == 4 + for j in range(4): + assert rds[j] in po + assert rds[0] == po[0] + assert rds[1] == po[1] + seen.add(tuple(po)) + assert len(seen) == 2 + + +def test_processing_order_empty(): + rds = dns.rdataset.from_text('in', 'naptr', 300) + po = rds.processing_order() + assert po == [] + + +def test_processing_singleton_priority(): + rds = dns.rdataset.from_text('in', 'mx', 300, '10 a') + po = rds.processing_order() + print(po) + assert po == [rds[0]] + + +def test_processing_singleton_weighted(): + rds = dns.rdataset.from_text('in', 'srv', 300, '1 10 1234 a') + po = rds.processing_order() + print(po) + assert po == [rds[0]] + + +def test_processing_all_zero_weight_srv(): + rds = dns.rdataset.from_text('in', 'srv', 300, + '1 0 1234 a', '1 0 1234 b', '1 0 1234 c') + seen = set() + for i in range(100): + po = rds.processing_order() + assert len(po) == 3 + for j in range(3): + assert rds[j] in po + seen.add(tuple(po)) + assert len(seen) == 6 + + +def test_processing_order_uri(): + # We're testing here just to provide coverage for URI methods; the + # testing of the weighting algorithm is done above in tests with + # SRV. + rds = dns.rdataset.from_text('in', 'uri', 300, + '1 1 "ftp://ftp1.example.com/public"', + '2 2 "ftp://ftp2.example.com/public"', + '3 3 "ftp://ftp3.example.com/public"') + po = rds.processing_order() + assert len(po) == 3 + for i in range(3): + assert po[i] == rds[i] + + +def test_processing_order_svcb(): + # We're testing here just to provide coverage for SVCB methods; the + # testing of the priority algorithm is done above in tests with + # MX and NAPTR. + rds = dns.rdataset.from_text('in', 'svcb', 300, + "1 . mandatory=alpn alpn=h2", + "2 . mandatory=alpn alpn=h2", + "3 . mandatory=alpn alpn=h2") + po = rds.processing_order() + assert len(po) == 3 + for i in range(3): + assert po[i] == rds[i] diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_query.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_query.py new file mode 100644 index 0000000..2cff377 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_query.py @@ -0,0 +1,583 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import socket +import sys +import time +import unittest + +try: + import ssl + have_ssl = True +except Exception: + have_ssl = False + +import dns.exception +import dns.inet +import dns.message +import dns.name +import dns.rdataclass +import dns.rdatatype +import dns.query +import dns.tsigkeyring +import dns.zone + +# Some tests require the internet to be available to run, so let's +# skip those if it's not there. +_network_available = True +try: + socket.gethostbyname('dnspython.org') +except socket.gaierror: + _network_available = False + +# Some tests use a "nano nameserver" for testing. It requires trio +# and threading, so try to import it and if it doesn't work, skip +# those tests. +try: + from .nanonameserver import Server + _nanonameserver_available = True +except ImportError: + _nanonameserver_available = False + class Server(object): + pass + +# Probe for IPv4 and IPv6 +query_addresses = [] +for (af, address) in ((socket.AF_INET, '8.8.8.8'), + (socket.AF_INET6, '2001:4860:4860::8888')): + try: + with socket.socket(af, socket.SOCK_DGRAM) as s: + # Connecting a UDP socket is supposed to return ENETUNREACH if + # no route to the network is present. + s.connect((address, 53)) + query_addresses.append(address) + except Exception: + pass + +keyring = dns.tsigkeyring.from_text({'name': 'tDz6cfXXGtNivRpQ98hr6A=='}) + +@unittest.skipIf(not _network_available, "Internet not reachable") +class QueryTests(unittest.TestCase): + + def testQueryUDP(self): + for address in query_addresses: + qname = dns.name.from_text('dns.google.') + q = dns.message.make_query(qname, dns.rdatatype.A) + response = dns.query.udp(q, address, timeout=2) + rrs = response.get_rrset(response.answer, qname, + dns.rdataclass.IN, dns.rdatatype.A) + self.assertTrue(rrs is not None) + seen = set([rdata.address for rdata in rrs]) + self.assertTrue('8.8.8.8' in seen) + self.assertTrue('8.8.4.4' in seen) + + def testQueryUDPWithSocket(self): + for address in query_addresses: + with socket.socket(dns.inet.af_for_address(address), + socket.SOCK_DGRAM) as s: + s.setblocking(0) + qname = dns.name.from_text('dns.google.') + q = dns.message.make_query(qname, dns.rdatatype.A) + response = dns.query.udp(q, address, sock=s, timeout=2) + rrs = response.get_rrset(response.answer, qname, + dns.rdataclass.IN, dns.rdatatype.A) + self.assertTrue(rrs is not None) + seen = set([rdata.address for rdata in rrs]) + self.assertTrue('8.8.8.8' in seen) + self.assertTrue('8.8.4.4' in seen) + + def testQueryTCP(self): + for address in query_addresses: + qname = dns.name.from_text('dns.google.') + q = dns.message.make_query(qname, dns.rdatatype.A) + response = dns.query.tcp(q, address, timeout=2) + rrs = response.get_rrset(response.answer, qname, + dns.rdataclass.IN, dns.rdatatype.A) + self.assertTrue(rrs is not None) + seen = set([rdata.address for rdata in rrs]) + self.assertTrue('8.8.8.8' in seen) + self.assertTrue('8.8.4.4' in seen) + + def testQueryTCPWithSocket(self): + for address in query_addresses: + with socket.socket(dns.inet.af_for_address(address), + socket.SOCK_STREAM) as s: + ll = dns.inet.low_level_address_tuple((address, 53)) + s.settimeout(2) + s.connect(ll) + s.setblocking(0) + qname = dns.name.from_text('dns.google.') + q = dns.message.make_query(qname, dns.rdatatype.A) + response = dns.query.tcp(q, None, sock=s, timeout=2) + rrs = response.get_rrset(response.answer, qname, + dns.rdataclass.IN, dns.rdatatype.A) + self.assertTrue(rrs is not None) + seen = set([rdata.address for rdata in rrs]) + self.assertTrue('8.8.8.8' in seen) + self.assertTrue('8.8.4.4' in seen) + + def testQueryTLS(self): + for address in query_addresses: + qname = dns.name.from_text('dns.google.') + q = dns.message.make_query(qname, dns.rdatatype.A) + response = dns.query.tls(q, address, timeout=2) + rrs = response.get_rrset(response.answer, qname, + dns.rdataclass.IN, dns.rdatatype.A) + self.assertTrue(rrs is not None) + seen = set([rdata.address for rdata in rrs]) + self.assertTrue('8.8.8.8' in seen) + self.assertTrue('8.8.4.4' in seen) + + @unittest.skipUnless(have_ssl, "No SSL support") + def testQueryTLSWithSocket(self): + for address in query_addresses: + with socket.socket(dns.inet.af_for_address(address), + socket.SOCK_STREAM) as base_s: + ll = dns.inet.low_level_address_tuple((address, 853)) + base_s.settimeout(2) + base_s.connect(ll) + ctx = ssl.create_default_context() + with ctx.wrap_socket(base_s, server_hostname='dns.google') as s: + s.setblocking(0) + qname = dns.name.from_text('dns.google.') + q = dns.message.make_query(qname, dns.rdatatype.A) + response = dns.query.tls(q, None, sock=s, timeout=2) + rrs = response.get_rrset(response.answer, qname, + dns.rdataclass.IN, dns.rdatatype.A) + self.assertTrue(rrs is not None) + seen = set([rdata.address for rdata in rrs]) + self.assertTrue('8.8.8.8' in seen) + self.assertTrue('8.8.4.4' in seen) + + def testQueryUDPFallback(self): + for address in query_addresses: + qname = dns.name.from_text('.') + q = dns.message.make_query(qname, dns.rdatatype.DNSKEY) + (_, tcp) = dns.query.udp_with_fallback(q, address, timeout=2) + self.assertTrue(tcp) + + def testQueryUDPFallbackWithSocket(self): + for address in query_addresses: + af = dns.inet.af_for_address(address) + with socket.socket(af, socket.SOCK_DGRAM) as udp_s: + udp_s.setblocking(0) + with socket.socket(af, socket.SOCK_STREAM) as tcp_s: + ll = dns.inet.low_level_address_tuple((address, 53)) + tcp_s.settimeout(2) + tcp_s.connect(ll) + tcp_s.setblocking(0) + qname = dns.name.from_text('.') + q = dns.message.make_query(qname, dns.rdatatype.DNSKEY) + (_, tcp) = dns.query.udp_with_fallback(q, address, + udp_sock=udp_s, + tcp_sock=tcp_s, + timeout=2) + self.assertTrue(tcp) + + def testQueryUDPFallbackNoFallback(self): + for address in query_addresses: + qname = dns.name.from_text('dns.google.') + q = dns.message.make_query(qname, dns.rdatatype.A) + (_, tcp) = dns.query.udp_with_fallback(q, address, timeout=2) + self.assertFalse(tcp) + + def testUDPReceiveQuery(self): + with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as listener: + listener.bind(('127.0.0.1', 0)) + with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sender: + sender.bind(('127.0.0.1', 0)) + q = dns.message.make_query('dns.google', dns.rdatatype.A) + dns.query.send_udp(sender, q, listener.getsockname()) + expiration = time.time() + 2 + (q, _, addr) = dns.query.receive_udp(listener, + expiration=expiration) + self.assertEqual(addr, sender.getsockname()) + + +# for brevity +_d_and_s = dns.query._destination_and_source + +class DestinationAndSourceTests(unittest.TestCase): + + def test_af_inferred_from_where(self): + (af, d, s) = _d_and_s('1.2.3.4', 53, None, 0) + self.assertEqual(af, socket.AF_INET) + + def test_af_inferred_from_where(self): + (af, d, s) = _d_and_s('1::2', 53, None, 0) + self.assertEqual(af, socket.AF_INET6) + + def test_af_inferred_from_source(self): + (af, d, s) = _d_and_s('https://example/dns-query', 443, + '1.2.3.4', 0, False) + self.assertEqual(af, socket.AF_INET) + + def test_af_mismatch(self): + def bad(): + (af, d, s) = _d_and_s('1::2', 53, '1.2.3.4', 0) + self.assertRaises(ValueError, bad) + + def test_source_port_but_no_af_inferred(self): + def bad(): + (af, d, s) = _d_and_s('https://example/dns-query', 443, + None, 12345, False) + self.assertRaises(ValueError, bad) + + def test_where_must_be_an_address(self): + def bad(): + (af, d, s) = _d_and_s('not a valid address', 53, '1.2.3.4', 0) + self.assertRaises(ValueError, bad) + + def test_destination_is_none_of_where_url(self): + (af, d, s) = _d_and_s('https://example/dns-query', 443, None, 0, False) + self.assertEqual(d, None) + + def test_v4_wildcard_source_set(self): + (af, d, s) = _d_and_s('1.2.3.4', 53, None, 12345) + self.assertEqual(s, ('0.0.0.0', 12345)) + + def test_v6_wildcard_source_set(self): + (af, d, s) = _d_and_s('1::2', 53, None, 12345) + self.assertEqual(s, ('::', 12345, 0, 0)) + + +class AddressesEqualTestCase(unittest.TestCase): + + def test_v4(self): + self.assertTrue(dns.query._addresses_equal(socket.AF_INET, + ('10.0.0.1', 53), + ('10.0.0.1', 53))) + self.assertFalse(dns.query._addresses_equal(socket.AF_INET, + ('10.0.0.1', 53), + ('10.0.0.2', 53))) + + def test_v6(self): + self.assertTrue(dns.query._addresses_equal(socket.AF_INET6, + ('1::1', 53), + ('0001:0000::1', 53))) + self.assertFalse(dns.query._addresses_equal(socket.AF_INET6, + ('::1', 53), + ('::2', 53))) + + def test_mixed(self): + self.assertFalse(dns.query._addresses_equal(socket.AF_INET, + ('10.0.0.1', 53), + ('::2', 53))) + + +axfr_zone = ''' +$TTL 300 +@ SOA ns1 root 1 7200 900 1209600 86400 +@ NS ns1 +@ NS ns2 +ns1 A 10.0.0.1 +ns2 A 10.0.0.1 +''' + +class AXFRNanoNameserver(Server): + + def handle(self, request): + self.zone = dns.zone.from_text(axfr_zone, origin=self.origin) + self.origin = self.zone.origin + items = [] + soa = self.zone.find_rrset(dns.name.empty, dns.rdatatype.SOA) + response = dns.message.make_response(request.message) + response.flags |= dns.flags.AA + response.answer.append(soa) + items.append(response) + response = dns.message.make_response(request.message) + response.question = [] + response.flags |= dns.flags.AA + for (name, rdataset) in self.zone.iterate_rdatasets(): + if rdataset.rdtype == dns.rdatatype.SOA and \ + name == dns.name.empty: + continue + rrset = dns.rrset.RRset(name, rdataset.rdclass, rdataset.rdtype, + rdataset.covers) + rrset.update(rdataset) + response.answer.append(rrset) + items.append(response) + response = dns.message.make_response(request.message) + response.question = [] + response.flags |= dns.flags.AA + response.answer.append(soa) + items.append(response) + return items + +ixfr_message = '''id 12345 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN IXFR +;ANSWER +example. 300 IN SOA ns1.example. root.example. 4 7200 900 1209600 86400 +example. 300 IN SOA ns1.example. root.example. 2 7200 900 1209600 86400 +deleted.example. 300 IN A 10.0.0.1 +changed.example. 300 IN A 10.0.0.2 +example. 300 IN SOA ns1.example. root.example. 3 7200 900 1209600 86400 +changed.example. 300 IN A 10.0.0.4 +added.example. 300 IN A 10.0.0.3 +example. 300 SOA ns1.example. root.example. 3 7200 900 1209600 86400 +example. 300 IN SOA ns1.example. root.example. 4 7200 900 1209600 86400 +added2.example. 300 IN A 10.0.0.5 +example. 300 IN SOA ns1.example. root.example. 4 7200 900 1209600 86400 +''' + +ixfr_trailing_junk = ixfr_message + 'junk.example. 300 IN A 10.0.0.6' + +ixfr_up_to_date_message = '''id 12345 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN IXFR +;ANSWER +example. 300 IN SOA ns1.example. root.example. 2 7200 900 1209600 86400 +''' + +axfr_trailing_junk = '''id 12345 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN AXFR +;ANSWER +example. 300 IN SOA ns1.example. root.example. 3 7200 900 1209600 86400 +added.example. 300 IN A 10.0.0.3 +added2.example. 300 IN A 10.0.0.5 +changed.example. 300 IN A 10.0.0.4 +example. 300 IN SOA ns1.example. root.example. 3 7200 900 1209600 86400 +junk.example. 300 IN A 10.0.0.6 +''' + +class IXFRNanoNameserver(Server): + + def __init__(self, response_text): + super().__init__() + self.response_text = response_text + + def handle(self, request): + try: + r = dns.message.from_text(self.response_text, one_rr_per_rrset=True) + r.id = request.message.id + return r + except Exception: + pass + +@unittest.skipIf(not _nanonameserver_available, "nanonameserver required") +class XfrTests(unittest.TestCase): + + def test_axfr(self): + expected = dns.zone.from_text(axfr_zone, origin='example') + with AXFRNanoNameserver(origin='example') as ns: + xfr = dns.query.xfr(ns.tcp_address[0], 'example', + port=ns.tcp_address[1]) + zone = dns.zone.from_xfr(xfr) + self.assertEqual(zone, expected) + + def test_axfr_tsig(self): + expected = dns.zone.from_text(axfr_zone, origin='example') + with AXFRNanoNameserver(origin='example', keyring=keyring) as ns: + xfr = dns.query.xfr(ns.tcp_address[0], 'example', + port=ns.tcp_address[1], + keyring=keyring, keyname='name') + zone = dns.zone.from_xfr(xfr) + self.assertEqual(zone, expected) + + def test_axfr_root_tsig(self): + expected = dns.zone.from_text(axfr_zone, origin='.') + with AXFRNanoNameserver(origin='.', keyring=keyring) as ns: + xfr = dns.query.xfr(ns.tcp_address[0], '.', + port=ns.tcp_address[1], + keyring=keyring, keyname='name') + zone = dns.zone.from_xfr(xfr) + self.assertEqual(zone, expected) + + def test_axfr_udp(self): + def bad(): + with AXFRNanoNameserver(origin='example') as ns: + xfr = dns.query.xfr(ns.udp_address[0], 'example', + port=ns.udp_address[1], use_udp=True) + l = list(xfr) + self.assertRaises(ValueError, bad) + + def test_axfr_bad_rcode(self): + def bad(): + # We just use Server here as by default it will refuse. + with Server() as ns: + xfr = dns.query.xfr(ns.tcp_address[0], 'example', + port=ns.tcp_address[1]) + l = list(xfr) + self.assertRaises(dns.query.TransferError, bad) + + def test_axfr_trailing_junk(self): + # we use the IXFR server here as it returns messages + def bad(): + with IXFRNanoNameserver(axfr_trailing_junk) as ns: + xfr = dns.query.xfr(ns.tcp_address[0], 'example', + dns.rdatatype.AXFR, + port=ns.tcp_address[1]) + l = list(xfr) + self.assertRaises(dns.exception.FormError, bad) + + def test_ixfr_tcp(self): + with IXFRNanoNameserver(ixfr_message) as ns: + xfr = dns.query.xfr(ns.tcp_address[0], 'example', + dns.rdatatype.IXFR, + port=ns.tcp_address[1], + serial=2, + relativize=False) + l = list(xfr) + self.assertEqual(len(l), 1) + expected = dns.message.from_text(ixfr_message, + one_rr_per_rrset=True) + expected.id = l[0].id + self.assertEqual(l[0], expected) + + def test_ixfr_udp(self): + with IXFRNanoNameserver(ixfr_message) as ns: + xfr = dns.query.xfr(ns.udp_address[0], 'example', + dns.rdatatype.IXFR, + port=ns.udp_address[1], + serial=2, + relativize=False, use_udp=True) + l = list(xfr) + self.assertEqual(len(l), 1) + expected = dns.message.from_text(ixfr_message, + one_rr_per_rrset=True) + expected.id = l[0].id + self.assertEqual(l[0], expected) + + def test_ixfr_up_to_date(self): + with IXFRNanoNameserver(ixfr_up_to_date_message) as ns: + xfr = dns.query.xfr(ns.tcp_address[0], 'example', + dns.rdatatype.IXFR, + port=ns.tcp_address[1], + serial=2, + relativize=False) + l = list(xfr) + self.assertEqual(len(l), 1) + expected = dns.message.from_text(ixfr_up_to_date_message, + one_rr_per_rrset=True) + expected.id = l[0].id + self.assertEqual(l[0], expected) + + def test_ixfr_trailing_junk(self): + def bad(): + with IXFRNanoNameserver(ixfr_trailing_junk) as ns: + xfr = dns.query.xfr(ns.tcp_address[0], 'example', + dns.rdatatype.IXFR, + port=ns.tcp_address[1], + serial=2, + relativize=False) + l = list(xfr) + self.assertRaises(dns.exception.FormError, bad) + + def test_ixfr_base_serial_mismatch(self): + def bad(): + with IXFRNanoNameserver(ixfr_message) as ns: + xfr = dns.query.xfr(ns.tcp_address[0], 'example', + dns.rdatatype.IXFR, + port=ns.tcp_address[1], + serial=1, + relativize=False) + l = list(xfr) + self.assertRaises(dns.exception.FormError, bad) + +class TSIGNanoNameserver(Server): + + def handle(self, request): + response = dns.message.make_response(request.message) + response.set_rcode(dns.rcode.REFUSED) + response.flags |= dns.flags.RA + try: + if request.qtype == dns.rdatatype.A and \ + request.qclass == dns.rdataclass.IN: + rrs = dns.rrset.from_text(request.qname, 300, + 'IN', 'A', '1.2.3.4') + response.answer.append(rrs) + response.set_rcode(dns.rcode.NOERROR) + response.flags |= dns.flags.AA + except Exception: + pass + return response + +@unittest.skipIf(not _nanonameserver_available, "nanonameserver required") +class TsigTests(unittest.TestCase): + + def test_tsig(self): + with TSIGNanoNameserver(keyring=keyring) as ns: + qname = dns.name.from_text('example.com') + q = dns.message.make_query(qname, 'A') + q.use_tsig(keyring=keyring, keyname='name') + response = dns.query.udp(q, ns.udp_address[0], + port=ns.udp_address[1]) + self.assertTrue(response.had_tsig) + rrs = response.get_rrset(response.answer, qname, + dns.rdataclass.IN, dns.rdatatype.A) + self.assertTrue(rrs is not None) + seen = set([rdata.address for rdata in rrs]) + self.assertTrue('1.2.3.4' in seen) + +@unittest.skipIf(sys.platform == 'win32', + 'low level tests do not work on win32') +class LowLevelWaitTests(unittest.TestCase): + + def test_wait_for(self): + try: + (l, r) = socket.socketpair() + # already expired + with self.assertRaises(dns.exception.Timeout): + dns.query._wait_for(l, True, True, True, 0) + # simple timeout + with self.assertRaises(dns.exception.Timeout): + dns.query._wait_for(l, False, False, False, time.time() + 0.05) + # writable no timeout (not hanging is passing) + dns.query._wait_for(l, False, True, False, None) + finally: + l.close() + r.close() + + +class MiscTests(unittest.TestCase): + def test_matches_destination(self): + self.assertTrue(dns.query._matches_destination(socket.AF_INET, + ('10.0.0.1', 1234), + ('10.0.0.1', 1234), + True)) + self.assertTrue(dns.query._matches_destination(socket.AF_INET6, + ('1::2', 1234), + ('0001::2', 1234), + True)) + self.assertTrue(dns.query._matches_destination(socket.AF_INET, + ('10.0.0.1', 1234), + None, + True)) + self.assertFalse(dns.query._matches_destination(socket.AF_INET, + ('10.0.0.1', 1234), + ('10.0.0.2', 1234), + True)) + self.assertFalse(dns.query._matches_destination(socket.AF_INET, + ('10.0.0.1', 1234), + ('10.0.0.1', 1235), + True)) + with self.assertRaises(dns.query.UnexpectedSource): + dns.query._matches_destination(socket.AF_INET, + ('10.0.0.1', 1234), + ('10.0.0.1', 1235), + False) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_rdata.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_rdata.py new file mode 100644 index 0000000..45ceb29 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_rdata.py @@ -0,0 +1,870 @@ +# -*- coding: utf-8 +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import io +import operator +import pickle +import struct +import unittest + +import dns.wire +import dns.exception +import dns.name +import dns.rdata +import dns.rdataclass +import dns.rdataset +import dns.rdatatype +from dns.rdtypes.ANY.OPT import OPT +from dns.rdtypes.ANY.LOC import LOC +from dns.rdtypes.ANY.GPOS import GPOS +import dns.rdtypes.ANY.RRSIG +import dns.rdtypes.util +import dns.tokenizer +import dns.ttl +import dns.wire + +import tests.stxt_module +import tests.ttxt_module +import tests.md_module +from tests.util import here + +class RdataTestCase(unittest.TestCase): + + def test_str(self): + rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + "1.2.3.4") + self.assertEqual(rdata.address, "1.2.3.4") + + def test_unicode(self): + rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + u"1.2.3.4") + self.assertEqual(rdata.address, "1.2.3.4") + + def test_module_registration(self): + TTXT = 64001 + dns.rdata.register_type(tests.ttxt_module, TTXT, 'TTXT') + rdata = dns.rdata.from_text(dns.rdataclass.IN, TTXT, 'hello world') + self.assertEqual(rdata.strings, (b'hello', b'world')) + self.assertEqual(dns.rdatatype.to_text(TTXT), 'TTXT') + self.assertEqual(dns.rdatatype.from_text('TTXT'), TTXT) + + def test_module_reregistration(self): + def bad(): + TTXTTWO = dns.rdatatype.TXT + dns.rdata.register_type(tests.ttxt_module, TTXTTWO, 'TTXTTWO') + self.assertRaises(dns.rdata.RdatatypeExists, bad) + + def test_module_registration_singleton(self): + STXT = 64002 + dns.rdata.register_type(tests.stxt_module, STXT, 'STXT', + is_singleton=True) + rdata1 = dns.rdata.from_text(dns.rdataclass.IN, STXT, 'hello') + rdata2 = dns.rdata.from_text(dns.rdataclass.IN, STXT, 'world') + rdataset = dns.rdataset.from_rdata(3600, rdata1, rdata2) + self.assertEqual(len(rdataset), 1) + self.assertEqual(rdataset[0].strings, (b'world',)) + + def test_replace(self): + a1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "1.2.3.4") + a2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "2.3.4.5") + self.assertEqual(a1.replace(address="2.3.4.5"), a2) + + mx = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, + "10 foo.example") + name = dns.name.from_text("bar.example") + self.assertEqual(mx.replace(preference=20).preference, 20) + self.assertEqual(mx.replace(preference=20).exchange, mx.exchange) + self.assertEqual(mx.replace(exchange=name).exchange, name) + self.assertEqual(mx.replace(exchange=name).preference, mx.preference) + + for invalid_parameter in ("rdclass", "rdtype", "foo", "__class__"): + with self.assertRaises(AttributeError): + mx.replace(invalid_parameter=1) + + def test_invalid_replace(self): + a1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "1.2.3.4") + with self.assertRaises(dns.exception.SyntaxError): + a1.replace(address="bogus") + + def test_replace_comment(self): + a1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + "1.2.3.4 ;foo") + self.assertEqual(a1.rdcomment, "foo") + a2 = a1.replace(rdcomment="bar") + self.assertEqual(a1, a2) + self.assertEqual(a1.rdcomment, "foo") + self.assertEqual(a2.rdcomment, "bar") + + def test_no_replace_class_or_type(self): + a1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "1.2.3.4") + with self.assertRaises(AttributeError): + a1.replace(rdclass=255) + with self.assertRaises(AttributeError): + a1.replace(rdtype=2) + + def test_to_generic(self): + a = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "1.2.3.4") + self.assertEqual(str(a.to_generic()), r'\# 4 01020304') + + mx = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "10 foo.") + self.assertEqual(str(mx.to_generic()), r'\# 7 000a03666f6f00') + + origin = dns.name.from_text('example') + ns = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + "foo.example.", relativize_to=origin) + self.assertEqual(str(ns.to_generic(origin=origin)), + r'\# 13 03666f6f076578616d706c6500') + + def test_txt_unicode(self): + # TXT records are not defined for Unicode, but if we get + # Unicode we should convert it to UTF-8 to preserve meaning as + # best we can. Note that it when the TXT record is sent + # to_text(), it does NOT convert embedded UTF-8 back to + # Unicode; it's just treated as binary TXT data. Probably + # there should be a TXT-like record with an encoding field. + rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.TXT, + '"foo\u200bbar"') + self.assertEqual(str(rdata), '"foo\\226\\128\\139bar"') + # We used to encode UTF-8 in UTF-8 because we processed + # escapes in quoted strings immediately. This meant that the + # \\226 below would be inserted as Unicode code point 226, and + # then when we did to_text, we would UTF-8 encode that code + # point, emitting \\195\\162 instead of \\226, and thus + # from_text followed by to_text was not the equal to the + # original input like it ought to be. + rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.TXT, + '"foo\\226\\128\\139bar"') + self.assertEqual(str(rdata), '"foo\\226\\128\\139bar"') + # Our fix for TXT-like records uses a new tokenizer method, + # unescape_to_bytes(), which converts Unicode to UTF-8 only + # once. + rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.TXT, + '"foo\u200b\\123bar"') + self.assertEqual(str(rdata), '"foo\\226\\128\\139{bar"') + + def test_unicode_idna2003_in_rdata(self): + rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + "Königsgäßchen") + self.assertEqual(str(rdata.target), 'xn--knigsgsschen-lcb0w') + + @unittest.skipUnless(dns.name.have_idna_2008, + 'Python idna cannot be imported; no IDNA2008') + def test_unicode_idna2008_in_rdata(self): + rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + "Königsgäßchen", + idna_codec=dns.name.IDNA_2008) + self.assertEqual(str(rdata.target), 'xn--knigsgchen-b4a3dun') + + def test_digestable_downcasing(self): + # Make sure all the types listed in RFC 4034 section 6.2 are + # downcased properly, except for: + # + # types we don't implement: MD, MF, MB, MG, MR, MINFO, SIG, + # NXT, A6 + # + # types that don't have names: HINFO + # + # NSEC3, whose downcasing was removed by RFC 6840 section 5.1 + # + cases = [ + ('SOA', 'NAME NAME 1 2 3 4 5'), + ('AFSDB', '0 NAME'), + ('CNAME', 'NAME'), + ('DNAME', 'NAME'), + ('KX', '10 NAME'), + ('MX', '10 NAME'), + ('NS', 'NAME'), + ('NAPTR', '0 0 a B c NAME'), + ('PTR', 'NAME'), + ('PX', '65535 NAME NAME'), + ('RP', 'NAME NAME'), + ('RT', '0 NAME'), + ('SRV', '0 0 0 NAME'), + ('RRSIG', + 'A 1 3 3600 20200701000000 20200601000000 1 NAME Ym9ndXM=') + ] + for rdtype, text in cases: + upper_origin = dns.name.from_text('EXAMPLE') + lower_origin = dns.name.from_text('example') + canonical_text = text.replace('NAME', 'name') + rdata = dns.rdata.from_text(dns.rdataclass.IN, rdtype, text, + origin=upper_origin, relativize=False) + canonical_rdata = dns.rdata.from_text(dns.rdataclass.IN, rdtype, + canonical_text, + origin=lower_origin, + relativize=False) + digestable_wire = rdata.to_digestable() + f = io.BytesIO() + canonical_rdata.to_wire(f) + expected_wire = f.getvalue() + self.assertEqual(digestable_wire, expected_wire) + + def test_digestable_no_downcasing(self): + # Make sure that currently known types with domain names that + # are NOT supposed to be downcased when canonicalized are + # handled properly. + # + cases = [ + ('HIP', '2 200100107B1A74DF365639CC39F1D578 Ym9ndXM= NAME name'), + ('IPSECKEY', '10 3 2 NAME Ym9ndXM='), + ('NSEC', 'NAME A'), + ] + for rdtype, text in cases: + origin = dns.name.from_text('example') + rdata = dns.rdata.from_text(dns.rdataclass.IN, rdtype, text, + origin=origin, relativize=False) + digestable_wire = rdata.to_digestable(origin) + expected_wire = rdata.to_wire(origin=origin) + self.assertEqual(digestable_wire, expected_wire) + + def test_basic_relations(self): + r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1') + r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.2') + self.assertTrue(r1 == r1) + self.assertTrue(r1 != r2) + self.assertTrue(r1 < r2) + self.assertTrue(r1 <= r2) + self.assertTrue(r2 > r1) + self.assertTrue(r2 >= r1) + + def test_incompatible_relations(self): + r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1') + r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.AAAA, + '::1') + for oper in [operator.lt, operator.le, operator.ge, operator.gt]: + self.assertRaises(TypeError, lambda: oper(r1, r2)) + self.assertFalse(r1 == r2) + self.assertTrue(r1 != r2) + + def test_immutability(self): + def bad1(): + r = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1') + r.address = '10.0.0.2' + self.assertRaises(TypeError, bad1) + def bad2(): + r = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1') + del r.address + self.assertRaises(TypeError, bad2) + + def test_pickle(self): + r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1') + p = pickle.dumps(r1) + r2 = pickle.loads(p) + self.assertEqual(r1, r2) + # Pickle something with a longer inheritance chain + r3 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, + '10 mail.example.') + p = pickle.dumps(r3) + r4 = pickle.loads(p) + self.assertEqual(r3, r4) + + def test_AFSDB_properties(self): + rd = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.AFSDB, + '0 afsdb.example.') + self.assertEqual(rd.preference, rd.subtype) + self.assertEqual(rd.exchange, rd.hostname) + + def equal_loc(self, a, b): + rda = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.LOC, a) + rdb = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.LOC, b) + self.assertEqual(rda, rdb) + + def test_misc_good_LOC_text(self): + # test just degrees + self.equal_loc('60 N 24 39 0.000 E 10.00m 20m 2000m 20m', + '60 0 0 N 24 39 0.000 E 10.00m 20m 2000m 20m') + self.equal_loc('60 0 0 N 24 E 10.00m 20m 2000m 20m', + '60 0 0 N 24 0 0 E 10.00m 20m 2000m 20m') + # test variable length latitude + self.equal_loc('60 9 0.510 N 24 39 0.000 E 10.00m 20m 2000m 20m', + '60 9 0.51 N 24 39 0.000 E 10.00m 20m 2000m 20m') + self.equal_loc('60 9 0.500 N 24 39 0.000 E 10.00m 20m 2000m 20m', + '60 9 0.5 N 24 39 0.000 E 10.00m 20m 2000m 20m') + self.equal_loc('60 9 1.000 N 24 39 0.000 E 10.00m 20m 2000m 20m', + '60 9 1 N 24 39 0.000 E 10.00m 20m 2000m 20m') + # test variable length longtitude + self.equal_loc('60 9 0.000 N 24 39 0.510 E 10.00m 20m 2000m 20m', + '60 9 0.000 N 24 39 0.51 E 10.00m 20m 2000m 20m') + self.equal_loc('60 9 0.000 N 24 39 0.500 E 10.00m 20m 2000m 20m', + '60 9 0.000 N 24 39 0.5 E 10.00m 20m 2000m 20m') + self.equal_loc('60 9 0.000 N 24 39 1.000 E 10.00m 20m 2000m 20m', + '60 9 0.000 N 24 39 1 E 10.00m 20m 2000m 20m') + # test siz, hp, vp defaults + self.equal_loc('60 9 0.510 N 24 39 0.000 E 10.00m', + '60 9 0.51 N 24 39 0.000 E 10.00m 1m 10000m 10m') + self.equal_loc('60 9 0.510 N 24 39 0.000 E 10.00m 2m', + '60 9 0.51 N 24 39 0.000 E 10.00m 2m 10000m 10m') + self.equal_loc('60 9 0.510 N 24 39 0.000 E 10.00m 2m 2000m', + '60 9 0.51 N 24 39 0.000 E 10.00m 2m 2000m 10m') + # test siz, hp, vp optional units + self.equal_loc('60 9 0.510 N 24 39 0.000 E 1m 20m 2000m 20m', + '60 9 0.51 N 24 39 0.000 E 1 20 2000 20') + + def test_LOC_to_text_SW_hemispheres(self): + # As an extra, we test int->float conversion in the constructor + loc = LOC(dns.rdataclass.IN, dns.rdatatype.LOC, -60, -24, 1) + text = '60 0 0.000 S 24 0 0.000 W 0.01m' + self.assertEqual(loc.to_text(), text) + + def test_zero_size(self): + # This is to exercise the 0 path in _exponent_of. + loc = dns.rdata.from_text('in', 'loc', '60 S 24 W 1 0') + self.assertEqual(loc.size, 0.0) + + def test_bad_LOC_text(self): + bad_locs = ['60 9 a.000 N 24 39 0.000 E 10.00m 20m 2000m 20m', + '60 9 60.000 N 24 39 0.000 E 10.00m 20m 2000m 20m', + '60 9 0.00a N 24 39 0.000 E 10.00m 20m 2000m 20m', + '60 9 0.0001 N 24 39 0.000 E 10.00m 20m 2000m 20m', + '60 9 0.000 Z 24 39 0.000 E 10.00m 20m 2000m 20m', + '91 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m', + '60 60 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m', + + '60 9 0.000 N 24 39 a.000 E 10.00m 20m 2000m 20m', + '60 9 0.000 N 24 39 60.000 E 10.00m 20m 2000m 20m', + '60 9 0.000 N 24 39 0.00a E 10.00m 20m 2000m 20m', + '60 9 0.000 N 24 39 0.0001 E 10.00m 20m 2000m 20m', + '60 9 0.000 N 24 39 0.000 Z 10.00m 20m 2000m 20m', + '60 9 0.000 N 181 39 0.000 E 10.00m 20m 2000m 20m', + '60 9 0.000 N 24 60 0.000 E 10.00m 20m 2000m 20m', + + '60 9 0.000 N 24 39 0.000 E 10.00m 100000000m 2000m 20m', + '60 9 0.000 N 24 39 0.000 E 10.00m 20m 100000000m 20m', + '60 9 0.000 N 24 39 0.000 E 10.00m 20m 20m 100000000m', + ] + for loc in bad_locs: + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.LOC, loc) + + def test_bad_LOC_wire(self): + bad_locs = [(0, 0, 0, 0x934fd901, 0x80000000, 100), + (0, 0, 0, 0x6cb026ff, 0x80000000, 100), + (0, 0, 0, 0x80000000, 0xa69fb201, 100), + (0, 0, 0, 0x80000000, 0x59604dff, 100), + (0xa0, 0, 0, 0x80000000, 0x80000000, 100), + (0x0a, 0, 0, 0x80000000, 0x80000000, 100), + (0, 0xa0, 0, 0x80000000, 0x80000000, 100), + (0, 0x0a, 0, 0x80000000, 0x80000000, 100), + (0, 0, 0xa0, 0x80000000, 0x80000000, 100), + (0, 0, 0x0a, 0x80000000, 0x80000000, 100), + ] + for t in bad_locs: + with self.assertRaises(dns.exception.FormError): + wire = struct.pack('!BBBBIII', 0, t[0], t[1], t[2], + t[3], t[4], t[5]) + dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.LOC, + wire, 0, len(wire)) + with self.assertRaises(dns.exception.FormError): + wire = struct.pack('!BBBBIII', 1, 0, 0, 0, 0, 0, 0) + dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.LOC, + wire, 0, len(wire)) + + def equal_wks(self, a, b): + rda = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.WKS, a) + rdb = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.WKS, b) + self.assertEqual(rda, rdb) + + def test_misc_good_WKS_text(self): + self.equal_wks('10.0.0.1 tcp ( http )', '10.0.0.1 6 ( 80 )') + self.equal_wks('10.0.0.1 udp ( domain )', '10.0.0.1 17 ( 53 )') + + def test_misc_bad_WKS_text(self): + try: + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.WKS, + '10.0.0.1 132 ( domain )') + self.assertTrue(False) # should not happen + except dns.exception.SyntaxError as e: + self.assertIsInstance(e.__cause__, NotImplementedError) + + def test_GPOS_float_converters(self): + rd = dns.rdata.from_text('in', 'gpos', '49 0 0') + self.assertEqual(rd.float_latitude, 49.0) + self.assertEqual(rd.float_longitude, 0.0) + self.assertEqual(rd.float_altitude, 0.0) + + def test_GPOS_constructor_conversion(self): + rd = GPOS(dns.rdataclass.IN, dns.rdatatype.GPOS, 49.0, 0.0, 0.0) + self.assertEqual(rd.float_latitude, 49.0) + self.assertEqual(rd.float_longitude, 0.0) + self.assertEqual(rd.float_altitude, 0.0) + rd = GPOS(dns.rdataclass.IN, dns.rdatatype.GPOS, 49, 0, 0) + self.assertEqual(rd.float_latitude, 49.0) + self.assertEqual(rd.float_longitude, 0.0) + self.assertEqual(rd.float_altitude, 0.0) + + def test_bad_GPOS_text(self): + bad_gpos = ['"-" "116.8652" "250"', + '"+" "116.8652" "250"', + '"" "116.8652" "250"', + '"." "116.8652" "250"', + '".a" "116.8652" "250"', + '"a." "116.8652" "250"', + '"a.a" "116.8652" "250"', + # We don't need to test all the bad permutations again + # but we do want to test that badness is detected + # in the other strings + '"0" "a" "250"', + '"0" "0" "a"', + # finally test bounds + '"90.1" "0" "0"', + '"-90.1" "0" "0"', + '"0" "180.1" "0"', + '"0" "-180.1" "0"', + ] + for gpos in bad_gpos: + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.GPOS, gpos) + + def test_bad_GPOS_wire(self): + bad_gpos = [b'\x01', + b'\x01\x31\x01', + b'\x01\x31\x01\x31\x01', + ] + for wire in bad_gpos: + self.assertRaises(dns.exception.FormError, + lambda: dns.rdata.from_wire(dns.rdataclass.IN, + dns.rdatatype.GPOS, + wire, 0, len(wire))) + + def test_chaos(self): + # avoid red spot on our coverage :) + r1 = dns.rdata.from_text(dns.rdataclass.CH, dns.rdatatype.A, + 'chaos. 12345') + w = r1.to_wire() + r2 = dns.rdata.from_wire(dns.rdataclass.CH, dns.rdatatype.A, w, 0, + len(w)) + self.assertEqual(r1, r2) + self.assertEqual(r1.domain, dns.name.from_text('chaos')) + # the address input is octal + self.assertEqual(r1.address, 0o12345) + self.assertEqual(r1.to_text(), 'chaos. 12345') + + def test_opt_repr(self): + opt = OPT(4096, dns.rdatatype.OPT, ()) + self.assertEqual(repr(opt), '') + + def test_opt_short_lengths(self): + with self.assertRaises(dns.exception.FormError): + parser = dns.wire.Parser(bytes.fromhex('f00102')) + OPT.from_wire_parser(4096, dns.rdatatype.OPT, parser) + with self.assertRaises(dns.exception.FormError): + parser = dns.wire.Parser(bytes.fromhex('f00100030000')) + OPT.from_wire_parser(4096, dns.rdatatype.OPT, parser) + + def test_from_wire_parser(self): + wire = bytes.fromhex('01020304') + rdata = dns.rdata.from_wire('in', 'a', wire, 0, 4) + self.assertEqual(rdata, dns.rdata.from_text('in', 'a', '1.2.3.4')) + + def test_unpickle(self): + expected_mx = dns.rdata.from_text('in', 'mx', '10 mx.example.') + with open(here('mx-2-0.pickle'), 'rb') as f: + mx = pickle.load(f) + self.assertEqual(mx, expected_mx) + self.assertIsNone(mx.rdcomment) + + def test_escaped_newline_in_quoted_string(self): + rd = dns.rdata.from_text('in', 'txt', '"foo\\\nbar"') + self.assertEqual(rd.strings, (b'foo\nbar',)) + self.assertEqual(rd.to_text(), '"foo\\010bar"') + + def test_escaped_newline_in_nonquoted_string(self): + with self.assertRaises(dns.exception.UnexpectedEnd): + dns.rdata.from_text('in', 'txt', 'foo\\\nbar') + + def test_wordbreak(self): + text = b'abcdefgh' + self.assertEqual(dns.rdata._wordbreak(text, 4), 'abcd efgh') + self.assertEqual(dns.rdata._wordbreak(text, 0), 'abcdefgh') + + def test_escapify(self): + self.assertEqual(dns.rdata._escapify('abc'), 'abc') + self.assertEqual(dns.rdata._escapify(b'abc'), 'abc') + self.assertEqual(dns.rdata._escapify(bytearray(b'abc')), 'abc') + self.assertEqual(dns.rdata._escapify(b'ab"c'), 'ab\\"c') + self.assertEqual(dns.rdata._escapify(b'ab\\c'), 'ab\\\\c') + self.assertEqual(dns.rdata._escapify(b'ab\x01c'), 'ab\\001c') + + def test_truncate_bitmap(self): + self.assertEqual(dns.rdata._truncate_bitmap(b'\x00\x01\x00\x00'), + b'\x00\x01') + self.assertEqual(dns.rdata._truncate_bitmap(b'\x00\x01\x00\x01'), + b'\x00\x01\x00\x01') + self.assertEqual(dns.rdata._truncate_bitmap(b'\x00\x00\x00\x00'), + b'\x00') + + def test_covers_and_extended_rdatatype(self): + rd = dns.rdata.from_text('in', 'a', '10.0.0.1') + self.assertEqual(rd.covers(), dns.rdatatype.NONE) + self.assertEqual(rd.extended_rdatatype(), 0x00000001) + rd = dns.rdata.from_text('in', 'rrsig', + 'NSEC 1 3 3600 ' + + '20200101000000 20030101000000 ' + + '2143 foo Ym9ndXM=') + self.assertEqual(rd.covers(), dns.rdatatype.NSEC) + self.assertEqual(rd.extended_rdatatype(), 0x002f002e) + + def test_uncomparable(self): + rd = dns.rdata.from_text('in', 'a', '10.0.0.1') + self.assertFalse(rd == 'a') + self.assertTrue(rd != 'a') + + def test_bad_generic(self): + # does not start with \# + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('in', 'type45678', '# 7 000a03666f6f00') + # wrong length + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('in', 'type45678', '\\# 6 000a03666f6f00') + + def test_covered_repr(self): + text = 'NSEC 1 3 3600 20190101000000 20030101000000 ' + \ + '2143 foo Ym9ndXM=' + rd = dns.rdata.from_text('in', 'rrsig', text) + self.assertEqual(repr(rd), '') + + def test_bad_registration_implementing_known_type_with_wrong_name(self): + # Try to register an implementation at the MG codepoint that isn't + # called "MG" + with self.assertRaises(dns.rdata.RdatatypeExists): + dns.rdata.register_type(None, dns.rdatatype.MG, 'NOTMG') + + def test_registration_implementing_known_type_with_right_name(self): + # Try to register an implementation at the MD codepoint + dns.rdata.register_type(tests.md_module, dns.rdatatype.MD, 'MD') + rd = dns.rdata.from_text('in', 'md', 'foo.') + self.assertEqual(rd.target, dns.name.from_text('foo.')) + + def test_CERT_with_string_type(self): + rd = dns.rdata.from_text('in', 'cert', 'SPKI 1 PRIVATEOID Ym9ndXM=') + self.assertEqual(rd.to_text(), 'SPKI 1 PRIVATEOID Ym9ndXM=') + + def test_CERT_algorithm(self): + rd = dns.rdata.from_text('in', 'cert', 'SPKI 1 0 Ym9ndXM=') + self.assertEqual(rd.algorithm, 0) + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('in', 'cert', 'SPKI 1 -1 Ym9ndXM=') + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('in', 'cert', 'SPKI 1 256 Ym9ndXM=') + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('in', 'cert', 'SPKI 1 BOGUS Ym9ndXM=') + + def test_bad_URI_text(self): + # empty target + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('in', 'uri', '10 1 ""') + # no target + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('in', 'uri', '10 1') + + def test_bad_URI_wire(self): + wire = bytes.fromhex('000a0001') + with self.assertRaises(dns.exception.FormError): + dns.rdata.from_wire('in', 'uri', wire, 0, 4) + + def test_bad_NSAP_text(self): + # does not start with 0x + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('in', 'nsap', '0y4700') + # odd hex string length + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('in', 'nsap', '0x470') + + def test_bad_CAA_text(self): + # tag too long + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('in', 'caa', + '0 ' + 'a' * 256 + ' "ca.example.net"') + # tag not alphanumeric + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('in', 'caa', + '0 a-b "ca.example.net"') + + def test_bad_HIP_text(self): + # hit too long + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('in', 'hip', + '2 ' + + '00' * 256 + + ' Ym9ndXM=') + + def test_bad_sigtime(self): + try: + dns.rdata.from_text('in', 'rrsig', + 'NSEC 1 3 3600 ' + + '202001010000000 20030101000000 ' + + '2143 foo Ym9ndXM=') + self.assertTrue(False) # should not happen + except dns.exception.SyntaxError as e: + self.assertIsInstance(e.__cause__, + dns.rdtypes.ANY.RRSIG.BadSigTime) + try: + dns.rdata.from_text('in', 'rrsig', + 'NSEC 1 3 3600 ' + + '20200101000000 2003010100000 ' + + '2143 foo Ym9ndXM=') + self.assertTrue(False) # should not happen + except dns.exception.SyntaxError as e: + self.assertIsInstance(e.__cause__, + dns.rdtypes.ANY.RRSIG.BadSigTime) + + def test_empty_TXT(self): + # hit too long + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('in', 'txt', '') + + def test_too_long_TXT(self): + # hit too long + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('in', 'txt', 'a' * 256) + + def equal_smimea(self, a, b): + a = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SMIMEA, a) + b = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SMIMEA, b) + self.assertEqual(a, b) + + def test_good_SMIMEA(self): + self.equal_smimea('3 0 1 aabbccddeeff', '3 0 01 AABBCCDDEEFF') + + def test_bad_SMIMEA(self): + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SMIMEA, '1 1 1 aGVsbG8gd29ybGQh') + + def test_DNSKEY_chunking(self): + inputs = ( # each with chunking as given by dig, unusual chunking, and no chunking + # example 1 + ( + '257 3 13 aCoEWYBBVsP9Fek2oC8yqU8ocKmnS1iDSFZNORnQuHKtJ9Wpyz+kNryq uB78Pyk/NTEoai5bxoipVQQXzHlzyg==', + '257 3 13 aCoEWYBBVsP9Fek2oC8yqU8ocK mnS1iDSFZNORnQuHKtJ9Wpyz+kNryquB78Pyk/ NTEoai5bxoipVQQXzHlzyg==', + '257 3 13 aCoEWYBBVsP9Fek2oC8yqU8ocKmnS1iDSFZNORnQuHKtJ9Wpyz+kNryquB78Pyk/NTEoai5bxoipVQQXzHlzyg==', + ), + # example 2 + ( + '257 3 8 AwEAAcw5QLr0IjC0wKbGoBPQv4qmeqHy9mvL5qGQTuaG5TSrNqEAR6b/ qvxDx6my4JmEmjUPA1JeEI9YfTUieMr2UZflu7aIbZFLw0vqiYrywCGr CHXLalOrEOmrvAxLvq4vHtuTlH7JIszzYBSes8g1vle6KG7xXiP3U5Ll 96Qiu6bZ31rlMQSPB20xbqJJh6psNSrQs41QvdcXAej+K2Hl1Wd8kPri ec4AgiBEh8sk5Pp8W9ROLQ7PcbqqttFaW2m7N/Wy4qcFU13roWKDEAst bxH5CHPoBfZSbIwK4KM6BK/uDHpSPIbiOvOCW+lvu9TAiZPc0oysY6as lO7jXv16Gws=', + '257 3 8 AwEAAcw5QLr0IjC0wKbGoBPQv4qmeq Hy9mvL5qGQTuaG5TSrNqEA R6b/qvxDx6my4JmEmjUPA1JeEI9Y fTUieMr2UZflu7aIbZFLw0vqiYrywCGrC HXLalOrEOmrvAxLvq4vHtuTlH7JIszzYBSes8g1vle6KG7 xXiP3U5Ll 96Qiu6bZ31rlMQSPB20xbqJJh6psNSrQs41QvdcXAej+K2Hl1Wd8kPriec4AgiBEh8sk5Pp8W9ROLQ7PcbqqttFaW2m7N/Wy4qcFU13roWKDEAst bxH5CHPoBfZSbIwK4KM6BK/uDHpSPIbiOvOCW+lvu9TAiZPc0oysY6as lO7jXv16Gws=', + '257 3 8 AwEAAcw5QLr0IjC0wKbGoBPQv4qmeqHy9mvL5qGQTuaG5TSrNqEAR6b/qvxDx6my4JmEmjUPA1JeEI9YfTUieMr2UZflu7aIbZFLw0vqiYrywCGrCHXLalOrEOmrvAxLvq4vHtuTlH7JIszzYBSes8g1vle6KG7xXiP3U5Ll96Qiu6bZ31rlMQSPB20xbqJJh6psNSrQs41QvdcXAej+K2Hl1Wd8kPriec4AgiBEh8sk5Pp8W9ROLQ7PcbqqttFaW2m7N/Wy4qcFU13roWKDEAstbxH5CHPoBfZSbIwK4KM6BK/uDHpSPIbiOvOCW+lvu9TAiZPc0oysY6aslO7jXv16Gws=', + ), + # example 3 + ( + '256 3 8 AwEAAday3UX323uVzQqtOMQ7EHQYfD5Ofv4akjQGN2zY5AgB/2jmdR/+ 1PvXFqzKCAGJv4wjABEBNWLLFm7ew1hHMDZEKVL17aml0EBKI6Dsz6Mx t6n7ScvLtHaFRKaxT4i2JxiuVhKdQR9XGMiWAPQKrRM5SLG0P+2F+TLK l3D0L/cD', + '256 3 8 AwEAAday3UX323uVzQqtOMQ7EHQYfD5Ofv4akjQGN2zY5 AgB/2jmdR/+1PvXFqzKCAGJv4wjABEBNWLLFm7ew1hHMDZEKVL17aml0EBKI6Dsz6Mxt6n7ScvLtHaFRKaxT4i2JxiuVhKdQR9XGMiWAPQKrRM5SLG0P+2F+ TLKl3D0L/cD', + '256 3 8 AwEAAday3UX323uVzQqtOMQ7EHQYfD5Ofv4akjQGN2zY5AgB/2jmdR/+1PvXFqzKCAGJv4wjABEBNWLLFm7ew1hHMDZEKVL17aml0EBKI6Dsz6Mxt6n7ScvLtHaFRKaxT4i2JxiuVhKdQR9XGMiWAPQKrRM5SLG0P+2F+TLKl3D0L/cD', + ), + ) + output_map = { + 32: ( + '257 3 13 aCoEWYBBVsP9Fek2oC8yqU8ocKmnS1iD SFZNORnQuHKtJ9Wpyz+kNryquB78Pyk/ NTEoai5bxoipVQQXzHlzyg==', + '257 3 8 AwEAAcw5QLr0IjC0wKbGoBPQv4qmeqHy 9mvL5qGQTuaG5TSrNqEAR6b/qvxDx6my 4JmEmjUPA1JeEI9YfTUieMr2UZflu7aI bZFLw0vqiYrywCGrCHXLalOrEOmrvAxL vq4vHtuTlH7JIszzYBSes8g1vle6KG7x XiP3U5Ll96Qiu6bZ31rlMQSPB20xbqJJ h6psNSrQs41QvdcXAej+K2Hl1Wd8kPri ec4AgiBEh8sk5Pp8W9ROLQ7PcbqqttFa W2m7N/Wy4qcFU13roWKDEAstbxH5CHPo BfZSbIwK4KM6BK/uDHpSPIbiOvOCW+lv u9TAiZPc0oysY6aslO7jXv16Gws=', + '256 3 8 AwEAAday3UX323uVzQqtOMQ7EHQYfD5O fv4akjQGN2zY5AgB/2jmdR/+1PvXFqzK CAGJv4wjABEBNWLLFm7ew1hHMDZEKVL1 7aml0EBKI6Dsz6Mxt6n7ScvLtHaFRKax T4i2JxiuVhKdQR9XGMiWAPQKrRM5SLG0 P+2F+TLKl3D0L/cD', + ), + 56: (t[0] for t in inputs), + 0: (t[0][:12] + t[0][12:].replace(' ', '') for t in inputs) + } + + for chunksize, outputs in output_map.items(): + for input, output in zip(inputs, outputs): + for input_variation in input: + rr = dns.rdata.from_text('IN', 'DNSKEY', input_variation) + new_text = rr.to_text(chunksize=chunksize) + self.assertEqual(output, new_text) + + +class UtilTestCase(unittest.TestCase): + + def test_Gateway_bad_type0(self): + with self.assertRaises(SyntaxError): + dns.rdtypes.util.Gateway(0, 'bad.') + + def test_Gateway_bad_type3(self): + with self.assertRaises(SyntaxError): + dns.rdtypes.util.Gateway(3, 'bad.') + + def test_Gateway_type4(self): + with self.assertRaises(SyntaxError): + dns.rdtypes.util.Gateway(4) + with self.assertRaises(dns.exception.FormError): + dns.rdtypes.util.Gateway.from_wire_parser(4, None) + + def test_Bitmap(self): + b = dns.rdtypes.util.Bitmap + tok = dns.tokenizer.Tokenizer('A MX') + windows = b.from_text(tok).windows + ba = bytearray() + ba.append(0x40) # bit 1, for A + ba.append(0x01) # bit 15, for MX + self.assertEqual(windows, [(0, bytes(ba))]) + + def test_Bitmap_with_duplicate_types(self): + b = dns.rdtypes.util.Bitmap + tok = dns.tokenizer.Tokenizer('A MX A A MX') + windows = b.from_text(tok).windows + ba = bytearray() + ba.append(0x40) # bit 1, for A + ba.append(0x01) # bit 15, for MX + self.assertEqual(windows, [(0, bytes(ba))]) + + def test_Bitmap_with_out_of_order_types(self): + b = dns.rdtypes.util.Bitmap + tok = dns.tokenizer.Tokenizer('MX A') + windows = b.from_text(tok).windows + ba = bytearray() + ba.append(0x40) # bit 1, for A + ba.append(0x01) # bit 15, for MX + self.assertEqual(windows, [(0, bytes(ba))]) + + def test_Bitmap_zero_padding_works(self): + b = dns.rdtypes.util.Bitmap + tok = dns.tokenizer.Tokenizer('SRV') + windows = b.from_text(tok).windows + ba = bytearray() + ba.append(0) + ba.append(0) + ba.append(0) + ba.append(0) + ba.append(0x40) # bit 33, for SRV + self.assertEqual(windows, [(0, bytes(ba))]) + + def test_Bitmap_has_type_0_set(self): + b = dns.rdtypes.util.Bitmap + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('NONE A MX') + b.from_text(tok) + + def test_Bitmap_empty_window_not_written(self): + b = dns.rdtypes.util.Bitmap + tok = dns.tokenizer.Tokenizer('URI CAA') # types 256 and 257 + windows = b.from_text(tok).windows + ba = bytearray() + ba.append(0xc0) # bits 0 and 1 in window 1 + self.assertEqual(windows, [(1, bytes(ba))]) + + def test_Bitmap_ok_parse(self): + parser = dns.wire.Parser(b'\x00\x01\x40') + b = dns.rdtypes.util.Bitmap([]) + windows = b.from_wire_parser(parser).windows + self.assertEqual(windows, [(0, b'@')]) + + def test_Bitmap_0_length_window_parse(self): + parser = dns.wire.Parser(b'\x00\x00') + with self.assertRaises(ValueError): + b = dns.rdtypes.util.Bitmap([]) + b.from_wire_parser(parser) + + def test_Bitmap_too_long_parse(self): + parser = dns.wire.Parser(b'\x00\x21' + b'\x01' * 33) + with self.assertRaises(ValueError): + b = dns.rdtypes.util.Bitmap([]) + b.from_wire_parser(parser) + + def test_compressed_in_generic_is_bad(self): + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, + r'\# 4 000aC000') + + def test_rdataset_ttl_conversion(self): + rds1 = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1') + self.assertEqual(rds1.ttl, 300) + rds2 = dns.rdataset.from_text('in', 'a', '5m', '10.0.0.1') + self.assertEqual(rds2.ttl, 300) + with self.assertRaises(ValueError): + dns.rdataset.from_text('in', 'a', 1.6, '10.0.0.1') + with self.assertRaises(dns.ttl.BadTTL): + dns.rdataset.from_text('in', 'a', '10.0.0.1', '10.0.0.2') + + +Rdata = dns.rdata.Rdata + + +class RdataConvertersTestCase(unittest.TestCase): + def test_as_name(self): + n = dns.name.from_text('hi') + self.assertEqual(Rdata._as_name(n), n) + self.assertEqual(Rdata._as_name('hi'), n) + with self.assertRaises(ValueError): + Rdata._as_name(100) + + def test_as_uint8(self): + self.assertEqual(Rdata._as_uint8(0), 0) + with self.assertRaises(ValueError): + Rdata._as_uint8('hi') + with self.assertRaises(ValueError): + Rdata._as_uint8(-1) + with self.assertRaises(ValueError): + Rdata._as_uint8(256) + + def test_as_uint16(self): + self.assertEqual(Rdata._as_uint16(0), 0) + with self.assertRaises(ValueError): + Rdata._as_uint16('hi') + with self.assertRaises(ValueError): + Rdata._as_uint16(-1) + with self.assertRaises(ValueError): + Rdata._as_uint16(65536) + + def test_as_uint32(self): + self.assertEqual(Rdata._as_uint32(0), 0) + with self.assertRaises(ValueError): + Rdata._as_uint32('hi') + with self.assertRaises(ValueError): + Rdata._as_uint32(-1) + with self.assertRaises(ValueError): + Rdata._as_uint32(2 ** 32) + + def test_as_uint48(self): + self.assertEqual(Rdata._as_uint48(0), 0) + with self.assertRaises(ValueError): + Rdata._as_uint48('hi') + with self.assertRaises(ValueError): + Rdata._as_uint48(-1) + with self.assertRaises(ValueError): + Rdata._as_uint48(2 ** 48) + + def test_as_int(self): + self.assertEqual(Rdata._as_int(0, 0, 10), 0) + with self.assertRaises(ValueError): + Rdata._as_int('hi', 0, 10) + with self.assertRaises(ValueError): + Rdata._as_int(-1, 0, 10) + with self.assertRaises(ValueError): + Rdata._as_int(11, 0, 10) + + def test_as_bool(self): + self.assertEqual(Rdata._as_bool(True), True) + self.assertEqual(Rdata._as_bool(False), False) + with self.assertRaises(ValueError): + Rdata._as_bool('hi') + + def test_as_ttl(self): + self.assertEqual(Rdata._as_ttl(300), 300) + self.assertEqual(Rdata._as_ttl('5m'), 300) + self.assertEqual(Rdata._as_ttl(dns.ttl.MAX_TTL), dns.ttl.MAX_TTL) + with self.assertRaises(dns.ttl.BadTTL): + Rdata._as_ttl('hi') + with self.assertRaises(ValueError): + Rdata._as_ttl(1.9) + with self.assertRaises(ValueError): + Rdata._as_ttl(dns.ttl.MAX_TTL + 1) + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_rdataset.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_rdataset.py new file mode 100644 index 0000000..4710e2a --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_rdataset.py @@ -0,0 +1,164 @@ +# -*- coding: utf-8 +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import unittest + +import dns.name +import dns.rdata +import dns.rdataclass +import dns.rdataset +import dns.rdatatype + +class RdatasetTestCase(unittest.TestCase): + + def testCodec2003(self): + r1 = dns.rdataset.from_text_list('in', 'ns', 30, + ['Königsgäßchen']) + r2 = dns.rdataset.from_text_list('in', 'ns', 30, + ['xn--knigsgsschen-lcb0w']) + self.assertEqual(r1, r2) + + @unittest.skipUnless(dns.name.have_idna_2008, + 'Python idna cannot be imported; no IDNA2008') + def testCodec2008(self): + r1 = dns.rdataset.from_text_list('in', 'ns', 30, + ['Königsgäßchen'], + idna_codec=dns.name.IDNA_2008) + r2 = dns.rdataset.from_text_list('in', 'ns', 30, + ['xn--knigsgchen-b4a3dun'], + idna_codec=dns.name.IDNA_2008) + self.assertEqual(r1, r2) + + def testCopy(self): + r1 = dns.rdataset.from_text_list('in', 'a', 30, + ['10.0.0.1', '10.0.0.2']) + r2 = r1.copy() + self.assertFalse(r1 is r2) + self.assertTrue(r1 == r2) + + def testAddIncompatible(self): + rds = dns.rdataset.Rdataset(dns.rdataclass.IN, dns.rdatatype.A) + rd1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1') + rd2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.AAAA, + '::1') + rds.add(rd1, 30) + self.assertRaises(dns.rdataset.IncompatibleTypes, + lambda: rds.add(rd2, 30)) + + def testDifferingCovers(self): + rds = dns.rdataset.Rdataset(dns.rdataclass.IN, dns.rdatatype.RRSIG, + dns.rdatatype.A) + rd1 = dns.rdata.from_text( + dns.rdataclass.IN, dns.rdatatype.RRSIG, + 'A 1 3 3600 20200101000000 20030101000000 2143 foo Ym9ndXM=') + rd2 = dns.rdata.from_text( + dns.rdataclass.IN, dns.rdatatype.RRSIG, + 'AAAA 1 3 3600 20200101000000 20030101000000 2143 foo Ym9ndXM=') + rds.add(rd1, 30) + self.assertRaises(dns.rdataset.DifferingCovers, + lambda: rds.add(rd2, 30)) + + def testUnionUpdate(self): + rds1 = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1') + rds2 = dns.rdataset.from_text('in', 'a', 30, '10.0.0.2') + rdse = dns.rdataset.from_text('in', 'a', 30, '10.0.0.1', '10.0.0.2') + rds1.union_update(rds2) + self.assertEqual(rds1, rdse) + + def testIntersectionUpdate(self): + rds1 = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1', '10.0.0.2') + rds2 = dns.rdataset.from_text('in', 'a', 30, '10.0.0.2') + rdse = dns.rdataset.from_text('in', 'a', 30, '10.0.0.2') + rds1.intersection_update(rds2) + self.assertEqual(rds1, rdse) + + def testNoEqualToOther(self): + rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1') + self.assertFalse(rds == 123) + + def testEmptyRdataList(self): + self.assertRaises(ValueError, + lambda: dns.rdataset.from_rdata_list(300, [])) + + def testToTextNoName(self): + rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1') + text = rds.to_text() + self.assertEqual(text, '300 IN A 10.0.0.1') + + def testToTextOverrideClass(self): + rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1') + text = rds.to_text(override_rdclass=dns.rdataclass.NONE) + self.assertEqual(text, '300 NONE A 10.0.0.1') + + def testRepr(self): + rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1') + self.assertEqual(repr(rds), "]>") + + def testTruncatedRepr(self): + rds = dns.rdataset.from_text('in', 'txt', 300, + 'a' * 200) + # * 99 not * 100 below as the " counts as one of the 100 chars + self.assertEqual(repr(rds), + ']>') + + def testStr(self): + rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1') + self.assertEqual(str(rds), "300 IN A 10.0.0.1") + + def testMultilineToText(self): + rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1', '10.0.0.2') + self.assertEqual(rds.to_text(), "300 IN A 10.0.0.1\n300 IN A 10.0.0.2") + + def testCoveredRepr(self): + rds = dns.rdataset.from_text('in', 'rrsig', 300, + 'NSEC 1 3 3600 ' + + '20190101000000 20030101000000 ' + + '2143 foo Ym9ndXM=') + # Using startswith as I don't care about the repr of the rdata, + # just the covers + print(repr(rds)) + self.assertTrue(repr(rds).startswith( + ' +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import unittest + +import dns.rrset +import dns.rdtypes.ANY.DNSKEY + +from typing import Set # pylint: disable=unused-import + +class RdtypeAnyDnskeyTestCase(unittest.TestCase): + + def testFlagsAll(self): # type: () -> None + '''Test that all defined flags are recognized.''' + good_s = {'SEP', 'REVOKE', 'ZONE'} + good_f = 0x181 + self.assertEqual(dns.rdtypes.ANY.DNSKEY.SEP | + dns.rdtypes.ANY.DNSKEY.REVOKE | + dns.rdtypes.ANY.DNSKEY.ZONE, good_f) + + def testFlagsRRToText(self): # type: () -> None + '''Test that RR method returns correct flags.''' + rr = dns.rrset.from_text('foo', 300, 'IN', 'DNSKEY', '257 3 8 KEY=')[0] + self.assertEqual(dns.rdtypes.ANY.DNSKEY.ZONE | + dns.rdtypes.ANY.DNSKEY.SEP, + rr.flags) + + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_rdtypeanyeui.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_rdtypeanyeui.py new file mode 100644 index 0000000..0852727 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_rdtypeanyeui.py @@ -0,0 +1,204 @@ +# Copyright (C) 2015 Red Hat, Inc. +# Author: Petr Spacek +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import unittest + +import dns.rrset +import dns.rdtypes.ANY.EUI48 +import dns.rdtypes.ANY.EUI64 +import dns.exception + + +class RdtypeAnyEUI48TestCase(unittest.TestCase): + def testInstOk(self): + '''Valid binary input.''' + eui = b'\x01\x23\x45\x67\x89\xab' + inst = dns.rdtypes.ANY.EUI48.EUI48(dns.rdataclass.IN, + dns.rdatatype.EUI48, + eui) + self.assertEqual(inst.eui, eui) + + def testInstLength(self): + '''Incorrect input length.''' + eui = b'\x01\x23\x45\x67\x89\xab\xcd' + with self.assertRaises(dns.exception.FormError): + dns.rdtypes.ANY.EUI48.EUI48(dns.rdataclass.IN, + dns.rdatatype.EUI48, + eui) + + def testFromTextOk(self): + '''Valid text input.''' + r1 = dns.rrset.from_text('foo', 300, 'IN', 'EUI48', + '01-23-45-67-89-ab') + eui = b'\x01\x23\x45\x67\x89\xab' + self.assertEqual(r1[0].eui, eui) + + def testFromTextLength(self): + '''Invalid input length.''' + with self.assertRaises(dns.exception.SyntaxError): + dns.rrset.from_text('foo', 300, 'IN', 'EUI48', + '00-01-23-45-67-89-ab') + + def testFromTextDelim(self): + '''Invalid delimiter.''' + with self.assertRaises(dns.exception.SyntaxError): + dns.rrset.from_text('foo', 300, 'IN', 'EUI48', '01_23-45-67-89-ab') + + def testFromTextExtraDash(self): + '''Extra dash instead of hex digit.''' + with self.assertRaises(dns.exception.SyntaxError): + dns.rrset.from_text('foo', 300, 'IN', 'EUI48', '0--23-45-67-89-ab') + + def testFromTextMultipleTokens(self): + '''Invalid input divided to multiple tokens.''' + with self.assertRaises(dns.exception.SyntaxError): + dns.rrset.from_text('foo', 300, 'IN', 'EUI48', '01 23-45-67-89-ab') + + def testFromTextInvalidHex(self): + '''Invalid hexadecimal input.''' + with self.assertRaises(dns.exception.SyntaxError): + dns.rrset.from_text('foo', 300, 'IN', 'EUI48', 'g0-23-45-67-89-ab') + + def testToTextOk(self): + '''Valid text output.''' + eui = b'\x01\x23\x45\x67\x89\xab' + exp_text = '01-23-45-67-89-ab' + inst = dns.rdtypes.ANY.EUI48.EUI48(dns.rdataclass.IN, + dns.rdatatype.EUI48, + eui) + text = inst.to_text() + self.assertEqual(exp_text, text) + + def testToWire(self): + '''Valid wire format.''' + eui = b'\x01\x23\x45\x67\x89\xab' + inst = dns.rdtypes.ANY.EUI48.EUI48(dns.rdataclass.IN, + dns.rdatatype.EUI48, + eui) + self.assertEqual(inst.to_wire(), eui) + + def testFromWireOk(self): + '''Valid wire format.''' + eui = b'\x01\x23\x45\x67\x89\xab' + pad_len = 100 + wire = b'x' * pad_len + eui + b'y' * pad_len * 2 + inst = dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.EUI48, + wire, pad_len, len(eui)) + self.assertEqual(inst.eui, eui) + + def testFromWireLength(self): + '''Valid wire format.''' + eui = b'\x01\x23\x45\x67\x89' + pad_len = 100 + wire = b'x' * pad_len + eui + b'y' * pad_len * 2 + with self.assertRaises(dns.exception.FormError): + dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.EUI48, + wire, pad_len, len(eui)) + + +class RdtypeAnyEUI64TestCase(unittest.TestCase): + def testInstOk(self): + '''Valid binary input.''' + eui = b'\x01\x23\x45\x67\x89\xab\xcd\xef' + inst = dns.rdtypes.ANY.EUI64.EUI64(dns.rdataclass.IN, + dns.rdatatype.EUI64, + eui) + self.assertEqual(inst.eui, eui) + + def testInstLength(self): + '''Incorrect input length.''' + eui = b'\x01\x23\x45\x67\x89\xab' + with self.assertRaises(dns.exception.FormError): + dns.rdtypes.ANY.EUI64.EUI64(dns.rdataclass.IN, + dns.rdatatype.EUI64, + eui) + + def testFromTextOk(self): + '''Valid text input.''' + r1 = dns.rrset.from_text('foo', 300, 'IN', 'EUI64', + '01-23-45-67-89-ab-cd-ef') + eui = b'\x01\x23\x45\x67\x89\xab\xcd\xef' + self.assertEqual(r1[0].eui, eui) + + def testFromTextLength(self): + '''Invalid input length.''' + with self.assertRaises(dns.exception.SyntaxError): + dns.rrset.from_text('foo', 300, 'IN', 'EUI64', + '01-23-45-67-89-ab') + + def testFromTextDelim(self): + '''Invalid delimiter.''' + with self.assertRaises(dns.exception.SyntaxError): + dns.rrset.from_text('foo', 300, 'IN', 'EUI64', + '01_23-45-67-89-ab-cd-ef') + + def testFromTextExtraDash(self): + '''Extra dash instead of hex digit.''' + with self.assertRaises(dns.exception.SyntaxError): + dns.rrset.from_text('foo', 300, 'IN', 'EUI64', + '0--23-45-67-89-ab-cd-ef') + + def testFromTextMultipleTokens(self): + '''Invalid input divided to multiple tokens.''' + with self.assertRaises(dns.exception.SyntaxError): + dns.rrset.from_text('foo', 300, 'IN', 'EUI64', + '01 23-45-67-89-ab-cd-ef') + + def testFromTextInvalidHex(self): + '''Invalid hexadecimal input.''' + with self.assertRaises(dns.exception.SyntaxError): + dns.rrset.from_text('foo', 300, 'IN', 'EUI64', + 'g0-23-45-67-89-ab-cd-ef') + + def testToTextOk(self): + '''Valid text output.''' + eui = b'\x01\x23\x45\x67\x89\xab\xcd\xef' + exp_text = '01-23-45-67-89-ab-cd-ef' + inst = dns.rdtypes.ANY.EUI64.EUI64(dns.rdataclass.IN, + dns.rdatatype.EUI64, + eui) + text = inst.to_text() + self.assertEqual(exp_text, text) + + def testToWire(self): + '''Valid wire format.''' + eui = b'\x01\x23\x45\x67\x89\xab\xcd\xef' + inst = dns.rdtypes.ANY.EUI64.EUI64(dns.rdataclass.IN, + dns.rdatatype.EUI64, + eui) + self.assertEqual(inst.to_wire(), eui) + + def testFromWireOk(self): + '''Valid wire format.''' + eui = b'\x01\x23\x45\x67\x89\xab\xcd\xef' + pad_len = 100 + wire = b'x' * pad_len + eui + b'y' * pad_len * 2 + inst = dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.EUI64, + wire, pad_len, len(eui)) + self.assertEqual(inst.eui, eui) + + def testFromWireLength(self): + '''Valid wire format.''' + eui = b'\x01\x23\x45\x67\x89' + pad_len = 100 + wire = b'x' * pad_len + eui + b'y' * pad_len * 2 + with self.assertRaises(dns.exception.FormError): + dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.EUI64, + wire, pad_len, len(eui)) + + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_rdtypeanyloc.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_rdtypeanyloc.py new file mode 100644 index 0000000..23a1f68 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_rdtypeanyloc.py @@ -0,0 +1,70 @@ +# Copyright (C) 2014 Red Hat, Inc. +# Author: Petr Spacek +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import unittest + +import dns.rrset +import dns.rdtypes.ANY.LOC + +class RdtypeAnyLocTestCase(unittest.TestCase): + + def testEqual1(self): + '''Test default values for size, horizontal and vertical precision.''' + r1 = dns.rrset.from_text('foo', 300, 'IN', 'LOC', + '49 11 42.400 N 16 36 29.600 E 227.64m') + r2 = dns.rrset.from_text('FOO', 600, 'in', 'loc', + '49 11 42.400 N 16 36 29.600 E 227.64m ' + '1.00m 10000.00m 10.00m') + self.assertEqual(r1, r2, '"{}" != "{}"'.format(r1, r2)) + + def testEqual2(self): + '''Test default values for size, horizontal and vertical precision.''' + r1 = dns.rdtypes.ANY.LOC.LOC(1, 29, (49, 11, 42, 400, 1), + (16, 36, 29, 600, 1), + 22764.0) # centimeters + r2 = dns.rdtypes.ANY.LOC.LOC(1, 29, (49, 11, 42, 400, 1), + (16, 36, 29, 600, 1), + 22764.0, # centimeters + 100.0, 1000000.00, 1000.0) # centimeters + self.assertEqual(r1, r2, '"{}" != "{}"'.format(r1, r2)) + + def testEqual3(self): + '''Test size, horizontal and vertical precision parsers: 100 cm == 1 m. + + Parsers in from_text() and __init__() have to produce equal results.''' + r1 = dns.rdtypes.ANY.LOC.LOC(1, 29, (49, 11, 42, 400, 1), + (16, 36, 29, 600, 1), 22764.0, + 200.0, 1000.00, 200.0) # centimeters + r2 = dns.rrset.from_text('FOO', 600, 'in', 'loc', + '49 11 42.400 N 16 36 29.600 E 227.64m ' + '2.00m 10.00m 2.00m')[0] + self.assertEqual(r1, r2, '"{}" != "{}"'.format(r1, r2)) + + def testEqual4(self): + '''Test size, horizontal and vertical precision parsers without unit. + + Parsers in from_text() and __init__() have produce equal result + for values with and without trailing "m".''' + r1 = dns.rdtypes.ANY.LOC.LOC(1, 29, (49, 11, 42, 400, 1), + (16, 36, 29, 600, 1), 22764.0, + 200.0, 1000.00, 200.0) # centimeters + r2 = dns.rrset.from_text('FOO', 600, 'in', 'loc', + '49 11 42.400 N 16 36 29.600 E 227.64 ' + '2 10 2')[0] # meters without explicit unit + self.assertEqual(r1, r2, '"{}" != "{}"'.format(r1, r2)) + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_rdtypeanytkey.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_rdtypeanytkey.py new file mode 100644 index 0000000..3a3ca57 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_rdtypeanytkey.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import unittest +import base64 + +import dns.name +import dns.zone +import dns.rdtypes.ANY.TKEY +from dns.rdataclass import RdataClass +from dns.rdatatype import RdataType + + +class RdtypeAnyTKeyTestCase(unittest.TestCase): + tkey_rdata_text = 'gss-tsig. 1594203795 1594206664 3 0 KEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEY OTHEROTHEROTHEROTHEROTHEROTHEROT' + tkey_rdata_text_no_other = 'gss-tsig. 1594203795 1594206664 3 0 KEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEY' + + def testTextOptionalData(self): + # construct the rdata from text and extract the TKEY + tkey = dns.rdata.from_text( + RdataClass.ANY, RdataType.TKEY, + RdtypeAnyTKeyTestCase.tkey_rdata_text, origin='.') + self.assertEqual(type(tkey), dns.rdtypes.ANY.TKEY.TKEY) + + # go to text and compare + tkey_out_text = tkey.to_text(relativize=False) + self.assertEqual(tkey_out_text, + RdtypeAnyTKeyTestCase.tkey_rdata_text) + + def testTextNoOptionalData(self): + # construct the rdata from text and extract the TKEY + tkey = dns.rdata.from_text( + RdataClass.ANY, RdataType.TKEY, + RdtypeAnyTKeyTestCase.tkey_rdata_text_no_other, origin='.') + self.assertEqual(type(tkey), dns.rdtypes.ANY.TKEY.TKEY) + + # go to text and compare + tkey_out_text = tkey.to_text(relativize=False) + self.assertEqual(tkey_out_text, + RdtypeAnyTKeyTestCase.tkey_rdata_text_no_other) + + def testWireOptionalData(self): + key = base64.b64decode('KEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEY') + other = base64.b64decode('OTHEROTHEROTHEROTHEROTHEROTHEROT') + + # construct the TKEY and compare the text output + tkey = dns.rdtypes.ANY.TKEY.TKEY(dns.rdataclass.ANY, + dns.rdatatype.TKEY, + dns.name.from_text('gss-tsig.'), + 1594203795, 1594206664, + 3, 0, key, other) + self.assertEqual(tkey.to_text(relativize=False), + RdtypeAnyTKeyTestCase.tkey_rdata_text) + + # go to/from wire and compare the text output + wire = tkey.to_wire() + tkey_out_wire = dns.rdata.from_wire(dns.rdataclass.ANY, + dns.rdatatype.TKEY, + wire, 0, len(wire)) + self.assertEqual(tkey_out_wire.to_text(relativize=False), + RdtypeAnyTKeyTestCase.tkey_rdata_text) + + def testWireNoOptionalData(self): + key = base64.b64decode('KEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEY') + + # construct the TKEY with no 'other' data and compare the text output + tkey = dns.rdtypes.ANY.TKEY.TKEY(dns.rdataclass.ANY, + dns.rdatatype.TKEY, + dns.name.from_text('gss-tsig.'), + 1594203795, 1594206664, + 3, 0, key) + self.assertEqual(tkey.to_text(relativize=False), + RdtypeAnyTKeyTestCase.tkey_rdata_text_no_other) + + # go to/from wire and compare the text output + wire = tkey.to_wire() + tkey_out_wire = dns.rdata.from_wire(dns.rdataclass.ANY, + dns.rdatatype.TKEY, + wire, 0, len(wire)) + self.assertEqual(tkey_out_wire.to_text(relativize=False), + RdtypeAnyTKeyTestCase.tkey_rdata_text_no_other) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_renderer.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_renderer.py new file mode 100644 index 0000000..c60ccf9 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_renderer.py @@ -0,0 +1,92 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import unittest + +import dns.exception +import dns.flags +import dns.message +import dns.renderer +import dns.tsig +import dns.tsigkeyring + +basic_answer = \ + """flags QR +edns 0 +payload 4096 +;QUESTION +foo.example. IN A +;ANSWER +foo.example. 30 IN A 10.0.0.1 +foo.example. 30 IN A 10.0.0.2 +""" + +class RendererTestCase(unittest.TestCase): + def test_basic(self): + r = dns.renderer.Renderer(flags=dns.flags.QR, max_size=512) + qname = dns.name.from_text('foo.example') + r.add_question(qname, dns.rdatatype.A) + rds = dns.rdataset.from_text('in', 'a', 30, '10.0.0.1', '10.0.0.2') + r.add_rdataset(dns.renderer.ANSWER, qname, rds) + r.add_edns(0, 0, 4096) + r.write_header() + wire = r.get_wire() + message = dns.message.from_wire(wire) + expected = dns.message.from_text(basic_answer) + # Our rendered message purposely has a random query id so we + # exercise that code, so copy it into the expected message. + expected.id = message.id + self.assertEqual(message, expected) + + def test_tsig(self): + r = dns.renderer.Renderer(flags=dns.flags.RD, max_size=512) + qname = dns.name.from_text('foo.example') + r.add_question(qname, dns.rdatatype.A) + keyring = dns.tsigkeyring.from_text({'key' : '12345678'}) + keyname = next(iter(keyring)) + r.write_header() + r.add_tsig(keyname, keyring[keyname], 300, r.id, 0, b'', b'', + dns.tsig.HMAC_SHA256) + wire = r.get_wire() + message = dns.message.from_wire(wire, keyring=keyring) + expected = dns.message.make_query(qname, dns.rdatatype.A) + expected.id = message.id + self.assertEqual(message, expected) + + def test_multi_tsig(self): + qname = dns.name.from_text('foo.example') + keyring = dns.tsigkeyring.from_text({'key' : '12345678'}) + keyname = next(iter(keyring)) + + r = dns.renderer.Renderer(flags=dns.flags.RD, max_size=512) + r.add_question(qname, dns.rdatatype.A) + r.write_header() + ctx = r.add_multi_tsig(None, keyname, keyring[keyname], 300, r.id, 0, + b'', b'', dns.tsig.HMAC_SHA256) + wire = r.get_wire() + message = dns.message.from_wire(wire, keyring=keyring, multi=True) + expected = dns.message.make_query(qname, dns.rdatatype.A) + expected.id = message.id + self.assertEqual(message, expected) + + r = dns.renderer.Renderer(flags=dns.flags.RD, max_size=512) + r.add_question(qname, dns.rdatatype.A) + r.write_header() + ctx = r.add_multi_tsig(ctx, keyname, keyring[keyname], 300, r.id, 0, + b'', b'', dns.tsig.HMAC_SHA256) + wire = r.get_wire() + message = dns.message.from_wire(wire, keyring=keyring, + tsig_ctx=message.tsig_ctx, multi=True) + expected = dns.message.make_query(qname, dns.rdatatype.A) + expected.id = message.id + self.assertEqual(message, expected) + + + def test_going_backwards_fails(self): + r = dns.renderer.Renderer(flags=dns.flags.QR, max_size=512) + qname = dns.name.from_text('foo.example') + r.add_question(qname, dns.rdatatype.A) + r.add_edns(0, 0, 4096) + rds = dns.rdataset.from_text('in', 'a', 30, '10.0.0.1', '10.0.0.2') + def bad(): + r.add_rdataset(dns.renderer.ANSWER, qname, rds) + self.assertRaises(dns.exception.FormError, bad) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_resolution.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_resolution.py new file mode 100644 index 0000000..731090b --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_resolution.py @@ -0,0 +1,472 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import unittest + +import dns.flags +import dns.message +import dns.name +import dns.rcode +import dns.rdataclass +import dns.rdatatype +import dns.resolver +import dns.tsigkeyring + +# Test the resolver's Resolution, i.e. the business logic of the resolver. + +class ResolutionTestCase(unittest.TestCase): + def setUp(self): + self.resolver = dns.resolver.Resolver(configure=False) + self.resolver.nameservers = ['10.0.0.1', '10.0.0.2'] + self.resolver.domain = dns.name.from_text('example') + self.qname = dns.name.from_text('www.dnspython.org') + self.resn = dns.resolver._Resolution(self.resolver, self.qname, + 'A', 'IN', + False, True, False) + + def test_next_request_abs(self): + (request, answer) = self.resn.next_request() + self.assertTrue(answer is None) + self.assertEqual(request.question[0].name, self.qname) + self.assertEqual(request.question[0].rdtype, dns.rdatatype.A) + + def test_next_request_rel_with_search(self): + qname = dns.name.from_text('www.dnspython.org', None) + abs_qname_1 = dns.name.from_text('www.dnspython.org.example') + self.resn = dns.resolver._Resolution(self.resolver, qname, + 'A', 'IN', + False, True, True) + (request, answer) = self.resn.next_request() + self.assertTrue(answer is None) + self.assertEqual(request.question[0].name, self.qname) + self.assertEqual(request.question[0].rdtype, dns.rdatatype.A) + (request, answer) = self.resn.next_request() + self.assertTrue(answer is None) + self.assertEqual(request.question[0].name, abs_qname_1) + self.assertEqual(request.question[0].rdtype, dns.rdatatype.A) + def bad(): + (request, answer) = self.resn.next_request() + self.assertRaises(dns.resolver.NXDOMAIN, bad) + + def test_next_request_rel_without_search(self): + qname = dns.name.from_text('www.dnspython.org', None) + abs_qname_1 = dns.name.from_text('www.dnspython.org.example') + self.resn = dns.resolver._Resolution(self.resolver, qname, + 'A', 'IN', + False, True, False) + (request, answer) = self.resn.next_request() + self.assertTrue(answer is None) + self.assertEqual(request.question[0].name, self.qname) + self.assertEqual(request.question[0].rdtype, dns.rdatatype.A) + def bad(): + (request, answer) = self.resn.next_request() + self.assertRaises(dns.resolver.NXDOMAIN, bad) + + def test_next_request_exhaust_causes_nxdomain(self): + def bad(): + (request, answer) = self.resn.next_request() + (request, answer) = self.resn.next_request() + self.assertRaises(dns.resolver.NXDOMAIN, bad) + + def make_address_response(self, q): + r = dns.message.make_response(q) + rrs = r.get_rrset(r.answer, self.qname, dns.rdataclass.IN, + dns.rdatatype.A, create=True) + rrs.add(dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1'), 300) + return r + + def make_negative_response(self, q, nxdomain=False): + r = dns.message.make_response(q) + rrs = r.get_rrset(r.authority, q.question[0].name, dns.rdataclass.IN, + dns.rdatatype.SOA, create=True) + rrs.add(dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, + '. . 1 2 3 4 300'), 300) + if nxdomain: + r.set_rcode(dns.rcode.NXDOMAIN) + return r + + def make_long_chain_response(self, q, count): + r = dns.message.make_response(q) + name = self.qname + for i in range(count): + rrs = r.get_rrset(r.answer, name, dns.rdataclass.IN, + dns.rdatatype.CNAME, create=True) + tname = dns.name.from_text(f'target{i}.') + rrs.add(dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, + str(tname)), 300) + name = tname + rrs = r.get_rrset(r.answer, name, dns.rdataclass.IN, + dns.rdatatype.A, create=True) + rrs.add(dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1'), 300) + return r + + def test_next_request_cache_hit(self): + self.resolver.cache = dns.resolver.Cache() + q = dns.message.make_query(self.qname, dns.rdatatype.A) + r = self.make_address_response(q) + cache_answer = dns.resolver.Answer(self.qname, dns.rdatatype.A, + dns.rdataclass.IN, r) + self.resolver.cache.put((self.qname, dns.rdatatype.A, + dns.rdataclass.IN), cache_answer) + (request, answer) = self.resn.next_request() + self.assertTrue(request is None) + self.assertTrue(answer is cache_answer) + + def test_next_request_cached_no_answer(self): + # In default mode, we should raise on a no-answer hit + self.resolver.cache = dns.resolver.Cache() + q = dns.message.make_query(self.qname, dns.rdatatype.A) + # Note we need an SOA so the cache doesn't expire the answer + # immediately, but our negative response code does that. + r = self.make_negative_response(q) + cache_answer = dns.resolver.Answer(self.qname, dns.rdatatype.A, + dns.rdataclass.IN, r) + self.resolver.cache.put((self.qname, dns.rdatatype.A, + dns.rdataclass.IN), cache_answer) + def bad(): + (request, answer) = self.resn.next_request() + self.assertRaises(dns.resolver.NoAnswer, bad) + # If raise_on_no_answer is False, we should get a cache hit. + self.resn = dns.resolver._Resolution(self.resolver, self.qname, + 'A', 'IN', + False, False, False) + (request, answer) = self.resn.next_request() + self.assertTrue(request is None) + self.assertTrue(answer is cache_answer) + + def test_next_request_cached_nxdomain_without_search(self): + # use a relative qname + qname = dns.name.from_text('www.dnspython.org', None) + self.resn = dns.resolver._Resolution(self.resolver, qname, + 'A', 'IN', + False, True, False) + qname1 = dns.name.from_text('www.dnspython.org.') + # Arrange to get NXDOMAIN hits on it. + self.resolver.cache = dns.resolver.Cache() + q1 = dns.message.make_query(qname1, dns.rdatatype.A) + r1 = self.make_negative_response(q1, True) + cache_answer = dns.resolver.Answer(qname1, dns.rdatatype.ANY, + dns.rdataclass.IN, r1) + self.resolver.cache.put((qname1, dns.rdatatype.ANY, + dns.rdataclass.IN), cache_answer) + try: + (request, answer) = self.resn.next_request() + self.assertTrue(False) # should not happen! + except dns.resolver.NXDOMAIN as nx: + self.assertTrue(nx.response(qname1) is r1) + + def test_next_request_cached_nxdomain_with_search(self): + # use a relative qname so we have two qnames to try + qname = dns.name.from_text('www.dnspython.org', None) + # also enable search mode or we'll only see www.dnspython.org. + self.resn = dns.resolver._Resolution(self.resolver, qname, + 'A', 'IN', + False, True, True) + qname1 = dns.name.from_text('www.dnspython.org.example.') + qname2 = dns.name.from_text('www.dnspython.org.') + # Arrange to get NXDOMAIN hits on both of those qnames. + self.resolver.cache = dns.resolver.Cache() + q1 = dns.message.make_query(qname1, dns.rdatatype.A) + r1 = self.make_negative_response(q1, True) + cache_answer = dns.resolver.Answer(qname1, dns.rdatatype.ANY, + dns.rdataclass.IN, r1) + self.resolver.cache.put((qname1, dns.rdatatype.ANY, + dns.rdataclass.IN), cache_answer) + q2 = dns.message.make_query(qname2, dns.rdatatype.A) + r2 = self.make_negative_response(q2, True) + cache_answer = dns.resolver.Answer(qname2, dns.rdatatype.ANY, + dns.rdataclass.IN, r2) + self.resolver.cache.put((qname2, dns.rdatatype.ANY, + dns.rdataclass.IN), cache_answer) + try: + (request, answer) = self.resn.next_request() + self.assertTrue(False) # should not happen! + except dns.resolver.NXDOMAIN as nx: + self.assertTrue(nx.response(qname1) is r1) + self.assertTrue(nx.response(qname2) is r2) + + def test_next_request_rotate(self): + self.resolver.rotate = True + order1 = ['10.0.0.1', '10.0.0.2'] + order2 = ['10.0.0.2', '10.0.0.1'] + seen1 = False + seen2 = False + # We're not interested in testing the randomness, but we'd + # like to see some shuffling, so try up to 50 times to see + # both orders at least once. This test can fail even with + # correct code, but it is *extremely* unlikely. + for count in range(0, 50): + self.resn = dns.resolver._Resolution(self.resolver, self.qname, + 'A', 'IN', + False, True, False) + self.resn.next_request() + if self.resn.nameservers == order1: + seen1 = True + elif self.resn.nameservers == order2: + seen2 = True + else: + raise ValueError # should not happen! + if seen1 and seen2: + break + self.assertTrue(seen1 and seen2) + + def test_next_request_TSIG(self): + self.resolver.keyring = dns.tsigkeyring.from_text({ + 'keyname.' : 'NjHwPsMKjdN++dOfE5iAiQ==' + }) + (keyname, secret) = next(iter(self.resolver.keyring.items())) + self.resolver.keyname = dns.name.from_text('keyname.') + (request, answer) = self.resn.next_request() + self.assertFalse(request is None) + self.assertEqual(request.keyring.name, keyname) + self.assertEqual(request.keyring.secret, secret) + + def test_next_request_flags(self): + self.resolver.flags = dns.flags.RD | dns.flags.CD + (request, answer) = self.resn.next_request() + self.assertFalse(request is None) + self.assertEqual(request.flags, self.resolver.flags) + + def test_next_nameserver_udp(self): + (request, answer) = self.resn.next_request() + (nameserver1, port, tcp, backoff) = self.resn.next_nameserver() + self.assertTrue(nameserver1 in self.resolver.nameservers) + self.assertEqual(port, 53) + self.assertFalse(tcp) + self.assertEqual(backoff, 0.0) + (nameserver2, port, tcp, backoff) = self.resn.next_nameserver() + self.assertTrue(nameserver2 in self.resolver.nameservers) + self.assertTrue(nameserver2 != nameserver1) + self.assertEqual(port, 53) + self.assertFalse(tcp) + self.assertEqual(backoff, 0.0) + (nameserver3, port, tcp, backoff) = self.resn.next_nameserver() + self.assertTrue(nameserver3 is nameserver1) + self.assertEqual(port, 53) + self.assertFalse(tcp) + self.assertEqual(backoff, 0.1) + (nameserver4, port, tcp, backoff) = self.resn.next_nameserver() + self.assertTrue(nameserver4 is nameserver2) + self.assertEqual(port, 53) + self.assertFalse(tcp) + self.assertEqual(backoff, 0.0) + (nameserver5, port, tcp, backoff) = self.resn.next_nameserver() + self.assertTrue(nameserver5 is nameserver1) + self.assertEqual(port, 53) + self.assertFalse(tcp) + self.assertEqual(backoff, 0.2) + + def test_next_nameserver_retry_with_tcp(self): + (request, answer) = self.resn.next_request() + (nameserver1, port, tcp, backoff) = self.resn.next_nameserver() + self.assertTrue(nameserver1 in self.resolver.nameservers) + self.assertEqual(port, 53) + self.assertFalse(tcp) + self.assertEqual(backoff, 0.0) + self.resn.retry_with_tcp = True + (nameserver2, port, tcp, backoff) = self.resn.next_nameserver() + self.assertTrue(nameserver2 is nameserver1) + self.assertEqual(port, 53) + self.assertTrue(tcp) + self.assertEqual(backoff, 0.0) + (nameserver3, port, tcp, backoff) = self.resn.next_nameserver() + self.assertTrue(nameserver3 in self.resolver.nameservers) + self.assertTrue(nameserver3 != nameserver1) + self.assertEqual(port, 53) + self.assertFalse(tcp) + self.assertEqual(backoff, 0.0) + + def test_next_nameserver_no_nameservers(self): + (request, answer) = self.resn.next_request() + (nameserver, _, _, _) = self.resn.next_nameserver() + self.resn.nameservers.remove(nameserver) + (nameserver, _, _, _) = self.resn.next_nameserver() + self.resn.nameservers.remove(nameserver) + def bad(): + (nameserver, _, _, _) = self.resn.next_nameserver() + self.assertRaises(dns.resolver.NoNameservers, bad) + + def test_query_result_nameserver_removing_exceptions(self): + # add some nameservers so we have enough to remove :) + self.resolver.nameservers.extend(['10.0.0.3', '10.0.0.4']) + (request, _) = self.resn.next_request() + exceptions = [dns.exception.FormError(), EOFError(), + NotImplementedError(), dns.message.Truncated()] + for i in range(4): + (nameserver, _, _, _) = self.resn.next_nameserver() + if i == 3: + # Truncated is only bad if we're doing TCP, make it look + # like that's the case + self.resn.tcp_attempt = True + self.assertTrue(nameserver in self.resn.nameservers) + (answer, done) = self.resn.query_result(None, exceptions[i]) + self.assertTrue(answer is None) + self.assertFalse(done) + self.assertFalse(nameserver in self.resn.nameservers) + self.assertEqual(len(self.resn.nameservers), 0) + + def test_query_result_nameserver_continuing_exception(self): + # except for the exceptions tested in + # test_query_result_nameserver_removing_exceptions(), we should + # not remove any nameservers and just continue resolving. + (_, _) = self.resn.next_request() + (_, _, _, _) = self.resn.next_nameserver() + nameservers = self.resn.nameservers[:] + (answer, done) = self.resn.query_result(None, dns.exception.Timeout()) + self.assertTrue(answer is None) + self.assertFalse(done) + self.assertEqual(nameservers, self.resn.nameservers) + + def test_query_result_retry_with_tcp(self): + (request, _) = self.resn.next_request() + (nameserver, _, tcp, _) = self.resn.next_nameserver() + self.assertFalse(tcp) + (answer, done) = self.resn.query_result(None, dns.message.Truncated()) + self.assertTrue(answer is None) + self.assertFalse(done) + self.assertTrue(self.resn.retry_with_tcp) + # The rest of TCP retry logic was tested above in + # test_next_nameserver_retry_with_tcp(), so we do not repeat + # it. + + def test_query_result_no_error_with_data(self): + q = dns.message.make_query(self.qname, dns.rdatatype.A) + r = self.make_address_response(q) + (_, _) = self.resn.next_request() + (_, _, _, _) = self.resn.next_nameserver() + (answer, done) = self.resn.query_result(r, None) + self.assertFalse(answer is None) + self.assertTrue(done) + self.assertEqual(answer.qname, self.qname) + self.assertEqual(answer.rdtype, dns.rdatatype.A) + + def test_query_result_no_error_with_data_cached(self): + self.resolver.cache = dns.resolver.Cache() + q = dns.message.make_query(self.qname, dns.rdatatype.A) + r = self.make_address_response(q) + (_, _) = self.resn.next_request() + (_, _, _, _) = self.resn.next_nameserver() + (answer, done) = self.resn.query_result(r, None) + self.assertFalse(answer is None) + cache_answer = self.resolver.cache.get((self.qname, dns.rdatatype.A, + dns.rdataclass.IN)) + self.assertTrue(answer is cache_answer) + + def test_query_result_no_error_no_data(self): + q = dns.message.make_query(self.qname, dns.rdatatype.A) + r = self.make_negative_response(q) + (_, _) = self.resn.next_request() + (_, _, _, _) = self.resn.next_nameserver() + def bad(): + (answer, done) = self.resn.query_result(r, None) + self.assertRaises(dns.resolver.NoAnswer, bad) + + def test_query_result_nxdomain(self): + q = dns.message.make_query(self.qname, dns.rdatatype.A) + r = self.make_negative_response(q, True) + (_, _) = self.resn.next_request() + (_, _, _, _) = self.resn.next_nameserver() + (answer, done) = self.resn.query_result(r, None) + self.assertTrue(answer is None) + self.assertTrue(done) + + def test_query_result_nxdomain_but_has_answer(self): + q = dns.message.make_query(self.qname, dns.rdatatype.A) + r = self.make_address_response(q) + r.set_rcode(dns.rcode.NXDOMAIN) + (_, _) = self.resn.next_request() + (nameserver, _, _, _) = self.resn.next_nameserver() + (answer, done) = self.resn.query_result(r, None) + self.assertIsNone(answer) + self.assertFalse(done) + self.assertTrue(nameserver not in self.resn.nameservers) + + def test_query_result_chain_not_too_long(self): + q = dns.message.make_query(self.qname, dns.rdatatype.A) + r = self.make_long_chain_response(q, 15) + (_, _) = self.resn.next_request() + (_, _, _, _) = self.resn.next_nameserver() + (answer, done) = self.resn.query_result(r, None) + self.assertIsNotNone(answer) + self.assertTrue(done) + + def test_query_result_chain_too_long(self): + q = dns.message.make_query(self.qname, dns.rdatatype.A) + r = self.make_long_chain_response(q, 16) + (_, _) = self.resn.next_request() + (nameserver, _, _, _) = self.resn.next_nameserver() + (answer, done) = self.resn.query_result(r, None) + self.assertIsNone(answer) + self.assertFalse(done) + self.assertTrue(nameserver not in self.resn.nameservers) + + def test_query_result_nxdomain_cached(self): + self.resolver.cache = dns.resolver.Cache() + q = dns.message.make_query(self.qname, dns.rdatatype.A) + r = self.make_negative_response(q, True) + (_, _) = self.resn.next_request() + (_, _, _, _) = self.resn.next_nameserver() + (answer, done) = self.resn.query_result(r, None) + self.assertTrue(answer is None) + self.assertTrue(done) + cache_answer = self.resolver.cache.get((self.qname, dns.rdatatype.ANY, + dns.rdataclass.IN)) + self.assertTrue(cache_answer.response is r) + + def test_query_result_yxdomain(self): + q = dns.message.make_query(self.qname, dns.rdatatype.A) + r = self.make_address_response(q) + r.set_rcode(dns.rcode.YXDOMAIN) + (_, _) = self.resn.next_request() + (_, _, _, _) = self.resn.next_nameserver() + def bad(): + (answer, done) = self.resn.query_result(r, None) + self.assertRaises(dns.resolver.YXDOMAIN, bad) + + def test_query_result_servfail_no_retry(self): + q = dns.message.make_query(self.qname, dns.rdatatype.A) + r = self.make_address_response(q) + r.set_rcode(dns.rcode.SERVFAIL) + (_, _) = self.resn.next_request() + (nameserver, _, _, _) = self.resn.next_nameserver() + (answer, done) = self.resn.query_result(r, None) + self.assertTrue(answer is None) + self.assertFalse(done) + self.assertTrue(nameserver not in self.resn.nameservers) + + def test_query_result_servfail_with_retry(self): + self.resolver.retry_servfail = True + q = dns.message.make_query(self.qname, dns.rdatatype.A) + r = self.make_address_response(q) + r.set_rcode(dns.rcode.SERVFAIL) + (_, _) = self.resn.next_request() + (_, _, _, _) = self.resn.next_nameserver() + nameservers = self.resn.nameservers[:] + (answer, done) = self.resn.query_result(r, None) + self.assertTrue(answer is None) + self.assertFalse(done) + self.assertEqual(nameservers, self.resn.nameservers) + + def test_query_result_other_unhappy_rcode(self): + q = dns.message.make_query(self.qname, dns.rdatatype.A) + r = self.make_address_response(q) + r.set_rcode(dns.rcode.REFUSED) + (_, _) = self.resn.next_request() + (nameserver, _, _, _) = self.resn.next_nameserver() + (answer, done) = self.resn.query_result(r, None) + self.assertTrue(answer is None) + self.assertFalse(done) + self.assertTrue(nameserver not in self.resn.nameservers) + + def test_no_metaqueries(self): + def bad1(): + self.resn = dns.resolver._Resolution(self.resolver, self.qname, + 'ANY', 'IN', + False, True, False) + def bad2(): + self.resn = dns.resolver._Resolution(self.resolver, self.qname, + 'A', 'ANY', + False, True, False) + self.assertRaises(dns.resolver.NoMetaqueries, bad1) + self.assertRaises(dns.resolver.NoMetaqueries, bad2) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_resolver.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_resolver.py new file mode 100644 index 0000000..4f5643d --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_resolver.py @@ -0,0 +1,945 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2017 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +from io import StringIO +import selectors +import sys +import socket +import time +import unittest + +import dns.e164 +import dns.message +import dns.name +import dns.rdataclass +import dns.rdatatype +import dns.resolver +import dns.tsig +import dns.tsigkeyring + +# Some tests require the internet to be available to run, so let's +# skip those if it's not there. +_network_available = True +try: + socket.gethostbyname('dnspython.org') +except socket.gaierror: + _network_available = False + +# Some tests use a "nano nameserver" for testing. It requires trio +# and threading, so try to import it and if it doesn't work, skip +# those tests. +try: + from .nanonameserver import Server + _nanonameserver_available = True +except ImportError: + _nanonameserver_available = False + class Server(object): + pass + +resolv_conf = u""" + /t/t +# comment 1 +; comment 2 +domain foo +nameserver 10.0.0.1 +nameserver 10.0.0.2 +""" + +resolv_conf_options1 = """ +nameserver 10.0.0.1 +nameserver 10.0.0.2 +search search1 search2 +options rotate timeout:1 edns0 ndots:2 +""" + +bad_timeout_1 = """ +nameserver 10.0.0.1 +nameserver 10.0.0.2 +options rotate timeout +""" + +bad_timeout_2 = """ +nameserver 10.0.0.1 +nameserver 10.0.0.2 +options rotate timeout:bogus +""" + +bad_ndots_1 = """ +nameserver 10.0.0.1 +nameserver 10.0.0.2 +options rotate ndots +""" + +bad_ndots_2 = """ +nameserver 10.0.0.1 +nameserver 10.0.0.2 +options rotate ndots:bogus +""" + +no_nameservers = """ +options rotate +""" + +unknown_and_bad_directives = """ +nameserver 10.0.0.1 +foo bar +bad +""" + +unknown_option = """ +nameserver 10.0.0.1 +option foobar +""" + +message_text = """id 1234 +opcode QUERY +rcode NOERROR +flags QR AA RD +;QUESTION +example. IN A +;ANSWER +example. 1 IN A 10.0.0.1 +;AUTHORITY +;ADDITIONAL +""" + +message_text_mx = """id 1234 +opcode QUERY +rcode NOERROR +flags QR AA RD +;QUESTION +example. IN MX +;ANSWER +example. 1 IN A 10.0.0.1 +;AUTHORITY +;ADDITIONAL +""" + +dangling_cname_0_message_text = """id 10000 +opcode QUERY +rcode NOERROR +flags QR AA RD RA +;QUESTION +91.11.17.172.in-addr.arpa.none. IN PTR +;ANSWER +;AUTHORITY +;ADDITIONAL +""" + +dangling_cname_1_message_text = """id 10001 +opcode QUERY +rcode NOERROR +flags QR AA RD RA +;QUESTION +91.11.17.172.in-addr.arpa. IN PTR +;ANSWER +11.17.172.in-addr.arpa. 86400 IN DNAME 11.8-22.17.172.in-addr.arpa. +91.11.17.172.in-addr.arpa. 86400 IN CNAME 91.11.8-22.17.172.in-addr.arpa. +;AUTHORITY +;ADDITIONAL +""" + +dangling_cname_2_message_text = """id 10002 +opcode QUERY +rcode NOERROR +flags QR AA RD RA +;QUESTION +91.11.17.172.in-addr.arpa.example. IN PTR +;ANSWER +91.11.17.172.in-addr.arpa.example. 86400 IN CNAME 91.11.17.172.in-addr.arpa.base. +91.11.17.172.in-addr.arpa.base. 86400 IN CNAME 91.11.17.172.clients.example. +91.11.17.172.clients.example. 86400 IN CNAME 91-11-17-172.dynamic.example. +;AUTHORITY +;ADDITIONAL +""" + + +class FakeAnswer(object): + def __init__(self, expiration): + self.expiration = expiration + + +class FakeTime: + # Mock the clock! + def __init__(self, now=None, want_fake=True): + if now is None: + now = time.time() + self.now = now + self.saved_time = time.time + self.want_fake = want_fake + + def __enter__(self): + if self.want_fake: + time.time = self.time + return self + + def __exit__(self, exc_type, exc_value, traceback): + if self.want_fake: + time.time = self.saved_time + return False + + def time(self): + if self.want_fake: + return self.now + else: + return time.time() + + def sleep(self, offset): + if self.want_fake: + self.now += offset + else: + time.sleep(offset) + + +class BaseResolverTests(unittest.TestCase): + + def testRead(self): + f = StringIO(resolv_conf) + r = dns.resolver.Resolver(configure=False) + r.read_resolv_conf(f) + self.assertEqual(r.nameservers, ['10.0.0.1', '10.0.0.2']) + self.assertEqual(r.domain, dns.name.from_text('foo')) + + def testReadOptions(self): + f = StringIO(resolv_conf_options1) + r = dns.resolver.Resolver(configure=False) + r.read_resolv_conf(f) + self.assertEqual(r.nameservers, ['10.0.0.1', '10.0.0.2']) + self.assertTrue(r.rotate) + self.assertEqual(r.timeout, 1) + self.assertEqual(r.ndots, 2) + self.assertEqual(r.edns, 0) + self.assertEqual(r.payload, dns.message.DEFAULT_EDNS_PAYLOAD) + + def testReadOptionsBadTimeouts(self): + f = StringIO(bad_timeout_1) + r = dns.resolver.Resolver(configure=False) + r.read_resolv_conf(f) + # timeout should still be default + self.assertEqual(r.timeout, 2.0) + f = StringIO(bad_timeout_2) + r = dns.resolver.Resolver(configure=False) + r.read_resolv_conf(f) + # timeout should still be default + self.assertEqual(r.timeout, 2.0) + + def testReadOptionsBadNdots(self): + f = StringIO(bad_ndots_1) + r = dns.resolver.Resolver(configure=False) + r.read_resolv_conf(f) + # ndots should still be default + self.assertEqual(r.ndots, None) + f = StringIO(bad_ndots_2) + r = dns.resolver.Resolver(configure=False) + r.read_resolv_conf(f) + # ndots should still be default + self.assertEqual(r.ndots, None) + + def testReadNoNameservers(self): + f = StringIO(no_nameservers) + r = dns.resolver.Resolver(configure=False) + with self.assertRaises(dns.resolver.NoResolverConfiguration): + r.read_resolv_conf(f) + + def testReadUnknownDirective(self): + # The real test here is ignoring the unknown directive and the bad + # directive. + f = StringIO(unknown_and_bad_directives) + r = dns.resolver.Resolver(configure=False) + r.read_resolv_conf(f) + self.assertEqual(r.nameservers, ['10.0.0.1']) + + def testReadUnknownOption(self): + # The real test here is ignoring the unknown option + f = StringIO(unknown_option) + r = dns.resolver.Resolver(configure=False) + r.read_resolv_conf(f) + self.assertEqual(r.nameservers, ['10.0.0.1']) + + def testCacheExpiration(self): + with FakeTime() as fake_time: + message = dns.message.from_text(message_text) + name = dns.name.from_text('example.') + answer = dns.resolver.Answer(name, dns.rdatatype.A, + dns.rdataclass.IN, message) + cache = dns.resolver.Cache() + cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer) + fake_time.sleep(2) + self.assertTrue(cache.get((name, dns.rdatatype.A, + dns.rdataclass.IN)) + is None) + + def testCacheCleaning(self): + with FakeTime() as fake_time: + message = dns.message.from_text(message_text) + name = dns.name.from_text('example.') + answer = dns.resolver.Answer(name, dns.rdatatype.A, + dns.rdataclass.IN, message) + cache = dns.resolver.Cache(cleaning_interval=1.0) + cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer) + fake_time.sleep(2) + cache._maybe_clean() + self.assertTrue(cache.data.get((name, dns.rdatatype.A, + dns.rdataclass.IN)) + is None) + + def testCacheNonCleaning(self): + with FakeTime() as fake_time: + message = dns.message.from_text(message_text) + name = dns.name.from_text('example.') + answer = dns.resolver.Answer(name, dns.rdatatype.A, + dns.rdataclass.IN, message) + # override TTL as we're testing non-cleaning + answer.expiration = fake_time.time() + 100 + cache = dns.resolver.Cache(cleaning_interval=1.0) + cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer) + fake_time.sleep(1.1) + self.assertEqual(cache.get((name, dns.rdatatype.A, + dns.rdataclass.IN)), answer) + + def testIndexErrorOnEmptyRRsetAccess(self): + def bad(): + message = dns.message.from_text(message_text_mx) + name = dns.name.from_text('example.') + answer = dns.resolver.Answer(name, dns.rdatatype.MX, + dns.rdataclass.IN, message) + return answer[0] + self.assertRaises(IndexError, bad) + + def testIndexErrorOnEmptyRRsetDelete(self): + def bad(): + message = dns.message.from_text(message_text_mx) + name = dns.name.from_text('example.') + answer = dns.resolver.Answer(name, dns.rdatatype.MX, + dns.rdataclass.IN, message) + del answer[0] + self.assertRaises(IndexError, bad) + + def testRRsetDelete(self): + message = dns.message.from_text(message_text) + name = dns.name.from_text('example.') + answer = dns.resolver.Answer(name, dns.rdatatype.A, + dns.rdataclass.IN, message) + del answer[0] + self.assertEqual(len(answer), 0) + + def testLRUReplace(self): + cache = dns.resolver.LRUCache(4) + for i in range(0, 5): + name = dns.name.from_text('example%d.' % i) + answer = FakeAnswer(time.time() + 1) + cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer) + for i in range(0, 5): + name = dns.name.from_text('example%d.' % i) + if i == 0: + self.assertTrue(cache.get((name, dns.rdatatype.A, + dns.rdataclass.IN)) + is None) + else: + self.assertTrue(not cache.get((name, dns.rdatatype.A, + dns.rdataclass.IN)) + is None) + + def testLRUDoesLRU(self): + cache = dns.resolver.LRUCache(4) + for i in range(0, 4): + name = dns.name.from_text('example%d.' % i) + answer = FakeAnswer(time.time() + 1) + cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer) + name = dns.name.from_text('example0.') + cache.get((name, dns.rdatatype.A, dns.rdataclass.IN)) + # The LRU is now example1. + name = dns.name.from_text('example4.') + answer = FakeAnswer(time.time() + 1) + cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer) + for i in range(0, 5): + name = dns.name.from_text('example%d.' % i) + if i == 1: + self.assertTrue(cache.get((name, dns.rdatatype.A, + dns.rdataclass.IN)) + is None) + else: + self.assertTrue(not cache.get((name, dns.rdatatype.A, + dns.rdataclass.IN)) + is None) + + def testLRUExpiration(self): + with FakeTime() as fake_time: + cache = dns.resolver.LRUCache(4) + for i in range(0, 4): + name = dns.name.from_text('example%d.' % i) + answer = FakeAnswer(time.time() + 1) + cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer) + fake_time.sleep(2) + for i in range(0, 4): + name = dns.name.from_text('example%d.' % i) + self.assertTrue(cache.get((name, dns.rdatatype.A, + dns.rdataclass.IN)) + is None) + + def test_cache_flush(self): + name1 = dns.name.from_text('name1') + name2 = dns.name.from_text('name2') + name3 = dns.name.from_text('name3') + basic_cache = dns.resolver.Cache() + lru_cache = dns.resolver.LRUCache(100) + for cache in [basic_cache, lru_cache]: + answer1 = FakeAnswer(time.time() + 10) + answer2 = FakeAnswer(time.time() + 10) + cache.put((name1, dns.rdatatype.A, dns.rdataclass.IN), answer1) + cache.put((name2, dns.rdatatype.A, dns.rdataclass.IN), answer2) + canswer = cache.get((name1, dns.rdatatype.A, dns.rdataclass.IN)) + self.assertTrue(canswer is answer1) + canswer = cache.get((name2, dns.rdatatype.A, dns.rdataclass.IN)) + self.assertTrue(canswer is answer2) + # explicit flush of nonexistent key, just to exercise the branch + cache.flush((name3, dns.rdatatype.A, dns.rdataclass.IN)) + canswer = cache.get((name1, dns.rdatatype.A, dns.rdataclass.IN)) + self.assertTrue(canswer is answer1) + canswer = cache.get((name2, dns.rdatatype.A, dns.rdataclass.IN)) + self.assertTrue(canswer is answer2) + # explicit flush + cache.flush((name1, dns.rdatatype.A, dns.rdataclass.IN)) + canswer = cache.get((name1, dns.rdatatype.A, dns.rdataclass.IN)) + self.assertTrue(canswer is None) + canswer = cache.get((name2, dns.rdatatype.A, dns.rdataclass.IN)) + self.assertTrue(canswer is answer2) + # flush all + cache.flush() + canswer = cache.get((name1, dns.rdatatype.A, dns.rdataclass.IN)) + self.assertTrue(canswer is None) + canswer = cache.get((name2, dns.rdatatype.A, dns.rdataclass.IN)) + self.assertTrue(canswer is None) + + def test_LRUCache_set_max_size(self): + cache = dns.resolver.LRUCache(4) + self.assertEqual(cache.max_size, 4) + cache.set_max_size(0) + self.assertEqual(cache.max_size, 1) + + def test_LRUCache_overwrite(self): + def on_lru_list(cache, key, value): + cnode = cache.sentinel.next + while cnode != cache.sentinel: + if cnode.key == key and cnode.value is value: + return True + cnode = cnode.next + return False + cache = dns.resolver.LRUCache(4) + answer1 = FakeAnswer(time.time() + 10) + answer2 = FakeAnswer(time.time() + 10) + key = (dns.name.from_text('key.'), dns.rdatatype.A, dns.rdataclass.IN) + cache.put(key, answer1) + canswer = cache.get(key) + self.assertTrue(canswer is answer1) + self.assertTrue(on_lru_list(cache, key, answer1)) + cache.put(key, answer2) + canswer = cache.get(key) + self.assertTrue(canswer is answer2) + self.assertFalse(on_lru_list(cache, key, answer1)) + self.assertTrue(on_lru_list(cache, key, answer2)) + + def test_cache_stats(self): + caches = [dns.resolver.Cache(), dns.resolver.LRUCache(4)] + key1 = (dns.name.from_text('key1.'), dns.rdatatype.A, dns.rdataclass.IN) + key2 = (dns.name.from_text('key2.'), dns.rdatatype.A, dns.rdataclass.IN) + for cache in caches: + answer1 = FakeAnswer(time.time() + 10) + answer2 = FakeAnswer(10) # expired! + a = cache.get(key1) + self.assertIsNone(a) + self.assertEqual(cache.hits(), 0) + self.assertEqual(cache.misses(), 1) + if isinstance(cache, dns.resolver.LRUCache): + self.assertEqual(cache.get_hits_for_key(key1), 0) + cache.put(key1, answer1) + a = cache.get(key1) + self.assertIs(a, answer1) + self.assertEqual(cache.hits(), 1) + self.assertEqual(cache.misses(), 1) + if isinstance(cache, dns.resolver.LRUCache): + self.assertEqual(cache.get_hits_for_key(key1), 1) + cache.put(key2, answer2) + a = cache.get(key2) + self.assertIsNone(a) + self.assertEqual(cache.hits(), 1) + self.assertEqual(cache.misses(), 2) + if isinstance(cache, dns.resolver.LRUCache): + self.assertEqual(cache.get_hits_for_key(key2), 0) + stats = cache.get_statistics_snapshot() + self.assertEqual(stats.hits, 1) + self.assertEqual(stats.misses, 2) + cache.reset_statistics() + stats = cache.get_statistics_snapshot() + self.assertEqual(stats.hits, 0) + self.assertEqual(stats.misses, 0) + + def testEmptyAnswerSection(self): + # TODO: dangling_cname_0_message_text was the only sample message + # with an empty answer section. Other than that it doesn't + # apply. + message = dns.message.from_text(dangling_cname_0_message_text) + name = dns.name.from_text('example.') + answer = dns.resolver.Answer(name, dns.rdatatype.A, dns.rdataclass.IN, + message) + def test_python_internal_truth(answer): + if answer: + return True + else: + return False + self.assertFalse(test_python_internal_truth(answer)) + for a in answer: + pass + + def testSearchListsRelative(self): + res = dns.resolver.Resolver(configure=False) + res.domain = dns.name.from_text('example') + res.search = [dns.name.from_text(x) for x in + ['dnspython.org', 'dnspython.net']] + qname = dns.name.from_text('www', None) + qnames = res._get_qnames_to_try(qname, True) + self.assertEqual(qnames, + [dns.name.from_text(x) for x in + ['www.dnspython.org', 'www.dnspython.net', 'www.']]) + qnames = res._get_qnames_to_try(qname, False) + self.assertEqual(qnames, + [dns.name.from_text('www.')]) + qnames = res._get_qnames_to_try(qname, None) + self.assertEqual(qnames, + [dns.name.from_text('www.')]) + # + # Now change search default on resolver to True + # + res.use_search_by_default = True + qnames = res._get_qnames_to_try(qname, None) + self.assertEqual(qnames, + [dns.name.from_text(x) for x in + ['www.dnspython.org', 'www.dnspython.net', 'www.']]) + # + # Now test ndots + # + qname = dns.name.from_text('a.b', None) + res.ndots = 1 + qnames = res._get_qnames_to_try(qname, True) + self.assertEqual(qnames, + [dns.name.from_text(x) for x in + ['a.b', 'a.b.dnspython.org', 'a.b.dnspython.net']]) + res.ndots = 2 + qnames = res._get_qnames_to_try(qname, True) + self.assertEqual(qnames, + [dns.name.from_text(x) for x in + ['a.b.dnspython.org', 'a.b.dnspython.net', 'a.b']]) + qname = dns.name.from_text('a.b.c', None) + qnames = res._get_qnames_to_try(qname, True) + self.assertEqual(qnames, + [dns.name.from_text(x) for x in + ['a.b.c', 'a.b.c.dnspython.org', + 'a.b.c.dnspython.net']]) + + def testSearchListsAbsolute(self): + res = dns.resolver.Resolver(configure=False) + qname = dns.name.from_text('absolute') + qnames = res._get_qnames_to_try(qname, True) + self.assertEqual(qnames, [qname]) + qnames = res._get_qnames_to_try(qname, False) + self.assertEqual(qnames, [qname]) + qnames = res._get_qnames_to_try(qname, None) + self.assertEqual(qnames, [qname]) + + def testUseEDNS(self): + r = dns.resolver.Resolver(configure=False) + r.use_edns(None) + self.assertEqual(r.edns, -1) + r.use_edns(False) + self.assertEqual(r.edns, -1) + r.use_edns(True) + self.assertEqual(r.edns, 0) + + def testSetFlags(self): + flags = dns.flags.CD | dns.flags.RD + r = dns.resolver.Resolver(configure=False) + r.set_flags(flags) + self.assertEqual(r.flags, flags) + + def testUseTSIG(self): + keyring = dns.tsigkeyring.from_text( + { + 'keyname.': 'NjHwPsMKjdN++dOfE5iAiQ==' + } + ) + r = dns.resolver.Resolver(configure=False) + r.use_tsig(keyring) + self.assertEqual(r.keyring, keyring) + self.assertEqual(r.keyname, None) + self.assertEqual(r.keyalgorithm, dns.tsig.default_algorithm) + +keyname = dns.name.from_text('keyname') + + + +@unittest.skipIf(not _network_available, "Internet not reachable") +class LiveResolverTests(unittest.TestCase): + def testZoneForName1(self): + name = dns.name.from_text('www.dnspython.org.') + ezname = dns.name.from_text('dnspython.org.') + zname = dns.resolver.zone_for_name(name) + self.assertEqual(zname, ezname) + + def testZoneForName2(self): + name = dns.name.from_text('a.b.www.dnspython.org.') + ezname = dns.name.from_text('dnspython.org.') + zname = dns.resolver.zone_for_name(name) + self.assertEqual(zname, ezname) + + def testZoneForName3(self): + ezname = dns.name.from_text('dnspython.org.') + zname = dns.resolver.zone_for_name('dnspython.org.') + self.assertEqual(zname, ezname) + + def testZoneForName4(self): + def bad(): + name = dns.name.from_text('dnspython.org', None) + dns.resolver.zone_for_name(name) + self.assertRaises(dns.resolver.NotAbsolute, bad) + + def testResolve(self): + answer = dns.resolver.resolve('dns.google.', 'A') + seen = set([rdata.address for rdata in answer]) + self.assertTrue('8.8.8.8' in seen) + self.assertTrue('8.8.4.4' in seen) + + def testResolveTCP(self): + answer = dns.resolver.resolve('dns.google.', 'A', tcp=True) + seen = set([rdata.address for rdata in answer]) + self.assertTrue('8.8.8.8' in seen) + self.assertTrue('8.8.4.4' in seen) + + def testResolveAddress(self): + answer = dns.resolver.resolve_address('8.8.8.8') + dnsgoogle = dns.name.from_text('dns.google.') + self.assertEqual(answer[0].target, dnsgoogle) + + def testResolveNodataException(self): + def bad(): + dns.resolver.resolve('dnspython.org.', 'SRV') + self.assertRaises(dns.resolver.NoAnswer, bad) + + def testResolveNodataAnswer(self): + qname = dns.name.from_text('dnspython.org') + qclass = dns.rdataclass.from_text('IN') + qtype = dns.rdatatype.from_text('SRV') + answer = dns.resolver.resolve(qname, qtype, raise_on_no_answer=False) + self.assertRaises(KeyError, + lambda: answer.response.find_rrset(answer.response.answer, + qname, qclass, qtype)) + + def testResolveNXDOMAIN(self): + qname = dns.name.from_text('nxdomain.dnspython.org') + qclass = dns.rdataclass.from_text('IN') + qtype = dns.rdatatype.from_text('A') + def bad(): + answer = dns.resolver.resolve(qname, qtype) + try: + dns.resolver.resolve(qname, qtype) + self.assertTrue(False) # should not happen! + except dns.resolver.NXDOMAIN as nx: + self.assertIn(qname, nx.qnames()) + self.assertGreaterEqual(len(nx.responses()), 1) + + def testResolveCacheHit(self): + res = dns.resolver.Resolver(configure=False) + res.nameservers = ['8.8.8.8'] + res.cache = dns.resolver.Cache() + answer1 = res.resolve('dns.google.', 'A') + seen = set([rdata.address for rdata in answer1]) + self.assertIn('8.8.8.8', seen) + self.assertIn('8.8.4.4', seen) + answer2 = res.resolve('dns.google.', 'A') + self.assertIs(answer2, answer1) + + def testCanonicalNameNoCNAME(self): + cname = dns.name.from_text('www.google.com') + self.assertEqual(dns.resolver.canonical_name('www.google.com'), cname) + + def testCanonicalNameCNAME(self): + name = dns.name.from_text('www.dnspython.org') + cname = dns.name.from_text('dmfrjf4ips8xa.cloudfront.net') + self.assertEqual(dns.resolver.canonical_name(name), cname) + + def testCanonicalNameDangling(self): + name = dns.name.from_text('dangling-cname.dnspython.org') + cname = dns.name.from_text('dangling-target.dnspython.org') + self.assertEqual(dns.resolver.canonical_name(name), cname) + +class PollingMonkeyPatchMixin(object): + def setUp(self): + self.__native_selector_class = dns.query._selector_class + dns.query._set_selector_class(self.selector_class()) + + unittest.TestCase.setUp(self) + + def tearDown(self): + dns.query._set_selector_class(self.__native_selector_class) + + unittest.TestCase.tearDown(self) + + +class SelectResolverTestCase(PollingMonkeyPatchMixin, LiveResolverTests, unittest.TestCase): + def selector_class(self): + return selectors.SelectSelector + + +if hasattr(selectors, 'PollSelector'): + class PollResolverTestCase(PollingMonkeyPatchMixin, LiveResolverTests, unittest.TestCase): + def selector_class(self): + return selectors.PollSelector + + +class NXDOMAINExceptionTestCase(unittest.TestCase): + + # pylint: disable=broad-except + + def test_nxdomain_compatible(self): + n1 = dns.name.Name(('a', 'b', '')) + n2 = dns.name.Name(('a', 'b', 's', '')) + + try: + raise dns.resolver.NXDOMAIN + except dns.exception.DNSException as e: + self.assertEqual(e.args, (e.__doc__,)) + self.assertTrue(('kwargs' in dir(e))) + self.assertEqual(str(e), e.__doc__, str(e)) + self.assertTrue(('qnames' not in e.kwargs)) + self.assertTrue(('responses' not in e.kwargs)) + + try: + raise dns.resolver.NXDOMAIN("errmsg") + except dns.exception.DNSException as e: + self.assertEqual(e.args, ("errmsg",)) + self.assertTrue(('kwargs' in dir(e))) + self.assertEqual(str(e), "errmsg", str(e)) + self.assertTrue(('qnames' not in e.kwargs)) + self.assertTrue(('responses' not in e.kwargs)) + + try: + raise dns.resolver.NXDOMAIN("errmsg", -1) + except dns.exception.DNSException as e: + self.assertEqual(e.args, ("errmsg", -1)) + self.assertTrue(('kwargs' in dir(e))) + self.assertEqual(str(e), "('errmsg', -1)", str(e)) + self.assertTrue(('qnames' not in e.kwargs)) + self.assertTrue(('responses' not in e.kwargs)) + + try: + raise dns.resolver.NXDOMAIN(qnames=None) + except Exception as e: + self.assertTrue((isinstance(e, AttributeError))) + + try: + raise dns.resolver.NXDOMAIN(qnames=n1) + except Exception as e: + self.assertTrue((isinstance(e, AttributeError))) + + try: + raise dns.resolver.NXDOMAIN(qnames=[]) + except Exception as e: + self.assertTrue((isinstance(e, AttributeError))) + + try: + raise dns.resolver.NXDOMAIN(qnames=[n1]) + except dns.exception.DNSException as e: + MSG = "The DNS query name does not exist: a.b." + self.assertEqual(e.args, (MSG,), repr(e.args)) + self.assertTrue(('kwargs' in dir(e))) + self.assertEqual(str(e), MSG, str(e)) + self.assertTrue(('qnames' in e.kwargs)) + self.assertEqual(e.kwargs['qnames'], [n1]) + self.assertTrue(('responses' in e.kwargs)) + self.assertEqual(e.kwargs['responses'], {}) + + try: + raise dns.resolver.NXDOMAIN(qnames=[n2, n1]) + except dns.resolver.NXDOMAIN as e: + e0 = dns.resolver.NXDOMAIN("errmsg") + e = e0 + e + MSG = "None of DNS query names exist: a.b.s., a.b." + self.assertEqual(e.args, (MSG,), repr(e.args)) + self.assertTrue(('kwargs' in dir(e))) + self.assertEqual(str(e), MSG, str(e)) + self.assertTrue(('qnames' in e.kwargs)) + self.assertEqual(e.kwargs['qnames'], [n2, n1]) + self.assertTrue(('responses' in e.kwargs)) + self.assertEqual(e.kwargs['responses'], {}) + + try: + raise dns.resolver.NXDOMAIN(qnames=[n1], responses=['r1.1']) + except Exception as e: + self.assertTrue((isinstance(e, AttributeError))) + + try: + raise dns.resolver.NXDOMAIN(qnames=[n1], responses={n1: 'r1.1'}) + except dns.resolver.NXDOMAIN as e: + MSG = "The DNS query name does not exist: a.b." + self.assertEqual(e.args, (MSG,), repr(e.args)) + self.assertTrue(('kwargs' in dir(e))) + self.assertEqual(str(e), MSG, str(e)) + self.assertTrue(('qnames' in e.kwargs)) + self.assertEqual(e.kwargs['qnames'], [n1]) + self.assertTrue(('responses' in e.kwargs)) + self.assertEqual(e.kwargs['responses'], {n1: 'r1.1'}) + + def test_nxdomain_merge(self): + n1 = dns.name.Name(('a', 'b', '')) + n2 = dns.name.Name(('a', 'b', '')) + n3 = dns.name.Name(('a', 'b', 'c', '')) + n4 = dns.name.Name(('a', 'b', 'd', '')) + responses1 = {n1: 'r1.1', n2: 'r1.2', n4: 'r1.4'} + qnames1 = [n1, n4] # n2 == n1 + responses2 = {n2: 'r2.2', n3: 'r2.3'} + qnames2 = [n2, n3] + e0 = dns.resolver.NXDOMAIN() + e1 = dns.resolver.NXDOMAIN(qnames=qnames1, responses=responses1) + e2 = dns.resolver.NXDOMAIN(qnames=qnames2, responses=responses2) + e = e1 + e0 + e2 + self.assertRaises(AttributeError, lambda: e0 + e0) + self.assertEqual(e.kwargs['qnames'], [n1, n4, n3], + repr(e.kwargs['qnames'])) + self.assertTrue(e.kwargs['responses'][n1].startswith('r2.')) + self.assertTrue(e.kwargs['responses'][n2].startswith('r2.')) + self.assertTrue(e.kwargs['responses'][n3].startswith('r2.')) + self.assertTrue(e.kwargs['responses'][n4].startswith('r1.')) + + def test_nxdomain_canonical_name(self): + cname1 = "91.11.8-22.17.172.in-addr.arpa." + cname2 = "91-11-17-172.dynamic.example." + message0 = dns.message.from_text(dangling_cname_0_message_text) + message1 = dns.message.from_text(dangling_cname_1_message_text) + message2 = dns.message.from_text(dangling_cname_2_message_text) + qname0 = message0.question[0].name + qname1 = message1.question[0].name + qname2 = message2.question[0].name + responses = {qname0: message0, qname1: message1, qname2: message2} + eX = dns.resolver.NXDOMAIN() + e0 = dns.resolver.NXDOMAIN(qnames=[qname0], responses=responses) + e1 = dns.resolver.NXDOMAIN(qnames=[qname0, qname1, qname2], responses=responses) + e2 = dns.resolver.NXDOMAIN(qnames=[qname0, qname2, qname1], responses=responses) + self.assertRaises(TypeError, lambda: eX.canonical_name) + self.assertEqual(e0.canonical_name, qname0) + self.assertEqual(e1.canonical_name, dns.name.from_text(cname1)) + self.assertEqual(e2.canonical_name, dns.name.from_text(cname2)) + + +class ResolverMiscTestCase(unittest.TestCase): + if sys.platform != 'win32': + def test_read_nonexistent_config(self): + res = dns.resolver.Resolver(configure=False) + pathname = '/etc/nonexistent-resolv.conf' + self.assertRaises(dns.resolver.NoResolverConfiguration, + lambda: res.read_resolv_conf(pathname)) + + def test_compute_timeout(self): + res = dns.resolver.Resolver(configure=False) + now = time.time() + self.assertRaises(dns.resolver.Timeout, + lambda: res._compute_timeout(now + 10000)) + self.assertRaises(dns.resolver.Timeout, + lambda: res._compute_timeout(0)) + # not raising is the test + res._compute_timeout(now + 0.5) + + +class ResolverNameserverValidTypeTestCase(unittest.TestCase): + def test_set_nameservers_to_list(self): + resolver = dns.resolver.Resolver(configure=False) + resolver.nameservers = ['1.2.3.4'] + self.assertEqual(resolver.nameservers, ['1.2.3.4']) + + def test_set_namservers_to_empty_list(self): + resolver = dns.resolver.Resolver(configure=False) + resolver.nameservers = [] + self.assertEqual(resolver.nameservers, []) + + def test_set_nameservers_invalid_type(self): + resolver = dns.resolver.Resolver(configure=False) + invalid_nameservers = [None, '1.2.3.4', 1234, (1, 2, 3, 4), {'invalid': 'nameserver'}] + for invalid_nameserver in invalid_nameservers: + with self.assertRaises(ValueError): + resolver.nameservers = invalid_nameserver + + +class NaptrNanoNameserver(Server): + + def handle(self, request): + response = dns.message.make_response(request.message) + response.set_rcode(dns.rcode.REFUSED) + response.flags |= dns.flags.RA + try: + zero_subdomain = dns.e164.from_e164('0') + if request.qname.is_subdomain(zero_subdomain): + response.set_rcode(dns.rcode.NXDOMAIN) + response.flags |= dns.flags.AA + elif request.qtype == dns.rdatatype.NAPTR and \ + request.qclass == dns.rdataclass.IN: + rrs = dns.rrset.from_text(request.qname, 300, 'IN', 'NAPTR', + '0 0 "" "" "" .') + response.answer.append(rrs) + response.set_rcode(dns.rcode.NOERROR) + response.flags |= dns.flags.AA + except Exception: + pass + return response + + +@unittest.skipIf(not (_network_available and _nanonameserver_available), + "Internet and NanoAuth required") +class NanoTests(unittest.TestCase): + + def testE164Query(self): + with NaptrNanoNameserver() as na: + res = dns.resolver.Resolver(configure=False) + res.port = na.udp_address[1] + res.nameservers = [na.udp_address[0]] + answer = dns.e164.query('1650551212', ['e164.arpa'], res) + self.assertEqual(answer[0].order, 0) + self.assertEqual(answer[0].preference, 0) + self.assertEqual(answer[0].flags, b'') + self.assertEqual(answer[0].service, b'') + self.assertEqual(answer[0].regexp, b'') + self.assertEqual(answer[0].replacement, dns.name.root) + with self.assertRaises(dns.resolver.NXDOMAIN): + dns.e164.query('0123456789', ['e164.arpa'], res) + + +class AlwaysType3NXDOMAINNanoNameserver(Server): + + def handle(self, request): + response = dns.message.make_response(request.message) + response.set_rcode(dns.rcode.NXDOMAIN) + response.flags |= dns.flags.RA + return response + +@unittest.skipIf(not (_network_available and _nanonameserver_available), + "Internet and NanoAuth required") +class ZoneForNameNoParentTest(unittest.TestCase): + + def testNoRootSOA(self): + with AlwaysType3NXDOMAINNanoNameserver() as na: + res = dns.resolver.Resolver(configure=False) + res.port = na.udp_address[1] + res.nameservers = [na.udp_address[0]] + with self.assertRaises(dns.resolver.NoRootSOA): + dns.resolver.zone_for_name('www.foo.bar.', resolver=res) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_resolver_override.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_resolver_override.py new file mode 100644 index 0000000..ac93316 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_resolver_override.py @@ -0,0 +1,222 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import socket +import sys +import unittest + +import dns.name +import dns.rdataclass +import dns.rdatatype +import dns.resolver + +# Some tests require the internet to be available to run, so let's +# skip those if it's not there. +_network_available = True +try: + socket.gethostbyname('dnspython.org') +except socket.gaierror: + _network_available = False + + +@unittest.skipIf(not _network_available, "Internet not reachable") +class OverrideSystemResolverTestCase(unittest.TestCase): + + def setUp(self): + self.res = dns.resolver.Resolver(configure=False) + self.res.nameservers = ['8.8.8.8'] + self.res.cache = dns.resolver.LRUCache() + dns.resolver.override_system_resolver(self.res) + + def tearDown(self): + dns.resolver.restore_system_resolver() + self.res = None + + def test_override(self): + self.assertTrue(socket.getaddrinfo is + dns.resolver._getaddrinfo) + socket.gethostbyname('www.dnspython.org') + answer = self.res.cache.get((dns.name.from_text('www.dnspython.org.'), + dns.rdatatype.A, dns.rdataclass.IN)) + self.assertTrue(answer is not None) + self.res.cache.flush() + socket.gethostbyname_ex('www.dnspython.org') + answer = self.res.cache.get((dns.name.from_text('www.dnspython.org.'), + dns.rdatatype.A, dns.rdataclass.IN)) + self.assertTrue(answer is not None) + self.res.cache.flush() + socket.getfqdn('8.8.8.8') + answer = self.res.cache.get( + (dns.name.from_text('8.8.8.8.in-addr.arpa.'), + dns.rdatatype.PTR, dns.rdataclass.IN)) + self.assertTrue(answer is not None) + self.res.cache.flush() + socket.gethostbyaddr('8.8.8.8') + answer = self.res.cache.get( + (dns.name.from_text('8.8.8.8.in-addr.arpa.'), + dns.rdatatype.PTR, dns.rdataclass.IN)) + self.assertTrue(answer is not None) + # restoring twice is harmless, so we restore now instead of + # waiting for tearDown so we can assert that it worked + dns.resolver.restore_system_resolver() + self.assertTrue(socket.getaddrinfo is + dns.resolver._original_getaddrinfo) + + def equivalent_info(self, a, b): + if len(a) != len(b): + return False + for x in a: + if x not in b: + # Windows does not set the protocol to non-zero, so try + # looking for a zero protocol. + y = (x[0], x[1], 0, x[3], x[4]) + if y not in b: + print('NOT EQUIVALENT') + print(a) + print(b) + return False + return True + + def equivalent(self, *args, **kwargs): + a = socket.getaddrinfo(*args, **kwargs) + b = dns.resolver._original_getaddrinfo(*args, **kwargs) + return self.equivalent_info(a, b) + + @unittest.skipIf(sys.platform == 'win32', + 'avoid windows original getaddrinfo issues') + def test_basic_getaddrinfo(self): + self.assertTrue(self.equivalent('dns.google', 53, socket.AF_INET, + socket.SOCK_DGRAM)) + self.assertTrue(self.equivalent('dns.google', 53, socket.AF_INET6, + socket.SOCK_DGRAM)) + self.assertTrue(self.equivalent('dns.google', None, socket.AF_UNSPEC, + socket.SOCK_DGRAM)) + self.assertTrue(self.equivalent('8.8.8.8', 53, socket.AF_INET, + socket.SOCK_DGRAM)) + self.assertTrue(self.equivalent('2001:4860:4860::8888', 53, + socket.AF_INET6, socket.SOCK_DGRAM)) + self.assertTrue(self.equivalent('8.8.8.8', 53, socket.AF_INET, + socket.SOCK_DGRAM, + flags=socket.AI_NUMERICHOST)) + self.assertTrue(self.equivalent('2001:4860:4860::8888', 53, + socket.AF_INET6, socket.SOCK_DGRAM, + flags=socket.AI_NUMERICHOST)) + + def test_getaddrinfo_nxdomain(self): + try: + socket.getaddrinfo('nxdomain.dnspython.org.', 53) + self.assertTrue(False) # should not happen! + except socket.gaierror as e: + self.assertEqual(e.errno, socket.EAI_NONAME) + + def test_getaddrinfo_service(self): + a = socket.getaddrinfo('dns.google', 'domain') + b = socket.getaddrinfo('dns.google', 53) + self.assertTrue(self.equivalent_info(a, b)) + try: + socket.getaddrinfo('dns.google', 'domain', + flags=socket.AI_NUMERICSERV) + self.assertTrue(False) # should not happen! + except socket.gaierror as e: + self.assertEqual(e.errno, socket.EAI_NONAME) + + def test_getaddrinfo_only_service(self): + infos = socket.getaddrinfo(service=53, family=socket.AF_INET, + socktype=socket.SOCK_DGRAM, + proto=socket.IPPROTO_UDP) + self.assertEqual(len(infos), 1) + info = infos[0] + self.assertEqual(info[0], socket.AF_INET) + self.assertEqual(info[1], socket.SOCK_DGRAM) + self.assertEqual(info[2], socket.IPPROTO_UDP) + self.assertEqual(info[4], ('127.0.0.1', 53)) + + def test_unknown_service_fails(self): + with self.assertRaises(socket.gaierror): + socket.getaddrinfo('dns.google.', 'bogus-service') + + def test_getnameinfo_tcp(self): + info = socket.getnameinfo(('8.8.8.8', 53)) + self.assertEqual(info, ('dns.google', 'domain')) + + def test_getnameinfo_udp(self): + info = socket.getnameinfo(('8.8.8.8', 53), socket.NI_DGRAM) + self.assertEqual(info, ('dns.google', 'domain')) + + +# Give up on testing this for now as all of the names I've considered +# using for testing are part of CDNs and there is deep magic in +# gethostbyaddr() that python's getfqdn() is using. At any rate, +# the problem is that dnspython just gives up whereas the native python +# code is looking up www.dnspython.org, picking a CDN IPv4 address +# (sometimes) and returning the reverse lookup of that address (i.e. +# the domain name of the CDN server). This isn't what I'd consider the +# FQDN of www.dnspython.org to be! +# +# def test_getfqdn(self): +# b = socket.getfqdn('www.dnspython.org') +# # we do this now because python's original getfqdn calls +# # gethostbyaddr() and we don't want it to call us! +# dns.resolver.restore_system_resolver() +# a = dns.resolver._original_getfqdn('www.dnspython.org') +# self.assertEqual(dns.name.from_text(a), dns.name.from_text(b)) + + def test_gethostbyaddr(self): + a = dns.resolver._original_gethostbyaddr('8.8.8.8') + b = socket.gethostbyaddr('8.8.8.8') + # We only test elements 0 and 2 as we don't set aliases currently! + self.assertEqual(a[0], b[0]) + self.assertEqual(a[2], b[2]) + a = dns.resolver._original_gethostbyaddr('2001:4860:4860::8888') + b = socket.gethostbyaddr('2001:4860:4860::8888') + self.assertEqual(a[0], b[0]) + self.assertEqual(a[2], b[2]) + + +class FakeResolver: + def resolve(self, *args, **kwargs): + raise dns.exception.Timeout + + +class OverrideSystemResolverUsingFakeResolverTestCase(unittest.TestCase): + + def setUp(self): + self.res = FakeResolver() + dns.resolver.override_system_resolver(self.res) + + def tearDown(self): + dns.resolver.restore_system_resolver() + self.res = None + + def test_temporary_failure(self): + with self.assertRaises(socket.gaierror): + socket.getaddrinfo('dns.google') + + # We don't need the fake resolver for the following tests, but we + # don't need the live network either, so we're testing here. + + def test_no_host_or_service_fails(self): + with self.assertRaises(socket.gaierror): + socket.getaddrinfo() + + def test_AI_ADDRCONFIG_fails(self): + with self.assertRaises(socket.gaierror): + socket.getaddrinfo('dns.google', flags=socket.AI_ADDRCONFIG) + + def test_gethostbyaddr_of_name_fails(self): + with self.assertRaises(socket.gaierror): + socket.gethostbyaddr('bogus') + + +@unittest.skipIf(not _network_available, "Internet not reachable") +class OverrideSystemResolverUsingDefaultResolverTestCase(unittest.TestCase): + + def setUp(self): + self.res = FakeResolver() + dns.resolver.override_system_resolver() + + def tearDown(self): + dns.resolver.restore_system_resolver() + self.res = None + + def test_override(self): + self.assertEqual(dns.resolver._resolver, dns.resolver.default_resolver) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_rrset.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_rrset.py new file mode 100644 index 0000000..5c3f17d --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_rrset.py @@ -0,0 +1,191 @@ +# -*- coding: utf-8 +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import unittest + +import dns.name +import dns.rrset + +class RRsetTestCase(unittest.TestCase): + + def testEqual1(self): + r1 = dns.rrset.from_text('foo', 300, 'in', 'a', '10.0.0.1', '10.0.0.2') + r2 = dns.rrset.from_text('FOO', 300, 'in', 'a', '10.0.0.2', '10.0.0.1') + self.assertEqual(r1, r2) + + def testEqual2(self): + r1 = dns.rrset.from_text('foo', 300, 'in', 'a', '10.0.0.1', '10.0.0.2') + r2 = dns.rrset.from_text('FOO', 600, 'in', 'a', '10.0.0.2', '10.0.0.1') + self.assertEqual(r1, r2) + + def testNotEqual1(self): + r1 = dns.rrset.from_text('fooa', 30, 'in', 'a', '10.0.0.1', '10.0.0.2') + r2 = dns.rrset.from_text('FOO', 30, 'in', 'a', '10.0.0.2', '10.0.0.1') + self.assertNotEqual(r1, r2) + + def testNotEqual2(self): + r1 = dns.rrset.from_text('foo', 30, 'in', 'a', '10.0.0.1', '10.0.0.3') + r2 = dns.rrset.from_text('FOO', 30, 'in', 'a', '10.0.0.2', '10.0.0.1') + self.assertNotEqual(r1, r2) + + def testNotEqual3(self): + r1 = dns.rrset.from_text('foo', 30, 'in', 'a', '10.0.0.1', '10.0.0.2', + '10.0.0.3') + r2 = dns.rrset.from_text('FOO', 30, 'in', 'a', '10.0.0.2', '10.0.0.1') + self.assertNotEqual(r1, r2) + + def testNotEqual4(self): + r1 = dns.rrset.from_text('foo', 30, 'in', 'a', '10.0.0.1') + r2 = dns.rrset.from_text('FOO', 30, 'in', 'a', '10.0.0.2', '10.0.0.1') + self.assertNotEqual(r1, r2) + + def testCodec2003(self): + r1 = dns.rrset.from_text_list('Königsgäßchen', 30, 'in', 'ns', + ['Königsgäßchen']) + r2 = dns.rrset.from_text_list('xn--knigsgsschen-lcb0w', 30, 'in', 'ns', + ['xn--knigsgsschen-lcb0w']) + self.assertEqual(r1, r2) + + @unittest.skipUnless(dns.name.have_idna_2008, + 'Python idna cannot be imported; no IDNA2008') + def testCodec2008(self): + r1 = dns.rrset.from_text_list('Königsgäßchen', 30, 'in', 'ns', + ['Königsgäßchen'], + idna_codec=dns.name.IDNA_2008) + r2 = dns.rrset.from_text_list('xn--knigsgchen-b4a3dun', 30, 'in', 'ns', + ['xn--knigsgchen-b4a3dun'], + idna_codec=dns.name.IDNA_2008) + self.assertEqual(r1, r2) + + def testCopy(self): + r1 = dns.rrset.from_text_list('foo', 30, 'in', 'a', + ['10.0.0.1', '10.0.0.2']) + r2 = r1.copy() + self.assertFalse(r1 is r2) + self.assertTrue(r1 == r2) + + def testFullMatch1(self): + r1 = dns.rrset.from_text_list('foo', 30, 'in', 'a', + ['10.0.0.1', '10.0.0.2']) + self.assertTrue(r1.full_match(r1.name, dns.rdataclass.IN, + dns.rdatatype.A, dns.rdatatype.NONE)) + + def testFullMatch2(self): + r1 = dns.rrset.from_text_list('foo', 30, 'in', 'a', + ['10.0.0.1', '10.0.0.2']) + r1.deleting = dns.rdataclass.NONE + self.assertTrue(r1.full_match(r1.name, dns.rdataclass.IN, + dns.rdatatype.A, dns.rdatatype.NONE, + dns.rdataclass.NONE)) + + def testNoFullMatch1(self): + n = dns.name.from_text('bar', None) + r1 = dns.rrset.from_text_list('foo', 30, 'in', 'a', + ['10.0.0.1', '10.0.0.2']) + self.assertFalse(r1.full_match(n, dns.rdataclass.IN, + dns.rdatatype.A, dns.rdatatype.NONE, + dns.rdataclass.ANY)) + + def testNoFullMatch2(self): + r1 = dns.rrset.from_text_list('foo', 30, 'in', 'a', + ['10.0.0.1', '10.0.0.2']) + r1.deleting = dns.rdataclass.NONE + self.assertFalse(r1.full_match(r1.name, dns.rdataclass.IN, + dns.rdatatype.A, dns.rdatatype.NONE, + dns.rdataclass.ANY)) + + def testNoFullMatch3(self): + r1 = dns.rrset.from_text_list('foo', 30, 'in', 'a', + ['10.0.0.1', '10.0.0.2']) + self.assertFalse(r1.full_match(r1.name, dns.rdataclass.IN, + dns.rdatatype.MX, dns.rdatatype.NONE, + dns.rdataclass.ANY)) + + def testMatchCompatibilityWithFullMatch(self): + r1 = dns.rrset.from_text_list('foo', 30, 'in', 'a', + ['10.0.0.1', '10.0.0.2']) + self.assertTrue(r1.match(r1.name, dns.rdataclass.IN, + dns.rdatatype.A, dns.rdatatype.NONE)) + + def testMatchCompatibilityWithRdatasetMatch(self): + r1 = dns.rrset.from_text_list('foo', 30, 'in', 'a', + ['10.0.0.1', '10.0.0.2']) + self.assertTrue(r1.match(dns.rdataclass.IN, dns.rdatatype.A, + dns.rdatatype.NONE)) + + def testToRdataset(self): + r1 = dns.rrset.from_text_list('foo', 30, 'in', 'a', + ['10.0.0.1', '10.0.0.2']) + r2 = dns.rdataset.from_text_list('in', 'a', 30, + ['10.0.0.1', '10.0.0.2']) + self.assertEqual(r1.to_rdataset(), r2) + + def testFromRdata(self): + rdata1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1') + rdata2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.2') + expected_rrs = dns.rrset.from_text('foo', 300, 'in', 'a', '10.0.0.1', + '10.0.0.2') + rrs = dns.rrset.from_rdata('foo', 300, rdata1, rdata2) + self.assertEqual(rrs, expected_rrs) + + def testEmptyList(self): + def bad(): + rrs = dns.rrset.from_rdata_list('foo', 300, []) + self.assertRaises(ValueError, bad) + + def testTTLMinimization(self): + rrs = dns.rrset.RRset(dns.name.from_text('foo'), + dns.rdataclass.IN, dns.rdatatype.A) + rdata1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1') + rdata2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.2') + rrs.add(rdata1, 300) + self.assertEqual(rrs.ttl, 300) + rrs.add(rdata2, 30) + self.assertEqual(rrs.ttl, 30) + # adding the same thing with a smaller TTL also minimizes + rrs.add(rdata2, 3) + self.assertEqual(rrs.ttl, 3) + + def testNotEqualOtherType(self): + rrs = dns.rrset.RRset(dns.name.from_text('foo'), + dns.rdataclass.IN, dns.rdatatype.A) + self.assertFalse(rrs == 123) + + def testRepr(self): + rrset = dns.rrset.from_text('foo', 30, 'in', 'a', '10.0.0.1', + '10.0.0.2') + self.assertEqual(repr(rrset), + ', <10.0.0.2>]>') + rrset.deleting = dns.rdataclass.NONE + self.assertEqual(repr(rrset), + ', <10.0.0.2>]>') + rrset = dns.rrset.from_text( + 'foo', 30, 'in', 'rrsig', + 'A 1 3 3600 20200701000000 20200601000000 1 NAME Ym9ndXM=') + self.assertEqual(repr(rrset), + ']>') + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_serial.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_serial.py new file mode 100644 index 0000000..a9ef2df --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_serial.py @@ -0,0 +1,117 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import unittest + +import dns.serial + +def S2(v): + return dns.serial.Serial(v, bits=2) + +def S8(v): + return dns.serial.Serial(v, bits=8) + +class SerialTestCase(unittest.TestCase): + def test_rfc_1982_2_bit_cases(self): + self.assertEqual(S2(0) + S2(1), S2(1)) + self.assertEqual(S2(1) + S2(1), S2(2)) + self.assertEqual(S2(2) + S2(1), S2(3)) + self.assertEqual(S2(3) + S2(1), S2(0)) + self.assertTrue(S2(1) > S2(0)) + self.assertTrue(S2(2) > S2(1)) + self.assertTrue(S2(3) > S2(2)) + self.assertTrue(S2(0) > S2(3)) + self.assertFalse(S2(2) > S2(0)) + self.assertFalse(S2(0) > S2(2)) + self.assertFalse(S2(2) < S2(0)) + self.assertFalse(S2(0) < S2(2)) + + def test_rfc_1982_8_bit_cases(self): + self.assertEqual(S8(255) + S8(1), S8(0)) + self.assertEqual(S8(100) + S8(100), S8(200)) + self.assertEqual(S8(200) + S8(100), S8(44)) + self.assertTrue(S8(1) > S8(0)) + self.assertTrue(S8(44) > S8(0)) + self.assertTrue(S8(100) > S8(0)) + self.assertTrue(S8(100) > S8(44)) + self.assertTrue(S8(200) > S8(100)) + self.assertTrue(S8(255) > S8(200)) + self.assertTrue(S8(0) > S8(255)) + self.assertTrue(S8(255) < S8(0)) + self.assertTrue(S8(100) > S8(255)) + self.assertTrue(S8(0) > S8(200)) + self.assertTrue(S8(44) > S8(200)) + self.assertFalse(S8(0) > S8(128)) + self.assertFalse(S8(128) > S8(0)) + self.assertFalse(S8(0) < S8(128)) + self.assertFalse(S8(128) < S8(0)) + self.assertFalse(S8(1) > S8(129)) + self.assertFalse(S8(129) > S8(1)) + + def test_incremental_ops(self): + v = S8(255) + v += 1 + self.assertEqual(v, 0) + v = S8(255) + v += S8(1) + self.assertEqual(v, 0) + v = S8(0) + v -= 1 + self.assertEqual(v, 255) + v = S8(0) + v -= S8(1) + self.assertEqual(v, 255) + + def test_sub(self): + self.assertEqual(S8(0) - S8(1), S8(255)) + + def test_addition_bounds(self): + self.assertRaises(ValueError, lambda: S8(0) + 128) + self.assertRaises(ValueError, lambda: S8(0) - 128) + def bad1(): + v = S8(0) + v += 128 + self.assertRaises(ValueError, bad1) + def bad2(): + v = S8(0) + v -= 128 + self.assertRaises(ValueError, bad2) + + def test_casting(self): + self.assertTrue(S8(0) == 0) + self.assertTrue(S8(0) != 1) + self.assertTrue(S8(0) < 1) + self.assertTrue(S8(0) <= 1) + self.assertTrue(S8(0) > 255) + self.assertTrue(S8(0) >= 255) + + def test_uncastable(self): + self.assertRaises(ValueError, lambda: S8(0) + 'a') + self.assertRaises(ValueError, lambda: S8(0) - 'a') + def bad1(): + v = S8(0) + v += 'a' + self.assertRaises(ValueError, bad1) + def bad2(): + v = S8(0) + v -= 'a' + self.assertRaises(ValueError, bad2) + + def test_uncomparable(self): + self.assertFalse(S8(0) == S2(0)) + self.assertFalse(S8(0) == 'a') + self.assertTrue(S8(0) != 'a') + self.assertRaises(TypeError, lambda: S8(0) < 'a') + self.assertRaises(TypeError, lambda: S8(0) <= 'a') + self.assertRaises(TypeError, lambda: S8(0) > 'a') + self.assertRaises(TypeError, lambda: S8(0) >= 'a') + + def test_modulo(self): + self.assertEqual(S8(-1), 255) + self.assertEqual(S8(257), 1) + + def test_repr(self): + self.assertEqual(repr(S8(1)), 'dns.serial.Serial(1, 8)') + + def test_not_equal(self): + self.assertNotEqual(S8(0), S8(1)) + self.assertNotEqual(S8(0), S2(0)) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_set.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_set.py new file mode 100644 index 0000000..8019d57 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_set.py @@ -0,0 +1,266 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import copy +import unittest + +import dns.set + +# for convenience +S = dns.set.Set + +class SetTestCase(unittest.TestCase): + + def testLen1(self): + s1 = S() + self.assertEqual(len(s1), 0) + + def testLen2(self): + s1 = S([1, 2, 3]) + self.assertEqual(len(s1), 3) + + def testLen3(self): + s1 = S([1, 2, 3, 3, 3]) + self.assertEqual(len(s1), 3) + + def testUnion1(self): + s1 = S([1, 2, 3]) + s2 = S([1, 2, 3]) + e = S([1, 2, 3]) + self.assertEqual(s1 | s2, e) + + def testUnion2(self): + s1 = S([1, 2, 3]) + s2 = S([]) + e = S([1, 2, 3]) + self.assertEqual(s1 | s2, e) + + def testUnion3(self): + s1 = S([1, 2, 3]) + s2 = S([3, 4]) + e = S([1, 2, 3, 4]) + self.assertEqual(s1 | s2, e) + + def testUnionPlusSyntax(self): + s1 = S([1, 2, 3]) + s2 = S([3, 4]) + e = S([1, 2, 3, 4]) + self.assertEqual(s1 + s2, e) + + def testIntersection1(self): + s1 = S([1, 2, 3]) + s2 = S([1, 2, 3]) + e = S([1, 2, 3]) + self.assertEqual(s1 & s2, e) + + def testIntersection2(self): + s1 = S([0, 1, 2, 3]) + s2 = S([1, 2, 3, 4]) + e = S([1, 2, 3]) + self.assertEqual(s1 & s2, e) + + def testIntersection3(self): + s1 = S([1, 2, 3]) + s2 = S([]) + e = S([]) + self.assertEqual(s1 & s2, e) + + def testIntersection4(self): + s1 = S([1, 2, 3]) + s2 = S([5, 4]) + e = S([]) + self.assertEqual(s1 & s2, e) + + def testDifference1(self): + s1 = S([1, 2, 3]) + s2 = S([5, 4]) + e = S([1, 2, 3]) + self.assertEqual(s1 - s2, e) + + def testDifference2(self): + s1 = S([1, 2, 3]) + s2 = S([]) + e = S([1, 2, 3]) + self.assertEqual(s1 - s2, e) + + def testDifference3(self): + s1 = S([1, 2, 3]) + s2 = S([3, 2]) + e = S([1]) + self.assertEqual(s1 - s2, e) + + def testDifference4(self): + s1 = S([1, 2, 3]) + s2 = S([3, 2, 1]) + e = S([]) + self.assertEqual(s1 - s2, e) + + def testSubset1(self): + s1 = S([1, 2, 3]) + s2 = S([3, 2, 1]) + self.assertTrue(s1.issubset(s2)) + + def testSubset2(self): + s1 = S([1, 2, 3]) + self.assertTrue(s1.issubset(s1)) + + def testSubset3(self): + s1 = S([]) + s2 = S([1, 2, 3]) + self.assertTrue(s1.issubset(s2)) + + def testSubset4(self): + s1 = S([1]) + s2 = S([1, 2, 3]) + self.assertTrue(s1.issubset(s2)) + + def testSubset5(self): + s1 = S([]) + s2 = S([]) + self.assertTrue(s1.issubset(s2)) + + def testSubset6(self): + s1 = S([1, 4]) + s2 = S([1, 2, 3]) + self.assertTrue(not s1.issubset(s2)) + + def testSuperset1(self): + s1 = S([1, 2, 3]) + s2 = S([3, 2, 1]) + self.assertTrue(s1.issuperset(s2)) + + def testSuperset2(self): + s1 = S([1, 2, 3]) + self.assertTrue(s1.issuperset(s1)) + + def testSuperset3(self): + s1 = S([1, 2, 3]) + s2 = S([]) + self.assertTrue(s1.issuperset(s2)) + + def testSuperset4(self): + s1 = S([1, 2, 3]) + s2 = S([1]) + self.assertTrue(s1.issuperset(s2)) + + def testSuperset5(self): + s1 = S([]) + s2 = S([]) + self.assertTrue(s1.issuperset(s2)) + + def testSuperset6(self): + s1 = S([1, 2, 3]) + s2 = S([1, 4]) + self.assertTrue(not s1.issuperset(s2)) + + def testUpdate1(self): + s1 = S([1, 2, 3]) + u = (4, 5, 6) + e = S([1, 2, 3, 4, 5, 6]) + s1.update(u) + self.assertEqual(s1, e) + + def testUpdate2(self): + s1 = S([1, 2, 3]) + u = [] + e = S([1, 2, 3]) + s1.update(u) + self.assertEqual(s1, e) + + def testGetitem(self): + s1 = S([1, 2, 3]) + i0 = s1[0] + i1 = s1[1] + i2 = s1[2] + s2 = S([i0, i1, i2]) + self.assertEqual(s1, s2) + + def testGetslice(self): + s1 = S([1, 2, 3]) + slice = s1[0:2] + self.assertEqual(len(slice), 2) + item = s1[2] + slice.append(item) + s2 = S(slice) + self.assertEqual(s1, s2) + + def testDelitem(self): + s1 = S([1, 2, 3]) + del s1[0] + self.assertEqual(list(s1), [2, 3]) + + def testDelslice(self): + s1 = S([1, 2, 3]) + del s1[0:2] + self.assertEqual(list(s1), [3]) + + def testRemoveNonexistent(self): + s1 = S([1, 2, 3]) + s2 = S([1, 2, 3]) + with self.assertRaises(ValueError): + s1.remove(4) + self.assertEqual(s1, s2) + + def testDiscardNonexistent(self): + s1 = S([1, 2, 3]) + s2 = S([1, 2, 3]) + s1.discard(4) + self.assertEqual(s1, s2) + + def testCopy(self): + s1 = S([1, 2, 3]) + s2 = s1.copy() + s1.remove(1) + self.assertNotEqual(s1, s2) + s1.add(1) + self.assertEqual(s1, s2) + s2 = copy.copy(s1) + self.assertEqual(s1, s2) + + def testBadUpdates(self): + s = S([1, 2, 3]) + self.assertRaises(ValueError, lambda: s.union_update(1)) + self.assertRaises(ValueError, lambda: s.intersection_update(1)) + + def testSelfUpdates(self): + expected = S([1, 2, 3]) + s = S([1, 2, 3]) + s.union_update(s) + self.assertEqual(s, expected) + s.intersection_update(s) + self.assertEqual(s, expected) + s.difference_update(s) + self.assertTrue(len(s) == 0) + + def testBadSubsetSuperset(self): + s = S([1, 2, 3]) + self.assertRaises(ValueError, lambda: s.issubset(123)) + self.assertRaises(ValueError, lambda: s.issuperset(123)) + + def testIncrementalOperators(self): + s = S([1, 2, 3]) + s += S([5, 4]) + self.assertEqual(s, S([1, 2, 3, 4, 5])) + s -= S([1, 2]) + self.assertEqual(s, S([3, 4, 5])) + s |= S([1, 2]) + self.assertEqual(s, S([1, 2, 3, 4, 5])) + s &= S([1, 2]) + self.assertEqual(s, S([1, 2])) + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_svcb.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_svcb.py new file mode 100644 index 0000000..7cd7768 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_svcb.py @@ -0,0 +1,326 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import io +import unittest + +import dns.rdata +import dns.rdtypes.svcbbase +import dns.rrset + +class SVCBTestCase(unittest.TestCase): + def check_valid_inputs(self, inputs): + expected = inputs[0] + for text in inputs: + rr = dns.rdata.from_text('IN', 'SVCB', text) + new_text = rr.to_text() + self.assertEqual(expected, new_text) + + def check_invalid_inputs(self, inputs): + for text in inputs: + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('IN', 'SVCB', text) + + def test_svcb_general_invalid(self): + invalid_inputs = ( + # Duplicate keys + "1 . alpn=h2 alpn=h3", + "1 . alpn=h2 key1=h3", + # Quoted keys + "1 . \"alpn=h2\"", + # Invalid space + "1 . alpn= h2", + "1 . alpn =h2", + "1 . alpn = h2", + "1 . alpn= \"h2\"", + "1 . =alpn", + ) + self.check_invalid_inputs(invalid_inputs) + + def test_svcb_mandatory(self): + valid_inputs = ( + "1 . mandatory=\"alpn,no-default-alpn\" alpn=\"h2\" no-default-alpn", + "1 . mandatory=alpn,no-default-alpn alpn=h2 no-default-alpn", + "1 . mandatory=key1,key2 alpn=h2 no-default-alpn", + "1 . mandatory=alpn,no-default-alpn key1=\\002h2 key2", + "1 . key0=\\000\\001\\000\\002 alpn=h2 no-default-alpn", + "1 . alpn=h2 no-default-alpn mandatory=alpn,no-default-alpn", + ) + self.check_valid_inputs(valid_inputs) + + invalid_inputs = ( + # empty + "1 . mandatory=", + "1 . mandatory", + # unknown key + "1 . mandatory=foo", + # key 0 + "1 . mandatory=key0", + "1 . mandatory=key0,alpn", + # missing key + "1 . mandatory=alpn", + # duplicate + "1 . mandatory=alpn,alpn alpn=h2", + # invalid escaping + "1 . mandatory=\\alpn alpn=h2", + # empty wire format + "1 . key0", + "1 . key0=", + # 0 in wire format + "1 . key0=\\000\\000", + # invalid length in wire format + "1 . key0=\\000", + # out of order in wire format + "1 . key0=\\000\\002\\000\\001 alpn=h2 no-default-alpn", + # leading zeros + "1 . mandatory=key1,key002 alpn=h2 no-default-alpn", + ) + self.check_invalid_inputs(invalid_inputs) + + def test_svcb_alpn(self): + valid_inputs_two_items = ( + "1 . alpn=\"h2,h3\"", + "1 . alpn=h2,h3", + "1 . alpn=h\\050,h3", + "1 . alpn=\"h\\050,h3\"", + "1 . alpn=\\h2,h3", + "1 . key1=\\002h2\\002h3", + ) + self.check_valid_inputs(valid_inputs_two_items) + + valid_inputs_one_item = ( + "1 . alpn=\"h2\\,h3\"", + "1 . alpn=h2\\,h3", + "1 . alpn=h2\\044h3", + ) + self.check_valid_inputs(valid_inputs_one_item) + + invalid_inputs = ( + "1 . alpn", + "1 . alpn=", + "1 . alpn=h2,,h3", + "1 . alpn=01234567890abcdef01234567890abcdef01234567890abcdef" + "01234567890abcdef01234567890abcdef01234567890abcdef" + "01234567890abcdef01234567890abcdef01234567890abcdef" + "01234567890abcdef01234567890abcdef01234567890abcdef" + "01234567890abcdef01234567890abcdef01234567890abcdef" + "01234567890abcdef", + "1 . alpn=\",h2,h3\"", + "1 . alpn=\"h2,h3,\"", + "1 . key1", + "1 . key1=", + "1 . key1=\\000", + "1 . key1=\\002x", + ) + self.check_invalid_inputs(invalid_inputs) + + def test_svcb_no_default_alpn(self): + valid_inputs = ( + "1 . no-default-alpn", + "1 . no-default-alpn=\"\"", + "1 . key2", + "1 . key2=\"\"", + ) + self.check_valid_inputs(valid_inputs) + + invalid_inputs = ( + "1 . no-default-alpn=foo", + "1 . no-default-alpn=", + "1 . key2=foo", + "1 . key2=", + ) + self.check_invalid_inputs(invalid_inputs) + + def test_svcb_port(self): + valid_inputs = ( + "1 . port=\"53\"", + "1 . port=53", + "1 . key3=\\000\\053", + ) + self.check_valid_inputs(valid_inputs) + + invalid_inputs = ( + "1 . port", + "1 . port=", + "1 . port=53x", + "1 . port=x53", + "1 . port=53,54", + "1 . port=53\\,54", + "1 . port=65536", + "1 . key3", + "1 . key3=", + "1 . key3=\\000", + ) + self.check_invalid_inputs(invalid_inputs) + + def test_svcb_ipv4hint(self): + valid_inputs = ( + "1 . ipv4hint=\"0.0.0.0,1.1.1.1\"", + "1 . ipv4hint=0.0.0.0,1.1.1.1", + "1 . key4=\\000\\000\\000\\000\\001\\001\\001\\001", + ) + self.check_valid_inputs(valid_inputs) + + invalid_inputs = ( + "1 . ipv4hint", + "1 . ipv4hint=", + "1 . ipv4hint=1234", + "1 . ipv4hint=1\\.2.3.4", + "1 . ipv4hint=1.2.3.4\\,2.3.4.5", + "1 . key4=", + "1 . key4=123", + ) + self.check_invalid_inputs(invalid_inputs) + + def test_svcb_echconfig(self): + valid_inputs = ( + "1 . echconfig=\"Zm9vMA==\"", + "1 . echconfig=Zm9vMA==", + "1 . key5=foo0", + "1 . key5=\\102\\111\\111\\048", + ) + self.check_valid_inputs(valid_inputs) + + invalid_inputs = ( + "1 . echconfig", + "1 . echconfig=", + "1 . echconfig=Zm9vMA", + "1 . echconfig=\\090m9vMA==", + "1 . key5", + "1 . key5=", + ) + self.check_invalid_inputs(invalid_inputs) + + def test_svcb_ipv6hint(self): + valid_inputs = ( + "1 . ipv6hint=\"::4,1::\"", + "1 . ipv6hint=::4,1::", + "1 . key6=\\000\\000\\000\\000\\000\\000\\000\\000" + "\\000\\000\\000\\000\\000\\000\\000\\004" + "\\000\\001\\000\\000\\000\\000\\000\\000" + "\\000\\000\\000\\000\\000\\000\\000\\000", + ) + self.check_valid_inputs(valid_inputs) + + invalid_inputs = ( + "1 . ipv6hint", + "1 . ipv6hint=", + "1 . ipv6hint=1234", + "1 . ipv6hint=1\\::2", + "1 . ipv6hint=::1\\,::2", + "1 . ipv6hint", + "1 . key6", + "1 . key6=", + "1 . key6=123", + ) + self.check_invalid_inputs(invalid_inputs) + + def test_svcb_unknown(self): + valid_inputs_one_key = ( + "1 . key23=\"key45\"", + "1 . key23=key45", + "1 . key23=key\\052\\053", + "1 . key23=\"key\\052\\053\"", + "1 . key23=\\107\\101\\121\\052\\053", + ) + self.check_valid_inputs(valid_inputs_one_key) + + valid_inputs_one_key_empty = ( + "1 . key23", + "1 . key23=\"\"", + ) + self.check_valid_inputs(valid_inputs_one_key_empty) + + invalid_inputs_one_key = ( + "1 . key65536=foo", + "1 . key24= key48", + ) + self.check_invalid_inputs(invalid_inputs_one_key) + + valid_inputs_two_keys = ( + "1 . key24 key48", + "1 . key24=\"\" key48", + ) + self.check_valid_inputs(valid_inputs_two_keys) + + def test_svcb_wire(self): + valid_inputs = ( + "1 . mandatory=\"alpn,port\" alpn=\"h2\" port=\"257\"", + "\\# 24 0001 00 0000000400010003 00010003026832 000300020101", + ) + self.check_valid_inputs(valid_inputs) + + everything = \ + "100 foo.com. mandatory=\"alpn,port\" alpn=\"h2,h3\" " \ + " no-default-alpn port=\"12345\" echconfig=\"abcd\" " \ + " ipv4hint=1.2.3.4,4.3.2.1 ipv6hint=1::2,3::4" \ + " key12345=\"foo\"" + rr = dns.rdata.from_text('IN', 'SVCB', everything) + rr2 = dns.rdata.from_text('IN', 'SVCB', rr.to_generic().to_text()) + self.assertEqual(rr, rr2) + + invalid_inputs = ( + # As above, but the keys are out of order. + "\\# 24 0001 00 0000000400010003 000300020101 00010003026832", + # As above, but the mandatory keys don't match + "\\# 24 0001 00 0000000400010002 000300020101 00010003026832", + "\\# 24 0001 00 0000000400010004 000300020101 00010003026832", + # Alias form shouldn't have parameters. + "\\# 08 0000 000300020101", + ) + self.check_invalid_inputs(invalid_inputs) + + def test_misc_escape(self): + rdata = dns.rdata.from_text('in', 'svcb', '1 . alpn=\\010\\010') + expected = '1 . alpn="\\010\\010"' + self.assertEqual(rdata.to_text(), expected) + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('in', 'svcb', '1 . alpn=\\0') + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('in', 'svcb', '1 . alpn=\\00') + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('in', 'svcb', '1 . alpn=\\00q') + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('in', 'svcb', '1 . alpn=\\256') + # This doesn't usually get exercised, so we do it directly. + gp = dns.rdtypes.svcbbase.GenericParam.from_value('\\001\\002') + expected = '"\\001\\002"' + self.assertEqual(gp.to_text(), expected) + + def test_alias_mode(self): + rd = dns.rdata.from_text('in', 'svcb', '0 .') + self.assertEqual(len(rd.params), 0) + self.assertEqual(rd.target, dns.name.root) + self.assertEqual(rd.to_text(), '0 .') + rd = dns.rdata.from_text('in', 'svcb', '0 elsewhere.') + self.assertEqual(rd.target, dns.name.from_text('elsewhere.')) + self.assertEqual(len(rd.params), 0) + # provoke 'parameters in AliasMode' from text. + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('in', 'svcb', '0 elsewhere. alpn=h2') + # provoke 'parameters in AliasMode' from wire too. + wire = bytes.fromhex('0000000000000400010003') + with self.assertRaises(dns.exception.FormError): + dns.rdata.from_wire('in', 'svcb', wire, 0, len(wire)) + + def test_immutability(self): + alpn = dns.rdtypes.svcbbase.ALPNParam.from_value(['h2', 'h3']) + with self.assertRaises(TypeError): + alpn.ids[0] = 'foo' + with self.assertRaises(TypeError): + del alpn.ids[0] + with self.assertRaises(TypeError): + alpn.ids = 'foo' + with self.assertRaises(TypeError): + del alpn.ids + + def test_alias_not_compressed(self): + rrs = dns.rrset.from_text('elsewhere.', 300, 'in', 'svcb', + '0 elseWhere.') + output = io.BytesIO() + compress = {} + rrs.to_wire(output, compress) + wire = output.getvalue() + # Just one of these assertions is enough, but we do both to show + # the bug we're checking is fixed. + assert not wire.endswith(b'\xc0\x00') + assert wire.endswith(b'\x09elseWhere\x00') diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_tokenizer.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_tokenizer.py new file mode 100644 index 0000000..6134d4b --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_tokenizer.py @@ -0,0 +1,362 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import unittest + +import dns.exception +import dns.tokenizer + +Token = dns.tokenizer.Token + +class TokenizerTestCase(unittest.TestCase): + + def testStr(self): + tok = dns.tokenizer.Tokenizer('foo') + token = tok.get() + self.assertEqual(token, Token(dns.tokenizer.IDENTIFIER, 'foo')) + + def testQuotedString1(self): + tok = dns.tokenizer.Tokenizer(r'"foo"') + token = tok.get() + self.assertEqual(token, Token(dns.tokenizer.QUOTED_STRING, 'foo')) + + def testQuotedString2(self): + tok = dns.tokenizer.Tokenizer(r'""') + token = tok.get() + self.assertEqual(token, Token(dns.tokenizer.QUOTED_STRING, '')) + + def testQuotedString3(self): + tok = dns.tokenizer.Tokenizer(r'"\"foo\""') + token = tok.get() + self.assertEqual(token, Token(dns.tokenizer.QUOTED_STRING, '\\"foo\\"')) + + def testQuotedString4(self): + tok = dns.tokenizer.Tokenizer(r'"foo\010bar"') + token = tok.get() + self.assertEqual(token, Token(dns.tokenizer.QUOTED_STRING, + 'foo\\010bar')) + + def testQuotedString5(self): + with self.assertRaises(dns.exception.UnexpectedEnd): + tok = dns.tokenizer.Tokenizer(r'"foo') + tok.get() + + def testQuotedString6(self): + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer(r'"foo\01') + tok.get() + + def testQuotedString7(self): + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('"foo\nbar"') + tok.get() + + def testEmpty1(self): + tok = dns.tokenizer.Tokenizer('') + token = tok.get() + self.assertTrue(token.is_eof()) + + def testEmpty2(self): + tok = dns.tokenizer.Tokenizer('') + token1 = tok.get() + token2 = tok.get() + self.assertTrue(token1.is_eof() and token2.is_eof()) + + def testEOL(self): + tok = dns.tokenizer.Tokenizer('\n') + token1 = tok.get() + token2 = tok.get() + self.assertTrue(token1.is_eol() and token2.is_eof()) + + def testWS1(self): + tok = dns.tokenizer.Tokenizer(' \n') + token1 = tok.get() + self.assertTrue(token1.is_eol()) + + def testWS2(self): + tok = dns.tokenizer.Tokenizer(' \n') + token1 = tok.get(want_leading=True) + self.assertTrue(token1.is_whitespace()) + + def testComment1(self): + tok = dns.tokenizer.Tokenizer(' ;foo\n') + token1 = tok.get() + self.assertTrue(token1.is_eol()) + + def testComment2(self): + tok = dns.tokenizer.Tokenizer(' ;foo\n') + token1 = tok.get(want_comment=True) + token2 = tok.get() + self.assertEqual(token1, Token(dns.tokenizer.COMMENT, 'foo')) + self.assertTrue(token2.is_eol()) + + def testComment3(self): + tok = dns.tokenizer.Tokenizer(' ;foo bar\n') + token1 = tok.get(want_comment=True) + token2 = tok.get() + self.assertEqual(token1, Token(dns.tokenizer.COMMENT, 'foo bar')) + self.assertTrue(token2.is_eol()) + + def testMultiline1(self): + tok = dns.tokenizer.Tokenizer('( foo\n\n bar\n)') + tokens = list(iter(tok)) + self.assertEqual(tokens, [Token(dns.tokenizer.IDENTIFIER, 'foo'), + Token(dns.tokenizer.IDENTIFIER, 'bar')]) + + def testMultiline2(self): + tok = dns.tokenizer.Tokenizer('( foo\n\n bar\n)\n') + tokens = list(iter(tok)) + self.assertEqual(tokens, [Token(dns.tokenizer.IDENTIFIER, 'foo'), + Token(dns.tokenizer.IDENTIFIER, 'bar'), + Token(dns.tokenizer.EOL, '\n')]) + + def testMultiline3(self): + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('foo)') + list(iter(tok)) + + def testMultiline4(self): + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('((foo)') + list(iter(tok)) + + def testUnget1(self): + tok = dns.tokenizer.Tokenizer('foo') + t1 = tok.get() + tok.unget(t1) + t2 = tok.get() + self.assertEqual(t1, t2) + self.assertEqual(t1.ttype, dns.tokenizer.IDENTIFIER) + self.assertEqual(t1.value, 'foo') + + def testUnget2(self): + with self.assertRaises(dns.tokenizer.UngetBufferFull): + tok = dns.tokenizer.Tokenizer('foo') + t1 = tok.get() + tok.unget(t1) + tok.unget(t1) + + def testGetEOL1(self): + tok = dns.tokenizer.Tokenizer('\n') + t = tok.get_eol() + self.assertEqual(t, '\n') + + def testGetEOL2(self): + tok = dns.tokenizer.Tokenizer('') + t = tok.get_eol() + self.assertEqual(t, '') + + def testEscapedDelimiter1(self): + tok = dns.tokenizer.Tokenizer(r'ch\ ld') + t = tok.get() + self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER) + self.assertEqual(t.value, r'ch\ ld') + + def testEscapedDelimiter2(self): + tok = dns.tokenizer.Tokenizer(r'ch\032ld') + t = tok.get() + self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER) + self.assertEqual(t.value, r'ch\032ld') + + def testEscapedDelimiter3(self): + tok = dns.tokenizer.Tokenizer(r'ch\ild') + t = tok.get() + self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER) + self.assertEqual(t.value, r'ch\ild') + + def testEscapedDelimiter1u(self): + tok = dns.tokenizer.Tokenizer(r'ch\ ld') + t = tok.get().unescape() + self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER) + self.assertEqual(t.value, r'ch ld') + + def testEscapedDelimiter2u(self): + tok = dns.tokenizer.Tokenizer(r'ch\032ld') + t = tok.get().unescape() + self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER) + self.assertEqual(t.value, 'ch ld') + + def testEscapedDelimiter3u(self): + tok = dns.tokenizer.Tokenizer(r'ch\ild') + t = tok.get().unescape() + self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER) + self.assertEqual(t.value, r'child') + + def testGetUInt(self): + tok = dns.tokenizer.Tokenizer('1234') + v = tok.get_int() + self.assertEqual(v, 1234) + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('"1234"') + tok.get_int() + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('q1234') + tok.get_int() + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('281474976710656') + tok.get_uint48() + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('4294967296') + tok.get_uint32() + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('65536') + tok.get_uint16() + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('256') + tok.get_uint8() + # Even though it is badly named get_int(), it's really get_unit! + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('-1234') + tok.get_int() + # get_uint16 can do other bases too, and has a custom error + # for base 8. + tok = dns.tokenizer.Tokenizer('177777') + self.assertEqual(tok.get_uint16(base=8), 65535) + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('200000') + tok.get_uint16(base=8) + + def testGetString(self): + tok = dns.tokenizer.Tokenizer('foo') + v = tok.get_string() + self.assertEqual(v, 'foo') + tok = dns.tokenizer.Tokenizer('"foo"') + v = tok.get_string() + self.assertEqual(v, 'foo') + tok = dns.tokenizer.Tokenizer('abcdefghij') + v = tok.get_string(max_length=10) + self.assertEqual(v, 'abcdefghij') + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('abcdefghij') + tok.get_string(max_length=9) + tok = dns.tokenizer.Tokenizer('') + with self.assertRaises(dns.exception.SyntaxError): + tok.get_string() + + def testMultiLineWithComment(self): + tok = dns.tokenizer.Tokenizer('( ; abc\n)') + tok.get_eol() + # Nothing to assert here, as we're testing tok.get_eol() does NOT + # raise. + + def testEOLAfterComment(self): + tok = dns.tokenizer.Tokenizer('; abc\n') + t = tok.get() + self.assertTrue(t.is_eol()) + + def testEOFAfterComment(self): + tok = dns.tokenizer.Tokenizer('; abc') + t = tok.get() + self.assertTrue(t.is_eof()) + + def testMultiLineWithEOFAfterComment(self): + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('( ; abc') + tok.get_eol() + + def testEscapeUnexpectedEnd(self): + with self.assertRaises(dns.exception.UnexpectedEnd): + tok = dns.tokenizer.Tokenizer('\\') + tok.get() + + def testEscapeBounds(self): + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('\\256') + tok.get().unescape() + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('\\256') + tok.get().unescape_to_bytes() + + def testGetUngetRegetComment(self): + tok = dns.tokenizer.Tokenizer(';comment') + t1 = tok.get(want_comment=True) + tok.unget(t1) + t2 = tok.get(want_comment=True) + self.assertEqual(t1, t2) + + def testBadAsName(self): + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('"not an identifier"') + t = tok.get() + tok.as_name(t) + + def testBadGetTTL(self): + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('"not an identifier"') + tok.get_ttl() + + def testBadGetEOL(self): + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('"not an identifier"') + tok.get_eol_as_token() + + def testDanglingEscapes(self): + for text in ['"\\"', '"\\0"', '"\\00"', '"\\00a"']: + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer(text) + tok.get().unescape() + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer(text) + tok.get().unescape_to_bytes() + + def testTokenMisc(self): + t1 = dns.tokenizer.Token(dns.tokenizer.IDENTIFIER, 'hi') + t2 = dns.tokenizer.Token(dns.tokenizer.IDENTIFIER, 'hi') + t3 = dns.tokenizer.Token(dns.tokenizer.IDENTIFIER, 'there') + self.assertEqual(t1, t2) + self.assertFalse(t1 == 'hi') # not NotEqual because we want to use == + self.assertNotEqual(t1, 'hi') + self.assertNotEqual(t1, t3) + self.assertEqual(str(t1), '3 "hi"') + + def testBadConcatenateRemaining(self): + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('a b "not an identifer" c') + tok.concatenate_remaining_identifiers() + + def testStdinFilename(self): + tok = dns.tokenizer.Tokenizer() + self.assertEqual(tok.filename, '') + + def testBytesLiteral(self): + tok = dns.tokenizer.Tokenizer(b'this is input') + self.assertEqual(tok.get().value, 'this') + self.assertEqual(tok.filename, '') + tok = dns.tokenizer.Tokenizer(b'this is input', 'myfilename') + self.assertEqual(tok.filename, 'myfilename') + + def testUngetBranches(self): + tok = dns.tokenizer.Tokenizer(b' this is input') + t = tok.get(want_leading=True) + tok.unget(t) + t = tok.get(want_leading=True) + self.assertEqual(t.ttype, dns.tokenizer.WHITESPACE) + tok.unget(t) + t = tok.get() + self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER) + self.assertEqual(t.value, 'this') + tok = dns.tokenizer.Tokenizer(b'; this is input\n') + t = tok.get(want_comment=True) + tok.unget(t) + t = tok.get(want_comment=True) + self.assertEqual(t.ttype, dns.tokenizer.COMMENT) + tok.unget(t) + t = tok.get() + self.assertEqual(t.ttype, dns.tokenizer.EOL) + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_transaction.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_transaction.py new file mode 100644 index 0000000..bb69b71 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_transaction.py @@ -0,0 +1,610 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import time + +import pytest + +import dns.name +import dns.rdataclass +import dns.rdatatype +import dns.rdataset +import dns.rrset +import dns.transaction +import dns.versioned +import dns.zone + + +class DB(dns.transaction.TransactionManager): + def __init__(self): + self.rdatasets = {} + + def reader(self): + return Transaction(self, False, True) + + def writer(self, replacement=False): + return Transaction(self, replacement, False) + + def origin_information(self): + return (dns.name.from_text('example'), True, dns.name.empty) + + def get_class(self): + return dns.rdataclass.IN + + +class Transaction(dns.transaction.Transaction): + def __init__(self, db, replacement, read_only): + super().__init__(db, replacement, read_only) + self.rdatasets = {} + if not replacement: + self.rdatasets.update(db.rdatasets) + + @property + def db(self): + return self.manager + + def _get_rdataset(self, name, rdtype, covers): + return self.rdatasets.get((name, rdtype, covers)) + + def _put_rdataset(self, name, rdataset): + self.rdatasets[(name, rdataset.rdtype, rdataset.covers)] = rdataset + + def _delete_name(self, name): + remove = [] + for key in self.rdatasets.keys(): + if key[0] == name: + remove.append(key) + if len(remove) > 0: + for key in remove: + del self.rdatasets[key] + + def _delete_rdataset(self, name, rdtype, covers): + del self.rdatasets[(name, rdtype, covers)] + + def _name_exists(self, name): + for key in self.rdatasets.keys(): + if key[0] == name: + return True + return False + + def _changed(self): + if self.read_only: + return False + else: + return len(self.rdatasets) > 0 + + def _end_transaction(self, commit): + if commit: + self.db.rdatasets = self.rdatasets + + def _set_origin(self, origin): + pass + +@pytest.fixture +def db(): + db = DB() + rrset = dns.rrset.from_text('content', 300, 'in', 'txt', 'content') + db.rdatasets[(rrset.name, rrset.rdtype, 0)] = rrset + return db + +def test_basic(db): + # successful txn + with db.writer() as txn: + rrset = dns.rrset.from_text('foo', 300, 'in', 'a', + '10.0.0.1', '10.0.0.2') + txn.add(rrset) + assert txn.name_exists(rrset.name) + assert db.rdatasets[(rrset.name, rrset.rdtype, 0)] == \ + rrset + # rollback + with pytest.raises(Exception): + with db.writer() as txn: + rrset2 = dns.rrset.from_text('foo', 300, 'in', 'a', + '10.0.0.3', '10.0.0.4') + txn.add(rrset2) + raise Exception() + assert db.rdatasets[(rrset.name, rrset.rdtype, 0)] == \ + rrset + with db.writer() as txn: + txn.delete(rrset.name) + assert db.rdatasets.get((rrset.name, rrset.rdtype, 0)) \ + is None + +def test_get(db): + with db.writer() as txn: + content = dns.name.from_text('content', None) + rdataset = txn.get(content, dns.rdatatype.TXT) + assert rdataset is not None + assert rdataset[0].strings == (b'content',) + assert isinstance(rdataset, dns.rdataset.ImmutableRdataset) + +def test_add(db): + with db.writer() as txn: + rrset = dns.rrset.from_text('foo', 300, 'in', 'a', + '10.0.0.1', '10.0.0.2') + txn.add(rrset) + rrset2 = dns.rrset.from_text('foo', 300, 'in', 'a', + '10.0.0.3', '10.0.0.4') + txn.add(rrset2) + expected = dns.rrset.from_text('foo', 300, 'in', 'a', + '10.0.0.1', '10.0.0.2', + '10.0.0.3', '10.0.0.4') + assert db.rdatasets[(rrset.name, rrset.rdtype, 0)] == \ + expected + +def test_replacement(db): + with db.writer() as txn: + rrset = dns.rrset.from_text('foo', 300, 'in', 'a', + '10.0.0.1', '10.0.0.2') + txn.add(rrset) + rrset2 = dns.rrset.from_text('foo', 300, 'in', 'a', + '10.0.0.3', '10.0.0.4') + txn.replace(rrset2) + assert db.rdatasets[(rrset.name, rrset.rdtype, 0)] == \ + rrset2 + +def test_delete(db): + with db.writer() as txn: + txn.delete(dns.name.from_text('nonexistent', None)) + content = dns.name.from_text('content', None) + content2 = dns.name.from_text('content2', None) + txn.delete(content) + assert not txn.name_exists(content) + txn.delete(content2, dns.rdatatype.TXT) + rrset = dns.rrset.from_text('content', 300, 'in', 'txt', 'new-content') + txn.add(rrset) + assert txn.name_exists(content) + txn.delete(content, dns.rdatatype.TXT) + assert not txn.name_exists(content) + rrset = dns.rrset.from_text('content2', 300, 'in', 'txt', 'new-content') + txn.delete(rrset) + content_keys = [k for k in db.rdatasets if k[0] == content] + assert len(content_keys) == 0 + +def test_delete_exact(db): + with db.writer() as txn: + rrset = dns.rrset.from_text('content', 300, 'in', 'txt', 'bad-content') + with pytest.raises(dns.transaction.DeleteNotExact): + txn.delete_exact(rrset) + rrset = dns.rrset.from_text('content2', 300, 'in', 'txt', 'bad-content') + with pytest.raises(dns.transaction.DeleteNotExact): + txn.delete_exact(rrset) + with pytest.raises(dns.transaction.DeleteNotExact): + txn.delete_exact(rrset.name) + with pytest.raises(dns.transaction.DeleteNotExact): + txn.delete_exact(rrset.name, dns.rdatatype.TXT) + rrset = dns.rrset.from_text('content', 300, 'in', 'txt', 'content') + txn.delete_exact(rrset) + assert db.rdatasets.get((rrset.name, rrset.rdtype, 0)) \ + is None + +def test_parameter_forms(db): + with db.writer() as txn: + foo = dns.name.from_text('foo', None) + rdataset = dns.rdataset.from_text('in', 'a', 300, + '10.0.0.1', '10.0.0.2') + rdata1 = dns.rdata.from_text('in', 'a', '10.0.0.3') + rdata2 = dns.rdata.from_text('in', 'a', '10.0.0.4') + txn.add(foo, rdataset) + txn.add(foo, 100, rdata1) + txn.add(foo, 30, rdata2) + expected = dns.rrset.from_text('foo', 30, 'in', 'a', + '10.0.0.1', '10.0.0.2', + '10.0.0.3', '10.0.0.4') + assert db.rdatasets[(foo, rdataset.rdtype, 0)] == \ + expected + with db.writer() as txn: + txn.delete(foo, rdataset) + txn.delete(foo, rdata1) + txn.delete(foo, rdata2) + assert db.rdatasets.get((foo, rdataset.rdtype, 0)) \ + is None + +def test_bad_parameters(db): + with db.writer() as txn: + with pytest.raises(TypeError): + txn.add(1) + with pytest.raises(TypeError): + rrset = dns.rrset.from_text('bar', 300, 'in', 'txt', 'bar') + txn.add(rrset, 1) + with pytest.raises(ValueError): + foo = dns.name.from_text('foo', None) + rdata = dns.rdata.from_text('in', 'a', '10.0.0.3') + txn.add(foo, 0x80000000, rdata) + with pytest.raises(TypeError): + txn.add(foo) + with pytest.raises(TypeError): + txn.add() + with pytest.raises(TypeError): + txn.add(foo, 300) + with pytest.raises(TypeError): + txn.add(foo, 300, 'hi') + with pytest.raises(TypeError): + txn.add(foo, 'hi') + with pytest.raises(TypeError): + txn.delete() + with pytest.raises(TypeError): + txn.delete(1) + +def test_cannot_store_non_origin_soa(db): + with pytest.raises(ValueError): + with db.writer() as txn: + rrset = dns.rrset.from_text('foo', 300, 'in', 'SOA', + '. . 1 2 3 4 5') + txn.add(rrset) + +example_text = """$TTL 3600 +$ORIGIN example. +@ soa foo bar 1 2 3 4 5 +@ ns ns1 +@ ns ns2 +ns1 a 10.0.0.1 +ns2 a 10.0.0.2 +$TTL 300 +$ORIGIN foo.example. +bar mx 0 blaz +""" + +example_text_output = """@ 3600 IN SOA foo bar 1 2 3 4 5 +@ 3600 IN NS ns1 +@ 3600 IN NS ns2 +@ 3600 IN NS ns3 +ns1 3600 IN A 10.0.0.1 +ns2 3600 IN A 10.0.0.2 +ns3 3600 IN A 10.0.0.3 +""" + +@pytest.fixture(params=[dns.zone.Zone, dns.versioned.Zone]) +def zone(request): + return dns.zone.from_text(example_text, zone_factory=request.param) + +def test_zone_basic(zone): + with zone.writer() as txn: + txn.delete(dns.name.from_text('bar.foo', None)) + rd = dns.rdata.from_text('in', 'ns', 'ns3') + txn.add(dns.name.empty, 3600, rd) + rd = dns.rdata.from_text('in', 'a', '10.0.0.3') + txn.add(dns.name.from_text('ns3', None), 3600, rd) + output = zone.to_text() + assert output == example_text_output + +def test_explicit_rollback_and_commit(zone): + with zone.writer() as txn: + assert not txn.changed() + txn.delete(dns.name.from_text('bar.foo', None)) + txn.rollback() + assert zone.get_node('bar.foo') is not None + with zone.writer() as txn: + assert not txn.changed() + txn.delete(dns.name.from_text('bar.foo', None)) + txn.commit() + assert zone.get_node('bar.foo') is None + with pytest.raises(dns.transaction.AlreadyEnded): + with zone.writer() as txn: + txn.rollback() + txn.delete(dns.name.from_text('bar.foo', None)) + with pytest.raises(dns.transaction.AlreadyEnded): + with zone.writer() as txn: + txn.rollback() + txn.add('bar.foo', 300, dns.rdata.from_text('in', 'txt', 'hi')) + with pytest.raises(dns.transaction.AlreadyEnded): + with zone.writer() as txn: + txn.rollback() + txn.replace('bar.foo', 300, dns.rdata.from_text('in', 'txt', 'hi')) + with pytest.raises(dns.transaction.AlreadyEnded): + with zone.reader() as txn: + txn.rollback() + txn.get('bar.foo', 'in', 'mx') + with pytest.raises(dns.transaction.AlreadyEnded): + with zone.writer() as txn: + txn.rollback() + txn.delete_exact('bar.foo') + with pytest.raises(dns.transaction.AlreadyEnded): + with zone.writer() as txn: + txn.rollback() + txn.name_exists('bar.foo') + with pytest.raises(dns.transaction.AlreadyEnded): + with zone.writer() as txn: + txn.rollback() + txn.update_serial() + with pytest.raises(dns.transaction.AlreadyEnded): + with zone.writer() as txn: + txn.rollback() + txn.changed() + with pytest.raises(dns.transaction.AlreadyEnded): + with zone.writer() as txn: + txn.rollback() + txn.rollback() + with pytest.raises(dns.transaction.AlreadyEnded): + with zone.writer() as txn: + txn.rollback() + txn.commit() + with pytest.raises(dns.transaction.AlreadyEnded): + with zone.writer() as txn: + txn.rollback() + for rdataset in txn: + print(rdataset) + +def test_zone_changed(zone): + # Read-only is not changed! + with zone.reader() as txn: + assert not txn.changed() + # delete an existing name + with zone.writer() as txn: + assert not txn.changed() + txn.delete(dns.name.from_text('bar.foo', None)) + assert txn.changed() + # delete a nonexistent name + with zone.writer() as txn: + assert not txn.changed() + txn.delete(dns.name.from_text('unknown.bar.foo', None)) + assert not txn.changed() + # delete a nonexistent rdataset from an extant node + with zone.writer() as txn: + assert not txn.changed() + txn.delete(dns.name.from_text('bar.foo', None), 'txt') + assert not txn.changed() + # add an rdataset to an extant Node + with zone.writer() as txn: + assert not txn.changed() + txn.add('bar.foo', 300, dns.rdata.from_text('in', 'txt', 'hi')) + assert txn.changed() + # add an rdataset to a nonexistent Node + with zone.writer() as txn: + assert not txn.changed() + txn.add('foo.foo', 300, dns.rdata.from_text('in', 'txt', 'hi')) + assert txn.changed() + +def test_zone_base_layer(zone): + with zone.writer() as txn: + # Get a set from the zone layer + rdataset = txn.get(dns.name.empty, dns.rdatatype.NS, dns.rdatatype.NONE) + expected = dns.rdataset.from_text('in', 'ns', 300, 'ns1', 'ns2') + assert rdataset == expected + +def test_zone_transaction_layer(zone): + with zone.writer() as txn: + # Make a change + rd = dns.rdata.from_text('in', 'ns', 'ns3') + txn.add(dns.name.empty, 3600, rd) + # Get a set from the transaction layer + expected = dns.rdataset.from_text('in', 'ns', 300, 'ns1', 'ns2', 'ns3') + rdataset = txn.get(dns.name.empty, dns.rdatatype.NS, dns.rdatatype.NONE) + assert rdataset == expected + assert txn.name_exists(dns.name.empty) + ns1 = dns.name.from_text('ns1', None) + assert txn.name_exists(ns1) + ns99 = dns.name.from_text('ns99', None) + assert not txn.name_exists(ns99) + +def test_zone_add_and_delete(zone): + with zone.writer() as txn: + a99 = dns.name.from_text('a99', None) + a100 = dns.name.from_text('a100', None) + a101 = dns.name.from_text('a101', None) + rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.99') + txn.add(a99, rds) + txn.delete(a99, dns.rdatatype.A) + txn.delete(a100, dns.rdatatype.A) + txn.delete(a101) + assert not txn.name_exists(a99) + assert not txn.name_exists(a100) + assert not txn.name_exists(a101) + ns1 = dns.name.from_text('ns1', None) + txn.delete(ns1, dns.rdatatype.A) + assert not txn.name_exists(ns1) + with zone.writer() as txn: + txn.add(a99, rds) + txn.delete(a99) + assert not txn.name_exists(a99) + with zone.writer() as txn: + txn.add(a100, rds) + txn.delete(a99) + assert not txn.name_exists(a99) + assert txn.name_exists(a100) + +def test_write_after_rollback(zone): + with pytest.raises(ExpectedException): + with zone.writer() as txn: + a99 = dns.name.from_text('a99', None) + rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.99') + txn.add(a99, rds) + raise ExpectedException + with zone.writer() as txn: + a99 = dns.name.from_text('a99', None) + rds = dns.rdataset.from_text('in', 'a', 300, '10.99.99.99') + txn.add(a99, rds) + assert zone.get_rdataset('a99', 'a') == rds + +def test_zone_get_deleted(zone): + with zone.writer() as txn: + print(zone.to_text()) + ns1 = dns.name.from_text('ns1', None) + assert txn.get(ns1, dns.rdatatype.A) is not None + txn.delete(ns1) + assert txn.get(ns1, dns.rdatatype.A) is None + ns2 = dns.name.from_text('ns2', None) + txn.delete(ns2, dns.rdatatype.A) + assert txn.get(ns2, dns.rdatatype.A) is None + +def test_zone_bad_class(zone): + with zone.writer() as txn: + rds = dns.rdataset.from_text('ch', 'ns', 300, 'ns1', 'ns2') + with pytest.raises(ValueError): + txn.add(dns.name.empty, rds) + with pytest.raises(ValueError): + txn.replace(dns.name.empty, rds) + with pytest.raises(ValueError): + txn.delete(dns.name.empty, rds) + +def test_update_serial(zone): + # basic + with zone.writer() as txn: + txn.update_serial() + rdataset = zone.find_rdataset('@', 'soa') + assert rdataset[0].serial == 2 + # max + with zone.writer() as txn: + txn.update_serial(0xffffffff, False) + rdataset = zone.find_rdataset('@', 'soa') + assert rdataset[0].serial == 0xffffffff + # wraparound to 1 + with zone.writer() as txn: + txn.update_serial() + rdataset = zone.find_rdataset('@', 'soa') + assert rdataset[0].serial == 1 + # trying to set to zero sets to 1 + with zone.writer() as txn: + txn.update_serial(0, False) + rdataset = zone.find_rdataset('@', 'soa') + assert rdataset[0].serial == 1 + with pytest.raises(KeyError): + with zone.writer() as txn: + txn.update_serial(name=dns.name.from_text('unknown', None)) + with pytest.raises(ValueError): + with zone.writer() as txn: + txn.update_serial(-1) + with pytest.raises(ValueError): + with zone.writer() as txn: + txn.update_serial(2**31) + +class ExpectedException(Exception): + pass + +def test_zone_rollback(zone): + try: + with zone.writer() as txn: + a99 = dns.name.from_text('a99.example.') + rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.99') + txn.add(a99, rds) + assert txn.name_exists(a99) + raise ExpectedException + except ExpectedException: + pass + assert not zone.get_node(a99) + +def test_zone_ooz_name(zone): + with zone.writer() as txn: + with pytest.raises(KeyError): + a99 = dns.name.from_text('a99.not-example.') + assert txn.name_exists(a99) + +def test_zone_iteration(zone): + expected = {} + for (name, rdataset) in zone.iterate_rdatasets(): + expected[(name, rdataset.rdtype, rdataset.covers)] = rdataset + with zone.writer() as txn: + actual = {} + for (name, rdataset) in txn: + actual[(name, rdataset.rdtype, rdataset.covers)] = rdataset + assert actual == expected + +@pytest.fixture +def vzone(): + return dns.zone.from_text(example_text, zone_factory=dns.versioned.Zone) + +def test_vzone_read_only(vzone): + with vzone.reader() as txn: + rdataset = txn.get(dns.name.empty, dns.rdatatype.NS, dns.rdatatype.NONE) + expected = dns.rdataset.from_text('in', 'ns', 300, 'ns1', 'ns2') + assert rdataset == expected + with pytest.raises(dns.transaction.ReadOnly): + txn.replace(dns.name.empty, expected) + +def test_vzone_multiple_versions(vzone): + assert len(vzone._versions) == 1 + vzone.set_max_versions(None) # unlimited! + with vzone.writer() as txn: + txn.update_serial() + with vzone.writer() as txn: + txn.update_serial() + with vzone.writer() as txn: + txn.update_serial(1000, False) + rdataset = vzone.find_rdataset('@', 'soa') + assert rdataset[0].serial == 1000 + assert len(vzone._versions) == 4 + with vzone.reader(id=5) as txn: + assert txn.version.id == 5 + rdataset = txn.get('@', 'soa') + assert rdataset[0].serial == 1000 + with vzone.reader(serial=1000) as txn: + assert txn.version.id == 5 + rdataset = txn.get('@', 'soa') + assert rdataset[0].serial == 1000 + vzone.set_max_versions(2) + assert len(vzone._versions) == 2 + # The ones that survived should be 3 and 1000 + rdataset = vzone._versions[0].get_rdataset(dns.name.empty, + dns.rdatatype.SOA, + dns.rdatatype.NONE) + assert rdataset[0].serial == 3 + rdataset = vzone._versions[1].get_rdataset(dns.name.empty, + dns.rdatatype.SOA, + dns.rdatatype.NONE) + assert rdataset[0].serial == 1000 + with pytest.raises(ValueError): + vzone.set_max_versions(0) + +# for debugging if needed +def _dump(zone): + for v in zone._versions: + print('VERSION', v.id) + for (name, n) in v.nodes.items(): + for rdataset in n: + print(rdataset.to_text(name)) + +def test_vzone_open_txn_pins_versions(vzone): + assert len(vzone._versions) == 1 + vzone.set_max_versions(None) # unlimited! + with vzone.writer() as txn: + txn.update_serial() + with vzone.writer() as txn: + txn.update_serial() + with vzone.writer() as txn: + txn.update_serial() + with vzone.reader(id=2) as txn: + vzone.set_max_versions(1) + with vzone.reader(id=3) as txn: + rdataset = txn.get('@', 'soa') + assert rdataset[0].serial == 2 + assert len(vzone._versions) == 4 + assert len(vzone._versions) == 1 + rdataset = vzone.find_rdataset('@', 'soa') + assert vzone._versions[0].id == 5 + assert rdataset[0].serial == 4 + + +try: + import threading + + one_got_lock = threading.Event() + + def run_one(zone): + with zone.writer() as txn: + one_got_lock.set() + # wait until two blocks + while len(zone._write_waiters) == 0: + time.sleep(0.01) + rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.98') + txn.add('a98', rds) + + def run_two(zone): + # wait until one has the lock so we know we will block if we + # get the call done before the sleep in one completes + one_got_lock.wait() + with zone.writer() as txn: + rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.99') + txn.add('a99', rds) + + def test_vzone_concurrency(vzone): + t1 = threading.Thread(target=run_one, args=(vzone,)) + t1.start() + t2 = threading.Thread(target=run_two, args=(vzone,)) + t2.start() + t1.join() + t2.join() + with vzone.reader() as txn: + assert txn.name_exists('a98') + assert txn.name_exists('a99') + +except ImportError: # pragma: no cover + pass diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_tsig.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_tsig.py new file mode 100644 index 0000000..a016cf8 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_tsig.py @@ -0,0 +1,275 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import unittest +from unittest.mock import Mock +import time +import base64 + +import dns.rcode +import dns.tsig +import dns.tsigkeyring +import dns.message +import dns.rdtypes.ANY.TKEY + +keyring = dns.tsigkeyring.from_text( + { + 'keyname.' : 'NjHwPsMKjdN++dOfE5iAiQ==' + } +) + +keyname = dns.name.from_text('keyname') + + +class TSIGTestCase(unittest.TestCase): + + def test_get_context(self): + key = dns.tsig.Key('foo.com', 'abcd', 'hmac-sha256') + ctx = dns.tsig.get_context(key) + self.assertEqual(ctx.name, 'hmac-sha256') + key = dns.tsig.Key('foo.com', 'abcd', 'hmac-sha512') + ctx = dns.tsig.get_context(key) + self.assertEqual(ctx.name, 'hmac-sha512') + bogus = dns.tsig.Key('foo.com', 'abcd', 'bogus') + with self.assertRaises(NotImplementedError): + dns.tsig.get_context(bogus) + + def test_tsig_message_properties(self): + m = dns.message.make_query('example', 'a') + self.assertIsNone(m.keyname) + self.assertIsNone(m.keyalgorithm) + self.assertIsNone(m.tsig_error) + m.use_tsig(keyring, keyname) + self.assertEqual(m.keyname, keyname) + self.assertEqual(m.keyalgorithm, dns.tsig.default_algorithm) + self.assertEqual(m.tsig_error, dns.rcode.NOERROR) + m = dns.message.make_query('example', 'a') + m.use_tsig(keyring, keyname, tsig_error=dns.rcode.BADKEY) + self.assertEqual(m.tsig_error, dns.rcode.BADKEY) + + def test_verify_mac_for_context(self): + key = dns.tsig.Key('foo.com', 'abcd', 'hmac-sha512') + ctx = dns.tsig.get_context(key) + bad_expected = b'xxxxxxxxxx' + with self.assertRaises(dns.tsig.BadSignature): + ctx.verify(bad_expected) + + def test_validate(self): + # make message and grab the TSIG + m = dns.message.make_query('example', 'a') + m.use_tsig(keyring, keyname, algorithm=dns.tsig.HMAC_SHA256) + w = m.to_wire() + tsig = m.tsig[0] + + # get the time and create a key with matching characteristics + now = int(time.time()) + key = dns.tsig.Key('foo.com', 'abcd', 'hmac-sha256') + + # add enough to the time to take it over the fudge amount + with self.assertRaises(dns.tsig.BadTime): + dns.tsig.validate(w, key, dns.name.from_text('foo.com'), + tsig, now + 1000, b'', 0) + + # change the key name + with self.assertRaises(dns.tsig.BadKey): + dns.tsig.validate(w, key, dns.name.from_text('bar.com'), + tsig, now, b'', 0) + + # change the key algorithm + key = dns.tsig.Key('foo.com', 'abcd', 'hmac-sha512') + with self.assertRaises(dns.tsig.BadAlgorithm): + dns.tsig.validate(w, key, dns.name.from_text('foo.com'), + tsig, now, b'', 0) + + def test_gssapi_context(self): + def verify_signature(data, mac): + if data == b'throw': + raise Exception + return None + + # mock out the gssapi context to return some dummy values + gssapi_context_mock = Mock() + gssapi_context_mock.get_signature.return_value = b'xxxxxxxxxxx' + gssapi_context_mock.verify_signature.side_effect = verify_signature + + # create the key and add it to the keyring + keyname = 'gsstsigtest' + key = dns.tsig.Key(keyname, gssapi_context_mock, 'gss-tsig') + ctx = dns.tsig.get_context(key) + self.assertEqual(ctx.name, 'gss-tsig') + gsskeyname = dns.name.from_text(keyname) + keyring[gsskeyname] = key + + # make sure we can get the keyring (no exception == success) + text = dns.tsigkeyring.to_text(keyring) + self.assertNotEqual(text, '') + + # test exceptional case for _verify_mac_for_context + with self.assertRaises(dns.tsig.BadSignature): + ctx.update(b'throw') + ctx.verify(b'bogus') + gssapi_context_mock.verify_signature.assert_called() + self.assertEqual(gssapi_context_mock.verify_signature.call_count, 1) + + # simulate case where TKEY message is used to establish the context; + # first, the query from the client + tkey_message = dns.message.make_query(keyname, 'tkey', 'any') + + # test existent/non-existent keys in the keyring + adapted_keyring = dns.tsig.GSSTSigAdapter(keyring) + + fetched_key = adapted_keyring(tkey_message, gsskeyname) + self.assertEqual(fetched_key, key) + key = adapted_keyring(None, gsskeyname) + self.assertEqual(fetched_key, key) + key = adapted_keyring(tkey_message, "dummy") + self.assertEqual(key, None) + + # create a response, TKEY and turn it into bytes, simulating the server + # sending the response to the query + tkey_response = dns.message.make_response(tkey_message) + key = base64.b64decode('KEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEY') + tkey = dns.rdtypes.ANY.TKEY.TKEY(dns.rdataclass.ANY, + dns.rdatatype.TKEY, + dns.name.from_text('gss-tsig.'), + 1594203795, 1594206664, + 3, 0, key) + + # add the TKEY answer and sign it + tkey_response.set_rcode(dns.rcode.NOERROR) + tkey_response.answer = [ + dns.rrset.from_rdata(dns.name.from_text(keyname), 0, tkey)] + tkey_response.use_tsig(keyring=dns.tsig.GSSTSigAdapter(keyring), + keyname=gsskeyname, + algorithm=dns.tsig.GSS_TSIG) + + # "send" it to the client + tkey_wire = tkey_response.to_wire() + + # grab the response from the "server" and simulate the client side + dns.message.from_wire(tkey_wire, dns.tsig.GSSTSigAdapter(keyring)) + + # assertions to make sure the "gssapi" functions were called + gssapi_context_mock.get_signature.assert_called() + self.assertEqual(gssapi_context_mock.get_signature.call_count, 1) + gssapi_context_mock.verify_signature.assert_called() + self.assertEqual(gssapi_context_mock.verify_signature.call_count, 2) + gssapi_context_mock.step.assert_called() + self.assertEqual(gssapi_context_mock.step.call_count, 1) + + # create example message and go to/from wire to simulate sign/verify + # of regular messages + a_message = dns.message.make_query('example', 'a') + a_message.use_tsig(dns.tsig.GSSTSigAdapter(keyring), gsskeyname) + a_wire = a_message.to_wire() + # not raising is passing + dns.message.from_wire(a_wire, dns.tsig.GSSTSigAdapter(keyring)) + + # assertions to make sure the "gssapi" functions were called again + gssapi_context_mock.get_signature.assert_called() + self.assertEqual(gssapi_context_mock.get_signature.call_count, 2) + gssapi_context_mock.verify_signature.assert_called() + self.assertEqual(gssapi_context_mock.verify_signature.call_count, 3) + + def test_sign_and_validate(self): + m = dns.message.make_query('example', 'a') + m.use_tsig(keyring, keyname) + w = m.to_wire() + # not raising is passing + dns.message.from_wire(w, keyring) + + def test_validate_with_bad_keyring(self): + m = dns.message.make_query('example', 'a') + m.use_tsig(keyring, keyname) + w = m.to_wire() + + # keyring == None is an error + with self.assertRaises(dns.message.UnknownTSIGKey): + dns.message.from_wire(w, None) + # callable keyring that returns None is an error + with self.assertRaises(dns.message.UnknownTSIGKey): + dns.message.from_wire(w, lambda m, n: None) + + def test_sign_and_validate_with_other_data(self): + m = dns.message.make_query('example', 'a') + m.use_tsig(keyring, keyname, other_data=b'other') + w = m.to_wire() + # not raising is passing + dns.message.from_wire(w, keyring) + + def test_sign_respond_and_validate(self): + mq = dns.message.make_query('example', 'a') + mq.use_tsig(keyring, keyname) + wq = mq.to_wire() + mq_with_tsig = dns.message.from_wire(wq, keyring) + mr = dns.message.make_response(mq) + mr.use_tsig(keyring, keyname) + wr = mr.to_wire() + dns.message.from_wire(wr, keyring, request_mac=mq_with_tsig.mac) + + def make_message_pair(self, qname='example', rdtype='A', tsig_error=0): + q = dns.message.make_query(qname, rdtype) + q.use_tsig(keyring=keyring, keyname=keyname) + q.to_wire() # to set q.mac + r = dns.message.make_response(q, tsig_error=tsig_error) + return(q, r) + + def test_peer_errors(self): + items = [(dns.rcode.BADSIG, dns.tsig.PeerBadSignature), + (dns.rcode.BADKEY, dns.tsig.PeerBadKey), + (dns.rcode.BADTIME, dns.tsig.PeerBadTime), + (dns.rcode.BADTRUNC, dns.tsig.PeerBadTruncation), + (99, dns.tsig.PeerError), + ] + for err, ex in items: + q, r = self.make_message_pair(tsig_error=err) + w = r.to_wire() + def bad(): + dns.message.from_wire(w, keyring=keyring, request_mac=q.mac) + self.assertRaises(ex, bad) + + def _test_truncated_algorithm(self, alg, length): + key = dns.tsig.Key('foo', b'abcdefg', algorithm=alg) + q = dns.message.make_query('example', 'a') + q.use_tsig(key) + q2 = dns.message.from_wire(q.to_wire(), keyring=key) + + self.assertTrue(q2.had_tsig) + self.assertEqual(q2.tsig[0].algorithm, q.tsig[0].algorithm) + self.assertEqual(len(q2.tsig[0].mac), length // 8) + + def test_hmac_sha256_128(self): + self._test_truncated_algorithm(dns.tsig.HMAC_SHA256_128, 128) + + def test_hmac_sha384_192(self): + self._test_truncated_algorithm(dns.tsig.HMAC_SHA384_192, 192) + + def test_hmac_sha512_256(self): + self._test_truncated_algorithm(dns.tsig.HMAC_SHA512_256, 256) + + def _test_text_format(self, alg): + key = dns.tsig.Key('foo', b'abcdefg', algorithm=alg) + q = dns.message.make_query('example', 'a') + q.use_tsig(key) + _ = q.to_wire() + + text = q.tsig[0].to_text() + tsig2 = dns.rdata.from_text('ANY', 'TSIG', text) + self.assertEqual(tsig2, q.tsig[0]) + + q = dns.message.make_query('example', 'a') + q.use_tsig(key, other_data=b'abc') + q.use_tsig(key) + _ = q.to_wire() + + text = q.tsig[0].to_text() + tsig2 = dns.rdata.from_text('ANY', 'TSIG', text) + self.assertEqual(tsig2, q.tsig[0]) + + def test_text_hmac_sha256_128(self): + self._test_text_format(dns.tsig.HMAC_SHA256_128) + + def test_text_hmac_sha384_192(self): + self._test_text_format(dns.tsig.HMAC_SHA384_192) + + def test_text_hmac_sha512_256(self): + self._test_text_format(dns.tsig.HMAC_SHA512_256) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_tsigkeyring.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_tsigkeyring.py new file mode 100644 index 0000000..47f8806 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_tsigkeyring.py @@ -0,0 +1,64 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import base64 +import unittest + +import dns.tsig +import dns.tsigkeyring + +text_keyring = { + 'keyname.' : ('hmac-sha256.', 'NjHwPsMKjdN++dOfE5iAiQ==') +} + +alt_text_keyring = { + 'keyname.' : (dns.tsig.HMAC_SHA256, 'NjHwPsMKjdN++dOfE5iAiQ==') +} + +old_text_keyring = { + 'keyname.' : 'NjHwPsMKjdN++dOfE5iAiQ==' +} + +key = dns.tsig.Key('keyname.', 'NjHwPsMKjdN++dOfE5iAiQ==') + +rich_keyring = { key.name : key } + +old_rich_keyring = { key.name : key.secret } + +class TSIGKeyRingTestCase(unittest.TestCase): + + def test_from_text(self): + """text keyring -> rich keyring""" + rkeyring = dns.tsigkeyring.from_text(text_keyring) + self.assertEqual(rkeyring, rich_keyring) + + def test_from_alt_text(self): + """alternate format text keyring -> rich keyring""" + rkeyring = dns.tsigkeyring.from_text(alt_text_keyring) + self.assertEqual(rkeyring, rich_keyring) + + def test_from_old_text(self): + """old format text keyring -> rich keyring""" + rkeyring = dns.tsigkeyring.from_text(old_text_keyring) + self.assertEqual(rkeyring, old_rich_keyring) + + def test_to_text(self): + """text keyring -> rich keyring -> text keyring""" + tkeyring = dns.tsigkeyring.to_text(rich_keyring) + self.assertEqual(tkeyring, text_keyring) + + def test_old_to_text(self): + """text keyring -> rich keyring -> text keyring""" + tkeyring = dns.tsigkeyring.to_text(old_rich_keyring) + self.assertEqual(tkeyring, old_text_keyring) + + def test_from_and_to_text(self): + """text keyring -> rich keyring -> text keyring""" + rkeyring = dns.tsigkeyring.from_text(text_keyring) + tkeyring = dns.tsigkeyring.to_text(rkeyring) + self.assertEqual(tkeyring, text_keyring) + + def test_old_from_and_to_text(self): + """text keyring -> rich keyring -> text keyring""" + rkeyring = dns.tsigkeyring.from_text(old_text_keyring) + tkeyring = dns.tsigkeyring.to_text(rkeyring) + self.assertEqual(tkeyring, old_text_keyring) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_ttl.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_ttl.py new file mode 100644 index 0000000..2bf298e --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_ttl.py @@ -0,0 +1,36 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import unittest + +import dns.ttl + +class TTLTestCase(unittest.TestCase): + + def test_bind_style_ok(self): + ttl = dns.ttl.from_text('2w1d1h1m1s') + self.assertEqual(ttl, 2 * 604800 + 86400 + 3600 + 60 + 1) + + def test_bind_style_ok2(self): + # no one should do this, but it is legal! :) + ttl = dns.ttl.from_text('1s2w1m1d1h') + self.assertEqual(ttl, 2 * 604800 + 86400 + 3600 + 60 + 1) + + def test_bind_style_bad_unit(self): + with self.assertRaises(dns.ttl.BadTTL): + dns.ttl.from_text('5y') + + def test_bind_style_no_unit(self): + with self.assertRaises(dns.ttl.BadTTL): + dns.ttl.from_text('1d5') + + def test_bind_style_leading_unit(self): + with self.assertRaises(dns.ttl.BadTTL): + dns.ttl.from_text('s') + + def test_bind_style_unit_without_digits(self): + with self.assertRaises(dns.ttl.BadTTL): + dns.ttl.from_text('1mw') + + def test_empty(self): + with self.assertRaises(dns.ttl.BadTTL): + dns.ttl.from_text('') diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_update.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_update.py new file mode 100644 index 0000000..3abec93 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_update.py @@ -0,0 +1,346 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import unittest +import binascii + +import dns.update +import dns.rdata +import dns.rdataset +import dns.tsigkeyring + +def hextowire(hex): + return binascii.unhexlify(hex.replace(' ', '').encode()) + +goodwire = hextowire( + '0001 2800 0001 0005 0007 0000' + '076578616d706c6500 0006 0001' + '03666f6fc00c 00ff 00ff 00000000 0000' + 'c019 0001 00ff 00000000 0000' + '03626172c00c 0001 0001 00000000 0004 0a000005' + '05626c617a32c00c 00ff 00fe 00000000 0000' + 'c049 0001 00fe 00000000 0000' + 'c019 0001 00ff 00000000 0000' + 'c019 0001 0001 0000012c 0004 0a000001' + 'c019 0001 0001 0000012c 0004 0a000002' + 'c035 0001 0001 0000012c 0004 0a000003' + 'c035 0001 00fe 00000000 0004 0a000004' + '04626c617ac00c 0001 00ff 00000000 0000' + 'c049 00ff 00ff 00000000 0000' +) + +goodwirenone = hextowire( + '0001 2800 0001 0000 0001 0000' + '076578616d706c6500 0006 0001' + '03666f6fc00c 0001 00fe 00000000 0004 01020304' +) + +badwirenone = hextowire( + '0001 2800 0001 0003 0000 0000' + '076578616d706c6500 0006 0001' + '03666f6fc00c 00ff 00ff 00000000 0000' + 'c019 0001 00ff 00000000 0000' + 'c019 0001 00fe 00000000 0004 01020304' +) + +badwireany = hextowire( + '0001 2800 0001 0002 0000 0000' + '076578616d706c6500 0006 0001' + '03666f6fc00c 00ff 00ff 00000000 0000' + 'c019 0001 00ff 00000000 0004 01020304' +) + +badwireanyany = hextowire( + '0001 2800 0001 0001 0000 0000' + '076578616d706c6500 0006 0001' + '03666f6fc00c 00ff 00ff 00000000 0004 01020304' +) + +badwirezonetype = hextowire( + '0001 2800 0001 0000 0000 0000' + '076578616d706c6500 0001 0001' +) + +badwirezoneclass = hextowire( + '0001 2800 0001 0000 0000 0000' + '076578616d706c6500 0006 00ff' +) + +badwirezonemulti = hextowire( + '0001 2800 0002 0000 0000 0000' + '076578616d706c6500 0006 0001' + 'c019 0006 0001' +) + +badwirenozone = hextowire( + '0001 2800 0000 0000 0001 0000' + '03666f6f076578616d706c6500 0001 0001 00000030 0004 01020304' +) + +update_text = """id 1 +opcode UPDATE +rcode NOERROR +;ZONE +example. IN SOA +;PREREQ +foo ANY ANY +foo ANY A +bar 0 IN A 10.0.0.5 +blaz2 NONE ANY +blaz2 NONE A +;UPDATE +foo ANY A +foo 300 IN A 10.0.0.1 +foo 300 IN A 10.0.0.2 +bar 300 IN A 10.0.0.3 +bar 0 NONE A 10.0.0.4 +blaz ANY A +blaz2 ANY ANY +""" + +added_text = """id 1 +opcode UPDATE +;ZONE +example. IN SOA +;UPDATE +foo 300 IN A 10.0.0.1 +foo 300 IN A 10.0.0.2 +""" + +replaced_text = """id 1 +opcode UPDATE +;ZONE +example. IN SOA +;UPDATE +foo ANY A +foo 300 IN A 10.0.0.1 +foo 300 IN A 10.0.0.2 +""" + +deleted_text = """id 1 +opcode UPDATE +;ZONE +example. IN SOA +;UPDATE +foo 0 NONE A 10.0.0.1 +foo 0 NONE A 10.0.0.2 +""" + +class UpdateTestCase(unittest.TestCase): + + def test_to_wire1(self): # type: () -> None + update = dns.update.Update('example') + update.id = 1 + update.present('foo') + update.present('foo', 'a') + update.present('bar', 'a', '10.0.0.5') + update.absent('blaz2') + update.absent('blaz2', 'a') + update.replace('foo', 300, 'a', '10.0.0.1', '10.0.0.2') + update.add('bar', 300, 'a', '10.0.0.3') + update.delete('bar', 'a', '10.0.0.4') + update.delete('blaz', 'a') + update.delete('blaz2') + self.assertEqual(update.to_wire(), goodwire) + + def test_to_wire2(self): # type: () -> None + update = dns.update.Update('example') + update.id = 1 + update.present('foo') + update.present('foo', 'a') + update.present('bar', 'a', '10.0.0.5') + update.absent('blaz2') + update.absent('blaz2', 'a') + update.replace('foo', 300, 'a', '10.0.0.1', '10.0.0.2') + update.add('bar', 300, dns.rdata.from_text(1, 1, '10.0.0.3')) + update.delete('bar', 'a', '10.0.0.4') + update.delete('blaz', 'a') + update.delete('blaz2') + self.assertEqual(update.to_wire(), goodwire) + + def test_to_wire3(self): # type: () -> None + update = dns.update.Update('example') + update.id = 1 + update.present('foo') + update.present('foo', 'a') + update.present('bar', 'a', '10.0.0.5') + update.absent('blaz2') + update.absent('blaz2', 'a') + update.replace('foo', 300, 'a', '10.0.0.1', '10.0.0.2') + update.add('bar', dns.rdataset.from_text(1, 1, 300, '10.0.0.3')) + update.delete('bar', 'a', '10.0.0.4') + update.delete('blaz', 'a') + update.delete('blaz2') + self.assertEqual(update.to_wire(), goodwire) + + def test_from_text1(self): # type: () -> None + update = dns.message.from_text(update_text) + self.assertTrue(isinstance(update, dns.update.UpdateMessage)) + w = update.to_wire(origin=dns.name.from_text('example'), + want_shuffle=False) + self.assertEqual(w, goodwire) + + def test_from_wire(self): + origin = dns.name.from_text('example') + u1 = dns.message.from_wire(goodwire, origin=origin) + u2 = dns.message.from_text(update_text, origin=origin) + self.assertEqual(u1, u2) + + def test_good_explicit_delete_wire(self): + name = dns.name.from_text('foo.example') + u = dns.message.from_wire(goodwirenone) + self.assertEqual(u.update[0].name, name) + self.assertEqual(u.update[0].rdtype, dns.rdatatype.A) + self.assertEqual(u.update[0].rdclass, dns.rdataclass.IN) + self.assertTrue(u.update[0].deleting) + self.assertEqual(u.update[0][0].address, '1.2.3.4') + + def test_none_with_rdata_from_wire(self): + def bad(): + dns.message.from_wire(badwirenone) + self.assertRaises(dns.exception.FormError, bad) + + def test_any_with_rdata_from_wire(self): + def bad(): + dns.message.from_wire(badwireany) + self.assertRaises(dns.exception.FormError, bad) + + def test_any_any_with_rdata_from_wire(self): + def bad(): + dns.message.from_wire(badwireanyany) + self.assertRaises(dns.exception.FormError, bad) + + def test_bad_zone_type_from_wire(self): + def bad(): + dns.message.from_wire(badwirezonetype) + self.assertRaises(dns.exception.FormError, bad) + + def test_bad_zone_class_from_wire(self): + def bad(): + dns.message.from_wire(badwirezoneclass) + self.assertRaises(dns.exception.FormError, bad) + + def test_bad_zone_multi_from_wire(self): + def bad(): + dns.message.from_wire(badwirezonemulti) + self.assertRaises(dns.exception.FormError, bad) + + def test_no_zone_section_from_wire(self): + def bad(): + dns.message.from_wire(badwirenozone) + self.assertRaises(dns.exception.FormError, bad) + + def test_TSIG(self): + keyring = dns.tsigkeyring.from_text({ + 'keyname.' : 'NjHwPsMKjdN++dOfE5iAiQ==' + }) + update = dns.update.Update('example.', keyring=keyring) + update.replace('host.example.', 300, 'A', '1.2.3.4') + wire = update.to_wire() + update2 = dns.message.from_wire(wire, keyring) + self.assertEqual(update, update2) + + def test_is_response(self): + update = dns.message.from_text(update_text) + self.assertTrue(isinstance(update, dns.update.UpdateMessage)) + r = dns.message.make_response(update) + self.assertTrue(isinstance(r, dns.update.UpdateMessage)) + self.assertTrue(update.is_response(r)) + + def test_making_UpdateSection(self): + self.assertEqual(dns.update.UpdateSection.make(0), + dns.update.UpdateSection.make('ZONE')) + with self.assertRaises(ValueError): + dns.update.UpdateSection.make(99) + + def test_setters(self): + u = dns.update.UpdateMessage(id=1) + qrrset = dns.rrset.RRset(dns.name.from_text('example'), + dns.rdataclass.IN, dns.rdatatype.SOA) + rrset = dns.rrset.from_text('foo', 300, 'in', 'a', '10.0.0.1') + u.zone = [qrrset] + self.assertEqual(u.sections[0], [qrrset]) + self.assertEqual(u.sections[1], []) + self.assertEqual(u.sections[2], []) + self.assertEqual(u.sections[3], []) + u.prerequisite = [rrset] + self.assertEqual(u.sections[0], [qrrset]) + self.assertEqual(u.sections[1], [rrset]) + self.assertEqual(u.sections[2], []) + self.assertEqual(u.sections[3], []) + u.update = [rrset] + self.assertEqual(u.sections[0], [qrrset]) + self.assertEqual(u.sections[1], [rrset]) + self.assertEqual(u.sections[2], [rrset]) + self.assertEqual(u.sections[3], []) + + def test_added_rdataset(self): + u = dns.update.UpdateMessage('example.', id=1) + rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1', '10.0.0.2') + u.add('foo', rds) + expected = dns.message.from_text(added_text) + self.assertEqual(u, expected) + + def test_replaced_rdataset(self): + u = dns.update.UpdateMessage('example.', id=1) + rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1', '10.0.0.2') + u.replace('foo', rds) + expected = dns.message.from_text(replaced_text) + self.assertEqual(u, expected) + + def test_delete_rdataset(self): + u = dns.update.UpdateMessage('example.', id=1) + rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1', '10.0.0.2') + u.delete('foo', rds) + expected = dns.message.from_text(deleted_text) + self.assertEqual(u, expected) + + def test_added_rdata(self): + u = dns.update.UpdateMessage('example.', id=1) + rd1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1') + rd2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.2') + u.add('foo', 300, rd1) + u.add('foo', 300, rd2) + expected = dns.message.from_text(added_text) + self.assertEqual(u, expected) + + def test_replaced_rdata(self): + u = dns.update.UpdateMessage('example.', id=1) + rd1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1') + rd2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.2') + u.replace('foo', 300, rd1) + u.add('foo', 300, rd2) + expected = dns.message.from_text(replaced_text) + self.assertEqual(u, expected) + + def test_deleted_rdata(self): + u = dns.update.UpdateMessage('example.', id=1) + rd1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1') + rd2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.2') + u.delete('foo', rd1) + u.delete('foo', rd2) + expected = dns.message.from_text(deleted_text) + self.assertEqual(u, expected) + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_wire.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_wire.py new file mode 100644 index 0000000..a4b5991 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_wire.py @@ -0,0 +1,88 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import unittest + +import dns.exception +import dns.wire +import dns.name + + +class BinaryTestCase(unittest.TestCase): + + def test_basic(self): + wire = bytes.fromhex('0102010203040102') + p = dns.wire.Parser(wire) + self.assertEqual(p.get_uint16(), 0x0102) + with p.restrict_to(5): + self.assertEqual(p.get_uint32(), 0x01020304) + self.assertEqual(p.get_uint8(), 0x01) + self.assertEqual(p.remaining(), 0) + with self.assertRaises(dns.exception.FormError): + p.get_uint16() + self.assertEqual(p.remaining(), 1) + self.assertEqual(p.get_uint8(), 0x02) + with self.assertRaises(dns.exception.FormError): + p.get_uint8() + + def test_name(self): + # www.dnspython.org NS IN question + wire = b'\x03www\x09dnspython\x03org\x00\x00\x02\x00\x01' + expected = dns.name.from_text('www.dnspython.org') + p = dns.wire.Parser(wire) + self.assertEqual(p.get_name(), expected) + self.assertEqual(p.get_uint16(), 2) + self.assertEqual(p.get_uint16(), 1) + self.assertEqual(p.remaining(), 0) + + def test_relativized_name(self): + # www.dnspython.org NS IN question + wire = b'\x03www\x09dnspython\x03org\x00\x00\x02\x00\x01' + origin = dns.name.from_text('dnspython.org') + expected = dns.name.from_text('www', None) + p = dns.wire.Parser(wire) + self.assertEqual(p.get_name(origin), expected) + self.assertEqual(p.remaining(), 4) + + def test_compressed_name(self): + # www.dnspython.org NS IN question + wire = b'\x09dnspython\x03org\x00\x03www\xc0\x00' + expected1 = dns.name.from_text('dnspython.org') + expected2 = dns.name.from_text('www.dnspython.org') + p = dns.wire.Parser(wire) + self.assertEqual(p.get_name(), expected1) + self.assertEqual(p.get_name(), expected2) + self.assertEqual(p.remaining(), 0) + # verify the restore_furthest() + self.assertEqual(p.current, len(wire)) + + def test_seek(self): + wire = b'\x09dnspython\x03org\x00' + p = dns.wire.Parser(wire) + p.seek(10) + self.assertEqual(p.get_uint8(), 3) + # seeking to the end index is OK + p.seek(len(wire)) + self.assertEqual(p.current, p.end) + with self.assertRaises(dns.exception.FormError): + # but reading there will not succeed + p.get_uint8() + with self.assertRaises(dns.exception.FormError): + p.seek(-1) + with self.assertRaises(dns.exception.FormError): + p.seek(len(wire) + 1) + + def test_not_reading_everything_in_restriction(self): + wire = bytes.fromhex('0102010203040102') + p = dns.wire.Parser(wire) + with self.assertRaises(dns.exception.FormError): + with p.restrict_to(5): + v = p.get_uint8() + self.assertEqual(v, 1) + # don't read the other 4 bytes + + def test_restriction_does_not_mask_exception(self): + wire = bytes.fromhex('0102010203040102') + p = dns.wire.Parser(wire) + with self.assertRaises(NotImplementedError): + with p.restrict_to(5): + raise NotImplementedError diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_xfr.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_xfr.py new file mode 100644 index 0000000..c1a011c --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_xfr.py @@ -0,0 +1,747 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +import asyncio + +import pytest + +import dns.asyncbackend +import dns.asyncquery +import dns.message +import dns.query +import dns.tsigkeyring +import dns.versioned +import dns.xfr + +# Some tests use a "nano nameserver" for testing. It requires trio +# and threading, so try to import it and if it doesn't work, skip +# those tests. +try: + from .nanonameserver import Server + _nanonameserver_available = True +except ImportError: + _nanonameserver_available = False + class Server(object): + pass + +axfr = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN AXFR +;ANSWER +@ 3600 IN SOA foo bar 1 2 3 4 5 +@ 3600 IN NS ns1 +@ 3600 IN NS ns2 +bar.foo 300 IN MX 0 blaz.foo +ns1 3600 IN A 10.0.0.1 +ns2 3600 IN A 10.0.0.2 +@ 3600 IN SOA foo bar 1 2 3 4 5 +''' + +axfr1 = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN AXFR +;ANSWER +@ 3600 IN SOA foo bar 1 2 3 4 5 +@ 3600 IN NS ns1 +@ 3600 IN NS ns2 +''' +axfr2 = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;ANSWER +bar.foo 300 IN MX 0 blaz.foo +ns1 3600 IN A 10.0.0.1 +ns2 3600 IN A 10.0.0.2 +@ 3600 IN SOA foo bar 1 2 3 4 5 +''' + +base = """@ 3600 IN SOA foo bar 1 2 3 4 5 +@ 3600 IN NS ns1 +@ 3600 IN NS ns2 +bar.foo 300 IN MX 0 blaz.foo +ns1 3600 IN A 10.0.0.1 +ns2 3600 IN A 10.0.0.2 +""" + +axfr_unexpected_origin = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN AXFR +;ANSWER +@ 3600 IN SOA foo bar 1 2 3 4 5 +@ 3600 IN SOA foo bar 1 2 3 4 7 +''' + +ixfr = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN IXFR +;ANSWER +@ 3600 IN SOA foo bar 4 2 3 4 5 +@ 3600 IN SOA foo bar 1 2 3 4 5 +bar.foo 300 IN MX 0 blaz.foo +ns2 3600 IN A 10.0.0.2 +@ 3600 IN SOA foo bar 2 2 3 4 5 +ns2 3600 IN A 10.0.0.4 +@ 3600 IN SOA foo bar 2 2 3 4 5 +@ 3600 IN SOA foo bar 3 2 3 4 5 +ns3 3600 IN A 10.0.0.3 +@ 3600 IN SOA foo bar 3 2 3 4 5 +@ 3600 IN NS ns2 +@ 3600 IN SOA foo bar 4 2 3 4 5 +@ 3600 IN SOA foo bar 4 2 3 4 5 +''' + +compressed_ixfr = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN IXFR +;ANSWER +@ 3600 IN SOA foo bar 4 2 3 4 5 +@ 3600 IN SOA foo bar 1 2 3 4 5 +bar.foo 300 IN MX 0 blaz.foo +ns2 3600 IN A 10.0.0.2 +@ 3600 IN NS ns2 +@ 3600 IN SOA foo bar 4 2 3 4 5 +ns2 3600 IN A 10.0.0.4 +ns3 3600 IN A 10.0.0.3 +@ 3600 IN SOA foo bar 4 2 3 4 5 +''' + +ixfr_expected = """@ 3600 IN SOA foo bar 4 2 3 4 5 +@ 3600 IN NS ns1 +ns1 3600 IN A 10.0.0.1 +ns2 3600 IN A 10.0.0.4 +ns3 3600 IN A 10.0.0.3 +""" + +ixfr_first_message = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN IXFR +;ANSWER +@ 3600 IN SOA foo bar 4 2 3 4 5 +''' + +ixfr_header = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;ANSWER +''' + +ixfr_body = [ + '@ 3600 IN SOA foo bar 1 2 3 4 5', + 'bar.foo 300 IN MX 0 blaz.foo', + 'ns2 3600 IN A 10.0.0.2', + '@ 3600 IN SOA foo bar 2 2 3 4 5', + 'ns2 3600 IN A 10.0.0.4', + '@ 3600 IN SOA foo bar 2 2 3 4 5', + '@ 3600 IN SOA foo bar 3 2 3 4 5', + 'ns3 3600 IN A 10.0.0.3', + '@ 3600 IN SOA foo bar 3 2 3 4 5', + '@ 3600 IN NS ns2', + '@ 3600 IN SOA foo bar 4 2 3 4 5', + '@ 3600 IN SOA foo bar 4 2 3 4 5', +] + +ixfrs = [ixfr_first_message] +ixfrs.extend([ixfr_header + l for l in ixfr_body]) + +good_empty_ixfr = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN IXFR +;ANSWER +@ 3600 IN SOA foo bar 1 2 3 4 5 +''' + +retry_tcp_ixfr = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN IXFR +;ANSWER +@ 3600 IN SOA foo bar 5 2 3 4 5 +''' + +bad_empty_ixfr = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN IXFR +;ANSWER +@ 3600 IN SOA foo bar 4 2 3 4 5 +@ 3600 IN SOA foo bar 4 2 3 4 5 +''' + +unexpected_end_ixfr = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN IXFR +;ANSWER +@ 3600 IN SOA foo bar 4 2 3 4 5 +@ 3600 IN SOA foo bar 1 2 3 4 5 +bar.foo 300 IN MX 0 blaz.foo +ns2 3600 IN A 10.0.0.2 +@ 3600 IN NS ns2 +@ 3600 IN SOA foo bar 3 2 3 4 5 +ns2 3600 IN A 10.0.0.4 +ns3 3600 IN A 10.0.0.3 +@ 3600 IN SOA foo bar 4 2 3 4 5 +''' + +unexpected_end_ixfr_2 = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN IXFR +;ANSWER +@ 3600 IN SOA foo bar 4 2 3 4 5 +@ 3600 IN SOA foo bar 1 2 3 4 5 +bar.foo 300 IN MX 0 blaz.foo +ns2 3600 IN A 10.0.0.2 +@ 3600 IN NS ns2 +''' + +bad_serial_ixfr = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN IXFR +;ANSWER +@ 3600 IN SOA foo bar 4 2 3 4 5 +@ 3600 IN SOA foo bar 2 2 3 4 5 +bar.foo 300 IN MX 0 blaz.foo +ns2 3600 IN A 10.0.0.2 +@ 3600 IN NS ns2 +@ 3600 IN SOA foo bar 4 2 3 4 5 +ns2 3600 IN A 10.0.0.4 +ns3 3600 IN A 10.0.0.3 +@ 3600 IN SOA foo bar 4 2 3 4 5 +''' + +ixfr_axfr = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN IXFR +;ANSWER +@ 3600 IN SOA foo bar 1 2 3 4 5 +@ 3600 IN NS ns1 +@ 3600 IN NS ns2 +bar.foo 300 IN MX 0 blaz.foo +ns1 3600 IN A 10.0.0.1 +ns2 3600 IN A 10.0.0.2 +@ 3600 IN SOA foo bar 1 2 3 4 5 +''' + +def test_basic_axfr(): + z = dns.versioned.Zone('example.') + m = dns.message.from_text(axfr, origin=z.origin, + one_rr_per_rrset=True) + with dns.xfr.Inbound(z, dns.rdatatype.AXFR) as xfr: + done = xfr.process_message(m) + assert done + ez = dns.zone.from_text(base, 'example.') + assert z == ez + +def test_basic_axfr_two_parts(): + z = dns.versioned.Zone('example.') + m1 = dns.message.from_text(axfr1, origin=z.origin, + one_rr_per_rrset=True) + m2 = dns.message.from_text(axfr2, origin=z.origin, + one_rr_per_rrset=True) + with dns.xfr.Inbound(z, dns.rdatatype.AXFR) as xfr: + done = xfr.process_message(m1) + assert not done + done = xfr.process_message(m2) + assert done + ez = dns.zone.from_text(base, 'example.') + assert z == ez + +def test_axfr_unexpected_origin(): + z = dns.versioned.Zone('example.') + m = dns.message.from_text(axfr_unexpected_origin, origin=z.origin, + one_rr_per_rrset=True) + with dns.xfr.Inbound(z, dns.rdatatype.AXFR) as xfr: + with pytest.raises(dns.exception.FormError): + xfr.process_message(m) + +def test_basic_ixfr(): + z = dns.zone.from_text(base, 'example.', + zone_factory=dns.versioned.Zone) + m = dns.message.from_text(ixfr, origin=z.origin, + one_rr_per_rrset=True) + with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr: + done = xfr.process_message(m) + assert done + ez = dns.zone.from_text(ixfr_expected, 'example.') + assert z == ez + +def test_compressed_ixfr(): + z = dns.zone.from_text(base, 'example.', + zone_factory=dns.versioned.Zone) + m = dns.message.from_text(compressed_ixfr, origin=z.origin, + one_rr_per_rrset=True) + with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr: + done = xfr.process_message(m) + assert done + ez = dns.zone.from_text(ixfr_expected, 'example.') + assert z == ez + +def test_basic_ixfr_many_parts(): + z = dns.zone.from_text(base, 'example.', + zone_factory=dns.versioned.Zone) + with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr: + done = False + for text in ixfrs: + assert not done + m = dns.message.from_text(text, origin=z.origin, + one_rr_per_rrset=True) + done = xfr.process_message(m) + assert done + ez = dns.zone.from_text(ixfr_expected, 'example.') + assert z == ez + +def test_good_empty_ixfr(): + z = dns.zone.from_text(ixfr_expected, 'example.', + zone_factory=dns.versioned.Zone) + m = dns.message.from_text(good_empty_ixfr, origin=z.origin, + one_rr_per_rrset=True) + with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr: + done = xfr.process_message(m) + assert done + ez = dns.zone.from_text(ixfr_expected, 'example.') + assert z == ez + +def test_retry_tcp_ixfr(): + z = dns.zone.from_text(ixfr_expected, 'example.', + zone_factory=dns.versioned.Zone) + m = dns.message.from_text(retry_tcp_ixfr, origin=z.origin, + one_rr_per_rrset=True) + with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1, is_udp=True) as xfr: + with pytest.raises(dns.xfr.UseTCP): + xfr.process_message(m) + +def test_bad_empty_ixfr(): + z = dns.zone.from_text(ixfr_expected, 'example.', + zone_factory=dns.versioned.Zone) + m = dns.message.from_text(bad_empty_ixfr, origin=z.origin, + one_rr_per_rrset=True) + with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=3) as xfr: + with pytest.raises(dns.exception.FormError): + xfr.process_message(m) + +def test_serial_went_backwards_ixfr(): + z = dns.zone.from_text(ixfr_expected, 'example.', + zone_factory=dns.versioned.Zone) + m = dns.message.from_text(bad_empty_ixfr, origin=z.origin, + one_rr_per_rrset=True) + with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=5) as xfr: + with pytest.raises(dns.xfr.SerialWentBackwards): + xfr.process_message(m) + +def test_ixfr_is_axfr(): + z = dns.zone.from_text(base, 'example.', + zone_factory=dns.versioned.Zone) + m = dns.message.from_text(ixfr_axfr, origin=z.origin, + one_rr_per_rrset=True) + with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=0xffffffff) as xfr: + done = xfr.process_message(m) + assert done + ez = dns.zone.from_text(base, 'example.') + assert z == ez + +def test_ixfr_requires_serial(): + z = dns.zone.from_text(base, 'example.', + zone_factory=dns.versioned.Zone) + with pytest.raises(ValueError): + dns.xfr.Inbound(z, dns.rdatatype.IXFR) + +def test_ixfr_unexpected_end_bad_diff_sequence(): + # This is where we get the end serial, but haven't seen all of + # the expected diffs + z = dns.zone.from_text(base, 'example.', + zone_factory=dns.versioned.Zone) + m = dns.message.from_text(unexpected_end_ixfr, origin=z.origin, + one_rr_per_rrset=True) + with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr: + with pytest.raises(dns.exception.FormError): + xfr.process_message(m) + +def test_udp_ixfr_unexpected_end_just_stops(): + # This is where everything looks good, but the IXFR just stops + # in the middle. + z = dns.zone.from_text(base, 'example.', + zone_factory=dns.versioned.Zone) + m = dns.message.from_text(unexpected_end_ixfr_2, origin=z.origin, + one_rr_per_rrset=True) + with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1, is_udp=True) as xfr: + with pytest.raises(dns.exception.FormError): + xfr.process_message(m) + +def test_ixfr_bad_serial(): + z = dns.zone.from_text(base, 'example.', + zone_factory=dns.versioned.Zone) + m = dns.message.from_text(bad_serial_ixfr, origin=z.origin, + one_rr_per_rrset=True) + with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr: + with pytest.raises(dns.exception.FormError): + xfr.process_message(m) + +def test_no_udp_with_axfr(): + z = dns.versioned.Zone('example.') + with pytest.raises(ValueError): + with dns.xfr.Inbound(z, dns.rdatatype.AXFR, is_udp=True) as xfr: + pass + +refused = '''id 1 +opcode QUERY +rcode REFUSED +flags AA +;QUESTION +example. IN AXFR +''' + +bad_qname = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +not-example. IN IXFR +''' + +bad_qtype = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN AXFR +''' + +soa_not_first = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN IXFR +;ANSWER +bar.foo 300 IN MX 0 blaz.foo +''' + +soa_not_first_2 = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN IXFR +;ANSWER +@ 300 IN MX 0 blaz.foo +''' + +no_answer = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN IXFR +;ADDITIONAL +bar.foo 300 IN MX 0 blaz.foo +''' + +axfr_answers_after_final_soa = '''id 1 +opcode QUERY +rcode NOERROR +flags AA +;QUESTION +example. IN AXFR +;ANSWER +@ 3600 IN SOA foo bar 1 2 3 4 5 +@ 3600 IN NS ns1 +@ 3600 IN NS ns2 +bar.foo 300 IN MX 0 blaz.foo +ns1 3600 IN A 10.0.0.1 +ns2 3600 IN A 10.0.0.2 +@ 3600 IN SOA foo bar 1 2 3 4 5 +ns3 3600 IN A 10.0.0.3 +''' + +def test_refused(): + z = dns.zone.from_text(base, 'example.', + zone_factory=dns.versioned.Zone) + m = dns.message.from_text(refused, origin=z.origin, + one_rr_per_rrset=True) + with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr: + with pytest.raises(dns.xfr.TransferError): + xfr.process_message(m) + +def test_bad_qname(): + z = dns.zone.from_text(base, 'example.', + zone_factory=dns.versioned.Zone) + m = dns.message.from_text(bad_qname, origin=z.origin, + one_rr_per_rrset=True) + with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr: + with pytest.raises(dns.exception.FormError): + xfr.process_message(m) + +def test_bad_qtype(): + z = dns.zone.from_text(base, 'example.', + zone_factory=dns.versioned.Zone) + m = dns.message.from_text(bad_qtype, origin=z.origin, + one_rr_per_rrset=True) + with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr: + with pytest.raises(dns.exception.FormError): + xfr.process_message(m) + +def test_soa_not_first(): + z = dns.zone.from_text(base, 'example.', + zone_factory=dns.versioned.Zone) + m = dns.message.from_text(soa_not_first, origin=z.origin, + one_rr_per_rrset=True) + with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr: + with pytest.raises(dns.exception.FormError): + xfr.process_message(m) + m = dns.message.from_text(soa_not_first_2, origin=z.origin, + one_rr_per_rrset=True) + with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr: + with pytest.raises(dns.exception.FormError): + xfr.process_message(m) + +def test_no_answer(): + z = dns.zone.from_text(base, 'example.', + zone_factory=dns.versioned.Zone) + m = dns.message.from_text(no_answer, origin=z.origin, + one_rr_per_rrset=True) + with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr: + with pytest.raises(dns.exception.FormError): + xfr.process_message(m) + +def test_axfr_answers_after_final_soa(): + z = dns.versioned.Zone('example.') + m = dns.message.from_text(axfr_answers_after_final_soa, origin=z.origin, + one_rr_per_rrset=True) + with dns.xfr.Inbound(z, dns.rdatatype.AXFR) as xfr: + with pytest.raises(dns.exception.FormError): + xfr.process_message(m) + +keyring = dns.tsigkeyring.from_text( + { + 'keyname.': 'NjHwPsMKjdN++dOfE5iAiQ==' + } +) + +keyname = dns.name.from_text('keyname') + +def test_make_query_basic(): + z = dns.versioned.Zone('example.') + (q, s) = dns.xfr.make_query(z) + assert q.question[0].rdtype == dns.rdatatype.AXFR + assert s is None + (q, s) = dns.xfr.make_query(z, serial=None) + assert q.question[0].rdtype == dns.rdatatype.AXFR + assert s is None + (q, s) = dns.xfr.make_query(z, serial=10) + assert q.question[0].rdtype == dns.rdatatype.IXFR + assert q.authority[0].rdtype == dns.rdatatype.SOA + assert q.authority[0][0].serial == 10 + assert s == 10 + with z.writer() as txn: + txn.add('@', 300, dns.rdata.from_text('in', 'soa', '. . 1 2 3 4 5')) + (q, s) = dns.xfr.make_query(z) + assert q.question[0].rdtype == dns.rdatatype.IXFR + assert q.authority[0].rdtype == dns.rdatatype.SOA + assert q.authority[0][0].serial == 1 + assert s == 1 + (q, s) = dns.xfr.make_query(z, keyring=keyring, keyname=keyname) + assert q.question[0].rdtype == dns.rdatatype.IXFR + assert q.authority[0].rdtype == dns.rdatatype.SOA + assert q.authority[0][0].serial == 1 + assert s == 1 + assert q.keyname == keyname + + +def test_make_query_bad_serial(): + z = dns.versioned.Zone('example.') + with pytest.raises(ValueError): + dns.xfr.make_query(z, serial='hi') + with pytest.raises(ValueError): + dns.xfr.make_query(z, serial=-1) + with pytest.raises(ValueError): + dns.xfr.make_query(z, serial=4294967296) + + +class XFRNanoNameserver(Server): + + def __init__(self): + super().__init__(origin=dns.name.from_text('example')) + + def handle(self, request): + try: + if request.message.question[0].rdtype == dns.rdatatype.IXFR: + text = ixfr + else: + text = axfr + r = dns.message.from_text(text, one_rr_per_rrset=True, + origin=self.origin) + r.id = request.message.id + return r + except Exception: + pass + +@pytest.mark.skipif(not _nanonameserver_available, + reason="requires nanonameserver") +def test_sync_inbound_xfr(): + with XFRNanoNameserver() as ns: + zone = dns.versioned.Zone('example') + dns.query.inbound_xfr(ns.tcp_address[0], zone, port=ns.tcp_address[1], + udp_mode=dns.query.UDPMode.TRY_FIRST) + dns.query.inbound_xfr(ns.tcp_address[0], zone, port=ns.tcp_address[1], + udp_mode=dns.query.UDPMode.TRY_FIRST) + expected = dns.zone.from_text(ixfr_expected, 'example') + assert zone == expected + +async def async_inbound_xfr(): + with XFRNanoNameserver() as ns: + zone = dns.versioned.Zone('example') + await dns.asyncquery.inbound_xfr(ns.tcp_address[0], zone, + port=ns.tcp_address[1], + udp_mode=dns.query.UDPMode.TRY_FIRST) + await dns.asyncquery.inbound_xfr(ns.tcp_address[0], zone, + port=ns.tcp_address[1], + udp_mode=dns.query.UDPMode.TRY_FIRST) + expected = dns.zone.from_text(ixfr_expected, 'example') + assert zone == expected + +@pytest.mark.skipif(not _nanonameserver_available, + reason="requires nanonameserver") +def test_asyncio_inbound_xfr(): + dns.asyncbackend.set_default_backend('asyncio') + async def run(): + await async_inbound_xfr() + try: + runner = asyncio.run + except AttributeError: + # this is only needed for 3.6 + def old_runner(awaitable): + loop = asyncio.get_event_loop() + return loop.run_until_complete(awaitable) + runner = old_runner + runner(run()) + +# +# We don't need to do this as it's all generic code, but +# just for extra caution we do it for each backend. +# + +try: + import trio + + @pytest.mark.skipif(not _nanonameserver_available, + reason="requires nanonameserver") + def test_trio_inbound_xfr(): + dns.asyncbackend.set_default_backend('trio') + async def run(): + await async_inbound_xfr() + trio.run(run) +except ImportError: + pass + +try: + import curio + + @pytest.mark.skipif(not _nanonameserver_available, + reason="requires nanonameserver") + def test_curio_inbound_xfr(): + dns.asyncbackend.set_default_backend('curio') + async def run(): + await async_inbound_xfr() + curio.run(run) +except ImportError: + pass + + +class UDPXFRNanoNameserver(Server): + + def __init__(self): + super().__init__(origin=dns.name.from_text('example')) + self.did_truncation = False + + def handle(self, request): + try: + if request.message.question[0].rdtype == dns.rdatatype.IXFR: + if self.did_truncation: + text = ixfr + else: + text = retry_tcp_ixfr + self.did_truncation = True + else: + text = axfr + r = dns.message.from_text(text, one_rr_per_rrset=True, + origin=self.origin) + r.id = request.message.id + return r + except Exception: + pass + +@pytest.mark.skipif(not _nanonameserver_available, + reason="requires nanonameserver") +def test_sync_retry_tcp_inbound_xfr(): + with UDPXFRNanoNameserver() as ns: + zone = dns.versioned.Zone('example') + dns.query.inbound_xfr(ns.tcp_address[0], zone, port=ns.tcp_address[1], + udp_mode=dns.query.UDPMode.TRY_FIRST) + dns.query.inbound_xfr(ns.tcp_address[0], zone, port=ns.tcp_address[1], + udp_mode=dns.query.UDPMode.TRY_FIRST) + expected = dns.zone.from_text(ixfr_expected, 'example') + assert zone == expected + +async def udp_async_inbound_xfr(): + with UDPXFRNanoNameserver() as ns: + zone = dns.versioned.Zone('example') + await dns.asyncquery.inbound_xfr(ns.tcp_address[0], zone, + port=ns.tcp_address[1], + udp_mode=dns.query.UDPMode.TRY_FIRST) + await dns.asyncquery.inbound_xfr(ns.tcp_address[0], zone, + port=ns.tcp_address[1], + udp_mode=dns.query.UDPMode.TRY_FIRST) + expected = dns.zone.from_text(ixfr_expected, 'example') + assert zone == expected + +@pytest.mark.skipif(not _nanonameserver_available, + reason="requires nanonameserver") +def test_asyncio_retry_tcp_inbound_xfr(): + dns.asyncbackend.set_default_backend('asyncio') + async def run(): + await udp_async_inbound_xfr() + try: + runner = asyncio.run + except AttributeError: + def old_runner(awaitable): + loop = asyncio.get_event_loop() + return loop.run_until_complete(awaitable) + runner = old_runner + runner(run()) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_zone.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_zone.py new file mode 100644 index 0000000..66f3ad5 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/test_zone.py @@ -0,0 +1,876 @@ +# -*- coding: utf-8 +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +from io import BytesIO, StringIO +import difflib +import os +import sys +import unittest +from typing import cast + +import dns.exception +import dns.message +import dns.name +import dns.node +import dns.rdata +import dns.rdataset +import dns.rdataclass +import dns.rdatatype +import dns.rrset +import dns.versioned +import dns.zone +import dns.node + +from tests.util import here + +example_text = """$TTL 3600 +$ORIGIN example. +@ soa foo bar 1 2 3 4 5 +@ ns ns1 +@ ns ns2 +ns1 a 10.0.0.1 +ns2 a 10.0.0.2 +$TTL 300 +$ORIGIN foo.example. +bar mx 0 blaz +""" + +example_text_output = """@ 3600 IN SOA foo bar 1 2 3 4 5 +@ 3600 IN NS ns1 +@ 3600 IN NS ns2 +bar.foo 300 IN MX 0 blaz.foo +ns1 3600 IN A 10.0.0.1 +ns2 3600 IN A 10.0.0.2 +""" + +something_quite_similar = """@ 3600 IN SOA foo bar 1 2 3 4 5 +@ 3600 IN NS ns1 +@ 3600 IN NS ns2 +bar.foo 300 IN MX 0 blaz.foo +ns1 3600 IN A 10.0.0.1 +ns2 3600 IN A 10.0.0.3 +""" + +something_different = """@ 3600 IN SOA fooa bar 1 2 3 4 5 +@ 3600 IN NS ns11 +@ 3600 IN NS ns21 +bar.fooa 300 IN MX 0 blaz.fooa +ns11 3600 IN A 10.0.0.11 +ns21 3600 IN A 10.0.0.21 +""" + +ttl_example_text = """$TTL 1h +$ORIGIN example. +@ soa foo bar 1 2 3 4 5 +@ ns ns1 +@ ns ns2 +ns1 1d1s a 10.0.0.1 +ns2 1w1D1h1m1S a 10.0.0.2 +""" + +# No $TTL so default TTL for RRs should be inherited from SOA minimum TTL ( +# not from the last explicit RR TTL). +ttl_from_soa_text = """$ORIGIN example. +@ 1h soa foo bar 1 2 3 4 5 +@ 1h ns ns1 +@ 1h ns ns2 +ns1 1w1D1h1m1S a 10.0.0.2 +ns2 a 10.0.0.1 +""" + +# No $TTL and no SOA, so default TTL for RRs should be inherited from last +# explicit RR TTL. +ttl_from_last_text = """$ORIGIN example. +@ 1h ns ns1 +@ 1h ns ns2 +ns1 a 10.0.0.1 +ns2 1w1D1h1m1S a 10.0.0.2 +""" + +# No $TTL and no SOA should raise SyntaxError as no TTL can be determined. +no_ttl_text = """$ORIGIN example. +@ ns ns1 +@ ns ns2 +ns1 a 10.0.0.1 +ns2 a 10.0.0.2 +""" + +no_soa_text = """$TTL 1h +$ORIGIN example. +@ ns ns1 +@ ns ns2 +ns1 1d1s a 10.0.0.1 +ns2 1w1D1h1m1S a 10.0.0.2 +""" + +no_ns_text = """$TTL 1h +$ORIGIN example. +@ soa foo bar 1 2 3 4 5 +""" + +include_text = """$INCLUDE "%s" +""" % here("example") + +bad_directive_text = """$FOO bar +$ORIGIN example. +@ soa foo bar 1 2 3 4 5 +@ ns ns1 +@ ns ns2 +ns1 1d1s a 10.0.0.1 +ns2 1w1D1h1m1S a 10.0.0.2 +""" + +codec_text = """ +@ soa foo bar 1 2 3 4 5 +@ ns ns1 +@ ns ns2 +Königsgäßchen 300 NS Königsgäßchen +""" + +misc_cases_input = """ +$ORIGIN example. +$TTL 300 + +@ soa foo bar 1 2 3 4 5 +@ ns ns1 +@ ns ns2 +out-of-zone. in a 10.0.0.1 +""" + +misc_cases_expected = """ +$ORIGIN example. +$TTL 300 +@ soa foo bar 1 2 3 4 5 +@ ns ns1 +@ ns ns2 +""" + +last_ttl_input = """ +$ORIGIN example. +@ 300 ns ns1 +@ 300 ns ns2 +foo a 10.0.0.1 +@ soa foo bar 1 2 3 4 5 +""" + +origin_sets_input = """ +$ORIGIN example. +@ soa foo bar 1 2 3 4 5 +@ 300 ns ns1 +@ 300 ns ns2 +""" + +example_comments_text = """$TTL 3600 +$ORIGIN example. +@ soa foo bar (1 ; not kept +2 3 4 5) ; kept +@ ns ns1 +@ ns ns2 +ns1 a 10.0.0.1 ; comment1 +ns2 a 10.0.0.2 ; comment2 +""" + +example_comments_text_output = """@ 3600 IN SOA foo bar 1 2 3 4 5 ; kept +@ 3600 IN NS ns1 +@ 3600 IN NS ns2 +ns1 3600 IN A 10.0.0.1 ; comment1 +ns2 3600 IN A 10.0.0.2 ; comment2 +""" + +_keep_output = True + +def _rdata_sort(a): + return (a[0], a[2].rdclass, a[2].to_text()) + +def add_rdataset(msg, name, rds): + rrset = msg.get_rrset(msg.answer, name, rds.rdclass, rds.rdtype, + create=True, force_unique=True) + for rd in rds: + rrset.add(rd, ttl=rds.ttl) + +def make_xfr(zone): + q = dns.message.make_query(zone.origin, 'AXFR') + msg = dns.message.make_response(q) + if zone.relativize: + msg.origin = zone.origin + soa_name = dns.name.empty + else: + soa_name = zone.origin + soa = zone.find_rdataset(soa_name, 'SOA') + add_rdataset(msg, soa_name, soa) + for (name, rds) in zone.iterate_rdatasets(): + if rds.rdtype == dns.rdatatype.SOA: + continue + add_rdataset(msg, name, rds) + add_rdataset(msg, soa_name, soa) + return [msg] + +def compare_files(test_name, a_name, b_name): + with open(a_name, 'r') as a: + with open(b_name, 'r') as b: + differences = list(difflib.unified_diff(a.readlines(), + b.readlines())) + if len(differences) == 0: + return True + else: + print(f'{test_name} differences:') + sys.stdout.writelines(differences) + return False + +class ZoneTestCase(unittest.TestCase): + + def testFromFile1(self): + z = dns.zone.from_file(here('example'), 'example') + ok = False + try: + z.to_file(here('example1.out'), nl=b'\x0a') + ok = compare_files('testFromFile1', + here('example1.out'), + here('example1.good')) + finally: + if not _keep_output: + os.unlink(here('example1.out')) + self.assertTrue(ok) + + def testFromFile2(self): + z = dns.zone.from_file(here('example'), 'example', relativize=False) + ok = False + try: + z.to_file(here('example2.out'), relativize=False, nl=b'\x0a') + ok = compare_files('testFromFile2', + here('example2.out'), + here('example2.good')) + finally: + if not _keep_output: + os.unlink(here('example2.out')) + self.assertTrue(ok) + + def testToFileTextualStream(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + f = StringIO() + z.to_file(f) + out = f.getvalue() + f.close() + self.assertEqual(out, example_text_output) + + def testToFileBinaryStream(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + f = BytesIO() + z.to_file(f, nl=b'\n') + out = f.getvalue() + f.close() + self.assertEqual(out, example_text_output.encode()) + + def testToFileTextual(self): + z = dns.zone.from_file(here('example'), 'example') + try: + f = open(here('example3-textual.out'), 'w') + z.to_file(f) + f.close() + ok = compare_files('testToFileTextual', + here('example3-textual.out'), + here('example3.good')) + finally: + if not _keep_output: + os.unlink(here('example3-textual.out')) + self.assertTrue(ok) + + def testToFileBinary(self): + z = dns.zone.from_file(here('example'), 'example') + try: + f = open(here('example3-binary.out'), 'wb') + z.to_file(f) + f.close() + ok = compare_files('testToFileBinary', + here('example3-binary.out'), + here('example3.good')) + finally: + if not _keep_output: + os.unlink(here('example3-binary.out')) + self.assertTrue(ok) + + def testToFileFilename(self): + z = dns.zone.from_file(here('example'), 'example') + try: + z.to_file(here('example3-filename.out')) + ok = compare_files('testToFileFilename', + here('example3-filename.out'), + here('example3.good')) + finally: + if not _keep_output: + os.unlink(here('example3-filename.out')) + self.assertTrue(ok) + + def testToText(self): + z = dns.zone.from_file(here('example'), 'example') + ok = False + try: + text_zone = z.to_text(nl='\x0a') + f = open(here('example3.out'), 'w') + f.write(text_zone) + f.close() + ok = compare_files('testToText', + here('example3.out'), + here('example3.good')) + finally: + if not _keep_output: + os.unlink(here('example3.out')) + self.assertTrue(ok) + + def testFromText(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + f = StringIO() + names = list(z.nodes.keys()) + names.sort() + for n in names: + f.write(z[n].to_text(n)) + f.write('\n') + self.assertEqual(f.getvalue(), example_text_output) + + def testTorture1(self): + # + # Read a zone containing all our supported RR types, and + # for each RR in the zone, convert the rdata into wire format + # and then back out, and see if we get equal rdatas. + # + f = BytesIO() + o = dns.name.from_text('example.') + z = dns.zone.from_file(here('example'), o) + for node in z.values(): + for rds in node: + for rd in rds: + f.seek(0) + f.truncate() + rd.to_wire(f, origin=o) + wire = f.getvalue() + rd2 = dns.rdata.from_wire(rds.rdclass, rds.rdtype, + wire, 0, len(wire), + origin=o) + self.assertEqual(rd, rd2) + + def testEqual(self): + z1 = dns.zone.from_text(example_text, 'example.', relativize=True) + z2 = dns.zone.from_text(example_text_output, 'example.', + relativize=True) + self.assertEqual(z1, z2) + + def testNotEqual1(self): + z1 = dns.zone.from_text(example_text, 'example.', relativize=True) + z2 = dns.zone.from_text(something_quite_similar, 'example.', + relativize=True) + self.assertNotEqual(z1, z2) + + def testNotEqual2(self): + z1 = dns.zone.from_text(example_text, 'example.', relativize=True) + z2 = dns.zone.from_text(something_different, 'example.', + relativize=True) + self.assertNotEqual(z1, z2) + + def testNotEqual3(self): + z1 = dns.zone.from_text(example_text, 'example.', relativize=True) + z2 = dns.zone.from_text(something_different, 'example2.', + relativize=True) + self.assertNotEqual(z1, z2) + + def testFindRdataset1(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + rds = z.find_rdataset('@', 'soa') + exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5') + self.assertEqual(rds, exrds) + + def testFindRdataset2(self): + def bad(): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + z.find_rdataset('@', 'loc') + self.assertRaises(KeyError, bad) + + def testFindRRset1(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + rrs = z.find_rrset('@', 'soa') + exrrs = dns.rrset.from_text('@', 300, 'IN', 'SOA', 'foo bar 1 2 3 4 5') + self.assertEqual(rrs, exrrs) + + def testFindRRset2(self): + def bad(): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + z.find_rrset('@', 'loc') + self.assertRaises(KeyError, bad) + + def testGetRdataset1(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + rds = z.get_rdataset('@', 'soa') + exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5') + self.assertEqual(rds, exrds) + + def testGetRdataset2(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + rds = z.get_rdataset('@', 'loc') + self.assertTrue(rds is None) + + def testGetRRset1(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + rrs = z.get_rrset('@', 'soa') + exrrs = dns.rrset.from_text('@', 300, 'IN', 'SOA', 'foo bar 1 2 3 4 5') + self.assertEqual(rrs, exrrs) + + def testGetRRset2(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + rrs = z.get_rrset('@', 'loc') + self.assertTrue(rrs is None) + + def testReplaceRdataset1(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + rdataset = dns.rdataset.from_text('in', 'ns', 300, 'ns3', 'ns4') + z.replace_rdataset('@', rdataset) + rds = z.get_rdataset('@', 'ns') + self.assertTrue(rds is rdataset) + + def testReplaceRdataset2(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + rdataset = dns.rdataset.from_text('in', 'txt', 300, '"foo"') + z.replace_rdataset('@', rdataset) + rds = z.get_rdataset('@', 'txt') + self.assertTrue(rds is rdataset) + + def testDeleteRdataset1(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + z.delete_rdataset('@', 'ns') + rds = z.get_rdataset('@', 'ns') + self.assertTrue(rds is None) + + def testDeleteRdataset2(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + z.delete_rdataset('ns1', 'a') + node = z.get_node('ns1') + self.assertTrue(node is None) + + def testNodeFindRdataset1(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + node = z['@'] + rds = node.find_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA) + exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5') + self.assertEqual(rds, exrds) + + def testNodeFindRdataset2(self): + def bad(): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + node = z['@'] + node.find_rdataset(dns.rdataclass.IN, dns.rdatatype.LOC) + self.assertRaises(KeyError, bad) + + def testNodeGetRdataset1(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + node = z['@'] + rds = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA) + exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5') + self.assertEqual(rds, exrds) + + def testNodeGetRdataset2(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + node = z['@'] + rds = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.LOC) + self.assertTrue(rds is None) + + def testNodeDeleteRdataset1(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + node = z['@'] + node.delete_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA) + rds = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA) + self.assertTrue(rds is None) + + def testNodeDeleteRdataset2(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + node = z['@'] + node.delete_rdataset(dns.rdataclass.IN, dns.rdatatype.LOC) + rds = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.LOC) + self.assertTrue(rds is None) + + def testIterateNodes(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + count = 0 + for n in z: + count += 1 + self.assertEqual(count, 4) + + def testIterateRdatasets(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + ns = [n for n, r in z.iterate_rdatasets('A')] + ns.sort() + self.assertEqual(ns, [dns.name.from_text('ns1', None), + dns.name.from_text('ns2', None)]) + + def testIterateAllRdatasets(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + ns = [n for n, r in z.iterate_rdatasets()] + ns.sort() + self.assertEqual(ns, [dns.name.from_text('@', None), + dns.name.from_text('@', None), + dns.name.from_text('bar.foo', None), + dns.name.from_text('ns1', None), + dns.name.from_text('ns2', None)]) + + def testIterateRdatas(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + l = list(z.iterate_rdatas('A')) + l.sort() + exl = [(dns.name.from_text('ns1', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1')), + (dns.name.from_text('ns2', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.2'))] + self.assertEqual(l, exl) + + def testIterateAllRdatas(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + l = list(z.iterate_rdatas()) + l.sort(key=_rdata_sort) + exl = [(dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + 'ns1')), + (dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, + 'ns2')), + (dns.name.from_text('@', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, + 'foo bar 1 2 3 4 5')), + (dns.name.from_text('bar.foo', None), + 300, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, + '0 blaz.foo')), + (dns.name.from_text('ns1', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.1')), + (dns.name.from_text('ns2', None), + 3600, + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, + '10.0.0.2'))] + exl.sort(key=_rdata_sort) + self.assertEqual(l, exl) + + def testNodeGetSetDel(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + n = z.node_factory() + rds = dns.rdataset.from_text('IN', 'A', 300, '10.0.0.1') + n.replace_rdataset(rds) + z['foo'] = n + self.assertTrue(z.find_rdataset('foo', 'A') is rds) + self.assertEqual(z['foo'], n) + self.assertEqual(z.get('foo'), n) + del z['foo'] + self.assertEqual(z.get('foo'), None) + with self.assertRaises(KeyError): + z[123] = n + with self.assertRaises(KeyError): + z['foo.'] = n + with self.assertRaises(KeyError): + bn = z.find_node('bar') + bn = z.find_node('bar', True) + self.assertTrue(isinstance(bn, dns.node.Node)) + # The next two tests pass by not raising KeyError + z.delete_node('foo') + z.delete_node('bar') + + def testBadReplacement(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + rds = dns.rdataset.from_text('CH', 'TXT', 300, 'hi') + def bad(): + z.replace_rdataset('foo', rds) + self.assertRaises(ValueError, bad) + + def testTTLs(self): + z = dns.zone.from_text(ttl_example_text, 'example.', relativize=True) + n = z['@'] # type: dns.node.Node + rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA)) + self.assertEqual(rds.ttl, 3600) + n = z['ns1'] + rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A)) + self.assertEqual(rds.ttl, 86401) + n = z['ns2'] + rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A)) + self.assertEqual(rds.ttl, 694861) + + def testTTLFromSOA(self): + z = dns.zone.from_text(ttl_from_soa_text, 'example.', relativize=True) + n = z['@'] + rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA)) + self.assertEqual(rds.ttl, 3600) + soa_rd = rds[0] + n = z['ns1'] + rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A)) + self.assertEqual(rds.ttl, 694861) + n = z['ns2'] + rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A)) + self.assertEqual(rds.ttl, soa_rd.minimum) + + def testTTLFromLast(self): + z = dns.zone.from_text(ttl_from_last_text, 'example.', check_origin=False) + n = z['@'] + rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.NS)) + self.assertEqual(rds.ttl, 3600) + n = z['ns1'] + rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A)) + self.assertEqual(rds.ttl, 3600) + n = z['ns2'] + rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A)) + self.assertEqual(rds.ttl, 694861) + + def testNoTTL(self): + def bad(): + dns.zone.from_text(no_ttl_text, 'example.', check_origin=False) + self.assertRaises(dns.exception.SyntaxError, bad) + + def testNoSOA(self): + def bad(): + dns.zone.from_text(no_soa_text, 'example.', relativize=True) + self.assertRaises(dns.zone.NoSOA, bad) + + def testNoNS(self): + def bad(): + dns.zone.from_text(no_ns_text, 'example.', relativize=True) + self.assertRaises(dns.zone.NoNS, bad) + + def testInclude(self): + z1 = dns.zone.from_text(include_text, 'example.', relativize=True, + allow_include=True) + z2 = dns.zone.from_file(here('example'), 'example.', relativize=True) + self.assertEqual(z1, z2) + + def testBadDirective(self): + def bad(): + dns.zone.from_text(bad_directive_text, 'example.', relativize=True) + self.assertRaises(dns.exception.SyntaxError, bad) + + def testFirstRRStartsWithWhitespace(self): + # no name is specified, so default to the initial origin + z = dns.zone.from_text(' 300 IN A 10.0.0.1', origin='example.', + check_origin=False) + n = z['@'] + rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A)) + self.assertEqual(rds.ttl, 300) + + def testZoneOrigin(self): + z = dns.zone.Zone('example.') + self.assertEqual(z.origin, dns.name.from_text('example.')) + def bad1(): + o = dns.name.from_text('example', None) + dns.zone.Zone(o) + self.assertRaises(ValueError, bad1) + def bad2(): + dns.zone.Zone(cast(str, 1.0)) + self.assertRaises(ValueError, bad2) + + def testZoneOriginNone(self): + dns.zone.Zone(cast(str, None)) + + def testZoneFromXFR(self): + z1_abs = dns.zone.from_text(example_text, 'example.', relativize=False) + z2_abs = dns.zone.from_xfr(make_xfr(z1_abs), relativize=False) + self.assertEqual(z1_abs, z2_abs) + + z1_rel = dns.zone.from_text(example_text, 'example.', relativize=True) + z2_rel = dns.zone.from_xfr(make_xfr(z1_rel), relativize=True) + self.assertEqual(z1_rel, z2_rel) + + def testCodec2003(self): + z = dns.zone.from_text(codec_text, 'example.', relativize=True) + n2003 = dns.name.from_text('xn--knigsgsschen-lcb0w', None) + n2008 = dns.name.from_text('xn--knigsgchen-b4a3dun', None) + self.assertTrue(n2003 in z) + self.assertFalse(n2008 in z) + rrs = z.find_rrset(n2003, 'NS') + self.assertEqual(rrs[0].target, n2003) + + @unittest.skipUnless(dns.name.have_idna_2008, + 'Python idna cannot be imported; no IDNA2008') + def testCodec2008(self): + z = dns.zone.from_text(codec_text, 'example.', relativize=True, + idna_codec=dns.name.IDNA_2008) + n2003 = dns.name.from_text('xn--knigsgsschen-lcb0w', None) + n2008 = dns.name.from_text('xn--knigsgchen-b4a3dun', None) + self.assertFalse(n2003 in z) + self.assertTrue(n2008 in z) + rrs = z.find_rrset(n2008, 'NS') + self.assertEqual(rrs[0].target, n2008) + + def testZoneMiscCases(self): + # test that leading whitespace folllowed by EOL is treated like + # a blank line, and that out-of-zone names are dropped. + z1 = dns.zone.from_text(misc_cases_input, 'example.') + z2 = dns.zone.from_text(misc_cases_expected, 'example.') + self.assertEqual(z1, z2) + + def testUnknownOrigin(self): + def bad(): + dns.zone.from_text('foo 300 in a 10.0.0.1') + self.assertRaises(dns.zone.UnknownOrigin, bad) + + def testBadClass(self): + def bad(): + dns.zone.from_text('foo 300 ch txt hi', 'example.') + self.assertRaises(dns.exception.SyntaxError, bad) + + def testUnknownRdatatype(self): + def bad(): + dns.zone.from_text('foo 300 BOGUSTYPE hi', 'example.') + self.assertRaises(dns.exception.SyntaxError, bad) + + def testDangling(self): + def bad1(): + dns.zone.from_text('foo', 'example.') + self.assertRaises(dns.exception.SyntaxError, bad1) + def bad2(): + dns.zone.from_text('foo 300', 'example.') + self.assertRaises(dns.exception.SyntaxError, bad2) + def bad3(): + dns.zone.from_text('foo 300 in', 'example.') + self.assertRaises(dns.exception.SyntaxError, bad3) + def bad4(): + dns.zone.from_text('foo 300 in a', 'example.') + self.assertRaises(dns.exception.SyntaxError, bad4) + def bad5(): + dns.zone.from_text('$TTL', 'example.') + self.assertRaises(dns.exception.SyntaxError, bad5) + def bad6(): + dns.zone.from_text('$ORIGIN', 'example.') + self.assertRaises(dns.exception.SyntaxError, bad6) + + def testUseLastTTL(self): + z = dns.zone.from_text(last_ttl_input, 'example.') + rds = z.find_rdataset('foo', 'A') + self.assertEqual(rds.ttl, 300) + + def testDollarOriginSetsZoneOriginIfUnknown(self): + z = dns.zone.from_text(origin_sets_input) + self.assertEqual(z.origin, dns.name.from_text('example')) + + def testValidateNameRelativizesNameInZone(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + self.assertEqual(z._validate_name('foo.bar.example.'), + dns.name.from_text('foo.bar', None)) + + def testComments(self): + z = dns.zone.from_text(example_comments_text, 'example.', + relativize=True) + f = StringIO() + z.to_file(f, want_comments=True) + out = f.getvalue() + f.close() + self.assertEqual(out, example_comments_text_output) + + def testUncomparable(self): + z = dns.zone.from_text(example_comments_text, 'example.', + relativize=True) + self.assertFalse(z == 'a') + + def testUnsorted(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True) + f = StringIO() + z.to_file(f, sorted=False) + out = f.getvalue() + f.close() + z2 = dns.zone.from_text(out, 'example.', relativize=True) + self.assertEqual(z, z2) + + def testNodeReplaceRdatasetConvertsRRsets(self): + node = dns.node.Node() + rrs = dns.rrset.from_text('foo', 300, 'in', 'a', '10.0.0.1') + node.replace_rdataset(rrs) + rds = node.find_rdataset(dns.rdataclass.IN, dns.rdatatype.A) + self.assertEqual(rds, rrs) + self.assertTrue(rds is not rrs) + self.assertFalse(isinstance(rds, dns.rrset.RRset)) + + +class VersionedZoneTestCase(unittest.TestCase): + def testUseTransaction(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True, + zone_factory=dns.versioned.Zone) + with self.assertRaises(dns.versioned.UseTransaction): + z.find_node('not_there', True) + with self.assertRaises(dns.versioned.UseTransaction): + z.delete_node('not_there') + with self.assertRaises(dns.versioned.UseTransaction): + z.find_rdataset('not_there', 'a', create=True) + with self.assertRaises(dns.versioned.UseTransaction): + z.get_rdataset('not_there', 'a', create=True) + with self.assertRaises(dns.versioned.UseTransaction): + z.delete_rdataset('not_there', 'a') + with self.assertRaises(dns.versioned.UseTransaction): + z.replace_rdataset('not_there', None) + + def testImmutableNodes(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True, + zone_factory=dns.versioned.Zone) + node = z.find_node('@') + with self.assertRaises(TypeError): + node.find_rdataset(dns.rdataclass.IN, dns.rdatatype.RP, + create=True) + with self.assertRaises(TypeError): + node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.RP, + create=True) + with self.assertRaises(TypeError): + node.delete_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA) + with self.assertRaises(TypeError): + node.replace_rdataset(None) + + def testSelectDefaultPruningPolicy(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True, + zone_factory=dns.versioned.Zone) + z.set_pruning_policy(None) + self.assertEqual(z._pruning_policy, z._default_pruning_policy) + + def testSetAlternatePruningPolicyInConstructor(self): + def never_prune(version): + return False + z = dns.versioned.Zone('example', pruning_policy=never_prune) + self.assertEqual(z._pruning_policy, never_prune) + + def testCannotSpecifyBothSerialAndVersionIdToReader(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True, + zone_factory=dns.versioned.Zone) + with self.assertRaises(ValueError): + z.reader(1, 1) + + def testUnknownVersion(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True, + zone_factory=dns.versioned.Zone) + with self.assertRaises(KeyError): + z.reader(99999) + + def testUnknownSerial(self): + z = dns.zone.from_text(example_text, 'example.', relativize=True, + zone_factory=dns.versioned.Zone) + with self.assertRaises(KeyError): + z.reader(serial=99999) + + def testNoRelativizeReader(self): + z = dns.zone.from_text(example_text, 'example.', relativize=False, + zone_factory=dns.versioned.Zone) + with z.reader(serial=1) as txn: + rds = txn.get('example.', 'soa') + self.assertEqual(rds[0].serial, 1) + +if __name__ == '__main__': + unittest.main() diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/ttxt_module.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/ttxt_module.py new file mode 100644 index 0000000..c66131b --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/ttxt_module.py @@ -0,0 +1,4 @@ +import dns.rdtypes.txtbase + +class TTXT(dns.rdtypes.txtbase.TXTBase): + """Test TXT-like record""" diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/utest.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/utest.py new file mode 100644 index 0000000..20f8e18 --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/utest.py @@ -0,0 +1,13 @@ +import os.path +import sys +import unittest + +if __name__ == '__main__': + sys.path.insert(0, os.path.realpath('..')) + if len(sys.argv) > 1: + pattern = sys.argv[1] + else: + pattern = 'test*.py' + suites = unittest.defaultTestLoader.discover('.', pattern) + if not unittest.TextTestRunner(verbosity=2).run(suites).wasSuccessful(): + sys.exit(1) diff --git a/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/util.py b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/util.py new file mode 100644 index 0000000..644a88a --- /dev/null +++ b/NSICollectionPlatformServer/packages/dnspython-2.1.0/tests/util.py @@ -0,0 +1,40 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import enum +import inspect +import os.path + +def here(filename): + return os.path.join(os.path.dirname(__file__), filename) + +def enumerate_module(module, super_class): + """Yield module attributes which are subclasses of given class""" + for attr_name in dir(module): + attr = getattr(module, attr_name) + if inspect.isclass(attr) and issubclass(attr, super_class): + yield attr + +def check_enum_exports(module, eq_callback, only=None): + """Make sure module exports all mnemonics from enums""" + for attr in enumerate_module(module, enum.Enum): + if only is not None and attr not in only: + print('SKIP', attr) + continue + for flag, value in attr.__members__.items(): + print(module, flag, value) + eq_callback(getattr(module, flag), value) diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar.gz b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar.gz new file mode 100644 index 0000000..f6c92f6 Binary files /dev/null and b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar.gz differ diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11.tar b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11.tar new file mode 100644 index 0000000..b95db06 Binary files /dev/null and b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11.tar differ diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/LICENSE b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/LICENSE new file mode 100644 index 0000000..5cd5268 --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright (c) hellysmile@gmail.com + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/MANIFEST.in b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/MANIFEST.in new file mode 100644 index 0000000..e24206f --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/MANIFEST.in @@ -0,0 +1,4 @@ +include README.rst +include LICENSE +recursive-exclude * __pycache__ +recursive-exclude * *.py[co] diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/PKG-INFO b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/PKG-INFO new file mode 100644 index 0000000..e9bef0b --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/PKG-INFO @@ -0,0 +1,268 @@ +Metadata-Version: 1.1 +Name: fake-useragent +Version: 0.1.11 +Summary: Up to date simple useragent faker with real world database +Home-page: https://github.com/hellysmile/fake-useragent +Author: hellysmile@gmail.com +Author-email: hellysmile@gmail.com +License: UNKNOWN +Description: fake-useragent + ============== + + :info: Up to date simple useragent faker with real world database + + .. image:: https://img.shields.io/travis/hellysmile/fake-useragent.svg + :target: https://travis-ci.org/hellysmile/fake-useragent + + .. image:: https://codecov.io/gh/hellysmile/fake-useragent/branch/master/graph/badge.svg + :target: https://codecov.io/gh/hellysmile/fake-useragent + + .. image:: https://landscape.io/github/hellysmile/fake-useragent/master/landscape.svg?style=flat + :target: https://landscape.io/github/hellysmile/fake-useragent/master + + .. image:: https://img.shields.io/pypi/v/fake-useragent.svg + :target: https://pypi.python.org/pypi/fake-useragent + + Features + ******** + + * grabs up to date ``useragent`` from `useragentstring.com `_ + * randomize with real world statistic via `w3schools.com `_ + + Installation + ------------ + + .. code-block:: shell + + pip install fake-useragent + + Usage + ----- + + .. code-block:: python + + from fake_useragent import UserAgent + ua = UserAgent() + + ua.ie + # Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US); + ua.msie + # Mozilla/5.0 (compatible; MSIE 10.0; Macintosh; Intel Mac OS X 10_7_3; Trident/6.0)' + ua['Internet Explorer'] + # Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.4; InfoPath.2; SV1; .NET CLR 3.3.69573; WOW64; en-US) + ua.opera + # Opera/9.80 (X11; Linux i686; U; ru) Presto/2.8.131 Version/11.11 + ua.chrome + # Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.2 (KHTML, like Gecko) Chrome/22.0.1216.0 Safari/537.2' + ua.google + # Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/537.13 (KHTML, like Gecko) Chrome/24.0.1290.1 Safari/537.13 + ua['google chrome'] + # Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11 + ua.firefox + # Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:16.0.1) Gecko/20121011 Firefox/16.0.1 + ua.ff + # Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:15.0) Gecko/20100101 Firefox/15.0.1 + ua.safari + # Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25 + + # and the best one, random via real world browser usage statistic + ua.random + + Notes + ----- + + ``fake-useragent`` store collected data at your os temp dir, like ``/tmp`` + + If You want to update saved database just: + + .. code-block:: python + + from fake_useragent import UserAgent + ua = UserAgent() + ua.update() + + If You don't want cache database or no writable file system: + + .. code-block:: python + + from fake_useragent import UserAgent + ua = UserAgent(cache=False) + + Sometimes, `useragentstring.com `_ or `w3schools.com `_ changes their html, or down, in such case + ``fake-useragent`` uses `heroku `_ fallback + + If You don't want to use hosted cache server (version 0.1.5 added) + + .. code-block:: python + + from fake_useragent import UserAgent + ua = UserAgent(use_cache_server=False) + + In very rare case, if hosted cache server and sources will be + unavailable ``fake-useragent`` wont be able to download data: (version 0.1.3 added) + + .. code-block:: python + + from fake_useragent import UserAgent + ua = UserAgent() + + # Traceback (most recent call last): + # ... + # fake_useragent.errors.FakeUserAgentError + + # You can catch it via + + from fake_useragent import FakeUserAgentError + + try: + ua = UserAgent() + except FakeUserAgentError: + pass + + If You will try to get unknown browser: (version 0.1.3 changed) + + .. code-block:: python + + from fake_useragent import UserAgent + ua = UserAgent() + ua.best_browser + # Traceback (most recent call last): + # ... + # fake_useragent.errors.FakeUserAgentError + + You can completely disable ANY annoying exception with adding ``fallback``: (version 0.1.4 added) + + .. code-block:: python + + import fake_useragent + + ua = fake_useragent.UserAgent(fallback='Your favorite Browser') + # in case if something went wrong, one more time it is REALLY!!! rare case + ua.random == 'Your favorite Browser' + + Want to control location of data file? (version 0.1.4 added) + + .. code-block:: python + + import fake_useragent + + # I am STRONGLY!!! recommend to use version suffix + location = '/home/user/fake_useragent%s.json' % fake_useragent.VERSION + + ua = fake_useragent.UserAgent(path=location) + ua.random + + If you need to safe some attributes from overriding them in UserAgent by ``__getattr__`` method + use ``safe_attrs`` you can pass there attributes names. + At least this will prevent you from raising FakeUserAgentError when attribute not found. + + For example, when using fake_useragent with `injections `_ you need to: + + .. code-block:: python + + import fake_useragent + + ua = fake_useragent.UserAgent(safe_attrs=('__injections__',)) + + Please, do not use if you don't understand why you need this. + This is magic for rarely extreme case. + + Experiencing issues??? + ---------------------- + + Make sure that You using latest version!!! + + .. code-block:: shell + + pip install -U fake-useragent + + Check version via python console: (version 0.1.4 added) + + .. code-block:: python + + import fake_useragent + + print(fake_useragent.VERSION) + + And You are always welcome to post `issues `_ + + Please do not forget mention version that You are using + + Tests + ----- + + .. code-block:: console + + pip install tox + tox + + Changelog + --------- + + * 0.1.11 October 4, 2018 + - moved `s3 + cloudfront` fallback to `heroku.com`, cuz someone from Florida did ~25M requests last month + + * 0.1.10 February 11, 2018 + - Minor fix docs `cloudfront` url + + * 0.1.9 February 11, 2018 + - fix ``w3schools.com`` renamed `IE/Edge` to `Edge/IE` + - moved `heroku.com` fallback to `s3 + cloudfront` + - stop testing Python3.3 and pypy + + * 0.1.8 November 2, 2017 + - fix ``useragentstring.com`` ``Can't connect to local MySQL server through socket`` + + * 0.1.7 April 2, 2017 + - fix broken README.rst + + * 0.1.6 April 2, 2017 + - fixes bug ``use_cache_server`` do not affected anything + - `w3schools.com `_ moved to ``https`` + - ``verify_ssl`` options added, by default it is ``True`` (``urllib.urlopen`` ssl context for Python 2.7.9- and 3.4.3- is not supported) + + * 0.1.5 February 28, 2017 + - added ``ua.edge`` alias to Internet Explorer + - w3schools.com starts displaying ``Edge`` statistic + - Python 2.6 is not tested anymore + - ``use_cache_server`` option added + - Increased ``fake_useragent.settings.HTTP_TIMEOUT`` to 5 seconds + + * 0.1.4 December 14, 2016 + - Added custom data file location support + - Added ``fallback`` browser support, in case of unavailable data sources + - Added alias ``fake_useragent.FakeUserAgent`` for ``fake_useragent.UserAgent`` + - Added alias ``fake_useragent.UserAgentError`` for ``fake_useragent.FakeUserAgentError`` + - Reduced ``fake_useragent.settings.HTTP_TIMEOUT`` to 3 seconds + - Started migration to new data file format + - Simplified a lot 4+ years out of date code + - Better thread/greenlet safety + - Added verbose logging + - Added ``safe_attrs`` for prevent overriding by ``__getattr__`` + + * 0.1.3 November 24, 2016 + - Added hosted data file, when remote services is unavailable + - Raises ``fake_useragent.errors.FakeUserAgentError`` in case when there is not way to download data + - Raises ``fake_useragent.errors.FakeUserAgentError`` instead of ``None`` in case of unknown browser + - Added ``gevent.sleep`` support in ``gevent`` patched environment when trying to download data + + * X.X.X xxxxxxx xx, xxxx + - xxxxx ????? + + Authors + ------- + + You can visit `authors page `_ + +Keywords: user,agent,user agent,useragent,fake,fake useragent,fake user agent +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Operating System :: POSIX +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Operating System :: Microsoft :: Windows +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 3 +Classifier: Operating System :: OS Independent diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/README.rst b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/README.rst new file mode 100644 index 0000000..5b46b11 --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/README.rst @@ -0,0 +1,247 @@ +fake-useragent +============== + +:info: Up to date simple useragent faker with real world database + +.. image:: https://img.shields.io/travis/hellysmile/fake-useragent.svg + :target: https://travis-ci.org/hellysmile/fake-useragent + +.. image:: https://codecov.io/gh/hellysmile/fake-useragent/branch/master/graph/badge.svg + :target: https://codecov.io/gh/hellysmile/fake-useragent + +.. image:: https://landscape.io/github/hellysmile/fake-useragent/master/landscape.svg?style=flat + :target: https://landscape.io/github/hellysmile/fake-useragent/master + +.. image:: https://img.shields.io/pypi/v/fake-useragent.svg + :target: https://pypi.python.org/pypi/fake-useragent + +Features +******** + +* grabs up to date ``useragent`` from `useragentstring.com `_ +* randomize with real world statistic via `w3schools.com `_ + +Installation +------------ + +.. code-block:: shell + + pip install fake-useragent + +Usage +----- + +.. code-block:: python + + from fake_useragent import UserAgent + ua = UserAgent() + + ua.ie + # Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US); + ua.msie + # Mozilla/5.0 (compatible; MSIE 10.0; Macintosh; Intel Mac OS X 10_7_3; Trident/6.0)' + ua['Internet Explorer'] + # Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.4; InfoPath.2; SV1; .NET CLR 3.3.69573; WOW64; en-US) + ua.opera + # Opera/9.80 (X11; Linux i686; U; ru) Presto/2.8.131 Version/11.11 + ua.chrome + # Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.2 (KHTML, like Gecko) Chrome/22.0.1216.0 Safari/537.2' + ua.google + # Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/537.13 (KHTML, like Gecko) Chrome/24.0.1290.1 Safari/537.13 + ua['google chrome'] + # Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11 + ua.firefox + # Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:16.0.1) Gecko/20121011 Firefox/16.0.1 + ua.ff + # Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:15.0) Gecko/20100101 Firefox/15.0.1 + ua.safari + # Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25 + + # and the best one, random via real world browser usage statistic + ua.random + +Notes +----- + +``fake-useragent`` store collected data at your os temp dir, like ``/tmp`` + +If You want to update saved database just: + +.. code-block:: python + + from fake_useragent import UserAgent + ua = UserAgent() + ua.update() + +If You don't want cache database or no writable file system: + +.. code-block:: python + + from fake_useragent import UserAgent + ua = UserAgent(cache=False) + +Sometimes, `useragentstring.com `_ or `w3schools.com `_ changes their html, or down, in such case +``fake-useragent`` uses `heroku `_ fallback + +If You don't want to use hosted cache server (version 0.1.5 added) + +.. code-block:: python + + from fake_useragent import UserAgent + ua = UserAgent(use_cache_server=False) + +In very rare case, if hosted cache server and sources will be +unavailable ``fake-useragent`` wont be able to download data: (version 0.1.3 added) + +.. code-block:: python + + from fake_useragent import UserAgent + ua = UserAgent() + + # Traceback (most recent call last): + # ... + # fake_useragent.errors.FakeUserAgentError + + # You can catch it via + + from fake_useragent import FakeUserAgentError + + try: + ua = UserAgent() + except FakeUserAgentError: + pass + +If You will try to get unknown browser: (version 0.1.3 changed) + +.. code-block:: python + + from fake_useragent import UserAgent + ua = UserAgent() + ua.best_browser + # Traceback (most recent call last): + # ... + # fake_useragent.errors.FakeUserAgentError + +You can completely disable ANY annoying exception with adding ``fallback``: (version 0.1.4 added) + +.. code-block:: python + + import fake_useragent + + ua = fake_useragent.UserAgent(fallback='Your favorite Browser') + # in case if something went wrong, one more time it is REALLY!!! rare case + ua.random == 'Your favorite Browser' + +Want to control location of data file? (version 0.1.4 added) + +.. code-block:: python + + import fake_useragent + + # I am STRONGLY!!! recommend to use version suffix + location = '/home/user/fake_useragent%s.json' % fake_useragent.VERSION + + ua = fake_useragent.UserAgent(path=location) + ua.random + +If you need to safe some attributes from overriding them in UserAgent by ``__getattr__`` method +use ``safe_attrs`` you can pass there attributes names. +At least this will prevent you from raising FakeUserAgentError when attribute not found. + +For example, when using fake_useragent with `injections `_ you need to: + +.. code-block:: python + + import fake_useragent + + ua = fake_useragent.UserAgent(safe_attrs=('__injections__',)) + +Please, do not use if you don't understand why you need this. +This is magic for rarely extreme case. + +Experiencing issues??? +---------------------- + +Make sure that You using latest version!!! + +.. code-block:: shell + + pip install -U fake-useragent + +Check version via python console: (version 0.1.4 added) + +.. code-block:: python + + import fake_useragent + + print(fake_useragent.VERSION) + +And You are always welcome to post `issues `_ + +Please do not forget mention version that You are using + +Tests +----- + +.. code-block:: console + + pip install tox + tox + +Changelog +--------- + +* 0.1.11 October 4, 2018 + - moved `s3 + cloudfront` fallback to `heroku.com`, cuz someone from Florida did ~25M requests last month + +* 0.1.10 February 11, 2018 + - Minor fix docs `cloudfront` url + +* 0.1.9 February 11, 2018 + - fix ``w3schools.com`` renamed `IE/Edge` to `Edge/IE` + - moved `heroku.com` fallback to `s3 + cloudfront` + - stop testing Python3.3 and pypy + +* 0.1.8 November 2, 2017 + - fix ``useragentstring.com`` ``Can't connect to local MySQL server through socket`` + +* 0.1.7 April 2, 2017 + - fix broken README.rst + +* 0.1.6 April 2, 2017 + - fixes bug ``use_cache_server`` do not affected anything + - `w3schools.com `_ moved to ``https`` + - ``verify_ssl`` options added, by default it is ``True`` (``urllib.urlopen`` ssl context for Python 2.7.9- and 3.4.3- is not supported) + +* 0.1.5 February 28, 2017 + - added ``ua.edge`` alias to Internet Explorer + - w3schools.com starts displaying ``Edge`` statistic + - Python 2.6 is not tested anymore + - ``use_cache_server`` option added + - Increased ``fake_useragent.settings.HTTP_TIMEOUT`` to 5 seconds + +* 0.1.4 December 14, 2016 + - Added custom data file location support + - Added ``fallback`` browser support, in case of unavailable data sources + - Added alias ``fake_useragent.FakeUserAgent`` for ``fake_useragent.UserAgent`` + - Added alias ``fake_useragent.UserAgentError`` for ``fake_useragent.FakeUserAgentError`` + - Reduced ``fake_useragent.settings.HTTP_TIMEOUT`` to 3 seconds + - Started migration to new data file format + - Simplified a lot 4+ years out of date code + - Better thread/greenlet safety + - Added verbose logging + - Added ``safe_attrs`` for prevent overriding by ``__getattr__`` + +* 0.1.3 November 24, 2016 + - Added hosted data file, when remote services is unavailable + - Raises ``fake_useragent.errors.FakeUserAgentError`` in case when there is not way to download data + - Raises ``fake_useragent.errors.FakeUserAgentError`` instead of ``None`` in case of unknown browser + - Added ``gevent.sleep`` support in ``gevent`` patched environment when trying to download data + +* X.X.X xxxxxxx xx, xxxx + - xxxxx ????? + +Authors +------- + +You can visit `authors page `_ diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/build/lib/fake_useragent/__init__.py b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/build/lib/fake_useragent/__init__.py new file mode 100644 index 0000000..2a54f0a --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/build/lib/fake_useragent/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + +from fake_useragent.fake import FakeUserAgent, UserAgent # noqa # isort:skip +from fake_useragent.errors import FakeUserAgentError, UserAgentError # noqa # isort:skip +from fake_useragent.settings import __version__ as VERSION # noqa # isort:skip diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/build/lib/fake_useragent/errors.py b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/build/lib/fake_useragent/errors.py new file mode 100644 index 0000000..34f2c3e --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/build/lib/fake_useragent/errors.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + + +class FakeUserAgentError(Exception): + pass + + +# common alias +UserAgentError = FakeUserAgentError diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/build/lib/fake_useragent/fake.py b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/build/lib/fake_useragent/fake.py new file mode 100644 index 0000000..224f8c1 --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/build/lib/fake_useragent/fake.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + +import random +from threading import Lock + +from fake_useragent import settings +from fake_useragent.errors import FakeUserAgentError +from fake_useragent.log import logger +from fake_useragent.utils import load, load_cached, str_types, update + + +class FakeUserAgent(object): + def __init__( + self, + cache=True, + use_cache_server=True, + path=settings.DB, + fallback=None, + verify_ssl=True, + safe_attrs=tuple(), + ): + assert isinstance(cache, bool), \ + 'cache must be True or False' + + self.cache = cache + + assert isinstance(use_cache_server, bool), \ + 'use_cache_server must be True or False' + + self.use_cache_server = use_cache_server + + assert isinstance(path, str_types), \ + 'path must be string or unicode' + + self.path = path + + if fallback is not None: + assert isinstance(fallback, str_types), \ + 'fallback must be string or unicode' + + self.fallback = fallback + + assert isinstance(verify_ssl, bool), \ + 'verify_ssl must be True or False' + + self.verify_ssl = verify_ssl + + assert isinstance(safe_attrs, (list, set, tuple)), \ + 'safe_attrs must be list\\tuple\\set of strings or unicode' + + if safe_attrs: + str_types_safe_attrs = [ + isinstance(attr, str_types) for attr in safe_attrs + ] + + assert all(str_types_safe_attrs), \ + 'safe_attrs must be list\\tuple\\set of strings or unicode' + + self.safe_attrs = set(safe_attrs) + + # initial empty data + self.data = {} + # TODO: change source file format + # version 0.1.4+ migration tool + self.data_randomize = [] + self.data_browsers = {} + + self.load() + + def load(self): + try: + with self.load.lock: + if self.cache: + self.data = load_cached( + self.path, + use_cache_server=self.use_cache_server, + verify_ssl=self.verify_ssl, + ) + else: + self.data = load( + use_cache_server=self.use_cache_server, + verify_ssl=self.verify_ssl, + ) + + # TODO: change source file format + # version 0.1.4+ migration tool + self.data_randomize = list(self.data['randomize'].values()) + self.data_browsers = self.data['browsers'] + except FakeUserAgentError: + if self.fallback is None: + raise + else: + logger.warning( + 'Error occurred during fetching data, ' + 'but was suppressed with fallback.', + ) + load.lock = Lock() + + def update(self, cache=None): + with self.update.lock: + if cache is not None: + assert isinstance(cache, bool), \ + 'cache must be True or False' + + self.cache = cache + + if self.cache: + update( + self.path, + use_cache_server=self.use_cache_server, + verify_ssl=self.verify_ssl, + ) + + self.load() + update.lock = Lock() + + def __getitem__(self, attr): + return self.__getattr__(attr) + + def __getattr__(self, attr): + if attr in self.safe_attrs: + return super(UserAgent, self).__getattr__(attr) + + try: + for value, replacement in settings.REPLACEMENTS.items(): + attr = attr.replace(value, replacement) + + attr = attr.lower() + + if attr == 'random': + browser = random.choice(self.data_randomize) + else: + browser = settings.SHORTCUTS.get(attr, attr) + + return random.choice(self.data_browsers[browser]) + except (KeyError, IndexError): + if self.fallback is None: + raise FakeUserAgentError('Error occurred during getting browser') # noqa + else: + logger.warning( + 'Error occurred during getting browser, ' + 'but was suppressed with fallback.', + ) + + return self.fallback + + +# common alias +UserAgent = FakeUserAgent diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/build/lib/fake_useragent/log.py b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/build/lib/fake_useragent/log.py new file mode 100644 index 0000000..5d46773 --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/build/lib/fake_useragent/log.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + +import logging + +logger = logging.getLogger(__package__) diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/build/lib/fake_useragent/settings.py b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/build/lib/fake_useragent/settings.py new file mode 100644 index 0000000..098f578 --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/build/lib/fake_useragent/settings.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + +import os +import tempfile + +__version__ = '0.1.11' + +DB = os.path.join( + tempfile.gettempdir(), + 'fake_useragent_{version}.json'.format( + version=__version__, + ), +) + +CACHE_SERVER = 'https://fake-useragent.herokuapp.com/browsers/{version}'.format( + version=__version__, +) + +BROWSERS_STATS_PAGE = 'https://www.w3schools.com/browsers/default.asp' + +BROWSER_BASE_PAGE = 'http://useragentstring.com/pages/useragentstring.php?name={browser}' # noqa + +BROWSERS_COUNT_LIMIT = 50 + +REPLACEMENTS = { + ' ': '', + '_': '', +} + +SHORTCUTS = { + 'internet explorer': 'internetexplorer', + 'ie': 'internetexplorer', + 'msie': 'internetexplorer', + 'edge': 'internetexplorer', + 'google': 'chrome', + 'googlechrome': 'chrome', + 'ff': 'firefox', +} + +OVERRIDES = { + 'Edge/IE': 'Internet Explorer', + 'IE/Edge': 'Internet Explorer', +} + +HTTP_TIMEOUT = 5 + +HTTP_RETRIES = 2 + +HTTP_DELAY = 0.1 diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/build/lib/fake_useragent/utils.py b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/build/lib/fake_useragent/utils.py new file mode 100644 index 0000000..e1a38f2 --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/build/lib/fake_useragent/utils.py @@ -0,0 +1,256 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + +import contextlib +import inspect +import io +import json +import os +import re +import ssl + +from fake_useragent.log import logger + +try: # Python 2 # pragma: no cover + from urllib2 import urlopen, Request, URLError + from urllib import quote_plus + + str_types = (unicode, str) # noqa + text = unicode # noqa +except ImportError: # Python 3 # pragma: no cover + from urllib.request import urlopen, Request + from urllib.parse import quote_plus + from urllib.error import URLError + + str_types = (str,) + text = str + +# gevent monkey patched environment check +try: # pragma: no cover + import socket + import gevent.socket + + if socket.socket is gevent.socket.socket: + from gevent import sleep + else: + from time import sleep +except (ImportError, AttributeError): # pragma: no cover + from time import sleep + + +try: + urlopen_args = inspect.getfullargspec(urlopen).kwonlyargs +except AttributeError: + urlopen_args = inspect.getargspec(urlopen).args + +urlopen_has_ssl_context = 'context' in urlopen_args + + +def get(url, verify_ssl=True): + attempt = 0 + + while True: + request = Request(url) + + attempt += 1 + + try: + if urlopen_has_ssl_context: + if not verify_ssl: + context = ssl._create_unverified_context() + else: + context = None + + with contextlib.closing(urlopen( + request, + timeout=settings.HTTP_TIMEOUT, + context=context, + )) as response: + return response.read() + else: # ssl context is not supported ;( + with contextlib.closing(urlopen( + request, + timeout=settings.HTTP_TIMEOUT, + )) as response: + return response.read() + except (URLError, OSError) as exc: + logger.debug( + 'Error occurred during fetching %s', + url, + exc_info=exc, + ) + + if attempt == settings.HTTP_RETRIES: + raise FakeUserAgentError('Maximum amount of retries reached') + else: + logger.debug( + 'Sleeping for %s seconds', + settings.HTTP_DELAY, + ) + sleep(settings.HTTP_DELAY) + + +def get_browsers(verify_ssl=True): + """ + very very hardcoded/dirty re/split stuff, but no dependencies + """ + html = get(settings.BROWSERS_STATS_PAGE, verify_ssl=verify_ssl) + html = html.decode('utf-8') + html = html.split('')[1] + html = html.split('
')[0] + + pattern = r'\.asp">(.+?)<' + browsers = re.findall(pattern, html, re.UNICODE) + + browsers = [ + settings.OVERRIDES.get(browser, browser) + for browser in browsers + ] + + pattern = r'td\sclass="right">(.+?)\s' + browsers_statistics = re.findall(pattern, html, re.UNICODE) + + return list(zip(browsers, browsers_statistics)) + + +def get_browser_versions(browser, verify_ssl=True): + """ + very very hardcoded/dirty re/split stuff, but no dependencies + """ + html = get( + settings.BROWSER_BASE_PAGE.format(browser=quote_plus(browser)), + verify_ssl=verify_ssl, + ) + html = html.decode('iso-8859-1') + html = html.split('
')[1] + html = html.split('
')[0] + + pattern = r'\?id=\d+\'>(.+?), 'firefox': ''} + for _ in range(int(float(percent) * 10)): + randomize_dict[str(len(randomize_dict))] = browser_key + except Exception as exc: + if not use_cache_server: + raise exc + + logger.warning( + 'Error occurred during loading data. ' + 'Trying to use cache server %s', + settings.CACHE_SERVER, + exc_info=exc, + ) + try: + ret = json.loads(get( + settings.CACHE_SERVER, + verify_ssl=verify_ssl, + ).decode('utf-8')) + except (TypeError, ValueError): + raise FakeUserAgentError('Can not load data from cache server') + else: + ret = { + 'browsers': browsers_dict, + 'randomize': randomize_dict, + } + + if not isinstance(ret, dict): + raise FakeUserAgentError('Data is not dictionary ', ret) + + for param in ['browsers', 'randomize']: + if param not in ret: + raise FakeUserAgentError('Missing data param: ', param) + + if not isinstance(ret[param], dict): + raise FakeUserAgentError('Data param is not dictionary', ret[param]) # noqa + + if not ret[param]: + raise FakeUserAgentError('Data param is empty', ret[param]) + + return ret + + +# TODO: drop these useless functions + + +def write(path, data): + with io.open(path, encoding='utf-8', mode='wt') as fp: + dumped = json.dumps(data) + + if not isinstance(dumped, text): # Python 2 + dumped = dumped.decode('utf-8') + + fp.write(dumped) + + +def read(path): + with io.open(path, encoding='utf-8', mode='rt') as fp: + return json.loads(fp.read()) + + +def exist(path): + return os.path.isfile(path) + + +def rm(path): + if exist(path): + os.remove(path) + + +def update(path, use_cache_server=True, verify_ssl=True): + rm(path) + + write(path, load(use_cache_server=use_cache_server, verify_ssl=verify_ssl)) + + +def load_cached(path, use_cache_server=True, verify_ssl=True): + if not exist(path): + update(path, use_cache_server=use_cache_server, verify_ssl=verify_ssl) + + return read(path) + + +from fake_useragent import settings # noqa # isort:skip +from fake_useragent.errors import FakeUserAgentError # noqa # isort:skip diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/dist/fake_useragent-0.1.11-py3.9.egg b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/dist/fake_useragent-0.1.11-py3.9.egg new file mode 100644 index 0000000..302ebbc Binary files /dev/null and b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/dist/fake_useragent-0.1.11-py3.9.egg differ diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent.egg-info/PKG-INFO b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent.egg-info/PKG-INFO new file mode 100644 index 0000000..e9bef0b --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent.egg-info/PKG-INFO @@ -0,0 +1,268 @@ +Metadata-Version: 1.1 +Name: fake-useragent +Version: 0.1.11 +Summary: Up to date simple useragent faker with real world database +Home-page: https://github.com/hellysmile/fake-useragent +Author: hellysmile@gmail.com +Author-email: hellysmile@gmail.com +License: UNKNOWN +Description: fake-useragent + ============== + + :info: Up to date simple useragent faker with real world database + + .. image:: https://img.shields.io/travis/hellysmile/fake-useragent.svg + :target: https://travis-ci.org/hellysmile/fake-useragent + + .. image:: https://codecov.io/gh/hellysmile/fake-useragent/branch/master/graph/badge.svg + :target: https://codecov.io/gh/hellysmile/fake-useragent + + .. image:: https://landscape.io/github/hellysmile/fake-useragent/master/landscape.svg?style=flat + :target: https://landscape.io/github/hellysmile/fake-useragent/master + + .. image:: https://img.shields.io/pypi/v/fake-useragent.svg + :target: https://pypi.python.org/pypi/fake-useragent + + Features + ******** + + * grabs up to date ``useragent`` from `useragentstring.com `_ + * randomize with real world statistic via `w3schools.com `_ + + Installation + ------------ + + .. code-block:: shell + + pip install fake-useragent + + Usage + ----- + + .. code-block:: python + + from fake_useragent import UserAgent + ua = UserAgent() + + ua.ie + # Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US); + ua.msie + # Mozilla/5.0 (compatible; MSIE 10.0; Macintosh; Intel Mac OS X 10_7_3; Trident/6.0)' + ua['Internet Explorer'] + # Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.4; InfoPath.2; SV1; .NET CLR 3.3.69573; WOW64; en-US) + ua.opera + # Opera/9.80 (X11; Linux i686; U; ru) Presto/2.8.131 Version/11.11 + ua.chrome + # Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.2 (KHTML, like Gecko) Chrome/22.0.1216.0 Safari/537.2' + ua.google + # Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/537.13 (KHTML, like Gecko) Chrome/24.0.1290.1 Safari/537.13 + ua['google chrome'] + # Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11 + ua.firefox + # Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:16.0.1) Gecko/20121011 Firefox/16.0.1 + ua.ff + # Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:15.0) Gecko/20100101 Firefox/15.0.1 + ua.safari + # Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25 + + # and the best one, random via real world browser usage statistic + ua.random + + Notes + ----- + + ``fake-useragent`` store collected data at your os temp dir, like ``/tmp`` + + If You want to update saved database just: + + .. code-block:: python + + from fake_useragent import UserAgent + ua = UserAgent() + ua.update() + + If You don't want cache database or no writable file system: + + .. code-block:: python + + from fake_useragent import UserAgent + ua = UserAgent(cache=False) + + Sometimes, `useragentstring.com `_ or `w3schools.com `_ changes their html, or down, in such case + ``fake-useragent`` uses `heroku `_ fallback + + If You don't want to use hosted cache server (version 0.1.5 added) + + .. code-block:: python + + from fake_useragent import UserAgent + ua = UserAgent(use_cache_server=False) + + In very rare case, if hosted cache server and sources will be + unavailable ``fake-useragent`` wont be able to download data: (version 0.1.3 added) + + .. code-block:: python + + from fake_useragent import UserAgent + ua = UserAgent() + + # Traceback (most recent call last): + # ... + # fake_useragent.errors.FakeUserAgentError + + # You can catch it via + + from fake_useragent import FakeUserAgentError + + try: + ua = UserAgent() + except FakeUserAgentError: + pass + + If You will try to get unknown browser: (version 0.1.3 changed) + + .. code-block:: python + + from fake_useragent import UserAgent + ua = UserAgent() + ua.best_browser + # Traceback (most recent call last): + # ... + # fake_useragent.errors.FakeUserAgentError + + You can completely disable ANY annoying exception with adding ``fallback``: (version 0.1.4 added) + + .. code-block:: python + + import fake_useragent + + ua = fake_useragent.UserAgent(fallback='Your favorite Browser') + # in case if something went wrong, one more time it is REALLY!!! rare case + ua.random == 'Your favorite Browser' + + Want to control location of data file? (version 0.1.4 added) + + .. code-block:: python + + import fake_useragent + + # I am STRONGLY!!! recommend to use version suffix + location = '/home/user/fake_useragent%s.json' % fake_useragent.VERSION + + ua = fake_useragent.UserAgent(path=location) + ua.random + + If you need to safe some attributes from overriding them in UserAgent by ``__getattr__`` method + use ``safe_attrs`` you can pass there attributes names. + At least this will prevent you from raising FakeUserAgentError when attribute not found. + + For example, when using fake_useragent with `injections `_ you need to: + + .. code-block:: python + + import fake_useragent + + ua = fake_useragent.UserAgent(safe_attrs=('__injections__',)) + + Please, do not use if you don't understand why you need this. + This is magic for rarely extreme case. + + Experiencing issues??? + ---------------------- + + Make sure that You using latest version!!! + + .. code-block:: shell + + pip install -U fake-useragent + + Check version via python console: (version 0.1.4 added) + + .. code-block:: python + + import fake_useragent + + print(fake_useragent.VERSION) + + And You are always welcome to post `issues `_ + + Please do not forget mention version that You are using + + Tests + ----- + + .. code-block:: console + + pip install tox + tox + + Changelog + --------- + + * 0.1.11 October 4, 2018 + - moved `s3 + cloudfront` fallback to `heroku.com`, cuz someone from Florida did ~25M requests last month + + * 0.1.10 February 11, 2018 + - Minor fix docs `cloudfront` url + + * 0.1.9 February 11, 2018 + - fix ``w3schools.com`` renamed `IE/Edge` to `Edge/IE` + - moved `heroku.com` fallback to `s3 + cloudfront` + - stop testing Python3.3 and pypy + + * 0.1.8 November 2, 2017 + - fix ``useragentstring.com`` ``Can't connect to local MySQL server through socket`` + + * 0.1.7 April 2, 2017 + - fix broken README.rst + + * 0.1.6 April 2, 2017 + - fixes bug ``use_cache_server`` do not affected anything + - `w3schools.com `_ moved to ``https`` + - ``verify_ssl`` options added, by default it is ``True`` (``urllib.urlopen`` ssl context for Python 2.7.9- and 3.4.3- is not supported) + + * 0.1.5 February 28, 2017 + - added ``ua.edge`` alias to Internet Explorer + - w3schools.com starts displaying ``Edge`` statistic + - Python 2.6 is not tested anymore + - ``use_cache_server`` option added + - Increased ``fake_useragent.settings.HTTP_TIMEOUT`` to 5 seconds + + * 0.1.4 December 14, 2016 + - Added custom data file location support + - Added ``fallback`` browser support, in case of unavailable data sources + - Added alias ``fake_useragent.FakeUserAgent`` for ``fake_useragent.UserAgent`` + - Added alias ``fake_useragent.UserAgentError`` for ``fake_useragent.FakeUserAgentError`` + - Reduced ``fake_useragent.settings.HTTP_TIMEOUT`` to 3 seconds + - Started migration to new data file format + - Simplified a lot 4+ years out of date code + - Better thread/greenlet safety + - Added verbose logging + - Added ``safe_attrs`` for prevent overriding by ``__getattr__`` + + * 0.1.3 November 24, 2016 + - Added hosted data file, when remote services is unavailable + - Raises ``fake_useragent.errors.FakeUserAgentError`` in case when there is not way to download data + - Raises ``fake_useragent.errors.FakeUserAgentError`` instead of ``None`` in case of unknown browser + - Added ``gevent.sleep`` support in ``gevent`` patched environment when trying to download data + + * X.X.X xxxxxxx xx, xxxx + - xxxxx ????? + + Authors + ------- + + You can visit `authors page `_ + +Keywords: user,agent,user agent,useragent,fake,fake useragent,fake user agent +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Operating System :: POSIX +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Operating System :: Microsoft :: Windows +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 3 +Classifier: Operating System :: OS Independent diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent.egg-info/SOURCES.txt b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent.egg-info/SOURCES.txt new file mode 100644 index 0000000..6ea3c85 --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent.egg-info/SOURCES.txt @@ -0,0 +1,16 @@ +LICENSE +MANIFEST.in +README.rst +setup.cfg +setup.py +fake_useragent/__init__.py +fake_useragent/errors.py +fake_useragent/fake.py +fake_useragent/log.py +fake_useragent/settings.py +fake_useragent/utils.py +fake_useragent.egg-info/PKG-INFO +fake_useragent.egg-info/SOURCES.txt +fake_useragent.egg-info/dependency_links.txt +fake_useragent.egg-info/not-zip-safe +fake_useragent.egg-info/top_level.txt \ No newline at end of file diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent.egg-info/dependency_links.txt b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent.egg-info/not-zip-safe b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent.egg-info/not-zip-safe new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent.egg-info/not-zip-safe @@ -0,0 +1 @@ + diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent.egg-info/top_level.txt b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent.egg-info/top_level.txt new file mode 100644 index 0000000..522136d --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent.egg-info/top_level.txt @@ -0,0 +1 @@ +fake_useragent diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent/__init__.py b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent/__init__.py new file mode 100644 index 0000000..2a54f0a --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + +from fake_useragent.fake import FakeUserAgent, UserAgent # noqa # isort:skip +from fake_useragent.errors import FakeUserAgentError, UserAgentError # noqa # isort:skip +from fake_useragent.settings import __version__ as VERSION # noqa # isort:skip diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent/errors.py b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent/errors.py new file mode 100644 index 0000000..34f2c3e --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent/errors.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + + +class FakeUserAgentError(Exception): + pass + + +# common alias +UserAgentError = FakeUserAgentError diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent/fake.py b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent/fake.py new file mode 100644 index 0000000..224f8c1 --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent/fake.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + +import random +from threading import Lock + +from fake_useragent import settings +from fake_useragent.errors import FakeUserAgentError +from fake_useragent.log import logger +from fake_useragent.utils import load, load_cached, str_types, update + + +class FakeUserAgent(object): + def __init__( + self, + cache=True, + use_cache_server=True, + path=settings.DB, + fallback=None, + verify_ssl=True, + safe_attrs=tuple(), + ): + assert isinstance(cache, bool), \ + 'cache must be True or False' + + self.cache = cache + + assert isinstance(use_cache_server, bool), \ + 'use_cache_server must be True or False' + + self.use_cache_server = use_cache_server + + assert isinstance(path, str_types), \ + 'path must be string or unicode' + + self.path = path + + if fallback is not None: + assert isinstance(fallback, str_types), \ + 'fallback must be string or unicode' + + self.fallback = fallback + + assert isinstance(verify_ssl, bool), \ + 'verify_ssl must be True or False' + + self.verify_ssl = verify_ssl + + assert isinstance(safe_attrs, (list, set, tuple)), \ + 'safe_attrs must be list\\tuple\\set of strings or unicode' + + if safe_attrs: + str_types_safe_attrs = [ + isinstance(attr, str_types) for attr in safe_attrs + ] + + assert all(str_types_safe_attrs), \ + 'safe_attrs must be list\\tuple\\set of strings or unicode' + + self.safe_attrs = set(safe_attrs) + + # initial empty data + self.data = {} + # TODO: change source file format + # version 0.1.4+ migration tool + self.data_randomize = [] + self.data_browsers = {} + + self.load() + + def load(self): + try: + with self.load.lock: + if self.cache: + self.data = load_cached( + self.path, + use_cache_server=self.use_cache_server, + verify_ssl=self.verify_ssl, + ) + else: + self.data = load( + use_cache_server=self.use_cache_server, + verify_ssl=self.verify_ssl, + ) + + # TODO: change source file format + # version 0.1.4+ migration tool + self.data_randomize = list(self.data['randomize'].values()) + self.data_browsers = self.data['browsers'] + except FakeUserAgentError: + if self.fallback is None: + raise + else: + logger.warning( + 'Error occurred during fetching data, ' + 'but was suppressed with fallback.', + ) + load.lock = Lock() + + def update(self, cache=None): + with self.update.lock: + if cache is not None: + assert isinstance(cache, bool), \ + 'cache must be True or False' + + self.cache = cache + + if self.cache: + update( + self.path, + use_cache_server=self.use_cache_server, + verify_ssl=self.verify_ssl, + ) + + self.load() + update.lock = Lock() + + def __getitem__(self, attr): + return self.__getattr__(attr) + + def __getattr__(self, attr): + if attr in self.safe_attrs: + return super(UserAgent, self).__getattr__(attr) + + try: + for value, replacement in settings.REPLACEMENTS.items(): + attr = attr.replace(value, replacement) + + attr = attr.lower() + + if attr == 'random': + browser = random.choice(self.data_randomize) + else: + browser = settings.SHORTCUTS.get(attr, attr) + + return random.choice(self.data_browsers[browser]) + except (KeyError, IndexError): + if self.fallback is None: + raise FakeUserAgentError('Error occurred during getting browser') # noqa + else: + logger.warning( + 'Error occurred during getting browser, ' + 'but was suppressed with fallback.', + ) + + return self.fallback + + +# common alias +UserAgent = FakeUserAgent diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent/log.py b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent/log.py new file mode 100644 index 0000000..5d46773 --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent/log.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + +import logging + +logger = logging.getLogger(__package__) diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent/settings.py b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent/settings.py new file mode 100644 index 0000000..098f578 --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent/settings.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + +import os +import tempfile + +__version__ = '0.1.11' + +DB = os.path.join( + tempfile.gettempdir(), + 'fake_useragent_{version}.json'.format( + version=__version__, + ), +) + +CACHE_SERVER = 'https://fake-useragent.herokuapp.com/browsers/{version}'.format( + version=__version__, +) + +BROWSERS_STATS_PAGE = 'https://www.w3schools.com/browsers/default.asp' + +BROWSER_BASE_PAGE = 'http://useragentstring.com/pages/useragentstring.php?name={browser}' # noqa + +BROWSERS_COUNT_LIMIT = 50 + +REPLACEMENTS = { + ' ': '', + '_': '', +} + +SHORTCUTS = { + 'internet explorer': 'internetexplorer', + 'ie': 'internetexplorer', + 'msie': 'internetexplorer', + 'edge': 'internetexplorer', + 'google': 'chrome', + 'googlechrome': 'chrome', + 'ff': 'firefox', +} + +OVERRIDES = { + 'Edge/IE': 'Internet Explorer', + 'IE/Edge': 'Internet Explorer', +} + +HTTP_TIMEOUT = 5 + +HTTP_RETRIES = 2 + +HTTP_DELAY = 0.1 diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent/utils.py b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent/utils.py new file mode 100644 index 0000000..e1a38f2 --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/fake_useragent/utils.py @@ -0,0 +1,256 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + +import contextlib +import inspect +import io +import json +import os +import re +import ssl + +from fake_useragent.log import logger + +try: # Python 2 # pragma: no cover + from urllib2 import urlopen, Request, URLError + from urllib import quote_plus + + str_types = (unicode, str) # noqa + text = unicode # noqa +except ImportError: # Python 3 # pragma: no cover + from urllib.request import urlopen, Request + from urllib.parse import quote_plus + from urllib.error import URLError + + str_types = (str,) + text = str + +# gevent monkey patched environment check +try: # pragma: no cover + import socket + import gevent.socket + + if socket.socket is gevent.socket.socket: + from gevent import sleep + else: + from time import sleep +except (ImportError, AttributeError): # pragma: no cover + from time import sleep + + +try: + urlopen_args = inspect.getfullargspec(urlopen).kwonlyargs +except AttributeError: + urlopen_args = inspect.getargspec(urlopen).args + +urlopen_has_ssl_context = 'context' in urlopen_args + + +def get(url, verify_ssl=True): + attempt = 0 + + while True: + request = Request(url) + + attempt += 1 + + try: + if urlopen_has_ssl_context: + if not verify_ssl: + context = ssl._create_unverified_context() + else: + context = None + + with contextlib.closing(urlopen( + request, + timeout=settings.HTTP_TIMEOUT, + context=context, + )) as response: + return response.read() + else: # ssl context is not supported ;( + with contextlib.closing(urlopen( + request, + timeout=settings.HTTP_TIMEOUT, + )) as response: + return response.read() + except (URLError, OSError) as exc: + logger.debug( + 'Error occurred during fetching %s', + url, + exc_info=exc, + ) + + if attempt == settings.HTTP_RETRIES: + raise FakeUserAgentError('Maximum amount of retries reached') + else: + logger.debug( + 'Sleeping for %s seconds', + settings.HTTP_DELAY, + ) + sleep(settings.HTTP_DELAY) + + +def get_browsers(verify_ssl=True): + """ + very very hardcoded/dirty re/split stuff, but no dependencies + """ + html = get(settings.BROWSERS_STATS_PAGE, verify_ssl=verify_ssl) + html = html.decode('utf-8') + html = html.split('')[1] + html = html.split('
')[0] + + pattern = r'\.asp">(.+?)<' + browsers = re.findall(pattern, html, re.UNICODE) + + browsers = [ + settings.OVERRIDES.get(browser, browser) + for browser in browsers + ] + + pattern = r'td\sclass="right">(.+?)\s' + browsers_statistics = re.findall(pattern, html, re.UNICODE) + + return list(zip(browsers, browsers_statistics)) + + +def get_browser_versions(browser, verify_ssl=True): + """ + very very hardcoded/dirty re/split stuff, but no dependencies + """ + html = get( + settings.BROWSER_BASE_PAGE.format(browser=quote_plus(browser)), + verify_ssl=verify_ssl, + ) + html = html.decode('iso-8859-1') + html = html.split('
')[1] + html = html.split('
')[0] + + pattern = r'\?id=\d+\'>(.+?), 'firefox': ''} + for _ in range(int(float(percent) * 10)): + randomize_dict[str(len(randomize_dict))] = browser_key + except Exception as exc: + if not use_cache_server: + raise exc + + logger.warning( + 'Error occurred during loading data. ' + 'Trying to use cache server %s', + settings.CACHE_SERVER, + exc_info=exc, + ) + try: + ret = json.loads(get( + settings.CACHE_SERVER, + verify_ssl=verify_ssl, + ).decode('utf-8')) + except (TypeError, ValueError): + raise FakeUserAgentError('Can not load data from cache server') + else: + ret = { + 'browsers': browsers_dict, + 'randomize': randomize_dict, + } + + if not isinstance(ret, dict): + raise FakeUserAgentError('Data is not dictionary ', ret) + + for param in ['browsers', 'randomize']: + if param not in ret: + raise FakeUserAgentError('Missing data param: ', param) + + if not isinstance(ret[param], dict): + raise FakeUserAgentError('Data param is not dictionary', ret[param]) # noqa + + if not ret[param]: + raise FakeUserAgentError('Data param is empty', ret[param]) + + return ret + + +# TODO: drop these useless functions + + +def write(path, data): + with io.open(path, encoding='utf-8', mode='wt') as fp: + dumped = json.dumps(data) + + if not isinstance(dumped, text): # Python 2 + dumped = dumped.decode('utf-8') + + fp.write(dumped) + + +def read(path): + with io.open(path, encoding='utf-8', mode='rt') as fp: + return json.loads(fp.read()) + + +def exist(path): + return os.path.isfile(path) + + +def rm(path): + if exist(path): + os.remove(path) + + +def update(path, use_cache_server=True, verify_ssl=True): + rm(path) + + write(path, load(use_cache_server=use_cache_server, verify_ssl=verify_ssl)) + + +def load_cached(path, use_cache_server=True, verify_ssl=True): + if not exist(path): + update(path, use_cache_server=use_cache_server, verify_ssl=verify_ssl) + + return read(path) + + +from fake_useragent import settings # noqa # isort:skip +from fake_useragent.errors import FakeUserAgentError # noqa # isort:skip diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/setup.cfg b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/setup.cfg new file mode 100644 index 0000000..8bfd5a1 --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/setup.cfg @@ -0,0 +1,4 @@ +[egg_info] +tag_build = +tag_date = 0 + diff --git a/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/setup.py b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/setup.py new file mode 100644 index 0000000..c5935d2 --- /dev/null +++ b/NSICollectionPlatformServer/packages/fake-useragent-0.1.11.tar/dist/fake-useragent-0.1.11/setup.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import io +import os +import re + +from setuptools import setup + + +def get_version(): + regex = r"__version__\s=\s\'(?P[\d\.]+?)\'" + + path = ('fake_useragent', 'settings.py') + + return re.search(regex, read(*path)).group('version') + + +def read(*parts): + filename = os.path.join(os.path.abspath(os.path.dirname(__file__)), *parts) + + with io.open(filename, encoding='utf-8', mode='rt') as fp: + return fp.read() + + +setup( + name='fake-useragent', + version=get_version(), + author='hellysmile@gmail.com', + author_email='hellysmile@gmail.com', + url='https://github.com/hellysmile/fake-useragent', + description='Up to date simple useragent faker with real world database', + long_description=read('README.rst'), + packages=[str('fake_useragent')], + include_package_data=True, + zip_safe=False, + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: Apache Software License', + 'Operating System :: POSIX', + 'Operating System :: MacOS :: MacOS X', + 'Operating System :: Microsoft :: Windows', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 3', + 'Operating System :: OS Independent', + ], + keywords=[ + 'user', 'agent', 'user agent', 'useragent', + 'fake', 'fake useragent', 'fake user agent', + ], +) diff --git a/NSICollectionPlatformServer/packages/idna-3.1-py3-none-any.whl b/NSICollectionPlatformServer/packages/idna-3.1-py3-none-any.whl new file mode 100644 index 0000000..509ef80 Binary files /dev/null and b/NSICollectionPlatformServer/packages/idna-3.1-py3-none-any.whl differ diff --git a/NSICollectionPlatformServer/packages/itsdangerous-2.0.0-py3-none-any.whl b/NSICollectionPlatformServer/packages/itsdangerous-2.0.0-py3-none-any.whl new file mode 100644 index 0000000..e0cd896 Binary files /dev/null and b/NSICollectionPlatformServer/packages/itsdangerous-2.0.0-py3-none-any.whl differ diff --git a/NSICollectionPlatformServer/packages/requests-2.25.1-py2.py3-none-any.whl b/NSICollectionPlatformServer/packages/requests-2.25.1-py2.py3-none-any.whl new file mode 100644 index 0000000..8d70e97 Binary files /dev/null and b/NSICollectionPlatformServer/packages/requests-2.25.1-py2.py3-none-any.whl differ diff --git a/NSICollectionPlatformServer/packages/urllib3-1.25.1-py2.py3-none-any.whl b/NSICollectionPlatformServer/packages/urllib3-1.25.1-py2.py3-none-any.whl new file mode 100644 index 0000000..bf2e49f Binary files /dev/null and b/NSICollectionPlatformServer/packages/urllib3-1.25.1-py2.py3-none-any.whl differ diff --git a/NSICollectionPlatformServer/portDetection.py b/NSICollectionPlatformServer/portDetection.py new file mode 100644 index 0000000..1ebc65c --- /dev/null +++ b/NSICollectionPlatformServer/portDetection.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import socket +import dns.resolver +import re + + +def __check_ip(ip): + p = re.compile('^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$') + if p.match(ip): + return True + else: + return False + + +def __resolution_a(domain): + query_list = [] + a = dns.resolver.resolve(domain, 'A') + for i in a.response.answer: + for j in i.items: + if j.rdtype == 1: + ip = j.address + query_list.append(ip) + return query_list + + +def __detect_port(ip, port): + """检测ip上的端口是否开放 + """ + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + s.connect((ip, int(port))) + s.shutdown(2) + return True + except: + return False + + +def detection(domain, port): + is_ip = __check_ip(domain) + __data = [] + if is_ip: + port_status = __detect_port(ip=domain, port=port) + __data.append({ + "domain": domain, + "port": port, + "status": port_status + }) + else: + ips = __resolution_a(domain=domain) + for ip in ips: + port_status = __detect_port(ip=ip, port=port) + __data.append({ + "domain": ip, + "port": port, + "status": port_status + }) + return __data diff --git a/NSICollectionPlatformServer/requirements.txt b/NSICollectionPlatformServer/requirements.txt new file mode 100644 index 0000000..4370271 --- /dev/null +++ b/NSICollectionPlatformServer/requirements.txt @@ -0,0 +1,22 @@ +beautifulsoup4==4.9.3 +bs4==0.0.1 +certifi==2020.12.5 +chardet==4.0.0 +click==8.0.0 +colorama==0.4.4 +dnspython==2.1.0 +dnspython3==1.15.0 +fake-useragent==0.1.11 +Flask==2.0.0 +idna==2.10 +itsdangerous==2.0.0 +Jinja2==3.0.0 +MarkupSafe==2.0.0 +mysql-connector-python==8.0.24 +protobuf==3.17.0 +PyMySQL==1.0.2 +requests==2.25.1 +six==1.16.0 +soupsieve==2.2.1 +urllib3==1.25.1 +Werkzeug==2.0.0 diff --git a/NSICollectionPlatformServer/subdomainLookup.py b/NSICollectionPlatformServer/subdomainLookup.py new file mode 100644 index 0000000..6320e6b --- /dev/null +++ b/NSICollectionPlatformServer/subdomainLookup.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import requests +from bs4 import BeautifulSoup +from fake_useragent import UserAgent + + +def __get_http_headers(): + try: + ua = UserAgent() + header = { + "User-Agent": ua.random, + "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7,zh-TW;q=0.6" + } + except Exception as e: + header = { + "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36"} + return header + + +def sub_domain_lookup(domain): + domain_list = {} + for n in range(1, 2): + j = 1 + if n > 1: + j = n * 10 - 1 + params = { + "q": domain, + "go": "搜索", + "qs": "n", + "form": "QBLH", + "first": j + } + cookies = { + "SRCHHPGUSR": "NRSLT=50" + } + res = requests.get("https://cn.bing.com/search", headers=__get_http_headers(), params=params, cookies=cookies) + resp = res.content + # BeautifulSoup匹配标题 + html = BeautifulSoup(resp, "html.parser") + h2_list = html.find_all("h2", {"class": ""}) + for h2 in h2_list: + if h2.find("a") is not None: + href = h2.find("a")["href"] + href = href.split("?")[0] + domain_list[href] = h2.find("a").text + return domain_list diff --git a/NSICollectionPlatformServer/userManager.py b/NSICollectionPlatformServer/userManager.py new file mode 100644 index 0000000..3b3097e --- /dev/null +++ b/NSICollectionPlatformServer/userManager.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from dataSource import DataSource +import hashlib + + +def create_token(message): + """ + 生成随机码 + :param message: 原始报文 + :return: 密文 + """ + m2 = hashlib.md5() + m2.update(message.encode("utf8")) + return m2.hexdigest() + + +class UserManager: + def __init__(self, host='localhost', port=3306, username=None, password=None, database=None): + self.db = DataSource(host, port, username, password, database) + + def valid_token(self, token=None): + sql = 'SELECT `password` FROM USER' + password_list = self.db.fetchall(sql) + token_list = [] + for passwd in password_list: + token_list.append(passwd["password"]) + if token in token_list: + return True + else: + return False + + def valid_login(self, username, password): + """ + 登录验证 + :param username: 用户名 + :param password: 密码 + :return: + """ + password = create_token(username + password) + sql = 'SELECT * FROM USER WHERE username="' + username + '" AND password="' + password + '"' + return self.db.fetchone(sql=sql) + + def user_register(self, username, password, role): + """ + 用户注册 + :param username: 用户名 + :param password: 密码 + :return: + """ + password = create_token(username + password) + sql_select = 'SELECT COUNT(1) FROM USER WHERE `username`="' + username + '"' + count = self.db.fetchone(sql_select) + if count["COUNT(1)"] >= 1: + return False + else: + sql_insert = 'INSERT INTO USER (`username`, `password`, `role`) VALUES ("' + username + '", "' + password + '", "' + role+'")' + self.db.execute(sql_insert) + return True + + def user_add(self, username, password, role): + password = create_token(username + password) + sql_select = 'SELECT COUNT(1) FROM USER WHERE `username`="' + username + '"' + count = self.db.fetchone(sql_select) + if count["COUNT(1)"] >= 1: + return False + else: + sql_insert = 'INSERT INTO USER (`username`, `password`, `role`) VALUES ("' + username + '", "' + password + '", "' + role + '") ' + self.db.execute(sql_insert) + return True + + def user_delete(self, user_id): + sql_delete = 'DELETE FROM USER WHERE `id`="' + str(user_id) + '"' + self.db.execute(sql_delete) + return True + + def user_edit(self, user_id, username, password, role): + password = create_token(username + password) + sql_edit = 'UPDATE USER SET `password`="' + password + '" WHERE `id`="' + str(user_id) + '"' + self.db.execute(sql_edit) + return True + + def user_list(self): + sql_list = 'SELECT * FROM USER' + return self.db.fetchall(sql_list) + + def user_get(self, user_id): + sql_select = 'SELECT * FROM USER WHERE `id`="' + str(user_id) + '"' + return self.db.fetchone(sql_select) + + def user_authority_change(self, user_id, role): + sql_edit = 'UPDATE USER SET `role`="' + role + '" WHERE `id`="' + str(user_id) + '"' + self.db.execute(sql_edit) + return True diff --git a/README.md b/README.md index 607f405..a8ffc2d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,21 @@ -# NSICollectionPlatform +# 网络安全信息搜集平台 +> Network Security Information Collection Platform -网络安全信息搜集平台 \ No newline at end of file +## 项目说明 + +### vue-manage-system +> 前端项目。用于对用户展示相关功能和信息数据页面。 + +### NSICollectionPlatformServer +> 后台服务。用于提供用户进行相关操作的后台服务。 + +## 技术说明 + +### 数据库 +使用免费的mysql作为我们服务的数据库,用以支撑对数据持久化的正删改查等操作。 + +### 前端 +使用基于vue架构完成的vue-manage-system框架完成对用户操作数据的展示和提供操作功能给用户。 + +### 后台 +使用基于Python3环境的Flask框架来提供对WEB服务的后台支撑。 \ No newline at end of file diff --git a/nsi-collection-platform/.browserslistrc b/nsi-collection-platform/.browserslistrc new file mode 100644 index 0000000..9dee646 --- /dev/null +++ b/nsi-collection-platform/.browserslistrc @@ -0,0 +1,3 @@ +> 1% +last 2 versions +not ie <= 8 diff --git a/nsi-collection-platform/.gitignore b/nsi-collection-platform/.gitignore new file mode 100644 index 0000000..74f39bd --- /dev/null +++ b/nsi-collection-platform/.gitignore @@ -0,0 +1,23 @@ +/node_modules +.DS_Store +node_modules +/dist +example.html +favicon.ico +# local env files +.env.local +.env.*.local + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw* diff --git a/nsi-collection-platform/.prettierrc b/nsi-collection-platform/.prettierrc new file mode 100644 index 0000000..c5f454b --- /dev/null +++ b/nsi-collection-platform/.prettierrc @@ -0,0 +1,6 @@ +{ + "tabWidth": 4, + "singleQuote": true, + "trailingComma": "none", + "printWidth": 140 +} \ No newline at end of file diff --git a/nsi-collection-platform/LICENSE b/nsi-collection-platform/LICENSE new file mode 100644 index 0000000..1ef7d3e --- /dev/null +++ b/nsi-collection-platform/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016-2019 vue-manage-system + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/nsi-collection-platform/README.md b/nsi-collection-platform/README.md new file mode 100644 index 0000000..9706f78 --- /dev/null +++ b/nsi-collection-platform/README.md @@ -0,0 +1,19 @@ +# nsi-collection-platform + +基于 Vue + Element UI 的后台管理系统解决方案。 + +## 前言 + +该方案作为一套多功能的后台框架模板,适用于绝大部分的后台管理系统(Web Management System)开发。基于 vue.js,使用 vue-cli3 脚手架,引用 Element UI 组件库,方便开发快速简洁好看的组件。分离颜色样式,支持手动切换主题色,而且很方便使用自定义主题色。 + +## To Start +``` +// 安装项目依赖,等待安装完成之后,安装失败可用 cnpm 或 yarn +npm install + +// 开启服务器,浏览器访问 http://localhost:8080 +npm run serve + +// 执行构建命令,生成的dist文件夹放在服务器下即可访问 +npm run build +``` \ No newline at end of file diff --git a/nsi-collection-platform/babel.config.js b/nsi-collection-platform/babel.config.js new file mode 100644 index 0000000..ba17966 --- /dev/null +++ b/nsi-collection-platform/babel.config.js @@ -0,0 +1,5 @@ +module.exports = { + presets: [ + '@vue/app' + ] +} diff --git a/nsi-collection-platform/package-lock.json b/nsi-collection-platform/package-lock.json new file mode 100644 index 0000000..6814ddd --- /dev/null +++ b/nsi-collection-platform/package-lock.json @@ -0,0 +1,17656 @@ +{ + "name": "nsi-collection-platform", + "version": "4.2.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/code-frame/download/@babel/code-frame-7.8.3.tgz", + "integrity": "sha1-M+JZA9dIEYFTThLsCiXxa2/PQZ4=", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/core": { + "version": "7.9.6", + "resolved": "https://registry.npm.taobao.org/@babel/core/download/@babel/core-7.9.6.tgz?cache=0&sync_timestamp=1588185908440&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fcore%2Fdownload%2F%40babel%2Fcore-7.9.6.tgz", + "integrity": "sha1-2aofWAq/OyKG70C2kE05CQTGM3Y=", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.9.6", + "@babel/helper-module-transforms": "^7.9.0", + "@babel/helpers": "^7.9.6", + "@babel/parser": "^7.9.6", + "@babel/template": "^7.8.6", + "@babel/traverse": "^7.9.6", + "@babel/types": "^7.9.6", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz", + "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz", + "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.9.6", + "resolved": "https://registry.npm.taobao.org/@babel/generator/download/@babel/generator-7.9.6.tgz", + "integrity": "sha1-VAjIKsXemM2g132BJOmfofIXCkM=", + "dev": true, + "requires": { + "@babel/types": "^7.9.6", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/helper-annotate-as-pure/download/@babel/helper-annotate-as-pure-7.8.3.tgz", + "integrity": "sha1-YLwLxlf2Ogkk/5pLSgskoTz03u4=", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/helper-builder-binary-assignment-operator-visitor/download/@babel/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz", + "integrity": "sha1-yECXpCegYaxWocMOv1S3si0kFQM=", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.9.6", + "resolved": "https://registry.npm.taobao.org/@babel/helper-create-class-features-plugin/download/@babel/helper-create-class-features-plugin-7.9.6.tgz", + "integrity": "sha1-llyLCp8FGAH9nTs3LKDM8gCpCJc=", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.9.5", + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.9.6", + "@babel/helper-split-export-declaration": "^7.8.3" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.8.8", + "resolved": "https://registry.npm.taobao.org/@babel/helper-create-regexp-features-plugin/download/@babel/helper-create-regexp-features-plugin-7.8.8.tgz", + "integrity": "sha1-XYQYC1iPVgt4ZO+u6okkPlgxIIc=", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-regex": "^7.8.3", + "regexpu-core": "^4.7.0" + } + }, + "@babel/helper-define-map": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/helper-define-map/download/@babel/helper-define-map-7.8.3.tgz", + "integrity": "sha1-oGVcrVRRw3YLcm66h18c2PqgLBU=", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.8.3", + "@babel/types": "^7.8.3", + "lodash": "^4.17.13" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/helper-explode-assignable-expression/download/@babel/helper-explode-assignable-expression-7.8.3.tgz", + "integrity": "sha1-pyjcW06J4w/C38fQT6KKkwZT+YI=", + "dev": true, + "requires": { + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-function-name": { + "version": "7.9.5", + "resolved": "https://registry.npm.taobao.org/@babel/helper-function-name/download/@babel/helper-function-name-7.9.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-function-name%2Fdownload%2F%40babel%2Fhelper-function-name-7.9.5.tgz", + "integrity": "sha1-K1OCDTUnUSDhh0qC5aq+E3aSClw=", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.9.5" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/helper-get-function-arity/download/@babel/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha1-uJS5R70AQ4HOY+odufCFR+kgq9U=", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/helper-hoist-variables/download/@babel/helper-hoist-variables-7.8.3.tgz", + "integrity": "sha1-Hb6ba1XXjJtBg/yM3G4wzrg7cTQ=", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/helper-member-expression-to-functions/download/@babel/helper-member-expression-to-functions-7.8.3.tgz", + "integrity": "sha1-ZZtxBJjqbB2ZB+DHPyBu7n2twkw=", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-module-imports": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/helper-module-imports/download/@babel/helper-module-imports-7.8.3.tgz", + "integrity": "sha1-f+OVibOcAWMxtrjD9EHo8LFBlJg=", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-module-transforms": { + "version": "7.9.0", + "resolved": "https://registry.npm.taobao.org/@babel/helper-module-transforms/download/@babel/helper-module-transforms-7.9.0.tgz", + "integrity": "sha1-Q7NN/hWWGRhwfSRzJ0MTiOn+luU=", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.6", + "@babel/helper-simple-access": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/template": "^7.8.6", + "@babel/types": "^7.9.0", + "lodash": "^4.17.13" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/helper-optimise-call-expression/download/@babel/helper-optimise-call-expression-7.8.3.tgz", + "integrity": "sha1-ftBxgT0Jx1KY708giVYAa2ER7Lk=", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/helper-plugin-utils/download/@babel/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha1-nqKTvhm6vA9S/4yoizTDYRsghnA=", + "dev": true + }, + "@babel/helper-regex": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/helper-regex/download/@babel/helper-regex-7.8.3.tgz", + "integrity": "sha1-E5dyYH1RuT8j7/5yEFsxnSpMaWU=", + "dev": true, + "requires": { + "lodash": "^4.17.13" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/helper-remap-async-to-generator/download/@babel/helper-remap-async-to-generator-7.8.3.tgz", + "integrity": "sha1-JzxgDYub9QBhQsHjWIfVVcEu3YY=", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-wrap-function": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-replace-supers": { + "version": "7.9.6", + "resolved": "https://registry.npm.taobao.org/@babel/helper-replace-supers/download/@babel/helper-replace-supers-7.9.6.tgz?cache=0&sync_timestamp=1588185907352&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-replace-supers%2Fdownload%2F%40babel%2Fhelper-replace-supers-7.9.6.tgz", + "integrity": "sha1-AxSdfmpVhqtnZJls0x1pgaF+FEQ=", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/traverse": "^7.9.6", + "@babel/types": "^7.9.6" + } + }, + "@babel/helper-simple-access": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/helper-simple-access/download/@babel/helper-simple-access-7.8.3.tgz", + "integrity": "sha1-f4EJkotNq0ZUB2mGr1dSMd62Oa4=", + "dev": true, + "requires": { + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/helper-split-export-declaration/download/@babel/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha1-ManzAHD5E2inGCzwX4MXgQZfx6k=", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.9.5", + "resolved": "https://registry.npm.taobao.org/@babel/helper-validator-identifier/download/@babel/helper-validator-identifier-7.9.5.tgz", + "integrity": "sha1-kJd6jm+/a0MafcMXUu7iM78FLYA=", + "dev": true + }, + "@babel/helper-wrap-function": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/helper-wrap-function/download/@babel/helper-wrap-function-7.8.3.tgz", + "integrity": "sha1-nb2yu1XvFKqgH+jJm2Kb1TUthhA=", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helpers": { + "version": "7.9.6", + "resolved": "https://registry.npm.taobao.org/@babel/helpers/download/@babel/helpers-7.9.6.tgz?cache=0&sync_timestamp=1588185908061&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelpers%2Fdownload%2F%40babel%2Fhelpers-7.9.6.tgz", + "integrity": "sha1-CSx3R0NHHQu2x9461GWrPTSG1YA=", + "dev": true, + "requires": { + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.9.6", + "@babel/types": "^7.9.6" + } + }, + "@babel/highlight": { + "version": "7.9.0", + "resolved": "https://registry.npm.taobao.org/@babel/highlight/download/@babel/highlight-7.9.0.tgz?cache=0&sync_timestamp=1584746125589&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhighlight%2Fdownload%2F%40babel%2Fhighlight-7.9.0.tgz", + "integrity": "sha1-TptFzLgreWBycbKXmtgse2gWMHk=", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.9.0", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.9.6", + "resolved": "https://registry.npm.taobao.org/@babel/parser/download/@babel/parser-7.9.6.tgz?cache=0&sync_timestamp=1588185910361&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fparser%2Fdownload%2F%40babel%2Fparser-7.9.6.tgz", + "integrity": "sha1-Oxu7MNq+YAzXLbWHIJmDdv9lO8c=", + "dev": true + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-async-generator-functions/download/@babel/plugin-proposal-async-generator-functions-7.8.3.tgz", + "integrity": "sha1-utMpxnCzgliXIbJ1QMfSiGAcbm8=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-remap-async-to-generator": "^7.8.3", + "@babel/plugin-syntax-async-generators": "^7.8.0" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-class-properties/download/@babel/plugin-proposal-class-properties-7.8.3.tgz", + "integrity": "sha1-XgZlSvXNBLYIkVqtqbKmeIAERk4=", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-proposal-decorators": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-decorators/download/@babel/plugin-proposal-decorators-7.8.3.tgz", + "integrity": "sha1-IVaGCrZcWr8GjD9nBCGEBBBmVD4=", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-decorators": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-json-strings/download/@babel/plugin-proposal-json-strings-7.8.3.tgz", + "integrity": "sha1-2lIWsjipi1ih4F1oUhBLEPmnDWs=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.0" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.9.6", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-object-rest-spread/download/@babel/plugin-proposal-object-rest-spread-7.9.6.tgz?cache=0&sync_timestamp=1588185906386&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-object-rest-spread%2Fdownload%2F%40babel%2Fplugin-proposal-object-rest-spread-7.9.6.tgz", + "integrity": "sha1-egk1hvyxiwgmbrGnF32mcaxXW2M=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.9.5" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-optional-catch-binding/download/@babel/plugin-proposal-optional-catch-binding-7.8.3.tgz", + "integrity": "sha1-ne6WqxZQ7tiGRq6XNMoWesSpxck=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.8.8", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-unicode-property-regex/download/@babel/plugin-proposal-unicode-property-regex-7.8.8.tgz?cache=0&sync_timestamp=1584039926670&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-unicode-property-regex%2Fdownload%2F%40babel%2Fplugin-proposal-unicode-property-regex-7.8.8.tgz", + "integrity": "sha1-7jqV6QzcBP6M2S7DJ5+gF9aKDR0=", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.8.8", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-async-generators/download/@babel/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha1-qYP7Gusuw/btBCohD2QOkOeG/g0=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-decorators": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-decorators/download/@babel/plugin-syntax-decorators-7.8.3.tgz", + "integrity": "sha1-jSwVqfGvYksAJflhaCqdU9MAG9o=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-dynamic-import/download/@babel/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha1-Yr+Ysto80h1iYVT8lu5bPLaOrLM=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-json-strings/download/@babel/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha1-AcohtmjNghjJ5kDLbdiMVBKyyWo=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-jsx/download/@babel/plugin-syntax-jsx-7.8.3.tgz", + "integrity": "sha1-UhsGyDxASA8eWLT9M7kuzrHW6pQ=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-object-rest-spread/download/@babel/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha1-YOIl7cvZimQDMqLnLdPmbxr1WHE=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-optional-catch-binding/download/@babel/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha1-YRGiZbz7Ag6579D9/X0mQCue1sE=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-arrow-functions/download/@babel/plugin-transform-arrow-functions-7.8.3.tgz", + "integrity": "sha1-gndsLtDNnhpJlW2uuJYCTJRzuLY=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-async-to-generator/download/@babel/plugin-transform-async-to-generator-7.8.3.tgz", + "integrity": "sha1-Qwj60NlAnXHq+5sabuNfnWS2QIY=", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-remap-async-to-generator": "^7.8.3" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-block-scoped-functions/download/@babel/plugin-transform-block-scoped-functions-7.8.3.tgz", + "integrity": "sha1-Q37sW3mbWFIHIISzrl72boNJ6KM=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-block-scoping/download/@babel/plugin-transform-block-scoping-7.8.3.tgz", + "integrity": "sha1-l9Ndq2aFekN8FmNYuR0JBQyGjzo=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "lodash": "^4.17.13" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.9.5", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-classes/download/@babel/plugin-transform-classes-7.9.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-classes%2Fdownload%2F%40babel%2Fplugin-transform-classes-7.9.5.tgz", + "integrity": "sha1-gAWX3biu/CwpPtJ0WcH8yTWibCw=", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-define-map": "^7.8.3", + "@babel/helper-function-name": "^7.9.5", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.6", + "@babel/helper-split-export-declaration": "^7.8.3", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-computed-properties/download/@babel/plugin-transform-computed-properties-7.8.3.tgz", + "integrity": "sha1-ltDSi3985OtbEguy4OlDNDyG+Bs=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.9.5", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-destructuring/download/@babel/plugin-transform-destructuring-7.9.5.tgz", + "integrity": "sha1-csl89fOGBK6jq/O5NbDhex23alA=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-dotall-regex/download/@babel/plugin-transform-dotall-regex-7.8.3.tgz", + "integrity": "sha1-w8bsXuYSXGmTxcvKINyGIanqem4=", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-duplicate-keys/download/@babel/plugin-transform-duplicate-keys-7.8.3.tgz", + "integrity": "sha1-jRLfMJqlN/JyiZxWXqF2jihuIfE=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-exponentiation-operator/download/@babel/plugin-transform-exponentiation-operator-7.8.3.tgz", + "integrity": "sha1-WBptf1aXDga/UVYM1k9elHtw17c=", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.9.0", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-for-of/download/@babel/plugin-transform-for-of-7.9.0.tgz", + "integrity": "sha1-DyYOJ9PinNG7MSjaXnbHYapsEI4=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-function-name/download/@babel/plugin-transform-function-name-7.8.3.tgz", + "integrity": "sha1-J5NzyycyKqrWfCaD53bfxHGW7Ys=", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-literals/download/@babel/plugin-transform-literals-7.8.3.tgz", + "integrity": "sha1-rvI5gj2RmU7Hto5VGTUl1229XcE=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.9.6", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-modules-amd/download/@babel/plugin-transform-modules-amd-7.9.6.tgz?cache=0&sync_timestamp=1588185902641&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-modules-amd%2Fdownload%2F%40babel%2Fplugin-transform-modules-amd-7.9.6.tgz", + "integrity": "sha1-hTnsQsFT0S6jg24OOsMNWq57JY4=", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.9.0", + "@babel/helper-plugin-utils": "^7.8.3", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.9.6", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-modules-commonjs/download/@babel/plugin-transform-modules-commonjs-7.9.6.tgz?cache=0&sync_timestamp=1588185907042&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-modules-commonjs%2Fdownload%2F%40babel%2Fplugin-transform-modules-commonjs-7.9.6.tgz", + "integrity": "sha1-ZLdHSkJ57liMrNGQZpXKchaHwnc=", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.9.0", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-simple-access": "^7.8.3", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.9.6", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-modules-systemjs/download/@babel/plugin-transform-modules-systemjs-7.9.6.tgz?cache=0&sync_timestamp=1588185909511&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-modules-systemjs%2Fdownload%2F%40babel%2Fplugin-transform-modules-systemjs-7.9.6.tgz", + "integrity": "sha1-IH8UYceKIx1TN6khQOUkIlENgaQ=", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.8.3", + "@babel/helper-module-transforms": "^7.9.0", + "@babel/helper-plugin-utils": "^7.8.3", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.9.0", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-modules-umd/download/@babel/plugin-transform-modules-umd-7.9.0.tgz", + "integrity": "sha1-6Qmsridv7CgPm4IaXzjh8ItIBpc=", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.9.0", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-named-capturing-groups-regex/download/@babel/plugin-transform-named-capturing-groups-regex-7.8.3.tgz", + "integrity": "sha1-oqcr/6ICrA4tBQav0JOcXsvEjGw=", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.8.3" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-new-target/download/@babel/plugin-transform-new-target-7.8.3.tgz", + "integrity": "sha1-YMwq5m2FyVq1QOs0urtkNNTHDEM=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-object-super/download/@babel/plugin-transform-object-super-7.8.3.tgz", + "integrity": "sha1-67ah56hv+paFi9asAQLWWUQmFyU=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.3" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.9.5", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-parameters/download/@babel/plugin-transform-parameters-7.9.5.tgz", + "integrity": "sha1-FzsmV0b14Vsq/lJ+7aZbc2I6B5U=", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.8.7", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-regenerator/download/@babel/plugin-transform-regenerator-7.8.7.tgz?cache=0&sync_timestamp=1583373435237&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-regenerator%2Fdownload%2F%40babel%2Fplugin-transform-regenerator-7.8.7.tgz", + "integrity": "sha1-Xkag3KK+4a2ChesFJ+arycN2cvg=", + "dev": true, + "requires": { + "regenerator-transform": "^0.14.2" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.9.6", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-runtime/download/@babel/plugin-transform-runtime-7.9.6.tgz?cache=0&sync_timestamp=1588185906678&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-runtime%2Fdownload%2F%40babel%2Fplugin-transform-runtime-7.9.6.tgz", + "integrity": "sha1-O6gEQ4rQ2IChe8peqgzfHt7tsv0=", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "resolve": "^1.8.1", + "semver": "^5.5.1" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-shorthand-properties/download/@babel/plugin-transform-shorthand-properties-7.8.3.tgz", + "integrity": "sha1-KFRSFuAjqDLU06EYXtSSvP6sCMg=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-spread/download/@babel/plugin-transform-spread-7.8.3.tgz", + "integrity": "sha1-nI/+gXD9+4ixFOy5ILgvtulf5eg=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-sticky-regex/download/@babel/plugin-transform-sticky-regex-7.8.3.tgz", + "integrity": "sha1-vnoSkPgdrnZ0dUUhmeH3bWF1sQA=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-regex": "^7.8.3" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-template-literals/download/@babel/plugin-transform-template-literals-7.8.3.tgz", + "integrity": "sha1-e/pHMrRV6mpDEwrcC6dn7A5AKoA=", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.8.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-typeof-symbol/download/@babel/plugin-transform-typeof-symbol-7.8.4.tgz", + "integrity": "sha1-7eQGIxXOCq+KZXqSCFjxovNfxBI=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-unicode-regex/download/@babel/plugin-transform-unicode-regex-7.8.3.tgz", + "integrity": "sha1-DO8247pz5cVyc+/7GC9GuRoeyq0=", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/preset-env": { + "version": "7.3.4", + "resolved": "https://registry.npm.taobao.org/@babel/preset-env/download/@babel/preset-env-7.3.4.tgz", + "integrity": "sha1-iHzzi20jyC8ZtRNSmL2xYAYuM+E=", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-async-generator-functions": "^7.2.0", + "@babel/plugin-proposal-json-strings": "^7.2.0", + "@babel/plugin-proposal-object-rest-spread": "^7.3.4", + "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.2.0", + "@babel/plugin-syntax-async-generators": "^7.2.0", + "@babel/plugin-syntax-json-strings": "^7.2.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", + "@babel/plugin-transform-arrow-functions": "^7.2.0", + "@babel/plugin-transform-async-to-generator": "^7.3.4", + "@babel/plugin-transform-block-scoped-functions": "^7.2.0", + "@babel/plugin-transform-block-scoping": "^7.3.4", + "@babel/plugin-transform-classes": "^7.3.4", + "@babel/plugin-transform-computed-properties": "^7.2.0", + "@babel/plugin-transform-destructuring": "^7.2.0", + "@babel/plugin-transform-dotall-regex": "^7.2.0", + "@babel/plugin-transform-duplicate-keys": "^7.2.0", + "@babel/plugin-transform-exponentiation-operator": "^7.2.0", + "@babel/plugin-transform-for-of": "^7.2.0", + "@babel/plugin-transform-function-name": "^7.2.0", + "@babel/plugin-transform-literals": "^7.2.0", + "@babel/plugin-transform-modules-amd": "^7.2.0", + "@babel/plugin-transform-modules-commonjs": "^7.2.0", + "@babel/plugin-transform-modules-systemjs": "^7.3.4", + "@babel/plugin-transform-modules-umd": "^7.2.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.3.0", + "@babel/plugin-transform-new-target": "^7.0.0", + "@babel/plugin-transform-object-super": "^7.2.0", + "@babel/plugin-transform-parameters": "^7.2.0", + "@babel/plugin-transform-regenerator": "^7.3.4", + "@babel/plugin-transform-shorthand-properties": "^7.2.0", + "@babel/plugin-transform-spread": "^7.2.0", + "@babel/plugin-transform-sticky-regex": "^7.2.0", + "@babel/plugin-transform-template-literals": "^7.2.0", + "@babel/plugin-transform-typeof-symbol": "^7.2.0", + "@babel/plugin-transform-unicode-regex": "^7.2.0", + "browserslist": "^4.3.4", + "invariant": "^2.2.2", + "js-levenshtein": "^1.1.3", + "semver": "^5.3.0" + } + }, + "@babel/runtime": { + "version": "7.9.6", + "resolved": "https://registry.npm.taobao.org/@babel/runtime/download/@babel/runtime-7.9.6.tgz?cache=0&sync_timestamp=1588185696009&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fruntime%2Fdownload%2F%40babel%2Fruntime-7.9.6.tgz", + "integrity": "sha1-qRAutcre3z8x0IqezylK94J+op8=", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.13.5", + "resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.13.5.tgz", + "integrity": "sha1-2Hih0JS0MG0QuQlkhLM+vVXiZpc=", + "dev": true + } + } + }, + "@babel/runtime-corejs2": { + "version": "7.9.6", + "resolved": "https://registry.npm.taobao.org/@babel/runtime-corejs2/download/@babel/runtime-corejs2-7.9.6.tgz", + "integrity": "sha1-rNXWNROEzCgo3CEapUJqkEdr9Kg=", + "dev": true, + "requires": { + "core-js": "^2.6.5", + "regenerator-runtime": "^0.13.4" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.13.5", + "resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.13.5.tgz", + "integrity": "sha1-2Hih0JS0MG0QuQlkhLM+vVXiZpc=", + "dev": true + } + } + }, + "@babel/template": { + "version": "7.8.6", + "resolved": "https://registry.npm.taobao.org/@babel/template/download/@babel/template-7.8.6.tgz", + "integrity": "sha1-hrIq8V+CjfsIZHT5ZNzD45xDzis=", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.6", + "@babel/types": "^7.8.6" + } + }, + "@babel/traverse": { + "version": "7.9.6", + "resolved": "https://registry.npm.taobao.org/@babel/traverse/download/@babel/traverse-7.9.6.tgz", + "integrity": "sha1-VUDXV3aXv2GcxXuSqg8cIxqU9EI=", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.9.6", + "@babel/helper-function-name": "^7.9.5", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.9.6", + "@babel/types": "^7.9.6", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz", + "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz", + "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.9.6", + "resolved": "https://registry.npm.taobao.org/@babel/types/download/@babel/types-7.9.6.tgz?cache=0&sync_timestamp=1588212210329&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Ftypes%2Fdownload%2F%40babel%2Ftypes-7.9.6.tgz", + "integrity": "sha1-LFUCtCclHp3hvS3/la3WRtlcyfc=", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.9.5", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "@hapi/address": { + "version": "2.1.4", + "resolved": "https://registry.npm.taobao.org/@hapi/address/download/@hapi/address-2.1.4.tgz", + "integrity": "sha1-XWftQ/P9QaadS5/3tW58DR0KgeU=", + "dev": true + }, + "@hapi/bourne": { + "version": "1.3.2", + "resolved": "https://registry.npm.taobao.org/@hapi/bourne/download/@hapi/bourne-1.3.2.tgz", + "integrity": "sha1-CnCVreoGckPOMoPhtWuKj0U7JCo=", + "dev": true + }, + "@hapi/hoek": { + "version": "8.5.1", + "resolved": "https://registry.npm.taobao.org/@hapi/hoek/download/@hapi/hoek-8.5.1.tgz", + "integrity": "sha1-/elgZMpEbeyMVajC8TCVewcMbgY=", + "dev": true + }, + "@hapi/joi": { + "version": "15.1.1", + "resolved": "https://registry.npm.taobao.org/@hapi/joi/download/@hapi/joi-15.1.1.tgz", + "integrity": "sha1-xnW4pxKW8Cgz+NbSQ7NMV7jOGdc=", + "dev": true, + "requires": { + "@hapi/address": "2.x.x", + "@hapi/bourne": "1.x.x", + "@hapi/hoek": "8.x.x", + "@hapi/topo": "3.x.x" + } + }, + "@hapi/topo": { + "version": "3.1.6", + "resolved": "https://registry.npm.taobao.org/@hapi/topo/download/@hapi/topo-3.1.6.tgz", + "integrity": "sha1-aNk1+j6uf91asNf5U/MgXYsr/Ck=", + "dev": true, + "requires": { + "@hapi/hoek": "^8.3.0" + } + }, + "@intervolga/optimize-cssnano-plugin": { + "version": "1.0.6", + "resolved": "https://registry.npm.taobao.org/@intervolga/optimize-cssnano-plugin/download/@intervolga/optimize-cssnano-plugin-1.0.6.tgz", + "integrity": "sha1-vnx4RhKLiPapsdEmGgrQbrXA/fg=", + "dev": true, + "requires": { + "cssnano": "^4.0.0", + "cssnano-preset-default": "^4.0.0", + "postcss": "^7.0.0" + } + }, + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npm.taobao.org/@mrmlnc/readdir-enhanced/download/@mrmlnc/readdir-enhanced-2.2.1.tgz", + "integrity": "sha1-UkryQNGjYFJ7cwR17PoTRKpUDd4=", + "dev": true, + "requires": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + } + }, + "@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/@nodelib/fs.stat/download/@nodelib/fs.stat-1.1.3.tgz", + "integrity": "sha1-K1o6s/kYzKSKjHVMCBaOPwPrphs=", + "dev": true + }, + "@soda/friendly-errors-webpack-plugin": { + "version": "1.7.1", + "resolved": "https://registry.npm.taobao.org/@soda/friendly-errors-webpack-plugin/download/@soda/friendly-errors-webpack-plugin-1.7.1.tgz", + "integrity": "sha1-cG9kvLSouWQrSK46zkRMcDNNYV0=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "error-stack-parser": "^2.0.0", + "string-width": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz?cache=0&sync_timestamp=1570188570027&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-regex%2Fdownload%2Fansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/chalk/download/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/@types/color-name/download/@types/color-name-1.1.1.tgz", + "integrity": "sha1-HBJhu+qhCoBVu8XYq4S3sq/IRqA=", + "dev": true + }, + "@types/events": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/@types/events/download/@types/events-3.0.0.tgz", + "integrity": "sha1-KGLz9Yqaf3w+eNefEw3U1xwlwqc=", + "dev": true + }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npm.taobao.org/@types/glob/download/@types/glob-7.1.1.tgz", + "integrity": "sha1-qlmhxuP7xCHgfM0xqUTDDrpSFXU=", + "dev": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npm.taobao.org/@types/minimatch/download/@types/minimatch-3.0.3.tgz", + "integrity": "sha1-PcoOPzOyAPx9ETnAzZbBJoyt/Z0=", + "dev": true + }, + "@types/node": { + "version": "13.13.5", + "resolved": "https://registry.npm.taobao.org/@types/node/download/@types/node-13.13.5.tgz", + "integrity": "sha1-luw7Cvr9ZKTM6pEHt1v4SJ8OV2U=", + "dev": true + }, + "@types/normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npm.taobao.org/@types/normalize-package-data/download/@types/normalize-package-data-2.4.0.tgz", + "integrity": "sha1-5IbQ2XOW15vu3QpuM/RTT/a0lz4=", + "dev": true + }, + "@types/q": { + "version": "1.5.2", + "resolved": "https://registry.npm.taobao.org/@types/q/download/@types/q-1.5.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fq%2Fdownload%2F%40types%2Fq-1.5.2.tgz", + "integrity": "sha1-aQoUdbhPKohP0HzXl8APXzE1bqg=", + "dev": true + }, + "@vue/babel-helper-vue-jsx-merge-props": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/@vue/babel-helper-vue-jsx-merge-props/download/@vue/babel-helper-vue-jsx-merge-props-1.0.0.tgz", + "integrity": "sha1-BI/leZWNpAj7eosqPsBQtQpmEEA=", + "dev": true + }, + "@vue/babel-plugin-transform-vue-jsx": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/@vue/babel-plugin-transform-vue-jsx/download/@vue/babel-plugin-transform-vue-jsx-1.1.2.tgz", + "integrity": "sha1-wKPm78Ai515CR7RIqPxrhvA+kcA=", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0", + "html-tags": "^2.0.0", + "lodash.kebabcase": "^4.1.1", + "svg-tags": "^1.0.0" + } + }, + "@vue/babel-preset-app": { + "version": "3.12.1", + "resolved": "https://registry.npm.taobao.org/@vue/babel-preset-app/download/@vue/babel-preset-app-3.12.1.tgz", + "integrity": "sha1-JMR3BS8HjzD9t3NRA7FN0fosv+E=", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/plugin-proposal-decorators": "^7.1.0", + "@babel/plugin-syntax-dynamic-import": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.4.0", + "@babel/preset-env": "^7.0.0 < 7.4.0", + "@babel/runtime": "^7.0.0", + "@babel/runtime-corejs2": "^7.2.0", + "@vue/babel-preset-jsx": "^1.0.0", + "babel-plugin-dynamic-import-node": "^2.2.0", + "babel-plugin-module-resolver": "3.2.0", + "core-js": "^2.6.5" + } + }, + "@vue/babel-preset-jsx": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/@vue/babel-preset-jsx/download/@vue/babel-preset-jsx-1.1.2.tgz", + "integrity": "sha1-LhaetMIE6jfKZsLqhaiAv8mdTyA=", + "dev": true, + "requires": { + "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0", + "@vue/babel-plugin-transform-vue-jsx": "^1.1.2", + "@vue/babel-sugar-functional-vue": "^1.1.2", + "@vue/babel-sugar-inject-h": "^1.1.2", + "@vue/babel-sugar-v-model": "^1.1.2", + "@vue/babel-sugar-v-on": "^1.1.2" + } + }, + "@vue/babel-sugar-functional-vue": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/@vue/babel-sugar-functional-vue/download/@vue/babel-sugar-functional-vue-1.1.2.tgz", + "integrity": "sha1-9+JPugnm8e5wEEVgqICAV1VfGpo=", + "dev": true, + "requires": { + "@babel/plugin-syntax-jsx": "^7.2.0" + } + }, + "@vue/babel-sugar-inject-h": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/@vue/babel-sugar-inject-h/download/@vue/babel-sugar-inject-h-1.1.2.tgz", + "integrity": "sha1-ilJ2ttji7Rb/yAeKrZQjYnTm7fA=", + "dev": true, + "requires": { + "@babel/plugin-syntax-jsx": "^7.2.0" + } + }, + "@vue/babel-sugar-v-model": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/@vue/babel-sugar-v-model/download/@vue/babel-sugar-v-model-1.1.2.tgz", + "integrity": "sha1-H/b9G4ACI/ycsehNzrXlLXN6gZI=", + "dev": true, + "requires": { + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0", + "@vue/babel-plugin-transform-vue-jsx": "^1.1.2", + "camelcase": "^5.0.0", + "html-tags": "^2.0.0", + "svg-tags": "^1.0.0" + } + }, + "@vue/babel-sugar-v-on": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/@vue/babel-sugar-v-on/download/@vue/babel-sugar-v-on-1.1.2.tgz", + "integrity": "sha1-su+ZuPL6sJ++rSWq1w70Lhz1sTs=", + "dev": true, + "requires": { + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-plugin-transform-vue-jsx": "^1.1.2", + "camelcase": "^5.0.0" + } + }, + "@vue/cli-overlay": { + "version": "3.12.1", + "resolved": "https://registry.npm.taobao.org/@vue/cli-overlay/download/@vue/cli-overlay-3.12.1.tgz?cache=0&sync_timestamp=1586274083715&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40vue%2Fcli-overlay%2Fdownload%2F%40vue%2Fcli-overlay-3.12.1.tgz", + "integrity": "sha1-vf3o9xI1YasG5OTGC4VMxQkvWrE=", + "dev": true + }, + "@vue/cli-plugin-babel": { + "version": "3.12.1", + "resolved": "https://registry.npm.taobao.org/@vue/cli-plugin-babel/download/@vue/cli-plugin-babel-3.12.1.tgz", + "integrity": "sha1-mnkVnejNCGsBP6bXijmDCy4uxwY=", + "dev": true, + "requires": { + "@babel/core": "^7.0.0", + "@vue/babel-preset-app": "^3.12.1", + "@vue/cli-shared-utils": "^3.12.1", + "babel-loader": "^8.0.5", + "webpack": "^4.0.0" + } + }, + "@vue/cli-service": { + "version": "3.12.1", + "resolved": "https://registry.npm.taobao.org/@vue/cli-service/download/@vue/cli-service-3.12.1.tgz", + "integrity": "sha1-EyILHBiSVOfAAzkN8ykIb5tud+Y=", + "dev": true, + "requires": { + "@intervolga/optimize-cssnano-plugin": "^1.0.5", + "@soda/friendly-errors-webpack-plugin": "^1.7.1", + "@vue/cli-overlay": "^3.12.1", + "@vue/cli-shared-utils": "^3.12.1", + "@vue/component-compiler-utils": "^3.0.0", + "@vue/preload-webpack-plugin": "^1.1.0", + "@vue/web-component-wrapper": "^1.2.0", + "acorn": "^6.1.1", + "acorn-walk": "^6.1.1", + "address": "^1.0.3", + "autoprefixer": "^9.5.1", + "browserslist": "^4.5.4", + "cache-loader": "^2.0.1", + "case-sensitive-paths-webpack-plugin": "^2.2.0", + "chalk": "^2.4.2", + "cli-highlight": "^2.1.0", + "clipboardy": "^2.0.0", + "cliui": "^5.0.0", + "copy-webpack-plugin": "^4.6.0", + "css-loader": "^1.0.1", + "cssnano": "^4.1.10", + "current-script-polyfill": "^1.0.0", + "debug": "^4.1.1", + "default-gateway": "^5.0.2", + "dotenv": "^7.0.0", + "dotenv-expand": "^5.1.0", + "escape-string-regexp": "^1.0.5", + "file-loader": "^3.0.1", + "fs-extra": "^7.0.1", + "globby": "^9.2.0", + "hash-sum": "^1.0.2", + "html-webpack-plugin": "^3.2.0", + "launch-editor-middleware": "^2.2.1", + "lodash.defaultsdeep": "^4.6.1", + "lodash.mapvalues": "^4.6.0", + "lodash.transform": "^4.6.0", + "mini-css-extract-plugin": "^0.8.0", + "minimist": "^1.2.0", + "ora": "^3.4.0", + "portfinder": "^1.0.20", + "postcss-loader": "^3.0.0", + "read-pkg": "^5.0.0", + "semver": "^6.0.0", + "slash": "^2.0.0", + "source-map-url": "^0.4.0", + "ssri": "^6.0.1", + "string.prototype.padend": "^3.0.0", + "terser-webpack-plugin": "^1.2.3", + "thread-loader": "^2.1.2", + "url-loader": "^1.1.2", + "vue-loader": "^15.7.0", + "webpack": "^4.0.0", + "webpack-bundle-analyzer": "^3.3.0", + "webpack-chain": "^4.11.0", + "webpack-dev-server": "^3.4.1", + "webpack-merge": "^4.2.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz", + "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz", + "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-6.3.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-6.3.0.tgz", + "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=", + "dev": true + } + } + }, + "@vue/cli-shared-utils": { + "version": "3.12.1", + "resolved": "https://registry.npm.taobao.org/@vue/cli-shared-utils/download/@vue/cli-shared-utils-3.12.1.tgz?cache=0&sync_timestamp=1586274154670&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40vue%2Fcli-shared-utils%2Fdownload%2F%40vue%2Fcli-shared-utils-3.12.1.tgz", + "integrity": "sha1-vPB2KH3a3uu7l8anSN/p/1DsjfA=", + "dev": true, + "requires": { + "@hapi/joi": "^15.0.1", + "chalk": "^2.4.1", + "execa": "^1.0.0", + "launch-editor": "^2.2.1", + "lru-cache": "^5.1.1", + "node-ipc": "^9.1.1", + "open": "^6.3.0", + "ora": "^3.4.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.7", + "semver": "^6.0.0", + "string.prototype.padstart": "^3.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-6.3.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-6.3.0.tgz", + "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=", + "dev": true + } + } + }, + "@vue/component-compiler-utils": { + "version": "3.1.2", + "resolved": "https://registry.npm.taobao.org/@vue/component-compiler-utils/download/@vue/component-compiler-utils-3.1.2.tgz?cache=0&sync_timestamp=1586331302562&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40vue%2Fcomponent-compiler-utils%2Fdownload%2F%40vue%2Fcomponent-compiler-utils-3.1.2.tgz", + "integrity": "sha1-ghOl/zIC+fITf+VTcPnouWVggcM=", + "dev": true, + "requires": { + "consolidate": "^0.15.1", + "hash-sum": "^1.0.2", + "lru-cache": "^4.1.2", + "merge-source-map": "^1.1.0", + "postcss": "^7.0.14", + "postcss-selector-parser": "^6.0.2", + "prettier": "^1.18.2", + "source-map": "~0.6.1", + "vue-template-es2015-compiler": "^1.9.0" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npm.taobao.org/lru-cache/download/lru-cache-4.1.5.tgz", + "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/yallist/download/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, + "@vue/preload-webpack-plugin": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/@vue/preload-webpack-plugin/download/@vue/preload-webpack-plugin-1.1.1.tgz", + "integrity": "sha1-GHI1MNME9EMCHaIpLW7JUCgmEEo=", + "dev": true + }, + "@vue/web-component-wrapper": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/@vue/web-component-wrapper/download/@vue/web-component-wrapper-1.2.0.tgz", + "integrity": "sha1-uw5G8VhafiibTuYGfcxaauYvHdE=", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/ast/download/@webassemblyjs/ast-1.9.0.tgz?cache=0&sync_timestamp=1580599461432&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fast%2Fdownload%2F%40webassemblyjs%2Fast-1.9.0.tgz", + "integrity": "sha1-vYUGBLQEJFmlpBzX0zjL7Wle2WQ=", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/floating-point-hex-parser/download/@webassemblyjs/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha1-PD07Jxvd/ITesA9xNEQ4MR1S/7Q=", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-api-error/download/@webassemblyjs/helper-api-error-1.9.0.tgz", + "integrity": "sha1-ID9nbjM7lsnaLuqzzO8zxFkotqI=", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-buffer/download/@webassemblyjs/helper-buffer-1.9.0.tgz", + "integrity": "sha1-oUQtJpxf6yP8vJ73WdrDVH8p3gA=", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-code-frame/download/@webassemblyjs/helper-code-frame-1.9.0.tgz", + "integrity": "sha1-ZH+Iks0gQ6gqwMjF51w28dkVnyc=", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-fsm/download/@webassemblyjs/helper-fsm-1.9.0.tgz", + "integrity": "sha1-wFJWtxJEIUZx9LCOwQitY7cO3bg=", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-module-context/download/@webassemblyjs/helper-module-context-1.9.0.tgz", + "integrity": "sha1-JdiIS3aDmHGgimxvgGw5ee9xLwc=", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-wasm-bytecode/download/@webassemblyjs/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha1-T+2L6sm4wU+MWLcNEk1UndH+V5A=", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-wasm-section/download/@webassemblyjs/helper-wasm-section-1.9.0.tgz", + "integrity": "sha1-WkE41aYpK6GLBMWuSXF+QWeWU0Y=", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/ieee754/download/@webassemblyjs/ieee754-1.9.0.tgz", + "integrity": "sha1-Fceg+6roP7JhQ7us9tbfFwKtOeQ=", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/leb128/download/@webassemblyjs/leb128-1.9.0.tgz", + "integrity": "sha1-8Zygt2ptxVYjoJz/p2noOPoeHJU=", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/utf8/download/@webassemblyjs/utf8-1.9.0.tgz", + "integrity": "sha1-BNM7Y2945qaBMifoJAL3Y3tiKas=", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wasm-edit/download/@webassemblyjs/wasm-edit-1.9.0.tgz", + "integrity": "sha1-P+bXnT8PkiGDqoYALELdJWz+6c8=", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wasm-gen/download/@webassemblyjs/wasm-gen-1.9.0.tgz", + "integrity": "sha1-ULxw7Gje2OJ2OwGhQYv0NJGnpJw=", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wasm-opt/download/@webassemblyjs/wasm-opt-1.9.0.tgz", + "integrity": "sha1-IhEYHlsxMmRDzIES658LkChyGmE=", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wasm-parser/download/@webassemblyjs/wasm-parser-1.9.0.tgz", + "integrity": "sha1-nUjkSCbfSmWYKUqmyHRp1kL/9l4=", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wast-parser/download/@webassemblyjs/wast-parser-1.9.0.tgz", + "integrity": "sha1-MDERXXmsW9JhVWzsw/qQo+9FGRQ=", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wast-printer/download/@webassemblyjs/wast-printer-1.9.0.tgz", + "integrity": "sha1-STXVTIX+9jewDOn1I3dFHQDUeJk=", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/@xtuc/ieee754/download/@xtuc/ieee754-1.2.0.tgz", + "integrity": "sha1-7vAUoxRa5Hehy8AM0eVSM23Ot5A=", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npm.taobao.org/@xtuc/long/download/@xtuc/long-4.2.2.tgz", + "integrity": "sha1-0pHGpOl5ibXGHZrPOWrk/hM6cY0=", + "dev": true + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npm.taobao.org/accepts/download/accepts-1.3.7.tgz", + "integrity": "sha1-UxvHJlF6OytB+FACHGzBXqq1B80=", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "acorn": { + "version": "6.4.1", + "resolved": "https://registry.npm.taobao.org/acorn/download/acorn-6.4.1.tgz?cache=0&sync_timestamp=1589008014473&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Facorn%2Fdownload%2Facorn-6.4.1.tgz", + "integrity": "sha1-Ux5Yuj9RudrLmmZGyk3r9bFMpHQ=", + "dev": true + }, + "acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npm.taobao.org/acorn-walk/download/acorn-walk-6.2.0.tgz", + "integrity": "sha1-Ejy487hMIXHx9/slJhWxx4prGow=", + "dev": true + }, + "address": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/address/download/address-1.1.2.tgz", + "integrity": "sha1-vxEWycdYxRt6kz0pa3LCIe2UKLY=", + "dev": true + }, + "ajv": { + "version": "6.12.2", + "resolved": "https://registry.npm.taobao.org/ajv/download/ajv-6.12.2.tgz?cache=0&sync_timestamp=1587338477514&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv%2Fdownload%2Fajv-6.12.2.tgz", + "integrity": "sha1-xinF7O0XuvMUQ3kY0tqIyZ1ZWM0=", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/ajv-errors/download/ajv-errors-1.0.1.tgz", + "integrity": "sha1-81mGrOuRr63sQQL72FAUlQzvpk0=", + "dev": true + }, + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npm.taobao.org/ajv-keywords/download/ajv-keywords-3.4.1.tgz", + "integrity": "sha1-75FuJxxkrBIXH9g4TqrmsjRYVNo=", + "dev": true + }, + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/alphanum-sort/download/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", + "dev": true + }, + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npm.taobao.org/ansi-colors/download/ansi-colors-3.2.4.tgz", + "integrity": "sha1-46PaS/uubIapwoViXeEkojQCb78=", + "dev": true + }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npm.taobao.org/ansi-html/download/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "dev": true + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-4.1.0.tgz?cache=0&sync_timestamp=1570188570027&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-regex%2Fdownload%2Fansi-regex-4.1.0.tgz", + "integrity": "sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-3.2.1.tgz", + "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npm.taobao.org/any-promise/download/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", + "dev": true + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/anymatch/download/anymatch-2.0.0.tgz?cache=0&sync_timestamp=1569897341237&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fanymatch%2Fdownload%2Fanymatch-2.0.0.tgz", + "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/normalize-path/download/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/aproba/download/aproba-1.2.0.tgz", + "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo=", + "dev": true + }, + "arch": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/arch/download/arch-2.1.2.tgz", + "integrity": "sha1-DFK75zRLtPomDEQ9LLrZwA/y8L8=", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npm.taobao.org/argparse/download/argparse-1.0.10.tgz", + "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/arr-diff/download/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/arr-flatten/download/arr-flatten-1.1.0.tgz", + "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/arr-union/download/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/array-flatten/download/array-flatten-1.1.1.tgz?cache=0&sync_timestamp=1574313384951&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Farray-flatten%2Fdownload%2Farray-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/array-union/download/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/array-uniq/download/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npm.taobao.org/array-unique/download/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npm.taobao.org/asn1/download/asn1-0.2.4.tgz", + "integrity": "sha1-jSR136tVO7M+d7VOWeiAu4ziMTY=", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npm.taobao.org/asn1.js/download/asn1.js-4.10.1.tgz", + "integrity": "sha1-ucK/WAXx5kqt7tbfOiv6+1pz9aA=", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.8.tgz", + "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=", + "dev": true + } + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npm.taobao.org/assert/download/assert-1.5.0.tgz", + "integrity": "sha1-VcEJqvbgrv2z3EtxJAxwv1dLGOs=", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npm.taobao.org/util/download/util-0.10.3.tgz?cache=0&sync_timestamp=1588238435623&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Futil%2Fdownload%2Futil-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/assign-symbols/download/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npm.taobao.org/async/download/async-2.6.3.tgz?cache=0&sync_timestamp=1582513244496&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fasync%2Fdownload%2Fasync-2.6.3.tgz", + "integrity": "sha1-1yYl4jRKNlbjo61Pp0n6gymdgv8=", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/async-each/download/async-each-1.0.3.tgz", + "integrity": "sha1-tyfb+H12UWAvBvTUrDh/R9kbDL8=", + "dev": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/async-limiter/download/async-limiter-1.0.1.tgz", + "integrity": "sha1-3TeelPDbgxCwgpH51kwyCXZmF/0=", + "dev": true + }, + "async-validator": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-1.8.5.tgz", + "integrity": "sha512-tXBM+1m056MAX0E8TL2iCjg8WvSyXu0Zc8LNtYqrVeyoL3+esHRZ4SieE9fKQyyU09uONjnMEjrNBMqT0mbvmA==", + "requires": { + "babel-runtime": "6.x" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/atob/download/atob-2.1.2.tgz", + "integrity": "sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k=", + "dev": true + }, + "autoprefixer": { + "version": "9.7.6", + "resolved": "https://registry.npm.taobao.org/autoprefixer/download/autoprefixer-9.7.6.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fautoprefixer%2Fdownload%2Fautoprefixer-9.7.6.tgz", + "integrity": "sha1-Y6xbvAznk05plyB9W7ANaPqCk6Q=", + "dev": true, + "requires": { + "browserslist": "^4.11.1", + "caniuse-lite": "^1.0.30001039", + "chalk": "^2.4.2", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^7.0.27", + "postcss-value-parser": "^4.0.3" + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.9.1", + "resolved": "https://registry.npm.taobao.org/aws4/download/aws4-1.9.1.tgz", + "integrity": "sha1-fjPY99RJs/ZzzXLeuavcVS2+Uo4=", + "dev": true + }, + "axios": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "requires": { + "follow-redirects": "^1.10.0" + }, + "dependencies": { + "follow-redirects": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", + "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==" + } + } + }, + "axios-mock-adapter": { + "version": "1.18.1", + "resolved": "https://registry.npm.taobao.org/axios-mock-adapter/download/axios-mock-adapter-1.18.1.tgz", + "integrity": "sha1-oromOO9RPZVHk/lr3j4mvUobeUA=", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "is-buffer": "^2.0.3" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npm.taobao.org/babel-code-frame/download/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz?cache=0&sync_timestamp=1570188570027&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-regex%2Fdownload%2Fansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/chalk/download/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npm.taobao.org/js-tokens/download/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "babel-helper-vue-jsx-merge-props": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz", + "integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg==" + }, + "babel-loader": { + "version": "8.1.0", + "resolved": "https://registry.npm.taobao.org/babel-loader/download/babel-loader-8.1.0.tgz?cache=0&sync_timestamp=1584715910722&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbabel-loader%2Fdownload%2Fbabel-loader-8.1.0.tgz", + "integrity": "sha1-xhHVESvVIJq+i5+oTD5NolJ18cM=", + "dev": true, + "requires": { + "find-cache-dir": "^2.1.0", + "loader-utils": "^1.4.0", + "mkdirp": "^0.5.3", + "pify": "^4.0.1", + "schema-utils": "^2.6.5" + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npm.taobao.org/babel-plugin-dynamic-import-node/download/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha1-hP2hnJduxcbe/vV/lCez3vZuF6M=", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-module-resolver": { + "version": "3.2.0", + "resolved": "https://registry.npm.taobao.org/babel-plugin-module-resolver/download/babel-plugin-module-resolver-3.2.0.tgz", + "integrity": "sha1-3fpeMB47mqEthSqZefGLN4gf9ac=", + "dev": true, + "requires": { + "find-babel-config": "^1.1.0", + "glob": "^7.1.2", + "pkg-up": "^2.0.0", + "reselect": "^3.0.1", + "resolve": "^1.4.0" + } + }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npm.taobao.org/babel-polyfill/download/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "requires": { + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npm.taobao.org/babel-runtime/download/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.11.1.tgz", + "integrity": "sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk=" + } + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npm.taobao.org/base/download/base-0.11.2.tgz", + "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npm.taobao.org/base64-js/download/base64-js-1.3.1.tgz", + "integrity": "sha1-WOzoy3XdB+ce0IxzarxfrE2/jfE=", + "dev": true + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/batch/download/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/bcrypt-pbkdf/download/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bfj": { + "version": "6.1.2", + "resolved": "https://registry.npm.taobao.org/bfj/download/bfj-6.1.2.tgz", + "integrity": "sha1-MlyGGoIryzWKQceKM7jm4ght3n8=", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "check-types": "^8.0.3", + "hoopy": "^0.1.4", + "tryer": "^1.0.1" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npm.taobao.org/big.js/download/big.js-5.2.2.tgz", + "integrity": "sha1-ZfCvOC9Xi83HQr2cKB6cstd2gyg=", + "dev": true + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npm.taobao.org/binary-extensions/download/binary-extensions-1.13.1.tgz", + "integrity": "sha1-WYr+VHVbKGilMw0q/51Ou1Mgm2U=", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npm.taobao.org/bindings/download/bindings-1.5.0.tgz", + "integrity": "sha1-EDU8npRTNLwFEabZCzj7x8nFBN8=", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npm.taobao.org/bluebird/download/bluebird-3.7.2.tgz", + "integrity": "sha1-nyKcFb4nJFT/qXOs4NvueaGww28=", + "dev": true + }, + "bn.js": { + "version": "5.1.1", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-5.1.1.tgz", + "integrity": "sha1-SO/EAxqcQEG5yZxpQdkDRjq2LrU=", + "dev": true + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npm.taobao.org/body-parser/download/body-parser-1.19.0.tgz", + "integrity": "sha1-lrJwnlfJxOCab9Zqj9l5hE9p8Io=", + "dev": true, + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npm.taobao.org/qs/download/qs-6.7.0.tgz", + "integrity": "sha1-QdwaAV49WB8WIXdr4xr7KHapsbw=", + "dev": true + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npm.taobao.org/bonjour/download/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "requires": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + }, + "dependencies": { + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/array-flatten/download/array-flatten-2.1.2.tgz?cache=0&sync_timestamp=1574313384951&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Farray-flatten%2Fdownload%2Farray-flatten-2.1.2.tgz", + "integrity": "sha1-JO+AoowaiTYX4hSbDG0NeIKTsJk=", + "dev": true + } + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/boolbase/download/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npm.taobao.org/brace-expansion/download/brace-expansion-1.1.11.tgz", + "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npm.taobao.org/braces/download/braces-2.3.2.tgz", + "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/brorand/download/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/browserify-aes/download/browserify-aes-1.2.0.tgz", + "integrity": "sha1-Mmc0ZC9APavDADIJhTu3CtQo70g=", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/browserify-cipher/download/browserify-cipher-1.0.1.tgz", + "integrity": "sha1-jWR0wbhwv9q807z8wZNKEOlPFfA=", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/browserify-des/download/browserify-des-1.0.2.tgz", + "integrity": "sha1-OvTx9Zg5QDVy8cZiBDdfen9wPpw=", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/browserify-rsa/download/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.8.tgz", + "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=", + "dev": true + } + } + }, + "browserify-sign": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/browserify-sign/download/browserify-sign-4.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbrowserify-sign%2Fdownload%2Fbrowserify-sign-4.1.0.tgz", + "integrity": "sha1-T+lxs3mlrrSSXgZ3n5+h9B0knXA=", + "dev": true, + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.2", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.6.0.tgz", + "integrity": "sha1-M3u9o63AcGvT4CRCaihtS0sskZg=", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npm.taobao.org/browserify-zlib/download/browserify-zlib-0.2.0.tgz", + "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.12.0", + "resolved": "https://registry.npm.taobao.org/browserslist/download/browserslist-4.12.0.tgz", + "integrity": "sha1-BsbVcVoe3mxR/Dn/Z/1kf3QLZW0=", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001043", + "electron-to-chromium": "^1.3.413", + "node-releases": "^1.1.53", + "pkg-up": "^2.0.0" + } + }, + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npm.taobao.org/buffer/download/buffer-4.9.2.tgz?cache=0&sync_timestamp=1588713323419&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbuffer%2Fdownload%2Fbuffer-4.9.2.tgz", + "integrity": "sha1-Iw6tNEACmIZEhBqwJEr4xEu+Pvg=", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/buffer-from/download/buffer-from-1.1.1.tgz", + "integrity": "sha1-MnE7wCj3XAL9txDXx7zsHyxgcO8=", + "dev": true + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/buffer-indexof/download/buffer-indexof-1.1.1.tgz", + "integrity": "sha1-Uvq8xqYG0aADAoAmSO9o9jnaJow=", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/buffer-xor/download/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/builtin-status-codes/download/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/bytes/download/bytes-3.1.0.tgz", + "integrity": "sha1-9s95M6Ng4FiPqf3oVlHNx/gF0fY=", + "dev": true + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npm.taobao.org/cacache/download/cacache-12.0.4.tgz", + "integrity": "sha1-ZovL0QWutfHZL+JVcOyVJcj6pAw=", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/cache-base/download/cache-base-1.0.1.tgz", + "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "cache-loader": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/cache-loader/download/cache-loader-2.0.1.tgz", + "integrity": "sha1-V1j0GmLXwjlB48PHAW5vrrA6ywc=", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "mkdirp": "^0.5.1", + "neo-async": "^2.6.0", + "normalize-path": "^3.0.0", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz?cache=0&sync_timestamp=1587138453873&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fschema-utils%2Fdownload%2Fschema-utils-1.0.0.tgz", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/call-me-maybe/download/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", + "dev": true + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/caller-callsite/download/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "requires": { + "callsites": "^2.0.0" + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/caller-path/download/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/callsites/download/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + }, + "camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/camel-case/download/camel-case-3.0.0.tgz?cache=0&sync_timestamp=1576721717499&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcamel-case%2Fdownload%2Fcamel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "dev": true, + "requires": { + "no-case": "^2.2.0", + "upper-case": "^1.1.1" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npm.taobao.org/camelcase/download/camelcase-5.3.1.tgz", + "integrity": "sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA=", + "dev": true + }, + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/caniuse-api/download/caniuse-api-3.0.0.tgz", + "integrity": "sha1-Xk2Q4idJYdRikZl99Znj7QCO5MA=", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "caniuse-lite": { + "version": "1.0.30001055", + "resolved": "https://registry.npm.taobao.org/caniuse-lite/download/caniuse-lite-1.0.30001055.tgz?cache=0&sync_timestamp=1589157211835&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcaniuse-lite%2Fdownload%2Fcaniuse-lite-1.0.30001055.tgz", + "integrity": "sha1-e1LDU396jAQIrKhn6D0rBCaLVM0=", + "dev": true + }, + "case-sensitive-paths-webpack-plugin": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/case-sensitive-paths-webpack-plugin/download/case-sensitive-paths-webpack-plugin-2.3.0.tgz", + "integrity": "sha1-I6xhPMmoVuT4j/i7c7u16YmCXPc=", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npm.taobao.org/caseless/download/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npm.taobao.org/chalk/download/chalk-2.4.2.tgz", + "integrity": "sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "check-types": { + "version": "8.0.3", + "resolved": "https://registry.npm.taobao.org/check-types/download/check-types-8.0.3.tgz", + "integrity": "sha1-M1bMoZyIlUTy16le1JzlCKDs9VI=", + "dev": true + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npm.taobao.org/chokidar/download/chokidar-2.1.8.tgz", + "integrity": "sha1-gEs6e2qZNYw8XGHnHYco8EHP+Rc=", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npm.taobao.org/chownr/download/chownr-1.1.4.tgz?cache=0&sync_timestamp=1581474805672&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchownr%2Fdownload%2Fchownr-1.1.4.tgz", + "integrity": "sha1-b8nXtC0ypYNZYzdmbn0ICE2izGs=", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/chrome-trace-event/download/chrome-trace-event-1.0.2.tgz", + "integrity": "sha1-I0CQ7pfH1K0aLEvq4nUF3v/GCKQ=", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/cipher-base/download/cipher-base-1.0.4.tgz", + "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npm.taobao.org/class-utils/download/class-utils-0.3.6.tgz", + "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "clean-css": { + "version": "4.2.3", + "resolved": "https://registry.npm.taobao.org/clean-css/download/clean-css-4.2.3.tgz", + "integrity": "sha1-UHtd59l7SO5T2ErbAWD/YhY4D3g=", + "dev": true, + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + } + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/cli-cursor/download/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-highlight": { + "version": "2.1.4", + "resolved": "https://registry.npm.taobao.org/cli-highlight/download/cli-highlight-2.1.4.tgz?cache=0&sync_timestamp=1573949240542&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcli-highlight%2Fdownload%2Fcli-highlight-2.1.4.tgz", + "integrity": "sha1-CYy2Qs8X9CrcHBFF4H+WDsTXUis=", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "highlight.js": "^9.6.0", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^5.1.1", + "yargs": "^15.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-4.2.1.tgz", + "integrity": "sha1-kK51xCTQCNJiTFvynq0xd+v881k=", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/chalk/download/chalk-3.0.0.tgz", + "integrity": "sha1-P3PCv1JlkfV0zEksUeJFY0n4ROQ=", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz", + "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npm.taobao.org/color-name/download/color-name-1.1.4.tgz", + "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-4.0.0.tgz", + "integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.1.0.tgz", + "integrity": "sha1-aOMlkd9z4lrRxLSRCKLsUHliv9E=", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "cli-spinners": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/cli-spinners/download/cli-spinners-2.3.0.tgz", + "integrity": "sha1-BjIjmktapMlYYQFCw0u3plH8jfU=", + "dev": true + }, + "clipboard": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz", + "integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==", + "requires": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, + "clipboardy": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/clipboardy/download/clipboardy-2.3.0.tgz", + "integrity": "sha1-PCkDZQxo5GqRs4iYW8J3QofbopA=", + "dev": true, + "requires": { + "arch": "^2.1.1", + "execa": "^1.0.0", + "is-wsl": "^2.1.1" + }, + "dependencies": { + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/is-wsl/download/is-wsl-2.2.0.tgz", + "integrity": "sha1-dKTHbnfKn9P5MvKQwX6jJs0VcnE=", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + } + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/cliui/download/cliui-5.0.0.tgz", + "integrity": "sha1-3u/P2y6AB4SqNPRvoI4GhRx7u8U=", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npm.taobao.org/emoji-regex/download/emoji-regex-7.0.3.tgz", + "integrity": "sha1-kzoEBShgyF6DwSJHnEdIqOTHIVY=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-3.1.0.tgz", + "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-5.1.0.tgz", + "integrity": "sha1-H9H2cjXVttD+54EFYAG/tpTAOwk=", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + } + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/clone/download/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + }, + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/coa/download/coa-2.0.2.tgz", + "integrity": "sha1-Q/bCEVG07yv1cYfbDXPeIp4+fsM=", + "dev": true, + "requires": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/collection-visit/download/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color": { + "version": "3.1.2", + "resolved": "https://registry.npm.taobao.org/color/download/color-3.1.2.tgz", + "integrity": "sha1-aBSOf4XUGtdknF+oyBBvCY0inhA=", + "dev": true, + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-1.9.3.tgz", + "integrity": "sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/color-name/download/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npm.taobao.org/color-string/download/color-string-1.5.3.tgz", + "integrity": "sha1-ybvF8BtYtUkvPWhXRZy2WQziBMw=", + "dev": true, + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npm.taobao.org/combined-stream/download/combined-stream-1.0.8.tgz", + "integrity": "sha1-w9RaizT9cwYxoRCoolIGgrMdWn8=", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npm.taobao.org/commander/download/commander-2.20.3.tgz", + "integrity": "sha1-/UhehMA+tIgcIHIrpIA16FMa6zM=" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/commondir/download/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npm.taobao.org/component-emitter/download/component-emitter-1.3.0.tgz", + "integrity": "sha1-FuQHD7qK4ptnnyIVhT7hgasuq8A=", + "dev": true + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npm.taobao.org/compressible/download/compressible-2.0.18.tgz", + "integrity": "sha1-r1PMprBw1MPAdQ+9dyhqbXzEb7o=", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npm.taobao.org/compression/download/compression-1.7.4.tgz?cache=0&sync_timestamp=1573614508541&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcompression%2Fdownload%2Fcompression-1.7.4.tgz", + "integrity": "sha1-lVI+/xcMpXwpoMpB5v4TH0Hlu48=", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/bytes/download/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npm.taobao.org/concat-map/download/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npm.taobao.org/concat-stream/download/concat-stream-1.6.2.tgz", + "integrity": "sha1-kEvfGUzTEi/Gdcd/xKw9T/D9GjQ=", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npm.taobao.org/connect-history-api-fallback/download/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha1-izIIk1kwjRERFdgcrT/Oq4iPl7w=", + "dev": true + }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/console-browserify/download/console-browserify-1.2.0.tgz", + "integrity": "sha1-ZwY871fOts9Jk6KrOlWECujEkzY=", + "dev": true + }, + "consolidate": { + "version": "0.15.1", + "resolved": "https://registry.npm.taobao.org/consolidate/download/consolidate-0.15.1.tgz", + "integrity": "sha1-IasEMjXHGgfUXZqtmFk7DbpWurc=", + "dev": true, + "requires": { + "bluebird": "^3.1.1" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/constants-browserify/download/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npm.taobao.org/content-disposition/download/content-disposition-0.5.3.tgz", + "integrity": "sha1-4TDK9+cnkIfFYWwgB9BIVpiYT70=", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/content-type/download/content-type-1.0.4.tgz", + "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=", + "dev": true + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npm.taobao.org/convert-source-map/download/convert-source-map-1.7.0.tgz", + "integrity": "sha1-F6LLiC1/d9NJBYXizmxSRCSjpEI=", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npm.taobao.org/cookie/download/cookie-0.4.0.tgz", + "integrity": "sha1-vrQ35wIrO21JAZ0IhmUwPr6cFLo=", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npm.taobao.org/cookie-signature/download/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npm.taobao.org/copy-concurrently/download/copy-concurrently-1.0.5.tgz", + "integrity": "sha1-kilzmMrjSTf8r9bsgTnBgFHwteA=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npm.taobao.org/copy-descriptor/download/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "copy-webpack-plugin": { + "version": "4.6.0", + "resolved": "https://registry.npm.taobao.org/copy-webpack-plugin/download/copy-webpack-plugin-4.6.0.tgz?cache=0&sync_timestamp=1576145009360&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcopy-webpack-plugin%2Fdownload%2Fcopy-webpack-plugin-4.6.0.tgz", + "integrity": "sha1-5/QN2KaEd9QF3Rt6hUquMksVi64=", + "dev": true, + "requires": { + "cacache": "^10.0.4", + "find-cache-dir": "^1.0.0", + "globby": "^7.1.1", + "is-glob": "^4.0.0", + "loader-utils": "^1.1.0", + "minimatch": "^3.0.4", + "p-limit": "^1.0.0", + "serialize-javascript": "^1.4.0" + }, + "dependencies": { + "cacache": { + "version": "10.0.4", + "resolved": "https://registry.npm.taobao.org/cacache/download/cacache-10.0.4.tgz", + "integrity": "sha1-ZFI2eZnv+dQYiu/ZoU6dfGomNGA=", + "dev": true, + "requires": { + "bluebird": "^3.5.1", + "chownr": "^1.0.1", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.1", + "mississippi": "^2.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^5.2.4", + "unique-filename": "^1.1.0", + "y18n": "^4.0.0" + } + }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^2.0.0" + } + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npm.taobao.org/globby/download/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "dir-glob": "^2.0.0", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + } + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npm.taobao.org/lru-cache/download/lru-cache-4.1.5.tgz", + "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npm.taobao.org/make-dir/download/make-dir-1.3.0.tgz?cache=0&sync_timestamp=1587567610342&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmake-dir%2Fdownload%2Fmake-dir-1.3.0.tgz", + "integrity": "sha1-ecEDO4BRW9bSTsmTPoYMp17ifww=", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "mississippi": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/mississippi/download/mississippi-2.0.0.tgz", + "integrity": "sha1-NEKlCPr8KFAEhv7qmUCWduTuWm8=", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^2.0.1", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/pify/download/pify-3.0.0.tgz?cache=0&sync_timestamp=1581697613983&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpify%2Fdownload%2Fpify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/pump/download/pump-2.0.1.tgz", + "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "serialize-javascript": { + "version": "1.9.1", + "resolved": "https://registry.npm.taobao.org/serialize-javascript/download/serialize-javascript-1.9.1.tgz", + "integrity": "sha1-z8IArvd7YAxH2pu4FJyUPnmML9s=", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/slash/download/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "ssri": { + "version": "5.3.0", + "resolved": "https://registry.npm.taobao.org/ssri/download/ssri-5.3.0.tgz", + "integrity": "sha1-ujhyycbTOgcEp9cf8EXl7EiZnQY=", + "dev": true, + "requires": { + "safe-buffer": "^5.1.1" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/yallist/download/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npm.taobao.org/core-js/download/core-js-2.6.11.tgz?cache=0&sync_timestamp=1586452619235&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcore-js%2Fdownload%2Fcore-js-2.6.11.tgz", + "integrity": "sha1-OIMUafmSK97Y7iHJ3EaYXgOZMIw=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npm.taobao.org/cosmiconfig/download/cosmiconfig-5.2.1.tgz", + "integrity": "sha1-BA9yaAnFked6F8CjYmykW08Wixo=", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npm.taobao.org/create-ecdh/download/create-ecdh-4.0.3.tgz", + "integrity": "sha1-yREbbzMEXEaX8UR4f5JUzcd8Rf8=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.8.tgz", + "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=", + "dev": true + } + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/create-hash/download/create-hash-1.2.0.tgz", + "integrity": "sha1-iJB4rxGmN1a8+1m9IhmWvjqe8ZY=", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npm.taobao.org/create-hmac/download/create-hmac-1.1.7.tgz", + "integrity": "sha1-aRcMeLOrlXFHsriwRXLkfq0iQ/8=", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cropperjs": { + "version": "1.5.6", + "resolved": "https://registry.npm.taobao.org/cropperjs/download/cropperjs-1.5.6.tgz", + "integrity": "sha1-gvr0Mr7HCdgo8vepbRF5GY7a8OI=" + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-6.0.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcross-spawn%2Fdownload%2Fcross-spawn-6.0.5.tgz", + "integrity": "sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q=", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npm.taobao.org/crypto-browserify/download/crypto-browserify-3.12.0.tgz", + "integrity": "sha1-OWz58xN/A+S45TLFj2mCVOAPgOw=", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npm.taobao.org/css-color-names/download/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", + "dev": true + }, + "css-declaration-sorter": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/css-declaration-sorter/download/css-declaration-sorter-4.0.1.tgz", + "integrity": "sha1-wZiUD2OnbX42wecQGLABchBUyyI=", + "dev": true, + "requires": { + "postcss": "^7.0.1", + "timsort": "^0.3.0" + } + }, + "css-loader": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/css-loader/download/css-loader-1.0.1.tgz", + "integrity": "sha1-aIW7UjOzXsR7AGBX2gHMZAtref4=", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "css-selector-tokenizer": "^0.7.0", + "icss-utils": "^2.1.0", + "loader-utils": "^1.0.2", + "lodash": "^4.17.11", + "postcss": "^6.0.23", + "postcss-modules-extract-imports": "^1.2.0", + "postcss-modules-local-by-default": "^1.2.0", + "postcss-modules-scope": "^1.1.0", + "postcss-modules-values": "^1.3.0", + "postcss-value-parser": "^3.3.0", + "source-list-map": "^2.0.0" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npm.taobao.org/postcss/download/postcss-6.0.23.tgz?cache=0&sync_timestamp=1589206165064&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss%2Fdownload%2Fpostcss-6.0.23.tgz", + "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&sync_timestamp=1588083303810&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + } + } + }, + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/css-select/download/css-select-2.1.0.tgz", + "integrity": "sha1-ajRlM1ZjWTSoG6ymjQJVQyEF2+8=", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npm.taobao.org/css-select-base-adapter/download/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha1-Oy/0lyzDYquIVhUHqVQIoUMhNdc=", + "dev": true + }, + "css-selector-tokenizer": { + "version": "0.7.2", + "resolved": "https://registry.npm.taobao.org/css-selector-tokenizer/download/css-selector-tokenizer-0.7.2.tgz?cache=0&sync_timestamp=1583234719732&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcss-selector-tokenizer%2Fdownload%2Fcss-selector-tokenizer-0.7.2.tgz", + "integrity": "sha1-EeXifJpI2QKE8i1FBhwwPXolrYc=", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "fastparse": "^1.1.2", + "regexpu-core": "^4.6.0" + } + }, + "css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npm.taobao.org/css-tree/download/css-tree-1.0.0-alpha.37.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcss-tree%2Fdownload%2Fcss-tree-1.0.0-alpha.37.tgz", + "integrity": "sha1-mL69YsTB2flg7DQM+fdSLjBwmiI=", + "dev": true, + "requires": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + } + } + }, + "css-what": { + "version": "3.2.1", + "resolved": "https://registry.npm.taobao.org/css-what/download/css-what-3.2.1.tgz", + "integrity": "sha1-9KjxJCEGRiG0VnVeNKA6LCLfXaE=", + "dev": true + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/cssesc/download/cssesc-3.0.0.tgz", + "integrity": "sha1-N3QZGZA7hoVl4cCep0dEXNGJg+4=", + "dev": true + }, + "cssfilter": { + "version": "0.0.10", + "resolved": "https://registry.npm.taobao.org/cssfilter/download/cssfilter-0.0.10.tgz", + "integrity": "sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4=" + }, + "cssnano": { + "version": "4.1.10", + "resolved": "https://registry.npm.taobao.org/cssnano/download/cssnano-4.1.10.tgz", + "integrity": "sha1-CsQfCxPRPUZUh+ERt3jULaYxuLI=", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.0", + "cssnano-preset-default": "^4.0.7", + "is-resolvable": "^1.0.0", + "postcss": "^7.0.0" + } + }, + "cssnano-preset-default": { + "version": "4.0.7", + "resolved": "https://registry.npm.taobao.org/cssnano-preset-default/download/cssnano-preset-default-4.0.7.tgz", + "integrity": "sha1-UexmLM/KD4izltzZZ5zbkxvhf3Y=", + "dev": true, + "requires": { + "css-declaration-sorter": "^4.0.1", + "cssnano-util-raw-cache": "^4.0.1", + "postcss": "^7.0.0", + "postcss-calc": "^7.0.1", + "postcss-colormin": "^4.0.3", + "postcss-convert-values": "^4.0.1", + "postcss-discard-comments": "^4.0.2", + "postcss-discard-duplicates": "^4.0.2", + "postcss-discard-empty": "^4.0.1", + "postcss-discard-overridden": "^4.0.1", + "postcss-merge-longhand": "^4.0.11", + "postcss-merge-rules": "^4.0.3", + "postcss-minify-font-values": "^4.0.2", + "postcss-minify-gradients": "^4.0.2", + "postcss-minify-params": "^4.0.2", + "postcss-minify-selectors": "^4.0.2", + "postcss-normalize-charset": "^4.0.1", + "postcss-normalize-display-values": "^4.0.2", + "postcss-normalize-positions": "^4.0.2", + "postcss-normalize-repeat-style": "^4.0.2", + "postcss-normalize-string": "^4.0.2", + "postcss-normalize-timing-functions": "^4.0.2", + "postcss-normalize-unicode": "^4.0.1", + "postcss-normalize-url": "^4.0.1", + "postcss-normalize-whitespace": "^4.0.2", + "postcss-ordered-values": "^4.1.2", + "postcss-reduce-initial": "^4.0.3", + "postcss-reduce-transforms": "^4.0.2", + "postcss-svgo": "^4.0.2", + "postcss-unique-selectors": "^4.0.1" + } + }, + "cssnano-util-get-arguments": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/cssnano-util-get-arguments/download/cssnano-util-get-arguments-4.0.0.tgz", + "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=", + "dev": true + }, + "cssnano-util-get-match": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/cssnano-util-get-match/download/cssnano-util-get-match-4.0.0.tgz", + "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=", + "dev": true + }, + "cssnano-util-raw-cache": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/cssnano-util-raw-cache/download/cssnano-util-raw-cache-4.0.1.tgz", + "integrity": "sha1-sm1f1fcqEd/np4RvtMZyYPlr8oI=", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "cssnano-util-same-parent": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/cssnano-util-same-parent/download/cssnano-util-same-parent-4.0.1.tgz", + "integrity": "sha1-V0CC+yhZ0ttDOFWDXZqEVuoYu/M=", + "dev": true + }, + "csso": { + "version": "4.0.3", + "resolved": "https://registry.npm.taobao.org/csso/download/csso-4.0.3.tgz?cache=0&sync_timestamp=1585052130344&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcsso%2Fdownload%2Fcsso-4.0.3.tgz", + "integrity": "sha1-DZmF3IUsfMKyys+74QeQFNGo6QM=", + "dev": true, + "requires": { + "css-tree": "1.0.0-alpha.39" + }, + "dependencies": { + "css-tree": { + "version": "1.0.0-alpha.39", + "resolved": "https://registry.npm.taobao.org/css-tree/download/css-tree-1.0.0-alpha.39.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcss-tree%2Fdownload%2Fcss-tree-1.0.0-alpha.39.tgz", + "integrity": "sha1-K/8//huz93bPfu/ZHuXLp3oUnus=", + "dev": true, + "requires": { + "mdn-data": "2.0.6", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.6", + "resolved": "https://registry.npm.taobao.org/mdn-data/download/mdn-data-2.0.6.tgz?cache=0&sync_timestamp=1584029207120&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmdn-data%2Fdownload%2Fmdn-data-2.0.6.tgz", + "integrity": "sha1-hS3GD8ql2qLoz2yRicRA7T4EKXg=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + } + } + }, + "current-script-polyfill": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/current-script-polyfill/download/current-script-polyfill-1.0.0.tgz", + "integrity": "sha1-8xz35PPiGLBybnOMqSoC00iO9hU=", + "dev": true + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/cyclist/download/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/de-indent/download/de-indent-1.0.2.tgz", + "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/decamelize/download/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npm.taobao.org/decode-uri-component/download/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/deep-equal/download/deep-equal-1.1.1.tgz", + "integrity": "sha1-tcmMlCzv+vfLBR4k4UNKJaLmB2o=", + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + } + }, + "deepmerge": { + "version": "1.5.2", + "resolved": "https://registry.npm.taobao.org/deepmerge/download/deepmerge-1.5.2.tgz", + "integrity": "sha1-EEmdhohEza1P7ghC34x/bwyVp1M=" + }, + "default-gateway": { + "version": "5.0.5", + "resolved": "https://registry.npm.taobao.org/default-gateway/download/default-gateway-5.0.5.tgz", + "integrity": "sha1-T9a9XShV05s0zFpZUFSG6ar8mxA=", + "dev": true, + "requires": { + "execa": "^3.3.0" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.2", + "resolved": "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-7.0.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcross-spawn%2Fdownload%2Fcross-spawn-7.0.2.tgz", + "integrity": "sha1-0Nfc+nTokRXHYZ9PchqU4f23FtY=", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "execa": { + "version": "3.4.0", + "resolved": "https://registry.npm.taobao.org/execa/download/execa-3.4.0.tgz", + "integrity": "sha1-wI7UVQ72XYWPrCaf/IVyRG8364k=", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "p-finally": "^2.0.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npm.taobao.org/get-stream/download/get-stream-5.1.0.tgz", + "integrity": "sha1-ASA83JJZf5uQkGfD5lbMH008Tck=", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/is-stream/download/is-stream-2.0.0.tgz", + "integrity": "sha1-venDJoDW+uBBKdasnZIc54FfeOM=", + "dev": true + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/mimic-fn/download/mimic-fn-2.1.0.tgz", + "integrity": "sha1-ftLCzMyvhNP/y3pptXcR/CCDQBs=", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/npm-run-path/download/npm-run-path-4.0.1.tgz", + "integrity": "sha1-t+zR5e1T2o43pV4cImnguX7XSOo=", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npm.taobao.org/onetime/download/onetime-5.1.0.tgz", + "integrity": "sha1-//DzyRYX/mK7UBiWNumayKbfe+U=", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "p-finally": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/p-finally/download/p-finally-2.0.1.tgz", + "integrity": "sha1-vW/KqcVZoJa2gIBvTWV7Pw8kBWE=", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/path-key/download/path-key-3.1.1.tgz", + "integrity": "sha1-WB9q3mWMu6ZaDTOA3ndTKVBU83U=", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/shebang-command/download/shebang-command-2.0.0.tgz", + "integrity": "sha1-zNCvT4g1+9wmW4JGGq8MNmY/NOo=", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/shebang-regex/download/shebang-regex-3.0.0.tgz", + "integrity": "sha1-rhbxZE2HPsrYQ7AwexQzYtTEIXI=", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/which/download/which-2.0.2.tgz", + "integrity": "sha1-fGqN0KY2oDJ+ELWckobu6T8/UbE=", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/defaults/download/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "^1.0.2" + }, + "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/clone/download/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + } + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/define-properties/download/define-properties-1.1.3.tgz", + "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=", + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-2.0.2.tgz", + "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "del": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/del/download/del-4.1.1.tgz", + "integrity": "sha1-no8RciLqRKMf86FWwEm5kFKp8LQ=", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "dependencies": { + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npm.taobao.org/globby/download/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz?cache=0&sync_timestamp=1581697613983&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpify%2Fdownload%2Fpify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/depd/download/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/des.js/download/des.js-1.0.1.tgz", + "integrity": "sha1-U4IULhvcU/hdhtU+X0qn3rkeCEM=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/destroy/download/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npm.taobao.org/detect-node/download/detect-node-2.0.4.tgz", + "integrity": "sha1-AU7o+PZpxcWAI9pkuBecCDooxGw=", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npm.taobao.org/diffie-hellman/download/diffie-hellman-5.0.3.tgz", + "integrity": "sha1-QOjumPVaIUlgcUaSHGPhrl89KHU=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.8.tgz", + "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=", + "dev": true + } + } + }, + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npm.taobao.org/dir-glob/download/dir-glob-2.2.2.tgz", + "integrity": "sha1-+gnwaUFTyJGLGLoN6vrpR2n8UMQ=", + "dev": true, + "requires": { + "path-type": "^3.0.0" + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/dns-equal/download/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "dns-packet": { + "version": "1.3.1", + "resolved": "https://registry.npm.taobao.org/dns-packet/download/dns-packet-1.3.1.tgz", + "integrity": "sha1-EqpCaYEHW+UAuRDu3NC0fdfe2lo=", + "dev": true, + "requires": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/dns-txt/download/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "requires": { + "buffer-indexof": "^1.0.0" + } + }, + "dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npm.taobao.org/dom-converter/download/dom-converter-0.2.0.tgz", + "integrity": "sha1-ZyGp2u4uKTaClVtq/kFncWJ7t2g=", + "dev": true, + "requires": { + "utila": "~0.4" + } + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npm.taobao.org/dom-serializer/download/dom-serializer-0.2.2.tgz?cache=0&sync_timestamp=1589067578490&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdom-serializer%2Fdownload%2Fdom-serializer-0.2.2.tgz", + "integrity": "sha1-GvuB9TNxcXXUeGVd68XjMtn5u1E=", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/domelementtype/download/domelementtype-2.0.1.tgz", + "integrity": "sha1-H4vf6R9aeAYydOgDtL3O326U+U0=", + "dev": true + } + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/domain-browser/download/domain-browser-1.2.0.tgz?cache=0&sync_timestamp=1589250265039&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomain-browser%2Fdownload%2Fdomain-browser-1.2.0.tgz", + "integrity": "sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto=", + "dev": true + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npm.taobao.org/domelementtype/download/domelementtype-1.3.1.tgz", + "integrity": "sha1-0EjESzew0Qp/Kj1f7j9DM9eQSB8=", + "dev": true + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npm.taobao.org/domhandler/download/domhandler-2.4.2.tgz", + "integrity": "sha1-iAUJfpM9ZehVRvcm1g9euItE+AM=", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npm.taobao.org/domutils/download/domutils-1.7.0.tgz?cache=0&sync_timestamp=1589053312321&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomutils%2Fdownload%2Fdomutils-1.7.0.tgz", + "integrity": "sha1-Vuo0HoNOBuZ0ivehyyXaZ+qfjCo=", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "dot-prop": { + "version": "5.2.0", + "resolved": "https://registry.npm.taobao.org/dot-prop/download/dot-prop-5.2.0.tgz", + "integrity": "sha1-w07MKVVtxF8fTCJpe29JBODMT8s=", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "dotenv": { + "version": "7.0.0", + "resolved": "https://registry.npm.taobao.org/dotenv/download/dotenv-7.0.0.tgz?cache=0&sync_timestamp=1571191376500&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdotenv%2Fdownload%2Fdotenv-7.0.0.tgz", + "integrity": "sha1-or481Sc2ZzIG6KhftSEO6ilijnw=", + "dev": true + }, + "dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npm.taobao.org/dotenv-expand/download/dotenv-expand-5.1.0.tgz", + "integrity": "sha1-P7rwIL/XlIhAcuomsel5HUWmKfA=", + "dev": true + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npm.taobao.org/duplexer/download/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npm.taobao.org/duplexify/download/duplexify-3.7.1.tgz", + "integrity": "sha1-Kk31MX9sz9kfhtb9JdjYoQO4gwk=", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "easy-stack": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/easy-stack/download/easy-stack-1.0.0.tgz", + "integrity": "sha1-EskbMIWjfwuqM26UhurEv5Tj54g=", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npm.taobao.org/ecc-jsbn/download/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/ee-first/download/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "ejs": { + "version": "2.7.4", + "resolved": "https://registry.npm.taobao.org/ejs/download/ejs-2.7.4.tgz", + "integrity": "sha1-SGYSh1c9zFPjZsehrlLDoSDuybo=", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.433", + "resolved": "https://registry.npm.taobao.org/electron-to-chromium/download/electron-to-chromium-1.3.433.tgz?cache=0&sync_timestamp=1589256459947&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Felectron-to-chromium%2Fdownload%2Felectron-to-chromium-1.3.433.tgz", + "integrity": "sha1-Xn2iLrhSlV9rFXWWvdib7g/Vxzo=", + "dev": true + }, + "element-ui": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/element-ui/-/element-ui-2.13.2.tgz", + "integrity": "sha512-r761DRPssMPKDiJZWFlG+4e4vr0cRG/atKr3Eqr8Xi0tQMNbtmYU1QXvFnKiFPFFGkgJ6zS6ASkG+sellcoHlQ==", + "requires": { + "async-validator": "~1.8.1", + "babel-helper-vue-jsx-merge-props": "^2.0.0", + "deepmerge": "^1.2.0", + "normalize-wheel": "^1.0.1", + "resize-observer-polyfill": "^1.5.0", + "throttle-debounce": "^1.0.1" + } + }, + "elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "requires": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npm.taobao.org/emoji-regex/download/emoji-regex-8.0.0.tgz", + "integrity": "sha1-6Bj9ac5cz8tARZT4QpY79TFkzDc=", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/emojis-list/download/emojis-list-3.0.0.tgz", + "integrity": "sha1-VXBmIEatKeLpFucariYKvf9Pang=", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/encodeurl/download/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npm.taobao.org/end-of-stream/download/end-of-stream-1.4.4.tgz?cache=0&sync_timestamp=1569416272686&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fend-of-stream%2Fdownload%2Fend-of-stream-1.4.4.tgz", + "integrity": "sha1-WuZKX0UFe682JuwU2gyl5LJDHrA=", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "entities": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/entities/download/entities-2.0.2.tgz", + "integrity": "sha1-rHTbC7qNM4CLvzaAnDpcNoNTFDY=", + "dev": true + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npm.taobao.org/errno/download/errno-0.1.7.tgz", + "integrity": "sha1-RoTXF3mtOa8Xfj8AeZb3xnyFJhg=", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npm.taobao.org/error-ex/download/error-ex-1.3.2.tgz", + "integrity": "sha1-tKxAZIEH/c3PriQvQovqihTU8b8=", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "error-stack-parser": { + "version": "2.0.6", + "resolved": "https://registry.npm.taobao.org/error-stack-parser/download/error-stack-parser-2.0.6.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ferror-stack-parser%2Fdownload%2Ferror-stack-parser-2.0.6.tgz", + "integrity": "sha1-WpmnB716TFinl5AtSNgoA+3mqtg=", + "dev": true, + "requires": { + "stackframe": "^1.1.1" + } + }, + "es-abstract": { + "version": "1.17.5", + "resolved": "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.17.5.tgz?cache=0&sync_timestamp=1584909155190&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fes-abstract%2Fdownload%2Fes-abstract-1.17.5.tgz", + "integrity": "sha1-2MnR1myJgfuSAOIlHXme7pJ3Suk=", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npm.taobao.org/es-to-primitive/download/es-to-primitive-1.2.1.tgz", + "integrity": "sha1-5VzUyc3BiLzvsDs2bHNjI/xciYo=", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/escape-html/download/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npm.taobao.org/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz?cache=0&sync_timestamp=1587627212242&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fescape-string-regexp%2Fdownload%2Fescape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npm.taobao.org/eslint-scope/download/eslint-scope-4.0.3.tgz", + "integrity": "sha1-ygODMxD2iJoyZHgaqC5j65z+eEg=", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/esprima/download/esprima-4.0.1.tgz", + "integrity": "sha1-E7BM2z5sXRnfkatph6hpVhmwqnE=", + "dev": true + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npm.taobao.org/esrecurse/download/esrecurse-4.2.1.tgz", + "integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npm.taobao.org/estraverse/download/estraverse-4.3.0.tgz", + "integrity": "sha1-OYrT88WiSUi+dyXoPRGn3ijNvR0=", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npm.taobao.org/esutils/download/esutils-2.0.3.tgz", + "integrity": "sha1-dNLrTeC42hKTcRkQ1Qd1ubcQ72Q=", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npm.taobao.org/etag/download/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "event-pubsub": { + "version": "4.3.0", + "resolved": "https://registry.npm.taobao.org/event-pubsub/download/event-pubsub-4.3.0.tgz", + "integrity": "sha1-9o2Ba8KfHsAsU53FjI3UDOcss24=", + "dev": true + }, + "eventemitter3": { + "version": "2.0.3", + "resolved": "https://registry.npm.taobao.org/eventemitter3/download/eventemitter3-2.0.3.tgz", + "integrity": "sha1-teEHm1n7XhuidxwKmTvgYKWMmbo=" + }, + "events": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/events/download/events-3.1.0.tgz?cache=0&sync_timestamp=1578498298945&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fevents%2Fdownload%2Fevents-3.1.0.tgz", + "integrity": "sha1-hCea8bNMt1qoi/X/KR9tC9mzGlk=", + "dev": true + }, + "eventsource": { + "version": "1.0.7", + "resolved": "https://registry.npm.taobao.org/eventsource/download/eventsource-1.0.7.tgz", + "integrity": "sha1-j7xyyT/NNAiAkLwKTmT0tc7m2NA=", + "dev": true, + "requires": { + "original": "^1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/evp_bytestokey/download/evp_bytestokey-1.0.3.tgz", + "integrity": "sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI=", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/execa/download/execa-1.0.0.tgz", + "integrity": "sha1-xiNqW7TfbW8V6I5/AXeYIWdJ3dg=", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npm.taobao.org/expand-brackets/download/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npm.taobao.org/express/download/express-4.17.1.tgz?cache=0&sync_timestamp=1585189541025&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fexpress%2Fdownload%2Fexpress-4.17.1.tgz", + "integrity": "sha1-RJH8OGBc9R+GKdOcK10Cb5ikwTQ=", + "dev": true, + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npm.taobao.org/qs/download/qs-6.7.0.tgz", + "integrity": "sha1-QdwaAV49WB8WIXdr4xr7KHapsbw=", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npm.taobao.org/extend/download/extend-3.0.2.tgz", + "integrity": "sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo=" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/is-extendable/download/is-extendable-1.0.1.tgz", + "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npm.taobao.org/extglob/download/extglob-2.0.4.tgz", + "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npm.taobao.org/extsprintf/download/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-3.1.1.tgz", + "integrity": "sha1-VFFFB3xQFJHjOxXsQIwpQ3bpSuQ=", + "dev": true + }, + "fast-diff": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/fast-diff/download/fast-diff-1.1.2.tgz", + "integrity": "sha1-S2LEK44D3j+EhGC2OQeZIGldAVQ=" + }, + "fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npm.taobao.org/fast-glob/download/fast-glob-2.2.7.tgz", + "integrity": "sha1-aVOFfDr6R1//ku5gFdUtpwpM050=", + "dev": true, + "requires": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/fast-json-stable-stringify/download/fast-json-stable-stringify-2.1.0.tgz?cache=0&sync_timestamp=1576340291001&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffast-json-stable-stringify%2Fdownload%2Ffast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha1-h0v2nG9ATCtdmcSBNBOZ/VWJJjM=", + "dev": true + }, + "fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/fastparse/download/fastparse-1.1.2.tgz", + "integrity": "sha1-kXKMWllC7O2FMSg8eUQe5BIsNak=", + "dev": true + }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npm.taobao.org/figgy-pudding/download/figgy-pudding-3.5.2.tgz", + "integrity": "sha1-tO7oFIq7Adzx0aw0Nn1Z4S+mHW4=", + "dev": true + }, + "file-loader": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/file-loader/download/file-loader-3.0.1.tgz", + "integrity": "sha1-+OC6C1mZGLUa3+RdZtHnca1WD6o=", + "dev": true, + "requires": { + "loader-utils": "^1.0.2", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz?cache=0&sync_timestamp=1587138453873&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fschema-utils%2Fdownload%2Fschema-utils-1.0.0.tgz", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/file-uri-to-path/download/file-uri-to-path-1.0.0.tgz", + "integrity": "sha1-VTp7hEb/b2hDWcRF8eN6BdrMM90=", + "dev": true, + "optional": true + }, + "filesize": { + "version": "3.6.1", + "resolved": "https://registry.npm.taobao.org/filesize/download/filesize-3.6.1.tgz", + "integrity": "sha1-CQuz7gG2+AGoqL6Z0xcQs0Irsxc=", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/fill-range/download/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/finalhandler/download/finalhandler-1.1.2.tgz", + "integrity": "sha1-t+fQAP/RGTjQ/bBTUG9uur6fWH0=", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "find-babel-config": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/find-babel-config/download/find-babel-config-1.2.0.tgz", + "integrity": "sha1-qbezF+tbmGDNqdVHQKjIM3oig6I=", + "dev": true, + "requires": { + "json5": "^0.5.1", + "path-exists": "^3.0.0" + }, + "dependencies": { + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npm.taobao.org/json5/download/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + } + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-2.1.0.tgz", + "integrity": "sha1-jQ+UzRP+Q8bHwmGg2GEVypGMBfc=", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/flush-write-stream/download/flush-write-stream-1.1.1.tgz", + "integrity": "sha1-jdfYc6G6vCB9lOrQwuDkQnbr8ug=", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.5.10.tgz", + "integrity": "sha1-e3qfmuov3/NnhqlP9kPtB/T/Xio=", + "dev": true, + "requires": { + "debug": "=3.1.0" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/for-in/download/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npm.taobao.org/form-data/download/form-data-2.3.3.tgz", + "integrity": "sha1-3M5SwF9kTymManq5Nr1yTO/786Y=", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npm.taobao.org/forwarded/download/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npm.taobao.org/fragment-cache/download/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npm.taobao.org/fresh/download/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/from2/download/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npm.taobao.org/fs-extra/download/fs-extra-7.0.1.tgz", + "integrity": "sha1-TxicRKoSO4lfcigE9V6iPq3DSOk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npm.taobao.org/fs-write-stream-atomic/download/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npm.taobao.org/fsevents/download/fsevents-1.2.13.tgz", + "integrity": "sha1-8yXLBFVZJCi88Rs4M3DvcOO/zDg=", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/function-bind/download/function-bind-1.1.1.tgz", + "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=" + }, + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npm.taobao.org/gensync/download/gensync-1.0.0-beta.1.tgz", + "integrity": "sha1-WPQ2H/mH5f9uHnohCCeqNx6qwmk=", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npm.taobao.org/get-caller-file/download/get-caller-file-2.0.5.tgz", + "integrity": "sha1-T5RBKoLbMvNuOwuXQfipf+sDH34=", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/get-stream/download/get-stream-4.1.0.tgz", + "integrity": "sha1-wbJVV189wh1Zv8ec09K0axw6VLU=", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npm.taobao.org/get-value/download/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npm.taobao.org/getpass/download/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npm.taobao.org/glob/download/glob-7.1.6.tgz", + "integrity": "sha1-FB8zuBp8JJLhJVlDB0gMRmeSeKY=", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/glob-parent/download/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npm.taobao.org/glob-to-regexp/download/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", + "dev": true + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npm.taobao.org/globals/download/globals-11.12.0.tgz", + "integrity": "sha1-q4eVM4hooLq9hSV1gBjCp+uVxC4=", + "dev": true + }, + "globby": { + "version": "9.2.0", + "resolved": "https://registry.npm.taobao.org/globby/download/globby-9.2.0.tgz", + "integrity": "sha1-/QKacGxwPSm90XD0tts6P3p8tj0=", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^1.0.2", + "dir-glob": "^2.2.2", + "fast-glob": "^2.2.6", + "glob": "^7.1.3", + "ignore": "^4.0.3", + "pify": "^4.0.1", + "slash": "^2.0.0" + }, + "dependencies": { + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npm.taobao.org/ignore/download/ignore-4.0.6.tgz", + "integrity": "sha1-dQ49tYYgh7RzfrrIIH/9HvJ7Jfw=", + "dev": true + } + } + }, + "good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", + "requires": { + "delegate": "^3.1.2" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.2.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fgraceful-fs%2Fdownload%2Fgraceful-fs-4.2.4.tgz", + "integrity": "sha1-Ila94U02MpWMRl68ltxGfKB6Kfs=", + "dev": true + }, + "gzip-size": { + "version": "5.1.1", + "resolved": "https://registry.npm.taobao.org/gzip-size/download/gzip-size-5.1.1.tgz", + "integrity": "sha1-y5vuaS+HwGErIyhAqHOQTkwTUnQ=", + "dev": true, + "requires": { + "duplexer": "^0.1.1", + "pify": "^4.0.1" + } + }, + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/handle-thing/download/handle-thing-2.0.1.tgz", + "integrity": "sha1-hX95zjWVgMNA1DCBzGSJcNC7I04=", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/har-schema/download/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npm.taobao.org/har-validator/download/har-validator-5.1.3.tgz", + "integrity": "sha1-HvievT5JllV2de7ZiTEQ3DUPoIA=", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/has/download/has-1.0.3.tgz", + "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/has-ansi/download/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz?cache=0&sync_timestamp=1570188570027&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-regex%2Fdownload%2Fansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/has-symbols/download/has-symbols-1.0.1.tgz?cache=0&sync_timestamp=1573950844856&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhas-symbols%2Fdownload%2Fhas-symbols-1.0.1.tgz", + "integrity": "sha1-n1IUdYpEGWxAbZvXbOv4HsLdMeg=" + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/has-value/download/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/has-values/download/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz", + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", + "dev": true + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/hash-base/download/hash-base-3.1.0.tgz", + "integrity": "sha1-VcOB2eBuHSmXqIO0o/3f5/DTrzM=", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.6.0.tgz", + "integrity": "sha1-M3u9o63AcGvT4CRCaihtS0sskZg=", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.2.1.tgz", + "integrity": "sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY=", + "dev": true + } + } + }, + "hash-sum": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/hash-sum/download/hash-sum-1.0.2.tgz", + "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", + "dev": true + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npm.taobao.org/hash.js/download/hash.js-1.1.7.tgz", + "integrity": "sha1-C6vKU46NTuSg+JiNaIZlN6ADz0I=", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/he/download/he-1.2.0.tgz", + "integrity": "sha1-hK5l+n6vsWX922FWauFLrwVmTw8=", + "dev": true + }, + "hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/hex-color-regex/download/hex-color-regex-1.1.0.tgz", + "integrity": "sha1-TAb8y0YC/iYCs8k9+C1+fb8aio4=", + "dev": true + }, + "highlight.js": { + "version": "9.18.1", + "resolved": "https://registry.npm.taobao.org/highlight.js/download/highlight.js-9.18.1.tgz", + "integrity": "sha1-7SGqAB/mJSuxCj121HVzxlOf4Tw=" + }, + "highlight.js-async-webpack": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/highlight.js-async-webpack/download/highlight.js-async-webpack-1.0.4.tgz", + "integrity": "sha1-wGtnv5nwSQRdYrdW5YVbCRLsYWw=" + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/hmac-drbg/download/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hoopy": { + "version": "0.1.4", + "resolved": "https://registry.npm.taobao.org/hoopy/download/hoopy-0.1.4.tgz", + "integrity": "sha1-YJIH1mEQADOpqUAq096mdzgcGx0=", + "dev": true + }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npm.taobao.org/hpack.js/download/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "hsl-regex": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/hsl-regex/download/hsl-regex-1.0.0.tgz", + "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=", + "dev": true + }, + "hsla-regex": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/hsla-regex/download/hsla-regex-1.0.0.tgz", + "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=", + "dev": true + }, + "html-comment-regex": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/html-comment-regex/download/html-comment-regex-1.1.2.tgz", + "integrity": "sha1-l9RoiutcgYhqNk+qDK0d2hTUM6c=", + "dev": true + }, + "html-entities": { + "version": "1.3.1", + "resolved": "https://registry.npm.taobao.org/html-entities/download/html-entities-1.3.1.tgz", + "integrity": "sha1-+5oaS1sUxdq6gtPjTGrk/nAaDkQ=", + "dev": true + }, + "html-minifier": { + "version": "3.5.21", + "resolved": "https://registry.npm.taobao.org/html-minifier/download/html-minifier-3.5.21.tgz", + "integrity": "sha1-0AQOBUcw41TbAIRjWTGUAVIS0gw=", + "dev": true, + "requires": { + "camel-case": "3.0.x", + "clean-css": "4.2.x", + "commander": "2.17.x", + "he": "1.2.x", + "param-case": "2.1.x", + "relateurl": "0.2.x", + "uglify-js": "3.4.x" + }, + "dependencies": { + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npm.taobao.org/commander/download/commander-2.17.1.tgz", + "integrity": "sha1-vXerfebelCBc6sxy8XFtKfIKd78=", + "dev": true + } + } + }, + "html-tags": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/html-tags/download/html-tags-2.0.0.tgz", + "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", + "dev": true + }, + "html-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npm.taobao.org/html-webpack-plugin/download/html-webpack-plugin-3.2.0.tgz?cache=0&sync_timestamp=1588268811144&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhtml-webpack-plugin%2Fdownload%2Fhtml-webpack-plugin-3.2.0.tgz", + "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=", + "dev": true, + "requires": { + "html-minifier": "^3.2.3", + "loader-utils": "^0.2.16", + "lodash": "^4.17.3", + "pretty-error": "^2.0.2", + "tapable": "^1.0.0", + "toposort": "^1.0.0", + "util.promisify": "1.0.0" + }, + "dependencies": { + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npm.taobao.org/big.js/download/big.js-3.2.0.tgz", + "integrity": "sha1-pfwpi4G54Nyi5FiCR4S2XFK6WI4=", + "dev": true + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/emojis-list/download/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npm.taobao.org/json5/download/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npm.taobao.org/loader-utils/download/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/util.promisify/download/util.promisify-1.0.0.tgz", + "integrity": "sha1-RA9xZaRZyaFtwUXrjnLzVocJcDA=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + } + } + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npm.taobao.org/htmlparser2/download/htmlparser2-3.10.1.tgz", + "integrity": "sha1-vWedw/WYl7ajS7EHSchVu1OpOS8=", + "dev": true, + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/entities/download/entities-1.1.2.tgz", + "integrity": "sha1-vfpzUplmTfr9NFKe1PhSKidf6lY=", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.6.0.tgz", + "integrity": "sha1-M3u9o63AcGvT4CRCaihtS0sskZg=", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npm.taobao.org/http-deceiver/download/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.7.2.tgz", + "integrity": "sha1-T1ApzxMjnzEDblsuVSkrz7zIXI8=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "http-parser-js": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", + "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==", + "dev": true + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "dependencies": { + "eventemitter3": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", + "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==", + "dev": true + } + } + }, + "http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npm.taobao.org/http-proxy-middleware/download/http-proxy-middleware-0.19.1.tgz?cache=0&sync_timestamp=1584394549840&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-proxy-middleware%2Fdownload%2Fhttp-proxy-middleware-0.19.1.tgz", + "integrity": "sha1-GDx9xKoUeRUDBkmMIQza+WCApDo=", + "dev": true, + "requires": { + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/http-signature/download/http-signature-1.2.0.tgz?cache=0&sync_timestamp=1585807780313&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-signature%2Fdownload%2Fhttp-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/https-browserify/download/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/human-signals/download/human-signals-1.1.1.tgz", + "integrity": "sha1-xbHNFPUK6uCatsWf5jujOV/k36M=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.24.tgz", + "integrity": "sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/icss-replace-symbols/download/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", + "dev": true + }, + "icss-utils": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/icss-utils/download/icss-utils-2.1.0.tgz", + "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", + "dev": true, + "requires": { + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npm.taobao.org/postcss/download/postcss-6.0.23.tgz?cache=0&sync_timestamp=1589206165064&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss%2Fdownload%2Fpostcss-6.0.23.tgz", + "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npm.taobao.org/ieee754/download/ieee754-1.1.13.tgz", + "integrity": "sha1-7BaFWOlaoYH9h9N/VcMrvLZwi4Q=", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npm.taobao.org/iferr/download/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npm.taobao.org/ignore/download/ignore-3.3.10.tgz", + "integrity": "sha1-Cpf7h2mG6AgcYxFg+PnziRV/AEM=", + "dev": true + }, + "import-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/import-cwd/download/import-cwd-2.1.0.tgz", + "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", + "dev": true, + "requires": { + "import-from": "^2.1.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/import-fresh/download/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "import-from": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/import-from/download/import-from-2.1.0.tgz", + "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/import-local/download/import-local-2.0.0.tgz", + "integrity": "sha1-VQcL44pZk88Y72236WH1vuXFoJ0=", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npm.taobao.org/imurmurhash/download/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/indexes-of/download/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/infer-owner/download/infer-owner-1.0.4.tgz", + "integrity": "sha1-xM78qo5RBRwqQLos6KPScpWvlGc=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.4.tgz", + "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=", + "dev": true + }, + "internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npm.taobao.org/internal-ip/download/internal-ip-4.3.0.tgz?cache=0&sync_timestamp=1583983307284&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Finternal-ip%2Fdownload%2Finternal-ip-4.3.0.tgz", + "integrity": "sha1-hFRSuq2dLKO2nGNaE3rLmg2tCQc=", + "dev": true, + "requires": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + }, + "dependencies": { + "default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npm.taobao.org/default-gateway/download/default-gateway-4.2.0.tgz", + "integrity": "sha1-FnEEx1AMIRX23WmwpTa7jtcgVSs=", + "dev": true, + "requires": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + } + } + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npm.taobao.org/invariant/download/invariant-2.2.4.tgz", + "integrity": "sha1-YQ88ksk1nOHbYW5TgAjSP/NRWOY=", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npm.taobao.org/ip/download/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/ip-regex/download/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npm.taobao.org/ipaddr.js/download/ipaddr.js-1.9.1.tgz", + "integrity": "sha1-v/OFQ+64mEglB5/zoqjmy9RngbM=", + "dev": true + }, + "is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/is-absolute-url/download/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz", + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/is-arguments/download/is-arguments-1.0.4.tgz", + "integrity": "sha1-P6+WbHy6D/Q3+zH2JQCC/PBEjPM=" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npm.taobao.org/is-arrayish/download/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/is-binary-path/download/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npm.taobao.org/is-buffer/download/is-buffer-2.0.4.tgz", + "integrity": "sha1-PlcvI8hBGlz9lVfISeNmXgspBiM=", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npm.taobao.org/is-callable/download/is-callable-1.1.5.tgz", + "integrity": "sha1-9+RrWWiQRW23Tn9ul2yzJz0G+qs=" + }, + "is-color-stop": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-color-stop/download/is-color-stop-1.1.0.tgz", + "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", + "dev": true, + "requires": { + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz", + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/is-date-object/download/is-date-object-1.0.2.tgz?cache=0&sync_timestamp=1576729165697&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-date-object%2Fdownload%2Fis-date-object-1.0.2.tgz", + "integrity": "sha1-vac28s2P0G0yhE53Q7+nSUw7/X4=" + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-0.1.6.tgz", + "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-5.1.0.tgz", + "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", + "dev": true + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npm.taobao.org/is-directory/download/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-docker": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/is-docker/download/is-docker-2.0.0.tgz", + "integrity": "sha1-LLDfDnXi0GT+GGTDfN6st7Lc8ls=", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npm.taobao.org/is-extendable/download/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/is-extglob/download/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-4.0.1.tgz", + "integrity": "sha1-dWfb6fL14kZ7x3q4PEopSCQHpdw=", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/is-number/download/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz", + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/is-obj/download/is-obj-2.0.0.tgz", + "integrity": "sha1-Rz+wXZc3BeP9liBUUBjKjiLvSYI=", + "dev": true + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/is-path-cwd/download/is-path-cwd-2.2.0.tgz", + "integrity": "sha1-Z9Q7gmZKe1GR/ZEZEn6zAASKn9s=", + "dev": true + }, + "is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/is-path-in-cwd/download/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha1-v+Lcomxp85cmWkAJljYCk1oFOss=", + "dev": true, + "requires": { + "is-path-inside": "^2.1.0" + } + }, + "is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/is-path-inside/download/is-path-inside-2.1.0.tgz", + "integrity": "sha1-fJgQWH1lmkDSe8201WFuqwWUlLI=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-plain-obj/download/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npm.taobao.org/is-plain-object/download/is-plain-object-2.0.4.tgz", + "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npm.taobao.org/is-regex/download/is-regex-1.0.5.tgz", + "integrity": "sha1-OdWJo1i/GJZ/cmlnEguPwa7XTq4=", + "requires": { + "has": "^1.0.3" + } + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-resolvable/download/is-resolvable-1.1.0.tgz", + "integrity": "sha1-+xj4fOH+uSUWnJpAfBkxijIG7Yg=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-stream/download/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-svg": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/is-svg/download/is-svg-3.0.0.tgz", + "integrity": "sha1-kyHb0pwhLlypnE+peUxxS8r6L3U=", + "dev": true, + "requires": { + "html-comment-regex": "^1.1.0" + } + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/is-symbol/download/is-symbol-1.0.3.tgz?cache=0&sync_timestamp=1574296721350&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-symbol%2Fdownload%2Fis-symbol-1.0.3.tgz", + "integrity": "sha1-OOEBS55jKb4N6dJKQU/XRB7GGTc=", + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/is-windows/download/is-windows-1.0.2.tgz", + "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-wsl/download/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/isexe/download/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/isobject/download/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npm.taobao.org/isstream/download/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "javascript-stringify": { + "version": "1.6.0", + "resolved": "https://registry.npm.taobao.org/javascript-stringify/download/javascript-stringify-1.6.0.tgz", + "integrity": "sha1-FC0RHzpuPa6PSpr9d9RYVbWpzOM=", + "dev": true + }, + "jquery": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz", + "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg==" + }, + "js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npm.taobao.org/js-levenshtein/download/js-levenshtein-1.1.6.tgz", + "integrity": "sha1-xs7ljrNVA3LfjeuF+tXOZs4B1Z0=", + "dev": true + }, + "js-message": { + "version": "1.0.5", + "resolved": "https://registry.npm.taobao.org/js-message/download/js-message-1.0.5.tgz", + "integrity": "sha1-IwDSSxrwjondCVvBpMnJz8uJLRU=", + "dev": true + }, + "js-queue": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/js-queue/download/js-queue-2.0.0.tgz", + "integrity": "sha1-NiITz4YPRo8BJfxslqvBdCUx+Ug=", + "dev": true, + "requires": { + "easy-stack": "^1.0.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/js-tokens/download/js-tokens-4.0.0.tgz", + "integrity": "sha1-GSA/tZmR35jjoocFDUZHzerzJJk=", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npm.taobao.org/js-yaml/download/js-yaml-3.13.1.tgz", + "integrity": "sha1-r/FRswv9+o5J4F2iLnQV6d+jeEc=", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npm.taobao.org/jsbn/download/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npm.taobao.org/jsesc/download/jsesc-2.5.2.tgz", + "integrity": "sha1-gFZNLkg9rPbo7yCWUKZ98/DCg6Q=", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/json-parse-better-errors/download/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha1-u4Z8+zRQ5pEHwTHRxRS6s9yLyqk=", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npm.taobao.org/json-schema-traverse/download/json-schema-traverse-0.4.1.tgz", + "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npm.taobao.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json3": { + "version": "3.3.3", + "resolved": "https://registry.npm.taobao.org/json3/download/json3-3.3.3.tgz", + "integrity": "sha1-f8EON1/FrkLEcFpcwKpvYr4wW4E=", + "dev": true + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npm.taobao.org/json5/download/json5-2.1.3.tgz", + "integrity": "sha1-ybD3+pIzv+WAf+ZvzzpWF+1ZfUM=", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/jsonfile/download/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "killable": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/killable/download/killable-1.0.1.tgz", + "integrity": "sha1-TIzkQRh6Bhx0dPuHygjipjgZSJI=", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz", + "integrity": "sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=", + "dev": true + }, + "launch-editor": { + "version": "2.2.1", + "resolved": "https://registry.npm.taobao.org/launch-editor/download/launch-editor-2.2.1.tgz", + "integrity": "sha1-hxtaPuOdZoD8wm03kwtu7aidsMo=", + "dev": true, + "requires": { + "chalk": "^2.3.0", + "shell-quote": "^1.6.1" + } + }, + "launch-editor-middleware": { + "version": "2.2.1", + "resolved": "https://registry.npm.taobao.org/launch-editor-middleware/download/launch-editor-middleware-2.2.1.tgz", + "integrity": "sha1-4UsH5scVSwpLhqD9NFeE5FgEwVc=", + "dev": true, + "requires": { + "launch-editor": "^2.2.1" + } + }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npm.taobao.org/lines-and-columns/download/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npm.taobao.org/loader-runner/download/loader-runner-2.4.0.tgz", + "integrity": "sha1-7UcGa/5TTX6ExMe5mYwqdWB9k1c=", + "dev": true + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npm.taobao.org/loader-utils/download/loader-utils-1.4.0.tgz", + "integrity": "sha1-xXm140yzSxp07cbB+za/o3HVphM=", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/json5/download/json5-1.0.1.tgz", + "integrity": "sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4=", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash.defaultsdeep": { + "version": "4.6.1", + "resolved": "https://registry.npm.taobao.org/lodash.defaultsdeep/download/lodash.defaultsdeep-4.6.1.tgz", + "integrity": "sha1-US6b1yHSctlOPTpjZT+hdRZ0HKY=", + "dev": true + }, + "lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/lodash.kebabcase/download/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=", + "dev": true + }, + "lodash.mapvalues": { + "version": "4.6.0", + "resolved": "https://registry.npm.taobao.org/lodash.mapvalues/download/lodash.mapvalues-4.6.0.tgz", + "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", + "dev": true + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npm.taobao.org/lodash.memoize/download/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "lodash.transform": { + "version": "4.6.0", + "resolved": "https://registry.npm.taobao.org/lodash.transform/download/lodash.transform-4.6.0.tgz", + "integrity": "sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A=", + "dev": true + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npm.taobao.org/lodash.uniq/download/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/log-symbols/download/log-symbols-2.2.0.tgz", + "integrity": "sha1-V0Dhxdbw39pK2TI7UzIQfva0xAo=", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "loglevel": { + "version": "1.6.8", + "resolved": "https://registry.npm.taobao.org/loglevel/download/loglevel-1.6.8.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Floglevel%2Fdownload%2Floglevel-1.6.8.tgz", + "integrity": "sha1-iiX7ddCSIw7NRFcnDYC1TigBEXE=", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npm.taobao.org/loose-envify/download/loose-envify-1.4.0.tgz", + "integrity": "sha1-ce5R+nvkyuwaY4OffmgtgTLTDK8=", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npm.taobao.org/lower-case/download/lower-case-1.1.4.tgz?cache=0&sync_timestamp=1575601618899&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flower-case%2Fdownload%2Flower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "dev": true + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npm.taobao.org/lru-cache/download/lru-cache-5.1.1.tgz", + "integrity": "sha1-HaJ+ZxAnGUdpXa9oSOhH8B2EuSA=", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/make-dir/download/make-dir-2.1.0.tgz?cache=0&sync_timestamp=1587567610342&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmake-dir%2Fdownload%2Fmake-dir-2.1.0.tgz", + "integrity": "sha1-XwMQ4YuL6JjMBwCSlaMK5B6R5vU=", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npm.taobao.org/map-cache/download/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/map-visit/download/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "mavon-editor": { + "version": "2.9.0", + "resolved": "https://registry.npm.taobao.org/mavon-editor/download/mavon-editor-2.9.0.tgz", + "integrity": "sha1-5Ru83N4YuSNjM6nOsS/tLYRUKQA=", + "requires": { + "highlight.js": "^9.11.0", + "highlight.js-async-webpack": "^1.0.4", + "xss": "^1.0.6" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npm.taobao.org/md5.js/download/md5.js-1.3.5.tgz", + "integrity": "sha1-tdB7jjIW4+J81yjXL3DR5qNCAF8=", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npm.taobao.org/mdn-data/download/mdn-data-2.0.4.tgz?cache=0&sync_timestamp=1584029207120&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmdn-data%2Fdownload%2Fmdn-data-2.0.4.tgz", + "integrity": "sha1-aZs8OKxvHXKAkaZGULZdOIUC/Vs=", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npm.taobao.org/media-typer/download/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npm.taobao.org/memory-fs/download/memory-fs-0.4.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmemory-fs%2Fdownload%2Fmemory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/merge-descriptors/download/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/merge-source-map/download/merge-source-map-1.1.0.tgz", + "integrity": "sha1-L93n5gIJOfcJBqaPLXrmheTIxkY=", + "dev": true, + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + } + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/merge-stream/download/merge-stream-2.0.0.tgz", + "integrity": "sha1-UoI2KaFN0AyXcPtq1H3GMQ8sH2A=", + "dev": true + }, + "merge2": { + "version": "1.3.0", + "resolved": "https://registry.npm.taobao.org/merge2/download/merge2-1.3.0.tgz", + "integrity": "sha1-WzZu6DsvFYLEj4fkfPGpNSEDyoE=", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/methods/download/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npm.taobao.org/micromatch/download/micromatch-3.1.10.tgz", + "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/miller-rabin/download/miller-rabin-4.0.1.tgz", + "integrity": "sha1-8IA1HIZbDcViqEYpZtqlNUPHik0=", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.8.tgz", + "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=", + "dev": true + } + } + }, + "mime": { + "version": "2.4.5", + "resolved": "https://registry.npm.taobao.org/mime/download/mime-2.4.5.tgz", + "integrity": "sha1-2N4uy5KYLe27ZUHJtoQdfyGOoAk=", + "dev": true + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npm.taobao.org/mime-db/download/mime-db-1.44.0.tgz?cache=0&sync_timestamp=1587603413053&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime-db%2Fdownload%2Fmime-db-1.44.0.tgz", + "integrity": "sha1-+hHF6wrKEzS0Izy01S8QxaYnL5I=", + "dev": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npm.taobao.org/mime-types/download/mime-types-2.1.27.tgz", + "integrity": "sha1-R5SfmOJ56lMRn1ci4PNOUpvsAJ8=", + "dev": true, + "requires": { + "mime-db": "1.44.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/mimic-fn/download/mimic-fn-1.2.0.tgz", + "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=", + "dev": true + }, + "mini-css-extract-plugin": { + "version": "0.8.2", + "resolved": "https://registry.npm.taobao.org/mini-css-extract-plugin/download/mini-css-extract-plugin-0.8.2.tgz?cache=0&sync_timestamp=1576856499989&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmini-css-extract-plugin%2Fdownload%2Fmini-css-extract-plugin-0.8.2.tgz", + "integrity": "sha1-qHXhab6yfIivd92WJ3HJ7tw9oWE=", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "normalize-url": "1.9.1", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" + }, + "dependencies": { + "normalize-url": { + "version": "1.9.1", + "resolved": "https://registry.npm.taobao.org/normalize-url/download/normalize-url-1.9.1.tgz", + "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz?cache=0&sync_timestamp=1587138453873&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fschema-utils%2Fdownload%2Fschema-utils-1.0.0.tgz", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/minimalistic-assert/download/minimalistic-assert-1.0.1.tgz", + "integrity": "sha1-LhlN4ERibUoQ5/f7wAznPoPk1cc=", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/minimalistic-crypto-utils/download/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npm.taobao.org/minimatch/download/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz?cache=0&sync_timestamp=1584051606680&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fminimist%2Fdownload%2Fminimist-1.2.5.tgz", + "integrity": "sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI=", + "dev": true + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/mississippi/download/mississippi-3.0.0.tgz", + "integrity": "sha1-6goykfl+C16HdrNj1fChLZTGcCI=", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npm.taobao.org/mixin-deep/download/mixin-deep-1.3.2.tgz", + "integrity": "sha1-ESC0PcNZp4Xc5ltVuC4lfM9HlWY=", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/is-extendable/download/is-extendable-1.0.1.tgz", + "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.5.tgz?cache=0&sync_timestamp=1587535418745&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmkdirp%2Fdownload%2Fmkdirp-0.5.5.tgz", + "integrity": "sha1-2Rzv1i0UNsoPQWIOJRKI1CAJne8=", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "mockjs": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/mockjs/download/mockjs-1.1.0.tgz", + "integrity": "sha1-5qDDeOkZBtuv8gkRzAJzs8fXWwY=", + "dev": true, + "requires": { + "commander": "*" + } + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/move-concurrently/download/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npm.taobao.org/multicast-dns/download/multicast-dns-6.2.3.tgz?cache=0&sync_timestamp=1585238976691&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmulticast-dns%2Fdownload%2Fmulticast-dns-6.2.3.tgz", + "integrity": "sha1-oOx72QVcQoL3kMPIL04o2zsxsik=", + "dev": true, + "requires": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/multicast-dns-service-types/download/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npm.taobao.org/mz/download/mz-2.7.0.tgz", + "integrity": "sha1-lQCAV6Vsr63CvGPd5/n/aVWUjjI=", + "dev": true, + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "nan": { + "version": "2.14.1", + "resolved": "https://registry.npm.taobao.org/nan/download/nan-2.14.1.tgz?cache=0&sync_timestamp=1587495873856&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnan%2Fdownload%2Fnan-2.14.1.tgz", + "integrity": "sha1-174036MQW5FJTDFHCJMV7/iHSwE=", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npm.taobao.org/nanomatch/download/nanomatch-1.2.13.tgz", + "integrity": "sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk=", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npm.taobao.org/negotiator/download/negotiator-0.6.2.tgz", + "integrity": "sha1-/qz3zPUlp3rpY0Q2pkiD/+yjRvs=", + "dev": true + }, + "neo-async": { + "version": "2.6.1", + "resolved": "https://registry.npm.taobao.org/neo-async/download/neo-async-2.6.1.tgz", + "integrity": "sha1-rCetpmFn+ohJpq3dg39rGJrSCBw=", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npm.taobao.org/nice-try/download/nice-try-1.0.5.tgz?cache=0&sync_timestamp=1584699756095&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnice-try%2Fdownload%2Fnice-try-1.0.5.tgz", + "integrity": "sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y=", + "dev": true + }, + "no-case": { + "version": "2.3.2", + "resolved": "https://registry.npm.taobao.org/no-case/download/no-case-2.3.2.tgz", + "integrity": "sha1-YLgTOWvjmz8SiKTB7V0efSi0ZKw=", + "dev": true, + "requires": { + "lower-case": "^1.1.1" + } + }, + "node-ipc": { + "version": "9.1.1", + "resolved": "https://registry.npm.taobao.org/node-ipc/download/node-ipc-9.1.1.tgz", + "integrity": "sha1-TiRe1pOOZRAOWV68XcNLFujdXWk=", + "dev": true, + "requires": { + "event-pubsub": "4.3.0", + "js-message": "1.0.5", + "js-queue": "2.0.0" + } + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npm.taobao.org/node-libs-browser/download/node-libs-browser-2.2.1.tgz", + "integrity": "sha1-tk9RPRgzhiX5A0bSew0jXmMfZCU=", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npm.taobao.org/punycode/download/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "node-releases": { + "version": "1.1.55", + "resolved": "https://registry.npm.taobao.org/node-releases/download/node-releases-1.1.55.tgz", + "integrity": "sha1-ivI7fFYdji5uNqRmN7q4RjOwfO4=", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npm.taobao.org/normalize-package-data/download/normalize-package-data-2.5.0.tgz", + "integrity": "sha1-5m2xg4sgDB38IzIl0SyzZSDiNKg=", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/normalize-path/download/normalize-path-3.0.0.tgz", + "integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=", + "dev": true + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npm.taobao.org/normalize-range/download/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npm.taobao.org/normalize-url/download/normalize-url-3.3.0.tgz", + "integrity": "sha1-suHE3E98bVd0PfczpPWXjRhlBVk=", + "dev": true + }, + "normalize-wheel": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/normalize-wheel/download/normalize-wheel-1.0.1.tgz", + "integrity": "sha1-rsiGr/2wRQcNhWRH32Ls+GFG7EU=" + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/npm-run-path/download/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/nth-check/download/nth-check-1.0.2.tgz", + "integrity": "sha1-sr0pXDfj3VijvwcAN2Zjuk2c8Fw=", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npm.taobao.org/num2fraction/download/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.9.0.tgz", + "integrity": "sha1-R6ewFrqmi1+g7PPe4IqFxnmsZFU=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz?cache=0&sync_timestamp=1571657171505&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fobject-assign%2Fdownload%2Fobject-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npm.taobao.org/object-copy/download/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz", + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npm.taobao.org/object-inspect/download/object-inspect-1.7.0.tgz", + "integrity": "sha1-9Pa9GBrXfwBrXs5gvQtvOY/3Smc=" + }, + "object-is": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/object-is/download/object-is-1.1.2.tgz", + "integrity": "sha1-xdLof/nhGfeLegiEQVGeLuwVc7Y=", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/object-keys/download/object-keys-1.1.1.tgz", + "integrity": "sha1-HEfyct8nfzsdrwYWd9nILiMixg4=" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/object-visit/download/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/object.assign/download/object.assign-4.1.0.tgz", + "integrity": "sha1-lovxEA15Vrs8oIbwBvhGs7xACNo=", + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/object.getownpropertydescriptors/download/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha1-Npvx+VktiridcS3O1cuBx8U1Jkk=", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npm.taobao.org/object.pick/download/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/object.values/download/object.values-1.1.1.tgz", + "integrity": "sha1-aKmezeNWt+kpWjxeDOMdyMlT3l4=", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/obuf/download/obuf-1.1.2.tgz", + "integrity": "sha1-Cb6jND1BhZ69RGKS0RydTbYZCE4=", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/on-finished/download/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/on-headers/download/on-headers-1.0.2.tgz", + "integrity": "sha1-dysK5qqlJcOZ5Imt+tkMQD6zwo8=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npm.taobao.org/once/download/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/onetime/download/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "open": { + "version": "6.4.0", + "resolved": "https://registry.npm.taobao.org/open/download/open-6.4.0.tgz", + "integrity": "sha1-XBPpbQ3IlGhhZPGJZez+iJ7PyKk=", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, + "opener": { + "version": "1.5.1", + "resolved": "https://registry.npm.taobao.org/opener/download/opener-1.5.1.tgz", + "integrity": "sha1-bS8Od/GgrwAyrKcWwsH7uOfoq+0=", + "dev": true + }, + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npm.taobao.org/opn/download/opn-5.5.0.tgz", + "integrity": "sha1-/HFk+rVtI1kExRw7J9pnWMo7m/w=", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, + "ora": { + "version": "3.4.0", + "resolved": "https://registry.npm.taobao.org/ora/download/ora-3.4.0.tgz?cache=0&sync_timestamp=1587481911978&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fora%2Fdownload%2Fora-3.4.0.tgz", + "integrity": "sha1-vwdSSRBZo+8+1MhQl1Md6f280xg=", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-spinners": "^2.0.0", + "log-symbols": "^2.2.0", + "strip-ansi": "^5.2.0", + "wcwidth": "^1.0.1" + } + }, + "original": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/original/download/original-1.0.2.tgz", + "integrity": "sha1-5EKmHP/hxf0gpl8yYcJmY7MD8l8=", + "dev": true, + "requires": { + "url-parse": "^1.4.3" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npm.taobao.org/os-browserify/download/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/p-finally/download/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npm.taobao.org/p-limit/download/p-limit-1.3.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-limit%2Fdownload%2Fp-limit-1.3.0.tgz", + "integrity": "sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg=", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/p-locate/download/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/p-map/download/p-map-2.1.0.tgz", + "integrity": "sha1-MQko/u+cnsxltosXaTAYpmXOoXU=", + "dev": true + }, + "p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/p-retry/download/p-retry-3.0.1.tgz", + "integrity": "sha1-MWtMiJPiyNwc+okfQGxLQivr8yg=", + "dev": true, + "requires": { + "retry": "^0.12.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/p-try/download/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npm.taobao.org/pako/download/pako-1.0.11.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpako%2Fdownload%2Fpako-1.0.11.tgz", + "integrity": "sha1-bJWZ00DVTf05RjgCUqNXBaa5kr8=", + "dev": true + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/parallel-transform/download/parallel-transform-1.2.0.tgz", + "integrity": "sha1-kEnKN9bLIYLDsdLHIL6U0UpYFPw=", + "dev": true, + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "param-case": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/param-case/download/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "dev": true, + "requires": { + "no-case": "^2.2.0" + } + }, + "parchment": { + "version": "1.1.4", + "resolved": "https://registry.npm.taobao.org/parchment/download/parchment-1.1.4.tgz", + "integrity": "sha1-rt7Xq5OP6SHUw0vDOc4RaLwv/eU=" + }, + "parse-asn1": { + "version": "5.1.5", + "resolved": "https://registry.npm.taobao.org/parse-asn1/download/parse-asn1-5.1.5.tgz", + "integrity": "sha1-ADJxND2ljclMrOSU+u89IUfs6g4=", + "dev": true, + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/parse-json/download/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse5": { + "version": "5.1.1", + "resolved": "https://registry.npm.taobao.org/parse5/download/parse5-5.1.1.tgz", + "integrity": "sha1-9o5OW6GFKsLK3AD0VV//bCq7YXg=", + "dev": true + }, + "parse5-htmlparser2-tree-adapter": { + "version": "5.1.1", + "resolved": "https://registry.npm.taobao.org/parse5-htmlparser2-tree-adapter/download/parse5-htmlparser2-tree-adapter-5.1.1.tgz", + "integrity": "sha1-6MdD1OkhlNUpPs3isIvjHmdGHLw=", + "dev": true, + "requires": { + "parse5": "^5.1.1" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npm.taobao.org/parseurl/download/parseurl-1.3.3.tgz", + "integrity": "sha1-naGee+6NEt/wUT7Vt2lXeTvC6NQ=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npm.taobao.org/pascalcase/download/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npm.taobao.org/path-browserify/download/path-browserify-0.0.1.tgz", + "integrity": "sha1-5sTd1+06onxoogzE5Q4aTug7vEo=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/path-dirname/download/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/path-exists/download/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/path-is-inside/download/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/path-key/download/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npm.taobao.org/path-parse/download/path-parse-1.0.6.tgz", + "integrity": "sha1-1i27VnlAXXLEc37FhgDp3c8G0kw=", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npm.taobao.org/path-to-regexp/download/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/path-type/download/path-type-3.0.0.tgz", + "integrity": "sha1-zvMdyOCho7sNEFwM2Xzzv0f0428=", + "dev": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/pify/download/pify-3.0.0.tgz?cache=0&sync_timestamp=1581697613983&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpify%2Fdownload%2Fpify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "pbkdf2": { + "version": "3.0.17", + "resolved": "https://registry.npm.taobao.org/pbkdf2/download/pbkdf2-3.0.17.tgz", + "integrity": "sha1-l2wgZTBhexTrsyEUI597CTNuk6Y=", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "picomatch": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", + "dev": true, + "optional": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/pify/download/pify-4.0.1.tgz?cache=0&sync_timestamp=1581697613983&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpify%2Fdownload%2Fpify-4.0.1.tgz", + "integrity": "sha1-SyzSXFDVmHNcUCkiJP2MbfQeMjE=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npm.taobao.org/pinkie/download/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/pinkie-promise/download/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-3.0.0.tgz", + "integrity": "sha1-J0kCDyOe2ZCIGx9xIQ1R62UjvqM=", + "dev": true, + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-3.0.0.tgz", + "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz", + "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/p-limit/download/p-limit-2.3.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-limit%2Fdownload%2Fp-limit-2.3.0.tgz", + "integrity": "sha1-PdM8ZHohT9//2DWTPrCG2g3CHbE=", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/p-locate/download/p-locate-3.0.0.tgz", + "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/p-try/download/p-try-2.2.0.tgz", + "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=", + "dev": true + } + } + }, + "pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/pkg-up/download/pkg-up-2.0.0.tgz", + "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "portfinder": { + "version": "1.0.26", + "resolved": "https://registry.npm.taobao.org/portfinder/download/portfinder-1.0.26.tgz", + "integrity": "sha1-R1ZY1WyjC+1yrH8TeO01C9G2TnA=", + "dev": true, + "requires": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.1" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.2.6.tgz", + "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz", + "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=", + "dev": true + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npm.taobao.org/posix-character-classes/download/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "7.0.30", + "resolved": "https://registry.npm.taobao.org/postcss/download/postcss-7.0.30.tgz?cache=0&sync_timestamp=1589206165064&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss%2Fdownload%2Fpostcss-7.0.30.tgz", + "integrity": "sha1-zJN4vv/kagLLxFBqBHfQX86pqOI=", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-6.1.0.tgz", + "integrity": "sha1-B2Srxpxj1ayELdSGfo0CXogN+PM=", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-calc": { + "version": "7.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-calc/download/postcss-calc-7.0.2.tgz?cache=0&sync_timestamp=1582015512279&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-calc%2Fdownload%2Fpostcss-calc-7.0.2.tgz", + "integrity": "sha1-UE780AjKAnMSBWiweSsWzc3oqsE=", + "dev": true, + "requires": { + "postcss": "^7.0.27", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.2" + } + }, + "postcss-colormin": { + "version": "4.0.3", + "resolved": "https://registry.npm.taobao.org/postcss-colormin/download/postcss-colormin-4.0.3.tgz", + "integrity": "sha1-rgYLzpPteUrHEmTwgTLVUJVr04E=", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "color": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&sync_timestamp=1588083303810&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", + "dev": true + } + } + }, + "postcss-convert-values": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-convert-values/download/postcss-convert-values-4.0.1.tgz", + "integrity": "sha1-yjgT7U2g+BL51DcDWE5Enr4Ymn8=", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&sync_timestamp=1588083303810&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", + "dev": true + } + } + }, + "postcss-discard-comments": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-discard-comments/download/postcss-discard-comments-4.0.2.tgz", + "integrity": "sha1-H7q9LCRr/2qq15l7KwkY9NevQDM=", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-duplicates": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-discard-duplicates/download/postcss-discard-duplicates-4.0.2.tgz", + "integrity": "sha1-P+EzzTyCKC5VD8myORdqkge3hOs=", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-empty": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-discard-empty/download/postcss-discard-empty-4.0.1.tgz", + "integrity": "sha1-yMlR6fc+2UKAGUWERKAq2Qu592U=", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-overridden": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-discard-overridden/download/postcss-discard-overridden-4.0.1.tgz", + "integrity": "sha1-ZSrvipZybwKfXj4AFG7npOdV/1c=", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-load-config": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/postcss-load-config/download/postcss-load-config-2.1.0.tgz", + "integrity": "sha1-yE1pK3u3tB3c7ZTuYuirMbQXsAM=", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.0", + "import-cwd": "^2.0.0" + } + }, + "postcss-loader": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-loader/download/postcss-loader-3.0.0.tgz", + "integrity": "sha1-a5eUPkfHLYRfqeA/Jzdz1OjdbC0=", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "postcss": "^7.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz?cache=0&sync_timestamp=1587138453873&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fschema-utils%2Fdownload%2Fschema-utils-1.0.0.tgz", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "postcss-merge-longhand": { + "version": "4.0.11", + "resolved": "https://registry.npm.taobao.org/postcss-merge-longhand/download/postcss-merge-longhand-4.0.11.tgz", + "integrity": "sha1-YvSaE+Sg7gTnuY9CuxYGLKJUniQ=", + "dev": true, + "requires": { + "css-color-names": "0.0.4", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "stylehacks": "^4.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&sync_timestamp=1588083303810&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", + "dev": true + } + } + }, + "postcss-merge-rules": { + "version": "4.0.3", + "resolved": "https://registry.npm.taobao.org/postcss-merge-rules/download/postcss-merge-rules-4.0.3.tgz", + "integrity": "sha1-NivqT/Wh+Y5AdacTxsslrv75plA=", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "cssnano-util-same-parent": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0", + "vendors": "^1.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npm.taobao.org/postcss-selector-parser/download/postcss-selector-parser-3.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-selector-parser%2Fdownload%2Fpostcss-selector-parser-3.1.2.tgz", + "integrity": "sha1-sxD1xMD9r3b5SQK7qjDbaqhPUnA=", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-minify-font-values": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-minify-font-values/download/postcss-minify-font-values-4.0.2.tgz", + "integrity": "sha1-zUw0TM5HQ0P6xdgiBqssvLiv1aY=", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&sync_timestamp=1588083303810&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", + "dev": true + } + } + }, + "postcss-minify-gradients": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-minify-gradients/download/postcss-minify-gradients-4.0.2.tgz", + "integrity": "sha1-k7KcL/UJnFNe7NpWxKpuZlpmNHE=", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "is-color-stop": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&sync_timestamp=1588083303810&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", + "dev": true + } + } + }, + "postcss-minify-params": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-minify-params/download/postcss-minify-params-4.0.2.tgz", + "integrity": "sha1-a5zvAwwR41Jh+V9hjJADbWgNuHQ=", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "browserslist": "^4.0.0", + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "uniqs": "^2.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&sync_timestamp=1588083303810&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", + "dev": true + } + } + }, + "postcss-minify-selectors": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-minify-selectors/download/postcss-minify-selectors-4.0.2.tgz", + "integrity": "sha1-4uXrQL/uUA0M2SQ1APX46kJi+9g=", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npm.taobao.org/postcss-selector-parser/download/postcss-selector-parser-3.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-selector-parser%2Fdownload%2Fpostcss-selector-parser-3.1.2.tgz", + "integrity": "sha1-sxD1xMD9r3b5SQK7qjDbaqhPUnA=", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-modules-extract-imports": { + "version": "1.2.1", + "resolved": "https://registry.npm.taobao.org/postcss-modules-extract-imports/download/postcss-modules-extract-imports-1.2.1.tgz", + "integrity": "sha1-3IfjQUjsfqtfeR981YSYMzdbdBo=", + "dev": true, + "requires": { + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npm.taobao.org/postcss/download/postcss-6.0.23.tgz?cache=0&sync_timestamp=1589206165064&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss%2Fdownload%2Fpostcss-6.0.23.tgz", + "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + } + } + }, + "postcss-modules-local-by-default": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/postcss-modules-local-by-default/download/postcss-modules-local-by-default-1.2.0.tgz", + "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", + "dev": true, + "requires": { + "css-selector-tokenizer": "^0.7.0", + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npm.taobao.org/postcss/download/postcss-6.0.23.tgz?cache=0&sync_timestamp=1589206165064&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss%2Fdownload%2Fpostcss-6.0.23.tgz", + "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + } + } + }, + "postcss-modules-scope": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/postcss-modules-scope/download/postcss-modules-scope-1.1.0.tgz", + "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", + "dev": true, + "requires": { + "css-selector-tokenizer": "^0.7.0", + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npm.taobao.org/postcss/download/postcss-6.0.23.tgz?cache=0&sync_timestamp=1589206165064&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss%2Fdownload%2Fpostcss-6.0.23.tgz", + "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + } + } + }, + "postcss-modules-values": { + "version": "1.3.0", + "resolved": "https://registry.npm.taobao.org/postcss-modules-values/download/postcss-modules-values-1.3.0.tgz", + "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", + "dev": true, + "requires": { + "icss-replace-symbols": "^1.1.0", + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npm.taobao.org/postcss/download/postcss-6.0.23.tgz?cache=0&sync_timestamp=1589206165064&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss%2Fdownload%2Fpostcss-6.0.23.tgz", + "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + } + } + }, + "postcss-normalize-charset": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-normalize-charset/download/postcss-normalize-charset-4.0.1.tgz", + "integrity": "sha1-izWt067oOhNrBHHg1ZvlilAoXdQ=", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-normalize-display-values": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-normalize-display-values/download/postcss-normalize-display-values-4.0.2.tgz", + "integrity": "sha1-Db4EpM6QY9RmftK+R2u4MMglk1o=", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&sync_timestamp=1588083303810&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", + "dev": true + } + } + }, + "postcss-normalize-positions": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-normalize-positions/download/postcss-normalize-positions-4.0.2.tgz", + "integrity": "sha1-BfdX+E8mBDc3g2ipH4ky1LECkX8=", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&sync_timestamp=1588083303810&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", + "dev": true + } + } + }, + "postcss-normalize-repeat-style": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-normalize-repeat-style/download/postcss-normalize-repeat-style-4.0.2.tgz", + "integrity": "sha1-xOu8KJ85kaAo1EdRy90RkYsXkQw=", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&sync_timestamp=1588083303810&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", + "dev": true + } + } + }, + "postcss-normalize-string": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-normalize-string/download/postcss-normalize-string-4.0.2.tgz", + "integrity": "sha1-zUTECrB6DHo23F6Zqs4eyk7CaQw=", + "dev": true, + "requires": { + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&sync_timestamp=1588083303810&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", + "dev": true + } + } + }, + "postcss-normalize-timing-functions": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-normalize-timing-functions/download/postcss-normalize-timing-functions-4.0.2.tgz", + "integrity": "sha1-jgCcoqOUnNr4rSPmtquZy159KNk=", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&sync_timestamp=1588083303810&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", + "dev": true + } + } + }, + "postcss-normalize-unicode": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-normalize-unicode/download/postcss-normalize-unicode-4.0.1.tgz", + "integrity": "sha1-hBvUj9zzAZrUuqdJOj02O1KuHPs=", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&sync_timestamp=1588083303810&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", + "dev": true + } + } + }, + "postcss-normalize-url": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-normalize-url/download/postcss-normalize-url-4.0.1.tgz", + "integrity": "sha1-EOQ3+GvHx+WPe5ZS7YeNqqlfquE=", + "dev": true, + "requires": { + "is-absolute-url": "^2.0.0", + "normalize-url": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&sync_timestamp=1588083303810&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", + "dev": true + } + } + }, + "postcss-normalize-whitespace": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-normalize-whitespace/download/postcss-normalize-whitespace-4.0.2.tgz", + "integrity": "sha1-vx1AcP5Pzqh9E0joJdjMDF+qfYI=", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&sync_timestamp=1588083303810&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", + "dev": true + } + } + }, + "postcss-ordered-values": { + "version": "4.1.2", + "resolved": "https://registry.npm.taobao.org/postcss-ordered-values/download/postcss-ordered-values-4.1.2.tgz", + "integrity": "sha1-DPdcgg7H1cTSgBiVWeC1ceusDu4=", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&sync_timestamp=1588083303810&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", + "dev": true + } + } + }, + "postcss-reduce-initial": { + "version": "4.0.3", + "resolved": "https://registry.npm.taobao.org/postcss-reduce-initial/download/postcss-reduce-initial-4.0.3.tgz", + "integrity": "sha1-f9QuvqXpyBRgljniwuhK4nC6SN8=", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0" + } + }, + "postcss-reduce-transforms": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-reduce-transforms/download/postcss-reduce-transforms-4.0.2.tgz", + "integrity": "sha1-F++kBerMbge+NBSlyi0QdGgdTik=", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&sync_timestamp=1588083303810&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", + "dev": true + } + } + }, + "postcss-selector-parser": { + "version": "6.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-selector-parser/download/postcss-selector-parser-6.0.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-selector-parser%2Fdownload%2Fpostcss-selector-parser-6.0.2.tgz", + "integrity": "sha1-k0z3mdAWyDQRhZ4J3Oyt4BKG7Fw=", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "postcss-svgo": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-svgo/download/postcss-svgo-4.0.2.tgz", + "integrity": "sha1-F7mXvHEbMzurFDqu07jT1uPTglg=", + "dev": true, + "requires": { + "is-svg": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "svgo": "^1.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&sync_timestamp=1588083303810&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", + "dev": true + } + } + }, + "postcss-unique-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-unique-selectors/download/postcss-unique-selectors-4.0.1.tgz", + "integrity": "sha1-lEaRHzKJv9ZMbWgPBzwDsfnuS6w=", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "postcss": "^7.0.0", + "uniqs": "^2.0.0" + } + }, + "postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-4.1.0.tgz?cache=0&sync_timestamp=1588083303810&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-4.1.0.tgz", + "integrity": "sha1-RD9qIM7WSBor2k+oUypuVdeJoss=", + "dev": true + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/prepend-http/download/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "prettier": { + "version": "1.19.1", + "resolved": "https://registry.npm.taobao.org/prettier/download/prettier-1.19.1.tgz", + "integrity": "sha1-99f1/4qc2HKnvkyhQglZVqYHl8s=", + "dev": true, + "optional": true + }, + "pretty-error": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/pretty-error/download/pretty-error-2.1.1.tgz", + "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", + "dev": true, + "requires": { + "renderkid": "^2.0.1", + "utila": "~0.4" + } + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npm.taobao.org/private/download/private-0.1.8.tgz", + "integrity": "sha1-I4Hts2ifelPWUxkAYPz4ItLzaP8=", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npm.taobao.org/process/download/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.1.tgz", + "integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I=", + "dev": true + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/promise-inflight/download/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npm.taobao.org/proxy-addr/download/proxy-addr-2.0.6.tgz", + "integrity": "sha1-/cIzZQVEfT8vLGOO0nLK9hS7sr8=", + "dev": true, + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/prr/download/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/pseudomap/download/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npm.taobao.org/psl/download/psl-1.8.0.tgz", + "integrity": "sha1-kyb4vPsBOtzABf3/BWrM4CDlHCQ=", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npm.taobao.org/public-encrypt/download/public-encrypt-4.0.3.tgz", + "integrity": "sha1-T8ydd6B+SLp1J+fL4N4z0HATMeA=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.8.tgz", + "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=", + "dev": true + } + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/pump/download/pump-3.0.0.tgz", + "integrity": "sha1-tKIRaBW94vTh6mAjVOjHVWUQemQ=", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npm.taobao.org/pumpify/download/pumpify-1.5.1.tgz?cache=0&sync_timestamp=1569938140182&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpumpify%2Fdownload%2Fpumpify-1.5.1.tgz", + "integrity": "sha1-NlE74karJ1cLGjdKXOJ4v9dDcM4=", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/pump/download/pump-2.0.1.tgz", + "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/punycode/download/punycode-2.1.1.tgz", + "integrity": "sha1-tYsBCsQMIsVldhbI0sLALHv0eew=", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npm.taobao.org/q/download/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, + "qs": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", + "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npm.taobao.org/query-string/download/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "dev": true, + "requires": { + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npm.taobao.org/querystring/download/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npm.taobao.org/querystring-es3/download/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "querystringify": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/querystringify/download/querystringify-2.1.1.tgz", + "integrity": "sha1-YOWl/WSn+L+k0qsu1v30yFutFU4=", + "dev": true + }, + "quill": { + "version": "1.3.7", + "resolved": "https://registry.npm.taobao.org/quill/download/quill-1.3.7.tgz", + "integrity": "sha1-2lsvOixHDpMjQM2/NmjJ8h+Shug=", + "requires": { + "clone": "^2.1.1", + "deep-equal": "^1.0.1", + "eventemitter3": "^2.0.3", + "extend": "^3.0.2", + "parchment": "^1.1.4", + "quill-delta": "^3.6.2" + } + }, + "quill-delta": { + "version": "3.6.3", + "resolved": "https://registry.npm.taobao.org/quill-delta/download/quill-delta-3.6.3.tgz", + "integrity": "sha1-sZ/SuJQSMBxg4f8hPY2GDqwPEDI=", + "requires": { + "deep-equal": "^1.0.1", + "extend": "^3.0.2", + "fast-diff": "1.1.2" + } + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/randombytes/download/randombytes-2.1.0.tgz", + "integrity": "sha1-32+ENy8CcNxlzfYpE0mrekc9Tyo=", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/randomfill/download/randomfill-1.0.4.tgz", + "integrity": "sha1-ySGW/IarQr6YPxvzF3giSTHWFFg=", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npm.taobao.org/range-parser/download/range-parser-1.2.1.tgz", + "integrity": "sha1-PPNwI9GZ4cJNGlW4SADC8+ZGgDE=", + "dev": true + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npm.taobao.org/raw-body/download/raw-body-2.4.0.tgz", + "integrity": "sha1-oc5vucm8NWylLoklarWQWeE9AzI=", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npm.taobao.org/read-pkg/download/read-pkg-5.2.0.tgz", + "integrity": "sha1-e/KVQ4yloz5WzTDgU7NO5yUMk8w=", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "parse-json": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/parse-json/download/parse-json-5.0.0.tgz", + "integrity": "sha1-c+URTJhtFD76NxLU6iTbmkJm9g8=", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1", + "lines-and-columns": "^1.1.6" + } + } + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npm.taobao.org/readdirp/download/readdirp-2.2.1.tgz", + "integrity": "sha1-DodiKjMlqjPokihcr4tOhGUppSU=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npm.taobao.org/regenerate/download/regenerate-1.4.0.tgz", + "integrity": "sha1-SoVuxLVuQHfFV1icroXnpMiGmhE=", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npm.taobao.org/regenerate-unicode-properties/download/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha1-5d5xEdZV57pgwFfb6f83yH5lzew=", + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } + }, + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" + }, + "regenerator-transform": { + "version": "0.14.4", + "resolved": "https://registry.npm.taobao.org/regenerator-transform/download/regenerator-transform-0.14.4.tgz", + "integrity": "sha1-UmaFeJZRjRYWp4oEeTN6MOqXTMc=", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.4", + "private": "^0.1.8" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/regex-not/download/regex-not-1.0.2.tgz", + "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npm.taobao.org/regexp.prototype.flags/download/regexp.prototype.flags-1.3.0.tgz?cache=0&sync_timestamp=1576388236739&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregexp.prototype.flags%2Fdownload%2Fregexp.prototype.flags-1.3.0.tgz", + "integrity": "sha1-erqJs8E6ZFCdq888qNn7ub31y3U=", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "regexpu-core": { + "version": "4.7.0", + "resolved": "https://registry.npm.taobao.org/regexpu-core/download/regexpu-core-4.7.0.tgz", + "integrity": "sha1-/L9FjFBDGwu3tF1pZ7gZLZHz2Tg=", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" + } + }, + "regjsgen": { + "version": "0.5.1", + "resolved": "https://registry.npm.taobao.org/regjsgen/download/regjsgen-0.5.1.tgz?cache=0&sync_timestamp=1571560370910&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregjsgen%2Fdownload%2Fregjsgen-0.5.1.tgz", + "integrity": "sha1-SPC/Gl6iBRlpKcDZeYtC0e2YRDw=", + "dev": true + }, + "regjsparser": { + "version": "0.6.4", + "resolved": "https://registry.npm.taobao.org/regjsparser/download/regjsparser-0.6.4.tgz", + "integrity": "sha1-p2n4aEMIQBpm6bUp0kNv9NBmYnI=", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npm.taobao.org/jsesc/download/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npm.taobao.org/relateurl/download/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/remove-trailing-separator/download/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "renderkid": { + "version": "2.0.3", + "resolved": "https://registry.npm.taobao.org/renderkid/download/renderkid-2.0.3.tgz", + "integrity": "sha1-OAF5wv9a4TZcUivy/Pz/AcW3QUk=", + "dev": true, + "requires": { + "css-select": "^1.1.0", + "dom-converter": "^0.2", + "htmlparser2": "^3.3.0", + "strip-ansi": "^3.0.0", + "utila": "^0.4.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz?cache=0&sync_timestamp=1570188570027&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-regex%2Fdownload%2Fansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/css-select/download/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dev": true, + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npm.taobao.org/css-what/download/css-what-2.1.3.tgz", + "integrity": "sha1-ptdgRXM2X+dGhsPzEcVlE9iChfI=", + "dev": true + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npm.taobao.org/domutils/download/domutils-1.5.1.tgz?cache=0&sync_timestamp=1589053312321&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomutils%2Fdownload%2Fdomutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/repeat-element/download/repeat-element-1.1.3.tgz", + "integrity": "sha1-eC4NglwMWjuzlzH4Tv7mt0Lmsc4=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npm.taobao.org/repeat-string/download/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npm.taobao.org/request/download/request-2.88.2.tgz", + "integrity": "sha1-1zyRhzHLWofaBH4gcjQUb2ZNErM=", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + } + } + }, + "request-promise-core": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/request-promise-core/download/request-promise-core-1.1.3.tgz", + "integrity": "sha1-6aPAgbUTgN/qZ3M2Bh/qh5qCnuk=", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, + "request-promise-native": { + "version": "1.0.8", + "resolved": "https://registry.npm.taobao.org/request-promise-native/download/request-promise-native-1.0.8.tgz?cache=0&sync_timestamp=1572829683581&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frequest-promise-native%2Fdownload%2Frequest-promise-native-1.0.8.tgz", + "integrity": "sha1-pFW5YLgm5E4r+Jma9k3/K/5YyzY=", + "dev": true, + "requires": { + "request-promise-core": "1.1.3", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/require-directory/download/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/require-main-filename/download/require-main-filename-2.0.0.tgz", + "integrity": "sha1-0LMp7MfMD2Fkn2IhW+aa9UqomJs=", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/requires-port/download/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "reselect": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/reselect/download/reselect-3.0.1.tgz", + "integrity": "sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc=", + "dev": true + }, + "resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npm.taobao.org/resolve/download/resolve-1.17.0.tgz", + "integrity": "sha1-sllBtUloIxzC0bt2p5y38sC/hEQ=", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/resolve-cwd/download/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/resolve-from/download/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npm.taobao.org/resolve-url/download/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/restore-cursor/download/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npm.taobao.org/ret/download/ret-0.1.15.tgz", + "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=", + "dev": true + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npm.taobao.org/retry/download/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true + }, + "rgb-regex": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/rgb-regex/download/rgb-regex-1.0.1.tgz", + "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=", + "dev": true + }, + "rgba-regex": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/rgba-regex/download/rgba-regex-1.0.0.tgz", + "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npm.taobao.org/rimraf/download/rimraf-2.7.1.tgz", + "integrity": "sha1-NXl/E6f9rcVmFCwp1PB8ytSD4+w=", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/ripemd160/download/ripemd160-2.0.2.tgz", + "integrity": "sha1-ocGm9iR1FXe6XQeRTLyShQWFiQw=", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/run-queue/download/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz", + "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/safe-regex/download/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/safer-buffer/download/safer-buffer-2.1.2.tgz", + "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=", + "dev": true + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npm.taobao.org/sax/download/sax-1.2.4.tgz", + "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=", + "dev": true + }, + "schart.js": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/schart.js/download/schart.js-3.0.0.tgz", + "integrity": "sha1-Rb22sRKmA/rgw6rV0v27m4D4bVc=" + }, + "schema-utils": { + "version": "2.6.6", + "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-2.6.6.tgz?cache=0&sync_timestamp=1587138453873&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fschema-utils%2Fdownload%2Fschema-utils-2.6.6.tgz", + "integrity": "sha1-KZ/mvUozZdwj2Z/URsr/jx1sMww=", + "dev": true, + "requires": { + "ajv": "^6.12.0", + "ajv-keywords": "^3.4.1" + } + }, + "select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=" + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/select-hose/download/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz", + "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=", + "dev": true + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npm.taobao.org/send/download/send-0.17.1.tgz", + "integrity": "sha1-wdiwWfeQD3Rm3Uk4vcROEd2zdsg=", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "dev": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npm.taobao.org/mime/download/mime-1.6.0.tgz", + "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.1.tgz", + "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=", + "dev": true + } + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npm.taobao.org/serve-index/download/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.0.tgz", + "integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=", + "dev": true + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npm.taobao.org/serve-static/download/serve-static-1.14.1.tgz", + "integrity": "sha1-Zm5jbcTwEPfvKZcKiKZ0MgiYsvk=", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/set-blocking/download/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/set-value/download/set-value-2.0.1.tgz?cache=0&sync_timestamp=1585775409029&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fset-value%2Fdownload%2Fset-value-2.0.1.tgz", + "integrity": "sha1-oY1AUw5vB95CKMfe/kInr4ytAFs=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npm.taobao.org/setimmediate/download/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.1.tgz", + "integrity": "sha1-fpWsskqpL1iF4KvvW6ExMw1K5oM=", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npm.taobao.org/sha.js/download/sha.js-2.4.11.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsha.js%2Fdownload%2Fsha.js-2.4.11.tgz", + "integrity": "sha1-N6XPC4HsvGlD3hCbopYNGyZYSuc=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/shebang-command/download/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/shebang-regex/download/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shell-quote": { + "version": "1.7.2", + "resolved": "https://registry.npm.taobao.org/shell-quote/download/shell-quote-1.7.2.tgz", + "integrity": "sha1-Z6fQLHbJ2iT5nSCAj8re0ODgS+I=", + "dev": true + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "dependencies": { + "object-inspect": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", + "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==" + } + } + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npm.taobao.org/signal-exit/download/signal-exit-3.0.3.tgz?cache=0&sync_timestamp=1585253750175&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsignal-exit%2Fdownload%2Fsignal-exit-3.0.3.tgz", + "integrity": "sha1-oUEMLt2PB3sItOJTyOrPyvBXRhw=", + "dev": true + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npm.taobao.org/simple-swizzle/download/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dev": true, + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npm.taobao.org/is-arrayish/download/is-arrayish-0.3.2.tgz", + "integrity": "sha1-RXSirlb3qyBolvtDHq7tBm/fjwM=", + "dev": true + } + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/slash/download/slash-2.0.0.tgz", + "integrity": "sha1-3lUoUaF1nfOo8gZTVEL17E3eq0Q=", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npm.taobao.org/snapdragon/download/snapdragon-0.8.2.tgz", + "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/snapdragon-node/download/snapdragon-node-2.1.1.tgz", + "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/snapdragon-util/download/snapdragon-util-3.0.1.tgz", + "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz", + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/sort-keys/download/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } + }, + "sortablejs": { + "version": "1.10.2", + "resolved": "https://registry.npm.taobao.org/sortablejs/download/sortablejs-1.10.2.tgz", + "integrity": "sha1-bkA2TZE/mLhaFPZnj5K1wSIfUpA=" + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/source-list-map/download/source-list-map-2.0.1.tgz", + "integrity": "sha1-OZO9hzv8SEecyp6jpUeDXHwVSzQ=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npm.taobao.org/source-map-resolve/download/source-map-resolve-0.5.3.tgz?cache=0&sync_timestamp=1584829593933&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map-resolve%2Fdownload%2Fsource-map-resolve-0.5.3.tgz", + "integrity": "sha1-GQhmvs51U+H48mei7oLGBrVQmho=", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npm.taobao.org/source-map-support/download/source-map-support-0.5.19.tgz?cache=0&sync_timestamp=1587719493563&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map-support%2Fdownload%2Fsource-map-support-0.5.19.tgz", + "integrity": "sha1-qYti+G3K9PZzmWSMCFKRq56P7WE=", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npm.taobao.org/source-map-url/download/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/spdx-correct/download/spdx-correct-3.1.0.tgz", + "integrity": "sha1-+4PlBERSaPFUsHTiGMh8ADzTHfQ=", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/spdx-exceptions/download/spdx-exceptions-2.3.0.tgz?cache=0&sync_timestamp=1587423110762&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fspdx-exceptions%2Fdownload%2Fspdx-exceptions-2.3.0.tgz", + "integrity": "sha1-PyjOGnegA3JoPq3kpDMYNSeiFj0=", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/spdx-expression-parse/download/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npm.taobao.org/spdx-license-ids/download/spdx-license-ids-3.0.5.tgz", + "integrity": "sha1-NpS1gEVnpFjTyARYQqY1hjL2JlQ=", + "dev": true + }, + "spdy": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/spdy/download/spdy-4.0.2.tgz?cache=0&sync_timestamp=1585970558936&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fspdy%2Fdownload%2Fspdy-4.0.2.tgz", + "integrity": "sha1-t09GYgOj7aRSwCSSuR+56EonZ3s=", + "dev": true, + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz", + "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz", + "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=", + "dev": true + } + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/spdy-transport/download/spdy-transport-3.0.0.tgz", + "integrity": "sha1-ANSGOmQArXXfkzYaFghgXl3NzzE=", + "dev": true, + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz", + "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz", + "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.6.0.tgz", + "integrity": "sha1-M3u9o63AcGvT4CRCaihtS0sskZg=", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/split-string/download/split-string-3.1.0.tgz", + "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npm.taobao.org/sshpk/download/sshpk-1.16.1.tgz", + "integrity": "sha1-+2YcC+8ps520B2nuOfpwCT1vaHc=", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npm.taobao.org/stable/download/stable-0.1.8.tgz", + "integrity": "sha1-g26zyDgv4pNv6vVEYxAXzn1Ho88=", + "dev": true + }, + "stackframe": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/stackframe/download/stackframe-1.1.1.tgz", + "integrity": "sha1-/+8KMxixtgw7WFZJiaylZgcp7HE=", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npm.taobao.org/static-extend/download/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npm.taobao.org/statuses/download/statuses-1.5.0.tgz?cache=0&sync_timestamp=1587328410122&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstatuses%2Fdownload%2Fstatuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/stealthy-require/download/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/stream-browserify/download/stream-browserify-2.0.2.tgz?cache=0&sync_timestamp=1587041519870&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstream-browserify%2Fdownload%2Fstream-browserify-2.0.2.tgz", + "integrity": "sha1-h1IdOKRKp+6RzhzSpH3wy0ndZgs=", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npm.taobao.org/stream-each/download/stream-each-1.2.3.tgz", + "integrity": "sha1-6+J6DDibBPvMIzZClS4Qcxr6m64=", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npm.taobao.org/stream-http/download/stream-http-2.8.3.tgz?cache=0&sync_timestamp=1588702237891&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstream-http%2Fdownload%2Fstream-http-2.8.3.tgz", + "integrity": "sha1-stJCRpKIpaJ+xP6JM6z2I95lFPw=", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/stream-shift/download/stream-shift-1.0.1.tgz?cache=0&sync_timestamp=1576147157429&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstream-shift%2Fdownload%2Fstream-shift-1.0.1.tgz", + "integrity": "sha1-1wiCgVWasneEJCebCHfaPDktWj0=", + "dev": true + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/strict-uri-encode/download/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-2.1.1.tgz", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-3.0.0.tgz?cache=0&sync_timestamp=1570188570027&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-regex%2Fdownload%2Fansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string.prototype.padend": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/string.prototype.padend/download/string.prototype.padend-3.1.0.tgz", + "integrity": "sha1-3Aj1eoAQ3FwVNVAxj2fhOtu3KsM=", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "string.prototype.padstart": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/string.prototype.padstart/download/string.prototype.padstart-3.1.0.tgz?cache=0&sync_timestamp=1576312999956&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring.prototype.padstart%2Fdownload%2Fstring.prototype.padstart-3.1.0.tgz", + "integrity": "sha1-tHwIdUDQcQvlpJN1dRoKYnvU/5A=", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/string.prototype.trimend/download/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha1-hYEqa4R6wAInD1gIFGBkyZX7aRM=", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string.prototype.trimleft": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/string.prototype.trimleft/download/string.prototype.trimleft-2.1.2.tgz?cache=0&sync_timestamp=1585584322600&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring.prototype.trimleft%2Fdownload%2Fstring.prototype.trimleft-2.1.2.tgz", + "integrity": "sha1-RAiqLl1t3QyagHObCH+8BnwDs8w=", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimstart": "^1.0.0" + } + }, + "string.prototype.trimright": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/string.prototype.trimright/download/string.prototype.trimright-2.1.2.tgz", + "integrity": "sha1-x28c7zDyG7rYr+uNsVEUls+w8qM=", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimend": "^1.0.0" + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/string.prototype.trimstart/download/string.prototype.trimstart-1.0.1.tgz?cache=0&sync_timestamp=1586465413621&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring.prototype.trimstart%2Fdownload%2Fstring.prototype.trimstart-1.0.1.tgz", + "integrity": "sha1-FK9tnzSwU/fPyJty+PLuFLkDmlQ=", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-5.2.0.tgz", + "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/strip-eof/download/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/strip-final-newline/download/strip-final-newline-2.0.0.tgz", + "integrity": "sha1-ibhS+y/L6Tb29LMYevsKEsGrWK0=", + "dev": true + }, + "stylehacks": { + "version": "4.0.3", + "resolved": "https://registry.npm.taobao.org/stylehacks/download/stylehacks-4.0.3.tgz", + "integrity": "sha1-Zxj8r00eB9ihMYaQiB6NlnJqcdU=", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npm.taobao.org/postcss-selector-parser/download/postcss-selector-parser-3.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-selector-parser%2Fdownload%2Fpostcss-selector-parser-3.1.2.tgz", + "integrity": "sha1-sxD1xMD9r3b5SQK7qjDbaqhPUnA=", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-5.5.0.tgz", + "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/svg-tags/download/svg-tags-1.0.0.tgz", + "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=", + "dev": true + }, + "svgo": { + "version": "1.3.2", + "resolved": "https://registry.npm.taobao.org/svgo/download/svgo-1.3.2.tgz", + "integrity": "sha1-ttxRHAYzRsnkFbgeQ0ARRbltQWc=", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/tapable/download/tapable-1.1.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftapable%2Fdownload%2Ftapable-1.1.3.tgz", + "integrity": "sha1-ofzMBrWNth/XpF2i2kT186Pme6I=", + "dev": true + }, + "terser": { + "version": "4.6.13", + "resolved": "https://registry.npm.taobao.org/terser/download/terser-4.6.13.tgz?cache=0&sync_timestamp=1588561614797&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fterser%2Fdownload%2Fterser-4.6.13.tgz", + "integrity": "sha1-6HmnNkpeDbUrpIkezeAHQixWqRY=", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "thenify": { + "version": "3.3.0", + "resolved": "https://registry.npm.taobao.org/thenify/download/thenify-3.3.0.tgz", + "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=", + "dev": true, + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npm.taobao.org/thenify-all/download/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "dev": true, + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, + "thread-loader": { + "version": "2.1.3", + "resolved": "https://registry.npm.taobao.org/thread-loader/download/thread-loader-2.1.3.tgz", + "integrity": "sha1-y9LBOfwrLebp0o9iKGq3cMGsvdo=", + "dev": true, + "requires": { + "loader-runner": "^2.3.1", + "loader-utils": "^1.1.0", + "neo-async": "^2.6.0" + } + }, + "throttle-debounce": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-1.1.0.tgz", + "integrity": "sha512-XH8UiPCQcWNuk2LYePibW/4qL97+ZQ1AN3FNXwZRBNPPowo/NRU5fAlDCSNBJIYCKbioZfuYtMhG4quqoJhVzg==" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npm.taobao.org/through2/download/through2-2.0.5.tgz", + "integrity": "sha1-AcHjnrMdB8t9A6lqcIIyYLIxMs0=", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "thunky": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/thunky/download/thunky-1.1.0.tgz", + "integrity": "sha1-Wrr3FKlAXbBQRzK7zNLO3Z75U30=", + "dev": true + }, + "timers-browserify": { + "version": "2.0.11", + "resolved": "https://registry.npm.taobao.org/timers-browserify/download/timers-browserify-2.0.11.tgz", + "integrity": "sha1-gAsfPu4nLlvFPuRloE0OgEwxIR8=", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "timsort": { + "version": "0.3.0", + "resolved": "https://registry.npm.taobao.org/timsort/download/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", + "dev": true + }, + "tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/to-arraybuffer/download/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/to-fast-properties/download/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npm.taobao.org/to-object-path/download/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz", + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npm.taobao.org/to-regex/download/to-regex-3.0.2.tgz", + "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/to-regex-range/download/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/toidentifier/download/toidentifier-1.0.0.tgz", + "integrity": "sha1-fhvjRw8ed5SLxD2Uo8j013UrpVM=", + "dev": true + }, + "toposort": { + "version": "1.0.7", + "resolved": "https://registry.npm.taobao.org/toposort/download/toposort-1.0.7.tgz", + "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", + "dev": true + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npm.taobao.org/tough-cookie/download/tough-cookie-2.5.0.tgz?cache=0&sync_timestamp=1584645708631&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftough-cookie%2Fdownload%2Ftough-cookie-2.5.0.tgz", + "integrity": "sha1-zZ+yoKodWhK0c72fuW+j3P9lreI=", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tryer": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/tryer/download/tryer-1.0.1.tgz", + "integrity": "sha1-8shUBoALmw90yfdGW4HqrSQSUvg=", + "dev": true + }, + "tslib": { + "version": "1.11.2", + "resolved": "https://registry.npm.taobao.org/tslib/download/tslib-1.11.2.tgz?cache=0&sync_timestamp=1588720998778&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftslib%2Fdownload%2Ftslib-1.11.2.tgz", + "integrity": "sha1-nHnYMnLJp6rxZvc5Fclmfs3ePMk=", + "dev": true + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npm.taobao.org/tty-browserify/download/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npm.taobao.org/tweetnacl/download/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npm.taobao.org/type-fest/download/type-fest-0.6.0.tgz", + "integrity": "sha1-jSojcNPfiG61yQraHFv2GIrPg4s=", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npm.taobao.org/type-is/download/type-is-1.6.18.tgz", + "integrity": "sha1-TlUs0F3wlGfcvE73Od6J8s83wTE=", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npm.taobao.org/typedarray/download/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uglify-js": { + "version": "3.4.10", + "resolved": "https://registry.npm.taobao.org/uglify-js/download/uglify-js-3.4.10.tgz", + "integrity": "sha1-mtlWPY6zrN+404WX0q8dgV9qdV8=", + "dev": true, + "requires": { + "commander": "~2.19.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npm.taobao.org/commander/download/commander-2.19.0.tgz", + "integrity": "sha1-9hmKqE5bg8RgVLlN3tv+1e6f8So=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + } + } + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/unicode-canonical-property-names-ecmascript/download/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha1-JhmADEyCWADv3YNDr33Zkzy+KBg=", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/unicode-match-property-ecmascript/download/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha1-jtKjJWmWG86SJ9Cc0/+7j+1fAgw=", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/unicode-match-property-value-ecmascript/download/unicode-match-property-value-ecmascript-1.2.0.tgz?cache=0&sync_timestamp=1583948752590&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Funicode-match-property-value-ecmascript%2Fdownload%2Funicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha1-DZH2AO7rMJaqlisdb8iIduZOpTE=", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/unicode-property-aliases-ecmascript/download/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha1-3Vepn2IHvt/0Yoq++5TFDblByPQ=", + "dev": true + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/union-value/download/union-value-1.0.1.tgz", + "integrity": "sha1-C2/nuDWuzaYcbqTU8CwUIh4QmEc=", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/uniq/download/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/uniqs/download/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", + "dev": true + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/unique-filename/download/unique-filename-1.1.1.tgz", + "integrity": "sha1-HWl2k2mtoFgxA6HmrodoG1ZXMjA=", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/unique-slug/download/unique-slug-2.0.2.tgz", + "integrity": "sha1-uqvOkQg/xk6UWw861hPiZPfNTmw=", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npm.taobao.org/universalify/download/universalify-0.1.2.tgz", + "integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/unpipe/download/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unquote": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/unquote/download/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/unset-value/download/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npm.taobao.org/has-value/download/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/isobject/download/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npm.taobao.org/has-values/download/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/upath/download/upath-1.2.0.tgz", + "integrity": "sha1-j2bbzVWog6za5ECK+LA1pQRMGJQ=", + "dev": true + }, + "upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/upper-case/download/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npm.taobao.org/uri-js/download/uri-js-4.2.2.tgz", + "integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npm.taobao.org/urix/download/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npm.taobao.org/url/download/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npm.taobao.org/punycode/download/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-loader": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/url-loader/download/url-loader-1.1.2.tgz", + "integrity": "sha1-uXHRkbg69pPF4/6kBkvp4fLX+Ng=", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "mime": "^2.0.3", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz?cache=0&sync_timestamp=1587138453873&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fschema-utils%2Fdownload%2Fschema-utils-1.0.0.tgz", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "url-parse": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.1.tgz", + "integrity": "sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==", + "dev": true, + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/use/download/use-3.1.1.tgz", + "integrity": "sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8=", + "dev": true + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npm.taobao.org/util/download/util-0.11.1.tgz?cache=0&sync_timestamp=1588238435623&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Futil%2Fdownload%2Futil-0.11.1.tgz", + "integrity": "sha1-MjZzNyDsZLsn9uJvQhqqLhtYjWE=", + "dev": true, + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/util.promisify/download/util.promisify-1.0.1.tgz", + "integrity": "sha1-a693dLgO6w91INi4HQeYKlmruu4=", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + } + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npm.taobao.org/utila/download/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/utils-merge/download/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npm.taobao.org/uuid/download/uuid-3.4.0.tgz", + "integrity": "sha1-sj5DWK+oogL+ehAK8fX4g/AgB+4=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npm.taobao.org/validate-npm-package-license/download/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha1-/JH2uce6FchX9MssXe/uw51PQQo=", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/vary/download/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "vendors": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/vendors/download/vendors-1.0.4.tgz", + "integrity": "sha1-4rgApT56Kbk1BsPPQRANFsTErY4=", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npm.taobao.org/verror/download/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/vm-browserify/download/vm-browserify-1.1.2.tgz", + "integrity": "sha1-eGQcSIuObKkadfUR56OzKobl3aA=", + "dev": true + }, + "vue": { + "version": "2.6.11", + "resolved": "https://registry.npm.taobao.org/vue/download/vue-2.6.11.tgz", + "integrity": "sha1-dllNh31LEiNEBuhONSdcbVFBJcU=" + }, + "vue-clipboard2": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/vue-clipboard2/-/vue-clipboard2-0.3.1.tgz", + "integrity": "sha512-H5S/agEDj0kXjUb5GP2c0hCzIXWRBygaWLN3NEFsaI9I3uWin778SFEMt8QRXiPG+7anyjqWiw2lqcxWUSfkYg==", + "requires": { + "clipboard": "^2.0.0" + } + }, + "vue-cropperjs": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/vue-cropperjs/download/vue-cropperjs-3.0.0.tgz", + "integrity": "sha1-s0VgCacgFK6YvTdKHYEqXB9f9G8=", + "requires": { + "cropperjs": "^1.1.3" + } + }, + "vue-hot-reload-api": { + "version": "2.3.4", + "resolved": "https://registry.npm.taobao.org/vue-hot-reload-api/download/vue-hot-reload-api-2.3.4.tgz", + "integrity": "sha1-UylVzB6yCKPZkLOp+acFdGV+CPI=", + "dev": true + }, + "vue-i18n": { + "version": "8.17.5", + "resolved": "https://registry.npm.taobao.org/vue-i18n/download/vue-i18n-8.17.5.tgz", + "integrity": "sha1-40ztpCc6g76Uw5I1iiJ9ZrdqyxI=" + }, + "vue-json-viewer": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/vue-json-viewer/-/vue-json-viewer-2.2.11.tgz", + "integrity": "sha512-1wKK5vlthju7cSmlXn3SVugOZjFpf6ApoZqGigo3eK6hrylNLzeMm+Pm6FzMS2ykdTUUYuWqhqR8uMl88CY76g==", + "requires": { + "clipboard": "^2.0.4", + "vue": "^2.6.9" + } + }, + "vue-loader": { + "version": "15.9.2", + "resolved": "https://registry.npm.taobao.org/vue-loader/download/vue-loader-15.9.2.tgz?cache=0&sync_timestamp=1588988550579&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-loader%2Fdownload%2Fvue-loader-15.9.2.tgz", + "integrity": "sha1-rgH19MnGoEv/RIORLnLvkaQCwa4=", + "dev": true, + "requires": { + "@vue/component-compiler-utils": "^3.1.0", + "hash-sum": "^1.0.2", + "loader-utils": "^1.1.0", + "vue-hot-reload-api": "^2.3.0", + "vue-style-loader": "^4.1.0" + } + }, + "vue-native-websocket": { + "version": "2.0.14", + "resolved": "https://registry.npm.taobao.org/vue-native-websocket/download/vue-native-websocket-2.0.14.tgz", + "integrity": "sha1-/dtW+fk9LsyGFIbuPI8pUG6ioWg=", + "dependencies": { + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=" + }, + "accepts": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", + "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", + "requires": { + "mime-types": "~2.1.11", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" + }, + "acorn-dynamic-import": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", + "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", + "requires": { + "acorn": "^4.0.3" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=" + } + } + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "requires": { + "acorn": "^3.0.4" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "http://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" + } + } + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "requires": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + }, + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=" + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "optional": true + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=" + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + }, + "arraybuffer.slice": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz", + "integrity": "sha1-8zshWfBTKj8xB6JywMz70a0peco=" + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "requires": { + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, + "babel-cli": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", + "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", + "requires": { + "babel-core": "^6.26.0", + "babel-polyfill": "^6.26.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "chokidar": "^1.6.1", + "commander": "^2.11.0", + "convert-source-map": "^1.5.0", + "fs-readdir-recursive": "^1.0.0", + "glob": "^7.1.2", + "lodash": "^4.17.4", + "output-file-sync": "^1.1.2", + "path-is-absolute": "^1.0.1", + "slash": "^1.0.0", + "source-map": "^0.5.6", + "v8flags": "^2.1.1" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + } + }, + "babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "requires": { + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "convert-source-map": "^1.5.1", + "debug": "^2.6.9", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.8", + "slash": "^1.0.0", + "source-map": "^0.5.7" + } + }, + "babel-eslint": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-7.2.3.tgz", + "integrity": "sha1-sv4tgBJkcPXBlELcdXJTqJdxCCc=", + "requires": { + "babel-code-frame": "^6.22.0", + "babel-traverse": "^6.23.1", + "babel-types": "^6.23.0", + "babylon": "^6.17.0" + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "requires": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "requires": { + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "requires": { + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-loader": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.5.tgz", + "integrity": "sha512-iCHfbieL5d1LfOQeeVJEUyD9rTwBcP/fcEbRCfempxTDuqrKpu0AZjLAQHEQa3Yqyj9ORKe2iHfoj4rHLf7xpw==", + "requires": { + "find-cache-dir": "^1.0.0", + "loader-utils": "^1.0.2", + "mkdirp": "^0.5.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "requires": { + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "requires": { + "babel-helper-define-map": "^6.24.1", + "babel-helper-function-name": "^6.24.1", + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-helper-replace-supers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", + "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "requires": { + "babel-plugin-transform-strict-mode": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-types": "^6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "requires": { + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "requires": { + "babel-helper-replace-supers": "^6.24.1", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "requires": { + "babel-helper-call-delegate": "^6.24.1", + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "regexpu-core": "^2.0.0" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "requires": { + "regenerator-transform": "^0.10.0" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "requires": { + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" + } + } + }, + "babel-preset-es2015": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", + "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", + "requires": { + "babel-plugin-check-es2015-constants": "^6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoping": "^6.24.1", + "babel-plugin-transform-es2015-classes": "^6.24.1", + "babel-plugin-transform-es2015-computed-properties": "^6.24.1", + "babel-plugin-transform-es2015-destructuring": "^6.22.0", + "babel-plugin-transform-es2015-duplicate-keys": "^6.24.1", + "babel-plugin-transform-es2015-for-of": "^6.22.0", + "babel-plugin-transform-es2015-function-name": "^6.24.1", + "babel-plugin-transform-es2015-literals": "^6.22.0", + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-plugin-transform-es2015-modules-systemjs": "^6.24.1", + "babel-plugin-transform-es2015-modules-umd": "^6.24.1", + "babel-plugin-transform-es2015-object-super": "^6.24.1", + "babel-plugin-transform-es2015-parameters": "^6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "^6.24.1", + "babel-plugin-transform-es2015-spread": "^6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "^6.24.1", + "babel-plugin-transform-es2015-template-literals": "^6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "^6.22.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.24.1", + "babel-plugin-transform-regenerator": "^6.24.1" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "requires": { + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "requires": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + }, + "base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=" + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "requires": { + "callsite": "1.0.0" + } + }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=" + }, + "blob": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", + "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=" + }, + "bluebird": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz", + "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==" + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=" + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "requires": { + "pako": "~1.0.5" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "requires": { + "callsites": "^0.2.0" + } + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=" + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "chai": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", + "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "requires": { + "assertion-error": "^1.0.1", + "check-error": "^1.0.1", + "deep-eql": "^3.0.0", + "get-func-name": "^2.0.0", + "pathval": "^1.0.0", + "type-detect": "^4.0.0" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==" + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "requires": { + "restore-cursor": "^1.0.1" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + } + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "colors": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.2.tgz", + "integrity": "sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ==" + }, + "combine-lists": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", + "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", + "requires": { + "lodash": "^4.5.0" + } + }, + "commander": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.18.0.tgz", + "integrity": "sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" + }, + "component-emitter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz", + "integrity": "sha1-KWWU8nU9qmOZbSrwjRWpURbJrsM=" + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "connect": { + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", + "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.0", + "parseurl": "~1.3.2", + "utils-merge": "1.0.1" + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "requires": { + "date-now": "^0.1.4" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "requires": { + "array-find-index": "^1.0.1" + } + }, + "custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=" + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "requires": { + "es5-ext": "^0.10.9" + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" + }, + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.3.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "requires": { + "type-detect": "^4.0.0" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "requires": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "requires": { + "repeating": "^2.0.0" + } + }, + "di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=" + }, + "diff": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", + "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=" + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "elliptic": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "engine.io": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-1.8.3.tgz", + "integrity": "sha1-jef5eJXSDTm4X4ju7nd7K9QrE9Q=", + "requires": { + "accepts": "1.3.3", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "2.3.3", + "engine.io-parser": "1.3.2", + "ws": "1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.3.3", + "resolved": "http://registry.npmjs.org/debug/-/debug-2.3.3.tgz", + "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "requires": { + "ms": "0.7.2" + } + }, + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + } + } + }, + "engine.io-client": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.8.3.tgz", + "integrity": "sha1-F5jtk0USRkU9TG9jXXogH+lA1as=", + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "2.3.3", + "engine.io-parser": "1.3.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parsejson": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "1.1.2", + "xmlhttprequest-ssl": "1.5.3", + "yeast": "0.1.2" + }, + "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "debug": { + "version": "2.3.3", + "resolved": "http://registry.npmjs.org/debug/-/debug-2.3.3.tgz", + "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "requires": { + "ms": "0.7.2" + } + }, + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + } + } + }, + "engine.io-parser": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.3.2.tgz", + "integrity": "sha1-k3sHnwAH0Ik+xW1GyyILjLQ1Igo=", + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "0.0.6", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.4", + "has-binary": "0.1.7", + "wtf-8": "1.0.0" + } + }, + "enhanced-resolve": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", + "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "object-assign": "^4.0.1", + "tapable": "^0.2.7" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=" + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es5-ext": { + "version": "0.10.46", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", + "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "1" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "requires": { + "d": "1", + "es5-ext": "^0.10.14", + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "requires": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.2.0" + }, + "dependencies": { + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=" + }, + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "optional": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "requires": { + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", + "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", + "requires": { + "babel-code-frame": "^6.16.0", + "chalk": "^1.1.3", + "concat-stream": "^1.5.2", + "debug": "^2.1.1", + "doctrine": "^2.0.0", + "escope": "^3.6.0", + "espree": "^3.4.0", + "esquery": "^1.0.0", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "glob": "^7.0.3", + "globals": "^9.14.0", + "ignore": "^3.2.0", + "imurmurhash": "^0.1.4", + "inquirer": "^0.12.0", + "is-my-json-valid": "^2.10.0", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.5.1", + "json-stable-stringify": "^1.0.0", + "levn": "^0.3.0", + "lodash": "^4.0.0", + "mkdirp": "^0.5.0", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.1", + "pluralize": "^1.2.1", + "progress": "^1.1.8", + "require-uncached": "^1.0.2", + "shelljs": "^0.7.5", + "strip-bom": "^3.0.0", + "strip-json-comments": "~2.0.1", + "table": "^3.7.8", + "text-table": "~0.2.0", + "user-home": "^2.0.0" + }, + "dependencies": { + "user-home": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", + "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "requires": { + "os-homedir": "^1.0.0" + } + } + } + }, + "eslint-config-standard": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", + "integrity": "sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE=" + }, + "eslint-import-resolver-node": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "requires": { + "debug": "^2.6.9", + "resolve": "^1.5.0" + } + }, + "eslint-module-utils": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", + "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", + "requires": { + "debug": "^2.6.8", + "pkg-dir": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "requires": { + "find-up": "^1.0.0" + } + } + } + }, + "eslint-plugin-import": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz", + "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==", + "requires": { + "contains-path": "^0.1.0", + "debug": "^2.6.8", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.1", + "eslint-module-utils": "^2.2.0", + "has": "^1.0.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.3", + "read-pkg-up": "^2.0.0", + "resolve": "^1.6.0" + }, + "dependencies": { + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + } + } + }, + "eslint-plugin-node": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-4.2.3.tgz", + "integrity": "sha512-vIUQPuwbVYdz/CYnlTLsJrRy7iXHQjdEe5wz0XhhdTym3IInM/zZLlPf9nZ2mThsH0QcsieCOWs2vOeCy/22LQ==", + "requires": { + "ignore": "^3.0.11", + "minimatch": "^3.0.2", + "object-assign": "^4.0.1", + "resolve": "^1.1.7", + "semver": "5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + } + } + }, + "eslint-plugin-promise": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz", + "integrity": "sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ==" + }, + "eslint-plugin-standard": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz", + "integrity": "sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w==" + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "eventemitter3": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", + "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==" + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=" + }, + "expand-braces": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", + "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", + "requires": { + "array-slice": "^0.2.3", + "array-unique": "^0.2.1", + "braces": "^0.1.2" + }, + "dependencies": { + "braces": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", + "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", + "requires": { + "expand-range": "^0.1.0" + } + }, + "expand-range": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", + "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", + "requires": { + "is-number": "^0.1.1", + "repeat-string": "^0.2.2" + } + }, + "is-number": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", + "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=" + }, + "repeat-string": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", + "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=" + } + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "requires": { + "fill-range": "^2.1.0" + } + }, + "exports-loader": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/exports-loader/-/exports-loader-0.6.4.tgz", + "integrity": "sha1-1w/GEhl1s1/BKDDPUnVL4nQPyIY=", + "requires": { + "loader-utils": "^1.0.2", + "source-map": "0.5.x" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "requires": { + "is-extglob": "^1.0.0" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "finalhandler": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.3.1", + "unpipe": "~1.0.0" + }, + "dependencies": { + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + } + } + }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "^2.0.0" + } + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "requires": { + "circular-json": "^0.3.1", + "del": "^2.0.2", + "graceful-fs": "^4.1.2", + "write": "^0.2.1" + } + }, + "follow-redirects": { + "version": "1.5.8", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.8.tgz", + "integrity": "sha512-sy1mXPmv7kLAMKW/8XofG7o9T+6gAjzdZK4AJF6ryqQYUa/hnzgiypoeUecZ53x7XiqKNEpNqLtS97MshW2nxg==", + "requires": { + "debug": "=3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "requires": { + "for-in": "^1.0.1" + } + }, + "formatio": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz", + "integrity": "sha1-87IWfZBoxGmKjVH092CjmlTYGOs=", + "requires": { + "samsam": "1.x" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "^0.2.2" + } + }, + "fs-access": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", + "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", + "requires": { + "null-check": "^1.0.0" + } + }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "optional": true, + "requires": { + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "bundled": true, + "optional": true, + "requires": { + "safer-buffer": "^2.1.0" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "optional": true + }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.1", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, + "optional": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.0", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.1.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "optional": true, + "requires": { + "deep-extend": "^0.5.1", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "optional": true, + "requires": { + "glob": "^7.0.5" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, + "optional": true, + "requires": { + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.2.4", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.1", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "optional": true, + "requires": { + "string-width": "^1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "optional": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "requires": { + "is-property": "^1.0.2" + } + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "requires": { + "is-property": "^1.0.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "requires": { + "is-glob": "^2.0.0" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=" + }, + "handlebars": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz", + "integrity": "sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==", + "requires": { + "async": "^2.5.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + }, + "dependencies": { + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "^4.17.10" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-binary": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.7.tgz", + "integrity": "sha1-aOYesWIQyVRaClzOBqhzkS/h5ow=", + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + } + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", + "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "http-proxy": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", + "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "requires": { + "eventemitter3": "^3.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==" + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "requires": { + "repeating": "^2.0.0" + } + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "inquirer": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "requires": { + "ansi-escapes": "^1.1.0", + "ansi-regex": "^2.0.0", + "chalk": "^1.0.0", + "cli-cursor": "^1.0.1", + "cli-width": "^2.0.0", + "figures": "^1.3.5", + "lodash": "^4.3.0", + "readline2": "^1.0.1", + "run-async": "^0.1.0", + "rx-lite": "^3.1.2", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" + } + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=" + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "requires": { + "is-primitive": "^2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "^1.0.0" + } + }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==" + }, + "is-my-json-valid": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz", + "integrity": "sha512-mG0f/unGX1HZ5ep4uhRaPOS8EkAY8/j6mDRMJrutq4CqhoJWYp7qAlonIPy3TV7p3ju4TK9fo/PbnoksWmsp5Q==", + "requires": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^4.0.0", + "xtend": "^4.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isbinaryfile": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "requires": { + "buffer-alloc": "^1.2.0" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + }, + "istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "requires": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" + }, + "json-loader": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", + "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "requires": { + "jsonify": "~0.0.0" + } + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=" + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=" + }, + "karma": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/karma/-/karma-1.7.1.tgz", + "integrity": "sha512-k5pBjHDhmkdaUccnC7gE3mBzZjcxyxYsYVaqiL2G5AqlfLyBO5nw2VdNK+O16cveEPd/gIOWULH7gkiYYwVNHg==", + "requires": { + "bluebird": "^3.3.0", + "body-parser": "^1.16.1", + "chokidar": "^1.4.1", + "colors": "^1.1.0", + "combine-lists": "^1.0.0", + "connect": "^3.6.0", + "core-js": "^2.2.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.0", + "expand-braces": "^0.1.1", + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "http-proxy": "^1.13.0", + "isbinaryfile": "^3.0.0", + "lodash": "^3.8.0", + "log4js": "^0.6.31", + "mime": "^1.3.4", + "minimatch": "^3.0.2", + "optimist": "^0.6.1", + "qjobs": "^1.1.4", + "range-parser": "^1.2.0", + "rimraf": "^2.6.0", + "safe-buffer": "^5.0.1", + "socket.io": "1.7.3", + "source-map": "^0.5.3", + "tmp": "0.0.31", + "useragent": "^2.1.12" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "http://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + } + } + }, + "karma-chrome-launcher": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", + "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", + "requires": { + "fs-access": "^1.0.0", + "which": "^1.2.1" + } + }, + "karma-coverage": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-1.1.2.tgz", + "integrity": "sha512-eQawj4Cl3z/CjxslYy9ariU4uDh7cCNFZHNWXWRpl0pNeblY/4wHR7M7boTYXWrn9bY0z2pZmr11eKje/S/hIw==", + "requires": { + "dateformat": "^1.0.6", + "istanbul": "^0.4.0", + "lodash": "^4.17.0", + "minimatch": "^3.0.0", + "source-map": "^0.5.1" + } + }, + "karma-mocha": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", + "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", + "requires": { + "minimist": "1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "karma-sinon-chai": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/karma-sinon-chai/-/karma-sinon-chai-1.3.4.tgz", + "integrity": "sha512-Oatu8tdkfWaSveM809euI6KGcNJRdoXFilz9ozSf+vPwrM73kncu54nsfkLcMqR/iht3PXASAGK9La5oU2xDKQ==", + "requires": { + "lolex": "^1.6.0" + } + }, + "karma-sourcemap-loader": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz", + "integrity": "sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=", + "requires": { + "graceful-fs": "^4.1.2" + } + }, + "karma-spec-reporter": { + "version": "0.0.31", + "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz", + "integrity": "sha1-SDDccUihVcfXoYbmMjOaDYD63sM=", + "requires": { + "colors": "^1.1.2" + } + }, + "karma-webpack": { + "version": "2.0.13", + "resolved": "http://registry.npmjs.org/karma-webpack/-/karma-webpack-2.0.13.tgz", + "integrity": "sha512-2cyII34jfrAabbI2+4Rk4j95Nazl98FvZQhgSiqKUDarT317rxfv/EdzZ60CyATN4PQxJdO5ucR5bOOXkEVrXw==", + "requires": { + "async": "^2.0.0", + "babel-runtime": "^6.0.0", + "loader-utils": "^1.0.0", + "lodash": "^4.0.0", + "source-map": "^0.5.6", + "webpack-dev-middleware": "^1.12.0" + }, + "dependencies": { + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "^4.17.10" + } + } + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "^1.0.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "loader-runner": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", + "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=" + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash.keys": "^3.0.0" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=" + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=" + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=" + }, + "lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "requires": { + "lodash._baseassign": "^3.0.0", + "lodash._basecreate": "^3.0.0", + "lodash._isiterateecall": "^3.0.0" + } + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "log4js": { + "version": "0.6.38", + "resolved": "http://registry.npmjs.org/log4js/-/log4js-0.6.38.tgz", + "integrity": "sha1-LElBFmldb7JUgJQ9P8hy5mKlIv0=", + "requires": { + "readable-stream": "~1.0.2", + "semver": "~4.3.3" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=" + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "lolex": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz", + "integrity": "sha1-OpoCg0UqR9dDnnJzG54H1zhuSfY=" + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "lru-cache": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "requires": { + "pify": "^3.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "^1.0.0" + } + }, + "math-random": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=" + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "^0.2.0" + } + } + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.36.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", + "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==" + }, + "mime-types": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", + "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", + "requires": { + "mime-db": "~1.36.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", + "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.6.8", + "diff": "3.2.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.1", + "growl": "1.9.2", + "he": "1.1.1", + "json3": "3.3.2", + "lodash.create": "3.1.1", + "mkdirp": "0.5.1", + "supports-color": "3.1.2" + }, + "dependencies": { + "commander": { + "version": "2.9.0", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "requires": { + "graceful-readlink": ">= 1.0.0" + } + }, + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "requires": { + "ms": "2.0.0" + } + }, + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "mock-socket": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-6.1.0.tgz", + "integrity": "sha1-8KiBXI0F6uSk2ySFvTmPI+MDBSw=" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mute-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=" + }, + "nan": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.0.tgz", + "integrity": "sha512-F4miItu2rGnV2ySkXOQoA8FKz/SR2Q2sWP0sbTxNxz/tuokeC8WxOhPMcwi0qIyGtVn/rrSeLbvVkznqCdwYnw==", + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "native-promise-only": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", + "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "neo-async": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.2.tgz", + "integrity": "sha512-vdqTKI9GBIYcAEbFAcpKPErKINfPF5zIuz3/niBfq8WUZjpT2tytLlFVrBgWdOtqI4uaA/Rb6No0hux39XXDuw==" + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, + "node-libs-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^1.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.0", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.10.3", + "vm-browserify": "0.0.4" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "null-check": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", + "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=" + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "options": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", + "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=" + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "output-file-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "requires": { + "graceful-fs": "^4.1.4", + "mkdirp": "^0.5.1", + "object-assign": "^4.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + }, + "pako": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==" + }, + "parse-asn1": { + "version": "5.1.1", + "resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", + "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "parsejson": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/parsejson/-/parsejson-0.0.3.tgz", + "integrity": "sha1-q343WfIJ7OmUN5c/fQ8fZK4OZKs=", + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=" + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "path-to-regexp": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + } + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "requires": { + "pify": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" + }, + "pbkdf2": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", + "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "requires": { + "find-up": "^2.1.0" + } + }, + "pluralize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", + "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=" + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=" + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "public-encrypt": { + "version": "4.0.2", + "resolved": "http://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", + "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" + }, + "randomatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", + "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "raw-loader": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz", + "integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=" + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "requires": { + "graceful-fs": "^4.1.2", + "minimatch": "^3.0.2", + "readable-stream": "^2.0.2", + "set-immediate-shim": "^1.0.1" + } + }, + "readline2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", + "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "mute-stream": "0.0.5" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "requires": { + "resolve": "^1.1.6" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "requires": { + "babel-runtime": "^6.18.0", + "babel-types": "^6.19.0", + "private": "^0.1.6" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "requires": { + "is-finite": "^1.0.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + } + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "requires": { + "path-parse": "^1.0.5" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=" + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "requires": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "requires": { + "align-text": "^0.1.1" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "^7.0.5" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "requires": { + "once": "^1.3.0" + } + }, + "rx-lite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "samsam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", + "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==" + }, + "script-loader": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/script-loader/-/script-loader-0.7.2.tgz", + "integrity": "sha512-UMNLEvgOAQuzK8ji8qIscM3GIrRCWN6MmMXGD4SD5l6cSycgGsCo0tX5xRnfQcoghqct0tjHjcykgI1PyBE2aA==", + "requires": { + "raw-loader": "~0.5.1" + } + }, + "semver": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", + "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "shelljs": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", + "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "sinon": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-2.4.1.tgz", + "integrity": "sha512-vFTrO9Wt0ECffDYIPSP/E5bBugt0UjcBQOfQUMh66xzkyPEnhl/vM2LRZi2ajuTdkH07sA6DzrM6KvdvGIH8xw==", + "requires": { + "diff": "^3.1.0", + "formatio": "1.2.0", + "lolex": "^1.6.0", + "native-promise-only": "^0.8.1", + "path-to-regexp": "^1.7.0", + "samsam": "^1.1.3", + "text-encoding": "0.6.4", + "type-detect": "^4.0.0" + } + }, + "sinon-chai": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-2.14.0.tgz", + "integrity": "sha512-9stIF1utB0ywNHNT7RgiXbdmen8QDCRsrTjw+G9TgKt1Yexjiv8TOWZ6WHsTPz57Yky3DIswZvEqX8fpuHNDtQ==" + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=" + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "^3.2.0" + } + }, + "socket.io": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-1.7.3.tgz", + "integrity": "sha1-uK+cq6AJSeVo42nxMn6pvp6iRhs=", + "requires": { + "debug": "2.3.3", + "engine.io": "1.8.3", + "has-binary": "0.1.7", + "object-assign": "4.1.0", + "socket.io-adapter": "0.5.0", + "socket.io-client": "1.7.3", + "socket.io-parser": "2.3.1" + }, + "dependencies": { + "debug": { + "version": "2.3.3", + "resolved": "http://registry.npmjs.org/debug/-/debug-2.3.3.tgz", + "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "requires": { + "ms": "0.7.2" + } + }, + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + }, + "object-assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", + "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=" + } + } + }, + "socket.io-adapter": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz", + "integrity": "sha1-y21LuL7IHhB4uZZ3+c7QBGBmu4s=", + "requires": { + "debug": "2.3.3", + "socket.io-parser": "2.3.1" + }, + "dependencies": { + "debug": { + "version": "2.3.3", + "resolved": "http://registry.npmjs.org/debug/-/debug-2.3.3.tgz", + "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "requires": { + "ms": "0.7.2" + } + }, + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + } + } + }, + "socket.io-client": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.7.3.tgz", + "integrity": "sha1-sw6GqhDV7zVGYBwJzeR2Xjgdo3c=", + "requires": { + "backo2": "1.0.2", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "2.3.3", + "engine.io-client": "1.8.3", + "has-binary": "0.1.7", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseuri": "0.0.5", + "socket.io-parser": "2.3.1", + "to-array": "0.1.4" + }, + "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "debug": { + "version": "2.3.3", + "resolved": "http://registry.npmjs.org/debug/-/debug-2.3.3.tgz", + "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "requires": { + "ms": "0.7.2" + } + }, + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + } + } + }, + "socket.io-parser": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.3.1.tgz", + "integrity": "sha1-3VMgJRA85Clpcya+/WQAX8/ltKA=", + "requires": { + "component-emitter": "1.1.2", + "debug": "2.2.0", + "isarray": "0.0.1", + "json3": "3.3.2" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "requires": { + "ms": "0.7.1" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" + } + } + }, + "source-list-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", + "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "requires": { + "source-map": "^0.5.6" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "spdx-correct": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz", + "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==" + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "requires": { + "get-stdin": "^4.0.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "table": { + "version": "3.8.3", + "resolved": "http://registry.npmjs.org/table/-/table-3.8.3.tgz", + "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "requires": { + "ajv": "^4.7.0", + "ajv-keywords": "^1.0.0", + "chalk": "^1.1.1", + "lodash": "^4.0.0", + "slice-ansi": "0.0.4", + "string-width": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "tapable": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", + "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=" + }, + "text-encoding": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=" + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + }, + "through": { + "version": "2.3.8", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "time-stamp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.1.0.tgz", + "integrity": "sha512-lJbq6KsFhZJtN3fPUVje1tq/hHsJOKUUcUj/MGCiQR6qWBDcyi5kxL9J7/RnaEChCn0+L/DUN2WvemDrkk4i3Q==" + }, + "timers-browserify": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", + "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", + "requires": { + "setimmediate": "^1.0.4" + } + }, + "tmp": { + "version": "0.0.31", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", + "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", + "requires": { + "os-tmpdir": "~1.0.1" + } + }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + } + } + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "uglify-js": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", + "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", + "optional": true, + "requires": { + "commander": "~2.17.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "optional": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "optional": true + }, + "uglifyjs-webpack-plugin": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", + "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", + "requires": { + "source-map": "^0.5.6", + "uglify-js": "^2.8.29", + "webpack-sources": "^1.0.1" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + } + }, + "yargs": { + "version": "3.10.0", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + } + } + }, + "ultron": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", + "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=" + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } + } + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "upath": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==" + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=" + }, + "useragent": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", + "requires": { + "lru-cache": "4.1.x", + "tmp": "0.0.x" + } + }, + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "requires": { + "inherits": "2.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "requires": { + "user-home": "^1.1.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "requires": { + "indexof": "0.0.1" + } + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=" + }, + "vue": { + "version": "2.5.17", + "resolved": "https://registry.npmjs.org/vue/-/vue-2.5.17.tgz", + "integrity": "sha512-mFbcWoDIJi0w0Za4emyLiW72Jae0yjANHbCVquMKijcavBGypqlF7zHRgMa5k4sesdv7hv2rB4JPdZfR+TPfhQ==" + }, + "watchpack": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", + "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "requires": { + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "webpack": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.12.0.tgz", + "integrity": "sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ==", + "requires": { + "acorn": "^5.0.0", + "acorn-dynamic-import": "^2.0.0", + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0", + "async": "^2.1.2", + "enhanced-resolve": "^3.4.0", + "escope": "^3.6.0", + "interpret": "^1.0.0", + "json-loader": "^0.5.4", + "json5": "^0.5.1", + "loader-runner": "^2.3.0", + "loader-utils": "^1.1.0", + "memory-fs": "~0.4.1", + "mkdirp": "~0.5.0", + "node-libs-browser": "^2.0.0", + "source-map": "^0.5.3", + "supports-color": "^4.2.1", + "tapable": "^0.2.7", + "uglifyjs-webpack-plugin": "^0.4.6", + "watchpack": "^1.4.0", + "webpack-sources": "^1.0.1", + "yargs": "^8.0.2" + }, + "dependencies": { + "ajv": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz", + "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==", + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=" + }, + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "^4.17.10" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "requires": { + "has-flag": "^2.0.0" + } + } + } + }, + "webpack-dev-middleware": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", + "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==", + "requires": { + "memory-fs": "~0.4.1", + "mime": "^1.5.0", + "path-is-absolute": "^1.0.0", + "range-parser": "^1.0.3", + "time-stamp": "^2.0.0" + } + }, + "webpack-sources": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.2.0.tgz", + "integrity": "sha512-9BZwxR85dNsjWz3blyxdOhTgtnQvv3OEs5xofI0wPYTwu5kaWxS08UuD1oI7WLBLpRO+ylf0ofnXLXWmGb2WMw==", + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "requires": { + "mkdirp": "^0.5.1" + } + }, + "ws": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.2.tgz", + "integrity": "sha1-iiRPoFJAHgjJiGz0SoUYnh/UBn8=", + "requires": { + "options": ">=0.0.5", + "ultron": "1.0.x" + } + }, + "wtf-8": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wtf-8/-/wtf-8-1.0.0.tgz", + "integrity": "sha1-OS2LotDxw00e4tYw8V0O+2jhBIo=" + }, + "xmlhttprequest-ssl": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz", + "integrity": "sha1-GFqIjATspGw+QHDZn3tJ3jUomS0=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yargs": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + } + } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "requires": { + "camelcase": "^4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + } + } + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" + } + } + }, + "vue-quill-editor": { + "version": "3.0.6", + "resolved": "https://registry.npm.taobao.org/vue-quill-editor/download/vue-quill-editor-3.0.6.tgz", + "integrity": "sha1-H4VkYhHWijGoCnLLf0W7LxGbyPs=", + "requires": { + "object-assign": "^4.1.1", + "quill": "^1.3.4" + } + }, + "vue-router": { + "version": "3.1.6", + "resolved": "https://registry.npm.taobao.org/vue-router/download/vue-router-3.1.6.tgz", + "integrity": "sha1-RfWjo4Q+MXAsBh3YKTk1VOQyj4k=" + }, + "vue-schart": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/vue-schart/download/vue-schart-2.0.0.tgz", + "integrity": "sha1-dE8mu788ELxaWEkx4AIzWXCBCQE=", + "requires": { + "schart.js": "^3.0.0" + } + }, + "vue-style-loader": { + "version": "4.1.2", + "resolved": "https://registry.npm.taobao.org/vue-style-loader/download/vue-style-loader-4.1.2.tgz", + "integrity": "sha1-3t80mAbyXOtOZPOtfApE+6c1/Pg=", + "dev": true, + "requires": { + "hash-sum": "^1.0.2", + "loader-utils": "^1.0.2" + } + }, + "vue-template-compiler": { + "version": "2.6.11", + "resolved": "https://registry.npm.taobao.org/vue-template-compiler/download/vue-template-compiler-2.6.11.tgz", + "integrity": "sha1-wEcE749JixUxMAGJk+VjCdRpgIA=", + "dev": true, + "requires": { + "de-indent": "^1.0.2", + "he": "^1.1.0" + } + }, + "vue-template-es2015-compiler": { + "version": "1.9.1", + "resolved": "https://registry.npm.taobao.org/vue-template-es2015-compiler/download/vue-template-es2015-compiler-1.9.1.tgz", + "integrity": "sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=", + "dev": true + }, + "vuedraggable": { + "version": "2.23.2", + "resolved": "https://registry.npm.taobao.org/vuedraggable/download/vuedraggable-2.23.2.tgz", + "integrity": "sha1-DZXX/fTwL1Z1Wiazydylx8qc+nI=", + "requires": { + "sortablejs": "^1.10.1" + } + }, + "watchpack-chokidar2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", + "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", + "dev": true, + "optional": true, + "requires": { + "chokidar": "^2.1.8" + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npm.taobao.org/wbuf/download/wbuf-1.7.3.tgz", + "integrity": "sha1-wdjRSTFtPqhShIiVy2oL/oh7h98=", + "dev": true, + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/wcwidth/download/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "optional": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "optional": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "optional": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.3.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + } + }, + "enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "optional": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "optional": true + }, + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "optional": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "optional": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.1" + } + } + } + }, + "webpack-bundle-analyzer": { + "version": "3.7.0", + "resolved": "https://registry.npm.taobao.org/webpack-bundle-analyzer/download/webpack-bundle-analyzer-3.7.0.tgz?cache=0&sync_timestamp=1586846532112&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack-bundle-analyzer%2Fdownload%2Fwebpack-bundle-analyzer-3.7.0.tgz", + "integrity": "sha1-hNpDTolEKJm4hNmtOORm0NsCpW8=", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1", + "bfj": "^6.1.1", + "chalk": "^2.4.1", + "commander": "^2.18.0", + "ejs": "^2.6.1", + "express": "^4.16.3", + "filesize": "^3.6.1", + "gzip-size": "^5.0.0", + "lodash": "^4.17.15", + "mkdirp": "^0.5.1", + "opener": "^1.5.1", + "ws": "^6.0.0" + }, + "dependencies": { + "acorn": { + "version": "7.2.0", + "resolved": "https://registry.npm.taobao.org/acorn/download/acorn-7.2.0.tgz?cache=0&sync_timestamp=1589008014473&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Facorn%2Fdownload%2Facorn-7.2.0.tgz", + "integrity": "sha1-F+p+QNfIZA/1SmlMiJwm8xcE7/4=", + "dev": true + }, + "acorn-walk": { + "version": "7.1.1", + "resolved": "https://registry.npm.taobao.org/acorn-walk/download/acorn-walk-7.1.1.tgz", + "integrity": "sha1-NF8N/61cc15zc9L+yaECPmpEuD4=", + "dev": true + } + } + }, + "webpack-chain": { + "version": "4.12.1", + "resolved": "https://registry.npm.taobao.org/webpack-chain/download/webpack-chain-4.12.1.tgz?cache=0&sync_timestamp=1580740851884&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack-chain%2Fdownload%2Fwebpack-chain-4.12.1.tgz", + "integrity": "sha1-bIQ5u7KrVQlS1g4eqTGRQZBsAqY=", + "dev": true, + "requires": { + "deepmerge": "^1.5.2", + "javascript-stringify": "^1.6.0" + } + }, + "webpack-dev-middleware": { + "version": "3.7.2", + "resolved": "https://registry.npm.taobao.org/webpack-dev-middleware/download/webpack-dev-middleware-3.7.2.tgz", + "integrity": "sha1-ABnD23FuP6XOy/ZPKriKdLqzMfM=", + "dev": true, + "requires": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + } + }, + "webpack-dev-server": { + "version": "3.11.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz", + "integrity": "sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ==", + "dev": true, + "requires": { + "ansi-html": "0.0.7", + "bonjour": "^3.5.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.3.1", + "http-proxy-middleware": "0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.3.0", + "ip": "^1.1.5", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.8", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.26", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.8", + "semver": "^6.3.0", + "serve-index": "^1.9.1", + "sockjs": "^0.3.21", + "sockjs-client": "^1.5.0", + "spdy": "^4.0.2", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.2", + "webpack-log": "^2.0.0", + "ws": "^6.2.1", + "yargs": "^13.3.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz?cache=0&sync_timestamp=1570188570027&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-regex%2Fdownload%2Fansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "selfsigned": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.11.tgz", + "integrity": "sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA==", + "dev": true, + "requires": { + "node-forge": "^0.10.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "sockjs": { + "version": "0.3.21", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.21.tgz", + "integrity": "sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw==", + "dev": true, + "requires": { + "faye-websocket": "^0.11.3", + "uuid": "^3.4.0", + "websocket-driver": "^0.7.4" + } + }, + "sockjs-client": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.1.tgz", + "integrity": "sha512-VnVAb663fosipI/m6pqRXakEOw7nvd7TUgdr3PlR/8V2I95QIdwT8L4nMxhyU8SmDBHYXU1TOElaKOmKLfYzeQ==", + "dev": true, + "requires": { + "debug": "^3.2.6", + "eventsource": "^1.0.7", + "faye-websocket": "^0.11.3", + "inherits": "^2.0.4", + "json3": "^3.3.3", + "url-parse": "^1.5.1" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/webpack-log/download/webpack-log-2.0.0.tgz", + "integrity": "sha1-W3ko4GN1k/EZ0y9iJ8HgrDHhtH8=", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + }, + "webpack-merge": { + "version": "4.2.2", + "resolved": "https://registry.npm.taobao.org/webpack-merge/download/webpack-merge-4.2.2.tgz?cache=0&sync_timestamp=1566978693896&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack-merge%2Fdownload%2Fwebpack-merge-4.2.2.tgz", + "integrity": "sha1-onxS6ng9E5iv0gh/VH17nS9DY00=", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npm.taobao.org/webpack-sources/download/webpack-sources-1.4.3.tgz", + "integrity": "sha1-7t2OwLko+/HL/plOItLYkPMwqTM=", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + } + } + }, + "websocket-extensions": { + "version": "0.1.3", + "resolved": "https://registry.npm.taobao.org/websocket-extensions/download/websocket-extensions-0.1.3.tgz", + "integrity": "sha1-XS/yKXcAPsaHpLhwc9+7rBRszyk=", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npm.taobao.org/which/download/which-1.3.1.tgz", + "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/which-module/download/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npm.taobao.org/worker-farm/download/worker-farm-1.7.0.tgz", + "integrity": "sha1-JqlMU5G7ypJhUgAvabhKS/dy5ag=", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-6.2.0.tgz", + "integrity": "sha1-6Tk7oHEC5skaOyIUePAlfNKFblM=", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-5.0.0.tgz?cache=0&sync_timestamp=1570188570027&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-regex%2Fdownload%2Fansi-regex-5.0.0.tgz", + "integrity": "sha1-OIU59VF5vzkznIGvMKZU1p+Hy3U=", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-4.2.1.tgz", + "integrity": "sha1-kK51xCTQCNJiTFvynq0xd+v881k=", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz", + "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npm.taobao.org/color-name/download/color-name-1.1.4.tgz", + "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha1-8Rb4Bk/pCz94RKOJl8C3UFEmnx0=", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-4.2.0.tgz", + "integrity": "sha1-lSGCxGzHssMT0VluYjmSvRY7crU=", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-6.0.0.tgz", + "integrity": "sha1-CxVx3XZpzNTz4G4U7x7tJiJa5TI=", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/wrappy/download/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npm.taobao.org/ws/download/ws-6.2.1.tgz", + "integrity": "sha1-RC/fCkftZPWbal2P8TD0dI7VJPs=", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xss": { + "version": "1.0.6", + "resolved": "https://registry.npm.taobao.org/xss/download/xss-1.0.6.tgz", + "integrity": "sha1-6vEen8R2464omUShAJ793YoSS1E=", + "requires": { + "commander": "^2.9.0", + "cssfilter": "0.0.10" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/xtend/download/xtend-4.0.2.tgz", + "integrity": "sha1-u3J3n1+kZRhrH0OPZ0+jR/2121Q=", + "dev": true + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/yallist/download/yallist-3.1.1.tgz", + "integrity": "sha1-27fa+b/YusmrRev2ArjLrQ1dCP0=", + "dev": true + }, + "yargs": { + "version": "15.3.1", + "resolved": "https://registry.npm.taobao.org/yargs/download/yargs-15.3.1.tgz?cache=0&sync_timestamp=1587149854446&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyargs%2Fdownload%2Fyargs-15.3.1.tgz", + "integrity": "sha1-lQW0cnY5Y+VK/mAUitJ6MwgY6Ys=", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-5.0.0.tgz?cache=0&sync_timestamp=1570188570027&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-regex%2Fdownload%2Fansi-regex-5.0.0.tgz", + "integrity": "sha1-OIU59VF5vzkznIGvMKZU1p+Hy3U=", + "dev": true + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npm.taobao.org/cliui/download/cliui-6.0.0.tgz", + "integrity": "sha1-UR1wLAxOQcoVbX0OlgIfI+EyJbE=", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-4.1.0.tgz", + "integrity": "sha1-l6/n1s3AvFkoWEt8jXsW6KmqXRk=", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha1-8Rb4Bk/pCz94RKOJl8C3UFEmnx0=", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-5.0.0.tgz", + "integrity": "sha1-Gvujlq/WdqbUJQTQpno6frn2KqA=", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/p-limit/download/p-limit-2.3.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-limit%2Fdownload%2Fp-limit-2.3.0.tgz", + "integrity": "sha1-PdM8ZHohT9//2DWTPrCG2g3CHbE=", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/p-locate/download/p-locate-4.1.0.tgz", + "integrity": "sha1-o0KLtwiLOmApL2aRkni3wpetTwc=", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/p-try/download/p-try-2.2.0.tgz", + "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/path-exists/download/path-exists-4.0.0.tgz", + "integrity": "sha1-UTvb4tO5XXdi6METfvoZXGxhtbM=", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-4.2.0.tgz", + "integrity": "sha1-lSGCxGzHssMT0VluYjmSvRY7crU=", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-6.0.0.tgz", + "integrity": "sha1-CxVx3XZpzNTz4G4U7x7tJiJa5TI=", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npm.taobao.org/yargs-parser/download/yargs-parser-18.1.3.tgz?cache=0&sync_timestamp=1587068016931&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyargs-parser%2Fdownload%2Fyargs-parser-18.1.3.tgz", + "integrity": "sha1-vmjEl1xrKr9GkjawyHA2L6sJp7A=", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } +} diff --git a/nsi-collection-platform/package.json b/nsi-collection-platform/package.json new file mode 100644 index 0000000..4b13fbc --- /dev/null +++ b/nsi-collection-platform/package.json @@ -0,0 +1,36 @@ +{ + "name": "nsi-collection-platform", + "version": "4.2.0", + "private": true, + "scripts": { + "dev": "npm run serve", + "serve": "vue-cli-service serve", + "build": "vue-cli-service build" + }, + "dependencies": { + "axios": "^0.21.1", + "babel-polyfill": "^6.26.0", + "clipboard": "^2.0.6", + "element-ui": "^2.13.2", + "jquery": "^3.5.1", + "mavon-editor": "^2.6.17", + "qs": "latest", + "vue": "^2.6.10", + "vue-clipboard2": "^0.3.1", + "vue-cropperjs": "^3.0.0", + "vue-i18n": "^8.10.0", + "vue-json-viewer": "^2.2.11", + "vue-native-websocket": "^2.0.14", + "vue-quill-editor": "^3.0.6", + "vue-router": "^3.0.3", + "vue-schart": "^2.0.0", + "vuedraggable": "^2.17.0" + }, + "devDependencies": { + "@vue/cli-plugin-babel": "^3.9.0", + "@vue/cli-service": "^3.9.0", + "vue-template-compiler": "^2.6.10", + "axios-mock-adapter": "^1.18.1", + "mockjs": "^1.0.1-beta3" + } +} diff --git a/nsi-collection-platform/postcss.config.js b/nsi-collection-platform/postcss.config.js new file mode 100644 index 0000000..961986e --- /dev/null +++ b/nsi-collection-platform/postcss.config.js @@ -0,0 +1,5 @@ +module.exports = { + plugins: { + autoprefixer: {} + } +} diff --git a/nsi-collection-platform/public/index.html b/nsi-collection-platform/public/index.html new file mode 100644 index 0000000..8dd50b3 --- /dev/null +++ b/nsi-collection-platform/public/index.html @@ -0,0 +1,17 @@ + + + + + + + + nsi-collection-platform + + + +
+ + + diff --git a/nsi-collection-platform/public/table.json b/nsi-collection-platform/public/table.json new file mode 100644 index 0000000..ddd2e32 --- /dev/null +++ b/nsi-collection-platform/public/table.json @@ -0,0 +1,40 @@ +{ + "list": [{ + "id": 1, + "name": "张三", + "money": 123, + "address": "广东省东莞市长安镇", + "state": "成功", + "date": "2019-11-1", + "thumb": "https://lin-xin.gitee.io/images/post/wms.png" + }, + { + "id": 2, + "name": "李四", + "money": 456, + "address": "广东省广州市白云区", + "state": "成功", + "date": "2019-10-11", + "thumb": "https://lin-xin.gitee.io/images/post/node3.png" + }, + { + "id": 3, + "name": "王五", + "money": 789, + "address": "湖南省长沙市", + "state": "失败", + "date": "2019-11-11", + "thumb": "https://lin-xin.gitee.io/images/post/parcel.png" + }, + { + "id": 4, + "name": "赵六", + "money": 1011, + "address": "福建省厦门市鼓浪屿", + "state": "成功", + "date": "2019-10-20", + "thumb": "https://lin-xin.gitee.io/images/post/notice.png" + } + ], + "pageTotal": 4 +} \ No newline at end of file diff --git a/nsi-collection-platform/screenshots/wms1.png b/nsi-collection-platform/screenshots/wms1.png new file mode 100644 index 0000000..1bc275f Binary files /dev/null and b/nsi-collection-platform/screenshots/wms1.png differ diff --git a/nsi-collection-platform/screenshots/wms2.png b/nsi-collection-platform/screenshots/wms2.png new file mode 100644 index 0000000..4283226 Binary files /dev/null and b/nsi-collection-platform/screenshots/wms2.png differ diff --git a/nsi-collection-platform/screenshots/wms3.png b/nsi-collection-platform/screenshots/wms3.png new file mode 100644 index 0000000..e61c199 Binary files /dev/null and b/nsi-collection-platform/screenshots/wms3.png differ diff --git a/nsi-collection-platform/src/App.vue b/nsi-collection-platform/src/App.vue new file mode 100644 index 0000000..22270b1 --- /dev/null +++ b/nsi-collection-platform/src/App.vue @@ -0,0 +1,10 @@ + + \ No newline at end of file diff --git a/nsi-collection-platform/src/api/index.js b/nsi-collection-platform/src/api/index.js new file mode 100644 index 0000000..08170a4 --- /dev/null +++ b/nsi-collection-platform/src/api/index.js @@ -0,0 +1,44 @@ +import request from '../utils/request'; + +// let base = '/admin'; +let base = 'http://127.0.0.1:5000/admin'; + +//过滤请求内容 +request.interceptors.request.use( + config => { + let token = localStorage.getItem('token'); + if (null == token){ + token = "" + } + config.headers["token"] = token; + // if (config.method === "post") { + // config.data = qs.stringify(config.data); + // config.headers['Content-Type'] = 'application/x-www-form-urlencoded'; + // config.headers["user_name"] = ""; + // } + config.timeout = 12000 + return config; + } +); + +//登录 +export const login = (params, headers) => { return request.post(`${base}/login`, params, {headers: headers }); }; +//注册 +export const register = (params, headers) => { return request.post(`${base}/register`, params, {headers: headers }); }; +//用户操作 +export const userList = (params, headers) => { return request.get(`${base}/user/list`, { params: params, headers: headers }); }; +export const userGet = (params, headers) => { return request.get(`${base}/user/get`, { params: params, headers: headers }); }; +export const userAdd = (params, headers) => { return request.post(`${base}/user/add`, params, {headers: headers }); }; +export const userDelete = (params, headers) => { return request.post(`${base}/user/delete`, params, {headers: headers }); }; +export const userEdit = (params, headers) => { return request.post(`${base}/user/edit`, params, {headers: headers }); }; +export const userAuthorityChange = (params, headers) => { return request.post(`${base}/user/authority/change`, params, {headers: headers }); }; +//DNS解析 +export const dnsResolve = (params, headers) => { return request.get(`${base}/dns/resolution`, { params: params, headers: headers }); }; +//子域名解析 +export const subDomainLookup = (params, headers) => { return request.get(`${base}/subdomain/lookup`, { params: params, headers: headers }); }; +//邮箱内容抓取 +export const emailGrabbing = (params, headers) => { return request.get(`${base}/email/grabbing`, { params: params, headers: headers }); }; +//端口检测 +export const portDetection = (params, headers) => { return request.get(`${base}/port/detection`, { params: params, headers: headers }); }; +//操作记录 +export const operationLog = (params, headers) => { return request.get(`${base}/operation/log/get`, { params: params, headers: headers }); }; diff --git a/nsi-collection-platform/src/assets/css/color-dark.css b/nsi-collection-platform/src/assets/css/color-dark.css new file mode 100644 index 0000000..237f164 --- /dev/null +++ b/nsi-collection-platform/src/assets/css/color-dark.css @@ -0,0 +1,28 @@ +.header{ + background-color: #242f42; +} +.login-wrap{ + background: #324157; +} +.plugins-tips{ + background: #eef1f6; +} +.plugins-tips a{ + color: #20a0ff; +} +.el-upload--text em { + color: #20a0ff; +} +.pure-button{ + background: #20a0ff; +} +.tags-li.active { + border: 1px solid #409EFF; + background-color: #409EFF; +} +.message-title{ + color: #20a0ff; +} +.collapse-btn:hover{ + background: rgb(40,52,70); +} \ No newline at end of file diff --git a/nsi-collection-platform/src/assets/css/icon.css b/nsi-collection-platform/src/assets/css/icon.css new file mode 100644 index 0000000..e76aed4 --- /dev/null +++ b/nsi-collection-platform/src/assets/css/icon.css @@ -0,0 +1,4 @@ + + [class*=" el-icon-lx"], [class^=el-icon-lx] { + font-family: lx-iconfont!important; + } \ No newline at end of file diff --git a/nsi-collection-platform/src/assets/css/main.css b/nsi-collection-platform/src/assets/css/main.css new file mode 100644 index 0000000..cb71802 --- /dev/null +++ b/nsi-collection-platform/src/assets/css/main.css @@ -0,0 +1,177 @@ +* { + margin: 0; + padding: 0; +} + +html, +body, +#app, +.wrapper { + width: 100%; + height: 100%; + overflow: hidden; +} + +body { + font-family: 'PingFang SC', "Helvetica Neue", Helvetica, "microsoft yahei", arial, STHeiTi, sans-serif; +} + +a { + text-decoration: none +} + + +.content-box { + position: absolute; + left: 250px; + right: 0; + top: 70px; + bottom: 0; + padding-bottom: 30px; + -webkit-transition: left .3s ease-in-out; + transition: left .3s ease-in-out; + background: #f0f0f0; +} + +.content { + width: auto; + height: 100%; + padding: 10px; + overflow-y: scroll; + box-sizing: border-box; +} + +.content-collapse { + left: 65px; +} + +.container { + padding: 30px; + background: #fff; + border: 1px solid #ddd; + border-radius: 5px; +} + +.crumbs { + margin: 10px 0; +} + +.el-table th { + background-color: #f5f7fa !important; +} + +.pagination { + margin: 20px 0; + text-align: right; +} + +.plugins-tips { + padding: 20px 10px; + margin-bottom: 20px; +} + +.el-button+.el-tooltip { + margin-left: 10px; +} + +.el-table tr:hover { + background: #f6faff; +} + +.mgb20 { + margin-bottom: 20px; +} + +.move-enter-active, +.move-leave-active { + transition: opacity .5s; +} + +.move-enter, +.move-leave { + opacity: 0; +} + +/*BaseForm*/ + +.form-box { + width: 600px; +} + +.form-box .line { + text-align: center; +} + +.el-time-panel__content::after, +.el-time-panel__content::before { + margin-top: -7px; +} + +.el-time-spinner__wrapper .el-scrollbar__wrap:not(.el-scrollbar__wrap--hidden-default) { + padding-bottom: 0; +} + +/*Upload*/ + +.pure-button { + width: 150px; + height: 40px; + line-height: 40px; + text-align: center; + color: #fff; + border-radius: 3px; +} + +.g-core-image-corp-container .info-aside { + height: 45px; +} + +.el-upload--text { + background-color: #fff; + border: 1px dashed #d9d9d9; + border-radius: 6px; + box-sizing: border-box; + width: 360px; + height: 180px; + text-align: center; + cursor: pointer; + position: relative; + overflow: hidden; +} + +.el-upload--text .el-icon-upload { + font-size: 67px; + color: #97a8be; + margin: 40px 0 16px; + line-height: 50px; +} + +.el-upload--text { + color: #97a8be; + font-size: 14px; + text-align: center; +} + +.el-upload--text em { + font-style: normal; +} + +/*VueEditor*/ + +.ql-container { + min-height: 400px; +} + +.ql-snow .ql-tooltip { + transform: translateX(117.5px) translateY(10px) !important; +} + +.editor-btn { + margin-top: 20px; +} + +/*markdown*/ + +.v-note-wrapper .v-note-panel { + min-height: 500px; +} \ No newline at end of file diff --git a/nsi-collection-platform/src/assets/css/theme-green/color-green.css b/nsi-collection-platform/src/assets/css/theme-green/color-green.css new file mode 100644 index 0000000..837d179 --- /dev/null +++ b/nsi-collection-platform/src/assets/css/theme-green/color-green.css @@ -0,0 +1,29 @@ +.header{ + background-color: #07c4a8; +} +.login-wrap{ + background: rgba(56, 157, 170, 0.82);; +} +.plugins-tips{ + background: #f2f2f2; +} +.plugins-tips a{ + color: #00d1b2; +} +.el-upload--text em { + color: #00d1b2; +} +.pure-button{ + background: #00d1b2; +} +.pagination > .active > a, .pagination > .active > a:hover, .pagination > .active > a:focus, .pagination > .active > span, .pagination > .active > span:hover, .pagination > .active > span:focus { + background-color: #00d1b2 !important; + border-color: #00d1b2 !important; +} +.tags-li.active { + border: 1px solid #00d1b2; + background-color: #00d1b2; +} +.collapse-btn:hover{ + background: #00d1b2; +} \ No newline at end of file diff --git a/nsi-collection-platform/src/assets/css/theme-green/fonts/element-icons.ttf b/nsi-collection-platform/src/assets/css/theme-green/fonts/element-icons.ttf new file mode 100644 index 0000000..91b74de Binary files /dev/null and b/nsi-collection-platform/src/assets/css/theme-green/fonts/element-icons.ttf differ diff --git a/nsi-collection-platform/src/assets/css/theme-green/fonts/element-icons.woff b/nsi-collection-platform/src/assets/css/theme-green/fonts/element-icons.woff new file mode 100644 index 0000000..02b9a25 Binary files /dev/null and b/nsi-collection-platform/src/assets/css/theme-green/fonts/element-icons.woff differ diff --git a/nsi-collection-platform/src/assets/css/theme-green/index.css b/nsi-collection-platform/src/assets/css/theme-green/index.css new file mode 100644 index 0000000..9897bf9 --- /dev/null +++ b/nsi-collection-platform/src/assets/css/theme-green/index.css @@ -0,0 +1 @@ +@charset "UTF-8";.el-pagination--small .arrow.disabled,.el-table .hidden-columns,.el-table td.is-hidden>*,.el-table th.is-hidden>*,.el-table--hidden{visibility:hidden}.el-dropdown .el-dropdown-selfdefine:focus:active,.el-dropdown .el-dropdown-selfdefine:focus:not(.focusing),.el-message__closeBtn:focus,.el-message__content:focus,.el-popover:focus,.el-popover:focus:active,.el-popover__reference:focus:hover,.el-popover__reference:focus:not(.focusing),.el-rate:active,.el-rate:focus,.el-tooltip:focus:hover,.el-tooltip:focus:not(.focusing),.el-upload-list__item.is-success:active,.el-upload-list__item.is-success:not(.focusing):focus{outline-width:0}.el-input__suffix,.el-tree.is-dragging .el-tree-node__content *{pointer-events:none}@font-face{font-family:element-icons;src:url(fonts/element-icons.woff) format("woff"),url(fonts/element-icons.ttf) format("truetype");font-weight:400;font-style:normal}[class*=" el-icon-"],[class^=el-icon-]{font-family:element-icons!important;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;vertical-align:baseline;display:inline-block;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.el-icon-ice-cream-round:before{content:"\e6a0"}.el-icon-ice-cream-square:before{content:"\e6a3"}.el-icon-lollipop:before{content:"\e6a4"}.el-icon-potato-strips:before{content:"\e6a5"}.el-icon-milk-tea:before{content:"\e6a6"}.el-icon-ice-drink:before{content:"\e6a7"}.el-icon-ice-tea:before{content:"\e6a9"}.el-icon-coffee:before{content:"\e6aa"}.el-icon-orange:before{content:"\e6ab"}.el-icon-pear:before{content:"\e6ac"}.el-icon-apple:before{content:"\e6ad"}.el-icon-cherry:before{content:"\e6ae"}.el-icon-watermelon:before{content:"\e6af"}.el-icon-grape:before{content:"\e6b0"}.el-icon-refrigerator:before{content:"\e6b1"}.el-icon-goblet-square-full:before{content:"\e6b2"}.el-icon-goblet-square:before{content:"\e6b3"}.el-icon-goblet-full:before{content:"\e6b4"}.el-icon-goblet:before{content:"\e6b5"}.el-icon-cold-drink:before{content:"\e6b6"}.el-icon-coffee-cup:before{content:"\e6b8"}.el-icon-water-cup:before{content:"\e6b9"}.el-icon-hot-water:before{content:"\e6ba"}.el-icon-ice-cream:before{content:"\e6bb"}.el-icon-dessert:before{content:"\e6bc"}.el-icon-sugar:before{content:"\e6bd"}.el-icon-tableware:before{content:"\e6be"}.el-icon-burger:before{content:"\e6bf"}.el-icon-knife-fork:before{content:"\e6c1"}.el-icon-fork-spoon:before{content:"\e6c2"}.el-icon-chicken:before{content:"\e6c3"}.el-icon-food:before{content:"\e6c4"}.el-icon-dish-1:before{content:"\e6c5"}.el-icon-dish:before{content:"\e6c6"}.el-icon-moon-night:before{content:"\e6ee"}.el-icon-moon:before{content:"\e6f0"}.el-icon-cloudy-and-sunny:before{content:"\e6f1"}.el-icon-partly-cloudy:before{content:"\e6f2"}.el-icon-cloudy:before{content:"\e6f3"}.el-icon-sunny:before{content:"\e6f6"}.el-icon-sunset:before{content:"\e6f7"}.el-icon-sunrise-1:before{content:"\e6f8"}.el-icon-sunrise:before{content:"\e6f9"}.el-icon-heavy-rain:before{content:"\e6fa"}.el-icon-lightning:before{content:"\e6fb"}.el-icon-light-rain:before{content:"\e6fc"}.el-icon-wind-power:before{content:"\e6fd"}.el-icon-baseball:before{content:"\e712"}.el-icon-soccer:before{content:"\e713"}.el-icon-football:before{content:"\e715"}.el-icon-basketball:before{content:"\e716"}.el-icon-ship:before{content:"\e73f"}.el-icon-truck:before{content:"\e740"}.el-icon-bicycle:before{content:"\e741"}.el-icon-mobile-phone:before{content:"\e6d3"}.el-icon-service:before{content:"\e6d4"}.el-icon-key:before{content:"\e6e2"}.el-icon-unlock:before{content:"\e6e4"}.el-icon-lock:before{content:"\e6e5"}.el-icon-watch:before{content:"\e6fe"}.el-icon-watch-1:before{content:"\e6ff"}.el-icon-timer:before{content:"\e702"}.el-icon-alarm-clock:before{content:"\e703"}.el-icon-map-location:before{content:"\e704"}.el-icon-delete-location:before{content:"\e705"}.el-icon-add-location:before{content:"\e706"}.el-icon-location-information:before{content:"\e707"}.el-icon-location-outline:before{content:"\e708"}.el-icon-location:before{content:"\e79e"}.el-icon-place:before{content:"\e709"}.el-icon-discover:before{content:"\e70a"}.el-icon-first-aid-kit:before{content:"\e70b"}.el-icon-trophy-1:before{content:"\e70c"}.el-icon-trophy:before{content:"\e70d"}.el-icon-medal:before{content:"\e70e"}.el-icon-medal-1:before{content:"\e70f"}.el-icon-stopwatch:before{content:"\e710"}.el-icon-mic:before{content:"\e711"}.el-icon-copy-document:before{content:"\e718"}.el-icon-full-screen:before{content:"\e719"}.el-icon-switch-button:before{content:"\e71b"}.el-icon-aim:before{content:"\e71c"}.el-icon-crop:before{content:"\e71d"}.el-icon-odometer:before{content:"\e71e"}.el-icon-time:before{content:"\e71f"}.el-icon-bangzhu:before{content:"\e724"}.el-icon-close-notification:before{content:"\e726"}.el-icon-microphone:before{content:"\e727"}.el-icon-turn-off-microphone:before{content:"\e728"}.el-icon-position:before{content:"\e729"}.el-icon-postcard:before{content:"\e72a"}.el-icon-message:before{content:"\e72b"}.el-icon-chat-line-square:before{content:"\e72d"}.el-icon-chat-dot-square:before{content:"\e72e"}.el-icon-chat-dot-round:before{content:"\e72f"}.el-icon-chat-square:before{content:"\e730"}.el-icon-chat-line-round:before{content:"\e731"}.el-icon-chat-round:before{content:"\e732"}.el-icon-set-up:before{content:"\e733"}.el-icon-turn-off:before{content:"\e734"}.el-icon-open:before{content:"\e735"}.el-icon-connection:before{content:"\e736"}.el-icon-link:before{content:"\e737"}.el-icon-cpu:before{content:"\e738"}.el-icon-thumb:before{content:"\e739"}.el-icon-female:before{content:"\e73a"}.el-icon-male:before{content:"\e73b"}.el-icon-guide:before{content:"\e73c"}.el-icon-news:before{content:"\e73e"}.el-icon-price-tag:before{content:"\e744"}.el-icon-discount:before{content:"\e745"}.el-icon-wallet:before{content:"\e747"}.el-icon-coin:before{content:"\e748"}.el-icon-money:before{content:"\e749"}.el-icon-bank-card:before{content:"\e74a"}.el-icon-box:before{content:"\e74b"}.el-icon-present:before{content:"\e74c"}.el-icon-sell:before{content:"\e6d5"}.el-icon-sold-out:before{content:"\e6d6"}.el-icon-shopping-bag-2:before{content:"\e74d"}.el-icon-shopping-bag-1:before{content:"\e74e"}.el-icon-shopping-cart-2:before{content:"\e74f"}.el-icon-shopping-cart-1:before{content:"\e750"}.el-icon-shopping-cart-full:before{content:"\e751"}.el-icon-smoking:before{content:"\e752"}.el-icon-no-smoking:before{content:"\e753"}.el-icon-house:before{content:"\e754"}.el-icon-table-lamp:before{content:"\e755"}.el-icon-school:before{content:"\e756"}.el-icon-office-building:before{content:"\e757"}.el-icon-toilet-paper:before{content:"\e758"}.el-icon-notebook-2:before{content:"\e759"}.el-icon-notebook-1:before{content:"\e75a"}.el-icon-files:before{content:"\e75b"}.el-icon-collection:before{content:"\e75c"}.el-icon-receiving:before{content:"\e75d"}.el-icon-suitcase-1:before{content:"\e760"}.el-icon-suitcase:before{content:"\e761"}.el-icon-film:before{content:"\e763"}.el-icon-collection-tag:before{content:"\e765"}.el-icon-data-analysis:before{content:"\e766"}.el-icon-pie-chart:before{content:"\e767"}.el-icon-data-board:before{content:"\e768"}.el-icon-data-line:before{content:"\e76d"}.el-icon-reading:before{content:"\e769"}.el-icon-magic-stick:before{content:"\e76a"}.el-icon-coordinate:before{content:"\e76b"}.el-icon-mouse:before{content:"\e76c"}.el-icon-brush:before{content:"\e76e"}.el-icon-headset:before{content:"\e76f"}.el-icon-umbrella:before{content:"\e770"}.el-icon-scissors:before{content:"\e771"}.el-icon-mobile:before{content:"\e773"}.el-icon-attract:before{content:"\e774"}.el-icon-monitor:before{content:"\e775"}.el-icon-search:before{content:"\e778"}.el-icon-takeaway-box:before{content:"\e77a"}.el-icon-paperclip:before{content:"\e77d"}.el-icon-printer:before{content:"\e77e"}.el-icon-document-add:before{content:"\e782"}.el-icon-document:before{content:"\e785"}.el-icon-document-checked:before{content:"\e786"}.el-icon-document-copy:before{content:"\e787"}.el-icon-document-delete:before{content:"\e788"}.el-icon-document-remove:before{content:"\e789"}.el-icon-tickets:before{content:"\e78b"}.el-icon-folder-checked:before{content:"\e77f"}.el-icon-folder-delete:before{content:"\e780"}.el-icon-folder-remove:before{content:"\e781"}.el-icon-folder-add:before{content:"\e783"}.el-icon-folder-opened:before{content:"\e784"}.el-icon-folder:before{content:"\e78a"}.el-icon-edit-outline:before{content:"\e764"}.el-icon-edit:before{content:"\e78c"}.el-icon-date:before{content:"\e78e"}.el-icon-c-scale-to-original:before{content:"\e7c6"}.el-icon-view:before{content:"\e6ce"}.el-icon-loading:before{content:"\e6cf"}.el-icon-rank:before{content:"\e6d1"}.el-icon-sort-down:before{content:"\e7c4"}.el-icon-sort-up:before{content:"\e7c5"}.el-icon-sort:before{content:"\e6d2"}.el-icon-finished:before{content:"\e6cd"}.el-icon-refresh-left:before{content:"\e6c7"}.el-icon-refresh-right:before{content:"\e6c8"}.el-icon-refresh:before{content:"\e6d0"}.el-icon-video-play:before{content:"\e7c0"}.el-icon-video-pause:before{content:"\e7c1"}.el-icon-d-arrow-right:before{content:"\e6dc"}.el-icon-d-arrow-left:before{content:"\e6dd"}.el-icon-arrow-up:before{content:"\e6e1"}.el-icon-arrow-down:before{content:"\e6df"}.el-icon-arrow-right:before{content:"\e6e0"}.el-icon-arrow-left:before{content:"\e6de"}.el-icon-top-right:before{content:"\e6e7"}.el-icon-top-left:before{content:"\e6e8"}.el-icon-top:before{content:"\e6e6"}.el-icon-bottom:before{content:"\e6eb"}.el-icon-right:before{content:"\e6e9"}.el-icon-back:before{content:"\e6ea"}.el-icon-bottom-right:before{content:"\e6ec"}.el-icon-bottom-left:before{content:"\e6ed"}.el-icon-caret-top:before{content:"\e78f"}.el-icon-caret-bottom:before{content:"\e790"}.el-icon-caret-right:before{content:"\e791"}.el-icon-caret-left:before{content:"\e792"}.el-icon-d-caret:before{content:"\e79a"}.el-icon-share:before{content:"\e793"}.el-icon-menu:before{content:"\e798"}.el-icon-s-grid:before{content:"\e7a6"}.el-icon-s-check:before{content:"\e7a7"}.el-icon-s-data:before{content:"\e7a8"}.el-icon-s-opportunity:before{content:"\e7aa"}.el-icon-s-custom:before{content:"\e7ab"}.el-icon-s-claim:before{content:"\e7ad"}.el-icon-s-finance:before{content:"\e7ae"}.el-icon-s-comment:before{content:"\e7af"}.el-icon-s-flag:before{content:"\e7b0"}.el-icon-s-marketing:before{content:"\e7b1"}.el-icon-s-shop:before{content:"\e7b4"}.el-icon-s-open:before{content:"\e7b5"}.el-icon-s-management:before{content:"\e7b6"}.el-icon-s-ticket:before{content:"\e7b7"}.el-icon-s-release:before{content:"\e7b8"}.el-icon-s-home:before{content:"\e7b9"}.el-icon-s-promotion:before{content:"\e7ba"}.el-icon-s-operation:before{content:"\e7bb"}.el-icon-s-unfold:before{content:"\e7bc"}.el-icon-s-fold:before{content:"\e7a9"}.el-icon-s-platform:before{content:"\e7bd"}.el-icon-s-order:before{content:"\e7be"}.el-icon-s-cooperation:before{content:"\e7bf"}.el-icon-bell:before{content:"\e725"}.el-icon-message-solid:before{content:"\e799"}.el-icon-video-camera:before{content:"\e772"}.el-icon-video-camera-solid:before{content:"\e796"}.el-icon-camera:before{content:"\e779"}.el-icon-camera-solid:before{content:"\e79b"}.el-icon-download:before{content:"\e77c"}.el-icon-upload2:before{content:"\e77b"}.el-icon-upload:before{content:"\e7c3"}.el-icon-picture-outline-round:before{content:"\e75f"}.el-icon-picture-outline:before{content:"\e75e"}.el-icon-picture:before{content:"\e79f"}.el-icon-close:before{content:"\e6db"}.el-icon-check:before{content:"\e6da"}.el-icon-plus:before{content:"\e6d9"}.el-icon-minus:before{content:"\e6d8"}.el-icon-help:before{content:"\e73d"}.el-icon-s-help:before{content:"\e7b3"}.el-icon-circle-close:before{content:"\e78d"}.el-icon-circle-check:before{content:"\e720"}.el-icon-circle-plus-outline:before{content:"\e723"}.el-icon-remove-outline:before{content:"\e722"}.el-icon-zoom-out:before{content:"\e776"}.el-icon-zoom-in:before{content:"\e777"}.el-icon-error:before{content:"\e79d"}.el-icon-success:before{content:"\e79c"}.el-icon-circle-plus:before{content:"\e7a0"}.el-icon-remove:before{content:"\e7a2"}.el-icon-info:before{content:"\e7a1"}.el-icon-question:before{content:"\e7a4"}.el-icon-warning-outline:before{content:"\e6c9"}.el-icon-warning:before{content:"\e7a3"}.el-icon-goods:before{content:"\e7c2"}.el-icon-s-goods:before{content:"\e7b2"}.el-icon-star-off:before{content:"\e717"}.el-icon-star-on:before{content:"\e797"}.el-icon-more-outline:before{content:"\e6cc"}.el-icon-more:before{content:"\e794"}.el-icon-phone-outline:before{content:"\e6cb"}.el-icon-phone:before{content:"\e795"}.el-icon-user:before{content:"\e6e3"}.el-icon-user-solid:before{content:"\e7a5"}.el-icon-setting:before{content:"\e6ca"}.el-icon-s-tools:before{content:"\e7ac"}.el-icon-delete:before{content:"\e6d7"}.el-icon-delete-solid:before{content:"\e7c9"}.el-icon-eleme:before{content:"\e7c7"}.el-icon-platform-eleme:before{content:"\e7ca"}.el-icon-loading{-webkit-animation:rotating 2s linear infinite;animation:rotating 2s linear infinite}.el-icon--right{margin-left:5px}.el-icon--left{margin-right:5px}@-webkit-keyframes rotating{0%{-webkit-transform:rotateZ(0);transform:rotateZ(0)}100%{-webkit-transform:rotateZ(360deg);transform:rotateZ(360deg)}}@keyframes rotating{0%{-webkit-transform:rotateZ(0);transform:rotateZ(0)}100%{-webkit-transform:rotateZ(360deg);transform:rotateZ(360deg)}}.el-pagination{white-space:nowrap;padding:2px 5px;color:#303133;font-weight:700}.el-pagination::after,.el-pagination::before{display:table;content:""}.el-pagination::after{clear:both}.el-pagination button,.el-pagination span:not([class*=suffix]){display:inline-block;font-size:13px;min-width:35.5px;height:28px;line-height:28px;vertical-align:top;-webkit-box-sizing:border-box;box-sizing:border-box}.el-pagination .el-input__inner{text-align:center;-moz-appearance:textfield;line-height:normal}.el-pagination .el-input__suffix{right:0;-webkit-transform:scale(.8);transform:scale(.8)}.el-pagination .el-select .el-input{width:100px;margin:0 5px}.el-pagination .el-select .el-input .el-input__inner{padding-right:25px;border-radius:3px}.el-pagination button{border:none;padding:0 6px;background:0 0}.el-pagination button:focus{outline:0}.el-pagination button:hover{color:#00D1B2}.el-pagination button:disabled{color:#C0C4CC;background-color:#FFF;cursor:not-allowed}.el-pagination .btn-next,.el-pagination .btn-prev{background:center center no-repeat #FFF;background-size:16px;cursor:pointer;margin:0;color:#303133}.el-pagination .btn-next .el-icon,.el-pagination .btn-prev .el-icon{display:block;font-size:12px;font-weight:700}.el-pagination .btn-prev{padding-right:12px}.el-pagination .btn-next{padding-left:12px}.el-pagination .el-pager li.disabled{color:#C0C4CC;cursor:not-allowed}.el-pager li,.el-pager li.btn-quicknext:hover,.el-pager li.btn-quickprev:hover{cursor:pointer}.el-pagination--small .btn-next,.el-pagination--small .btn-prev,.el-pagination--small .el-pager li,.el-pagination--small .el-pager li.btn-quicknext,.el-pagination--small .el-pager li.btn-quickprev,.el-pagination--small .el-pager li:last-child{border-color:transparent;font-size:12px;line-height:22px;height:22px;min-width:22px}.el-pagination--small .more::before,.el-pagination--small li.more::before{line-height:24px}.el-pagination--small button,.el-pagination--small span:not([class*=suffix]){height:22px;line-height:22px}.el-pagination--small .el-pagination__editor,.el-pagination--small .el-pagination__editor.el-input .el-input__inner{height:22px}.el-pagination__sizes{margin:0 10px 0 0;font-weight:400;color:#606266}.el-pagination__sizes .el-input .el-input__inner{font-size:13px;padding-left:8px}.el-pagination__sizes .el-input .el-input__inner:hover{border-color:#00D1B2}.el-pagination__total{margin-right:10px;font-weight:400;color:#606266}.el-pagination__jump{margin-left:24px;font-weight:400;color:#606266}.el-pagination__jump .el-input__inner{padding:0 3px}.el-pagination__rightwrapper{float:right}.el-pagination__editor{line-height:18px;padding:0 2px;height:28px;text-align:center;margin:0 2px;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:3px}.el-pager,.el-pagination.is-background .btn-next,.el-pagination.is-background .btn-prev{padding:0}.el-pagination__editor.el-input{width:50px}.el-pagination__editor.el-input .el-input__inner{height:28px}.el-pagination__editor .el-input__inner::-webkit-inner-spin-button,.el-pagination__editor .el-input__inner::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.el-pagination.is-background .btn-next,.el-pagination.is-background .btn-prev,.el-pagination.is-background .el-pager li{margin:0 5px;background-color:#f4f4f5;color:#606266;min-width:30px;border-radius:2px}.el-pagination.is-background .btn-next.disabled,.el-pagination.is-background .btn-next:disabled,.el-pagination.is-background .btn-prev.disabled,.el-pagination.is-background .btn-prev:disabled,.el-pagination.is-background .el-pager li.disabled{color:#C0C4CC}.el-pagination.is-background .el-pager li:not(.disabled):hover{color:#00D1B2}.el-pagination.is-background .el-pager li:not(.disabled).active{background-color:#00D1B2;color:#FFF}.el-dialog,.el-pager li{background:#FFF;-webkit-box-sizing:border-box}.el-pagination.is-background.el-pagination--small .btn-next,.el-pagination.is-background.el-pagination--small .btn-prev,.el-pagination.is-background.el-pagination--small .el-pager li{margin:0 3px;min-width:22px}.el-pager,.el-pager li{vertical-align:top;margin:0;display:inline-block}.el-pager{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;list-style:none;font-size:0}.el-date-table,.el-table th{-webkit-user-select:none;-ms-user-select:none}.el-pager .more::before{line-height:30px}.el-pager li{padding:0 4px;font-size:13px;min-width:35.5px;height:28px;line-height:28px;box-sizing:border-box;text-align:center}.el-menu--collapse .el-menu .el-submenu,.el-menu--popup{min-width:200px}.el-pager li.btn-quicknext,.el-pager li.btn-quickprev{line-height:28px;color:#303133}.el-pager li.btn-quicknext.disabled,.el-pager li.btn-quickprev.disabled{color:#C0C4CC}.el-pager li.active+li{border-left:0}.el-pager li:hover{color:#00D1B2}.el-pager li.active{color:#00D1B2;cursor:default}@-webkit-keyframes v-modal-in{0%{opacity:0}}@-webkit-keyframes v-modal-out{100%{opacity:0}}.el-dialog{position:relative;margin:0 auto 50px;border-radius:2px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,.3);box-shadow:0 1px 3px rgba(0,0,0,.3);box-sizing:border-box;width:50%}.el-dialog.is-fullscreen{width:100%;margin-top:0;margin-bottom:0;height:100%;overflow:auto}.el-dialog__wrapper{position:fixed;top:0;right:0;bottom:0;left:0;overflow:auto;margin:0}.el-dialog__header{padding:20px 20px 10px}.el-dialog__headerbtn{position:absolute;top:20px;right:20px;padding:0;background:0 0;border:none;outline:0;cursor:pointer;font-size:16px}.el-dialog__headerbtn .el-dialog__close{color:#909399}.el-dialog__headerbtn:focus .el-dialog__close,.el-dialog__headerbtn:hover .el-dialog__close{color:#00D1B2}.el-dialog__title{line-height:24px;font-size:18px;color:#303133}.el-dialog__body{padding:30px 20px;color:#606266;font-size:14px;word-break:break-all}.el-dialog__footer{padding:10px 20px 20px;text-align:right;-webkit-box-sizing:border-box;box-sizing:border-box}.el-dialog--center{text-align:center}.el-dialog--center .el-dialog__body{text-align:initial;padding:25px 25px 30px}.el-dialog--center .el-dialog__footer{text-align:inherit}.dialog-fade-enter-active{-webkit-animation:dialog-fade-in .3s;animation:dialog-fade-in .3s}.dialog-fade-leave-active{-webkit-animation:dialog-fade-out .3s;animation:dialog-fade-out .3s}@-webkit-keyframes dialog-fade-in{0%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@keyframes dialog-fade-in{0%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@-webkit-keyframes dialog-fade-out{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}100%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}}@keyframes dialog-fade-out{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}100%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}}.el-autocomplete{position:relative;display:inline-block}.el-autocomplete-suggestion{margin:5px 0;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);border-radius:4px;border:1px solid #E4E7ED;-webkit-box-sizing:border-box;box-sizing:border-box;background-color:#FFF}.el-dropdown-menu,.el-menu--collapse .el-submenu .el-menu{z-index:10;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-autocomplete-suggestion__wrap{max-height:280px;padding:10px 0;-webkit-box-sizing:border-box;box-sizing:border-box}.el-autocomplete-suggestion__list{margin:0;padding:0}.el-autocomplete-suggestion li{padding:0 20px;margin:0;line-height:34px;cursor:pointer;color:#606266;font-size:14px;list-style:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.el-autocomplete-suggestion li.highlighted,.el-autocomplete-suggestion li:hover{background-color:#F5F7FA}.el-autocomplete-suggestion li.divider{margin-top:6px;border-top:1px solid #000}.el-autocomplete-suggestion li.divider:last-child{margin-bottom:-6px}.el-autocomplete-suggestion.is-loading li{text-align:center;height:100px;line-height:100px;font-size:20px;color:#999}.el-autocomplete-suggestion.is-loading li::after{display:inline-block;content:"";height:100%;vertical-align:middle}.el-autocomplete-suggestion.is-loading li:hover{background-color:#FFF}.el-autocomplete-suggestion.is-loading .el-icon-loading{vertical-align:middle}.el-dropdown{display:inline-block;position:relative;color:#606266;font-size:14px}.el-dropdown .el-button-group{display:block}.el-dropdown .el-button-group .el-button{float:none}.el-dropdown .el-dropdown__caret-button{padding-left:5px;padding-right:5px;position:relative;border-left:none}.el-dropdown .el-dropdown__caret-button::before{content:'';position:absolute;display:block;width:1px;top:5px;bottom:5px;left:0;background:rgba(255,255,255,.5)}.el-dropdown .el-dropdown__caret-button.el-button--default::before{background:rgba(220,223,230,.5)}.el-dropdown .el-dropdown__caret-button:hover::before{top:0;bottom:0}.el-dropdown .el-dropdown__caret-button .el-dropdown__icon{padding-left:0}.el-dropdown__icon{font-size:12px;margin:0 3px}.el-dropdown-menu{position:absolute;top:0;left:0;padding:10px 0;margin:5px 0;background-color:#FFF;border:1px solid #EBEEF5;border-radius:4px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-dropdown-menu__item{list-style:none;line-height:36px;padding:0 20px;margin:0;font-size:14px;color:#606266;cursor:pointer;outline:0}.el-dropdown-menu__item:focus,.el-dropdown-menu__item:not(.is-disabled):hover{background-color:rgb(230, 250, 247);color:rgb(51, 218, 193)}.el-dropdown-menu__item i{margin-right:5px}.el-dropdown-menu__item--divided{position:relative;margin-top:6px;border-top:1px solid #EBEEF5}.el-dropdown-menu__item--divided:before{content:'';height:6px;display:block;margin:0 -20px;background-color:#FFF}.el-dropdown-menu__item.is-disabled{cursor:default;color:#bbb;pointer-events:none}.el-dropdown-menu--medium{padding:6px 0}.el-dropdown-menu--medium .el-dropdown-menu__item{line-height:30px;padding:0 17px;font-size:14px}.el-dropdown-menu--medium .el-dropdown-menu__item.el-dropdown-menu__item--divided{margin-top:6px}.el-dropdown-menu--medium .el-dropdown-menu__item.el-dropdown-menu__item--divided:before{height:6px;margin:0 -17px}.el-dropdown-menu--small{padding:6px 0}.el-dropdown-menu--small .el-dropdown-menu__item{line-height:27px;padding:0 15px;font-size:13px}.el-dropdown-menu--small .el-dropdown-menu__item.el-dropdown-menu__item--divided{margin-top:4px}.el-dropdown-menu--small .el-dropdown-menu__item.el-dropdown-menu__item--divided:before{height:4px;margin:0 -15px}.el-dropdown-menu--mini{padding:3px 0}.el-dropdown-menu--mini .el-dropdown-menu__item{line-height:24px;padding:0 10px;font-size:12px}.el-dropdown-menu--mini .el-dropdown-menu__item.el-dropdown-menu__item--divided{margin-top:3px}.el-dropdown-menu--mini .el-dropdown-menu__item.el-dropdown-menu__item--divided:before{height:3px;margin:0 -10px}.el-menu{border-right:solid 1px #e6e6e6;list-style:none;position:relative;margin:0;padding-left:0;background-color:#FFF}.el-menu--horizontal>.el-menu-item:not(.is-disabled):focus,.el-menu--horizontal>.el-menu-item:not(.is-disabled):hover,.el-menu--horizontal>.el-submenu .el-submenu__title:hover{background-color:#fff}.el-menu::after,.el-menu::before{display:table;content:""}.el-menu::after{clear:both}.el-menu.el-menu--horizontal{border-bottom:solid 1px #e6e6e6}.el-menu--horizontal{border-right:none}.el-menu--horizontal>.el-menu-item{float:left;height:60px;line-height:60px;margin:0;border-bottom:2px solid transparent;color:#909399}.el-menu--horizontal>.el-menu-item a,.el-menu--horizontal>.el-menu-item a:hover{color:inherit}.el-menu--horizontal>.el-submenu{float:left}.el-menu--horizontal>.el-submenu:focus,.el-menu--horizontal>.el-submenu:hover{outline:0}.el-menu--horizontal>.el-submenu:focus .el-submenu__title,.el-menu--horizontal>.el-submenu:hover .el-submenu__title{color:#303133}.el-menu--horizontal>.el-submenu.is-active .el-submenu__title{border-bottom:2px solid #00D1B2;color:#303133}.el-menu--horizontal>.el-submenu .el-submenu__title{height:60px;line-height:60px;border-bottom:2px solid transparent;color:#909399}.el-menu--horizontal>.el-submenu .el-submenu__icon-arrow{position:static;vertical-align:middle;margin-left:8px;margin-top:-3px}.el-menu--horizontal .el-menu .el-menu-item,.el-menu--horizontal .el-menu .el-submenu__title{background-color:#FFF;float:none;height:36px;line-height:36px;padding:0 10px;color:#909399}.el-menu--horizontal .el-menu .el-menu-item.is-active,.el-menu--horizontal .el-menu .el-submenu.is-active>.el-submenu__title{color:#303133}.el-menu--horizontal .el-menu-item:not(.is-disabled):focus,.el-menu--horizontal .el-menu-item:not(.is-disabled):hover{outline:0;color:#303133}.el-menu--horizontal>.el-menu-item.is-active{border-bottom:2px solid #00D1B2;color:#303133}.el-menu--collapse{width:64px}.el-menu--collapse>.el-menu-item [class^=el-icon-],.el-menu--collapse>.el-submenu>.el-submenu__title [class^=el-icon-]{margin:0;vertical-align:middle;width:24px;text-align:center}.el-menu--collapse>.el-menu-item .el-submenu__icon-arrow,.el-menu--collapse>.el-submenu>.el-submenu__title .el-submenu__icon-arrow{display:none}.el-menu--collapse>.el-menu-item span,.el-menu--collapse>.el-submenu>.el-submenu__title span{height:0;width:0;overflow:hidden;visibility:hidden;display:inline-block}.el-menu--collapse>.el-menu-item.is-active i{color:inherit}.el-menu--collapse .el-submenu{position:relative}.el-menu--collapse .el-submenu .el-menu{position:absolute;margin-left:5px;top:0;left:100%;border:1px solid #E4E7ED;border-radius:2px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-menu-item,.el-submenu__title{height:56px;line-height:56px;position:relative;-webkit-box-sizing:border-box;white-space:nowrap;list-style:none}.el-menu--collapse .el-submenu.is-opened>.el-submenu__title .el-submenu__icon-arrow{-webkit-transform:none;transform:none}.el-menu--popup{z-index:100;border:none;padding:5px 0;border-radius:2px;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-menu--popup-bottom-start{margin-top:5px}.el-menu--popup-right-start{margin-left:5px;margin-right:5px}.el-menu-item{font-size:14px;color:#303133;padding:0 20px;cursor:pointer;-webkit-transition:border-color .3s,background-color .3s,color .3s;transition:border-color .3s,background-color .3s,color .3s;box-sizing:border-box}.el-menu-item *{vertical-align:middle}.el-menu-item i{color:#909399}.el-menu-item:focus,.el-menu-item:hover{outline:0;background-color:rgb(230, 250, 247)}.el-menu-item.is-disabled{opacity:.25;cursor:not-allowed;background:0 0!important}.el-menu-item [class^=el-icon-]{margin-right:5px;width:24px;text-align:center;font-size:18px;vertical-align:middle}.el-menu-item.is-active{color:#00D1B2}.el-menu-item.is-active i{color:inherit}.el-submenu{list-style:none;margin:0;padding-left:0}.el-submenu__title{font-size:14px;color:#303133;padding:0 20px;cursor:pointer;-webkit-transition:border-color .3s,background-color .3s,color .3s;transition:border-color .3s,background-color .3s,color .3s;box-sizing:border-box}.el-submenu__title *{vertical-align:middle}.el-submenu__title i{color:#909399}.el-submenu__title:focus,.el-submenu__title:hover{outline:0;background-color:rgb(230, 250, 247)}.el-submenu__title.is-disabled{opacity:.25;cursor:not-allowed;background:0 0!important}.el-submenu__title:hover{background-color:rgb(230, 250, 247)}.el-submenu .el-menu{border:none}.el-submenu .el-menu-item{height:50px;line-height:50px;padding:0 45px;min-width:200px}.el-submenu__icon-arrow{position:absolute;top:50%;right:20px;margin-top:-7px;-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;font-size:12px}.el-submenu.is-active .el-submenu__title{border-bottom-color:#00D1B2}.el-submenu.is-opened>.el-submenu__title .el-submenu__icon-arrow{-webkit-transform:rotateZ(180deg);transform:rotateZ(180deg)}.el-submenu.is-disabled .el-menu-item,.el-submenu.is-disabled .el-submenu__title{opacity:.25;cursor:not-allowed;background:0 0!important}.el-submenu [class^=el-icon-]{vertical-align:middle;margin-right:5px;width:24px;text-align:center;font-size:18px}.el-menu-item-group>ul{padding:0}.el-menu-item-group__title{padding:7px 0 7px 20px;line-height:normal;font-size:12px;color:#909399}.el-radio-button__inner,.el-radio-group{display:inline-block;line-height:1;vertical-align:middle}.horizontal-collapse-transition .el-submenu__title .el-submenu__icon-arrow{-webkit-transition:.2s;transition:.2s;opacity:0}.el-radio-group{font-size:0}.el-radio-button{position:relative;display:inline-block;outline:0}.el-radio-button__inner{white-space:nowrap;background:#FFF;border:1px solid #DCDFE6;font-weight:500;border-left:0;color:#606266;-webkit-appearance:none;text-align:center;-webkit-box-sizing:border-box;box-sizing:border-box;outline:0;margin:0;position:relative;cursor:pointer;-webkit-transition:all .3s cubic-bezier(.645,.045,.355,1);transition:all .3s cubic-bezier(.645,.045,.355,1);padding:12px 20px;font-size:14px;border-radius:0}.el-radio-button__inner.is-round{padding:12px 20px}.el-radio-button__inner:hover{color:#00D1B2}.el-radio-button__inner [class*=el-icon-]{line-height:.9}.el-radio-button__inner [class*=el-icon-]+span{margin-left:5px}.el-radio-button:first-child .el-radio-button__inner{border-left:1px solid #DCDFE6;border-radius:4px 0 0 4px;-webkit-box-shadow:none!important;box-shadow:none!important}.el-radio-button__orig-radio{opacity:0;outline:0;position:absolute;z-index:-1}.el-radio-button__orig-radio:checked+.el-radio-button__inner{color:#FFF;background-color:#00D1B2;border-color:#00D1B2;-webkit-box-shadow:-1px 0 0 0 #00D1B2;box-shadow:-1px 0 0 0 #00D1B2}.el-radio-button__orig-radio:disabled+.el-radio-button__inner{color:#C0C4CC;cursor:not-allowed;background-image:none;background-color:#FFF;border-color:#EBEEF5;-webkit-box-shadow:none;box-shadow:none}.el-radio-button__orig-radio:disabled:checked+.el-radio-button__inner{background-color:#F2F6FC}.el-radio-button:last-child .el-radio-button__inner{border-radius:0 4px 4px 0}.el-popover,.el-radio-button:first-child:last-child .el-radio-button__inner{border-radius:4px}.el-radio-button--medium .el-radio-button__inner{padding:10px 20px;font-size:14px;border-radius:0}.el-radio-button--medium .el-radio-button__inner.is-round{padding:10px 20px}.el-radio-button--small .el-radio-button__inner{padding:9px 15px;font-size:12px;border-radius:0}.el-radio-button--small .el-radio-button__inner.is-round{padding:9px 15px}.el-radio-button--mini .el-radio-button__inner{padding:7px 15px;font-size:12px;border-radius:0}.el-radio-button--mini .el-radio-button__inner.is-round{padding:7px 15px}.el-radio-button:focus:not(.is-focus):not(:active):not(.is-disabled){-webkit-box-shadow:0 0 2px 2px #00D1B2;box-shadow:0 0 2px 2px #00D1B2}.el-switch{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;position:relative;font-size:14px;line-height:20px;height:20px;vertical-align:middle}.el-switch__core,.el-switch__label{display:inline-block;cursor:pointer}.el-switch.is-disabled .el-switch__core,.el-switch.is-disabled .el-switch__label{cursor:not-allowed}.el-switch__label{-webkit-transition:.2s;transition:.2s;height:20px;font-size:14px;font-weight:500;vertical-align:middle;color:#303133}.el-switch__label.is-active{color:#00D1B2}.el-switch__label--left{margin-right:10px}.el-switch__label--right{margin-left:10px}.el-switch__label *{line-height:1;font-size:14px;display:inline-block}.el-switch__input{position:absolute;width:0;height:0;opacity:0;margin:0}.el-switch__core{margin:0;position:relative;width:40px;height:20px;border:1px solid #DCDFE6;outline:0;border-radius:10px;-webkit-box-sizing:border-box;box-sizing:border-box;background:#DCDFE6;-webkit-transition:border-color .3s,background-color .3s;transition:border-color .3s,background-color .3s;vertical-align:middle}.el-switch__core:after{content:"";position:absolute;top:1px;left:1px;border-radius:100%;-webkit-transition:all .3s;transition:all .3s;width:16px;height:16px;background-color:#FFF}.el-switch.is-checked .el-switch__core{border-color:#00D1B2;background-color:#00D1B2}.el-switch.is-checked .el-switch__core::after{left:100%;margin-left:-17px}.el-switch.is-disabled{opacity:.6}.el-switch--wide .el-switch__label.el-switch__label--left span{left:10px}.el-switch--wide .el-switch__label.el-switch__label--right span{right:10px}.el-switch .label-fade-enter,.el-switch .label-fade-leave-active{opacity:0}.el-select-dropdown{position:absolute;z-index:1001;border:1px solid #E4E7ED;border-radius:4px;background-color:#FFF;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);-webkit-box-sizing:border-box;box-sizing:border-box;margin:5px 0}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected{color:#00D1B2;background-color:#FFF}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected.hover{background-color:#F5F7FA}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected::after{position:absolute;right:20px;font-family:element-icons;content:"\e6da";font-size:12px;font-weight:700;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.el-select-dropdown .el-scrollbar.is-empty .el-select-dropdown__list{padding:0}.el-select-dropdown__empty{padding:10px 0;margin:0;text-align:center;color:#999;font-size:14px}.el-select-dropdown__wrap{max-height:274px}.el-select-dropdown__list{list-style:none;padding:6px 0;margin:0;-webkit-box-sizing:border-box;box-sizing:border-box}.el-select-dropdown__item{font-size:14px;padding:0 20px;position:relative;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#606266;height:34px;line-height:34px;-webkit-box-sizing:border-box;box-sizing:border-box;cursor:pointer}.el-select .el-tag,.el-table{-webkit-box-sizing:border-box}.el-select-dropdown__item.is-disabled{color:#C0C4CC;cursor:not-allowed}.el-select-dropdown__item.is-disabled:hover{background-color:#FFF}.el-select-dropdown__item.hover,.el-select-dropdown__item:hover{background-color:#F5F7FA}.el-select-dropdown__item.selected{color:#00D1B2;font-weight:700}.el-select-group{margin:0;padding:0}.el-select-group__wrap{position:relative;list-style:none;margin:0;padding:0}.el-select-group__wrap:not(:last-of-type){padding-bottom:24px}.el-select-group__wrap:not(:last-of-type)::after{content:'';position:absolute;display:block;left:20px;right:20px;bottom:12px;height:1px;background:#E4E7ED}.el-select-group__title{padding-left:20px;font-size:12px;color:#909399;line-height:30px}.el-select-group .el-select-dropdown__item{padding-left:20px}.el-select{display:inline-block;position:relative}.el-select .el-select__tags>span{display:contents}.el-select:hover .el-input__inner{border-color:#C0C4CC}.el-select .el-input__inner{cursor:pointer;padding-right:35px}.el-select .el-input__inner:focus{border-color:#00D1B2}.el-select .el-input .el-select__caret{color:#C0C4CC;font-size:14px;-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;-webkit-transform:rotateZ(180deg);transform:rotateZ(180deg);cursor:pointer}.el-select .el-input .el-select__caret.is-reverse{-webkit-transform:rotateZ(0);transform:rotateZ(0)}.el-select .el-input .el-select__caret.is-show-close{font-size:14px;text-align:center;-webkit-transform:rotateZ(180deg);transform:rotateZ(180deg);border-radius:100%;color:#C0C4CC;-webkit-transition:color .2s cubic-bezier(.645,.045,.355,1);transition:color .2s cubic-bezier(.645,.045,.355,1)}.el-select .el-input .el-select__caret.is-show-close:hover{color:#909399}.el-select .el-input.is-disabled .el-input__inner{cursor:not-allowed}.el-select .el-input.is-disabled .el-input__inner:hover{border-color:#E4E7ED}.el-select .el-input.is-focus .el-input__inner{border-color:#00D1B2}.el-select>.el-input{display:block}.el-select__input{border:none;outline:0;padding:0;margin-left:15px;color:#666;font-size:14px;-webkit-appearance:none;-moz-appearance:none;appearance:none;height:28px;background-color:transparent}.el-select__input.is-mini{height:14px}.el-select__close{cursor:pointer;position:absolute;top:8px;z-index:1000;right:25px;color:#C0C4CC;line-height:18px;font-size:14px}.el-select__close:hover{color:#909399}.el-select__tags{position:absolute;line-height:normal;white-space:normal;z-index:1;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-wrap:wrap;flex-wrap:wrap}.el-select .el-tag__close{margin-top:-2px}.el-select .el-tag{box-sizing:border-box;border-color:transparent;margin:2px 0 2px 6px;background-color:#f0f2f5}.el-select .el-tag__close.el-icon-close{background-color:#C0C4CC;right:-7px;top:0;color:#FFF}.el-select .el-tag__close.el-icon-close:hover{background-color:#909399}.el-table,.el-table__expanded-cell{background-color:#FFF}.el-select .el-tag__close.el-icon-close::before{display:block;-webkit-transform:translate(0,.5px);transform:translate(0,.5px)}.el-table{position:relative;overflow:hidden;box-sizing:border-box;-webkit-box-flex:1;-ms-flex:1;flex:1;width:100%;max-width:100%;font-size:14px;color:#606266}.el-table--mini,.el-table--small,.el-table__expand-icon{font-size:12px}.el-table__empty-block{min-height:60px;text-align:center;width:100%;height:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.el-table__empty-text{line-height:60px;width:50%;color:#909399}.el-table__expand-column .cell{padding:0;text-align:center}.el-table__expand-icon{position:relative;cursor:pointer;color:#666;-webkit-transition:-webkit-transform .2s ease-in-out;transition:-webkit-transform .2s ease-in-out;transition:transform .2s ease-in-out;transition:transform .2s ease-in-out,-webkit-transform .2s ease-in-out;height:20px}.el-table__expand-icon--expanded{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.el-table__expand-icon>.el-icon{position:absolute;left:50%;top:50%;margin-left:-5px;margin-top:-5px}.el-table__expanded-cell[class*=cell]{padding:20px 50px}.el-table__expanded-cell:hover{background-color:transparent!important}.el-table__placeholder{display:inline-block;width:20px}.el-table__append-wrapper{overflow:hidden}.el-table--fit{border-right:0;border-bottom:0}.el-table--fit td.gutter,.el-table--fit th.gutter{border-right-width:1px}.el-table--scrollable-x .el-table__body-wrapper{overflow-x:auto}.el-table--scrollable-y .el-table__body-wrapper{overflow-y:auto}.el-table thead{color:#909399;font-weight:500}.el-table thead.is-group th{background:#F5F7FA}.el-table th,.el-table tr{background-color:#FFF}.el-table td,.el-table th{padding:12px 0;min-width:0;-webkit-box-sizing:border-box;box-sizing:border-box;text-overflow:ellipsis;vertical-align:middle;position:relative;text-align:left}.el-table td.is-center,.el-table th.is-center{text-align:center}.el-table td.is-right,.el-table th.is-right{text-align:right}.el-table td.gutter,.el-table th.gutter{width:15px;border-right-width:0;border-bottom-width:0;padding:0}.el-table--medium td,.el-table--medium th{padding:10px 0}.el-table--small td,.el-table--small th{padding:8px 0}.el-table--mini td,.el-table--mini th{padding:6px 0}.el-table .cell,.el-table th div{padding-right:10px;overflow:hidden;text-overflow:ellipsis}.el-table .cell,.el-table th div,.el-table--border td:first-child .cell,.el-table--border th:first-child .cell{padding-left:10px}.el-table tr input[type=checkbox]{margin:0}.el-table td,.el-table th.is-leaf{border-bottom:1px solid #EBEEF5}.el-table th.is-sortable{cursor:pointer}.el-table th{white-space:nowrap;overflow:hidden;-moz-user-select:none;user-select:none}.el-table th div{display:inline-block;line-height:40px;-webkit-box-sizing:border-box;box-sizing:border-box;white-space:nowrap}.el-table th>.cell{position:relative;word-wrap:normal;text-overflow:ellipsis;display:inline-block;vertical-align:middle;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.el-table th>.cell.highlight{color:#00D1B2}.el-table th.required>div::before{display:inline-block;content:"";width:8px;height:8px;border-radius:50%;background:#ff4d51;margin-right:5px;vertical-align:middle}.el-table td div{-webkit-box-sizing:border-box;box-sizing:border-box}.el-table td.gutter{width:0}.el-table .cell{-webkit-box-sizing:border-box;box-sizing:border-box;white-space:normal;word-break:break-all;line-height:23px}.el-table .cell.el-tooltip{white-space:nowrap;min-width:50px}.el-table--border,.el-table--group{border:1px solid #EBEEF5}.el-table--border::after,.el-table--group::after,.el-table::before{content:'';position:absolute;background-color:#EBEEF5;z-index:1}.el-table--border::after,.el-table--group::after{top:0;right:0;width:1px;height:100%}.el-table::before{left:0;bottom:0;width:100%;height:1px}.el-table--border{border-right:none;border-bottom:none}.el-table--border.el-loading-parent--relative{border-color:transparent}.el-table--border td,.el-table--border th,.el-table__body-wrapper .el-table--border.is-scrolling-left~.el-table__fixed{border-right:1px solid #EBEEF5}.el-table--border th.gutter:last-of-type{border-bottom:1px solid #EBEEF5;border-bottom-width:1px}.el-table--border th,.el-table__fixed-right-patch{border-bottom:1px solid #EBEEF5}.el-table__fixed,.el-table__fixed-right{position:absolute;top:0;left:0;overflow-x:hidden;overflow-y:hidden;-webkit-box-shadow:0 0 10px rgba(0,0,0,.12);box-shadow:0 0 10px rgba(0,0,0,.12)}.el-table__fixed-right::before,.el-table__fixed::before{content:'';position:absolute;left:0;bottom:0;width:100%;height:1px;background-color:#EBEEF5;z-index:4}.el-table__fixed-right-patch{position:absolute;top:-1px;right:0;background-color:#FFF}.el-table__fixed-right{top:0;left:auto;right:0}.el-table__fixed-right .el-table__fixed-body-wrapper,.el-table__fixed-right .el-table__fixed-footer-wrapper,.el-table__fixed-right .el-table__fixed-header-wrapper{left:auto;right:0}.el-table__fixed-header-wrapper{position:absolute;left:0;top:0;z-index:3}.el-table__fixed-footer-wrapper{position:absolute;left:0;bottom:0;z-index:3}.el-table__fixed-footer-wrapper tbody td{border-top:1px solid #EBEEF5;background-color:#F5F7FA;color:#606266}.el-table__fixed-body-wrapper{position:absolute;left:0;top:37px;overflow:hidden;z-index:3}.el-table__body-wrapper,.el-table__footer-wrapper,.el-table__header-wrapper{width:100%}.el-table__footer-wrapper{margin-top:-1px}.el-table__footer-wrapper td{border-top:1px solid #EBEEF5}.el-table__body,.el-table__footer,.el-table__header{table-layout:fixed;border-collapse:separate}.el-table__footer-wrapper,.el-table__header-wrapper{overflow:hidden}.el-table__footer-wrapper tbody td,.el-table__header-wrapper tbody td{background-color:#F5F7FA;color:#606266}.el-table__body-wrapper{overflow:hidden;position:relative}.el-table__body-wrapper.is-scrolling-left~.el-table__fixed,.el-table__body-wrapper.is-scrolling-none~.el-table__fixed,.el-table__body-wrapper.is-scrolling-none~.el-table__fixed-right,.el-table__body-wrapper.is-scrolling-right~.el-table__fixed-right{-webkit-box-shadow:none;box-shadow:none}.el-picker-panel,.el-table-filter{-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-table__body-wrapper .el-table--border.is-scrolling-right~.el-table__fixed-right{border-left:1px solid #EBEEF5}.el-table .caret-wrapper{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:34px;width:24px;vertical-align:middle;cursor:pointer;overflow:initial;position:relative}.el-table .sort-caret{width:0;height:0;border:5px solid transparent;position:absolute;left:7px}.el-table .sort-caret.ascending{border-bottom-color:#C0C4CC;top:5px}.el-table .sort-caret.descending{border-top-color:#C0C4CC;bottom:7px}.el-table .ascending .sort-caret.ascending{border-bottom-color:#00D1B2}.el-table .descending .sort-caret.descending{border-top-color:#00D1B2}.el-table .hidden-columns{position:absolute;z-index:-1}.el-table--striped .el-table__body tr.el-table__row--striped td{background:#FAFAFA}.el-table--striped .el-table__body tr.el-table__row--striped.current-row td{background-color:rgb(230, 250, 247)}.el-table__body tr.hover-row.current-row>td,.el-table__body tr.hover-row.el-table__row--striped.current-row>td,.el-table__body tr.hover-row.el-table__row--striped>td,.el-table__body tr.hover-row>td{background-color:#F5F7FA}.el-table__body tr.current-row>td{background-color:rgb(230, 250, 247)}.el-table__column-resize-proxy{position:absolute;left:200px;top:0;bottom:0;width:0;border-left:1px solid #EBEEF5;z-index:10}.el-table__column-filter-trigger{display:inline-block;line-height:34px;cursor:pointer}.el-table__column-filter-trigger i{color:#909399;font-size:12px;-webkit-transform:scale(.75);transform:scale(.75)}.el-table--enable-row-transition .el-table__body td{-webkit-transition:background-color .25s ease;transition:background-color .25s ease}.el-table--enable-row-hover .el-table__body tr:hover>td{background-color:#F5F7FA}.el-table--fluid-height .el-table__fixed,.el-table--fluid-height .el-table__fixed-right{bottom:0;overflow:hidden}.el-table [class*=el-table__row--level] .el-table__expand-icon{display:inline-block;width:20px;line-height:20px;height:20px;text-align:center;margin-right:3px}.el-table-column--selection .cell{padding-left:14px;padding-right:14px}.el-table-filter{border:1px solid #EBEEF5;border-radius:2px;background-color:#FFF;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);-webkit-box-sizing:border-box;box-sizing:border-box;margin:2px 0}.el-date-table td,.el-date-table td div{height:30px;-webkit-box-sizing:border-box}.el-table-filter__list{padding:5px 0;margin:0;list-style:none;min-width:100px}.el-table-filter__list-item{line-height:36px;padding:0 10px;cursor:pointer;font-size:14px}.el-table-filter__list-item:hover{background-color:rgb(230, 250, 247);color:rgb(51, 218, 193)}.el-table-filter__list-item.is-active{background-color:#00D1B2;color:#FFF}.el-table-filter__content{min-width:100px}.el-table-filter__bottom{border-top:1px solid #EBEEF5;padding:8px}.el-table-filter__bottom button{background:0 0;border:none;color:#606266;cursor:pointer;font-size:13px;padding:0 3px}.el-date-table td.in-range div,.el-date-table td.in-range div:hover,.el-date-table.is-week-mode .el-date-table__row.current div,.el-date-table.is-week-mode .el-date-table__row:hover div{background-color:#F2F6FC}.el-table-filter__bottom button:hover{color:#00D1B2}.el-table-filter__bottom button:focus{outline:0}.el-table-filter__bottom button.is-disabled{color:#C0C4CC;cursor:not-allowed}.el-table-filter__wrap{max-height:280px}.el-table-filter__checkbox-group{padding:10px}.el-table-filter__checkbox-group label.el-checkbox{display:block;margin-right:5px;margin-bottom:8px;margin-left:5px}.el-table-filter__checkbox-group .el-checkbox:last-child{margin-bottom:0}.el-date-table{font-size:12px;-moz-user-select:none;user-select:none}.el-slider__button-wrapper,.el-time-panel{-webkit-user-select:none;-ms-user-select:none}.el-date-table.is-week-mode .el-date-table__row:hover td.available:hover{color:#606266}.el-date-table.is-week-mode .el-date-table__row:hover td:first-child div{margin-left:5px;border-top-left-radius:15px;border-bottom-left-radius:15px}.el-date-table.is-week-mode .el-date-table__row:hover td:last-child div{margin-right:5px;border-top-right-radius:15px;border-bottom-right-radius:15px}.el-date-table td{width:32px;padding:4px 0;box-sizing:border-box;text-align:center;cursor:pointer;position:relative}.el-date-table td div{padding:3px 0;box-sizing:border-box}.el-date-table td span{width:24px;height:24px;display:block;margin:0 auto;line-height:24px;position:absolute;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%);border-radius:50%}.el-date-table td.next-month,.el-date-table td.prev-month{color:#C0C4CC}.el-date-table td.today{position:relative}.el-date-table td.today span{color:#00D1B2;font-weight:700}.el-date-table td.today.end-date span,.el-date-table td.today.start-date span{color:#FFF}.el-date-table td.available:hover{color:#00D1B2}.el-date-table td.current:not(.disabled) span{color:#FFF;background-color:#00D1B2}.el-date-table td.end-date div,.el-date-table td.start-date div{color:#FFF}.el-date-table td.end-date span,.el-date-table td.start-date span{background-color:#00D1B2}.el-date-table td.start-date div{margin-left:5px;border-top-left-radius:15px;border-bottom-left-radius:15px}.el-date-table td.end-date div{margin-right:5px;border-top-right-radius:15px;border-bottom-right-radius:15px}.el-date-table td.disabled div{background-color:#F5F7FA;opacity:1;cursor:not-allowed;color:#C0C4CC}.el-date-table td.selected div{margin-left:5px;margin-right:5px;background-color:#F2F6FC;border-radius:15px}.el-date-table td.selected div:hover{background-color:#F2F6FC}.el-date-table td.selected span{background-color:#00D1B2;color:#FFF;border-radius:15px}.el-date-table td.week{font-size:80%;color:#606266}.el-month-table,.el-year-table{font-size:12px;border-collapse:collapse}.el-date-table th{padding:5px;color:#606266;font-weight:400;border-bottom:solid 1px #EBEEF5}.el-month-table{margin:-1px}.el-month-table td{text-align:center;padding:8px 0;cursor:pointer}.el-month-table td div{height:48px;padding:6px 0;-webkit-box-sizing:border-box;box-sizing:border-box}.el-month-table td.today .cell{color:#00D1B2;font-weight:700}.el-month-table td.today.end-date .cell,.el-month-table td.today.start-date .cell{color:#FFF}.el-month-table td.disabled .cell{background-color:#F5F7FA;cursor:not-allowed;color:#C0C4CC}.el-month-table td.disabled .cell:hover{color:#C0C4CC}.el-month-table td .cell{width:60px;height:36px;display:block;line-height:36px;color:#606266;margin:0 auto;border-radius:18px}.el-month-table td .cell:hover{color:#00D1B2}.el-month-table td.in-range div,.el-month-table td.in-range div:hover{background-color:#F2F6FC}.el-month-table td.end-date div,.el-month-table td.start-date div{color:#FFF}.el-month-table td.end-date .cell,.el-month-table td.start-date .cell{color:#FFF;background-color:#00D1B2}.el-month-table td.start-date div{border-top-left-radius:24px;border-bottom-left-radius:24px}.el-month-table td.end-date div{border-top-right-radius:24px;border-bottom-right-radius:24px}.el-month-table td.current:not(.disabled) .cell{color:#00D1B2}.el-year-table{margin:-1px}.el-year-table .el-icon{color:#303133}.el-year-table td{text-align:center;padding:20px 3px;cursor:pointer}.el-year-table td.today .cell{color:#00D1B2;font-weight:700}.el-year-table td.disabled .cell{background-color:#F5F7FA;cursor:not-allowed;color:#C0C4CC}.el-year-table td.disabled .cell:hover{color:#C0C4CC}.el-year-table td .cell{width:48px;height:32px;display:block;line-height:32px;color:#606266;margin:0 auto}.el-year-table td .cell:hover,.el-year-table td.current:not(.disabled) .cell{color:#00D1B2}.el-date-range-picker{width:646px}.el-date-range-picker.has-sidebar{width:756px}.el-date-range-picker table{table-layout:fixed;width:100%}.el-date-range-picker .el-picker-panel__body{min-width:513px}.el-date-range-picker .el-picker-panel__content{margin:0}.el-date-range-picker__header{position:relative;text-align:center;height:28px}.el-date-range-picker__header [class*=arrow-left]{float:left}.el-date-range-picker__header [class*=arrow-right]{float:right}.el-date-range-picker__header div{font-size:16px;font-weight:500;margin-right:50px}.el-date-range-picker__content{float:left;width:50%;-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;padding:16px}.el-date-range-picker__content.is-left{border-right:1px solid #e4e4e4}.el-date-range-picker__content .el-date-range-picker__header div{margin-left:50px;margin-right:50px}.el-date-range-picker__editors-wrap{-webkit-box-sizing:border-box;box-sizing:border-box;display:table-cell}.el-date-range-picker__editors-wrap.is-right{text-align:right}.el-date-range-picker__time-header{position:relative;border-bottom:1px solid #e4e4e4;font-size:12px;padding:8px 5px 5px;display:table;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.el-date-range-picker__time-header>.el-icon-arrow-right{font-size:20px;vertical-align:middle;display:table-cell;color:#303133}.el-date-range-picker__time-picker-wrap{position:relative;display:table-cell;padding:0 5px}.el-date-range-picker__time-picker-wrap .el-picker-panel{position:absolute;top:13px;right:0;z-index:1;background:#FFF}.el-date-picker{width:322px}.el-date-picker.has-sidebar.has-time{width:434px}.el-date-picker.has-sidebar{width:438px}.el-date-picker.has-time .el-picker-panel__body-wrapper{position:relative}.el-date-picker .el-picker-panel__content{width:292px}.el-date-picker table{table-layout:fixed;width:100%}.el-date-picker__editor-wrap{position:relative;display:table-cell;padding:0 5px}.el-date-picker__time-header{position:relative;border-bottom:1px solid #e4e4e4;font-size:12px;padding:8px 5px 5px;display:table;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.el-date-picker__header{margin:12px;text-align:center}.el-date-picker__header--bordered{margin-bottom:0;padding-bottom:12px;border-bottom:solid 1px #EBEEF5}.el-date-picker__header--bordered+.el-picker-panel__content{margin-top:0}.el-date-picker__header-label{font-size:16px;font-weight:500;padding:0 5px;line-height:22px;text-align:center;cursor:pointer;color:#606266}.el-date-picker__header-label.active,.el-date-picker__header-label:hover{color:#00D1B2}.el-date-picker__prev-btn{float:left}.el-date-picker__next-btn{float:right}.el-date-picker__time-wrap{padding:10px;text-align:center}.el-date-picker__time-label{float:left;cursor:pointer;line-height:30px;margin-left:10px}.time-select{margin:5px 0;min-width:0}.time-select .el-picker-panel__content{max-height:200px;margin:0}.time-select-item{padding:8px 10px;font-size:14px;line-height:20px}.time-select-item.selected:not(.disabled){color:#00D1B2;font-weight:700}.time-select-item.disabled{color:#E4E7ED;cursor:not-allowed}.time-select-item:hover{background-color:#F5F7FA;font-weight:700;cursor:pointer}.el-date-editor{position:relative;display:inline-block;text-align:left}.el-date-editor.el-input,.el-date-editor.el-input__inner{width:220px}.el-date-editor--monthrange.el-input,.el-date-editor--monthrange.el-input__inner{width:300px}.el-date-editor--daterange.el-input,.el-date-editor--daterange.el-input__inner,.el-date-editor--timerange.el-input,.el-date-editor--timerange.el-input__inner{width:350px}.el-date-editor--datetimerange.el-input,.el-date-editor--datetimerange.el-input__inner{width:400px}.el-date-editor--dates .el-input__inner{text-overflow:ellipsis;white-space:nowrap}.el-date-editor .el-icon-circle-close{cursor:pointer}.el-date-editor .el-range__icon{font-size:14px;margin-left:-5px;color:#C0C4CC;float:left;line-height:32px}.el-date-editor .el-range-input,.el-date-editor .el-range-separator{height:100%;margin:0;text-align:center;display:inline-block;font-size:14px}.el-date-editor .el-range-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;outline:0;padding:0;width:39%;color:#606266}.el-date-editor .el-range-input::-webkit-input-placeholder{color:#C0C4CC}.el-date-editor .el-range-input:-ms-input-placeholder{color:#C0C4CC}.el-date-editor .el-range-input::-ms-input-placeholder{color:#C0C4CC}.el-date-editor .el-range-input::placeholder{color:#C0C4CC}.el-date-editor .el-range-separator{padding:0 5px;line-height:32px;width:5%;color:#303133}.el-date-editor .el-range__close-icon{font-size:14px;color:#C0C4CC;width:25px;display:inline-block;float:right;line-height:32px}.el-range-editor.el-input__inner{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:3px 10px}.el-range-editor .el-range-input{line-height:1}.el-range-editor.is-active,.el-range-editor.is-active:hover{border-color:#00D1B2}.el-range-editor--medium.el-input__inner{height:36px}.el-range-editor--medium .el-range-separator{line-height:28px;font-size:14px}.el-range-editor--medium .el-range-input{font-size:14px}.el-range-editor--medium .el-range__close-icon,.el-range-editor--medium .el-range__icon{line-height:28px}.el-range-editor--small.el-input__inner{height:32px}.el-range-editor--small .el-range-separator{line-height:24px;font-size:13px}.el-range-editor--small .el-range-input{font-size:13px}.el-range-editor--small .el-range__close-icon,.el-range-editor--small .el-range__icon{line-height:24px}.el-range-editor--mini.el-input__inner{height:28px}.el-range-editor--mini .el-range-separator{line-height:20px;font-size:12px}.el-range-editor--mini .el-range-input{font-size:12px}.el-range-editor--mini .el-range__close-icon,.el-range-editor--mini .el-range__icon{line-height:20px}.el-range-editor.is-disabled{background-color:#F5F7FA;border-color:#E4E7ED;color:#C0C4CC;cursor:not-allowed}.el-range-editor.is-disabled:focus,.el-range-editor.is-disabled:hover{border-color:#E4E7ED}.el-range-editor.is-disabled input{background-color:#F5F7FA;color:#C0C4CC;cursor:not-allowed}.el-range-editor.is-disabled input::-webkit-input-placeholder{color:#C0C4CC}.el-range-editor.is-disabled input:-ms-input-placeholder{color:#C0C4CC}.el-range-editor.is-disabled input::-ms-input-placeholder{color:#C0C4CC}.el-range-editor.is-disabled input::placeholder{color:#C0C4CC}.el-range-editor.is-disabled .el-range-separator{color:#C0C4CC}.el-picker-panel{color:#606266;border:1px solid #E4E7ED;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);background:#FFF;border-radius:4px;line-height:30px;margin:5px 0}.el-popover,.el-time-panel{-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-picker-panel__body-wrapper::after,.el-picker-panel__body::after{content:"";display:table;clear:both}.el-picker-panel__content{position:relative;margin:15px}.el-picker-panel__footer{border-top:1px solid #e4e4e4;padding:4px;text-align:right;background-color:#FFF;position:relative;font-size:0}.el-picker-panel__shortcut{display:block;width:100%;border:0;background-color:transparent;line-height:28px;font-size:14px;color:#606266;padding-left:12px;text-align:left;outline:0;cursor:pointer}.el-picker-panel__shortcut:hover{color:#00D1B2}.el-picker-panel__shortcut.active{background-color:#e6f1fe;color:#00D1B2}.el-picker-panel__btn{border:1px solid #dcdcdc;color:#333;line-height:24px;border-radius:2px;padding:0 20px;cursor:pointer;background-color:transparent;outline:0;font-size:12px}.el-picker-panel__btn[disabled]{color:#ccc;cursor:not-allowed}.el-picker-panel__icon-btn{font-size:12px;color:#303133;border:0;background:0 0;cursor:pointer;outline:0;margin-top:8px}.el-picker-panel__icon-btn:hover{color:#00D1B2}.el-picker-panel__icon-btn.is-disabled{color:#bbb}.el-picker-panel__icon-btn.is-disabled:hover{cursor:not-allowed}.el-picker-panel__link-btn{vertical-align:middle}.el-picker-panel [slot=sidebar],.el-picker-panel__sidebar{position:absolute;top:0;bottom:0;width:110px;border-right:1px solid #e4e4e4;-webkit-box-sizing:border-box;box-sizing:border-box;padding-top:6px;background-color:#FFF;overflow:auto}.el-picker-panel [slot=sidebar]+.el-picker-panel__body,.el-picker-panel__sidebar+.el-picker-panel__body{margin-left:110px}.el-time-spinner.has-seconds .el-time-spinner__wrapper{width:33.3%}.el-time-spinner__wrapper{max-height:190px;overflow:auto;display:inline-block;width:50%;vertical-align:top;position:relative}.el-time-spinner__wrapper .el-scrollbar__wrap:not(.el-scrollbar__wrap--hidden-default){padding-bottom:15px}.el-time-spinner__input.el-input .el-input__inner,.el-time-spinner__list{padding:0;text-align:center}.el-time-spinner__wrapper.is-arrow{-webkit-box-sizing:border-box;box-sizing:border-box;text-align:center;overflow:hidden}.el-time-spinner__wrapper.is-arrow .el-time-spinner__list{-webkit-transform:translateY(-32px);transform:translateY(-32px)}.el-time-spinner__wrapper.is-arrow .el-time-spinner__item:hover:not(.disabled):not(.active){background:#FFF;cursor:default}.el-time-spinner__arrow{font-size:12px;color:#909399;position:absolute;left:0;width:100%;z-index:1;text-align:center;height:30px;line-height:30px;cursor:pointer}.el-time-spinner__arrow:hover{color:#00D1B2}.el-time-spinner__arrow.el-icon-arrow-up{top:10px}.el-time-spinner__arrow.el-icon-arrow-down{bottom:10px}.el-time-spinner__input.el-input{width:70%}.el-time-spinner__list{margin:0;list-style:none}.el-time-spinner__list::after,.el-time-spinner__list::before{content:'';display:block;width:100%;height:80px}.el-time-spinner__item{height:32px;line-height:32px;font-size:12px;color:#606266}.el-time-spinner__item:hover:not(.disabled):not(.active){background:#F5F7FA;cursor:pointer}.el-time-spinner__item.active:not(.disabled){color:#303133;font-weight:700}.el-time-spinner__item.disabled{color:#C0C4CC;cursor:not-allowed}.el-time-panel{margin:5px 0;border:1px solid #E4E7ED;background-color:#FFF;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);border-radius:2px;position:absolute;width:180px;left:0;z-index:1000;-moz-user-select:none;user-select:none;-webkit-box-sizing:content-box;box-sizing:content-box}.el-time-panel__content{font-size:0;position:relative;overflow:hidden}.el-time-panel__content::after,.el-time-panel__content::before{content:"";top:50%;position:absolute;margin-top:-15px;height:32px;z-index:-1;left:0;right:0;-webkit-box-sizing:border-box;box-sizing:border-box;padding-top:6px;text-align:left;border-top:1px solid #E4E7ED;border-bottom:1px solid #E4E7ED}.el-time-panel__content::after{left:50%;margin-left:12%;margin-right:12%}.el-time-panel__content::before{padding-left:50%;margin-right:12%;margin-left:12%}.el-time-panel__content.has-seconds::after{left:calc(100% / 3 * 2)}.el-time-panel__content.has-seconds::before{padding-left:calc(100% / 3)}.el-time-panel__footer{border-top:1px solid #e4e4e4;padding:4px;height:36px;line-height:25px;text-align:right;-webkit-box-sizing:border-box;box-sizing:border-box}.el-time-panel__btn{border:none;line-height:28px;padding:0 5px;margin:0 5px;cursor:pointer;background-color:transparent;outline:0;font-size:12px;color:#303133}.el-time-panel__btn.confirm{font-weight:800;color:#00D1B2}.el-time-range-picker{width:354px;overflow:visible}.el-time-range-picker__content{position:relative;text-align:center;padding:10px}.el-time-range-picker__cell{-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;padding:4px 7px 7px;width:50%;display:inline-block}.el-time-range-picker__header{margin-bottom:5px;text-align:center;font-size:14px}.el-time-range-picker__body{border-radius:2px;border:1px solid #E4E7ED}.el-popover{position:absolute;background:#FFF;min-width:150px;border:1px solid #EBEEF5;padding:12px;z-index:2000;color:#606266;line-height:1.4;text-align:justify;font-size:14px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);word-break:break-all}.el-popover--plain{padding:18px 20px}.el-popover__title{color:#303133;font-size:16px;line-height:1;margin-bottom:12px}.v-modal-enter{-webkit-animation:v-modal-in .2s ease;animation:v-modal-in .2s ease}.v-modal-leave{-webkit-animation:v-modal-out .2s ease forwards;animation:v-modal-out .2s ease forwards}@keyframes v-modal-in{0%{opacity:0}}@keyframes v-modal-out{100%{opacity:0}}.v-modal{position:fixed;left:0;top:0;width:100%;height:100%;opacity:.5;background:#000}.el-popup-parent--hidden{overflow:hidden}.el-message-box{display:inline-block;width:420px;padding-bottom:10px;vertical-align:middle;background-color:#FFF;border-radius:4px;border:1px solid #EBEEF5;font-size:18px;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);text-align:left;overflow:hidden;-webkit-backface-visibility:hidden;backface-visibility:hidden}.el-message-box__wrapper{position:fixed;top:0;bottom:0;left:0;right:0;text-align:center}.el-message-box__wrapper::after{content:"";display:inline-block;height:100%;width:0;vertical-align:middle}.el-message-box__header{position:relative;padding:15px 15px 10px}.el-message-box__title{padding-left:0;margin-bottom:0;font-size:18px;line-height:1;color:#303133}.el-message-box__headerbtn{position:absolute;top:15px;right:15px;padding:0;border:none;outline:0;background:0 0;font-size:16px;cursor:pointer}.el-form-item.is-error .el-input__inner,.el-form-item.is-error .el-input__inner:focus,.el-form-item.is-error .el-textarea__inner,.el-form-item.is-error .el-textarea__inner:focus,.el-message-box__input input.invalid,.el-message-box__input input.invalid:focus{border-color:#F56C6C}.el-message-box__headerbtn .el-message-box__close{color:#909399}.el-message-box__headerbtn:focus .el-message-box__close,.el-message-box__headerbtn:hover .el-message-box__close{color:#00D1B2}.el-message-box__content{position:relative;padding:10px 15px;color:#606266;font-size:14px}.el-message-box__input{padding-top:15px}.el-message-box__status{position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);font-size:24px!important}.el-message-box__status::before{padding-left:1px}.el-message-box__status+.el-message-box__message{padding-left:36px;padding-right:12px}.el-message-box__status.el-icon-success{color:#67C23A}.el-message-box__status.el-icon-info{color:#909399}.el-message-box__status.el-icon-warning{color:#E6A23C}.el-message-box__status.el-icon-error{color:#F56C6C}.el-message-box__message{margin:0}.el-message-box__message p{margin:0;line-height:24px}.el-message-box__errormsg{color:#F56C6C;font-size:12px;min-height:18px;margin-top:2px}.el-message-box__btns{padding:5px 15px 0;text-align:right}.el-message-box__btns button:nth-child(2){margin-left:10px}.el-message-box__btns-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.el-container,.el-container.is-vertical,.el-drawer,.el-link,.el-steps--vertical{-webkit-box-direction:normal}.el-message-box--center{padding-bottom:30px}.el-message-box--center .el-message-box__header{padding-top:30px}.el-message-box--center .el-message-box__title{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.el-message-box--center .el-message-box__status{position:relative;top:auto;padding-right:5px;text-align:center;-webkit-transform:translateY(-1px);transform:translateY(-1px)}.el-message-box--center .el-message-box__message{margin-left:0}.el-message-box--center .el-message-box__btns,.el-message-box--center .el-message-box__content{text-align:center}.el-message-box--center .el-message-box__content{padding-left:27px;padding-right:27px}.msgbox-fade-enter-active{-webkit-animation:msgbox-fade-in .3s;animation:msgbox-fade-in .3s}.msgbox-fade-leave-active{-webkit-animation:msgbox-fade-out .3s;animation:msgbox-fade-out .3s}@-webkit-keyframes msgbox-fade-in{0%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@keyframes msgbox-fade-in{0%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@-webkit-keyframes msgbox-fade-out{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}100%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}}@keyframes msgbox-fade-out{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}100%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}}.el-breadcrumb{font-size:14px;line-height:1}.el-breadcrumb::after,.el-breadcrumb::before{display:table;content:""}.el-breadcrumb::after{clear:both}.el-breadcrumb__separator{margin:0 9px;font-weight:700;color:#C0C4CC}.el-breadcrumb__separator[class*=icon]{margin:0 6px;font-weight:400}.el-breadcrumb__item{float:left}.el-breadcrumb__inner{color:#606266}.el-breadcrumb__inner a,.el-breadcrumb__inner.is-link{font-weight:700;text-decoration:none;-webkit-transition:color .2s cubic-bezier(.645,.045,.355,1);transition:color .2s cubic-bezier(.645,.045,.355,1);color:#303133}.el-breadcrumb__inner a:hover,.el-breadcrumb__inner.is-link:hover{color:#00D1B2;cursor:pointer}.el-breadcrumb__item:last-child .el-breadcrumb__inner,.el-breadcrumb__item:last-child .el-breadcrumb__inner a,.el-breadcrumb__item:last-child .el-breadcrumb__inner a:hover,.el-breadcrumb__item:last-child .el-breadcrumb__inner:hover{font-weight:400;color:#606266;cursor:text}.el-breadcrumb__item:last-child .el-breadcrumb__separator{display:none}.el-form--label-left .el-form-item__label{text-align:left}.el-form--label-top .el-form-item__label{float:none;display:inline-block;text-align:left;padding:0 0 10px}.el-form--inline .el-form-item{display:inline-block;margin-right:10px;vertical-align:top}.el-form--inline .el-form-item__label{float:none;display:inline-block}.el-form--inline .el-form-item__content{display:inline-block;vertical-align:top}.el-form--inline.el-form--label-top .el-form-item__content{display:block}.el-form-item{margin-bottom:22px}.el-form-item::after,.el-form-item::before{display:table;content:""}.el-form-item::after{clear:both}.el-form-item .el-form-item{margin-bottom:0}.el-form-item--mini.el-form-item,.el-form-item--small.el-form-item{margin-bottom:18px}.el-form-item .el-input__validateIcon{display:none}.el-form-item--medium .el-form-item__content,.el-form-item--medium .el-form-item__label{line-height:36px}.el-form-item--small .el-form-item__content,.el-form-item--small .el-form-item__label{line-height:32px}.el-form-item--small .el-form-item__error{padding-top:2px}.el-form-item--mini .el-form-item__content,.el-form-item--mini .el-form-item__label{line-height:28px}.el-form-item--mini .el-form-item__error{padding-top:1px}.el-form-item__label-wrap{float:left}.el-form-item__label-wrap .el-form-item__label{display:inline-block;float:none}.el-form-item__label{text-align:right;vertical-align:middle;float:left;font-size:14px;color:#606266;line-height:40px;padding:0 12px 0 0;-webkit-box-sizing:border-box;box-sizing:border-box}.el-form-item__content{line-height:40px;position:relative;font-size:14px}.el-form-item__content::after,.el-form-item__content::before{display:table;content:""}.el-form-item__content::after{clear:both}.el-form-item__content .el-input-group{vertical-align:top}.el-form-item__error{color:#F56C6C;font-size:12px;line-height:1;padding-top:4px;position:absolute;top:100%;left:0}.el-form-item__error--inline{position:relative;top:auto;left:auto;display:inline-block;margin-left:10px}.el-form-item.is-required:not(.is-no-asterisk) .el-form-item__label-wrap>.el-form-item__label:before,.el-form-item.is-required:not(.is-no-asterisk)>.el-form-item__label:before{content:'*';color:#F56C6C;margin-right:4px}.el-form-item.is-error .el-input-group__append .el-input__inner,.el-form-item.is-error .el-input-group__prepend .el-input__inner{border-color:transparent}.el-form-item.is-error .el-input__validateIcon{color:#F56C6C}.el-form-item--feedback .el-input__validateIcon{display:inline-block}.el-tabs__header{padding:0;position:relative;margin:0 0 15px}.el-tabs__active-bar{position:absolute;bottom:0;left:0;height:2px;background-color:#00D1B2;z-index:1;-webkit-transition:-webkit-transform .3s cubic-bezier(.645,.045,.355,1);transition:-webkit-transform .3s cubic-bezier(.645,.045,.355,1);transition:transform .3s cubic-bezier(.645,.045,.355,1);transition:transform .3s cubic-bezier(.645,.045,.355,1),-webkit-transform .3s cubic-bezier(.645,.045,.355,1);list-style:none}.el-tabs__new-tab{float:right;border:1px solid #d3dce6;height:18px;width:18px;line-height:18px;margin:12px 0 9px 10px;border-radius:3px;text-align:center;font-size:12px;color:#d3dce6;cursor:pointer;-webkit-transition:all .15s;transition:all .15s}.el-collapse-item__arrow,.el-tabs__nav{-webkit-transition:-webkit-transform .3s}.el-tabs__new-tab .el-icon-plus{-webkit-transform:scale(.8,.8);transform:scale(.8,.8)}.el-tabs__new-tab:hover{color:#00D1B2}.el-tabs__nav-wrap{overflow:hidden;margin-bottom:-1px;position:relative}.el-tabs__nav-wrap::after{content:"";position:absolute;left:0;bottom:0;width:100%;height:2px;background-color:#E4E7ED;z-index:1}.el-tabs--border-card>.el-tabs__header .el-tabs__nav-wrap::after,.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap::after{content:none}.el-tabs__nav-wrap.is-scrollable{padding:0 20px;-webkit-box-sizing:border-box;box-sizing:border-box}.el-tabs__nav-scroll{overflow:hidden}.el-tabs__nav-next,.el-tabs__nav-prev{position:absolute;cursor:pointer;line-height:44px;font-size:12px;color:#909399}.el-tabs__nav-next{right:0}.el-tabs__nav-prev{left:0}.el-tabs__nav{white-space:nowrap;position:relative;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;float:left;z-index:2}.el-tabs__nav.is-stretch{min-width:100%;display:-webkit-box;display:-ms-flexbox;display:flex}.el-tabs__nav.is-stretch>*{-webkit-box-flex:1;-ms-flex:1;flex:1;text-align:center}.el-tabs__item{padding:0 20px;height:40px;-webkit-box-sizing:border-box;box-sizing:border-box;line-height:40px;display:inline-block;list-style:none;font-size:14px;font-weight:500;color:#303133;position:relative}.el-tabs__item:focus,.el-tabs__item:focus:active{outline:0}.el-tabs__item:focus.is-active.is-focus:not(:active){-webkit-box-shadow:0 0 2px 2px #00D1B2 inset;box-shadow:0 0 2px 2px #00D1B2 inset;border-radius:3px}.el-tabs__item .el-icon-close{border-radius:50%;text-align:center;-webkit-transition:all .3s cubic-bezier(.645,.045,.355,1);transition:all .3s cubic-bezier(.645,.045,.355,1);margin-left:5px}.el-tabs__item .el-icon-close:before{-webkit-transform:scale(.9);transform:scale(.9);display:inline-block}.el-tabs__item .el-icon-close:hover{background-color:#C0C4CC;color:#FFF}.el-tabs__item.is-active{color:#00D1B2}.el-tabs__item:hover{color:#00D1B2;cursor:pointer}.el-tabs__item.is-disabled{color:#C0C4CC;cursor:default}.el-tabs__content{overflow:hidden;position:relative}.el-tabs--card>.el-tabs__header{border-bottom:1px solid #E4E7ED}.el-tabs--card>.el-tabs__header .el-tabs__nav{border:1px solid #E4E7ED;border-bottom:none;border-radius:4px 4px 0 0;-webkit-box-sizing:border-box;box-sizing:border-box}.el-tabs--card>.el-tabs__header .el-tabs__active-bar{display:none}.el-tabs--card>.el-tabs__header .el-tabs__item .el-icon-close{position:relative;font-size:12px;width:0;height:14px;vertical-align:middle;line-height:15px;overflow:hidden;top:-1px;right:-2px;-webkit-transform-origin:100% 50%;transform-origin:100% 50%}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active.is-closable .el-icon-close,.el-tabs--card>.el-tabs__header .el-tabs__item.is-closable:hover .el-icon-close{width:14px}.el-tabs--card>.el-tabs__header .el-tabs__item{border-bottom:1px solid transparent;border-left:1px solid #E4E7ED;-webkit-transition:color .3s cubic-bezier(.645,.045,.355,1),padding .3s cubic-bezier(.645,.045,.355,1);transition:color .3s cubic-bezier(.645,.045,.355,1),padding .3s cubic-bezier(.645,.045,.355,1)}.el-tabs--card>.el-tabs__header .el-tabs__item:first-child{border-left:none}.el-tabs--card>.el-tabs__header .el-tabs__item.is-closable:hover{padding-left:13px;padding-right:13px}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active{border-bottom-color:#FFF}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active.is-closable{padding-left:20px;padding-right:20px}.el-tabs--border-card{background:#FFF;border:1px solid #DCDFE6;-webkit-box-shadow:0 2px 4px 0 rgba(0,0,0,.12),0 0 6px 0 rgba(0,0,0,.04);box-shadow:0 2px 4px 0 rgba(0,0,0,.12),0 0 6px 0 rgba(0,0,0,.04)}.el-tabs--border-card>.el-tabs__content{padding:15px}.el-tabs--border-card>.el-tabs__header{background-color:#F5F7FA;border-bottom:1px solid #E4E7ED;margin:0}.el-tabs--border-card>.el-tabs__header .el-tabs__item{-webkit-transition:all .3s cubic-bezier(.645,.045,.355,1);transition:all .3s cubic-bezier(.645,.045,.355,1);border:1px solid transparent;margin-top:-1px;color:#909399}.el-tabs--border-card>.el-tabs__header .el-tabs__item+.el-tabs__item,.el-tabs--border-card>.el-tabs__header .el-tabs__item:first-child{margin-left:-1px}.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active{color:#00D1B2;background-color:#FFF;border-right-color:#DCDFE6;border-left-color:#DCDFE6}.el-tabs--border-card>.el-tabs__header .el-tabs__item:not(.is-disabled):hover{color:#00D1B2}.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-disabled{color:#C0C4CC}.el-tabs--border-card>.el-tabs__header .is-scrollable .el-tabs__item:first-child{margin-left:0}.el-tabs--bottom .el-tabs__item.is-bottom:nth-child(2),.el-tabs--bottom .el-tabs__item.is-top:nth-child(2),.el-tabs--top .el-tabs__item.is-bottom:nth-child(2),.el-tabs--top .el-tabs__item.is-top:nth-child(2){padding-left:0}.el-tabs--bottom .el-tabs__item.is-bottom:last-child,.el-tabs--bottom .el-tabs__item.is-top:last-child,.el-tabs--top .el-tabs__item.is-bottom:last-child,.el-tabs--top .el-tabs__item.is-top:last-child{padding-right:0}.el-tabs--bottom .el-tabs--left>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--bottom .el-tabs--right>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--bottom.el-tabs--border-card>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--bottom.el-tabs--card>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--top .el-tabs--left>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--top .el-tabs--right>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--top.el-tabs--border-card>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--top.el-tabs--card>.el-tabs__header .el-tabs__item:nth-child(2){padding-left:20px}.el-tabs--bottom .el-tabs--left>.el-tabs__header .el-tabs__item:last-child,.el-tabs--bottom .el-tabs--right>.el-tabs__header .el-tabs__item:last-child,.el-tabs--bottom.el-tabs--border-card>.el-tabs__header .el-tabs__item:last-child,.el-tabs--bottom.el-tabs--card>.el-tabs__header .el-tabs__item:last-child,.el-tabs--top .el-tabs--left>.el-tabs__header .el-tabs__item:last-child,.el-tabs--top .el-tabs--right>.el-tabs__header .el-tabs__item:last-child,.el-tabs--top.el-tabs--border-card>.el-tabs__header .el-tabs__item:last-child,.el-tabs--top.el-tabs--card>.el-tabs__header .el-tabs__item:last-child{padding-right:20px}.el-tabs--bottom .el-tabs__header.is-bottom{margin-bottom:0;margin-top:10px}.el-tabs--bottom.el-tabs--border-card .el-tabs__header.is-bottom{border-bottom:0;border-top:1px solid #DCDFE6}.el-tabs--bottom.el-tabs--border-card .el-tabs__nav-wrap.is-bottom{margin-top:-1px;margin-bottom:0}.el-tabs--bottom.el-tabs--border-card .el-tabs__item.is-bottom:not(.is-active){border:1px solid transparent}.el-tabs--bottom.el-tabs--border-card .el-tabs__item.is-bottom{margin:0 -1px -1px}.el-tabs--left,.el-tabs--right{overflow:hidden}.el-tabs--left .el-tabs__header.is-left,.el-tabs--left .el-tabs__header.is-right,.el-tabs--left .el-tabs__nav-scroll,.el-tabs--left .el-tabs__nav-wrap.is-left,.el-tabs--left .el-tabs__nav-wrap.is-right,.el-tabs--right .el-tabs__header.is-left,.el-tabs--right .el-tabs__header.is-right,.el-tabs--right .el-tabs__nav-scroll,.el-tabs--right .el-tabs__nav-wrap.is-left,.el-tabs--right .el-tabs__nav-wrap.is-right{height:100%}.el-tabs--left .el-tabs__active-bar.is-left,.el-tabs--left .el-tabs__active-bar.is-right,.el-tabs--right .el-tabs__active-bar.is-left,.el-tabs--right .el-tabs__active-bar.is-right{top:0;bottom:auto;width:2px;height:auto}.el-tabs--left .el-tabs__nav-wrap.is-left,.el-tabs--left .el-tabs__nav-wrap.is-right,.el-tabs--right .el-tabs__nav-wrap.is-left,.el-tabs--right .el-tabs__nav-wrap.is-right{margin-bottom:0}.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-next,.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-next,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-next,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-next,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev{height:30px;line-height:30px;width:100%;text-align:center;cursor:pointer}.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-next i,.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev i,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-next i,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev i,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-next i,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev i,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-next i,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev i{-webkit-transform:rotateZ(90deg);transform:rotateZ(90deg)}.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev{left:auto;top:0}.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-next,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-next,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-next,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-next{right:auto;bottom:0}.el-tabs--left .el-tabs__active-bar.is-left,.el-tabs--left .el-tabs__nav-wrap.is-left::after{right:0;left:auto}.el-tabs--left .el-tabs__nav-wrap.is-left.is-scrollable,.el-tabs--left .el-tabs__nav-wrap.is-right.is-scrollable,.el-tabs--right .el-tabs__nav-wrap.is-left.is-scrollable,.el-tabs--right .el-tabs__nav-wrap.is-right.is-scrollable{padding:30px 0}.el-tabs--left .el-tabs__nav-wrap.is-left::after,.el-tabs--left .el-tabs__nav-wrap.is-right::after,.el-tabs--right .el-tabs__nav-wrap.is-left::after,.el-tabs--right .el-tabs__nav-wrap.is-right::after{height:100%;width:2px;bottom:auto;top:0}.el-tabs--left .el-tabs__nav.is-left,.el-tabs--left .el-tabs__nav.is-right,.el-tabs--right .el-tabs__nav.is-left,.el-tabs--right .el-tabs__nav.is-right{float:none}.el-tabs--left .el-tabs__item.is-left,.el-tabs--left .el-tabs__item.is-right,.el-tabs--right .el-tabs__item.is-left,.el-tabs--right .el-tabs__item.is-right{display:block}.el-tabs--left.el-tabs--card .el-tabs__active-bar.is-left,.el-tabs--right.el-tabs--card .el-tabs__active-bar.is-right{display:none}.el-tabs--left .el-tabs__header.is-left{float:left;margin-bottom:0;margin-right:10px}.el-tabs--left .el-tabs__nav-wrap.is-left{margin-right:-1px}.el-tabs--left .el-tabs__item.is-left{text-align:right}.el-tabs--left.el-tabs--card .el-tabs__item.is-left{border-left:none;border-right:1px solid #E4E7ED;border-bottom:none;border-top:1px solid #E4E7ED;text-align:left}.el-tabs--left.el-tabs--card .el-tabs__item.is-left:first-child{border-right:1px solid #E4E7ED;border-top:none}.el-tabs--left.el-tabs--card .el-tabs__item.is-left.is-active{border:1px solid #E4E7ED;border-right-color:#fff;border-left:none;border-bottom:none}.el-tabs--left.el-tabs--card .el-tabs__item.is-left.is-active:first-child{border-top:none}.el-tabs--left.el-tabs--card .el-tabs__item.is-left.is-active:last-child{border-bottom:none}.el-tabs--left.el-tabs--card .el-tabs__nav{border-radius:4px 0 0 4px;border-bottom:1px solid #E4E7ED;border-right:none}.el-tabs--left.el-tabs--card .el-tabs__new-tab{float:none}.el-tabs--left.el-tabs--border-card .el-tabs__header.is-left{border-right:1px solid #dfe4ed}.el-tabs--left.el-tabs--border-card .el-tabs__item.is-left{border:1px solid transparent;margin:-1px 0 -1px -1px}.el-tabs--left.el-tabs--border-card .el-tabs__item.is-left.is-active{border-color:#d1dbe5 transparent}.el-tabs--right .el-tabs__header.is-right{float:right;margin-bottom:0;margin-left:10px}.el-tabs--right .el-tabs__nav-wrap.is-right{margin-left:-1px}.el-tabs--right .el-tabs__nav-wrap.is-right::after{left:0;right:auto}.el-tabs--right .el-tabs__active-bar.is-right{left:0}.el-tabs--right.el-tabs--card .el-tabs__item.is-right{border-bottom:none;border-top:1px solid #E4E7ED}.el-tabs--right.el-tabs--card .el-tabs__item.is-right:first-child{border-left:1px solid #E4E7ED;border-top:none}.el-tabs--right.el-tabs--card .el-tabs__item.is-right.is-active{border:1px solid #E4E7ED;border-left-color:#fff;border-right:none;border-bottom:none}.el-tabs--right.el-tabs--card .el-tabs__item.is-right.is-active:first-child{border-top:none}.el-tabs--right.el-tabs--card .el-tabs__item.is-right.is-active:last-child{border-bottom:none}.el-tabs--right.el-tabs--card .el-tabs__nav{border-radius:0 4px 4px 0;border-bottom:1px solid #E4E7ED;border-left:none}.el-tabs--right.el-tabs--border-card .el-tabs__header.is-right{border-left:1px solid #dfe4ed}.el-tabs--right.el-tabs--border-card .el-tabs__item.is-right{border:1px solid transparent;margin:-1px -1px -1px 0}.el-tabs--right.el-tabs--border-card .el-tabs__item.is-right.is-active{border-color:#d1dbe5 transparent}.slideInLeft-transition,.slideInRight-transition{display:inline-block}.slideInRight-enter{-webkit-animation:slideInRight-enter .3s;animation:slideInRight-enter .3s}.slideInRight-leave{position:absolute;left:0;right:0;-webkit-animation:slideInRight-leave .3s;animation:slideInRight-leave .3s}.slideInLeft-enter{-webkit-animation:slideInLeft-enter .3s;animation:slideInLeft-enter .3s}.slideInLeft-leave{position:absolute;left:0;right:0;-webkit-animation:slideInLeft-leave .3s;animation:slideInLeft-leave .3s}@-webkit-keyframes slideInRight-enter{0%{opacity:0;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(100%);transform:translateX(100%)}to{opacity:1;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes slideInRight-enter{0%{opacity:0;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(100%);transform:translateX(100%)}to{opacity:1;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0)}}@-webkit-keyframes slideInRight-leave{0%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0);opacity:1}100%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(100%);transform:translateX(100%);opacity:0}}@keyframes slideInRight-leave{0%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0);opacity:1}100%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(100%);transform:translateX(100%);opacity:0}}@-webkit-keyframes slideInLeft-enter{0%{opacity:0;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(-100%);transform:translateX(-100%)}to{opacity:1;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes slideInLeft-enter{0%{opacity:0;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(-100%);transform:translateX(-100%)}to{opacity:1;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0)}}@-webkit-keyframes slideInLeft-leave{0%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0);opacity:1}100%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(-100%);transform:translateX(-100%);opacity:0}}@keyframes slideInLeft-leave{0%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0);opacity:1}100%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(-100%);transform:translateX(-100%);opacity:0}}.el-tree{position:relative;cursor:default;background:#FFF;color:#606266}.el-tree__empty-block{position:relative;min-height:60px;text-align:center;width:100%;height:100%}.el-tree__empty-text{position:absolute;left:50%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);color:#909399}.el-tree__drop-indicator{position:absolute;left:0;right:0;height:1px;background-color:#00D1B2}.el-tree-node{white-space:nowrap;outline:0}.el-tree-node:focus>.el-tree-node__content{background-color:#F5F7FA}.el-tree-node.is-drop-inner>.el-tree-node__content .el-tree-node__label{background-color:#00D1B2;color:#fff}.el-tree-node__content{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:26px;cursor:pointer}.el-tree-node__content>.el-tree-node__expand-icon{padding:6px}.el-tree-node__content>.el-checkbox{margin-right:8px}.el-tree-node__content:hover{background-color:#F5F7FA}.el-tree.is-dragging .el-tree-node__content{cursor:move}.el-tree.is-dragging.is-drop-not-allow .el-tree-node__content{cursor:not-allowed}.el-tree-node__expand-icon{cursor:pointer;color:#C0C4CC;font-size:12px;-webkit-transform:rotate(0);transform:rotate(0);-webkit-transition:-webkit-transform .3s ease-in-out;transition:-webkit-transform .3s ease-in-out;transition:transform .3s ease-in-out;transition:transform .3s ease-in-out,-webkit-transform .3s ease-in-out}.el-tree-node__expand-icon.expanded{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.el-tree-node__expand-icon.is-leaf{color:transparent;cursor:default}.el-tree-node__label{font-size:14px}.el-tree-node__loading-icon{margin-right:8px;font-size:14px;color:#C0C4CC}.el-tree-node>.el-tree-node__children{overflow:hidden;background-color:transparent}.el-tree-node.is-expanded>.el-tree-node__children{display:block}.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content{background-color:#f0f7ff}.el-alert{width:100%;padding:8px 16px;margin:0;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:4px;position:relative;background-color:#FFF;overflow:hidden;opacity:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-transition:opacity .2s;transition:opacity .2s}.el-alert.is-light .el-alert__closebtn{color:#C0C4CC}.el-alert.is-dark .el-alert__closebtn,.el-alert.is-dark .el-alert__description{color:#FFF}.el-alert.is-center{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.el-alert--success.is-light{background-color:#f0f9eb;color:#67C23A}.el-alert--success.is-light .el-alert__description{color:#67C23A}.el-alert--success.is-dark{background-color:#67C23A;color:#FFF}.el-alert--info.is-light{background-color:#f4f4f5;color:#909399}.el-alert--info.is-dark{background-color:#909399;color:#FFF}.el-alert--info .el-alert__description{color:#909399}.el-alert--warning.is-light{background-color:#fdf6ec;color:#E6A23C}.el-alert--warning.is-light .el-alert__description{color:#E6A23C}.el-alert--warning.is-dark{background-color:#E6A23C;color:#FFF}.el-alert--error.is-light{background-color:#fef0f0;color:#F56C6C}.el-alert--error.is-light .el-alert__description{color:#F56C6C}.el-alert--error.is-dark{background-color:#F56C6C;color:#FFF}.el-alert__content{display:table-cell;padding:0 8px}.el-alert__icon{font-size:16px;width:16px}.el-alert__icon.is-big{font-size:28px;width:28px}.el-alert__title{font-size:13px;line-height:18px}.el-alert__title.is-bold{font-weight:700}.el-alert .el-alert__description{font-size:12px;margin:5px 0 0}.el-alert__closebtn{font-size:12px;opacity:1;position:absolute;top:12px;right:15px;cursor:pointer}.el-alert-fade-enter,.el-alert-fade-leave-active,.el-loading-fade-enter,.el-loading-fade-leave-active,.el-notification-fade-leave-active{opacity:0}.el-alert__closebtn.is-customed{font-style:normal;font-size:13px;top:9px}.el-notification{display:-webkit-box;display:-ms-flexbox;display:flex;width:330px;padding:14px 26px 14px 13px;border-radius:8px;-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid #EBEEF5;position:fixed;background-color:#FFF;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);-webkit-transition:opacity .3s,left .3s,right .3s,top .4s,bottom .3s,-webkit-transform .3s;transition:opacity .3s,left .3s,right .3s,top .4s,bottom .3s,-webkit-transform .3s;transition:opacity .3s,transform .3s,left .3s,right .3s,top .4s,bottom .3s;transition:opacity .3s,transform .3s,left .3s,right .3s,top .4s,bottom .3s,-webkit-transform .3s;overflow:hidden}.el-notification.right{right:16px}.el-notification.left{left:16px}.el-notification__group{margin-left:13px;margin-right:8px}.el-notification__title{font-weight:700;font-size:16px;color:#303133;margin:0}.el-notification__content{font-size:14px;line-height:21px;margin:6px 0 0;color:#606266;text-align:justify}.el-notification__content p{margin:0}.el-notification__icon{height:24px;width:24px;font-size:24px}.el-notification__closeBtn{position:absolute;top:18px;right:15px;cursor:pointer;color:#909399;font-size:16px}.el-notification__closeBtn:hover{color:#606266}.el-notification .el-icon-success{color:#67C23A}.el-notification .el-icon-error{color:#F56C6C}.el-notification .el-icon-info{color:#909399}.el-notification .el-icon-warning{color:#E6A23C}.el-notification-fade-enter.right{right:0;-webkit-transform:translateX(100%);transform:translateX(100%)}.el-notification-fade-enter.left{left:0;-webkit-transform:translateX(-100%);transform:translateX(-100%)}.el-input-number{position:relative;display:inline-block;width:180px;line-height:38px}.el-input-number .el-input{display:block}.el-input-number .el-input__inner{-webkit-appearance:none;padding-left:50px;padding-right:50px;text-align:center}.el-input-number__decrease,.el-input-number__increase{position:absolute;z-index:1;top:1px;width:40px;height:auto;text-align:center;background:#F5F7FA;color:#606266;cursor:pointer;font-size:13px}.el-input-number__decrease:hover,.el-input-number__increase:hover{color:#00D1B2}.el-input-number__decrease:hover:not(.is-disabled)~.el-input .el-input__inner:not(.is-disabled),.el-input-number__increase:hover:not(.is-disabled)~.el-input .el-input__inner:not(.is-disabled){border-color:#00D1B2}.el-input-number__decrease.is-disabled,.el-input-number__increase.is-disabled{color:#C0C4CC;cursor:not-allowed}.el-input-number__increase{right:1px;border-radius:0 4px 4px 0;border-left:1px solid #DCDFE6}.el-input-number__decrease{left:1px;border-radius:4px 0 0 4px;border-right:1px solid #DCDFE6}.el-input-number.is-disabled .el-input-number__decrease,.el-input-number.is-disabled .el-input-number__increase{border-color:#E4E7ED;color:#E4E7ED}.el-input-number.is-disabled .el-input-number__decrease:hover,.el-input-number.is-disabled .el-input-number__increase:hover{color:#E4E7ED;cursor:not-allowed}.el-input-number--medium{width:200px;line-height:34px}.el-input-number--medium .el-input-number__decrease,.el-input-number--medium .el-input-number__increase{width:36px;font-size:14px}.el-input-number--medium .el-input__inner{padding-left:43px;padding-right:43px}.el-input-number--small{width:130px;line-height:30px}.el-input-number--small .el-input-number__decrease,.el-input-number--small .el-input-number__increase{width:32px;font-size:13px}.el-input-number--small .el-input-number__decrease [class*=el-icon],.el-input-number--small .el-input-number__increase [class*=el-icon]{-webkit-transform:scale(.9);transform:scale(.9)}.el-input-number--small .el-input__inner{padding-left:39px;padding-right:39px}.el-input-number--mini{width:130px;line-height:26px}.el-input-number--mini .el-input-number__decrease,.el-input-number--mini .el-input-number__increase{width:28px;font-size:12px}.el-input-number--mini .el-input-number__decrease [class*=el-icon],.el-input-number--mini .el-input-number__increase [class*=el-icon]{-webkit-transform:scale(.8);transform:scale(.8)}.el-input-number--mini .el-input__inner{padding-left:35px;padding-right:35px}.el-input-number.is-without-controls .el-input__inner{padding-left:15px;padding-right:15px}.el-input-number.is-controls-right .el-input__inner{padding-left:15px;padding-right:50px}.el-input-number.is-controls-right .el-input-number__decrease,.el-input-number.is-controls-right .el-input-number__increase{height:auto;line-height:19px}.el-input-number.is-controls-right .el-input-number__decrease [class*=el-icon],.el-input-number.is-controls-right .el-input-number__increase [class*=el-icon]{-webkit-transform:scale(.8);transform:scale(.8)}.el-input-number.is-controls-right .el-input-number__increase{border-radius:0 4px 0 0;border-bottom:1px solid #DCDFE6}.el-input-number.is-controls-right .el-input-number__decrease{right:1px;bottom:1px;top:auto;left:auto;border-right:none;border-left:1px solid #DCDFE6;border-radius:0 0 4px}.el-input-number.is-controls-right[class*=medium] [class*=decrease],.el-input-number.is-controls-right[class*=medium] [class*=increase]{line-height:17px}.el-input-number.is-controls-right[class*=small] [class*=decrease],.el-input-number.is-controls-right[class*=small] [class*=increase]{line-height:15px}.el-input-number.is-controls-right[class*=mini] [class*=decrease],.el-input-number.is-controls-right[class*=mini] [class*=increase]{line-height:13px}.el-tooltip__popper{position:absolute;border-radius:4px;padding:10px;z-index:2000;font-size:12px;line-height:1.2;min-width:10px;word-wrap:break-word}.el-tooltip__popper .popper__arrow,.el-tooltip__popper .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.el-tooltip__popper .popper__arrow{border-width:6px}.el-tooltip__popper .popper__arrow::after{content:" ";border-width:5px}.el-progress-bar__inner::after,.el-row::after,.el-row::before,.el-slider::after,.el-slider::before,.el-slider__button-wrapper::after,.el-upload-cover::after{content:""}.el-tooltip__popper[x-placement^=top]{margin-bottom:12px}.el-tooltip__popper[x-placement^=top] .popper__arrow{bottom:-6px;border-top-color:#303133;border-bottom-width:0}.el-tooltip__popper[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-5px;border-top-color:#303133;border-bottom-width:0}.el-tooltip__popper[x-placement^=bottom]{margin-top:12px}.el-tooltip__popper[x-placement^=bottom] .popper__arrow{top:-6px;border-top-width:0;border-bottom-color:#303133}.el-tooltip__popper[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-5px;border-top-width:0;border-bottom-color:#303133}.el-tooltip__popper[x-placement^=right]{margin-left:12px}.el-tooltip__popper[x-placement^=right] .popper__arrow{left:-6px;border-right-color:#303133;border-left-width:0}.el-tooltip__popper[x-placement^=right] .popper__arrow::after{bottom:-5px;left:1px;border-right-color:#303133;border-left-width:0}.el-tooltip__popper[x-placement^=left]{margin-right:12px}.el-tooltip__popper[x-placement^=left] .popper__arrow{right:-6px;border-right-width:0;border-left-color:#303133}.el-tooltip__popper[x-placement^=left] .popper__arrow::after{right:1px;bottom:-5px;margin-left:-5px;border-right-width:0;border-left-color:#303133}.el-tooltip__popper.is-dark{background:#303133;color:#FFF}.el-tooltip__popper.is-light{background:#FFF;border:1px solid #303133}.el-tooltip__popper.is-light[x-placement^=top] .popper__arrow{border-top-color:#303133}.el-tooltip__popper.is-light[x-placement^=top] .popper__arrow::after{border-top-color:#FFF}.el-tooltip__popper.is-light[x-placement^=bottom] .popper__arrow{border-bottom-color:#303133}.el-tooltip__popper.is-light[x-placement^=bottom] .popper__arrow::after{border-bottom-color:#FFF}.el-tooltip__popper.is-light[x-placement^=left] .popper__arrow{border-left-color:#303133}.el-tooltip__popper.is-light[x-placement^=left] .popper__arrow::after{border-left-color:#FFF}.el-tooltip__popper.is-light[x-placement^=right] .popper__arrow{border-right-color:#303133}.el-tooltip__popper.is-light[x-placement^=right] .popper__arrow::after{border-right-color:#FFF}.el-slider::after,.el-slider::before{display:table}.el-slider__button-wrapper .el-tooltip,.el-slider__button-wrapper::after{vertical-align:middle;display:inline-block}.el-slider::after{clear:both}.el-slider__runway{width:100%;height:6px;margin:16px 0;background-color:#E4E7ED;border-radius:3px;position:relative;cursor:pointer;vertical-align:middle}.el-slider__runway.show-input{margin-right:160px;width:auto}.el-slider__runway.disabled{cursor:default}.el-slider__runway.disabled .el-slider__bar{background-color:#C0C4CC}.el-slider__runway.disabled .el-slider__button{border-color:#C0C4CC}.el-slider__runway.disabled .el-slider__button-wrapper.dragging,.el-slider__runway.disabled .el-slider__button-wrapper.hover,.el-slider__runway.disabled .el-slider__button-wrapper:hover{cursor:not-allowed}.el-slider__runway.disabled .el-slider__button.dragging,.el-slider__runway.disabled .el-slider__button.hover,.el-slider__runway.disabled .el-slider__button:hover{-webkit-transform:scale(1);transform:scale(1);cursor:not-allowed}.el-slider__button-wrapper,.el-slider__stop{-webkit-transform:translateX(-50%);position:absolute}.el-slider__input{float:right;margin-top:3px;width:130px}.el-slider__input.el-input-number--mini{margin-top:5px}.el-slider__input.el-input-number--medium{margin-top:0}.el-slider__input.el-input-number--large{margin-top:-2px}.el-slider__bar{height:6px;background-color:#00D1B2;border-top-left-radius:3px;border-bottom-left-radius:3px;position:absolute}.el-slider__button-wrapper{height:36px;width:36px;z-index:1001;top:-15px;transform:translateX(-50%);background-color:transparent;text-align:center;-moz-user-select:none;user-select:none;line-height:normal}.el-slider__button,.el-step__icon-inner{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.el-slider__button-wrapper::after{height:100%}.el-slider__button-wrapper.hover,.el-slider__button-wrapper:hover{cursor:-webkit-grab;cursor:grab}.el-slider__button-wrapper.dragging{cursor:-webkit-grabbing;cursor:grabbing}.el-slider__button{width:16px;height:16px;border:2px solid #00D1B2;background-color:#FFF;border-radius:50%;-webkit-transition:.2s;transition:.2s;user-select:none}.el-slider__button.dragging,.el-slider__button.hover,.el-slider__button:hover{-webkit-transform:scale(1.2);transform:scale(1.2)}.el-slider__button.hover,.el-slider__button:hover{cursor:-webkit-grab;cursor:grab}.el-slider__button.dragging{cursor:-webkit-grabbing;cursor:grabbing}.el-slider__stop{height:6px;width:6px;border-radius:100%;background-color:#FFF;transform:translateX(-50%)}.el-slider__marks{top:0;left:12px;width:18px;height:100%}.el-slider__marks-text{position:absolute;-webkit-transform:translateX(-50%);transform:translateX(-50%);font-size:14px;color:#909399;margin-top:15px}.el-slider.is-vertical{position:relative}.el-slider.is-vertical .el-slider__runway{width:6px;height:100%;margin:0 16px}.el-slider.is-vertical .el-slider__bar{width:6px;height:auto;border-radius:0 0 3px 3px}.el-slider.is-vertical .el-slider__button-wrapper{top:auto;left:-15px;-webkit-transform:translateY(50%);transform:translateY(50%)}.el-slider.is-vertical .el-slider__stop{-webkit-transform:translateY(50%);transform:translateY(50%)}.el-slider.is-vertical.el-slider--with-input{padding-bottom:58px}.el-slider.is-vertical.el-slider--with-input .el-slider__input{overflow:visible;float:none;position:absolute;bottom:22px;width:36px;margin-top:15px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input__inner{text-align:center;padding-left:5px;padding-right:5px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__decrease,.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase{top:32px;margin-top:-1px;border:1px solid #DCDFE6;line-height:20px;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__decrease{width:18px;right:18px;border-bottom-left-radius:4px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase{width:19px;border-bottom-right-radius:4px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase~.el-input .el-input__inner{border-bottom-left-radius:0;border-bottom-right-radius:0}.el-slider.is-vertical.el-slider--with-input .el-slider__input:hover .el-input-number__decrease,.el-slider.is-vertical.el-slider--with-input .el-slider__input:hover .el-input-number__increase{border-color:#C0C4CC}.el-slider.is-vertical.el-slider--with-input .el-slider__input:active .el-input-number__decrease,.el-slider.is-vertical.el-slider--with-input .el-slider__input:active .el-input-number__increase{border-color:#00D1B2}.el-slider.is-vertical .el-slider__marks-text{margin-top:0;left:15px;-webkit-transform:translateY(50%);transform:translateY(50%)}.el-loading-parent--relative{position:relative!important}.el-loading-parent--hidden{overflow:hidden!important}.el-loading-mask{position:absolute;z-index:2000;background-color:rgba(255,255,255,.9);margin:0;top:0;right:0;bottom:0;left:0;-webkit-transition:opacity .3s;transition:opacity .3s}.el-loading-mask.is-fullscreen{position:fixed}.el-loading-mask.is-fullscreen .el-loading-spinner{margin-top:-25px}.el-loading-mask.is-fullscreen .el-loading-spinner .circular{height:50px;width:50px}.el-loading-spinner{top:50%;margin-top:-21px;width:100%;text-align:center;position:absolute}.el-col-pull-0,.el-col-pull-1,.el-col-pull-10,.el-col-pull-11,.el-col-pull-13,.el-col-pull-14,.el-col-pull-15,.el-col-pull-16,.el-col-pull-17,.el-col-pull-18,.el-col-pull-19,.el-col-pull-2,.el-col-pull-20,.el-col-pull-21,.el-col-pull-22,.el-col-pull-23,.el-col-pull-24,.el-col-pull-3,.el-col-pull-4,.el-col-pull-5,.el-col-pull-6,.el-col-pull-7,.el-col-pull-8,.el-col-pull-9,.el-col-push-0,.el-col-push-1,.el-col-push-10,.el-col-push-11,.el-col-push-12,.el-col-push-13,.el-col-push-14,.el-col-push-15,.el-col-push-16,.el-col-push-17,.el-col-push-18,.el-col-push-19,.el-col-push-2,.el-col-push-20,.el-col-push-21,.el-col-push-22,.el-col-push-23,.el-col-push-24,.el-col-push-3,.el-col-push-4,.el-col-push-5,.el-col-push-6,.el-col-push-7,.el-col-push-8,.el-col-push-9,.el-row{position:relative}.el-loading-spinner .el-loading-text{color:#00D1B2;margin:3px 0;font-size:14px}.el-loading-spinner .circular{height:42px;width:42px;-webkit-animation:loading-rotate 2s linear infinite;animation:loading-rotate 2s linear infinite}.el-loading-spinner .path{-webkit-animation:loading-dash 1.5s ease-in-out infinite;animation:loading-dash 1.5s ease-in-out infinite;stroke-dasharray:90,150;stroke-dashoffset:0;stroke-width:2;stroke:#00D1B2;stroke-linecap:round}.el-loading-spinner i{color:#00D1B2}@-webkit-keyframes loading-rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes loading-rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes loading-dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-40px}100%{stroke-dasharray:90,150;stroke-dashoffset:-120px}}@keyframes loading-dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-40px}100%{stroke-dasharray:90,150;stroke-dashoffset:-120px}}.el-row{-webkit-box-sizing:border-box;box-sizing:border-box}.el-row::after,.el-row::before{display:table}.el-row::after{clear:both}.el-row--flex{display:-webkit-box;display:-ms-flexbox;display:flex}.el-col-0,.el-row--flex:after,.el-row--flex:before{display:none}.el-row--flex.is-justify-center{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.el-row--flex.is-justify-end{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.el-row--flex.is-justify-space-between{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.el-row--flex.is-justify-space-around{-ms-flex-pack:distribute;justify-content:space-around}.el-row--flex.is-align-middle{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.el-row--flex.is-align-bottom{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}[class*=el-col-]{float:left;-webkit-box-sizing:border-box;box-sizing:border-box}.el-upload--picture-card,.el-upload-dragger{-webkit-box-sizing:border-box;cursor:pointer}.el-col-0{width:0%}.el-col-offset-0{margin-left:0}.el-col-pull-0{right:0}.el-col-push-0{left:0}.el-col-1{width:4.16667%}.el-col-offset-1{margin-left:4.16667%}.el-col-pull-1{right:4.16667%}.el-col-push-1{left:4.16667%}.el-col-2{width:8.33333%}.el-col-offset-2{margin-left:8.33333%}.el-col-pull-2{right:8.33333%}.el-col-push-2{left:8.33333%}.el-col-3{width:12.5%}.el-col-offset-3{margin-left:12.5%}.el-col-pull-3{right:12.5%}.el-col-push-3{left:12.5%}.el-col-4{width:16.66667%}.el-col-offset-4{margin-left:16.66667%}.el-col-pull-4{right:16.66667%}.el-col-push-4{left:16.66667%}.el-col-5{width:20.83333%}.el-col-offset-5{margin-left:20.83333%}.el-col-pull-5{right:20.83333%}.el-col-push-5{left:20.83333%}.el-col-6{width:25%}.el-col-offset-6{margin-left:25%}.el-col-pull-6{right:25%}.el-col-push-6{left:25%}.el-col-7{width:29.16667%}.el-col-offset-7{margin-left:29.16667%}.el-col-pull-7{right:29.16667%}.el-col-push-7{left:29.16667%}.el-col-8{width:33.33333%}.el-col-offset-8{margin-left:33.33333%}.el-col-pull-8{right:33.33333%}.el-col-push-8{left:33.33333%}.el-col-9{width:37.5%}.el-col-offset-9{margin-left:37.5%}.el-col-pull-9{right:37.5%}.el-col-push-9{left:37.5%}.el-col-10{width:41.66667%}.el-col-offset-10{margin-left:41.66667%}.el-col-pull-10{right:41.66667%}.el-col-push-10{left:41.66667%}.el-col-11{width:45.83333%}.el-col-offset-11{margin-left:45.83333%}.el-col-pull-11{right:45.83333%}.el-col-push-11{left:45.83333%}.el-col-12{width:50%}.el-col-offset-12{margin-left:50%}.el-col-pull-12{position:relative;right:50%}.el-col-push-12{left:50%}.el-col-13{width:54.16667%}.el-col-offset-13{margin-left:54.16667%}.el-col-pull-13{right:54.16667%}.el-col-push-13{left:54.16667%}.el-col-14{width:58.33333%}.el-col-offset-14{margin-left:58.33333%}.el-col-pull-14{right:58.33333%}.el-col-push-14{left:58.33333%}.el-col-15{width:62.5%}.el-col-offset-15{margin-left:62.5%}.el-col-pull-15{right:62.5%}.el-col-push-15{left:62.5%}.el-col-16{width:66.66667%}.el-col-offset-16{margin-left:66.66667%}.el-col-pull-16{right:66.66667%}.el-col-push-16{left:66.66667%}.el-col-17{width:70.83333%}.el-col-offset-17{margin-left:70.83333%}.el-col-pull-17{right:70.83333%}.el-col-push-17{left:70.83333%}.el-col-18{width:75%}.el-col-offset-18{margin-left:75%}.el-col-pull-18{right:75%}.el-col-push-18{left:75%}.el-col-19{width:79.16667%}.el-col-offset-19{margin-left:79.16667%}.el-col-pull-19{right:79.16667%}.el-col-push-19{left:79.16667%}.el-col-20{width:83.33333%}.el-col-offset-20{margin-left:83.33333%}.el-col-pull-20{right:83.33333%}.el-col-push-20{left:83.33333%}.el-col-21{width:87.5%}.el-col-offset-21{margin-left:87.5%}.el-col-pull-21{right:87.5%}.el-col-push-21{left:87.5%}.el-col-22{width:91.66667%}.el-col-offset-22{margin-left:91.66667%}.el-col-pull-22{right:91.66667%}.el-col-push-22{left:91.66667%}.el-col-23{width:95.83333%}.el-col-offset-23{margin-left:95.83333%}.el-col-pull-23{right:95.83333%}.el-col-push-23{left:95.83333%}.el-col-24{width:100%}.el-col-offset-24{margin-left:100%}.el-col-pull-24{right:100%}.el-col-push-24{left:100%}@media only screen and (max-width:767px){.el-col-xs-0{display:none;width:0%}.el-col-xs-offset-0{margin-left:0}.el-col-xs-pull-0{position:relative;right:0}.el-col-xs-push-0{position:relative;left:0}.el-col-xs-1{width:4.16667%}.el-col-xs-offset-1{margin-left:4.16667%}.el-col-xs-pull-1{position:relative;right:4.16667%}.el-col-xs-push-1{position:relative;left:4.16667%}.el-col-xs-2{width:8.33333%}.el-col-xs-offset-2{margin-left:8.33333%}.el-col-xs-pull-2{position:relative;right:8.33333%}.el-col-xs-push-2{position:relative;left:8.33333%}.el-col-xs-3{width:12.5%}.el-col-xs-offset-3{margin-left:12.5%}.el-col-xs-pull-3{position:relative;right:12.5%}.el-col-xs-push-3{position:relative;left:12.5%}.el-col-xs-4{width:16.66667%}.el-col-xs-offset-4{margin-left:16.66667%}.el-col-xs-pull-4{position:relative;right:16.66667%}.el-col-xs-push-4{position:relative;left:16.66667%}.el-col-xs-5{width:20.83333%}.el-col-xs-offset-5{margin-left:20.83333%}.el-col-xs-pull-5{position:relative;right:20.83333%}.el-col-xs-push-5{position:relative;left:20.83333%}.el-col-xs-6{width:25%}.el-col-xs-offset-6{margin-left:25%}.el-col-xs-pull-6{position:relative;right:25%}.el-col-xs-push-6{position:relative;left:25%}.el-col-xs-7{width:29.16667%}.el-col-xs-offset-7{margin-left:29.16667%}.el-col-xs-pull-7{position:relative;right:29.16667%}.el-col-xs-push-7{position:relative;left:29.16667%}.el-col-xs-8{width:33.33333%}.el-col-xs-offset-8{margin-left:33.33333%}.el-col-xs-pull-8{position:relative;right:33.33333%}.el-col-xs-push-8{position:relative;left:33.33333%}.el-col-xs-9{width:37.5%}.el-col-xs-offset-9{margin-left:37.5%}.el-col-xs-pull-9{position:relative;right:37.5%}.el-col-xs-push-9{position:relative;left:37.5%}.el-col-xs-10{width:41.66667%}.el-col-xs-offset-10{margin-left:41.66667%}.el-col-xs-pull-10{position:relative;right:41.66667%}.el-col-xs-push-10{position:relative;left:41.66667%}.el-col-xs-11{width:45.83333%}.el-col-xs-offset-11{margin-left:45.83333%}.el-col-xs-pull-11{position:relative;right:45.83333%}.el-col-xs-push-11{position:relative;left:45.83333%}.el-col-xs-12{width:50%}.el-col-xs-offset-12{margin-left:50%}.el-col-xs-pull-12{position:relative;right:50%}.el-col-xs-push-12{position:relative;left:50%}.el-col-xs-13{width:54.16667%}.el-col-xs-offset-13{margin-left:54.16667%}.el-col-xs-pull-13{position:relative;right:54.16667%}.el-col-xs-push-13{position:relative;left:54.16667%}.el-col-xs-14{width:58.33333%}.el-col-xs-offset-14{margin-left:58.33333%}.el-col-xs-pull-14{position:relative;right:58.33333%}.el-col-xs-push-14{position:relative;left:58.33333%}.el-col-xs-15{width:62.5%}.el-col-xs-offset-15{margin-left:62.5%}.el-col-xs-pull-15{position:relative;right:62.5%}.el-col-xs-push-15{position:relative;left:62.5%}.el-col-xs-16{width:66.66667%}.el-col-xs-offset-16{margin-left:66.66667%}.el-col-xs-pull-16{position:relative;right:66.66667%}.el-col-xs-push-16{position:relative;left:66.66667%}.el-col-xs-17{width:70.83333%}.el-col-xs-offset-17{margin-left:70.83333%}.el-col-xs-pull-17{position:relative;right:70.83333%}.el-col-xs-push-17{position:relative;left:70.83333%}.el-col-xs-18{width:75%}.el-col-xs-offset-18{margin-left:75%}.el-col-xs-pull-18{position:relative;right:75%}.el-col-xs-push-18{position:relative;left:75%}.el-col-xs-19{width:79.16667%}.el-col-xs-offset-19{margin-left:79.16667%}.el-col-xs-pull-19{position:relative;right:79.16667%}.el-col-xs-push-19{position:relative;left:79.16667%}.el-col-xs-20{width:83.33333%}.el-col-xs-offset-20{margin-left:83.33333%}.el-col-xs-pull-20{position:relative;right:83.33333%}.el-col-xs-push-20{position:relative;left:83.33333%}.el-col-xs-21{width:87.5%}.el-col-xs-offset-21{margin-left:87.5%}.el-col-xs-pull-21{position:relative;right:87.5%}.el-col-xs-push-21{position:relative;left:87.5%}.el-col-xs-22{width:91.66667%}.el-col-xs-offset-22{margin-left:91.66667%}.el-col-xs-pull-22{position:relative;right:91.66667%}.el-col-xs-push-22{position:relative;left:91.66667%}.el-col-xs-23{width:95.83333%}.el-col-xs-offset-23{margin-left:95.83333%}.el-col-xs-pull-23{position:relative;right:95.83333%}.el-col-xs-push-23{position:relative;left:95.83333%}.el-col-xs-24{width:100%}.el-col-xs-offset-24{margin-left:100%}.el-col-xs-pull-24{position:relative;right:100%}.el-col-xs-push-24{position:relative;left:100%}}@media only screen and (min-width:768px){.el-col-sm-0{display:none;width:0%}.el-col-sm-offset-0{margin-left:0}.el-col-sm-pull-0{position:relative;right:0}.el-col-sm-push-0{position:relative;left:0}.el-col-sm-1{width:4.16667%}.el-col-sm-offset-1{margin-left:4.16667%}.el-col-sm-pull-1{position:relative;right:4.16667%}.el-col-sm-push-1{position:relative;left:4.16667%}.el-col-sm-2{width:8.33333%}.el-col-sm-offset-2{margin-left:8.33333%}.el-col-sm-pull-2{position:relative;right:8.33333%}.el-col-sm-push-2{position:relative;left:8.33333%}.el-col-sm-3{width:12.5%}.el-col-sm-offset-3{margin-left:12.5%}.el-col-sm-pull-3{position:relative;right:12.5%}.el-col-sm-push-3{position:relative;left:12.5%}.el-col-sm-4{width:16.66667%}.el-col-sm-offset-4{margin-left:16.66667%}.el-col-sm-pull-4{position:relative;right:16.66667%}.el-col-sm-push-4{position:relative;left:16.66667%}.el-col-sm-5{width:20.83333%}.el-col-sm-offset-5{margin-left:20.83333%}.el-col-sm-pull-5{position:relative;right:20.83333%}.el-col-sm-push-5{position:relative;left:20.83333%}.el-col-sm-6{width:25%}.el-col-sm-offset-6{margin-left:25%}.el-col-sm-pull-6{position:relative;right:25%}.el-col-sm-push-6{position:relative;left:25%}.el-col-sm-7{width:29.16667%}.el-col-sm-offset-7{margin-left:29.16667%}.el-col-sm-pull-7{position:relative;right:29.16667%}.el-col-sm-push-7{position:relative;left:29.16667%}.el-col-sm-8{width:33.33333%}.el-col-sm-offset-8{margin-left:33.33333%}.el-col-sm-pull-8{position:relative;right:33.33333%}.el-col-sm-push-8{position:relative;left:33.33333%}.el-col-sm-9{width:37.5%}.el-col-sm-offset-9{margin-left:37.5%}.el-col-sm-pull-9{position:relative;right:37.5%}.el-col-sm-push-9{position:relative;left:37.5%}.el-col-sm-10{width:41.66667%}.el-col-sm-offset-10{margin-left:41.66667%}.el-col-sm-pull-10{position:relative;right:41.66667%}.el-col-sm-push-10{position:relative;left:41.66667%}.el-col-sm-11{width:45.83333%}.el-col-sm-offset-11{margin-left:45.83333%}.el-col-sm-pull-11{position:relative;right:45.83333%}.el-col-sm-push-11{position:relative;left:45.83333%}.el-col-sm-12{width:50%}.el-col-sm-offset-12{margin-left:50%}.el-col-sm-pull-12{position:relative;right:50%}.el-col-sm-push-12{position:relative;left:50%}.el-col-sm-13{width:54.16667%}.el-col-sm-offset-13{margin-left:54.16667%}.el-col-sm-pull-13{position:relative;right:54.16667%}.el-col-sm-push-13{position:relative;left:54.16667%}.el-col-sm-14{width:58.33333%}.el-col-sm-offset-14{margin-left:58.33333%}.el-col-sm-pull-14{position:relative;right:58.33333%}.el-col-sm-push-14{position:relative;left:58.33333%}.el-col-sm-15{width:62.5%}.el-col-sm-offset-15{margin-left:62.5%}.el-col-sm-pull-15{position:relative;right:62.5%}.el-col-sm-push-15{position:relative;left:62.5%}.el-col-sm-16{width:66.66667%}.el-col-sm-offset-16{margin-left:66.66667%}.el-col-sm-pull-16{position:relative;right:66.66667%}.el-col-sm-push-16{position:relative;left:66.66667%}.el-col-sm-17{width:70.83333%}.el-col-sm-offset-17{margin-left:70.83333%}.el-col-sm-pull-17{position:relative;right:70.83333%}.el-col-sm-push-17{position:relative;left:70.83333%}.el-col-sm-18{width:75%}.el-col-sm-offset-18{margin-left:75%}.el-col-sm-pull-18{position:relative;right:75%}.el-col-sm-push-18{position:relative;left:75%}.el-col-sm-19{width:79.16667%}.el-col-sm-offset-19{margin-left:79.16667%}.el-col-sm-pull-19{position:relative;right:79.16667%}.el-col-sm-push-19{position:relative;left:79.16667%}.el-col-sm-20{width:83.33333%}.el-col-sm-offset-20{margin-left:83.33333%}.el-col-sm-pull-20{position:relative;right:83.33333%}.el-col-sm-push-20{position:relative;left:83.33333%}.el-col-sm-21{width:87.5%}.el-col-sm-offset-21{margin-left:87.5%}.el-col-sm-pull-21{position:relative;right:87.5%}.el-col-sm-push-21{position:relative;left:87.5%}.el-col-sm-22{width:91.66667%}.el-col-sm-offset-22{margin-left:91.66667%}.el-col-sm-pull-22{position:relative;right:91.66667%}.el-col-sm-push-22{position:relative;left:91.66667%}.el-col-sm-23{width:95.83333%}.el-col-sm-offset-23{margin-left:95.83333%}.el-col-sm-pull-23{position:relative;right:95.83333%}.el-col-sm-push-23{position:relative;left:95.83333%}.el-col-sm-24{width:100%}.el-col-sm-offset-24{margin-left:100%}.el-col-sm-pull-24{position:relative;right:100%}.el-col-sm-push-24{position:relative;left:100%}}@media only screen and (min-width:992px){.el-col-md-0{display:none;width:0%}.el-col-md-offset-0{margin-left:0}.el-col-md-pull-0{position:relative;right:0}.el-col-md-push-0{position:relative;left:0}.el-col-md-1{width:4.16667%}.el-col-md-offset-1{margin-left:4.16667%}.el-col-md-pull-1{position:relative;right:4.16667%}.el-col-md-push-1{position:relative;left:4.16667%}.el-col-md-2{width:8.33333%}.el-col-md-offset-2{margin-left:8.33333%}.el-col-md-pull-2{position:relative;right:8.33333%}.el-col-md-push-2{position:relative;left:8.33333%}.el-col-md-3{width:12.5%}.el-col-md-offset-3{margin-left:12.5%}.el-col-md-pull-3{position:relative;right:12.5%}.el-col-md-push-3{position:relative;left:12.5%}.el-col-md-4{width:16.66667%}.el-col-md-offset-4{margin-left:16.66667%}.el-col-md-pull-4{position:relative;right:16.66667%}.el-col-md-push-4{position:relative;left:16.66667%}.el-col-md-5{width:20.83333%}.el-col-md-offset-5{margin-left:20.83333%}.el-col-md-pull-5{position:relative;right:20.83333%}.el-col-md-push-5{position:relative;left:20.83333%}.el-col-md-6{width:25%}.el-col-md-offset-6{margin-left:25%}.el-col-md-pull-6{position:relative;right:25%}.el-col-md-push-6{position:relative;left:25%}.el-col-md-7{width:29.16667%}.el-col-md-offset-7{margin-left:29.16667%}.el-col-md-pull-7{position:relative;right:29.16667%}.el-col-md-push-7{position:relative;left:29.16667%}.el-col-md-8{width:33.33333%}.el-col-md-offset-8{margin-left:33.33333%}.el-col-md-pull-8{position:relative;right:33.33333%}.el-col-md-push-8{position:relative;left:33.33333%}.el-col-md-9{width:37.5%}.el-col-md-offset-9{margin-left:37.5%}.el-col-md-pull-9{position:relative;right:37.5%}.el-col-md-push-9{position:relative;left:37.5%}.el-col-md-10{width:41.66667%}.el-col-md-offset-10{margin-left:41.66667%}.el-col-md-pull-10{position:relative;right:41.66667%}.el-col-md-push-10{position:relative;left:41.66667%}.el-col-md-11{width:45.83333%}.el-col-md-offset-11{margin-left:45.83333%}.el-col-md-pull-11{position:relative;right:45.83333%}.el-col-md-push-11{position:relative;left:45.83333%}.el-col-md-12{width:50%}.el-col-md-offset-12{margin-left:50%}.el-col-md-pull-12{position:relative;right:50%}.el-col-md-push-12{position:relative;left:50%}.el-col-md-13{width:54.16667%}.el-col-md-offset-13{margin-left:54.16667%}.el-col-md-pull-13{position:relative;right:54.16667%}.el-col-md-push-13{position:relative;left:54.16667%}.el-col-md-14{width:58.33333%}.el-col-md-offset-14{margin-left:58.33333%}.el-col-md-pull-14{position:relative;right:58.33333%}.el-col-md-push-14{position:relative;left:58.33333%}.el-col-md-15{width:62.5%}.el-col-md-offset-15{margin-left:62.5%}.el-col-md-pull-15{position:relative;right:62.5%}.el-col-md-push-15{position:relative;left:62.5%}.el-col-md-16{width:66.66667%}.el-col-md-offset-16{margin-left:66.66667%}.el-col-md-pull-16{position:relative;right:66.66667%}.el-col-md-push-16{position:relative;left:66.66667%}.el-col-md-17{width:70.83333%}.el-col-md-offset-17{margin-left:70.83333%}.el-col-md-pull-17{position:relative;right:70.83333%}.el-col-md-push-17{position:relative;left:70.83333%}.el-col-md-18{width:75%}.el-col-md-offset-18{margin-left:75%}.el-col-md-pull-18{position:relative;right:75%}.el-col-md-push-18{position:relative;left:75%}.el-col-md-19{width:79.16667%}.el-col-md-offset-19{margin-left:79.16667%}.el-col-md-pull-19{position:relative;right:79.16667%}.el-col-md-push-19{position:relative;left:79.16667%}.el-col-md-20{width:83.33333%}.el-col-md-offset-20{margin-left:83.33333%}.el-col-md-pull-20{position:relative;right:83.33333%}.el-col-md-push-20{position:relative;left:83.33333%}.el-col-md-21{width:87.5%}.el-col-md-offset-21{margin-left:87.5%}.el-col-md-pull-21{position:relative;right:87.5%}.el-col-md-push-21{position:relative;left:87.5%}.el-col-md-22{width:91.66667%}.el-col-md-offset-22{margin-left:91.66667%}.el-col-md-pull-22{position:relative;right:91.66667%}.el-col-md-push-22{position:relative;left:91.66667%}.el-col-md-23{width:95.83333%}.el-col-md-offset-23{margin-left:95.83333%}.el-col-md-pull-23{position:relative;right:95.83333%}.el-col-md-push-23{position:relative;left:95.83333%}.el-col-md-24{width:100%}.el-col-md-offset-24{margin-left:100%}.el-col-md-pull-24{position:relative;right:100%}.el-col-md-push-24{position:relative;left:100%}}@media only screen and (min-width:1200px){.el-col-lg-0{display:none;width:0%}.el-col-lg-offset-0{margin-left:0}.el-col-lg-pull-0{position:relative;right:0}.el-col-lg-push-0{position:relative;left:0}.el-col-lg-1{width:4.16667%}.el-col-lg-offset-1{margin-left:4.16667%}.el-col-lg-pull-1{position:relative;right:4.16667%}.el-col-lg-push-1{position:relative;left:4.16667%}.el-col-lg-2{width:8.33333%}.el-col-lg-offset-2{margin-left:8.33333%}.el-col-lg-pull-2{position:relative;right:8.33333%}.el-col-lg-push-2{position:relative;left:8.33333%}.el-col-lg-3{width:12.5%}.el-col-lg-offset-3{margin-left:12.5%}.el-col-lg-pull-3{position:relative;right:12.5%}.el-col-lg-push-3{position:relative;left:12.5%}.el-col-lg-4{width:16.66667%}.el-col-lg-offset-4{margin-left:16.66667%}.el-col-lg-pull-4{position:relative;right:16.66667%}.el-col-lg-push-4{position:relative;left:16.66667%}.el-col-lg-5{width:20.83333%}.el-col-lg-offset-5{margin-left:20.83333%}.el-col-lg-pull-5{position:relative;right:20.83333%}.el-col-lg-push-5{position:relative;left:20.83333%}.el-col-lg-6{width:25%}.el-col-lg-offset-6{margin-left:25%}.el-col-lg-pull-6{position:relative;right:25%}.el-col-lg-push-6{position:relative;left:25%}.el-col-lg-7{width:29.16667%}.el-col-lg-offset-7{margin-left:29.16667%}.el-col-lg-pull-7{position:relative;right:29.16667%}.el-col-lg-push-7{position:relative;left:29.16667%}.el-col-lg-8{width:33.33333%}.el-col-lg-offset-8{margin-left:33.33333%}.el-col-lg-pull-8{position:relative;right:33.33333%}.el-col-lg-push-8{position:relative;left:33.33333%}.el-col-lg-9{width:37.5%}.el-col-lg-offset-9{margin-left:37.5%}.el-col-lg-pull-9{position:relative;right:37.5%}.el-col-lg-push-9{position:relative;left:37.5%}.el-col-lg-10{width:41.66667%}.el-col-lg-offset-10{margin-left:41.66667%}.el-col-lg-pull-10{position:relative;right:41.66667%}.el-col-lg-push-10{position:relative;left:41.66667%}.el-col-lg-11{width:45.83333%}.el-col-lg-offset-11{margin-left:45.83333%}.el-col-lg-pull-11{position:relative;right:45.83333%}.el-col-lg-push-11{position:relative;left:45.83333%}.el-col-lg-12{width:50%}.el-col-lg-offset-12{margin-left:50%}.el-col-lg-pull-12{position:relative;right:50%}.el-col-lg-push-12{position:relative;left:50%}.el-col-lg-13{width:54.16667%}.el-col-lg-offset-13{margin-left:54.16667%}.el-col-lg-pull-13{position:relative;right:54.16667%}.el-col-lg-push-13{position:relative;left:54.16667%}.el-col-lg-14{width:58.33333%}.el-col-lg-offset-14{margin-left:58.33333%}.el-col-lg-pull-14{position:relative;right:58.33333%}.el-col-lg-push-14{position:relative;left:58.33333%}.el-col-lg-15{width:62.5%}.el-col-lg-offset-15{margin-left:62.5%}.el-col-lg-pull-15{position:relative;right:62.5%}.el-col-lg-push-15{position:relative;left:62.5%}.el-col-lg-16{width:66.66667%}.el-col-lg-offset-16{margin-left:66.66667%}.el-col-lg-pull-16{position:relative;right:66.66667%}.el-col-lg-push-16{position:relative;left:66.66667%}.el-col-lg-17{width:70.83333%}.el-col-lg-offset-17{margin-left:70.83333%}.el-col-lg-pull-17{position:relative;right:70.83333%}.el-col-lg-push-17{position:relative;left:70.83333%}.el-col-lg-18{width:75%}.el-col-lg-offset-18{margin-left:75%}.el-col-lg-pull-18{position:relative;right:75%}.el-col-lg-push-18{position:relative;left:75%}.el-col-lg-19{width:79.16667%}.el-col-lg-offset-19{margin-left:79.16667%}.el-col-lg-pull-19{position:relative;right:79.16667%}.el-col-lg-push-19{position:relative;left:79.16667%}.el-col-lg-20{width:83.33333%}.el-col-lg-offset-20{margin-left:83.33333%}.el-col-lg-pull-20{position:relative;right:83.33333%}.el-col-lg-push-20{position:relative;left:83.33333%}.el-col-lg-21{width:87.5%}.el-col-lg-offset-21{margin-left:87.5%}.el-col-lg-pull-21{position:relative;right:87.5%}.el-col-lg-push-21{position:relative;left:87.5%}.el-col-lg-22{width:91.66667%}.el-col-lg-offset-22{margin-left:91.66667%}.el-col-lg-pull-22{position:relative;right:91.66667%}.el-col-lg-push-22{position:relative;left:91.66667%}.el-col-lg-23{width:95.83333%}.el-col-lg-offset-23{margin-left:95.83333%}.el-col-lg-pull-23{position:relative;right:95.83333%}.el-col-lg-push-23{position:relative;left:95.83333%}.el-col-lg-24{width:100%}.el-col-lg-offset-24{margin-left:100%}.el-col-lg-pull-24{position:relative;right:100%}.el-col-lg-push-24{position:relative;left:100%}}@media only screen and (min-width:1920px){.el-col-xl-0{display:none;width:0%}.el-col-xl-offset-0{margin-left:0}.el-col-xl-pull-0{position:relative;right:0}.el-col-xl-push-0{position:relative;left:0}.el-col-xl-1{width:4.16667%}.el-col-xl-offset-1{margin-left:4.16667%}.el-col-xl-pull-1{position:relative;right:4.16667%}.el-col-xl-push-1{position:relative;left:4.16667%}.el-col-xl-2{width:8.33333%}.el-col-xl-offset-2{margin-left:8.33333%}.el-col-xl-pull-2{position:relative;right:8.33333%}.el-col-xl-push-2{position:relative;left:8.33333%}.el-col-xl-3{width:12.5%}.el-col-xl-offset-3{margin-left:12.5%}.el-col-xl-pull-3{position:relative;right:12.5%}.el-col-xl-push-3{position:relative;left:12.5%}.el-col-xl-4{width:16.66667%}.el-col-xl-offset-4{margin-left:16.66667%}.el-col-xl-pull-4{position:relative;right:16.66667%}.el-col-xl-push-4{position:relative;left:16.66667%}.el-col-xl-5{width:20.83333%}.el-col-xl-offset-5{margin-left:20.83333%}.el-col-xl-pull-5{position:relative;right:20.83333%}.el-col-xl-push-5{position:relative;left:20.83333%}.el-col-xl-6{width:25%}.el-col-xl-offset-6{margin-left:25%}.el-col-xl-pull-6{position:relative;right:25%}.el-col-xl-push-6{position:relative;left:25%}.el-col-xl-7{width:29.16667%}.el-col-xl-offset-7{margin-left:29.16667%}.el-col-xl-pull-7{position:relative;right:29.16667%}.el-col-xl-push-7{position:relative;left:29.16667%}.el-col-xl-8{width:33.33333%}.el-col-xl-offset-8{margin-left:33.33333%}.el-col-xl-pull-8{position:relative;right:33.33333%}.el-col-xl-push-8{position:relative;left:33.33333%}.el-col-xl-9{width:37.5%}.el-col-xl-offset-9{margin-left:37.5%}.el-col-xl-pull-9{position:relative;right:37.5%}.el-col-xl-push-9{position:relative;left:37.5%}.el-col-xl-10{width:41.66667%}.el-col-xl-offset-10{margin-left:41.66667%}.el-col-xl-pull-10{position:relative;right:41.66667%}.el-col-xl-push-10{position:relative;left:41.66667%}.el-col-xl-11{width:45.83333%}.el-col-xl-offset-11{margin-left:45.83333%}.el-col-xl-pull-11{position:relative;right:45.83333%}.el-col-xl-push-11{position:relative;left:45.83333%}.el-col-xl-12{width:50%}.el-col-xl-offset-12{margin-left:50%}.el-col-xl-pull-12{position:relative;right:50%}.el-col-xl-push-12{position:relative;left:50%}.el-col-xl-13{width:54.16667%}.el-col-xl-offset-13{margin-left:54.16667%}.el-col-xl-pull-13{position:relative;right:54.16667%}.el-col-xl-push-13{position:relative;left:54.16667%}.el-col-xl-14{width:58.33333%}.el-col-xl-offset-14{margin-left:58.33333%}.el-col-xl-pull-14{position:relative;right:58.33333%}.el-col-xl-push-14{position:relative;left:58.33333%}.el-col-xl-15{width:62.5%}.el-col-xl-offset-15{margin-left:62.5%}.el-col-xl-pull-15{position:relative;right:62.5%}.el-col-xl-push-15{position:relative;left:62.5%}.el-col-xl-16{width:66.66667%}.el-col-xl-offset-16{margin-left:66.66667%}.el-col-xl-pull-16{position:relative;right:66.66667%}.el-col-xl-push-16{position:relative;left:66.66667%}.el-col-xl-17{width:70.83333%}.el-col-xl-offset-17{margin-left:70.83333%}.el-col-xl-pull-17{position:relative;right:70.83333%}.el-col-xl-push-17{position:relative;left:70.83333%}.el-col-xl-18{width:75%}.el-col-xl-offset-18{margin-left:75%}.el-col-xl-pull-18{position:relative;right:75%}.el-col-xl-push-18{position:relative;left:75%}.el-col-xl-19{width:79.16667%}.el-col-xl-offset-19{margin-left:79.16667%}.el-col-xl-pull-19{position:relative;right:79.16667%}.el-col-xl-push-19{position:relative;left:79.16667%}.el-col-xl-20{width:83.33333%}.el-col-xl-offset-20{margin-left:83.33333%}.el-col-xl-pull-20{position:relative;right:83.33333%}.el-col-xl-push-20{position:relative;left:83.33333%}.el-col-xl-21{width:87.5%}.el-col-xl-offset-21{margin-left:87.5%}.el-col-xl-pull-21{position:relative;right:87.5%}.el-col-xl-push-21{position:relative;left:87.5%}.el-col-xl-22{width:91.66667%}.el-col-xl-offset-22{margin-left:91.66667%}.el-col-xl-pull-22{position:relative;right:91.66667%}.el-col-xl-push-22{position:relative;left:91.66667%}.el-col-xl-23{width:95.83333%}.el-col-xl-offset-23{margin-left:95.83333%}.el-col-xl-pull-23{position:relative;right:95.83333%}.el-col-xl-push-23{position:relative;left:95.83333%}.el-col-xl-24{width:100%}.el-col-xl-offset-24{margin-left:100%}.el-col-xl-pull-24{position:relative;right:100%}.el-col-xl-push-24{position:relative;left:100%}}@-webkit-keyframes progress{0%{background-position:0 0}100%{background-position:32px 0}}.el-upload{display:inline-block;text-align:center;cursor:pointer;outline:0}.el-upload__input{display:none}.el-upload__tip{font-size:12px;color:#606266;margin-top:7px}.el-upload iframe{position:absolute;z-index:-1;top:0;left:0;opacity:0;filter:alpha(opacity=0)}.el-upload--picture-card{background-color:#fbfdff;border:1px dashed #c0ccda;border-radius:6px;box-sizing:border-box;width:148px;height:148px;line-height:146px;vertical-align:top}.el-upload--picture-card i{font-size:28px;color:#8c939d}.el-upload--picture-card:hover,.el-upload:focus{border-color:#00D1B2;color:#00D1B2}.el-upload:focus .el-upload-dragger{border-color:#00D1B2}.el-upload-dragger{background-color:#fff;border:1px dashed #d9d9d9;border-radius:6px;box-sizing:border-box;width:360px;height:180px;text-align:center;position:relative;overflow:hidden}.el-upload-dragger .el-icon-upload{font-size:67px;color:#C0C4CC;margin:40px 0 16px;line-height:50px}.el-upload-dragger+.el-upload__tip{text-align:center}.el-upload-dragger~.el-upload__files{border-top:1px solid #DCDFE6;margin-top:7px;padding-top:5px}.el-upload-dragger .el-upload__text{color:#606266;font-size:14px;text-align:center}.el-upload-dragger .el-upload__text em{color:#00D1B2;font-style:normal}.el-upload-dragger:hover{border-color:#00D1B2}.el-upload-dragger.is-dragover{background-color:rgba(32,159,255,.06);border:2px dashed #00D1B2}.el-upload-list{margin:0;padding:0;list-style:none}.el-upload-list__item{-webkit-transition:all .5s cubic-bezier(.55,0,.1,1);transition:all .5s cubic-bezier(.55,0,.1,1);font-size:14px;color:#606266;line-height:1.8;margin-top:5px;position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:4px;width:100%}.el-upload-list__item .el-progress{position:absolute;top:20px;width:100%}.el-upload-list__item .el-progress__text{position:absolute;right:0;top:-13px}.el-upload-list__item .el-progress-bar{margin-right:0;padding-right:0}.el-upload-list__item:first-child{margin-top:10px}.el-upload-list__item .el-icon-upload-success{color:#67C23A}.el-upload-list__item .el-icon-close{display:none;position:absolute;top:5px;right:5px;cursor:pointer;opacity:.75;color:#606266}.el-upload-list__item .el-icon-close:hover{opacity:1}.el-upload-list__item .el-icon-close-tip{display:none;position:absolute;top:5px;right:5px;font-size:12px;cursor:pointer;opacity:1;color:#00D1B2}.el-upload-list__item:hover{background-color:#F5F7FA}.el-upload-list__item:hover .el-icon-close{display:inline-block}.el-upload-list__item:hover .el-progress__text{display:none}.el-upload-list__item.is-success .el-upload-list__item-status-label{display:block}.el-upload-list__item.is-success .el-upload-list__item-name:focus,.el-upload-list__item.is-success .el-upload-list__item-name:hover{color:#00D1B2;cursor:pointer}.el-upload-list__item.is-success:focus:not(:hover) .el-icon-close-tip{display:inline-block}.el-upload-list__item.is-success:active .el-icon-close-tip,.el-upload-list__item.is-success:focus .el-upload-list__item-status-label,.el-upload-list__item.is-success:hover .el-upload-list__item-status-label,.el-upload-list__item.is-success:not(.focusing):focus .el-icon-close-tip{display:none}.el-upload-list.is-disabled .el-upload-list__item:hover .el-upload-list__item-status-label{display:block}.el-upload-list__item-name{color:#606266;display:block;margin-right:40px;overflow:hidden;padding-left:4px;text-overflow:ellipsis;-webkit-transition:color .3s;transition:color .3s;white-space:nowrap}.el-upload-list__item-name [class^=el-icon]{height:100%;margin-right:7px;color:#909399;line-height:inherit}.el-upload-list__item-status-label{position:absolute;right:5px;top:0;line-height:inherit;display:none}.el-upload-list__item-delete{position:absolute;right:10px;top:0;font-size:12px;color:#606266;display:none}.el-upload-list__item-delete:hover{color:#00D1B2}.el-upload-list--picture-card{margin:0;display:inline;vertical-align:top}.el-upload-list--picture-card .el-upload-list__item{overflow:hidden;background-color:#fff;border:1px solid #c0ccda;border-radius:6px;-webkit-box-sizing:border-box;box-sizing:border-box;width:148px;height:148px;margin:0 8px 8px 0;display:inline-block}.el-upload-list--picture-card .el-upload-list__item .el-icon-check,.el-upload-list--picture-card .el-upload-list__item .el-icon-circle-check{color:#FFF}.el-upload-list--picture-card .el-upload-list__item .el-icon-close,.el-upload-list--picture-card .el-upload-list__item:hover .el-upload-list__item-status-label{display:none}.el-upload-list--picture-card .el-upload-list__item:hover .el-progress__text{display:block}.el-upload-list--picture-card .el-upload-list__item-name{display:none}.el-upload-list--picture-card .el-upload-list__item-thumbnail{width:100%;height:100%}.el-upload-list--picture-card .el-upload-list__item-status-label{position:absolute;right:-15px;top:-6px;width:40px;height:24px;background:#13ce66;text-align:center;-webkit-transform:rotate(45deg);transform:rotate(45deg);-webkit-box-shadow:0 0 1pc 1px rgba(0,0,0,.2);box-shadow:0 0 1pc 1px rgba(0,0,0,.2)}.el-upload-list--picture-card .el-upload-list__item-status-label i{font-size:12px;margin-top:11px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.el-upload-list--picture-card .el-upload-list__item-actions{position:absolute;width:100%;height:100%;left:0;top:0;cursor:default;text-align:center;color:#fff;opacity:0;font-size:20px;background-color:rgba(0,0,0,.5);-webkit-transition:opacity .3s;transition:opacity .3s}.el-upload-list--picture-card .el-upload-list__item-actions::after{display:inline-block;content:"";height:100%;vertical-align:middle}.el-upload-list--picture-card .el-upload-list__item-actions span{display:none;cursor:pointer}.el-upload-list--picture-card .el-upload-list__item-actions span+span{margin-left:15px}.el-upload-list--picture-card .el-upload-list__item-actions .el-upload-list__item-delete{position:static;font-size:inherit;color:inherit}.el-upload-list--picture-card .el-upload-list__item-actions:hover{opacity:1}.el-upload-list--picture-card .el-upload-list__item-actions:hover span{display:inline-block}.el-upload-list--picture-card .el-progress{top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);bottom:auto;width:126px}.el-upload-list--picture-card .el-progress .el-progress__text{top:50%}.el-upload-list--picture .el-upload-list__item{overflow:hidden;z-index:0;background-color:#fff;border:1px solid #c0ccda;border-radius:6px;-webkit-box-sizing:border-box;box-sizing:border-box;margin-top:10px;padding:10px 10px 10px 90px;height:92px}.el-upload-list--picture .el-upload-list__item .el-icon-check,.el-upload-list--picture .el-upload-list__item .el-icon-circle-check{color:#FFF}.el-upload-list--picture .el-upload-list__item:hover .el-upload-list__item-status-label{background:0 0;-webkit-box-shadow:none;box-shadow:none;top:-2px;right:-12px}.el-upload-list--picture .el-upload-list__item:hover .el-progress__text{display:block}.el-upload-list--picture .el-upload-list__item.is-success .el-upload-list__item-name{line-height:70px;margin-top:0}.el-upload-list--picture .el-upload-list__item.is-success .el-upload-list__item-name i{display:none}.el-upload-list--picture .el-upload-list__item-thumbnail{vertical-align:middle;display:inline-block;width:70px;height:70px;float:left;position:relative;z-index:1;margin-left:-80px;background-color:#FFF}.el-upload-list--picture .el-upload-list__item-name{display:block;margin-top:20px}.el-upload-list--picture .el-upload-list__item-name i{font-size:70px;line-height:1;position:absolute;left:9px;top:10px}.el-upload-list--picture .el-upload-list__item-status-label{position:absolute;right:-17px;top:-7px;width:46px;height:26px;background:#13ce66;text-align:center;-webkit-transform:rotate(45deg);transform:rotate(45deg);-webkit-box-shadow:0 1px 1px #ccc;box-shadow:0 1px 1px #ccc}.el-upload-list--picture .el-upload-list__item-status-label i{font-size:12px;margin-top:12px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.el-upload-list--picture .el-progress{position:relative;top:-7px}.el-upload-cover{position:absolute;left:0;top:0;width:100%;height:100%;overflow:hidden;z-index:10;cursor:default}.el-upload-cover::after{display:inline-block;height:100%;vertical-align:middle}.el-upload-cover img{display:block;width:100%;height:100%}.el-upload-cover__label{position:absolute;right:-15px;top:-6px;width:40px;height:24px;background:#13ce66;text-align:center;-webkit-transform:rotate(45deg);transform:rotate(45deg);-webkit-box-shadow:0 0 1pc 1px rgba(0,0,0,.2);box-shadow:0 0 1pc 1px rgba(0,0,0,.2)}.el-upload-cover__label i{font-size:12px;margin-top:11px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);color:#fff}.el-upload-cover__progress{display:inline-block;vertical-align:middle;position:static;width:243px}.el-upload-cover__progress+.el-upload__inner{opacity:0}.el-upload-cover__content{position:absolute;top:0;left:0;width:100%;height:100%}.el-upload-cover__interact{position:absolute;bottom:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.72);text-align:center}.el-upload-cover__interact .btn{display:inline-block;color:#FFF;font-size:14px;cursor:pointer;vertical-align:middle;-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);margin-top:60px}.el-upload-cover__interact .btn span{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.el-upload-cover__interact .btn:not(:first-child){margin-left:35px}.el-upload-cover__interact .btn:hover{-webkit-transform:translateY(-13px);transform:translateY(-13px)}.el-upload-cover__interact .btn:hover span{opacity:1}.el-upload-cover__interact .btn i{color:#FFF;display:block;font-size:24px;line-height:inherit;margin:0 auto 5px}.el-upload-cover__title{position:absolute;bottom:0;left:0;background-color:#FFF;height:36px;width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:400;text-align:left;padding:0 10px;margin:0;line-height:36px;font-size:14px;color:#303133}.el-upload-cover+.el-upload__inner{opacity:0;position:relative;z-index:1}.el-progress{position:relative;line-height:1}.el-progress__text{font-size:14px;color:#606266;display:inline-block;vertical-align:middle;margin-left:10px;line-height:1}.el-progress__text i{vertical-align:middle;display:block}.el-progress--circle,.el-progress--dashboard{display:inline-block}.el-progress--circle .el-progress__text,.el-progress--dashboard .el-progress__text{position:absolute;top:50%;left:0;width:100%;text-align:center;margin:0;-webkit-transform:translate(0,-50%);transform:translate(0,-50%)}.el-progress--circle .el-progress__text i,.el-progress--dashboard .el-progress__text i{vertical-align:middle;display:inline-block}.el-progress--without-text .el-progress__text{display:none}.el-progress--without-text .el-progress-bar{padding-right:0;margin-right:0;display:block}.el-progress-bar,.el-progress-bar__inner::after,.el-progress-bar__innerText,.el-spinner{display:inline-block;vertical-align:middle}.el-progress--text-inside .el-progress-bar{padding-right:0;margin-right:0}.el-progress.is-success .el-progress-bar__inner{background-color:#67C23A}.el-progress.is-success .el-progress__text{color:#67C23A}.el-progress.is-warning .el-progress-bar__inner{background-color:#E6A23C}.el-progress.is-warning .el-progress__text{color:#E6A23C}.el-progress.is-exception .el-progress-bar__inner{background-color:#F56C6C}.el-progress.is-exception .el-progress__text{color:#F56C6C}.el-progress-bar{padding-right:50px;width:100%;margin-right:-55px;-webkit-box-sizing:border-box;box-sizing:border-box}.el-progress-bar__outer{height:6px;border-radius:100px;background-color:#EBEEF5;overflow:hidden;position:relative;vertical-align:middle}.el-progress-bar__inner{position:absolute;left:0;top:0;height:100%;background-color:#00D1B2;text-align:right;border-radius:100px;line-height:1;white-space:nowrap;-webkit-transition:width .6s ease;transition:width .6s ease}.el-card,.el-message{border-radius:4px;overflow:hidden}.el-progress-bar__inner::after{height:100%}.el-progress-bar__innerText{color:#FFF;font-size:12px;margin:0 5px}@keyframes progress{0%{background-position:0 0}100%{background-position:32px 0}}.el-time-spinner{width:100%;white-space:nowrap}.el-spinner-inner{-webkit-animation:rotate 2s linear infinite;animation:rotate 2s linear infinite;width:50px;height:50px}.el-spinner-inner .path{stroke:#ececec;stroke-linecap:round;-webkit-animation:dash 1.5s ease-in-out infinite;animation:dash 1.5s ease-in-out infinite}@-webkit-keyframes rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes dash{0%{stroke-dasharray:1,150;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-35}100%{stroke-dasharray:90,150;stroke-dashoffset:-124}}@keyframes dash{0%{stroke-dasharray:1,150;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-35}100%{stroke-dasharray:90,150;stroke-dashoffset:-124}}.el-message{min-width:380px;-webkit-box-sizing:border-box;box-sizing:border-box;border-width:1px;border-style:solid;border-color:#EBEEF5;position:fixed;left:50%;top:20px;-webkit-transform:translateX(-50%);transform:translateX(-50%);background-color:#edf2fc;-webkit-transition:opacity .3s,top .4s,-webkit-transform .4s;transition:opacity .3s,top .4s,-webkit-transform .4s;transition:opacity .3s,transform .4s,top .4s;transition:opacity .3s,transform .4s,top .4s,-webkit-transform .4s;padding:15px 15px 15px 20px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.el-message.is-center{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.el-message.is-closable .el-message__content{padding-right:16px}.el-message p{margin:0}.el-message--info .el-message__content{color:#909399}.el-message--success{background-color:#f0f9eb;border-color:#e1f3d8}.el-message--success .el-message__content{color:#67C23A}.el-message--warning{background-color:#fdf6ec;border-color:#faecd8}.el-message--warning .el-message__content{color:#E6A23C}.el-message--error{background-color:#fef0f0;border-color:#fde2e2}.el-message--error .el-message__content{color:#F56C6C}.el-message__icon{margin-right:10px}.el-message__content{padding:0;font-size:14px;line-height:1}.el-message__closeBtn{position:absolute;top:50%;right:15px;-webkit-transform:translateY(-50%);transform:translateY(-50%);cursor:pointer;color:#C0C4CC;font-size:16px}.el-message__closeBtn:hover{color:#909399}.el-message .el-icon-success{color:#67C23A}.el-message .el-icon-error{color:#F56C6C}.el-message .el-icon-info{color:#909399}.el-message .el-icon-warning{color:#E6A23C}.el-message-fade-enter,.el-message-fade-leave-active{opacity:0;-webkit-transform:translate(-50%,-100%);transform:translate(-50%,-100%)}.el-badge{position:relative;vertical-align:middle;display:inline-block}.el-badge__content{background-color:#F56C6C;border-radius:10px;color:#FFF;display:inline-block;font-size:12px;height:18px;line-height:18px;padding:0 6px;text-align:center;white-space:nowrap;border:1px solid #FFF}.el-badge__content.is-fixed{position:absolute;top:0;right:10px;-webkit-transform:translateY(-50%) translateX(100%);transform:translateY(-50%) translateX(100%)}.el-rate__icon,.el-rate__item{position:relative;display:inline-block}.el-badge__content.is-fixed.is-dot{right:5px}.el-badge__content.is-dot{height:8px;width:8px;padding:0;right:0;border-radius:50%}.el-badge__content--primary{background-color:#00D1B2}.el-badge__content--success{background-color:#67C23A}.el-badge__content--warning{background-color:#E6A23C}.el-badge__content--info{background-color:#909399}.el-badge__content--danger{background-color:#F56C6C}.el-card{border:1px solid #EBEEF5;background-color:#FFF;color:#303133;-webkit-transition:.3s;transition:.3s}.el-card.is-always-shadow,.el-card.is-hover-shadow:focus,.el-card.is-hover-shadow:hover{-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-card__header{padding:18px 20px;border-bottom:1px solid #EBEEF5;-webkit-box-sizing:border-box;box-sizing:border-box}.el-card__body{padding:20px}.el-rate{height:20px;line-height:1}.el-rate__item{font-size:0;vertical-align:middle}.el-rate__icon{font-size:18px;margin-right:6px;color:#C0C4CC;-webkit-transition:.3s;transition:.3s}.el-rate__decimal,.el-rate__icon .path2{position:absolute;top:0;left:0}.el-rate__icon.hover{-webkit-transform:scale(1.15);transform:scale(1.15)}.el-rate__decimal{display:inline-block;overflow:hidden}.el-step.is-vertical,.el-steps{display:-webkit-box;display:-ms-flexbox}.el-rate__text{font-size:14px;vertical-align:middle}.el-steps{display:flex}.el-steps--simple{padding:13px 8%;border-radius:4px;background:#F5F7FA}.el-steps--horizontal{white-space:nowrap}.el-steps--vertical{height:100%;-webkit-box-orient:vertical;-ms-flex-flow:column;flex-flow:column}.el-step{position:relative;-ms-flex-negative:1;flex-shrink:1}.el-step:last-of-type .el-step__line{display:none}.el-step:last-of-type.is-flex{-ms-flex-preferred-size:auto!important;flex-basis:auto!important;-ms-flex-negative:0;flex-shrink:0;-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0}.el-step:last-of-type .el-step__description,.el-step:last-of-type .el-step__main{padding-right:0}.el-step__head{position:relative;width:100%}.el-step__head.is-process{color:#303133;border-color:#303133}.el-step__head.is-wait{color:#C0C4CC;border-color:#C0C4CC}.el-step__head.is-success{color:#67C23A;border-color:#67C23A}.el-step__head.is-error{color:#F56C6C;border-color:#F56C6C}.el-step__head.is-finish{color:#00D1B2;border-color:#00D1B2}.el-step__icon{position:relative;z-index:1;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;width:24px;height:24px;font-size:14px;-webkit-box-sizing:border-box;box-sizing:border-box;background:#FFF;-webkit-transition:.15s ease-out;transition:.15s ease-out}.el-step__icon.is-text{border-radius:50%;border:2px solid;border-color:inherit}.el-step__icon.is-icon{width:40px}.el-step__icon-inner{display:inline-block;user-select:none;text-align:center;font-weight:700;line-height:1;color:inherit}.el-button,.el-checkbox,.el-image-viewer__btn{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.el-step__icon-inner[class*=el-icon]:not(.is-status){font-size:25px;font-weight:400}.el-step__icon-inner.is-status{-webkit-transform:translateY(1px);transform:translateY(1px)}.el-step__line{position:absolute;border-color:inherit;background-color:#C0C4CC}.el-step__line-inner{display:block;border-width:1px;border-style:solid;border-color:inherit;-webkit-transition:.15s ease-out;transition:.15s ease-out;-webkit-box-sizing:border-box;box-sizing:border-box;width:0;height:0}.el-step__main{white-space:normal;text-align:left}.el-step__title{font-size:16px;line-height:38px}.el-step__title.is-process{font-weight:700;color:#303133}.el-step__title.is-wait{color:#C0C4CC}.el-step__title.is-success{color:#67C23A}.el-step__title.is-error{color:#F56C6C}.el-step__title.is-finish{color:#00D1B2}.el-step__description{padding-right:10%;margin-top:-5px;font-size:12px;line-height:20px;font-weight:400}.el-step__description.is-process{color:#303133}.el-step__description.is-wait{color:#C0C4CC}.el-step__description.is-success{color:#67C23A}.el-step__description.is-error{color:#F56C6C}.el-step__description.is-finish{color:#00D1B2}.el-step.is-horizontal{display:inline-block}.el-step.is-horizontal .el-step__line{height:2px;top:11px;left:0;right:0}.el-step.is-vertical{display:flex}.el-step.is-vertical .el-step__head{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;width:24px}.el-step.is-vertical .el-step__main{padding-left:10px;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.el-step.is-vertical .el-step__title{line-height:24px;padding-bottom:8px}.el-step.is-vertical .el-step__line{width:2px;top:0;bottom:0;left:11px}.el-step.is-vertical .el-step__icon.is-icon{width:24px}.el-step.is-center .el-step__head,.el-step.is-center .el-step__main{text-align:center}.el-step.is-center .el-step__description{padding-left:20%;padding-right:20%}.el-step.is-center .el-step__line{left:50%;right:-50%}.el-step.is-simple{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.el-step.is-simple .el-step__head{width:auto;font-size:0;padding-right:10px}.el-step.is-simple .el-step__icon{background:0 0;width:16px;height:16px;font-size:12px}.el-step.is-simple .el-step__icon-inner[class*=el-icon]:not(.is-status){font-size:18px}.el-step.is-simple .el-step__icon-inner.is-status{-webkit-transform:scale(.8) translateY(1px);transform:scale(.8) translateY(1px)}.el-step.is-simple .el-step__main{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.el-step.is-simple .el-step__title{font-size:16px;line-height:20px}.el-step.is-simple:not(:last-of-type) .el-step__title{max-width:50%;word-break:break-all}.el-step.is-simple .el-step__arrow{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.el-step.is-simple .el-step__arrow::after,.el-step.is-simple .el-step__arrow::before{content:'';display:inline-block;position:absolute;height:15px;width:1px;background:#C0C4CC}.el-step.is-simple .el-step__arrow::before{-webkit-transform:rotate(-45deg) translateY(-4px);transform:rotate(-45deg) translateY(-4px);-webkit-transform-origin:0 0;transform-origin:0 0}.el-step.is-simple .el-step__arrow::after{-webkit-transform:rotate(45deg) translateY(4px);transform:rotate(45deg) translateY(4px);-webkit-transform-origin:100% 100%;transform-origin:100% 100%}.el-step.is-simple:last-of-type .el-step__arrow{display:none}.el-carousel{position:relative}.el-carousel--horizontal{overflow-x:hidden}.el-carousel--vertical{overflow-y:hidden}.el-carousel__container{position:relative;height:300px}.el-carousel__arrow{border:none;outline:0;padding:0;margin:0;height:36px;width:36px;cursor:pointer;-webkit-transition:.3s;transition:.3s;border-radius:50%;background-color:rgba(31,45,61,.11);color:#FFF;position:absolute;top:50%;z-index:10;-webkit-transform:translateY(-50%);transform:translateY(-50%);text-align:center;font-size:12px}.el-carousel__arrow--left{left:16px}.el-carousel__arrow--right{right:16px}.el-carousel__arrow:hover{background-color:rgba(31,45,61,.23)}.el-carousel__arrow i{cursor:pointer}.el-carousel__indicators{position:absolute;list-style:none;margin:0;padding:0;z-index:2}.el-carousel__indicators--horizontal{bottom:0;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.el-carousel__indicators--vertical{right:0;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.el-carousel__indicators--outside{bottom:26px;text-align:center;position:static;-webkit-transform:none;transform:none}.el-carousel__indicators--outside .el-carousel__indicator:hover button{opacity:.64}.el-carousel__indicators--outside button{background-color:#C0C4CC;opacity:.24}.el-carousel__indicators--labels{left:0;right:0;-webkit-transform:none;transform:none;text-align:center}.el-carousel__indicators--labels .el-carousel__button{height:auto;width:auto;padding:2px 18px;font-size:12px}.el-carousel__indicators--labels .el-carousel__indicator{padding:6px 4px}.el-carousel__indicator{background-color:transparent;cursor:pointer}.el-carousel__indicator:hover button{opacity:.72}.el-carousel__indicator--horizontal{display:inline-block;padding:12px 4px}.el-carousel__indicator--vertical{padding:4px 12px}.el-carousel__indicator--vertical .el-carousel__button{width:2px;height:15px}.el-carousel__indicator.is-active button{opacity:1}.el-carousel__button{display:block;opacity:.48;width:30px;height:2px;background-color:#FFF;border:none;outline:0;padding:0;margin:0;cursor:pointer;-webkit-transition:.3s;transition:.3s}.el-carousel__item,.el-carousel__mask{height:100%;top:0;left:0;position:absolute}.carousel-arrow-left-enter,.carousel-arrow-left-leave-active{-webkit-transform:translateY(-50%) translateX(-10px);transform:translateY(-50%) translateX(-10px);opacity:0}.carousel-arrow-right-enter,.carousel-arrow-right-leave-active{-webkit-transform:translateY(-50%) translateX(10px);transform:translateY(-50%) translateX(10px);opacity:0}.el-carousel__item{width:100%;display:inline-block;overflow:hidden;z-index:0}.el-carousel__item.is-active{z-index:2}.el-carousel__item.is-animating{-webkit-transition:-webkit-transform .4s ease-in-out;transition:-webkit-transform .4s ease-in-out;transition:transform .4s ease-in-out;transition:transform .4s ease-in-out,-webkit-transform .4s ease-in-out}.el-carousel__item--card{width:50%;-webkit-transition:-webkit-transform .4s ease-in-out;transition:-webkit-transform .4s ease-in-out;transition:transform .4s ease-in-out;transition:transform .4s ease-in-out,-webkit-transform .4s ease-in-out}.el-carousel__item--card.is-in-stage{cursor:pointer;z-index:1}.el-carousel__item--card.is-in-stage.is-hover .el-carousel__mask,.el-carousel__item--card.is-in-stage:hover .el-carousel__mask{opacity:.12}.el-carousel__item--card.is-active{z-index:2}.el-carousel__mask{width:100%;background-color:#FFF;opacity:.24;-webkit-transition:.2s;transition:.2s}.el-fade-in-enter,.el-fade-in-leave-active,.el-fade-in-linear-enter,.el-fade-in-linear-leave,.el-fade-in-linear-leave-active,.fade-in-linear-enter,.fade-in-linear-leave,.fade-in-linear-leave-active{opacity:0}.fade-in-linear-enter-active,.fade-in-linear-leave-active{-webkit-transition:opacity .2s linear;transition:opacity .2s linear}.el-fade-in-linear-enter-active,.el-fade-in-linear-leave-active{-webkit-transition:opacity .2s linear;transition:opacity .2s linear}.el-fade-in-enter-active,.el-fade-in-leave-active{-webkit-transition:all .3s cubic-bezier(.55,0,.1,1);transition:all .3s cubic-bezier(.55,0,.1,1)}.el-zoom-in-center-enter-active,.el-zoom-in-center-leave-active{-webkit-transition:all .3s cubic-bezier(.55,0,.1,1);transition:all .3s cubic-bezier(.55,0,.1,1)}.el-zoom-in-center-enter,.el-zoom-in-center-leave-active{opacity:0;-webkit-transform:scaleX(0);transform:scaleX(0)}.el-zoom-in-top-enter-active,.el-zoom-in-top-leave-active{opacity:1;-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);-webkit-transform-origin:center top;transform-origin:center top}.el-zoom-in-top-enter,.el-zoom-in-top-leave-active{opacity:0;-webkit-transform:scaleY(0);transform:scaleY(0)}.el-zoom-in-bottom-enter-active,.el-zoom-in-bottom-leave-active{opacity:1;-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);-webkit-transform-origin:center bottom;transform-origin:center bottom}.el-zoom-in-bottom-enter,.el-zoom-in-bottom-leave-active{opacity:0;-webkit-transform:scaleY(0);transform:scaleY(0)}.el-zoom-in-left-enter-active,.el-zoom-in-left-leave-active{opacity:1;-webkit-transform:scale(1,1);transform:scale(1,1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);-webkit-transform-origin:top left;transform-origin:top left}.el-zoom-in-left-enter,.el-zoom-in-left-leave-active{opacity:0;-webkit-transform:scale(.45,.45);transform:scale(.45,.45)}.collapse-transition{-webkit-transition:.3s height ease-in-out,.3s padding-top ease-in-out,.3s padding-bottom ease-in-out;transition:.3s height ease-in-out,.3s padding-top ease-in-out,.3s padding-bottom ease-in-out}.horizontal-collapse-transition{-webkit-transition:.3s width ease-in-out,.3s padding-left ease-in-out,.3s padding-right ease-in-out;transition:.3s width ease-in-out,.3s padding-left ease-in-out,.3s padding-right ease-in-out}.el-list-enter-active,.el-list-leave-active{-webkit-transition:all 1s;transition:all 1s}.el-list-enter,.el-list-leave-active{opacity:0;-webkit-transform:translateY(-30px);transform:translateY(-30px)}.el-opacity-transition{-webkit-transition:opacity .3s cubic-bezier(.55,0,.1,1);transition:opacity .3s cubic-bezier(.55,0,.1,1)}.el-collapse{border-top:1px solid #EBEEF5;border-bottom:1px solid #EBEEF5}.el-collapse-item.is-disabled .el-collapse-item__header{color:#bbb;cursor:not-allowed}.el-collapse-item__header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:48px;line-height:48px;background-color:#FFF;color:#303133;cursor:pointer;border-bottom:1px solid #EBEEF5;font-size:13px;font-weight:500;-webkit-transition:border-bottom-color .3s;transition:border-bottom-color .3s;outline:0}.el-collapse-item__arrow{margin:0 8px 0 auto;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;font-weight:300}.el-collapse-item__arrow.is-active{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.el-collapse-item__header.focusing:focus:not(:hover){color:#00D1B2}.el-collapse-item__header.is-active{border-bottom-color:transparent}.el-collapse-item__wrap{will-change:height;background-color:#FFF;overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;border-bottom:1px solid #EBEEF5}.el-cascader__tags,.el-tag{-webkit-box-sizing:border-box}.el-collapse-item__content{padding-bottom:25px;font-size:13px;color:#303133;line-height:1.769230769230769}.el-collapse-item:last-child{margin-bottom:-1px}.el-popper .popper__arrow,.el-popper .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.el-popper .popper__arrow{border-width:6px;-webkit-filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03));filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03))}.el-popper .popper__arrow::after{content:" ";border-width:6px}.el-popper[x-placement^=top]{margin-bottom:12px}.el-popper[x-placement^=top] .popper__arrow{bottom:-6px;left:50%;margin-right:3px;border-top-color:#EBEEF5;border-bottom-width:0}.el-popper[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-6px;border-top-color:#FFF;border-bottom-width:0}.el-popper[x-placement^=bottom]{margin-top:12px}.el-popper[x-placement^=bottom] .popper__arrow{top:-6px;left:50%;margin-right:3px;border-top-width:0;border-bottom-color:#EBEEF5}.el-popper[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-6px;border-top-width:0;border-bottom-color:#FFF}.el-popper[x-placement^=right]{margin-left:12px}.el-popper[x-placement^=right] .popper__arrow{top:50%;left:-6px;margin-bottom:3px;border-right-color:#EBEEF5;border-left-width:0}.el-popper[x-placement^=right] .popper__arrow::after{bottom:-6px;left:1px;border-right-color:#FFF;border-left-width:0}.el-popper[x-placement^=left]{margin-right:12px}.el-popper[x-placement^=left] .popper__arrow{top:50%;right:-6px;margin-bottom:3px;border-right-width:0;border-left-color:#EBEEF5}.el-popper[x-placement^=left] .popper__arrow::after{right:1px;bottom:-6px;margin-left:-6px;border-right-width:0;border-left-color:#FFF}.el-tag{background-color:rgb(230, 250, 247);border-color:rgb(204, 246, 240);display:inline-block;height:32px;padding:0 10px;line-height:30px;font-size:12px;color:#00D1B2;border-width:1px;border-style:solid;border-radius:4px;box-sizing:border-box;white-space:nowrap}.el-tag.is-hit{border-color:#00D1B2}.el-tag .el-tag__close{color:#00D1B2}.el-tag .el-tag__close:hover{color:#FFF;background-color:#00D1B2}.el-tag.el-tag--info{background-color:#f4f4f5;border-color:#e9e9eb;color:#909399}.el-tag.el-tag--info.is-hit{border-color:#909399}.el-tag.el-tag--info .el-tag__close{color:#909399}.el-tag.el-tag--info .el-tag__close:hover{color:#FFF;background-color:#909399}.el-tag.el-tag--success{background-color:#f0f9eb;border-color:#e1f3d8;color:#67c23a}.el-tag.el-tag--success.is-hit{border-color:#67C23A}.el-tag.el-tag--success .el-tag__close{color:#67c23a}.el-tag.el-tag--success .el-tag__close:hover{color:#FFF;background-color:#67c23a}.el-tag.el-tag--warning{background-color:#fdf6ec;border-color:#faecd8;color:#e6a23c}.el-tag.el-tag--warning.is-hit{border-color:#E6A23C}.el-tag.el-tag--warning .el-tag__close{color:#e6a23c}.el-tag.el-tag--warning .el-tag__close:hover{color:#FFF;background-color:#e6a23c}.el-tag.el-tag--danger{background-color:#fef0f0;border-color:#fde2e2;color:#f56c6c}.el-tag.el-tag--danger.is-hit{border-color:#F56C6C}.el-tag.el-tag--danger .el-tag__close{color:#f56c6c}.el-tag.el-tag--danger .el-tag__close:hover{color:#FFF;background-color:#f56c6c}.el-tag .el-icon-close{border-radius:50%;text-align:center;position:relative;cursor:pointer;font-size:12px;height:16px;width:16px;line-height:16px;vertical-align:middle;top:-1px;right:-5px}.el-tag .el-icon-close::before{display:block}.el-tag--dark{background-color:#00D1B2;border-color:#00D1B2;color:#fff}.el-tag--dark.is-hit{border-color:#00D1B2}.el-tag--dark .el-tag__close{color:#fff}.el-tag--dark .el-tag__close:hover{color:#FFF;background-color:rgb(51, 218, 193)}.el-tag--dark.el-tag--info{background-color:#909399;border-color:#909399;color:#fff}.el-tag--dark.el-tag--info.is-hit{border-color:#909399}.el-tag--dark.el-tag--info .el-tag__close{color:#fff}.el-tag--dark.el-tag--info .el-tag__close:hover{color:#FFF;background-color:#a6a9ad}.el-tag--dark.el-tag--success{background-color:#67c23a;border-color:#67c23a;color:#fff}.el-tag--dark.el-tag--success.is-hit{border-color:#67C23A}.el-tag--dark.el-tag--success .el-tag__close{color:#fff}.el-tag--dark.el-tag--success .el-tag__close:hover{color:#FFF;background-color:#85ce61}.el-tag--dark.el-tag--warning{background-color:#e6a23c;border-color:#e6a23c;color:#fff}.el-tag--dark.el-tag--warning.is-hit{border-color:#E6A23C}.el-tag--dark.el-tag--warning .el-tag__close{color:#fff}.el-tag--dark.el-tag--warning .el-tag__close:hover{color:#FFF;background-color:#ebb563}.el-tag--dark.el-tag--danger{background-color:#f56c6c;border-color:#f56c6c;color:#fff}.el-tag--dark.el-tag--danger.is-hit{border-color:#F56C6C}.el-tag--dark.el-tag--danger .el-tag__close{color:#fff}.el-tag--dark.el-tag--danger .el-tag__close:hover{color:#FFF;background-color:#f78989}.el-tag--plain{background-color:#fff;border-color:rgb(153, 237, 224);color:#00D1B2}.el-tag--plain.is-hit{border-color:#00D1B2}.el-tag--plain .el-tag__close{color:#00D1B2}.el-tag--plain .el-tag__close:hover{color:#FFF;background-color:#00D1B2}.el-tag--plain.el-tag--info{background-color:#fff;border-color:#d3d4d6;color:#909399}.el-tag--plain.el-tag--info.is-hit{border-color:#909399}.el-tag--plain.el-tag--info .el-tag__close{color:#909399}.el-tag--plain.el-tag--info .el-tag__close:hover{color:#FFF;background-color:#909399}.el-tag--plain.el-tag--success{background-color:#fff;border-color:#c2e7b0;color:#67c23a}.el-tag--plain.el-tag--success.is-hit{border-color:#67C23A}.el-tag--plain.el-tag--success .el-tag__close{color:#67c23a}.el-tag--plain.el-tag--success .el-tag__close:hover{color:#FFF;background-color:#67c23a}.el-tag--plain.el-tag--warning{background-color:#fff;border-color:#f5dab1;color:#e6a23c}.el-tag--plain.el-tag--warning.is-hit{border-color:#E6A23C}.el-tag--plain.el-tag--warning .el-tag__close{color:#e6a23c}.el-tag--plain.el-tag--warning .el-tag__close:hover{color:#FFF;background-color:#e6a23c}.el-tag--plain.el-tag--danger{background-color:#fff;border-color:#fbc4c4;color:#f56c6c}.el-tag--plain.el-tag--danger.is-hit{border-color:#F56C6C}.el-tag--plain.el-tag--danger .el-tag__close{color:#f56c6c}.el-tag--plain.el-tag--danger .el-tag__close:hover{color:#FFF;background-color:#f56c6c}.el-tag--medium{height:28px;line-height:26px}.el-tag--medium .el-icon-close{-webkit-transform:scale(.8);transform:scale(.8)}.el-tag--small{height:24px;padding:0 8px;line-height:22px}.el-tag--small .el-icon-close{-webkit-transform:scale(.8);transform:scale(.8)}.el-tag--mini{height:20px;padding:0 5px;line-height:19px}.el-tag--mini .el-icon-close{margin-left:-3px;-webkit-transform:scale(.7);transform:scale(.7)}.el-cascader{display:inline-block;position:relative;font-size:14px;line-height:40px}.el-cascader:not(.is-disabled):hover .el-input__inner{cursor:pointer;border-color:#C0C4CC}.el-cascader .el-input .el-input__inner:focus,.el-cascader .el-input.is-focus .el-input__inner{border-color:#00D1B2}.el-cascader .el-input{cursor:pointer}.el-cascader .el-input .el-input__inner{text-overflow:ellipsis}.el-cascader .el-input .el-icon-arrow-down{-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;font-size:14px}.el-cascader .el-input .el-icon-arrow-down.is-reverse{-webkit-transform:rotateZ(180deg);transform:rotateZ(180deg)}.el-cascader .el-input .el-icon-circle-close:hover{color:#909399}.el-cascader--medium{font-size:14px;line-height:36px}.el-cascader--small{font-size:13px;line-height:32px}.el-cascader--mini{font-size:12px;line-height:28px}.el-cascader.is-disabled .el-cascader__label{z-index:2;color:#C0C4CC}.el-cascader__dropdown{margin:5px 0;font-size:14px;background:#FFF;border:1px solid #E4E7ED;border-radius:4px;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-cascader__tags{position:absolute;left:0;right:30px;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;line-height:normal;text-align:left;box-sizing:border-box}.el-cascader__tags .el-tag{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;max-width:100%;margin:2px 0 2px 6px;text-overflow:ellipsis;background:#f0f2f5}.el-cascader__tags .el-tag:not(.is-hit){border-color:transparent}.el-cascader__tags .el-tag>span{-webkit-box-flex:1;-ms-flex:1;flex:1;overflow:hidden;text-overflow:ellipsis}.el-cascader__tags .el-tag .el-icon-close{-webkit-box-flex:0;-ms-flex:none;flex:none;background-color:#C0C4CC;color:#FFF}.el-cascader__tags .el-tag .el-icon-close:hover{background-color:#909399}.el-cascader__suggestion-panel{border-radius:4px}.el-cascader__suggestion-list{max-height:204px;margin:0;padding:6px 0;font-size:14px;color:#606266;text-align:center}.el-cascader__suggestion-item{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:34px;padding:0 15px;text-align:left;outline:0;cursor:pointer}.el-cascader__suggestion-item:focus,.el-cascader__suggestion-item:hover{background:#F5F7FA}.el-cascader__suggestion-item.is-checked{color:#00D1B2;font-weight:700}.el-cascader__suggestion-item>span{margin-right:10px}.el-cascader__empty-text{margin:10px 0;color:#C0C4CC}.el-cascader__search-input{-webkit-box-flex:1;-ms-flex:1;flex:1;height:24px;min-width:60px;margin:2px 0 2px 15px;padding:0;color:#606266;border:none;outline:0;-webkit-box-sizing:border-box;box-sizing:border-box}.el-cascader__search-input::-webkit-input-placeholder{color:#C0C4CC}.el-cascader__search-input:-ms-input-placeholder{color:#C0C4CC}.el-cascader__search-input::-ms-input-placeholder{color:#C0C4CC}.el-cascader__search-input::placeholder{color:#C0C4CC}.el-color-predefine{display:-webkit-box;display:-ms-flexbox;display:flex;font-size:12px;margin-top:8px;width:280px}.el-color-predefine__colors{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1;flex:1;-ms-flex-wrap:wrap;flex-wrap:wrap}.el-color-predefine__color-selector{margin:0 0 8px 8px;width:20px;height:20px;border-radius:4px;cursor:pointer}.el-color-predefine__color-selector:nth-child(10n+1){margin-left:0}.el-color-predefine__color-selector.selected{-webkit-box-shadow:0 0 3px 2px #00D1B2;box-shadow:0 0 3px 2px #00D1B2}.el-color-predefine__color-selector>div{display:-webkit-box;display:-ms-flexbox;display:flex;height:100%;border-radius:3px}.el-color-predefine__color-selector.is-alpha{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.el-color-hue-slider{position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;width:280px;height:12px;background-color:red;padding:0 2px}.el-color-hue-slider__bar{position:relative;background:-webkit-gradient(linear,left top,right top,from(red),color-stop(17%,#ff0),color-stop(33%,#0f0),color-stop(50%,#0ff),color-stop(67%,#00f),color-stop(83%,#f0f),to(red));background:linear-gradient(to right,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%);height:100%}.el-color-hue-slider__thumb{position:absolute;cursor:pointer;-webkit-box-sizing:border-box;box-sizing:border-box;left:0;top:0;width:4px;height:100%;border-radius:1px;background:#fff;border:1px solid #f0f0f0;-webkit-box-shadow:0 0 2px rgba(0,0,0,.6);box-shadow:0 0 2px rgba(0,0,0,.6);z-index:1}.el-color-hue-slider.is-vertical{width:12px;height:180px;padding:2px 0}.el-color-hue-slider.is-vertical .el-color-hue-slider__bar{background:-webkit-gradient(linear,left top,left bottom,from(red),color-stop(17%,#ff0),color-stop(33%,#0f0),color-stop(50%,#0ff),color-stop(67%,#00f),color-stop(83%,#f0f),to(red));background:linear-gradient(to bottom,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%)}.el-color-hue-slider.is-vertical .el-color-hue-slider__thumb{left:0;top:0;width:100%;height:4px}.el-color-svpanel{position:relative;width:280px;height:180px}.el-color-svpanel__black,.el-color-svpanel__white{position:absolute;top:0;left:0;right:0;bottom:0}.el-color-svpanel__white{background:-webkit-gradient(linear,left top,right top,from(#fff),to(rgba(255,255,255,0)));background:linear-gradient(to right,#fff,rgba(255,255,255,0))}.el-color-svpanel__black{background:-webkit-gradient(linear,left bottom,left top,from(#000),to(rgba(0,0,0,0)));background:linear-gradient(to top,#000,rgba(0,0,0,0))}.el-color-svpanel__cursor{position:absolute}.el-color-svpanel__cursor>div{cursor:head;width:4px;height:4px;-webkit-box-shadow:0 0 0 1.5px #fff,inset 0 0 1px 1px rgba(0,0,0,.3),0 0 1px 2px rgba(0,0,0,.4);box-shadow:0 0 0 1.5px #fff,inset 0 0 1px 1px rgba(0,0,0,.3),0 0 1px 2px rgba(0,0,0,.4);border-radius:50%;-webkit-transform:translate(-2px,-2px);transform:translate(-2px,-2px)}.el-color-alpha-slider{position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;width:280px;height:12px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.el-color-alpha-slider__bar{position:relative;background:-webkit-gradient(linear,left top,right top,from(rgba(255,255,255,0)),to(white));background:linear-gradient(to right,rgba(255,255,255,0) 0,#fff 100%);height:100%}.el-color-alpha-slider__thumb{position:absolute;cursor:pointer;-webkit-box-sizing:border-box;box-sizing:border-box;left:0;top:0;width:4px;height:100%;border-radius:1px;background:#fff;border:1px solid #f0f0f0;-webkit-box-shadow:0 0 2px rgba(0,0,0,.6);box-shadow:0 0 2px rgba(0,0,0,.6);z-index:1}.el-color-alpha-slider.is-vertical{width:20px;height:180px}.el-color-alpha-slider.is-vertical .el-color-alpha-slider__bar{background:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,0)),to(white));background:linear-gradient(to bottom,rgba(255,255,255,0) 0,#fff 100%)}.el-color-alpha-slider.is-vertical .el-color-alpha-slider__thumb{left:0;top:0;width:100%;height:4px}.el-color-dropdown{width:300px}.el-color-dropdown__main-wrapper{margin-bottom:6px}.el-color-dropdown__main-wrapper::after{content:"";display:table;clear:both}.el-color-dropdown__btns{margin-top:6px;text-align:right}.el-color-dropdown__value{float:left;line-height:26px;font-size:12px;color:#000;width:160px}.el-color-dropdown__btn{border:1px solid #dcdcdc;color:#333;line-height:24px;border-radius:2px;padding:0 20px;cursor:pointer;background-color:transparent;outline:0;font-size:12px}.el-color-dropdown__btn[disabled]{color:#ccc;cursor:not-allowed}.el-color-dropdown__btn:hover{color:#00D1B2;border-color:#00D1B2}.el-color-dropdown__link-btn{cursor:pointer;color:#00D1B2;text-decoration:none;padding:15px;font-size:12px}.el-color-dropdown__link-btn:hover{color:tint(primary,20%)}.el-color-picker{display:inline-block;position:relative;line-height:normal;height:40px}.el-color-picker.is-disabled .el-color-picker__trigger{cursor:not-allowed}.el-color-picker--medium{height:36px}.el-color-picker--medium .el-color-picker__trigger{height:36px;width:36px}.el-color-picker--medium .el-color-picker__mask{height:34px;width:34px}.el-color-picker--small{height:32px}.el-color-picker--small .el-color-picker__trigger{height:32px;width:32px}.el-color-picker--small .el-color-picker__mask{height:30px;width:30px}.el-color-picker--small .el-color-picker__empty,.el-color-picker--small .el-color-picker__icon{-webkit-transform:translate3d(-50%,-50%,0) scale(.8);transform:translate3d(-50%,-50%,0) scale(.8)}.el-color-picker--mini{height:28px}.el-color-picker--mini .el-color-picker__trigger{height:28px;width:28px}.el-color-picker--mini .el-color-picker__mask{height:26px;width:26px}.el-color-picker--mini .el-color-picker__empty,.el-color-picker--mini .el-color-picker__icon{-webkit-transform:translate3d(-50%,-50%,0) scale(.8);transform:translate3d(-50%,-50%,0) scale(.8)}.el-color-picker__mask{height:38px;width:38px;border-radius:4px;position:absolute;top:1px;left:1px;z-index:1;cursor:not-allowed;background-color:rgba(255,255,255,.7)}.el-color-picker__trigger{display:inline-block;-webkit-box-sizing:border-box;box-sizing:border-box;height:40px;width:40px;padding:4px;border:1px solid #e6e6e6;border-radius:4px;font-size:0;position:relative;cursor:pointer}.el-color-picker__color{position:relative;display:block;-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid #999;border-radius:2px;width:100%;height:100%;text-align:center}.el-color-picker__color.is-alpha{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.el-color-picker__color-inner{position:absolute;left:0;top:0;right:0;bottom:0}.el-color-picker__empty,.el-color-picker__icon{top:50%;left:50%;font-size:12px;position:absolute}.el-color-picker__empty{color:#999;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.el-color-picker__icon{display:inline-block;width:100%;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0);color:#FFF;text-align:center}.el-color-picker__panel{position:absolute;z-index:10;padding:6px;-webkit-box-sizing:content-box;box-sizing:content-box;background-color:#FFF;border:1px solid #EBEEF5;border-radius:4px;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-textarea{position:relative;display:inline-block;width:100%;vertical-align:bottom;font-size:14px}.el-textarea__inner{display:block;resize:vertical;padding:5px 15px;line-height:1.5;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;font-size:inherit;color:#606266;background-color:#FFF;background-image:none;border:1px solid #DCDFE6;border-radius:4px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.el-textarea__inner::-webkit-input-placeholder{color:#C0C4CC}.el-textarea__inner:-ms-input-placeholder{color:#C0C4CC}.el-textarea__inner::-ms-input-placeholder{color:#C0C4CC}.el-textarea__inner::placeholder{color:#C0C4CC}.el-textarea__inner:hover{border-color:#C0C4CC}.el-textarea__inner:focus{outline:0;border-color:#00D1B2}.el-textarea .el-input__count{color:#909399;background:#FFF;position:absolute;font-size:12px;bottom:5px;right:10px}.el-textarea.is-disabled .el-textarea__inner{background-color:#F5F7FA;border-color:#E4E7ED;color:#C0C4CC;cursor:not-allowed}.el-textarea.is-disabled .el-textarea__inner::-webkit-input-placeholder{color:#C0C4CC}.el-textarea.is-disabled .el-textarea__inner:-ms-input-placeholder{color:#C0C4CC}.el-textarea.is-disabled .el-textarea__inner::-ms-input-placeholder{color:#C0C4CC}.el-textarea.is-disabled .el-textarea__inner::placeholder{color:#C0C4CC}.el-textarea.is-exceed .el-textarea__inner{border-color:#F56C6C}.el-textarea.is-exceed .el-input__count{color:#F56C6C}.el-input{position:relative;font-size:14px;display:inline-block;width:100%}.el-input::-webkit-scrollbar{z-index:11;width:6px}.el-input::-webkit-scrollbar:horizontal{height:6px}.el-input::-webkit-scrollbar-thumb{border-radius:5px;width:6px;background:#b4bccc}.el-input::-webkit-scrollbar-corner{background:#fff}.el-input::-webkit-scrollbar-track{background:#fff}.el-input::-webkit-scrollbar-track-piece{background:#fff;width:6px}.el-input .el-input__clear{color:#C0C4CC;font-size:14px;cursor:pointer;-webkit-transition:color .2s cubic-bezier(.645,.045,.355,1);transition:color .2s cubic-bezier(.645,.045,.355,1)}.el-input .el-input__clear:hover{color:#909399}.el-input .el-input__count{height:100%;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;color:#909399;font-size:12px}.el-input .el-input__count .el-input__count-inner{background:#FFF;line-height:initial;display:inline-block;padding:0 5px}.el-input__inner{-webkit-appearance:none;background-color:#FFF;background-image:none;border-radius:4px;border:1px solid #DCDFE6;-webkit-box-sizing:border-box;box-sizing:border-box;color:#606266;display:inline-block;font-size:inherit;height:40px;line-height:40px;outline:0;padding:0 15px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}.el-button,.el-transfer-panel{-webkit-box-sizing:border-box}.el-input__prefix,.el-input__suffix{position:absolute;top:0;-webkit-transition:all .3s;height:100%;color:#C0C4CC;text-align:center}.el-input__inner::-webkit-input-placeholder{color:#C0C4CC}.el-input__inner:-ms-input-placeholder{color:#C0C4CC}.el-input__inner::-ms-input-placeholder{color:#C0C4CC}.el-input__inner::placeholder{color:#C0C4CC}.el-input__inner:hover{border-color:#C0C4CC}.el-input.is-active .el-input__inner,.el-input__inner:focus{border-color:#00D1B2;outline:0}.el-input__suffix{right:5px;transition:all .3s}.el-input__suffix-inner{pointer-events:all}.el-input__prefix{left:5px;transition:all .3s}.el-input__icon{height:100%;width:25px;text-align:center;-webkit-transition:all .3s;transition:all .3s;line-height:40px}.el-input__icon:after{content:'';height:100%;width:0;display:inline-block;vertical-align:middle}.el-input__validateIcon{pointer-events:none}.el-input.is-disabled .el-input__inner{background-color:#F5F7FA;border-color:#E4E7ED;color:#C0C4CC;cursor:not-allowed}.el-input.is-disabled .el-input__inner::-webkit-input-placeholder{color:#C0C4CC}.el-input.is-disabled .el-input__inner:-ms-input-placeholder{color:#C0C4CC}.el-input.is-disabled .el-input__inner::-ms-input-placeholder{color:#C0C4CC}.el-input.is-disabled .el-input__inner::placeholder{color:#C0C4CC}.el-input.is-disabled .el-input__icon{cursor:not-allowed}.el-input.is-exceed .el-input__inner{border-color:#F56C6C}.el-input.is-exceed .el-input__suffix .el-input__count{color:#F56C6C}.el-input--suffix .el-input__inner{padding-right:30px}.el-input--prefix .el-input__inner{padding-left:30px}.el-input--medium{font-size:14px}.el-input--medium .el-input__inner{height:36px;line-height:36px}.el-input--medium .el-input__icon{line-height:36px}.el-input--small{font-size:13px}.el-input--small .el-input__inner{height:32px;line-height:32px}.el-input--small .el-input__icon{line-height:32px}.el-input--mini{font-size:12px}.el-input--mini .el-input__inner{height:28px;line-height:28px}.el-input--mini .el-input__icon{line-height:28px}.el-input-group{line-height:normal;display:inline-table;width:100%;border-collapse:separate;border-spacing:0}.el-input-group>.el-input__inner{vertical-align:middle;display:table-cell}.el-input-group__append,.el-input-group__prepend{background-color:#F5F7FA;color:#909399;vertical-align:middle;display:table-cell;position:relative;border:1px solid #DCDFE6;border-radius:4px;padding:0 20px;width:1px;white-space:nowrap}.el-input-group--prepend .el-input__inner,.el-input-group__append{border-top-left-radius:0;border-bottom-left-radius:0}.el-input-group--append .el-input__inner,.el-input-group__prepend{border-top-right-radius:0;border-bottom-right-radius:0}.el-input-group__append:focus,.el-input-group__prepend:focus{outline:0}.el-input-group__append .el-button,.el-input-group__append .el-select,.el-input-group__prepend .el-button,.el-input-group__prepend .el-select{display:inline-block;margin:-10px -20px}.el-input-group__append button.el-button,.el-input-group__append div.el-select .el-input__inner,.el-input-group__append div.el-select:hover .el-input__inner,.el-input-group__prepend button.el-button,.el-input-group__prepend div.el-select .el-input__inner,.el-input-group__prepend div.el-select:hover .el-input__inner{border-color:transparent;background-color:transparent;color:inherit;border-top:0;border-bottom:0}.el-input-group__append .el-button,.el-input-group__append .el-input,.el-input-group__prepend .el-button,.el-input-group__prepend .el-input{font-size:inherit}.el-input-group__prepend{border-right:0}.el-input-group__append{border-left:0}.el-input-group--append .el-select .el-input.is-focus .el-input__inner,.el-input-group--prepend .el-select .el-input.is-focus .el-input__inner{border-color:transparent}.el-input__inner::-ms-clear{display:none;width:0;height:0}.el-button{display:inline-block;line-height:1;white-space:nowrap;cursor:pointer;background:#FFF;border:1px solid #DCDFE6;color:#606266;-webkit-appearance:none;text-align:center;box-sizing:border-box;outline:0;margin:0;-webkit-transition:.1s;transition:.1s;font-weight:500;padding:12px 20px;font-size:14px;border-radius:4px}.el-button+.el-button{margin-left:10px}.el-button:focus,.el-button:hover{color:#00D1B2;border-color:rgb(179, 241, 232);background-color:rgb(230, 250, 247)}.el-button:active{color:rgb(0, 188, 160);border-color:rgb(0, 188, 160);outline:0}.el-button::-moz-focus-inner{border:0}.el-button [class*=el-icon-]+span{margin-left:5px}.el-button.is-plain:focus,.el-button.is-plain:hover{background:#FFF;border-color:#00D1B2;color:#00D1B2}.el-button.is-active,.el-button.is-plain:active{color:rgb(0, 188, 160);border-color:rgb(0, 188, 160)}.el-button.is-plain:active{background:#FFF;outline:0}.el-button.is-disabled,.el-button.is-disabled:focus,.el-button.is-disabled:hover{color:#C0C4CC;cursor:not-allowed;background-image:none;background-color:#FFF;border-color:#EBEEF5}.el-link,.el-transfer-panel__filter .el-icon-circle-close{cursor:pointer}.el-button.is-disabled.el-button--text{background-color:transparent}.el-button.is-disabled.is-plain,.el-button.is-disabled.is-plain:focus,.el-button.is-disabled.is-plain:hover{background-color:#FFF;border-color:#EBEEF5;color:#C0C4CC}.el-button.is-loading{position:relative;pointer-events:none}.el-button.is-loading:before{pointer-events:none;content:'';position:absolute;left:-1px;top:-1px;right:-1px;bottom:-1px;border-radius:inherit;background-color:rgba(255,255,255,.35)}.el-button.is-round{border-radius:20px;padding:12px 23px}.el-button.is-circle{border-radius:50%;padding:12px}.el-button--primary{color:#FFF;background-color:#00D1B2;border-color:#00D1B2}.el-button--primary:focus,.el-button--primary:hover{background:rgb(51, 218, 193);border-color:rgb(51, 218, 193);color:#FFF}.el-button--primary.is-active,.el-button--primary:active{background:rgb(0, 188, 160);border-color:rgb(0, 188, 160);color:#FFF}.el-button--primary:active{outline:0}.el-button--primary.is-disabled,.el-button--primary.is-disabled:active,.el-button--primary.is-disabled:focus,.el-button--primary.is-disabled:hover{color:#FFF;background-color:rgb(128, 232, 217);border-color:rgb(128, 232, 217)}.el-button--primary.is-plain{color:#00D1B2;background:rgb(230, 250, 247);border-color:rgb(153, 237, 224)}.el-button--primary.is-plain:focus,.el-button--primary.is-plain:hover{background:#00D1B2;border-color:#00D1B2;color:#FFF}.el-button--primary.is-plain:active{background:rgb(0, 188, 160);border-color:rgb(0, 188, 160);color:#FFF;outline:0}.el-button--primary.is-plain.is-disabled,.el-button--primary.is-plain.is-disabled:active,.el-button--primary.is-plain.is-disabled:focus,.el-button--primary.is-plain.is-disabled:hover{color:rgb(102, 227, 209);background-color:rgb(230, 250, 247);border-color:rgb(204, 246, 240)}.el-button--success{color:#FFF;background-color:#67C23A;border-color:#67C23A}.el-button--success:focus,.el-button--success:hover{background:#85ce61;border-color:#85ce61;color:#FFF}.el-button--success.is-active,.el-button--success:active{background:#5daf34;border-color:#5daf34;color:#FFF}.el-button--success:active{outline:0}.el-button--success.is-disabled,.el-button--success.is-disabled:active,.el-button--success.is-disabled:focus,.el-button--success.is-disabled:hover{color:#FFF;background-color:#b3e19d;border-color:#b3e19d}.el-button--success.is-plain{color:#67C23A;background:#f0f9eb;border-color:#c2e7b0}.el-button--success.is-plain:focus,.el-button--success.is-plain:hover{background:#67C23A;border-color:#67C23A;color:#FFF}.el-button--success.is-plain:active{background:#5daf34;border-color:#5daf34;color:#FFF;outline:0}.el-button--success.is-plain.is-disabled,.el-button--success.is-plain.is-disabled:active,.el-button--success.is-plain.is-disabled:focus,.el-button--success.is-plain.is-disabled:hover{color:#a4da89;background-color:#f0f9eb;border-color:#e1f3d8}.el-button--warning{color:#FFF;background-color:#E6A23C;border-color:#E6A23C}.el-button--warning:focus,.el-button--warning:hover{background:#ebb563;border-color:#ebb563;color:#FFF}.el-button--warning.is-active,.el-button--warning:active{background:#cf9236;border-color:#cf9236;color:#FFF}.el-button--warning:active{outline:0}.el-button--warning.is-disabled,.el-button--warning.is-disabled:active,.el-button--warning.is-disabled:focus,.el-button--warning.is-disabled:hover{color:#FFF;background-color:#f3d19e;border-color:#f3d19e}.el-button--warning.is-plain{color:#E6A23C;background:#fdf6ec;border-color:#f5dab1}.el-button--warning.is-plain:focus,.el-button--warning.is-plain:hover{background:#E6A23C;border-color:#E6A23C;color:#FFF}.el-button--warning.is-plain:active{background:#cf9236;border-color:#cf9236;color:#FFF;outline:0}.el-button--warning.is-plain.is-disabled,.el-button--warning.is-plain.is-disabled:active,.el-button--warning.is-plain.is-disabled:focus,.el-button--warning.is-plain.is-disabled:hover{color:#f0c78a;background-color:#fdf6ec;border-color:#faecd8}.el-button--danger{color:#FFF;background-color:#F56C6C;border-color:#F56C6C}.el-button--danger:focus,.el-button--danger:hover{background:#f78989;border-color:#f78989;color:#FFF}.el-button--danger.is-active,.el-button--danger:active{background:#dd6161;border-color:#dd6161;color:#FFF}.el-button--danger:active{outline:0}.el-button--danger.is-disabled,.el-button--danger.is-disabled:active,.el-button--danger.is-disabled:focus,.el-button--danger.is-disabled:hover{color:#FFF;background-color:#fab6b6;border-color:#fab6b6}.el-button--danger.is-plain{color:#F56C6C;background:#fef0f0;border-color:#fbc4c4}.el-button--danger.is-plain:focus,.el-button--danger.is-plain:hover{background:#F56C6C;border-color:#F56C6C;color:#FFF}.el-button--danger.is-plain:active{background:#dd6161;border-color:#dd6161;color:#FFF;outline:0}.el-button--danger.is-plain.is-disabled,.el-button--danger.is-plain.is-disabled:active,.el-button--danger.is-plain.is-disabled:focus,.el-button--danger.is-plain.is-disabled:hover{color:#f9a7a7;background-color:#fef0f0;border-color:#fde2e2}.el-button--info{color:#FFF;background-color:#909399;border-color:#909399}.el-button--info:focus,.el-button--info:hover{background:#a6a9ad;border-color:#a6a9ad;color:#FFF}.el-button--info.is-active,.el-button--info:active{background:#82848a;border-color:#82848a;color:#FFF}.el-button--info:active{outline:0}.el-button--info.is-disabled,.el-button--info.is-disabled:active,.el-button--info.is-disabled:focus,.el-button--info.is-disabled:hover{color:#FFF;background-color:#c8c9cc;border-color:#c8c9cc}.el-button--info.is-plain{color:#909399;background:#f4f4f5;border-color:#d3d4d6}.el-button--info.is-plain:focus,.el-button--info.is-plain:hover{background:#909399;border-color:#909399;color:#FFF}.el-button--info.is-plain:active{background:#82848a;border-color:#82848a;color:#FFF;outline:0}.el-button--info.is-plain.is-disabled,.el-button--info.is-plain.is-disabled:active,.el-button--info.is-plain.is-disabled:focus,.el-button--info.is-plain.is-disabled:hover{color:#bcbec2;background-color:#f4f4f5;border-color:#e9e9eb}.el-button--text,.el-button--text.is-disabled,.el-button--text.is-disabled:focus,.el-button--text.is-disabled:hover,.el-button--text:active{border-color:transparent}.el-button--medium{padding:10px 20px;font-size:14px;border-radius:4px}.el-button--mini,.el-button--small{font-size:12px;border-radius:3px}.el-button--medium.is-round{padding:10px 20px}.el-button--medium.is-circle{padding:10px}.el-button--small,.el-button--small.is-round{padding:9px 15px}.el-button--small.is-circle{padding:9px}.el-button--mini,.el-button--mini.is-round{padding:7px 15px}.el-button--mini.is-circle{padding:7px}.el-button--text{color:#00D1B2;background:0 0;padding-left:0;padding-right:0}.el-button--text:focus,.el-button--text:hover{color:rgb(51, 218, 193);border-color:transparent;background-color:transparent}.el-button--text:active{color:rgb(0, 188, 160);background-color:transparent}.el-button-group{display:inline-block;vertical-align:middle}.el-button-group::after,.el-button-group::before{display:table;content:""}.el-button-group::after{clear:both}.el-button-group>.el-button{float:left;position:relative}.el-button-group>.el-button+.el-button{margin-left:0}.el-button-group>.el-button.is-disabled{z-index:1}.el-button-group>.el-button:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.el-button-group>.el-button:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.el-button-group>.el-button:first-child:last-child{border-radius:4px}.el-button-group>.el-button:first-child:last-child.is-round{border-radius:20px}.el-button-group>.el-button:first-child:last-child.is-circle{border-radius:50%}.el-button-group>.el-button:not(:first-child):not(:last-child){border-radius:0}.el-button-group>.el-button:not(:last-child){margin-right:-1px}.el-button-group>.el-button.is-active,.el-button-group>.el-button:active,.el-button-group>.el-button:focus,.el-button-group>.el-button:hover{z-index:1}.el-button-group>.el-dropdown>.el-button{border-top-left-radius:0;border-bottom-left-radius:0;border-left-color:rgba(255,255,255,.5)}.el-button-group .el-button--primary:first-child{border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--primary:last-child{border-left-color:rgba(255,255,255,.5)}.el-button-group .el-button--primary:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--success:first-child{border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--success:last-child{border-left-color:rgba(255,255,255,.5)}.el-button-group .el-button--success:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--warning:first-child{border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--warning:last-child{border-left-color:rgba(255,255,255,.5)}.el-button-group .el-button--warning:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--danger:first-child{border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--danger:last-child{border-left-color:rgba(255,255,255,.5)}.el-button-group .el-button--danger:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--info:first-child{border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--info:last-child{border-left-color:rgba(255,255,255,.5)}.el-button-group .el-button--info:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.el-transfer{font-size:14px}.el-transfer__buttons{display:inline-block;vertical-align:middle;padding:0 30px}.el-transfer__button{display:block;margin:0 auto;padding:10px;border-radius:50%;color:#FFF;background-color:#00D1B2;font-size:0}.el-transfer-panel__item+.el-transfer-panel__item,.el-transfer__button [class*=el-icon-]+span{margin-left:0}.el-transfer__button.is-with-texts{border-radius:4px}.el-transfer__button.is-disabled,.el-transfer__button.is-disabled:hover{border:1px solid #DCDFE6;background-color:#F5F7FA;color:#C0C4CC}.el-transfer__button:first-child{margin-bottom:10px}.el-transfer__button:nth-child(2){margin:0}.el-transfer__button i,.el-transfer__button span{font-size:14px}.el-transfer-panel{border:1px solid #EBEEF5;border-radius:4px;overflow:hidden;background:#FFF;display:inline-block;vertical-align:middle;width:200px;max-height:100%;box-sizing:border-box;position:relative}.el-transfer-panel__body{height:246px}.el-transfer-panel__body.is-with-footer{padding-bottom:40px}.el-transfer-panel__list{margin:0;padding:6px 0;list-style:none;height:246px;overflow:auto;-webkit-box-sizing:border-box;box-sizing:border-box}.el-transfer-panel__list.is-filterable{height:194px;padding-top:0}.el-transfer-panel__item{height:30px;line-height:30px;padding-left:15px;display:block}.el-transfer-panel__item.el-checkbox{color:#606266}.el-transfer-panel__item:hover{color:#00D1B2}.el-transfer-panel__item.el-checkbox .el-checkbox__label{width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;-webkit-box-sizing:border-box;box-sizing:border-box;padding-left:24px;line-height:30px}.el-transfer-panel__item .el-checkbox__input{position:absolute;top:8px}.el-transfer-panel__filter{text-align:center;margin:15px;-webkit-box-sizing:border-box;box-sizing:border-box;display:block;width:auto}.el-transfer-panel__filter .el-input__inner{height:32px;width:100%;font-size:12px;display:inline-block;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:16px;padding-right:10px;padding-left:30px}.el-transfer-panel__filter .el-input__icon{margin-left:5px}.el-transfer-panel .el-transfer-panel__header{height:40px;line-height:40px;background:#F5F7FA;margin:0;padding-left:15px;border-bottom:1px solid #EBEEF5;-webkit-box-sizing:border-box;box-sizing:border-box;color:#000}.el-transfer-panel .el-transfer-panel__header .el-checkbox{display:block;line-height:40px}.el-transfer-panel .el-transfer-panel__header .el-checkbox .el-checkbox__label{font-size:16px;color:#303133;font-weight:400}.el-transfer-panel .el-transfer-panel__header .el-checkbox .el-checkbox__label span{position:absolute;right:15px;color:#909399;font-size:12px;font-weight:400}.el-divider__text,.el-link{font-weight:500;font-size:14px}.el-transfer-panel .el-transfer-panel__footer{height:40px;background:#FFF;margin:0;padding:0;border-top:1px solid #EBEEF5;position:absolute;bottom:0;left:0;width:100%;z-index:1}.el-transfer-panel .el-transfer-panel__footer::after{display:inline-block;content:"";height:100%;vertical-align:middle}.el-container,.el-timeline-item__node{display:-webkit-box;display:-ms-flexbox}.el-transfer-panel .el-transfer-panel__footer .el-checkbox{padding-left:20px;color:#606266}.el-transfer-panel .el-transfer-panel__empty{margin:0;height:30px;line-height:30px;padding:6px 15px 0;color:#909399;text-align:center}.el-transfer-panel .el-checkbox__label{padding-left:8px}.el-transfer-panel .el-checkbox__inner{height:14px;width:14px;border-radius:3px}.el-transfer-panel .el-checkbox__inner::after{height:6px;width:3px;left:4px}.el-container{display:flex;-webkit-box-orient:horizontal;-ms-flex-direction:row;flex-direction:row;-webkit-box-flex:1;-ms-flex:1;flex:1;-ms-flex-preferred-size:auto;flex-basis:auto;-webkit-box-sizing:border-box;box-sizing:border-box;min-width:0}.el-aside,.el-header{-webkit-box-sizing:border-box}.el-container.is-vertical{-webkit-box-orient:vertical;-ms-flex-direction:column;flex-direction:column}.el-header{padding:0 20px;box-sizing:border-box;-ms-flex-negative:0;flex-shrink:0}.el-aside{overflow:auto;box-sizing:border-box;-ms-flex-negative:0;flex-shrink:0}.el-footer,.el-main{-webkit-box-sizing:border-box}.el-main{display:block;-webkit-box-flex:1;-ms-flex:1;flex:1;-ms-flex-preferred-size:auto;flex-basis:auto;overflow:auto;box-sizing:border-box;padding:20px}.el-footer{padding:0 20px;box-sizing:border-box;-ms-flex-negative:0;flex-shrink:0}.el-timeline{margin:0;font-size:14px;list-style:none}.el-timeline .el-timeline-item:last-child .el-timeline-item__tail{display:none}.el-timeline-item{position:relative;padding-bottom:20px}.el-timeline-item__wrapper{position:relative;padding-left:28px;top:-3px}.el-timeline-item__tail{position:absolute;left:4px;height:100%;border-left:2px solid #E4E7ED}.el-timeline-item__icon{color:#FFF;font-size:13px}.el-timeline-item__node{position:absolute;background-color:#E4E7ED;border-radius:50%;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.el-image__error,.el-timeline-item__dot{display:-webkit-box;display:-ms-flexbox}.el-timeline-item__node--normal{left:-1px;width:12px;height:12px}.el-timeline-item__node--large{left:-2px;width:14px;height:14px}.el-timeline-item__node--primary{background-color:#00D1B2}.el-timeline-item__node--success{background-color:#67C23A}.el-timeline-item__node--warning{background-color:#E6A23C}.el-timeline-item__node--danger{background-color:#F56C6C}.el-timeline-item__node--info{background-color:#909399}.el-timeline-item__dot{position:absolute;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.el-timeline-item__content{color:#303133}.el-timeline-item__timestamp{color:#909399;line-height:1;font-size:13px}.el-timeline-item__timestamp.is-top{margin-bottom:8px;padding-top:4px}.el-timeline-item__timestamp.is-bottom{margin-top:8px}.el-link{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:horizontal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;vertical-align:middle;position:relative;text-decoration:none;outline:0;padding:0}.el-link.is-underline:hover:after{content:"";position:absolute;left:0;right:0;height:0;bottom:0;border-bottom:1px solid #00D1B2}.el-link.el-link--default:after,.el-link.el-link--primary.is-underline:hover:after,.el-link.el-link--primary:after{border-color:#00D1B2}.el-link.is-disabled{cursor:not-allowed}.el-link [class*=el-icon-]+span{margin-left:5px}.el-link.el-link--default{color:#606266}.el-link.el-link--default:hover{color:#00D1B2}.el-link.el-link--default.is-disabled{color:#C0C4CC}.el-link.el-link--primary{color:#00D1B2}.el-link.el-link--primary:hover{color:rgb(51, 218, 193)}.el-link.el-link--primary.is-disabled{color:rgb(128, 232, 217)}.el-link.el-link--danger.is-underline:hover:after,.el-link.el-link--danger:after{border-color:#F56C6C}.el-link.el-link--danger{color:#F56C6C}.el-link.el-link--danger:hover{color:#f78989}.el-link.el-link--danger.is-disabled{color:#fab6b6}.el-link.el-link--success.is-underline:hover:after,.el-link.el-link--success:after{border-color:#67C23A}.el-link.el-link--success{color:#67C23A}.el-link.el-link--success:hover{color:#85ce61}.el-link.el-link--success.is-disabled{color:#b3e19d}.el-link.el-link--warning.is-underline:hover:after,.el-link.el-link--warning:after{border-color:#E6A23C}.el-link.el-link--warning{color:#E6A23C}.el-link.el-link--warning:hover{color:#ebb563}.el-link.el-link--warning.is-disabled{color:#f3d19e}.el-link.el-link--info.is-underline:hover:after,.el-link.el-link--info:after{border-color:#909399}.el-link.el-link--info{color:#909399}.el-link.el-link--info:hover{color:#a6a9ad}.el-link.el-link--info.is-disabled{color:#c8c9cc}.el-divider{background-color:#DCDFE6;position:relative}.el-divider--horizontal{display:block;height:1px;width:100%;margin:24px 0}.el-divider--vertical{display:inline-block;width:1px;height:1em;margin:0 8px;vertical-align:middle;position:relative}.el-divider__text{position:absolute;background-color:#FFF;padding:0 20px;color:#303133}.el-image__error,.el-image__placeholder{background:#F5F7FA}.el-divider__text.is-left{left:20px;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.el-divider__text.is-center{left:50%;-webkit-transform:translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%)}.el-divider__text.is-right{right:20px;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.el-image__error,.el-image__inner,.el-image__placeholder{width:100%;height:100%}.el-image{position:relative;display:inline-block;overflow:hidden}.el-image__inner{vertical-align:top}.el-image__inner--center{position:relative;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);display:block}.el-image__error{display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;font-size:14px;color:#C0C4CC;vertical-align:middle}.el-image__preview{cursor:pointer}.el-image-viewer__wrapper{position:fixed;top:0;right:0;bottom:0;left:0}.el-image-viewer__btn{position:absolute;z-index:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;border-radius:50%;opacity:.8;cursor:pointer;-webkit-box-sizing:border-box;box-sizing:border-box;user-select:none}.el-image-viewer__close{top:40px;right:40px;width:40px;height:40px;font-size:40px}.el-image-viewer__canvas{width:100%;height:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.el-image-viewer__actions{left:50%;bottom:30px;-webkit-transform:translateX(-50%);transform:translateX(-50%);width:282px;height:44px;padding:0 23px;background-color:#606266;border-color:#fff;border-radius:22px}.el-image-viewer__actions__inner{width:100%;height:100%;text-align:justify;cursor:default;font-size:23px;color:#fff;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-pack:distribute;justify-content:space-around}.el-image-viewer__next,.el-image-viewer__prev{top:50%;width:44px;height:44px;font-size:24px;color:#fff;background-color:#606266;border-color:#fff}.el-image-viewer__prev{-webkit-transform:translateY(-50%);transform:translateY(-50%);left:40px}.el-image-viewer__next{-webkit-transform:translateY(-50%);transform:translateY(-50%);right:40px;text-indent:2px}.el-image-viewer__mask{position:absolute;width:100%;height:100%;top:0;left:0;opacity:.5;background:#000}.viewer-fade-enter-active{-webkit-animation:viewer-fade-in .3s;animation:viewer-fade-in .3s}.viewer-fade-leave-active{-webkit-animation:viewer-fade-out .3s;animation:viewer-fade-out .3s}@-webkit-keyframes viewer-fade-in{0%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@keyframes viewer-fade-in{0%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@-webkit-keyframes viewer-fade-out{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}100%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}}@keyframes viewer-fade-out{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}100%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}}.el-calendar{background-color:#fff}.el-calendar__header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;padding:12px 20px;border-bottom:1px solid #EBEEF5}.el-backtop,.el-page-header{display:-webkit-box;display:-ms-flexbox}.el-calendar__title{color:#000;-ms-flex-item-align:center;align-self:center}.el-calendar__body{padding:12px 20px 35px}.el-calendar-table{table-layout:fixed;width:100%}.el-calendar-table thead th{padding:12px 0;color:#606266;font-weight:400}.el-calendar-table:not(.is-range) td.next,.el-calendar-table:not(.is-range) td.prev{color:#C0C4CC}.el-backtop,.el-calendar-table td.is-today{color:#00D1B2}.el-calendar-table td{border-bottom:1px solid #EBEEF5;border-right:1px solid #EBEEF5;vertical-align:top;-webkit-transition:background-color .2s ease;transition:background-color .2s ease}.el-calendar-table td.is-selected{background-color:#F2F8FE}.el-calendar-table tr:first-child td{border-top:1px solid #EBEEF5}.el-calendar-table tr td:first-child{border-left:1px solid #EBEEF5}.el-calendar-table tr.el-calendar-table__row--hide-border td{border-top:none}.el-calendar-table .el-calendar-day{-webkit-box-sizing:border-box;box-sizing:border-box;padding:8px;height:85px}.el-calendar-table .el-calendar-day:hover{cursor:pointer;background-color:#F2F8FE}.el-backtop{position:fixed;background-color:#FFF;width:40px;height:40px;border-radius:50%;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;font-size:20px;-webkit-box-shadow:0 0 6px rgba(0,0,0,.12);box-shadow:0 0 6px rgba(0,0,0,.12);cursor:pointer;z-index:5}.el-backtop:hover{background-color:#F2F6FC}.el-page-header{display:flex;line-height:24px}.el-page-header__left{display:-webkit-box;display:-ms-flexbox;display:flex;cursor:pointer;margin-right:40px;position:relative}.el-page-header__left::after{content:"";position:absolute;width:1px;height:16px;right:-20px;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);background-color:#DCDFE6}.el-checkbox,.el-checkbox__input{display:inline-block;position:relative;white-space:nowrap}.el-page-header__left .el-icon-back{font-size:18px;margin-right:6px;-ms-flex-item-align:center;align-self:center}.el-page-header__title{font-size:14px;font-weight:500}.el-page-header__content{font-size:18px;color:#303133}.el-checkbox{color:#606266;font-weight:500;font-size:14px;cursor:pointer;user-select:none;margin-right:30px}.el-checkbox-button__inner,.el-radio{font-weight:500;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.el-checkbox.is-bordered{padding:9px 20px 9px 10px;border-radius:4px;border:1px solid #DCDFE6;-webkit-box-sizing:border-box;box-sizing:border-box;line-height:normal;height:40px}.el-checkbox.is-bordered.is-checked{border-color:#00D1B2}.el-checkbox.is-bordered.is-disabled{border-color:#EBEEF5;cursor:not-allowed}.el-checkbox.is-bordered+.el-checkbox.is-bordered{margin-left:10px}.el-checkbox.is-bordered.el-checkbox--medium{padding:7px 20px 7px 10px;border-radius:4px;height:36px}.el-checkbox.is-bordered.el-checkbox--medium .el-checkbox__label{line-height:17px;font-size:14px}.el-checkbox.is-bordered.el-checkbox--medium .el-checkbox__inner{height:14px;width:14px}.el-checkbox.is-bordered.el-checkbox--small{padding:5px 15px 5px 10px;border-radius:3px;height:32px}.el-checkbox.is-bordered.el-checkbox--small .el-checkbox__label{line-height:15px;font-size:12px}.el-checkbox.is-bordered.el-checkbox--small .el-checkbox__inner{height:12px;width:12px}.el-checkbox.is-bordered.el-checkbox--small .el-checkbox__inner::after{height:6px;width:2px}.el-checkbox.is-bordered.el-checkbox--mini{padding:3px 15px 3px 10px;border-radius:3px;height:28px}.el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__label{line-height:12px;font-size:12px}.el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__inner{height:12px;width:12px}.el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__inner::after{height:6px;width:2px}.el-checkbox__input{cursor:pointer;outline:0;line-height:1;vertical-align:middle}.el-checkbox__input.is-disabled .el-checkbox__inner{background-color:#edf2fc;border-color:#DCDFE6;cursor:not-allowed}.el-checkbox__input.is-disabled .el-checkbox__inner::after{cursor:not-allowed;border-color:#C0C4CC}.el-checkbox__input.is-disabled .el-checkbox__inner+.el-checkbox__label{cursor:not-allowed}.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner{background-color:#F2F6FC;border-color:#DCDFE6}.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner::after{border-color:#C0C4CC}.el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner{background-color:#F2F6FC;border-color:#DCDFE6}.el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner::before{background-color:#C0C4CC;border-color:#C0C4CC}.el-checkbox__input.is-checked .el-checkbox__inner,.el-checkbox__input.is-indeterminate .el-checkbox__inner{background-color:#00D1B2;border-color:#00D1B2}.el-checkbox__input.is-disabled+span.el-checkbox__label{color:#C0C4CC;cursor:not-allowed}.el-checkbox__input.is-checked .el-checkbox__inner::after{-webkit-transform:rotate(45deg) scaleY(1);transform:rotate(45deg) scaleY(1)}.el-checkbox__input.is-checked+.el-checkbox__label{color:#00D1B2}.el-checkbox__input.is-focus .el-checkbox__inner{border-color:#00D1B2}.el-checkbox__input.is-indeterminate .el-checkbox__inner::before{content:'';position:absolute;display:block;background-color:#FFF;height:2px;-webkit-transform:scale(.5);transform:scale(.5);left:0;right:0;top:5px}.el-checkbox__input.is-indeterminate .el-checkbox__inner::after{display:none}.el-checkbox__inner{display:inline-block;position:relative;border:1px solid #DCDFE6;border-radius:2px;-webkit-box-sizing:border-box;box-sizing:border-box;width:14px;height:14px;background-color:#FFF;z-index:1;-webkit-transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46);transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46)}.el-checkbox__inner:hover{border-color:#00D1B2}.el-checkbox__inner::after{-webkit-box-sizing:content-box;box-sizing:content-box;content:"";border:1px solid #FFF;border-left:0;border-top:0;height:7px;left:4px;position:absolute;top:1px;-webkit-transform:rotate(45deg) scaleY(0);transform:rotate(45deg) scaleY(0);width:3px;-webkit-transition:-webkit-transform .15s ease-in .05s;transition:-webkit-transform .15s ease-in .05s;transition:transform .15s ease-in .05s;transition:transform .15s ease-in .05s,-webkit-transform .15s ease-in .05s;-webkit-transform-origin:center;transform-origin:center}.el-checkbox__original{opacity:0;outline:0;position:absolute;margin:0;width:0;height:0;z-index:-1}.el-checkbox-button,.el-checkbox-button__inner{display:inline-block;position:relative}.el-checkbox__label{display:inline-block;padding-left:10px;line-height:19px;font-size:14px}.el-checkbox:last-of-type{margin-right:0}.el-checkbox-button__inner{line-height:1;white-space:nowrap;vertical-align:middle;cursor:pointer;background:#FFF;border:1px solid #DCDFE6;border-left:0;color:#606266;-webkit-appearance:none;text-align:center;-webkit-box-sizing:border-box;box-sizing:border-box;outline:0;margin:0;-webkit-transition:all .3s cubic-bezier(.645,.045,.355,1);transition:all .3s cubic-bezier(.645,.045,.355,1);padding:12px 20px;font-size:14px;border-radius:0}.el-checkbox-button__inner.is-round{padding:12px 20px}.el-checkbox-button__inner:hover{color:#00D1B2}.el-checkbox-button__inner [class*=el-icon-]{line-height:.9}.el-radio,.el-radio__input{line-height:1;outline:0;white-space:nowrap}.el-checkbox-button__inner [class*=el-icon-]+span{margin-left:5px}.el-checkbox-button__original{opacity:0;outline:0;position:absolute;margin:0;z-index:-1}.el-radio,.el-radio__inner,.el-radio__input{position:relative;display:inline-block}.el-checkbox-button.is-checked .el-checkbox-button__inner{color:#FFF;background-color:#00D1B2;border-color:#00D1B2;-webkit-box-shadow:-1px 0 0 0 rgb(102, 227, 209);box-shadow:-1px 0 0 0 rgb(102, 227, 209)}.el-checkbox-button.is-checked:first-child .el-checkbox-button__inner{border-left-color:#00D1B2}.el-checkbox-button.is-disabled .el-checkbox-button__inner{color:#C0C4CC;cursor:not-allowed;background-image:none;background-color:#FFF;border-color:#EBEEF5;-webkit-box-shadow:none;box-shadow:none}.el-checkbox-button.is-disabled:first-child .el-checkbox-button__inner{border-left-color:#EBEEF5}.el-checkbox-button:first-child .el-checkbox-button__inner{border-left:1px solid #DCDFE6;border-radius:4px 0 0 4px;-webkit-box-shadow:none!important;box-shadow:none!important}.el-checkbox-button.is-focus .el-checkbox-button__inner{border-color:#00D1B2}.el-checkbox-button:last-child .el-checkbox-button__inner{border-radius:0 4px 4px 0}.el-checkbox-button--medium .el-checkbox-button__inner{padding:10px 20px;font-size:14px;border-radius:0}.el-checkbox-button--medium .el-checkbox-button__inner.is-round{padding:10px 20px}.el-checkbox-button--small .el-checkbox-button__inner{padding:9px 15px;font-size:12px;border-radius:0}.el-checkbox-button--small .el-checkbox-button__inner.is-round{padding:9px 15px}.el-checkbox-button--mini .el-checkbox-button__inner{padding:7px 15px;font-size:12px;border-radius:0}.el-checkbox-button--mini .el-checkbox-button__inner.is-round{padding:7px 15px}.el-checkbox-group{font-size:0}.el-radio,.el-radio--medium.is-bordered .el-radio__label{font-size:14px}.el-radio{color:#606266;cursor:pointer;margin-right:30px}.el-cascader-node>.el-checkbox,.el-cascader-node>.el-radio,.el-radio:last-child{margin-right:0}.el-radio.is-bordered{padding:12px 20px 0 10px;border-radius:4px;border:1px solid #DCDFE6;-webkit-box-sizing:border-box;box-sizing:border-box;height:40px}.el-radio.is-bordered.is-checked{border-color:#00D1B2}.el-radio.is-bordered.is-disabled{cursor:not-allowed;border-color:#EBEEF5}.el-radio__input.is-disabled .el-radio__inner,.el-radio__input.is-disabled.is-checked .el-radio__inner{background-color:#F5F7FA;border-color:#E4E7ED}.el-radio.is-bordered+.el-radio.is-bordered{margin-left:10px}.el-radio--medium.is-bordered{padding:10px 20px 0 10px;border-radius:4px;height:36px}.el-radio--mini.is-bordered .el-radio__label,.el-radio--small.is-bordered .el-radio__label{font-size:12px}.el-radio--medium.is-bordered .el-radio__inner{height:14px;width:14px}.el-radio--small.is-bordered{padding:8px 15px 0 10px;border-radius:3px;height:32px}.el-radio--small.is-bordered .el-radio__inner{height:12px;width:12px}.el-radio--mini.is-bordered{padding:6px 15px 0 10px;border-radius:3px;height:28px}.el-radio--mini.is-bordered .el-radio__inner{height:12px;width:12px}.el-radio__input{cursor:pointer;vertical-align:middle}.el-radio__input.is-disabled .el-radio__inner{cursor:not-allowed}.el-radio__input.is-disabled .el-radio__inner::after{cursor:not-allowed;background-color:#F5F7FA}.el-radio__input.is-disabled .el-radio__inner+.el-radio__label{cursor:not-allowed}.el-radio__input.is-disabled.is-checked .el-radio__inner::after{background-color:#C0C4CC}.el-radio__input.is-disabled+span.el-radio__label{color:#C0C4CC;cursor:not-allowed}.el-radio__input.is-checked .el-radio__inner{border-color:#00D1B2;background:#00D1B2}.el-radio__input.is-checked .el-radio__inner::after{-webkit-transform:translate(-50%,-50%) scale(1);transform:translate(-50%,-50%) scale(1)}.el-radio__input.is-checked+.el-radio__label{color:#00D1B2}.el-radio__input.is-focus .el-radio__inner{border-color:#00D1B2}.el-radio__inner{border:1px solid #DCDFE6;border-radius:100%;width:14px;height:14px;background-color:#FFF;cursor:pointer;-webkit-box-sizing:border-box;box-sizing:border-box}.el-radio__inner:hover{border-color:#00D1B2}.el-radio__inner::after{width:4px;height:4px;border-radius:100%;background-color:#FFF;content:"";position:absolute;left:50%;top:50%;-webkit-transform:translate(-50%,-50%) scale(0);transform:translate(-50%,-50%) scale(0);-webkit-transition:-webkit-transform .15s ease-in;transition:-webkit-transform .15s ease-in;transition:transform .15s ease-in;transition:transform .15s ease-in,-webkit-transform .15s ease-in}.el-radio__original{opacity:0;outline:0;position:absolute;z-index:-1;top:0;left:0;right:0;bottom:0;margin:0}.el-radio:focus:not(.is-focus):not(:active):not(.is-disabled) .el-radio__inner{-webkit-box-shadow:0 0 2px 2px #00D1B2;box-shadow:0 0 2px 2px #00D1B2}.el-radio__label{font-size:14px;padding-left:10px}.el-scrollbar{overflow:hidden;position:relative}.el-scrollbar:active>.el-scrollbar__bar,.el-scrollbar:focus>.el-scrollbar__bar,.el-scrollbar:hover>.el-scrollbar__bar{opacity:1;-webkit-transition:opacity 340ms ease-out;transition:opacity 340ms ease-out}.el-scrollbar__wrap{overflow:scroll;height:100%}.el-scrollbar__wrap--hidden-default::-webkit-scrollbar{width:0;height:0}.el-scrollbar__thumb{position:relative;display:block;width:0;height:0;cursor:pointer;border-radius:inherit;background-color:rgba(144,147,153,.3);-webkit-transition:.3s background-color;transition:.3s background-color}.el-scrollbar__thumb:hover{background-color:rgba(144,147,153,.5)}.el-scrollbar__bar{position:absolute;right:2px;bottom:2px;z-index:1;border-radius:4px;opacity:0;-webkit-transition:opacity 120ms ease-out;transition:opacity 120ms ease-out}.el-scrollbar__bar.is-vertical{width:6px;top:2px}.el-scrollbar__bar.is-vertical>div{width:100%}.el-scrollbar__bar.is-horizontal{height:6px;left:2px}.el-scrollbar__bar.is-horizontal>div{height:100%}.el-cascader-panel{display:-webkit-box;display:-ms-flexbox;display:flex;border-radius:4px;font-size:14px}.el-cascader-node,.el-drawer{display:-webkit-box;display:-ms-flexbox}.el-cascader-panel.is-bordered{border:1px solid #E4E7ED;border-radius:4px}.el-cascader-menu{min-width:180px;-webkit-box-sizing:border-box;box-sizing:border-box;color:#606266;border-right:solid 1px #E4E7ED}.el-cascader-menu:last-child{border-right:none}.el-cascader-menu:last-child .el-cascader-node{padding-right:20px}.el-cascader-menu__wrap{height:204px}.el-cascader-menu__list{position:relative;min-height:100%;margin:0;padding:6px 0;list-style:none;-webkit-box-sizing:border-box;box-sizing:border-box}.el-avatar,.el-drawer{-webkit-box-sizing:border-box;overflow:hidden}.el-cascader-menu__hover-zone{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none}.el-cascader-menu__empty-text{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);text-align:center;color:#C0C4CC}.el-cascader-node{position:relative;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:0 30px 0 20px;height:34px;line-height:34px;outline:0}.el-cascader-node.is-selectable.in-active-path{color:#606266}.el-cascader-node.in-active-path,.el-cascader-node.is-active,.el-cascader-node.is-selectable.in-checked-path{color:#00D1B2;font-weight:700}.el-cascader-node:not(.is-disabled){cursor:pointer}.el-cascader-node:not(.is-disabled):focus,.el-cascader-node:not(.is-disabled):hover{background:#F5F7FA}.el-cascader-node.is-disabled{color:#C0C4CC;cursor:not-allowed}.el-cascader-node__prefix{position:absolute;left:10px}.el-cascader-node__postfix{position:absolute;right:10px}.el-cascader-node__label{-webkit-box-flex:1;-ms-flex:1;flex:1;padding:0 10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.el-cascader-node>.el-radio .el-radio__label{padding-left:0}.el-avatar{display:inline-block;box-sizing:border-box;text-align:center;color:#fff;background:#C0C4CC;width:40px;height:40px;line-height:40px;font-size:14px}.el-avatar>img{display:block;height:100%;vertical-align:middle}.el-avatar--circle{border-radius:50%}.el-avatar--square{border-radius:4px}.el-avatar--icon{font-size:18px}.el-avatar--large{width:40px;height:40px;line-height:40px}.el-avatar--medium{width:36px;height:36px;line-height:36px}.el-avatar--small{width:28px;height:28px;line-height:28px}.el-drawer.btt,.el-drawer.ttb,.el-drawer__container{left:0;right:0;width:100%}.el-drawer.ltr,.el-drawer.rtl,.el-drawer__container{top:0;bottom:0;height:100%}@-webkit-keyframes el-drawer-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes el-drawer-fade-in{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes rtl-drawer-in{0%{-webkit-transform:translate(100%,0);transform:translate(100%,0)}100%{-webkit-transform:translate(0,0);transform:translate(0,0)}}@keyframes rtl-drawer-in{0%{-webkit-transform:translate(100%,0);transform:translate(100%,0)}100%{-webkit-transform:translate(0,0);transform:translate(0,0)}}@-webkit-keyframes rtl-drawer-out{0%{-webkit-transform:translate(0,0);transform:translate(0,0)}100%{-webkit-transform:translate(100%,0);transform:translate(100%,0)}}@keyframes rtl-drawer-out{0%{-webkit-transform:translate(0,0);transform:translate(0,0)}100%{-webkit-transform:translate(100%,0);transform:translate(100%,0)}}@-webkit-keyframes ltr-drawer-in{0%{-webkit-transform:translate(-100%,0);transform:translate(-100%,0)}100%{-webkit-transform:translate(0,0);transform:translate(0,0)}}@keyframes ltr-drawer-in{0%{-webkit-transform:translate(-100%,0);transform:translate(-100%,0)}100%{-webkit-transform:translate(0,0);transform:translate(0,0)}}@-webkit-keyframes ltr-drawer-out{0%{-webkit-transform:translate(0,0);transform:translate(0,0)}100%{-webkit-transform:translate(-100%,0);transform:translate(-100%,0)}}@keyframes ltr-drawer-out{0%{-webkit-transform:translate(0,0);transform:translate(0,0)}100%{-webkit-transform:translate(-100%,0);transform:translate(-100%,0)}}@-webkit-keyframes ttb-drawer-in{0%{-webkit-transform:translate(0,-100%);transform:translate(0,-100%)}100%{-webkit-transform:translate(0,0);transform:translate(0,0)}}@keyframes ttb-drawer-in{0%{-webkit-transform:translate(0,-100%);transform:translate(0,-100%)}100%{-webkit-transform:translate(0,0);transform:translate(0,0)}}@-webkit-keyframes ttb-drawer-out{0%{-webkit-transform:translate(0,0);transform:translate(0,0)}100%{-webkit-transform:translate(0,-100%);transform:translate(0,-100%)}}@keyframes ttb-drawer-out{0%{-webkit-transform:translate(0,0);transform:translate(0,0)}100%{-webkit-transform:translate(0,-100%);transform:translate(0,-100%)}}@-webkit-keyframes btt-drawer-in{0%{-webkit-transform:translate(0,100%);transform:translate(0,100%)}100%{-webkit-transform:translate(0,0);transform:translate(0,0)}}@keyframes btt-drawer-in{0%{-webkit-transform:translate(0,100%);transform:translate(0,100%)}100%{-webkit-transform:translate(0,0);transform:translate(0,0)}}@-webkit-keyframes btt-drawer-out{0%{-webkit-transform:translate(0,0);transform:translate(0,0)}100%{-webkit-transform:translate(0,100%);transform:translate(0,100%)}}@keyframes btt-drawer-out{0%{-webkit-transform:translate(0,0);transform:translate(0,0)}100%{-webkit-transform:translate(0,100%);transform:translate(0,100%)}}.el-drawer{position:absolute;box-sizing:border-box;background-color:#FFF;display:flex;-webkit-box-orient:vertical;-ms-flex-direction:column;flex-direction:column;-webkit-box-shadow:0 8px 10px -5px rgba(0,0,0,.2),0 16px 24px 2px rgba(0,0,0,.14),0 6px 30px 5px rgba(0,0,0,.12);box-shadow:0 8px 10px -5px rgba(0,0,0,.2),0 16px 24px 2px rgba(0,0,0,.14),0 6px 30px 5px rgba(0,0,0,.12)}.el-drawer.rtl{-webkit-animation:rtl-drawer-out 225ms cubic-bezier(0,0,.2,1) 0s;animation:rtl-drawer-out 225ms cubic-bezier(0,0,.2,1) 0s;right:0}.el-drawer__open .el-drawer.rtl{-webkit-animation:rtl-drawer-in 225ms cubic-bezier(0,0,.2,1) 0s;animation:rtl-drawer-in 225ms cubic-bezier(0,0,.2,1) 0s}.el-drawer.ltr{-webkit-animation:ltr-drawer-out 225ms cubic-bezier(0,0,.2,1) 0s;animation:ltr-drawer-out 225ms cubic-bezier(0,0,.2,1) 0s;left:0}.el-drawer__open .el-drawer.ltr{-webkit-animation:ltr-drawer-in 225ms cubic-bezier(0,0,.2,1) 0s;animation:ltr-drawer-in 225ms cubic-bezier(0,0,.2,1) 0s}.el-drawer.ttb{-webkit-animation:ttb-drawer-out 225ms cubic-bezier(0,0,.2,1) 0s;animation:ttb-drawer-out 225ms cubic-bezier(0,0,.2,1) 0s;top:0}.el-drawer__open .el-drawer.ttb{-webkit-animation:ttb-drawer-in 225ms cubic-bezier(0,0,.2,1) 0s;animation:ttb-drawer-in 225ms cubic-bezier(0,0,.2,1) 0s}.el-drawer.btt{-webkit-animation:btt-drawer-out 225ms cubic-bezier(0,0,.2,1) 0s;animation:btt-drawer-out 225ms cubic-bezier(0,0,.2,1) 0s;bottom:0}.el-drawer__open .el-drawer.btt{-webkit-animation:btt-drawer-in 225ms cubic-bezier(0,0,.2,1) 0s;animation:btt-drawer-in 225ms cubic-bezier(0,0,.2,1) 0s}.el-drawer__header{-webkit-box-align:center;-ms-flex-align:center;align-items:center;color:#72767b;display:-webkit-box;display:-ms-flexbox;display:flex;margin-bottom:32px;padding:20px 20px 0}.el-drawer__header>:first-child{-webkit-box-flex:1;-ms-flex:1;flex:1}.el-drawer__title{margin:0;-webkit-box-flex:1;-ms-flex:1;flex:1;line-height:inherit;font-size:1rem}.el-drawer__close-btn{border:none;cursor:pointer;font-size:20px;color:inherit;background-color:transparent}.el-drawer__body{-webkit-box-flex:1;-ms-flex:1;flex:1}.el-drawer__body>*{-webkit-box-sizing:border-box;box-sizing:border-box}.el-drawer__container{position:relative}.el-drawer-fade-enter-active{-webkit-animation:el-drawer-fade-in 225ms cubic-bezier(0,0,.2,1) 0s;animation:el-drawer-fade-in 225ms cubic-bezier(0,0,.2,1) 0s}.el-drawer-fade-leave-active{animation:el-drawer-fade-in 225ms cubic-bezier(0,0,.2,1) 0s reverse} \ No newline at end of file diff --git a/nsi-collection-platform/src/assets/icon/iconfont.css b/nsi-collection-platform/src/assets/icon/iconfont.css new file mode 100644 index 0000000..4f83e98 --- /dev/null +++ b/nsi-collection-platform/src/assets/icon/iconfont.css @@ -0,0 +1,369 @@ +@font-face {font-family: "iconfont"; + src: url('iconfont.eot?t=1591583895128'); /* IE9 */ + src: url('iconfont.eot?t=1591583895128#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAADYQAAsAAAAAdSAAADW9AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCPEgqBwzyBmVMBNgIkA4JQC4EqAAQgBYRtB4sPG8JeJcptpwKcBwSR7FdAFKVhFaMo36R+9v+fE/yPQ+rHXgU2d0JEKlVjytpbUjJTUpcee7+0Y6P5aqZCP254tyZpFzvGQsqQon6xp0UcewMNidAQHAQ/i8HpUVbupMf3kDO0BCcEg0acv7Ohz/ZyxGMSbxkOhuKsFnjYIUnR9MO1zzc/k91MMtnNIWIBVWUVkaqsAqnKRlVVqRvidfPvvZc1SUiAAAlhrZAwBeGFhDAFEpIoIBBWGCuMLSQqRRAnWiU4iKNVoI79FZXgbCtWqnQbxfpba1ttOrVDc9lWifiPqnteMYus3ktEvlMhNEkz0CEJjRERY7R9dcU1ERkapZAZkkomZUI+rDJsG627Mt51UGcm/Si1PwkCLQeOp8L0zxugk1wBMYu82qslBcofsnPEDZTBdsK8AQLMzKMM7tMYIk/LAfP/ALivpp9VM9JC9YBmIy8AnYD9X3JkQ0+3ISAwfMTVZebafSVLpgVJpoQNAQJDePB37e1PizjAOKUJZZGf4A3O6WpbO0RIcwK2rdBXDshu/CdQ1C72DzlJhTFm9w4qb0rVsgVI6UKW7v8douZHTnl6yjn0qbvx9LsLgMTuEqSWIk+CoETx9COQF7gKf4QuUbxE6VNOAMMNoXQkHWMo3Xncuejcedy5+6J256Zz76Ir3RlLOZUC2Gw5eahlsmxofMMFsI7VaS3GtJxFvdL0EIlBVFRALEn8UsrPmPs+NIflOPWKFPfkidSbBwJ47UJAx/v179IWlh2IAPTklFja0jrwQBNxocwwZ3FOX2G5ws+Vd4Av8kdP/7AYD1TYImQVL/cuX3p58HeVuOnHFcOncDqAdC7AAEYBMJhHxkTlYasVHpXUmx5jrXAygO+cl9a13mpNXUtb/8jkplyhLiqra2pp6xtsuNF2drDDvd9i0qtn0LPzTP+s+5nx2bpn8pl+dueZ/+zrH+qfxz1/9iPux+dwdM4BxOrAT+0TFC6RNXVm1+4civfP6VDj/xvw7zPbscBjfX1j/tQtbR3bnje9eLn27Xvx43P6ufF7LT/YlvNmdbrEc4Knanblw78QPS0qLFk3ak2H3RRFalp6RmYW07xlZ9nKeGKHYU6jFl3aXOcI1apTr8GQYRv0P8DbdLcVrNqgYMy07RhqxrgJk6bc8tenX48aTUiFwaxMCQWl2TNUA8XzG++CANrANgRCGQRGJQTBMgSDfggWV0GI5xcJKIeQbzgKUANxQieEhWsgzhiG8M6UB9AL8cE6xBe1ED9sQIKwCwnGNCQcOxAR+iASHINE4gQkCqcg0TgDEoOzILE4BxKH8yDLcAEkHhdBEtAAWf7ClojnUxJwCQTFZRDZ7UdyvLApgApI3rNLDdRDCt75VAi0Q1ajC1KEAUgZeiA1uA5SiysgdRiENKIZ0oQWSAtaIW1og6zBBKQPk5BB7EGGTjUM7IOMohuyEwcgBzEFOYxGyPsYhyyiCvIKM/ALmkWUgTlEeswa6sZUIyNmCa3DzKJ3MXNoN2Ye7ccsoEXMDfQlZgx9hRlBXwOj8LseQ/AnbprQM6AD/kJPBuMhBA9h8BAWD+Hw0D74wm3UAW6KWb4rfKZ/GWNlWbTwmMWVyhmNDKlaIsPplDBVp1k4Yi6KYSmjzgbZpkTgfbbNMFbI3lsjwVvMCER9hR6o98YGhlf3vp0KaPlenrKixoT8tUpAKORMzbj9GJnV+2oGag4qc205NTPmxNlq4/zurRarqbXajj91pkajsV7Ys0ji7TXRj0iJBGlZFqpCqCU5t4ubP4fWVhXV9VrdkAoVJ4WmKyQRTctMcbVFHZldXSqlSCEnFHJXO0l0MXvnumubRVoUYynUNGE1qJok11ur/fRMRg2wZIfpKZgPGuLJHV1JWTiVgdWwmoaNJ1JD4zPOdXqv1anYOCri46Bjc8NmamapaSy0JhtdNdZe2NVGmiNZtiPSkZjL6Ny0zZE93zVE1hLnZs/BGKXdSWkIMUFsRpcSgsQsahOWRFXrGdEwNLDTuDigNx3T9itVJ1JtZrZiSSi3RHVVUGY7sN/IXN1ZrcoZgEgnw75BSzWJk0shfS3TJM8ykqt2vlFbD6yIhSk2Wl1RRl7PUssFO6vl+ph7lvdFQpiqLf2RIzXQxRo/Th9dlbwrqKTCkJfc7nsKL71yaZ4E+Hva8B1vtIIeEO4dPuxGk1wkJbTkJQrOT1v+DgFH0iedOs66cNeBaW47pFVoXtwKOD9ZtpzYWxeFKdjnPNfYT2963f5iJa3OETLkeHqZ6abbezenOi0Mn2CdP2SWAQHH3PL07gFb8pwMn9z63XxzH3JxKuer3aPLZX/3XdndtzOo3alh9pEILF9XDoQBMuhADTu1IONBLZTWsxHEkoAJ/obmKGCzuLMd50OSPw3/vjjAK5Qba4+ZS6t1he6F9+JnvcIfVHUgQ77c9387q9bGs6A2y4Akf6uarWqz0q42Ws12awoEQo4iwrLAXKpnxOoI8nD7QaKei9CT+gLOEVJqU21wQpqZywW3FV/7SSC7gAnaek0lO4JSKY4jlj6vYYrZobqxlILigQdYVGCmgvhAndIoIXG2Gc2Mh28cOiicUucmaquOY+JQiVpipNZSggfAOBKXpomEV9CXoXFU6S5CJRj2QTnClDLtDWLcMbYodZk/oDfAhN3HlM44pbRNR2pExU5KqDId0Zrvo/WbVoK6XQwmvCwUm3d1bl9UcJtksoA8BZAeRjFOSJQuurVRGqHNpONQabImQkd8/EByrmHd8bo8E1tXNEjkzeygLVpWx+xyhtSIjaCR88zmNdOupBrCtZump/7qDiRDD2LZxKl2o7DUMCgWl1/9dDpoq3A+iXJtp+lKgMn15W46jttwIhp2jMvL4VjLxLcYRaqTT3Y/SWH1sy89+KrAtS+gaCCPUSR7AKdgAcfWLqrnhso41ZhutmfE89393EyzSmBcmu+AVoZDipixSJdazf1kvDdUd5Bijnw8mbJDd7ocuDzTzk8jF2IJctO0rBtm0+fXsjlDwNoc3XpnaTkW/dwRyomGY8OlqUg3aax9Yzb+gGbOMA5zseVJ7rmmNro0dsy3IKceJdFlS+BT90YTpqpspHDzpJSpMasqW2sJKoWz0wTXb/XKJ2+kVmIWx/rh5N3YoG1E6o3Y6UsRp+neY9nKp8OtP+GOO+veGltCGO1/ka9/DcR7ny3e59XdlmhvjQ+6ZmdbQ3lm03ZFI6tuuYtxpw6QC8tnh3dDePxsDMlWy71Gi4aL+s9EHYNh2m6ZQXv6Xp+Z24xSS2NifPnz+cyJFZRC1DjPaGszyLcsX1MOuKuQONMa3l2q67UwQ0m73injS+joXNUL38IIokpWvU5VdgYlomrcGm4AWkMRudZG2uyrY4fCUqFEOQDQwxsoUYDEHb8lZM0ojBtjF25KotBa/Tjp0HZDmFY8xkjMPB+xnC1lWkMs1SgpQkaDA0V0hpD4vX7k1L7Pq/0d9yzgyLn334O5FYTz2SyplUwZQkpxIeGdd4FwOprje+/DUPRDZD7AEH4Hez7rVUbAu+8A6c2oJM9yIyjCGa8I85Ma3gdRYHuVV4MX4yDKm81XapjxfIpRt9sIZzRtV1463QryLwmUOQr+jAMflfgpvgy5xC8CD0YsALr3SPM0zVPQx7axZ3/KT4JcDGS5aW+avJV6U2sHW3xotSIF5UFuQLdtD+Zt3AiTXKxlqL6R3Q90ec/ONYSHvU5KERHKgd2FJZNN6DeEm3xFWVtPx2H0YQwRSLG2qrchowKbBxkS4BKdTLsARCNRGwi0HeZDUU21HWzaBxnexuUvqlrJLNfxwBWNnbqoo/mUXksMLrFMf0A5mqNvlRAbklhGIXzujE6SnwzRFn0k1B6L43bUb0SAhl4Ml4emTjBnyq+Ggi5ZKLfK5fHTMJ8UwJGhmO7fnAIyLI9S6Z+qwXJmYGcWIn10qeWb2MHdwM5JO4rmEB95pv9GzbhGP/z+lyGDF+RA/Vdvi5huv6aKZQxTX/AkUOvr600wq+kXG63E7EhVMdV6RaLy0zHT5DFEGBCZaizE2/PQqVEKGfdDspW/Ud8h011+eGdlaV9OH0ISdyKpzflcJbFpF6R4XuIuKq+ZtvuDZoce9/VqsVBBsxnULg2y4R0aG6UKDHvtbquVa0uQgt6CrHwl6ySYhpIY4Ksl6H5X101m9Wb87p6X4sggQdM1FdjN9jZAYOspwtK7zoAyPZ2uOd4dKe3u4HPheUI93ey+/FWbUsLthikcSSCdwbOX6IPPAprl8VEtdP8xmiFlYqaFQc7kzCqymR2tMBsiE6rviJ92P52theTcO2v/nXSlf+u5INZ8YxKufbBb5wJzfP0tz/Plh3ijHbVJvxztHiqMjYiQeQW24QRhqfolCXcSMCf7rQhQw41ShkXcYJLddpJBS26HSKNVzEMb3TgW+q8WpwoHJUrBaqlxqiWI6jONLUvrf3b9hzvDvluy2wIg+newUxDLMgkXzTs5RPfvwIvYn4VzWuhQ+4CnwdO7rTXuYGOElBZc62zLoSh4f0gJ4vrT2DWGsaatjrriOgKABZFyIRg5SvLUSuCJYosddAn9nW3nvfEvwwf8G8qVCuWMndf5IAs5Ibvd7bULxOiiMk+bnMdC3+RMm4iqNWUJ4hwh6b2xDIFAlXVEyPHNOICcq9267CBCAmlo95EUgIKEjNU2nnT7kXHwlHBjTBWVRi5U3xycDsYBJ0UsZtalgWkQA2pVhXreuQRS0R8bx1gZ+YFQ+yFxY4plekQr5ev8BLPStko56FAEpxwOvr4cINrvmF2g9cFsi9YlHeigeBTsO1Yt9dMnBNzoGfpb3gBFELJVu85/9lSBb+2PDCgE31NZFiqad32uOKgh/bMeAV0IDBtV3NvgQ/nQRyyJ3QYGJzVpjiH9MWouF7MMwz+Kme6ydMKb+NjPAoghd9ZSTEsBJGSCMyBMijM76Q2TwJC4ILn6/LUozIKPqChW57FerJdh6dWYY28JjbvA12AtqwOsLNUWrEqlIGS1Sp+TVSmcUR9SNcUu9T74d989r76DjxIyFcLU/gvAukojAMcsLRjDxPBNuNBoBakAwtkEmu1bRwIhjDsgGLhRBrT0jtnEhGzEZUgRfWDZs6xt8v2qN6+OhffWHVJLkaXoQ4nK2ERNjJ3KidTz8btheN+/CqyxIlbN+SRIW0tnpl1QkBEJlhIGGVkuj3F8lV5/GpygPeBNCuqTjGMJ0GttnNM/SxCkYeOpZ/B9JKenn0Qi9lz9PGuAvnB8FM74qRSTWWwO+xASOGEZjhFp/f7joWH0+b7NNbtD3walU8uMhp4vPw3opKVoNf9er0AYVZBC0pEpRH3eaD+Ul08DeANreWe0BjOgi3EfI1NI8FyF3E5zr0uqgngPuPwkFwVZ1dzDT0PYdGz/ww9SeHYMHdn0mZgdOQSGrvpfXa8hK2KtpXvvv/+lhh7RFmu+wyZUY/nJlGdrvd9BwPN1cx3f9d1W9vfidshg/Gt9PRyP4V8z1x/0bOX/qmwFbC1/qa0Eo07fqliDd5L9zrpwvbs93WuvDVZaVxVrst7NxdoFEQiYJOaS25LUgMhsIUfiYW0dvCMgKvSFkzF8S/LxOVMoVrHli7faXvAPLAyFXB0cQVFvfDQqH0T9TJ5MN+YqJqhtjNFSOIhgtGSYxVClMpe+KguEmzP8WpSzElUmb3Ir+8EUE66k6zS3xUKWnh4lNpRZPqtNIgRrrN1b8I9qABAuTnUTYukhzuBSA8XOZ02ooYZoGwMxxOeXNACyONzua8OoUwgc5Wib6rYx00MPPvCmjXhkHHud3c+c6Ol6mAsFDW/lICIHaHaJYtDdkVPjkfzWd2cdZxT5PRmmPSnyySMp+zffCVkvluxTeNLOeOGjac8HYqOtYt3MHw9XQ6YBCvoJOKQ5weXESWfF2HGgmjshhbx00fxPVGBrbGo71IrlhjerdtwK8qJjsYmlYPRvyJ+OE87kr2ibji+Hd02mJjgCqDDs2MIvexNsGg/Xv7KECRtYt6MbePCoa7o0+doC6TcAQCgcS0HsGWlkrbMH4AdRRZFdwfLBC+PunMLNNW5Fp38RUL2ebocEYOSKyHbKxyoRrGp6N9oBLiQERBLwwagFoyztTjJ4JQGWwA3CJMaIMoYzQhoh4Ak5BS/iTognUjAOipTaU5mlaGyrObMSXICCZDD0NDQbBKVgKXpJWTAzwy1HxkYnvWI/9aObvuxF1gNm1QTWmx3ceesb45LhfzVNdn3j5iu9I3zT6vw/KL2pLH1e0b9lD8q9nuVXPbtjc4aRTw5bYtigkpSk7ZyJuMzySJw3Ofjs1kq9k8Cc/fTxhCf/1NFHH763wkCFxsTxvEtYxbhxQMWhQ6o1R+Y1rM6aFEkhuZKE6TTNAJJZnGIJpudTTKBNlnU6gOVkqKjWzVpFIYdbZ7fJJa/LyFgl4RzsSnyyZsC1JIxAPQBcsnpxuWFn5FTuYuFL1jxVvqHn7xfrTLLOz5H2b20L4WZ3q+eGRc5x9UkGdKE6p8HIXTlJqCCcyhBs+mgsp0+++7FRIPgrUSQwgGXojf9ej/X/744aH9siQ4hUZDUwyZ/7CGHMZ+KT/pcQox9k5GjOgDQ6LzLAucQjfYtB4VbrRBNiLC6OR1h6TQClBnX/JBe3ML16VnXimN7DiPGNJoSOhIhopmJPicfBjbzGhRzlAmo68g/lTwLK7iWkkAl9x/6Q+f4vuDM5f26U/zQkLT/K5+VJ4dQHC6d2UlGPaeTz39arrB2pAgmspLGvZ7I8x1NQU1sEheMQg8g8MaeH6UFqRq4TjNs0KGi7tciyF1hZDjKdicqow1kd+VCszV0ciwS88x1HhJRcZqKaqmYWuTgj/2Iyh4TwiXPEPRtdyCl1IuKY/JhMfSvgXImFvhy1mVzQYA8xQZzJ1yhnUCOlYVli6YD0RLKCFM0Hxhf3v7zU3zN53uGvrGXydVfZir94eIKjiz55po7vtXrfIX9Sc/CIhSBComVTpWR3v11eB6G54xyVlf7P5F1EukF56f8w507vhct+60V0kiHrmBzy86SSixaMqmklUsQWLO6CsFp6h8tSzaoUgNjt+z9YFKt2vQx7ntU4QzrfvhQT13np+vQhNeznG/v8A3piV78lhBNcXsQf+4dJ4YOCzv8dMuaXj8IjN7OBXRH5DPkp8X0v/9Zq4toCyjgHKbhDk3ADwBurtfmih1iejlnoGitMc1/6lCgH04TS0W+RCpxgMXSCeNGsgbRkkVBzmkRtWRVDdCapMqsTsDYblh0f15l+ou4k+LN99Lxjz2eHT8q/pAG9HbFYrhfD5bh45Ec/PJDx/IF6Wj7wQprTpFfMDOhINSlHXqLFqKUPGZYBUIjkDxoS8MHq+90ympW4c/iyN5knI3tPzNsDfOh92r61pZ/g4sRm3+YjoRPdCOqa7z42bfXLgb/x5J69PSAgl3xncOepZDneSYBhKu16+UMZsDA/tdCpLI4/q578qkZoMFqXPgtlu5m8V/xEi/xmWebDGe0Ke78Mjdzciroa4ZuBw8HR9W7MVrncCQE3YG3AVVLFtm4X88SFzh0uPVztH6IibNugz7dve3qS6GW1emtbGFs8EicfOGZIT7S8XWHloZOed709YRmJM1XKwXITs59yHkZSVixCEnFnUiDBojVNRKThFGUJUCXkWRCIxAQNWZ6IdjHKlTf3D/ziFMnAegmICbjJiLXRXBYAYGuSHKgOHLP0INRkNHbNGq3EjbMoYMQ6zsnPbI6E3P79awIgQsDACblmgInZbvjgQTjV7gURUG9LvjtU3N9fDPklc2/ExmZxkx9fjIlf91tZDhWi4jffNKsJFrVHbgHg/1nuofemhAsDJ7ObmoSoo3ubA+deJDA9PLD7v2KKQsWry1Ksv+9MUVbxeZIWvf02pPWCjGU14UUdkh3cRh5K/Dl5A5O+DYyoK5cudHXczcz4ZVqJ+r9ZSzvhR3xey/l9L146AMOKxormSBigQrfOGvvh5RBNdZlQEAc7HiofRpoCDCEGf81hweGjzR8GvzvXAq5N+Ac4ySneOM89AlwCmrkfVxClPIO0jI03w2mgW7YSkw4nexf740npUj0F0rQ0q6GDePzRbKi2BsoBKRp9MhUIkQ4vYlbW9u37HXQFmPUh/xj+ibhN2UWRPPUziAxMyjylMUl8Vnz0DNZPnqkqgl1JaMM6VLl/7pdVc5OocoDKXBkz5p77Mj633lSS8r1omLZG+GkkKpQqFSuNjz0WjXgcjy678MejDpuoY8nHRMjxiOOsDX5sImjHI3HHJPjjklm1uOZE2S7avqfv0Db1KqnXqbM7ILXBoIYCAIuAmhOp7g3NosCabYYGiLT2rHDov2ogy6yMPQHaWmCMlzD322ZhDQRDIpET2wnCQASJFGbX3NdzgqKw2AocDpaHJGDf737pLcAKgo9CHCWC6aLDyV7ePhAMP0HEwuTVIrK/HxJNQESnL95PhToQiCHwXRLToW9dsXKSmwNmDEgvEbiuvuyIkLiNGGndloF3YFYUAVG8Pg1pxNxh71qRepcA5rLEaiaBwPKOc5aXja3pzVDiXFzzEDi2bYZIH4UYqm1PBPlOiQFKqKkGmxtxEE8mxrFhP8RPJLzFGD2/NiJmvbNzjV6Q0gGDhAnB6GlGuTfXz19NKG3pqCiPODAigfrdsDi5mBnNY9955V2DLUPY0ZAf2d932TUYkgAvqRKswlOWGG6MJUqDoGK5fQbN2/nLnc/uZjZ6NTB73AVNbxOXJ2ZRGW5MN8gNdFMOvy9XphuDMzwnmHTuYO1hz7HMmA6Muf+2zUpX6DAC01kVvXMARBCEun2GK4PIcB6aY9GnAN4DAmWmCeSbW7SxNq/tx6F2ZOONq7tIO48gj/+PTCPvPVw6QonQXWxtv0KSWD63SKLF9mArWcL7nCeJ0YJbzDSmXTuIBnethiocitcbrAY9HsVV4ffTAd3KdZQGydkgmoofyjL7DfsN+Y2VTIzwj3w+vF4hBDyWytADysnBqCH4ELkcP4GcrOphPzOYeZV0GW5JPo/OIK1DnvHcw3DKMn2aNvkOVMR6YxFBW/v+1nABgs/7sQCDDESMRvyTgYXd32EgOJ+Y9rb1W3lt7TGRWITxTsXW81NBqk6agVtXlsJy7nupAS6HYflsfVZwcSSc8m2fLt3vTJAcDsWYoVA3S5uXAOsdWzHQuv+TgYoYHxw8E9+SayKQCE6gBAGYLkG+vV7vKVoHKmN8sIhXW8XmpKTbhPFREi2onEC+FXqAGPH4rkQmFEWMSttgbMGPKh0iaIcxGYQQE2Fvrqh9gQkFMUcIKhWAkkwyq5bFmQ+5jLXiIA6VF+L0ZD0um5sdHaAQq8eKcHoMt7AO6stiezxWqFt0m7qgIyy6tG8IffevifyhRU/Pi9Ejn+IXnYXJ3LV+IwbFMxzJHBve6bXIXRlY+On054rpB+tdwOJJM5lsPpnU4zgDZpJnwCJjOnmacXEd50WYLa+Fk+t03+wJkR21ASZUT9JjTViKfa2eUygVDU07/9zms7CUs25F6vevFCzq1pVkPrV4ykx6qvW5L0Jfhj4KPZzxqdkDRudIsaR/3YKjM9k2df5M1/IvRi33lt4zN3ZyP498me0luprNOVIWKI90XuT4yANlPpzzXfYiNKE86XDJI7X+p4qrFv5+q0h6kIBoTKQpEn9i6HeTFmiDB4xTwRrj1EGaoHeTPhcdSKoN1l7Bi2ghBE2tGagGTJyuQWsEF00XS3Y7Oh38DseTdFgCnWBZ5rzTvDNnghBgFvgzR1yMLoJ+eDy500V3nO6w4ACSIJPBgB/CMyKms4IATdQFl2TtRwwnDfdOGASG8CQ7ahecRE/S76E6tKmEuu6V6JxMwATxo1+io/+8fDXVr9Xr3QcEFy55DOBGCFJrkLDX+q4JMkJz73r1LjuZgh/G/YAfIx5JpgYb9XiKzBUAdvYUzesF/8vYc/mxCZ6ehlM1LYiAsnnN7OlJ7VVXMCqo9ZtVI8ZlFE/CZu6m/jiLJ2Gf/9ZbverUXmHN8egVx2I5X3hY4kaMfpsMnrJn365rPWiSwDmY2upX6oHZEVZx9gwYIRNUQ8LeICsOIR2R+o1nCKbKkWOKWOSplcK5jvfLGhU5fnYTQ5zNBE+5ly8SpuC/OODdzicNs3zUik6E34FPQoRMBeSdn7DuYltGXnB/O8Ee4FMlSdKFPKsT3VidcKM47ePkNL6j6/bRAt/R/HW3CudZprtzhU+G6nxqjlcMpVSY1Gn01Q0gC8qrb1HhMH2T7/fBpWBjZpBS6iGQVkdngjJoYD1UTiWnDdhP5uaQiZkrdkYkQi4FXo2zBsDJnByea8/bAWKVVsv6x4Mr6JFMEp6zS2sdyPInEYVRTgbuikz59Qf1pwZQHK55BHu5El3eDu7Wko8HV2AwJK9tnDftsl0DWXSJ0A2Pa0t+2mYkyhhkjKKeHAW2Q/HElZoroHd9r1ekR7whvv6j3MQfMd1hv85DVtl0VXj1w6teVwE2T6N16nSaHgZDy5A8U6116nKaggLYkI2ak1Um0zStnY4q1U4FKKxRVX+2SI4/xDkUT2Zs8NnAVJOXHeIeWkZ2GlplAWWHZ2PuQ04152GuXLJFrIaEMH+SW6DuJlvIXQ5u5Ng4VVxh5hYJ52GoR+HQebD222zO3dC7nOzsJiqzNUv0nrbceWzkP4VRjZ2f9Ij34YV/61mzSQ9Z2zihc1QlrcAOxMI6FJuWlgtycycs6mHw8jJ4lJNNKyN0ZZK+JUkswCIhofKYWPXUBJ/GdM+npx1swJsiT55NUuBTKcfUVN8CCU+4pL+kT+RV80k2Z9u24BmQN22JJ9vIkYEeaWNpHkpquTP+MfdjohiF1Bo+Xz9dyQ+1jKuJHBqY5mH2SAuE1M3Nv6yALTbSzy4MJskiRJvwx4VLC2MVZROSMtv84yqNc9lbR0yTC7hn1VEhajcVWHVWIHshym+JRu2EDYG6vIeylNIz6na3rrvkt4Lv0fVgdjOprgy4ur01YHX/qpjUg1FUMtA5EtHEqxOCk+7gU48ijzmydolG57MHvRcwF1DHAgHAccYKrJHgK6KBqNzgKV+hnSqzqGF0QgDqZACZdHwGp7U4UbXjUC1IeGAad7Y5V2Eu547nXsZUOdtirGeqGCUAVUBhbDLsTPcLzmCrACYJkMzP3626K5aASFCpvxt85TyQgMrK9uctCLCY4MMKuAGsbtxWxGf2nBnvhwvBbm1I1iD9g0vwALLhUvlGiDzZAJuHSbUsnxzn0i6QA63aEFAFvWpFxhVwM9Ri3ttOYPZ5KUw5kss3qe7Um7RdJuOmlWe9ucCjpt9blT4JBLXBYVB/GvWFqjE4TCnAOPWlLDwk9zvm049LhHXyjCUMBs3f4ELOxrf/R2ZPbvJU6XKfFB09xlt40JCE6D4LB8Rw8l32XXLs6ljLvPM8OXYzRWPdFEt+yH5Iji2KJTNMMst6arNVQ9lMHktun8bNAC9JK4JnE4nD7W+LWx3uQpghlPHdrfi1saL83fhlpco1Fv71fw8Y/1kYFPnZbvABi113zusS6ACXvAb5iiovqyMOUuzUDqqdMkh1WFVVCv6eArDtoXMYsNfngOOD58+DWzrpFkm4ZnWCKTAo0FTaO+yVGsHg0/Hds0JAOdpRFwNINnYeyq2a7164RUmCy+oGM16DK6E1ba1mfu1yPbTIQIpWucVrBmR3TeSPO6M7J+/dXELeFN62wWGAQ1AoLGMTB9ADQa0CxbC6mMc+RQGKLYm/oED9ebZVQsmmSKw9FA6lR+fAZePe6NjYVvKA81fRzYuf2DsFG78CTC6USvjkKVZC0q+V/eGal+kZsgoayg/NbwqcDSwqCC0YLAjh4G3mm34gVpiMwfwQunwb4afA/KFkkWk2qNj8IQoJYfex5exWdrtzDDtLGs05omBTSCQKc0FFzabkLYxQSSTqlq3YOMB/C8SBVjwSuD2L7uTupLjtnjNYugoKUJXcc+po6/fC9YT6nZvq4asCPYCvR+r/M4a/uloM9fVBWUnb0KMhzSXFu8gMudubc+e7Gp80pyE19EBaqLivb1dZtvvz2eirz92zt3equwJPZn8iLovKzC62jOxdJwzBBP2B4OKRkO/7FZKRArYd+aHFxw91/qKOWXueU4Jteb37pqWQ/t6oSKSa2V+FdJ24E6aijrb/f0A2o63OynGJeOWL4LfOL0hvJCvFe1StHPnvDCe9UMjEwhG11VQFApjbn3NlhuztTTlb4Vy4oSE/kVBOQ6MSIoYSn+SpaLS8vCWG6QsXt9UpnUUKYuLCboWSSMrOuxGag6mth7KhNG0VECDaaniLiVS+Kx+P9lZYA6kamtU4MHlv/Y9Pnz9dtzAJ5eEaDJAK0na0rIIhYtmWtbgdfWzUaAqaSo9qi/+DL2MqyCQ1xn8OpoHEUhlB//NYlBM3pu80mQblH1hr8t1+qFRL1O+04IlPznYTImh/7MUIvhu573I1qGOubY59gbrhxhKe5PRZ9OvEEaHA1JTeZBIIR0Q1G5d0z3yecek93dsrFwlbLTHU36gxFpOsbPwe7UrsyjclGVEr6jCaSi8fALQLTPyKuqbUY9Av+VI/KLW8OANqSkm1td1Eb34AJ8IfIL3NlprSlAHdLwyl+vGlX7iHZmT4Wj7q5Mo3fJD8yKXRL3/LcDl//Z/iKLfGfW6Uf+zt9n+Ut7cxOHJruPK3eytZwOGwSEimzzQQ63LMAv9k7py1BFu2cz7i0OqdplnEsOecFMs171U+qwItweFhgrDwYIu6zMXJhVhOkl3g0rgGMcErIAiYgLHku66hx9VupsbW2ObQ8mv3/e9fEwVuryX3/dKh0dDRnuFlucZvY/wJH9jcWRK/+joDjgjoLZjOySHjFNlaajB/hW0FP0Q+3dd9zNPlnHdvy8Sh55FQ8qpVUojNgkApt2QB8IqZAqDc4duoiWOkQboSkEam4qpzRRYzibhy3c8P4lGa/3QC+Mlp/AC4swxAj2T18nroZUZIUDxwFVAFPyV444MCjQZCQbmiEOXbtfu8vkomLNioVNtC9P4gem/2/soljMrXaFEwJw25HjOejVccShhLjlPyHoxtRN0zVP3GsesqnjTu6PKDeEX2xtTrIb3q3tBracM510oHEyalsSp3AYao34jyMrBuND9QuifHmhPsPmg55throSPqEf9dvag4MJWsHAu49XOmhzrT86dbLkPk3MA0VNyLJqEDj5dGzh1yuS14PF/AmDMA0XbuI4YNssI2hvyAwFbIduybZQIb/Ai2rVWu4X7P/IH5PbhFzIMaG6E8SNXYlBeDox1S4dLYmBcFUJTBQFEIQsNUg6L5e5303nooQdn9oOeBKhquIqKSN98fDLmybn/izz8lms+cGVLsTqDa50+fBstXrdmelUkkZmVtW7MtKxN5Aj1790PR23SHaI0IEiITx/aKWR2Z260AS6tYaxzpb0WfPrso0ZtupzPjhVeBf/HbgBpqatqwqq7Z1dAA+RHHRh54olJ5eqjylur2HUVkO6uzrqhD+hjT0XW0S18PkG0cm2VgSZXn4alSPYHdI/JAHmRogtRQnhVqKiS2V+V3YB6L3iF+qaWIvITpOA5IHyOd2LfrVhMr61Z3YBgW1mDtuAH2EnAI+rk7lOZxGpNm4poVupGPimw6EyUfvGFox82aVbISfiIA6i6O7S01J1DyFsxeBdZfJs1Ob5klS3izPJk7j/w/0QTonU2y3lmtPAl5liRx6+84CXCVXUQiNGsdy9bEzuWNg8Kh+Z03C0wek/aGFvHN66hMajylAqRozM0zb7s9b78IQa/A98eVZsfngZ3LdsqtfP6cVp50QlGZYr/2B5WZEhaEw96PAarY7QFCvtXK71wuk30AypL/C8mhMjRx9kEgp8eH0+xqJp79fQzIi9sRJ7EZ2ZEoTzmeqwr0V3H5B7IykPxYdOY+lZHCxKLZcSqwPXZUHuw3JiP/LJd/Qk72Tia/qezidEmHOEOVV0nJ3p1fKJIN3M5KG1kKIiNemfwJN3Fbai9fR1ZWeoUNdpKZGKpKkg0/nO4napV+xPIMF8Hi3n6e/cG+bPdgv4AteGE9QzDM1gPs616BR+Q94UaBoAZZU/s4kTDTXg1erB7WOghCyC+cX5ClrJrccdg+tOmFYT7617eGVeG94gScZdHeeSjIDILUDc0qKEB9wCC1e5fwQCKgKfPmFnLz+PQZEK9Mto/Tj9DN9pt2Mz29Kp0+aT9S4Zut02dUZZihlo03L71q52+kR+SbpJekI+QX225abOTDT/DAR8SbpGt0hPTiL/OguSMpxD65YDyYPm4X2SoNfONnUM/4fzRNUtnNEobYzEmRM+RUM0XeqeE2Bmk7fnXRyClyabKcKtcYGWhX5YHvmtV793iJKyCWLFlOMVPlUumVzJk7Gd/s3CmXO095M0qK/A1rOBt5Pu5iD28PEyLp6BCTNNs6kerVpe/hWPIajQKL76JtwEFKXFcpZwWn4KMIKHNlSyq7tCDhXaWKW7kOaPFj1C78F68fYNzcMKk+MIiAyqDKLs5hYBiDOmcQAfaLgWWql68I4/hoVDdJaCBM4ZO3Q7LUeL/w/qcv7n90X2kMhozpob6hPnizYdTnpuuQqfC5CkcICzdOn6JP0s0FeCeSq6uzYgWkQ6b/Il6dopDTU5xX06domqHh0unpyYGu4SENbYquNn3w6PIUhfqMkGiJLbufJj0ZV34/nR6VbjDTxwnphHG6+RUY0U3Sp/BhNaMdqB48qm3M59MJZoaZIAz39EawRvw69Nhzx3v1ccLx2lFNvXa/0A0koUC4sY7u9uv7inmrnF8GO1/ZT0/CgKflpJfPV+v3mr0x3ivVVltG2mnx6Y5H4kfxcqKr30io5Jqx2Dyo6cNVe0QQf8l/vpTKzmQ234j88ctbziO3W5rchpeL9yUxxWCtuMM1LXx1qkiYx9CCyE+DnNlTrkfkH+HHv48trCZ6Zf37U1BlJTE/3qMsoLwgvIaNZuM8NJZ4gVgwSZZ7p6Y2twgLnmwUb9TSSsU54rUF+SZ5rxWfKReDpImjInYPYxOjhy16/Y4x/Fr3HL2lX5QYTIaJxxa9j0tA15JaRHr/me1iOvE9pcXMCeSgGvWGoezsqpzs01GiU6RRZhOU6zZ0rlvnoXQLjtQF6EtK0tM1mh33ben8LJDK26uphfYeF3I41qmqNZ2htw6VJQXNzQUFijSy5w6y0HkOZ/5F2tgv2EnMPnDiEs3b6Zd9VDtlH8VhfbXSqfuooPGQa79rW18gt/TgfTrZ+GHpWiYz3LWgjyfuc/9A/AHPeYf/koTuT2QR/PGdOn8Sa9VX0pXUrgNUqg+Nnne9g8f7E1hEfzr7UyOxPvEmXGJeMihiPTs9eXL8FHOKIA+XEy4xLhHkYTqv9ayixqaYbn9YxJTwFOI0Y5qYEgY+jqpf4KcRbZPEtPA0ou+JpYXRHKqFDs84BWGGMUNQhCuWDoUh7p9AAaeZtJP3UeynakMt+F78gbu4jydSmlDn6d0JU/va0g+3kunfHizlBva71lCpB7opK3fQaYWxuzIKOPgmjSp/ioC3Mig/H5KBgkWWSr9ykPbl8+jo3XmQVqUbrtD/o2CSA9TxrtBVKeAoERcKNhYX94icraIjFRXy+JwmkBZNZhA0Jk5gf//oY+dAaFzEYukrtevfgoJ5nU7YErg00VXQVw2ukLWjlbgpy3MrxounZH/nakEsAsAnI6YABeCHNnZoYsImd7EMP29REvV8vVv9eSoyGTCZyLpt43k9YGJWh5ommWJNz2/dWyfiNkttrvZ+8pvlW33vZyDOHfqiF5EZ0nDnI8R8w99F66cN0aiZfWEpB5Ev/7+vFRdvoVq/JsYVzH//VapXFkRAzRD8CVRAG5qdtS2c42+yVpGpHlwQAXV2SJIExwxH1l7Srfr692VzK/q50ThGtY6xthmmLs2hkpIxt7GcbYi2NJLqTagJzCbRgWc+fpvD0iiq+4Es4pDGh5UAE0AFDYtAZ7IKkDThFLGCC5TYBA7HL3EovYq03oNNMGFETbruQR1wOL7LjL7drLD0qES4lFBdHZSqckEEVMWyfWGZEa857rWyHTzD0qeys8rhhr+/ruPdG+lVrOmLmWzNzvbGEDDeXVNrBPFeHe/rvyOyqt1rt18X2O2dzLEunNcRmWF1vCrOhGXt6qyI84IJBNgreb9nrS4ouN47cm9voyhCudghFVZ8VPcKvCdyiHnq+ulZtzR/dYsnL9Cz5fYDrBz74LaVD+S1eKr9092uTtfnqW1e/Ks8E0QiwLp/6Dnj/Ie2H57/jv6eb7otOgqoNo0GuzgMRoMDH/wNXeIpoX8TjNebXYJHLd+XV6yrGFgcNQR1Fs+3JF7+C75J/H3Z8b/Q+kl40GiIy9sHv8WHfOMJzwCOoLMYu51TPbsgslSaZC+ysICg7jWIAKumIEygwf2s1/9ygb36sFkuv4vVwDTY1pqXF5yFseFPsOqEFf0u60mt5g2it85VTgV39fqH5ySFd+WyKlLZ9CDb4VzFLHyyjSwADrganKysPjcvSOngEPL118ihAJVxKHIEuXgRGQEAi4D6Y4r+/c0p5mJhoe0QK3NgyLYHm2XTq4pS2DSEps5Klo2ltWsvFxbeqaT3ldg0xOLhdi0AWyJ6TAg5JvCjaunHQl1PGHbSU4dS6VpP7RI1ZGtWlqnelIl96KRTLegxkjwkirZiDeNVME27dCzkrj+EuuQiYU93O71CIXBUV37shkDfXyvA5c6Q9v3lGPwvk7cHwI1Jni3dv/Q/JAAAwPySNwM3izoOQcusKUTasslGxJiaZxVp0zQIv2454wAS0TLlc9qWf8zxSO13Rxk8H3MAyxASLm91CkFtWx6rRzzDS9RkQgSplz7ktISRA8+ZmqyA+ZlpJBjGuqrb8uUvuUUhU28MIzB5Lal3faYuhPEiv6PT74CPLa3g8QBjgq1rdQjhFVEEGF8Q75H+kWSkfmDlsndeR2q/v5DaJb1WPLu0mGSu9QbpI8NYdMQmtckfSBuMC/BLX9mEr9vmJ0pj1nd7njJ5YAUZ7fB/6LXmEsN/AD9nFBCd2zP/0n6CG1O2LhHcQ01n4zkbMOHzS+TH7G3LG+sRZIulAKIj5Z+jFezKmX9VUib86cgYkJ3vX3jzSuPGWPL6lIADcB+hBTiHKVZjTbeCI/DvSv1Z9Dbmbt9yFGzv7Y7NgrDHwXB7vJV/CCTt7uG36y6Q/xElvMrDP0ztr/boZaDVWSOBnSanrRW5tlbD6RW5cbTVCmZbM85Gqzcidf6gRotVVCwAhr0TtZLkRGtF4Ts2psa7mNFoa7XqvVAzVoZbvbuxqgz6+0f2IFrIg2wMUBoqtL7dORz5NyiuhCN/fKD/4DwaCuJZ9LT5AxC4EC6+U0nbFkHhTB28jypAVZmgcaYE2c40m5oXNzfFdf0zaeqlHTscILRALlDmhbFtDckghTjz1k7rh/8bUFhFcAM575/+P+B4eOMDEcKILMQPlKxybsXaqqMk2sgsBPSpbtSVpmA6qPKUETCYi5WA1Jqp9jAbL4TTdHpbOlteq98FULzy7Tab/XYwGWKylFFOjuQ/qKG/U0B/vwD/oPUbnEAkkSlUGp3BZLE5XB5fIBSJJVKZXKFUqTVand5gNJktVpvd4XS5PV4fqWQycikUUqVJlyFTlhWy5cj97JOovkH7R0XT8ym9hgywAiy4Z4vn+o2UmiWTYd0rHFDQ5Y3jGrDFiys8BrgwQeo6Tk0aSBlHnmQojNdJcJ6cRHjaTE+cFi7vtyPsy8pwPp+D8GFD210V4gOCtjduEXpwnYIbThu2R6Zq3C64EsOr1hwVY8kWpHbQGNeGm83x8V7PFZa95lUP2K9yULGgN6QfozCHgjOg8Lrz6MXJs5d0pn6TLN4/osXlVFmRlsg7TvcHpAlIDeTduvpHRe922WOE0jTj8+gID7R82UmL6xOOwtFrIIukKmR5NNT+9PKaGk7uc78l3fvw8582ZT/ujPfS0u/e/Dks2QnvUc5fHlsdlCg8p/GjXNB5hFUjfF7NKciyoB7Qa7z0tTSgK37ESRtSPkfnCvDSMcOLKNP0bXdNdein199iPbaLbI1MGXvN64LbnzSb2k8i/bQQwSiv0PAaKbFHonuhpTLfTBu3kXh3H6MDevt3UALdFjsWIuNdKTAPKbuMTNIngAvzVIGx5wZJtQJrILrDll/9h+evfv5ckChEickFw1wcTB2Jn62DztWdy0EZUhObm45wP1HS7eONEmFheLPcGG+/+vnpSLfPqKcF/4FFqvJi5pP4pD63Pnc+9z4PPo+rn3ZjcbSOaHJwTf3unwmpw7qWjFmR7qHLPVjhEgAAAA==') format('woff2'), + url('iconfont.woff?t=1591583895128') format('woff'), + url('iconfont.ttf?t=1591583895128') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ + url('iconfont.svg?t=1591583895128#iconfont') format('svg'); /* iOS 4.1- */ +} + +.iconfont { + font-family: "iconfont" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.iconshebeileifuwuqi:before { + content: "\ea01"; +} + +.iconshebeileifuwuqichucun:before { + content: "\ea02"; +} + +.iconshebeileifuwuqilixian:before { + content: "\ea03"; +} + +.iconshebeileifuwuqiliumeiti:before { + content: "\ea04"; +} + +.iconshebeileifuwuqiyichang:before { + content: "\ea05"; +} + +.iconshebeileifuwuqizhengchang:before { + content: "\ea06"; +} + +.iconbiaoshilei_fuwuqi-:before { + content: "\e601"; +} + +.iconbiaoshilei_fuwuqi-1:before { + content: "\e609"; +} + +.iconbiaoshilei_fuwuqi-2:before { + content: "\e60a"; +} + +.iconhardware:before { + content: "\e646"; +} + +.iconcloud__easyic:before { + content: "\e602"; +} + +.iconhardware1:before { + content: "\e6d4"; +} + +.iconnetwork-server:before { + content: "\e779"; +} + +.iconfuwuqi:before { + content: "\e60c"; +} + +.iconyunfuwuqi:before { + content: "\e625"; +} + +.iconerji-fuwuqi:before { + content: "\ea9d"; +} + +.icondiguifuwuqi:before { + content: "\e654"; +} + +.icontechreport-:before { + content: "\e63c"; +} + +.iconfuwuqi1:before { + content: "\e6a4"; +} + +.iconwulijifuwuqi:before { + content: "\e939"; +} + +.iconweiwangguanicon-defuben-:before { + content: "\e66e"; +} + +.iconweiwangguanicon-defuben-1:before { + content: "\e66f"; +} + +.iconweiwangguanicon-defuben-2:before { + content: "\e672"; +} + +.iconweiwangguanicon-defuben-3:before { + content: "\e674"; +} + +.iconyunfuwuqi1:before { + content: "\e65b"; +} + +.iconyunwulifuwuqi:before { + content: "\e9e7"; +} + +.iconfuwuqi2:before { + content: "\e612"; +} + +.iconfuwuqi3:before { + content: "\e65c"; +} + +.iconxinzengfuwuqi:before { + content: "\e692"; +} + +.iconfuwuqi4:before { + content: "\e662"; +} + +.iconyunfuwuqi2:before { + content: "\e61d"; +} + +.iconfuwuqi5:before { + content: "\e630"; +} + +.iconfuwuqi-copy:before { + content: "\e604"; +} + +.iconqiyefuwuqijixiangguanziyuanshenqingliucheng:before { + content: "\e65d"; +} + +.iconzichan-fuwuqi:before { + content: "\e66b"; +} + +.iconfuwuqi6:before { + content: "\e86c"; +} + +.iconyunfuwuqi3:before { + content: "\e615"; +} + +.iconGPUyunfuwuqi:before { + content: "\e7d9"; +} + +.iconGPUyunfuwuqi1:before { + content: "\e7da"; +} + +.iconyunfuwuqiECS:before { + content: "\e7d8"; +} + +.iconjurassic_server:before { + content: "\e6a6"; +} + +.iconjiasuyunfuwuqi:before { + content: "\e67c"; +} + +.icondanxingyunfuwuqi:before { + content: "\e67d"; +} + +.iconyunfuwuqianquanweishi:before { + content: "\e6a2"; +} + +.iconsmcfuwuqiqianyizhongxin:before { + content: "\e62b"; +} + +.iconsmcfuwuqiqianyizhongxin1:before { + content: "\e6f7"; +} + +.iconyoujianfuwuqi:before { + content: "\e782"; +} + +.iconvpnfuwuqi:before { + content: "\e795"; +} + +.iconIBMfuwuqi:before { + content: "\e797"; +} + +.iconwinfuwuqi:before { + content: "\e79e"; +} + +.iconyunbushu:before { + content: "\e701"; +} + +.iconbushu:before { + content: "\e77f"; +} + +.iconzhuomianbushu:before { + content: "\e603"; +} + +.iconfangxunxingshibushu:before { + content: "\e65a"; +} + +.iconnavicon-bspz:before { + content: "\e63d"; +} + +.iconbushu1:before { + content: "\e766"; +} + +.iconguanxibushu:before { + content: "\e624"; +} + +.iconliuchengbushu:before { + content: "\e626"; +} + +.iconbushufabu:before { + content: "\e63e"; +} + +.iconcaidanbushu:before { + content: "\e644"; +} + +.iconbushu2:before { + content: "\e600"; +} + +.iconbeikongshuiwupingtaimenhu-tubiao_APPkaifajibushu-da:before { + content: "\e62f"; +} + +.iconliuchengbushu1:before { + content: "\e62a"; +} + +.iconicon_bushudegongzuo_bushudegongzuo-:before { + content: "\e686"; +} + +.iconbushugongzuo:before { + content: "\e688"; +} + +.iconbushugongzuo1:before { + content: "\e689"; +} + +.iconjiekou:before { + content: "\e694"; +} + +.iconjiekou1:before { + content: "\e74a"; +} + +.iconAPIjiekou:before { + content: "\e653"; +} + +.iconicon-test:before { + content: "\e633"; +} + +.iconicon-test1:before { + content: "\e634"; +} + +.iconicon-test2:before { + content: "\e635"; +} + +.iconicon-test3:before { + content: "\e636"; +} + +.iconicon-test4:before { + content: "\e637"; +} + +.iconicon-test5:before { + content: "\e638"; +} + +.iconicon-test6:before { + content: "\e639"; +} + +.iconicon-test7:before { + content: "\e63a"; +} + +.iconicon-test8:before { + content: "\e63b"; +} + +.iconicon-test9:before { + content: "\e63f"; +} + +.iconicon-test10:before { + content: "\e640"; +} + +.iconjiekou2:before { + content: "\e66a"; +} + +.iconjiekoushuoming:before { + content: "\e605"; +} + +.iconjiekoushuoming1:before { + content: "\e60b"; +} + +.iconjiekoushuoming2:before { + content: "\e613"; +} + +.iconjiekoushuoming3:before { + content: "\e61b"; +} + +.iconjiekoushuoming4:before { + content: "\e643"; +} + +.iconjiekou3:before { + content: "\e669"; +} + +.iconjiekouguanli:before { + content: "\e7d4"; +} + diff --git a/nsi-collection-platform/src/assets/icon/iconfont.eot b/nsi-collection-platform/src/assets/icon/iconfont.eot new file mode 100644 index 0000000..3d0c52b Binary files /dev/null and b/nsi-collection-platform/src/assets/icon/iconfont.eot differ diff --git a/nsi-collection-platform/src/assets/icon/iconfont.svg b/nsi-collection-platform/src/assets/icon/iconfont.svg new file mode 100644 index 0000000..6dd83f8 --- /dev/null +++ b/nsi-collection-platform/src/assets/icon/iconfont.svg @@ -0,0 +1,290 @@ + + + + + +Created by iconfont + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nsi-collection-platform/src/assets/icon/iconfont.ttf b/nsi-collection-platform/src/assets/icon/iconfont.ttf new file mode 100644 index 0000000..7ef9517 Binary files /dev/null and b/nsi-collection-platform/src/assets/icon/iconfont.ttf differ diff --git a/nsi-collection-platform/src/assets/icon/iconfont.woff b/nsi-collection-platform/src/assets/icon/iconfont.woff new file mode 100644 index 0000000..5ea216d Binary files /dev/null and b/nsi-collection-platform/src/assets/icon/iconfont.woff differ diff --git a/nsi-collection-platform/src/assets/img/img.jpg b/nsi-collection-platform/src/assets/img/img.jpg new file mode 100644 index 0000000..cbe6c00 Binary files /dev/null and b/nsi-collection-platform/src/assets/img/img.jpg differ diff --git a/nsi-collection-platform/src/assets/img/login-bg.jpg b/nsi-collection-platform/src/assets/img/login-bg.jpg new file mode 100644 index 0000000..bd2ba25 Binary files /dev/null and b/nsi-collection-platform/src/assets/img/login-bg.jpg differ diff --git a/nsi-collection-platform/src/assets/logo.png b/nsi-collection-platform/src/assets/logo.png new file mode 100644 index 0000000..f3d2503 Binary files /dev/null and b/nsi-collection-platform/src/assets/logo.png differ diff --git a/nsi-collection-platform/src/components/common/Header.vue b/nsi-collection-platform/src/components/common/Header.vue new file mode 100644 index 0000000..6cd5636 --- /dev/null +++ b/nsi-collection-platform/src/components/common/Header.vue @@ -0,0 +1,189 @@ + + + diff --git a/nsi-collection-platform/src/components/common/Home.vue b/nsi-collection-platform/src/components/common/Home.vue new file mode 100644 index 0000000..0624dc3 --- /dev/null +++ b/nsi-collection-platform/src/components/common/Home.vue @@ -0,0 +1,51 @@ + + + diff --git a/nsi-collection-platform/src/components/common/Sidebar.vue b/nsi-collection-platform/src/components/common/Sidebar.vue new file mode 100644 index 0000000..ac56713 --- /dev/null +++ b/nsi-collection-platform/src/components/common/Sidebar.vue @@ -0,0 +1,122 @@ + + + + + diff --git a/nsi-collection-platform/src/components/common/Tags.vue b/nsi-collection-platform/src/components/common/Tags.vue new file mode 100644 index 0000000..148ca61 --- /dev/null +++ b/nsi-collection-platform/src/components/common/Tags.vue @@ -0,0 +1,186 @@ + + + + + + diff --git a/nsi-collection-platform/src/components/common/bus.js b/nsi-collection-platform/src/components/common/bus.js new file mode 100644 index 0000000..b433c90 --- /dev/null +++ b/nsi-collection-platform/src/components/common/bus.js @@ -0,0 +1,6 @@ +import Vue from 'vue'; + +// 使用 Event Bus +const bus = new Vue(); + +export default bus; \ No newline at end of file diff --git a/nsi-collection-platform/src/components/common/directives.js b/nsi-collection-platform/src/components/common/directives.js new file mode 100644 index 0000000..b9d1834 --- /dev/null +++ b/nsi-collection-platform/src/components/common/directives.js @@ -0,0 +1,80 @@ +import Vue from 'vue'; + +// v-dialogDrag: 弹窗拖拽属性 +Vue.directive('dialogDrag', { + bind(el, binding, vnode, oldVnode) { + const dialogHeaderEl = el.querySelector('.el-dialog__header'); + const dragDom = el.querySelector('.el-dialog'); + + dialogHeaderEl.style.cssText += ';cursor:move;' + dragDom.style.cssText += ';top:0px;' + + // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null); + const sty = (() => { + if (window.document.currentStyle) { + return (dom, attr) => dom.currentStyle[attr]; + } else { + return (dom, attr) => getComputedStyle(dom, false)[attr]; + } + })() + + dialogHeaderEl.onmousedown = (e) => { + // 鼠标按下,计算当前元素距离可视区的距离 + const disX = e.clientX - dialogHeaderEl.offsetLeft; + const disY = e.clientY - dialogHeaderEl.offsetTop; + + const screenWidth = document.body.clientWidth; // body当前宽度 + const screenHeight = document.documentElement.clientHeight; // 可见区域高度(应为body高度,可某些环境下无法获取) + + const dragDomWidth = dragDom.offsetWidth; // 对话框宽度 + const dragDomheight = dragDom.offsetHeight; // 对话框高度 + + const minDragDomLeft = dragDom.offsetLeft; + const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth; + + const minDragDomTop = dragDom.offsetTop; + const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight; + + + // 获取到的值带px 正则匹配替换 + let styL = sty(dragDom, 'left'); + let styT = sty(dragDom, 'top'); + + // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px + if (styL.includes('%')) { + styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100); + styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100); + } else { + styL = +styL.replace(/\px/g, ''); + styT = +styT.replace(/\px/g, ''); + }; + + document.onmousemove = function (e) { + // 通过事件委托,计算移动的距离 + let left = e.clientX - disX; + let top = e.clientY - disY; + + // 边界处理 + if (-(left) > minDragDomLeft) { + left = -(minDragDomLeft); + } else if (left > maxDragDomLeft) { + left = maxDragDomLeft; + } + + if (-(top) > minDragDomTop) { + top = -(minDragDomTop); + } else if (top > maxDragDomTop) { + top = maxDragDomTop; + } + + // 移动当前元素 + dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`; + }; + + document.onmouseup = function (e) { + document.onmousemove = null; + document.onmouseup = null; + }; + } + } +}) diff --git a/nsi-collection-platform/src/components/common/i18n.js b/nsi-collection-platform/src/components/common/i18n.js new file mode 100644 index 0000000..299d2da --- /dev/null +++ b/nsi-collection-platform/src/components/common/i18n.js @@ -0,0 +1,30 @@ +export const messages = { + 'zh': { + i18n: { + breadcrumb: '国际化产品', + tips: '通过切换语言按钮,来改变当前内容的语言。', + btn: '切换英文', + title1: '常用用法', + p1: '要是你把你的秘密告诉了风,那就别怪风把它带给树。', + p2: '没有什么比信念更能支撑我们度过艰难的时光了。', + p3: '只要能把自己的事做好,并让自己快乐,你就领先于大多数人了。', + title2: '组件插值', + info: 'Element组件需要国际化,请参考 {action}。', + value: '文档' + } + }, + 'en': { + i18n: { + breadcrumb: 'International Products', + tips: 'Click on the button to change the current language. ', + btn: 'Switch Chinese', + title1: 'Common usage', + p1: "If you reveal your secrets to the wind you should not blame the wind for revealing them to the trees.", + p2: "Nothing can help us endure dark times better than our faith. ", + p3: "If you can do what you do best and be happy, you're further along in life than most people.", + title2: 'Component interpolation', + info: 'The default language of Element is Chinese. If you wish to use another language, please refer to the {action}.', + value: 'documentation' + } + } +} \ No newline at end of file diff --git a/nsi-collection-platform/src/components/page/403.vue b/nsi-collection-platform/src/components/page/403.vue new file mode 100644 index 0000000..45adc1d --- /dev/null +++ b/nsi-collection-platform/src/components/page/403.vue @@ -0,0 +1,56 @@ + + + + + + diff --git a/nsi-collection-platform/src/components/page/404.vue b/nsi-collection-platform/src/components/page/404.vue new file mode 100644 index 0000000..02b30ba --- /dev/null +++ b/nsi-collection-platform/src/components/page/404.vue @@ -0,0 +1,56 @@ + + + + + + diff --git a/nsi-collection-platform/src/components/page/DnsResolution.vue b/nsi-collection-platform/src/components/page/DnsResolution.vue new file mode 100644 index 0000000..0b6678a --- /dev/null +++ b/nsi-collection-platform/src/components/page/DnsResolution.vue @@ -0,0 +1,98 @@ + + + + + + diff --git a/nsi-collection-platform/src/components/page/EmailInformationCapture.vue b/nsi-collection-platform/src/components/page/EmailInformationCapture.vue new file mode 100644 index 0000000..cbeac92 --- /dev/null +++ b/nsi-collection-platform/src/components/page/EmailInformationCapture.vue @@ -0,0 +1,90 @@ + + + + + + diff --git a/nsi-collection-platform/src/components/page/Login.vue b/nsi-collection-platform/src/components/page/Login.vue new file mode 100644 index 0000000..148a8ad --- /dev/null +++ b/nsi-collection-platform/src/components/page/Login.vue @@ -0,0 +1,133 @@ + + + + + diff --git a/nsi-collection-platform/src/components/page/OperationLog.vue b/nsi-collection-platform/src/components/page/OperationLog.vue new file mode 100644 index 0000000..5dd95a6 --- /dev/null +++ b/nsi-collection-platform/src/components/page/OperationLog.vue @@ -0,0 +1,113 @@ + + + + + + diff --git a/nsi-collection-platform/src/components/page/PortDetection.vue b/nsi-collection-platform/src/components/page/PortDetection.vue new file mode 100644 index 0000000..a95b4b3 --- /dev/null +++ b/nsi-collection-platform/src/components/page/PortDetection.vue @@ -0,0 +1,91 @@ + + + + + + diff --git a/nsi-collection-platform/src/components/page/Register.vue b/nsi-collection-platform/src/components/page/Register.vue new file mode 100644 index 0000000..5a3e01b --- /dev/null +++ b/nsi-collection-platform/src/components/page/Register.vue @@ -0,0 +1,110 @@ + + + + + diff --git a/nsi-collection-platform/src/components/page/SubdomainLookup.vue b/nsi-collection-platform/src/components/page/SubdomainLookup.vue new file mode 100644 index 0000000..a1c5fad --- /dev/null +++ b/nsi-collection-platform/src/components/page/SubdomainLookup.vue @@ -0,0 +1,83 @@ + + + + + + diff --git a/nsi-collection-platform/src/components/page/UserManager.vue b/nsi-collection-platform/src/components/page/UserManager.vue new file mode 100644 index 0000000..735ed99 --- /dev/null +++ b/nsi-collection-platform/src/components/page/UserManager.vue @@ -0,0 +1,277 @@ + + + + + + diff --git a/nsi-collection-platform/src/main.js b/nsi-collection-platform/src/main.js new file mode 100644 index 0000000..2cc34a7 --- /dev/null +++ b/nsi-collection-platform/src/main.js @@ -0,0 +1,57 @@ +import Vue from 'vue'; +import App from './App.vue'; +import router from './router'; +import ElementUI from 'element-ui'; +import VueI18n from 'vue-i18n'; +import { messages } from './components/common/i18n'; +//import 'element-ui/lib/theme-chalk/index.css'; // 默认主题 +import './assets/css/theme-green/index.css'; // 浅绿色主题 +import './assets/css/icon.css'; +import './components/common/directives'; +import 'babel-polyfill'; +import JsonViewer from 'vue-json-viewer' +import './assets/icon/iconfont.css' +import Clipboard from 'vue-clipboard2'; + +// 如果不需要mock数据,请注释下面两行 +// import Mock from './mock' +// Mock.bootstrap(); + +Vue.config.productionTip = false; +Vue.use(VueI18n); +Vue.use(ElementUI, { + size: 'small' +}); +Vue.use(JsonViewer); +Vue.use(Clipboard); +const i18n = new VueI18n({ + locale: 'zh', + messages +}); + +//使用钩子函数对路由进行权限跳转 +router.beforeEach((to, from, next) => { + document.title = `${to.meta.title} | nsi-collection-platform`; + const role = localStorage.getItem('token'); + if (!role && to.path !== '/login' && to.path !== '/register') { + next('/login'); + } else if (to.meta.permission) { + // 如果是管理员权限则可进入,这里只是简单的模拟管理员权限而已 + role === 'admin' ? next() : next('/403'); + } else { + // 简单的判断IE10及以下不进入富文本编辑器,该组件不兼容 + if (navigator.userAgent.indexOf('MSIE') > -1 && to.path === '/editor') { + Vue.prototype.$alert('vue-quill-editor组件不兼容IE10及以下浏览器,请使用更高版本的浏览器查看', '浏览器不兼容通知', { + confirmButtonText: '确定' + }); + } else { + next(); + } + } +}); + +new Vue({ + router, + i18n, + render: h => h(App) +}).$mount('#app'); diff --git a/nsi-collection-platform/src/mock/data/interfaces.js b/nsi-collection-platform/src/mock/data/interfaces.js new file mode 100644 index 0000000..5e4660b --- /dev/null +++ b/nsi-collection-platform/src/mock/data/interfaces.js @@ -0,0 +1,38 @@ +import Mock from 'mockjs'; + + + +const interfacesInfo = { + 'pageTotal':15, + 'data':[ + { + id: "1", + name: "/admin/task/non_ignoreInterface", + desc: "忽略接口与无调用接口对比", + service: "crbt_admin", + type: "业务", + enable: "启用", + request: "curl http://10.25.151.67:18083/admin/task/non_ignoreInterface", + response: "{\"status\": \"000000\", \"desc\": \"success\", \"data\": \"管理端已忽略,还有调用记录的接口列表:\\n/v2.0/content/exclusiveBroadcastDetail.do\\n/v1.0/content/videotone-search-all/32\\n/v1.0/content/tone-search-all/32\\n管理端未忽略,没有调用记录的接口列表:\\n/ringbacktone/vrbt-ordering-detail/32/v1.0\\n/v1.0/payment/unified-subscribe/card/40\\n/v1.0/payment/unified-subscribe/card/33\\n/ringbacktone/basedel/32/v1.0\\n/ringbacktone/tonedel/32/v1.0\\n/v1.0/payment/unified-subscribe/card/35\\n/ringbacktone/baseset/32/v1.0\\n/v1.0/payment/unified-subscribe/card/38\\n/v1.0/payment/unified-subscribe/card/39\\n/v2.0/content/getvideotonelist.do\\n/v1.0/rbt/rbt-lib\\n/v2.0/content/getHotWords.do\\n告警时间:2020-04-10 17:46:09\" }", + user_name: "jianghao", + update_time: "2020-05-28 11:28:19", + create_time: "2020-05-28 11:28:19" + }, + { + id: "2", + name: "/special/data_cycle", + desc: "根据数据上报周期获取模版列表,无参时获取全部数据,参数 day 按日 week 按周 month 按月", + service: "crbt_persistence", + type: "非业务", + enable: "废弃", + request: "curl -X GET \"http://10.25.151.67:18083/special/data_cycle?cycle=day\"", + response: "{\"status\":\"000000\",\"desc\":\"success\",\"data\":[{\"data_name\":\"客户端启动日志\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00048_\",\"file_name\":\"a_10000_00048_YYYYMMDD_00_001.dat\\na_10000_00048_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"duanhao\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":25,\"file_number\":null,\"isMd5Insert\":\"1\"},{\"data_name\":\"客户端使用时长日志\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00049_\",\"file_name\":\"a_10000_00049_YYYYMMDD_00_001.dat\\na_10000_00049_YYYYMMDD_00.verf\",\"file_from\":\"l\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"songbangjia\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":29,\"file_number\":\"\",\"isMd5Insert\":\"1\"},{\"data_name\":\"客户端登录日志\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00050_\",\"file_name\":\"a_10000_00050_YYYYMMDD_00_001.dat\\n\\na_10000_00050_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"duanhao\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":27,\"file_number\":\"\",\"isMd5Insert\":\"1\"},{\"data_name\":\"客户端用户页面访问日志\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00051_\",\"file_name\":\"a_10000_00051_YYYYMMDD_00_001.dat\\n\\na_10000_00051_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"duanhao\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":29,\"file_number\":null,\"isMd5Insert\":\"1\"},{\"data_name\":\"客户端搜索日志\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00052_\",\"file_name\":\"a_10000_00052_YYYYMMDD_00_001.dat\\na_10000_00052_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"duanhao\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":30,\"file_number\":null,\"isMd5Insert\":\"1\"},{\"data_name\":\"客户端广告日志\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00053_\",\"file_name\":\"a_10000_00053_YYYYMMDD_00_001.dat\\na_10000_00053_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"songbangjia\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":32,\"file_number\":null,\"isMd5Insert\":\"1\"},{\"data_name\":\"客户端内容下载日志\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00054_\",\"file_name\":\"a_10000_00054_YYYYMMDD_00_001.dat\\na_10000_00054_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"duanhao\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":32,\"file_number\":null,\"isMd5Insert\":\"1\"},{\"data_name\":\"客户端视频(MV,短视频,演唱会)播放日志\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00055_\",\"file_name\":\"a_10000_00055_YYYYMMDD_00_001.dat\\na_10000_00055_YYYYMMDD_00.verf\",\"file_from\":\"l\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"songbangjia\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":35,\"file_number\":\"\",\"isMd5Insert\":\"1\"},{\"data_name\":\"客户端业务日志—订购类(信息费类业务)\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00056_\",\"file_name\":\"a_10000_00056_YYYYMMDD_00_001.dat\\na_10000_00056_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"Admin\",\"enable\":0,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":0,\"file_number\":\"\",\"isMd5Insert\":\"2\"},{\"data_name\":\"客户端业务日志—订购类(功能费类业务)\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00057_\",\"file_name\":\"a_10000_00057_YYYYMMDD_00_001.dat a_10000_00057_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"duanhao\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":36,\"file_number\":null,\"isMd5Insert\":\"1\"},{\"data_name\":\"客户端业务日志—演唱会互动类\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00058_\",\"file_name\":\"a_10000_00058_YYYYMMDD_00_001.dat\\na_10000_00058_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"duanhao\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":37,\"file_number\":null,\"isMd5Insert\":\"1\"},{\"data_name\":\"客户端内容分享日志\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00059_\",\"file_name\":\"a_10000_00059_YYYYMMDD_00_001.dat\\na_10000_00059_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"duanhao\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":31,\"file_number\":\"\",\"isMd5Insert\":\"1\"},{\"data_name\":\"客户端评论日志\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00060_\",\"file_name\":\"a_10000_00060_YYYYMMDD_00_001.dat\\na_10000_00060_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"duanhao\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":30,\"file_number\":\"\",\"isMd5Insert\":\"1\"},{\"data_name\":\"客户端活动日志\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00061_\",\"file_name\":\"a_10000_00061_YYYYMMDD_00_001.dat\\na_10000_00061_YYYYMMDD_00.verf\",\"file_from\":\"a\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"Admin\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":33,\"file_number\":\"\",\"isMd5Insert\":\"1\"},{\"data_name\":\"客户端歌曲试听日志\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00062_\",\"file_name\":\"a_10000_00062_YYYYMMDD_00_001.dat\\na_10000_00062_YYYYMMDD_00.verf\",\"file_from\":\"l\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"songbangjia\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":39,\"file_number\":\"\",\"isMd5Insert\":\"1\"},{\"data_name\":\"演唱会直播时间同步日志\",\"data_sources\":\"定时任务\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"每天生成一个文件\",\"file_prefix\":\"a_10000_00063_\",\"file_name\":\"a_10000_00063_YYYYMMDD_00_001.dat\\na_10000_00063_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"duanhao\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":2,\"file_number\":null,\"isMd5Insert\":\"2\"},{\"data_name\":\"歌单标签同步日志\",\"data_sources\":\"定时任务\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"每天生成一个文件\",\"file_prefix\":\"a_10000_00064_\",\"file_name\":\"a_10000_00064_YYYYMMDD_00_001.dat\\na_10000_00064_YYYYMMDD_00.verf\",\"file_from\":\"g\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"Admin\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":5,\"file_number\":null,\"isMd5Insert\":\"2\"},{\"data_name\":\"歌单系统同步日志(歌单系统同步日志)\",\"data_sources\":\"定时任务\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"每天生成一个文件\",\"file_prefix\":\"a_10000_00065_\",\"file_name\":\"a_10000_00065_YYYYMMDD_00_001.dat\\na_10000_00065_YYYYMMDD_00.verf\",\"file_from\":\"g\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"Admin\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":12,\"file_number\":null,\"isMd5Insert\":\"2\"},{\"data_name\":\"歌单系统同步日志(歌单和歌曲对应关系)\",\"data_sources\":\"定时任务\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"每天生成一个文件\",\"file_prefix\":\"a_10000_00066_\",\"file_name\":\"a_10000_00066_YYYYMMDD_00_001.dat a_10000_00066_YYYYMMDD_00.verf\",\"file_from\":\"g\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"Admin\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":5,\"file_number\":null,\"isMd5Insert\":\"2\"},{\"data_name\":\"客户端活动中奖用户明细数据\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00069_\",\"file_name\":\"a_10000_00069_YYYYMMDD_00_001.dat\\na_10000_00069_YYYYMMDD_00.verf\",\"file_from\":\"a\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"Admin\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":11,\"file_number\":null,\"isMd5Insert\":\"2\"},{\"data_name\":\"客户端内容分享日志\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00070_\",\"file_name\":\"a_10000_00070_YYYYMMDD_00_001.dat\\na_10000_00070_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"Admin\",\"enable\":0,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":27,\"file_number\":null,\"isMd5Insert\":\"1\"},{\"data_name\":\"客户端本地歌曲上报日志\",\"data_sources\":\"新日志系统上报\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00071_\",\"file_name\":\"a_10000_00071_YYYYMMDD_00_001.dat a_10000_00071_YYYYMMDD_00.verf\",\"file_from\":\"l\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"Admin\",\"enable\":0,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":37,\"file_number\":null,\"isMd5Insert\":\"1\"},{\"data_name\":\"客户端点击曝光日志\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00099_\",\"file_name\":\"a_10000_00099_YYYYMMDD_00_001.dat\\na_10000_00099_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"songbangjia\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":33,\"file_number\":\"\",\"isMd5Insert\":\"1\"},{\"data_name\":\"客户端内容分享日志\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00101_\",\"file_name\":\"a_10000_00101_YYYYMMDD_00_001.dat\\na_10000_00101_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"duanhao\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":30,\"file_number\":\"\",\"isMd5Insert\":\"1\"},{\"data_name\":\"客户端本地歌曲上报日志\",\"data_sources\":\"新日志系统上报\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00102_\",\"file_name\":\"a_10000_00102_YYYYMMDD_00_001.dat\\na_10000_00102_YYYYMMDD_00.verf\",\"file_from\":\"l\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"songbangjia\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":39,\"file_number\":\"\",\"isMd5Insert\":\"1\"},{\"data_name\":\"明星打榜日志\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00108_\",\"file_name\":\"a_10000_00108_YYYYMMDD_00_001.dat\\na_10000_00108_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"duanhao\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":30,\"file_number\":\"\",\"isMd5Insert\":\"1\"},{\"data_name\":\"贡献榜日志\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00109_\",\"file_name\":\"a_10000_00109_YYYYMMDD_00_001.dat\\na_10000_00109_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"duanhao\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":28,\"file_number\":null,\"isMd5Insert\":\"1\"},{\"data_name\":\"小编修改营销数据变更日志\",\"data_sources\":\"客户端后台 MS\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00110_\",\"file_name\":\"a_10000_00110_YYYYMMDD_00_001.dat\\na_10000_00110_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"duanhao\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":7,\"file_number\":\"\",\"isMd5Insert\":\"2\"},{\"data_name\":\"DIY视频彩铃,DIY音频彩铃用户的上传记录日志\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"2:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00124_\",\"file_name\":\"a_10000_00124_YYYYMM_00_001.dat\\na_10000_00124_YYYYMM_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"duanhao\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":33,\"file_number\":\"\",\"isMd5Insert\":\"1\"},{\"data_name\":\"彩铃设置日志\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00125_\",\"file_name\":\"a_10000_00125_YYYYMMDD_00_001.dat\\na_10000_00125_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"duanhao\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":30,\"file_number\":null,\"isMd5Insert\":\"1\"},{\"data_name\":\"达人身份认证信息\",\"data_sources\":\"客户端后台数据库(mongodb)\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"a_10000_00166_\",\"file_name\":\"a_10000_00166_YYYYMMDD_00_001.dat\\na_10000_00166_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"liuxuewen\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":7,\"file_number\":null,\"isMd5Insert\":\"2\"},{\"data_name\":\"歌单系统同步日志(歌单和歌曲对应关系)\",\"data_sources\":\"定时任务\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"每天生成一个文件\",\"file_prefix\":\"i_10000_00066_\",\"file_name\":\"i_10000_00066_YYYYMMDD_00_001.dat\\ni_10000_00066_YYYYMMDD_00.verf\",\"file_from\":\"g\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"Admin\",\"enable\":0,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":5,\"file_number\":null,\"isMd5Insert\":\"2\"},{\"data_name\":\"客户端活动基本信息维码表\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"i_10000_00126_\",\"file_name\":\"i_10000_00126_YYYYMMDD_00_001.dat\\ni_10000_00126_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"songbangjia\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":8,\"file_number\":\"\",\"isMd5Insert\":\"2\"},{\"data_name\":\"客户端活动基本信息维码表\",\"data_sources\":\"客户端后台\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"i_10000_00128_\",\"file_name\":\"i_10000_00128_YYYYMMDD_00_001.dat\\ni_10000_00128_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"Admin\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":4,\"file_number\":\"\",\"isMd5Insert\":\"2\"},{\"data_name\":\"道具维表\",\"data_sources\":\"客户端后台数据库(mysql)\",\"data_cycle\":\"day\",\"transmission_time\":\"3:00之前\",\"transmission_mode\":\"以ftp方式定时传送\",\"file_prefix\":\"i_10000_00167_\",\"file_name\":\"i_10000_00167_YYYYMMDD_00_001.dat\\ni_10000_00167_YYYYMMDD_00.verf\",\"file_from\":\"t\",\"create_time\":\"2020-04-13 15:07:49.0\",\"create_by\":\"liuxuewen\",\"enable\":1,\"appointment\":null,\"appointment_type\":null,\"separatorNum\":7,\"file_number\":null,\"isMd5Insert\":\"2\"}]}", + user_name: "liuxuewen", + update_time: "2020-06-03 11:28:19", + create_time: "2020-06-03 11:28:19" + } + ] +}; + + +export { interfacesInfo }; diff --git a/nsi-collection-platform/src/mock/index.js b/nsi-collection-platform/src/mock/index.js new file mode 100644 index 0000000..925ee4f --- /dev/null +++ b/nsi-collection-platform/src/mock/index.js @@ -0,0 +1,3 @@ +import mock from './mock'; + +export default mock; diff --git a/nsi-collection-platform/src/mock/mock.js b/nsi-collection-platform/src/mock/mock.js new file mode 100644 index 0000000..165eebd --- /dev/null +++ b/nsi-collection-platform/src/mock/mock.js @@ -0,0 +1,35 @@ +import axios from 'axios'; +import MockAdapter from 'axios-mock-adapter'; +import Mock from 'mockjs'; + +export default { + /** + * mock bootstrap + */ + bootstrap() { + let mock = new MockAdapter(axios); + + // mock success request + mock.onGet('/success').reply(200, { + msg: 'success' + }); + + // mock error request + mock.onGet('/error').reply(500, { + msg: 'failure' + }); + + //登录 + mock.onPost('/admin/login').reply(config => { + return new Promise((resolve, reject) => { + setTimeout(() => { + resolve([200, { code: '000000', desc: '请求成功', data: { + "token": 'e0c5b8de1d04d1cc412c4a44925a1c3f', + "role": "admin" + } }]); + }, 1000); + }); + }); + + } +}; diff --git a/nsi-collection-platform/src/router/index.js b/nsi-collection-platform/src/router/index.js new file mode 100644 index 0000000..3b74471 --- /dev/null +++ b/nsi-collection-platform/src/router/index.js @@ -0,0 +1,64 @@ +import Vue from 'vue'; +import Router from 'vue-router'; + +Vue.use(Router); + +export default new Router({ + routes: [ + { + path: '/', + redirect: '/UserManager' + }, + { + path: '/', + component: () => import(/* webpackChunkName: "home" */ '../components/common/Home.vue'), + meta: { title: '自述文件' }, + children: [ + { + path: '/UserManager', + component: () => import(/* webpackChunkName: "dashboard" */ '../components/page/UserManager.vue'), + meta: { title: '用户管理' } + }, + { + path: '/DnsResolution', + component: () => import(/* webpackChunkName: "tabs" */ '../components/page/DnsResolution.vue'), + meta: { title: 'DNS解析' } + }, + { + path: '/SubdomainLookup', + component: () => import(/* webpackChunkName: "table" */ '../components/page/SubdomainLookup.vue'), + meta: { title: '子域名查询' } + }, + { + path: '/EmailInformationCapture', + component: () => import(/* webpackChunkName: "table" */ '../components/page/EmailInformationCapture.vue'), + meta: { title: '邮箱信息抓取' } + }, + { + path: '/PortDetection', + component: () => import(/* webpackChunkName: "table" */ '../components/page/PortDetection.vue'), + meta: { title: '端口检测' } + }, + { + path: '/OperationLog', + component: () => import(/* webpackChunkName: "table" */ '../components/page/OperationLog.vue'), + meta: { title: '操作记录' } + } + ] + }, + { + path: '/login', + component: () => import(/* webpackChunkName: "login" */ '../components/page/Login.vue'), + meta: { title: '登录' } + }, + { + path: '/register', + component: () => import(/* webpackChunkName: "login" */ '../components/page/Register.vue'), + meta: { title: '注册' } + }, + { + path: '*', + redirect: '/404' + } + ] +}); diff --git a/nsi-collection-platform/src/utils/request.js b/nsi-collection-platform/src/utils/request.js new file mode 100644 index 0000000..8e3bc0d --- /dev/null +++ b/nsi-collection-platform/src/utils/request.js @@ -0,0 +1,73 @@ +import axios from 'axios'; +import { errorLog, errorCreate } from './tools' +import router from '../router' +import { Message } from 'element-ui' + +const service = axios.create({ + // process.env.NODE_ENV === 'development' 来判断是否开发环境 + // easy-mock服务挂了,暂时不使用了 + // baseURL: 'https://www.easy-mock.com/mock/592501a391470c0ac1fab128', + timeout: 5000 +}); + +service.interceptors.request.use( + config => { + return config; + }, + error => { + return Promise.reject(); + } +); + +service.interceptors.response.use( + response => { + const dataAxios = response.data + const { code } = dataAxios + if (code === undefined) { + // 如果没有 code 代表这不是项目后端开发的接口 比如可能是 D2Admin 请求最新版本 + return dataAxios + } else{ + // 有 code 代表这是一个后端接口 可以进行进一步的判断 + switch (code) { + case '000000': + return dataAxios.data; + case '999999': + //登录注销 + Message({ + message: '登录过期,注销登录,自动跳转登录页面.', + type: 'error' + }) + localStorage.removeItem('user_name'); + localStorage.removeItem('token'); + router.push({path:'/login'}) + break; + default: + // 不是正确的 code + errorCreate(`${dataAxios.desc}`); + break + } + } + }, + error => { + if (error && error.response) { + switch (error.response.code) { + case 400: error.message = '请求错误'; break; + case 401: error.message = '未授权,请登录'; window.location.href = '/#/login';break; + case 403: error.message = '拒绝访问'; break; + case 404: error.message = `请求地址出错: ${error.response.config.url}`; break; + case 408: error.message = '请求超时'; break; + case 500: error.message = '服务器内部错误'; break; + case 501: error.message = '服务未实现'; break; + case 502: error.message = '网关错误'; break; + case 503: error.message = '服务不可用'; break; + case 504: error.message = '网关超时'; break; + case 505: error.message = 'HTTP版本不受支持'; break; + default: break + } + } + errorLog(error); + return Promise.reject(error) + } +); + +export default service; diff --git a/nsi-collection-platform/src/utils/tools.js b/nsi-collection-platform/src/utils/tools.js new file mode 100644 index 0000000..2aa6be5 --- /dev/null +++ b/nsi-collection-platform/src/utils/tools.js @@ -0,0 +1,75 @@ +import { Message } from 'element-ui' + +/** + * @description 安全地解析 json 字符串 + * @param {String} jsonString 需要解析的 json 字符串 + * @param {String} defaultValue 默认值 + */ +export function parse (jsonString = '{}', defaultValue = {}) { + let result = defaultValue + try { + result = JSON.parse(jsonString) + } catch (error) { + console.log(error) + } + return result +} + +/** + * @description 接口请求返回 + * @param {Any} data 返回值 + * @param {String} msg 状态信息 + * @param {Number} code 状态码 + */ +export function response (data = {}, msg = '', code = 0) { + return [ + 200, + { code, msg, data } + ] +} + +/** + * @description 接口请求返回 正确返回 + * @param {Any} data 返回值 + * @param {String} msg 状态信息 + */ +export function responseSuccess (data = {}, msg = '成功') { + return response(data, msg) +} + +/** + * @description 接口请求返回 错误返回 + * @param {Any} data 返回值 + * @param {String} msg 状态信息 + * @param {Number} code 状态码 + */ +export function responseError (data = {}, msg = '请求失败', code = 500) { + return response(data, msg, code) +} + +/** + * @description 记录和显示错误 + * @param {Error} error 错误对象 + */ +export function errorLog (error) { + // 打印到控制台 + if (process.env.NODE_ENV === 'development') { + console.log(error) + } + // 显示提示 + Message({ + message: error.message, + type: 'error', + duration: 5 * 1000 + }) +} + +/** + * @description 创建一个错误 + * @param {String} msg 错误信息 + */ +export function errorCreate (msg) { + const error = new Error(msg) + errorLog(error) + throw error +} diff --git a/nsi-collection-platform/vue.config.js b/nsi-collection-platform/vue.config.js new file mode 100644 index 0000000..2c67ce6 --- /dev/null +++ b/nsi-collection-platform/vue.config.js @@ -0,0 +1,16 @@ +module.exports = { + // baseUrl: '/', + assetsDir: 'static', + productionSourceMap: false, + // devServer: { + // proxy: { + // '/api':{ + // target:'http://jsonplaceholder.typicode.com', + // changeOrigin:true, + // pathRewrite:{ + // '/api':'' + // } + // } + // } + // } +} \ No newline at end of file diff --git a/nsi.sql b/nsi.sql new file mode 100644 index 0000000..3a8bb78 --- /dev/null +++ b/nsi.sql @@ -0,0 +1,52 @@ +/* + Navicat Premium Data Transfer + + Source Server : 118.24.151.27 + Source Server Type : MySQL + Source Server Version : 80025 + Source Host : 118.24.151.27:3306 + Source Schema : NSI + + Target Server Type : MySQL + Target Server Version : 80025 + File Encoding : 65001 + + Date: 15/05/2021 01:19:09 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for LOG_OPERATION +-- ---------------------------- +DROP TABLE IF EXISTS `LOG_OPERATION`; +CREATE TABLE `LOG_OPERATION` ( + `id` int NOT NULL AUTO_INCREMENT COMMENT '主键', + `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名', + `operationContent` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '操作内容', + `operationData` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '执行数据', + `updateTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '操作记录' ROW_FORMAT = Dynamic; + + +-- ---------------------------- +-- Table structure for USER +-- ---------------------------- +DROP TABLE IF EXISTS `USER`; +CREATE TABLE `USER` ( + `id` int NOT NULL AUTO_INCREMENT COMMENT '主键', + `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户名', + `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '密码', + `role` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '角色', + `updateTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of USER +-- ---------------------------- +INSERT INTO `USER` VALUES (1, 'admin', 'f6fdffe48c908deb0f4c3bd36c032e72', 'admin', '2021-05-14 22:56:27'); + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/网络安全信息搜集平台.md b/网络安全信息搜集平台.md new file mode 100644 index 0000000..e73e5f5 --- /dev/null +++ b/网络安全信息搜集平台.md @@ -0,0 +1,16 @@ +# 网络安全信息搜集平台 + +## 需求文档 + +1. 实现用户验证登录(数据放数据库) +2. 实现用户自行注册(数据放数据库) +3. admin权限用户可以对所有用户的账户信息进行增删改查 +4. 用户登录成功后实现以下功能 + 4.1 dns解析 + 4.2 子域名查询 + 4.3 抓取163邮箱账号 + 4.3.1 客户提供邮箱账号 + 4.3.2 抓取客户邮箱中的邮件信息并展示 + 4.4 端口检测(根据ip和端口参数判断该端口是否打开) +5. 系统名称:网络安全信息搜集平台 +6. 所有4中的子功能全部采用python进行开发,每个功能单独一个页面 \ No newline at end of file