├── src ├── .idea │ ├── misc.xml │ ├── vcs.xml │ ├── modules.xml │ ├── DDNS.iml │ └── workspace.xml ├── config.json ├── CommonRequestSingleton.py ├── AcsClientSingleton.py ├── IpGetter.py ├── DDNS.py └── Utils.py ├── README_ZH_CN.md ├── README.md └── LICENSE /src/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "AccessKeyId": "Your_AccessKeyId", 3 | "AccessKeySecret": "Your_AccessKeySecret", 4 | "First-level-domain": "Your_First-level-domain", 5 | "Second-level-domain": "Your_Second-level-domain" 6 | } -------------------------------------------------------------------------------- /src/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/.idea/DDNS.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | -------------------------------------------------------------------------------- /src/CommonRequestSingleton.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 获取阿里云Common Request请求类 3 | 单实例 4 | Created By Martin Huang on 2018/5/26 5 | ''' 6 | from aliyunsdkcore.request import CommonRequest 7 | 8 | class CommonRequestSing: 9 | #私有类变量 10 | __request = None 11 | 12 | #该修饰符将实例方法变成类方法 13 | #,因为类方法无法操作私有的类变量,所以使用实例方法进行操作,再进行转换为类方法 14 | @classmethod 15 | def getInstance(self): 16 | if self.__request is None: 17 | self.__request = CommonRequest() 18 | return self.__request 19 | 20 | if __name__ == "__main__": 21 | CommonRequestSing.getInstance() 22 | -------------------------------------------------------------------------------- /src/AcsClientSingleton.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @desc:AcsClient的单实例类 3 | @author: Martin Huang 4 | @time: created on 2018/5/26 18:50 5 | @修改记录: 6 | 2018/6/10 =》 AccessKeyId 和 AccessKeySecret从配置文件中读取 7 | ''' 8 | from aliyunsdkcore.client import AcsClient 9 | import Utils as tools 10 | class AcsClientSing: 11 | __client = None 12 | 13 | @classmethod 14 | def getInstance(self): 15 | if self.__client is None: 16 | acsDict = tools.Utils.getConfigJson() 17 | self.__client = AcsClient(acsDict.get('AccessKeyId'), acsDict.get('AccessKeySecret'), 'cn-hangzhou') 18 | return self.__client 19 | -------------------------------------------------------------------------------- /src/IpGetter.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 获取用户真实IP地址 3 | Created By Martin Huang on 2018/5/19 4 | 修改记录: 5 | 2018/12/24 =》改进ip获取方式 取消BS4依赖 感谢@Nielamu的建议 6 | 2020/05/05 =》改进ipv4获取方式,如果获取失败,则会写入日志文件,并过10秒后使用新的网址重试,感谢@sunsheho贡献的代码 7 | 我在休眠时间上略作修改 8 | ''' 9 | import urllib.request 10 | from urllib import request,error 11 | import json 12 | import time,datetime 13 | from time import sleep 14 | 15 | def senderror(errcont): 16 | enow=datetime.datetime.now() 17 | now=enow.strftime('%Y-%m-%d %H:%M:%S') 18 | errfile=open('DDNS.log','a') 19 | errfile.write(now) 20 | errfile.write(str(errcont)) 21 | errfile.write('\n') 22 | errfile.close() 23 | 24 | 25 | 26 | def getIpPage(): 27 | try: 28 | url = "https://api.ipify.org/?format=json" 29 | response = request.urlopen(url,timeout=60) 30 | html = response.read().decode('utf-8') 31 | return html 32 | except error.HTTPError as e: 33 | print(e.reason) 34 | senderror(e.reason) 35 | time.sleep(10) 36 | getIpPage() 37 | except error.URLError as e: 38 | print(e.reason) 39 | senderror(e.reason) 40 | time.sleep(10) 41 | getIpPage() 42 | except: 43 | url = "http://members.3322.org/dyndns/getip" 44 | response = request.urlopen(url,timeout=60) 45 | html = response.read().decode('utf-8') 46 | html = html.replace("\n","") 47 | htm={} 48 | htm['ip'] = html 49 | HTL = json.dumps(htm) 50 | return HTL 51 | 52 | # 解析数据,获得IP 53 | def getRealIp(data): 54 | try: 55 | jsonData = json.loads(data) 56 | return jsonData['ip'] 57 | except: 58 | time.sleep(200) 59 | getIpPage() 60 | 61 | 62 | # 利用API获取含有用户ip的JSON数据 63 | def getIpPageV6(): 64 | url = "https://v6.ident.me/.json" 65 | response = urllib.request.urlopen(url) 66 | html = response.read().decode('utf-8') 67 | return html 68 | 69 | 70 | # 解析数据,获得IP 71 | def getRealIpV6(data): 72 | jsonData = json.loads(data) 73 | return jsonData['address'] 74 | -------------------------------------------------------------------------------- /src/DDNS.py: -------------------------------------------------------------------------------- 1 | ''' 2 | DDNS 主程序 使用阿里云的SDK发起请求 3 | Created By Martin Huang on 2018/5/20 4 | 修改记录: 5 | 2018/5/20 => 第一版本 6 | 2018/5/26 => 增加异常处理、Requst使用单例模式,略有优化 7 | 2018/5/29 => 增加网络连通性检测,只有联通时才进行操作,否则等待 8 | 2018/6/10 => 使用配置文件存储配置,避免代码内部修改(需要注意Python模块相互引用问题) 9 | 2018/9/24 => 修改失败提示信息 10 | ''' 11 | from aliyunsdkcore.acs_exception.exceptions import ServerException 12 | from aliyunsdkcore.acs_exception.exceptions import ClientException 13 | from Utils import Utils 14 | import time 15 | import argparse 16 | 17 | def DDNS(use_v6): 18 | client = Utils.getAcsClient() 19 | recordId = Utils.getRecordId(Utils.getConfigJson().get('Second-level-domain')) 20 | if use_v6: 21 | ip = Utils.getRealIPv6() 22 | type = 'AAAA' 23 | else: 24 | ip = Utils.getRealIP() 25 | type = 'A' 26 | print({'type': type, 'ip':ip}) 27 | 28 | request = Utils.getCommonRequest() 29 | request.set_domain('alidns.aliyuncs.com') 30 | request.set_version('2015-01-09') 31 | request.set_action_name('UpdateDomainRecord') 32 | request.add_query_param('RecordId', recordId) 33 | request.add_query_param('RR', Utils.getConfigJson().get('Second-level-domain')) 34 | request.add_query_param('Type', type) 35 | request.add_query_param('Value', ip) 36 | response = client.do_action_with_exception(request) 37 | return response 38 | 39 | if __name__ == "__main__": 40 | parser = argparse.ArgumentParser(description='DDNS') 41 | parser.add_argument('-6', '--ipv6', nargs='*', default=False) 42 | args = parser.parse_args() 43 | isipv6 = isinstance(args.ipv6, list) 44 | 45 | try: 46 | while not Utils.isOnline(): 47 | time.sleep(3) 48 | continue 49 | result = DDNS(isipv6) 50 | print("成功!") 51 | except (ServerException,ClientException) as reason: 52 | print("失败!原因为") 53 | print(reason.get_error_msg()) 54 | print("可参考:https://help.aliyun.com/document_detail/29774.html?spm=a2c4g.11186623.2.20.fDjexq#%E9%94%99%E8%AF%AF%E7%A0%81") 55 | print("或阿里云帮助文档") -------------------------------------------------------------------------------- /README_ZH_CN.md: -------------------------------------------------------------------------------- 1 | # DDNS 2 | 3 | [中文](https://github.com/mgsky1/DDNS/blob/master/README_ZH_CN.md)|[English](https://github.com/mgsky1/DDNS/blob/master/README.md) 4 | 5 | ## Summary 6 | 7 | > 利用Python和阿里云云解析API实现。可利用于家庭环境,向公网映射NAS,DB,Web等应用 8 | 9 | ## Install 10 | 11 | ```bash 12 | pip3 install aliyun-python-sdk-core-v3 13 | ``` 14 | 15 | ## Run 16 | ```bash 17 | python3 src/DDNS.py # 默认ipv4 18 | python3 src/DDNS.py -6 # 改用ipv6 19 | ``` 20 | 21 | 22 | ## Note 23 | > * 基于:Python 3 、阿里云Python SDK、阿里云云解析API 24 | > * 直接运行DDNS.py文件的main函数即可,其他的py文件的main函数都为测试 25 | > * 可将此脚本设置为系统定时任务,例如每天凌晨4:30执行一次或者每次联网时自动执行一次 26 | > * *在最新的[dev](https://github.com/mgsky1/DDNS/tree/dev)分支中增加了同一IP同时绑定多个域名的功能,欢迎体验* 27 | > * 如果您使用iPv4地址,请确保域名的记录类型设置为**A**,如果是要使用iPv6,设置成**AAAA** 28 | > * 此脚本为DDNS实现的个人想法 29 | 30 | ## Restrict 31 | > 本脚本适用于家庭宽带IP为动态IP的情形,若不是,可以利用[frp](https://github.com/fatedier/frp)等NAT-DDNS内网穿透工具 32 | ## Configuration 33 | 本项目修改为使用配置文件方式存储用户配置,配置文件为JSON格式,存放于config.json文件中,形式如下: 34 | ``` 35 | { 36 | "AccessKeyId": "Your_AccessKeyId",//你的阿里云AccessKeyId 37 | "AccessKeySecret": "Your_AccessKeySecret",//你的阿里云AccessKeySecret 38 | "First-level-domain": "Your_First-level-domain",//一级域名,例如 example.com 39 | "Second-level-domain": "Your_Second-level-domain"//二级域名,例如 ddns.example.com 填入ddns即可 40 | } 41 | ``` 42 | ## Tip 43 | > 判断自家宽带是否是动态IP的方式: 44 | > * Step 1:百度搜索IP,查到自己的IP地址 45 | > * Step 2:接着本地开一个网站,比如在Windows下直接启动IIS,Linux下安装一个Apache或者Nginx启动,使用它们的默认页面 46 | > * Step 3:然后在路由器上设置好转发规则,公网IP的网络访问端口最好不要用80,80端口可能被运营商封了 47 | > * Step 4:最后利用前面查到的公网IP+端口号访问一下,看看能不能显示内网上的页面,如果可以,恭喜你! 48 | ## ScreenShots 49 | 50 | 注:因为我已经更新过了,所以它提示IP地址已存在,阿里云是不允许同一个IP重复更新的。第二张图为本地,第三张图为外网
51 | ![](http://xxx.fishc.org/forum/201805/26/181341tp2frcnnnvnvc5iz.png) 52 | 53 | ![](http://xxx.fishc.org/forum/201805/26/200124rsubrwwdblr8ffwz.png) 54 | 55 | ![](http://xxx.fishc.org/forum/201805/26/200228kb1u63hargn0pc1n.png) 56 | 57 | ## Change Log 58 | > * 2018/5/29 网络连通性检测,只有在有网时才进行操作,否则等待网络连接 59 | > * 2018/6/10 启用配置文件存储用户数据 60 | > * 2018/9/24 修改失败提示输出,添加阿里帮助网址,让用户可查询错误对应信息 61 | > * 2018/12/24 改进ip获取方式,删除BS4依赖,感谢[@Nielamu](https://github.com/NieLamu) 62 | > * 2018/12/27 增加ipv6支持,感谢[@chnlkw](https://github.com/chnlkw) 63 | > * 2020/05/05 修改ipv4地址获取方式。如果失败,会写入日志,并在10秒后采用新的方式重试。感谢[@sunsheho](https://github.com/sunsheho) 64 | 65 | ## Contribution 66 | 如果感兴趣欢迎fork项目,如果有任何问题欢迎在issue区提问~ 67 | 68 | -------------------------------------------------------------------------------- /src/Utils.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 工具类 3 | Created By Martin Huang on 2018/5/19 4 | 修改记录: 5 | 2018/5/16 =》删除不需要的方法 6 | 2018/5/29 =》增加获取操作系统平台方法,增加网络连通性检测(后续考虑重构) 7 | 2018/6/3 =》网络连通性代码重构 8 | 2018/6/10 =》增加配置文件读取方法(可能有IO性能影响,考虑重构) 9 | ''' 10 | import IpGetter 11 | import platform 12 | import subprocess 13 | import json 14 | from AcsClientSingleton import AcsClientSing 15 | from CommonRequestSingleton import CommonRequestSing 16 | class Utils: 17 | 18 | #获取真实公网IP 19 | def getRealIP(): 20 | url = IpGetter.getIpPage(); 21 | ip = IpGetter.getRealIp(url) 22 | return ip 23 | 24 | #获取真实公网IPv6 25 | def getRealIPv6(): 26 | url = IpGetter.getIpPageV6(); 27 | ip = IpGetter.getRealIpV6(url) 28 | return ip 29 | 30 | #获取二级域名的RecordId 31 | def getRecordId(domain): 32 | client = Utils.getAcsClient() 33 | request = Utils.getCommonRequest() 34 | request.set_domain('alidns.aliyuncs.com') 35 | request.set_version('2015-01-09') 36 | request.set_action_name('DescribeDomainRecords') 37 | request.add_query_param('DomainName', Utils.getConfigJson().get('First-level-domain')) 38 | response = client.do_action_with_exception(request) 39 | jsonObj = json.loads(response.decode("UTF-8")) 40 | records = jsonObj["DomainRecords"]["Record"] 41 | for each in records: 42 | if each["RR"] == domain: 43 | return each["RecordId"] 44 | 45 | #获取CommonRequest 46 | def getCommonRequest(): 47 | return CommonRequestSing.getInstance() 48 | 49 | #获取AcsClient 50 | def getAcsClient(): 51 | return AcsClientSing.getInstance() 52 | 53 | #获取操作系统平台 54 | def getOpeningSystem(): 55 | return platform.system() 56 | 57 | #判断是否联网 58 | def isOnline(): 59 | userOs = Utils.getOpeningSystem() 60 | try: 61 | if userOs == "Windows": 62 | subprocess.check_call(["ping", "-n", "2", "www.baidu.com"], stdout=subprocess.PIPE) 63 | else: 64 | subprocess.check_call(["ping", "-c", "2", "www.baidu.com"], stdout=subprocess.PIPE) 65 | return True 66 | except subprocess.CalledProcessError: 67 | print("网络未连通!请检查网络") 68 | return False 69 | 70 | #从config.json中获取配置信息JSON串 71 | def getConfigJson(): 72 | with open('config.json') as file: 73 | jsonStr = json.loads(file.read()) 74 | return jsonStr 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DDNS 2 | [中文](https://github.com/mgsky1/DDNS/blob/master/README_ZH_CN.md)|[English](https://github.com/mgsky1/DDNS/blob/master/README.md) 3 | ## Summary 4 | > Python and Aliyun SDK API have been used in this project. You can use this tool to map the local applications like NAS, DB, WEB etc to the internet. 5 | ## Install 6 | ```bash 7 | pip3 install aliyun-python-sdk-core-v3 8 | ``` 9 | ## Run 10 | ```bash 11 | python3 src/DDNS.py # default ipv4 12 | python3 src/DDNS.py -6 # change to ipv6 13 | ``` 14 | ## Note 15 | > * Based on Python3、Aliyun API. 16 | > * To begin, you can run the main function in DDNS.py. The main function in other .py files are for the test purpose. 17 | > * You can set this script as a timer task in your opening system. For example, running this script at 4:30am everyday or when connecting to the internet. 18 | > * On the [dev](https://github.com/mgsky1/DDNS/tree/dev) branch, this project supports binding multiple domains to the same ip address. 19 | > * If you use iPv4, please make sure that the record type of your domain which will be used is **A**. If you use iPv6, the type is **AAAA**. 20 | > * This script is my idea for implementing DDNS. 21 | 22 | ## Restrict 23 | > This script is suitable for the broadband which has a dynamic IP. If not, you can try NAT-DDNS tools like [frp](https://github.com/fatedier/frp). 24 | 25 | ## Configuration 26 | The config.json has some infomation you should provide. The config structure may like this: 27 | ``` 28 | { 29 | "AccessKeyId": "Your_AccessKeyId",//Your Aliyun AccessKeyId 30 | "AccessKeySecret": "Your_AccessKeySecret",//Your Aliyun AccessKeySecret 31 | "First-level-domain": "Your_First-level-domain",//First level domain, eg example.com 32 | "Second-level-domain": "Your_Second-level-domain"//Second level domain, eg ddns.example.com Just input ddns 33 | } 34 | ``` 35 | ## Tip 36 | > How to determine wether your broadband service has a dynamic IP. 37 | > * Step 1:Find your WAN IP by google or other tools. 38 | > * Step 2:Run a web service locally. For example, starting IIS in Windows or Apache in Linux and using their default webpage. 39 | > * Step 3: Set the map rules in your home router. The ports which you will use to access the local service over internet had better not to be 80 beacuse the 80 port may be blocked by your internet service provider. 40 | > * Step 4: Use the IP you fond by google and the port to access your local web service. If ok, congratulations! 41 | 42 | ## ScreenShots 43 | NOTE: Because I have updated before, the script tells me the DNS record has already exists. Aliyun does not allow users to update the same IP when the IP has not been changed. The second picture shows the local service. The Third one shows accessing local service over internet under the help of DDNS. 44 | 45 | ![](http://xxx.fishc.org/forum/201805/26/181341tp2frcnnnvnvc5iz.png) 46 | 47 | ![](http://xxx.fishc.org/forum/201805/26/200124rsubrwwdblr8ffwz.png) 48 | 49 | ![](http://xxx.fishc.org/forum/201805/26/200228kb1u63hargn0pc1n.png) 50 | 51 | ## Change Log 52 | > * 2018/5/29 Add detecting internet access. 53 | > * 2018/6/10 Start using configuration file. 54 | > * 2018/9/24 Improve the error output 55 | > * 2018/12/24 Improve the way to get IP, deleteing BS4 dependence. Thanks [@Nielamu](https://github.com/NieLamu). 56 | > * 2018/12/27 Support ipv6. Thanks [@chnlkw](https://github.com/chnlkw). 57 | > * 2020/05/05 Improve the policy of getting ipv4 address. Once failed, it will write into the log and retry with new method after 10 sec. Thanks [@sunsheho](https://github.com/sunsheho). 58 | 59 | ## Contribution 60 | If you interest in this project and want to improve it, welcome to fork the project. Have any questions? you can ask in issue~ 61 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /src/.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 61 | 62 | 63 | 64 | Request 65 | CommonRequest 66 | 67 | 68 | 69 | 75 | 76 | 77 | 92 | 93 | 94 | 95 | 96 | true 97 | DEFINITION_ORDER 98 | 99 | 100 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 |